From: notaz Date: Sun, 9 Dec 2007 15:17:50 +0000 (+0000) Subject: GP2X: low volume and fast forward X-Git-Tag: v1.85~608 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a32f01f5527929fe5feafd53937007dcfd64735;p=picodrive.git GP2X: low volume and fast forward git-svn-id: file:///home/notaz/opt/svn/PicoDrive@310 be3aeb3a-fb24-0410-a615-afba39da0efa --- diff --git a/Pico/Pico.h b/Pico/Pico.h index b0f5a737..cdba60b2 100644 --- a/Pico/Pico.h +++ b/Pico/Pico.h @@ -131,6 +131,7 @@ extern void (*PicoPrepareCram)(); // prepares PicoCramHigh for renderer to us // sound.c extern int PsndRate,PsndLen; extern short *PsndOut; +extern void (*PsndMix_32_to_16l)(short *dest, int *src, int count); void PsndRerate(int preserve_state); // Utils.c diff --git a/Pico/sound/mix.h b/Pico/sound/mix.h index be1b43b8..b9315114 100644 --- a/Pico/sound/mix.h +++ b/Pico/sound/mix.h @@ -6,3 +6,5 @@ void mix_16h_to_32_s2(int *dest, short *src, int count); void mix_32_to_16l_stereo(short *dest, int *src, int count); void mix_32_to_16_mono(short *dest, int *src, int count); +extern int mix_32_to_16l_level; +void mix_32_to_16l_stereo_lvl(short *dest, int *src, int count); diff --git a/Pico/sound/mix.s b/Pico/sound/mix.s index d0c1dc3f..d44e2280 100644 --- a/Pico/sound/mix.s +++ b/Pico/sound/mix.s @@ -4,6 +4,9 @@ @ (c) Copyright 2007, Grazvydas "notaz" Ignotas +.text +.align 4 + @ this assumes src is word aligned .global mix_16h_to_32 @ int *dest, short *src, int count @@ -293,3 +296,72 @@ m32_16_mo_no_unal2: ldmfd sp!, {r4-r8,lr} bx lr + + +.data +.align 4 + +.global mix_32_to_16l_level +mix_32_to_16l_level: + .word 0 + +.text +.align 4 + +@ same as mix_32_to_16l_stereo, but with additional shift +.global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count + +mix_32_to_16l_stereo_lvl: + stmfd sp!, {r4-r9,lr} + + ldr r9, =mix_32_to_16l_level + mov lr, #1 + ldr r9, [r9] + + mov r2, r2, lsl #1 + subs r2, r2, #4 + bmi m32_16l_st_l_end + +m32_16l_st_l_loop: + ldmia r0, {r8,r12} + ldmia r1!, {r4-r7} + mov r8, r8, lsl #16 + mov r12,r12,lsl #16 + add r4, r4, r8, asr #16 + add r5, r5, r8, asr #16 + add r6, r6, r12,asr #16 + add r7, r7, r12,asr #16 + mov r4, r4, asr r9 + mov r5, r5, asr r9 + mov r6, r6, asr r9 + mov r7, r7, asr r9 + Limitsh r4 + Limitsh r5 + Limitsh r6 + Limitsh r7 + subs r2, r2, #4 + orr r4, r5, r4, lsr #16 + orr r5, r7, r6, lsr #16 + stmia r0!, {r4,r5} + bpl m32_16l_st_l_loop + +m32_16l_st_l_end: + @ check for remaining bytes to convert + tst r2, #2 + beq m32_16l_st_l_no_unal2 + ldrsh r6, [r0] + ldmia r1!,{r4,r5} + add r4, r4, r6 + add r5, r5, r6 + mov r4, r4, asr r9 + mov r5, r5, asr r9 + Limitsh r4 + Limitsh r5 + orr r4, r5, r4, lsr #16 + str r4, [r0], #4 + +m32_16l_st_l_no_unal2: + ldmfd sp!, {r4-r9,lr} + bx lr + + diff --git a/Pico/sound/sound.c b/Pico/sound/sound.c index b966b1f7..fbb81c89 100644 --- a/Pico/sound/sound.c +++ b/Pico/sound/sound.c @@ -15,6 +15,8 @@ #include "../cd/pcm.h" #include "mix.h" +void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo; + // master int buffer to mix to static int PsndBuffer[2*44100/50]; @@ -151,6 +153,9 @@ void PsndRerate(int preserve_state) memset32(PsndBuffer, 0, sizeof(PsndBuffer)/4); if (PsndOut) PsndClear(); + + // set mixer + PsndMix_32_to_16l = (PicoOpt & 8) ? mix_32_to_16l_stereo : mix_32_to_16_mono; } @@ -260,9 +265,7 @@ PICO_INTERNAL int PsndRender(int offset, int length) mp3_update(buf32, length, stereo); // convert + limit to normal 16bit output - if (stereo) - mix_32_to_16l_stereo(PsndOut+offset, buf32, length); - else mix_32_to_16_mono (PsndOut+offset, buf32, length); + PsndMix_32_to_16l(PsndOut+offset, buf32, length); return length; } diff --git a/platform/base_readme.txt b/platform/base_readme.txt index 17578a57..b7f641ab 100644 --- a/platform/base_readme.txt +++ b/platform/base_readme.txt @@ -641,7 +641,11 @@ Changelog * Fixed a sram bug in memhandlers (fixes Shining in the Darkness saves). * PSP: fixed another bug in memhanlers, which crashed the emu for some games (like NBA Jam and NHL 9x). - * Added suspend/resume handling for Sega CD games. + + PSP: added suspend/resume handling for Sega CD games. + + GP2X: added additional low volume levels for my late-night gaming sessions + (in stereo mode only). + + GP2X: added "fast forward" action in key config. Not recommended to use for + Sega CD, may case problems there. * Some other small tweaks I forgot about. 1.35a @@ -649,7 +653,7 @@ Changelog * PSP: fixed incorrect CZ80 memory map setup, which caused Z80 crashes and graphics corruption in EU Mega CD model1 BIOS menus. + PSP: added additional "set to 4:3 scaled" display option for convenience. - + Added an option to disable frame limitter (works only with non-auto frameskip). + + PSP: Added an option to disable frame limitter (works only with non-auto frameskip). 1.35 + PSP port added. Lots of new code for it. Integrated modified FAME/C, CZ80 cores. diff --git a/platform/common/arm_utils.s b/platform/common/arm_utils.s index 787ecb91..1d14265c 100644 --- a/platform/common/arm_utils.s +++ b/platform/common/arm_utils.s @@ -1,11 +1,14 @@ @ vim:filetype=armasm @ some color conversion and blitting routines -@ (c) Copyright 2006, notaz +@ (c) Copyright 2006, 2007 notaz @ All Rights Reserved @ vim:filetype=armasm +.text +.align 4 + @ Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0 @ to 00000000 rrr00000 ggg00000 bbb00000 ... @@ -217,3 +220,4 @@ flushcache: swi #0x9f0002 mov pc, lr + diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 3f2ed3fc..a658044d 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -25,6 +25,7 @@ #include #include +#include #include //#define PFRAMES @@ -432,9 +433,69 @@ static void emu_msg_tray_open(void) gettimeofday(¬iceMsgTime, 0); } +static void update_volume(int has_changed, int is_up) +{ + static int prev_frame = 0, wait_frames = 0; + int vol = currentConfig.volume; + + if (has_changed) + { + if (vol < 5 && (PicoOpt&8) && prev_frame == Pico.m.frame_count - 1 && wait_frames < 12) + wait_frames++; + else { + if (is_up) { + if (vol < 99) vol++; + } else { + if (vol > 0) vol--; + } + wait_frames = 0; + gp2x_sound_volume(vol, vol); + currentConfig.volume = vol; + } + sprintf(noticeMsg, "VOL: %02i", vol); + gettimeofday(¬iceMsgTime, 0); + prev_frame = Pico.m.frame_count; + } + + // set the right mixer func + if (!(PicoOpt&8)) return; // just use defaults for mono + if (vol >= 5) + PsndMix_32_to_16l = mix_32_to_16l_stereo; + else { + mix_32_to_16l_level = 5 - vol; + PsndMix_32_to_16l = mix_32_to_16l_stereo_lvl; + } +} + +static void change_fast_forward(int set_on) +{ + static void *set_PsndOut = NULL; + static int set_Frameskip, set_EmuOpt, is_on = 0; + + if (set_on && !is_on) { + set_PsndOut = PsndOut; + set_Frameskip = currentConfig.Frameskip; + set_EmuOpt = currentConfig.EmuOpt; + PsndOut = NULL; + currentConfig.Frameskip = 8; + currentConfig.EmuOpt &= ~4; + is_on = 1; + } + else if (!set_on && is_on) { + PsndOut = set_PsndOut; + currentConfig.Frameskip = set_Frameskip; + currentConfig.EmuOpt = set_EmuOpt; + PsndRerate(1); + update_volume(0, 0); + reset_timing = 1; + is_on = 0; + } +} + static void RunEvents(unsigned int which) { - if(which & 0x1800) { // save or load (but not both) + if (which & 0x1800) // save or load (but not both) + { int do_it = 1; if ( emu_checkSaveFile(state_slot) && (( (which & 0x1000) && (currentConfig.EmuOpt & 0x800)) || // load @@ -456,7 +517,8 @@ static void RunEvents(unsigned int which) reset_timing = 1; } - if(which & 0x0400) { // switch renderer + if (which & 0x0400) // switch renderer + { if ( PicoOpt&0x10) { PicoOpt&=~0x10; currentConfig.EmuOpt |= 0x80; } else if (!(currentConfig.EmuOpt&0x80)) PicoOpt|= 0x10; else currentConfig.EmuOpt &= ~0x80; @@ -473,7 +535,8 @@ static void RunEvents(unsigned int which) gettimeofday(¬iceMsgTime, 0); } - if(which & 0x0300) { + if (which & 0x0300) + { if(which&0x0200) { state_slot -= 1; if(state_slot < 0) state_slot = 9; @@ -484,7 +547,7 @@ static void RunEvents(unsigned int which) sprintf(noticeMsg, "SAVE SLOT %i [%s]", state_slot, emu_checkSaveFile(state_slot) ? "USED" : "FREE"); gettimeofday(¬iceMsgTime, 0); } - if(which & 0x0080) { + if (which & 0x0080) { engineState = PGS_Menu; } } @@ -552,18 +615,11 @@ static void updateKeys(void) events = (allActions[0] | allActions[1]) >> 16; // volume is treated in special way and triggered every frame - if(events & 0x6000) { - int vol = currentConfig.volume; - if (events & 0x2000) { - if (vol < 99) vol++; - } else { - if (vol > 0) vol--; - } - gp2x_sound_volume(vol, vol); - sprintf(noticeMsg, "VOL: %02i", vol); - gettimeofday(¬iceMsgTime, 0); - currentConfig.volume = vol; - } + if (events & 0x6000) + update_volume(1, events & 0x2000); + + if ((events ^ prevEvents) & 0x40) + change_fast_forward(events & 0x40); events &= ~prevEvents; if (events) RunEvents(events); @@ -685,15 +741,11 @@ void emu_Loop(void) reset_timing = 1; // prepare sound stuff - if(currentConfig.EmuOpt & 4) { + if (currentConfig.EmuOpt & 4) + { int snd_excess_add; if (PsndRate != PsndRate_old || (PicoOpt&0x20b) != (PicoOpt_old&0x20b) || Pico.m.pal != pal_old || ((PicoOpt&0x200) && crashed_940)) { - /* if 940 is turned off, we need it to be put back to sleep */ - if (!(PicoOpt&0x200) && ((PicoOpt^PicoOpt_old)&0x200)) { - Reset940(1, 2); - Pause940(1); - } PsndRerate(Pico.m.frame_count ? 1 : 0); } snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps; @@ -702,13 +754,14 @@ void emu_Loop(void) gp2x_start_sound(PsndRate, 16, (PicoOpt&8)>>3); gp2x_sound_volume(currentConfig.volume, currentConfig.volume); PicoWriteSound = updateSound; + update_volume(0, 0); memset(sndBuffer, 0, sizeof(sndBuffer)); PsndOut = sndBuffer; PsndRate_old = PsndRate; PicoOpt_old = PicoOpt; pal_old = Pico.m.pal; } else { - PsndOut = 0; + PsndOut = NULL; } // prepare CD buffer @@ -733,14 +786,15 @@ void emu_Loop(void) int modes; gettimeofday(&tval, 0); - if(reset_timing) { + if (reset_timing) { reset_timing = 0; thissec = tval.tv_sec; frames_shown = frames_done = tval.tv_usec/target_frametime; } // show notice message? - if(noticeMsgTime.tv_sec) { + if (noticeMsgTime.tv_sec) + { static int noticeMsgSum; if((tval.tv_sec*1000000+tval.tv_usec) - (noticeMsgTime.tv_sec*1000000+noticeMsgTime.tv_usec) > 2000000) { // > 2.0 sec noticeMsgTime.tv_sec = noticeMsgTime.tv_usec = 0; @@ -755,7 +809,8 @@ void emu_Loop(void) // check for mode changes modes = ((Pico.video.reg[12]&1)<<2)|(Pico.video.reg[1]&8); - if (modes != oldmodes) { + if (modes != oldmodes) + { int scalex = 320; osd_fps_x = OSD_FPS_X; if (modes & 4) { @@ -777,10 +832,11 @@ void emu_Loop(void) } // second changed? - if(thissec != tval.tv_sec) { + if (thissec != tval.tv_sec) + { #ifdef BENCHMARK static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; - if(++bench == 10) { + if (++bench == 10) { bench = 0; bench_fps_s = bench_fps; bf[bfp++ & 3] = bench_fps; @@ -789,12 +845,13 @@ void emu_Loop(void) bench_fps += frames_shown; sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2); #else - if(currentConfig.EmuOpt & 2) + if (currentConfig.EmuOpt & 2) sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done); + if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; } #endif thissec = tval.tv_sec; - if(PsndOut == 0 && currentConfig.Frameskip >= 0) { + if (PsndOut == 0 && currentConfig.Frameskip >= 0) { frames_done = frames_shown = 0; } else { // it is quite common for this implementation to leave 1 fame unfinished @@ -818,7 +875,7 @@ void emu_Loop(void) for(i = 0; i < currentConfig.Frameskip; i++) { updateKeys(); SkipFrame(1); frames_done++; - if (PsndOut) { // do framelimitting if sound is enabled + if (PsndOut && !reset_timing) { // do framelimitting if sound is enabled gettimeofday(&tval, 0); if(thissec != tval.tv_sec) tval.tv_usec+=1000000; if(tval.tv_usec < lim_time) { // we are too fast @@ -911,7 +968,7 @@ if (Pico.m.frame_count == 31563) { { // sleep or vsync if we are still too fast // usleep sleeps for ~20ms minimum, so it is not a solution here - if(tval.tv_usec < lim_time) + if (!reset_timing && tval.tv_usec < lim_time) { // we are too fast if (vsync_offset) { @@ -929,6 +986,7 @@ if (Pico.m.frame_count == 31563) { frames_done++; frames_shown++; } + change_fast_forward(0); if (PicoMCD & 1) PicoCDBufferFree(); diff --git a/platform/gp2x/gp2x.c b/platform/gp2x/gp2x.c index 3ed64fb3..7a5156c7 100644 --- a/platform/gp2x/gp2x.c +++ b/platform/gp2x/gp2x.c @@ -232,8 +232,8 @@ void gp2x_start_sound(int rate, int bits, int stereo) if (sounddev == -1) printf("open(\"/dev/dsp\") failed with %i\n", errno); - ioctl(sounddev, SNDCTL_DSP_SPEED, &rate); ioctl(sounddev, SNDCTL_DSP_SETFMT, &bits); + ioctl(sounddev, SNDCTL_DSP_SPEED, &rate); ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo); // calculate buffer size buffers = 16; @@ -242,11 +242,12 @@ void gp2x_start_sound(int rate, int bits, int stereo) while ((bsize>>=1)) frag++; frag |= buffers<<16; // 16 buffers ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag); + usleep(192*1024); + printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n", rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff)); s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo; - usleep(100000); } diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c index ddb9d2e3..ef54ed63 100644 --- a/platform/gp2x/menu.c +++ b/platform/gp2x/menu.c @@ -838,6 +838,7 @@ static bind_action_t emuctrl_actions[] = { "Switch Renderer", 1<<26 }, { "Volume Down ", 1<<30 }, { "Volume Up ", 1<<29 }, + { "Fast forward ", 1<<22 }, { "Enter Menu ", 1<<23 }, };