GBA: Support printing debug strings from inside a game

This commit is contained in:
Jeffrey Pfau 2016-09-28 14:37:48 -07:00
parent 278ac5f35b
commit e79963b007
5 changed files with 60 additions and 1 deletions

View File

@ -1,4 +1,6 @@
0.6.0: (Future) 0.6.0: (Future)
Features:
- GBA: Support printing debug strings from inside a game
Bugfixes: Bugfixes:
- GB MBC: Fix MBC7 when size is incorrectly specified - GB MBC: Fix MBC7 when size is incorrectly specified
- GB Video: Setting LYC=LY during mode 2 should trigger an IRQ - GB Video: Setting LYC=LY during mode 2 should trigger an IRQ

View File

@ -27,6 +27,7 @@
#include "util/vfs.h" #include "util/vfs.h"
mLOG_DEFINE_CATEGORY(GBA, "GBA"); mLOG_DEFINE_CATEGORY(GBA, "GBA");
mLOG_DEFINE_CATEGORY(GBA_DEBUG, "GBA Debug");
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000; const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
@ -199,6 +200,9 @@ void GBAReset(struct ARMCore* cpu) {
gba->haltPending = false; gba->haltPending = false;
gba->idleDetectionStep = 0; gba->idleDetectionStep = 0;
gba->idleDetectionFailures = 0; gba->idleDetectionFailures = 0;
gba->debug = false;
memset(gba->debugString, 0, sizeof(gba->debugString));
} }
void GBASkipBIOS(struct GBA* gba) { void GBASkipBIOS(struct GBA* gba) {
@ -681,6 +685,19 @@ void GBAStop(struct GBA* gba) {
gba->stopCallback->stop(gba->stopCallback); gba->stopCallback->stop(gba->stopCallback);
} }
void GBADebug(struct GBA* gba, uint16_t flags) {
gba->debugFlags = flags;
if (GBADebugFlagsIsSend(gba->debugFlags)) {
int level = 1 << GBADebugFlagsGetLevel(gba->debugFlags);
level &= 0x1F;
char oolBuf[0x101];
strncpy(oolBuf, gba->debugString, sizeof(gba->debugString));
oolBuf[0x100] = '\0';
mLog(_mLOG_CAT_GBA_DEBUG(), level, "%s", oolBuf);
}
gba->debugFlags = GBADebugFlagsClearSend(gba->debugFlags);
}
bool GBAIsROM(struct VFile* vf) { bool GBAIsROM(struct VFile* vf) {
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) { if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
return false; return false;

View File

@ -53,6 +53,7 @@ struct Patch;
struct VFile; struct VFile;
mLOG_DECLARE_CATEGORY(GBA); mLOG_DECLARE_CATEGORY(GBA);
mLOG_DECLARE_CATEGORY(GBA_DEBUG);
DECL_BITFIELD(GBATimerFlags, uint32_t); DECL_BITFIELD(GBATimerFlags, uint32_t);
DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4); DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4);
@ -60,6 +61,10 @@ DECL_BIT(GBATimerFlags, CountUp, 4);
DECL_BIT(GBATimerFlags, DoIrq, 5); DECL_BIT(GBATimerFlags, DoIrq, 5);
DECL_BIT(GBATimerFlags, Enable, 6); DECL_BIT(GBATimerFlags, Enable, 6);
DECL_BITFIELD(GBADebugFlags, uint16_t);
DECL_BITS(GBADebugFlags, Level, 0, 3);
DECL_BIT(GBADebugFlags, Send, 8);
struct GBATimer { struct GBATimer {
uint16_t reload; uint16_t reload;
uint16_t oldReload; uint16_t oldReload;
@ -120,6 +125,10 @@ struct GBA {
bool realisticTiming; bool realisticTiming;
bool hardCrash; bool hardCrash;
bool allowOpposingDirections; bool allowOpposingDirections;
bool debug;
char debugString[0x100];
GBADebugFlags debugFlags;
}; };
struct GBACartridge { struct GBACartridge {
@ -153,6 +162,7 @@ void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq);
void GBATestIRQ(struct ARMCore* cpu); void GBATestIRQ(struct ARMCore* cpu);
void GBAHalt(struct GBA* gba); void GBAHalt(struct GBA* gba);
void GBAStop(struct GBA* gba); void GBAStop(struct GBA* gba);
void GBADebug(struct GBA* gba, uint16_t value);
void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger); void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger);
void GBADetachDebugger(struct GBA* gba); void GBADetachDebugger(struct GBA* gba);

View File

@ -540,7 +540,20 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
case REG_MAX: case REG_MAX:
// Some bad interrupt libraries will write to this // Some bad interrupt libraries will write to this
break; break;
case REG_DEBUG_ENABLE:
gba->debug = value == 0xC0DE;
return;
case REG_DEBUG_FLAGS:
if (gba->debug) {
GBADebug(gba, value);
return;
}
// Fall through
default: default:
if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
STORE_16LE(value, address - REG_DEBUG_STRING, gba->debugString);
return;
}
mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address); mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address);
if (address >= REG_MAX) { if (address >= REG_MAX) {
mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address); mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address);
@ -562,6 +575,10 @@ void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
} }
return; return;
} }
if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
gba->debugString[address - REG_DEBUG_STRING] = value;
return;
}
if (address > SIZE_IO) { if (address > SIZE_IO) {
return; return;
} }
@ -613,6 +630,10 @@ void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
value = GBAMemoryWriteDMADAD(gba, 3, value); value = GBAMemoryWriteDMADAD(gba, 3, value);
break; break;
default: default:
if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
STORE_32LE(value, address - REG_DEBUG_STRING, gba->debugString);
return;
}
GBAIOWrite(gba, address, value & 0xFFFF); GBAIOWrite(gba, address, value & 0xFFFF);
GBAIOWrite(gba, address | 2, value >> 16); GBAIOWrite(gba, address | 2, value >> 16);
return; return;
@ -848,6 +869,11 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
case 0x8A: case 0x8A:
mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address); mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
return 0; return 0;
case REG_DEBUG_ENABLE:
if (gba->debug) {
return 0x1DEA;
}
// Fall through
default: default:
mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address); mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
return GBALoadBad(gba->cpu); return GBALoadBad(gba->cpu);

View File

@ -150,7 +150,11 @@ enum GBAIORegisters {
REG_MAX = 0x20A, REG_MAX = 0x20A,
REG_POSTFLG = 0x300, REG_POSTFLG = 0x300,
REG_HALTCNT = 0x301 REG_HALTCNT = 0x301,
REG_DEBUG_STRING = 0xFFF600,
REG_DEBUG_FLAGS = 0xFFF700,
REG_DEBUG_ENABLE = 0xFFF780,
}; };
mLOG_DECLARE_CATEGORY(GBA_IO); mLOG_DECLARE_CATEGORY(GBA_IO);