Skip to content

Commit

Permalink
Merge pull request #18633 from hrydgard/chd-stream-support
Browse files Browse the repository at this point in the history
Remote ISO: Add working support for streaming CHD files over the network
  • Loading branch information
hrydgard authored Dec 29, 2023
2 parents a5afba2 + 7d114eb commit 5b0e821
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 28 deletions.
72 changes: 48 additions & 24 deletions Core/FileSystems/BlockDevices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,58 @@ struct CHDImpl {
const chd_header *header = nullptr;
};

struct ExtendedCoreFile {
core_file core; // Must be the first struct member, for some tricky pointer casts.
uint64_t seekPos;
};

CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader)
: BlockDevice(fileLoader), impl_(new CHDImpl())
{
Path paths[8];
paths[0] = fileLoader->GetPath();
int depth = 0;

core_file_ = new ExtendedCoreFile();
core_file_->core.argp = fileLoader;
core_file_->core.fsize = [](core_file *file) -> uint64_t {
FileLoader *loader = (FileLoader *)file->argp;
return loader->FileSize();
};
core_file_->core.fseek = [](core_file *file, int64_t offset, int seekType) -> int {
ExtendedCoreFile *coreFile = (ExtendedCoreFile *)file;
switch (seekType) {
case SEEK_SET:
coreFile->seekPos = offset;
break;
case SEEK_CUR:
coreFile->seekPos += offset;
break;
case SEEK_END:
{
FileLoader *loader = (FileLoader *)file->argp;
coreFile->seekPos = loader->FileSize() + offset;
break;
}
default:
break;
}
return 0;
};
core_file_->core.fread = [](void *out_data, size_t size, size_t count, core_file *file) {
ExtendedCoreFile *coreFile = (ExtendedCoreFile *)file;
FileLoader *loader = (FileLoader *)file->argp;
uint64_t totalSize = size * count;
loader->ReadAt(coreFile->seekPos, totalSize, out_data);
coreFile->seekPos += totalSize;
return size * count;
};
core_file_->core.fclose = [](core_file *file) {
ExtendedCoreFile *coreFile = (ExtendedCoreFile *)file;
delete coreFile;
return 0;
};

/*
// TODO: Support parent/child CHD files.
Expand Down Expand Up @@ -582,36 +627,15 @@ CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader)
}
*/

chd_file *parent = NULL;
chd_file *child = NULL;

FILE *file = File::OpenCFile(paths[depth], "rb");
if (!file) {
ERROR_LOG(LOADER, "Error opening CHD file '%s'", paths[depth].c_str());
NotifyReadError();
return;
}
chd_error err = chd_open_file(file, CHD_OPEN_READ, NULL, &child);
chd_file *file = nullptr;
chd_error err = chd_open_core_file(&core_file_->core, CHD_OPEN_READ, NULL, &file);
if (err != CHDERR_NONE) {
ERROR_LOG(LOADER, "Error loading CHD '%s': %s", paths[depth].c_str(), chd_error_string(err));
NotifyReadError();
return;
}

// We won't enter this loop until we enable the parent/child stuff above.
for (int d = depth - 1; d >= 0; d--) {
parent = child;
child = NULL;
// TODO: Use chd_open_file
err = chd_open(paths[d].c_str(), CHD_OPEN_READ, parent, &child);
if (err != CHDERR_NONE) {
ERROR_LOG(LOADER, "Error loading CHD '%s': %s", paths[d].c_str(), chd_error_string(err));
NotifyReadError();
return;
}
}
impl_->chd = child;

impl_->chd = file;
impl_->header = chd_get_header(impl_->chd);
readBuffer = new u8[impl_->header->hunkbytes];
currentHunk = -1;
Expand Down
3 changes: 3 additions & 0 deletions Core/FileSystems/BlockDevices.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ class NPDRMDemoBlockDevice : public BlockDevice {

struct CHDImpl;

struct ExtendedCoreFile;

class CHDFileBlockDevice : public BlockDevice {
public:
CHDFileBlockDevice(FileLoader *fileLoader);
Expand All @@ -146,6 +148,7 @@ class CHDFileBlockDevice : public BlockDevice {
bool IsDisc() const override { return true; }

private:
struct ExtendedCoreFile *core_file_ = nullptr;
std::unique_ptr<CHDImpl> impl_;
u8 *readBuffer = nullptr;
u32 currentHunk = 0;
Expand Down
4 changes: 1 addition & 3 deletions Core/WebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ static bool RegisterServer(int port) {

bool RemoteISOFileSupported(const std::string &filename) {
// Disc-like files.
// NOTE: chd is temporarily disabled until we can make it use the FileLoader instead of
// trying to re-open the file, since otherwise won't work over HTTP.
if (endsWithNoCase(filename, ".cso") || endsWithNoCase(filename, ".iso")) {
if (endsWithNoCase(filename, ".cso") || endsWithNoCase(filename, ".iso") || endsWithNoCase(filename, ".chd")) {
return true;
}
// May work - but won't have supporting files.
Expand Down
2 changes: 1 addition & 1 deletion UI/RemoteISOScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ static bool LoadGameList(const Path &url, std::vector<Path> &games) {
std::vector<File::FileInfo> files;
browser.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION));
browser.SetRootAlias("ms:", GetSysDirectory(DIRECTORY_MEMSTICK_ROOT).ToVisualString());
browser.GetListing(files, "iso:cso:pbp:elf:prx:ppdmp:", &scanCancelled);
browser.GetListing(files, "iso:cso:chd:pbp:elf:prx:ppdmp:", &scanCancelled);
if (scanCancelled) {
return false;
}
Expand Down

0 comments on commit 5b0e821

Please sign in to comment.