Qt: Boot both a multiboot image and ROM with CLI args (closes #1941)

This commit is contained in:
Vicki Pfau 2022-04-21 22:06:22 -07:00
parent b10a5b7f02
commit f326d02e33
7 changed files with 48 additions and 25 deletions

View File

@ -70,6 +70,7 @@ Misc:
- Qt: Add tile range selection to tile viewer (closes mgba.io/i/2455)
- Qt: Show warning if XQ audio is toggled while loaded (fixes mgba.io/i/2295)
- Qt: Add e-Card passing to the command line (closes mgba.io/i/2474)
- Qt: Boot both a multiboot image and ROM with CLI args (closes mgba.io/i/1941)
- Windows: Attach to console if present
- Vita: Add bilinear filtering option (closes mgba.io/i/344)

View File

@ -98,6 +98,7 @@ struct GBA {
uint32_t romCrc32;
struct VFile* romVf;
struct VFile* biosVf;
struct VFile* mbVf;
struct mAVStream* stream;
struct mKeyCallback* keyCallback;
@ -171,6 +172,8 @@ void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
bool GBALoadMB(struct GBA* gba, struct VFile* vf);
void GBAUnloadMB(struct GBA* gba);
bool GBALoadNull(struct GBA* gba);
void GBAGetGameCode(const struct GBA* gba, char* out);

View File

@ -139,7 +139,7 @@ void GBAUnloadROM(struct GBA* gba) {
if (gba->romVf) {
#ifndef FIXED_ROM_BUFFER
if (gba->isPristine) {
if (gba->isPristine && gba->memory.rom) {
gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize);
}
#endif
@ -147,6 +147,8 @@ void GBAUnloadROM(struct GBA* gba) {
gba->romVf = NULL;
}
gba->memory.rom = NULL;
gba->memory.romSize = 0;
gba->memory.romMask = 0;
gba->isPristine = false;
if (!gba->memory.savedata.dirty) {
@ -163,6 +165,7 @@ void GBAUnloadROM(struct GBA* gba) {
void GBADestroy(struct GBA* gba) {
GBAUnloadROM(gba);
GBAUnloadMB(gba);
if (gba->biosVf) {
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
@ -228,16 +231,18 @@ void GBAReset(struct ARMCore* cpu) {
bool isELF = false;
#ifdef USE_ELF
struct ELF* elf = ELFOpen(gba->romVf);
if (elf) {
isELF = true;
ELFClose(elf);
if (gba->mbVf) {
struct ELF* elf = ELFOpen(gba->mbVf);
if (elf) {
isELF = true;
ELFClose(elf);
}
}
#endif
if (GBAIsMB(gba->romVf) && !isELF) {
gba->romVf->seek(gba->romVf, 0, SEEK_SET);
gba->romVf->read(gba->romVf, gba->memory.wram, gba->pristineRomSize);
if (GBAIsMB(gba->mbVf) && !isELF) {
gba->mbVf->seek(gba->mbVf, 0, SEEK_SET);
gba->mbVf->read(gba->mbVf, gba->memory.wram, SIZE_WORKING_RAM);
}
gba->lastJump = 0;
@ -367,25 +372,24 @@ bool GBALoadNull(struct GBA* gba) {
}
bool GBALoadMB(struct GBA* gba, struct VFile* vf) {
GBAUnloadROM(gba);
gba->romVf = vf;
gba->pristineRomSize = vf->size(vf);
GBAUnloadMB(gba);
gba->mbVf = vf;
vf->seek(vf, 0, SEEK_SET);
if (gba->pristineRomSize > SIZE_WORKING_RAM) {
gba->pristineRomSize = SIZE_WORKING_RAM;
}
gba->isPristine = true;
memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
gba->yankedRomSize = 0;
gba->memory.romSize = 0;
gba->memory.romMask = 0;
gba->romCrc32 = doCrc32(gba->memory.wram, gba->pristineRomSize);
vf->read(vf, gba->memory.wram, SIZE_WORKING_RAM);
if (gba->cpu && gba->memory.activeRegion == REGION_WORKING_RAM) {
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
}
return true;
}
void GBAUnloadMB(struct GBA* gba) {
if (gba->mbVf) {
gba->mbVf->close(gba->mbVf);
gba->mbVf = NULL;
}
}
bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
if (!vf) {
return false;

View File

@ -5,8 +5,8 @@
const uint8_t hleBios[SIZE_BIOS] = {
0x06, 0x00, 0x00, 0xea, 0x66, 0x00, 0x00, 0xea, 0x0c, 0x00, 0x00, 0xea,
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3,
0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x4c, 0x01, 0x9f, 0x15,
0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x58, 0x01, 0x9f, 0xe5,
0x00, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x03, 0xa0, 0x03,
0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03,
0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xc0, 0x5e, 0xe5,

View File

@ -17,10 +17,10 @@ b irqBase
b fiqBase
resetBase:
mov r0, #0x8000000
ldrb r1, [r0, #3]
cmp r1, #0xEA
ldrne r0, =0x20000C0
ldr r0, =0x20000C0
ldr r1, [r0]
cmp r1, #0
moveq r0, #0x8000000
bx r0
.word 0
.word 0xE129F000

View File

@ -15,6 +15,7 @@
static const mOption s_frontendOptions[] = {
{ "ecard", true, '\0' },
{ "mb", true, '\0' },
{ 0 }
};
@ -136,6 +137,7 @@ ConfigController::ConfigController(QObject* parent)
m_subparsers[1].usage = "Frontend options:\n"
" --ecard FILE Scan an e-Reader card in the first loaded game\n"
" Can be paassed multiple times for multiple cards\n"
" --mb FILE Boot a multiboot image with FILE inserted into the ROM slot";
m_subparsers[1].parse = nullptr;
m_subparsers[1].parseLong = [](struct mSubParser* parser, const char* option, const char* arg) {
ConfigController* self = static_cast<ConfigController*>(parser->opts);
@ -149,6 +151,10 @@ ConfigController::ConfigController(QObject* parent)
self->m_argvOptions[optionName] = ecards;
return true;
}
if (optionName == QLatin1String("mb")) {
self->m_argvOptions[optionName] = QString::fromUtf8(arg);
return true;
}
return false;
};
m_subparsers[1].apply = nullptr;

View File

@ -2057,6 +2057,15 @@ void Window::setController(CoreController* controller, const QString& fname) {
connect(m_controller.get(), &CoreController::failed, this, &Window::gameFailed);
connect(m_controller.get(), &CoreController::unimplementedBiosCall, this, &Window::unimplementedBiosCall);
#ifdef M_CORE_GBA
if (m_controller->platform() == mPLATFORM_GBA) {
QVariant mb = m_config->takeArgvOption(QString("mb"));
if (mb.canConvert(QMetaType::QString)) {
m_controller->replaceGame(mb.toString());
}
}
#endif
#ifdef USE_GDB_STUB
if (m_gdbController) {
m_gdbController->setController(m_controller);