all repos — mgba @ 596c7503b62ae8762b77840850790f26381f7392

mGBA Game Boy Advance Emulator

GBA: Ability to boot directly into the BIOS
Jeffrey Pfau jeffrey@endrift.com
Mon, 08 Jun 2015 00:19:13 -0700
commit

596c7503b62ae8762b77840850790f26381f7392

parent

a51ae873bd3c71ae1f2493f393169b53c360a9b9

M CHANGESCHANGES

@@ -20,6 +20,7 @@ - Support varible speed (PWM) rumble

- 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
M src/gba/gba.csrc/gba/gba.c

@@ -633,10 +633,18 @@ return true;

} 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); }
M src/gba/memory.csrc/gba/memory.c

@@ -47,6 +47,7 @@ gba->memory.fullBios = 0;

gba->memory.wram = 0; gba->memory.iwram = 0; gba->memory.rom = 0; + gba->memory.romSize = 0; gba->memory.hw.p = gba; int i;
M src/gba/serialize.csrc/gba/serialize.c

@@ -29,8 +29,13 @@ state->versionMagic = GBA_SAVESTATE_MAGIC;

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,8 +72,11 @@ if (state->cpu.gprs[ARM_PC] < SIZE_BIOS && state->cpu.gprs[ARM_PC] >= 0x20) {

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) {
M src/gba/supervisor/thread.csrc/gba/supervisor/thread.c

@@ -167,13 +167,13 @@ if (threadContext->hasOverride) {

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) {

@@ -400,7 +400,9 @@ if (!threadContext->fpsTarget) {

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

} - if (!threadContext->rom) { + if (!threadContext->rom && !bootBios) { threadContext->state = THREAD_SHUTDOWN; return false; }
M src/gba/supervisor/thread.hsrc/gba/supervisor/thread.h

@@ -72,6 +72,7 @@ int activeKeys;

struct GBAAVStream* stream; struct Configuration* overrides; enum GBAIdleLoopOptimization idleOptimization; + bool bootBios; bool hasOverride; struct GBACartridgeOverride override;
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -247,7 +247,18 @@ m_dirmode = 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 @@ m_threadContext.sync.audioWait = m_audioSync;

} 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;
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -102,7 +102,7 @@ void setUseBIOS(bool);

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 @@ void enableLogLevel(int);

void disableLogLevel(int); private slots: + void openGame(bool bios = false); void crashGame(const QString& crashMessage); void pollEvents();
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -482,7 +482,9 @@ MutexUnlock(&context->stateMutex);

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 @@ installEventFilter(m_shortcutController);

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