WIP. lay base for EmuInstance.

This commit is contained in:
Arisotura
2024-05-10 12:48:32 +02:00
parent f93937e88b
commit faa6cfec48
11 changed files with 514 additions and 134 deletions

View File

@ -0,0 +1,362 @@
/*
Copyright 2016-2023 melonDS team
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <codecvt>
#include <locale>
#include <memory>
#include <tuple>
#include <string>
#include <utility>
#include <fstream>
#include <QDateTime>
#include <QMessageBox>
#include <zstd.h>
#ifdef ARCHIVE_SUPPORT_ENABLED
#include "ArchiveUtil.h"
#endif
#include "EmuInstance.h"
#include "Config.h"
#include "Platform.h"
#include "NDS.h"
#include "DSi.h"
#include "SPI.h"
#include "RTC.h"
#include "DSi_I2C.h"
#include "FreeBIOS.h"
#include "main.h"
using std::make_unique;
using std::pair;
using std::string;
using std::tie;
using std::unique_ptr;
using std::wstring_convert;
using namespace melonDS;
using namespace melonDS::Platform;
MainWindow* topWindow = nullptr;
EmuInstance::EmuInstance(int inst)
{
instanceID = inst;
globalCfg = Config::GetGlobalTable();
localCfg = Config::GetLocalTable(inst);
emuThread = new EmuThread();
numWindows = 0;
mainWindow = nullptr;
for (int i = 0; i < kMaxWindows; i++)
windowList[i] = nullptr;
if (inst == 0) topWindow = nullptr;
createWindow();
emuThread->start();
emuThread->emuPause();
}
EmuInstance::~EmuInstance()
{
// TODO window cleanup and shit?
emuThread->emuStop();
emuThread->wait();
delete emuThread;
}
void EmuInstance::createWindow()
{
if (numWindows >= kMaxWindows)
{
// TODO
return;
}
int id = -1;
for (int i = 0; i < kMaxWindows; i++)
{
if (windowList[i]) continue;
id = i;
break;
}
if (id == -1)
return;
MainWindow* win = new MainWindow(topWindow);
if (!topWindow) topWindow = win;
if (!mainWindow) mainWindow = win;
windowList[id] = win;
numWindows++;
emuThread->attachWindow(win);
}
int EmuInstance::lastSep(const std::string& path)
{
int i = path.length() - 1;
while (i >= 0)
{
if (path[i] == '/' || path[i] == '\\')
return i;
i--;
}
return -1;
}
string EmuInstance::getAssetPath(bool gba, const string& configpath, const string& ext, const string& file = "")
{
string result;
if (configpath.empty())
result = gba ? baseGBAROMDir : baseROMDir;
else
result = configpath;
// cut off trailing slashes
for (;;)
{
int i = result.length() - 1;
if (i < 0) break;
if (result[i] == '/' || result[i] == '\\')
result.resize(i);
else
break;
}
if (!result.empty())
result += '/';
if (file.empty())
{
std::string& baseName = gba ? baseGBAAssetName : baseAssetName;
if (baseName.empty())
result += "firmware";
else
result += baseName;
}
else
{
result += file;
}
result += ext;
return result;
}
QString EmuInstance::verifyDSBIOS()
{
FileHandle* f;
long len;
f = Platform::OpenLocalFile(globalCfg.GetString("DS.BIOS9Path"), FileMode::Read);
if (!f) return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
len = FileLength(f);
if (len != 0x1000)
{
CloseFile(f);
return "DS ARM9 BIOS is not a valid BIOS dump.";
}
CloseFile(f);
f = Platform::OpenLocalFile(globalCfg.GetString("DS.BIOS7Path"), FileMode::Read);
if (!f) return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
len = FileLength(f);
if (len != 0x4000)
{
CloseFile(f);
return "DS ARM7 BIOS is not a valid BIOS dump.";
}
CloseFile(f);
return "";
}
QString EmuInstance::verifyDSiBIOS()
{
FileHandle* f;
long len;
// TODO: check the first 32 bytes
f = Platform::OpenLocalFile(globalCfg.GetString("DSi.BIOS9Path"), FileMode::Read);
if (!f) return "DSi ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
len = FileLength(f);
if (len != 0x10000)
{
CloseFile(f);
return "DSi ARM9 BIOS is not a valid BIOS dump.";
}
CloseFile(f);
f = Platform::OpenLocalFile(globalCfg.GetString("DSi.BIOS7Path"), FileMode::Read);
if (!f) return "DSi ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
len = FileLength(f);
if (len != 0x10000)
{
CloseFile(f);
return "DSi ARM7 BIOS is not a valid BIOS dump.";
}
CloseFile(f);
return "";
}
QString EmuInstance::verifyDSFirmware()
{
FileHandle* f;
long len;
std::string fwpath = globalCfg.GetString("DS.FirmwarePath");
f = Platform::OpenLocalFile(fwpath, FileMode::Read);
if (!f) return "DS firmware was not found or could not be accessed. Check your emu settings.";
if (!Platform::CheckFileWritable(fwpath))
return "DS firmware is unable to be written to.\nPlease check file/folder write permissions.";
len = FileLength(f);
if (len == 0x20000)
{
// 128KB firmware, not bootable
CloseFile(f);
// TODO report it somehow? detect in core?
return "";
}
else if (len != 0x40000 && len != 0x80000)
{
CloseFile(f);
return "DS firmware is not a valid firmware dump.";
}
CloseFile(f);
return "";
}
QString EmuInstance::verifyDSiFirmware()
{
FileHandle* f;
long len;
std::string fwpath = globalCfg.GetString("DSi.FirmwarePath");
f = Platform::OpenLocalFile(fwpath, FileMode::Read);
if (!f) return "DSi firmware was not found or could not be accessed. Check your emu settings.";
if (!Platform::CheckFileWritable(fwpath))
return "DSi firmware is unable to be written to.\nPlease check file/folder write permissions.";
len = FileLength(f);
if (len != 0x20000)
{
// not 128KB
// TODO: check whether those work
CloseFile(f);
return "DSi firmware is not a valid firmware dump.";
}
CloseFile(f);
return "";
}
QString EmuInstance::verifyDSiNAND()
{
FileHandle* f;
long len;
std::string nandpath = globalCfg.GetString("DSi.NANDPath");
f = Platform::OpenLocalFile(nandpath, FileMode::ReadWriteExisting);
if (!f) return "DSi NAND was not found or could not be accessed. Check your emu settings.";
if (!Platform::CheckFileWritable(nandpath))
return "DSi NAND is unable to be written to.\nPlease check file/folder write permissions.";
// TODO: some basic checks
// check that it has the nocash footer, and all
CloseFile(f);
return "";
}
QString EmuInstance::verifySetup()
{
QString res;
bool extbios = globalCfg.GetBool("Emu.ExternalBIOSEnable");
int console = globalCfg.GetInt("Emu.ConsoleType");
if (extbios)
{
res = verifyDSBIOS();
if (!res.isEmpty()) return res;
}
if (console == 1)
{
res = verifyDSiBIOS();
if (!res.isEmpty()) return res;
if (extbios)
{
res = verifyDSiFirmware();
if (!res.isEmpty()) return res;
}
res = verifyDSiNAND();
if (!res.isEmpty()) return res;
}
else
{
if (extbios)
{
res = verifyDSFirmware();
if (!res.isEmpty()) return res;
}
}
return "";
}