DSK format

From Sinclair Wiki
Jump to navigation Jump to search
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  |................|
...