; ============================================================================== ; Apple II [$D0 ROM] (341-0016) - Programmer's Aid #1 [1978] ; ------------------------------------------------------------------------------ ; Part 4 [$D52E~$D5BB]: Tape Verify Routine by Steve Wozniak [WOZ], 1978-01; ; Copyright (c) 1978 by Apple Computer Inc. All Rights Reserved ; ------------------------------------------------------------------------------ ; Instructions are in the Programmer's Aid #1 Installation and Operating Manual ; ============================================================================== ; Analyzed (via McFadden's SourceGen) by James Davis [Last Updated: 2020/06/10] ; ============================================================================== ; ; Tape Verify Routine Equates: ; CHKSUM EQU $2E {addr/1} ;Tape Input Accumulated Checksum A1 EQU $3C {addr/2} ;Monitor General Purpose A1-Register HIMEM EQU $4C {addr/2} ;Integer BASIC: HIMEM Address Pointer PP EQU $CA {addr/2} ;Integer BASIC: Start of Program Pointer PRLEN EQU $CE {addr/2} ;Integer BASIC: Program Length XSAVE EQU $D8 {addr/1} ;Integer BASIC: X-Index Register Safe USRADR EQU $03F8 {addr/3} ;Monitor User Command (Ctrl-Y) Vector HDRSET EQU $F11E ;BASIC S/R: Sets Tape Pointers to $CE,$CF PRGSET EQU $F12C ;BASIC S/R: Sets Tape Pointers for Program NXTA1 EQU $FCBA ;Monitor Routine to INC (A1) then CMP (A2) HEADR EQU $FCC9 ;Monitor Write Tape Sync Header Routine RDBYTE EQU $FCEC ;Monitor Tape READ Routine (1-Byte|8-Bits) RD2BIT EQU $FCFA ;Monitor Tape READ Routine (2 Transitions) RDBIT EQU $FCFD ;Monitor Tape READ Routine (1 Transition) PRA1 EQU $FD92 ;Print CR, Hex of (A1), then Minus Sign PRBYTE EQU $FDDA ;Print A-Reg as Two-Digit Hex Number COUT EQU $FDED ;Print A-Reg to Output Device FINISH EQU $FF26 ;Check Accumulated Checksum & Ring Bell PRERR EQU $FF2D ;Print "ERR" & Sound Bell (Beep) ORG $D52E ; ; ============================================================================== ; Tape Verify Routines: ; ============================================================================== ; Set Monitor User Command (Ctrl-Y) Vector to Tape Verify Routine Location: ; ------------------------------------------------------------------------------ ; ; ----------------------------------- ;Monitor Verify S/R Entry Pt.: D52EG <Rtn> ; ;(to verify Mem-Range just saved on Tape) ; ; ----------------------------------- ;Setup Mon User Cmd (Ctrl-Y) Location: D52E: A9 54 SETTVCYV LDA #<TAPEVFY ;Get Tape Verify Routine Address, Low D530: A0 D5 LDY #>TAPEVFY ;Get Tape Verify Routine Address, High D532: 4C B0 D5 JMP SETUSRADR ;Setup Mon User Cmd (Ctrl-Y) Vector ; ============================================================================== ; Tape Verify BASIC Routine: ; ============================================================================== ; ; ----------------------------------- ;BASIC Verify S/R Entry Pt.: Call -10955 ; ;(to verify a program just saved on Tape) D535: 86 D8 VFYBSC STX XSAVE ;Preserve X-Index Register for BASIC ; ;Calculate Program Length, Put into PRLEN: D537: 38 SEC ;Prep for Subtract w/o Borrow [A-Data-!C] D538: A2 FF LDX #$FF ;Prep X-Index: Adrs+1, X=255=-1 & X=256=0 D53A: B5 4D GETLEN LDA HIMEM+1,X ;GET HIMEM Address, Low 1st & High 2nd It D53C: F5 CB SBC PP+1,X ;Subtract Program Start Address, Low/High D53E: 95 CF STA PRLEN+1,X ;Set Program Length, Low 1st & High 2nd D540: E8 INX ;Advance X-Index: X=255=-1 -> X=256=0 D541: F0 F7 BEQ GETLEN ;Loop to Do High Addresses, 2nd Iteration D543: 20 1E F1 JSR HDRSET ;Set Tape Pointers to ... D546: 20 54 D5 JSR TAPEVFY ;Verify Header on Tape D549: A2 01 LDX #1 ;Prep for PRGSET D54B: 20 2C F1 JSR PRGSET ;Set Tape Pointers to ... D54E: 20 54 D5 JSR TAPEVFY ;Verify Program on Tape D551: A6 D8 LDX XSAVE ;Restore X-Reg for BASIC D553: 60 RTS ;Return to Caller ; ============================================================================== ; Tape Verify RAM Image (A1,A2): ; ============================================================================== ; D554: 20 FA FC TAPEVFY JSR RD2BIT ;Monitor Tape READ Routine (2 Transitions) D557: A9 16 LDA #$16 ;Set Synchronization Header Length D559: 20 C9 FC JSR HEADR ;Synchronize on Tape Header D55C: 85 2E STA CHKSUM ;Initialize Tape Accumulated Checksum D55E: 20 FA FC JSR RD2BIT ;Monitor Tape READ Routine (2 Transitions) ; ----------------------------------- ;Read a Bit from Tape (Loop): D561: A0 24 VRFY2 LDY #$24 ;Set Count for RD2BIT/RDBIT Sampling ; ;^[Gets Reduced Until Voltage Transitions] ; ;^[(Used to Set Carry Flag for a One-Bit)] D563: 20 FD FC JSR RDBIT ;Monitor Tape READ Routine (1 Transition) D566: B0 F9 BCS VRFY2 ;Loop if RD2BIT/RDBIT Read a One-Bit D568: 20 FD FC JSR RDBIT ;Monitor Tape READ Routine (1 Transition) D56B: A0 3B LDY #$3B ;Set Count for RD2BIT/RDBIT Sampling ; ;^[Gets Reduced Until Voltage Transitions] ; ;^[2 Transitions/Bit; 16 Transitions/Byte] ; ----------------------------------- ;Read a Byte from Tape (Loop): D56D: 20 EC FC VRFY3 JSR RDBYTE ;Monitor Tape READ Routine (1-Byte|8-Bits) D570: F0 0E BEQ EXTDEL ;RDBYTE Returns (X=0)->(Z=1); Always Taken ; ; ----------------------------------- ;Accumulator contains Byte Read from Tape D572: 45 2E VFYLOOP EOR CHKSUM ;Update Tape Accumulated Checksum D574: 85 2E STA CHKSUM ;Set New Tape Accumulated Checksum D576: 20 BA FC JSR NXTA1 ;Increment A1; Sets Carry Flag if A1>A2 D579: A0 34 LDY #$34 ;Set Count for RD2BIT/RDBIT Sampling ; ;^[Gets Reduced Until Voltage Transitions] ; ;^[2 Transitions/Bit; 16 Transitions/Byte] ; ;^[One < used in Read for an Extra 12 (?)] D57B: 90 F0 BCC VRFY3 ;Loop Until A1>A2 D57D: 4C 26 FF JMP FINISH ;Verify Checksum & Beep; Returns to Caller ; ----------------------------------- ;Extra Delay to Equalize Timing: D580: EA EXTDEL NOP ;Delay 2 Machine Cycles D581: EA NOP ;Delay 2 Machine Cycles More D582: EA NOP ;Delay 2 Machine Cycles (+12 usec total) ; ----------------------------------- ;Accumulator contains Byte Read from Tape D583: C1 3C CMP (A1,X) ;Is Byte in Mem Same as Byte from Tape? D585: F0 EB BEQ VFYLOOP ;Loop if Bytes Match ; =================================== ;Else, Handle Error: D587: 48 PHA ;Push/Save Wrong Byte from Tape D588: 20 2D FF JSR PRERR ;Print "ERR" & Sound Bell (Beep) D58B: 20 92 FD JSR PRA1 ;Print CR, (A1:Address), then Minus Sign D58E: B1 3C LDA (A1),Y ;Get Byte from Memory at (A1:Address),Y=0 D590: 20 DA FD JSR PRBYTE ;Print A-Reg as Two-Digit Hex Number D593: A9 A0 LDA #' ' | $80 ;Get a Blank/Space Character D595: 20 ED FD JSR COUT ;Print A-Reg to Output Device D598: A9 A8 LDA #'(' | $80 ;Get an Open-Parenthesis Character D59A: 20 ED FD JSR COUT ;Print A-Reg to Output Device D59D: 68 PLA ;Pull/Retrieve Bad Byte Saved from Tape D59E: 20 DA FD JSR PRBYTE ;Print A-Reg as Two-Digit Hex Number D5A1: A9 A9 LDA #')' | $80 ;Get a Close-Parenthesis Character D5A3: 20 ED FD JSR COUT ;Print A-Reg to Output Device D5A6: A9 8D LDA #$8D ;Get High ASCII Ctrl-M: Carriage Return D5A8: 4C ED FD JMP COUT ;Print A-Reg to Output; Returns to Caller ; =================================== ;Extra Repeated Code (Unused/Filler): D5AB: A9 8D XCROUT LDA #$8D ;Get High ASCII Ctrl-M: Carriage Return D5AD: 4C ED FD JMP COUT ;Print A-Reg to Output; Returns to Caller ; ============================================================================== ; Monitor User Command (Ctrl-Y) Vector Setup Routine: ; ============================================================================== ; Shared by: Tape Verify, Relocater, & RAM Test Routines ; ------------------------------------------------------------------------------ ; ; ----------------------------------- ;Setup Mon User Cmd (Ctrl-Y) Vector: D5B0: 8D F9 03 SETUSRADR STA USRADR+1 ;Preset User Address, Low D5B3: 8C FA 03 STY USRADR+2 ;Preset User Address, High D5B6: A9 4C LDA #$4C ;Get JMP OpCode D5B8: 8D F8 03 STA USRADR ;Preset to JMP OpCode D5BB: 60 RTS ;Return to Caller