mirror of
https://github.com/libretro/mgba.git
synced 2024-11-27 02:00:42 +00:00
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: 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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user