diff --git a/tests/diskii-woz-test.asm b/tests/diskii-woz-test.asm new file mode 100644 index 0000000..07ec8b6 --- /dev/null +++ b/tests/diskii-woz-test.asm @@ -0,0 +1,944 @@ +.feature labels_without_colons +.feature leading_dot_in_identifiers +.feature c_comments +.P02 ; normal 6502 + +.macro ADR val + .addr val +.endmacro + +.macro BLT val + BCC val +.endmacro + +.macro BGE val + BCS val +.endmacro + +; Force APPLE 'text' to have high bit on; Will display as NORMAL characters +.macro ASC text + .repeat .strlen(text), I + .byte .strat(text, I) | $80 + .endrep +.endmacro + +a_cr = $0d ; Carriage return. + +F8ROM_YXHEX = $F940 +F8ROM_AXHEX = $F941 +F8ROM_XHEX = $F944 ; print X register in hex -- kills X,A +F8ROM_AHEX = $FDDA ; print A register in hex + +F8ROM_INIT = $FB2F +F8ROM_HOME = $FC58 ; Kills A,Y +F8ROM_CROUT = $FC62 ; carriage return out +F8ROM_MONWAIT = $FCA8 ; wait for (A*A*2.5 + A*13.5 + 7) * 0.980 usec +F8ROM_COUT = $FDED ; Load A with character to print +F8ROM_RDKEY = $FD0C + +WRVEC = $03D0 ; warm re-entry point + +PHSOFF = $C080 +PHSON = $C081 +DISKOFF = $C088 +DISKON = $C089 +DRIVEA = $C08A +DISK_LATCHR = $C08C +DISK_LATCHW = $C08D +DISK_MODER = $C08E +DISK_MODEW = $C08F + + + ;; Zero-page addresses used + ;; 00/01: storage pointer for loops in nybble code + ;; 02/03: second storage pointer for loops in nybble code + ;; 04/05: lookup table indexer for the _trans table + ;; FA/FB: DST pointer for memset + ;; FC/FD: pointer to sector buffer + ;; FF: scratch, used when erasing a track +ZP_STORPTR = $00 +ZP_STOR2 = $02 +ZP_TRANSP = $04 +DST = $FA +ZP_SECTP = $FC +ZP_SCRATCH = $FF + +.segment "CODE" +START + JMP Entry + +Entry + JSR F8ROM_INIT + JSR F8ROM_HOME + LDY #>STARTMSG + LDA #SECDATA + STA ZP_SECTP+1 + LDA #TRANS62 ; set up ZP_TRANSP to point at TRANS62 + STA ZP_TRANSP+1 ; (a 64-byte lookup table) + LDA #NYBDATA + STA DST+1 + LDA #ENDMSG ; All done, tell the user + LDA #SECDATA + JSR F8ROM_AHEX + LDA #SECDATAMSG + LDA #NYBDATA + JSR F8ROM_AHEX + LDA #NYBDATAMSG + LDA #WPMSG + LDA #WRITEMSG + LDA #NYBDATA ; set up ZP_STORPTR to the start of NYBDATA + STA ZP_STORPTR+1 + LDA #NYBDATA + STA ZP_STORPTR+1 ; high address + LDA #SECTORMSG + LDA #SECTORMSG2 + LDA # 0x100 + INY ; bytes + STY ZP_STOR2+1 + + ;; Clear output buffer 0x157 bytes + LDY #>SECTORMSG3 + LDA #SECTORMSG4 + LDA #= 0; idx6--) + LDA #$01 + STA IDX6 + STA IDX6+1 ; IDX6 = 0x0101 +@WorkLoopA + LDY IDX6 ; val6 = input[idx6 & 0xFF] + LDA (ZP_SECTP),Y + STA VAL6 + + LDY IDX2 ; val2 = output[idx2]; + LDA (ZP_STORPTR),Y + STA VAL2 + + ;; val2 = (val2 << 1) | (val6 & 1); val6 >>= 1; + LSR VAL6+1 + ROR VAL6 ; val6 >>= 1, and C = old (val6&1) + LDA VAL2 + ROL ; A = (val2 << 1) | C + STA VAL2 ; val2 = all that jazz + + ;; another round of the same + LSR VAL6+1 + ROR VAL6 ; val6 >>= 1, and C = old (val6&1) + LDA VAL2 + ROL ; A = (val2 << 1) | C + STA VAL2 ; val2 = all that jazz + + LDY IDX2 ; output[idx2] = val2 + LDA VAL2 + STA (ZP_STORPTR),Y + + ;; if (idx6 < 0x100) { output[0x56+idx6] = val6; } + LDA IDX6+1 + CMP #01 + BEQ @decidx2 + LDA #$56 + CLC + ADC IDX6 + BCC @storeLT100 + + ;; we need to store in ZP_STOR2 (the result overflowed) + TAY ; Y = idx6 + 0x56 and is >= 0x100 + LDA VAL6 + STA (ZP_STOR2),Y + JMP @decidx2 + +@storeLT100 + TAY ; Y = idx6 + 0x56 and is < 0x100 + LDA VAL6 + STA (ZP_STORPTR),Y + JMP @decidx2 + +@decidx2 + ;; if (--idx2 < 0) { idx2 = 0x55; } + ;; IDX2 never exceeds $55, so we can test using DEC and BMI/BPL + DEC IDX2 + BPL @dontresetidx2 + ;; ... high bit is set, so we underflowed; reset IDX2 back to $55 + + LDA #$55 + STA IDX2 +@dontresetidx2 + + ;; End of WorkLoopA: 16-bit decrement idx6, and loop to @WorkLoopA + ;; if it is >= 0 + LDA IDX6 ; sets Z if it's zero + BNE @simpledeclo ; if not zero, just decrement and continue + LDA IDX6+1 ; low was zero, so repeat w/ high + BEQ @DoneWorkloopA ; if high is also zero we're done + DEC IDX6+1 +@simpledeclo + DEC IDX6 + + ;; continue loop + JMP @WorkLoopA + + ;; Both IDX6 and IDX6+1 reached 0, so we are done the loop +@DoneWorkloopA + ;; Mask out the "extra" 2-bit data: + ;; output[0x54] &= 0x0F; output[0x55] &= 0x0F; + LDY #$54 + LDA (ZP_STORPTR),Y + AND #$0F + STA (ZP_STORPTR),Y + INY + AND #$0F + STA (ZP_STORPTR),Y + + ;; Loop over the data one more time to construct the actual output + ;; and compute the checksum + ;; Checksum is initialized to 0 above + ;; for (int idx6=0; idx6<0x156; idx6++) + LDY #>SECTORMSG5 + LDA #= 0x56 - done loop + JMP @WorkLoopB +@incHigh + INC IDX6+1 + JMP @f + +@setCksum + ;; output[342] = _trans[cksum] + LDY CKSUM ; A = _trans[cksum] + LDA (ZP_TRANSP),Y + LDY #$56 + STA (ZP_STOR2),Y ; output[0x100 + Y] = A + + ;; Add 0x157 to ZP_STORPTR (number of bytes we added to the buffer) + INC ZP_STORPTR+1 ; add 0x100 + LDA ZP_STORPTR + CLC + ADC #$57 + BCC @nocarry + INC ZP_STORPTR+1 +@nocarry + STA ZP_STORPTR + +@done + RTS + + + ;; set CNT, CNT+1, DST, DST+1, VALUE before calling +memset +@a + LDY #0 + LDA CNT + ORA CNT+1 + BEQ @fin + LDA VALUE + STA (DST),y + INC DST + BNE @b + INC DST+1 +@b + DEC CNT + LDA CNT + CMP #$FF + BNE @c + DEC CNT+1 +@c + SEC + BCS @a +@fin + RTS +;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Start of data segment +;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +STARTMSG + ASC "Insert a blank floppy in s6d1 and press a key..." + .byte $8D, $00 + +SECTORMSG + ASC " : Making this sector of data..." + .byte $00 +SECTORMSG2 + ASC "Building sector data chunk..." + .byte $00 +SECTORMSG3 + ASC "Clearing output buffer..." + .byte $00 +SECTORMSG4 + ASC "Constructing 6-and-2 data..." + .byte $00 +SECTORMSG5 + ASC "Building checksum..." + .byte $00 +ENDMSG + ASC "Test complete, no errors found." + .byte $00 +SECDATAMSG + ASC " : sector data buffer" + .byte $00 +NYBDATAMSG + ASC " : nybble data buffer" + .byte $00 + +WPMSG + ASC "Disk is write protected; aborting" + .byte $00 +WRITEMSG + ASC "Writing fresh track..." + .byte $00 + +;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; variable space + ;; + ;; Many/all of these could be zero-page and not here. + ;; They also don't need to be initialized to zero so they + ;; could just be memory locations instead of byte defines. +;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +WAITCTR + .byte $00, $00 + +CURHALFTRK + .byte $00 + +DSTHALFTRK + .byte $00 + +NYBCOUNT + .byte $00 + +TARGETTRK + .byte $00 +TARGETSEC + .byte $00 +SECCOUNT + .byte $00 + +IDX6 + .byte $00, $00 +IDX2 + .byte $00 +CKSUM + .byte $00 +VAL2 + .byte $00 +VAL6 + .byte $00 + +CNT + .byte $00, $00 +VALUE + .byte $00 + +;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Block data area +;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.align 256 + + ;; 6-and-2 DOS3.3 translation table (here so it doesn't + ;; cross a page boundary) +TRANS62 + .byte $96, $97, $9a, $9b, $9d, $9e, $9f, $a6 + .byte $a7, $ab, $ac, $ad, $ae, $af, $b2, $b3 + .byte $b4, $b5, $b6, $b7, $b9, $ba, $bb, $bc + .byte $bd, $be, $bf, $cb, $cd, $ce, $cf, $d3 + .byte $d6, $d7, $d9, $da, $db, $dc, $dd, $de + .byte $df, $e5, $e6, $e7, $e9, $ea, $eb, $ec + .byte $ed, $ee, $ef, $f2, $f3, $f4, $f5, $f6 + .byte $f7, $f9, $fa, $fb, $fc, $fd, $fe, $ff + + ;; scratch space for a sector of data + ;; FIXME: is there an easier way to define a block so that + ;; ca65 honors it and shows it properly in the lst? +.align 256 +SECDATA + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + + ;; nybblized data that we precalculate + ;; and then write to the track; or that we read in from the track + ;; and store here +.align 256 +NYBDATA + .byte $00 + +