Add feature to cache ISOs in RAM to avoid I/O stutters. 64-bit only. Loading gets slow though.

TODO: Make it cache in the background on load. Allow on 32-bit for small ISOs.
This commit is contained in:
Henrik Rydgard 2014-10-31 00:14:00 +01:00
parent 0df4afce67
commit 291e5e53c0
6 changed files with 56 additions and 4 deletions

View file

@ -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),

View file

@ -112,6 +112,7 @@ public:
bool bAtomicAudioLocks;
int iLockedCPUSpeed;
bool bAutoSaveSymbolMap;
bool bCacheFullIsoInRam;
int iScreenRotation;
std::string sReportHost;

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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);