GBA: Booting of multiboot images

This commit is contained in:
Jeffrey Pfau 2015-10-20 19:40:03 -07:00
parent c41a3a2c0a
commit 98016c55a3
8 changed files with 130 additions and 55 deletions

View File

@ -2,6 +2,7 @@
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

View File

@ -183,7 +183,7 @@ bool GBAContextStart(struct GBAContext* context) {
ARMReset(context->cpu);
if (opts.skipBios) {
GBASkipBIOS(context->cpu);
GBASkipBIOS(context->gba);
}
struct GBACartridgeOverride override;

View File

@ -27,6 +27,9 @@ const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
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 @@ void GBAReset(struct ARMCore* cpu) {
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 @@ void GBADetachDebugger(struct GBA* gba) {
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,9 +712,26 @@ bool GBAIsROM(struct VFile* vf) {
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) {
if (vf->seek(vf, 0, SEEK_SET) < 0) {
return false;
@ -704,11 +758,15 @@ void GBAGetGameCode(struct GBA* gba, char* out) {
}
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) {

View File

@ -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);

View File

@ -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
};

View File

@ -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

View File

@ -96,6 +96,10 @@ void GBAMemoryReset(struct GBA* gba) {
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);

View File

@ -167,10 +167,14 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
}
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 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
GBARRInitPlay(&gba);
}
if (threadContext->skipBios && gba.memory.rom) {
GBASkipBIOS(&cpu);
if (threadContext->skipBios && gba.pristineRom) {
GBASkipBIOS(&gba);
}
if (!threadContext->cheats) {
@ -305,8 +309,8 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
MutexUnlock(&threadContext->stateMutex);
if (resetScheduled) {
ARMReset(&cpu);
if (threadContext->skipBios && gba.memory.rom) {
GBASkipBIOS(&cpu);
if (threadContext->skipBios && gba.pristineRom) {
GBASkipBIOS(&gba);
}
}
}