DSK format
- Not to be confused with the MGT format which is used with the DSK file extension for SAM Coupé disks.
The DSK format is a standard for storing floppy disk images. [1]
It is a container format which means that it can be used for differing filesystems, although it is usually used for the CPM2.2 variant used with Amstrad computers or copy-protected software for these machines.
An extended version of the format called EDSK was developed by Marco Vieth, Ulrich Doewich, and Kevin Thacker to enable images of disks utilizing certain copy protection schemes. The EDSK specification includes further extensions proposed by John Elliot and Simon Owen to store more information about the floppy disk controller state and support even more copy protection schemes respectively. [2]
Both format specifications are also available on the CPC Wiki
Links
[DSK file format] [EDSK extensions]
Format
There is both a basic and extended format of disks.
Extended format can be used for variable sector sizes and uPD765 status register results, so is the preferred version for copy protected disks.
Disk information block
The first 256 bytes are the "disk information block". There are two types, Normal and Extended
Normal
byte | notes |
---|---|
00-16 | "MV - CPCEMU Disk-File\r\n" - header for NORMAL disks. |
17-21 | Disk-Info\r\n" - Should consider this to be part of the header |
22-2f | Name of the creator - Can be any ASCII text or blank. |
30 | Number of tracks |
31 | Number of sides |
32-33 | Track size - This is the combined track size including the track information at the start of each block. |
34-FF | Unused |
Extended
This format allows for variable track sizes.
byte | notes |
---|---|
00-16 | "EXTENDED CPC DSK File\r\n" - Extended disk header |
17-21 | "Disk-Info\r\n" - Again, should be considered part of the disk header. |
22-2f | Name of the creator - Can be any ASCII text or blank. |
30 | Number of tracks |
31 | Number of sides |
32-33 | Not used |
34-FF | For each track, one byte representing MSB of track size, Eg, of the track length is 4864 (0x1300 = 9 sectors of 512 bytes + 256 bytes for the track header) then the byte would be 13 |
Track data
From $100 onwards is the track data. Note that some images don't put blank tracks in the file (I don't know if this only applies to Extended disks) In this case, any emulator should probably treat those tracks as unformatted, OR if they are in all other ways a valid CPM disk, a track with 9 sectors of 512 bytes filled with the default filler byte of 0xE5.
For each track:
byte | notes |
---|---|
00-0b | "Track Info\r\n" - Track header |
0c-0f | unused |
10 | Track number |
11 | Side number |
12-13 | unused |
14 | Sector size (1=256, 2=512, 3=1024 ect) |
15 | Number of sectors |
16 | Gap#3 length |
17 | Filler byte |
Next from 18 onward of the track info, is the sector list information. Note that the sectors in the file are not necessarily consecutive (Indeed i have found they are mostly interleaved) This list is the same order as the data in the file There are 8 bytes per record
byte | notes |
---|---|
00 | Track (Equivalent to "C" parameter in the 765 FDC) |
01 | Side (Equivalent to "H" parameter in the 765 FDC) |
02 | Sector ID (Equivalent to "R" parameter in the 765 FDC) (These are 1-9 for +3 disks, Others use $40-49 and $C0-C9) |
03 | Sector size (Equivalent to "N" parameter in the 765 FDC) should be the same as #14 above |
04 | FDC status register 1 after reading |
05 | FDC status register 2 after reading |
06-07 | Actual data length of the sector in bytes (EXTENDED only), 00 otherwise [1] |
[1] Note, bytes 0x06 and 0x07 containing the actual data length is used for some forms of copy protection where the written sector is smaller than the requested sector. These copy protection methods rely on the FDC returning an error (As returned in 0x04 and 0x05, so they may request a sector of 512 bytes, but the actual data on the disk is only (Say) 200 bytes. The sector still has (Sector+03) bytes reserved in the file, but any emulator should only return (Sector+6/7) bytes before reporting an FDC error to the disk (Preferably the ones stored in +04/05)
At the next $100 boundary, the actual data starts.
this is just a stream of data for each sector in the same order and with the same size as the data above.
Example
00000000 4d 56 20 2d 20 43 50 43 45 4d 55 20 44 69 73 6b |MV - CPCEMU Disk| 00000010 2d 46 69 6c 65 0d 0a 44 69 73 6b 2d 49 6e 66 6f |-File..Disk-Info| 00000020 0d 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 28 01 00 13 00 00 00 00 00 00 00 00 00 00 00 00 |(...............| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| ... 00000100 54 72 61 63 6b 2d 49 6e 66 6f 0d 0a 00 00 00 00 |Track-Info......| 00000110 00 00 00 00 02 09 4e e5 00 00 01 02 00 00 00 00 |......N.........| 00000120 00 00 02 02 00 00 00 00 00 00 03 02 00 00 00 00 |................| 00000130 00 00 04 02 00 00 00 00 00 00 05 02 00 00 00 00 |................| 00000140 00 00 06 02 00 00 00 00 00 00 07 02 00 00 00 00 |................| 00000150 00 00 08 02 00 00 00 00 00 00 09 02 00 00 00 00 |................| 00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000200 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 |................| ...
Breakdown
AMS header: ($00-$FF)
00000000 4d 56 20 2d 20 43 50 43 45 4d 55 20 44 69 73 6b |MV - CPCEMU Disk| 00000010 2d 46 69 6c 65 0d 0a |-File..| 00-16: "MV - CPCEMU Disk-File\r\n"
00000017 44 69 73 6b 2d 49 6e 66 6f 0d 0a |Disk-Info..| 17-21: "Disk-Info\r\n"
00000022 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 22-2f: <Name of creator, blank in this case>
00000030 28 01 00 13 30: Number of tracks: $28= 40 tracks 31: Number of sides: $01 = 1 side 32-33: Track size in file: $1300 = 4864 = 9 tracks*256 + 256 byte track header
00000034 00 00 00 00 00 00 00 00 00 00 00 00 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| ... 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| $34-$ff blank (unused in normal disks)
First track - Track header ($100-$200)
00000100 54 72 61 63 6b 2d 49 6e 66 6f 0d 0a |Track-Info..| Track: 00-0b: "Track-Info\r\n" 0000010c 00 00 00 Track: 00-0c: unused bytes 00000110 00 00 00 00 02 09 4e e5 |......N.| track: 10: track number: 0 track: 11: side number: 0 track: 12-13 unused track: 14: Sector size shift (1=256, 2=512, 3=1024 ect): 02=512 track: 15: Number of sectors: 9 track: 16: Gap#3length = 4E track: 17: Filler byte E5
From here on, we have 8 bytes for each sector. There are 9 sectors in this example:
00000118 00 00 01 02 00 00 00 00 Sector descriptor 1: Sector+00: Track=0 Sector+01: Side=0 Sector+02: Sector ID=1 Sector+03: Sector size shift(1=256, 2=512, 3=1024 ect): 02=512 Sector+04: uPD765 status register 1 after reading: 00 Sector+05: uPD765 status register 2 after reading: 00 Sector+06: Actual data length: LSB - EXTENDED DISKS ONLY, BLANK HERE ** Sector+07: Actual data length: MSB - EXTENDED DISKS ONLY, BLANK HERE **
00000120 00 00 02 02 00 00 00 00 T:0 S:0 ID:2 sz:512 sr1:0 sr2:0 unused unused 00000128 00 00 03 02 00 00 00 00 T:0 S:0 ID:3 sz:512 sr1:0 sr2:0 unused unused 00000130 00 00 04 02 00 00 00 00 T:0 S:0 ID:4 sz:512 sr1:0 sr2:0 unused unused 00000138 00 00 05 02 00 00 00 00 T:0 S:0 ID:5 sz:512 sr1:0 sr2:0 unused unused 00000140 00 00 06 02 00 00 00 00 T:0 S:0 ID:6 sz:512 sr1:0 sr2:0 unused unused 00000148 00 00 07 02 00 00 00 00 T:0 S:0 ID:7 sz:512 sr1:0 sr2:0 unused unused 00000150 00 00 08 02 00 00 00 00 T:0 S:0 ID:8 sz:512 sr1:0 sr2:0 unused unused 00000158 00 00 09 02 00 00 00 00 T:0 S:0 ID:9 sz:512 sr1:0 sr2:0 unused unused
After 9 sectors, blank until the next $100 boundary.
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Sector bytes in order.
00000200 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 |................| ...
- ↑ DSK specification http://cpctech.cpc-live.com/docs/dsk.html
- ↑ EDSK specification http://cpctech.cpc-live.com/docs/extdsk.html