====== 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. ^Media^Description^ |5.25|5.25" Floppy Disk| |3.5|3.5" Floppy Disk| |8|8" Floppy Disk| ^Encoding^Description^ |fm|FM encoding| |mfm|MFM encoding| |m2fm|M2FM encoding| ^Density^Description^ |250|250kbps (4µs cell window) also covers 125K FM| |500|500kbps (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''. ^Value^Description^ |msb|Most significant bit comes first| |lsb|Least 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"''. ^Value^Description^ |be|Stored checksum is big endian| |le|Stored 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. The IBM standard uses a set of 4 values which are: cylinder, head, sector, and size. 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). For 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. === 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\\ The bit index of the start of the head number. If no value is provided, then it defaults to ''16''. ex: ''"headBitIndex": 16'' === headBitSize === Int\\ The number of bits that comprise the head number. If no value is provided, then it defaults to ''8''. If the format does not contain an entry for the head number, then you can set this value to ''0'' and the physical head number will be used instead. 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\\ The bit index of the start of the size value. If no value is provided, then it defaults to ''32''. ex: ''"sectorBitIndex": 32'' === sizeBitSize === Int\\ The number of bits that comprise the size value. If no value is provided, then it defaults to ''8''. If the format does not contain an entry for the size, then you can set this value to ''0'' and the size defined by ''sizeDefault'' will be used instead. ex: ''"sizeBitSize": 8'' === sizeDefault === Int\\ Used only if the format does not contain an entry for the size and you have ''sizeBitSize'' set to ''0''. This value defines the sector size to use for all sectors. The IBM standard uses the value 0 to describe a 128 byte sector, 1 for 256 bytes, 2 for 512 byes, etc. ex: ''"sizeDefault": 1'' ---- ===== 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''. ^Value^Description^ |none|No special handling is needed| |rx02|DEC 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 } ]