Debugger: Keep track of global cycle count
@@ -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
@@ -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*);
@@ -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];
@@ -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;
@@ -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) {
@@ -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) {
@@ -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;
@@ -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;
@@ -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);
@@ -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) {
@@ -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;