Skip to content

Latest commit

 

History

History
186 lines (149 loc) · 7.43 KB

File metadata and controls

186 lines (149 loc) · 7.43 KB

01 — The disc image

It is CD-i Ready, and that changes the first move

Extract the CHD and the cue sheet is the first surprise:

FILE "disc.bin" BINARY
  TRACK 01 AUDIO
    INDEX 00 00:00:00
    INDEX 01 15:22:00
  TRACK 02 AUDIO
    INDEX 00 19:42:00
    INDEX 01 19:44:00
  ...
  TRACK 22 AUDIO

Twenty-two tracks, every one of them AUDIO, and track 1 with a 15:22 pregap. There is no MODE2_RAW and no CDI/2352 anywhere. The CHD's own metadata says the same thing:

TRACK:1 TYPE:AUDIO SUBTYPE:NONE FRAMES:88650 PREGAP:69150
TRACK:2 TYPE:AUDIO SUBTYPE:NONE FRAMES:18825 PREGAP:150
...

15:22 is 69,150 sectors. That is where the whole CD-i disc lives. CD-i Ready puts the application in track 1's pregap precisely so that an audio CD player, which begins at INDEX 01, plays past it and treats the disc as an album. The CD-i player, which reads the TOC differently, starts at LBA 0.

Grepping the extracted image for CD-RTOS finds nothing, and grepping for the 12-byte sync mark finds nothing either — until you look at byte 0 of sector 0:

00 ff ff ff ff ff ff ff ff ff ff 00   01 82 00 62   00 28 20 1e 80 08 40 06
^------------ sync, intact --------^  ^-- header --^ ^------ subheader ------^

Sync is there. The header is not a header and the subheader's two halves do not match. Both are scrambled, and the reason is mechanical: the ripper followed the TOC, read an audio track, and returned raw channel data without descrambling it — which is exactly the inverse of the situation the platform notes describe for audio hidden inside a data track.

Proving it takes one XOR

A Mode 2 sector at LBA 0 must carry MSF 00:02:00 in BCD and mode 02. The ECMA-130 Annex B scrambler — 15-bit LFSR, x^15 + x + 1, preset $0001, LSB first, reset every sector — begins 01 80 00 60. So:

  LBA    stored       want       scrambler   xor        verdict
     0   01820062     00020002   01800060    01820062   scrambled
     1   01820162     00020102   01800060    01820162   scrambled
    16   01821662     00021602   01800060    01821662   scrambled
    17   01821762     00021702   01800060    01821762   scrambled
   100   01832562     00032502   01800060    01832562   scrambled
  1000   01952562     00152502   01800060    01952562   scrambled
 60000   12a20062     13220002   01800060    12a20062   scrambled

Seven probes, seven exact matches, across four orders of magnitude of LBA. XOR bytes 12.. of the first 69,150 sectors with the scrambler sequence and the result is an ordinary Mode 2 image:

python tools/cdiready.py probe
python tools/cdiready.py extract          # -> _work/data.bin

Sector 16 then reads CD-I , CD-RTOS, The Apprentice, and every other tool in tools/ works on _work/data.bin unchanged.

Sync survives because the scrambler starts at byte 12. That is the tell: an image with correct sync marks and nonsense headers is scrambled, not corrupt, and a disc whose TOC says the first track is audio when a CD-i volume descriptor is sitting in it is CD-i Ready.

The layout

       0 -    15   zeroes
      16 -    17   volume descriptors
      18 -  2267   filler, 2,250 sectors           <- head
    2268           path table
    2269 -  2270   free
    2271 - 57866   files, and two directory extents
    57868 - 60117  filler, 2,250 sectors           <- tail, identical to head
    60118 - 69149  9,032 sectors of digital silence, no sync at all
    69150 -279299  22 Red Book audio tracks

The head filler ends immediately before the path table and the tail filler begins immediately after the last directory sector. Whatever wrote them bracketed the volume.

The filler, and why it is worth two paragraphs

Both regions are Mode 2 Form 2 sectors with a correct sync, a correct MSF header, the subheader 00 00 20 00 on every one of the 4,500 — Form 2 with none of the data, audio or video bits set, a sector declaring itself to be of no type — and an EDC field of four zero bytes on every one of them. That is the same signature Link, Origami and Merlin carry.

The content is 16-bit little-endian PCM at 44,100 Hz, and here it needs no XOR at all. It comes off this disc in the clear:

head clip 18-640:      361,963 frames   8.21 s
   mean|x| 1750.7   mean|dx| 274.5   ratio 0.157   L==R 100.00%   peak 16383
head clip 1087-2205:   650,139 frames  14.74 s
   mean|x| 1776.2   mean|dx| 265.9   ratio 0.150   L==R 100.00%   peak 16383

XOR the same bytes with the scrambler and the ratio goes to 1.284, L==R to 0 %, which is what noise looks like. So the audio really is in the clear, and that is a direct confirmation of the mechanism the other pipelines had to infer: the CD-i authoring system writes this region in the post-scramble channel domain. A data-mode rip descrambles it on the way out and you see audio-XOR-scrambler; an audio-mode rip does not, and you see audio. Same object, two views, and this disc is the one that shows the second.

Two more measurements are worth having:

  • Peak is exactly 16,383 on both clips — 2^14 − 1, so the source was either 14-bit or deliberately attenuated 6 dB. Neither previously documented recording does this.
  • Left equals right on 100.00 % of frames. The 1993–95 recording correlates at 0.9988 but is not bit-identical; Soccer's 1997 clips are. This disc is in the Soccer family on that test and in neither on identity (see 10-cross-disc.md).

Twenty-eight bytes per sector are still gone

The boundary discontinuity test works here too, and it is the same answer:

head clip 18-640     boundary jump 1275.2   matches mean|x[i]-x[i-8]| (1258.6)
head clip 1087-2205  boundary jump 1200.9   matches mean|x[i]-x[i-8]| (1225.5)

Two frames either side of a sector boundary are 8 apart in the original stream, so 7 stereo frames — 28 bytes — are destroyed per sector: sync (12) + header (4) + subheader (8) + the four bytes at the EDC position. That is Link's and Merlin's number, reproduced on a different recording, from a differently made dump, with the audio never having been descrambled.

(Quote the lag index with its convention. mean|x[i]-x[i-k]| matching the boundary jump means k-1 frames are missing, not k, because the two surviving frames are k apart in the original. The conclusion — 28 bytes — is the same one section 2 of the platform notes reaches; only the label differs.)

And the tail is the same bytes

head  18-2267      5,229,000 B  md5 4e61f608e1f1455d9ad5b2a0615dbbd3
tail  57868-60117  5,229,000 B  md5 4e61f608e1f1455d9ad5b2a0615dbbd3
head == tail: True

Same length, same internal layout — 623 sectors of PCM, 446 of zero, 1,119 of PCM, 62 of zero — same MD5. The authoring tool wrote its filler block twice, bracketing the volume. Link, Origami, Merlin and Soccer all pad the tail with plain zeroes; this is a different tool, or the same tool used differently, and it is the first time the pattern has been seen.

The 9,032 sectors between the tail filler and track 1's INDEX 01 are a third thing again: no sync mark at all, every byte zero. Genuine CD-DA digital silence, not a data sector. Three padding mechanisms in one image. Classify padding by content, never by position.

Reproducing this

chdman extractcd -i "Apprentice The (Europe).chd" -o _work/disc.cue -ob _work/disc.bin
python tools/cdiready.py probe
python tools/cdiready.py extract
python tools/cdihead.py map
python tools/cdihead.py check
python tools/cdihead.py hash
python tools/cdihead.py stats