Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote ISO: Add working support for streaming CHD files over the network #18633

Merged
merged 1 commit into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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