Adding Support for a modified IBM Sectored Disk Format

As of Applesauce 1.66, it is possible for users to be able to add their own format definitions to be used by Applesauce. When you add a format, it will automatically be recognized everywhere in the client software such as the Disk Analyzer and Fast Imager. In order to add new formats, there is an Applesauce directory in your Documents folder. Within this folder there is a Formats one that contains the file ibmsector_config.json. The IBM sector configuration files are text files in JSON format. The root object of the JSON should be an array. A single file can have as may format descriptions as desired. Whenever you edit the ibmsector_config.json, you will need to restart the Applesauce client in order to have it load the changes.

Creating a format definition is a highly technical process and if you are not very familiar with how disks are structured, this will likely seem a daunting task.

There is an example of a configuration file at the end of this document.


Format Identification

name

String - Required
This is a descriptive name of the format. It must be unique, but otherwise is only used for informational purposes.

ex: “name”: “IBM”

settings

String - Required
This name is used by the Fast Imager to remember user preferences related to this format.

ex: “settings”: “IbmMFM”

fastname

String - Required
This is used by the Fast Imager when displaying the name of this format.

ex: “fastname”: “IBM”

export

[String]
An array of disk image format names that can be used to save images of this format. It uses the internal names of formats. Raw disk output (IMG) will always be available.

ex: “export”: [“any_imd”]


Media and Geometry

encodingAndMedia

[String] - Required
Array of the physical type of media used as well as the encoding and density. It is represented as a string structured as {media}_{encoding}_{density}. If the format supports more than a single value for either the media or density parameters you can use a * as a wildcard value. Being as specific as possible speeds up the analysis process as it limits the number of comparisons that need to be done.

MediaDescription
5.255.25“ Floppy Disk
3.53.5” Floppy Disk
88“ Floppy Disk
EncodingDescription
fmFM encoding
mfmMFM encoding
m2fmM2FM encoding
DensityDescription
250250kbps (4µs cell window) also covers 125K FM
500500kbps (2µs cell window)

ex: “encodingAndMedia”: [“5.25_mfm_*”,”8_mfm_500]

bitOrder

String
Bytes stored on disk are most commonly stored in “most significant bit” order, although some platforms store bytes in “least significant bit” order. This value allows you to specify which order should be used. If no value is provided, then it defaults to msb.

ValueDescription
msbMost significant bit comes first
lsbLeast significant bit comes first

ex: “bitOrder”: “lsb”

endian

String
Byte order of any values larger than 8-bits like the CRC-16. If no value is provided, then it defaults to “be”.

ValueDescription
beStored checksum is big endian
leStored checksum is little endian

ex: “addrCksumEndian”: “le”


Sector Structure and Synchronization

syncPatterns

[String] - Required
All disk formats have sync pattern(s) that inform the disk controller about how to synchronize itself to the proper start of bytes. Applesauce uses a sequence of 48 bits (6 bytes) that are represented by their hex values. Please note that the values used here are the values physically on the media for FM or MFM encoding, so every logical byte (8 bits) is represented by 16 bits. The last value of the sync pattern is also typically used as a start marker for the disk controller. If there are multiple possible sync sequences, then include them all.

ex: “syncPatterns”: [“AAAAAAAAFFEF”]


Address Field Structure

addrMarkers

[String] - Required
Array of valid address field marker values in hex.

ex: “addrMarkers”: [“FE”]

addrMarkerInset

Int - Required
Number of bytes from the last synchronization byte to the marker. FM encoding uses a marker that is also the synchronization byte, so it has a value of 0. Whereas MFM encoding tends to have a sequence of 3 A1 bytes that are the synchronization bytes followed by the marker, so it has a value of 1.

ex: “addrMarkerInset”: 1

addrFieldSize

Int - Required
Byte size of the address field following the marker.

ex: “addrFieldSize”: 6

addrStoredCRCIndex

Int - Required
Byte index of the start of the stored checksum relative to the address marker (0 = address marker).

ex: “addrStoredCRCIndex”: 5

addrCRCFromIndex

Int - Required
Byte index of the first byte of the address field that needs to be checksummed, relative to the address marker (0 = address marker).

ex: “addrCRCFromIndex”: 1

addrCRCToIndex

Int - Required
Byte index of the last byte of the address field that needs to be checksummed, relative to the address marker (0 = address marker).

ex: “addrCRCToIndex”: 4

addrCRCInit

Int
Starting value (seed) of the CRC-16. If omitted, then it defaults to 65535 (FFFF hex).

ex: “addrCRCInit”: 0

addrCRCPoly

Int
The polynomial to use for the CRC-16. If omitted, then it defaults to 4129 (1021 hex).

ex: “addrCRCPoly”: 0

addrCRCRefIn

Boolean
True if the input data should be reflected (bit reversed) before passing to the CRC-16. Defaults to false.

ex: “addrCRCRefIn”: false

addrCRCRefOut

Boolean
True if the CRC-16 result should be reflected (bit reversed) before returning. Defaults to false.

ex: “addrCRCRefOut”: false

addrCRCXorOut

Int
A 16-bit value that is xor'ed with checksum post calculation. If no value is provided, then it defaults to 0 which means not to perform an xor.

ex: “addrCRCXorOut”: 0


Sector Identification

These values are within the address field and used to identify which sector it is. All bit indexes referenced below are relative to the address marker (0 is the first bit of the address marker, 8 is the start of the byte following the address marker).

trackBitIndex

Int - Required
The bit index of the start of the track number.

ex: “trackBitIndex”: 8

trackBitSize

Int
The number of bits that comprise the track number. If no value is provided, then it defaults to 8.

ex: “trackBitSize”: 8

headBitIndex

Int - Required
The bit index of the start of the head number.

ex: “headBitIndex”: 16

headBitSize

Int
The number of bits that comprise the head number. If no value is provided, then it defaults to 8.

ex: “headBitSize”: 8

sectorBitIndex

Int - Required
The bit index of the start of the sector number.

ex: “sectorBitIndex”: 24

sectorBitSize

Int
The number of bits that comprise the sector number. If no value is provided, then it defaults to 8.

ex: “sectorBitSize”: 8

sizeBitIndex

Int - Required
The bit index of the start of the size value. The IBM standard uses the value 0 to describe a 128 byte sector, 1 for 256 bytes, 2 for 512 byes, etc.

ex: “sectorBitIndex”: 32

sizeBitSize

Int
The number of bits that comprise the size value. If no value is provided, then it defaults to 8.

ex: “sizeBitSize”: 8


Data Field Structure

dataMarkers

[String] - Required
Array of data field marker values in hex.

ex: “dataMarkers”: [“FB”, “F8”]

dataMarkerInset

Int - Required
Number of bytes from the last synchronization byte to the marker. FM encoding uses a marker that is also the synchronization byte, so it has a value of 0. Whereas MFM encoding tends to have a sequence of 3 A1 bytes that are the synchronization bytes followed by the marker, so it has a value of 1.

ex: “dataMarkerInset”: 1

dataStartIndex

Int - Required
Byte index of the start of the actual sector data relative to the data marker (0 = data marker).

ex: “dataStartIndex”: 1

dataStoredCRCOffset

Int - Required
Byte index of the start of the stored checksum value relative to the data field. Positive values are offset from the end of the data (0 = immediately following data) and negative numbers are relative to the start of the data (-2 = immediately preceding the data).

ex: “dataStoredCRCOffset”: 0

dataCRCFromOffset

Int - Required
Byte index offset (0 = data marker) of first byte used for checksum calculation.

ex: “dataCRCFromOffset”: 0

dataCRCToOffset

Int - Required
Byte index offset (0 = last byte of data field) of last byte used for checksum calculation. The data field size is determined by the size value provided in the address field.

ex: “dataCRCToOffset”: 0

dataCRCInit

Int
Starting value (seed) of the CRC-16. If omitted, then it defaults to 65535 (FFFF hex).

ex: “dataCRCInit”: 0

dataCRCPoly

Int
The polynomial to use for the CRC-16. If omitted, then it defaults to 4129 (1021 hex).

ex: “dataCRCPoly”: 0

dataCRCRefIn

Boolean
True if the input data should be reflected (bit reversed) before passing to the CRC-16. Defaults to false.

ex: “dataCRCRefIn”: false

dataCRCRefOut

Boolean
True if the CRC-16 result should be reflected (bit reversed) before returning. Defaults to false.

ex: “dataCRCRefOut”: false

dataCRCXorOut

Int
A 16-bit value that is xor'ed with checksum post calculation. If no value is provided, then it defaults to 0 which means not to perform an xor.

ex: “dataCRCXorOut”: 0

specialDataHandling

String
If the data field required special handling/processing, then that can be indicated here. Defaults to none.

ValueDescription
noneNo special handling is needed
rx02DEC RX02 format uses an FM sector structure, but the data fields contain MFM encoded data

ex: “specialDataHandling”: “rx02”


Example Configuration File

[
	{
		"name": "IBM MFM",
		"enabled": true,
		"settings": "IbmMFM",
		"fastname": "IBM",
		"encodingAndMedia": ["*_mfm_*"],
		"syncPatterns": ["AAAA44894489", "AAAA52245224"],
		"addrMarkers": ["FE"],
		"addrMarkerInset": 1,
		"addrFieldSize": 6,
		"addrStoredCRCIndex": 5,
		"addrCRCFromIndex": -3,
		"addrCRCToIndex": 4,
		"trackBitIndex": 8,
		"headBitIndex": 16,
		"sectorBitIndex": 24,
		"sizeBitIndex": 32,
		"dataMarkers": ["FB","F8"],
		"dataMarkerInset": 1,
		"dataStartIndex": 1,
		"dataStoredCRCOffset": 0,
		"dataCRCFromOffset": -3,
		"dataCRCToOffset": 0
	}
]