34
edits
(Added the data checksum to the table.) |
(Added the checksum formula to the data.) |
||
Line 226: | Line 226: | ||
| 0200H || 0xnn || The data checksum. | | 0200H || 0xnn || The data checksum. | ||
|- | |- | ||
|} | |||
=== Calculating the checksum === | |||
The checksum isn't a standard checksum, a parity, a logitudinal redundancy check or a a two's compliment checksum. | |||
It starts as a basic 8-bit sum of each of the characters, but has additional calculated bits inserted to avoid the sum "255" ever being calculated at any stage during the sum process. | |||
The assembly language in the Interface1 ROM is called with HL pointing to the buffer where the microdrive data is stored. It looks like this (below); | |||
{| class="wikitable" style="text-align: left;" | |||
|- | |||
|SECTOR:||LD BC,$000E||14 bytes in the header. Entry point for headers, location 0x1426. | |||
|- | |||
| ||JR SUM|| Calculate the checksum. | |||
|- | |||
|RECORD:||LD BC,$0200||200 bytes in the record. Location 0x142B | |||
|- | |||
|SUM:||PUSH HL|| Enter with HL pointing to the buffer, either at the header, or the record contents. Store the start. | |||
|- | |||
| ||LD E,$00||Zero the checksum to start. | |||
|- | |||
|LOOP:||LD A,E|| Pick up the current checksum. | |||
|- | |||
| ||ADD A,(HL)||Add a byte from the buffer to the checksum. | |||
|- | |||
| ||INC HL||Move the pointer to the next byte in the buffer. | |||
|- | |||
| ||ADC A,$01||Here's where it gets complicated. If the previous add overflowed, add Carry plus 1 ( add 2 ). Otherwise just add 1. | |||
|- | |||
| ||JR Z,SKIP||However if the last checksum calculation was 0FF, now it will be zero, and the zero flag set. If it's zero, skip the next instruction. | |||
|- | |||
| ||DEC A|| If not skipped, remove the 1 just added, however if two were added, then just subtract 1. If it was 0FF, just leave it as 00 now. | |||
|- | |||
|SKIP:||LD E,A||Store the sum so far... | |||
|- | |||
| ||DEC BC||Reduce the counter of bytes in the buffer. | |||
|- | |||
| ||LD A,B||We need to test if the counter is zero. | |||
|- | |||
| ||OR C||Set the zero flag now if BC is zero. | |||
|- | |||
| ||JR NZ,LOOP||If we haven't summed all the bytes in the buffer, loop back and iterate. | |||
|- | |||
| ||LD A,E||Collect the checksum. | |||
|- | |||
| ||CP (HL)||Byte after the buffer is where the checksum should be stored. Test the calculated checksum against the stored checksum. | |||
|- | |||
| ||LD (HL),A||And regardless of whether it's right or wrong, write the correct checksum in there now... So this routine both checks and calculates the checksum. | |||
|- | |||
| ||POP HL||Retrieve HL to point to the start of the buffer again. | |||
|- | |||
| ||RET||Zero flag is set if the checksum was correct. Can be tested by the routine that called this one. | |||
|- | |||
|} | |||
The Pseudocode for this process, if calculated in a high level language looks something like this; | |||
{| class="wikitable" style="text-align: left;" | |||
|- | |||
|Checksum = 0 | |||
|- | |||
|while (bytes in buffer) do | |||
|- | |||
|...Add byte to checksum | |||
|- | |||
|...If checksum=255 then checksum=0 | |||
|- | |||
|...If checksum>255 then checksum=(checksum modulo 256)+1 | |||
|- | |||
|done | |||
|- | |||
|} | |} | ||
edits