diff --git a/_spg/ZIFI/zifi.spg b/_spg/ZIFI/zifi.spg index 02de339..1a82cd1 100644 Binary files a/_spg/ZIFI/zifi.spg and b/_spg/ZIFI/zifi.spg differ diff --git a/zifi.asm b/zifi.asm index 1a55369..b5e68f1 100644 --- a/zifi.asm +++ b/zifi.asm @@ -61,8 +61,6 @@ start ld (#beff),hl call gfx_init call set_text_colors - call test_sd_raw ;DIAG: standalone SD read test, remove once verified - call test_sd_raw2 ;DIAG: standalone SD FAT32 file read test, remove once verified call load_ini IF cable_zifi call psb_start @@ -3791,795 +3789,6 @@ parsed_link ds #080 modem_command ds 256+128 current_paging_url ds 150 -;DIAG: standalone raw SD-card hardware test - bypasses WDFCVBI2 entirely, -;DIAG: talks to the SD controller directly via ports CONF=#77/DATA=#57. -;DIAG: Goal: verify our own init+read code can talk to the hardware at all, -;DIAG: before writing more of a replacement driver. Reads LBA 0 and checks -;DIAG: for the standard 55 AA boot-sector signature. Remove after testing. -test_sd_raw - call set_Textpage - ;DIAG: pre-fill the buffer with a recognizable marker before touching - ;DIAG: the card at all -- if this marker survives a "successful" read, - ;DIAG: the read loop isn't actually writing to sdraw_buf - ld hl,sdraw_buf - ld de,sdraw_buf+1 - ld (hl),#ee - ld bc,511 - ldir - - ld a,%00000001 - ld (sdraw_csl_val),a ;DIAG: interface 1 only -- interface 2 (#0B) hung - ;DIAG: the whole machine on real hardware, do not retry it - - di ;DIAG: off_int_dma alone didn't help -- try a real interrupt - ;DIAG: mask, in case int_main pages away our resident slot - ;DIAG: mid-read (not just an SPI timing issue) - call sdraw_init - or a - jp nz,test_sd_raw_noc - - call sdraw_read0 - or a - jp nz,test_sd_raw_rderr - ;DIAG: keep DI held through the prints too now -- ei was previously - ;DIAG: right here, leaving a window for int_main to run between the - ;DIAG: read and the dump; test whether that window is the culprit - - ;DIAG: show the raw command handshake bytes -- R1 response after - ;DIAG: CMD18, and the token byte WTDO settled on (should be #FE) - ld a,(sdraw_last_r1) - ld de,sdraw_hexbuf3 - call sdraw_hexch_pair - ld a,(sdraw_last_token) - ld de,sdraw_hexbuf3+2 - call sdraw_hexch_pair - xor a - ld (sdraw_hexbuf3+4),a - ld (sdraw_hexbuf3+5),a - ld hl,sdraw_r1tok_msg - ld b,1 - call zifi_echo - ld hl,sdraw_hexbuf3 - ld b,1 - call zifi_echo - - ;DIAG: always dump [0..15] and [508..511] before judging the signature, - ;DIAG: so a mismatch shows real vs. garbage/shifted bytes instead of guessing - ld hl,sdraw_buf - ld de,sdraw_hexbuf - ld b,16 - call sdraw_hexdump - ld hl,sdraw_head_msg - ld b,1 - call zifi_echo - ld hl,sdraw_hexbuf - ld b,1 - call zifi_echo - - ld hl,sdraw_buf+508 - ld de,sdraw_hexbuf2 - ld b,4 - call sdraw_hexdump - ld hl,sdraw_tail_msg - ld b,1 - call zifi_echo - ld hl,sdraw_hexbuf2 - ld b,1 - call zifi_echo - - ;DIAG: read LBA0 again, right now, and dump it too -- same bytes as - ;DIAG: above would mean a deterministic bug in our code, not a flaky card - call sdraw_read0 - or a - jr nz,test_sd_raw_rderr - ld hl,sdraw_buf - ld de,sdraw_hexbuf - ld b,16 - call sdraw_hexdump - ld hl,sdraw_head2_msg - ld b,1 - call zifi_echo - ld hl,sdraw_hexbuf - ld b,1 - call zifi_echo - - ld hl,sdraw_buf+510 - ld a,(hl) - cp #55 - jr nz,test_sd_raw_sigerr - inc hl - ld a,(hl) - cp #aa - jr nz,test_sd_raw_sigerr - - ;DIAG: now read a totally different LBA (1000, not 0) -- does the - ;DIAG: garbage pattern shift/change, or stay pinned to the same values? - ld hl,0 - ld de,1000 - call sdraw_readlba - or a - jr nz,test_sd_raw_rderr - ld hl,sdraw_buf - ld de,sdraw_hexbuf - ld b,16 - call sdraw_hexdump - ld hl,sdraw_lba1000_msg - ld b,1 - call zifi_echo - ld hl,sdraw_hexbuf - ld b,1 - call zifi_echo - - ei ;DIAG: only now, after every print, re-enable interrupts - ld hl,sdraw_ok_msg - ld b,1 - call zifi_echo - ret - -test_sd_raw_noc - ei - ld hl,sdraw_noc_msg - ld b,1 - call zifi_echo - ret -test_sd_raw_rderr - ei - ld hl,sdraw_rderr_msg - ld b,1 - call zifi_echo - ret -test_sd_raw_sigerr - ei - ld hl,sdraw_sigerr_msg - ld b,1 - call zifi_echo - ret - -sdraw_noc_msg db 'SD raw test: FAIL, no card found',0,0 -sdraw_rderr_msg db 'SD raw test: FAIL, read error',0,0 -sdraw_sigerr_msg db 'SD raw test: no 55 AA signature (see above)',0,0 -sdraw_ok_msg db 'SD raw test: OK, signature valid',0,0 -sdraw_head_msg db 'sector0[0..15]=',0,0 -sdraw_head2_msg db '2nd read[0..15]=',0,0 -sdraw_lba1000_msg db 'LBA1000[0..15]=',0,0 -sdraw_tail_msg db 'sector0[508..511]=',0,0 -sdraw_r1tok_msg db 'R1,token=',0,0 -sdraw_iface_msg db 'interface CS_ON=',0,0 -sdraw_hexbuf ds 40 -sdraw_hexbuf2 ds 16 -sdraw_hexbuf3 ds 8 -sdraw_last_r1 ds 1 -sdraw_last_token ds 1 - -sdraw_CONF equ #77 -sdraw_DATA equ #57 - -;--- convert A into 2 hex ASCII chars at (DE) --- -sdraw_hexch_pair - push af - rra - rra - rra - rra - call sdraw_hexch - ld (de),a - inc de - pop af - call sdraw_hexch - ld (de),a - ret - -;--- hex dump helper: HL=src, DE=dest ascii buffer, B=byte count --- -sdraw_hexdump - ld a,(hl) - push af - rra - rra - rra - rra - call sdraw_hexch - ld (de),a - inc de - pop af - call sdraw_hexch - ld (de),a - inc de - inc hl - djnz sdraw_hexdump - xor a - ld (de),a - inc de - ld (de),a - ret - -sdraw_hexch - and #0f - cp 10 - jr c,1f - add a,7 -1 add a,'0' - ret - -;--- low-level SD-over-SPI primitives, ported from source/DSDZC.ASM (Wild -;--- Commander Improved) which targets the same ZX Evolution SD controller. -sdraw_csh - push bc - push af - ld bc,sdraw_CONF - ld a,%00000011 - out (c),a - ld bc,sdraw_DATA - ld a,#ff - out (c),a - pop af - pop bc - ret - -sdraw_csl_val db %00000001 ;DIAG: interface 1 by default; test_sd_raw - ;DIAG: flips this to %00001011 (interface 2) - ;DIAG: if interface 1's signature check fails -sdraw_csl - push bc - push af - ld bc,sdraw_CONF - ld a,(sdraw_csl_val) - out (c),a - ld bc,sdraw_DATA - ld a,#ff - out (c),a - pop af - pop bc - jp sdraw_wait - -sdraw_wait - push bc - push af - ld bc,sdraw_DATA - ld de,60000 -1 in a,(c) - inc a - jr z,2f - dec de - ld a,d - or e - jr nz,1b -2 pop af - pop bc - ret - -sdraw_wtdo - push bc - push de - ld bc,sdraw_DATA - ld de,60000 -1 in a,(c) - cp #ff - jr nz,2f - dec de - ld a,d - or e - jr nz,1b -2 pop de - pop bc - ret - -sdraw_resp - push de - push bc - ld bc,sdraw_DATA - ld d,10 -1 in a,(c) - bit 7,a - jr z,2f - dec d - jr nz,1b - inc d -2 pop bc - pop de - ret - -sdraw_cycl ; DE = number of #FF clock bytes to send - ld bc,sdraw_DATA -1 ld a,#ff - out (c),a - dec de - ld a,d - or e - jr nz,1b - ret - -;--- send a pre-built 6-byte command frame pointed to by HL (real CRC). -;--- Matches D:\ST\ZP\PLAY60.ASM's actual shipped timing (not the blog -;--- article, which the article's own author -- who wrote that player -- -;--- says has bugs): two dummy IN (C) reads before the frame ("; savelij" -;--- in the source), and a NOP between each byte sent. Without this, the -;--- handshake (R1/token) still looks valid but the payload comes back as -;--- deterministic garbage -- exactly what we were seeing. -sdraw_cmd - call sdraw_csh - call sdraw_csl - ld bc,sdraw_DATA - in (c) - in (c) - outi - nop - outi - nop - outi - nop - outi - nop - outi - nop - outi - jp sdraw_resp - -;--- send a simple command: A=opcode, all-zero args, CRC=#FF --- -sdraw_cmdo - call sdraw_csh - call sdraw_csl -sdraw_cmdx - ld bc,sdraw_DATA - in (c) - in (c) - out (c),a - xor a - out (c),a - nop - out (c),a - nop - out (c),a - nop - out (c),a - ld a,#ff - out (c),a - ret - -sdraw_cmd00 db %01000000+0,0,0,0,0,#95 -sdraw_cmd08 db %01000000+8,0,0,1,#aa,#87 -sdraw_cmd16 db %01000000+16,0,0,2,0,#ff - -sdraw_do_cmd0 ld hl,sdraw_cmd00 - jp sdraw_cmd -sdraw_do_cmd8 ld hl,sdraw_cmd08 - jp sdraw_cmd -sdraw_do_cmd16 ld hl,sdraw_cmd16 - jp sdraw_cmd -sdraw_do_cmd1 ld a,%01000000+1 - call sdraw_cmdo - jp sdraw_resp -sdraw_do_cmd55 ld a,%01000000+55 - call sdraw_cmdo - jp sdraw_resp - -;--- ACMD41: H = argument high byte (0, or #40 for HCS), rest zero --- -sdraw_do_acmd41 - call sdraw_do_cmd55 - call sdraw_csh - call sdraw_csl - ld bc,sdraw_DATA - in (c) - in (c) - ld a,%01000000+41 - out (c),a - ld l,0 - out (c),h - nop - out (c),l - nop - out (c),l - nop - out (c),l - dec l - out (c),l - jp sdraw_resp - -;--- card init: CMD0/CMD8/ACMD41 (SDv2), falls back to ACMD41/CMD1 (SDv1/MMC) -; A=0 on success, A=1 on failure -sdraw_init - call sdraw_csh - ld de,512+10 - call sdraw_cycl - - ld de,8000 -1 dec de - ld a,d - or e - jp z,sdraw_init_fail - call sdraw_do_cmd0 - jr nz,1b - dec a - jp nz,1b - - call sdraw_do_cmd8 - push af - ld bc,sdraw_DATA - in e,(c) - nop - in e,(c) - nop - in h,(c) - nop - in l,(c) - pop af - jr nz,1b - bit 2,a - jr z,sdraw_v2 - -;--- legacy path: SDv1 (ACMD41) then MMC (CMD1) --- - ld de,8000 -2 dec de - ld a,d - or e - jr z,3f - ld h,0 - call sdraw_do_acmd41 - jr nz,2b - cp 1 - jr z,2b - or a - jr nz,3f - jr sdraw_fbs - -3 ld de,8000 -4 dec de - ld a,d - or e - jr z,sdraw_init_fail - call sdraw_do_cmd1 - jr nz,4b - cp 1 - jr z,4b - or a - jr nz,sdraw_init_fail - -sdraw_fbs call sdraw_do_cmd16 - jr nz,sdraw_init_fail - or a - jr nz,sdraw_init_fail - jr sdraw_init_ok - -;--- SDv2 path: verify the 0x1AA echo pattern from CMD8, then ACMD41+HCS --- -sdraw_v2 ld de,#01aa - or a - sbc hl,de - jr nz,sdraw_init_fail - - ld de,8000 -5 dec de - ld a,d - or e - jr z,sdraw_init_fail - ld h,#40 - call sdraw_do_acmd41 - jr nz,5b - cp 1 - jr z,5b - or a - jr nz,sdraw_init_fail - ; not distinguishing byte/block addressing (CMD58/CCS) here -- - ; irrelevant for reading LBA 0, which is address 0 either way. - -sdraw_init_ok - call sdraw_csh - xor a - ret - -sdraw_init_fail - call sdraw_csh - xor a - inc a - ret - -;--- read LBA 0 (single 512-byte sector) into sdraw_buf --- -; A=0 on success, A=1 on failure -sdraw_read0 - ld hl,0 - ld de,0 - jp sdraw_readlba - -;--- read an arbitrary LBA (single 512-byte sector) via CMD18+CMD12 into -;--- sdraw_buf. Matches the proven reference implementation in D:\ST\ZP's -;--- Z-Player source (SD-CARD2.TXT / PLAY60.ASM) byte-for-byte in approach: -;--- CMD18 (not CMD17!) for the read, and INI (not manual IN+LD(HL),A) for -;--- the bulk 512-byte transfer. -; HL = LBA bits31-16, DE = LBA bits15-0 -; A=0 on success, A=1 on failure -sdraw_readlba - call sdraw_csh - call sdraw_csl - ld bc,sdraw_DATA - in (c) ;DIAG: settling reads + inter-byte NOPs, matching - in (c) ;DIAG: PLAY60.ASM's CMzz exactly (see sdraw_cmd) - ld a,%01000000+18 - out (c),a - nop - out (c),h - nop - out (c),l - nop - out (c),d - nop - out (c),e - ld a,#ff - out (c),a - call sdraw_resp - ld (sdraw_last_r1),a ;DIAG: record for display, whatever the outcome - or a - jr nz,sdraw_readlba_fail - - call sdraw_wtdo - ld (sdraw_last_token),a ;DIAG: record for display, whatever the outcome - cp #fe - jr nz,sdraw_readlba_fail - - ;DIAG: manual IN+store loop, reloading BC (so B is pinned at 0) before - ;DIAG: every single byte -- ruling out B-register drift across INI's - ;DIAG: as a hardware port-decode issue, however unlikely - ld hl,sdraw_buf - ld e,32 -1 ld b,16 -2 ld c,sdraw_DATA - in a,(c) - ld (hl),a - inc hl - djnz 2b - dec e - jr nz,1b - - ld bc,sdraw_DATA - in a,(c) ; discard 2 CRC bytes - in a,(c) - - call sdraw_do_cmd12 - call sdraw_snb - call sdraw_wtby - call sdraw_csh - xor a - ret - -sdraw_readlba_fail - call sdraw_csh - xor a - inc a - ret - -;--- stop a multi-block transfer (CMD12). Sent without a fresh CSH/CSL -- -;--- the card is still selected from the CMD18 that started the transfer. -sdraw_do_cmd12 - ld bc,sdraw_DATA - ld a,%01000000+12 - out (c),a - xor a - out (c),a - out (c),a - out (c),a - out (c),a - ld a,#ff - out (c),a - xor a - in a,(sdraw_DATA) ; one stuff byte before the R1 response, per spec - jp sdraw_resp - -sdraw_snb - push bc - ld b,16 -1 xor a - in a,(sdraw_DATA) - djnz 1b - pop bc - ret - -sdraw_wtby - push bc - ld bc,sdraw_DATA -1 in a,(c) - or a - jr z,1b - pop bc - ret - -;DIAG: step 2 - parse the FAT32 BPB (already validated in sdraw_buf's first -;DIAG: 16 bytes), locate the root directory, find ZIFI.INI's short-name -;DIAG: entry there, and read+print its first line. Proves we can navigate -;DIAG: the filesystem and read a real file, not just a raw sector. -test_sd_raw2 - di ;DIAG: real interrupt mask, see test_sd_raw - call sdraw_read0 - or a - jp nz,t2_fail - - ld a,(sdraw_buf+13) - ld (sdraw_secpclus),a - - ; acc(32-bit) = reservedSectors - ld hl,(sdraw_buf+14) - ld (sdraw_acc_lo),hl - ld hl,0 - ld (sdraw_acc_hi),hl - - ; acc += FATSz32 * numFATs - ld hl,(sdraw_buf+36) - ld (sdraw_fatsz_lo),hl - ld hl,(sdraw_buf+38) - ld (sdraw_fatsz_hi),hl - ld a,(sdraw_buf+16) - ld b,a - or a - jr z,t2_fatdone -t2_fatloop - push bc - ld hl,(sdraw_fatsz_lo) - ld de,(sdraw_fatsz_hi) - call sdraw_acc_add32 - pop bc - djnz t2_fatloop -t2_fatdone - ; acc now = firstDataSector -- save it, needed again for the file itself - ld hl,(sdraw_acc_lo) - ld (sdraw_firstdata_lo),hl - ld hl,(sdraw_acc_hi) - ld (sdraw_firstdata_hi),hl - - ; acc += (rootCluster-2) * sectorsPerCluster - ld hl,(sdraw_buf+44) - ld de,2 - or a - sbc hl,de - ld b,h - ld c,l -t2_clusloop - ld a,b - or c - jr z,t2_clusdone - push bc - ld a,(sdraw_secpclus) - ld l,a - ld h,0 - ld de,0 - call sdraw_acc_add32 - pop bc - dec bc - jr t2_clusloop -t2_clusdone - ld hl,(sdraw_acc_hi) - ld de,(sdraw_acc_lo) - call sdraw_readlba - or a - jp nz,t2_fail - - ld hl,sdraw_buf -t2_scan - ld a,h - cp high (sdraw_buf+512) - jr nz,t2_chk - ld a,l - cp low (sdraw_buf+512) - jr z,t2_notfound -t2_chk - push hl - ld de,sdraw_zifiini_name - ld b,11 -1 ld a,(de) - cp (hl) - jr nz,2f - inc hl - inc de - djnz 1b - pop hl - jr t2_found -2 pop hl - ld de,32 - add hl,de - jr t2_scan - -t2_found - ; extract starting cluster: low word @ entry+26, high word @ entry+20 - push hl - ld de,26 - add hl,de - ld a,(hl) - inc hl - ld h,(hl) - ld l,a - ld (sdraw_filecl_lo),hl - pop hl - push hl - ld de,20 - add hl,de - ld a,(hl) - inc hl - ld h,(hl) - ld l,a - ld (sdraw_filecl_hi),hl - pop hl - - ; acc = firstDataSector + (fileCluster-2)*sectorsPerCluster - ld hl,(sdraw_firstdata_lo) - ld (sdraw_acc_lo),hl - ld hl,(sdraw_firstdata_hi) - ld (sdraw_acc_hi),hl - - ld hl,(sdraw_filecl_lo) - ld de,2 - or a - sbc hl,de - ld b,h - ld c,l -t2_fclusloop - ld a,b - or c - jr z,t2_fclusdone - push bc - ld a,(sdraw_secpclus) - ld l,a - ld h,0 - ld de,0 - call sdraw_acc_add32 - pop bc - dec bc - jr t2_fclusloop -t2_fclusdone - ld hl,(sdraw_acc_hi) - ld de,(sdraw_acc_lo) - call sdraw_readlba - or a - jr nz,t2_fail - - ei - ld hl,sdraw_found_msg - ld b,1 - call zifi_echo - ld hl,sdraw_buf - ld b,1 - call zifi_echo - ret - -t2_notfound - ei - ld hl,sdraw_notfound_msg - ld b,1 - call zifi_echo - ret -t2_fail - ei - ld hl,sdraw_fail2_msg - ld b,1 - call zifi_echo - ret - -; adds a 32-bit value (DE=high word, HL=low word) into the 32-bit -; accumulator sdraw_acc_hi:sdraw_acc_lo -sdraw_acc_add32 - push de - ld de,(sdraw_acc_lo) - add hl,de - ld (sdraw_acc_lo),hl - pop hl - ld de,(sdraw_acc_hi) - adc hl,de - ld (sdraw_acc_hi),hl - ret - -sdraw_found_msg db 'ZIFI.INI found, first line:',0,0 -sdraw_notfound_msg db 'ZIFI.INI not found in root dir sector0',0,0 -sdraw_fail2_msg db 'SD raw test2: FAIL',0,0 -sdraw_zifiini_name db "ZIFI INI" - -sdraw_secpclus ds 1 -sdraw_acc_lo ds 2 -sdraw_acc_hi ds 2 -sdraw_fatsz_lo ds 2 -sdraw_fatsz_hi ds 2 -sdraw_firstdata_lo ds 2 -sdraw_firstdata_hi ds 2 -sdraw_filecl_lo ds 2 -sdraw_filecl_hi ds 2 - - align 256 -sdraw_buf ds 512 -;DIAG: end of standalone raw SD-card test block - sd_init call init_sd_card