mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-09-29 08:55:06 +00:00
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:
parent
fa1de4dee7
commit
a0cadc83c6
@ -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) {
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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*/);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
20
src/keys.c
20
src/keys.c
@ -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
|
||||||
|
@ -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
|
||||||
|
130
src/timing.c
130
src/timing.c
@ -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
|
||||||
|
26
src/timing.h
26
src/timing.h
@ -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)
|
||||||
*/
|
*/
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user