GP2X: low volume and fast forward

git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@310 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2007-12-09 15:17:50 +00:00
parent 91b2c3e133
commit 0480e6c969
5 changed files with 105 additions and 37 deletions

View file

@ -641,7 +641,11 @@ Changelog
* Fixed a sram bug in memhandlers (fixes Shining in the Darkness saves). * 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 * PSP: fixed another bug in memhanlers, which crashed the emu for some games
(like NBA Jam and NHL 9x). (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. * Some other small tweaks I forgot about.
1.35a 1.35a
@ -649,7 +653,7 @@ Changelog
* PSP: fixed incorrect CZ80 memory map setup, which caused Z80 crashes and * PSP: fixed incorrect CZ80 memory map setup, which caused Z80 crashes and
graphics corruption in EU Mega CD model1 BIOS menus. graphics corruption in EU Mega CD model1 BIOS menus.
+ PSP: added additional "set to 4:3 scaled" display option for convenience. + 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 1.35
+ PSP port added. Lots of new code for it. Integrated modified FAME/C, CZ80 cores. + PSP port added. Lots of new code for it. Integrated modified FAME/C, CZ80 cores.

View file

@ -1,11 +1,14 @@
@ vim:filetype=armasm @ vim:filetype=armasm
@ some color conversion and blitting routines @ some color conversion and blitting routines
@ (c) Copyright 2006, notaz @ (c) Copyright 2006, 2007 notaz
@ All Rights Reserved @ All Rights Reserved
@ vim:filetype=armasm @ vim:filetype=armasm
.text
.align 4
@ Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0 @ Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0
@ to 00000000 rrr00000 ggg00000 bbb00000 ... @ to 00000000 rrr00000 ggg00000 bbb00000 ...
@ -217,3 +220,4 @@ flushcache:
swi #0x9f0002 swi #0x9f0002
mov pc, lr mov pc, lr

View file

@ -25,6 +25,7 @@
#include <Pico/PicoInt.h> #include <Pico/PicoInt.h>
#include <Pico/Patch.h> #include <Pico/Patch.h>
#include <Pico/sound/mix.h>
#include <zlib/zlib.h> #include <zlib/zlib.h>
//#define PFRAMES //#define PFRAMES
@ -432,9 +433,69 @@ static void emu_msg_tray_open(void)
gettimeofday(&noticeMsgTime, 0); gettimeofday(&noticeMsgTime, 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(&noticeMsgTime, 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) 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; int do_it = 1;
if ( emu_checkSaveFile(state_slot) && if ( emu_checkSaveFile(state_slot) &&
(( (which & 0x1000) && (currentConfig.EmuOpt & 0x800)) || // load (( (which & 0x1000) && (currentConfig.EmuOpt & 0x800)) || // load
@ -456,7 +517,8 @@ static void RunEvents(unsigned int which)
reset_timing = 1; reset_timing = 1;
} }
if(which & 0x0400) { // switch renderer if (which & 0x0400) // switch renderer
{
if ( PicoOpt&0x10) { PicoOpt&=~0x10; currentConfig.EmuOpt |= 0x80; } if ( PicoOpt&0x10) { PicoOpt&=~0x10; currentConfig.EmuOpt |= 0x80; }
else if (!(currentConfig.EmuOpt&0x80)) PicoOpt|= 0x10; else if (!(currentConfig.EmuOpt&0x80)) PicoOpt|= 0x10;
else currentConfig.EmuOpt &= ~0x80; else currentConfig.EmuOpt &= ~0x80;
@ -473,7 +535,8 @@ static void RunEvents(unsigned int which)
gettimeofday(&noticeMsgTime, 0); gettimeofday(&noticeMsgTime, 0);
} }
if(which & 0x0300) { if (which & 0x0300)
{
if(which&0x0200) { if(which&0x0200) {
state_slot -= 1; state_slot -= 1;
if(state_slot < 0) state_slot = 9; 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"); sprintf(noticeMsg, "SAVE SLOT %i [%s]", state_slot, emu_checkSaveFile(state_slot) ? "USED" : "FREE");
gettimeofday(&noticeMsgTime, 0); gettimeofday(&noticeMsgTime, 0);
} }
if(which & 0x0080) { if (which & 0x0080) {
engineState = PGS_Menu; engineState = PGS_Menu;
} }
} }
@ -552,18 +615,11 @@ static void updateKeys(void)
events = (allActions[0] | allActions[1]) >> 16; events = (allActions[0] | allActions[1]) >> 16;
// volume is treated in special way and triggered every frame // volume is treated in special way and triggered every frame
if(events & 0x6000) { if (events & 0x6000)
int vol = currentConfig.volume; update_volume(1, events & 0x2000);
if (events & 0x2000) {
if (vol < 99) vol++; if ((events ^ prevEvents) & 0x40)
} else { change_fast_forward(events & 0x40);
if (vol > 0) vol--;
}
gp2x_sound_volume(vol, vol);
sprintf(noticeMsg, "VOL: %02i", vol);
gettimeofday(&noticeMsgTime, 0);
currentConfig.volume = vol;
}
events &= ~prevEvents; events &= ~prevEvents;
if (events) RunEvents(events); if (events) RunEvents(events);
@ -685,15 +741,11 @@ void emu_Loop(void)
reset_timing = 1; reset_timing = 1;
// prepare sound stuff // prepare sound stuff
if(currentConfig.EmuOpt & 4) { if (currentConfig.EmuOpt & 4)
{
int snd_excess_add; int snd_excess_add;
if (PsndRate != PsndRate_old || (PicoOpt&0x20b) != (PicoOpt_old&0x20b) || Pico.m.pal != pal_old || if (PsndRate != PsndRate_old || (PicoOpt&0x20b) != (PicoOpt_old&0x20b) || Pico.m.pal != pal_old ||
((PicoOpt&0x200) && crashed_940)) { ((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); PsndRerate(Pico.m.frame_count ? 1 : 0);
} }
snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps; 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_start_sound(PsndRate, 16, (PicoOpt&8)>>3);
gp2x_sound_volume(currentConfig.volume, currentConfig.volume); gp2x_sound_volume(currentConfig.volume, currentConfig.volume);
PicoWriteSound = updateSound; PicoWriteSound = updateSound;
update_volume(0, 0);
memset(sndBuffer, 0, sizeof(sndBuffer)); memset(sndBuffer, 0, sizeof(sndBuffer));
PsndOut = sndBuffer; PsndOut = sndBuffer;
PsndRate_old = PsndRate; PsndRate_old = PsndRate;
PicoOpt_old = PicoOpt; PicoOpt_old = PicoOpt;
pal_old = Pico.m.pal; pal_old = Pico.m.pal;
} else { } else {
PsndOut = 0; PsndOut = NULL;
} }
// prepare CD buffer // prepare CD buffer
@ -733,14 +786,15 @@ void emu_Loop(void)
int modes; int modes;
gettimeofday(&tval, 0); gettimeofday(&tval, 0);
if(reset_timing) { if (reset_timing) {
reset_timing = 0; reset_timing = 0;
thissec = tval.tv_sec; thissec = tval.tv_sec;
frames_shown = frames_done = tval.tv_usec/target_frametime; frames_shown = frames_done = tval.tv_usec/target_frametime;
} }
// show notice message? // show notice message?
if(noticeMsgTime.tv_sec) { if (noticeMsgTime.tv_sec)
{
static int noticeMsgSum; static int noticeMsgSum;
if((tval.tv_sec*1000000+tval.tv_usec) - (noticeMsgTime.tv_sec*1000000+noticeMsgTime.tv_usec) > 2000000) { // > 2.0 sec 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; noticeMsgTime.tv_sec = noticeMsgTime.tv_usec = 0;
@ -755,7 +809,8 @@ void emu_Loop(void)
// check for mode changes // check for mode changes
modes = ((Pico.video.reg[12]&1)<<2)|(Pico.video.reg[1]&8); modes = ((Pico.video.reg[12]&1)<<2)|(Pico.video.reg[1]&8);
if (modes != oldmodes) { if (modes != oldmodes)
{
int scalex = 320; int scalex = 320;
osd_fps_x = OSD_FPS_X; osd_fps_x = OSD_FPS_X;
if (modes & 4) { if (modes & 4) {
@ -777,10 +832,11 @@ void emu_Loop(void)
} }
// second changed? // second changed?
if(thissec != tval.tv_sec) { if (thissec != tval.tv_sec)
{
#ifdef BENCHMARK #ifdef BENCHMARK
static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4];
if(++bench == 10) { if (++bench == 10) {
bench = 0; bench = 0;
bench_fps_s = bench_fps; bench_fps_s = bench_fps;
bf[bfp++ & 3] = bench_fps; bf[bfp++ & 3] = bench_fps;
@ -789,12 +845,13 @@ void emu_Loop(void)
bench_fps += frames_shown; bench_fps += frames_shown;
sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2); sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2);
#else #else
if(currentConfig.EmuOpt & 2) if (currentConfig.EmuOpt & 2)
sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done); sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done);
if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; }
#endif #endif
thissec = tval.tv_sec; thissec = tval.tv_sec;
if(PsndOut == 0 && currentConfig.Frameskip >= 0) { if (PsndOut == 0 && currentConfig.Frameskip >= 0) {
frames_done = frames_shown = 0; frames_done = frames_shown = 0;
} else { } else {
// it is quite common for this implementation to leave 1 fame unfinished // 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++) { for(i = 0; i < currentConfig.Frameskip; i++) {
updateKeys(); updateKeys();
SkipFrame(1); frames_done++; 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); gettimeofday(&tval, 0);
if(thissec != tval.tv_sec) tval.tv_usec+=1000000; if(thissec != tval.tv_sec) tval.tv_usec+=1000000;
if(tval.tv_usec < lim_time) { // we are too fast 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 // sleep or vsync if we are still too fast
// usleep sleeps for ~20ms minimum, so it is not a solution here // 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 // we are too fast
if (vsync_offset) { if (vsync_offset) {
@ -929,6 +986,7 @@ if (Pico.m.frame_count == 31563) {
frames_done++; frames_shown++; frames_done++; frames_shown++;
} }
change_fast_forward(0);
if (PicoMCD & 1) PicoCDBufferFree(); if (PicoMCD & 1) PicoCDBufferFree();

View file

@ -232,8 +232,8 @@ void gp2x_start_sound(int rate, int bits, int stereo)
if (sounddev == -1) if (sounddev == -1)
printf("open(\"/dev/dsp\") failed with %i\n", errno); 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_SETFMT, &bits);
ioctl(sounddev, SNDCTL_DSP_SPEED, &rate);
ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo); ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo);
// calculate buffer size // calculate buffer size
buffers = 16; buffers = 16;
@ -242,11 +242,12 @@ void gp2x_start_sound(int rate, int bits, int stereo)
while ((bsize>>=1)) frag++; while ((bsize>>=1)) frag++;
frag |= buffers<<16; // 16 buffers frag |= buffers<<16; // 16 buffers
ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag); ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag);
usleep(192*1024);
printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n", printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n",
rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff)); rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff));
s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo; s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo;
usleep(100000);
} }

View file

@ -838,6 +838,7 @@ static bind_action_t emuctrl_actions[] =
{ "Switch Renderer", 1<<26 }, { "Switch Renderer", 1<<26 },
{ "Volume Down ", 1<<30 }, { "Volume Down ", 1<<30 },
{ "Volume Up ", 1<<29 }, { "Volume Up ", 1<<29 },
{ "Fast forward ", 1<<22 },
{ "Enter Menu ", 1<<23 }, { "Enter Menu ", 1<<23 },
}; };