mirror of https://github.com/mgba-emu/mgba.git
GBA: Support printing debug strings from inside a game
This commit is contained in:
parent
278ac5f35b
commit
e79963b007
2
CHANGES
2
CHANGES
|
@ -1,4 +1,6 @@
|
|||
0.6.0: (Future)
|
||||
Features:
|
||||
- GBA: Support printing debug strings from inside a game
|
||||
Bugfixes:
|
||||
- GB MBC: Fix MBC7 when size is incorrectly specified
|
||||
- GB Video: Setting LYC=LY during mode 2 should trigger an IRQ
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "util/vfs.h"
|
||||
|
||||
mLOG_DEFINE_CATEGORY(GBA, "GBA");
|
||||
mLOG_DEFINE_CATEGORY(GBA_DEBUG, "GBA Debug");
|
||||
|
||||
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
||||
|
||||
|
@ -199,6 +200,9 @@ void GBAReset(struct ARMCore* cpu) {
|
|||
gba->haltPending = false;
|
||||
gba->idleDetectionStep = 0;
|
||||
gba->idleDetectionFailures = 0;
|
||||
|
||||
gba->debug = false;
|
||||
memset(gba->debugString, 0, sizeof(gba->debugString));
|
||||
}
|
||||
|
||||
void GBASkipBIOS(struct GBA* gba) {
|
||||
|
@ -681,6 +685,19 @@ void GBAStop(struct GBA* gba) {
|
|||
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) {
|
||||
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
|
||||
return false;
|
||||
|
|
|
@ -53,6 +53,7 @@ struct Patch;
|
|||
struct VFile;
|
||||
|
||||
mLOG_DECLARE_CATEGORY(GBA);
|
||||
mLOG_DECLARE_CATEGORY(GBA_DEBUG);
|
||||
|
||||
DECL_BITFIELD(GBATimerFlags, uint32_t);
|
||||
DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4);
|
||||
|
@ -60,6 +61,10 @@ DECL_BIT(GBATimerFlags, CountUp, 4);
|
|||
DECL_BIT(GBATimerFlags, DoIrq, 5);
|
||||
DECL_BIT(GBATimerFlags, Enable, 6);
|
||||
|
||||
DECL_BITFIELD(GBADebugFlags, uint16_t);
|
||||
DECL_BITS(GBADebugFlags, Level, 0, 3);
|
||||
DECL_BIT(GBADebugFlags, Send, 8);
|
||||
|
||||
struct GBATimer {
|
||||
uint16_t reload;
|
||||
uint16_t oldReload;
|
||||
|
@ -120,6 +125,10 @@ struct GBA {
|
|||
bool realisticTiming;
|
||||
bool hardCrash;
|
||||
bool allowOpposingDirections;
|
||||
|
||||
bool debug;
|
||||
char debugString[0x100];
|
||||
GBADebugFlags debugFlags;
|
||||
};
|
||||
|
||||
struct GBACartridge {
|
||||
|
@ -153,6 +162,7 @@ void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq);
|
|||
void GBATestIRQ(struct ARMCore* cpu);
|
||||
void GBAHalt(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 GBADetachDebugger(struct GBA* gba);
|
||||
|
|
26
src/gba/io.c
26
src/gba/io.c
|
@ -540,7 +540,20 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
|
|||
case REG_MAX:
|
||||
// Some bad interrupt libraries will write to this
|
||||
break;
|
||||
case REG_DEBUG_ENABLE:
|
||||
gba->debug = value == 0xC0DE;
|
||||
return;
|
||||
case REG_DEBUG_FLAGS:
|
||||
if (gba->debug) {
|
||||
GBADebug(gba, value);
|
||||
return;
|
||||
}
|
||||
// Fall through
|
||||
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);
|
||||
if (address >= REG_MAX) {
|
||||
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;
|
||||
}
|
||||
if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
|
||||
gba->debugString[address - REG_DEBUG_STRING] = value;
|
||||
return;
|
||||
}
|
||||
if (address > SIZE_IO) {
|
||||
return;
|
||||
}
|
||||
|
@ -613,6 +630,10 @@ void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
|
|||
value = GBAMemoryWriteDMADAD(gba, 3, value);
|
||||
break;
|
||||
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 | 2, value >> 16);
|
||||
return;
|
||||
|
@ -848,6 +869,11 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
|
|||
case 0x8A:
|
||||
mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
|
||||
return 0;
|
||||
case REG_DEBUG_ENABLE:
|
||||
if (gba->debug) {
|
||||
return 0x1DEA;
|
||||
}
|
||||
// Fall through
|
||||
default:
|
||||
mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
|
||||
return GBALoadBad(gba->cpu);
|
||||
|
|
|
@ -150,7 +150,11 @@ enum GBAIORegisters {
|
|||
REG_MAX = 0x20A,
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue