Savestates: Allow saving/loading to arbitrary files
This commit is contained in:
parent
31502f6c16
commit
150d2eaec9
21 changed files with 191 additions and 55 deletions
|
@ -173,19 +173,24 @@ bool Console::LoadROM(string romName, HashInfo hashInfo)
|
|||
}
|
||||
}
|
||||
|
||||
string lcRomname = romName;
|
||||
std::transform(lcRomname.begin(), lcRomname.end(), lcRomname.begin(), ::tolower);
|
||||
std::unordered_set<string> validExtensions = { { ".nes", ".fds", "*.unif", "*.unif", "*.nsf", "*.nsfe", "*.7z", "*.zip" } };
|
||||
vector<string> romFiles;
|
||||
for(string folder : FolderUtilities::GetKnownGameFolders()) {
|
||||
string match = RomLoader::FindMatchingRomInFolder(folder, romName, hashInfo, true);
|
||||
if(!match.empty()) {
|
||||
return Console::LoadROM(match);
|
||||
}
|
||||
vector<string> files = FolderUtilities::GetFilesInFolder(folder, validExtensions, true);
|
||||
romFiles.insert(romFiles.end(), files.begin(), files.end());
|
||||
}
|
||||
|
||||
string match = RomLoader::FindMatchingRom(romFiles, romName, hashInfo, true);
|
||||
if(!match.empty()) {
|
||||
return Console::LoadROM(match);
|
||||
}
|
||||
|
||||
//Perform slow CRC32 search for ROM
|
||||
for(string folder : FolderUtilities::GetKnownGameFolders()) {
|
||||
string match = RomLoader::FindMatchingRomInFolder(folder, romName, hashInfo, false);
|
||||
if(!match.empty()) {
|
||||
return Console::LoadROM(match);
|
||||
}
|
||||
match = RomLoader::FindMatchingRom(romFiles, romName, hashInfo, false);
|
||||
if(!match.empty()) {
|
||||
return Console::LoadROM(match);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -501,7 +501,7 @@ int LuaApi::LoadSavestate(lua_State *lua)
|
|||
checkstartframe();
|
||||
stringstream ss;
|
||||
ss << savestate;
|
||||
l.Return(SaveStateManager::LoadState(ss));
|
||||
l.Return(SaveStateManager::LoadState(ss, true));
|
||||
return l.ReturnCount();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ std::unordered_map<string, string> MessageManager::_enResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"State #%1 is incompatible with this version of Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Invalid save state file." },
|
||||
{ "SaveStateLoaded", u8"State #%1 loaded." },
|
||||
{ "SaveStateMissingRom", u8"Missing ROM required (%1) to load save state." },
|
||||
{ "SaveStateNewerVersion", u8"Cannot load save states created by a more recent version of Mesen. Please download the latest version." },
|
||||
{ "SaveStateSaved", u8"State #%1 saved." },
|
||||
{ "SaveStateSlotSelected", u8"Slot #%1 selected." },
|
||||
|
@ -123,6 +124,7 @@ std::unordered_map<string, string> MessageManager::_frResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"La sauvegarde #%1 est incompatible avec cette version de Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Fichier de sauvegarde invalide ou corrompu." },
|
||||
{ "SaveStateLoaded", u8"Sauvegarde #%1 chargée." },
|
||||
{ "SaveStateMissingRom", u8"Le rom (%1) correspondant à la sauvegarde rapide sélectionnée est introuvable." },
|
||||
{ "SaveStateNewerVersion", u8"Impossible de charger une sauvegarde qui a été créée avec une version plus récente de Mesen. Veuillez mettre à jour Mesen." },
|
||||
{ "SaveStateSaved", u8"Sauvegarde #%1 sauvegardée." },
|
||||
{ "SaveStateSlotSelected", u8"Position de sauvegarde #%1 choisie." },
|
||||
|
@ -192,6 +194,7 @@ std::unordered_map<string, string> MessageManager::_jaResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"クイックセーブ%1は古いMesenのバージョンで作られたもので、ロードできませんでした。" },
|
||||
{ "SaveStateInvalidFile", u8"クイックセーブデータを読めませんでした。" },
|
||||
{ "SaveStateLoaded", u8"クイックセーブ%1をロードしました。" },
|
||||
{ "SaveStateMissingRom", u8"クイックセーブデータをロードするためのゲームファイルを見つかりませんでした。(%1)" },
|
||||
{ "SaveStateNewerVersion", u8"クイックセーブデータは使用中のMesenより新しいバージョンで作られたため、ロードできません。 Mesenのサイトで最新のバージョンをダウンロードしてください。" },
|
||||
{ "SaveStateSaved", u8"クイックセーブ%1をセーブしました。" },
|
||||
{ "SaveStateSlotSelected", u8"クイックセーブスロット%1。" },
|
||||
|
@ -261,6 +264,7 @@ std::unordered_map<string, string> MessageManager::_ruResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"Сохранение #%1 несовместимо с вашей версией Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Некорректное сохранение." },
|
||||
{ "SaveStateLoaded", u8"Сохранение #%1 загружено." },
|
||||
{ "SaveStateMissingRom", u8"Missing ROM required (%1) to load save state." },
|
||||
{ "SaveStateNewerVersion", u8"Сохранение создано в более новой версии Mesen. Пожалуйста загрузите последнюю версию." },
|
||||
{ "SaveStateSaved", u8"Сохранено в #%1 слот." },
|
||||
{ "ScanlineTimingWarning", u8"Тайминг PPU был изменён." },
|
||||
|
@ -330,9 +334,10 @@ std::unordered_map<string, string> MessageManager::_esResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"Partida guardada #%1 incompatible con esta versión de Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Partida guardada no válida." },
|
||||
{ "SaveStateLoaded", u8"Partida #%1 cargada." },
|
||||
{ "SaveStateMissingRom", u8"Missing ROM required (%1) to load save state." },
|
||||
{ "SaveStateNewerVersion", u8"No se puede cargar una partida creada con una versión mas reciente de Mesen. Por favor descargue la última versión." },
|
||||
{ "SaveStateSaved", u8"Partida #%1 guardada." },
|
||||
{ "SaveStateSlotSelected", u8"Espacio de guardado #%1 elegido." },
|
||||
{ "SaveStateSlotSelected", u8"Espacio de guardado #%1 elegido." },
|
||||
{ "ScanlineTimingWarning", u8"El timing de PPU ha sido cambiado." },
|
||||
{ "ServerStarted", u8"Servidor iniciado (Puerto: %1)" },
|
||||
{ "ServerStopped", u8"Servidor detenido" },
|
||||
|
@ -400,6 +405,7 @@ std::unordered_map<string, string> MessageManager::_ukResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"Збереження #%1 несумісне з вашою версією Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Некоректне збереження." },
|
||||
{ "SaveStateLoaded", u8"Збереження #%1 завантажено." },
|
||||
{ "SaveStateMissingRom", u8"Missing ROM required (%1) to load save state." },
|
||||
{ "SaveStateNewerVersion", u8"Збереження створено в більш нової версії Mesen. Будь ласка завантажте останню версію." },
|
||||
{ "SaveStateSaved", u8"Збережено в #%1 слот." },
|
||||
{ "ScanlineTimingWarning", u8"Таймiнг PPU був змінений." },
|
||||
|
@ -469,6 +475,7 @@ std::unordered_map<string, string> MessageManager::_ptResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"Save State #%1 incompatível com esta versão de Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Save State inválido." },
|
||||
{ "SaveStateLoaded", u8"Save State #%1 carregado." },
|
||||
{ "SaveStateMissingRom", u8"Missing ROM required (%1) to load save state." },
|
||||
{ "SaveStateNewerVersion", u8"Não se pode carregar um save state com uma versão mais recente de Mesen. Por favor baixe a última versão." },
|
||||
{ "SaveStateSaved", u8"Save State #%1 salvo." },
|
||||
{ "SaveStateSlotSelected", u8"Slot do Save State #%1 elegido." },
|
||||
|
@ -538,6 +545,7 @@ std::unordered_map<string, string> MessageManager::_caResources = {
|
|||
{ "SaveStateIncompatibleVersion", u8"La partida guardada nº%1 és incompatible amb aquesta versió de Mesen." },
|
||||
{ "SaveStateInvalidFile", u8"Fitxer de partida guardada invàlid." },
|
||||
{ "SaveStateLoaded", u8"Partida guardada nº%1 carregada." },
|
||||
{ "SaveStateMissingRom", u8"Missing ROM required (%1) to load save state." },
|
||||
{ "SaveStateNewerVersion", u8"Incapaç de carregar partides guardades creades per una versió més recent de Mesen. Si us plau, descarregueu-vos la darrera versió de Mesen." },
|
||||
{ "SaveStateSaved", u8"Partida guardada nº%1 desada." },
|
||||
{ "SaveStateSlotSelected", u8"Partida guardada nº%1 seleccionada." },
|
||||
|
|
|
@ -119,12 +119,8 @@ string RomLoader::FindMatchingRomInFile(string filePath, HashInfo hashInfo)
|
|||
return "";
|
||||
}
|
||||
|
||||
string RomLoader::FindMatchingRomInFolder(string folder, string romFilename, HashInfo hashInfo, bool useFastSearch)
|
||||
string RomLoader::FindMatchingRom(vector<string> romFiles, string romFilename, HashInfo hashInfo, bool useFastSearch)
|
||||
{
|
||||
std::transform(romFilename.begin(), romFilename.end(), romFilename.begin(), ::tolower);
|
||||
std::unordered_set<string> validExtensions = { { ".nes", ".fds", "*.unif", "*.unif", "*.nsf", "*.nsfe", "*.7z", "*.zip" } };
|
||||
vector<string> romFiles = FolderUtilities::GetFilesInFolder(folder, validExtensions, true);
|
||||
|
||||
if(useFastSearch) {
|
||||
for(string romFile : romFiles) {
|
||||
//Quick search by filename
|
||||
|
|
|
@ -17,5 +17,5 @@ class RomLoader
|
|||
bool LoadFile(string filename, vector<uint8_t> &fileData);
|
||||
|
||||
RomData GetRomData();
|
||||
static string FindMatchingRomInFolder(string folder, string romFilename, HashInfo hashInfo, bool useFastSearch);
|
||||
static string FindMatchingRom(vector<string> romFiles, string romFilename, HashInfo hashInfo, bool useFastSearch);
|
||||
};
|
||||
|
|
|
@ -61,27 +61,42 @@ void SaveStateManager::SaveState(ostream &stream)
|
|||
stream.write((char*)&emuVersion, sizeof(emuVersion));
|
||||
stream.write((char*)&SaveStateManager::FileFormatVersion, sizeof(uint32_t));
|
||||
|
||||
string sha1Hash = Console::GetHashInfo().Sha1Hash;
|
||||
stream.write(sha1Hash.c_str(), sha1Hash.size());
|
||||
|
||||
string romName = Console::GetRomName();
|
||||
uint32_t nameLength = (uint32_t)romName.size();
|
||||
stream.write((char*)&nameLength, sizeof(uint32_t));
|
||||
stream.write(romName.c_str(), romName.size());
|
||||
|
||||
Console::SaveState(stream);
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
bool SaveStateManager::SaveState(string filepath)
|
||||
{
|
||||
ofstream file(filepath, ios::out | ios::binary);
|
||||
|
||||
if(file) {
|
||||
SaveState(file);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SaveStateManager::SaveState(int stateIndex, bool displayMessage)
|
||||
{
|
||||
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
||||
ofstream file(filepath, ios::out | ios::binary);
|
||||
|
||||
if(file) {
|
||||
if(SaveState(filepath)) {
|
||||
_lastIndex = stateIndex;
|
||||
SaveState(file);
|
||||
file.close();
|
||||
|
||||
if(displayMessage) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateSaved", std::to_string(stateIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState(istream &stream)
|
||||
bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
|
||||
{
|
||||
char header[3];
|
||||
stream.read(header, 3);
|
||||
|
@ -95,9 +110,35 @@ bool SaveStateManager::LoadState(istream &stream)
|
|||
}
|
||||
|
||||
stream.read((char*)&fileFormatVersion, sizeof(fileFormatVersion));
|
||||
if(fileFormatVersion != SaveStateManager::FileFormatVersion) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion"); // , std::to_string(stateIndex));
|
||||
if(fileFormatVersion < 5) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion");
|
||||
return false;
|
||||
} else if(fileFormatVersion == 5) {
|
||||
//No SHA1 field in version 5
|
||||
if(hashCheckRequired) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
char hash[41] = {};
|
||||
stream.read(hash, 40);
|
||||
|
||||
uint32_t nameLength = 0;
|
||||
stream.read((char*)&nameLength, sizeof(uint32_t));
|
||||
|
||||
vector<char> nameBuffer(nameLength);
|
||||
stream.read(nameBuffer.data(), nameBuffer.size());
|
||||
string romName(nameBuffer.data());
|
||||
|
||||
if(Console::GetHashInfo().Sha1Hash != string(hash)) {
|
||||
//Wrong game
|
||||
HashInfo info;
|
||||
info.Sha1Hash = hash;
|
||||
if(!Console::LoadROM(romName, info)) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateMissingRom", romName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console::Pause();
|
||||
|
@ -106,32 +147,36 @@ bool SaveStateManager::LoadState(istream &stream)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateInvalidFile");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState(string filepath, bool hashCheckRequired)
|
||||
{
|
||||
ifstream file(filepath, ios::in | ios::binary);
|
||||
bool result = false;
|
||||
|
||||
if(file.good()) {
|
||||
if(LoadState(file, hashCheckRequired)) {
|
||||
result = true;
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateEmpty");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState(int stateIndex)
|
||||
{
|
||||
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
||||
ifstream file(filepath, ios::in | ios::binary);
|
||||
bool result = false;
|
||||
|
||||
if(file) {
|
||||
if(LoadState(file)) {
|
||||
_lastIndex = stateIndex;
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateLoaded", std::to_string(stateIndex));
|
||||
result = true;
|
||||
} else {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateInvalidFile");
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateEmpty");
|
||||
if(LoadState(filepath, true)) {
|
||||
_lastIndex = stateIndex;
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateLoaded", std::to_string(stateIndex));
|
||||
return true;
|
||||
}
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath)
|
||||
|
@ -173,7 +218,7 @@ void SaveStateManager::LoadRecentGame(string filename, bool resetGame)
|
|||
try {
|
||||
Console::LoadROM(romPath, patchPath);
|
||||
if(!resetGame) {
|
||||
SaveStateManager::LoadState(stateStream);
|
||||
SaveStateManager::LoadState(stateStream, false);
|
||||
}
|
||||
} catch(std::exception ex) {
|
||||
Console::GetInstance()->Stop();
|
||||
|
|
|
@ -11,7 +11,7 @@ private:
|
|||
static string GetStateFilepath(int stateIndex);
|
||||
|
||||
public:
|
||||
static const uint32_t FileFormatVersion = 5;
|
||||
static const uint32_t FileFormatVersion = 6;
|
||||
|
||||
static uint64_t GetStateInfo(int stateIndex);
|
||||
|
||||
|
@ -19,8 +19,10 @@ public:
|
|||
static bool LoadState();
|
||||
|
||||
static void SaveState(ostream &stream);
|
||||
static bool SaveState(string filepath);
|
||||
static void SaveState(int stateIndex, bool displayMessage = true);
|
||||
static bool LoadState(istream &stream);
|
||||
static bool LoadState(istream &stream, bool hashCheckRequired = true);
|
||||
static bool LoadState(string filepath, bool hashCheckRequired = true);
|
||||
static bool LoadState(int stateIndex);
|
||||
|
||||
static void SaveRecentGame(string romName, string romPath, string patchPath);
|
||||
|
|
2
GUI.NET/Debugger/frmDebugger.Designer.cs
generated
2
GUI.NET/Debugger/frmDebugger.Designer.cs
generated
|
@ -1160,7 +1160,7 @@ namespace Mesen.GUI.Debugger
|
|||
//
|
||||
this.mnuTraceLogger.Image = global::Mesen.GUI.Properties.Resources.LogWindow;
|
||||
this.mnuTraceLogger.Name = "mnuTraceLogger";
|
||||
this.mnuTraceLogger.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L)));
|
||||
this.mnuTraceLogger.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
|
||||
this.mnuTraceLogger.Size = new System.Drawing.Size(196, 22);
|
||||
this.mnuTraceLogger.Text = "Trace Logger";
|
||||
this.mnuTraceLogger.Click += new System.EventHandler(this.mnuTraceLogger_Click);
|
||||
|
|
|
@ -586,6 +586,10 @@
|
|||
<Message ID="FilterRomIps">Tots els formats suportats (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Fitxers NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Arxius comprimits (*.zip)|*.ZIP|Arxius 7-Zip (*.7z)|*.7z|Pedaços IPS/UPS/BPS (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|Tots els fitxers (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Fitxers de proves (*.mtp)|*.mtp|Tots els fitxers (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">Tots els formats suportats (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesen Savestates (*.mst)|*.mst|Tots els fitxers (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Load from file...</Message>
|
||||
<Message ID="SaveToFile">Save to file...</Message>
|
||||
|
||||
<Message ID="Resume">Continua</Message>
|
||||
<Message ID="Pause">Pausa</Message>
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
<Message ID="FilterRomIps">All supported formats (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS/UPS/BPS Patches (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|All (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Test files (*.mtp)|*.mtp|All (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">All supported formats (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesen Savestates (*.mst)|*.mst|All files (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Load from file...</Message>
|
||||
<Message ID="SaveToFile">Save to file...</Message>
|
||||
|
||||
<Message ID="Resume">Resume</Message>
|
||||
<Message ID="Pause">Pause</Message>
|
||||
|
|
|
@ -620,6 +620,10 @@
|
|||
<Message ID="FilterRomIps">Todos los formatos soportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Archivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Archivos ZIP (*.zip)|*.ZIP|Archivos 7-Zip (*.7z)|*.7z|Archivos IPS/UPS/BPS (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|Todos los archivos (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Archivos de test (*.mtp)|*.mtp|Todos los archivos (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">Todos los formatos soportados (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesen Savestates (*.mst)|*.mst|Todos los archivos (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Load from file...</Message>
|
||||
<Message ID="SaveToFile">Save to file...</Message>
|
||||
|
||||
<Message ID="Resume">Continuar</Message>
|
||||
<Message ID="Pause">Pausa</Message>
|
||||
|
|
|
@ -634,7 +634,11 @@
|
|||
<Message ID="FilterRomIps">Tous les formats supportés (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES (*.nes, *.unf)|*.NES;*.UNF|Roms du Famicom Disk System (*.fds)|*.FDS|Fichiers NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Fichiers ZIP (*.zip)|*.ZIP|Fichiers 7-Zip (*.7z)|*.7z|Fichiers IPS/UPS/BPS (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|Tous les fichiers (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Fichiers de test (*.mtp)|*.mtp|Tous les fichiers (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">Tous les formats supportés (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Sauvegardes d'états Mesen (*.mst)|*.mst|Tous les fichiers (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Charger à partir d'un fichier...</Message>
|
||||
<Message ID="SaveToFile">Sauvegarder dans un fichier...</Message>
|
||||
|
||||
<Message ID="Resume">Continuer</Message>
|
||||
<Message ID="Pause">Pause</Message>
|
||||
<Message ID="StartServer">Démarrer serveur</Message>
|
||||
|
|
|
@ -617,6 +617,10 @@
|
|||
<Message ID="FilterRomIps">対応するすべてのファイル (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|ファミコンゲーム (*.nes, *.unf)|*.NES;*.UNF|ファミコンディスクシステムのゲーム (*.fds)|*.FDS|NSFファイル (*.nsf, *.nsfe)|*.NSF;*.NSFE|ZIPファイル (*.zip)|*.ZIP|7-Zipファイル (*.7z)|*.7z|パッチファイル (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|すべてのファイル (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">テストファイル (*.mtp)|*.mtp|すべてのファイル (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">対応するすべてのファイル (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesenのクイックセーブデータ (*.mst)|*.mst|すべてのファイル (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">ファイルからロードする…</Message>
|
||||
<Message ID="SaveToFile">ファイルに保存する…</Message>
|
||||
|
||||
<Message ID="Resume">再開</Message>
|
||||
<Message ID="Pause">ポーズ</Message>
|
||||
|
|
|
@ -620,6 +620,10 @@
|
|||
<Message ID="FilterRomIps">Todos os formatos suportados (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|Roms de NES(*.nes, *.unf)|*.NES;*.UNF|Roms de Famicom Disk System (*.fds)|*.FDS|Arquivos NSF (*.nsf, *.nsfe)|*.NSF;*.NSFE|Arquivos ZIP (*.zip)|*.ZIP|Arquivos 7-Zip (*.7z)|*.7z|Arquivos IPS/UPS/BPS (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|Todos os arquivos (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Arquivos de teste (*.mtp)|*.mtp|Todos os arquivos (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">Todos os formatos suportados (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesen Savestates (*.mst)|*.mst|Todos os arquivos (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Load from file...</Message>
|
||||
<Message ID="SaveToFile">Save to file...</Message>
|
||||
|
||||
<Message ID="Resume">Continuar</Message>
|
||||
<Message ID="Pause">Pausar</Message>
|
||||
|
|
|
@ -624,7 +624,11 @@
|
|||
<Message ID="FilterRomIps">Все поддерживаемые форматы (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS/UPS/BPS Patches (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|All (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Test files (*.mtp)|*.mtp|All (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">Все поддерживаемые форматы (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesen Savestates (*.mst)|*.mst|All Files (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Load from file...</Message>
|
||||
<Message ID="SaveToFile">Save to file...</Message>
|
||||
|
||||
<Message ID="Resume">Продолжить</Message>
|
||||
<Message ID="Pause">Пауза</Message>
|
||||
<Message ID="StartServer">Запустить сервер</Message>
|
||||
|
|
|
@ -624,7 +624,11 @@
|
|||
<Message ID="FilterRomIps">Всі підтримувані формати (*.nes, *.zip, *.7z, *.fds, *.nsf, *.nsfe, *.unf, *.ips, *.bps, *.ups)|*.NES;*.ZIP;*.7z;*.IPS;*.BPS;*.UPS;*.FDS;*.NSF;*.NSFE;*.UNF|NES Roms (*.nes, *.unf)|*.NES;*.UNF|Famicom Disk System Roms (*.fds)|*.FDS|NSF files (*.nsf, *.nsfe)|*.nsf;*.nsfe|ZIP Archives (*.zip)|*.ZIP|7-Zip Archives (*.7z)|*.7z|IPS/UPS/BPS Patches (*.ips, *.bps, *.ups)|*.IPS;*.BPS;*.UPS|All (*.*)|*.*</Message>
|
||||
<Message ID="FilterTest">Test files (*.mtp)|*.mtp|All (*.*)|*.*</Message>
|
||||
<Message ID="FilterCheat">Всі підтримувані формати (*.cht, *.xml)|*.cht;*.xml</Message>
|
||||
<Message ID="FilterSavestate">Mesen Savestates (*.mst)|*.mst|All Files (*.*)|*.*</Message>
|
||||
|
||||
<Message ID="LoadFromFile">Load from file...</Message>
|
||||
<Message ID="SaveToFile">Save to file...</Message>
|
||||
|
||||
<Message ID="Resume">Продовжити</Message>
|
||||
<Message ID="Pause">Пауза</Message>
|
||||
<Message ID="StartServer">Запустити сервер</Message>
|
||||
|
|
2
GUI.NET/Forms/frmMain.Designer.cs
generated
2
GUI.NET/Forms/frmMain.Designer.cs
generated
|
@ -1507,7 +1507,7 @@ namespace Mesen.GUI.Forms
|
|||
//
|
||||
this.mnuTraceLogger.Image = global::Mesen.GUI.Properties.Resources.LogWindow;
|
||||
this.mnuTraceLogger.Name = "mnuTraceLogger";
|
||||
this.mnuTraceLogger.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L)));
|
||||
this.mnuTraceLogger.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
|
||||
this.mnuTraceLogger.Size = new System.Drawing.Size(196, 22);
|
||||
this.mnuTraceLogger.Text = "Trace Logger";
|
||||
this.mnuTraceLogger.Click += new System.EventHandler(this.mnuTraceLogger_Click);
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Properties;
|
||||
|
||||
namespace Mesen.GUI.Forms
|
||||
{
|
||||
|
@ -58,10 +59,48 @@ namespace Mesen.GUI.Forms
|
|||
if(!forSave) {
|
||||
menu.DropDownItems.Add("-");
|
||||
addSaveStateInfo(NumberOfSaveSlots+1);
|
||||
menu.DropDownItems.Add("-");
|
||||
ToolStripMenuItem loadFromFile = new ToolStripMenuItem(ResourceHelper.GetMessage("LoadFromFile"), Resources.FolderOpen);
|
||||
loadFromFile.ShortcutKeys = Keys.Control | Keys.L;
|
||||
loadFromFile.Click += LoadFromFile_Click;
|
||||
menu.DropDownItems.Add(loadFromFile);
|
||||
} else {
|
||||
menu.DropDownItems.Add("-");
|
||||
ToolStripMenuItem saveToFile = new ToolStripMenuItem(ResourceHelper.GetMessage("SaveToFile"), Resources.Floppy);
|
||||
saveToFile.ShortcutKeys = Keys.Control | Keys.S;
|
||||
saveToFile.Click += SaveToFile_Click;
|
||||
menu.DropDownItems.Add(saveToFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void LoadFromFile_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(_emuThread != null) {
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(ofd.ShowDialog() == DialogResult.OK) {
|
||||
InteropEmu.LoadStateFile(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveToFile_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(_emuThread != null) {
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".mst";
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(sfd.ShowDialog() == DialogResult.OK) {
|
||||
InteropEmu.SaveStateFile(sfd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuExit_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
|
|
|
@ -113,6 +113,8 @@ namespace Mesen.GUI
|
|||
|
||||
[DllImport(DLLPath)] public static extern void SaveState(UInt32 stateIndex);
|
||||
[DllImport(DLLPath)] public static extern void LoadState(UInt32 stateIndex);
|
||||
[DllImport(DLLPath)] public static extern void SaveStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath);
|
||||
[DllImport(DLLPath)] public static extern void LoadStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filepath);
|
||||
[DllImport(DLLPath)] public static extern Int64 GetStateInfo(UInt32 stateIndex);
|
||||
|
||||
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsNsf();
|
||||
|
|
|
@ -312,7 +312,9 @@ namespace InteropEmu {
|
|||
}
|
||||
|
||||
DllExport void __stdcall SaveState(uint32_t stateIndex) { SaveStateManager::SaveState(stateIndex); }
|
||||
DllExport uint32_t __stdcall LoadState(uint32_t stateIndex) { return SaveStateManager::LoadState(stateIndex); }
|
||||
DllExport void __stdcall LoadState(uint32_t stateIndex) { SaveStateManager::LoadState(stateIndex); }
|
||||
DllExport void __stdcall SaveStateFile(char* filepath) { SaveStateManager::SaveState(filepath); }
|
||||
DllExport void __stdcall LoadStateFile(char* filepath) { SaveStateManager::LoadState(filepath); }
|
||||
DllExport int64_t __stdcall GetStateInfo(uint32_t stateIndex) { return SaveStateManager::GetStateInfo(stateIndex); }
|
||||
|
||||
DllExport void __stdcall MoviePlay(char* filename) { MovieManager::Play(filename); }
|
||||
|
|
|
@ -37,7 +37,7 @@ void FolderUtilities::AddKnownGameFolder(string gameFolder)
|
|||
|
||||
for(string folder : _gameFolders) {
|
||||
std::transform(folder.begin(), folder.end(), folder.begin(), ::tolower);
|
||||
if(folder.compare(gameFolder) == 0) {
|
||||
if(folder.compare(lowerCaseFolder) == 0) {
|
||||
alreadyExists = true;
|
||||
break;
|
||||
}
|
||||
|
@ -131,8 +131,13 @@ vector<string> FolderUtilities::GetFolders(string rootFolder)
|
|||
}
|
||||
|
||||
for(fs::recursive_directory_iterator i(fs::u8path(rootFolder)), end; i != end; i++) {
|
||||
if(fs::is_directory(i->path())) {
|
||||
folders.push_back(i->path().u8string());
|
||||
if(i.depth() > 1) {
|
||||
//Prevent excessive recursion
|
||||
i.disable_recursion_pending();
|
||||
} else {
|
||||
if(fs::is_directory(i->path())) {
|
||||
folders.push_back(i->path().u8string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue