meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
adv:hardsectorconf [2022/06/07 02:57] – created diskblitzadv:hardsectorconf [2023/06/12 13:11] (current) – Add sectorVerify david-schmidt
Line 1: Line 1:
 ====== Adding Support for a Hard Sectored Disk Format ====== ====== Adding Support for a Hard Sectored Disk Format ======
  
-Info how to do it.+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 ''hardsector_config.json''. The hard 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 ''hardsector_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. 
 +The hard 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. 
 + 
 +There is an example of a configuration file with 2 definitions in it at the end of this document.
  
 ---- ----
-===== Identification =====+===== Format Identification =====
  
 === name === === name ===
 String - //Required//\\ String - //Required//\\
-This is a descriptive name of the format. It is only used for informational purposes.+This is a descriptive name of the format. It must be unique, but otherwise is only used for informational purposes.
  
-ex: ''"name": "North Star"''+ex: ''"name": "North Star SD"''
  
 === settings === === settings ===
Line 18: Line 23:
 ex: ''"settings": "525NorthStar_Hard10x256"'' ex: ''"settings": "525NorthStar_Hard10x256"''
  
 +=== fastname ===
 +String - //Required//\\
 +This is used by the Fast Imager when displaying the name of this format.
 +
 +ex: ''"fastname": "North Star"''
  
 === export === === export ===
Line 24: Line 34:
  
 ex: ''"export": ["northstar_nsi"]'' ex: ''"export": ["northstar_nsi"]''
 +
 +=== enabled ===
 +[Boolean] - //Required//\\
 +Set to ''true'' if you would like this named format definition to be considered when analyzing disks. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"enabled": true''
  
  
