Refactor timing locking behavior

- Do not start CPU thread until after splash screen
    - Insure that only CPU thread can actually create/destroy the audio interfaces
This commit is contained in:
Aaron Culliney 2015-07-26 13:38:43 -07:00
parent fa1de4dee7
commit a0cadc83c6
15 changed files with 160 additions and 112 deletions

View File

@ -140,9 +140,6 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobje
c_initialize_firsttime(); c_initialize_firsttime();
pthread_create(&cpu_thread_id, NULL, (void *) &cpu_thread, (void *)NULL); pthread_create(&cpu_thread_id, NULL, (void *) &cpu_thread, (void *)NULL);
#endif #endif
sleep(1);
#warning FIXME TODO instead of problematic sleep ... need to preempt CPU thread by holding interface lock and displaying a splash screen and setting preferences/settings defaults before starting CPU
} }
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeGraphicsChanged(JNIEnv *env, jobject obj, jint width, jint height) { void Java_org_deadc0de_apple2ix_Apple2Activity_nativeGraphicsChanged(JNIEnv *env, jobject obj, jint width, jint height) {

View File

@ -57,18 +57,16 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetSpeakerVolume(JNIEnv
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetAudioLatency(JNIEnv *env, jclass cls, jfloat latencySecs) { void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetAudioLatency(JNIEnv *env, jclass cls, jfloat latencySecs) {
LOG("native set audio latency : %f", latencySecs); LOG("native set audio latency : %f", latencySecs);
//assert(cpu_isPaused()); assert(cpu_isPaused());
audio_setLatency(latencySecs); audio_setLatency(latencySecs);
timing_reinitializeAudio();
} }
jboolean Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetMockingboardEnabled(JNIEnv *env, jclass cls, jboolean enabled) { jboolean Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetMockingboardEnabled(JNIEnv *env, jclass cls, jboolean enabled) {
LOG("native set set mockingboard enabled : %d", enabled); LOG("native set set mockingboard enabled : %d", enabled);
//assert(cpu_isPaused()); assert(cpu_isPaused());
#warning FIXME ^^^ this should be true MB_SetEnabled(enabled);
MB_Destroy(); timing_reinitializeAudio();
if (enabled) {
MB_Initialize();
}
return MB_ISEnabled(); return MB_ISEnabled();
} }

View File

@ -177,9 +177,7 @@
[self.altSliderLabel setStringValue:[NSString stringWithFormat:@"%.0f%%", value*100]]; [self.altSliderLabel setStringValue:[NSString stringWithFormat:@"%.0f%%", value*100]];
} }
#warning HACK TODO FIXME ... refactor timing stuff timing_initialize();
timing_toggle_cpu_speed();
timing_toggle_cpu_speed();
[self _savePrefs]; [self _savePrefs];
} }
@ -198,9 +196,7 @@
cpu_altscale_factor = ([maxButton state] == NSOnState) ? CPU_SCALE_FASTEST : [self.altSlider doubleValue]; cpu_altscale_factor = ([maxButton state] == NSOnState) ? CPU_SCALE_FASTEST : [self.altSlider doubleValue];
} }
#warning HACK TODO FIXME ... refactor timing stuff timing_initialize();
timing_toggle_cpu_speed();
timing_toggle_cpu_speed();
[self _savePrefs]; [self _savePrefs];
} }

View File

@ -97,7 +97,9 @@
- (IBAction)toggleCPUSpeed:(id)sender - (IBAction)toggleCPUSpeed:(id)sender
{ {
timing_toggle_cpu_speed(); cpu_pause();
timing_toggleCPUSpeed();
cpu_resume();
} }
- (IBAction)togglePause:(id)sender - (IBAction)togglePause:(id)sender
@ -117,7 +119,7 @@
if (paused) if (paused)
{ {
[[self pauseMenuItem] setTitle:@"Resume Emulation"]; [[self pauseMenuItem] setTitle:@"Resume Emulation"];
pthread_mutex_lock(&interface_mutex); cpu_pause();
#ifdef AUDIO_ENABLED #ifdef AUDIO_ENABLED
SoundSystemPause(); SoundSystemPause();
#endif #endif
@ -128,7 +130,7 @@
#ifdef AUDIO_ENABLED #ifdef AUDIO_ENABLED
SoundSystemUnpause(); SoundSystemUnpause();
#endif #endif
pthread_mutex_unlock(&interface_mutex); cpu_resume();
} }
} }

