Consistently use FileLoader for standard ISOs.

This commit is contained in:
Unknown W. Brackets 2014-11-23 13:59:56 -08:00
parent 102b7b03fa
commit 967b589778
10 changed files with 90 additions and 126 deletions

View File

@ -31,9 +31,11 @@ enum GPUCore {
GPU_DIRECTX9,
};
class FileLoader;
// PSP_CoreParameter()
struct CoreParameter {
CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true), freezeNext(false), frozen(false) {}
CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true), freezeNext(false), frozen(false), mountIsoLoader(nullptr) {}
CPUCore cpuCore;
GPUCore gpuCore;
bool enableSound; // there aren't multiple sound cores.
@ -65,4 +67,6 @@ struct CoreParameter {
// Freeze-frame. For nvidia perfhud profiling. Developers only.
bool freezeNext;
bool frozen;
FileLoader *mountIsoLoader;
};

View File

@ -17,6 +17,7 @@
#include "Common/FileUtil.h"
#include "Core/Loaders.h"
#include "Core/FileSystems/BlockDevices.h"
#include <cstdio>
#include <cstring>
@ -29,20 +30,19 @@ extern "C"
#include "ext/libkirk/kirk_engine.h"
};
BlockDevice *constructBlockDevice(const char *filename) {
BlockDevice *constructBlockDevice(FileLoader *fileLoader) {
// Check for CISO
FILE *f = File::OpenCFile(filename, "rb");
if (!f)
return 0;
if (!fileLoader->Exists())
return nullptr;
char buffer[4];
auto size = fread(buffer, 1, 4, f); //size_t
fseek(f, 0, SEEK_SET);
size_t size = fileLoader->ReadAt(0, 1, 4, buffer);
fileLoader->Seek(0);
if (!memcmp(buffer, "CISO", 4) && size == 4)
return new CISOFileBlockDevice(f);
return new CISOFileBlockDevice(fileLoader);
else if (!memcmp(buffer, "\x00PBP", 4) && size == 4)
return new NPDRMDemoBlockDevice(f);
return new NPDRMDemoBlockDevice(fileLoader);
else
return new FileBlockDevice(f);
return new FileBlockDevice(fileLoader);
}
RAMBlockDevice::RAMBlockDevice(BlockDevice *device) {
@ -74,67 +74,16 @@ u32 RAMBlockDevice::GetNumBlocks() {
// Android NDK does not support 64-bit file I/O using C streams
// so we fall back onto syscalls
#ifdef ANDROID
FileBlockDevice::FileBlockDevice(FILE *file)
: f(file)
{
fd = fileno(file);
off64_t off = lseek64(fd, 0, SEEK_END);
filesize = off;
lseek64(fd, 0, SEEK_SET);
FileBlockDevice::FileBlockDevice(FileLoader *fileLoader)
: fileLoader_(fileLoader) {
filesize_ = fileLoader->FileSize();
}
FileBlockDevice::~FileBlockDevice()
{
fclose(f);
FileBlockDevice::~FileBlockDevice() {
}
bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
{
lseek64(fd, (u64)blockNumber * (u64)GetBlockSize(), SEEK_SET);
if (read(fd, outPtr, 2048) != 2048) {
ERROR_LOG(FILESYS, "Could not read() 2048 bytes from block");
return false;
}
return true;
}
bool FileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr)
{
lseek64(fd, (u64)minBlock * (u64)GetBlockSize(), SEEK_SET);
const s32 bytes = GetBlockSize() * count;
if (read(fd, outPtr, bytes) != bytes) {
ERROR_LOG(FILESYS, "Could not read() %d bytes from block", bytes);
return false;
}
return true;
}
#else
FileBlockDevice::FileBlockDevice(FILE *file)
: f(file)
{
fseek(f, 0, SEEK_END);
filesize = ftello(f);
fseek(f, 0, SEEK_SET);
}
FileBlockDevice::~FileBlockDevice()
{
fclose(f);
}
bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
{
fseeko(f, (u64)blockNumber * (u64)GetBlockSize(), SEEK_SET);
if (fread(outPtr, 1, 2048, f) != 2048) {
bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr) {
if (fileLoader_->ReadAt((u64)blockNumber * (u64)GetBlockSize(), 1, 2048, outPtr) != 2048) {
DEBUG_LOG(FILESYS, "Could not read 2048 bytes from block");
return false;
}
@ -142,18 +91,14 @@ bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
return true;
}
bool FileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr)
{
fseeko(f, (u64)minBlock * (u64)GetBlockSize(), SEEK_SET);
if (fread(outPtr, 2048, count, f) != count) {
bool FileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
if (fileLoader_->ReadAt((u64)minBlock * (u64)GetBlockSize(), 2048, count, outPtr) != count) {
ERROR_LOG(FILESYS, "Could not read %d bytes from block", 2048 * count);
return false;
}
return true;
}
#endif
// .CSO format
// compressed ISO(9660) header format
@ -184,14 +129,13 @@ typedef struct ciso_header
static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024;
CISOFileBlockDevice::CISOFileBlockDevice(FILE *file)
: f(file)
CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
: fileLoader_(fileLoader)
{
// CISO format is fairly simple, but most tools do not write the header_size.
f = file;
CISO_H hdr;
size_t readSize = fread(&hdr, sizeof(CISO_H), 1, f);
size_t readSize = fileLoader->ReadAt(0, sizeof(CISO_H), 1, &hdr);
if (readSize != 1 || memcmp(hdr.magic, "CISO", 4) != 0)
{
WARN_LOG(LOADER, "Invalid CSO!");
@ -235,13 +179,13 @@ CISOFileBlockDevice::CISOFileBlockDevice(FILE *file)
#if COMMON_LITTLE_ENDIAN
index = new u32[indexSize];
if (fread(index, sizeof(u32), indexSize, f) != indexSize)
if (fileLoader->ReadAt(sizeof(hdr), sizeof(u32), indexSize, index) != indexSize)
memset(index, 0, indexSize * sizeof(u32));
#else
index = new u32[indexSize];
u32_le *indexTemp = new u32_le[indexSize];
if (fread(indexTemp, sizeof(u32), indexSize, f) != indexSize)
if (fileLoader->ReadAt(sizeof(hdr), sizeof(u32), indexSize, indexTemp) != indexSize)
{
memset(indexTemp, 0, indexSize * sizeof(u32_le));
}
@ -257,7 +201,6 @@ CISOFileBlockDevice::CISOFileBlockDevice(FILE *file)
CISOFileBlockDevice::~CISOFileBlockDevice()
{
fclose(f);
delete [] index;
delete [] readBuffer;
delete [] zlibBuffer;
@ -285,8 +228,7 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
const int plain = idx & 0x80000000;
if (plain)
{
fseeko(f, compressedReadPos + compressedOffset, SEEK_SET);
int readSize = (u32)fread(outPtr, 1, GetBlockSize(), f);
int readSize = (u32)fileLoader_->ReadAt(compressedReadPos + compressedOffset, 1, GetBlockSize(), outPtr);
if (readSize < GetBlockSize())
memset(outPtr + readSize, 0, GetBlockSize() - readSize);
}
@ -297,8 +239,7 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
}
else
{
fseeko(f, compressedReadPos, SEEK_SET);
const u32 readSize = (u32)fread(readBuffer, 1, compressedReadSize, f);
const u32 readSize = (u32)fileLoader_->ReadAt(compressedReadPos, 1, compressedReadSize, readBuffer);
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
@ -387,8 +328,7 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
const s64 maxNeeded = totalReadEnd - frameReadPos;
const size_t chunkSize = (size_t)std::min(maxNeeded, (s64)std::max(frameReadSize, CSO_READ_BUFFER_SIZE));
fseeko(f, frameReadPos, SEEK_SET);
const u32 readSize = (u32)fread(readBuffer, 1, chunkSize, f);
const u32 readSize = (u32)fileLoader_->ReadAt(frameReadPos, 1, chunkSize, readBuffer);
if (readSize < chunkSize) {
memset(readBuffer + readSize, 0, chunkSize - readSize);
}
@ -432,8 +372,8 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
}
NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FILE *file)
: f(file)
NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader)
: fileLoader_(fileLoader)
{
MAC_KEY mkey;
CIPHER_KEY ckey;
@ -441,10 +381,8 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FILE *file)
u32 tableOffset, tableSize;
u32 lbaStart, lbaEnd;
fseek(f, 0x24, SEEK_SET);
fread(&psarOffset, 1, 4, f);
fseek(f, psarOffset, SEEK_SET);
size_t readSize = fread(&np_header, 1, 256, f);
fileLoader_->ReadAt(0x24, 1, 4, &psarOffset);
size_t readSize = fileLoader_->ReadAt(psarOffset, 1, 256, &np_header);
if(readSize!=256){
ERROR_LOG(LOADER, "Invalid NPUMDIMG header!");
}
@ -473,12 +411,11 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FILE *file)
tempBuf = new u8[blockSize];
tableOffset = *(u32*)(np_header+0x6c); // table offset
fseek(f, psarOffset+tableOffset, SEEK_SET);
tableSize = numBlocks*32;
table = new table_info[numBlocks];
readSize = fread(table, 1, tableSize, f);
readSize = fileLoader_->ReadAt(psarOffset + tableOffset, 1, tableSize, table);
if(readSize!=tableSize){
ERROR_LOG(LOADER, "Invalid NPUMDIMG table!");
}
@ -503,7 +440,6 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FILE *file)
NPDRMDemoBlockDevice::~NPDRMDemoBlockDevice()
{
fclose(f);
delete [] table;
delete [] tempBuf;
delete [] blockBuf;
@ -535,14 +471,12 @@ bool NPDRMDemoBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
return false;
}
fseek(f, psarOffset+table[block].offset, SEEK_SET);
if(table[block].size<blockSize)
readBuf = tempBuf;
else
readBuf = blockBuf;
readSize = fread(readBuf, 1, table[block].size, f);
readSize = fileLoader_->ReadAt(psarOffset+table[block].offset, 1, table[block].size, readBuf);
if(readSize != (size_t)table[block].size){
if((u32)block==(numBlocks-1))
return true;

View File

@ -26,6 +26,8 @@
#include "Common/CommonTypes.h"
#include "Core/ELF/PBPReader.h"
class FileLoader;
class BlockDevice
{
public:
@ -48,14 +50,14 @@ public:
class CISOFileBlockDevice : public BlockDevice
{
public:
CISOFileBlockDevice(FILE *file);
CISOFileBlockDevice(FileLoader *fileLoader);
~CISOFileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr) override;
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
u32 GetNumBlocks() { return numBlocks;}
private:
FILE *f;
FileLoader *fileLoader_;
u32 *index;
u8 *readBuffer;
u8 *zlibBuffer;
@ -71,18 +73,15 @@ private:
class FileBlockDevice : public BlockDevice
{
public:
FileBlockDevice(FILE *file);
FileBlockDevice(FileLoader *fileLoader);
~FileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr) override;
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
u32 GetNumBlocks() override {return (u32)(filesize / GetBlockSize());}
u32 GetNumBlocks() override {return (u32)(filesize_ / GetBlockSize());}
private:
#ifdef ANDROID
int fd;
#endif
FILE *f;
u64 filesize;
FileLoader *fileLoader_;
u64 filesize_;
};
@ -99,14 +98,14 @@ struct table_info {
class NPDRMDemoBlockDevice : public BlockDevice
{
public:
NPDRMDemoBlockDevice(FILE *file);
NPDRMDemoBlockDevice(FileLoader *fileLoader);
~NPDRMDemoBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr) override;
u32 GetNumBlocks() override {return (u32)lbaSize;}
private:
FILE *f;
FileLoader *fileLoader_;
u32 lbaSize;
u32 psarOffset;
@ -140,4 +139,4 @@ private:
};
BlockDevice *constructBlockDevice(const char *filename);
BlockDevice *constructBlockDevice(FileLoader *fileLoader);

View File

@ -20,6 +20,7 @@
#include "file/file_util.h"
#include "Common/ChunkFile.h"
#include "Core/Loaders.h"
#include "Core/MemMap.h"
#include "Core/System.h"
#include "Core/CoreTiming.h"
@ -460,20 +461,28 @@ u32 sceUmdGetErrorStat()
}
void __UmdReplace(std::string filepath) {
// TODO: This should really go through Loaders, no? What if it's an invalid file?
// Only get system from disc0 seems have been enough.
IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:");
IFileSystem* currentISOBlock = pspFileSystem.GetSystem("umd0:");
if (!currentUMD)
return;
FileLoader *loadedFile = new LocalFileLoader(filepath);
IFileSystem* umd2;
FileInfo info;
if (!getFileInfo(filepath.c_str(), &info)) // This shouldn't happen, but for safety.
if (!loadedFile->Exists()) {
delete loadedFile;
return;
}
UpdateLoadedFile(loadedFile);
if (info.isDirectory) {
umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath);
} else {
auto bd = constructBlockDevice(filepath.c_str());
auto bd = constructBlockDevice(loadedFile);
if (!bd)
return;
umd2 = new ISOFileSystem(&pspFileSystem, bd);

View File

@ -47,6 +47,8 @@ bool LocalFileLoader::Reopen(const std::string &filename) {
}
#ifdef ANDROID
// Android NDK does not support 64-bit file I/O using C streams
// so we fall back onto syscalls
fd_ = fileno(f_);
off64_t off = lseek64(fd_, 0, SEEK_END);
@ -282,7 +284,7 @@ bool LoadFile(FileLoader *fileLoader, std::string *error_string) {
if (ebootType == FILETYPE_PSP_ISO_NP) {
InitMemoryForGameISO(fileLoader);
pspFileSystem.SetStartingDirectory("disc0:/PSP_GAME/USRDIR");
return Load_PSP_ISO(filename.c_str(), error_string);
return Load_PSP_ISO(fileLoader, error_string);
}
else if (ebootType == FILETYPE_PSP_PS1_PBP) {
*error_string = "PS1 EBOOTs are not supported by PPSSPP.";
@ -292,7 +294,7 @@ bool LoadFile(FileLoader *fileLoader, std::string *error_string) {
size_t pos = path.find("/PSP/GAME/");
if (pos != std::string::npos)
pspFileSystem.SetStartingDirectory("ms0:" + path.substr(pos));
return Load_PSP_ELF_PBP(fileLoader->Path().c_str(), error_string);
return Load_PSP_ELF_PBP(fileLoader, error_string);
} else {
*error_string = "No EBOOT.PBP, misidentified game";
return false;
@ -303,14 +305,14 @@ bool LoadFile(FileLoader *fileLoader, std::string *error_string) {
case FILETYPE_PSP_ELF:
{
INFO_LOG(LOADER,"File is an ELF or loose PBP!");
return Load_PSP_ELF_PBP(fileLoader->Path().c_str(), error_string);
return Load_PSP_ELF_PBP(fileLoader, error_string);
}
case FILETYPE_PSP_ISO:
case FILETYPE_PSP_ISO_NP:
case FILETYPE_PSP_DISC_DIRECTORY: // behaves the same as the mounting is already done by now
pspFileSystem.SetStartingDirectory("disc0:/PSP_GAME/USRDIR");
return Load_PSP_ISO(fileLoader->Path().c_str(), error_string);
return Load_PSP_ISO(fileLoader, error_string);
case FILETYPE_PSP_PS1_PBP:
*error_string = "PS1 EBOOTs are not supported by PPSSPP.";

View File

@ -68,7 +68,7 @@ void InitMemoryForGameISO(FileLoader *fileLoader) {
}
else
{
auto bd = constructBlockDevice(fileLoader->Path().c_str());
auto bd = constructBlockDevice(fileLoader);
// Can't init anything without a block device...
if (!bd)
return;
@ -151,7 +151,7 @@ static const char *altBootNames[] = {
"disc0:/PSP_GAME/SYSDIR/ss.RAW",
};
bool Load_PSP_ISO(const char *filename, std::string *error_string)
bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string)
{
// Mounting stuff relocated to InitMemoryForGameISO due to HD Remaster restructuring of code.
@ -224,12 +224,12 @@ static std::string NormalizePath(const std::string &path)
return buf;
}
bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string)
bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string)
{
// This is really just for headless, might need tweaking later.
if (!PSP_CoreParameter().mountIso.empty())
if (PSP_CoreParameter().mountIsoLoader != nullptr)
{
auto bd = constructBlockDevice(PSP_CoreParameter().mountIso.c_str());
auto bd = constructBlockDevice(PSP_CoreParameter().mountIsoLoader);
if (bd != NULL) {
ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, bd);
@ -239,7 +239,7 @@ bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string)
}
}
std::string full_path = filename;
std::string full_path = fileLoader->Path();
std::string path, file, extension;
SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension);
#ifdef _WIN32

View File

@ -21,6 +21,6 @@
class FileLoader;
bool Load_PSP_ISO(const char *filename, std::string *error_string);
bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string);
bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string);
bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string);
void InitMemoryForGameISO(FileLoader *fileLoader);

View File

@ -185,6 +185,11 @@ void CPU_Init() {
loadedFile = new LocalFileLoader(filename);
IdentifiedFileType type = Identify_File(loadedFile);
// TODO: Put this somewhere better?
if (coreParameter.mountIso != "") {
coreParameter.mountIsoLoader = new LocalFileLoader(coreParameter.mountIso);
}
MIPSAnalyst::Reset();
Replacement_Init();
@ -249,7 +254,16 @@ void CPU_Shutdown() {
Memory::Shutdown();
delete loadedFile;
loadedFile = 0;
loadedFile = nullptr;
delete coreParameter.mountIsoLoader;
coreParameter.mountIsoLoader = nullptr;
}
// TODO: Maybe loadedFile doesn't even belong here...
void UpdateLoadedFile(FileLoader *fileLoader) {
delete loadedFile;
loadedFile = fileLoader;
}
void CPU_RunLoop() {

View File

@ -63,6 +63,8 @@ void Audio_Init();
bool IsOnSeparateCPUThread();
bool IsAudioInitialised();
void UpdateLoadedFile(FileLoader *fileLoader);
std::string GetSysDirectory(PSPDirectories directoryType);
#ifdef _WIN32
void InitSysDirectories();

View File

@ -378,7 +378,7 @@ handleELF:
// Let's assume it's an ISO.
// TODO: This will currently read in the whole directory tree. Not really necessary for just a
// few files.
BlockDevice *bd = constructBlockDevice(gamePath_.c_str());
BlockDevice *bd = constructBlockDevice(fileLoader.get());
if (!bd)
return; // nothing to do here..
ISOFileSystem umd(&handles, bd, "/PSP_GAME");