Merge pull request #331 from retro-wertz/gba_timings
Reduce input delay by 1 frame and audio timing fix
This commit is contained in:
commit
0d1b23c5e8
107
src/gba/GBA.cpp
107
src/gba/GBA.cpp
|
@ -480,8 +480,8 @@ inline int CPUUpdateTicks()
|
||||||
{
|
{
|
||||||
int cpuLoopTicks = lcdTicks;
|
int cpuLoopTicks = lcdTicks;
|
||||||
|
|
||||||
if (soundTicks < cpuLoopTicks)
|
//if (soundTicks < cpuLoopTicks)
|
||||||
cpuLoopTicks = soundTicks;
|
//cpuLoopTicks = soundTicks;
|
||||||
|
|
||||||
if (timer0On && (timer0Ticks < cpuLoopTicks)) {
|
if (timer0On && (timer0Ticks < cpuLoopTicks)) {
|
||||||
cpuLoopTicks = timer0Ticks;
|
cpuLoopTicks = timer0Ticks;
|
||||||
|
@ -3669,6 +3669,40 @@ void CPUInterrupt()
|
||||||
biosProtected[3] = 0xe5;
|
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)
|
void CPULoop(int ticks)
|
||||||
{
|
{
|
||||||
int clockTicks;
|
int clockTicks;
|
||||||
|
@ -3733,6 +3767,8 @@ void CPULoop(int ticks)
|
||||||
|
|
||||||
lcdTicks -= clockTicks;
|
lcdTicks -= clockTicks;
|
||||||
|
|
||||||
|
soundTicks += clockTicks;
|
||||||
|
|
||||||
if (lcdTicks <= 0) {
|
if (lcdTicks <= 0) {
|
||||||
if (DISPSTAT & 1) { // V-BLANK
|
if (DISPSTAT & 1) { // V-BLANK
|
||||||
// if in V-Blank mode, keep computing...
|
// if in V-Blank mode, keep computing...
|
||||||
|
@ -3789,32 +3825,6 @@ void CPULoop(int ticks)
|
||||||
lastTime = time;
|
lastTime = time;
|
||||||
count = 0;
|
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);
|
uint32_t ext = (joy >> 10);
|
||||||
// If no (m) code is enabled, apply the cheats at each LCDline
|
// If no (m) code is enabled, apply the cheats at each LCDline
|
||||||
|
@ -3837,6 +3847,9 @@ void CPULoop(int ticks)
|
||||||
UPDATE_REG(0x202, IF);
|
UPDATE_REG(0x202, IF);
|
||||||
}
|
}
|
||||||
CPUCheckDMA(1, 0x0f);
|
CPUCheckDMA(1, 0x0f);
|
||||||
|
|
||||||
|
psoundTickfn();
|
||||||
|
|
||||||
if (frameCount >= framesToSkip) {
|
if (frameCount >= framesToSkip) {
|
||||||
systemDrawScreen();
|
systemDrawScreen();
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
|
@ -3844,6 +3857,8 @@ void CPULoop(int ticks)
|
||||||
frameCount++;
|
frameCount++;
|
||||||
if (systemPauseOnFrame())
|
if (systemPauseOnFrame())
|
||||||
ticks = 0;
|
ticks = 0;
|
||||||
|
|
||||||
|
has_frames = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
UPDATE_REG(0x04, DISPSTAT);
|
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
|
// 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
|
// if sound is disabled, so in stop state, soundTick will just produce
|
||||||
// mute sound
|
// mute sound
|
||||||
soundTicks -= clockTicks;
|
|
||||||
if (soundTicks <= 0) {
|
//soundTicks -= clockTicks;
|
||||||
psoundTickfn();
|
//if (soundTicks <= 0) {
|
||||||
soundTicks += SOUND_CLOCK_TICKS;
|
//psoundTickfn();
|
||||||
}
|
//soundTicks += SOUND_CLOCK_TICKS;
|
||||||
|
//}
|
||||||
|
|
||||||
if (!stopState) {
|
if (!stopState) {
|
||||||
if (timer0On) {
|
if (timer0On) {
|
||||||
|
@ -4180,7 +4196,8 @@ void CPULoop(int ticks)
|
||||||
if (cpuNextEvent > ticks)
|
if (cpuNextEvent > ticks)
|
||||||
cpuNextEvent = ticks;
|
cpuNextEvent = ticks;
|
||||||
|
|
||||||
if (ticks <= 0 || cpuBreakLoop)
|
// end loop when a frame is done
|
||||||
|
if (ticks <= 0 || cpuBreakLoop || has_frames)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4190,9 +4207,25 @@ void CPULoop(int ticks)
|
||||||
#endif
|
#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 = {
|
struct EmulatedSystem GBASystem = {
|
||||||
// emuMain
|
// emuMain
|
||||||
CPULoop,
|
gbaEmulate,
|
||||||
// emuReset
|
// emuReset
|
||||||
CPUReset,
|
CPUReset,
|
||||||
// emuCleanUp
|
// emuCleanUp
|
||||||
|
@ -4221,9 +4254,9 @@ struct EmulatedSystem GBASystem = {
|
||||||
CPUUpdateCPSR,
|
CPUUpdateCPSR,
|
||||||
// emuHasDebugger
|
// emuHasDebugger
|
||||||
true,
|
true,
|
||||||
// emuCount
|
// emuCount
|
||||||
#ifdef FINAL_VERSION
|
#ifdef FINAL_VERSION
|
||||||
250000
|
300000
|
||||||
#else
|
#else
|
||||||
5000
|
5000
|
||||||
#endif
|
#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 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()
|
void Gba_Pcm::init()
|
||||||
|
@ -390,7 +390,7 @@ void psoundTickfn()
|
||||||
{
|
{
|
||||||
if (gb_apu && stereo_buffer) {
|
if (gb_apu && stereo_buffer) {
|
||||||
// Run sound hardware to present
|
// Run sound hardware to present
|
||||||
end_frame(SOUND_CLOCK_TICKS);
|
end_frame(soundTicks);
|
||||||
|
|
||||||
flush_samples(stereo_buffer);
|
flush_samples(stereo_buffer);
|
||||||
|
|
||||||
|
@ -400,6 +400,8 @@ void psoundTickfn()
|
||||||
if (soundVolume_ != soundVolume)
|
if (soundVolume_ != soundVolume)
|
||||||
apply_volume();
|
apply_volume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
soundTicks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_muting()
|
static void apply_muting()
|
||||||
|
@ -429,7 +431,7 @@ static void reset_apu()
|
||||||
if (stereo_buffer)
|
if (stereo_buffer)
|
||||||
stereo_buffer->clear();
|
stereo_buffer->clear();
|
||||||
|
|
||||||
soundTicks = SOUND_CLOCK_TICKS;
|
soundTicks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remake_stereo_buffer()
|
static void remake_stereo_buffer()
|
||||||
|
@ -524,8 +526,7 @@ void soundReset()
|
||||||
reset_apu();
|
reset_apu();
|
||||||
|
|
||||||
soundPaused = true;
|
soundPaused = true;
|
||||||
SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
|
soundTicks = 0;
|
||||||
soundTicks = SOUND_CLOCK_TICKS_;
|
|
||||||
|
|
||||||
soundEvent(NR52, (uint8_t)0x80);
|
soundEvent(NR52, (uint8_t)0x80);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,9 @@ void interp_rate();
|
||||||
// Notifies emulator that SOUND_CLOCK_TICKS clocks have passed
|
// Notifies emulator that SOUND_CLOCK_TICKS clocks have passed
|
||||||
void psoundTickfn();
|
void psoundTickfn();
|
||||||
extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to soundTick()
|
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
|
// Saves/loads emulator state
|
||||||
#ifdef __LIBRETRO__
|
#ifdef __LIBRETRO__
|
||||||
|
|
Loading…
Reference in New Issue