From 3dccaa6ad1505b5046481ea78e2a945ccc187e94 Mon Sep 17 00:00:00 2001 From: holub Date: Sun, 2 Feb 2025 14:27:36 -0500 Subject: [PATCH] formats/tzx_cas.cpp: Fixed regression in TAP format; Added checksum validation (MT9104) (#13322) --- src/lib/formats/tzx_cas.cpp | 54 +++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/lib/formats/tzx_cas.cpp b/src/lib/formats/tzx_cas.cpp index 8c9d34e44d4..39fe054e017 100644 --- a/src/lib/formats/tzx_cas.cpp +++ b/src/lib/formats/tzx_cas.cpp @@ -804,31 +804,56 @@ static int cdt_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes return size; } -static int tap_cas_to_wav_size( const uint8_t *casdata, int caslen ) +static int tap_cas_to_wav_size(const uint8_t *casdata, int caslen) { + /* + TAP Header: + | 0 | W | Length of Data Block (N) | -+ + | 2 | B | Flag Byte | -+ + | 3 | B*(N-2) | Data | | Data Block + | N+1 | B | XOR Checksum of [2..N] | -+ + */ + int size = 0; const uint8_t *p = casdata; - while (caslen > 0) + while (caslen > 2) { int data_size = get_u16le(&p[0]); - int pilot_length = (p[2] == 0x00) ? 8063 : 3223; - caslen -= data_size; - if (caslen < 0) - { - LOG_FORMATS("tap_cas_to_wav_size: Requested 0x%X byte but only 0x%X available.\n", data_size, data_size + caslen); - data_size += caslen; - } - LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size); p += 2; + caslen -= 2; + if (caslen < data_size) + { + LOG_FORMATS("tap_cas_to_wav_size: Requested 0x%X bytes but only 0x%X available.\n", data_size, caslen); + data_size = caslen; + } + caslen -= data_size; + + // Data Block + LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size); + const int pilot_length = (p[0] == 0x00) ? 8063 : 3223; size += tzx_cas_handle_block(nullptr, p, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8); - LOG_FORMATS(", total size is now: %d\n", size); + LOG_FORMATS(", total size is now: %d", size); + + // Validate Checksum + const uint8_t checksum = p[data_size - 1]; + LOG_FORMATS(", checksum 0x%X\n", checksum); + uint8_t check = 0x00; + for(int i = 0; i < (data_size - 1); i++) + { + check ^= p[i]; + } + if (check != checksum) + { + LOG_FORMATS("tap_cas_to_wav_size: wrong checksum 0x%X\n", check); + } + p += data_size; } return size; } -static int tap_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes ) +static int tap_cas_fill_wave(int16_t *buffer, int length, const uint8_t *bytes) { int16_t *p = buffer; int size = 0; @@ -837,7 +862,9 @@ static int tap_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes while (size < length) { int data_size = get_u16le(&bytes[0]); - int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223; + bytes += 2; + + int pilot_length = (bytes[0] == 0x00) ? 8063 : 3223; LOG_FORMATS("tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size); /* length -= data_size; @@ -846,7 +873,6 @@ static int tap_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes data_size += length; // Take as much as we can. } */ - bytes += 2; size += tzx_cas_handle_block(&p, bytes, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8); bytes += data_size; }