Skip to content

Commit

Permalink
tap: verify checksum values
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcook committed Aug 6, 2024
1 parent e345528 commit c93dc8b
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
23 changes: 21 additions & 2 deletions format/tap/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package tzx
// https://worldofspectrum.net/zx-modules/fileformats/tapformat.html

import (
"bufio"
"bytes"
"embed"

"golang.org/x/text/encoding/charmap"

"github.com/wader/fq/format"
"github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
Expand Down Expand Up @@ -67,6 +70,8 @@ func decodeTapBlock(d *decode.D) {

// decodes the different types of 19-byte header blocks.
func decodeHeader(d *decode.D) {
blockStartPosition := d.Pos()

// Always 0: byte indicating a standard ROM loading header
d.FieldU8("flag", scalar.UintMapSymStr{0: "standard_speed_data"})
// Header type
Expand Down Expand Up @@ -119,10 +124,12 @@ func decodeHeader(d *decode.D) {
}

// Simply all bytes XORed (including flag byte).
d.FieldU8("checksum", scalar.UintHex)
d.FieldU8("checksum", d.UintValidate(calculateChecksum(d, blockStartPosition, d.Pos()-blockStartPosition)), scalar.UintHex)
}

func decodeDataBlock(d *decode.D, length uint64) {
blockStartPosition := d.Pos()

// flag indicating the type of data block, usually 255 (standard speed data)
d.FieldU8("flag", scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
if s.Actual == 0xFF {
Expand All @@ -135,5 +142,17 @@ func decodeDataBlock(d *decode.D, length uint64) {
// The essential data: length minus the flag/checksum bytes (may be empty)
d.FieldRawLen("data", int64(length-2)*8)
// Simply all bytes (including flag byte) XORed
d.FieldU8("checksum", scalar.UintHex)
d.FieldU8("checksum", d.UintValidate(calculateChecksum(d, blockStartPosition, d.Pos()-blockStartPosition)), scalar.UintHex)
}

func calculateChecksum(d *decode.D, blockStartPos, blockEndPos int64) uint64 {
var blockSlice bytes.Buffer
writer := bufio.NewWriter(&blockSlice)
d.Copy(writer, bitio.NewIOReader(d.BitBufRange(blockStartPos, blockEndPos)))

var checksum uint8
for _, v := range blockSlice.Bytes() {
checksum ^= v
}
return uint64(checksum)
}
4 changes: 2 additions & 2 deletions format/tap/testdata/basic_prog1.fqtest
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ $ fq -d tap dv basic_prog1.tap
0x00| 26 00| &.| data_length: 38 0xe-0x10 (2)
0x10|0a 00 |.. | auto_start_line: 10 0x10-0x12 (2)
0x10| 26 00 | &. | program_length: 38 0x12-0x14 (2)
0x10| 01 | . | checksum: 0x1 0x14-0x15 (1)
0x10| 01 | . | checksum: 0x1 (valid) 0x14-0x15 (1)
| | | [1]{}: block 0x15-0x3f (42)
0x10| 28 00 | (. | length: 40 0x15-0x17 (2)
| | | data{}: 0x17-0x3f (40)
0x10| ff | . | flag: "standard_speed_data" (255) 0x17-0x18 (1)
0x10| 00 0a 14 00 20 f5 22 66| .... ."f| data: raw bits 0x18-0x3e (38)
0x20|71 20 69 73 20 74 68 65 20 62 65 73 74 21 22 0d|q is the best!".|
0x30|00 14 0a 00 ec 31 30 0e 00 00 0a 00 00 0d |.....10....... |
0x30| b6| | .|| checksum: 0xb6 0x3e-0x3f (1)
0x30| b6| | .|| checksum: 0xb6 (valid) 0x3e-0x3f (1)
10 changes: 5 additions & 5 deletions format/tzx/testdata/basic_prog1.fqtest
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ $ fq -d tzx dv basic_prog1.tzx
0x00| 14 | . | minor_version: 20 0x9-0xa (1)
| | | blocks[0:3]: 0xa-0xcd (195)
| | | [0]{}: block 0xa-0x88 (126)
0x00| 32 | 2 | block_type: "archive_info" (50) 0xa-0xb (1)
0x00| 32 | 2 | type: "archive_info" (50) 0xa-0xb (1)
0x00| 7b 00 | {. | length: 123 0xb-0xd (2)
0x00| 09 | . | count: 9 0xd-0xe (1)
| | | archive_info[0:9]: 0xe-0x88 (122)
Expand Down Expand Up @@ -51,7 +51,7 @@ $ fq -d tzx dv basic_prog1.tzx
0x70|54 5a 58 65 64 20 62 79 20 4d 69 63 68 61 65 6c|TZXed by Michael| value: "TZXed by Michael R. Cook" 0x70-0x88 (24)
0x80|20 52 2e 20 43 6f 6f 6b | R. Cook |
| | | [1]{}: block 0x88-0xa0 (24)
0x80| 10 | . | block_type: "standard_speed_data" (16) 0x88-0x89 (1)
0x80| 10 | . | type: "standard_speed_data" (16) 0x88-0x89 (1)
0x80| e8 03 | .. | pause: 1000 0x89-0x8b (2)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| tap{}: (tap) 0x8b-0xa0 (21)
| | | blocks[0:1]: 0x8b-0xa0 (21)
Expand All @@ -65,9 +65,9 @@ $ fq -d tzx dv basic_prog1.tzx
0x90| 26 00 | &. | data_length: 38 0x99-0x9b (2)
0x90| 0a 00 | .. | auto_start_line: 10 0x9b-0x9d (2)
0x90| 26 00 | &. | program_length: 38 0x9d-0x9f (2)
0x90| 01| .| checksum: 0x1 0x9f-0xa0 (1)
0x90| 01| .| checksum: 0x1 (valid) 0x9f-0xa0 (1)
| | | [2]{}: block 0xa0-0xcd (45)
0xa0|10 |. | block_type: "standard_speed_data" (16) 0xa0-0xa1 (1)
0xa0|10 |. | type: "standard_speed_data" (16) 0xa0-0xa1 (1)
0xa0| e8 03 | .. | pause: 1000 0xa1-0xa3 (2)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| tap{}: (tap) 0xa3-0xcd (42)
| | | blocks[0:1]: 0xa3-0xcd (42)
Expand All @@ -78,4 +78,4 @@ $ fq -d tzx dv basic_prog1.tzx
0xa0| 00 0a 14 00 20 f5 22 66 71 20| .... ."fq | data: raw bits 0xa6-0xcc (38)
0xb0|69 73 20 74 68 65 20 62 65 73 74 21 22 0d 00 14|is the best!"...|
0xc0|0a 00 ec 31 30 0e 00 00 0a 00 00 0d |...10....... |
0xc0| b6| | .| | checksum: 0xb6 0xcc-0xcd (1)
0xc0| b6| | .| | checksum: 0xb6 (valid) 0xcc-0xcd (1)

0 comments on commit c93dc8b

Please sign in to comment.