[Scummvm-git-logs] scummvm-web master -> f011a0a6a2420a497efd30812c01281b60bbdfb4
lephilousophe
noreply at scummvm.org
Sat Jun 6 18:20:51 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm-web' repo located at https://api.github.com/repos/scummvm/scummvm-web .
Summary:
f011a0a6a2 DUMPER-COMPANION: Add support for hybrid ISO/HFS discs
Commit: f011a0a6a2420a497efd30812c01281b60bbdfb4
https://github.com/scummvm/scummvm-web/commit/f011a0a6a2420a497efd30812c01281b60bbdfb4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2026-06-06T20:19:58+02:00
Commit Message:
DUMPER-COMPANION: Add support for hybrid ISO/HFS discs
Only dump the HFS partition, though.
Changed paths:
dumper-companion/src/hfs/main.ts
diff --git a/dumper-companion/src/hfs/main.ts b/dumper-companion/src/hfs/main.ts
index f6055418..fafc7ea0 100644
--- a/dumper-companion/src/hfs/main.ts
+++ b/dumper-companion/src/hfs/main.ts
@@ -30,7 +30,7 @@
import * as bitmanip from './bitmanip';
import * as btree from './btree';
import { AbstractFolder, FileOrFolder, MacFile, MacFolder } from './directory';
-import { charCode, joinBytes, bytes } from '../util';
+import { joinBytes, bytes, bytesToString } from '../util';
import struct from '../struct';
@@ -66,28 +66,78 @@ export class Volume extends AbstractFolder {
this.name = 'Untitled';
}
- findMagicNumber(from_volume: Uint8Array): number {
- // Image data starts at 0x54 in DiskCopy 4.2 format https://wiki.68kmla.org/DiskCopy_4.2_format_specification
+ probePartition(from_volume: Uint8Array): Uint8Array|null {
+ // Search for partition first
+ for (let partition_num = 1; ; partition_num++) {
+ // Apple Partition Map
+ if (from_volume.length < partition_num*512+1 || from_volume[partition_num*512] != 0x50 || from_volume[partition_num*512+1] != 0x4D) { // Searching PM
+ break;
+ }
+
+ const [num_partitions, partition_start, partition_size] = struct<[number, number, number]>('>III').unpack_from(from_volume.subarray(partition_num*512+4, partition_num*512+16));
+ const partition_type = bytesToString(from_volume.subarray(partition_num*512+48, partition_num*512+80));
+ if (partition_type.startsWith("Apple_HFS\x00")) {
+ // First HFS partition: take it
+ return from_volume.subarray(partition_start*512, (partition_start+partition_size)*512);
+ }
- for (const startOffset of [0x0, 0x54]) {
- for (let i = startOffset; i < from_volume.length; i += 512) {
- if (from_volume[i+1024] === charCode('B') && from_volume[i+1024+1] === charCode('D')) {
- return i;
+ if (partition_num >= num_partitions) {
+ break;
+ }
+ }
+
+ // No partition
+ return null;
+ }
+
+ probeStart(from_volume: Uint8Array): Uint8Array|null {
+ for (let i = 0; i + 1024 + 1 < from_volume.length; i += 512) {
+ if (from_volume[i+1024] === 0x42 && from_volume[i+1024+1] === 0x44) { // Searching BD
+ if (i == 0) {
+ return from_volume;
}
+ return from_volume.subarray(i);
+ }
+ }
+
+ return null;
+ }
+
+ probe(from_volume: Uint8Array): Uint8Array|null {
+ // Image data starts at 0x54 in DiskCopy 4.2 format https://wiki.68kmla.org/DiskCopy_4.2_format_specification
+ // 0x52-0x53 bytes have 01 00 value
+ const maybeDC42 = from_volume.length >= 0x54 && from_volume[0x52] == 0x01 && from_volume[0x53] == 0x00;
+
+ if (maybeDC42) {
+ const dc42 = from_volume.subarray(0x54);
+
+ // Try to find a partition first with DC42 offset
+ const partitioned = this.probePartition(dc42);
+ if (partitioned !== null) {
+ return this.probeStart(partitioned);
}
+ // Try looking for start using DC42 offset then
+ const start = this.probeStart(dc42);
+ if (start !== null) {
+ return start;
+ }
+
+ // If it failed, follow on with RAW images
}
- return -1;
+ const partitioned = this.probePartition(from_volume);
+ if (partitioned !== null) {
+ return this.probeStart(partitioned);
+ }
+
+ return this.probeStart(from_volume);
}
read(from_volume: Uint8Array): void {
- const magicOffset = this.findMagicNumber(from_volume);
- if (magicOffset < 0) {
+ const volume = this.probe(from_volume);
+ if (volume === null) {
throw new Error('Magic number not found in image');
}
- if (magicOffset > 0) {
- from_volume = from_volume.subarray(magicOffset);
- }
/* eslint-disable @typescript-eslint/no-unused-vars */
const [drSigWord, drCrDate, drLsMod, drAtrb, drNmFls,
@@ -103,7 +153,7 @@ export class Volume extends AbstractFolder {
number, number, number, number, number, number,
Uint8Array, number, number, number,
number, Uint8Array,
- number, Uint8Array]>('>2sLLHHHHHLLHLH28pLHLLLHLL32sHHHL12sL12s').unpack_from(from_volume, 1024);
+ number, Uint8Array]>('>2sLLHHHHHLLHLH28pLHLLLHLL32sHHHL12sL12s').unpack_from(volume, 1024);
/* eslint-enable @typescript-eslint/no-unused-vars */
this.crdate = drCrDate;
@@ -113,7 +163,7 @@ export class Volume extends AbstractFolder {
const block2offset = (block: number) => 512*drAlBlSt + drAlBlkSiz*block;
const getextents = (extents: [number, number][]) => joinBytes(
extents.map(
- ([firstblk, blkcnt]: [number, number]) => from_volume.subarray(
+ ([firstblk, blkcnt]: [number, number]) => volume.subarray(
block2offset(firstblk),
block2offset(firstblk+blkcnt)
)
More information about the Scummvm-git-logs
mailing list