GP2X: low volume and fast forward

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@310 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2007-12-09 15:17:50 +00:00
parent 53668ca0f8
commit 4a32f01f55
9 changed files with 186 additions and 40 deletions

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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;
}

View file

@ -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.

View file

@ -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

View file

@ -25,6 +25,7 @@
#include <Pico/PicoInt.h>
#include <Pico/Patch.h>
#include <Pico/sound/mix.h>
#include <zlib/zlib.h>
//#define PFRAMES
@ -432,9 +433,69 @@ static void emu_msg_tray_open(void)
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)
{
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(&noticeMsgTime, 0);
}
if(which & 0x0300) {
if (which & 0x0300)
{
if(which&0x0200) {
state_slot -= 1;
if(state_slot < 0) state_slot = 9;
@ -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(&noticeMsgTime, 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
@ -740,7 +793,8 @@ void emu_Loop(void)
}
// 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,7 +832,8 @@ 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) {
@ -791,6 +847,7 @@ void emu_Loop(void)
#else
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;
@ -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();

View file

@ -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);
}

View file

@ -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 },
};