RC6502-Apple-1-Replica/software/firmware/WozMon/wozaci.list

241 lines
18 KiB
Plaintext

0000- 4 ;-------------------------------------------------------------------------
0000- 5 ;
0000- 6 ; The WOZ Apple Cassette Interface for the Apple 1
0000- 7 ; Written by Steve Wozniak somewhere around 1976
0000- 8 ;
0000- 9 ;-------------------------------------------------------------------------
0000- 10
0000- 11
0000- 12 ;-------------------------------------------------------------------------
0000- 13 ; Memory declaration
0000- 14 ;-------------------------------------------------------------------------
0000- 15
0024- 16 HEX1L .EQ $24 End address of dump block
0025- 17 HEX1H .EQ $25
0026- 18 HEX2L .EQ $26 Begin address of dump block
0027- 19 HEX2H .EQ $27
0028- 20 SAVEINDEX .EQ $28 Save index in input buffer
0029- 21 LASTSTATE .EQ $29 Last input state
0000- 22
0200- 23 IN .EQ $0200 Input buffer
C000- 24 FLIP .EQ $C000 Output flip-flop
C081- 25 TAPEIN .EQ $C081 Tape input
D010- 26 KBD .EQ $D010 PIA.A keyboard input
D011- 27 KBDCR .EQ $D011 PIA.A keyboard control register
FF1A- 28 ESCAPE .EQ $FF1A Escape back to monitor
FFEF- 29 ECHO .EQ $FFEF Echo character to terminal
0000- 30
0000- 31 ;-------------------------------------------------------------------------
0000- 32 ; Constants
0000- 33 ;-------------------------------------------------------------------------
0000- 34
008D- 35 CR .EQ $8D Carriage Return
009B- 36 ESC .EQ $9B ASCII ESC
0000- 37
0000- 38 ;-------------------------------------------------------------------------
0000- 39 ; Let's get started
0000- 40 ;-------------------------------------------------------------------------
C100- 41 .OR $C100
C100-A9 AA 42 ( 2) WOZACI LDA #"*" Print the Tape prompt
C102-20 EF FF 43 ( 6) JSR ECHO
C105-A9 8D 44 ( 2) LDA #CR And drop the cursor one line
C107-20 EF FF 45 ( 6) JSR ECHO
C10A- 46
C10A-A0 FF 47 ( 2) LDY #-1 Reset the input buffer index
C10C-C8 48 ( 2) NEXTCHAR INY
C10D-AD 11 D0 49 ( 4) KBDWAIT LDA KBDCR Wait for a key
C110-10 FB 50 (2**) BPL KBDWAIT Still no key!
C112- 51
C112-AD 10 D0 52 ( 4) LDA KBD Read key from keyboard
C115-99 00 02 53 ( 5) STA IN,Y Save it into buffer
C118-20 EF FF 54 ( 6) JSR ECHO And type it on the screen
C11B-C9 9B 55 ( 2) CMP #ESC
C11D-F0 E1 56 (2**) BEQ WOZACI Start from scratch if ESC!
C11F-C9 8D 57 ( 2) CMP #CR
C121-D0 E9 58 (2**) BNE NEXTCHAR Read keys until CR
C123- 59
C123-A2 FF 60 ( 2) LDX #-1 Initialize parse buffer pointer
C125- 61
C125- 62 ;-------------------------------------------------------------------------
C125- 63 ; Start parsing first or a new tape command
C125- 64 ;-------------------------------------------------------------------------
C125- 65
C125-A9 00 66 ( 2) NEXTCMD LDA #0 Clear begin and end values
C127-85 24 67 ( 2) STA HEX1L
C129-85 25 68 ( 2) STA HEX1H
C12B-85 26 69 ( 2) STA HEX2L
C12D-85 27 70 ( 2) STA HEX2H
C12F- 71
C12F-E8 72 ( 2) NEXTCHR INX Increment input pointer
C130-BD 00 02 73 ( 4*) LDA IN,X Get next char from input line
C133-C9 D2 74 ( 2) CMP #"R" Read command?
C135-F0 56 75 (2**) BEQ READ Yes!
C137-C9 D7 76 ( 2) CMP #"W" Write command?
C139-F0 35 77 (2**) BEQ WRITE Yes! (note: CY=1)
C13B-C9 AE 78 ( 2) CMP #"." Separator?
C13D-F0 27 79 (2**) BEQ SEP Yes!
C13F-C9 8D 80 ( 2) CMP #CR End of line?
C141-F0 20 81 (2**) BEQ GOESC Escape to monitor! We're done
C143-C9 A0 82 ( 2) CMP #" " Ignore spaces
C145-F0 E8 83 (2**) BEQ NEXTCHR
C147-49 B0 84 ( 2) EOR #"0" Map digits to 0-9
C149-C9 0A 85 ( 2) CMP #9+1 Is it a decimal digit?
C14B-90 06 86 (2**) BCC DIG Yes!
C14D-69 88 87 ( 2) ADC #$88 Map letter "A"-"F" to $FA-$FF
C14F-C9 FA 88 ( 2) CMP #$FA Hex letter?
C151-90 AD 89 (2**) BCC WOZACI No! Character not hex!
C153- 90
C153-0A 91 ( 2) DIG ASL Hex digit to MSD of A
C154-0A 92 ( 2) ASL
C155-0A 93 ( 2) ASL
C156-0A 94 ( 2) ASL
C157- 95
C157-A0 04 96 ( 2) LDY #4 Shift count
C159-0A 97 ( 2) HEXSHIFT ASL Hex digit left, MSB to carry
C15A-26 24 98 ( 5) ROL HEX1L Rotate into LSD
C15C-26 25 99 ( 5) ROL HEX1H Rotate into MSD
C15E-88 100 ( 2) DEY Done 4 shifts?
C15F-D0 F8 101 (2**) BNE HEXSHIFT No! Loop
C161-F0 CC 102 (2**) BEQ NEXTCHR Handle next character
C163- 103
C163- 104 ;-------------------------------------------------------------------------
C163- 105 ; Return to monitor, prints \ first
C163- 106 ;-------------------------------------------------------------------------
C163- 107
C163-4C 1A FF 108 ( 3) GOESC JMP ESCAPE Escape back to monitor
C166- 109
C166- 110 ;-------------------------------------------------------------------------
C166- 111 ; Separating . found. Copy HEX1 to Hex2. Doesn't clear HEX1!!!
C166- 112 ;-------------------------------------------------------------------------
C166- 113
C166-A5 24 114 ( 3) SEP LDA HEX1L Copy hex value 1 to hex value 2
C168-85 26 115 ( 2) STA HEX2L
C16A-A5 25 116 ( 3) LDA HEX1H
C16C-85 27 117 ( 2) STA HEX2H
C16E-B0 BF 118 (2**) BCS NEXTCHR Always taken!
C170- 119
C170- 120 ;-------------------------------------------------------------------------
C170- 121 ; Write a block of memory to tape
C170- 122 ;-------------------------------------------------------------------------
C170- 123
C170-A9 40 124 ( 2) WRITE LDA #64 Write 10 second header
C172-20 CC C1 125 ( 6) JSR WHEADER
C175- 126
C175-88 127 ( 2) WRNEXT DEY Compensate timing for extra work
C176-A2 00 128 ( 2) LDX #0 Get next byte to write
C178-A1 26 129 ( 6) LDA (HEX2L,X)
C17A- 130
C17A-A2 10 131 ( 2) LDX #8*2 Shift 8 bits (decremented twice)
C17C-0A 132 ( 2) WBITLOOP ASL Shift MSB to carry
C17D-20 DB C1 133 ( 6) JSR WRITEBIT Write this bit
C180-D0 FA 134 (2**) BNE WBITLOOP Do all 8 bits!
C182- 135
C182-20 F1 C1 136 ( 6) JSR INCADDR Increment address
C185-A0 1E 137 ( 2) LDY #30 Compensate timer for extra work
C187-90 EC 138 (2**) BCC WRNEXT Not done yet! Write next byte
C189- 139
C189-A6 28 140 ( 3) RESTIDX LDX SAVEINDEX Restore index in input line
C18B-B0 98 141 (2**) BCS NEXTCMD Always taken!
C18D- 142
C18D- 143 ;-------------------------------------------------------------------------
C18D- 144 ; Read from tape
C18D- 145 ;-------------------------------------------------------------------------
C18D- 146
C18D-20 BC C1 147 ( 6) READ JSR FULLCYCLE Wait until full cycle is detected
C190-A9 16 148 ( 2) LDA #22 Introduce some delay to allow
C192-20 CC C1 149 ( 6) JSR WHEADER the tape speed to stabilize
C195-20 BC C1 150 ( 6) JSR FULLCYCLE Synchronize with full cycle
C198- 151
C198-A0 1F 152 ( 2) NOTSTART LDY #31 Try to detect the much shorter
C19A-20 BF C1 153 ( 6) JSR CMPLEVEL start bit
C19D-B0 F9 154 (2**) BCS NOTSTART Start bit not detected yet!
C19F- 155
C19F-20 BF C1 156 ( 6) JSR CMPLEVEL Wait for 2nd phase of start bit
C1A2- 157
C1A2-A0 3A 158 ( 2) LDY #58 Set threshold value in middle
C1A4-A2 08 159 ( 2) RDBYTE LDX #8 Receiver 8 bits
C1A6-48 160 ( 3) RDBIT PHA
C1A7-20 BC C1 161 ( 6) JSR FULLCYCLE Detect a full cycle
C1AA-68 162 ( 4) PLA
C1AB-2A 163 ( 2) ROL Roll new bit into result
C1AC-A0 39 164 ( 2) LDY #57 Set threshold value in middle
C1AE-CA 165 ( 2) DEX Decrement bit counter
C1AF-D0 F5 166 (2**) BNE RDBIT Read next bit!
C1B1-81 26 167 ( 6) STA (HEX2L,X) Save new byte
C1B3- 168
C1B3-20 F1 C1 169 ( 6) JSR INCADDR Increment address
C1B6-A0 35 170 ( 2) LDY #53 Compensate threshold with workload
C1B8-90 EA 171 (2**) BCC RDBYTE Do next byte if not done yet!
C1BA-B0 CD 172 (2**) BCS RESTIDX Always taken! Restore parse index
C1BC- 173
C1BC-20 BF C1 174 ( 6) FULLCYCLE JSR CMPLEVEL Wait for two level changes
C1BF-88 175 ( 2) CMPLEVEL DEY Decrement time counter
C1C0-AD 81 C0 176 ( 4) LDA TAPEIN Get Tape In data
C1C3-C5 29 177 ( 3) CMP LASTSTATE Same as before?
C1C5-F0 F8 178 (2**) BEQ CMPLEVEL Yes!
C1C7-85 29 179 ( 2) STA LASTSTATE Save new data
C1C9- 180
C1C9-C0 80 181 ( 2) CPY #128 Compare threshold
C1CB-60 182 ( 6) RTS
C1CC- 183
C1CC- 184 ;-------------------------------------------------------------------------
C1CC- 185 ; Write header to tape
C1CC- 186 ;
C1CC- 187 ; The header consists of an asymmetric cycle, starting with one phase of
C1CC- 188 ; approximately (66+47)x5=565us, followed by a second phase of
C1CC- 189 ; approximately (44+47)x5=455us.
C1CC- 190 ; Total cycle duration is approximately 1020us ~ 1kHz. The actual
C1CC- 191 ; frequencywill be a bit lower because of the additional workload between
C1CC- 192 ; the twoloops.
C1CC- 193 ; The header ends with a short phase of (30+47)x5=385us and a normal
C1CC- 194 ; phase of (44+47)x5=455us. This start bit must be detected by the read
C1CC- 195 ; routine to trigger the reading of the actual data.
C1CC- 196 ;-------------------------------------------------------------------------
C1CC- 197
C1CC-86 28 198 ( 3) WHEADER STX SAVEINDEX Save index in input line
C1CE-A0 42 199 ( 2) HCOUNT LDY #66 Extra long delay
C1D0-20 E0 C1 200 ( 6) JSR WDELAY CY is constantly 1, writing a 1
C1D3-D0 F9 201 (2**) BNE HCOUNT Do this 64 * 256 time!
C1D5-69 FE 202 ( 2) ADC #-2 Decrement A (CY=1 all the time)
C1D7-B0 F5 203 (2**) BCS HCOUNT Not all done!
C1D9-A0 1E 204 ( 2) LDY #30 Write a final short bit (start)
C1DB- 205
C1DB- 206 ;-------------------------------------------------------------------------
C1DB- 207 ; Write a full bit cycle
C1DB- 208 ;
C1DB- 209 ; Upon entry Y contains a compensated value for the first phase of 0
C1DB- 210 ; bit length. All subsequent loops don't have to be time compensated.
C1DB- 211 ;-------------------------------------------------------------------------
C1DB- 212
C1DB-20 E0 C1 213 ( 6) WRITEBIT JSR WDELAY Do two equal phases
C1DE-A0 2C 214 ( 2) LDY #44 Load 250us counter - compensation
C1E0- 215
C1E0-88 216 ( 2) WDELAY DEY Delay 250us (one phase of 2kHz)
C1E1-D0 FD 217 (2**) BNE WDELAY
C1E3-90 05 218 (2**) BCC WRITE1 Write a '1' (2kHz)
C1E5- 219
C1E5-A0 2F 220 ( 2) LDY #47 Additional delay for '0' (1kHz)
C1E7-88 221 ( 2) WDELAY0 DEY (delay 250us)
C1E8-D0 FD 222 (2**) BNE WDELAY0
C1EA- 223
C1EA-BC 00 C0 224 ( 4*) WRITE1 LDY FLIP,X Flip the output bit
C1ED-A0 29 225 ( 2) LDY #41 Reload 250us cntr (compensation)
C1EF-CA 226 ( 2) DEX Decrement bit counter
C1F0-60 227 ( 6) RTS
C1F1- 228
C1F1- 229 ;-------------------------------------------------------------------------
C1F1- 230 ; Increment current address and compare with last address
C1F1- 231 ;-------------------------------------------------------------------------
C1F1- 232
C1F1-A5 26 233 ( 3) INCADDR LDA HEX2L Compare current address with
C1F3-C5 24 234 ( 3) CMP HEX1L end address
C1F5-A5 27 235 ( 3) LDA HEX2H
C1F7-E5 25 236 ( 3) SBC HEX1H
C1F9-E6 26 237 ( 5) INC HEX2L And increment current address
C1FB-D0 02 238 (2**) BNE NOCARRY No carry to MSB!
C1FD-E6 27 239 ( 5) INC HEX2H
C1FF-60 240 ( 6) NOCARRY RTS
C200- 241
C200- 242 ;-------------------------------------------------------------------------
C200- 243