mirror of https://github.com/mgba-emu/mgba.git
Qt: Boot both a multiboot image and ROM with CLI args (closes #1941)
This commit is contained in:
parent
b10a5b7f02
commit
f326d02e33
1
CHANGES
1
CHANGES
|
@ -70,6 +70,7 @@ Misc:
|
||||||
- Qt: Add tile range selection to tile viewer (closes mgba.io/i/2455)
|
- 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: 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: 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
|
- Windows: Attach to console if present
|
||||||
- Vita: Add bilinear filtering option (closes mgba.io/i/344)
|
- Vita: Add bilinear filtering option (closes mgba.io/i/344)
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ struct GBA {
|
||||||
uint32_t romCrc32;
|
uint32_t romCrc32;
|
||||||
struct VFile* romVf;
|
struct VFile* romVf;
|
||||||
struct VFile* biosVf;
|
struct VFile* biosVf;
|
||||||
|
struct VFile* mbVf;
|
||||||
|
|
||||||
struct mAVStream* stream;
|
struct mAVStream* stream;
|
||||||
struct mKeyCallback* keyCallback;
|
struct mKeyCallback* keyCallback;
|
||||||
|
@ -171,6 +172,8 @@ void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
|
||||||
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
|
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
|
||||||
|
|
||||||
bool GBALoadMB(struct GBA* gba, struct VFile* vf);
|
bool GBALoadMB(struct GBA* gba, struct VFile* vf);
|
||||||
|
void GBAUnloadMB(struct GBA* gba);
|
||||||
|
|
||||||
bool GBALoadNull(struct GBA* gba);
|
bool GBALoadNull(struct GBA* gba);
|
||||||
|
|
||||||
void GBAGetGameCode(const struct GBA* gba, char* out);
|
void GBAGetGameCode(const struct GBA* gba, char* out);
|
||||||
|
|
|
@ -139,7 +139,7 @@ void GBAUnloadROM(struct GBA* gba) {
|
||||||
|
|
||||||
if (gba->romVf) {
|
if (gba->romVf) {
|
||||||
#ifndef FIXED_ROM_BUFFER
|
#ifndef FIXED_ROM_BUFFER
|
||||||
if (gba->isPristine) {
|
if (gba->isPristine && gba->memory.rom) {
|
||||||
gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize);
|
gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -147,6 +147,8 @@ void GBAUnloadROM(struct GBA* gba) {
|
||||||
gba->romVf = NULL;
|
gba->romVf = NULL;
|
||||||
}
|
}
|
||||||
gba->memory.rom = NULL;
|
gba->memory.rom = NULL;
|
||||||
|
gba->memory.romSize = 0;
|
||||||
|
gba->memory.romMask = 0;
|
||||||
gba->isPristine = false;
|
gba->isPristine = false;
|
||||||
|
|
||||||
if (!gba->memory.savedata.dirty) {
|
if (!gba->memory.savedata.dirty) {
|
||||||
|
@ -163,6 +165,7 @@ void GBAUnloadROM(struct GBA* gba) {
|
||||||
|
|
||||||
void GBADestroy(struct GBA* gba) {
|
void GBADestroy(struct GBA* gba) {
|
||||||
GBAUnloadROM(gba);
|
GBAUnloadROM(gba);
|
||||||
|
GBAUnloadMB(gba);
|
||||||
|
|
||||||
if (gba->biosVf) {
|
if (gba->biosVf) {
|
||||||
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
|
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
|
||||||
|
@ -228,16 +231,18 @@ void GBAReset(struct ARMCore* cpu) {
|
||||||
|
|
||||||
bool isELF = false;
|
bool isELF = false;
|
||||||
#ifdef USE_ELF
|
#ifdef USE_ELF
|
||||||
struct ELF* elf = ELFOpen(gba->romVf);
|
if (gba->mbVf) {
|
||||||
|
struct ELF* elf = ELFOpen(gba->mbVf);
|
||||||
if (elf) {
|
if (elf) {
|
||||||
isELF = true;
|
isELF = true;
|
||||||
ELFClose(elf);
|
ELFClose(elf);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (GBAIsMB(gba->romVf) && !isELF) {
|
if (GBAIsMB(gba->mbVf) && !isELF) {
|
||||||
gba->romVf->seek(gba->romVf, 0, SEEK_SET);
|
gba->mbVf->seek(gba->mbVf, 0, SEEK_SET);
|
||||||
gba->romVf->read(gba->romVf, gba->memory.wram, gba->pristineRomSize);
|
gba->mbVf->read(gba->mbVf, gba->memory.wram, SIZE_WORKING_RAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
gba->lastJump = 0;
|
gba->lastJump = 0;
|
||||||
|
@ -367,25 +372,24 @@ bool GBALoadNull(struct GBA* gba) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GBALoadMB(struct GBA* gba, struct VFile* vf) {
|
bool GBALoadMB(struct GBA* gba, struct VFile* vf) {
|
||||||
GBAUnloadROM(gba);
|
GBAUnloadMB(gba);
|
||||||
gba->romVf = vf;
|
gba->mbVf = vf;
|
||||||
gba->pristineRomSize = vf->size(vf);
|
|
||||||
vf->seek(vf, 0, SEEK_SET);
|
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);
|
memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
|
||||||
gba->yankedRomSize = 0;
|
vf->read(vf, gba->memory.wram, SIZE_WORKING_RAM);
|
||||||
gba->memory.romSize = 0;
|
|
||||||
gba->memory.romMask = 0;
|
|
||||||
gba->romCrc32 = doCrc32(gba->memory.wram, gba->pristineRomSize);
|
|
||||||
if (gba->cpu && gba->memory.activeRegion == REGION_WORKING_RAM) {
|
if (gba->cpu && gba->memory.activeRegion == REGION_WORKING_RAM) {
|
||||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||||
}
|
}
|
||||||
return true;
|
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) {
|
bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
|
||||||
if (!vf) {
|
if (!vf) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
const uint8_t hleBios[SIZE_BIOS] = {
|
const uint8_t hleBios[SIZE_BIOS] = {
|
||||||
0x06, 0x00, 0x00, 0xea, 0x66, 0x00, 0x00, 0xea, 0x0c, 0x00, 0x00, 0xea,
|
0x06, 0x00, 0x00, 0xea, 0x66, 0x00, 0x00, 0xea, 0x0c, 0x00, 0x00, 0xea,
|
||||||
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
||||||
0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3,
|
0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x58, 0x01, 0x9f, 0xe5,
|
||||||
0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x4c, 0x01, 0x9f, 0x15,
|
0x00, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x03, 0xa0, 0x03,
|
||||||
0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1,
|
0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03,
|
||||||
0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xc0, 0x5e, 0xe5,
|
0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xc0, 0x5e, 0xe5,
|
||||||
|
|
|
@ -17,10 +17,10 @@ b irqBase
|
||||||
b fiqBase
|
b fiqBase
|
||||||
|
|
||||||
resetBase:
|
resetBase:
|
||||||
mov r0, #0x8000000
|
ldr r0, =0x20000C0
|
||||||
ldrb r1, [r0, #3]
|
ldr r1, [r0]
|
||||||
cmp r1, #0xEA
|
cmp r1, #0
|
||||||
ldrne r0, =0x20000C0
|
moveq r0, #0x8000000
|
||||||
bx r0
|
bx r0
|
||||||
.word 0
|
.word 0
|
||||||
.word 0xE129F000
|
.word 0xE129F000
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
static const mOption s_frontendOptions[] = {
|
static const mOption s_frontendOptions[] = {
|
||||||
{ "ecard", true, '\0' },
|
{ "ecard", true, '\0' },
|
||||||
|
{ "mb", true, '\0' },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,6 +137,7 @@ ConfigController::ConfigController(QObject* parent)
|
||||||
m_subparsers[1].usage = "Frontend options:\n"
|
m_subparsers[1].usage = "Frontend options:\n"
|
||||||
" --ecard FILE Scan an e-Reader card in the first loaded game\n"
|
" --ecard FILE Scan an e-Reader card in the first loaded game\n"
|
||||||
" Can be paassed multiple times for multiple cards\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].parse = nullptr;
|
||||||
m_subparsers[1].parseLong = [](struct mSubParser* parser, const char* option, const char* arg) {
|
m_subparsers[1].parseLong = [](struct mSubParser* parser, const char* option, const char* arg) {
|
||||||
ConfigController* self = static_cast<ConfigController*>(parser->opts);
|
ConfigController* self = static_cast<ConfigController*>(parser->opts);
|
||||||
|
@ -149,6 +151,10 @@ ConfigController::ConfigController(QObject* parent)
|
||||||
self->m_argvOptions[optionName] = ecards;
|
self->m_argvOptions[optionName] = ecards;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (optionName == QLatin1String("mb")) {
|
||||||
|
self->m_argvOptions[optionName] = QString::fromUtf8(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
m_subparsers[1].apply = nullptr;
|
m_subparsers[1].apply = nullptr;
|
||||||
|
|
|
@ -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::failed, this, &Window::gameFailed);
|
||||||
connect(m_controller.get(), &CoreController::unimplementedBiosCall, this, &Window::unimplementedBiosCall);
|
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
|
#ifdef USE_GDB_STUB
|
||||||
if (m_gdbController) {
|
if (m_gdbController) {
|
||||||
m_gdbController->setController(m_controller);
|
m_gdbController->setController(m_controller);
|
||||||
|
|
Loading…
Reference in New Issue