From 21d4c3361e53d04d001aa40c78c6dbedf31064a0 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 9 Sep 2026 23:15:13 +0300 Subject: [PATCH] Fix SAVE512/LOAD512 page-wrap losing a marker-stripped offset remainder sv512_advance/lv512_advance hardcoded the post-wrap offset to exactly #4000, discarding whatever the add overshot #8000 by. Invisible for page-aligned transfers, but create_filename's ".EXT"-marker handling (strips a leading 4-byte ".TRD"/".SCL"/etc marker some archive downloads carry) starts thread.adress a few bytes past #4000, so the reset silently dropped that offset on the first page wrap only, splicing 4 stray bytes into the saved file and losing its real last 4 bytes. Fixed by subtracting #40 from H instead of resetting it (CP doesn't touch A, so this costs zero extra bytes). Confirmed via a direct RAM-vs-disk MD5 comparison on a 640KB, 40-page-boundary download: byte-for-byte identical after the fix. --- _sd/zc_sd_driver_body.asm | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/_sd/zc_sd_driver_body.asm b/_sd/zc_sd_driver_body.asm index bb0c12e..78f05c4 100644 --- a/_sd/zc_sd_driver_body.asm +++ b/_sd/zc_sd_driver_body.asm @@ -3938,8 +3938,9 @@ lv512_advance ld hl,(lv512_off) ld a,h cp #80 jr c,lv512_nowrap - ld hl,#4000 - ld a,(lv512_page) + sub #40 ; preserve the overflow remainder instead + ld h,a ; of resetting to exactly #4000 -- see + ld a,(lv512_page) ; sv512_advance's own comment below inc a ld (lv512_page),a lv512_nowrap ld (lv512_off),hl @@ -3960,14 +3961,32 @@ lv512_eoc ld a,(lv512_page) ;--- sv512_advance: sv512_off += 512, wrapping to sv512_page+1 (back to ;--- slot-1 offset 0x4000, NOT 0 -- see header comment on the real ;--- 0x4000-0x7FFF convention) once it would leave the 0x4000-0x7FFF -;--- range, i.e. reach 0x8000 (one page = exactly 32 blocks). --- +;--- range, i.e. reach 0x8000 (one page = exactly 32 blocks). +;--- +;--- The wrap subtracts #40 from H (preserving whatever this add +;--- overshot #8000 by) instead of hardcoding H:=#40 -- CP doesn't +;--- touch A, so A still holds the pre-wrap H here, free to reuse. +;--- create_filename's ".EXT"-marker handling can start thread.adress +;--- (and so sv512_off, on the very first call) a few bytes PAST +;--- #4000 (skipping a leading ".TRD"/".SCL"/etc marker some servers +;--- prepend to the real payload) -- a hardcoded reset to exactly +;--- #4000 silently drops that remainder on the FIRST page wrap only +;--- (every wrap after that starts page-aligned, so the bug is +;--- invisible again), splicing 4 stray bytes from the tail of the +;--- block just written into the next one and losing the file's real +;--- last 4 bytes. Confirmed via a live memory-vs-disk diff on a real +;--- multi-page download (2026-09-09): RAM was correct throughout, +;--- only the on-disk copy had the extra bytes -- see +;--- [[project-zifi-custom-sd-driver]]. Same fix applied to +;--- lv512_advance above (LOAD512's own copy of this logic). --- sv512_advance ld hl,(sv512_off) ld de,512 add hl,de ld a,h cp #80 jr c,sv512_nowrap - ld hl,#4000 + sub #40 + ld h,a ld a,(sv512_page) inc a ld (sv512_page),a