SAMdisk — Amstrad CPC

To use original 3” CPC disks you’ll need a 3” drive and a special cable [link currently dead] to connect it to your PC.

If you’re only looking to use existing software images it may be easier to connect a 3.5” drive to your CPC instead.

Floppy to Image

To create a disk image from an existing CPC disk use:

SAMdisk a: image.dsk -c42 -h0 --gaps

That reads 42 tracks from the first side of the disk, including inter-sector gaps known to be required by copy-protection checks on some CPC disks.

You can change the name of the output image, but keep the .dsk file extension to ensure it’s created in EDSK format.

Image to Floppy

To write a CPC disk image back to a real disk use:

SAMdisk image.dsk a:

The default behaviour writes all tracks in the source image, but you can specify your own range to override that. Adding -c42 -h0 ensures that exactly 42 tracks are written to the first side only, ignoring any extra tracks or padding shorter images with blank tracks.

Whether you’re using disk images in an emulator or writing them back to disk for use on a real CPC, it’s essential that the source image is complete. Some existing CPC dumps are missing gap data or extra weak sector copies, and may not work without being redumped.

Special Formats

Most CPC disks are supported automatically, even if they include custom formatting tricks such as mixed sector sizes, 8K sectors, fake error sectors, etc. A few protections require special attention to ensure they’re written back to disk accurately enough to pass copy-protection checks. SAMdisk is able to handle the following:

KBI-19

Examples: Titan, Knight Force, Dakar Moto, Wild Streets, Fugitif, Canadair, Secret England, …

The protection is usually on cyl 40, though Titan uses cyl 14 instead. The track appears to contain 19 valid 512-byte sectors, which is impossible for a double-density disk!

250Kbps MFM, 19 sectors, 512 bytes/sector:
   40.0  0 1 4 7 10 13 16 2 5 8 11 14 17 3 6 9 12 15 18
    6295: 72 574 121 121 654 121 121 654 121 121 654 121 121 654 121 121 654 121 121

The sector offsets reveal the true layout, showing that only sectors 0,7,16,8,17,9,18 are full size, with the remaining sectors overlapping them. The address marks, gaps and even CRCs of the later sectors form part of the data area of earlier sectors, crafted so the FDC checksums are all correct. It’s a clever trick, and something that requires single-pass formatting (usually a trace machine) to reproduce exactly.

The protection check ensures all 19 sectors can be read from without error, and that a string signature in the gap area is present.

It was originally thought this protection could be written back on the PC FDC, with multiple headers positioned against a single data field. However, this only worked with the basic FDC implementations found in Super-I/O chips, not original dedicated FDC chips. Writing requires a device that can write the track in a single pass.

This protection requires no special support to work in emulators; each of the 19 data fields is stored separately in the disk image, so the overlaps aren’t a problem.

Speedlock Weak Sector

Examples: (part-weak): After Burner, Target Renegade, Victory Road, The Train, Wanderer 3D, PHM Pegasus, (fully-weak): 6-Pak, We Are The Champions, The Archon Collection, …

The protection is on cyl 0, and appears as a 9-sector track with the 8th sector (id=72) showing a data CRC error. The contents of the error sector change between successive reads, with either all or just part of the contents appearing different.

250Kbps MFM, 9 sectors, 512 bytes/sector:
    0.0  65 66 67 68 69 70 71 72[m3,dc] 73d
          diff(72): =256 -32 +48 -176

This example represents a partially weak sector; the first 256 bytes of the sector are the same each time, the next ~32 bytes differ between reads, a further ~48 bytes are filler bytes (but have changing value), and the final ~176 bytes differ between reads. In some early versions of Speedlock the weak and filler blocks were 16 and 64 bytes in length, respectively.

The protection checks vary between titles, but in all cases it reads up to 3 copies of the sector and expects to encounter a data CRC error and a difference between the copies read. In some versions of the protection it checks for unchanging filler at the start of the data field. Some also check for a patch of filler bytes beyond the weak area.

To write the weak sector SAMdisk prepares the track area using an 07 filler written at 300Kbps, which was found to be particularly effective at losing FDC sync when the data is read back at a normal 250Kbps. A normal sector header and data address mark is then written to overlap the ‘weak’ area, followed by the required number of constant bytes in the data area. For partially weak sectors a constant block of 256+80=336 bytes followed by a weak area of 176 bytes is sufficient to satisfy all known variations of the protection check.

For this protection to work in emulators they must support the EDSK extension to use multiple copies of error sectors, ideally cycling through the different data copies each time the sector is read. At the time of writing only WinAPE supports this.

Rainbow Arts Weak Sector

Examples: Bad Cat, Rock ‘n Roll, Spherical, …

The protection is similar to the Speedlock weak sector above, but the protected track is cyl 40 and the 2nd sector (id=198) contains a weak area after 100 constant bytes:

250Kbps MFM, 9 sectors, 512 bytes/sector:
   40.0  193 198[m3,dc] 194 109 195 200 196 201 197
          diff(198): =100 -207 +205

