mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-10-30 19:23:07 +01:00
RMG-Core: introduce Core*RomHeaderAndSettingsCache() functions
This commit is contained in:
1 parent
9472f41bf4
commit
e00a24ae3e
8 files changed
+356
No files matched your search
@@ -17,6 +17,7 @@ set(RMG_CORE_SOURCES
|
||||
m64p/CoreApi.cpp
|
||||
m64p/ConfigApi.cpp
|
||||
m64p/PluginApi.cpp
|
||||
CachedRomHeaderAndSettings.cpp
|
||||
Settings/Settings.cpp
|
||||
SpeedLimiter.cpp
|
||||
RomSettings.cpp
|
||||
@@ -39,10 +40,12 @@ set(RMG_CORE_SOURCES
|
||||
if (WIN32 OR MSYS)
|
||||
list(APPEND RMG_CORE_SOURCES
|
||||
osal/osal_dynlib_win32.cpp
|
||||
osal/osal_files_win32.cpp
|
||||
)
|
||||
else()
|
||||
list(APPEND RMG_CORE_SOURCES
|
||||
osal/osal_dynlib_unix.cpp
|
||||
osal/osal_files_unix.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "CachedRomHeaderAndSettings.hpp"
|
||||
#include "Directories.hpp"
|
||||
#include "Error.hpp"
|
||||
|
||||
#include "osal/osal_files.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
//
|
||||
// Local Defines
|
||||
//
|
||||
|
||||
#define MAX_FILENAME_LEN 4096
|
||||
#define ROMHEADER_NAME_LEN 20
|
||||
#define GOODNAME_LEN 256
|
||||
#define MD5_LEN 33
|
||||
|
||||
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCache_01"
|
||||
|
||||
//
|
||||
// Local Structures
|
||||
//
|
||||
|
||||
struct l_CacheEntry
|
||||
{
|
||||
std::string fileName;
|
||||
osal_files_file_time fileTime;
|
||||
|
||||
CoreRomHeader header;
|
||||
CoreRomSettings settings;
|
||||
};
|
||||
|
||||
//
|
||||
// Local Variables
|
||||
//
|
||||
|
||||
static bool l_HasReadCache = false;
|
||||
static std::vector<l_CacheEntry> l_CacheEntries;
|
||||
|
||||
//
|
||||
// Internal Functions
|
||||
//
|
||||
|
||||
static std::string get_cache_file_name()
|
||||
{
|
||||
std::string file;
|
||||
|
||||
file = CoreGetUserCacheDirectory();
|
||||
file += OSAL_FILES_DIR_SEPERATOR_STR;
|
||||
file += "RomHeaderAndSettingsCache.cache";
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static std::vector<l_CacheEntry>::iterator get_cache_entry_iter(std::string file, bool checkFileTime = true)
|
||||
{
|
||||
osal_files_file_time fileTime = osal_files_get_file_time(file);
|
||||
|
||||
auto predicate = [file, fileTime, checkFileTime](const auto& entry)
|
||||
{
|
||||
return entry.fileName == file &&
|
||||
(!checkFileTime || entry.fileTime == fileTime);
|
||||
};
|
||||
|
||||
return std::find_if(l_CacheEntries.begin(), l_CacheEntries.end(), predicate);
|
||||
}
|
||||
|
||||
//
|
||||
// Exported Functions
|
||||
//
|
||||
|
||||
void CoreReadRomHeaderAndSettingsCache(void)
|
||||
{
|
||||
std::ifstream inputStream;
|
||||
char magicBuf[sizeof(CACHE_FILE_MAGIC)];
|
||||
char fileNameBuf[MAX_FILENAME_LEN];
|
||||
char headerNameBuf[ROMHEADER_NAME_LEN];
|
||||
char goodNameBuf[GOODNAME_LEN];
|
||||
char md5Buf[MD5_LEN];
|
||||
l_CacheEntry cacheEntry;
|
||||
|
||||
inputStream.open(get_cache_file_name());
|
||||
if (!inputStream.good())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// when magic doesn't match, don't read cache file
|
||||
inputStream.read((char*)magicBuf, sizeof(CACHE_FILE_MAGIC));
|
||||
if (std::string(magicBuf) != std::string(CACHE_FILE_MAGIC))
|
||||
{
|
||||
inputStream.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// read all file entries
|
||||
#define FREAD(x) inputStream.read((char*)&x, sizeof(x))
|
||||
while (!inputStream.eof())
|
||||
{
|
||||
// file info
|
||||
inputStream.read((char*)fileNameBuf, sizeof(fileNameBuf));
|
||||
cacheEntry.fileName = std::string(fileNameBuf);
|
||||
FREAD(cacheEntry.fileTime);
|
||||
// header
|
||||
inputStream.read((char*)headerNameBuf, sizeof(headerNameBuf));
|
||||
cacheEntry.header.Name = std::string(headerNameBuf);
|
||||
FREAD(cacheEntry.header.CRC1);
|
||||
FREAD(cacheEntry.header.CRC2);
|
||||
// (partial) settings
|
||||
inputStream.read((char*)goodNameBuf, sizeof(goodNameBuf));
|
||||
cacheEntry.settings.GoodName = std::string(goodNameBuf);
|
||||
inputStream.read((char*)md5Buf, sizeof(md5Buf));
|
||||
cacheEntry.settings.MD5 = std::string(md5Buf);
|
||||
|
||||
// add to cached entries
|
||||
l_CacheEntries.push_back(cacheEntry);
|
||||
}
|
||||
#undef FREAD
|
||||
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
bool CoreSaveRomHeaderAndSettingsCache(void)
|
||||
{
|
||||
std::ofstream outputStream;
|
||||
char fileNameBuf[MAX_FILENAME_LEN];
|
||||
char headerNameBuf[ROMHEADER_NAME_LEN];
|
||||
char goodNameBuf[GOODNAME_LEN];
|
||||
char md5Buf[MD5_LEN];
|
||||
|
||||
outputStream.open(get_cache_file_name());
|
||||
if (!outputStream.good())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// write magic header
|
||||
outputStream.write((char*)CACHE_FILE_MAGIC, sizeof(CACHE_FILE_MAGIC));
|
||||
|
||||
// write each entry in the file
|
||||
#define FWRITE(x) outputStream.write((char*)&x, sizeof(x))
|
||||
for (const auto& entry : l_CacheEntries)
|
||||
{
|
||||
strncpy(fileNameBuf, entry.fileName.c_str(), MAX_FILENAME_LEN);
|
||||
strncpy(headerNameBuf, entry.header.Name.c_str(), sizeof(headerNameBuf));
|
||||
strncpy(goodNameBuf, entry.settings.GoodName.c_str(), sizeof(goodNameBuf));
|
||||
strncpy(md5Buf, entry.settings.MD5.c_str(), sizeof(md5Buf));
|
||||
|
||||
// file info
|
||||
outputStream.write((char*)fileNameBuf, sizeof(fileNameBuf));
|
||||
FWRITE(entry.fileTime);
|
||||
// header
|
||||
outputStream.write((char*)headerNameBuf, sizeof(headerNameBuf));
|
||||
FWRITE(entry.header.CRC1);
|
||||
FWRITE(entry.header.CRC2);
|
||||
// (partial) settings
|
||||
outputStream.write((char*)goodNameBuf, sizeof(goodNameBuf));
|
||||
outputStream.write((char*)md5Buf, sizeof(md5Buf));
|
||||
}
|
||||
#undef FWRITE
|
||||
|
||||
outputStream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreHasRomHeaderAndSettingsCached(std::string file)
|
||||
{
|
||||
return get_cache_entry_iter(file) != l_CacheEntries.end();
|
||||
}
|
||||
|
||||
bool CoreGetCachedRomHeaderAndSettings(std::string file, CoreRomHeader& header, CoreRomSettings& settings)
|
||||
{
|
||||
auto iter = get_cache_entry_iter(file);
|
||||
if (iter == l_CacheEntries.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
header = (*iter).header;
|
||||
settings = (*iter).settings;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreAddCachedRomHeaderAndSettings(std::string file, CoreRomHeader header, CoreRomSettings settings)
|
||||
{
|
||||
l_CacheEntry cacheEntry;
|
||||
|
||||
// try to find existing entry with same filename,
|
||||
// when found, remove it from the cache
|
||||
auto iter = get_cache_entry_iter(file, false);
|
||||
if (iter != l_CacheEntries.end())
|
||||
{
|
||||
l_CacheEntries.erase(iter);
|
||||
}
|
||||
|
||||
cacheEntry.fileName = file;
|
||||
cacheEntry.fileTime = osal_files_get_file_time(file);
|
||||
cacheEntry.header = header;
|
||||
cacheEntry.settings = settings;
|
||||
|
||||
l_CacheEntries.push_back(cacheEntry);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CORE_CACHEDROMHEADERANDSETTINGS_HPP
|
||||
#define CORE_CACHEDROMHEADERANDSETTINGS_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "RomHeader.hpp"
|
||||
#include "RomSettings.hpp"
|
||||
|
||||
#ifdef CORE_INTERNAL
|
||||
// attempts to read rom header & settings cache
|
||||
void CoreReadRomHeaderAndSettingsCache(void);
|
||||
|
||||
// returns whether saving the rom header & settings cache
|
||||
// succeeds
|
||||
bool CoreSaveRomHeaderAndSettingsCache(void);
|
||||
#endif // CORE_INTERNAL
|
||||
|
||||
// returns whether rom header & settings have been cached
|
||||
// for given filename
|
||||
bool CoreHasRomHeaderAndSettingsCached(std::string file);
|
||||
|
||||
// returns whether retrieving the rom header & settings
|
||||
// for given filename succeeds
|
||||
bool CoreGetCachedRomHeaderAndSettings(std::string file, CoreRomHeader& header, CoreRomSettings& settings);
|
||||
|
||||
// returns whether adding cached rom header & settings
|
||||
// for given filename succeeds
|
||||
bool CoreAddCachedRomHeaderAndSettings(std::string file, CoreRomHeader header, CoreRomSettings settings);
|
||||
|
||||
#endif // CORE_CACHEDROMHEADERANDSETTINGS_HPP
|
||||
@@ -144,6 +144,8 @@ bool CoreInit(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
CoreReadRomHeaderAndSettingsCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -175,5 +177,7 @@ void CoreShutdown(void)
|
||||
{
|
||||
CorePluginsShutdown();
|
||||
|
||||
CoreSaveRomHeaderAndSettingsCache();
|
||||
|
||||
osal_dynlib_close(l_CoreLibHandle);
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
#ifndef CORE_HPP
|
||||
#define CORE_HPP
|
||||
|
||||
#include "CachedRomHeaderAndSettings.hpp"
|
||||
#include "Settings/Settings.hpp"
|
||||
#include "SpeedLimiter.hpp"
|
||||
#include "RomSettings.hpp"
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef OSAL_FILES_HPP
|
||||
#define OSAL_FILES_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef uint64_t osal_files_file_time;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define OSAL_FILES_DIR_SEPERATOR_STR "\\"
|
||||
#else // Unix
|
||||
#define OSAL_FILES_DIR_SEPERATOR_STR "/"
|
||||
#endif // _WIN32
|
||||
|
||||
// returns file time for given file,
|
||||
// returns -1 on failure
|
||||
osal_files_file_time osal_files_get_file_time(std::string file);
|
||||
|
||||
#endif // OSAL_FILES_HPP
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "osal_files.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
osal_files_file_time osal_files_get_file_time(std::string file)
|
||||
{
|
||||
int ret;
|
||||
struct stat file_stat;
|
||||
|
||||
ret = stat(file.c_str(), &file_stat);
|
||||
if (ret != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return file_stat.st_mtime;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "osal_files.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
#include <fileapi.h>
|
||||
|
||||
osal_files_file_time osal_files_get_file_time(std::string file)
|
||||
{
|
||||
BOOL ret;
|
||||
HANDLE file_handle;
|
||||
FILETIME file_time;
|
||||
|
||||
file_handle = CreateFileA(file.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = GetFileTime(file_handle, nullptr, nullptr, &file_time);
|
||||
if (ret != TRUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = CloseHandle(file_handle);
|
||||
if (ret != TRUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// this is probably incorrect but it doesn't matter
|
||||
// for our use-case
|
||||
return file_time.dwLowDateTime + file_time.dwHighDateTime;
|
||||
}
|
||||
Reference in new issue
Block a user