all repos — mgba @ 7f64f8cf3bee4b8bff476cda46c84a5008fb33f4

mGBA Game Boy Advance Emulator

Debugger: Keep track of global cycle count
Vicki Pfau vi@endrift.com
Sat, 30 May 2020 18:01:15 -0700
commit

7f64f8cf3bee4b8bff476cda46c84a5008fb33f4

parent

d7ecdb5e4eda3e195d6d319f94280486d01d0bc3

M CHANGESCHANGES

@@ -40,6 +40,7 @@ - Debugger: Don't skip undefined instructions when debugger attached

- Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix OpenGL 2.1 support (fixes mgba.io/i/1678) Misc: + - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG - Qt: Renderer can be changed while a game is running - Qt: Add hex index to palette view
M include/mgba/core/timing.hinclude/mgba/core/timing.h

@@ -25,6 +25,7 @@ struct mTiming {

struct mTimingEvent* root; struct mTimingEvent* reroot; + uint64_t globalCycles; uint32_t masterCycles; int32_t* relativeCycles; int32_t* nextEvent;

@@ -38,6 +39,7 @@ void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent*);

bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent*); int32_t mTimingTick(struct mTiming* timing, int32_t cycles); int32_t mTimingCurrentTime(const struct mTiming* timing); +uint64_t mTimingGlobalTime(const struct mTiming* timing); int32_t mTimingNextEvent(struct mTiming* timing); int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent*);
M include/mgba/internal/gb/serialize.hinclude/mgba/internal/gb/serialize.h

@@ -155,7 +155,8 @@ * | bit 3: IME

* | bit 4: Is HDMA active? * | bits 5 - 7: Active RTC register * | 0x00196 - 0x00197: Reserved (leave zero) - * 0x00198 - 0x0025F: Reserved (leave zero) + * 0x00198 - 0x0019F: Global cycle counter + * 0x001A0 - 0x0025F: Reserved (leave zero) * 0x00260 - 0x002FF: OAM * 0x00300 - 0x0037F: I/O memory * 0x00380 - 0x003FE: HRAM

@@ -388,7 +389,9 @@ GBSerializedMemoryFlags flags;

uint16_t reserved; } memory; - uint32_t reserved[50]; + uint64_t globalCycles; + + uint32_t reserved[48]; uint8_t oam[GB_SIZE_OAM];
M include/mgba/internal/gba/serialize.hinclude/mgba/internal/gba/serialize.h

@@ -193,7 +193,8 @@ * 0x002F4 - 0x002FF: Prefetch

* | 0x002F4 - 0x002F7: GBA BIOS bus prefetch * | 0x002F8 - 0x002FB: CPU prefecth (decode slot) * | 0x002FC - 0x002FF: CPU prefetch (fetch slot) - * 0x00300 - 0x00317: Reserved (leave zero) + * 0x00300 - 0x0030F: Reserved (leave zero) + * 0x00310 - 0x00317: Global cycle counter * 0x00318 - 0x0031B: Last prefetched program counter * 0x0031C - 0x0031F: Miscellaneous flags * | bit 0: Is CPU halted?

@@ -326,8 +327,9 @@

uint32_t biosPrefetch; uint32_t cpuPrefetch[2]; - uint32_t reservedCpu[6]; + uint32_t reservedCpu[4]; + uint64_t globalCycles; uint32_t lastPrefetchedPc; GBASerializedMiscFlags miscFlags; uint32_t nextIrq;
M src/arm/debugger/cli-debugger.csrc/arm/debugger/cli-debugger.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <mgba/internal/arm/debugger/cli-debugger.h> #include <mgba/core/core.h> +#include <mgba/core/timing.h> #include <mgba/internal/arm/debugger/debugger.h> #include <mgba/internal/arm/debugger/memory-debugger.h> #include <mgba/internal/arm/decoder.h>

