Merge pull request #22750 from hrydgard/chd-psp-detection

Fix CHD identification bug (it routed some PSP CHDs to POPS)
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-10-23 22:58:51 +02:00
commit 42bb9b134b
3 files changed
+29 -7

No files matched your search

+25 -3
View File
@@ -487,6 +487,8 @@ static int CHDTrackSectorSize(std::string_view type) {
// A CD CHD's tracks are in its metadata, one entry each, and its frames (2352 bytes of sector and 96 of
// subcode) are in hunks of several. Each track's frames are padded to a multiple of four, and a pregap is
// in them only if its type starts with V.
//
// NOTE: We can't re-use CHDFileBlockDevice here, because it doesn't support multiple tracks.
bool PS1EbootFileLoader::OpenCHD(const Path &path) {
const int file = AddFile(path);
if (file < 0) {
@@ -547,15 +549,35 @@ bool PS1EbootFileLoader::OpenCHD(const Path &path) {
return true;
}
bool IsCDChd(FileLoader *fileLoader) {
bool IsPS1Chd(FileLoader *fileLoader) {
std::string error;
chd_file *chd = OpenCHDThroughLoader(fileLoader, &error);
if (!chd) {
return false;
}
const bool cd = chd_get_header(chd)->unitbytes == CD_FRAME_SIZE;
const chd_header *header = chd_get_header(chd);
bool ps1 = false;
if (header->unitbytes == CD_FRAME_SIZE && header->hunkbytes % CD_FRAME_SIZE == 0) {
// The volume descriptor, in sector 16 of the first track, after its pregap if that's stored.
u32 frame = 16;
char meta[256]{};
int number = 0, frames = 0, pregap = 0;
char type[32]{}, subtype[32]{}, pgtype[32]{};
if (chd_get_metadata(chd, CDROM_TRACK_METADATA2_TAG, 0, meta, sizeof(meta) - 1, nullptr, nullptr, nullptr) == CHDERR_NONE &&
sscanf(meta, "TRACK:%d TYPE:%31s SUBTYPE:%31s FRAMES:%d PREGAP:%d PGTYPE:%31s", &number, type, subtype, &frames, &pregap, pgtype) == 6 && pgtype[0] == 'V') {
frame += pregap;
}
const u32 framesPerHunk = header->hunkbytes / CD_FRAME_SIZE;
std::vector<u8> hunk(header->hunkbytes);
if (chd_read(chd, frame / framesPerHunk, hunk.data()) == CHDERR_NONE) {
const u8 *sector = hunk.data() + (frame % framesPerHunk) * CD_FRAME_SIZE;
const u8 *pvd = sector + (sector[15] == 1 ? 16 : 24);
// Every PS1 disc's system ID is PLAYSTATION. A PSP disc's is PSP GAME.
ps1 = memcmp(pvd, "\x01" "CD001", 6) == 0 && memcmp(pvd + 8, "PLAYSTATION", 11) == 0;
}
}
chd_close(chd);
return cd;
return ps1;
}
bool PS1EbootFileLoader::ParseCue(const Path &cuePath, const std::string &text) {
+3 -2
View File
@@ -115,8 +115,9 @@ struct FileInfo;
// Whether a .cue, .ccd or .mds describes a disc, by its contents.
bool IsPS1DiscSheet(FileLoader *fileLoader);
// Whether a CHD is of a CD (rather than a DVD, like a PSP disc).
bool IsCDChd(FileLoader *fileLoader);
// Whether a CHD is of a PS1 disc, by its volume descriptor. A PSP disc's can be a CD's too, as chdman
// createcd makes them.
bool IsPS1Chd(FileLoader *fileLoader);
// The file names a cue sheet's FILE lines give.
std::vector<std::string> CueSheetFileNames(const Path &cuePath);
+1 -2
View File
@@ -109,8 +109,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
return IdentifiedFileType::ERROR_IDENTIFYING;
}
if (extension == ".chd" && IsCDChd(fileLoader)) {
// PSP discs are DVDs, so a CD is a PS1 disc.
if (extension == ".chd" && IsPS1Chd(fileLoader)) {
return IdentifiedFileType::PSX_ISO;
}