Skip to content

Commit

Permalink
Reduce input delay by 1 frame and audio timing fix
Browse files Browse the repository at this point in the history
  • Loading branch information
retro-wertz committed Dec 10, 2018
1 parent 3cb3842 commit 85891fc
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 46 deletions.
111 changes: 72 additions & 39 deletions src/gba/GBA.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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...
Expand Down Expand Up @@ -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
Expand All @@ -3837,13 +3847,18 @@ void CPULoop(int ticks)
UPDATE_REG(0x202, IF);
}
CPUCheckDMA(1, 0x0f);

psoundTickfn();

if (frameCount >= framesToSkip) {
systemDrawScreen();
frameCount = 0;
} else
frameCount++;
if (systemPauseOnFrame())
ticks = 0;

has_frames = true;
}

UPDATE_REG(0x04, DISPSTAT);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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
Expand Down Expand Up @@ -4221,9 +4254,9 @@ struct EmulatedSystem GBASystem = {
CPUUpdateCPSR,
// emuHasDebugger
true,
// emuCount
// emuCount
#ifdef FINAL_VERSION
250000
300000
#else
5000
#endif
Expand Down
13 changes: 7 additions & 6 deletions src/gba/Sound.cpp
Expand Up @@ -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()
Expand Down Expand Up @@ -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);

Expand All @@ -400,6 +400,8 @@ void psoundTickfn()
if (soundVolume_ != soundVolume)
apply_volume();
}

soundTicks = 0;
}

static void apply_muting()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 3 additions & 1 deletion src/gba/Sound.h
Expand Up @@ -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__
Expand Down

0 comments on commit 85891fc

Please sign in to comment.