diff --git a/Core/Config.cpp b/Core/Config.cpp index 6343ac63b2..a707a4e9e9 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -295,6 +295,7 @@ static ConfigSetting generalSettings[] = { // "default" means let emulator decide, "" means disable. ConfigSetting("ReportingHost", &g_Config.sReportHost, "default"), ConfigSetting("AutoSaveSymbolMap", &g_Config.bAutoSaveSymbolMap, false), + ConfigSetting("CacheFullIsoInRam", &g_Config.bCacheFullIsoInRam, false), #ifdef ANDROID ConfigSetting("ScreenRotation", &g_Config.iScreenRotation, 1), diff --git a/Core/Config.h b/Core/Config.h index dc32fe6596..f271bb5d51 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -112,6 +112,7 @@ public: bool bAtomicAudioLocks; int iLockedCPUSpeed; bool bAutoSaveSymbolMap; + bool bCacheFullIsoInRam; int iScreenRotation; std::string sReportHost; diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp index 407f8fe027..a3005d5357 100644 --- a/Core/FileSystems/BlockDevices.cpp +++ b/Core/FileSystems/BlockDevices.cpp @@ -44,6 +44,20 @@ BlockDevice *constructBlockDevice(const char *filename) { return new FileBlockDevice(f); } +RAMBlockDevice::RAMBlockDevice(BlockDevice *device) { + totalBlocks_ = device->GetNumBlocks(); + u32 blockSize = GetBlockSize(); + image_ = new u8[totalBlocks_ * blockSize]; + for (int i = 0; i < totalBlocks_; i++) { + device->ReadBlock(i, image_ + i * blockSize); + } + delete device; +} + +RAMBlockDevice::~RAMBlockDevice() { + delete[] image_; +} + // Android NDK does not support 64-bit file I/O using C streams // so we fall back onto syscalls diff --git a/Core/FileSystems/BlockDevices.h b/Core/FileSystems/BlockDevices.h index b167340d7b..b188b088f3 100644 --- a/Core/FileSystems/BlockDevices.h +++ b/Core/FileSystems/BlockDevices.h @@ -63,8 +63,8 @@ class FileBlockDevice : public BlockDevice public: FileBlockDevice(FILE *file); ~FileBlockDevice(); - bool ReadBlock(int blockNumber, u8 *outPtr); - u32 GetNumBlocks() {return (u32)(filesize / GetBlockSize());} + bool ReadBlock(int blockNumber, u8 *outPtr) override; + u32 GetNumBlocks() override {return (u32)(filesize / GetBlockSize());} private: #ifdef ANDROID @@ -91,8 +91,8 @@ public: NPDRMDemoBlockDevice(FILE *file); ~NPDRMDemoBlockDevice(); - bool ReadBlock(int blockNumber, u8 *outPtr); - u32 GetNumBlocks() {return (u32)lbaSize;} + bool ReadBlock(int blockNumber, u8 *outPtr) override; + u32 GetNumBlocks() override {return (u32)lbaSize;} private: FILE *f; @@ -112,5 +112,31 @@ private: u8 *tempBuf; }; +// This simply fully reads another block device and caches it in RAM. +// A bit slow to initialize. +class RAMBlockDevice : public BlockDevice +{ +public: + RAMBlockDevice(BlockDevice *device); + ~RAMBlockDevice(); + + bool ReadBlock(int blockNumber, u8 *outPtr) override { + if (blockNumber >= 0 && blockNumber < totalBlocks_) { + u32 blockSize = GetBlockSize(); + memcpy(outPtr, image_ + blockSize * blockNumber, blockSize); + return true; + } + return false; + } + + u32 GetNumBlocks() override { + return totalBlocks_; + } + +private: + int totalBlocks_; + u8 *image_; +}; + BlockDevice *constructBlockDevice(const char *filename); diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 75040cd312..ac0b5b205b 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -71,6 +71,12 @@ void InitMemoryForGameISO(std::string fileToStart) { // Can't init anything without a block device... if (!bd) return; + + if (g_Config.bCacheFullIsoInRam) { + // The constructor destroys the original block device object after reading it. + bd = new RAMBlockDevice(bd); + } + umd2 = new ISOFileSystem(&pspFileSystem, bd); actualIso = true; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index ca92f75619..91b714a50d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -391,6 +391,10 @@ void GameSettingsScreen::CreateViews() { systemSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, s->T("Enable Windows native keyboard", "Enable Windows native keyboard"))); #endif +#if defined(_M_X64) + systemSettings->Add(new CheckBox(&g_Config.bCacheFullIsoInRam, s->T("Cache ISO in RAM", "Cache full ISO in RAM (slow startup)"))); +#endif + systemSettings->Add(new ItemHeader(s->T("Developer Tools"))); systemSettings->Add(new Choice(s->T("Developer Tools")))->OnClick.Handle(this, &GameSettingsScreen::OnDeveloperTools);