Reduce input delay by 1 frame and audio timing fix
This commit is contained in:
parent
3cb38420bd
commit
85891fc7fd
111
src/gba/GBA.cpp
111
src/gba/GBA.cpp
|
@ -480,8 +480,8 @@ inline int CPUUpdateTicks()
|
|||
{
|
||||
int cpuLoopTicks = lcdTicks;
|
||||
|
||||
if (soundTicks < cpuLoopTicks)
|
||||
cpuLoopTicks = soundTicks;
|
||||
//if (soundTicks < cpuLoopTicks)
|
||||
//cpuLoopTicks = soundTicks;
|
||||
|
||||
if (timer0On && (timer0Ticks < cpuLoopTicks)) {
|
||||
cpuLoopTicks = timer0Ticks;
|
||||
|
@ -1567,7 +1567,7 @@ int CPULoadRom(const char* szFile)
|
|||
CPUCleanUp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
pix = (uint8_t*)calloc(1, 4 * 241 * 162);
|
||||
if (pix == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
|
@ -1660,7 +1660,7 @@ int CPULoadRomData(const char* data, int size)
|
|||
CPUCleanUp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
pix = (uint8_t*)calloc(1, 4 * 240 * 160);
|
||||
if (pix == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
|
@ -3669,6 +3669,40 @@ void CPUInterrupt()
|
|||
biosProtected[3] = 0xe5;
|
||||
}
|
||||
|
||||
static uint32_t joy;
|
||||
static bool has_frames;
|
||||
|
||||
static void gbaUpdateJoypads(void)
|
||||
{
|
||||
// update joystick information
|
||||
if (systemReadJoypads())
|
||||
// read default joystick
|
||||
joy = systemReadJoypad(-1);
|
||||
|
||||
P1 = 0x03FF ^ (joy & 0x3FF);
|
||||
systemUpdateMotionSensor();
|
||||
UPDATE_REG(0x130, P1);
|
||||
uint16_t P1CNT = READ16LE(((uint16_t*)&ioMem[0x132]));
|
||||
|
||||
// this seems wrong, but there are cases where the game
|
||||
// can enter the stop state without requesting an IRQ from
|
||||
// the joypad.
|
||||
if ((P1CNT & 0x4000) || stopState) {
|
||||
uint16_t p1 = (0x3FF ^ P1) & 0x3FF;
|
||||
if (P1CNT & 0x8000) {
|
||||
if (p1 == (P1CNT & 0x3FF)) {
|
||||
IF |= 0x1000;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
} else {
|
||||
if (p1 & P1CNT) {
|
||||
IF |= 0x1000;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPULoop(int ticks)
|
||||
{
|
||||
int clockTicks;
|
||||
|
@ -3733,6 +3767,8 @@ void CPULoop(int ticks)
|
|||
|
||||
lcdTicks -= clockTicks;
|
||||
|
||||
soundTicks += clockTicks;
|
||||
|
||||
if (lcdTicks <= 0) {
|
||||
if (DISPSTAT & 1) { // V-BLANK
|
||||
// if in V-Blank mode, keep computing...
|
||||
|
@ -3789,32 +3825,6 @@ void CPULoop(int ticks)
|
|||
lastTime = time;
|
||||
count = 0;
|
||||
}
|
||||
uint32_t joy = 0;
|
||||
// update joystick information
|
||||
if (systemReadJoypads())
|
||||
// read default joystick
|
||||
joy = systemReadJoypad(-1);
|
||||
P1 = 0x03FF ^ (joy & 0x3FF);
|
||||
systemUpdateMotionSensor();
|
||||
UPDATE_REG(0x130, P1);
|
||||
uint16_t P1CNT = READ16LE(((uint16_t*)&ioMem[0x132]));
|
||||
// this seems wrong, but there are cases where the game
|
||||
// can enter the stop state without requesting an IRQ from
|
||||
// the joypad.
|
||||
if ((P1CNT & 0x4000) || stopState) {
|
||||
uint16_t p1 = (0x3FF ^ P1) & 0x3FF;
|
||||
if (P1CNT & 0x8000) {
|
||||
if (p1 == (P1CNT & 0x3FF)) {
|
||||
IF |= 0x1000;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
} else {
|
||||
if (p1 & P1CNT) {
|
||||
IF |= 0x1000;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ext = (joy >> 10);
|
||||
// If no (m) code is enabled, apply the cheats at each LCDline
|
||||
|
@ -3837,6 +3847,9 @@ void CPULoop(int ticks)
|
|||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
CPUCheckDMA(1, 0x0f);
|
||||
|
||||
psoundTickfn();
|
||||
|
||||
if (frameCount >= framesToSkip) {
|
||||
systemDrawScreen();
|
||||
frameCount = 0;
|
||||
|
@ -3844,6 +3857,8 @@ void CPULoop(int ticks)
|
|||
frameCount++;
|
||||
if (systemPauseOnFrame())
|
||||
ticks = 0;
|
||||
|
||||
has_frames = true;
|
||||
}
|
||||
|
||||
UPDATE_REG(0x04, DISPSTAT);
|
||||
|
@ -3971,11 +3986,12 @@ void CPULoop(int ticks)
|
|||
// we shouldn't be doing sound in stop state, but we loose synchronization
|
||||
// if sound is disabled, so in stop state, soundTick will just produce
|
||||
// mute sound
|
||||
soundTicks -= clockTicks;
|
||||
if (soundTicks <= 0) {
|
||||
psoundTickfn();
|
||||
soundTicks += SOUND_CLOCK_TICKS;
|
||||
}
|
||||
|
||||
//soundTicks -= clockTicks;
|
||||
//if (soundTicks <= 0) {
|
||||
//psoundTickfn();
|
||||
//soundTicks += SOUND_CLOCK_TICKS;
|
||||
//}
|
||||
|
||||
if (!stopState) {
|
||||
if (timer0On) {
|
||||
|
@ -4180,7 +4196,8 @@ void CPULoop(int ticks)
|
|||
if (cpuNextEvent > ticks)
|
||||
cpuNextEvent = ticks;
|
||||
|
||||
if (ticks <= 0 || cpuBreakLoop)
|
||||
// end loop when a frame is done
|
||||
if (ticks <= 0 || cpuBreakLoop || has_frames)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4190,9 +4207,25 @@ void CPULoop(int ticks)
|
|||
#endif
|
||||
}
|
||||
|
||||
void gbaEmulate(int ticks)
|
||||
{
|
||||
has_frames = false;
|
||||
|
||||
// Read and process inputs
|
||||
gbaUpdateJoypads();
|
||||
|
||||
// Runs nth number of ticks till vblank, outputs audio
|
||||
// then the video frames.
|
||||
// sanity check:
|
||||
// wrapped in loop in case frames has not been written yet
|
||||
do {
|
||||
CPULoop(ticks);
|
||||
} while (!has_frames);
|
||||
}
|
||||
|
||||
struct EmulatedSystem GBASystem = {
|
||||
// emuMain
|
||||
CPULoop,
|
||||
gbaEmulate,
|
||||
// emuReset
|
||||
CPUReset,
|
||||
// emuCleanUp
|
||||
|
@ -4221,9 +4254,9 @@ struct EmulatedSystem GBASystem = {
|
|||
CPUUpdateCPSR,
|
||||
// emuHasDebugger
|
||||
true,
|
||||
// emuCount
|
||||
// emuCount
|
||||
#ifdef FINAL_VERSION
|
||||
250000
|
||||
300000
|
||||
#else
|
||||
5000
|
||||
#endif
|
||||
|
|
|
@ -96,9 +96,9 @@ static Stereo_Buffer* stereo_buffer;
|
|||
|
||||
static Blip_Synth<blip_best_quality, 1> pcm_synth[3]; // 32 kHz, 16 kHz, 8 kHz
|
||||
|
||||
static inline blip_time_t blip_time()
|
||||
static inline blip_time_t blip_time(void)
|
||||
{
|
||||
return SOUND_CLOCK_TICKS - soundTicks;
|
||||
return soundTicks;
|
||||
}
|
||||
|
||||
void Gba_Pcm::init()
|
||||
|
@ -390,7 +390,7 @@ void psoundTickfn()
|
|||
{
|
||||
if (gb_apu && stereo_buffer) {
|
||||
// Run sound hardware to present
|
||||
end_frame(SOUND_CLOCK_TICKS);
|
||||
end_frame(soundTicks);
|
||||
|
||||
flush_samples(stereo_buffer);
|
||||
|
||||
|
@ -400,6 +400,8 @@ void psoundTickfn()
|
|||
if (soundVolume_ != soundVolume)
|
||||
apply_volume();
|
||||
}
|
||||
|
||||
soundTicks = 0;
|
||||
}
|
||||
|
||||
static void apply_muting()
|
||||
|
@ -429,7 +431,7 @@ static void reset_apu()
|
|||
if (stereo_buffer)
|
||||
stereo_buffer->clear();
|
||||
|
||||
soundTicks = SOUND_CLOCK_TICKS;
|
||||
soundTicks = 0;
|
||||
}
|
||||
|
||||
static void remake_stereo_buffer()
|
||||
|
@ -524,8 +526,7 @@ void soundReset()
|
|||
reset_apu();
|
||||
|
||||
soundPaused = true;
|
||||
SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
|
||||
soundTicks = SOUND_CLOCK_TICKS_;
|
||||
soundTicks = 0;
|
||||
|
||||
soundEvent(NR52, (uint8_t)0x80);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,9 @@ void interp_rate();
|
|||
// Notifies emulator that SOUND_CLOCK_TICKS clocks have passed
|
||||
void psoundTickfn();
|
||||
extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to soundTick()
|
||||
extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called
|
||||
|
||||
// 2018-12-10 - counts up from 0 since last psoundTickfn() was called
|
||||
extern int soundTicks;
|
||||
|
||||
// Saves/loads emulator state
|
||||
#ifdef __LIBRETRO__
|
||||
|
|
Loading…
Reference in New Issue