void fade(bool fade_in, bool updatewps) { int fp_global_vol = global_settings.volume << 8; int fp_min_vol = sound_min(SOUND_VOLUME) << 8; int fp_step = (fp_global_vol - fp_min_vol) / 10; skin_get_global_state()->is_fading = !fade_in; if (fade_in) { /* fade in */ int fp_volume = fp_min_vol; /* zero out the sound */ sound_set_volume(fp_min_vol >> 8); sleep(HZ/10); /* let audio thread run */ audio_resume(); if (updatewps) update_non_static(); while (fp_volume < fp_global_vol - fp_step) { fp_volume += fp_step; sound_set_volume(fp_volume >> 8); sleep(1); } sound_set_volume(global_settings.volume); } else {
int SndOpen() { unsigned int BufferSize; unsigned int bufferStart; BufferSize = (nBurnSoundLen * nAudioChannels * AUDIO_BLOCKS)*2+512; EzxAudioBuffer= (unsigned short *)malloc(BufferSize); AudioBufferSize = nBurnSoundLen * nAudioChannels * 2; memset(EzxAudioBuffer,0,BufferSize); EzxAudioBuffer[1]=(EzxAudioBuffer[0]=(nBurnSoundLen * nAudioChannels * 2)); EzxAudioBuffer[2]=(1000000000/nBurnSoundRate)&0xFFFF; EzxAudioBuffer[3]=(1000000000/nBurnSoundRate)>>16; bufferStart = (unsigned int)&EzxAudioBuffer[4]; pOutput[0] = (short*)bufferStart; pOutput[1] = (short*)(bufferStart+1*EzxAudioBuffer[1]); pOutput[2] = (short*)(bufferStart+2*EzxAudioBuffer[1]); pOutput[3] = (short*)(bufferStart+3*EzxAudioBuffer[1]); pOutput[4] = (short*)(bufferStart+4*EzxAudioBuffer[1]); pOutput[5] = (short*)(bufferStart+5*EzxAudioBuffer[1]); pOutput[6] = (short*)(bufferStart+6*EzxAudioBuffer[1]); pOutput[7] = (short*)(bufferStart+7*EzxAudioBuffer[1]); if ( !GameMute ) { int frag = 10 + config_options.option_samplerate; frag |= 2 << 16; if (config_options.option_sound_enable==1) { dspfd = ezx_open_dsp ( nBurnSoundRate, nAudioChannels, AUDIO_FORMAT, frag ); if (dspfd >= 0) { pthread_create(&soundthread_p, NULL, &soundthread_f, NULL); return 0; } } if (config_options.option_sound_enable==2) { for(int i=0;i<NUM_BUFS;i++) buffer[i]=(unsigned char *) malloc(BUFFSIZE); SAMPLESIZE=512; //lowest value accepted by audio driver dspfd=configure(nBurnSoundRate,nAudioChannels,AUDIO_S16); } // printf("SOUND: Init done (%d)\n", dspfd); if (((dspfd > 0) && (config_options.option_sound_enable==2)) || ((dspfd>=0) && (config_options.option_sound_enable==1))) { if (config_options.option_sound_enable==2) pBurnSoundOut = (short*)pOutput[0]; if (config_options.option_sound_enable==2) audio_resume(); return 0; } else { nBurnSoundRate = 0; nBurnSoundLen = 0; } } sampletime=EZX_GetTicks(); return -1; }
void fade(bool fade_in, bool updatewps) { int fp_global_vol = global_settings.volume << 8; int fp_min_vol = sound_min(SOUND_VOLUME) << 8; int fp_step = (fp_global_vol - fp_min_vol) / 30; int i; skin_get_global_state()->is_fading = !fade_in; if (fade_in) { /* fade in */ int fp_volume = fp_min_vol; /* zero out the sound */ sound_set_volume(fp_min_vol >> 8); sleep(HZ/10); /* let audio thread run */ audio_resume(); while (fp_volume < fp_global_vol - fp_step) { fp_volume += fp_step; sound_set_volume(fp_volume >> 8); if (updatewps) { FOR_NB_SCREENS(i) skin_update(WPS, i, SKIN_REFRESH_NON_STATIC); } sleep(1); } sound_set_volume(global_settings.volume); } else {
void play_click(int sound) { int snd_bf_pointer; uae_s16 gui_volume; if (!changed_prefs.gui_volume) return; if (changed_prefs.sound_stereo!=1) return; //Only stereo implemented gui_volume = 5-changed_prefs.gui_volume; if (gui_volume<0) gui_volume=0; if (gui_volume>5) gui_volume=5; audio_resume(); for(snd_bf_pointer=0; snd_bf_pointer< (len_click_buffer[sound]-sndbufsize); snd_bf_pointer+=sndbufsize) { memcpy_volume((uae_s16 *)sndbuffer, (uae_s16 *)(click_buffer_pointer[sound]+snd_bf_pointer), sndbufsize, gui_volume); finish_sound_buffer(); } memcpy(sndbuffer, click_buffer_pointer[sound] + snd_bf_pointer, len_click_buffer[sound] - snd_bf_pointer); //The last chunk memset((char *) sndbuffer + len_click_buffer[sound]-snd_bf_pointer,0, sndbufsize -(len_click_buffer[sound]- snd_bf_pointer)); finish_sound_buffer(); clearbuffer(); audio_pause(); }
void unpause_action(bool may_fade, bool updatewps) { #if CONFIG_CODEC == SWCODEC /* Do audio first, then update, unless skin were to use its local status in which case, reverse it */ audio_resume(); if (updatewps) update_non_static(); #else if (may_fade && global_settings.fade_on_stop) fade(true, updatewps); else audio_resume(); #endif (void)may_fade; }
void ab_jump_to_A_marker(void) { #if (CONFIG_CODEC != SWCODEC) bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0; if ( ! paused ) audio_pause(); #endif audio_ff_rewind(ab_A_marker); #if (CONFIG_CODEC != SWCODEC) if ( ! paused ) audio_resume(); #endif }
/* takes care of seeking to a track in a playlist * returns false if audio isn't playing */ static bool seek(unsigned long pos) { if (!(audio_status() & AUDIO_STATUS_PLAY)) { return false; } else { #if (CONFIG_CODEC == SWCODEC) audio_pre_ff_rewind(); audio_ff_rewind(pos); #else audio_pause(); audio_ff_rewind(pos); audio_resume(); #endif return true; } }
static int play(void* output_samples,int num_bytes,int flags) { int wrote, b_digital; SInt32 exit_reason; // Check whether we need to reset the digital output stream. if (ao->b_digital && ao->b_stream_format_changed) { ao->b_stream_format_changed = 0; b_digital = AudioStreamSupportsDigital(ao->i_stream_id); if (b_digital) { /* Current stream supports digital format output, let's set it. */ ao_msg(MSGT_AO, MSGL_V, "Detected current stream supports digital, try to restore digital output...\n"); if (!AudioStreamChangeFormat(ao->i_stream_id, ao->stream_format)) { ao_msg(MSGT_AO, MSGL_WARN, "Restoring digital output failed.\n"); } else { ao_msg(MSGT_AO, MSGL_WARN, "Restoring digital output succeeded.\n"); reset(); } } else ao_msg(MSGT_AO, MSGL_V, "Detected current stream does not support digital.\n"); } wrote=write_buffer(output_samples, num_bytes); audio_resume(); do { exit_reason = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, true); } while (exit_reason == kCFRunLoopRunHandledSource); return wrote; }
int psp_main_menu(void) { gp2xCtrlData c; long new_pad; long old_pad; int last_time; int end_menu; audio_pause(); cap32_save_back_to_blit(); psp_kbd_wait_no_button(); old_pad = 0; last_time = 0; end_menu = 0; while (! end_menu) { psp_display_screen_menu(); psp_sdl_flip(); while (1) { gp2xCtrlReadBufferPositive(&c, 1); c.Buttons &= PSP_ALL_BUTTON_MASK; if (c.Buttons) break; } new_pad = c.Buttons; if ((old_pad != new_pad) || ((c.TimeStamp - last_time) > PSP_MENU_MIN_TIME)) { last_time = c.TimeStamp; old_pad = new_pad; } else continue; if ((c.Buttons & GP2X_CTRL_LTRIGGER) == GP2X_CTRL_LTRIGGER) { psp_settings_menu(); old_pad = new_pad = 0; } else if ((c.Buttons & GP2X_CTRL_RTRIGGER) == GP2X_CTRL_RTRIGGER) { psp_main_menu_reset(); end_menu = 1; } else if ((new_pad == GP2X_CTRL_LEFT ) || (new_pad == GP2X_CTRL_RIGHT) || (new_pad == GP2X_CTRL_CROSS) || (new_pad == GP2X_CTRL_CIRCLE)) { int step = 0; if (new_pad & GP2X_CTRL_RIGHT) { step = 1; } else if (new_pad & GP2X_CTRL_LEFT) { step = -1; } switch (cur_menu_id ) { case MENU_LOAD_SLOT : if (step) psp_main_menu_cur_slot(step); else if (psp_main_menu_load_slot()) end_menu = 1; break; case MENU_SAVE_SLOT : if (step) psp_main_menu_cur_slot(step); else psp_main_menu_save_slot(); break; case MENU_DEL_SLOT : if (step) psp_main_menu_cur_slot(step); else psp_main_menu_del_slot(); break; case MENU_LOAD_SNA : if (psp_main_menu_load(FMGR_FORMAT_SNA, 0)) end_menu = 1; old_pad = new_pad = 0; break; case MENU_LOAD_DSKA : if (psp_main_menu_load(FMGR_FORMAT_DSK, 'A')) { if (CPC.psp_explore_disk == CPC_EXPLORE_LOAD) { if (psp_disk_menu()) { end_menu = 1; } } else if (CPC.psp_explore_disk >= CPC_EXPLORE_AUTO) { if (psp_disk_auto()) { end_menu = 1; } } } old_pad = new_pad = 0; break; case MENU_LOAD_DSKB : psp_main_menu_load(FMGR_FORMAT_DSK, 'B'); old_pad = new_pad = 0; break; case MENU_COMMAND : if (step) psp_main_menu_cur_command(step); else { psp_main_menu_command(); end_menu = 1; } break; case MENU_EDITOR : psp_main_menu_editor(); old_pad = new_pad = 0; break; case MENU_CHEATS : psp_cheat_menu(); old_pad = new_pad = 0; break; case MENU_KEYBOARD : psp_keyboard_menu(); old_pad = new_pad = 0; break; case MENU_JOYSTICK : psp_joystick_menu(); old_pad = new_pad = 0; break; case MENU_SETTINGS : psp_settings_menu(); old_pad = new_pad = 0; break; case MENU_SCREENSHOT : psp_main_menu_screenshot(); end_menu = 1; break; case MENU_RESET : psp_main_menu_reset(); end_menu = 1; break; case MENU_BACK : end_menu = 1; break; case MENU_EXIT : psp_main_menu_exit(); break; case MENU_HELP : psp_help_menu(); old_pad = new_pad = 0; break; } } else if(new_pad & GP2X_CTRL_UP) { if (cur_menu_id > 0) cur_menu_id--; else cur_menu_id = MAX_MENU_ITEM-1; } else if(new_pad & GP2X_CTRL_DOWN) { if (cur_menu_id < (MAX_MENU_ITEM-1)) cur_menu_id++; else cur_menu_id = 0; } else if(new_pad & GP2X_CTRL_SQUARE) { /* Cancel */ end_menu = -1; } else if((new_pad & GP2X_CTRL_SELECT) == GP2X_CTRL_SELECT) { /* Back to CPC */ end_menu = 1; } } psp_kbd_wait_no_button(); psp_sdl_clear_screen( PSP_MENU_BLACK_COLOR ); psp_sdl_flip(); psp_sdl_clear_screen( PSP_MENU_BLACK_COLOR ); psp_sdl_flip(); psp_sdl_clear_blit(0); audio_resume(); return 1; }
/* * Here's where all the action takes place! */ void real_main (int argc, char **argv) { show_version (); #if defined (NATMEM_OFFSET) if (NATMEM_OFFSET == 0 && sizeof (void*) < 8) { write_log ("NATMEM_OFFSET is 0; I hope you used 'uae-preloader' to load me, or else ...\n"); } #endif #ifdef FILESYS currprefs.mountinfo = changed_prefs.mountinfo = &options_mountinfo; #endif restart_program = 1; #ifdef _WIN32 sprintf (restart_config, "%sConfigurations\\", start_path); #endif strcat (restart_config, OPTIONSFILENAME); /* Initial state is stopped */ uae_target_state = UAE_STATE_STOPPED; while (uae_target_state != UAE_STATE_QUITTING) { int want_gui; set_state (uae_target_state); do_preinit_machine (argc, argv); /* Should we open the GUI? TODO: This mess needs to go away */ want_gui = currprefs.start_gui; if (restart_program == 2) want_gui = 0; else if (restart_program == 3) want_gui = 1; changed_prefs = currprefs; if (want_gui) { /* Handle GUI at start-up */ int err = gui_open (); if (err >= 0) { do { gui_handle_events (); uae_msleep (10); } while (!uae_state_change_pending ()); } else if (err == - 1) { if (restart_program == 3) { restart_program = 0; uae_quit (); } } else uae_quit (); currprefs = changed_prefs; fix_options (); inputdevice_init (); } restart_program = 0; if (uae_target_state == UAE_STATE_QUITTING) break; uae_target_state = UAE_STATE_COLD_START; /* Start emulator proper. */ if (!do_init_machine ()) break; while (uae_target_state != UAE_STATE_QUITTING && uae_target_state != UAE_STATE_STOPPED) { /* Reset */ set_state (uae_target_state); do_reset_machine (uae_state == UAE_STATE_COLD_START); /* Running */ uae_target_state = UAE_STATE_RUNNING; /* * Main Loop */ do { set_state (uae_target_state); /* Run emulator. */ do_run_machine (); if (uae_target_state == UAE_STATE_PAUSED) { /* Paused */ set_state (uae_target_state); audio_pause (); /* While UAE is paused we have to handle * input events, etc. ourselves. */ do { gui_handle_events (); handle_events (); /* Manually pump input device */ inputdevicefunc_keyboard.read (); inputdevicefunc_mouse.read (); inputdevicefunc_joystick.read (); inputdevice_handle_inputcode (); /* Don't busy wait. */ uae_msleep (10); } while (!uae_state_change_pending ()); audio_resume (); } } while (uae_target_state == UAE_STATE_RUNNING); /* * End of Main Loop * * We're no longer running or paused. */ set_inhibit_frame (IHF_QUIT_PROGRAM); #ifdef FILESYS /* Ensure any cached changes to virtual filesystem are flushed before * resetting or exitting. */ filesys_prepare_reset (); #endif } /* while (!QUITTING && !STOPPED) */ do_exit_machine (); /* TODO: This stuff is a hack. What we need to do is * check whether a config GUI is available. If not, * then quit. */ restart_program = 3; } zfile_exit (); }
void SACM_Resume(void) { audio_resume(&__gaudio); }
static void *cpu_thread(void *dummyptr) { #ifndef NDEBUG // Spamsung Galaxy Y running Gingerbread triggers this, wTf?! ASSERT_ON_CPU_THREAD(); #endif LOG("cpu_thread : initialized..."); struct timespec deltat = { 0 }; struct timespec disk_motor_time = { 0 }; struct timespec t0 = { 0 }; // the target timer struct timespec ti = { 0 }; // actual before time sample struct timespec tj = { 0 }; // actual after time sample bool negative = false; long drift_adj_nsecs = 0; // generic drift adjustment between target and actual int debugging_cycles = 0; unsigned long dbg_ticks = 0; #if DEBUG_TIMING int speaker_neg_feedback = 0; int speaker_pos_feedback = 0; unsigned long dbg_cycles_executed = 0; #endif audio_init(); speaker_init(); MB_Initialize(); run_args.emul_reinitialize = 1; cpu_runloop: do { LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", (unsigned long)cpu_thread_id); pthread_mutex_lock(&interface_mutex); if (emul_reinitialize_audio) { emul_reinitialize_audio = false; speaker_destroy(); extern void MB_SoftDestroy(void); MB_SoftDestroy(); audio_shutdown(); audio_init(); speaker_init(); extern void MB_SoftInitialize(void); MB_SoftInitialize(); } pthread_mutex_unlock(&interface_mutex); LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ..."); if (run_args.emul_reinitialize) { reinitialize(); } LOG("cpu_thread : begin main loop ..."); clock_gettime(CLOCK_MONOTONIC, &t0); do { ////SCOPE_TRACE_CPU("CPU mainloop"); // -LOCK----------------------------------------------------------------------------------------- SAMPLE ti if (UNLIKELY(emul_pause_audio)) { emul_pause_audio = false; audio_pause(); } pthread_mutex_lock(&interface_mutex); if (UNLIKELY(emul_resume_audio)) { emul_resume_audio = false; audio_resume(); } if (UNLIKELY(emul_video_dirty)) { emul_video_dirty = false; video_setDirty(A2_DIRTY_FLAG); } clock_gettime(CLOCK_MONOTONIC, &ti); deltat = timespec_diff(t0, ti, &negative); if (deltat.tv_sec) { if (!is_fullspeed) { TIMING_LOG("NOTE : serious divergence from target time ..."); } t0 = ti; deltat = timespec_diff(t0, ti, &negative); } t0 = timespec_add(t0, EXECUTION_PERIOD_NSECS); // expected interval drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec; // set up increment & decrement counters run_args.cpu65_cycles_to_execute = (cycles_persec_target / 1000); // cycles_persec_target * EXECUTION_PERIOD_NSECS / NANOSECONDS_PER_SECOND if (!is_fullspeed) { run_args.cpu65_cycles_to_execute += cycles_speaker_feedback; } if (run_args.cpu65_cycles_to_execute < 0) { run_args.cpu65_cycles_to_execute = 0; } MB_StartOfCpuExecute(); if (is_debugging) { debugging_cycles = run_args.cpu65_cycles_to_execute; } do { if (is_debugging) { run_args.cpu65_cycles_to_execute = 1; } run_args.cpu65_cycle_count = 0; cycles_checkpoint_count = 0; cpu65_run(&run_args); // run emulation for cpu65_cycles_to_execute cycles ... #if DEBUG_TIMING dbg_cycles_executed += run_args.cpu65_cycle_count; #endif if (is_debugging) { debugging_cycles -= run_args.cpu65_cycle_count; timing_checkpointCycles(); if (c_debugger_should_break() || (debugging_cycles <= 0)) { int err = 0; if ((err = pthread_cond_signal(&dbg_thread_cond))) { LOG("pthread_cond_signal : %d", err); } if ((err = pthread_cond_wait(&cpu_thread_cond, &interface_mutex))) { LOG("pthread_cond_wait : %d", err); } if (debugging_cycles <= 0) { break; } } if (run_args.emul_reinitialize) { pthread_mutex_unlock(&interface_mutex); goto cpu_runloop; } } } while (is_debugging); MB_UpdateCycles(); // TODO : modularize MB and other peripheral card cycles/interrupts ... speaker_flush(); // play audio TRACE_CPU_BEGIN("advance scanner"); video_scannerUpdate(); TRACE_CPU_END(); clock_gettime(CLOCK_MONOTONIC, &tj); pthread_mutex_unlock(&interface_mutex); // -UNLOCK--------------------------------------------------------------------------------------- SAMPLE tj if (timing_shouldAutoAdjustSpeed() && !is_fullspeed) { disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); if (UNLIKELY(negative)) { LOG("WHOA... time went backwards #1! Did you just cross a timezone?"); disk_motor_time.tv_sec = 1; } if (!speaker_isActive() && !video_isDirty(A2_DIRTY_FLAG) && (disk6.disk[disk6.drive].file_name != NULL) && !disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS) ) { TIMING_LOG("auto switching to full speed"); _timing_initialize(CPU_SCALE_FASTEST); } } if (!is_fullspeed) { deltat = timespec_diff(ti, tj, &negative); if (UNLIKELY(negative)) { LOG("WHOA... time went backwards #2! Did you just cross a timezone?"); deltat.tv_sec = 1; } long sleepfor = 0; if (LIKELY(!deltat.tv_sec)) { sleepfor = EXECUTION_PERIOD_NSECS - drift_adj_nsecs - deltat.tv_nsec; } if (sleepfor <= 0) { // lagging ... static time_t throttle_warning = 0; if (t0.tv_sec - throttle_warning > 0) { TIMING_LOG("not sleeping to catch up ... %ld . %ld", deltat.tv_sec, deltat.tv_nsec); throttle_warning = t0.tv_sec; } } else { deltat.tv_sec = 0; deltat.tv_nsec = sleepfor; ////TRACE_CPU_BEGIN("sleep"); nanosleep(&deltat, NULL); ////TRACE_CPU_END(); } #if DEBUG_TIMING // collect timing statistics if (speaker_neg_feedback > cycles_speaker_feedback) { speaker_neg_feedback = cycles_speaker_feedback; } if (speaker_pos_feedback < cycles_speaker_feedback) { speaker_pos_feedback = cycles_speaker_feedback; } if ((dbg_ticks % NANOSECONDS_PER_SECOND) == 0) { TIMING_LOG("tick:(%ld.%ld) real:(%ld.%ld) cycles exe: %d ... speaker feedback: %d/%d", t0.tv_sec, t0.tv_nsec, ti.tv_sec, ti.tv_nsec, dbg_cycles_executed, speaker_neg_feedback, speaker_pos_feedback); dbg_cycles_executed = 0; speaker_neg_feedback = 0; speaker_pos_feedback = 0; } #endif if ((dbg_ticks % NANOSECONDS_PER_SECOND) == 0) { dbg_ticks = 0; } } if (timing_shouldAutoAdjustSpeed() && is_fullspeed) { disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); if (UNLIKELY(negative)) { LOG("WHOA... time went backwards #3! Did you just cross a timezone?"); disk_motor_time.tv_sec = 1; } if (speaker_isActive() || video_isDirty(A2_DIRTY_FLAG) || (disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS)) ) { double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor; if (speed <= CPU_SCALE_FASTEST_PIVOT) { TIMING_LOG("auto switching to configured speed"); _timing_initialize(speed); } } } if (UNLIKELY(run_args.emul_reinitialize)) { break; } if (UNLIKELY(emul_reinitialize_audio)) { break; } if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); speaker_destroy(); MB_Destroy(); audio_shutdown(); cpu_thread_id = 0; cpu_pause(); disk6_eject(0); disk6_eject(1); return NULL; }
static javacall_result video_resume(javacall_handle handle) { return audio_resume(handle); }
static void *cpu_thread(void *dummyptr) { assert(pthread_self() == cpu_thread_id); LOG("cpu_thread : initialized..."); struct timespec deltat; #if !MOBILE_DEVICE struct timespec disk_motor_time; #endif struct timespec t0; // the target timer struct timespec ti, tj; // actual time samples bool negative = false; long drift_adj_nsecs = 0; // generic drift adjustment between target and actual int debugging_cycles0 = 0; int debugging_cycles = 0; #if DEBUG_TIMING unsigned long dbg_ticks = 0; int speaker_neg_feedback = 0; int speaker_pos_feedback = 0; unsigned int dbg_cycles_executed = 0; #endif do { #ifdef AUDIO_ENABLED LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", cpu_thread_id); pthread_mutex_lock(&interface_mutex); if (emul_reinitialize_audio) { emul_reinitialize_audio = false; speaker_destroy(); MB_Destroy(); audio_shutdown(); audio_init(); speaker_init(); MB_Initialize(); } pthread_mutex_unlock(&interface_mutex); LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ..."); #endif if (emul_reinitialize) { reinitialize(); } LOG("cpu_thread : begin main loop ..."); clock_gettime(CLOCK_MONOTONIC, &t0); do { SCOPE_TRACE_CPU("CPU mainloop"); // -LOCK----------------------------------------------------------------------------------------- SAMPLE ti #ifdef AUDIO_ENABLED if (UNLIKELY(emul_pause_audio)) { emul_pause_audio = false; audio_pause(); } #endif pthread_mutex_lock(&interface_mutex); #ifdef AUDIO_ENABLED if (UNLIKELY(emul_resume_audio)) { emul_resume_audio = false; audio_resume(); } #endif clock_gettime(CLOCK_MONOTONIC, &ti); deltat = timespec_diff(t0, ti, &negative); if (deltat.tv_sec) { if (!is_fullspeed) { TIMING_LOG("NOTE : serious divergence from target time ..."); } t0 = ti; deltat = timespec_diff(t0, ti, &negative); } t0 = timespec_add(t0, EXECUTION_PERIOD_NSECS); // expected interval drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec; // set up increment & decrement counters cpu65_cycles_to_execute = (cycles_persec_target / 1000); // cycles_persec_target * EXECUTION_PERIOD_NSECS / NANOSECONDS_PER_SECOND if (!is_fullspeed) { cpu65_cycles_to_execute += cycles_speaker_feedback; } if (cpu65_cycles_to_execute < 0) { cpu65_cycles_to_execute = 0; } #ifdef AUDIO_ENABLED MB_StartOfCpuExecute(); #endif if (is_debugging) { debugging_cycles0 = cpu65_cycles_to_execute; debugging_cycles = cpu65_cycles_to_execute; } do { if (is_debugging) { cpu65_cycles_to_execute = 1; } cpu65_cycle_count = 0; cycles_checkpoint_count = 0; cpu65_run(); // run emulation for cpu65_cycles_to_execute cycles ... if (is_debugging) { debugging_cycles -= cpu65_cycle_count; if (c_debugger_should_break() || (debugging_cycles <= 0)) { int err = 0; if ((err = pthread_cond_signal(&dbg_thread_cond))) { ERRLOG("pthread_cond_signal : %d", err); } if ((err = pthread_cond_wait(&cpu_thread_cond, &interface_mutex))) { ERRLOG("pthread_cond_wait : %d", err); } if (debugging_cycles <= 0) { cpu65_cycle_count = debugging_cycles0 - debugging_cycles/*<=0*/; break; } } } if (emul_reinitialize) { reinitialize(); } } while (is_debugging); #if DEBUG_TIMING dbg_cycles_executed += cpu65_cycle_count; #endif g_dwCyclesThisFrame += cpu65_cycle_count; #ifdef AUDIO_ENABLED MB_UpdateCycles(); // update 6522s (NOTE: do this before updating cycles_count_total) #endif timing_checkpoint_cycles(); #if CPU_TRACING cpu65_trace_checkpoint(); #endif #ifdef AUDIO_ENABLED speaker_flush(); // play audio #endif if (g_dwCyclesThisFrame >= dwClksPerFrame) { g_dwCyclesThisFrame -= dwClksPerFrame; #ifdef AUDIO_ENABLED MB_EndOfVideoFrame(); #endif } clock_gettime(CLOCK_MONOTONIC, &tj); pthread_mutex_unlock(&interface_mutex); // -UNLOCK--------------------------------------------------------------------------------------- SAMPLE tj #if !MOBILE_DEVICE if (timing_shouldAutoAdjustSpeed()) { disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); assert(!negative); if (!is_fullspeed && #ifdef AUDIO_ENABLED !speaker_isActive() && #endif !video_isDirty() && (!disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS)) ) { TIMING_LOG("auto switching to full speed"); _timing_initialize(CPU_SCALE_FASTEST); } } #endif if (!is_fullspeed) { deltat = timespec_diff(ti, tj, &negative); assert(!negative); long sleepfor = 0; if (!deltat.tv_sec) { sleepfor = EXECUTION_PERIOD_NSECS - drift_adj_nsecs - deltat.tv_nsec; } if (sleepfor <= 0) { // lagging ... static time_t throttle_warning = 0; if (t0.tv_sec - throttle_warning > 0) { TIMING_LOG("not sleeping to catch up ... %ld . %ld", deltat.tv_sec, deltat.tv_nsec); throttle_warning = t0.tv_sec; } } else { deltat.tv_sec = 0; deltat.tv_nsec = sleepfor; TRACE_CPU_BEGIN("sleep"); nanosleep(&deltat, NULL); TRACE_CPU_END(); } #if DEBUG_TIMING // collect timing statistics if (speaker_neg_feedback > cycles_speaker_feedback) { speaker_neg_feedback = cycles_speaker_feedback; } if (speaker_pos_feedback < cycles_speaker_feedback) { speaker_pos_feedback = cycles_speaker_feedback; } dbg_ticks += EXECUTION_PERIOD_NSECS; if ((dbg_ticks % NANOSECONDS_PER_SECOND) == 0) { TIMING_LOG("tick:(%ld.%ld) real:(%ld.%ld) cycles exe: %d ... speaker feedback: %d/%d", t0.tv_sec, t0.tv_nsec, ti.tv_sec, ti.tv_nsec, dbg_cycles_executed, speaker_neg_feedback, speaker_pos_feedback); dbg_cycles_executed = 0; dbg_ticks = 0; speaker_neg_feedback = 0; speaker_pos_feedback = 0; } #endif } #if !MOBILE_DEVICE if (timing_shouldAutoAdjustSpeed()) { if (is_fullspeed && ( #ifdef AUDIO_ENABLED speaker_isActive() || #endif video_isDirty() || (disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS))) ) { double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor; if (speed < CPU_SCALE_FASTEST) { TIMING_LOG("auto switching to configured speed"); _timing_initialize(speed); } } } #endif if (UNLIKELY(emul_reinitialize)) { break; } #ifdef AUDIO_ENABLED if (UNLIKELY(emul_reinitialize_audio)) { break; } #endif if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); #ifdef AUDIO_ENABLED speaker_destroy(); MB_Destroy(); audio_shutdown(); #endif return NULL; }