The protection reads the weak sector 3 times, sampling bytes from data offset 105+106 in each read. If a difference is found between any of the copies the check is passed. In the known titles, no further checks are made on other areas of the weak sector data.

Reading the disk requires no special handling, with SAMdisk storing 3 samples of any error sector encountered. Writing the protection back to disk uses the same technique as Speedlock, but with a fixed 100 bytes written before the weak area. Emulator support also has the same requirements as Speedlock above.

KBI-10 Weak Sector

Used by: Pacific, Asterix et la Potion Magique, Duel 2000, Fer & Flamme, Histoire D’Or, Lucky Luke - Nitroglycerine, …

Another weak sector protection, this time found on cyl 39. The 10th sector (id=202, size=256) contains a couple of small weak areas:

250Kbps MFM, 10 sectors, 512 bytes/sector:
  39.0  193 198 194 199 195 200 196 201 197 202[n1,m3,dc]
         diff(202): =4 -4 +124 -4 +120

The protection reads the weak sector 10 times, keeping only the first 16 bytes of each. The byte at offset 0 in each copy must be ‘K’, from the “KBI” signature string. The byte at offset 5 must change at least once between copies to pass the weak sector check. Finally, the bytes at offsets 14 and 15 must match, though the actual value is not important. The second weak area doesn’t appear to be checked at all.

This is a difficult protection to write back to disk reliably, in its original format. The weak check is at a strict point early in the sector, and is closely followed by a non-weak check. This close proximity prevents us using the same 300Kbps trick as used for other weak sectors. To achieve a similar effect we deliberately create write-splices just ahead of the weak point, to vary the FDC sync between successive reads. SAMdisk tests the weak point after writing, repeating the process if necessary.

Alternatively, you can use the --no-weak option during writing. This uses a duplicate sector to achieve the weak effect, with the data contents varying in the appropriate locations. This changes the original track format but is more reliable.

Infogrames / Loriciel Gap Data

Examples: Jim Power, Skweek, Mach 3, Sapiens, Chamonix Challenge, Championship Water-Skiing, Clash, Top Secret, The Sydney Affair, Stir Crazy featuring Bobo, …

This is a gap-based protection, usually found on cyl 39, though Jim Power uses cyl 41. It appears to be a normal 9-sector track, but there are filler bytes hidden in the gap area following the data field of the first sector:

250Kbps MFM, 9 sectors, 512 bytes/sector:
   39.0  65[g28] 67 69 71 73 66 68 70 72

Skweek uses the same technique but with sector numbers from 193 instead of 65, and a 2:1 interleave instead of 5:1.

The protection check uses READ_TRACK with a 1K sector size, but reading only 519 bytes from it: 512 data + 2 CRC + 5 gap3. The 5 gap bytes must all be F7 for the protection to be passed. Failing the protection isn’t always made apparent at the point it is checked — Mach 3 only crashes when the player flies through the first archway during gameplay! (thanks to Nich Campbell for that important detail).

Writing a disk using the protection requires no special handling, as long as the gap data is present in the source image. SAMdisk uses a multi-pass technique to add the gap data, initially formatting the sector with a 1K size header and terminating the data write when the required data+crc+gap bytes have been written. It then writes a new sector header with the correct size, again terminating after the CRC bytes of the header have been written, leaving the extended data field in place.

For this protection to work in emulators they must support the EDSK extension to include crc+gap data at the end of a sector’s data field. They also need to support over-reading of the first sector using the READ_TRACK command, as well as the protection reading only 519 bytes during the command, generating an overrun when the FDC FIFO overflows.

Disc Manager by Goldmark Systems

The protected track is on cyl 1, which appears to be a normal 9-sector track matching most others on the disk:

250Kbps MFM, 9 sectors, 512 bytes/sector:
    1.0  65[g35] 70 66[g35] 71 67[g35] 72 68 73 69
           6242: 172 646 644 644 644 644 646 645 644 [913]

The protection uses READ_TRACK to read 3 sectors using a 1K sector size. Each 1K read starts from the next encountered data field, with the final 512 bytes including the data CRC, gap3 area, next sector header, and part of the following data field. In all, gap data is read from between the sector pairs 65/70, 66/71 and 67/72.

The protection checks a byte at offset 546 (32 bytes into gap3 area) in each of the three 1K blocks read. The first and last are expected to be normal 4E filler, but the middle one (after sector 66) must be something other than 4E. As well as the content check, the protection relies on a lack of splice points after the data fields of sectors 65,66,67, which would usually cause loss of data sync when reading into the gap areas.

If the original disk can’t be dumped reliably, it’s possible to create an alternative format to pass the protection. Having three 1024-byte sectors with the appropriate byte at offset 546 in each is good enough:

250Kbps MFM, 3 sectors, 1024 bytes/sector:
    1.0  65 66 67

Emulator requirements are the same as other gap protections, so it should work on any emulator supporting gap data. The second method for fixing should work on any emulator with a working READ_TRACK implementation.

Thanks

Many thanks to Philippe Depre, Denis Lechevalier, Nicholas Campbell, Brice Rivé, Tomaz Kac, and Bruce Canu for help with testing, and providing details and sample images.