mirror of https://github.com/mgba-emu/mgba.git
GBA: Ability to boot directly into the BIOS
This commit is contained in:
parent
a51ae873bd
commit
596c7503b6
1
CHANGES
1
CHANGES
|
@ -20,6 +20,7 @@ Features:
|
|||
- Ability to cap fast forward speed
|
||||
- Finer control over FPS target
|
||||
- Holdable shortcut for rewinding one frame at a time
|
||||
- Ability to boot directly into the BIOS
|
||||
Bugfixes:
|
||||
- ARM7: Fix SWI and IRQ timings
|
||||
- GBA Audio: Force audio FIFOs to 32-bit
|
||||
|
|
|
@ -633,10 +633,18 @@ bool GBAIsBIOS(struct VFile* vf) {
|
|||
}
|
||||
|
||||
void GBAGetGameCode(struct GBA* gba, char* out) {
|
||||
if (!gba->memory.rom) {
|
||||
out[0] = '\0';
|
||||
return;
|
||||
}
|
||||
memcpy(out, &((struct GBACartridge*) gba->memory.rom)->id, 4);
|
||||
}
|
||||
|
||||
void GBAGetGameTitle(struct GBA* gba, char* out) {
|
||||
if (!gba->memory.rom) {
|
||||
strncpy(out, "(BIOS)", 12);
|
||||
return;
|
||||
}
|
||||
memcpy(out, &((struct GBACartridge*) gba->memory.rom)->title, 12);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ void GBAMemoryInit(struct GBA* gba) {
|
|||
gba->memory.wram = 0;
|
||||
gba->memory.iwram = 0;
|
||||
gba->memory.rom = 0;
|
||||
gba->memory.romSize = 0;
|
||||
gba->memory.hw.p = gba;
|
||||
|
||||
int i;
|
||||
|
|
|
@ -29,8 +29,13 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
|
|||
state->biosChecksum = gba->biosChecksum;
|
||||
state->romCrc32 = gba->romCrc32;
|
||||
|
||||
state->id = ((struct GBACartridge*) gba->memory.rom)->id;
|
||||
memcpy(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title));
|
||||
if (gba->memory.rom) {
|
||||
state->id = ((struct GBACartridge*) gba->memory.rom)->id;
|
||||
memcpy(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title));
|
||||
} else {
|
||||
state->id = 0;
|
||||
memset(state->title, 0, sizeof(state->title));
|
||||
}
|
||||
|
||||
memcpy(state->cpu.gprs, gba->cpu->gprs, sizeof(state->cpu.gprs));
|
||||
state->cpu.cpsr = gba->cpu->cpsr;
|
||||
|
@ -67,9 +72,12 @@ void GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (state->id != ((struct GBACartridge*) gba->memory.rom)->id || memcmp(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title))) {
|
||||
if (gba->memory.rom && state->id != ((struct GBACartridge*) gba->memory.rom)->id || memcmp(state->title, ((struct GBACartridge*) gba->memory.rom)->title, sizeof(state->title))) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is for a different game");
|
||||
return;
|
||||
} else if (!gba->memory.rom && state->id != 0) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is for a game, but no game loaded");
|
||||
return;
|
||||
}
|
||||
if (state->romCrc32 != gba->romCrc32) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is for a different version of the game");
|
||||
|
|
|
@ -167,15 +167,15 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
|||
GBAOverrideApply(&gba, &threadContext->override);
|
||||
}
|
||||
|
||||
if (threadContext->bios && GBAIsBIOS(threadContext->bios)) {
|
||||
GBALoadBIOS(&gba, threadContext->bios);
|
||||
}
|
||||
|
||||
if (threadContext->patch && loadPatch(threadContext->patch, &patch)) {
|
||||
GBAApplyPatch(&gba, &patch);
|
||||
}
|
||||
}
|
||||
|
||||
if (threadContext->bios && GBAIsBIOS(threadContext->bios)) {
|
||||
GBALoadBIOS(&gba, threadContext->bios);
|
||||
}
|
||||
|
||||
if (threadContext->movie) {
|
||||
struct VDir* movieDir = VDirOpen(threadContext->movie);
|
||||
#ifdef USE_LIBZIP
|
||||
|
@ -400,7 +400,9 @@ bool GBAThreadStart(struct GBAThread* threadContext) {
|
|||
threadContext->fpsTarget = _defaultFPSTarget;
|
||||
}
|
||||
|
||||
if (threadContext->rom && !GBAIsROM(threadContext->rom)) {
|
||||
bool bootBios = threadContext->bootBios && threadContext->bios;
|
||||
|
||||
if (threadContext->rom && (!GBAIsROM(threadContext->rom) || bootBios)) {
|
||||
threadContext->rom->close(threadContext->rom);
|
||||
threadContext->rom = 0;
|
||||
}
|
||||
|
@ -427,7 +429,7 @@ bool GBAThreadStart(struct GBAThread* threadContext) {
|
|||
|
||||
}
|
||||
|
||||
if (!threadContext->rom) {
|
||||
if (!threadContext->rom && !bootBios) {
|
||||
threadContext->state = THREAD_SHUTDOWN;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ struct GBAThread {
|
|||
struct GBAAVStream* stream;
|
||||
struct Configuration* overrides;
|
||||
enum GBAIdleLoopOptimization idleOptimization;
|
||||
bool bootBios;
|
||||
|
||||
bool hasOverride;
|
||||
struct GBACartridgeOverride override;
|
||||
|
|
|
@ -247,7 +247,18 @@ void GameController::loadGame(const QString& path, bool dirmode) {
|
|||
openGame();
|
||||
}
|
||||
|
||||
void GameController::openGame() {
|
||||
void GameController::bootBIOS() {
|
||||
closeGame();
|
||||
m_fname = QString();
|
||||
m_dirmode = false;
|
||||
openGame(true);
|
||||
}
|
||||
|
||||
void GameController::openGame(bool biosOnly) {
|
||||
if (biosOnly && (!m_useBios || m_bios.isNull())) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_gameOpen = true;
|
||||
|
||||
m_pauseAfterFrame = false;
|
||||
|
@ -261,25 +272,30 @@ void GameController::openGame() {
|
|||
}
|
||||
|
||||
m_threadContext.gameDir = 0;
|
||||
m_threadContext.fname = strdup(m_fname.toLocal8Bit().constData());
|
||||
if (m_dirmode) {
|
||||
m_threadContext.gameDir = VDirOpen(m_threadContext.fname);
|
||||
m_threadContext.stateDir = m_threadContext.gameDir;
|
||||
m_threadContext.bootBios = biosOnly;
|
||||
if (biosOnly) {
|
||||
m_threadContext.fname = nullptr;
|
||||
} else {
|
||||
m_threadContext.rom = VFileOpen(m_threadContext.fname, O_RDONLY);
|
||||
m_threadContext.fname = strdup(m_fname.toLocal8Bit().constData());
|
||||
if (m_dirmode) {
|
||||
m_threadContext.gameDir = VDirOpen(m_threadContext.fname);
|
||||
m_threadContext.stateDir = m_threadContext.gameDir;
|
||||
} else {
|
||||
m_threadContext.rom = VFileOpen(m_threadContext.fname, O_RDONLY);
|
||||
#if USE_LIBZIP
|
||||
if (!m_threadContext.gameDir) {
|
||||
m_threadContext.gameDir = VDirOpenZip(m_threadContext.fname, 0);
|
||||
}
|
||||
if (!m_threadContext.gameDir) {
|
||||
m_threadContext.gameDir = VDirOpenZip(m_threadContext.fname, 0);
|
||||
}
|
||||
#endif
|
||||
#if USE_LZMA
|
||||
if (!m_threadContext.gameDir) {
|
||||
m_threadContext.gameDir = VDirOpen7z(m_threadContext.fname, 0);
|
||||
}
|
||||
if (!m_threadContext.gameDir) {
|
||||
m_threadContext.gameDir = VDirOpen7z(m_threadContext.fname, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_bios.isNull() &&m_useBios) {
|
||||
if (!m_bios.isNull() && m_useBios) {
|
||||
m_threadContext.bios = VFileDevice::open(m_bios, O_RDONLY);
|
||||
} else {
|
||||
m_threadContext.bios = nullptr;
|
||||
|
|
|
@ -102,7 +102,7 @@ public slots:
|
|||
void loadPatch(const QString& path);
|
||||
void importSharkport(const QString& path);
|
||||
void exportSharkport(const QString& path);
|
||||
void openGame();
|
||||
void bootBIOS();
|
||||
void closeGame();
|
||||
void setPaused(bool paused);
|
||||
void reset();
|
||||
|
@ -148,6 +148,7 @@ public slots:
|
|||
void disableLogLevel(int);
|
||||
|
||||
private slots:
|
||||
void openGame(bool bios = false);
|
||||
void crashGame(const QString& crashMessage);
|
||||
|
||||
void pollEvents();
|
||||
|
|
|
@ -482,7 +482,9 @@ void Window::gameStarted(GBAThread* context) {
|
|||
foreach (QAction* action, m_gameActions) {
|
||||
action->setDisabled(false);
|
||||
}
|
||||
appendMRU(context->fname);
|
||||
if (context->fname) {
|
||||
appendMRU(context->fname);
|
||||
}
|
||||
updateTitle();
|
||||
attachWidget(m_display);
|
||||
|
||||
|
@ -609,6 +611,7 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
addControlledAction(fileMenu, fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open), "loadROM");
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("Load &BIOS..."), this, SLOT(selectBIOS())), "loadBIOS");
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("Load &patch..."), this, SLOT(selectPatch())), "loadPatch");
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("Boot BIOS"), m_controller, SLOT(bootBIOS())), "bootBIOS");
|
||||
|
||||
m_mruMenu = fileMenu->addMenu(tr("Recent"));
|
||||
|
||||
|
|
Loading…
Reference in New Issue