From f2f7ef3fe9ac8333b1db09b023dac191ed4736fb Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 17:07:26 -0500 Subject: Fix Tools/Global hotkeys/* refusing to work by touch. --- source/nds/gui.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 09e01ac..9dfe95b 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -3727,7 +3727,6 @@ u32 menu(u16 *screen) && current_menu != ((main_menu.options +1)->sub_menu->options + 3)->sub_menu && current_menu != (main_menu.options +3)->sub_menu && current_menu != ((main_menu.options +3)->sub_menu->options + 1)->sub_menu - && current_menu != ((main_menu.options +3)->sub_menu->options + 2)->sub_menu && current_menu != (main_menu.options +6)->sub_menu && current_menu != ((main_menu.options +6)->sub_menu->options + 2)->sub_menu) { -- cgit v1.2.3 From 365a69d72ebfc986a59d269359bf04f53a18a8e5 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 19:44:37 -0500 Subject: Release 1.24. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 9dfe95b..93b3e7b 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.23" +#define NDSSFC_VERSION "1.24" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From dded2161378bdf0ead156f47f2473872854fc129 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 20:31:11 -0500 Subject: Turn off the lower screen's backlight when returning from suspend during emulation. --- source/nds/entry.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 13486b0..45360a8 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -1081,6 +1081,10 @@ unsigned int S9xReadJoypad (int which1) mdelay(1); } while (inputdata.key & KEY_LID); ds2_wakeup(); + // Before starting to emulate again, turn off the lower + // screen's backlight. + mdelay(100); // needed to avoid ds2_setBacklight crashing + ds2_setBacklight(2); set_cpu_clock(clock_speed_number); } -- cgit v1.2.3 From 362b28e9372d124ac6602bfc49e9775e510ba929 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 27 Jan 2013 00:30:48 -0500 Subject: Suspend on lid-close in the menu. --- source/nds/gui.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 93b3e7b..ece310c 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -324,6 +324,21 @@ gui_action_type get_gui_input(void) key = getKey(); + if (key & KEY_LID) + { + ds2_setSupend(); + struct key_buf inputdata; + do { + ds2_getrawInput(&inputdata); + mdelay(1); + } while (inputdata.key & KEY_LID); + ds2_wakeup(); + // In the menu, the lower screen's backlight needs to be on, + // and it is on right away after resuming from suspend. + // mdelay(100); // needed to avoid ds2_setBacklight crashing + // ds2_setBacklight(3); + } + switch(key) { case KEY_UP: -- cgit v1.2.3 From cfa1c811c65f1b8a10d9034a5974d617cda92ec6 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 27 Jan 2013 00:45:59 -0500 Subject: Reimplement Quicksort correctly for file selection screens. Before this commit, the emulator could sometimes give a file out of its order, for example an O* file between two S* files. --- source/nds/gui.c | 69 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index ece310c..c57c660 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -435,53 +435,52 @@ void change_ext(char *src, char *buffer, char *extension) --------------------------------------------------------*/ static int sort_function(const void *dest_str_ptr, const void *src_str_ptr) { - char *dest_str = *((char **)dest_str_ptr); - char *src_str = *((char **)src_str_ptr); + char *dest_str = ((char *)dest_str_ptr); + char *src_str = ((char *)src_str_ptr); // For files and directories, . and .. sort first. - if(src_str[0] == '.') + if(src_str[0] == '.' && dest_str[0] != '.') return 1; - if(dest_str[0] == '.') + if(dest_str[0] == '.' && src_str[0] != '.') return -1; return strcasecmp(dest_str, src_str); } -static int my_array_partion(void *array, int left, int right) +static int my_array_partion(void **array, int left, int right) { - unsigned int pivot= *((unsigned int*)array + left); - - while(left < right) - { - while(sort_function((void*)((unsigned int*)array+left), (void*)((unsigned int *)array+right)) < 0) { - right--; - } - - if(right== left) break; - *((unsigned int*)array + left) = *((unsigned int*)array + right); - *((unsigned int*)array + right) = pivot; - - if(left < right) - { - left++; - if(right== left) break; - } - - while(sort_function((void*)((unsigned int*)array+right), (void*)((unsigned int *)array+left)) > 0) { - left++; - } + // Choose a pivot, left <= pivot <= right + unsigned int pivotIndex = left + (right - left) / 2; + + // Move pivot value to the end + void *temp = array[pivotIndex]; + array[pivotIndex] = array[right]; + array[right] = temp; + + // Move values that sort before the pivot value to before the new + // pivot's location + unsigned int storeIndex = left, i; + for (i = left; i <= right - 1; i++) + { + if (sort_function(array[i], array[right]) < 0) + { + temp = array[i]; + array[i] = array[storeIndex]; + array[storeIndex] = temp; + storeIndex++; + } + } - if(left== right) break; - *((unsigned int*)array + right) = *((unsigned int*)array + left); - *((unsigned int*)array + left) = pivot; - right--; - } + // Move the pivot value to its correct location + temp = array[storeIndex]; + array[storeIndex] = array[right]; + array[right] = temp; - return left; + return storeIndex; } -static void my_qsort(void *array, int left, int right) +static void my_qsort(void **array, int left, int right) { if(left < right) { @@ -748,9 +747,9 @@ static int load_file_list(struct FILE_LIST_INFO *filelist_infop) #if 0 my_qsort((void *)file_list, 0, num_files-1); #else //to support ".." directory, but take it as file - my_qsort((void *)file_list, 1, num_files-1); + my_qsort((void **)file_list, 1, num_files-1); #endif - my_qsort((void *)dir_list, 0, num_dirs-1); + my_qsort((void **)dir_list, 0, num_dirs-1); return 0; } -- cgit v1.2.3 From f0fab191e48f165c551980d724bba2f26a764795 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 29 Jan 2013 22:24:20 -0500 Subject: Prevent a file descriptor becoming unusable if the emulator configuration file is not in the correct format. --- source/nds/gui.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index c57c660..fd9007b 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -4335,6 +4335,10 @@ int load_emu_config_file(void) fclose(fp); return 0; } + else + { + fclose(fp); + } } //have no confiure file, set default -- cgit v1.2.3 From 60f6ffcc701c4175e31d90f950fb34f6b07a1712 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 00:36:51 -0500 Subject: When starting CATSFC, assume the backlights are both on, so don't delay 100 milliseconds and set both backlights to on. --- source/nds/entry.cpp | 4 +++- source/nds/gui.c | 10 ++++++---- source/nds/gui.h | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 45360a8..949cecf 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -540,6 +540,7 @@ int sfc_main (int argc, char **argv) #endif Settings.Paused = 1; + bool8 FirstInvocation = TRUE; while (1) { @@ -564,7 +565,8 @@ int sfc_main (int argc, char **argv) unsigned short screen[256*192]; copy_screen((void*)screen, up_screen_addr, 0, 0, 256, 192); - menu(screen); + menu(screen, FirstInvocation); + FirstInvocation = FALSE; game_disableAudio(); Settings.Paused = 0; } diff --git a/source/nds/gui.c b/source/nds/gui.c index fd9007b..b529b9f 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1682,7 +1682,7 @@ unsigned int frame_interval; /*-------------------------------------------------------- Main Menu --------------------------------------------------------*/ -u32 menu(u16 *screen) +u32 menu(u16 *screen, bool8 FirstInvocation) { gui_action_type gui_action; u32 i; @@ -3568,9 +3568,11 @@ u32 menu(u16 *screen) //----------------------------------------------------------------------------// // Menu Start ds2_setCPUclocklevel(0); - mdelay(100); // to prevent ds2_setBacklight() from crashing - ds2_setBacklight(3); - + if (!FirstInvocation) + { // assume that the backlight is already at 3 when the emulator starts + mdelay(100); // to prevent ds2_setBacklight() from crashing + ds2_setBacklight(3); + } wait_Allkey_release(0); bg_screenp= (u16*)malloc(256*192*2); diff --git a/source/nds/gui.h b/source/nds/gui.h index 87c14e4..482ceec 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -124,7 +124,7 @@ extern GAME_CONFIG game_config; /****************************************************************************** ******************************************************************************/ extern void gui_init(u32 lang_id); -extern u32 menu(u16 *original_screen); +extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern void game_disableAudio(); extern void game_set_frameskip(); extern void set_cpu_clock(u32 num); -- cgit v1.2.3 From 58a3dc9b1762ef0b1b12090d1b707a7f7fc9d9f9 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 06:10:57 -0500 Subject: Hook fast-forward into Settings.TurboSkipFrames. --- source/nds/entry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 949cecf..6fab5fc 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -403,7 +403,7 @@ void init_sfc_setting(void) #endif Settings.ApplyCheats = TRUE; Settings.TurboMode = FALSE; - Settings.TurboSkipFrames = 40; + Settings.TurboSkipFrames = 10; Settings.StretchScreenshots = 1; Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; @@ -608,7 +608,7 @@ void S9xSyncSpeed () sync_last = syncnow; sync_next = syncnow; - if(++skip_rate < 10) + if(++skip_rate < Settings.TurboSkipFrames) IPPU.RenderThisFrame = false; else { -- cgit v1.2.3 From 58948ffd1d05084f3d84bc12a2e75144741b292c Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 06:11:59 -0500 Subject: Make the audio timing more precise. * Fake out the buffer timing by sending a buffer full of silence when returning from pause. Reduces crackling introduced by the next point. * Send buffers only once every 23.22 milliseconds, not up to four buffers at once (92.88 milliseconds) and randomly thereafter. Reduces note-length jumpiness. * Audio may have trouble catching up if external jitter reaches 11.61 milliseconds. That happens if Mode 7 images or filtered modes take a long time to render, or if chips take a long time to execute. --- source/nds/entry.cpp | 216 +++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 95 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 6fab5fc..c0c8efa 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -677,6 +677,7 @@ void S9xSyncSpeed () skip_rate = 0; ds2_setCPUclocklevel(0); if (syncdif > 0) + // TODO Turn this delay into a ProcessSound loop? udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); set_cpu_clock(clock_speed_number); S9xProcessSound (0); @@ -709,6 +710,7 @@ void S9xSyncSpeed () if (syncdif > 0) { ds2_setCPUclocklevel(0); + // TODO Turn this delay into a ProcessSound loop? udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); set_cpu_clock(clock_speed_number); S9xProcessSound (0); @@ -903,6 +905,9 @@ void S9xGenerateSound () } } +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +unsigned int LastSoundEmissionTime = 0; + void S9xProcessSound (unsigned int) { unsigned short *audiobuff; @@ -910,143 +915,164 @@ void S9xProcessSound (unsigned int) if (so.mute_sound || !game_enable_audio) return; - if(ds2_checkAudiobuff() > 4) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT / 2) + { + LastSoundEmissionTime++; return; + } - /* Number of samples to generate now */ - int sample_count; - sample_count = so.buffer_size; -#ifndef FOREVER_16_BIT_SOUND - if (so.sixteen_bit) + unsigned int Now = getSysTime(); + if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { + if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */) + { + LastSoundEmissionTime = Now; + // We were probably paused. Restart sending sound with an + // empty buffer. + do { + audiobuff = (unsigned short*)ds2_getAudiobuff(); + } while (audiobuff == NULL); //There are audio queue in sending or wait to send + + memset(audiobuff, 0, DS2_BUFFER_SIZE); + + ds2_updateAudio(); + // And then the real audio. (fall through) + } + else + { + LastSoundEmissionTime += SOUND_EMISSION_INTERVAL; + } + /* Number of samples to generate now */ + int sample_count = so.buffer_size; +#ifndef FOREVER_16_BIT_SOUND + if (so.sixteen_bit) + { #endif - /* to prevent running out of buffer space, - * create less samples - */ - sample_count >>= 1; + /* to prevent running out of buffer space, + * create less samples + */ + sample_count >>= 1; #ifndef FOREVER_16_BIT_SOUND - } + } #endif - audiobuff = (unsigned short*)ds2_getAudiobuff(); - if(NULL == audiobuff) //There are audio queue in sending or wait to send - { - return; - } + do { + audiobuff = (unsigned short*)ds2_getAudiobuff(); + } while (audiobuff == NULL); //There are audio queue in sending or wait to send - /* If we need more audio samples */ - if (so.samples_mixed_so_far < sample_count) - { - /* Where to put the samples to */ + /* If we need more audio samples */ + if (so.samples_mixed_so_far < sample_count) + { + /* Where to put the samples to */ #ifndef FOREVER_16_BIT_SOUND - unsigned byte_offset = (so.play_position + - (so.sixteen_bit ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far)) & SOUND_BUFFER_SIZE_MASK; + unsigned byte_offset = (so.play_position + + (so.sixteen_bit ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far)) & SOUND_BUFFER_SIZE_MASK; #else - unsigned byte_offset = (so.play_position + - (so.samples_mixed_so_far << 1)) & SOUND_BUFFER_SIZE_MASK; + unsigned byte_offset = (so.play_position + + (so.samples_mixed_so_far << 1)) & SOUND_BUFFER_SIZE_MASK; #endif - //printf ("%d:", sample_count - so.samples_mixed_so_far); fflush (stdout); - if (Settings.SoundSync == 2) - { - /*memset (Buf + (byte_offset & SOUND_BUFFER_SIZE_MASK), 0, - sample_count - so.samples_mixed_so_far);*/ - } - else - { - /* Mix the missing samples */ + if (Settings.SoundSync == 2) + { + /*memset (Buf + (byte_offset & SOUND_BUFFER_SIZE_MASK), 0, + sample_count - so.samples_mixed_so_far);*/ + } + else + { + /* Mix the missing samples */ #ifndef FOREVER_16_BIT_SOUND - int bytes_so_far = so.sixteen_bit ? (so.samples_mixed_so_far << 1) : - so.samples_mixed_so_far; + int bytes_so_far = so.sixteen_bit ? (so.samples_mixed_so_far << 1) : + so.samples_mixed_so_far; #else - int bytes_so_far = so.samples_mixed_so_far << 1; + int bytes_so_far = so.samples_mixed_so_far << 1; #endif - uint32 samples_to_write = sample_count - so.samples_mixed_so_far; - do - { - int bytes_this_run = samples_to_write; + uint32 samples_to_write = sample_count - so.samples_mixed_so_far; + do + { + int bytes_this_run = samples_to_write; #ifndef FOREVER_16_BIT_SOUND - if (so.sixteen_bit) + if (so.sixteen_bit) #endif - bytes_this_run <<= 1; + bytes_this_run <<= 1; - if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE) - { - bytes_this_run = SOUND_BUFFER_SIZE - byte_offset; - } + if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE) + { + bytes_this_run = SOUND_BUFFER_SIZE - byte_offset; + } - if (bytes_so_far + bytes_this_run > so.buffer_size) - { - bytes_this_run = so.buffer_size - bytes_so_far; - if (bytes_this_run == 0) - break; - } + if (bytes_so_far + bytes_this_run > so.buffer_size) + { + bytes_this_run = so.buffer_size - bytes_so_far; + if (bytes_this_run == 0) + break; + } - int samples_this_run = bytes_this_run; + int samples_this_run = bytes_this_run; #ifndef FOREVER_16_BIT_SOUND - if (so.sixteen_bit) + if (so.sixteen_bit) #endif - samples_this_run >>= 1; + samples_this_run >>= 1; - S9xMixSamples (Buf + byte_offset, samples_this_run); - so.samples_mixed_so_far += samples_this_run; - samples_to_write -= samples_this_run; + S9xMixSamples (Buf + byte_offset, samples_this_run); + so.samples_mixed_so_far += samples_this_run; + samples_to_write -= samples_this_run; #ifndef FOREVER_16_BIT_SOUND - bytes_so_far += so.sixteen_bit ? (samples_this_run << 1) : - samples_this_run; + bytes_so_far += so.sixteen_bit ? (samples_this_run << 1) : + samples_this_run; #else - bytes_so_far += samples_this_run << 1; + bytes_so_far += samples_this_run << 1; #endif - byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK; - } while (samples_to_write > 0); + byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK; + } while (samples_to_write > 0); + } } - } -// if (!so.mute_sound) - { - unsigned bytes_to_write = sample_count; + // if (!so.mute_sound) + { + unsigned bytes_to_write = sample_count; #ifndef FOREVER_16_BIT_SOUND - if(so.sixteen_bit) + if(so.sixteen_bit) #endif - bytes_to_write <<= 1; + bytes_to_write <<= 1; - unsigned byte_offset = so.play_position; - so.play_position = (so.play_position + bytes_to_write) & SOUND_BUFFER_SIZE_MASK; /* wrap to beginning */ + unsigned byte_offset = so.play_position; + so.play_position = (so.play_position + bytes_to_write) & SOUND_BUFFER_SIZE_MASK; /* wrap to beginning */ - unsigned short *dst_pt = audiobuff; - unsigned short *dst_pt1 = dst_pt + DS2_BUFFER_SIZE; + unsigned short *dst_pt = audiobuff; + unsigned short *dst_pt1 = dst_pt + DS2_BUFFER_SIZE; - /* Feed the samples to the soundcard until nothing is left */ - for(;;) - { - int I = bytes_to_write; - if (byte_offset + I > SOUND_BUFFER_SIZE) + /* Feed the samples to the soundcard until nothing is left */ + for(;;) { - I = SOUND_BUFFER_SIZE - byte_offset; - } - if(I == 0) break; + int I = bytes_to_write; + if (byte_offset + I > SOUND_BUFFER_SIZE) + { + I = SOUND_BUFFER_SIZE - byte_offset; + } + if(I == 0) break; -// memcpy(dst_pt, (char *) Buf + byte_offset, I); -// dst_pt += I; + // memcpy(dst_pt, (char *) Buf + byte_offset, I); + // dst_pt += I; - unsigned short *src_pt= (unsigned short*)(Buf + byte_offset); - for(int m= 0; m < I/4; m++) - { - *dst_pt++= *src_pt++;//(*src_pt++) <<1; - *dst_pt1++= *src_pt++;//(*src_pt++) <<1; + unsigned short *src_pt= (unsigned short*)(Buf + byte_offset); + for(int m= 0; m < I/4; m++) + { + *dst_pt++= *src_pt++;//(*src_pt++) <<1; + *dst_pt1++= *src_pt++;//(*src_pt++) <<1; + } + + bytes_to_write -= I; + byte_offset = (byte_offset + I) & SOUND_BUFFER_SIZE_MASK; /* wrap */ } - bytes_to_write -= I; - byte_offset = (byte_offset + I) & SOUND_BUFFER_SIZE_MASK; /* wrap */ - } + ds2_updateAudio(); - ds2_updateAudio(); + /* All data sent. */ + } - /* All data sent. */ + so.samples_mixed_so_far -= sample_count; } - - so.samples_mixed_so_far -= sample_count; } /* -- cgit v1.2.3 From 30fe9eaf6ab8b0701419949a4415736675d15377 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 18:27:03 -0500 Subject: While killing time between frames, process audio instead of doing nothing. Also correctly fill the buffer with silence when returning from pause. This reduces or eliminates crackling. The emulator kills time in two circumstances: * In automatic frameskip mode, without fast forwarding, the emulator kills time if it rendered a frame early. * In manual frameskip mode, without fast forwarding, the emulator kills time to wait for the next rendered frame. --- source/nds/entry.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index c0c8efa..a55c10d 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -675,12 +675,13 @@ void S9xSyncSpeed () else // Early { skip_rate = 0; - ds2_setCPUclocklevel(0); if (syncdif > 0) - // TODO Turn this delay into a ProcessSound loop? - udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); - set_cpu_clock(clock_speed_number); - S9xProcessSound (0); + { + do { + S9xProcessSound (0); + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); + } IPPU.RenderThisFrame = TRUE; sync_next += frame_time; @@ -709,11 +710,10 @@ void S9xSyncSpeed () syncdif = sync_next - syncnow; if (syncdif > 0) { - ds2_setCPUclocklevel(0); - // TODO Turn this delay into a ProcessSound loop? - udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); - set_cpu_clock(clock_speed_number); - S9xProcessSound (0); + do { + S9xProcessSound (0); + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); // After that little delay, what time is it? syncnow = getSysTime(); } @@ -910,8 +910,6 @@ unsigned int LastSoundEmissionTime = 0; void S9xProcessSound (unsigned int) { - unsigned short *audiobuff; - if (so.mute_sound || !game_enable_audio) return; @@ -921,6 +919,8 @@ void S9xProcessSound (unsigned int) return; } + unsigned short *audiobuff; + unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { @@ -933,7 +933,18 @@ void S9xProcessSound (unsigned int) audiobuff = (unsigned short*)ds2_getAudiobuff(); } while (audiobuff == NULL); //There are audio queue in sending or wait to send - memset(audiobuff, 0, DS2_BUFFER_SIZE); + memset(audiobuff, 0, DS2_BUFFER_SIZE +#ifndef FOREVER_STEREO + << (so.stereo ? 1 : 0) +#else + << 1 +#endif +#ifndef FOREVER_16_BIT_SOUND + << (so.sixteen_bit ? 1 : 0) +#else + << 1 +#endif + ); ds2_updateAudio(); // And then the real audio. (fall through) -- cgit v1.2.3 From d4dd98e8c180532f24de342482e54f28874f06ef Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 20:09:24 -0500 Subject: Add an option that controls which element should be more fluid, per game: video or audio. This makes most games playable, but the player can choose to get fluid audio instead of fluid video in sound-test modes or games with epic soundtracks. --- source/nds/entry.cpp | 12 ++++++++++++ source/nds/gui.c | 13 ++++++++++--- source/nds/gui.h | 4 +++- source/nds/message.h | 19 +++++++++++-------- 4 files changed, 36 insertions(+), 12 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index a55c10d..1cf31df 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -350,6 +350,18 @@ void game_set_frameskip() Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */; } } + +void game_set_fluidity() +{ + if( game_config.SoundSync == 1) + { + Settings.SoundSync = TRUE; + } + else + { + Settings.SoundSync = FALSE; + } +} void init_sfc_setting(void) { diff --git a/source/nds/gui.c b/source/nds/gui.c index b529b9f..b6bd0f4 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2814,6 +2814,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; + char *on_off_options[] = { (char*)&msg[MSG_GENERAL_OFF], (char*)&msg[MSG_GENERAL_ON] }; char *sound_seletion[] = { (char*)&msg[MSG_AUDIO_MUTED], (char*)&msg[MSG_AUDIO_ENABLED] }; @@ -2838,8 +2840,11 @@ u32 menu(u16 *screen, bool8 FirstInvocation) /* 03 */ STRING_SELECTION_OPTION(game_disableAudio, NULL, &msg[FMT_AUDIO_SOUND], sound_seletion, &game_enable_audio, 2, NULL, ACTION_TYPE, 3), - /* 04 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, - &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 4) + /* 04 */ STRING_SELECTION_OPTION(game_set_fluidity, NULL, &msg[FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE], fluidity_options, + &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), + + /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, + &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5) }; MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0); @@ -4253,6 +4258,7 @@ void init_game_config(void) clock_speed_number = 5; game_config.graphic = 3; // By default, have a good-looking aspect ratio game_config.frameskip_value = 0; // Automatic frame skipping + game_config.SoundSync = 0; // Prefer fluid images by default game_config.backward = 0; //time backward disable game_config.backward_time = 2; //time backward granularity 1s @@ -4306,7 +4312,8 @@ void load_game_config_file(void) fread(&game_config, 1, sizeof(GAME_CONFIG), fp); clock_speed_number = game_config.clock_speed_number; - Settings.SkipFrames = (game_config.frameskip_value == 0 ? AUTO_FRAMERATE : game_config.frameskip_value - 1 /* 1 -> 0 and so on */); + game_set_frameskip(); + game_set_fluidity(); } fclose(fp); diff --git a/source/nds/gui.h b/source/nds/gui.h index 482ceec..0b91758 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -59,7 +59,8 @@ struct _GAME_CONFIG u32 HotkeyReturnToMenu; u32 HotkeyTemporaryFastForward; u32 HotkeyToggleSound; - u32 Reserved2[45]; + u32 SoundSync; + u32 Reserved2[44]; }; typedef enum @@ -127,6 +128,7 @@ extern void gui_init(u32 lang_id); extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern void game_disableAudio(); extern void game_set_frameskip(); +extern void game_set_fluidity(); extern void set_cpu_clock(u32 num); extern int load_language_msg(char *filename, u32 language); diff --git a/source/nds/message.h b/source/nds/message.h index 0aff8d9..3eb9e74 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -31,6 +31,9 @@ enum MSG MSG_MAIN_MENU_TOOLS, MSG_MAIN_MENU_OPTIONS, MSG_MAIN_MENU_EXIT, + FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE, + MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO, + MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO, FMT_VIDEO_ASPECT_RATIO, FMT_VIDEO_FAST_FORWARD, FMT_VIDEO_FRAME_SKIPPING, @@ -41,8 +44,8 @@ enum MSG FMT_CHEAT_PAGE, MSG_CHEAT_LOAD_FROM_FILE, MSG_TOOLS_SCREENSHOT_GENERAL, - MSG_TOOLS_GLOBAL_HOTKEY_GENERAL, // currently unused - MSG_TOOLS_GAME_HOTKEY_GENERAL, // currently unused + MSG_TOOLS_GLOBAL_HOTKEY_GENERAL, + MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, MSG_OPTIONS_CARD_CAPACITY, @@ -50,12 +53,12 @@ enum MSG MSG_OPTIONS_VERSION, MSG_SCREENSHOT_CREATE, MSG_SCREENSHOT_BROWSE, - MSG_HOTKEY_MAIN_MENU, // currently unused - MSG_HOTKEY_TEMPORARY_FAST_FORWARD, // currently unused - MSG_HOTKEY_SOUND_TOGGLE, // currently unused - MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS, // currently unused - MSG_HOTKEY_DELETE_WITH_A, // currently unused - MSG_HOTKEY_CANCEL_WITH_B, // currently unused + MSG_HOTKEY_MAIN_MENU, + MSG_HOTKEY_TEMPORARY_FAST_FORWARD, + MSG_HOTKEY_SOUND_TOGGLE, + MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS, + MSG_HOTKEY_DELETE_WITH_A, + MSG_HOTKEY_CANCEL_WITH_B, MSG_LOAD_GAME_RECENTLY_PLAYED, MSG_LOAD_GAME_FROM_CARD, MSG_LOAD_GAME_MENU_TITLE, -- cgit v1.2.3 From 25aeb83f7bf395a49742c957ada5d2b917fe62aa Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 20:47:46 -0500 Subject: Release 1.25. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index b6bd0f4..3933277 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.24" +#define NDSSFC_VERSION "1.25" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From 91d7bf5b9177ac8d80d586723f2b6c10a9649148 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 01:37:16 -0500 Subject: Correct overzealous detection of buffer overruns. It was making the sound crackle constantly, like a record player. Most audible with earphones. --- source/nds/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 1cf31df..35ebec1 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -925,7 +925,7 @@ void S9xProcessSound (unsigned int) if (so.mute_sound || !game_enable_audio) return; - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT / 2) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) { LastSoundEmissionTime++; return; -- cgit v1.2.3 From 984682682c26edb5a9bbcd1e1d8f4aa6ce135596 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 01:39:50 -0500 Subject: Release 1.26. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 3933277..4f808b4 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.25" +#define NDSSFC_VERSION "1.26" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From 7aeebe97e72b07d60ea77041a5259086e68e2db2 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 02:21:52 -0500 Subject: Fix an oddity in the sound when returning from a global mute. Fixes music loading in Super Mario World. --- source/nds/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 35ebec1..986ecce 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -922,7 +922,7 @@ unsigned int LastSoundEmissionTime = 0; void S9xProcessSound (unsigned int) { - if (so.mute_sound || !game_enable_audio) + if (!game_enable_audio) return; if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) -- cgit v1.2.3 From 02f8184fe07d99cceb85f4abd3ef0e5e3765b5ea Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 17:37:51 -0500 Subject: Make it easier to change the "high" and "low" CPU frequencies, as well as to switch to the user's chosen frequency for the game. Conflicts: source/nds/ds2_main.c source/nds/entry.cpp source/nds/gui.c --- source/nds/ds2_main.c | 5 ++++- source/nds/entry.cpp | 6 +++--- source/nds/gui.c | 54 ++++++++++++++++++++++++++++++--------------------- source/nds/gui.h | 4 +++- 4 files changed, 42 insertions(+), 27 deletions(-) (limited to 'source/nds') diff --git a/source/nds/ds2_main.c b/source/nds/ds2_main.c index f9b29d5..af81df3 100644 --- a/source/nds/ds2_main.c +++ b/source/nds/ds2_main.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "port.h" + #include #include "console.h" #include "fs_api.h" @@ -25,6 +27,7 @@ #include "ds2_timer.h" #include "ds2_malloc.h" #include "ds2sound.h" +#include "gui.h" #define BLACK_COLOR RGB15(0, 0, 0) #define WHITE_COLOR RGB15(31, 31, 31) @@ -47,7 +50,7 @@ void ddump_mem(unsigned char* addr, unsigned int len) void ds2_main(void) { int err; - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); //Initial video and audio and other input and output err = ds2io_initb(DS2_BUFFER_SIZE, SND_SAMPLE_RATE, 0, 0); if(err) goto _failure; diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 986ecce..5d79b64 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -86,7 +86,7 @@ void S9xParseDisplayArg (char **argv, int &ind, int) void S9xExit () { - ds2_setCPUclocklevel(13); // Crank it up to exit quickly + HighFrequencyCPU(); // Crank it up to exit quickly if(Settings.SPC7110) (*CleanUp7110)(); @@ -1125,7 +1125,7 @@ unsigned int S9xReadJoypad (int which1) if (inputdata.key & KEY_LID) { - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); ds2_setSupend(); do { ds2_getrawInput(&inputdata); @@ -1136,7 +1136,7 @@ unsigned int S9xReadJoypad (int which1) // screen's backlight. mdelay(100); // needed to avoid ds2_setBacklight crashing ds2_setBacklight(2); - set_cpu_clock(clock_speed_number); + GameFrequencyCPU(); } u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; diff --git a/source/nds/gui.c b/source/nds/gui.c index 4f808b4..3942672 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1651,12 +1651,22 @@ int save_state(char* file, void* screen) return 0; } -void set_cpu_clock(u32 num) +void LowFrequencyCPU() { - u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 394 + ds2_setCPUclocklevel(0); // 60 MHz +} + +void HighFrequencyCPU() +{ + ds2_setCPUclocklevel(13); // 396 MHz +} + +void GameFrequencyCPU() +{ + u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 - if(num <= 5) - ds2_setCPUclocklevel(clock_speed_table[num]); + if(clock_speed_number <= 5) + ds2_setCPULevel(clock_speed_table[clock_speed_number]); } void savefast_int(void) @@ -1761,7 +1771,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void menu_exit() { - ds2_setCPUclocklevel(13); // Crank it up, leave quickly + HighFrequencyCPU(); // Crank it up, leave quickly if(gamepak_name[0] != 0) { game_config.clock_speed_number = clock_speed_number; @@ -1794,9 +1804,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int load_result = load_gamepak(line_buffer); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(load_result == -1) { first_load = 1; @@ -1862,9 +1872,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int load_result = load_gamepak(args[1]); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(load_result == -1) { @@ -2074,9 +2084,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_CREATING]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int flag = save_state(tmp_filename, (void*)screen); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); //clear message draw_message(down_screen_addr, NULL, 28, 31, 227, 96, 0); if(flag < 0) @@ -2143,9 +2153,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(up_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_LOADING]); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int flag = load_state(tmp_filename); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(0 == flag) { return_value = 1; @@ -2160,9 +2170,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } else //load screen snapshot { - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); load_game_stat_snapshot(tmp_filename); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); } } else @@ -2732,7 +2742,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { if(gui_action == CURSOR_LEFT || gui_action == CURSOR_RIGHT) { - ds2_setCPUclocklevel(13); // crank it up + HighFrequencyCPU(); // crank it up if(bg_screenp != NULL) { bg_screenp_color = COLOR16(43, 11, 11); @@ -2757,7 +2767,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } save_emu_config_file(); - ds2_setCPUclocklevel(0); // and back down + LowFrequencyCPU(); // and back down wait_Allkey_release(0); } } @@ -3497,9 +3507,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ext_pos = emu_config.latest_file[current_option_num -1]; - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int load_result = load_gamepak(ext_pos); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(load_result == -1) { first_load = 1; @@ -3572,7 +3582,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) //----------------------------------------------------------------------------// // Menu Start - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if (!FirstInvocation) { // assume that the backlight is already at 3 when the emulator starts mdelay(100); // to prevent ds2_setBacklight() from crashing @@ -4100,7 +4110,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) mdelay(100); // to prevent ds2_setBacklight() from crashing ds2_setBacklight(2); - set_cpu_clock(clock_speed_number); + GameFrequencyCPU(); return return_value; } @@ -4708,7 +4718,7 @@ void gui_init(u32 lang_id) { int flag; - ds2_setCPUclocklevel(13); // Crank it up. When the menu starts, -> 0. + HighFrequencyCPU(); // Crank it up. When the menu starts, -> 0. // Start with no saved state existing, as no game is loaded yet. int i; diff --git a/source/nds/gui.h b/source/nds/gui.h index 0b91758..b2eae62 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -129,7 +129,9 @@ extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern void game_disableAudio(); extern void game_set_frameskip(); extern void game_set_fluidity(); -extern void set_cpu_clock(u32 num); +extern void LowFrequencyCPU(); +extern void HighFrequencyCPU(); +extern void GameFrequencyCPU(); extern int load_language_msg(char *filename, u32 language); #ifdef __cplusplus -- cgit v1.2.3 From fd92545013ed91d2867e1e180a9b86611eb19f9c Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 04:20:51 -0500 Subject: Whoops. I forgot to replace an instance of ds2_setCPULevel from the experimental branch cherry-pick. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 3942672..7100cf2 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1666,7 +1666,7 @@ void GameFrequencyCPU() u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 if(clock_speed_number <= 5) - ds2_setCPULevel(clock_speed_table[clock_speed_number]); + ds2_setCPUclocklevel(clock_speed_table[clock_speed_number]); } void savefast_int(void) -- cgit v1.2.3 From 461f2406555faaee7191871390192d06625f5a81 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 05:59:48 -0500 Subject: Fix a name clash between Snes9x's dma.h and the DS2 dma.h by renaming the DS2 dma.h to ds2_dma.h. Add preliminary support for drawing emulated screens with DS2 DMA. --- source/nds/entry.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 5d79b64..4aa2977 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -23,6 +23,11 @@ #include "entry.h" #include "ds2sound.h" +#ifdef DS2_DMA +#include "ds2_dma.h" +#include "dma_adj.h" +#endif + void S9xProcessSound (unsigned int); char *rom_filename = NULL; @@ -58,7 +63,11 @@ void S9xExtraUsage () */ void S9xDeinitDisplay (void) { +#ifdef DS2_DMA + if(GFX.Screen) AlignedFree(GFX.Screen, PtrAdj.GFXScreen); +#else if(GFX.Screen) free(GFX.Screen); +#endif if(GFX.SubScreen) free(GFX.SubScreen); if(GFX.ZBuffer) free(GFX.ZBuffer); if(GFX.SubZBuffer) free(GFX.SubZBuffer); @@ -69,7 +78,11 @@ void S9xInitDisplay (int, char **) int h = IMAGE_HEIGHT; GFX.Pitch = IMAGE_WIDTH * 2; +#ifdef DS2_DMA + GFX.Screen = (unsigned char*) AlignedMalloc (GFX.Pitch * h, 32, &PtrAdj.GFXScreen); +#else GFX.Screen = (unsigned char*) malloc (GFX.Pitch * h); +#endif GFX.SubScreen = (unsigned char*) malloc (GFX.Pitch * h); GFX.ZBuffer = (unsigned char*) malloc ((GFX.Pitch >> 1) * h); GFX.SubZBuffer =(unsigned char*) malloc ((GFX.Pitch >> 1) * h); @@ -130,17 +143,35 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) { //Up case 1: +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2); +#endif break; //Down case 2: +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(up_screen_addr, GFX.Screen, 256*192*2); +#endif break; //Both case 3: +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2); +#endif break; case 4: @@ -157,7 +188,13 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) dst = (unsigned char*)up_screen_addr; for(m = 0; m < 32; m++) { +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, dst, src, 256 * 6 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(dst, src, 256*6*2); +#endif dst += 256*6*2; src += 256*7*2; } -- cgit v1.2.3 From 9b75c09a7fd7c78d8c42077478e796672fae5c1b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 06:25:12 -0500 Subject: Force waiting for a screen to be transferred (update mode 1) because otherwise the next screen can go into DMA. Use channel 1 instead of channel 5, which must be busy for some reason. --- source/nds/entry.cpp | 24 ++++++++++++------------ source/nds/gui.h | 4 ++++ 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 4aa2977..3fa6517 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -144,9 +144,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Up case 1: #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2); #endif @@ -155,9 +155,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Down case 2: #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(up_screen_addr, GFX.Screen, 256*192*2); #endif @@ -166,9 +166,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Both case 3: #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2); #endif @@ -189,9 +189,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) for(m = 0; m < 32; m++) { #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, dst, src, 256 * 6 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(dst, src, 256*6*2); #endif diff --git a/source/nds/gui.h b/source/nds/gui.h index b2eae62..9df2ad2 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,7 +24,11 @@ #include "fs_api.h" #include "gcheat.h" +#ifdef DS2_DMA +#define UP_SCREEN_UPDATE_METHOD 1 +#else #define UP_SCREEN_UPDATE_METHOD 0 +#endif #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From 397bf5192a44ea95a82a9792cb7a8a23b112bb3e Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 15:29:05 -0500 Subject: Add some forgotten DMA files. --- source/nds/dma_adj.c | 26 ++++++++++++++++++++++++++ source/nds/dma_adj.h | 25 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 source/nds/dma_adj.c create mode 100644 source/nds/dma_adj.h (limited to 'source/nds') diff --git a/source/nds/dma_adj.c b/source/nds/dma_adj.c new file mode 100644 index 0000000..8b6f9ad --- /dev/null +++ b/source/nds/dma_adj.c @@ -0,0 +1,26 @@ +#include "ds2_malloc.h" +#include "dma_adj.h" + +#ifdef DS2_DMA + +struct SPointerAdjustments PtrAdj; + +void* AlignedMalloc (unsigned int Size, unsigned int Alignment, unsigned int* Adjustment) +{ + if (Alignment == 0) Alignment = 1; + + unsigned char* result = (unsigned char*) malloc(Size + Alignment); + if (!result) { + return result; + } else { + *Adjustment = Alignment - ((unsigned int) result & (Alignment - 1)); + return (void*) (result + *Adjustment); + } +} + +void AlignedFree (void* Memory, unsigned int Adjustment) +{ + free((void*) ((unsigned char*) Memory - Adjustment)); +} + +#endif // DS2_DMA diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h new file mode 100644 index 0000000..62b0098 --- /dev/null +++ b/source/nds/dma_adj.h @@ -0,0 +1,25 @@ +#ifndef _DMA_ADJ_H_ +#define _DMA_ADJ_H_ + +#ifdef DS2_DMA + +#ifdef __cplusplus +extern "C" { +#endif + +struct SPointerAdjustments { + unsigned int GFXScreen; +}; + +extern struct SPointerAdjustments PtrAdj; + +extern void* AlignedMalloc (unsigned int Size, unsigned int Alignment, unsigned int* Adjustment); +extern void AlignedFree (void* Memory, unsigned int Adjustment); + +#ifdef __cplusplus +} +#endif + +#endif // DS2_DMA + +#endif // !_DMA_ADJ_H_ -- cgit v1.2.3 From 538718997fd9c85289669c1b5a8e46a45b6328af Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 15:52:45 -0500 Subject: Write back the data cache before using DMA to draw emulated frames. --- source/nds/entry.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 3fa6517..286722e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -144,6 +144,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Up case 1: #ifdef DS2_DMA + __dcache_writeback_all(); dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); dma_wait_finish(1); dma_stop(1); @@ -155,6 +156,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Down case 2: #ifdef DS2_DMA + __dcache_writeback_all(); dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); dma_wait_finish(1); dma_stop(1); @@ -166,6 +168,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Both case 3: #ifdef DS2_DMA + __dcache_writeback_all(); dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); dma_wait_finish(1); dma_stop(1); @@ -181,8 +184,11 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) default: { - unsigned char *src, *dst; - unsigned int m; +#ifdef DS2_DMA + __dcache_writeback_all(); +#endif + register unsigned char *src, *dst; + register unsigned int m; src = GFX.Screen; dst = (unsigned char*)up_screen_addr; -- cgit v1.2.3 From 1ddc8b53fe92a88578f23ace849168bc19ca0cd0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 16:17:06 -0500 Subject: Faking out the sound synchronisation with a buffer of silence wasn't necessary. --- source/nds/entry.cpp | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 286722e..727986e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -982,27 +982,8 @@ void S9xProcessSound (unsigned int) if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */) { LastSoundEmissionTime = Now; - // We were probably paused. Restart sending sound with an - // empty buffer. - do { - audiobuff = (unsigned short*)ds2_getAudiobuff(); - } while (audiobuff == NULL); //There are audio queue in sending or wait to send - - memset(audiobuff, 0, DS2_BUFFER_SIZE -#ifndef FOREVER_STEREO - << (so.stereo ? 1 : 0) -#else - << 1 -#endif -#ifndef FOREVER_16_BIT_SOUND - << (so.sixteen_bit ? 1 : 0) -#else - << 1 -#endif - ); - - ds2_updateAudio(); - // And then the real audio. (fall through) + // We were probably paused. Restart sending sound, + // synchronising from now. } else { -- cgit v1.2.3 From b3a7f8f1fceddcd45ec62bcbf75ba128e4f84f5a Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 19:26:34 -0500 Subject: Synchronise the controller status more spread out inside a rendered frame: * before rendering a background; * before rendering sprites; * while rendering more than 128 samples of audio at once ("Prefer fluid video"); * after every 16 scanlines of CPU execution instead of every 1; * while waiting for an audio buffer to become available; * while killing time between frames with fast-forward disabled. Controller presses and releases are now combined in a DS button bitfield using a shorter 32-bit algorithm. See entry.cpp:NDSSFCAccumulateJoypad and #define ACCUMULATE_JOYPAD in the source. This is still not suitable for playing platformers frame-perfectly, but it's much better than half a second of latency to press or release a button, and one still needs to press buttons a bit more than just light taps. I'd say 50 milliseconds is the latency now. Platformers requiring more precision can be played with frameskip 0. DMA does not require double-buffered displaying, so synchronise the controller more often by disabling double-buffered displaying again. --- source/nds/entry.cpp | 162 +++++++++++++++++++++++++++++++++------------------ source/nds/gui.h | 4 -- 2 files changed, 105 insertions(+), 61 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 727986e..14c6243 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -734,6 +734,14 @@ void S9xSyncSpeed () { do { S9xProcessSound (0); +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif syncdif = sync_next - getSysTime(); } while (syncdif > 0); } @@ -767,6 +775,14 @@ void S9xSyncSpeed () { do { S9xProcessSound (0); +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif syncdif = sync_next - getSysTime(); } while (syncdif > 0); // After that little delay, what time is it? @@ -968,17 +984,17 @@ void S9xProcessSound (unsigned int) if (!game_enable_audio) return; - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) - { - LastSoundEmissionTime++; - return; - } - - unsigned short *audiobuff; - unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) + { + LastSoundEmissionTime++; + return; + } + + unsigned short *audiobuff; + if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */) { LastSoundEmissionTime = Now; @@ -1003,9 +1019,14 @@ void S9xProcessSound (unsigned int) } #endif - do { + audiobuff = (unsigned short*)ds2_getAudiobuff(); + while (audiobuff == NULL) //There are audio queue in sending or wait to send + { +#ifdef ACCUMULATE_JOYPAD + NDSSFCAccumulateJoypad (); +#endif audiobuff = (unsigned short*)ds2_getAudiobuff(); - } while (audiobuff == NULL); //There are audio queue in sending or wait to send + } /* If we need more audio samples */ if (so.samples_mixed_so_far < sample_count) @@ -1141,72 +1162,99 @@ const unsigned int keymap[12] = { static bool8 SoundToggleWasHeld = FALSE; -unsigned int S9xReadJoypad (int which1) -{ - struct key_buf inputdata; +#ifdef ACCUMULATE_JOYPAD +// These are kept as DS key bitfields until it's time to send them to Snes9x. +static uint32 PreviousControls = 0x00000000; +static uint32 ControlsPressed = 0x00000000; +static uint32 ControlsReleased = 0x00000000; +void NDSSFCAccumulateJoypad () +{ + struct key_buf inputdata; ds2_getrawInput(&inputdata); - if (inputdata.key & KEY_LID) + ControlsPressed |= inputdata.key & ~PreviousControls; + ControlsReleased |= PreviousControls & ~inputdata.key; +} +#endif // ACCUMULATE_JOYPAD + +uint32 S9xReadJoypad (int which1) +{ + if(which1 < 1) { - LowFrequencyCPU(); - ds2_setSupend(); - do { + uint32 Controls; +#ifdef ACCUMULATE_JOYPAD + Controls = (PreviousControls | ControlsPressed) & ~ControlsReleased; + PreviousControls = Controls; + ControlsPressed = ControlsReleased = 0x00000000; +#else + { + struct key_buf inputdata; ds2_getrawInput(&inputdata); - mdelay(1); - } while (inputdata.key & KEY_LID); - ds2_wakeup(); - // Before starting to emulate again, turn off the lower - // screen's backlight. - mdelay(100); // needed to avoid ds2_setBacklight crashing - ds2_setBacklight(2); - GameFrequencyCPU(); - } - u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; - u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward; - u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound; + Controls = inputdata.key; + } +#endif - if(inputdata.key & KEY_TOUCH || - (HotkeyReturnToMenu && ((inputdata.key & HotkeyReturnToMenu) == HotkeyReturnToMenu)) - ) //Active menu - Settings.Paused = 1; + if (Controls & KEY_LID) + { + LowFrequencyCPU(); + ds2_setSupend(); + struct key_buf inputdata; + do { + ds2_getrawInput(&inputdata); + mdelay(1); + } while (inputdata.key & KEY_LID); + ds2_wakeup(); + // Before starting to emulate again, turn off the lower + // screen's backlight. + mdelay(100); // needed to avoid ds2_setBacklight crashing + ds2_setBacklight(2); + GameFrequencyCPU(); + } - temporary_fast_forward = - (HotkeyTemporaryFastForward && ((inputdata.key & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward)) - ; + u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; + u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward; + u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound; - bool8 SoundToggleIsHeld = - (HotkeyToggleSound && ((inputdata.key & HotkeyToggleSound) == HotkeyToggleSound)) - ; + if(Controls & KEY_TOUCH || + (HotkeyReturnToMenu && ((Controls & HotkeyReturnToMenu) == HotkeyReturnToMenu)) + ) //Active menu + Settings.Paused = 1; - if (SoundToggleIsHeld && !SoundToggleWasHeld) - { - game_enable_audio = !game_enable_audio; - game_disableAudio(); - } + temporary_fast_forward = + (HotkeyTemporaryFastForward && ((Controls & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward)) + ; - SoundToggleWasHeld = SoundToggleIsHeld; + bool8 SoundToggleIsHeld = + (HotkeyToggleSound && ((Controls & HotkeyToggleSound) == HotkeyToggleSound)) + ; - if(which1 < 1) - { - unsigned int key; + if (SoundToggleIsHeld && !SoundToggleWasHeld) + { + game_enable_audio = !game_enable_audio; + game_disableAudio(); + } + + SoundToggleWasHeld = SoundToggleIsHeld; + + uint32 key = 0x80000000; // Required by Snes9x // DS -> SNES - key = (inputdata.key & KEY_A ) << 7; // 0x0001 -> 0x0080 - key |= (inputdata.key & KEY_B ) << 14; // 0x0002 -> 0x8000 - key |= (inputdata.key & KEY_SELECT) << 11; // 0x0004 -> 0x2000 - key |= (inputdata.key & KEY_START ) << 9; // 0x0008 -> 0x1000 - key |= (inputdata.key & KEY_UP ) << 5; // 0x0040 -> 0x0800 + key |= (Controls & KEY_A ) << 7; // 0x0001 -> 0x0080 + key |= (Controls & KEY_B ) << 14; // 0x0002 -> 0x8000 + key |= (Controls & KEY_SELECT) << 11; // 0x0004 -> 0x2000 + key |= (Controls & KEY_START ) << 9; // 0x0008 -> 0x1000 + key |= (Controls & KEY_UP ) << 5; // 0x0040 -> 0x0800 // 0x0010 -> 0x0100; 0x0020 -> 0x0200 // 0x0030 -> 0x0300 - key |= (inputdata.key & (KEY_RIGHT | KEY_LEFT)) << 4; + key |= (Controls & (KEY_RIGHT | KEY_LEFT)) << 4; // 0x0100 -> 0x0010; 0x0200 -> 0x0020; 0x0400 -> 0x0040 // 0x0700 -> 0x0070 - key |= (inputdata.key & (KEY_R | KEY_L | KEY_X)) >> 4; + key |= (Controls & (KEY_R | KEY_L | KEY_X)) >> 4; // 0x0080 -> 0x0400; 0x0800 -> 0x4000 // 0x0880 -> 0x4400 - key |= (inputdata.key & (KEY_DOWN | KEY_Y)) << 3; + key |= (Controls & (KEY_DOWN | KEY_Y)) << 3; /* for(i= 0; i < 12; i++) //remap key { @@ -1214,7 +1262,7 @@ unsigned int S9xReadJoypad (int which1) } */ - return (key | 0x80000000); + return key; } else return 0; diff --git a/source/nds/gui.h b/source/nds/gui.h index 9df2ad2..b2eae62 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,11 +24,7 @@ #include "fs_api.h" #include "gcheat.h" -#ifdef DS2_DMA -#define UP_SCREEN_UPDATE_METHOD 1 -#else #define UP_SCREEN_UPDATE_METHOD 0 -#endif #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From 4096050f400f0a9cafa237ac11766e6b0faa70f0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 20:12:29 -0500 Subject: Release 1.27. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 7100cf2..e2a469d 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.26" +#define NDSSFC_VERSION "1.27" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From 1c9094d99f6cb2f9ca63134cb7a348370b568b7c Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Mon, 4 Feb 2013 05:57:53 -0500 Subject: Release 1.28 after disabling the controller status sync hack. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index e2a469d..3d2ab70 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.27" +#define NDSSFC_VERSION "1.28" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From d1a7bf5eb558e7db4a1a27e15ebedb02e6b7f804 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Mon, 4 Feb 2013 23:45:44 -0500 Subject: Fully integrate BassAceGold's libraries, finally. The README still states that 1.2 is required to overwrite 0.13's stuff; really, 0.13 is needed only for `gcc`. So the sequence goes 0.13's `gcc` -> 1.2 -> BassAceGold's libraries -> make `libds2a.a`. DMA function names changed to match BassAceGold's. --- source/nds/entry.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 14c6243..de30332 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -145,9 +145,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) case 1: #ifdef DS2_DMA __dcache_writeback_all(); - dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2); #endif @@ -157,9 +157,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) case 2: #ifdef DS2_DMA __dcache_writeback_all(); - dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(up_screen_addr, GFX.Screen, 256*192*2); #endif @@ -169,9 +169,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) case 3: #ifdef DS2_DMA __dcache_writeback_all(); - dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2); #endif @@ -195,9 +195,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) for(m = 0; m < 32; m++) { #ifdef DS2_DMA - dma_copy32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(dst, src, 256*6*2); #endif @@ -987,7 +987,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) + if(ds2_checkAudiobuff() > 4) { LastSoundEmissionTime++; return; -- cgit v1.2.3 From 3cd1e0327898acf0bd09a035c7a68c7362bb07c0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 5 Feb 2013 16:05:16 -0500 Subject: Change the upper screen updates to be double-buffered. Require that one audio buffer be free (1 out of 4). --- source/nds/entry.cpp | 2 +- source/nds/gui.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index de30332..18802a0 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -987,7 +987,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > 4) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1) { LastSoundEmissionTime++; return; diff --git a/source/nds/gui.h b/source/nds/gui.h index b2eae62..e8302eb 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,7 +24,7 @@ #include "fs_api.h" #include "gcheat.h" -#define UP_SCREEN_UPDATE_METHOD 0 +#define UP_SCREEN_UPDATE_METHOD 1 #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From e7ac6f675f9faf5894aea8dd80e01c649933c322 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 5 Feb 2013 16:35:45 -0500 Subject: Disable the free space line in the options for the time being. Currently it invokes a recursive directory scan to calculate how much space is used first. --- source/nds/gui.c | 24 ++++++++++++++++++++++-- source/nds/message.h | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 3d2ab70..764ca66 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1756,7 +1756,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) auto void latest_game_menu_end(); auto void language_set(); auto void game_fastforward(); +#ifdef ENABLE_FREE_SPACE auto void show_card_space(); +#endif auto void savestate_selitem(u32 sel, u32 y_pos); auto void game_state_menu_passive(); auto void gamestate_delette_menu_passive(); @@ -2772,6 +2774,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } } +#ifdef ENABLE_FREE_SPACE unsigned int freespace; void show_card_space () { @@ -2815,6 +2818,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) PRINT_STRING_BG(down_screen_addr, line_buffer, COLOR_INACTIVE_ITEM, COLOR_TRANS, 147, 40 + (display_option->line_number)*27); } +#endif char *screen_ratio_options[] = { (char*)&msg[MSG_VIDEO_ASPECT_RATIO_0], (char*)&msg[MSG_VIDEO_ASPECT_RATIO_1], @@ -3004,12 +3008,26 @@ u32 menu(u16 *screen, bool8 FirstInvocation) /* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options, &emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2), +#ifdef ENABLE_FREE_SPACE /* 03 */ STRING_SELECTION_OPTION(NULL, show_card_space, &msg[MSG_OPTIONS_CARD_CAPACITY], NULL, &desert, 2, NULL, PASSIVE_TYPE | HIDEN_TYPE, 3), +#endif - /* 04 */ ACTION_OPTION(load_default_setting, NULL, &msg[MSG_OPTIONS_RESET], NULL, 4), + /* 04 */ ACTION_OPTION(load_default_setting, NULL, &msg[MSG_OPTIONS_RESET], NULL, +#ifdef ENABLE_FREE_SPACE + 4 +#else + 3 +#endif + ), - /* 05 */ ACTION_OPTION(check_gbaemu_version, NULL, &msg[MSG_OPTIONS_VERSION], NULL, 5), + /* 05 */ ACTION_OPTION(check_gbaemu_version, NULL, &msg[MSG_OPTIONS_VERSION], NULL, +#ifdef ENABLE_FREE_SPACE + 5 +#else + 4 +#endif + ), }; MAKE_MENU(others, others_menu_init, NULL, NULL, NULL, 1, 1); @@ -3556,11 +3574,13 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void others_menu_init() { +#ifdef ENABLE_FREE_SPACE unsigned int total, used; //get card space info freespace = 0; fat_getDiskSpaceInfo("fat:", &total, &used, &freespace); +#endif } void choose_menu(MENU_TYPE *new_menu) diff --git a/source/nds/message.h b/source/nds/message.h index 3eb9e74..b5bb47b 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -48,7 +48,7 @@ enum MSG MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, - MSG_OPTIONS_CARD_CAPACITY, + MSG_OPTIONS_CARD_CAPACITY /* unused if !defined(ENABLE_FREE_SPACE) */, MSG_OPTIONS_RESET, MSG_OPTIONS_VERSION, MSG_SCREENSHOT_CREATE, -- cgit v1.2.3 From f2adea7bb2250876df3d1b6e076a6b5380c6b13e Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 5 Feb 2013 19:39:09 -0500 Subject: Force both manual and automatic frameskipping to be at or above 2. Resets the default value for all games which previously had this value configured. --- source/nds/entry.cpp | 14 +++++++++++--- source/nds/gui.c | 4 ++-- source/nds/gui.h | 22 ++++++++++++++++++++-- source/nds/message.h | 4 ++-- 4 files changed, 35 insertions(+), 9 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 18802a0..6cbf3ef 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -390,7 +390,7 @@ void game_set_frameskip() } else { - Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */; + Settings.SkipFrames = game_config.frameskip_value + 1 /* 1 -> 2 and so on */; } } @@ -639,7 +639,6 @@ int sfc_main (int argc, char **argv) static unsigned int sync_last= 0; static unsigned int sync_next = 0; -static unsigned int auto_equivalent_skip = 0; static unsigned int skip_rate= 0; @@ -690,7 +689,16 @@ void S9xSyncSpeed () // If this is negative, we're late by syncdif*42.66 // microseconds. syncdif = sync_next - syncnow; - if (syncdif < 0 && syncdif >= -(frame_time / 2)) + if(skip_rate < 2 /* did not skip 2 frames yet */) + { + // Skip a minimum of 2 frames between rendered frames. + // This prevents the DSTwo-DS link from being too busy + // to return button statuses. + ++skip_rate; + IPPU.RenderThisFrame = FALSE; + sync_next += frame_time; + } + else if (syncdif < 0 && syncdif >= -(frame_time / 2)) { // We're late, but by less than half a frame. Draw it // anyway. If the next frame is too late, it'll be diff --git a/source/nds/gui.c b/source/nds/gui.c index 764ca66..4b5955a 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2826,7 +2826,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) (char*)&msg[MSG_VIDEO_ASPECT_RATIO_3], (char*)&msg[MSG_VIDEO_ASPECT_RATIO_4]}; - char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; @@ -2858,7 +2858,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, - &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5) + &game_config.frameskip_value, 10 /* auto (0) and 2..10 (1..9) make 10 option values */, NULL, ACTION_TYPE, 5) }; MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0); diff --git a/source/nds/gui.h b/source/nds/gui.h index e8302eb..b390b69 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -50,7 +50,24 @@ struct _GAME_CONFIG { u32 clock_speed_number; u32 Reserved0; - u32 frameskip_value; + /* + * PreviouslyUsed_20130205_1 was formerly known as 'frameskip_value'; + * its values were in [0, 10]. 0 was automatic frameskipping and + * [1, 10] were mapped to skip 0 to 9 frames respectively. + * Version 1.29 changes the value range for 'frameskip_value' to + * [0, 8], with 0 as automatic frameskipping and [1, 10] to skip 2 to + * 9 frames. + * Change rationale: Frame skip values under 2 cause too much + * communication between the DSTwo and the DS, therefore the DS cannot + * timely send controller information. + * If this variable were to be used as is, the meaning of the option + * would be changed for values in [1, 8], and values in [9, 10] would + * cause undefined behavior, including crashes. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE + * FOR WHICH IT WAS INTENDED. + */ + u32 PreviouslyUsed_20130205_1; u32 graphic; u32 enable_audio; u32 Reserved1; @@ -60,7 +77,8 @@ struct _GAME_CONFIG u32 HotkeyTemporaryFastForward; u32 HotkeyToggleSound; u32 SoundSync; - u32 Reserved2[44]; + u32 frameskip_value; + u32 Reserved2[43]; }; typedef enum diff --git a/source/nds/message.h b/source/nds/message.h index b5bb47b..86389b1 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -70,8 +70,8 @@ enum MSG MSG_VIDEO_ASPECT_RATIO_4, MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC, - MSG_VIDEO_FRAME_SKIPPING_0, - MSG_VIDEO_FRAME_SKIPPING_1, + MSG_VIDEO_FRAME_SKIPPING_0 /* unused */, + MSG_VIDEO_FRAME_SKIPPING_1 /* unused */, MSG_VIDEO_FRAME_SKIPPING_2, MSG_VIDEO_FRAME_SKIPPING_3, MSG_VIDEO_FRAME_SKIPPING_4, -- cgit v1.2.3 From 9e87a7a2b2659785bc05266fbb3292b60aecdf27 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 00:34:01 -0500 Subject: Implement automatic CPU frequency switching, which improves battery life if playing games that don't use all of the MIPS CPU. If all of it is indeed needed, then the game will constantly play at 396 MHz. --- source/nds/entry.cpp | 244 ++++++++++++++++++++++++++++++--------------------- source/nds/entry.h | 2 + source/nds/gui.c | 22 +++-- source/nds/gui.h | 23 ++++- source/nds/message.h | 7 ++ 5 files changed, 185 insertions(+), 113 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 6cbf3ef..08e95cb 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -642,10 +642,19 @@ static unsigned int sync_next = 0; static unsigned int skip_rate= 0; +#define CPU_DOWNCLOCK_EARLY_TIME 293 /* 1 = 42.667 us. 391 = 16.67 ms */ +#define CPU_DOWNCLOCK_DETERMINATION_INTERVAL 46874 /* 23437 = 1 s */ + +static unsigned int LastAutoCPUTime = 0; +unsigned int AutoCPUFrequency = 5; +static bool8 ConsistentlyEarly = FALSE; +static bool8 FastForwardLastFrame = FALSE; + void S9xSyncSpeed () { uint32 syncnow; int32 syncdif; + unsigned int LastAutoCPUFrequency = AutoCPUFrequency; #if 0 if (Settings.SoundSync == 2) @@ -657,8 +666,19 @@ void S9xSyncSpeed () #endif syncnow = getSysTime(); - if (game_fast_forward || temporary_fast_forward /* hotkey is held */) + bool8 FastForward = game_fast_forward || temporary_fast_forward /* hotkey is held */; + + if (game_config.clock_speed_number == 0) + if (FastForward && !FastForwardLastFrame) + HighFrequencyCPU (); + else if (!FastForward && FastForwardLastFrame) + GameFrequencyCPU (); + + FastForwardLastFrame = FastForward; + + if (FastForward) { + ConsistentlyEarly = FALSE; // don't use fast-forward to lower CPU sync_last = syncnow; sync_next = syncnow; @@ -670,137 +690,149 @@ void S9xSyncSpeed () IPPU.RenderThisFrame = true; } } - else if (Settings.SkipFrames == AUTO_FRAMERATE /* && !game_fast_forward && !temporary_fast_forward */) + else { - // frame_time is in getSysTime units: 42.667 microseconds. - int32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; - if (sync_last > syncnow) // Overflow occurred! (every 50 hrs) + // Manual or automatic frame skipping, no fast-forward. + if (Settings.SkipFrames == AUTO_FRAMERATE) { - // Render this frame regardless, set the - // sync_next, and get the hell out. - IPPU.RenderThisFrame = TRUE; + // frame_time is in getSysTime units: 42.667 microseconds. + int32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; + if (sync_last > syncnow) // Overflow occurred! (every 50 hrs) + { + // Render this frame regardless, set the + // sync_next, and get the hell out. + ConsistentlyEarly = FALSE; + AutoCPUFrequency = 5; + LastAutoCPUTime = syncnow; + + IPPU.RenderThisFrame = TRUE; + sync_last = syncnow; + sync_next = syncnow + frame_time; + goto finalise; + } sync_last = syncnow; - sync_next = syncnow + frame_time; - return; - } - sync_last = syncnow; - // If this is positive, we have syncdif*42.66 microseconds to - // spare. - // If this is negative, we're late by syncdif*42.66 - // microseconds. - syncdif = sync_next - syncnow; - if(skip_rate < 2 /* did not skip 2 frames yet */) - { - // Skip a minimum of 2 frames between rendered frames. - // This prevents the DSTwo-DS link from being too busy - // to return button statuses. - ++skip_rate; - IPPU.RenderThisFrame = FALSE; - sync_next += frame_time; - } - else if (syncdif < 0 && syncdif >= -(frame_time / 2)) - { - // We're late, but by less than half a frame. Draw it - // anyway. If the next frame is too late, it'll be - // skipped. - skip_rate = 0; - IPPU.RenderThisFrame = true; - sync_next += frame_time; - } - else if(syncdif < 0) - { - /* - * If we're consistently late, delay up to 8 frames. - * - * That really helps with certain games, such as - * Super Mario RPG and Yoshi's Island. - */ - if(++skip_rate < 10) + // If this is positive, we have syncdif*42.66 microseconds to + // spare. + // If this is negative, we're late by syncdif*42.66 + // microseconds. + syncdif = sync_next - syncnow; + if(skip_rate < 2 /* did not skip 2 frames yet */) { - if(syncdif >= -11719 /* not more than 500.0 ms late */) + // Skip a minimum of 2 frames between rendered frames. + // This prevents the DSTwo-DS link from being too busy + // to return button statuses. + ++skip_rate; + IPPU.RenderThisFrame = FALSE; + sync_next += frame_time; + } + else if(syncdif < 0) + { + ConsistentlyEarly = FALSE; + AutoCPUFrequency = 5; + LastAutoCPUTime = syncnow; + + /* + * If we're consistently late, delay up to 8 frames. + * + * That really helps with certain games, such as + * Super Mario RPG and Yoshi's Island. + */ + if(++skip_rate < 10) { - IPPU.RenderThisFrame = FALSE; - sync_next += frame_time; + if(syncdif >= -11719 /* not more than 500.0 ms late */) + { + IPPU.RenderThisFrame = FALSE; + sync_next += frame_time; + } + else + { //lag more than 0.5s, maybe paused + IPPU.RenderThisFrame = TRUE; + sync_next = syncnow + frame_time; + } } else - { //lag more than 0.5s, maybe paused + { + skip_rate = 0; IPPU.RenderThisFrame = TRUE; sync_next = syncnow + frame_time; } } - else + else // Early { + ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; skip_rate = 0; - IPPU.RenderThisFrame = TRUE; - sync_next = syncnow + frame_time; - } - } - else // Early - { - skip_rate = 0; - if (syncdif > 0) - { - do { - S9xProcessSound (0); + if (syncdif > 0) + { + do { + S9xProcessSound (0); #ifdef ACCUMULATE_JOYPAD /* * This call allows NDSSFC to synchronise the DS controller more often. * If porting a later version of Snes9x into NDSSFC, it is essential to * preserve it. */ - NDSSFCAccumulateJoypad (); + NDSSFCAccumulateJoypad (); #endif - syncdif = sync_next - getSysTime(); - } while (syncdif > 0); - } + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); + } - IPPU.RenderThisFrame = TRUE; - sync_next += frame_time; - } + IPPU.RenderThisFrame = TRUE; + sync_next += frame_time; + } #if 0 - if(++framenum >= 60) - { - syncdif = syncnow - sync_last; - sync_last = syncnow; - framenum = 0; - //printf("T %d %d\n", syncdif*42667/1000, realframe); - realframe = 0; - } + if(++framenum >= 60) + { + syncdif = syncnow - sync_last; + sync_last = syncnow; + framenum = 0; + //printf("T %d %d\n", syncdif*42667/1000, realframe); + realframe = 0; + } #endif - } - else /* if (Settings.SkipFrames != AUTO_FRAMERATE && !game_fast_forward && !temporary_fast_forward) */ - { - // frame_time is in getSysTime units: 42.667 microseconds. - uint32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; - sync_last = syncnow; - if (++skip_rate > Settings.SkipFrames) + } + else /* if (Settings.SkipFrames != AUTO_FRAMERATE) */ { - skip_rate = 0; - IPPU.RenderThisFrame = TRUE; - // Are we early? - syncdif = sync_next - syncnow; - if (syncdif > 0) + // frame_time is in getSysTime units: 42.667 microseconds. + uint32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; + sync_last = syncnow; + if (++skip_rate > Settings.SkipFrames) { - do { - S9xProcessSound (0); + skip_rate = 0; + IPPU.RenderThisFrame = TRUE; + // Are we early? + syncdif = sync_next - syncnow; + if (syncdif > 0) + { + ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; + do { + S9xProcessSound (0); #ifdef ACCUMULATE_JOYPAD /* * This call allows NDSSFC to synchronise the DS controller more often. * If porting a later version of Snes9x into NDSSFC, it is essential to * preserve it. */ - NDSSFCAccumulateJoypad (); + NDSSFCAccumulateJoypad (); #endif - syncdif = sync_next - getSysTime(); - } while (syncdif > 0); - // After that little delay, what time is it? - syncnow = getSysTime(); + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); + // After that little delay, what time is it? + syncnow = getSysTime(); + } + else + { + // Nope, we're late. + ConsistentlyEarly = FALSE; + AutoCPUFrequency = 5; + LastAutoCPUTime = syncnow; + } + sync_next = syncnow + frame_time * (Settings.SkipFrames + 1); + } + else + { + IPPU.RenderThisFrame = FALSE; } - sync_next = syncnow + frame_time * (Settings.SkipFrames + 1); - } - else - { - IPPU.RenderThisFrame = FALSE; } } @@ -887,6 +919,20 @@ void S9xSyncSpeed () next1.tv_usec %= 1000000; } #endif + +finalise: ; + + if (syncnow - LastAutoCPUTime >= CPU_DOWNCLOCK_DETERMINATION_INTERVAL) { + if (ConsistentlyEarly && AutoCPUFrequency > 0) + AutoCPUFrequency--; + + LastAutoCPUTime = syncnow; + ConsistentlyEarly = TRUE; + // will get unset if the CPU should stay the same at next check + } + + if (game_config.clock_speed_number == 0 && LastAutoCPUFrequency != AutoCPUFrequency) + GameFrequencyCPU (); } bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) diff --git a/source/nds/entry.h b/source/nds/entry.h index a6bd350..2d3f7db 100644 --- a/source/nds/entry.h +++ b/source/nds/entry.h @@ -8,6 +8,8 @@ extern "C" { void game_restart(void); int load_gamepak(char* file); + + extern unsigned int AutoCPUFrequency; #ifdef __cplusplus } #endif diff --git a/source/nds/gui.c b/source/nds/gui.c index 4b5955a..2dad9c8 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -289,7 +289,6 @@ u32 game_enable_audio = 1; /****************************************************************************** ******************************************************************************/ static u32 menu_cheat_page = 0; -u32 clock_speed_number = 5; u32 gamepad_config_menu; /****************************************************************************** @@ -1665,8 +1664,10 @@ void GameFrequencyCPU() { u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 - if(clock_speed_number <= 5) - ds2_setCPUclocklevel(clock_speed_table[clock_speed_number]); + if (game_config.clock_speed_number == 0) + ds2_setCPUclocklevel(clock_speed_table[AutoCPUFrequency]); + else if(game_config.clock_speed_number <= 6) + ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number - 1]); } void savefast_int(void) @@ -1776,8 +1777,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) HighFrequencyCPU(); // Crank it up, leave quickly if(gamepak_name[0] != 0) { - game_config.clock_speed_number = clock_speed_number; - reorder_latest_file(); S9xAutoSaveSRAM (); save_game_config_file(); @@ -2828,6 +2827,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] }; + char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; char *on_off_options[] = { (char*)&msg[MSG_GENERAL_OFF], (char*)&msg[MSG_GENERAL_ON] }; @@ -3002,8 +3003,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_OPTIONS], NULL, 0), - //CPU speed - /* 01 */ NUMERIC_SELECTION_OPTION(NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], &clock_speed_number, 6, NULL, 1), + //CPU speed (string: shows MHz) + /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], cpu_frequency_options, + &game_config.clock_speed_number, 7, NULL, PASSIVE_TYPE, 1), /* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options, &emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2), @@ -4113,8 +4115,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(gamepak_name[0] != 0) { - game_config.clock_speed_number = clock_speed_number; - reorder_latest_file(); S9xAutoSaveSRAM (); save_game_config_file(); @@ -4284,8 +4284,7 @@ u32 load_font() --------------------------------------------------------*/ void init_game_config(void) { - game_config.clock_speed_number = 5; // 396 MHz by default - clock_speed_number = 5; + game_config.clock_speed_number = 0; // "Auto" by default game_config.graphic = 3; // By default, have a good-looking aspect ratio game_config.frameskip_value = 0; // Automatic frame skipping game_config.SoundSync = 0; // Prefer fluid images by default @@ -4341,7 +4340,6 @@ void load_game_config_file(void) { fread(&game_config, 1, sizeof(GAME_CONFIG), fp); - clock_speed_number = game_config.clock_speed_number; game_set_frameskip(); game_set_fluidity(); } diff --git a/source/nds/gui.h b/source/nds/gui.h index b390b69..df1bff9 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -48,7 +48,25 @@ struct _EMU_CONFIG struct _GAME_CONFIG { - u32 clock_speed_number; + /* + * PreviouslyUsed_20130205_2 was formerly known as + * 'clock_speed_number'; its values were in [0, 5]. [0, 5] were mapped + * to 240, 300, 336, 360, 384 and 394 MHz respectively. + * Version 1.29 changes the value range for 'clock_speed_number' to + * [0, 6], with 0 as an automatic CPU speed setting. + * Change rationale: The default value becomes 0 instead of 5. + * If this variable were to be used as is, the meaning of the default + * value would change. Games which had a configuration file before + * 1.29 would be using the older default of 5 (394 MHz), the meaning + * of which would become 384 MHz instead of "staying the default". + * Games which did not have a configuration file before 1.29 would be + * using the correct default. + * This would confuse users or cause undue hassle. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE + * FOR WHICH IT WAS INTENDED. + */ + u32 PreviouslyUsed_20130205_2; u32 Reserved0; /* * PreviouslyUsed_20130205_1 was formerly known as 'frameskip_value'; @@ -78,7 +96,8 @@ struct _GAME_CONFIG u32 HotkeyToggleSound; u32 SoundSync; u32 frameskip_value; - u32 Reserved2[43]; + u32 clock_speed_number; + u32 Reserved2[42]; }; typedef enum diff --git a/source/nds/message.h b/source/nds/message.h index 86389b1..e58d7b8 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -48,6 +48,13 @@ enum MSG MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, + MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC, + MSG_OPTIONS_CPU_FREQUENCY_0, + MSG_OPTIONS_CPU_FREQUENCY_1, + MSG_OPTIONS_CPU_FREQUENCY_2, + MSG_OPTIONS_CPU_FREQUENCY_3, + MSG_OPTIONS_CPU_FREQUENCY_4, + MSG_OPTIONS_CPU_FREQUENCY_5, MSG_OPTIONS_CARD_CAPACITY /* unused if !defined(ENABLE_FREE_SPACE) */, MSG_OPTIONS_RESET, MSG_OPTIONS_VERSION, -- cgit v1.2.3 From 8c5f5ba1823ac57f78ef6bec72fca93c45d0d2fa Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 00:43:21 -0500 Subject: Document the auto CPU behavior a bit. --- source/nds/entry.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 08e95cb..5cca41e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -642,6 +642,18 @@ static unsigned int sync_next = 0; static unsigned int skip_rate= 0; +/* + * Automatic CPU frequency support is here. + * Whenever, after one downclock determination interval, each frame rendered + * during it has been rendered at least as early as CPU_DOWNCLOCK_EARLY_TIME, + * lower the CPU frequency in response. + * If at least one frame has been early, but not early enough, the CPU + * frequency stays stable. + * If at least one frame has been late, the CPU will have be switched back + * to 396 MHz. + * This improves battery life to a certain extent. + */ + #define CPU_DOWNCLOCK_EARLY_TIME 293 /* 1 = 42.667 us. 391 = 16.67 ms */ #define CPU_DOWNCLOCK_DETERMINATION_INTERVAL 46874 /* 23437 = 1 s */ -- cgit v1.2.3 From 4ac61d443d5786db1b1e365e0005a1d5740183b0 Mon Sep 17 00:00:00 2001 From: BassAceGold Date: Wed, 6 Feb 2013 00:56:33 -0500 Subject: Load the game from plug-in launch arguments. Make the CATSFC system directory become the one transferred via arguments in that case. --- source/nds/gui.c | 276 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 143 insertions(+), 133 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 2dad9c8..495e3c8 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -45,10 +45,13 @@ char rom_path[MAX_PATH]; char gamepak_name[MAX_PATH]; char gcheat_filename[MAX_PATH]; +//program arguments +char argv[2][MAX_PATH]; + // If adding a language, make sure you update the size of the array in // message.h too. char *lang[3] = - { + { "English", // 0 "简体中文", // 1 "Français", // 2 @@ -571,7 +574,7 @@ static int manage_filelist_info(struct FILE_LIST_INFO *filelist_infop, int flag) int i; void *pt; - //Increase all + //Increase all if(flag & 0x1) { i = NAME_MEM_SIZE; @@ -1095,7 +1098,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) //Path if(-1 == redraw) { draw_hscroll_over(0); - draw_hscroll_init(down_screen_addr, 49, 10, 170, COLOR_TRANS, + draw_hscroll_init(down_screen_addr, 49, 10, 170, COLOR_TRANS, COLOR_WHITE, default_dir_name); path_scroll = 0x8000; //first scroll left } @@ -1142,7 +1145,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) pt = file_list[m]; } - draw_hscroll_init(down_screen_addr, 41, 40 + k*27, 185, + draw_hscroll_init(down_screen_addr, 41, 40 + k*27, 185, COLOR_TRANS, color, pt); } @@ -1273,7 +1276,7 @@ u32 play_screen_snapshot(void) if(draw_yesno_dialog(DOWN_SCREEN, 115, msg[MSG_GENERAL_CONFIRM_WITH_A], msg[MSG_GENERAL_CANCEL_WITH_B])) return 1; - else + else return 0; } @@ -1378,7 +1381,7 @@ u32 play_screen_snapshot(void) time1= time0; } break; - + case CURSOR_DOWN: if(!pause) { @@ -1386,21 +1389,21 @@ u32 play_screen_snapshot(void) time1= time0; } break; - + case CURSOR_LEFT: time1 = ticks; if(i > 1) i -= 2; else if(i == 1) i= file_num -1; else i= file_num -2; break; - + case CURSOR_RIGHT: time1 = ticks; break; - + case CURSOR_SELECT: if(!pause) - { + { time1 = -1; pause= 1; } @@ -1408,15 +1411,15 @@ u32 play_screen_snapshot(void) { time1 = ticks; pause= 0; - } + } break; - - case CURSOR_BACK: + + case CURSOR_BACK: if(screenp) free((void*)screenp); //deconstruct filelist_info struct manage_filelist_info(&filelist_info, -1); repeat = 0; - break; + break; default: gui_action= CURSOR_NONE; break; @@ -1456,7 +1459,7 @@ int search_dir(char *directory, char* directory_path) //while((current_file = readdir(current_dir)) != NULL) while((current_file = readdir_ex(current_dir, &st)) != NULL) { - //Is directory + //Is directory if(S_ISDIR(st.st_mode)) { if(strcmp(".", current_file->d_name) || strcmp("..", current_file->d_name)) @@ -1635,7 +1638,7 @@ int save_state(char* file, void* screen) n = ftell(fp); ds2_getTime(&time); - sprintf(str, "%02d-%02d %02d:%02d:%02d", + sprintf(str, "%02d-%02d %02d:%02d:%02d", time.month, time.day, time.hours, time.minutes, time.seconds); PRINT_STRING_BG(screen, str, COLOR_WHITE, COLOR_BLACK, 0, 0); @@ -1709,7 +1712,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) MENU_TYPE *current_menu = NULL; MENU_OPTION_TYPE *current_option = NULL; MENU_OPTION_TYPE *display_option = NULL; - + u32 current_option_num; // u32 parent_option_num; u32 string_select; @@ -1801,7 +1804,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) strcat(line_buffer, "/"); strcat(line_buffer, tmp_filename); - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); @@ -1833,71 +1836,36 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(current_menu); } } - - bool Get_Args(char *file, char **filebuf) - { - FILE* dat = fat_fopen(file, "rb"); - if(dat) - { - int i = 0; - while(!fat_feof (dat)) - { - fat_fgets(filebuf[i], 512, dat); - int len = strlen(filebuf[i]); - if(filebuf[i][len - 1] == '\n') - filebuf[i][len - 1] = '\0'; - i++; - } - - fat_fclose(dat); - fat_remove(file); - return i; - } - return 0; - } - int CheckLoad_Arg() - { - char args[2][512]; - char *argarray[2]; - - argarray[0] = args[0]; - argarray[1] = args[1]; - - if(!Get_Args("/plgargs.dat", argarray)) - return 0; - - fat_remove("plgargs.dat"); - - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); - draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); + int Menu_loadGame(char *filename){ + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); + ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - HighFrequencyCPU(); - int load_result = load_gamepak(args[1]); - LowFrequencyCPU(); + HighFrequencyCPU(); + int load_result = load_gamepak(filename); + LowFrequencyCPU(); - if(load_result == -1) - { - first_load = 1; - gamepak_name[0] = '\0'; - return 0; - } + if(load_result == -1) + { + first_load = 1; + gamepak_name[0] = '\0'; + return 0; + } - strcpy(gamepak_name, args[1]); - first_load = 0; - load_game_config_file(); + strcpy(gamepak_name, filename); + first_load = 0; + load_game_config_file(); - return_value = 1; - repeat = 0; + return_value = 1; + repeat = 0; - reorder_latest_file(); - get_savestate_filelist(); + reorder_latest_file(); + get_savestate_filelist(); - game_fast_forward= 0; - return 1; - - } + game_fast_forward= 0; + return 1; + } void menu_restart() { @@ -2111,7 +2079,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } } } - + void menu_load_state() { if(!first_load) @@ -2151,7 +2119,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) //right if(gui_action == CURSOR_SELECT) { - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(up_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_LOADING]); HighFrequencyCPU(); @@ -2235,7 +2203,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } else if(current_option_num == 2) //delette single { - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); if(SavedStateFileExists(delette_savestate_num)) { @@ -2303,7 +2271,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { m= current_menu->screen_focus -1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } else @@ -2313,7 +2281,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) m= current_menu->focus_option - current_menu->screen_focus+2; for(n= 0; n < SUBMENU_ROW_NUM-1; n++) - draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[m+n].display_string); } } @@ -2321,7 +2289,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(current_option_num == 0) { draw_hscroll_over(0); - draw_hscroll_init(down_screen_addr, 50, 9, 180, + draw_hscroll_init(down_screen_addr, 50, 9, 180, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string); } @@ -2334,7 +2302,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(m >= SUBMENU_ROW_NUM) m -= 1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } @@ -2348,7 +2316,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { m = current_menu->screen_focus -1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } else @@ -2363,7 +2331,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(k > SUBMENU_ROW_NUM) k = SUBMENU_ROW_NUM; for(n= 1; n < k; n++) - draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[m+n].display_string); } } @@ -2375,7 +2343,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(current_option_num == 0) { draw_hscroll_over(0); - draw_hscroll_init(down_screen_addr, 50, 9, 180, + draw_hscroll_init(down_screen_addr, 50, 9, 180, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string); } } @@ -2390,7 +2358,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) m = current_menu->screen_focus -1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } break; @@ -2666,7 +2634,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) mm = *(display_option->current_option); sprintf(line_buffer, *(display_option->display_string), str[mm]); - + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 27, 38 + (display_option-> line_number)*32); } @@ -2757,7 +2725,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 95, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE_WAITING]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - load_language_msg(LANGUAGE_PACK, emu_config.language); + load_language_msg(LANGUAGE_PACK, emu_config.language); // gui_change_icon(emu_config.language); // uncomment if images change per language [Neb] if(first_load) @@ -2846,18 +2814,18 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_VIDEO_AUDIO], NULL, 0), - /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_VIDEO_ASPECT_RATIO], screen_ratio_options, + /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_VIDEO_ASPECT_RATIO], screen_ratio_options, &game_config.graphic, 5, NULL, PASSIVE_TYPE, 1), - /* 02 */ STRING_SELECTION_OPTION(game_fastforward, NULL, &msg[FMT_VIDEO_FAST_FORWARD], on_off_options, + /* 02 */ STRING_SELECTION_OPTION(game_fastforward, NULL, &msg[FMT_VIDEO_FAST_FORWARD], on_off_options, &game_fast_forward, 2, NULL, ACTION_TYPE, 2), - + /* 03 */ STRING_SELECTION_OPTION(game_disableAudio, NULL, &msg[FMT_AUDIO_SOUND], sound_seletion, &game_enable_audio, 2, NULL, ACTION_TYPE, 3), - + /* 04 */ STRING_SELECTION_OPTION(game_set_fluidity, NULL, &msg[FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE], fluidity_options, &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), - + /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, &game_config.frameskip_value, 10 /* auto (0) and 2..10 (1..9) make 10 option values */, NULL, ACTION_TYPE, 5) }; @@ -2905,9 +2873,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_CHEATS], NULL,0), - /* 01 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, + /* 01 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, ((CHEATS_PER_PAGE * menu_cheat_page) + 0), 1), - /* 02 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, + /* 02 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, ((CHEATS_PER_PAGE * menu_cheat_page) + 1), 2), /* 03 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, ((CHEATS_PER_PAGE * menu_cheat_page) + 2), 3), @@ -2974,7 +2942,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) /*-------------------------------------------------------- Tools --------------------------------------------------------*/ - MENU_OPTION_TYPE tools_options[] = + MENU_OPTION_TYPE tools_options[] = { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_TOOLS], NULL, 0), @@ -2986,10 +2954,10 @@ u32 menu(u16 *screen, bool8 FirstInvocation) // /* 02 */ SUBMENU_OPTION(&tools_keyremap_menu, &msg[MSG_SUB_MENU_31], NULL, 2), -// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options, +// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options, // &game_config.backward, 2, NULL, ACTION_TYPE, 3), -// /* 04 */ NUMERIC_SELECTION_ACTION_OPTION(time_period_action, time_period_passive, &msg[MSG_SUB_MENU_32], +// /* 04 */ NUMERIC_SELECTION_ACTION_OPTION(time_period_action, time_period_passive, &msg[MSG_SUB_MENU_32], // &game_config.backward_time, 6, NULL, 4) }; @@ -3038,7 +3006,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) Load_game --------------------------------------------------------*/ MENU_TYPE latest_game_menu; - + MENU_OPTION_TYPE load_game_options[] = { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_LOAD_GAME_MENU_TITLE], NULL, 0), @@ -3169,7 +3137,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) show_icon(down_screen_addr, &ICON_MSEL, 173, 131); } else { - show_icon(down_screen_addr, &ICON_NEXIT, 187, 75); + show_icon(down_screen_addr, &ICON_NEXIT, 187, 75); show_icon(down_screen_addr, &ICON_MNSEL, 173, 131); } draw_string_vcenter(down_screen_addr, 175, 131, 75, COLOR_WHITE, line_buffer); @@ -3364,7 +3332,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { ext_pos= strrchr(emu_config.latest_file[k], '/'); if(ext_pos != NULL) - draw_hscroll_init(down_screen_addr, 26, 40 + k*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + k*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1); else break; @@ -3422,7 +3390,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void latest_game_menu_end() { u32 k; - + for(k= 0; k < 5; k++) { if(emu_config.latest_file[k][0] != '\0') @@ -3442,12 +3410,12 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1); } current_option_num += 1; - if(current_option_num >= latest_game_menu.num_options) + if(current_option_num >= latest_game_menu.num_options) current_option_num = 0; current_option = current_menu->options + current_option_num; @@ -3456,7 +3424,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, ext_pos+1); } @@ -3468,7 +3436,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1); } @@ -3481,7 +3449,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, ext_pos+1); } @@ -3562,7 +3530,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void game_fastforward() { } - + void reload_cheats_page() @@ -3610,7 +3578,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) mdelay(100); // to prevent ds2_setBacklight() from crashing ds2_setBacklight(3); } - + wait_Allkey_release(0); bg_screenp= (u16*)malloc(256*192*2); @@ -3619,7 +3587,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(gamepak_name[0] == 0) { first_load = 1; - if(CheckLoad_Arg()) + //try auto loading games passed through argv first + if(Menu_loadGame(argv[1])) repeat = 0; else { @@ -3642,7 +3611,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(&main_menu); // Menu loop - + while(repeat) { display_option = current_menu->options; @@ -3691,7 +3660,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) focus_option = line_num; } current_menu -> focus_option = focus_option; - + i = focus_option - screen_focus; display_option += i +1; @@ -3737,7 +3706,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) color= COLOR_ACTIVE_ITEM; else color= COLOR_INACTIVE_ITEM; - + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 23, 40 + i*27); } } @@ -3767,7 +3736,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) current_option_num = (inputdata.y / 80) * 3 + (inputdata.x / 86); current_option = current_menu->options + current_option_num; - + if(current_option -> option_type & HIDEN_TYPE) break; else if(current_option->option_type & ACTION_TYPE) @@ -3776,9 +3745,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(current_option->sub_menu); } /* This is the majority case, covering all menus except save states, screen shots, and game loading */ - else if(current_menu != (main_menu.options + 1)->sub_menu + else if(current_menu != (main_menu.options + 1)->sub_menu && current_menu != ((main_menu.options +1)->sub_menu->options + 3)->sub_menu - && current_menu != (main_menu.options +3)->sub_menu + && current_menu != (main_menu.options +3)->sub_menu && current_menu != ((main_menu.options +3)->sub_menu->options + 1)->sub_menu && current_menu != (main_menu.options +6)->sub_menu && current_menu != ((main_menu.options +6)->sub_menu->options + 2)->sub_menu) @@ -3846,9 +3815,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) next_option_num = 3; else break; - + struct _MENU_OPTION_TYPE *next_option = current_menu->options + next_option_num; - + if(next_option_num == 1 /* write */ || next_option_num == 2 /* read */) { u32 current_option_val = *(next_option->current_option); @@ -3893,7 +3862,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } break; } - + gui_action = CURSOR_SELECT; if(next_option -> option_type & HIDEN_TYPE) break; @@ -3920,9 +3889,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) next_option_num = 2; else break; - + struct _MENU_OPTION_TYPE *next_option = current_menu->options + next_option_num; - + if(next_option_num == 2) { u32 current_option_val = *(next_option->current_option); @@ -3960,7 +3929,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } break; } - + gui_action = CURSOR_SELECT; if(next_option -> option_type & HIDEN_TYPE) break; @@ -4093,7 +4062,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(current_option->sub_menu); break; - case CURSOR_BACK: + case CURSOR_BACK: if(current_menu != &main_menu) choose_menu(current_menu->options->sub_menu); else @@ -4112,7 +4081,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) destroy_dynamic_cheats(); if(bg_screenp != NULL) free((void*)bg_screenp); - + if(gamepak_name[0] != 0) { reorder_latest_file(); @@ -4120,7 +4089,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) save_game_config_file(); } save_emu_config_file(); - + ds2_clearScreen(DOWN_SCREEN, 0); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); copy_screen(up_screen_addr, (void*) screen, 0, 0, 256, 192); @@ -4396,7 +4365,7 @@ int save_game_config_file(void) sprintf(game_config_filename, "%s/%s", DEFAULT_CFG_DIR, gamepak_name); pt = strrchr(game_config_filename, '.'); - if(NULL == pt) + if(NULL == pt) return -1; *pt = '\0'; @@ -4472,7 +4441,7 @@ void reorder_latest_file(void) else break; } - + strcpy(emu_config.latest_file[i-1], full_file); } return ; @@ -4638,7 +4607,7 @@ void get_newest_savestate(char *name_buffer) get_savestate_filename(latest_save, name_buffer); } -static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon, +static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon, u16 day, u16 wday, u16 hour, u16 min, u16 sec, u32 msec) { char *weekday_strings[] = @@ -4646,7 +4615,7 @@ static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon, "SUN", "MON", "TUE", "WED", "TUR", "FRI", "SAT" }; - sprintf(buffer, "%s %02d/%02d/%04d %02d:%02d:%02d", weekday_strings[wday], + sprintf(buffer, "%s %02d/%02d/%04d %02d:%02d:%02d", weekday_strings[wday], day, mon, year, hour, min, sec); } @@ -4671,7 +4640,7 @@ static u32 save_ss_bmp(u16 *image) change_ext(gamepak_name, ss_filename, "_"); ds2_getTime(¤t_time); - sprintf(save_ss_path, "%s/%s%02d%02d%02d%02d%02d.bmp", DEFAULT_SS_DIR, ss_filename, + sprintf(save_ss_path, "%s/%s%02d%02d%02d%02d%02d.bmp", DEFAULT_SS_DIR, ss_filename, current_time.month, current_time.day, current_time.hours, current_time.minutes, current_time.seconds); for(y = 0; y < 192; y++) @@ -4706,7 +4675,7 @@ void quit(void) __asm__ __volatile__("or %0, $0, $ra" : "=r" (reg_ra) :); - + dbg_printf("return address= %08x\n", reg_ra); */ @@ -4732,6 +4701,37 @@ u32 file_length(FILE* file) /* * GUI Initialize */ +static bool Get_Args(char *file, char **filebuf){ + FILE* dat = fat_fopen(file, "rb"); + if(dat){ + int i = 0; + while(!fat_feof (dat)){ + fat_fgets(filebuf[i], 512, dat); + int len = strlen(filebuf[i]); + if(filebuf[i][len - 1] == '\n') + filebuf[i][len - 1] = '\0'; + i++; + } + + fat_fclose(dat); + fat_remove(file); + return i; + } + return 0; +} + +int CheckLoad_Arg(){ + char *argarray[2]; + argarray[0] = argv[0]; + argarray[1] = argv[1]; + + if(!Get_Args("/plgargs.dat", argarray)) + return 0; + + fat_remove("plgargs.dat"); + return 1; +} + void gui_init(u32 lang_id) { int flag; @@ -4749,7 +4749,17 @@ void gui_init(u32 lang_id) //Find the "CATSFC" system directory DIR *current_dir; - strcpy(main_path, "fat:/CATSFC"); + if(CheckLoad_Arg()){ + //copy new folder location + strcpy(main_path, "fat:"); + strcat(main_path, argv[0]); + //strip off the binary name + char *endStr = strrchr(main_path, '/'); + *endStr = '\0'; + } + else + strcpy(main_path, "fat:/CATSFC"); + current_dir = opendir(main_path); if(current_dir) closedir(current_dir); -- cgit v1.2.3 From ea330e8f79c16894deda51509e769cbd02ff83df Mon Sep 17 00:00:00 2001 From: BassAceGold Date: Wed, 6 Feb 2013 02:04:39 -0500 Subject: Fix settings not getting loaded with a ROM provided by plugin arguments. --- source/nds/entry.cpp | 2 +- source/nds/entry.h | 2 +- source/nds/gui.c | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 5cca41e..8b1724e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -499,7 +499,7 @@ void game_restart(void) S9xReset (); } -int load_gamepak(char* file) +int load_gamepak(const char* file) { CPU.Flags = 0; // mdelay(50); // Delete this delay diff --git a/source/nds/entry.h b/source/nds/entry.h index 2d3f7db..0728768 100644 --- a/source/nds/entry.h +++ b/source/nds/entry.h @@ -7,7 +7,7 @@ extern "C" { void game_restart(void); - int load_gamepak(char* file); + int load_gamepak(const char* file); extern unsigned int AutoCPUFrequency; #ifdef __cplusplus diff --git a/source/nds/gui.c b/source/nds/gui.c index 495e3c8..427f7d7 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1853,7 +1853,21 @@ u32 menu(u16 *screen, bool8 FirstInvocation) return 0; } - strcpy(gamepak_name, filename); + char tempPath[MAX_PATH]; + strcpy(tempPath, filename); + + //update folders and names for settings/config uses + char *dirEnd = strrchr(tempPath, '/'); + //make sure a valid path was provided + if(!dirEnd) + return 0; + + //copy file name as gamepak_name + strcpy(gamepak_name, dirEnd+1); + //then strip filename from directory path and set it + *dirEnd = '\0'; + strcpy(g_default_rom_dir, tempPath); + first_load = 0; load_game_config_file(); -- cgit v1.2.3 From a358ef69a85a7252ed6b5a30496c49b28b26eecd Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 02:18:35 -0500 Subject: Make all gamepak loads call LoadGameAndItsData, that way its "Loading" screen, current gamepak variables, game config stuff and so on are all consistent. --- source/nds/gui.c | 106 ++++++++++++++----------------------------------------- 1 file changed, 27 insertions(+), 79 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 427f7d7..f71f70f 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1788,56 +1788,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) quit(); } - void menu_load() - { - char *file_ext[] = { ".smc", ".sfc", ".zip", NULL }; - - if(gamepak_name[0] != 0) - { - S9xAutoSaveSRAM (); - save_game_config_file(); - } - - if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1) - { - strcpy(line_buffer, g_default_rom_dir); - strcat(line_buffer, "/"); - strcat(line_buffer, tmp_filename); - - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); - draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - - HighFrequencyCPU(); - int load_result = load_gamepak(line_buffer); - LowFrequencyCPU(); - if(load_result == -1) - { - first_load = 1; - gamepak_name[0] = '\0'; - return; - } - - strcpy(gamepak_name, tmp_filename); - first_load = 0; - load_game_config_file(); -// time_period_action(); - - return_value = 1; - repeat = 0; - - reorder_latest_file(); - get_savestate_filelist(); - - game_fast_forward= 0; - } - else - { - choose_menu(current_menu); - } - } - - int Menu_loadGame(char *filename){ + int LoadGameAndItsData(char *filename){ draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); @@ -1881,6 +1832,30 @@ u32 menu(u16 *screen, bool8 FirstInvocation) return 1; } + void menu_load() + { + char *file_ext[] = { ".smc", ".sfc", ".zip", NULL }; + + if(gamepak_name[0] != 0) + { + S9xAutoSaveSRAM (); + save_game_config_file(); + } + + if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1) + { + strcpy(line_buffer, g_default_rom_dir); + strcat(line_buffer, "/"); + strcat(line_buffer, tmp_filename); + + LoadGameAndItsData(line_buffer); + } + else + { + choose_menu(current_menu); + } + } + void menu_restart() { if(!first_load) @@ -3486,10 +3461,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { char *ext_pos; - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, 0); - draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - if(gamepak_name[0] != 0) { S9xAutoSaveSRAM (); @@ -3509,36 +3480,13 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ext_pos = emu_config.latest_file[current_option_num -1]; - HighFrequencyCPU(); - int load_result = load_gamepak(ext_pos); - LowFrequencyCPU(); - - if(load_result == -1) { - first_load = 1; - return; - } - - strcpy(g_default_rom_dir, ext_pos); - ext_pos = strrchr(g_default_rom_dir, '/'); - *ext_pos= '\0'; - strcpy(gamepak_name, ext_pos+1); - - - load_game_config_file(); -// time_period_action(); - - reorder_latest_file(); - get_savestate_filelist(); - game_fast_forward= 0; + LoadGameAndItsData(ext_pos); get_newest_savestate(tmp_filename); if(tmp_filename[0] != '\0') { load_state(tmp_filename); } - - return_value = 1; - repeat = 0; } void game_fastforward() @@ -3602,7 +3550,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { first_load = 1; //try auto loading games passed through argv first - if(Menu_loadGame(argv[1])) + if(LoadGameAndItsData(argv[1])) repeat = 0; else { -- cgit v1.2.3 From 9829c836089c44d5c8cc7e3d0f7007ab33b0cb1a Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 02:31:55 -0500 Subject: Fix the loading screen for a ROM appearing for a split second after the splash screen. Fix uninitialised memory access in Check_LoadArg. --- source/nds/gui.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index f71f70f..5d969a2 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -3550,7 +3550,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { first_load = 1; //try auto loading games passed through argv first - if(LoadGameAndItsData(argv[1])) + if(strlen(argv[1]) > 0 && LoadGameAndItsData(argv[1])) repeat = 0; else { @@ -4683,6 +4683,8 @@ static bool Get_Args(char *file, char **filebuf){ } int CheckLoad_Arg(){ + argv[0][0] = '\0'; // Initialise the first byte to be a NULL in case + argv[1][0] = '\0'; // there are no arguments to avoid uninit. memory char *argarray[2]; argarray[0] = argv[0]; argarray[1] = argv[1]; -- cgit v1.2.3 From b08a201ea2de43d70047673114c705a26887ea4b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 02:53:53 -0500 Subject: Allow all audio buffers to get full again before declaring underflow. --- source/nds/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 8b1724e..a5a98de 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -1053,7 +1053,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT) { LastSoundEmissionTime++; return; -- cgit v1.2.3 From 772e24ae503310eb1ee0d5ed5061eebb138e5808 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 03:46:48 -0500 Subject: Reinstate frame skipping options 0 and 1, but keep the new meaning (>= 2 equivalent skip level) for automatic frame skipping. Remove the automatic CPU frequency option, which was making audio emit 0.25 second of silence every so often. --- source/nds/entry.cpp | 2 +- source/nds/gui.c | 16 +++++++--------- source/nds/gui.h | 53 ++++++++++++++-------------------------------------- source/nds/message.h | 5 ++--- 4 files changed, 24 insertions(+), 52 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index a5a98de..ca27249 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -390,7 +390,7 @@ void game_set_frameskip() } else { - Settings.SkipFrames = game_config.frameskip_value + 1 /* 1 -> 2 and so on */; + Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */; } } diff --git a/source/nds/gui.c b/source/nds/gui.c index 5d969a2..838b5b9 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1667,10 +1667,8 @@ void GameFrequencyCPU() { u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 - if (game_config.clock_speed_number == 0) - ds2_setCPUclocklevel(clock_speed_table[AutoCPUFrequency]); - else if(game_config.clock_speed_number <= 6) - ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number - 1]); + if(game_config.clock_speed_number <= 5) + ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number]); } void savefast_int(void) @@ -2782,9 +2780,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) (char*)&msg[MSG_VIDEO_ASPECT_RATIO_3], (char*)&msg[MSG_VIDEO_ASPECT_RATIO_4]}; - char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; - char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] }; + char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] }; char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; @@ -2816,7 +2814,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, - &game_config.frameskip_value, 10 /* auto (0) and 2..10 (1..9) make 10 option values */, NULL, ACTION_TYPE, 5) + &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5) }; MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0); @@ -2962,7 +2960,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) //CPU speed (string: shows MHz) /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], cpu_frequency_options, - &game_config.clock_speed_number, 7, NULL, PASSIVE_TYPE, 1), + &game_config.clock_speed_number, 6, NULL, PASSIVE_TYPE, 1), /* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options, &emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2), @@ -4215,7 +4213,7 @@ u32 load_font() --------------------------------------------------------*/ void init_game_config(void) { - game_config.clock_speed_number = 0; // "Auto" by default + game_config.clock_speed_number = 5; // 396 MHz by default game_config.graphic = 3; // By default, have a good-looking aspect ratio game_config.frameskip_value = 0; // Automatic frame skipping game_config.SoundSync = 0; // Prefer fluid images by default diff --git a/source/nds/gui.h b/source/nds/gui.h index df1bff9..6bb9ed8 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -48,44 +48,9 @@ struct _EMU_CONFIG struct _GAME_CONFIG { - /* - * PreviouslyUsed_20130205_2 was formerly known as - * 'clock_speed_number'; its values were in [0, 5]. [0, 5] were mapped - * to 240, 300, 336, 360, 384 and 394 MHz respectively. - * Version 1.29 changes the value range for 'clock_speed_number' to - * [0, 6], with 0 as an automatic CPU speed setting. - * Change rationale: The default value becomes 0 instead of 5. - * If this variable were to be used as is, the meaning of the default - * value would change. Games which had a configuration file before - * 1.29 would be using the older default of 5 (394 MHz), the meaning - * of which would become 384 MHz instead of "staying the default". - * Games which did not have a configuration file before 1.29 would be - * using the correct default. - * This would confuse users or cause undue hassle. - * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. - * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE - * FOR WHICH IT WAS INTENDED. - */ - u32 PreviouslyUsed_20130205_2; + u32 clock_speed_number; u32 Reserved0; - /* - * PreviouslyUsed_20130205_1 was formerly known as 'frameskip_value'; - * its values were in [0, 10]. 0 was automatic frameskipping and - * [1, 10] were mapped to skip 0 to 9 frames respectively. - * Version 1.29 changes the value range for 'frameskip_value' to - * [0, 8], with 0 as automatic frameskipping and [1, 10] to skip 2 to - * 9 frames. - * Change rationale: Frame skip values under 2 cause too much - * communication between the DSTwo and the DS, therefore the DS cannot - * timely send controller information. - * If this variable were to be used as is, the meaning of the option - * would be changed for values in [1, 8], and values in [9, 10] would - * cause undefined behavior, including crashes. - * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. - * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE - * FOR WHICH IT WAS INTENDED. - */ - u32 PreviouslyUsed_20130205_1; + u32 frameskip_value; u32 graphic; u32 enable_audio; u32 Reserved1; @@ -95,8 +60,18 @@ struct _GAME_CONFIG u32 HotkeyTemporaryFastForward; u32 HotkeyToggleSound; u32 SoundSync; - u32 frameskip_value; - u32 clock_speed_number; + /* + * PreviouslyUsed_20130206_1 was for a second meaning of + * frameskip_value that is now dropped. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + */ + u32 PreviouslyUsed_20130206_1; + /* + * PreviouslyUsed_20130206_2 was for a second meaning of + * clock_speed_number that is now dropped. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + */ + u32 PreviouslyUsed_20130206_2; u32 Reserved2[42]; }; diff --git a/source/nds/message.h b/source/nds/message.h index e58d7b8..64c3a6c 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -48,7 +48,6 @@ enum MSG MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, - MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC, MSG_OPTIONS_CPU_FREQUENCY_0, MSG_OPTIONS_CPU_FREQUENCY_1, MSG_OPTIONS_CPU_FREQUENCY_2, @@ -77,8 +76,8 @@ enum MSG MSG_VIDEO_ASPECT_RATIO_4, MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC, - MSG_VIDEO_FRAME_SKIPPING_0 /* unused */, - MSG_VIDEO_FRAME_SKIPPING_1 /* unused */, + MSG_VIDEO_FRAME_SKIPPING_0, + MSG_VIDEO_FRAME_SKIPPING_1, MSG_VIDEO_FRAME_SKIPPING_2, MSG_VIDEO_FRAME_SKIPPING_3, MSG_VIDEO_FRAME_SKIPPING_4, -- cgit v1.2.3 From b277570daee54faf93804f5ae2d5e82e8fa11708 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 04:38:18 -0500 Subject: Quit saving the files so often for nothing; that uses up erase cycles on storage cards! Instead, save them once when the menu that contains the settings that the user changed is exited, IF the settings' values changed, OR once when updating the list of most-recently played games. Automatically save the SRAM in most cases, including game changes. This commit also makes it unnecessary to save the game config of the previous game when loading another, makes it load certain settings correctly, and MAY make it avoid creating a file for a game's settings if the user never changes them from the defaults. --- source/nds/gui.c | 58 +++++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 838b5b9..581c905 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1718,6 +1718,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) u16 *bg_screenp; u32 bg_screenp_color; + GAME_CONFIG PreviousGameConfig; // Compared with current settings to + EMU_CONFIG PreviousEmuConfig; // determine if they need to be saved + auto void choose_menu(); auto void menu_return(); auto void menu_exit(); @@ -1776,17 +1779,32 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void menu_exit() { HighFrequencyCPU(); // Crank it up, leave quickly - if(gamepak_name[0] != 0) - { - reorder_latest_file(); + if(gamepak_name[0] != 0) + { S9xAutoSaveSRAM (); - save_game_config_file(); } - save_emu_config_file(); quit(); } + void SaveConfigsIfNeeded() + { + if (memcmp(&PreviousGameConfig, &game_config, sizeof(GAME_CONFIG)) != 0) + save_game_config_file(); + if (memcmp(&PreviousEmuConfig, &emu_config, sizeof(EMU_CONFIG)) != 0) + save_emu_config_file(); + } + + void PreserveConfigs() + { + memcpy(&PreviousGameConfig, &game_config, sizeof(GAME_CONFIG)); + memcpy(&PreviousEmuConfig, &emu_config, sizeof(EMU_CONFIG)); + } + int LoadGameAndItsData(char *filename){ + if (gamepak_name[0] != '\0') { + S9xAutoSaveSRAM(); + } + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); @@ -1819,6 +1837,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) first_load = 0; load_game_config_file(); + PreserveConfigs(); // Make the emulator not save what we've JUST read + // but it will save the emulator configuration below for latest files return_value = 1; repeat = 0; @@ -1834,12 +1854,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { char *file_ext[] = { ".smc", ".sfc", ".zip", NULL }; - if(gamepak_name[0] != 0) - { - S9xAutoSaveSRAM (); - save_game_config_file(); - } - if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1) { strcpy(line_buffer, g_default_rom_dir); @@ -2056,10 +2070,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - //save game config - reorder_latest_file(); - save_game_config_file(); - SavedStateCacheInvalidate (); mdelay(500); // let the progress message linger @@ -2722,7 +2732,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ds2_flipScreen(UP_SCREEN, 1); } - save_emu_config_file(); LowFrequencyCPU(); // and back down wait_Allkey_release(0); } @@ -3459,12 +3468,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { char *ext_pos; - if(gamepak_name[0] != 0) - { - S9xAutoSaveSRAM (); - save_game_config_file(); - } - if(bg_screenp != NULL) { bg_screenp_color = COLOR16(43, 11, 11); } @@ -3521,11 +3524,13 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(NULL != current_menu) { if(current_menu->end_function) current_menu->end_function(); + SaveConfigsIfNeeded(); } current_menu = new_menu; current_option_num= current_menu -> focus_option; current_option = new_menu->options + current_option_num; + PreserveConfigs(); if(current_menu->init_function) current_menu->init_function(); } @@ -4038,18 +4043,11 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if (current_menu && current_menu->end_function) current_menu->end_function(); + SaveConfigsIfNeeded(); destroy_dynamic_cheats(); if(bg_screenp != NULL) free((void*)bg_screenp); - if(gamepak_name[0] != 0) - { - reorder_latest_file(); - S9xAutoSaveSRAM (); - save_game_config_file(); - } - save_emu_config_file(); - ds2_clearScreen(DOWN_SCREEN, 0); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); copy_screen(up_screen_addr, (void*) screen, 0, 0, 256, 192); -- cgit v1.2.3 From 3c3a97219dbe3a2e7555e6f65eb093d4f3435e49 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 04:57:12 -0500 Subject: Fix 2 compiler warnings in gui.c. --- source/nds/gui.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 581c905..9ce602c 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2852,10 +2852,12 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_SAVED_STATES], NULL, 0), - /* 01 */ NUMERIC_SELECTION_ACTION_OPTION(menu_save_state, NULL, &msg[FMT_SAVED_STATE_CREATE], &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 1), + // savestate_index is still a signed int + /* 01 */ NUMERIC_SELECTION_ACTION_OPTION(menu_save_state, NULL, &msg[FMT_SAVED_STATE_CREATE], (u32*) &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 1), + // savestate_index is still a signed int /* 02 */ NUMERIC_SELECTION_ACTION_OPTION(menu_load_state, NULL, - &msg[FMT_SAVED_STATE_LOAD], &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 2), + &msg[FMT_SAVED_STATE_LOAD], (u32*) &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 2), /* 03 */ SUBMENU_OPTION(&gamestate_delette_menu, &msg[MSG_SAVED_STATE_DELETE_GENERAL], NULL, 5), }; -- cgit v1.2.3 From 3dc666810732dcabb95a3bd1d02d4fcee0befd3f Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 05:59:22 -0500 Subject: Raise the sound frequency from 22050 Hz to 32000 Hz, which is like the SNES. Use sound interpolation to make it sound even more like the SNES. --- source/nds/ds2sound.h | 21 ++++++++++++--------- source/nds/entry.cpp | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'source/nds') diff --git a/source/nds/ds2sound.h b/source/nds/ds2sound.h index f51a6e1..8c0e2bf 100644 --- a/source/nds/ds2sound.h +++ b/source/nds/ds2sound.h @@ -1,21 +1,24 @@ // The sound buffer sizes used on the DS2's side, for each value of // Settings.SoundPlaybackRate. +// * Don't buffer too much, otherwise audio is delayed from video. +// * Don't go below one frame (20 milliseconds). +// * Buffer sizes must be multiples of 128. #define DS2_BUFFER_SIZE_4 512 /* tested working */ -#define DS2_BUFFER_SIZE_5 1024 /* like the SNES! tested working, but slow */ -#define DS2_BUFFER_SIZE_6 1024 /* tested working, slow because of upsampling */ -#define DS2_BUFFER_SIZE_7 1024 /* tested working, slow because of upsampling */ +#define DS2_BUFFER_SIZE_5 640 /* like the SNES! tested working */ +#define DS2_BUFFER_SIZE_6 896 /* tested working */ +#define DS2_BUFFER_SIZE_7 1024 /* tested working */ // The sampling rate for the sound, in Hz, for each value of // Settings.SoundPlaybackRate. #define SND_SAMPLE_RATE_1 8000 #define SND_SAMPLE_RATE_2 11025 #define SND_SAMPLE_RATE_3 16000 -#define SND_SAMPLE_RATE_4 22050 -#define SND_SAMPLE_RATE_5 32000 +#define SND_SAMPLE_RATE_4 22050 /* NDSSFC 1.06 - CATSFC 1.28 used this one */ +#define SND_SAMPLE_RATE_5 32000 /* like the SNES! */ #define SND_SAMPLE_RATE_6 44100 -#define SND_SAMPLE_RATE_7 48000 +#define SND_SAMPLE_RATE_7 48000 /* CATSFC 1.25 made using this one possible */ // Settings in use. The number should match in all three settings. -#define DS2_BUFFER_SIZE DS2_BUFFER_SIZE_4 -#define SND_SAMPLE_RATE SND_SAMPLE_RATE_4 -#define SNES9X_SRATE_ID 4 +#define DS2_BUFFER_SIZE DS2_BUFFER_SIZE_5 +#define SND_SAMPLE_RATE SND_SAMPLE_RATE_5 +#define SNES9X_SRATE_ID 5 diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index ca27249..723374c 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -425,7 +425,7 @@ void init_sfc_setting(void) //sound settings Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; Settings.FixFrequency = 1; - + Settings.InterpolatedSound = TRUE; Settings.H_Max = SNES_CYCLES_PER_SCANLINE; Settings.SkipFrames = AUTO_FRAMERATE; @@ -1042,7 +1042,7 @@ void S9xGenerateSound () } } -#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) - 1) /* -1 is for roundoff errors */ unsigned int LastSoundEmissionTime = 0; void S9xProcessSound (unsigned int) -- cgit v1.2.3 From 04037a309694dc56e3139f676b409ba7deab9298 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 06:27:11 -0500 Subject: When changing languages, quit doing the "Changing language, please wait..." as it only takes a few milliseconds. --- source/nds/gui.c | 14 -------------- source/nds/message.h | 3 --- 2 files changed, 17 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 9ce602c..5e02a55 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2709,21 +2709,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(gui_action == CURSOR_LEFT || gui_action == CURSOR_RIGHT) { HighFrequencyCPU(); // crank it up - if(bg_screenp != NULL) - { - bg_screenp_color = COLOR16(43, 11, 11); - memcpy(bg_screenp, down_screen_addr, 256*192*2); - } - else - bg_screenp_color = COLOR_BG; - - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); - draw_string_vcenter(down_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE]); - draw_string_vcenter(down_screen_addr, 36, 95, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE_WAITING]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); load_language_msg(LANGUAGE_PACK, emu_config.language); - // gui_change_icon(emu_config.language); // uncomment if images change per language [Neb] if(first_load) { @@ -2733,7 +2720,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } LowFrequencyCPU(); // and back down - wait_Allkey_release(0); } } diff --git a/source/nds/message.h b/source/nds/message.h index 64c3a6c..c7e79b8 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -121,9 +121,6 @@ enum MSG MSG_PROGRESS_SCREENSHOT_CREATION_SUCCEEDED, MSG_PROGRESS_SCREENSHOT_CREATION_FAILED, - MSG_CHANGE_LANGUAGE, - MSG_CHANGE_LANGUAGE_WAITING, - MSG_NO_SLIDE, MSG_PLAYING_SLIDE, MSG_PAUSE_SLIDE, -- cgit v1.2.3 From ebf48b1bf77d0093277640fd514877b3b26baeac Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 15:51:23 -0500 Subject: Yeah... Despite the audio optimisations, sound still crackles with display double-buffering. Disable that, again. --- source/nds/gui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.h b/source/nds/gui.h index 6bb9ed8..290a927 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,7 +24,7 @@ #include "fs_api.h" #include "gcheat.h" -#define UP_SCREEN_UPDATE_METHOD 1 +#define UP_SCREEN_UPDATE_METHOD 0 #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From 0b165c3133b2c97bfe2eaf6195f36094c1213164 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 16:16:43 -0500 Subject: Use key pictograms from Pictochat to display keys for yes/no dialog(ue)s. --- source/nds/gui.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 5e02a55..7270891 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -4140,7 +4140,61 @@ int load_language_msg(char *filename, u32 language) break; len= strlen(pt); - memcpy(dst, pt, len); + // memcpy(dst, pt, len); + + // Replace key definitions (*letter) with Pictochat icons + // while copying. + unsigned int curChar; + for (curChar = 0; curChar < len; curChar++) + { + if (pt[curChar] == '*') + { + switch (pt[curChar + 1]) + { + case 'A': + memcpy(&dst[curChar], HOTKEY_A_DISPLAY, 2); + curChar++; + break; + case 'B': + memcpy(&dst[curChar], HOTKEY_B_DISPLAY, 2); + curChar++; + break; + case 'X': + memcpy(&dst[curChar], HOTKEY_X_DISPLAY, 2); + curChar++; + break; + case 'Y': + memcpy(&dst[curChar], HOTKEY_Y_DISPLAY, 2); + curChar++; + break; + case 'L': + memcpy(&dst[curChar], HOTKEY_L_DISPLAY, 2); + curChar++; + break; + case 'R': + memcpy(&dst[curChar], HOTKEY_R_DISPLAY, 2); + curChar++; + break; + case 'S': + memcpy(&dst[curChar], HOTKEY_START_DISPLAY, 2); + curChar++; + break; + case 's': + memcpy(&dst[curChar], HOTKEY_SELECT_DISPLAY, 2); + curChar++; + break; + case '\0': + dst[curChar] = pt[curChar]; + break; + default: + memcpy(&dst[curChar], &pt[curChar], 2); + curChar++; + break; + } + } + else + dst[curChar] = pt[curChar]; + } dst += len; //at a line return, when "\n" paded, this message not end @@ -4163,7 +4217,7 @@ int load_language_msg(char *filename, u32 language) else//a message end { if(*(dst-2) == 0x0D) - dst -= 1; + dst -= 1; *(dst-1) = '\0'; msg[++loop] = dst; } -- cgit v1.2.3 From 90de0280db8e33d9e54a65639be6ec76510e4bb0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 16:24:09 -0500 Subject: gui.c: Require all keys to be released after the B, A or X button or the Touch Screen is pressed. This avoids bringing up, or exiting from, multiple menus if you happen to press something for longer than 1/5 second. The modification does not apply to the directional pad in all menus, or the L and R buttons in file selectors. --- source/nds/gui.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 7270891..f0671b0 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -836,6 +836,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) { case CURSOR_TOUCH: ds2_getrawInput(&inputdata); + wait_Allkey_release(0); // ___ 33 This screen has 6 possible rows. Touches // ___ 60 above or below these are ignored. // . . . (+27) @@ -1001,6 +1002,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) break; case CURSOR_SELECT: + wait_Allkey_release(0); //file selected if(selected_item_on_list + 1 <= num_files) { @@ -1040,6 +1042,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) case CURSOR_BACK: { + wait_Allkey_release(0); char *ext_pos; strcpy(filelist_info.current_path, default_dir_name); @@ -1057,6 +1060,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) } case CURSOR_EXIT: + wait_Allkey_release(0); return_value = -1; repeat = 0; break; @@ -3672,6 +3676,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { case CURSOR_TOUCH: ds2_getrawInput(&inputdata); + wait_Allkey_release(0); /* Back button at the top of every menu but the main one */ if(current_menu != &main_menu && inputdata.x > 231 && inputdata.y <= 25) { @@ -4006,9 +4011,11 @@ u32 menu(u16 *screen, bool8 FirstInvocation) break; case CURSOR_EXIT: + wait_Allkey_release(0); break; case CURSOR_SELECT: + wait_Allkey_release(0); if(current_option->option_type & ACTION_TYPE) current_option->action_function(); else if(current_option->option_type & SUBMENU_TYPE) @@ -4016,6 +4023,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) break; case CURSOR_BACK: + wait_Allkey_release(0); if(current_menu != &main_menu) choose_menu(current_menu->options->sub_menu); else -- cgit v1.2.3 From 5e3426d0d26bb25810aca6593416ac0125ea6e8f Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 19:07:39 -0500 Subject: Remove 320 KiB of memory allocations in APU emulation that were completely unused but constantly re-zeroed. Frees up 320 KiB for other uses, and saves ~4 milliseconds at emulator startup, when resetting the APU and when loading a new game. --- source/nds/dma_adj.h | 3 +++ source/nds/entry.cpp | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h index 62b0098..dd4a6e4 100644 --- a/source/nds/dma_adj.h +++ b/source/nds/dma_adj.h @@ -8,7 +8,10 @@ extern "C" { #endif struct SPointerAdjustments { + /* These are used by the DSTWO-NDS side code. */ unsigned int GFXScreen; + + /* These are used by Snes9x. */ }; extern struct SPointerAdjustments PtrAdj; diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 723374c..ae52ff0 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -432,7 +432,6 @@ void init_sfc_setting(void) Settings.ShutdownMaster = TRUE; Settings.FrameTimePAL = 20000; Settings.FrameTimeNTSC = 16667; - Settings.DisableSampleCaching = FALSE; Settings.DisableMasterVolume = FALSE; Settings.Mouse = TRUE; Settings.SuperScope = TRUE; -- cgit v1.2.3 From 55895f01f73ba1b4fab7095fa5cb8cf7884846ed Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 02:38:45 -0500 Subject: De-interleave the ROM using DMA. This helps the more esoteric jumbo memory maps load faster. --- source/nds/dma_adj.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source/nds') diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h index dd4a6e4..3852f09 100644 --- a/source/nds/dma_adj.h +++ b/source/nds/dma_adj.h @@ -12,6 +12,7 @@ struct SPointerAdjustments { unsigned int GFXScreen; /* These are used by Snes9x. */ + unsigned int ROM; }; extern struct SPointerAdjustments PtrAdj; -- cgit v1.2.3 From ea8ff33951d53f0e71801052c540dcc1bd0f7f42 Mon Sep 17 00:00:00 2001 From: SignZ Date: Thu, 7 Feb 2013 04:56:34 -0500 Subject: EN: Added a German translation. DE: Deutsche Übersetzung hinzugefügt. --- source/nds/gui.c | 11 ++++++++--- source/nds/message.h | 7 ++++--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index f0671b0..190fcc9 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -50,14 +50,15 @@ char argv[2][MAX_PATH]; // If adding a language, make sure you update the size of the array in // message.h too. -char *lang[3] = +char *lang[4] = { "English", // 0 "简体中文", // 1 - "Français", // 2 + "Français", // 2 + "Deutsch", // 3 }; -char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lang[2] }; +char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lang[2], (char *) &lang[3] }; /****************************************************************************** * Macro definition @@ -4105,6 +4106,10 @@ int load_language_msg(char *filename, u32 language) strcpy(start, "STARTFRENCH"); strcpy(end, "ENDFRENCH"); break; + case GERMAN: + strcpy(start, "STARTGERMAN"); + strcpy(end, "ENDGERMAN"); + break; } u32 cmplen = strlen(start); diff --git a/source/nds/message.h b/source/nds/message.h index c7e79b8..538bc3b 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -145,13 +145,14 @@ enum MSG enum LANGUAGE { ENGLISH, CHINESE_SIMPLIFIED, - FRENCH + FRENCH, + GERMAN }; -extern char* lang[3]; // Allocated in gui.c, needs to match the languages ^ +extern char* lang[4]; // Allocated in gui.c, needs to match the languages ^ char *msg[MSG_END+1]; -char msg_data[16 * 1024]; +char msg_data[32 * 1024]; #endif //__MESSAGE_H__ -- cgit v1.2.3 From 635c87890530777a2e7b2f4c45a72f8f51c7d5f0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 17:58:37 -0500 Subject: Allow the user to be pressing a button when the emulator starts. This allows the Loading screen to disappear, and allows invoking New Game straight away. --- source/nds/gui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/nds') diff --git a/source/nds/gui.c b/source/nds/gui.c index 190fcc9..4299db2 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -3535,9 +3535,10 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { // assume that the backlight is already at 3 when the emulator starts mdelay(100); // to prevent ds2_setBacklight() from crashing ds2_setBacklight(3); + // also allow the user to press A for New Game right away + wait_Allkey_release(0); } - wait_Allkey_release(0); bg_screenp= (u16*)malloc(256*192*2); repeat = 1; -- cgit v1.2.3 From 703d522c4c9ef83dda0bd386a6c5ac8870a8df50 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 20:08:44 -0500 Subject: Remove remnants of a failed auto-CPU implementation. Changing CPU speeds on-the-fly is just not stable on the DSTwo. --- source/nds/entry.cpp | 62 +--------------------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index ae52ff0..d82ed85 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -641,26 +641,6 @@ static unsigned int sync_next = 0; static unsigned int skip_rate= 0; -/* - * Automatic CPU frequency support is here. - * Whenever, after one downclock determination interval, each frame rendered - * during it has been rendered at least as early as CPU_DOWNCLOCK_EARLY_TIME, - * lower the CPU frequency in response. - * If at least one frame has been early, but not early enough, the CPU - * frequency stays stable. - * If at least one frame has been late, the CPU will have be switched back - * to 396 MHz. - * This improves battery life to a certain extent. - */ - -#define CPU_DOWNCLOCK_EARLY_TIME 293 /* 1 = 42.667 us. 391 = 16.67 ms */ -#define CPU_DOWNCLOCK_DETERMINATION_INTERVAL 46874 /* 23437 = 1 s */ - -static unsigned int LastAutoCPUTime = 0; -unsigned int AutoCPUFrequency = 5; -static bool8 ConsistentlyEarly = FALSE; -static bool8 FastForwardLastFrame = FALSE; - void S9xSyncSpeed () { uint32 syncnow; @@ -679,17 +659,8 @@ void S9xSyncSpeed () bool8 FastForward = game_fast_forward || temporary_fast_forward /* hotkey is held */; - if (game_config.clock_speed_number == 0) - if (FastForward && !FastForwardLastFrame) - HighFrequencyCPU (); - else if (!FastForward && FastForwardLastFrame) - GameFrequencyCPU (); - - FastForwardLastFrame = FastForward; - if (FastForward) { - ConsistentlyEarly = FALSE; // don't use fast-forward to lower CPU sync_last = syncnow; sync_next = syncnow; @@ -712,14 +683,10 @@ void S9xSyncSpeed () { // Render this frame regardless, set the // sync_next, and get the hell out. - ConsistentlyEarly = FALSE; - AutoCPUFrequency = 5; - LastAutoCPUTime = syncnow; - IPPU.RenderThisFrame = TRUE; sync_last = syncnow; sync_next = syncnow + frame_time; - goto finalise; + return; } sync_last = syncnow; // If this is positive, we have syncdif*42.66 microseconds to @@ -738,10 +705,6 @@ void S9xSyncSpeed () } else if(syncdif < 0) { - ConsistentlyEarly = FALSE; - AutoCPUFrequency = 5; - LastAutoCPUTime = syncnow; - /* * If we're consistently late, delay up to 8 frames. * @@ -770,7 +733,6 @@ void S9xSyncSpeed () } else // Early { - ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; skip_rate = 0; if (syncdif > 0) { @@ -815,7 +777,6 @@ void S9xSyncSpeed () syncdif = sync_next - syncnow; if (syncdif > 0) { - ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; do { S9xProcessSound (0); #ifdef ACCUMULATE_JOYPAD @@ -831,13 +792,6 @@ void S9xSyncSpeed () // After that little delay, what time is it? syncnow = getSysTime(); } - else - { - // Nope, we're late. - ConsistentlyEarly = FALSE; - AutoCPUFrequency = 5; - LastAutoCPUTime = syncnow; - } sync_next = syncnow + frame_time * (Settings.SkipFrames + 1); } else @@ -930,20 +884,6 @@ void S9xSyncSpeed () next1.tv_usec %= 1000000; } #endif - -finalise: ; - - if (syncnow - LastAutoCPUTime >= CPU_DOWNCLOCK_DETERMINATION_INTERVAL) { - if (ConsistentlyEarly && AutoCPUFrequency > 0) - AutoCPUFrequency--; - - LastAutoCPUTime = syncnow; - ConsistentlyEarly = TRUE; - // will get unset if the CPU should stay the same at next check - } - - if (game_config.clock_speed_number == 0 && LastAutoCPUFrequency != AutoCPUFrequency) - GameFrequencyCPU (); } bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) -- cgit v1.2.3 From 4676a520e1b181e5891550331100b2629d7cbd7f Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 22:27:44 -0500 Subject: Synchronise fractions of a hertz correctly in the audio output timing code to avoid buffer overruns. Buffer overruns pause the game for about half a second. --- source/nds/entry.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index d82ed85..af832f9 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -981,8 +981,20 @@ void S9xGenerateSound () } } -#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) - 1) /* -1 is for roundoff errors */ -unsigned int LastSoundEmissionTime = 0; +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +#define TRUE_SOUND_EMISSION_INTERVAL ((((double) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) +#define SOUND_EMISSION_INTERVAL_ERROR ((int) ((TRUE_SOUND_EMISSION_INTERVAL - SOUND_EMISSION_INTERVAL) * FIXED_POINT)) +static unsigned int LastSoundEmissionTime = 0; + +/* + * Accumulated error in the sound emission time. The unit is as follows: + * FIXED_POINT = 42.667 microseconds. + * As the error goes past FIXED_POINT, the new target for sound emission + * becomes 42.667 microseconds LATER. This helps with sound buffer overruns, + * correctly dealing with the fact that 42.667 microseconds does not fit + * an integer number of times in 1/32000 second (or whatever sampling rate). + */ +static unsigned int SoundEmissionTimeError = 0; void S9xProcessSound (unsigned int) { @@ -1009,6 +1021,12 @@ void S9xProcessSound (unsigned int) else { LastSoundEmissionTime += SOUND_EMISSION_INTERVAL; + SoundEmissionTimeError += SOUND_EMISSION_INTERVAL_ERROR; + if (SoundEmissionTimeError > FIXED_POINT) + { + LastSoundEmissionTime += SoundEmissionTimeError >> FIXED_POINT_SHIFT; + SoundEmissionTimeError &= FIXED_POINT_REMAINDER; + } } /* Number of samples to generate now */ int sample_count = so.buffer_size; -- cgit v1.2.3 From d4fcf2697c9a45594e3ee0b8bf82e480ddd0b69b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 8 Feb 2013 03:22:27 -0500 Subject: Require one audio buffer to be free again. Otherwise, if the 4 buffers get full, it's already game over, and getAudiobuff becomes NULL for about 400 milliseconds, stopping all emulation. --- source/nds/entry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/nds') diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index af832f9..77620bf 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -1004,7 +1004,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1) { LastSoundEmissionTime++; return; @@ -1022,7 +1022,7 @@ void S9xProcessSound (unsigned int) { LastSoundEmissionTime += SOUND_EMISSION_INTERVAL; SoundEmissionTimeError += SOUND_EMISSION_INTERVAL_ERROR; - if (SoundEmissionTimeError > FIXED_POINT) + if (SoundEmissionTimeError >= FIXED_POINT) { LastSoundEmissionTime += SoundEmissionTimeError >> FIXED_POINT_SHIFT; SoundEmissionTimeError &= FIXED_POINT_REMAINDER; -- cgit v1.2.3