View File

@ -1689,11 +1689,12 @@ static void MB_DSUninit()
void MB_Initialize() void MB_Initialize()
{ {
#ifdef APPLE2IX #ifdef APPLE2IX
assert(pthread_self() == cpu_thread_id);
memset(SSI263Voice, 0x0, sizeof(AudioBuffer_s)*MAX_VOICES); memset(SSI263Voice, 0x0, sizeof(AudioBuffer_s)*MAX_VOICES);
#endif #endif
if (g_bDisableDirectSoundMockingboard) if (g_bDisableDirectSoundMockingboard)
{ {
MockingboardVoice->bMute = true; //MockingboardVoice->bMute = true;
g_SoundcardType = CT_Empty; g_SoundcardType = CT_Empty;
} }
else else
@ -1745,6 +1746,7 @@ void MB_Reinitialize()
void MB_Destroy() void MB_Destroy()
{ {
assert(pthread_self() == cpu_thread_id);
MB_DSUninit(); MB_DSUninit();
for(int i=0; i<NUM_VOICES; i++) for(int i=0; i<NUM_VOICES; i++)
@ -1757,6 +1759,10 @@ void MB_Destroy()
} }
} }
void MB_SetEnabled(bool enabled) {
g_bDisableDirectSoundMockingboard = true;
}
bool MB_ISEnabled(void) { bool MB_ISEnabled(void) {
return (MockingboardVoice != NULL); return (MockingboardVoice != NULL);
} }

View File

@ -98,6 +98,7 @@ extern uint32_t g_uTimer1IrqCount; // DEBUG
void MB_Initialize(); void MB_Initialize();
void MB_Reinitialize(); void MB_Reinitialize();
void MB_Destroy(); void MB_Destroy();
void MB_SetEnabled(bool enabled);
bool MB_ISEnabled(void); bool MB_ISEnabled(void);
void MB_Reset(); void MB_Reset();
void MB_InitializeIO(char *pCxRomPeripheral, unsigned int uSlot4, unsigned int uSlot5); void MB_InitializeIO(char *pCxRomPeripheral, unsigned int uSlot4, unsigned int uSlot5);

View File

