Identify a CHD as a PS1 disc by its volume descriptor, not by being a CD's

chdman createcd makes CD CHDs of PSP discs too, which were taken for PS1 games. A CHD is now a PS1
disc only when its volume descriptor's system ID is PLAYSTATION, and otherwise goes on to the PSP
disc checks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-23 21:50:53 +02:00
1 parent 31e94fcf68
commit e91357c9a1
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) {