GBA: Booting of multiboot images
Jeffrey Pfau jeffrey@endrift.com
Tue, 20 Oct 2015 19:40:03 -0700
8 files changed,
130 insertions(+),
55 deletions(-)
M
CHANGES
→
CHANGES
@@ -2,6 +2,7 @@ 0.4.0: (Future)
Features: - Officially supported ports for the Nintendo 3DS, Wii, and PlayStation Vita - I/O viewer + - Booting of multiboot images Bugfixes: - Qt: Windows no longer spawn in the top left on first launch - Qt: Fix install path of XDG desktop file with DESTDIR
M
src/gba/context/context.c
→
src/gba/context/context.c
@@ -183,7 +183,7 @@
ARMReset(context->cpu); if (opts.skipBios) { - GBASkipBIOS(context->cpu); + GBASkipBIOS(context->gba); } struct GBACartridgeOverride override;
M
src/gba/gba.c
→
src/gba/gba.c
@@ -27,6 +27,9 @@
static const size_t GBA_ROM_MAGIC_OFFSET = 3; static const uint8_t GBA_ROM_MAGIC[] = { 0xEA }; +static const size_t GBA_MB_MAGIC_OFFSET = 0xC3; +static const uint8_t GBA_MB_MAGIC[] = { 0xEA }; + static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component); static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh); static void GBAProcessEvents(struct ARMCore* cpu);@@ -181,9 +184,14 @@ gba->timersEnabled = 0;
memset(gba->timers, 0, sizeof(gba->timers)); } -void GBASkipBIOS(struct ARMCore* cpu) { +void GBASkipBIOS(struct GBA* gba) { + struct ARMCore* cpu = gba->cpu; if (cpu->gprs[ARM_PC] == BASE_RESET + WORD_SIZE_ARM) { - cpu->gprs[ARM_PC] = BASE_CART0; + if (gba->memory.rom) { + cpu->gprs[ARM_PC] = BASE_CART0; + } else { + cpu->gprs[ARM_PC] = BASE_WORKING_RAM; + } int currentCycles = 0; ARM_WRITE_PC; }@@ -398,6 +406,35 @@ ARMHotplugDetach(gba->cpu, GBA_COMPONENT_DEBUGGER);
gba->cpu->components[GBA_COMPONENT_DEBUGGER] = 0; } +bool GBALoadMB(struct GBA* gba, struct VFile* vf, const char* fname) { + GBAUnloadROM(gba); + gba->romVf = vf; + gba->pristineRomSize = vf->size(vf); + vf->seek(vf, 0, SEEK_SET); + if (gba->pristineRomSize > SIZE_WORKING_RAM) { + gba->pristineRomSize = SIZE_WORKING_RAM; + } +#ifdef _3DS + gba->pristineRom = 0; + if (gba->pristineRomSize <= romBufferSize) { + gba->pristineRom = romBuffer; + vf->read(vf, romBuffer, gba->pristineRomSize); + } +#else + gba->pristineRom = vf->map(vf, gba->pristineRomSize, MAP_READ); +#endif + if (!gba->pristineRom) { + GBALog(gba, GBA_LOG_WARN, "Couldn't map ROM"); + return false; + } + gba->yankedRomSize = 0; + gba->activeFile = fname; + gba->memory.romSize = 0; + gba->memory.romMask = 0; + gba->romCrc32 = doCrc32(gba->pristineRom, gba->pristineRomSize); + return true; +} + bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) { GBAUnloadROM(gba); gba->romVf = vf;@@ -675,7 +712,24 @@ uint8_t signature[sizeof(GBA_ROM_MAGIC)];
if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) { return false; } + if (GBAIsBIOS(vf)) { + return false; + } return memcmp(signature, GBA_ROM_MAGIC, sizeof(signature)) == 0; +} + +bool GBAIsMB(struct VFile* vf) { + if (!GBAIsROM(vf)) { + return false; + } + if (vf->seek(vf, GBA_MB_MAGIC_OFFSET, SEEK_SET) < 0) { + return false; + } + uint8_t signature[sizeof(GBA_MB_MAGIC)]; + if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) { + return false; + } + return memcmp(signature, GBA_MB_MAGIC, sizeof(signature)) == 0; } bool GBAIsBIOS(struct VFile* vf) {@@ -704,11 +758,15 @@ memcpy(out, &((struct GBACartridge*) gba->memory.rom)->id, 4);
} void GBAGetGameTitle(struct GBA* gba, char* out) { - if (!gba->memory.rom) { - strncpy(out, "(BIOS)", 12); + if (gba->memory.rom) { + memcpy(out, &((struct GBACartridge*) gba->memory.rom)->title, 12); return; } - memcpy(out, &((struct GBACartridge*) gba->memory.rom)->title, 12); + if (gba->pristineRom) { + memcpy(out, &((struct GBACartridge*) gba->pristineRom)->title, 12); + return; + } + strncpy(out, "(BIOS)", 12); } void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) {
M
src/gba/gba.h
→
src/gba/gba.h
@@ -149,7 +149,7 @@ void GBACreate(struct GBA* gba);
void GBADestroy(struct GBA* gba); void GBAReset(struct ARMCore* cpu); -void GBASkipBIOS(struct ARMCore* cpu); +void GBASkipBIOS(struct GBA* gba); void GBATimerUpdateRegister(struct GBA* gba, int timer); void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value);@@ -175,7 +175,10 @@ void GBAUnloadROM(struct GBA* gba);
void GBALoadBIOS(struct GBA* gba, struct VFile* vf); void GBAApplyPatch(struct GBA* gba, struct Patch* patch); +bool GBALoadMB(struct GBA* gba, struct VFile* vf, const char* fname); + bool GBAIsROM(struct VFile* vf); +bool GBAIsMB(struct VFile* vf); bool GBAIsBIOS(struct VFile* vf); void GBAGetGameCode(struct GBA* gba, char* out); void GBAGetGameTitle(struct GBA* gba, char* out);
M
src/gba/hle-bios.c
→
src/gba/hle-bios.c
@@ -3,49 +3,50 @@
#include "gba/memory.h" const uint8_t hleBios[SIZE_BIOS] = { - 0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x07, 0x00, 0x00, 0xea, + 0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x0b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1, - 0x28, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0xf3, 0xa0, 0xe3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3, - 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9, - 0x02, 0xb0, 0x5e, 0xe5, 0x8c, 0xc0, 0xa0, 0xe3, 0x0b, 0xb1, 0x9c, 0xe7, - 0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1, 0x00, 0x10, 0x2d, 0xe9, - 0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3, 0x0c, 0xf0, 0x29, 0xe1, - 0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1, 0x1b, 0xff, 0x2f, 0x11, - 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, 0x00, 0x10, 0xbd, 0xe8, - 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, 0x0e, 0xf0, 0xb0, 0xe1, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, + 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x02, 0x04, 0xa0, 0x13, + 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, + 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, + 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3, + 0x0b, 0xb1, 0x9c, 0xe7, 0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1, + 0x00, 0x10, 0x2d, 0xe9, 0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3, + 0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1, + 0x1b, 0xff, 0x2f, 0x11, 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, + 0x00, 0x10, 0xbd, 0xe8, 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, + 0x0e, 0xf0, 0xb0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe8, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, - 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, 0x00, 0xe0, 0x8f, 0xe2, - 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, 0x01, 0x00, 0xa0, 0xe3, - 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3, - 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3, - 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1, - 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5, - 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10, - 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a, - 0x0c, 0x80, 0xbd, 0xe8, 0x00, 0x40, 0x2d, 0xe9, 0x02, 0x36, 0xa0, 0xe1, - 0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, - 0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0, 0x04, 0x00, 0xb0, 0xe8, - 0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, - 0x16, 0x00, 0x00, 0xea, 0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, - 0xa3, 0x35, 0x81, 0xe0, 0xb0, 0x20, 0xd0, 0xe1, 0x03, 0x00, 0x51, 0xe1, - 0xb2, 0x20, 0xc1, 0xb0, 0xfc, 0xff, 0xff, 0xba, 0x0e, 0x00, 0x00, 0xea, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, + 0xd0, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, + 0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, + 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, + 0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, + 0x01, 0xc3, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, + 0x01, 0x20, 0xa0, 0xe3, 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, + 0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, + 0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, + 0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, + 0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8, 0x00, 0x40, 0x2d, 0xe9, + 0x02, 0x36, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0, - 0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xb0, 0xb8, 0x04, 0x00, 0xa1, 0xb8, - 0xfb, 0xff, 0xff, 0xba, 0x06, 0x00, 0x00, 0xea, 0xa3, 0x35, 0x81, 0xe0, - 0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, 0x03, 0x00, 0x51, 0xe1, - 0xb2, 0x20, 0xd0, 0xb0, 0xb2, 0x20, 0xc1, 0xb0, 0xfb, 0xff, 0xff, 0xba, - 0x00, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, - 0x02, 0x36, 0xa0, 0xe1, 0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, - 0x00, 0x30, 0x90, 0xe5, 0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, - 0x03, 0x60, 0xa0, 0xe1, 0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1, - 0x03, 0x90, 0xa0, 0xe1, 0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1, - 0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea, - 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8, - 0xfb, 0xff, 0xff, 0xba, 0xf0, 0x87, 0xbd, 0xe8 + 0x04, 0x00, 0xb0, 0xe8, 0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xa1, 0xb8, + 0xfc, 0xff, 0xff, 0xba, 0x16, 0x00, 0x00, 0xea, 0x01, 0x00, 0xc0, 0xe3, + 0x01, 0x10, 0xc1, 0xe3, 0xa3, 0x35, 0x81, 0xe0, 0xb0, 0x20, 0xd0, 0xe1, + 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xc1, 0xb0, 0xfc, 0xff, 0xff, 0xba, + 0x0e, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, + 0x23, 0x35, 0x81, 0xe0, 0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xb0, 0xb8, + 0x04, 0x00, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, 0x06, 0x00, 0x00, 0xea, + 0xa3, 0x35, 0x81, 0xe0, 0x01, 0x00, 0xc0, 0xe3, 0x01, 0x10, 0xc1, 0xe3, + 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xd0, 0xb0, 0xb2, 0x20, 0xc1, 0xb0, + 0xfb, 0xff, 0xff, 0xba, 0x00, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9, + 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1, 0x23, 0x25, 0x81, 0xe0, + 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5, 0x03, 0x40, 0xa0, 0xe1, + 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1, 0x03, 0x70, 0xa0, 0xe1, + 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1, 0x03, 0xa0, 0xa0, 0xe1, + 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, + 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, + 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, 0xf0, 0x87, 0xbd, 0xe8 };
M
src/gba/hle-bios.s
→
src/gba/hle-bios.s
@@ -17,7 +17,11 @@ b irqBase
b fiqBase resetBase: -mov pc, #0x8000000 +mov r0, #0x8000000 +ldrb r1, [r0, #3] +cmp r1, #0xEA +movne r0, #0x2000000 +bx r0 .word 0 .word 0xE129F000
M
src/gba/memory.c
→
src/gba/memory.c
@@ -96,6 +96,10 @@ if (gba->memory.wram) {
mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM); } gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM); + if (gba->pristineRom && !gba->memory.rom) { + // Multiboot + memcpy(gba->memory.wram, gba->pristineRom, gba->pristineRomSize); + } if (gba->memory.iwram) { mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
M
src/gba/supervisor/thread.c
→
src/gba/supervisor/thread.c
@@ -167,10 +167,14 @@ GBAVideoAssociateRenderer(&gba.video, threadContext->renderer);
} if (threadContext->rom) { - GBALoadROM(&gba, threadContext->rom, threadContext->save, threadContext->fname); + if (GBAIsMB(threadContext->rom)) { + GBALoadMB(&gba, threadContext->rom, threadContext->fname); + } else { + GBALoadROM(&gba, threadContext->rom, threadContext->save, threadContext->fname); + } struct GBACartridgeOverride override; - const struct GBACartridge* cart = (const struct GBACartridge*) gba.memory.rom; + const struct GBACartridge* cart = (const struct GBACartridge*) gba.pristineRom; memcpy(override.id, &cart->id, sizeof(override.id)); if (GBAOverrideFind(threadContext->overrides, &override)) { GBAOverrideApply(&gba, &override);@@ -225,8 +229,8 @@ movie->startPlaying(movie, false);
GBARRInitPlay(&gba); } - if (threadContext->skipBios && gba.memory.rom) { - GBASkipBIOS(&cpu); + if (threadContext->skipBios && gba.pristineRom) { + GBASkipBIOS(&gba); } if (!threadContext->cheats) {@@ -305,8 +309,8 @@ }
MutexUnlock(&threadContext->stateMutex); if (resetScheduled) { ARMReset(&cpu); - if (threadContext->skipBios && gba.memory.rom) { - GBASkipBIOS(&cpu); + if (threadContext->skipBios && gba.pristineRom) { + GBASkipBIOS(&gba); } } }