diff --git a/src/main/services/emulators/extract-disc-sku.ts b/src/main/services/emulators/extract-disc-sku.ts index 76dc45a3d1..6491589a53 100644 --- a/src/main/services/emulators/extract-disc-sku.ts +++ b/src/main/services/emulators/extract-disc-sku.ts @@ -54,24 +54,7 @@ const extractCsoSku = async (filePath: string): Promise => { return sku; }; -const extractPs12Sku = async (filePath: string): Promise => { - const lower = filePath.toLowerCase(); - if (lower.endsWith(".chd")) { - return extractChdSku(filePath); - } - if (lower.endsWith(".cso")) { - return extractCsoSku(filePath); - } - - const target = await resolveSniffTarget(filePath); - logger.log("[extract-sku] start", { filePath, target }); - if (!target) { - logger.log("[extract-sku] no sniff target (unsupported format)", { - filePath, - }); - return null; - } - +const scanTargetForSku = async (target: string): Promise => { let fh: import("node:fs/promises").FileHandle | null = null; try { fh = await fs.open(target, "r"); @@ -143,6 +126,39 @@ const extractPs12Sku = async (filePath: string): Promise => { } }; +const extractPs12Sku = async (filePath: string): Promise => { + const lower = filePath.toLowerCase(); + if (lower.endsWith(".chd")) { + return extractChdSku(filePath); + } + if (lower.endsWith(".cso")) { + return extractCsoSku(filePath); + } + + const target = await resolveSniffTarget(filePath); + logger.log("[extract-sku] start", { filePath, target }); + if (!target) { + logger.log("[extract-sku] no sniff target (unsupported format)", { + filePath, + }); + return null; + } + + const targetExists = await fs + .access(target) + .then(() => true) + .catch(() => false); + if (!targetExists) { + logger.warn("[extract-sku] sniff target missing on disk", { + filePath, + target, + }); + return null; + } + + return scanTargetForSku(target); +}; + const findKeyOffset = ( data: Buffer, keyTableStart: number, diff --git a/src/main/services/emulators/sniff-disc-platform.ts b/src/main/services/emulators/sniff-disc-platform.ts index 9d96db61b9..e76e664665 100644 --- a/src/main/services/emulators/sniff-disc-platform.ts +++ b/src/main/services/emulators/sniff-disc-platform.ts @@ -37,6 +37,30 @@ export const sniffDiscImage = async ( } }; +const resolveCueRef = async ( + dir: string, + ref: string +): Promise => { + const base = path.basename(ref.replaceAll("\\", "/")); + const resolved = path.resolve(dir, base); + + try { + await fs.access(resolved); + return resolved; + } catch { + try { + const entries = await fs.readdir(dir); + const match = entries.find( + (entry) => entry.toLowerCase() === base.toLowerCase() + ); + if (match) return path.resolve(dir, match); + } catch { + return null; + } + return null; + } +}; + export const parseCueReferencedFiles = async ( cuePath: string ): Promise => { @@ -44,7 +68,10 @@ export const parseCueReferencedFiles = async ( const content = await fs.readFile(cuePath, "utf-8"); const dir = path.dirname(cuePath); const matches = [...content.matchAll(/FILE\s+"(.+?)"\s+\w+/gi)]; - return matches.map((m) => path.resolve(dir, m[1])); + const resolved = await Promise.all( + matches.map((m) => resolveCueRef(dir, m[1])) + ); + return resolved.filter((p): p is string => p !== null); } catch { return []; }