@@ -138,6 +139,7 @@ r < 7 ? " " : "", r + 3, cpu->gprs[r + 3]);

} be->printf(be, "cpsr: "); _printPSR(be, cpu->cpsr); + be->printf(be, "Cycle: %" PRIu64 "\n", mTimingGlobalTime(debugger->p->d.core->timing)); int instructionLength; enum ExecutionMode mode = cpu->cpsr.t; if (mode == MODE_ARM) {
M src/core/timing.csrc/core/timing.c

@@ -8,6 +8,7 @@

void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent) { timing->root = NULL; timing->reroot = NULL; + timing->globalCycles = 0; timing->masterCycles = 0; timing->relativeCycles = relativeCycles; timing->nextEvent = nextEvent;

@@ -20,6 +21,7 @@

void mTimingClear(struct mTiming* timing) { timing->root = NULL; timing->reroot = NULL; + timing->globalCycles = 0; timing->masterCycles = 0; }

@@ -101,6 +103,10 @@ }

int32_t mTimingCurrentTime(const struct mTiming* timing) { return timing->masterCycles + *timing->relativeCycles; +} + +uint64_t mTimingGlobalTime(const struct mTiming* timing) { + return timing->globalCycles + *timing->relativeCycles; } int32_t mTimingNextEvent(struct mTiming* timing) {
M src/gb/gb.csrc/gb/gb.c

@@ -674,6 +674,9 @@ int32_t cycles = cpu->cycles;

int32_t nextEvent; cpu->cycles = 0; +#ifdef USE_DEBUGGERS + gb->timing.globalCycles += cycles; +#endif cpu->nextEvent = INT_MAX; nextEvent = cycles;
M src/gb/serialize.csrc/gb/serialize.c

@@ -23,6 +23,7 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {

STORE_32LE(GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, 0, &state->versionMagic); STORE_32LE(gb->romCrc32, 0, &state->romCrc32); STORE_32LE(gb->timing.masterCycles, 0, &state->masterCycles); + STORE_64LE(gb->timing.globalCycles, 0, &state->globalCycles); if (gb->memory.rom) { memcpy(state->title, ((struct GBCartridge*) &gb->memory.rom[0x100])->titleLong, sizeof(state->title));

@@ -150,6 +151,7 @@ return false;

} mTimingClear(&gb->timing); LOAD_32LE(gb->timing.masterCycles, 0, &state->masterCycles); + LOAD_64LE(gb->timing.globalCycles, 0, &state->globalCycles); gb->cpu->a = state->cpu.a; gb->cpu->f.packed = state->cpu.f;
M src/gba/gba.csrc/gba/gba.c

@@ -277,6 +277,9 @@ nextEvent = 0;

do { int32_t cycles = cpu->cycles; cpu->cycles = 0; +#ifdef USE_DEBUGGERS + gba->timing.globalCycles += cycles; +#endif #ifndef NDEBUG if (cycles < 0) { mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles);
M src/gba/serialize.csrc/gba/serialize.c

@@ -28,6 +28,7 @@ STORE_32(GBA_SAVESTATE_MAGIC + GBA_SAVESTATE_VERSION, 0, &state->versionMagic);

STORE_32(gba->biosChecksum, 0, &state->biosChecksum); STORE_32(gba->romCrc32, 0, &state->romCrc32); STORE_32(gba->timing.masterCycles, 0, &state->masterCycles); + STORE_64LE(gba->timing.globalCycles, 0, &state->globalCycles); if (gba->memory.rom) { state->id = ((struct GBACartridge*) gba->memory.rom)->id;

@@ -128,6 +129,7 @@ return false;

} mTimingClear(&gba->timing); LOAD_32(gba->timing.masterCycles, 0, &state->masterCycles); + LOAD_64LE(gba->timing.globalCycles, 0, &state->globalCycles); size_t i; for (i = 0; i < 16; ++i) {
M src/sm83/debugger/cli-debugger.csrc/sm83/debugger/cli-debugger.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <mgba/internal/sm83/debugger/cli-debugger.h> #include <mgba/core/core.h> +#include <mgba/core/timing.h> #include <mgba/internal/debugger/cli-debugger.h> #include <mgba/internal/sm83/decoder.h> #include <mgba/internal/sm83/debugger/debugger.h>

@@ -88,6 +89,7 @@ be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de);

be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp); _printFlags(be, cpu->f); + be->printf(be, "T-cycle: %" PRIu64 "\n", mTimingGlobalTime(debugger->p->d.core->timing)); struct SM83Debugger* platDebugger = (struct SM83Debugger*) debugger->p->d.platform; size_t i;