mirror of https://github.com/mgba-emu/mgba.git
Core: Add option to allow preloading the entire ROM before running
This commit is contained in:
parent
58c9bcf67a
commit
959f66a1a0
1
CHANGES
1
CHANGES
|
@ -13,6 +13,7 @@ Features:
|
||||||
- Qt: German translation (by Lothar Serra Mari)
|
- Qt: German translation (by Lothar Serra Mari)
|
||||||
- Savestates now contain any RTC override data
|
- Savestates now contain any RTC override data
|
||||||
- Command line ability to override configuration values
|
- Command line ability to override configuration values
|
||||||
|
- Add option to allow preloading the entire ROM before running
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- LR35902: Fix core never exiting with certain event patterns
|
- LR35902: Fix core never exiting with certain event patterns
|
||||||
- GB Timer: Improve DIV reset behavior
|
- GB Timer: Improve DIV reset behavior
|
||||||
|
|
|
@ -151,6 +151,9 @@ struct mCore {
|
||||||
struct mCore* mCoreFind(const char* path);
|
struct mCore* mCoreFind(const char* path);
|
||||||
bool mCoreLoadFile(struct mCore* core, const char* path);
|
bool mCoreLoadFile(struct mCore* core, const char* path);
|
||||||
|
|
||||||
|
bool mCorePreloadVF(struct mCore* core, struct VFile* vf);
|
||||||
|
bool mCorePreloadFile(struct mCore* core, const char* path);
|
||||||
|
|
||||||
bool mCoreAutoloadSave(struct mCore* core);
|
bool mCoreAutoloadSave(struct mCore* core);
|
||||||
bool mCoreAutoloadPatch(struct mCore* core);
|
bool mCoreAutoloadPatch(struct mCore* core);
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,35 @@ bool mCoreLoadFile(struct mCore* core, const char* path) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mCorePreloadVF(struct mCore* core, struct VFile* vf) {
|
||||||
|
struct VFile* vfm = VFileMemChunk(NULL, vf->size(vf));
|
||||||
|
uint8_t buffer[2048];
|
||||||
|
ssize_t read;
|
||||||
|
vf->seek(vf, 0, SEEK_SET);
|
||||||
|
while ((read = vf->read(vf, buffer, sizeof(buffer))) > 0) {
|
||||||
|
vfm->write(vfm, buffer, read);
|
||||||
|
}
|
||||||
|
vf->close(vf);
|
||||||
|
bool ret = core->loadROM(core, vfm);
|
||||||
|
if (!ret) {
|
||||||
|
vfm->close(vfm);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mCorePreloadFile(struct mCore* core, const char* path) {
|
||||||
|
struct VFile* rom = mDirectorySetOpenPath(&core->dirs, path, core->isROM);
|
||||||
|
if (!rom) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = mCorePreloadVF(core, rom);
|
||||||
|
if (!ret) {
|
||||||
|
rom->close(rom);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool mCoreAutoloadSave(struct mCore* core) {
|
bool mCoreAutoloadSave(struct mCore* core) {
|
||||||
return core->loadSave(core, mDirectorySetOpenSuffix(&core->dirs, core->dirs.save, ".sav", O_CREAT | O_RDWR));
|
return core->loadSave(core, mDirectorySetOpenSuffix(&core->dirs, core->dirs.save, ".sav", O_CREAT | O_RDWR));
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ GameController::GameController(QObject* parent)
|
||||||
, m_backupSaveState(nullptr)
|
, m_backupSaveState(nullptr)
|
||||||
, m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC)
|
, m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC)
|
||||||
, m_loadStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_RTC)
|
, m_loadStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_RTC)
|
||||||
|
, m_preload(false)
|
||||||
, m_override(nullptr)
|
, m_override(nullptr)
|
||||||
{
|
{
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
|
@ -458,11 +459,20 @@ void GameController::openGame(bool biosOnly) {
|
||||||
QByteArray bytes;
|
QByteArray bytes;
|
||||||
if (!biosOnly) {
|
if (!biosOnly) {
|
||||||
bytes = m_fname.toUtf8();
|
bytes = m_fname.toUtf8();
|
||||||
if (m_vf) {
|
if (m_preload) {
|
||||||
m_threadContext.core->loadROM(m_threadContext.core, m_vf);
|
if (m_vf) {
|
||||||
|
mCorePreloadVF(m_threadContext.core, m_vf);
|
||||||
|
} else {
|
||||||
|
mCorePreloadFile(m_threadContext.core, bytes.constData());
|
||||||
|
mDirectorySetDetachBase(&m_threadContext.core->dirs);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mCoreLoadFile(m_threadContext.core, bytes.constData());
|
if (m_vf) {
|
||||||
mDirectorySetDetachBase(&m_threadContext.core->dirs);
|
m_threadContext.core->loadROM(m_threadContext.core, m_vf);
|
||||||
|
} else {
|
||||||
|
mCoreLoadFile(m_threadContext.core, bytes.constData());
|
||||||
|
mDirectorySetDetachBase(&m_threadContext.core->dirs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bytes = m_bios.toUtf8();
|
bytes = m_bios.toUtf8();
|
||||||
|
@ -1107,6 +1117,10 @@ void GameController::setLoadStateExtdata(int flags) {
|
||||||
m_loadStateFlags = flags;
|
m_loadStateFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameController::setPreload(bool preload) {
|
||||||
|
m_preload = preload;
|
||||||
|
}
|
||||||
|
|
||||||
void GameController::setLuminanceValue(uint8_t value) {
|
void GameController::setLuminanceValue(uint8_t value) {
|
||||||
m_luxValue = value;
|
m_luxValue = value;
|
||||||
value = std::max<int>(value - 0x16, 0);
|
value = std::max<int>(value - 0x16, 0);
|
||||||
|
|
|
@ -154,6 +154,7 @@ public slots:
|
||||||
void reloadAudioDriver();
|
void reloadAudioDriver();
|
||||||
void setSaveStateExtdata(int flags);
|
void setSaveStateExtdata(int flags);
|
||||||
void setLoadStateExtdata(int flags);
|
void setLoadStateExtdata(int flags);
|
||||||
|
void setPreload(bool);
|
||||||
|
|
||||||
#ifdef USE_PNG
|
#ifdef USE_PNG
|
||||||
void screenshot();
|
void screenshot();
|
||||||
|
@ -234,6 +235,8 @@ private:
|
||||||
int m_saveStateFlags;
|
int m_saveStateFlags;
|
||||||
int m_loadStateFlags;
|
int m_loadStateFlags;
|
||||||
|
|
||||||
|
bool m_preload;
|
||||||
|
|
||||||
InputController* m_inputController;
|
InputController* m_inputController;
|
||||||
MultiplayerController* m_multiplayer;
|
MultiplayerController* m_multiplayer;
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,7 @@ void SettingsView::updateConfig() {
|
||||||
saveSetting("screenshotPath", m_ui.screenshotPath);
|
saveSetting("screenshotPath", m_ui.screenshotPath);
|
||||||
saveSetting("patchPath", m_ui.patchPath);
|
saveSetting("patchPath", m_ui.patchPath);
|
||||||
saveSetting("showLibrary", m_ui.showLibrary);
|
saveSetting("showLibrary", m_ui.showLibrary);
|
||||||
|
saveSetting("preload", m_ui.preload);
|
||||||
|
|
||||||
if (m_ui.fastForwardUnbounded->isChecked()) {
|
if (m_ui.fastForwardUnbounded->isChecked()) {
|
||||||
saveSetting("fastForwardRatio", "-1");
|
saveSetting("fastForwardRatio", "-1");
|
||||||
|
@ -283,6 +284,7 @@ void SettingsView::reloadConfig() {
|
||||||
loadSetting("screenshotPath", m_ui.screenshotPath);
|
loadSetting("screenshotPath", m_ui.screenshotPath);
|
||||||
loadSetting("patchPath", m_ui.patchPath);
|
loadSetting("patchPath", m_ui.patchPath);
|
||||||
loadSetting("showLibrary", m_ui.showLibrary);
|
loadSetting("showLibrary", m_ui.showLibrary);
|
||||||
|
loadSetting("preload", m_ui.preload);
|
||||||
|
|
||||||
double fastForwardRatio = loadSetting("fastForwardRatio").toDouble();
|
double fastForwardRatio = loadSetting("fastForwardRatio").toDouble();
|
||||||
if (fastForwardRatio <= 0) {
|
if (fastForwardRatio <= 0) {
|
||||||
|
|
|
@ -568,21 +568,21 @@
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="2">
|
<item row="8" column="0" colspan="2">
|
||||||
<widget class="Line" name="line_2">
|
<widget class="Line" name="line_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="9" column="0">
|
||||||
<widget class="QLabel" name="label_24">
|
<widget class="QLabel" name="label_24">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Savestate extra data:</string>
|
<string>Savestate extra data:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="9" column="1">
|
||||||
<widget class="QCheckBox" name="saveStateScreenshot">
|
<widget class="QCheckBox" name="saveStateScreenshot">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Screenshot</string>
|
<string>Screenshot</string>
|
||||||
|
@ -592,7 +592,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QCheckBox" name="saveStateSave">
|
<widget class="QCheckBox" name="saveStateSave">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save data</string>
|
<string>Save data</string>
|
||||||
|
@ -602,7 +602,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="1">
|
<item row="11" column="1">
|
||||||
<widget class="QCheckBox" name="saveStateCheats">
|
<widget class="QCheckBox" name="saveStateCheats">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Cheat codes</string>
|
<string>Cheat codes</string>
|
||||||
|
@ -612,14 +612,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="0">
|
<item row="13" column="0">
|
||||||
<widget class="QLabel" name="label_25">
|
<widget class="QLabel" name="label_25">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Load extra data:</string>
|
<string>Load extra data:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="1">
|
<item row="13" column="1">
|
||||||
<widget class="QCheckBox" name="loadStateScreenshot">
|
<widget class="QCheckBox" name="loadStateScreenshot">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Screenshot</string>
|
<string>Screenshot</string>
|
||||||
|
@ -629,21 +629,21 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="1">
|
<item row="14" column="1">
|
||||||
<widget class="QCheckBox" name="loadStateSave">
|
<widget class="QCheckBox" name="loadStateSave">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save data</string>
|
<string>Save data</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="1">
|
<item row="15" column="1">
|
||||||
<widget class="QCheckBox" name="loadStateCheats">
|
<widget class="QCheckBox" name="loadStateCheats">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Cheat codes</string>
|
<string>Cheat codes</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="0" colspan="2">
|
<item row="12" column="0" colspan="2">
|
||||||
<widget class="Line" name="line_9">
|
<widget class="Line" name="line_9">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
|
@ -660,6 +660,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QCheckBox" name="preload">
|
||||||
|
<property name="text">
|
||||||
|
<string>Preload entire ROM into memory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="bios">
|
<widget class="QWidget" name="bios">
|
||||||
|
|
|
@ -1476,6 +1476,12 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||||
m_controller->setLoadStateExtdata(value.toInt());
|
m_controller->setLoadStateExtdata(value.toInt());
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
ConfigOption* preload = m_config->addOption("preload");
|
||||||
|
preload->connect([this](const QVariant& value) {
|
||||||
|
m_controller->setPreload(value.toBool());
|
||||||
|
}, this);
|
||||||
|
m_config->updateOption("preload");
|
||||||
|
|
||||||
QAction* exitFullScreen = new QAction(tr("Exit fullscreen"), frameMenu);
|
QAction* exitFullScreen = new QAction(tr("Exit fullscreen"), frameMenu);
|
||||||
connect(exitFullScreen, SIGNAL(triggered()), this, SLOT(exitFullScreen()));
|
connect(exitFullScreen, SIGNAL(triggered()), this, SLOT(exitFullScreen()));
|
||||||
exitFullScreen->setShortcut(QKeySequence("Esc"));
|
exitFullScreen->setShortcut(QKeySequence("Esc"));
|
||||||
|
|
Loading…
Reference in New Issue