Line 135: Line 151:
 If the disk uses address and data fields (and your ''sectorFields'' is set to ''adda''), then the following settings allow you to specify how the address field is structured. If your ''sectorFields'' is ''blob'', then you can skip this section. If the disk uses address and data fields (and your ''sectorFields'' is set to ''adda''), then the following settings allow you to specify how the address field is structured. If your ''sectorFields'' is ''blob'', then you can skip this section.
  
 +=== addrSync ===
 +String - //Required//\\
 +Sync values leading up to the marker. These values are in hex.
 +
 +ex: ''"addrSync": "0000"''
 +
 +=== addrMarker ===
 +String - //Required//\\
 +Address field marker value in hex.
 +
 +ex: ''"addrMarker": "FB"''
 +
 +=== addrMarkerBitMask ===
 +String - //Optional//\\
 +Address field marker bit mask to apply - value in hex.
 +
 +ex: ''"addrMarkerBitMask": "0F"''
 +
 +=== addrFieldSize ===
 +Int - //Required//\\
 +Byte size of the address field following the marker.
 +
 +ex: ''"addrFieldSize": 6''
 +
 +=== addrCksumType ===
 +String - //Required//\\
 +Type of checksum to be used to validate the address field.
 +
 +^Value^Description^
 +|none|There is no checksum|
 +|8xrl|8-bit rolling xor - xor data into register and then rotate left|
 +|8add|8-bit add|
 +|8adc|8-bit add with carry|
 +|16add|16-bit add|
 +|12adc|16-bit add with carry|
 +|crc16|16-bit CRC (additional parameters can be set below)|
 +
 +ex: ''"addrCksumType": "8xrl"''
 +
 +=== addrCksumIndex ===
 +Int - //Required//\\
 +Byte index of the start of the stored checksum relative to the address marker (0 = address marker).
 +
 +ex: ''"addrCksumIndex": 5''
 +
 +=== addrCksumByteSize ===
 +Int - //Required//\\
 +Number of bytes for the stored checksum.
 +
 +ex: ''"addrCksumByteSize": 1''
 +
 +=== addrCksumEndian ===
 +String\\
 +Byte order of the stored checksum. 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"''
 +
 +=== addrCksumFromIndex ===
 +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: ''"addrCksumFromIndex": 1''
 +
 +=== addrCksumToIndex ===
 +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: ''"addrCksumToIndex": 4''
 +
 +=== addrCksumInit ===
 +Int\\
 +A 32-bit value that is used as the initial value of the checksum. If no value is provided, then it defaults to ''0''.
 +
 +ex: ''"addrCksumInit": 0''
 +
 +=== addrCksumXorOut ===
 +Int\\
 +A 32-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: ''"addrCksumXorOut": 0''
 +
 +=== addrCksumPoly ===
 +Int\\
 +A 32-bit value that is the polynomial to be used for CRC checksums. If no value is provided, then it defaults to ''4129'' (0x1021) for crc16 checksums.
 +
 +ex: ''"addrCksumPoly": 4129''
 +
 +=== addrCksumRefIn ===
 +Boolean\\
 +If ''true'', then the data bytes will be reflected (bit-endian reversed (eg: 0x80 becomes 0x01)) on input to the checksum algorithm. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"addrCksumRefIn": true''
 +
 +=== addrCksumRefOut ===
 +Boolean\\
 +If ''true'', then the result of the checksum algorithm will have its data reflected (bit-endian reversed) on output. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"addrCksumRefOut": true''
 +
 +=== addrEpilog ===
 +String\\
 +Some formats use bytes that follow the address field as part of the data integrity check. If an epilog is included, then it will be verified in order to consider a sector as being valid. Epilog values are in hex.
 +
 +ex: ''"addrEpilog": "DEAAEB"''
 +
 +=== addrEpilogIndex ===
 +Int - //Required if including an addrEpilog//\\
 +Byte index of the start of the epilog relative to the address marker (0 = address marker).
 +
 +ex: ''"addrEpilogIndex": 258''
  
 ---- ----
 ===== Sector Identification ===== ===== Sector Identification =====
  
 +If the format uses an address field, then the bit indexes referenced below are relative to the address marker. Otherwise they are relative to the data marker.
 +
 +=== volumeDerived ===
 +String\\
 +Method that is to be used to determine the volume number for a sector. If no value is provided, then it defaults to ''none''.
 +
 +^Value^Description^
 +|none|This format does not use a volume number|
 +|data|The volume number should be derived from data on the disk|
 +
 +ex: ''"volumeDerived": "data"''
 +
 +=== volumeBitIndex ===
 +Int - //Required if volumeDerived is "data"//\\
 +The bit index of the start of the volume number. This index is relative to the field marker with ''0'' being the first bit of the marker.
 +
 +ex: ''"volumeBitIndex": 8''
 +
 +=== volumeBitSize ===
 +Int - //Only used if volumeDerived is "data"//\\
 +The number of bits that comprise the volume number. If no value is provided, then it defaults to ''8''.
 +
 +ex: ''"volumeBitSize": 8''
 +
 +=== trackDerived ===
 +String - //Required//\\
 +Method that is to be used to determine the track number for a sector.
 +
 +^Value^Description^
 +|data|The track number should be derived from data on the disk|
 +|phys|The track number should be derived from the physical track|
 +
 +ex: ''"trackDerived": "phys"''
 +
 +=== trackBitIndex ===
 +Int - //Required if trackDerived is "data"//\\
 +The bit index of the start of the track number. This index is relative to the field marker with ''0'' being the first bit of the marker.
 +
 +ex: ''"trackBitIndex": 8''
 +
 +=== trackBitSize ===
 +Int - //Only used if trackDerived is "data"//\\
 +The number of bits that comprise the track number. If no value is provided, then it defaults to ''8''.
 +
 +ex: ''"trackBitSize": 8''
 +
 +=== trackVerify ===
 +Boolean - //Only used if trackDerived is "data"//\\
 +Set to ''true'' if you would like to validate that the track number matches the physical track number. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"trackVerify": true''
 +
 +=== headDerived ===
 +String\\
 +Method that is to be used to determine the head number for a sector. If no value is provided, then it defaults to ''none''.
 +
 +^Value^Description^
 +|none|This format does not use a head number|
 +|data|The head number should be derived from data on the disk|
 +|phys|The head number should be derived from the physical head|
 +
 +ex: ''"headDerived": "data"''
 +
 +=== headBitIndex ===
 +Int - //Required if headDerived is "data"//\\
 +The bit index of the start of the head number. This index is relative to the field marker with ''0'' being the first bit of the marker.
 +
 +ex: ''"headBitIndex": 16''
 +
 +=== headBitSize ===
 +Int - //Only used if headDerived is "data"//\\
 +The number of bits that comprise the head number. If no value is provided, then it defaults to ''8''.
 +
 +ex: ''"headBitSize": 8''
 +
 +=== sectorDerived ===
 +String - //Required//\\
 +Method that is to be used to determine the sector number for a sector.
 +
 +^Value^Description^
 +|data|The sector number should be derived from data on the disk|
 +|phys|The sector number should be derived from the physical sector index holes|
 +
 +ex: ''"sectorDerived": "data"''
 +
 +=== sectorBitIndex ===
 +Int - //Required if sectorDerived is "data"//\\
 +The bit index of the start of the sector number. This index is relative to the field marker with ''0'' being the first bit of the marker.
 +
 +ex: ''"sectorBitIndex": 24''
 +
 +=== sectorBitSize ===
 +Int - //Only used if sectorDerived is "data"//\\
 +The number of bits that comprise the sector number. If no value is provided, then it defaults to ''8''.
 +
 +ex: ''"sectorBitSize": 8''
 +
 +=== sectorVerify ===
 +Boolean - //Only used if sectorDerived is "data"//\\
 +Set to ''true'' if you would like to validate that the sector number matches the physical sector number. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"sectorVerify": true''
  
 ---- ----
 ===== Data Field Structure ===== ===== Data Field Structure =====
 +
 +=== dataSync ===
 +String - //Required//\\
 +Sync values leading up to the marker. These values are in hex.
 +
 +ex: ''"dataSync": "0000"''
 +
 +=== dataMarker ===
 +String - //Required//\\
 +Data field marker value in hex.
 +
 +ex: ''"dataMarker": "FB"''
 +
 +=== dataMarkerBitMask ===
 +String - //Optional//\\
 +Data field marker bit mask to apply - value in hex. The length of the bit mask should equal the length of the marker.  This value is used to "mask off" particular bits to exclude them from consideration when locating a marker.  A binary value of 1 in any position will retain that bit for comparison.  A binary value of 0 in any position will exclude that bit from comparison.
 +
 +ex: ''"dataMarkerBitMask": "0F"''
 +
 +=== dataStartIndex ===
 +Int - //Required//\\
 +Byte index of the start of the data relative to the data marker (0 = data marker byte).
 +
 +ex: ''"dataStartIndex": 1''
 +
 +=== dataSize ===
 +Int - //Required//\\
 +Number of bytes of data.
 +
 +ex: ''"dataSize": 256''
 +
 +=== dataCksumType ===
 +String - //Required//\\
 +Type of checksum to be used to validate the data.
 +
 +^Value^Description^
 +|none|There is no checksum|
 +|8xrl|8-bit rolling xor - xor data into register and then rotate left|
 +|8add|8-bit add|
 +|8adc|8-bit add with carry|
 +|16add|16-bit add|
 +|12adc|16-bit add with carry|
 +|crc16|16-bit crc (additional parameters can be set below)|
 +
 +ex: ''"dataCksumType": "8xrl"''
 +
 +=== dataCksumIndex ===
 +Int - //Required//\\
 +Byte index of the start of the stored checksum relative to the data marker (0 = data marker).
 +
 +ex: ''"dataCksumIndex": 257''
 +
 +=== dataCksumByteSize ===
 +Int - //Required//\\
 +Number of bytes for the stored checksum.
 +
 +ex: ''"dataCksumByteSize": 1''
 +
 +=== dataCksumEndian ===
 +String\\
 +Byte order of the stored checksum. 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: ''"dataCksumEndian": "le"''
 +
 +=== dataCksumFromIndex ===
 +Int - //Required//\\
 +Byte index of the first byte of data that needs to be checksummed, relative to the data marker (0 = data marker).
 +
 +ex: ''"dataCksumFromIndex": 1''
 +
 +=== dataCksumToIndex ===
 +Int - //Required//\\
 +Byte index of the last byte of disk data that needs to be checksummed, relative to the data marker (0 = data marker).
 +
 +ex: ''"dataCksumToIndex": 256''
 +
 +=== dataCksumInit ===
 +Int\\
 +A 32-bit value that is used as the initial value of the checksum. If no value is provided, then it defaults to ''0''.
 +
 +ex: ''"dataCksumInit": 0''
 +
 +=== dataCksumXorOut ===
 +Int\\
 +A 32-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: ''"dataCksumXorOut": 0''
 +
 +=== dataCksumPoly ===
 +Int\\
 +A 32-bit value that is the polynomial to be used for CRC checksums. If no value is provided, then it defaults to ''4129'' (0x1021) for crc16 checksums.
 +
 +ex: ''"dataCksumPoly": 4129''
 +
 +=== dataCksumRefIn ===
 +Boolean\\
 +If ''true'', then the data bytes will be reflected (bit-endian reversed (eg: 0x80 becomes 0x01)) on input to the checksum algorithm. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"dataCksumRefIn": true''
 +
 +=== dataCksumRefOut ===
 +Boolean\\
 +If ''true'', then the result of the checksum algorithm will have its data reflected (bit-endian reversed) on output. If no value is provided, then it defaults to ''false''.
 +
 +ex: ''"dataCksumRefOut": true''
 +
 +=== dataEpilog ===
 +String\\
 +Some formats use bytes that follow the sector data as part of the data integrity check. If an epilog is included, then it will be verified in order to consider a sector as being valid. Data epilog values are in hex.
 +
 +ex: ''"dataEpilog": "DEAAEB"''
 +
 +=== dataEpilogIndex ===
 +Int - //Required if including a dataEpilog//\\
 +Byte index of the start of the epilog relative to the data marker (0 = data marker).
 +
 +ex: ''"dataEpilogIndex": 258''
 +
 +=== dataProcess ===
 +[String]\\
 +Used if the sector data requires any kind of special processing. Multiple values can be used.
 +
 +^Value^Description^
 +|flip16|Data is 16-bit words that need to be endian flipped|
 +|negate|Bitwise negation of sector data|
 +
 +ex: ''"dataProcess": ["negate"]''
 +
 +----
 +===== Example Configuration File =====
 +
 +<code>
 +[
 + {
 + "name": "North Star",
 + "enabled": true,
 + "settings": "525NorthStar_Hard10x512",
 + "export": ["northstar_nsi"],
 + "media": "5.25",
 + "encoding": "mfm_250",
 + "trackCount": 35,
 + "trackBase": 0,
 + "headCount": 2,
 + "sectorsPerTrack": 10,
 + "sectorBase": 0,
 + "syncPatterns": ["AAAAAAAA5545"],
 + "sectorFields": "blob",
 + "trackDerived": "phys",
 + "headDerived": "phys",
 + "sectorDerived": "phys",
 + "dataSync": "0000",
 + "dataMarker": "FB",
 + "dataStartIndex": 2,
 + "dataSize": 512,
 + "dataCksumType": "8xrl",
 + "dataCksumIndex": 514,
 + "dataCksumByteSize": 1,
 + "dataCksumFromIndex": 2,
 + "dataCksumToIndex": 513
 + },
 + {
 + "name": "Heath/Zenith H-17",
 + "enabled": true,
 + "settings": "525HeathH17_Hard10x256",
 + "export": ["heath_h8d"],
 + "media": "5.25",
 + "encoding": "fm_250",
 + "trackCount": 40,
 + "trackBase": 0,
 + "headCount": 2,
 + "sectorsPerTrack": 10,
 + "sectorBase": 0,
 + "sideOrganization": "trks",
 + "syncPatterns": ["AAAAAAAAEFFF"],
 + "bitOrder": "lsb",
 + "sectorFields": "adda",
 + "addrSync": "0000",
 + "addrMarker": "FD",
 + "addrFieldSize": 3,
 + "addrCksumType": "8xrl",
 + "addrCksumIndex": 4,
 + "addrCksumByteSize": 1,
 + "addrCksumFromIndex": 1,
 + "addrCksumToIndex": 3,
 + "volumeDerived": "data",
 + "volumeBitIndex": 8,
 + "trackDerived": "data",
 + "trackBitIndex": 16,
 + "trackVerify": true,
 + "headDerived": "phys",
 + "sectorDerived": "data",
 + "sectorBitIndex": 24,
 + "dataSync": "0000",
 + "dataMarker": "FD",
 + "dataStartIndex": 1,
 + "dataSize": 256,
 + "dataCksumType": "8xrl",
 + "dataCksumIndex": 257,
 + "dataCksumByteSize": 1,
 + "dataCksumFromIndex": 1,
 + "dataCksumToIndex": 256
 + }
 +]
 +</code>