@ -61,6 +61,7 @@ void audio_destroySoundBuffer(INOUT AudioBuffer_s **audioBuffer) {
} }
bool audio_init(void) { bool audio_init(void) {
assert(pthread_self() == cpu_thread_id);
if (audio_isAvailable) { if (audio_isAvailable) {
return true; return true;
} }
@ -88,6 +89,7 @@ bool audio_init(void) {
} }
void audio_shutdown(void) { void audio_shutdown(void) {
assert(pthread_self() == cpu_thread_id);
if (!audio_isAvailable) { if (!audio_isAvailable) {
return; return;
} }
@ -110,17 +112,7 @@ void audio_resume(void) {
} }
void audio_setLatency(float latencySecs) { void audio_setLatency(float latencySecs) {
#warning FIXME TODO ... dynamically changing buffer size is really heavyweight since this buffer size percolates up to speaker/mockingboard allocations ... ugh we will live with this for now ... pumping this will be a great test for Valgrind heap profiling =P
speaker_destroy();
MB_Destroy();
audio_shutdown();
audio_latencySecs = latencySecs; audio_latencySecs = latencySecs;
audio_init();
speaker_init();
MB_Initialize();
#warning FIXME TODO ... also ugh we should have a registration mechanism of audio devices so we don't need to explicitly list them here, suggest something similar to the glnode registration stuff in video
} }
float audio_getLatency(void) { float audio_getLatency(void) {

View File

@ -324,6 +324,7 @@ static unsigned int _submit_samples_buffer(const unsigned long num_channel_sampl
// speaker public API functions // speaker public API functions
void speaker_destroy(void) { void speaker_destroy(void) {
assert(pthread_self() == cpu_thread_id);
speaker_isAvailable = false; speaker_isAvailable = false;
audio_destroySoundBuffer(&speakerBuffer); audio_destroySoundBuffer(&speakerBuffer);
FREE(samples_buffer); FREE(samples_buffer);
@ -331,6 +332,8 @@ void speaker_destroy(void) {
} }
void speaker_init(void) { void speaker_init(void) {
assert(pthread_self() == cpu_thread_id);
long err = 0; long err = 0;
speaker_isAvailable = false; speaker_isAvailable = false;
do { do {
@ -479,9 +482,11 @@ GLUE_C_READ(speaker_toggle)
speaker_accessed_since_last_flush = true; speaker_accessed_since_last_flush = true;
speaker_recently_active = true; speaker_recently_active = true;
if (timing_should_auto_adjust_speed()) { #if !defined(MOBILE_DEVICE)
if (timing_shouldAutoAdjustSpeed()) {
is_fullspeed = false; is_fullspeed = false;
} }
#endif
if (speaker_isAvailable) { if (speaker_isAvailable) {
_speaker_update(/*toggled:true*/); _speaker_update(/*toggled:true*/);

View File

@ -160,7 +160,6 @@ static void _interface_plotMessageCentered(uint8_t *fb, int fb_cols, int fb_rows
static struct stat statbuf = { 0 }; static struct stat statbuf = { 0 };
static int altdrive = 0; static int altdrive = 0;
bool in_interface = false;
void video_plotchar(const int col, const int row, const interface_colorscheme_t cs, const uint8_t c) { void video_plotchar(const int col, const int row, const interface_colorscheme_t cs, const uint8_t c) {
unsigned int off = row * SCANWIDTH * FONT_HEIGHT_PIXELS + col * FONT80_WIDTH_PIXELS + _INTERPOLATED_PIXEL_ADJUSTMENT_PRE; unsigned int off = row * SCANWIDTH * FONT_HEIGHT_PIXELS + col * FONT80_WIDTH_PIXELS + _INTERPOLATED_PIXEL_ADJUSTMENT_PRE;
@ -1547,11 +1546,7 @@ void c_interface_keyboard_layout()
static void *interface_thread(void *current_key) static void *interface_thread(void *current_key)
{ {
pthread_mutex_lock(&interface_mutex); cpu_pause();
#ifdef AUDIO_ENABLED
audio_pause();
#endif
in_interface = true;
switch ((__SWORD_TYPE)current_key) { switch ((__SWORD_TYPE)current_key) {
case kF1: case kF1:
@ -1592,11 +1587,7 @@ static void *interface_thread(void *current_key)
break; break;
} }
#ifdef AUDIO_ENABLED cpu_resume();
audio_resume();
#endif
pthread_mutex_unlock(&interface_mutex);
in_interface = false;
return NULL; return NULL;
} }

View File

@ -26,7 +26,6 @@ typedef enum interface_colorscheme_t {
} interface_colorscheme_t; } interface_colorscheme_t;
#ifdef INTERFACE_CLASSIC #ifdef INTERFACE_CLASSIC
extern bool in_interface;
void video_plotchar(int col, int row, interface_colorscheme_t cs, uint8_t c); void video_plotchar(int col, int row, interface_colorscheme_t cs, uint8_t c);
void c_interface_begin(int current_key); void c_interface_begin(int current_key);
void c_interface_print(int x, int y, const interface_colorscheme_t cs, const char *s); void c_interface_print(int x, int y, const interface_colorscheme_t cs, const char *s);

View File

@ -234,7 +234,7 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
if ((next_key >= 0) if ((next_key >= 0)
#ifdef INTERFACE_CLASSIC #ifdef INTERFACE_CLASSIC
&& !in_interface && !cpu_isPaused()
#endif #endif
) )
{ {
@ -252,7 +252,9 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
#ifdef INTERFACE_CLASSIC #ifdef INTERFACE_CLASSIC
if (current_key == kF9) if (current_key == kF9)
{ {
timing_toggle_cpu_speed(); cpu_pause();
timing_toggleCPUSpeed();
cpu_resume();
if (video_backend->animation_showCPUSpeed) { if (video_backend->animation_showCPUSpeed) {
video_backend->animation_showCPUSpeed(); video_backend->animation_showCPUSpeed();
} }
@ -287,9 +289,10 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
if (video_backend->animation_showCPUSpeed) { if (video_backend->animation_showCPUSpeed) {
video_backend->animation_showCPUSpeed(); video_backend->animation_showCPUSpeed();
} }
#warning HACK TODO FIXME ... refactor timing stuff
timing_toggle_cpu_speed(); cpu_pause();
timing_toggle_cpu_speed(); timing_initialize();
cpu_resume();
break; break;
} }
if (current_key == kF4) { if (current_key == kF4) {
@ -316,9 +319,10 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
if (video_backend->animation_showCPUSpeed) { if (video_backend->animation_showCPUSpeed) {
video_backend->animation_showCPUSpeed(); video_backend->animation_showCPUSpeed();
} }
#warning HACK TODO FIXME ... refactor timing stuff
timing_toggle_cpu_speed(); cpu_pause();
timing_toggle_cpu_speed(); timing_initialize();
cpu_resume();
break; break;
} }
#endif #endif

View File

@ -40,6 +40,11 @@ static unsigned int stepping_timeout = 0;
volatile bool is_debugging = false; volatile bool is_debugging = false;
extern pthread_mutex_t interface_mutex;
extern pthread_cond_t cpu_thread_cond;
extern pthread_cond_t dbg_thread_cond;
#warning ^^^ HACK FIXME TODO ... debugger should not have raw access to mutex variables
#define BUF_X DEBUGGER_BUF_X #define BUF_X DEBUGGER_BUF_X
#define BUF_Y DEBUGGER_BUF_Y #define BUF_Y DEBUGGER_BUF_Y
#define SCREEN_X 81 // 80col + 1 #define SCREEN_X 81 // 80col + 1

View File

@ -42,6 +42,16 @@
#define DISK_MOTOR_QUIET_NSECS 2000000 #define DISK_MOTOR_QUIET_NSECS 2000000
#define _LOCK_CPU_THREAD() \
if (pthread_self() != cpu_thread_id) { \
pthread_mutex_lock(&interface_mutex); \
}
#define _UNLOCK_CPU_THREAD() \
if (pthread_self() != cpu_thread_id) { \
pthread_mutex_unlock(&interface_mutex); \
}
// VBL constants? // VBL constants?
#define uCyclesPerLine 65 // 25 cycles of HBL & 40 cycles of HBL' #define uCyclesPerLine 65 // 25 cycles of HBL & 40 cycles of HBL'
#define uVisibleLinesPerFrame (64*3) // 192 #define uVisibleLinesPerFrame (64*3) // 192
@ -59,8 +69,9 @@ static unsigned int g_dwCyclesThisFrame = 0;
// scaling and speed adjustments // scaling and speed adjustments
#if MOBILE_DEVICE #if MOBILE_DEVICE
static bool auto_adjust_speed = false; static bool is_paused = true;
#else #else
static bool is_paused = false;
static bool auto_adjust_speed = true; static bool auto_adjust_speed = true;
#endif #endif
double cpu_scale_factor = 1.0; double cpu_scale_factor = 1.0;
@ -69,7 +80,8 @@ bool is_fullspeed = false;
bool alt_speed_enabled = false; bool alt_speed_enabled = false;
// misc // misc
volatile uint8_t emul_reinitialize = 0; volatile uint8_t emul_reinitialize = 1;
unsigned long emul_reinitialize_audio = 1UL;
pthread_t cpu_thread_id = 0; pthread_t cpu_thread_id = 0;
pthread_mutex_t interface_mutex = { 0 }; pthread_mutex_t interface_mutex = { 0 };
pthread_cond_t dbg_thread_cond = PTHREAD_COND_INITIALIZER; pthread_cond_t dbg_thread_cond = PTHREAD_COND_INITIALIZER;
@ -145,67 +157,77 @@ static void _timing_initialize(double scale) {
#endif #endif
} }
static inline void _lock_gui_thread(void) {
if (pthread_self() != cpu_thread_id) {
pthread_mutex_lock(&interface_mutex);
}
}
static inline void _unlock_gui_thread(void) {
if (pthread_self() != cpu_thread_id) {
pthread_mutex_unlock(&interface_mutex);
}
}
void timing_initialize(void) { void timing_initialize(void) {
_lock_gui_thread(); assert(cpu_isPaused() || (pthread_self() == cpu_thread_id));
_timing_initialize(alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor); _timing_initialize(alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor);
_unlock_gui_thread();
} }
void timing_toggle_cpu_speed(void) { void timing_toggleCPUSpeed(void) {
_lock_gui_thread(); assert(cpu_isPaused() || (pthread_self() == cpu_thread_id));
alt_speed_enabled = !alt_speed_enabled; alt_speed_enabled = !alt_speed_enabled;
timing_initialize(); timing_initialize();
_unlock_gui_thread();
} }
void timing_set_auto_adjust_speed(bool auto_adjust) { void timing_reinitializeAudio(void) {
_lock_gui_thread(); assert(cpu_isPaused() || (pthread_self() == cpu_thread_id));
auto_adjust_speed = auto_adjust; __sync_fetch_and_or(&emul_reinitialize_audio, 1UL);
timing_initialize();
_unlock_gui_thread();
} }
void cpu_pause(void) { void cpu_pause(void) {
_lock_gui_thread(); _LOCK_CPU_THREAD();
#ifdef AUDIO_ENABLED
audio_pause(); audio_pause();
#endif
is_paused = true;
}
static void _cpu_thread_really_start(void) {
int err = 0;
if ( (err = pthread_cond_signal(&cpu_thread_cond)) ) {
ERRLOG("pthread_cond_signal : %d", err);
}
} }
void cpu_resume(void) { void cpu_resume(void) {
assert(cpu_isPaused());
is_paused = false;
static pthread_once_t onceToken = PTHREAD_ONCE_INIT;
if (onceToken == PTHREAD_ONCE_INIT) {
int err = 0;
if ( (err = pthread_once(&onceToken, _cpu_thread_really_start)) ) {
ERRLOG("pthread_once : %d", err);
}
}
#ifdef AUDIO_ENABLED
audio_resume(); audio_resume();
_unlock_gui_thread(); #endif
_UNLOCK_CPU_THREAD();
} }
bool timing_should_auto_adjust_speed(void) { bool cpu_isPaused(void) {
return is_paused;
}
#if !MOBILE_DEVICE
bool timing_shouldAutoAdjustSpeed(void) {
double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor; double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor;
return auto_adjust_speed && (speed < CPU_SCALE_FASTEST); return auto_adjust_speed && (speed < CPU_SCALE_FASTEST);
} }
#endif
void *cpu_thread(void *dummyptr) { void *cpu_thread(void *dummyptr) {
assert(pthread_self() == cpu_thread_id); assert(pthread_self() == cpu_thread_id);
#ifdef AUDIO_ENABLED LOG("cpu_thread : initialized...");
audio_init();
speaker_init();
MB_Initialize();
#endif
reinitialize();
struct timespec deltat; struct timespec deltat;
#if !MOBILE_DEVICE
struct timespec disk_motor_time; struct timespec disk_motor_time;
#endif
struct timespec t0; // the target timer struct timespec t0; // the target timer
struct timespec ti, tj; // actual time samples struct timespec ti, tj; // actual time samples
bool negative = false; bool negative = false;
@ -221,13 +243,37 @@ void *cpu_thread(void *dummyptr) {
unsigned int dbg_cycles_executed = 0; unsigned int dbg_cycles_executed = 0;
#endif #endif
#if !TESTING
pthread_mutex_lock(&interface_mutex);
int err = 0;
LOG("cpu_thread : waiting for splash screen completion...");
pthread_cond_wait(&cpu_thread_cond, &interface_mutex);
pthread_mutex_unlock(&interface_mutex);
LOG("cpu_thread : starting...");
#endif
do do
{ {
#ifdef AUDIO_ENABLED
bool reinit_audio = __sync_fetch_and_and(&emul_reinitialize_audio, 0UL);
if (reinit_audio) {
speaker_destroy();
MB_Destroy();
audio_shutdown();
audio_init();
speaker_init();
MB_Initialize();
}
#endif
if (emul_reinitialize) {
reinitialize();
}
LOG("cpu_thread : begin main loop ..."); LOG("cpu_thread : begin main loop ...");
clock_gettime(CLOCK_MONOTONIC, &t0); clock_gettime(CLOCK_MONOTONIC, &t0);
emul_reinitialize = 1;
do { do {
// -LOCK----------------------------------------------------------------------------------------- SAMPLE ti // -LOCK----------------------------------------------------------------------------------------- SAMPLE ti
pthread_mutex_lock(&interface_mutex); pthread_mutex_lock(&interface_mutex);
@ -321,7 +367,8 @@ void *cpu_thread(void *dummyptr) {
pthread_mutex_unlock(&interface_mutex); pthread_mutex_unlock(&interface_mutex);
// -UNLOCK--------------------------------------------------------------------------------------- SAMPLE tj // -UNLOCK--------------------------------------------------------------------------------------- SAMPLE tj
if (timing_should_auto_adjust_speed()) { #if !MOBILE_DEVICE
if (timing_shouldAutoAdjustSpeed()) {
disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative);
assert(!negative); assert(!negative);
if (!is_fullspeed && if (!is_fullspeed &&
@ -334,6 +381,7 @@ void *cpu_thread(void *dummyptr) {
_timing_initialize(CPU_SCALE_FASTEST); _timing_initialize(CPU_SCALE_FASTEST);
} }
} }
#endif
if (!is_fullspeed) { if (!is_fullspeed) {
deltat = timespec_diff(ti, tj, &negative); deltat = timespec_diff(ti, tj, &negative);
@ -384,7 +432,8 @@ void *cpu_thread(void *dummyptr) {
#endif #endif
} }
if (timing_should_auto_adjust_speed()) { #if !MOBILE_DEVICE
if (timing_shouldAutoAdjustSpeed()) {
if (is_fullspeed && ( if (is_fullspeed && (
#ifdef AUDIO_ENABLED #ifdef AUDIO_ENABLED
speaker_isActive() || speaker_isActive() ||
@ -398,11 +447,16 @@ void *cpu_thread(void *dummyptr) {
} }
} }
} }
#endif
if (UNLIKELY(emul_reinitialize)) { if (UNLIKELY(emul_reinitialize)) {
break; break;
} }
if (UNLIKELY(emul_reinitialize_audio)) {
break;
}
if (UNLIKELY(emulator_shutting_down)) { if (UNLIKELY(emulator_shutting_down)) {
break; break;
} }
@ -411,8 +465,6 @@ void *cpu_thread(void *dummyptr) {
if (UNLIKELY(emulator_shutting_down)) { if (UNLIKELY(emulator_shutting_down)) {
break; break;
} }
reinitialize();
} while (1); } while (1);
#ifdef AUDIO_ENABLED #ifdef AUDIO_ENABLED

View File

@ -62,10 +62,7 @@ extern double cpu_altscale_factor; // scale factor #2
extern bool is_fullspeed; // emulation in full native speed? extern bool is_fullspeed; // emulation in full native speed?
extern bool alt_speed_enabled; extern bool alt_speed_enabled;
extern pthread_t cpu_thread_id; extern READONLY pthread_t cpu_thread_id;
extern pthread_mutex_t interface_mutex;
extern pthread_cond_t cpu_thread_cond;
extern pthread_cond_t dbg_thread_cond;
/* /*
* calculate the difference between two timespec structures * calculate the difference between two timespec structures
@ -75,23 +72,25 @@ struct timespec timespec_diff(struct timespec start, struct timespec end, bool *
/* /*
* toggles CPU speed between configured values * toggles CPU speed between configured values
*/ */
void timing_toggle_cpu_speed(void); void timing_toggleCPUSpeed(void);
/*
* (dis)allow automatic adjusting of CPU speed between presently configured and max (when loading disk images).
*/
void timing_set_auto_adjust_speed(bool auto_adjust);
#if !defined(MOBILE_DEVICE)
/* /*
* check whether automatic adjusting of CPU speed is configured. * check whether automatic adjusting of CPU speed is configured.
*/ */
bool timing_should_auto_adjust_speed(void); bool timing_shouldAutoAdjustSpeed(void);
#endif
/* /*
* initialize timing * initialize timing
*/ */
void timing_initialize(void); void timing_initialize(void);
/*
* force audio reinitialization
*/
void timing_reinitializeAudio(void);
/* /*
* timing/CPU thread entry point * timing/CPU thread entry point
*/ */
@ -107,6 +106,11 @@ void cpu_pause(void);
*/ */
void cpu_resume(void); void cpu_resume(void);
/*
* Is the CPU paused?
*/
bool cpu_isPaused(void);
/* /*
* checkpoints current cycle count and updates total (for timing-dependent I/O) * checkpoints current cycle count and updates total (for timing-dependent I/O)
*/ */

View File

@ -185,11 +185,11 @@ static inline void _screen_to_menu(float x, float y, OUTPARM int *col, OUTPARM i
*row = 0; *row = 0;
} }
LOG("SCREEN TO MENU : menuX:%d menuXMax:%d menuW:%d keyW:%d ... scrn:(%f,%f)->kybd:(%d,%d)", touchport.topLeftX, touchport.topLeftXMax, touchport.width, keyW, x, y, *col, *row); //LOG("SCREEN TO MENU : menuX:%d menuXMax:%d menuW:%d keyW:%d ... scrn:(%f,%f)->kybd:(%d,%d)", touchport.topLeftX, touchport.topLeftXMax, touchport.width, keyW, x, y, *col, *row);
} }
static void _increase_cpu_speed(void) { static void _increase_cpu_speed(void) {
pthread_mutex_lock(&interface_mutex); cpu_pause();
int percent_scale = (int)round(cpu_scale_factor * 100.0); int percent_scale = (int)round(cpu_scale_factor * 100.0);
if (percent_scale >= 100) { if (percent_scale >= 100) {
@ -209,15 +209,13 @@ static void _increase_cpu_speed(void) {
video_backend->animation_showCPUSpeed(); video_backend->animation_showCPUSpeed();
} }
#warning HACK TODO FIXME ... refactor timing stuff timing_initialize();
timing_toggle_cpu_speed();
timing_toggle_cpu_speed();
pthread_mutex_unlock(&interface_mutex); cpu_resume();
} }
void _decrease_cpu_speed(void) { void _decrease_cpu_speed(void) {
pthread_mutex_lock(&interface_mutex); cpu_pause();
int percent_scale = (int)round(cpu_scale_factor * 100.0); int percent_scale = (int)round(cpu_scale_factor * 100.0);
if (cpu_scale_factor == CPU_SCALE_FASTEST) { if (cpu_scale_factor == CPU_SCALE_FASTEST) {
@ -242,11 +240,9 @@ void _decrease_cpu_speed(void) {
video_backend->animation_showCPUSpeed(); video_backend->animation_showCPUSpeed();
} }
#warning HACK TODO FIXME ... refactor timing stuff timing_initialize();
timing_toggle_cpu_speed();
timing_toggle_cpu_speed();
pthread_mutex_unlock(&interface_mutex); cpu_resume();
} }
static inline bool _sprout_menu(float x, float y) { static inline bool _sprout_menu(float x, float y) {