GB: Allow pausing event loop while CPU is blocked

This commit is contained in:
Vicki Pfau 2020-07-12 23:50:28 -07:00
parent 0fd6532b38
commit ba2175f5c5
5 changed files with 13 additions and 1 deletions

View File

@ -55,6 +55,7 @@ Other fixes:
- SM83: Simplify register pair access on big endian - SM83: Simplify register pair access on big endian
- Wii: Fix pixelated filtering on interframe blending (fixes mgba.io/i/1830) - Wii: Fix pixelated filtering on interframe blending (fixes mgba.io/i/1830)
Misc: Misc:
- GB: Allow pausing event loop while CPU is blocked
- Debugger: Keep track of global cycle count - Debugger: Keep track of global cycle count
- FFmpeg: Add looping option for GIF/APNG - FFmpeg: Add looping option for GIF/APNG
- FFmpeg: Use range coder for FFV1 to reduce output size - FFmpeg: Use range coder for FFV1 to reduce output size

View File

@ -235,6 +235,8 @@ DECL_BIT(GBSerializedCpuFlags, Condition, 0);
DECL_BIT(GBSerializedCpuFlags, IrqPending, 1); DECL_BIT(GBSerializedCpuFlags, IrqPending, 1);
DECL_BIT(GBSerializedCpuFlags, DoubleSpeed, 2); DECL_BIT(GBSerializedCpuFlags, DoubleSpeed, 2);
DECL_BIT(GBSerializedCpuFlags, EiPending, 3); DECL_BIT(GBSerializedCpuFlags, EiPending, 3);
DECL_BIT(GBSerializedCpuFlags, Halted, 4);
DECL_BIT(GBSerializedCpuFlags, Blocked, 5);
DECL_BITFIELD(GBSerializedTimerFlags, uint8_t); DECL_BITFIELD(GBSerializedTimerFlags, uint8_t);
DECL_BIT(GBSerializedTimerFlags, IrqPending, 0); DECL_BIT(GBSerializedTimerFlags, IrqPending, 0);

View File

@ -681,7 +681,7 @@ void GBProcessEvents(struct SM83Core* cpu) {
nextEvent = cycles; nextEvent = cycles;
do { do {
nextEvent = mTimingTick(&gb->timing, nextEvent); nextEvent = mTimingTick(&gb->timing, nextEvent);
} while (gb->cpuBlocked); } while (gb->cpuBlocked && !gb->earlyExit);
cpu->nextEvent = nextEvent; cpu->nextEvent = nextEvent;
if (cpu->halted) { if (cpu->halted) {
@ -695,6 +695,9 @@ void GBProcessEvents(struct SM83Core* cpu) {
} }
} while (cpu->cycles >= cpu->nextEvent); } while (cpu->cycles >= cpu->nextEvent);
gb->earlyExit = false; gb->earlyExit = false;
if (gb->cpuBlocked) {
cpu->cycles = cpu->nextEvent;
}
} }
void GBSetInterrupts(struct SM83Core* cpu, bool enable) { void GBSetInterrupts(struct SM83Core* cpu, bool enable) {

View File

@ -56,6 +56,8 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
flags = GBSerializedCpuFlagsSetIrqPending(flags, gb->cpu->irqPending); flags = GBSerializedCpuFlagsSetIrqPending(flags, gb->cpu->irqPending);
flags = GBSerializedCpuFlagsSetDoubleSpeed(flags, gb->doubleSpeed); flags = GBSerializedCpuFlagsSetDoubleSpeed(flags, gb->doubleSpeed);
flags = GBSerializedCpuFlagsSetEiPending(flags, mTimingIsScheduled(&gb->timing, &gb->eiPending)); flags = GBSerializedCpuFlagsSetEiPending(flags, mTimingIsScheduled(&gb->timing, &gb->eiPending));
flags = GBSerializedCpuFlagsSetHalted(flags, gb->cpu->halted);
flags = GBSerializedCpuFlagsSetBlocked(flags, gb->cpuBlocked);
STORE_32LE(flags, 0, &state->cpu.flags); STORE_32LE(flags, 0, &state->cpu.flags);
STORE_32LE(gb->eiPending.when - mTimingCurrentTime(&gb->timing), 0, &state->cpu.eiPending); STORE_32LE(gb->eiPending.when - mTimingCurrentTime(&gb->timing), 0, &state->cpu.eiPending);
@ -173,6 +175,9 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
gb->cpu->condition = GBSerializedCpuFlagsGetCondition(flags); gb->cpu->condition = GBSerializedCpuFlagsGetCondition(flags);
gb->cpu->irqPending = GBSerializedCpuFlagsGetIrqPending(flags); gb->cpu->irqPending = GBSerializedCpuFlagsGetIrqPending(flags);
gb->doubleSpeed = GBSerializedCpuFlagsGetDoubleSpeed(flags); gb->doubleSpeed = GBSerializedCpuFlagsGetDoubleSpeed(flags);
gb->cpu->halted = GBSerializedCpuFlagsGetHalted(flags);
gb->cpuBlocked = GBSerializedCpuFlagsGetBlocked(flags);
gb->audio.timingFactor = gb->doubleSpeed + 1; gb->audio.timingFactor = gb->doubleSpeed + 1;
LOAD_32LE(gb->cpu->cycles, 0, &state->cpu.cycles); LOAD_32LE(gb->cpu->cycles, 0, &state->cpu.cycles);

View File

@ -379,6 +379,7 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat
GBFrameEnded(video->p); GBFrameEnded(video->p);
mCoreSyncPostFrame(video->p->sync); mCoreSyncPostFrame(video->p->sync);
++video->frameCounter; ++video->frameCounter;
video->p->earlyExit = true;
GBFrameStarted(video->p); GBFrameStarted(video->p);
} }