; AODIS ; Copyright (c) 1997,98 Xaviar ; Version 0.31, Apr. 21, 1998 ; Disassembly of file 6502.rom ; File size is 8192 bytes, loaded at $C000-$DFFF ; Reset: $C000, nmi: $C000, brk/irq: $C009 ; Data included ; Start-up/reset routine ; NMI routine ;;============================================================================= ;; RESET vector ;;----------------------------------------------------------------------------- C000 4C FC C1 JMP $C1FC ;;============================================================================= ;;============================================================================= ;; ??? vector -- Reached via RPC request from CP-1600 side. ;;----------------------------------------------------------------------------- C003 4C 7B C2 JMP $C27B ;;============================================================================= ;; ??? vector ;;----------------------------------------------------------------------------- C006 4C CD C2 JMP $C2CD ;;============================================================================= ;; BRK/IRQ vector ;;----------------------------------------------------------------------------- C009 48 PHA ; Save accumulator C00A AD 07 40 LDA $4007 ; \_ Bit 7 clear indicates pending tape int C00D 30 16 BMI $C025 ; / If set, go to SR1 (60Hz) handler instead ;; -------------------------------------------------------------------- ;; ;; Handle tape-oriented interrupts. ;; ;; -------------------------------------------------------------------- ;; C00F A5 B7 LDA $B7 ; \_ Data to XOR with next bit read via $4000? C011 8D 40 40 STA $4040 ; / (Manchester decoder?) C014 8A TXA ; \ C015 48 PHA ; |__ Save X and Y on stack. C016 98 TYA ; | C017 48 PHA ; / C018 AC 05 40 LDY $4005 ; Data detect in bit 7 (0 = data present) C01B AD 00 40 LDA $4000 ; Data from tape in bit 7 ? C01E 8D 80 40 STA $4080 ; Clear Tape Interrupt pending C021 D8 CLD ; Clear decimal mode... but why here? C022 6C E8 03 JMP ($03E8) ; Jump to tape-oriented interrupt handler ;; -------------------------------------------------------------------- ;; ;; Handle SR1 (60Hz refresh) and other interrupts ;; ;; -------------------------------------------------------------------- ;; C025 AD 06 40 LDA $4006 ; \_ Bit 7 clear indicates pending SR1 int. C028 30 78 BMI $C0A2 ; / If set, it must be cart bus int or other C02A AD A0 40 LDA $40A0 ; Clear SR1 Interrupt Pending C02D 58 CLI ; Enable interrupts (why here??) C02E AD D5 03 LDA $03D5 ; Are SR1 interrupts blocked? C031 F0 05 BEQ $C038 ; No, then go handle it. C033 EE D6 03 INC $03D6 ; \ C036 68 PLA ; |-- Yes: Increment drop count and exit. C037 40 RTI ; / C038 AD D8 03 LDA $03D8 ; Is SR1 interrupt handler busy? C03B F0 05 BEQ $C042 ; No: push state and go to user-installed hook C03D EE D8 03 INC $03D8 ; \ C040 68 PLA ; |-- Yes: Increment drop count and exit. C041 40 RTI ; / (Is this a CP-1600 handshake?) ;; -------------------------------------------------------------------- ;; ;; SR1 primary interrupt service. ;; ;; -------------------------------------------------------------------- ;; C042 8A TXA ; \ C043 48 PHA ; | C044 98 TYA ; | C045 48 PHA ; | C046 A5 96 LDA $96 ; | C048 48 PHA ; | C049 A5 97 LDA $97 ; | C04B 48 PHA ; | C04C A5 98 LDA $98 ; | C04E 48 PHA ; | C04F A5 99 LDA $99 ; |-- Push X, Y, and temp variables. C051 48 PHA ; | C052 A5 90 LDA $90 ; | C054 48 PHA ; | C055 A5 91 LDA $91 ; | C057 48 PHA ; | C058 A5 92 LDA $92 ; | C05A 48 PHA ; | C05B A5 94 LDA $94 ; | C05D 48 PHA ; | C05E A5 95 LDA $95 ; | C060 48 PHA ; / C061 D8 CLD ; For sanity's sake. C062 20 6E C0 JSR $C06E ; Call handler vector at ($03D3) C065 68 PLA ; \ C066 85 95 STA $95 ; | C068 68 PLA ; |-- Restore variables and return from int. C069 85 94 STA $94 ; | C06B 4C 87 C0 JMP $C087 ; / C06E 6C D3 03 JMP ($03D3) ; Call handler. ;; -------------------------------------------------------------------- ;; ;; Extended interrupt return path (called from below) ;; ;; ... JMP C071 plugged into "soft interrupt table" at $0400 at init ;; ;; -------------------------------------------------------------------- ;; C071 68 PLA ; \ C072 85 FC STA $FC ; |__ Restore $FC, $FB C074 68 PLA ; | C075 85 FB STA $FB ; / C077 CE D5 03 DEC $03D5 ; Decrement busy count (make un-busy) C07A A9 00 LDA #$00 ; \ C07C 8D 42 40 STA $4042 ; |__ Handle dropped events. C07F CE D6 03 DEC $03D6 ; | C082 10 D7 BPL $C05B ; / C084 EE D6 03 INC $03D6 ; Set event count back to 0. ;; -------------------------------------------------------------------- ;; ;; Common interrupt return path. SR1 path comes in here. ;; ;; -------------------------------------------------------------------- ;; C087 68 PLA ; \ C088 85 92 STA $92 ; | C08A 68 PLA ; | C08B 85 91 STA $91 ; | C08D 68 PLA ; | C08E 85 90 STA $90 ; | C090 68 PLA ; | C091 85 99 STA $99 ; | C093 68 PLA ; |-- Restore variables, X, Y and return. C094 85 98 STA $98 ; | C096 68 PLA ; | C097 85 97 STA $97 ; | C099 68 PLA ; | C09A 85 96 STA $96 ; | C09C 68 PLA ; | C09D A8 TAY ; | C09E 68 PLA ; | C09F AA TAX ; | C0A0 68 PLA ; / C0A1 40 RTI ; Return from interrupt ;;============================================================================= ;; Handle Cartridge Bus Interrupt and other non-SR1, non-tape interrupts. ;;----------------------------------------------------------------------------- C0A2 A9 01 LDA #$01 ; \_ Disable keyboard cartridge bus interrupts C0A4 8D 42 40 STA $4042 ; / C0A7 EE D5 03 INC $03D5 ; Up the semaphore ("busy flag") C0AA 58 CLI ; Enable interrupts (re-entrant) C0AB 8D 07 03 STA $0307 ; Prevent screen from blanking ("recent input") C0AE 8A TXA ; \ C0AF 48 PHA ; | C0B0 98 TYA ; | C0B1 48 PHA ; | C0B2 A5 96 LDA $96 ; | C0B4 48 PHA ; | C0B5 A5 97 LDA $97 ; | C0B7 48 PHA ; | C0B8 A5 98 LDA $98 ; | C0BA 48 PHA ; | C0BB A5 99 LDA $99 ; |-- Push X, Y, and temp variables. C0BD 48 PHA ; | C0BE A5 90 LDA $90 ; | C0C0 48 PHA ; | C0C1 A5 91 LDA $91 ; | C0C3 48 PHA ; | C0C4 A5 92 LDA $92 ; | C0C6 48 PHA ; | C0C7 A5 FB LDA $FB ; | C0C9 48 PHA ; | C0CA A5 FC LDA $FC ; | C0CC 48 PHA ; / C0CD D8 CLD ; For sanity's sake. C0CE A2 02 LDX #$02 ; \__ Invoke handler that was unpacked to C0D0 4C 00 04 JMP $0400 ; / RAM at $0400. (Why unpacked to RAM?) ;;============================================================================= ;;============================================================================= ;; Interrupt-driven device driver / FIFO management ;; ;; X holds FIFO number ;; Handler registry begins at $0342. ;; Each registry entry is 12 bytes ;; ;; $0341 Driver flags ;; Bit Meaning ;; 0 Driver has xmit ;; 1 Driver has recv ;; ;; $0342 - $0343 Xmit FIFO address ;; $0344 - $0345 Recv FIFO address ;; $0346 - $0347 Pointer to ? (written to selfmod code @ $FA-$FD) ;; $0348 - $0349 Pointer to handler jump table: ;; Offset Description ;; 0 Work-to-do handler. ;; V=1 means "no work" ;; V=0, C=1 means "do xmit" ;; V=0, C=0 means "do recv" ;; 3 Recv FIFO empty handler ;; 6 Called with "received byte" in 'A' ;; 9 ? ;; 12 Xmit FIFO full handler ;; 15 Returns byte to xmit in 'A' ;; $034A - $034B Unknown. ;; $034C Polled on CP-1600 side ? (at least for FIFO #0) ;; ;;----------------------------------------------------------------------------- C0D3 8A TXA ; \ C0D4 85 90 STA $90 ; | C0D6 0A ASL A ; | C0D7 65 90 ADC $90 ; |- Multiply X by 12 C0D9 0A ASL A ; | C0DA 0A ASL A ; | C0DB AA TAX ; / C0DC BD 46 03 LDA $0346,X ; \ C0DF 85 FB STA $FB ; |_ Point STA in self-mod code to point C0E1 BD 47 03 LDA $0347,X ; | to addr in $346,X - $347,X C0E4 85 FC STA $FC ; / C0E6 A9 00 LDA #$00 C0E8 20 2D C1 JSR $C12D ; Jump to address held in $348,X - $349,X C0EB 70 84 BVS $C071 ; If V=1, return from interrupt. C0ED 90 1F BCC $C10E ; If C=1, do xmit. If C=0, do recv. C0EF BD 42 03 LDA $0342,X ; \ C0F2 85 98 STA $98 ; |_ Put xmit FIFO address in ($98) C0F4 BD 43 03 LDA $0343,X ; | C0F7 85 99 STA $99 ; / C0F9 A9 0F LDA #$0F ; \_ Jump to 15 past addr in $348,X - $349,X C0FB 20 2D C1 JSR $C12D ; / Get a byte to send into 'A' C0FE 20 E0 DE JSR $DEE0 ; Put 'A' in FIFO C101 20 1E DF JSR $DF1E ; Is FIFO full? C104 90 05 BCC $C10B ; No: Return from interrupt C106 A9 0C LDA #$0C ; \_ Yes: Call handler at 12 past addr C108 20 2D C1 JSR $C12D ; / in $348,X - $349,X C10B 4C 71 C0 JMP $C071 ; Return from interrupt C10E BD 44 03 LDA $0344,X ; \ C111 85 98 STA $98 ; |_ Put recv FIFO address in ($98) C113 BD 45 03 LDA $0345,X ; | C116 85 99 STA $99 ; / C118 20 A1 DE JSR $DEA1 ; Get a decle from the FIFO C11B A9 06 LDA #$06 ; \_ Jump to 6 past addr in $348,X - $349,X C11D 20 2D C1 JSR $C12D ; / Send byte held in 'X' C120 20 34 DF JSR $DF34 ; Is FIFO empty? C123 90 E6 BCC $C10B ; No? Return from interrupt C125 A9 03 LDA #$03 ; \_ Yes: Call handler 3 past addr in C127 20 2D C1 JSR $C12D ; / $348,X - $349,X C12A 4C 71 C0 JMP $C071 ; Return from interrupt ;;============================================================================= ;; Jump 'A' bytes past vector stored in $348,X ;;----------------------------------------------------------------------------- C12D 18 CLC ; C12E 7D 48 03 ADC $0348,X ; \ C131 85 96 STA $96 ; |__ Copy vector from $348,X and add A to C133 BD 49 03 LDA $0349,X ; | low byte. C136 85 97 STA $97 ; / C138 6C 96 00 JMP ($0096) ; Dispatch to the vector. ;;============================================================================= ;;============================================================================= ;; Default vector for ($03D3) ;;----------------------------------------------------------------------------- C13B 20 5C C1 JSR $C15C ; C13E CE D7 03 DEC $03D7 ; C141 D0 15 BNE $C158 ; If $03D7 was zero, CP-1600 wants to print. C143 AD 06 03 LDA $0306 ; \__ CP-1600 handshake. C146 8D 06 43 STA $4306 ; / C149 20 07 C3 JSR $C307 ; C14C 20 41 C4 JSR $C441 ; Disp str from CP-1600 side as it arrives C14F 20 A7 C4 JSR $C4A7 ; ?? C152 20 88 C6 JSR $C688 ; Display rest of string from CP-1600 side. C155 20 D2 C8 JSR $C8D2 ; C158 EE D7 03 INC $03D7 ; C15B 60 RTS ; ;;============================================================================= ;;============================================================================= ;; ?TAPE ISR handler? ;;----------------------------------------------------------------------------- C15C EE D8 03 INC $03D8 ; Set busy semaphore C15F 20 71 C1 JSR $C171 ; Timer tick update C162 20 0F D0 JSR $D00F ; C165 20 3A D1 JSR $D13A ; C168 20 DB D0 JSR $D0DB ; Set up tape mode? C16B CE D8 03 DEC $03D8 ; Decrement busy semaphore C16E D0 EF BNE $C15F ; Handle dropped events. C170 60 RTS ;;============================================================================= ;;============================================================================= ;; Timer Tick Interrupt handler: Count the time, blank the screen ;;----------------------------------------------------------------------------- C171 AE C6 03 LDX $03C6 ; \ C174 E8 INX ; |_ Increment count from $03C6 C175 E0 3C CPX #$3C ; | and jump if less than 60 C177 30 21 BMI $C19A ; / C179 A2 00 LDX #$00 ; Reset count to 0 C17B AC C5 03 LDY $03C5 ; \ C17E C8 INY ; |_ Increment count from $03C5 C17F C0 3C CPY #$3C ; | and jump if less than 60 C181 30 14 BMI $C197 ; / C183 A0 00 LDY #$00 ; Reset count to 0 C185 AD C4 03 LDA $03C4 ; \ C188 18 CLC ; |_ Increment count from $03C4 C189 69 01 ADC #$01 ; | and jump if less than 60 C18B C9 3C CMP #$3C ; / C18D 30 05 BMI $C194 ; C18F A9 00 LDA #$00 ; Reset count to 0 C191 EE C3 03 INC $03C3 ; Increment count at $03C3 C194 8D C4 03 STA $03C4 ; \ C197 8C C5 03 STY $03C5 ; |- store updated time C19A 8E C6 03 STX $03C6 ; / C19D EE C7 03 INC $03C7 ; \ C1A0 D0 19 BNE $C1BB ; |_ Count down time-compensation counter C1A2 EE C8 03 INC $03C8 ; | C1A5 30 14 BMI $C1BB ; / C1A7 8A TXA ; \ C1A8 49 FF EOR #$FF ; |_ Do something, erm, interesting with C1AA 2D CB 03 AND $03CB ; | tic count? C1AD 85 F7 STA $F7 ; / C1AF A9 F6 LDA #$F6 ; \ C1B1 8D C7 03 STA $03C7 ; | C1B4 A9 FC LDA #$FC ; |- Reinitialize time-compensation counter. C1B6 8D C8 03 STA $03C8 ; | Add a new tic every 1033 tics. C1B9 30 B9 BMI $C174 ; / (Always taken.) C1BB A2 04 LDX #$04 ; C1BD BD FD 3F LDA $3FFD,X ; Strobe $4001 (why is it written this way?) C1C0 A9 40 LDA #$40 ; \ C1C2 35 9C AND $9C,X ; | C1C4 D0 02 BNE $C1C8 ; |__ Decrement each of $A0 downto $9C C1C6 D6 9C DEC $9C,X ; | if bit 6 isn't set in that location. C1C8 CA DEX ; | (Countdown timers?) C1C9 10 F5 BPL $C1C0 ; / C1CB AD 7F 04 LDA $047F ; \ C1CE F0 03 BEQ $C1D3 ; |-- If $047F isn't zero yet, decrement it C1D0 CE 7F 04 DEC $047F ; / C1D3 EE CA 03 INC $03CA ; \___ Incr $03CA, and return if it didn't C1D6 D0 08 BNE $C1E0 ; / roll over. C1D8 AD 07 03 LDA $0307 ; \ If display is blanked, leave it that C1DB F0 03 BEQ $C1E0 ; |-- way for now. Otherwise, increment the C1DD EE 07 03 INC $0307 ; / "input happened recently" flag. C1E0 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Set initial tape ISR vector & init $4041 to 0. (point $3E8 @ $CE79) ;;----------------------------------------------------------------------------- C1E1 A9 79 LDA #$79 ; \_ $CE79 is "return from interrupt" C1E3 A2 CE LDX #$CE ; / C1E5 8E 00 44 STX $4400 ; ?? why? Only stores $02 to here. C1E8 A0 00 LDY #$00 C1EA F0 02 BEQ $C1EE ; Always taken. ;;============================================================================= ;; Set tape ISR vector in A, X, and enable tape interrupts ;;----------------------------------------------------------------------------- C1EC A0 FF LDY #$FF C1EE 08 PHP ; Save flags C1EF 78 SEI C1F0 8D E8 03 STA $03E8 ; Set interrupt vector to $CE79 C1F3 8E E9 03 STX $03E9 ; C1F6 8C 41 40 STY $4041 ; Enable tape interrupts C1F9 28 PLP ; Restore flags C1FA 60 RTS ; Return ;;============================================================================= ; Data at $C1FB C1FB .byte $8D ; ??? ;;============================================================================= ;; RESET Bootup Sequence ;;----------------------------------------------------------------------------- C1FC 78 SEI ; Disable interrupts C1FD D8 CLD ; Clear "decimal" mode -- 2s complement arith. C1FE A2 FF LDX #$FF ; \ C200 9A TXS ; / Init stack ptr to $FF (Top==$100) C201 A9 9C LDA #$9C ; \ C203 85 94 STA $94 ; | C205 A9 00 LDA #$00 ; | C207 85 95 STA $95 ; |-- Clear $64 bytes starting C209 A9 64 LDA #$64 ; | at location $009C. C20B 85 90 STA $90 ; | C20D 20 D2 DF JSR $DFD2 ; / C210 A9 02 LDA #$02 ; \ C212 85 95 STA $95 ; | C214 A9 0E LDA #$0E ; | C216 85 97 STA $97 ; |__ Clear $0E00 bytes starting C218 A9 00 LDA #$00 ; | at location $0200. C21A 85 94 STA $94 ; | C21C 85 96 STA $96 ; | C21E 20 BE DF JSR $DFBE ; / C221 A9 42 LDA #$42 ; \ C223 85 95 STA $95 ; | C225 A9 0E LDA #$0E ; |-- Clear $0E00 bytes starting C227 85 97 STA $97 ; | at location $4200. C229 20 BE DF JSR $DFBE ; / C22C A9 B8 LDA #$B8 ; \ C22E 85 95 STA $95 ; | C230 A9 08 LDA #$08 ; |-- Clear $0800 bytes starting C232 85 97 STA $97 ; | at location $B800. C234 20 BE DF JSR $DFBE ; / C237 A9 3B LDA #$3B ; \ C239 8D D3 03 STA $03D3 ; |__ Set vector $03D3 ==> $C13B C23C A9 C1 LDA #$C1 ; | (??) C23E 8D D4 03 STA $03D4 ; / C241 A9 16 LDA #$16 ; \ C243 8D 6A 04 STA $046A ; |__ Set vector $046A ==> $CC16 C246 A9 CC LDA #$CC ; | (??) C248 8D 6B 04 STA $046B ; / C24B 20 26 C9 JSR $C926 ; Initialize display. C24E 20 24 D2 JSR $D224 ; Init $34C-$357, set up ISR vector C251 EE D7 03 INC $03D7 ; Enable default ISR activities (?) C254 EE 07 03 INC $0307 ; Unblank screen ("recent input") C257 EE C3 43 INC $43C3 ; ? (set flag to 1?) C25A A2 30 LDX #$30 C25C 20 CB DB JSR $DBCB ; ? (initialize some routine at $400) ; PROBE FOR EXPANSION ROMs. C25F A2 07 LDX #$07 ; C261 BD E7 C2 LDA $C2E7,X ; Get upper byte of expansion ROM addr C264 85 95 STA $95 ; Store it to upper byte if indr addr C266 A9 00 LDA #$00 ; Clear lower byte of indr. addr. C268 85 94 STA $94 ; C26A A0 03 LDY #$03 ; C26C A9 FF LDA #$FF ; C26E 91 94 STA ($94),Y ; Store $FF to $xx03. C270 B1 94 LDA ($94),Y ; Read it back. C272 D0 03 BNE $C277 ; Did it read as zero? C274 20 73 DC JSR $DC73 ; YES: Branch to expansion ROM. C277 CA DEX ; Decrement count -- go to next ROM. C278 10 E7 BPL $C261 ; C27A 58 CLI ; Enable Interrupts ;;============================================================================= ;; ?Slave Mode? vector -- Reached via RPC request from CP-1600 side. ;;----------------------------------------------------------------------------- C27B A9 00 LDA #$00 ; \ C27D 8D D9 03 STA $03D9 ; / Clear ? at $03D9 C280 20 96 C6 JSR $C696 ; Display any pending messages from CP1600 C283 AC BA 03 LDY $03BA ; ? C286 F0 16 BEQ $C29E ; ? C288 20 C0 C2 JSR $C2C0 ; Copy FIFO addr in $3BB-$3BC to $98-$99 C28B 20 1E DF JSR $DF1E ; Is FIFO full? C28E B0 0E BCS $C29E ; C290 AC BA 03 LDY $03BA ; ? C293 20 5F DF JSR $DF5F ; Read something from CP-1600 ? C296 B0 06 BCS $C29E ; If error ? C298 20 C0 C2 JSR $C2C0 ; Copy FIFO addr in $3BB-$3BC to $98-$99 C29B 20 E2 DE JSR $DEE2 ; Put byte into FIFO. C29E AD BD 03 LDA $03BD ; C2A1 F0 17 BEQ $C2BA ; C2A3 85 92 STA $92 ; C2A5 20 A7 DF JSR $DFA7 ; C2A8 20 1E DF JSR $DF1E ; Is FIFO full? C2AB B0 0D BCS $C2BA ; C2AD 20 BD C2 JSR $C2BD ; C2B0 20 A1 DE JSR $DEA1 ; C2B3 B0 05 BCS $C2BA ; C2B5 A4 92 LDY $92 ; C2B7 20 8B DF JSR $DF8B ; Put something to CP-1600 ? C2BA 4C 7B C2 JMP $C27B ; Loop. ;;============================================================================= C2BD A2 03 LDX #$03 C2BF 2C A2 00 BIT $00A2 ; Alt entry @ $C2C0: LDX #$00 C2C2 BD BB 03 LDA $03BB,X C2C5 85 98 STA $98 C2C7 BD BC 03 LDA $03BC,X C2CA 85 99 STA $99 C2CC 60 RTS C2CD A9 0C LDA #$0C C2CF AC 36 04 LDY $0436 C2D2 D0 FB BNE $C2CF C2D4 8D 36 04 STA $0436 C2D7 AD 35 04 LDA $0435 C2DA F0 FB BEQ $C2D7 C2DC A0 00 LDY #$00 C2DE 8C 35 04 STY $0435 C2E1 C9 1B CMP #$1B C2E3 F0 F2 BEQ $C2D7 C2E5 D0 E8 BNE $C2CF ; Data from $C2E7 to $C2EE (24 bytes) ; Expansion ROM prefix values (searched in reverse order) C2E7 .byte $E0 ; $E000 C2E8 .byte $80 ; $8000 C2E9 .byte $F0 ; $F000 C2EA .byte $B0 ; $B000 C2EB .byte $90 ; $9000 C2EC .byte $A0 ; $A000 C2ED .byte $A4 ; $A400 C2EE .byte $A8 ; $A800 ; Data from $C2EF to $C306 (24 bytes) ; jump table for CP1600->6502 RPC. C2EF .byte $6B, $C3 ; C36B $01 PEEK($340 + 12*Arg1) C2F1 .byte $71, $C3 ; C371 $02 POKE $340 + 12*Arg1, Arg2 C2F3 .byte $76, $C3 ; C376 $03 PEEK(PEEK($340 + 12*Arg1 + 6)) C2F5 .byte $81, $C3 ; C381 $04 POKE PEEK($340 + 12*Arg1 + 6)), Arg2 C2F7 .byte $40, $C3 ; C340 $05 C2F9 .byte $99, $C3 ; C399 $06 Various and sundry tape commands. C2FB .byte $E8, $C3 ; C3E8 $07 PEEK address in Arg1/Arg2 C2FD .byte $EE, $C3 ; C3EE $08 POKE Arg3 to address in Arg1/Arg2 C2FF .byte $F3, $C3 ; C3F3 $09 Jump to address in Arg1/Arg2 C301 .byte $F6, $C3 ; C3F6 $0A Reset 6502 side and vector to routine C303 .byte $0F, $C4 ; C40F $0B MemCopy C305 .byte $22, $C4 ; C422 $0C Kbd Pause Mode / Flush output FIFO ;;============================================================================= ;; Receive command from CP-1600 side ;;----------------------------------------------------------------------------- C307 AD 01 03 LDA $0301 ; \___ If no command pending from CP-1600 C30A F0 33 BEQ $C33F ; / side, then just leave. C30C A0 01 LDY #$01 C30E C9 0D CMP #$0D ; Is CMD >= $0D? C310 B0 25 BCS $C337 ; Yes: Store 1 to $0300 (error?) and return C312 0A ASL A ; \ C313 AA TAX ; | C314 BD ED C2 LDA $C2ED,X ; |__ Look up command number in jump table C317 85 98 STA $98 ; | C319 BD EE C2 LDA $C2EE,X ; | C31C 85 99 STA $99 ; / C31E AD 03 03 LDA $0303 ; \ C321 85 94 STA $94 ; | C323 85 91 STA $91 ; |-- $303/$304 maybe address in ($94), C325 AD 04 03 LDA $0304 ; | or $303 "arg2" in $91 C328 85 95 STA $95 ; / C32A AD 02 03 LDA $0302 ; \___ $302 always "arg1" in $90 C32D 85 90 STA $90 ; / C32F 20 98 C4 JSR $C498 ; Point ($96) at $340+12*A. Clear Y. C332 A5 90 LDA $90 ; C334 20 21 D2 JSR $D221 ; Jump to command vector ($98) C337 8C 00 03 STY $0300 ; Store command return value in $0300 C33A A9 00 LDA #$00 ; \___ Clear command C33C 8D 01 03 STA $0301 ; / C33F 60 RTS ; Return ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #5: ? ;;----------------------------------------------------------------------------- C340 C9 02 CMP #$02 ; \ C342 10 03 BPL $C347 ; |__ If A is >= 2, store it to $03D2, else C344 AD D2 03 LDA $03D2 ; | get A from $03D2. C347 8D D2 03 STA $03D2 ; / C34A 20 98 C4 JSR $C498 ; Set $96/$97 to $340 + 12*A. C34D C8 INY ; Set Y==1 C34E B1 94 LDA ($94),Y ; Get byte from (Arg2/Arg3), 1 C350 D0 04 BNE $C356 ; If it's zero, store it to ($96),1 C352 91 96 STA ($96),Y ; C354 F0 32 BEQ $C388 ; always taken: Return "code==0 / Success" C356 B1 96 LDA ($96),Y ; If ($96),1 was already non-zero, return Y==2 C358 D0 06 BNE $C360 ; C35A 20 21 DC JSR $DC21 ; ?? C35D A0 00 LDY #$00 ; Return code==0 / Success. C35F 60 RTS ; C360 A0 02 LDY #$02 ; Return code==2 / ??? C362 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Copy 12 bytes from ($94) to $340 + 12*A ;;----------------------------------------------------------------------------- C363 20 98 C4 JSR $C498 ; Set $96/$97 to $340 + 12*A C366 A0 0C LDY #$0C C368 4C E0 DF JMP $DFE0 ; Copy 12 bytes, src=($94), dst=($96) ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #1: "PEEK($340+12*arg1)" ;;----------------------------------------------------------------------------- C36B B1 96 LDA ($96),Y ; Read location on CP-1600's behalf C36D 8D 05 03 STA $0305 ; Store it to return value loc C370 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #2: "POKE $340+12*arg1, arg2" ;;----------------------------------------------------------------------------- C371 A5 91 LDA $91 ; Get value to store on CP-1600's behalf C373 91 96 STA ($96),Y ; Store it to $340 + 12*arg1 C375 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #3: "PEEK(PEEK($340 + 12*Arg1 + 6) + Arg2)" ;;----------------------------------------------------------------------------- C376 20 8B C3 JSR $C38B ; C379 B1 90 LDA ($90),Y ; Peek there. C37B 8D 05 03 STA $0305 ; Return this to CP-1600 C37E 4C 88 C3 JMP $C388 ; Return "no error". ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #4: "POKE PEEK($340 + 12*Arg1 + 6) + Arg2), Arg3" ;;----------------------------------------------------------------------------- C381 20 8B C3 JSR $C38B ; Prepare to index into ?? table C384 A5 95 LDA $95 ; Get value to store C386 91 90 STA ($90),Y ; Store it. C388 A0 00 LDY #$00 ; Return "no error" C38A 60 RTS ;;============================================================================= ;;============================================================================= ;; Prepare to index into array pointed to by ($340 + 12*arg1 + 6) ;; ;; Get 16-bit address from ($340 + 12*arg1 + 6) into ($90). ;; Copy arg2 from $91 into Y to serve as offset. ;;----------------------------------------------------------------------------- C38B A0 06 LDY #$06 C38D B1 96 LDA ($96),Y C38F 85 90 STA $90 C391 C8 INY C392 B1 96 LDA ($96),Y C394 A4 91 LDY $91 C396 85 91 STA $91 C398 60 RTS ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #6: Various and sundry TAPE commands. ;;----------------------------------------------------------------------------- C399 A0 00 LDY #$00 ; clear flag in $E7 C39B 84 E7 STY $E7 ; C39D A0 03 LDY #$03 ; Y = 3 C39F AA TAX ; X = arg1 C3A0 F0 45 BEQ $C3E7 ; If arg1 == 0, return code==3. C3A2 C9 11 CMP #$11 ; \___ If arg1 > $11, return code == 3 C3A4 10 41 BPL $C3E7 ; / C3A6 C9 04 CMP #$04 ; \___ If arg1 < $4, goto $C3D9 C3A8 30 2F BMI $C3D9 ; / C3AA D0 0A BNE $C3B6 ; If arg1 != $4, goto $C3B6 C3AC 24 D8 BIT $D8 ; \___ Is bit 7 of $D8 set? Yes: goto $C3BC C3AE 30 0C BMI $C3BC ; / C3B0 AD 02 44 LDA $4402 ; \ C3B3 4A LSR A ; |-- Is Bit 0 of $4402 zero? Yes: $C3BC C3B4 90 06 BCC $C3BC ; / C3B6 A0 04 LDY #$04 ; \_ State #4 in tape state machine C3B8 A5 E4 LDA $E4 ; / C3BA D0 2B BNE $C3E7 ; (always taken) C3BC EE D8 03 INC $03D8 ; C3BF A5 90 LDA $90 ; C3C1 85 E4 STA $E4 ; C3C3 A5 94 LDA $94 ; C3C5 85 E5 STA $E5 ; C3C7 A5 95 LDA $95 ; C3C9 85 E6 STA $E6 ; C3CB A9 00 LDA #$00 ; C3CD 8D D0 00 STA $00D0 ; C3D0 8D D1 00 STA $00D1 ; C3D3 20 3A D1 JSR $D13A ; ?? (big routine!) C3D6 4C DF C3 JMP $C3DF ; C3D9 EE D8 03 INC $03D8 ; Increment "TAPE event pending" semaphore C3DC 20 FB D1 JSR $D1FB ; ? C3DF A5 E7 LDA $E7 ; \ Save whatever from $E7 on stack C3E1 48 PHA ; / C3E2 20 6B C1 JSR $C16B ; Handle any pending TAPE events. C3E5 68 PLA ; \ C3E6 A8 TAY ; / Return what we saved from $E7 to CP-1600 C3E7 60 RTS ; ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #7: PEEK address in Arg1/Arg2 ;;----------------------------------------------------------------------------- C3E8 B1 90 LDA ($90),Y ; Read requested location. (Note Y==0) C3EA 8D 05 03 STA $0305 ; Store it to our return value. C3ED 60 RTS ; Return (code==0 aka Success, since Y==0) ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #8: POKE Arg3 to address in Arg1/Arg2 ;;----------------------------------------------------------------------------- C3EE A5 95 LDA $95 ; Get value to write C3F0 91 90 STA ($90),Y ; Store out to requested address. (Note Y==0) C3F2 60 RTS ; Return (code==0 aka Success, since Y==0). ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #9: Jump to address in Arg1/Arg2 ;;----------------------------------------------------------------------------- C3F3 6C 02 03 JMP ($0302) ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #A: Reset 6502 side and vector to routine ;; Arg1/Arg2 Address to vector to. ;;----------------------------------------------------------------------------- C3F6 A2 FF LDX #$FF ; \___ Reset the stack pointer (!) C3F8 9A TXS ; / C3F9 A9 00 LDA #$00 ; \ C3FB 8D 00 03 STA $0300 ; |-- Clear return code, RPC command C3FE 8D 01 03 STA $0301 ; / C401 EE D7 03 INC $03D7 ; ? C404 A9 81 LDA #$81 ; C406 8D D9 03 STA $03D9 ; Set "Can print from CP-1600" flag. C409 8E DA 03 STX $03DA ; Set "No message pending" flag. C40C 6C 90 00 JMP ($0090) ; Vector to address provided by RPC call. ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #B: memcpy() ;; Arg1/Arg2 Forms pointer to block w/ src, dst addresses. ;; Arg3 Gives count of bytes to copy. ;;----------------------------------------------------------------------------- C40F A0 03 LDY #$03 ; C411 B1 90 LDA ($90),Y ; \ Copy 4 bytes from ($90),0..3 to C413 99 94 00 STA $0094,Y ; |__ locations $94..$97. This sets up C416 88 DEY ; | src/dst args for memcpy() below. C417 10 F8 BPL $C411 ; / C419 AC 04 03 LDY $0304 ; Get length of block to copy into Y. C41C 20 E0 DF JSR $DFE0 ; Copy arg3 bytes C41F A0 00 LDY #$00 ; Return "success" C421 60 RTS ; ;;============================================================================= ;;============================================================================= ;; CP-1600 -> 6502 RPC cmd #C: ;; If Z==0, set bit 6 of mode bits in $A8. ;; If Z==1, clear all mode bits in $A8 and flush CP-1600->6502 msg FIFO ;;----------------------------------------------------------------------------- C422 F0 09 BEQ $C42D ; C424 A9 40 LDA #$40 ; ;fallthru ;;============================================================================= ;; Set mode bits in $A8 by ORing with 'A' ;;----------------------------------------------------------------------------- C426 05 A8 ORA $A8 ; C428 85 A8 STA $A8 ; C42A A0 00 LDY #$00 ; C42C 60 RTS ; ;;============================================================================= ;; Clear mode bits (except bit 0) and flush CP-1600=>6502 message FIFO ;;----------------------------------------------------------------------------- C42D A9 01 LDA #$01 ; C42F 20 8C C9 JSR $C98C ; Clear all but bit 0 of mode bits. C432 20 AE C6 JSR $C6AE ; Get address of CP-1600->6502 message FIFO C435 A0 01 LDY #$01 ; \ C437 B1 98 LDA ($98),Y ; |__ Force message FIFO to be empty. C439 88 DEY ; | (Flush all its contents.) C43A 91 98 STA ($98),Y ; / C43C 60 RTS ; ;;============================================================================= ;;============================================================================= ;; ESC: Set Bit 1 of $A8 flags ;;----------------------------------------------------------------------------- C43D A9 02 LDA #$02 C43F D0 E5 BNE $C426 ; Always taken. ;;============================================================================= ;;============================================================================= ;; Receive message from CP-1600 side of things. (flag-aware) ;;----------------------------------------------------------------------------- C441 AD DA 03 LDA $03DA ; \__ If $03DA is zero, CP-1600 wants to C444 D0 34 BNE $C47A ; / say something. C446 AD D9 03 LDA $03D9 ; \__ If $03D9 is zero, we're already C449 F0 2E BEQ $C479 ; / listening to the CP-1600-side C44B A9 00 LDA #$00 ; \ C44D 85 94 STA $94 ; | C44F A9 03 LDA #$03 ; | C451 85 95 STA $95 ; | C453 A9 DC LDA #$DC ; |-- Block copy $0300-$0305 to $03DC-$3E0 C455 85 96 STA $96 ; | C457 A9 03 LDA #$03 ; | C459 85 97 STA $97 ; | C45B 20 DE DF JSR $DFDE ; / C45E A0 00 LDY #$00 ; \__ Mark ourselves as busy listening. C460 8C D9 03 STY $03D9 ; / C463 88 DEY ; \__ Set $03DB to #$FF ?? C464 8C DB 03 STY $03DB ; / C467 68 PLA ;?\__ prepare to return to caller's caller? C468 68 PLA ;?/ C469 EE D7 03 INC $03D7 ; ? C46C 20 96 C6 JSR $C696 ; Disp pend string from CP-1600 if flag permit C46F AD DB 03 LDA $03DB ; \__ Keep doing this as long as strings are C472 D0 F8 BNE $C46C ; / pending? C474 A9 81 LDA #$81 ; C476 8D D9 03 STA $03D9 ; Set bit so $C688 will disp str from CP-1600 C479 60 RTS C47A AD DB 03 LDA $03DB ; \__ We weren't busy trying to receive, so C47D F0 FA BEQ $C479 ; / exit. ; Else, we were, so signal receiver to give ; up and flag it so routine at $C688 will ; get the message. (The 6502 side must've ; blocked the receive for some reason via ; a flag in $A8.) C47F A9 DC LDA #$DC ; \ C481 85 94 STA $94 ; | C483 A9 03 LDA #$03 ; | C485 85 95 STA $95 ; | C487 A9 00 LDA #$00 ; |-- Copy $03DC-$03E0 back to $0300-$0305 C489 85 96 STA $96 ; | C48B A9 03 LDA #$03 ; | C48D 85 97 STA $97 ; | C48F 20 DE DF JSR $DFDE ; / C492 A9 00 LDA #$00 ; \ Signal to receiver loop to give up. C494 8D DB 03 STA $03DB ; / C497 60 RTS ;;============================================================================= ;;============================================================================= ;; Point ($96) at $340 + 12*A. ;;----------------------------------------------------------------------------- C498 20 EE DF JSR $DFEE ; X = A = A*12 C49B 18 CLC C49C 69 40 ADC #$40 ; \ C49E 85 96 STA $96 ; |__ Store "$340 + 12*A" to $96/$97. C4A0 A9 03 LDA #$03 ; | C4A2 85 97 STA $97 ; / C4A4 A0 00 LDY #$00 ; Clear Y C4A6 60 RTS ;;============================================================================= ;;============================================================================= ;; Scan the keyboard ;;----------------------------------------------------------------------------- C4A7 A9 01 LDA #$01 ; \ C4A9 20 F3 C5 JSR $C5F3 ; | C4AC 0A ASL A ; | C4AD 0A ASL A ; | Scan modifier keys (CTRL, SHIFT, LOCK C4AE 85 90 STA $90 ; |-- and RPT) into four LSBs of loc $90. C4B0 A9 00 LDA #$00 ; | C4B2 20 F3 C5 JSR $C5F3 ; | Bit 3 Bit 2 Bit 1 Bit 0 C4B5 29 03 AND #$03 ; | RPT LOCK CTRL SHIFT C4B7 05 90 ORA $90 ; | C4B9 85 90 STA $90 ; / C4BB A0 00 LDY #$00 ; \ C4BD C9 0F CMP #$0F ; | C4BF F0 0A BEQ $C4CB ; | If all 4 are set, or LOCK is set, C4C1 29 04 AND #$04 ; |__ or at least one bit is same as prev. C4C3 F0 06 BEQ $C4CB ; | scan, don't toggle bit 7. Otherwise C4C5 25 A7 AND $A7 ; | set up to toggle bit 7 of $A7. C4C7 D0 02 BNE $C4CB ; | C4C9 A0 80 LDY #$80 ; / C4CB 98 TYA ; \ C4CC 45 A7 EOR $A7 ; | Toggle bit 7 if we were supposed to, C4CE 29 80 AND #$80 ; |-- and merge remaining bits of $A7 with C4D0 05 90 ORA $90 ; | mod bits, and store new bits to $A7. C4D2 85 A7 STA $A7 ; / (Bit 7 seems to be the "capitalize" bit) C4D4 A5 A5 LDA $A5 ; C4D6 F0 20 BEQ $C4F8 ; C4D8 A5 A4 LDA $A4 ; C4DA 20 F3 C5 JSR $C5F3 ; Scan kbd C4DD 25 A5 AND $A5 ; C4DF F0 15 BEQ $C4F6 ; C4E1 A5 A1 LDA $A1 ; C4E3 20 F3 C5 JSR $C5F3 ; Scan kbd C4E6 25 A2 AND $A2 ; C4E8 D0 42 BNE $C52C ; C4EA A4 A5 LDY $A5 ; C4EC 84 A2 STY $A2 ; C4EE A4 A4 LDY $A4 ; C4F0 84 A1 STY $A1 ; C4F2 A4 A6 LDY $A6 ; C4F4 84 A3 STY $A3 ; C4F6 85 A5 STA $A5 ; C4F8 A2 02 LDX #$02 ; C4FA 8A TXA ; C4FB 20 F3 C5 JSR $C5F3 ; Scan kbd C4FE E4 A1 CPX $A1 ; C500 D0 0A BNE $C50C ; C502 85 90 STA $90 ; C504 25 A2 AND $A2 ; C506 D0 02 BNE $C50A ; C508 85 A2 STA $A2 ; C50A 45 90 EOR $90 ; C50C A8 TAY ; C50D F0 18 BEQ $C527 ; C50F 85 90 STA $90 ; C511 A9 80 LDA #$80 ; C513 85 91 STA $91 ; C515 A0 00 LDY #$00 ; C517 06 90 ASL $90 ; C519 90 07 BCC $C522 ; C51B 20 45 C5 JSR $C545 ; C51E A5 A5 LDA $A5 ; C520 D0 0A BNE $C52C ; C522 C8 INY ; C523 46 91 LSR $91 ; C525 D0 F0 BNE $C517 ; C527 E8 INX ; C528 E0 0A CPX #$0A ; C52A 30 CE BMI $C4FA ; C52C 24 9D BIT $9D ; C52E 10 14 BPL $C544 ; C530 AD 26 BE LDA $BE26 ; C533 85 9D STA $9D ; C535 A5 A7 LDA $A7 ; C537 29 08 AND #$08 ; C539 F0 09 BEQ $C544 ; C53B A5 A2 LDA $A2 ; C53D F0 05 BEQ $C544 ; C53F A5 A3 LDA $A3 ; C541 20 7A C5 JSR $C57A ; C544 60 RTS ; ;;============================================================================= ;;============================================================================= ;; ?? ;;----------------------------------------------------------------------------- C545 A5 90 LDA $90 C547 48 PHA C548 8A TXA C549 48 PHA C54A 98 TYA C54B 48 PHA C54C A5 A2 LDA $A2 C54E F0 0A BEQ $C55A C550 85 A5 STA $A5 C552 A5 A1 LDA $A1 C554 85 A4 STA $A4 C556 A5 A3 LDA $A3 C558 85 A6 STA $A6 C55A 86 A1 STX $A1 C55C A5 91 LDA $91 C55E 85 A2 STA $A2 C560 8A TXA C561 0A ASL A C562 0A ASL A C563 0A ASL A C564 84 90 STY $90 C566 18 CLC C567 65 90 ADC $90 C569 85 A3 STA $A3 C56B 20 7A C5 JSR $C57A C56E A5 A2 LDA $A2 C570 85 91 STA $91 C572 68 PLA C573 A8 TAY C574 68 PLA C575 AA TAX C576 68 PLA C577 85 90 STA $90 C579 60 RTS ;;============================================================================= ;;============================================================================= ;; ?? ;;----------------------------------------------------------------------------- C57A 85 90 STA $90 C57C A5 A7 LDA $A7 C57E 4A LSR A C57F A5 90 LDA $90 C581 90 02 BCC $C585 C583 69 3F ADC #$3F C585 AA TAX C586 BD F8 C5 LDA $C5F8,X C589 F0 B9 BEQ $C544 C58B 85 90 STA $90 C58D 29 7F AND #$7F C58F 24 90 BIT $90 C591 85 90 STA $90 C593 10 11 BPL $C5A6 C595 A5 A7 LDA $A7 C597 29 02 AND #$02 C599 F0 0B BEQ $C5A6 C59B 20 E3 C5 JSR $C5E3 C59E 38 SEC C59F E9 40 SBC #$40 C5A1 85 90 STA $90 C5A3 4C AD C5 JMP $C5AD ;;============================================================================= ;;============================================================================= ;; ?? ;;----------------------------------------------------------------------------- C5A6 24 A7 BIT $A7 ; Bit 7 of $A7 says to force to uppercase. C5A8 10 03 BPL $C5AD ; If clear, do not force to uppercase. C5AA 20 E3 C5 JSR $C5E3 ; If set, force to uppercase. C5AD 24 A8 BIT $A8 ; \__ If bit 6 of $A8 flags is clear, enqueue C5AF 50 15 BVC $C5C6 ; / the keystroke. C5B1 A6 90 LDX $90 ; C5B3 E0 13 CPX #$13 ; Is it control S? (XOFF) C5B5 D0 05 BNE $C5BC ; C5B7 06 A8 ASL $A8 ; \ C5B9 38 SEC ; |-- Yes: Set "display paused" flag. C5BA B0 07 BCS $C5C3 ; / C5BC E0 11 CPX #$11 ; Is it control Q? (XON) C5BE D0 06 BNE $C5C6 ; \ C5C0 06 A8 ASL $A8 ; |-- Yes: Clear "display paused" flag. C5C2 18 CLC ; / C5C3 66 A8 ROR $A8 ; C5C5 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; Enqueue a keystroke. ;;----------------------------------------------------------------------------- C5C6 20 B1 C6 JSR $C6B1 ; Get address of (?keyboard input) FIFO. C5C9 A5 90 LDA $90 ; C5CB 20 E0 DE JSR $DEE0 ; C5CE C9 0D CMP #$0D ; \ C5D0 D0 35 BNE $C607 ; | C5D2 A9 10 LDA #$10 ; | If it was a carriage return, and C5D4 2C 40 03 BIT $0340 ; | bit 4 in $0340 is set, and we're C5D7 F0 2E BEQ $C607 ; |-- not in an escape sequence (bits 1 C5D9 A9 06 LDA #$06 ; | and 2 in $A8 are clear), enqueue C5DB 24 A8 BIT $A8 ; | a linefeed as well. Otherwise return. C5DD D0 28 BNE $C607 ; | C5DF A9 0A LDA #$0A ; | C5E1 D0 E8 BNE $C5CB ; / (always taken) ;;============================================================================= ;;============================================================================= ;; Uppercase a keystroke. ;;----------------------------------------------------------------------------- C5E3 A5 90 LDA $90 ; \ C5E5 C9 61 CMP #$61 ; | C5E7 30 07 BMI $C5F0 ; | C5E9 C9 7B CMP #$7B ; |-- If it was lowercase, force it to C5EB 10 03 BPL $C5F0 ; | uppercase C5ED 38 SEC ; | C5EE E9 20 SBC #$20 ; / C5F0 85 90 STA $90 ; Remember the character in $90. C5F2 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Read a row of the keyboard matrix. ;; Row # passed in 'A', column data comes back in A. ;;----------------------------------------------------------------------------- C5F3 A0 FC LDY #$FC ; \ C5F5 99 48 3F STA $3F48,Y ; | C5F8 4A LSR A ; |-- Write four LSBs of A to $4044-$4047 C5F9 C8 INY ; | C5FA D0 F9 BNE $C5F5 ; / C5FC AD 60 40 LDA $4060 ; \ C5FF 49 FF EOR #$FF ; | C601 F0 04 BEQ $C607 ; |-- Set $307 to 1 if $4060 reads != $FF. C603 C8 INY ; | ($307 is global "input pending" flag) C604 8C 07 03 STY $0307 ; / C607 60 RTS ;;============================================================================= ; Data from $C608 to $C687 (128 bytes) C608 .byte $00, $2F, $2C, $EE, $F6, $F8, $00, $20, $1D, $2E ; ./,.... .. C612 .byte $ED, $E2, $E3, $FA, $00, $00, $0A, $3B, $EB, $E8 ; .......;.. C61C .byte $E6, $F3, $00, $09, $DD, $F0, $E9, $F9, $F2, $F7 ; .......... C626 .byte $00, $F1, $1C, $2D, $39, $37, $35, $33, $00, $31 ; ...-9753.1 C630 .byte $3D, $30, $38, $36, $34, $32, $00, $DB, $0D, $08 ; =08642.... C63A .byte $EF, $F5, $F4, $E5, $00, $1B, $7F, $27, $EC, $EA ; .......'.. C644 .byte $E7, $E4, $00, $E1, $00, $3F, $2C, $CE, $D6, $D8 ; .....?,... C64E .byte $00, $20, $3E, $2E, $CD, $C2, $C3, $DA, $00, $0C ; . >....... C658 .byte $DC, $3A, $CB, $C8, $C6, $D3, $00, $09, $7D, $D0 ; .:......}. C662 .byte $C9, $D9, $D2, $D7, $00, $D1, $7C, $DF, $28, $26 ; ......|.(& C66C .byte $25, $23, $00, $21, $2B, $29, $2A, $60, $24, $40 ; %#.!+)*`$@ C676 .byte $00, $7B, $0D, $3C, $CF, $D5, $D4, $C5, $00, $1B ; .{.<...... C680 .byte $7F, $22, $CC, $CA, $C7, $C4, $00, $C1 ; ."...... ;;============================================================================= ;; Display string from CP-1600 if bit 7 of $03D9 set. ;;----------------------------------------------------------------------------- C688 0E D9 03 ASL $03D9 C68B 90 20 BCC $C6AD ; Return if MSB of $03D9 was 0. C68D 20 96 C6 JSR $C696 : Display pending string from CP-1600. C690 A9 40 LDA #$40 ; \ C692 8D D9 03 STA $03D9 ; / Set $03D9 to #$40 C695 60 RTS ;;============================================================================= ;;============================================================================= ;; Display pending string from CP-1600 if display not paused ;;----------------------------------------------------------------------------- C696 24 A8 BIT $A8 ; Test flag bits at $A8 C698 30 13 BMI $C6AD ; If display is paused (XOFF), return C69A 20 AE C6 JSR $C6AE ; Get address of CP-1600 message FIFO. C69D 4C A8 C6 JMP $C6A8 ; Get characters from CP-1600-side. ;;============================================================================= ;; Strcpy from CP-1600 loop. ;;----------------------------------------------------------------------------- C6A0 20 CF C6 JSR $C6CF ; Interpret and display character. C6A3 A9 01 LDA #$01 ; \ C6A5 8D 07 03 STA $0307 ; |-- Fetch a decle from CP-1600 side C6A8 20 A1 DE JSR $DEA1 ; / into $90/$91. C6AB 90 F3 BCC $C6A0 ; Loop while data is available. C6AD 60 RTS ;;============================================================================= ;; Get address of CP-1600 to 6502 Message Display FIFO. ;;----------------------------------------------------------------------------- C6AE A2 02 LDX #$02 ; Offset to CP-1600 message FIFO address. ;;============================================================================= ;; C6B1: Get address of keyboard input FIFO?? ;;----------------------------------------------------------------------------- C6B0 2C A2 00 BIT $00A2 ; $C6B1: LDX #$00. Offset to kbd input FIFO C6B3 BD 42 03 LDA $0342,X ; \ C6B6 85 98 STA $98 ; |__ Load CP-1600 FIFO address C6B8 BD 43 03 LDA $0343,X ; | from vector table @ $0342. C6BB 85 99 STA $99 ; / C6BD 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; Process escape sequence and update current row pointer. ;;----------------------------------------------------------------------------- C6BE 20 91 C9 JSR $C991 ; Advance the escape-sequence state machine ;fallthru ;;============================================================================= ;; Set ($B1) to address of current row position. ;;----------------------------------------------------------------------------- C6C1 A5 AE LDA $AE ; Load current row position. C6C3 20 A9 C8 JSR $C8A9 ; Convert to screen address in ($94) C6C6 A5 94 LDA $94 ; \ C6C8 85 B1 STA $B1 ; |__ Copy display address from ($94) C6CA A5 95 LDA $95 ; | to ($B1). C6CC 85 B2 STA $B2 ; / C6CE 60 RTS ;;============================================================================= ;;============================================================================= ;; Interpret and display character ;; $90 Character to display. ;; $91 Escape mode to display character with. ;; $A8 Escape-mode state machine bits. ;;----------------------------------------------------------------------------- C6CF A9 06 LDA #$06 ; \ C6D1 24 A8 BIT $A8 ; |-- Are we in an escape sequence? C6D3 D0 E9 BNE $C6BE ; / Go to $C6BE if we are (bit 1 or 2 set) C6D5 A5 91 LDA $91 ; Get special character shift mode C6D7 D0 31 BNE $C70A ; If != 0, treat this as a special character C6D9 A5 90 LDA $90 ; Get character to display C6DB C9 20 CMP #$20 ; Is it a control character? C6DD 90 39 BCC $C718 ; Yes: Process the control character C6DF C9 7F CMP #$7F ; Is it a delete character? C6E1 F0 35 BEQ $C718 ; Yes: Process the control character C6E3 C9 60 CMP #$60 ; Is it a backtick? C6E5 D0 04 BNE $C6EB ; No: Display it as-is. C6E7 A9 7F LDA #$7F ; \ C6E9 85 90 STA $90 ; / Yes: Remap back-tick to $7F ?? ;;----------------------------------------------------------------------------- C6EB A4 AD LDY $AD ; Get current cursor column C6ED C4 AA CPY $AA ; Compare it to width of the window C6EF 30 0F BMI $C700 ; Is it onscreen? C6F1 88 DEY ; No: It's just to the right, so decrement. C6F2 2C 40 03 BIT $0340 ; Test flag bit 6. C6F5 50 09 BVC $C700 ; If bit 6 was clear, don't wrap--peg at right. C6F7 20 C5 C7 JSR $C7C5 ; Else, do CR+LF to wrap to next line. C6FA 20 C1 C6 JSR $C6C1 ; Re-calc current row address into ($B1) C6FD 4C EB C6 JMP $C6EB ; Repeat until cursor is on screen. ;;----------------------------------------------------------------------------- ; Cursor was onscreen: C700 A5 90 LDA $90 ; Get character from $90 C702 85 B0 STA $B0 ; Save it in $B0 (for ^R) C704 91 B1 STA ($B1),Y ; Store it to the screen. C706 C8 INY ; Increment our cursor position C707 84 AD STY $AD ; Save new cursor position C709 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; Special character handler for shift mode (from location $91) ;;----------------------------------------------------------------------------- C70A A5 90 LDA $90 ; \ C70C 0A ASL A ; | C70D 26 91 ROL $91 ; |-- Shift two MSBs of character into C70F 0A ASL A ; | two LSBs of location $91 C710 26 91 ROL $91 ; / C712 20 A5 C9 JSR $C9A5 ; Do special-character handler C715 4C C1 C6 JMP $C6C1 ; Update current row pointer. ;;============================================================================= ;;============================================================================= ;; Dispatch for control characters ;;----------------------------------------------------------------------------- C718 A5 90 LDA $90 ; Get character number C71A 18 CLC ; C71B 69 01 ADC #$01 ; Map DEL (#$7F) to index 0 C71D 29 7F AND #$7F ; (redundant since "ASL A" eats that bit?) C71F 0A ASL A ; \ C720 AA TAX ; | C721 BD 31 C7 LDA $C731,X ; | C724 85 94 STA $94 ; |-- Put address of handler into ($94) C726 BD 32 C7 LDA $C732,X ; | from the lookup table below. C729 85 95 STA $95 ; | C72B 20 73 DC JSR $DC73 ; / C72E 4C C1 C6 JMP $C6C1 ; Update current row address ptr in ($B1) ;;============================================================================= ; Data from $C731 to $C772 (66 bytes) C731 .byte $1A, $C8 ; C81A: DEL C733 .byte $AF, $C7 ; C7AF: ^@ Do nothing C735 .byte $E0, $C7 ; C7E0: ^A Move down / Scroll text up one row C737 .byte $EF, $C7 ; C7EF: ^B Move up / Scroll text down one row C739 .byte $AF, $C7 ; C7AF: ^C Do nothing C73B .byte $49, $C8 ; C849: ^D Clear to end of line C73D .byte $AF, $C7 ; C7AF: ^E Do nothing C73F .byte $0D, $CC ; CC0D: ^F Move to right of last non-space char C741 .byte $AF, $C7 ; C7AF: ^G Do nothing C743 .byte $94, $C7 ; C794: ^H Backspace C745 .byte $B0, $C7 ; C7B0: ^I TAB C747 .byte $C8, $C7 ; C7C8: ^J Line feed C749 .byte $00, $C8 ; C800: ^K Home cursor C74B .byte $FD, $C7 ; C7FD: ^L Clear display and home cursor C74D .byte $16, $C8 ; C816: ^M Carriage return. C74F .byte $84, $C7 ; C784: ^N Incr and redisp last disp char in-place C751 .byte $7F, $C7 ; C77F: ^O Decr and redisp last disp char in-place C753 .byte $AF, $C7 ; C7AF: ^P Do nothing C755 .byte $AF, $C7 ; C7AF: ^Q Do nothing C757 .byte $89, $C7 ; C789: ^R Repeat last character displayed C759 .byte $AF, $C7 ; C7AF: ^S Do nothing C75B .byte $73, $C7 ; C773: ^T Retype char to left of cursor C75D .byte $24, $C8 ; C824: ^U Delete to start of line, shift text left C75F .byte $85, $CB ; CB85: ^V Insert space, slide text right. C761 .byte $9B, $CB ; CB9B: ^W Insert line-break, shift text down C763 .byte $2D, $CB ; CB2D: ^X Delete char, slide text left. C765 .byte $44, $CB ; CB44: ^Y C767 .byte $93, $C8 ; C893: ^Z Clear window and home cursor C769 .byte $3D, $C4 ; C43D: ESC Set bit 1 of A8 flags C76B .byte $07, $C8 ; C807: ^\ Move cursor up, clamp to top C76D .byte $0F, $C8 ; C80F: ^] Move cursor right, linewrap/clamp to right C76F .byte $90, $C7 ; C790: ^^ Display a backtick. C771 .byte $EE, $CB ; CBEE: ^_ Backtab. ;;============================================================================= ;; CTRL-T: Retype character to left of cursor? ;;----------------------------------------------------------------------------- C773 A4 AD LDY $AD ; Get current cursor column C775 C4 AA CPY $AA ; Is it beyond width of screen? C777 30 01 BMI $C77A ; C779 88 DEY ; Yes: back it up by one. C77A B1 B1 LDA ($B1),Y ; Get character from said position on screen. C77C 4C 8B C7 JMP $C78B ; Display the character w/out interpreting it ;;============================================================================= ;;============================================================================= ;; CTRL-O: Decrement and redisplay last character in place (?) ;;----------------------------------------------------------------------------- C77F C6 B0 DEC $B0 ; Decrement last displayed character C781 4C 86 C7 JMP $C786 ; Backspace and display. ;;============================================================================= ;;============================================================================= ;; CTRL-N: Increment and redisplay last character in place (?) ;;----------------------------------------------------------------------------- C784 E6 B0 INC $B0 ; Increment last displayed character C786 20 94 C7 JSR $C794 ; Backspace ;;============================================================================= ;; CTRL-R: Repeat last character displayed ;;----------------------------------------------------------------------------- C789 A5 B0 LDA $B0 ; Get last displayed character (+/-1) C78B 85 90 STA $90 ; \ C78D 4C EB C6 JMP $C6EB ; / Display char in 'A' w/out interpretation ;;============================================================================= ;;============================================================================= ;; CTRL-^: Display character #$60. ;;----------------------------------------------------------------------------- C790 A9 60 LDA #$60 ; C792 D0 F7 BNE $C78B ; always taken. Store to $90 and display it. ;;============================================================================= ;;============================================================================= ;; CTRL-H: Backspace. ;;----------------------------------------------------------------------------- C794 A6 AD LDX $AD ; Get our current column position. C796 CA DEX ; Decrement it. C797 10 13 BPL $C7AC ; If it is still in same row, store and leave C799 2C 40 03 BIT $0340 ; \ C79C 18 CLC ; |-- Reverse wrap if bit 6 in $340 permits C79D 50 67 BVC $C806 ; / and return. C79F A6 AE LDX $AE ; Get row position. C7A1 CA DEX ; Decrement it. C7A2 30 62 BMI $C806 ; Don't go off top of screen. C7A4 86 AE STX $AE ; Store new row. C7A6 20 C1 C6 JSR $C6C1 ; Update current row address C7A9 A6 AA LDX $AA ; \ C7AB CA DEX ; |-- Put cursor at far right. C7AC 86 AD STX $AD ; / C7AE 38 SEC ; Flag that we did not reverse-wrap. C7AF 60 RTS ; Return ;;============================================================================= ;;============================================================================= ;; CTRL-I: Move to next tabstop ;;----------------------------------------------------------------------------- C7B0 A5 AD LDA $AD ; \ C7B2 18 CLC ; |__ Advance column to next tabstop C7B3 69 04 ADC #$04 ; | (TABs are every 4 spaces!) C7B5 29 FC AND #$FC ; / C7B7 C5 AA CMP $AA ; Is it onscreen? C7B9 90 49 BCC $C804 ; Yes: Store it and return. C7BB 2C 40 03 BIT $0340 ; \__ If we can line wrap, CR+LF to next line C7BE 70 05 BVS $C7C5 ; / C7C0 A6 AA LDX $AA ; Else, set cursor immediately right of window C7C2 86 AD STX $AD ; C7C4 60 RTS ;;============================================================================= ;;============================================================================= ;; Execute CR + LF. Scroll display if necessary. ;;----------------------------------------------------------------------------- C7C5 20 16 C8 JSR $C816 ; Carriage return. ;fallthru ;;============================================================================= ;; CTRL-J: Linefeed. Scroll display if necessary. ;;----------------------------------------------------------------------------- C7C8 A6 AE LDX $AE ; Get current row C7CA E8 INX ; Increment. C7CB E4 AC CPX $AC ; Is it past end of display? C7CD 30 3D BMI $C80C ; No: Store and leave. C7CF A9 00 LDA #$00 ; Yes: Set us to top of screen ? C7D1 85 AE STA $AE C7D3 A9 20 LDA #$20 ; \ C7D5 2C 40 03 BIT $0340 ; |-- If scrolling is ok, scroll the screen. C7D8 F0 01 BEQ $C7DB ; / C7DA 60 RTS ;;============================================================================= ;;============================================================================= ;; Clamp cursor to bottom, Move down / Scroll text up one row. ;;----------------------------------------------------------------------------- C7DB A6 AC LDX $AC ; Load screen height. C7DD CA DEX ; Subtract one. C7DE 86 AE STX $AE ; Make it the new row position. ;fall thru ;;============================================================================= ;; CTRL-A: Move down / Scroll text up one row. ;;----------------------------------------------------------------------------- C7E0 20 F8 C7 JSR $C7F8 ; Clear newly exposed line on the display. C7E3 A6 AF LDX $AF ; Load current hardware scroll factor.' C7E5 E8 INX ; \ C7E6 E0 18 CPX #$18 ; |__ Increment it modulo 24 for 9927's C7E8 30 02 BMI $C7EC ; | hardware scroll feature. C7EA A2 00 LDX #$00 ; / C7EC 86 AF STX $AF ; Store updated scroll factor. C7EE 60 RTS ;;============================================================================= ;; CTRL-B: Move up / Scroll text down one row. ;;----------------------------------------------------------------------------- C7EF A6 AF LDX $AF ; Get current scroll factor. C7F1 CA DEX ; \ C7F2 10 02 BPL $C7F6 ; |-- Decrement it modulo 24 for hdwr scroll C7F4 A2 17 LDX #$17 ; / C7F6 86 AF STX $AF ; Store updated scroll factor. C7F8 A9 00 LDA #$00 ; Calculate address for top row of screen. C7FA 4C 83 C8 JMP $C883 ; Clear newly exposed line. ;;============================================================================= ;;============================================================================= ;; CTRL-L: Clear display and home cursor ;;----------------------------------------------------------------------------- C7FD 20 56 C8 JSR $C856 ; Clear the display ;fallthru ;;============================================================================= ;; CTRL-K: Home cursor ;;----------------------------------------------------------------------------- C800 A9 00 LDA #$00 ; \ C802 85 AE STA $AE ; |-- Set current row, column to 0. C804 85 AD STA $AD ; / C806 60 RTS ;;============================================================================= ;;============================================================================= ;; CTRL-\: Move up a row, but do not move off top of screen. ;;----------------------------------------------------------------------------- C807 A6 AE LDX $AE ; Get current row C809 CA DEX ; Decrement it. C80A 30 FA BMI $C806 ; Did it go negative? Don't store it. C80C 86 AE STX $AE ; Store new row C80E 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; CTRL-]: Move cursor right, and linewrap if permitted. ;;----------------------------------------------------------------------------- C80F A5 AD LDA $AD ; Get current column position C811 18 CLC ; C812 69 01 ADC #$01 ; Add 1. C814 D0 A1 BNE $C7B7 ; Clamp to right / linewrap as needed. ;;============================================================================= ;;============================================================================= ;; CTRL-M: Carriage Return (Set cursor column # to zero and return.) ;;----------------------------------------------------------------------------- C816 A2 00 LDX #$00 ; C818 F0 92 BEQ $C7AC ; Always taken. Set column to ZERO & return. ;;============================================================================= ;;============================================================================= ;; DEL: Backspace and erase previous char w/ space ;;----------------------------------------------------------------------------- C81A 20 94 C7 JSR $C794 ; Backspace. C81D 90 E7 BCC $C806 ; If we reverse-wrapped, return. C81F A4 AD LDY $AD ; C821 4C 96 CB JMP $CB96 ; Put a space char if we stayed on same line. ;;============================================================================= ;;============================================================================= ;; CTRL-U: Delete to start of line, shifting text left. ;;----------------------------------------------------------------------------- C824 A5 B2 LDA $B2 ; \ C826 85 95 STA $95 ; | C828 85 97 STA $97 ; | Copy current row address into $96 and C82A A5 B1 LDA $B1 ; |__ $94. Add our current column address C82C 85 96 STA $96 ; | to $94. C82E 18 CLC ; | C82F 65 AD ADC $AD ; | C831 85 94 STA $94 ; / C833 A5 AA LDA $AA ; \ C835 38 SEC ; |-- Subtract current column from window C836 E5 AD SBC $AD ; / width. C838 A8 TAY ; C839 F0 03 BEQ $C83E ; If result's zero, skip block move. C83B 20 E0 DF JSR $DFE0 ; Move the text over with block move. C83E A9 80 LDA #$80 ; Prepare to fill exposed area w/ spaces. C840 C4 AA CPY $AA ; \ C842 10 D2 BPL $C816 ; | C844 91 96 STA ($96),Y ; |-- Fill out width with spaces. C846 C8 INY ; | C847 D0 F7 BNE $C840 ; / (always taken?) ;;============================================================================= ;;============================================================================= ;; CTRL-D: Clear to end-of-line. ;;----------------------------------------------------------------------------- C849 A4 AD LDY $AD ; Get current cursor column as starting pt. C84B A5 AA LDA $AA ; \ C84D 38 SEC ; |__ If in rightmost column, return. C84E E5 AD SBC $AD ; | C850 F0 25 BEQ $C877 ; / C852 AA TAX ; \___ Clear to end-of-line C853 4C 78 C8 JMP $C878 ; / ;;============================================================================= ;;============================================================================= ;; Clear the whole display ;;----------------------------------------------------------------------------- C856 A9 00 LDA #$00 ; \ C858 85 94 STA $94 ; |__ Point to display buffer at C85A A9 B8 LDA #$B8 ; | $B800 .. $BFFF C85C 85 95 STA $95 ; / C85E A2 18 LDX #$18 ; X == $18 rows (24 rows) C860 A9 80 LDA #$80 ; Fill with $80 C862 A0 27 LDY #$27 ; Y == $28 columns (40 columns), $00..$27 C864 91 94 STA ($94),Y ; \ C866 88 DEY ; |-- Fill from ($94)+$27 down thru ($94)+$00 C867 10 FB BPL $C864 ; / C869 18 CLC C86A A9 40 LDA #$40 ; \ C86C 65 94 ADC $94 ; | C86E 85 94 STA $94 ; |-- Add $40 (64) to our 16-bit address. C870 90 02 BCC $C874 ; | C872 E6 95 INC $95 ; / C874 CA DEX ; Decrement our row count C875 D0 E9 BNE $C860 ; Fill all the rows. C877 60 RTS ;;============================================================================= ;;============================================================================= ;; Clear within row at address specified by ($B1), starting at 'Y' ;;----------------------------------------------------------------------------- C878 A5 B1 LDA $B1 C87A 85 94 STA $94 C87C A5 B2 LDA $B2 C87E 85 95 STA $95 C880 4C 8A C8 JMP $C88A ;;============================================================================= ;;============================================================================= ;; Clear row specified in 'A' ;;----------------------------------------------------------------------------- C883 A0 00 LDY #$00 ; Clear 'Y' C885 A6 AA LDX $AA ; Get screen width C887 20 A9 C8 JSR $C8A9 ; Get address of row C88A A9 80 LDA #$80 ; Space character. C88C 91 94 STA ($94),Y ; Write the space character to the display. C88E C8 INY ; Move to next column C88F CA DEX ; \__ Loop until we've cleared the entire C890 D0 FA BNE $C88C ; / newly-exposed row of the display. C892 60 RTS ;;============================================================================= ;;============================================================================= ;; CTRL-Z: Clear current window and home cursor ;;----------------------------------------------------------------------------- C893 A9 00 LDA #$00 ; Start at top row. C895 85 90 STA $90 ; C897 A5 AC LDA $AC ; Get display height. C899 85 91 STA $91 ; C89B A5 90 LDA $90 ; Get current row C89D 20 83 C8 JSR $C883 ; Clear current row C8A0 E6 90 INC $90 ; Incr. current row C8A2 C6 91 DEC $91 ; Decr. loop count C8A4 D0 F5 BNE $C89B ; Zero? No: Do next row. C8A6 4C 00 C8 JMP $C800 ; Home the cursor ;;============================================================================= ;;============================================================================= ;; Calculate screen address for row number given in 'A'. ;;----------------------------------------------------------------------------- C8A9 38 SEC C8AA 65 AB ADC $AB ; Add top-of-window and 1 to current row posn C8AC 65 AF ADC $AF ; Add current scroll factor to row C8AE C9 18 CMP #$18 C8B0 30 03 BMI $C8B5 ; Is it bigger than $18? C8B2 38 SEC C8B3 E9 18 SBC #$18 ; Wrap modulo 24, since screen memory wraps. ;------------- Convert row number in 'A' and column number in $A9 ;------------- to character address on the display. This is the address ;------------- of the upper left corner of the logical display. ;------------- The row number in 'A' has been adjusted for the current 9927 ;------------- scroll setting. C8B5 48 PHA ; Save 'A' C8B6 A9 00 LDA #$00 ; C8B8 85 95 STA $95 ; Clear upper byte of address C8BA 68 PLA ; Restore 'A' C8BB 0A ASL A ; \ C8BC 0A ASL A ; | C8BD 0A ASL A ; | C8BE 0A ASL A ; | C8BF 26 95 ROL $95 ; |-- Multiply A by 64 into loc $94/$95 C8C1 0A ASL A ; | C8C2 26 95 ROL $95 ; | C8C4 0A ASL A ; | C8C5 26 95 ROL $95 ; / C8C7 65 A9 ADC $A9 ; Add in column address C8C9 85 94 STA $94 ; Store low byte of final address to $94 C8CB A9 B8 LDA #$B8 ; C8CD 65 95 ADC $95 ; Add $B8 to row address C8CF 85 95 STA $95 ; Store high byte of final address to $95 C8D1 60 RTS ;;============================================================================= ;;============================================================================= ;; Update cursor on the screen as well as strange stuff with $4043. ;;----------------------------------------------------------------------------- C8D2 A2 00 LDX #$00 ; \ C8D4 24 9E BIT $9E ; | C8D6 10 0B BPL $C8E3 ; | C8D8 AD 27 BE LDA $BE27 ; |__ Toggle bit 0 of $A8 if $9E tells us C8DB 85 9E STA $9E ; | to. C8DD A9 01 LDA #$01 ; | C8DF 45 A8 EOR $A8 ; | C8E1 85 A8 STA $A8 ; / C8E3 A5 AF LDA $AF ; \___ Set hardware scroll C8E5 8D C6 40 STA $40C6 ; / C8E8 38 SEC ; \ C8E9 65 AB ADC $AB ; | Calculate hardware cursor row value C8EB 65 AE ADC $AE ; |__ based on hardware scroll and top-of C8ED C9 18 CMP #$18 ; | window values. C8EF 90 02 BCC $C8F3 ; | C8F1 E9 18 SBC #$18 ; / C8F3 8D CD 40 STA $40CD ; Set cursor row register. C8F6 2C 40 03 BIT $0340 ; \ C8F9 30 1C BMI $C917 ; |__ If bit 7 of $340 set or $0307 is zero C8FB AD 07 03 LDA $0307 ; | set cursor column & $4043, and leave. C8FE F0 17 BEQ $C917 ; / C900 A9 01 LDA #$01 ; \__ C902 8D 43 40 STA $4043 ; / C905 24 A8 BIT $A8 ; \__ If bit 0 of $A8 clear, just set cursor C907 F0 11 BEQ $C91A ; / column and leave. C909 A5 AD LDA $AD ; Get current cursor column C90B C5 AA CMP $AA ; Compare to screen width. C90D 18 CLC ; C90E F0 01 BEQ $C911 ; If at right edge of screen, stay there .. C910 38 SEC ; .. else put cursor just to the right. C911 65 A9 ADC $A9 ; Add left edge of screen C913 8D CC 40 STA $40CC ; Store to cursor column register. C916 60 RTS ; Return. ;;============================================================================= ;; Store X to column position register on 9927 and loc $4043 ;;----------------------------------------------------------------------------- C917 8E 43 40 STX $4043 ; Store X to ?? C91A 8E CC 40 STX $40CC ; Store X to column position register on 9927 C91D 60 RTS ; Return. ;;============================================================================= ; Data from $C91E to $C925 (7 bytes) C91E .byte $5F ; $5F: Initial display mode flags ? C91F .byte $07 ; $07: C920 .byte $08, $03 ; $0308: Addr: 6502->CP1600 kbd input FIFO C922 .byte $15, $03 ; $0315: Addr: CP1600->6502 message disp FIFO C924 .byte $A8, $00 ; $00A8: Flags register pointer? ;;============================================================================= ;; Set up default communication channels (FIFOs, display window, 9927 regs) ;;----------------------------------------------------------------------------- C926 A9 1E LDA #$1E ; \ C928 85 94 STA $94 ; | C92A A9 C9 LDA #$C9 ; | C92C 85 95 STA $95 ; |-- Block copy 12 bytes @ $C91E to $340 C92E A9 00 LDA #$00 ; | C930 85 90 STA $90 ; | C932 20 63 C3 JSR $C363 ; / C935 A2 0D LDX #$0D ; \ C937 8E 0A 03 STX $030A ; | C93A CA DEX ; |-- Set up 12 byte FIFO at $308. C93B 8E 08 03 STX $0308 ; | (Purpose of FIFO??) C93E 8E 09 03 STX $0309 ; / C941 A2 2B LDX #$2B ; \ C943 8E 17 03 STX $0317 ; | Set up 42 byte FIFO at $315. C946 CA DEX ; |-- This FIFO is used when displaying C947 8E 15 03 STX $0315 ; | messages from the CP-1600 to 6502. C94A 8E 16 03 STX $0316 ; / C94D 20 F3 CA JSR $CAF3 ; Set display parameter variables C950 20 C1 C6 JSR $C6C1 ; Set saved top-of-window address. C953 20 56 C8 JSR $C856 ; Clear the display C956 AD CA 40 LDA $40CA ; Strobe screen scan location reset C959 A2 07 LDX #$07 C95B BD 6A C9 LDA $C96A,X ; \ C95E 9D BF 40 STA $40BF,X ; |__ Copy video parameters to display from C961 CA DEX ; | table below. 9927 is at $40C0..$40CF C962 D0 F7 BNE $C95B ; / C964 20 17 C9 JSR $C917 ; Clear column position. C967 AD CE 40 LDA $40CE ; Strobe 9927 timing chain start C96A 60 RTS ; Done! ;;============================================================================= ; Data from $C96B to $C989 (31 bytes) C96B .byte $38 ; Horiz character count = 56?? .byte $25 ; HSync Width = 4, HSync Delay = 5 .byte $3A ; Scans/Data Row = 7, Chars/Data Row = 4 .byte $97 ; Skew = 2, Data Rows/Frame = 23 .byte $03 ; Scan lines/Frame = 3 ? .byte $44 ; Vertical Data Start = 70 .byte $17 ; Last displayed data row = 23 ; Jump table / array of pointers. Indexed off of 3 MSBs of ; character when special character handler in place. C972 .byte $01, $CA ; CA01 Set column position C974 .byte $3E, $CA ; CA3E Set row position C976 .byte $D2, $C9 ; C9D2 Set left edge of display C978 .byte $EB, $C9 ; C9EB Set right edge of display C97A .byte $0C, $CA ; CA0C Set top edge of display C97C .byte $25, $CA ; CA25 Set bottom edge of display C97E .byte $54, $CA ; CA54 Control mode flags in $A8, $9E, $BE27 C980 .byte $50, $CA ; CA50 Store argument to $BE26 (keyboard scan mode?) C982 .byte $78, $CA ; CA78 \ / default case C984 .byte $6E, $CA ; CA6E |- Print string from tbl -| 1st letter Caps C986 .byte $72, $CA ; CA72 / \ in all CAPS C988 .byte $0F, $CB ; CB0F Manipulate mask at $340 w/ char LSBs. ;;============================================================================= ;; Clear display mode bits 1 and 2. (Reset escape sequence state machine) ;;----------------------------------------------------------------------------- C98A A9 F9 LDA #$F9 ; Load mask ;fallthru ;;============================================================================= ;; Clear display mode bits based on mask in 'A' ;;----------------------------------------------------------------------------- C98C 25 A8 AND $A8 ; Clear bits 1 and 2 from display mode C98E 85 A8 STA $A8 ; Save updated mode C990 60 RTS ; Return ;;============================================================================= ;;============================================================================= ;; Escape sequence state machine.: ;; If flag bit 2 is clear, set flag and save character for next. ;; If flag bit 2 is set, process escape sequence using saved character. ;;----------------------------------------------------------------------------- C991 A9 04 LDA #$04 ; \ C993 24 A8 BIT $A8 ; |-- Test some display-mode flags. C995 D0 09 BNE $C9A0 ; / Go to $C9A0 if bit 2 already set. C997 A6 90 LDX $90 ; \ C999 8E C9 03 STX $03C9 ; / Copy character to $3C9 (save it as an arg) C99C 05 A8 ORA $A8 ; Set bit 2 in existing flags. C99E D0 EE BNE $C98E ; Always taken. Store new flag and exit. C9A0 AD C9 03 LDA $03C9 ; Get saved character from $3C9 C9A3 85 91 STA $91 ; Use character as escape-mode. ;fallthru ;;============================================================================= ;; Interpret special characters / Escape sequences ;;----------------------------------------------------------------------------- C9A5 20 8A C9 JSR $C98A ; Force bits 1 and 2 of display mode clear. C9A8 A5 91 LDA $91 ; Get Escape Command character C9AA 29 0F AND #$0F ; Keep lower nibble -- rest are insignificant. C9AC C9 04 CMP #$04 ; Is it < 4? C9AE 30 15 BMI $C9C5 ; Yes: Display character from merged cmd&arg C9B0 0A ASL A ; No: C9B1 AA TAX ; \ C9B2 BD 6A C9 LDA $C96A,X ; | C9B5 85 94 STA $94 ; |-- Use the command char as a lookup into C9B7 BD 6B C9 LDA $C96B,X ; | a jump-table. C9BA 85 95 STA $95 ; / C9BC A5 90 LDA $90 ; \ C9BE 29 3F AND #$3F ; |-- Get lower 6 bits of argument char as C9C0 85 90 STA $90 ; / argument for escape sequence. C9C2 6C 94 00 JMP ($0094) ; Jump to the special handler. C9C5 06 90 ASL $90 ; \ C9C7 06 90 ASL $90 ; | C9C9 6A ROR A ; |__ Set the 2 MSBs of the character in $90 C9CA 66 90 ROR $90 ; | from the 2 LSBs of $91 (already in 'A') C9CC 6A ROR A ; | C9CD 66 90 ROR $90 ; / C9CF 4C EB C6 JMP $C6EB ; Display the merged character as-is. ;;============================================================================= ;;============================================================================= ;; Set left edge of display to 'A' ;;----------------------------------------------------------------------------- C9D2 C9 28 CMP #$28 ; is it wider than physical screen? C9D4 90 02 BCC $C9D8 ; \ C9D6 A9 27 LDA #$27 ; / Yes: clamp to screen. C9D8 A6 A9 LDX $A9 ; Get old left edge C9DA 85 A9 STA $A9 ; Store new left edge C9DC 8A TXA ; C9DD 38 SEC ; C9DE E5 A9 SBC $A9 ; Get diff between old and new left-edges C9E0 18 CLC C9E1 65 AD ADC $AD ; Add to cursor position C9E3 10 02 BPL $C9E7 ; Is it still in row? C9E5 A9 00 LDA #$00 ; No: Clamp to left C9E7 85 AD STA $AD ; Store as updated cursor position C9E9 A5 B3 LDA $B3 ; Get right column number ;fallthru ;;============================================================================= ;; Set right edge of display to 'A' ;;----------------------------------------------------------------------------- C9EB 85 B3 STA $B3 ; Set new right column C9ED 38 SEC C9EE E5 A9 SBC $A9 ; Calculate width of screen. C9F0 10 02 BPL $C9F4 ; Did it go negative? C9F2 A9 00 LDA #$00 ; Yes: clamp to 0 C9F4 C9 28 CMP #$28 ; Compare against actual display width C9F6 90 02 BCC $C9FA ; Is it wider than the display? C9F8 A9 27 LDA #$27 ; Yes: clamp to actual display width C9FA 18 CLC C9FB 69 01 ADC #$01 ; Add 1 C9FD 85 AA STA $AA ; Store as new display width. C9FF A5 AD LDA $AD ; Get current cursor column ;fallthru ;;============================================================================= ;; Set column position to value in 'A' ;;----------------------------------------------------------------------------- CA01 C5 AA CMP $AA ; Is it beyond right side of screen? CA03 90 04 BCC $CA09 ; \ CA05 A5 AA LDA $AA ; |-- Yes: Clamp to right side. CA07 E9 01 SBC #$01 ; / CA09 85 AD STA $AD ; Save new column position. CA0B 60 RTS ;;============================================================================= ;;============================================================================= ;; Set top edge of display to 'A' ;;----------------------------------------------------------------------------- CA0C C9 18 CMP #$18 ; Is row position in A >= 24? CA0E 30 02 BMI $CA12 CA10 A9 17 LDA #$17 ; Yes, clamp to 23. CA12 A6 AB LDX $AB ; Save current top-edge-of-window CA14 85 AB STA $AB ; Store new top-edge-of-window CA16 8A TXA ; CA17 38 SEC ; CA18 E5 AB SBC $AB ; Subtract old top-edge from new. CA1A 18 CLC CA1B 65 AE ADC $AE ; Add current cursor row CA1D 10 02 BPL $CA21 ; Is it on-screen? CA1F A9 00 LDA #$00 ; No -- clamp it to top of screen. CA21 85 AE STA $AE ; Store new cursor row CA23 A5 B4 LDA $B4 ; Load bottom edge of display CA25 C9 20 CMP #$20 ; ??? Magic "taller-than-screen" value? CA27 B0 20 BCS $CA49 ; Is it >= $20? ;fallthru ;;============================================================================= ;; Set bottom edge of display to 'A' ;;----------------------------------------------------------------------------- CA29 85 B4 STA $B4 ; No: Store bottom edge of disp. CA2B E5 AB SBC $AB ; Subtract new top-edge from it. CA2D 10 02 BPL $CA31 ; Is it off top of screen? CA2F A9 00 LDA #$00 ; Yes: Clamp to top-of-screen CA31 C9 17 CMP #$17 ; Is it off bottom of screen? CA33 90 02 BCC $CA37 ; \ CA35 A9 17 LDA #$17 ; / Yes: Clamp to bottom of screen?? CA37 18 CLC ; CA38 69 01 ADC #$01 ; Add 1... CA3A 85 AC STA $AC ; Make this the new window height. CA3C A5 AE LDA $AE ; Get current cursor row ;fallthru ;;============================================================================= ;; Set current row position to 'A' ;;----------------------------------------------------------------------------- CA3E C5 AC CMP $AC ; Is it past the bottom of the display window? CA40 90 04 BCC $CA46 ; \ CA42 A5 AC LDA $AC ; |- Yes: Clamp to bottom of the display. CA44 E9 01 SBC #$01 ; / CA46 85 AE STA $AE ; Store updated cursor row. CA48 60 RTS ;;----------------------------------------------------------------------------- CA49 E9 20 SBC #$20 ; ??? CA4B 85 90 STA $90 ; ??? CA4D 4C EB C6 JMP $C6EB ; ??? ;;============================================================================= ;;============================================================================= ;; Store 'A' to $BE26 ;;----------------------------------------------------------------------------- CA50 8D 26 BE STA $BE26 ; CA53 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Manipulate $A8 flag bit 0 based on 'A', and flags @ $BE27, $9E ;;----------------------------------------------------------------------------- CA54 F0 0A BEQ $CA60 ; Is 'A' zero? Clear bit 0 of flags in $A8 CA56 C9 3F CMP #$3F ; Is 'A' $3F? Yes: Set bit 0 of flags in $A8 CA58 D0 0E BNE $CA68 ; No: Don't change flags in $A8. ;;----------------------------------------------------------------------------- CA5A A5 A8 LDA $A8 ; Set bit 0 of mode flag CA5C 09 01 ORA #$01 ; CA5E D0 04 BNE $CA64 ; Always taken. ORA w/ 1 should never set Z. CA60 A5 A8 LDA $A8 ; Get mode flags CA62 29 FE AND #$FE ; Clear bit 0 CA64 85 A8 STA $A8 ; Store updated mode flags CA66 A9 7F LDA #$7F ; CA68 8D 27 BE STA $BE27 ; ? CA6B 85 9E STA $9E ; ? CA6D 60 RTS ;;============================================================================= ;;============================================================================= ;; Display string from string table, with first letter caps, subsequent ;; letters in lower-case. ;;----------------------------------------------------------------------------- CA6E A2 00 LDX #$00 CA70 F0 02 BEQ $CA74 ; always taken ;;============================================================================= ;; Display string from string table in all-caps ;;----------------------------------------------------------------------------- CA72 A2 20 LDX #$20 CA74 A9 20 LDA #$20 CA76 D0 03 BNE $CA7B ; always taken. ;;============================================================================= ;; Display a string from a string message buffer in default case. ;;----------------------------------------------------------------------------- CA78 A9 00 LDA #$00 ; CA7A AA TAX ; CA7B 85 92 STA $92 ; \__ Store initial and subsequent letter CA7D 86 91 STX $91 ; / capitalization modes. CA7F AD 6C 04 LDA $046C ; \ CA82 85 94 STA $94 ; | Copy string table base address to CA84 85 96 STA $96 ; |__ both ($94) and ($96). We use ($96) CA86 AD 6D 04 LDA $046D ; | when stepping through the TOC, and CA89 85 95 STA $95 ; | ($94) to actually read the string. CA8B 85 97 STA $97 ; / CA8D A0 00 LDY #$00 ; CA8F A5 90 LDA $90 ; CA91 F0 60 BEQ $CAF3 ; String #$00 just resets the display. CA93 D1 96 CMP ($96),Y ; \___ If past end of string length table, CA95 B0 5B BCS $CAF2 ; / just return. CA97 A8 TAY ; \ CA98 B1 96 LDA ($96),Y ; |-- Use arg as index into string length CA9A 85 90 STA $90 ; / table. CA9C 88 DEY ; \ CA9D 18 CLC ; | CA9E B1 96 LDA ($96),Y ; | Advance our string pointer by the CAA0 65 94 ADC $94 ; |-- lengths of the string prior to the CAA2 85 94 STA $94 ; | one we're interested in. CAA4 90 02 BCC $CAA8 ; | CAA6 E6 95 INC $95 ; / CAA8 88 DEY ; \___ Add up all the string lengths for CAA9 10 F2 BPL $CA9D ; / the string before this one. CAAB A4 90 LDY $90 ; Restore the len of the string we're showing CAAD A5 91 LDA $91 ; Get our initial letter capitalization mode. CAAF 48 PHA ; Remember caps mode on the stack CAB0 A2 00 LDX #$00 ; CAB2 86 91 STX $91 ; CAB4 A1 94 LDA ($94,X) ; Get value from ($94) CAB6 E6 94 INC $94 ; \ CAB8 D0 02 BNE $CABC ; |-- Move ($94) along by one byte CABA E6 95 INC $95 ; / CABC A6 91 LDX $91 ; \___ If escape-mode flag set, display as-is. CABE D0 17 BNE $CAD7 ; / CAC0 C9 03 CMP #$03 ; \___ Was it bigger than 3? CAC2 B0 08 BCS $CACC ; / Yes: Display it adjusting case as needed CAC4 69 01 ADC #$01 ; \___ No: Add 1 and store to "escape mode" CAC6 85 91 STA $91 ; / field. CAC8 88 DEY ; Always an extra character after escape. CAC9 D0 E9 BNE $CAB4 ; Always taken. CACB 60 RTS ; (Should never be reached, else will crash) CACC C9 61 CMP #$61 ; \ CACE 90 07 BCC $CAD7 ; |__ Was it lowercase? CAD0 C9 7B CMP #$7B ; | CAD2 B0 03 BCS $CAD7 ; / CAD4 38 SEC ; \___ Make it uppercase if subsequent-letter CAD5 E5 92 SBC $92 ; / caps mode was #$20. CAD7 85 90 STA $90 ; Store modified character to $90 CAD9 98 TYA ; \ CADA 48 PHA ; | CADB A5 94 LDA $94 ; |__ Save our temp variables on the stack CADD 48 PHA ; | since strings may expand recursively. CADE A5 95 LDA $95 ; | CAE0 48 PHA ; / CAE1 20 CF C6 JSR $C6CF ; Interpret / display character CAE4 68 PLA ; \ CAE5 85 95 STA $95 ; | CAE7 68 PLA ; |__ Restore our temp variables CAE8 85 94 STA $94 ; | CAEA 68 PLA ; | CAEB A8 TAY ; / CAEC 68 PLA ; \___ Remember Arg #2, save in arg #3 CAED 85 92 STA $92 ; / CAEF 88 DEY ; Decrement our string count. CAF0 D0 BD BNE $CAAF ; Loop until string length goes to zero. CAF2 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Set up default display parameters ;;----------------------------------------------------------------------------- CAF3 A9 00 LDA #$00 ; CAF5 85 A9 STA $A9 ; Left edge = 0 CAF7 85 AB STA $AB ; Top edge = 0 CAF9 A0 28 LDY #$28 ; CAFB 84 AA STY $AA ; Width = 40 CAFD 88 DEY ; CAFE 84 B3 STY $B3 ; Right edge = 39 CB00 A0 18 LDY #$18 ; CB02 84 AC STY $AC ; Height = 24 CB04 88 DEY ; CB05 84 B4 STY $B4 ; Bottom edge = 23 CB07 A9 02 LDA #$02 ; CB09 8D 26 BE STA $BE26 ; Flag @ $BE26 == 2 ??? CB0C 4C 5A CA JMP $CA5A ; Set bit 0 of $A8, set $BE27 and $9E to #$7F. ;;============================================================================= ;;============================================================================= ;; Manipulate display mode flags in $340 based on argument in 'A'. ;; If bit 4 is clear, set bits in $340 from 4 LSBs of A. ;; If bit 4 is set, clear bits in $340 from 4 LSBs of A. ;; If bit 5 is clear, manipulate lower 4 bits of $340 from A. ;; If bit 5 is set, manipulate upper 4 bits of $340 from A. ;;----------------------------------------------------------------------------- CB0F 0A ASL A ; Move A left by to so bits 5, 4 are in 6, 7 CB10 0A ASL A ; CB11 85 91 STA $91 ; Save this for the BIT instruction below CB13 0A ASL A ; CB14 0A ASL A ; CB15 24 91 BIT $91 ; CB17 30 04 BMI $CB1D ; Bit 5 of arg set: modify upper half of $340 CB19 A5 90 LDA $90 ; Bit 5 of arg clr: modify lower half of $340 CB1B 29 0F AND #$0F ; CB1D 50 05 BVC $CB24 ; Bit 4 of arg clr: Clear bits in $340 CB1F 0D 40 03 ORA $0340 ; Bit 4 of arg set: Set bits in $340 CB22 70 05 BVS $CB29 ; CB24 49 FF EOR #$FF ; \__ Bit 4 of arg clr: Clear bits in $340 CB26 2D 40 03 AND $0340 ; / CB29 8D 40 03 STA $0340 ; Store updated flag bits back to $340. CB2C 60 RTS ;;============================================================================= ;;============================================================================= ;; CTRL-X: Delete char at cursor, slide text left. ;;----------------------------------------------------------------------------- CB2D A4 AD LDY $AD ; Start at current cursor position CB2F C8 INY ; \ CB30 C4 AA CPY $AA ; | CB32 F0 0A BEQ $CB3E ; | CB34 10 0D BPL $CB43 ; | Slide text to the left until we hit CB36 B1 B1 LDA ($B1),Y ; |-- the right edge of the window. Exit CB38 88 DEY ; | immediately if the cursor is just CB39 91 B1 STA ($B1),Y ; | to the right of the window. CB3B C8 INY ; | CB3C 10 F1 BPL $CB2F ; / CB3E 88 DEY ; \ CB3F A9 80 LDA #$80 ; |-- Put a space character at right edge CB41 91 B1 STA ($B1),Y ; / CB43 60 RTS ; Leave. ;;============================================================================= ;;============================================================================= ;; CTRL-Y: Join next line at cursor, pull display up. ;;----------------------------------------------------------------------------- CB44 A5 B1 LDA $B1 ; \ CB46 18 CLC ; | CB47 65 AD ADC $AD ; |__ Point ($96) at current cursor posn. CB49 85 96 STA $96 ; | CB4B A5 B2 LDA $B2 ; | CB4D 85 97 STA $97 ; / CB4F A5 AE LDA $AE ; \___ Set $90 to current cursor row. CB51 85 90 STA $90 ; / CB53 A5 AA LDA $AA ; \ CB55 38 SEC ; |__ Set Y to number of characters between CB56 E5 AD SBC $AD ; | current position and right edge. CB58 A8 TAY ; / CB59 A6 90 LDX $90 ; \ CB5B E8 INX ; |-- Move down a row CB5C 86 90 STX $90 ; / CB5E E4 AC CPX $AC ; \___ If we're past the bottom skip to CB60 10 1A BPL $CB7C ; / space-filler at end. CB62 8A TXA ; \___ Get address for current screen row CB63 20 A9 C8 JSR $C8A9 ; / CB66 88 DEY ; \ CB67 30 07 BMI $CB70 ; | CB69 B1 94 LDA ($94),Y ; |-- Copy text from current row to previous CB6B 91 96 STA ($96),Y ; | CB6D 4C 66 CB JMP $CB66 ; / CB70 A5 94 LDA $94 ; \ CB72 85 96 STA $96 ; |__ Make current row previous CB74 A5 95 LDA $95 ; | CB76 85 97 STA $97 ; / CB78 A4 AA LDY $AA ; On next iter, iterate for whole scrn width CB7A 10 DD BPL $CB59 ; Do next row. CB7C A9 80 LDA #$80 ; \ CB7E 88 DEY ; | CB7F 30 C2 BMI $CB43 ; |-- Fill empty row at end w/ spaces and CB81 91 96 STA ($96),Y ; | then return. CB83 10 F9 BPL $CB7E ; / ;;============================================================================= ;;============================================================================= ;; CTRL-V: Insert a space character, slide text right. ;;----------------------------------------------------------------------------- CB85 A4 AA LDY $AA ; \ CB87 88 DEY ; | CB88 C4 AD CPY $AD ; | CB8A F0 0A BEQ $CB96 ; | Slide text to the right of the cursor CB8C 30 0C BMI $CB9A ; |__ right by exactly one column. If the CB8E 88 DEY ; | cursor is off the right edge, do CB8F B1 B1 LDA ($B1),Y ; | nothing and exit. CB91 C8 INY ; | CB92 91 B1 STA ($B1),Y ; | CB94 10 F1 BPL $CB87 ; / CB96 A9 80 LDA #$80 ; \__ Put a single space character in the CB98 91 B1 STA ($B1),Y ; / space we just made available. CB9A 60 RTS ; ;;============================================================================= ;;============================================================================= ;; CTRL-W: Insert line-break at cursor, move text down. ;;----------------------------------------------------------------------------- CB9B A6 AC LDX $AC ; \ CB9D CA DEX ; |__ Store display height - 1 to $91 CB9E 86 91 STX $91 ; | CBA0 8A TXA ; / CBA1 20 A9 C8 JSR $C8A9 ; Get row address for bottom row CBA4 A5 94 LDA $94 ; \ CBA6 85 96 STA $96 ; |__ Put bottom-row address in ($96) CBA8 A5 95 LDA $95 ; | CBAA 85 97 STA $97 ; / CBAC A4 AA LDY $AA ; Get width of active window in Y CBAE A6 91 LDX $91 ; \ CBB0 CA DEX ; | CBB1 86 91 STX $91 ; |-- Move up a row, put pointer in ($94) CBB3 8A TXA ; | CBB4 20 A9 C8 JSR $C8A9 ; / CBB7 A6 91 LDX $91 ; CBB9 E4 AE CPX $AE ; Are we up to the cursor's row yet? CBBB 30 2E BMI $CBEB ; Above? Leave via "clear to end of line" CBBD D0 13 BNE $CBD2 ; Not there yet? Skip to block-move CBBF 18 CLC ; \ CBC0 A5 AD LDA $AD ; | CBC2 65 94 ADC $94 ; |__ Add column position to source address CBC4 85 94 STA $94 ; | CBC6 90 02 BCC $CBCA ; | CBC8 E6 95 INC $95 ; / CBCA A5 AA LDA $AA ; \ CBCC 38 SEC ; |__ Subtract col posn from screen width CBCD E5 AD SBC $AD ; | CBCF A8 TAY ; / CBD0 F0 03 BEQ $CBD5 ; If result's zero, skip block move. CBD2 20 E0 DF JSR $DFE0 ; Block move current row down one. CBD5 A9 80 LDA #$80 ; \ CBD7 C4 AA CPY $AA ; | CBD9 10 05 BPL $CBE0 ; |__ If we moved partial row, fill out CBDB 91 96 STA ($96),Y ; | the rest with space characters. CBDD C8 INY ; | CBDE 10 F7 BPL $CBD7 ; / CBE0 A5 94 LDA $94 ; \ CBE2 85 96 STA $96 ; |__ Make current src the new dst. CBE4 A5 95 LDA $95 ; | CBE6 85 97 STA $97 ; / CBE8 4C AC CB JMP $CBAC ; Iterate until done moving down. CBEB 4C 49 C8 JMP $C849 ; Exit via "clear to end of line" ;;============================================================================= ;;============================================================================= ;; CTRL-_: Backtab. Back up to previous tab stop, or first non-space char ;;----------------------------------------------------------------------------- CBEE A5 AD LDA $AD ; Get current cursor column CBF0 38 SEC ; \ CBF1 E9 01 SBC #$01 ; |-- Back up to previous tab stop? CBF3 29 03 AND #$03 ; / CBF5 85 90 STA $90 ; CBF7 20 94 C7 JSR $C794 ; Backspace up to previous tab stop. CBFA 20 C1 C6 JSR $C6C1 ; Update current row pointer (for rev wrap) ;fallthru ;;============================================================================= ;; Backspace up to # of times in $90, until we hit a space character. ;;----------------------------------------------------------------------------- CBFD A4 AD LDY $AD ; Get current cursor column CBFF B1 B1 LDA ($B1),Y ; Read from screen CC01 C9 80 CMP #$80 ; Is it a space character? CC03 D0 05 BNE $CC0A ; No: Move cursor right and leave. CC05 C6 90 DEC $90 ; Yes: Keep backspacing until we hit a CC07 10 EE BPL $CBF7 ; non-space character or reverse line-wrap. CC09 60 RTS ;;============================================================================= CC0A 4C 0F C8 JMP $C80F ;;============================================================================= ;; CTRL-F: End-of-line. Set cursor to right of last non-space char on line. ;;----------------------------------------------------------------------------- CC0D A6 AA LDX $AA ; \ CC0F CA DEX ; |-- Move cursor to right column CC10 86 AD STX $AD ; / CC12 86 90 STX $90 ; CC14 10 E7 BPL $CBFD ; Back up until we hit non-space char. ;;============================================================================= ; Data from $CC17 to $CDF7 (481 bytes) ;;============================================================================= ;; String Message Table: ;;----------------------------------------------------------------------------- CC16 .byte $27 ; 37 messages in message table. (#$01 thru #$26) CC17 .byte $02 ; 01 CR+LF .byte $0E ; 02 "(Recording)\r\n\t" .byte $06 ; 03 "rewind" .byte $05 ; 04 "\r\n ? " .byte $05 ; 05 "error" .byte $09 ; 06 "cartridge" .byte $08 ; 07 "cassette" .byte $04 ; 08 "tape" .byte $D6 ; 09 The Intellivision logo / bootup screen .byte $06 ; 0A "\r\n > " .byte $03 ; 0B "..." .byte $05 ; 0C "don't" .byte $0A ; 0D "understand" .byte $03 ; 0E "see" .byte $05 ; 0F "can't" .byte $06 ; 10 "load\x02\x24" .byte $05 ; 11 "sorry" .byte $06 ; 12 "writer" .byte $05 ; 13 "start" .byte $06 ; 14 "resume" .byte $05 ; 15 "eject" .byte $03 ; 16 "the" .byte $07 ; 17 "program" .byte $07 ; 18 "clean\x02\x24" .byte $07 ; 19 "comm\x02\x1Cs" .byte $04 ; 1A "list" .byte $06 ; 1B "return" .byte $03 ; 1C "and" .byte $05 ; 1D "enter" .byte $04 ; 1E "mode" .byte $04 ; 1F "head" .byte $04 ; 20 "type" .byte $0D ; 21 " one of \x02\x16se " .byte $11 ; 22 "For index, \x02\x20 \"I\"" .byte $08 ; 23 ", \x02\x16n \x02\x9B" .byte $03 ; 24 "ing" .byte $08 ; 25 "K. Smith" .byte $08 ; 26 "L. Zwick" .byte $0D, $0A ; .. CC3F .byte $28, $52, $65, $63, $6F, $72, $64, $69, $6E, $67 ; (Recording CC49 .byte $29, $0D, $0A, $09 ; )... CC4D .byte $72, $65, $77, $69, $6E, $64 ; rewind CC53 .byte $0D, $0A, $20, $3F, $20 ; .. ? CC58 .byte $65, $72, $72, $6F, $72 ; error CC5D .byte $63, $61, $72, $74, $72, $69, $64, $67, $65 ; cartridge CC66 .byte $63, $61, $73, $73, $65, $74, $74, $65 ; cassette CC6E .byte $74, $61, $70, $65 ; tape CC72 .byte $00, $02, $BF, $00, $08, $A0, $00, $17, $96 ; ......... CC7B .byte $0A, $00, $02, $BF, $A8, $BD, $80, $95, $AE, $BF ; .......... CC85 .byte $84, $BE, $83, $AA, $95, $80, $BF, $80, $8A, $85 ; .......... CC8F .byte $BF, $90, $80, $BA, $8A, $85, $BE, $9F, $83, $81 ; .......... CC99 .byte $8F, $A8, $9F, $AF, $94, $BE, $94, $AA, $54, $4D ; ........TM CCA3 .byte $0A, $00, $02, $BF, $AA, $8B, $BD, $95, $AA, $BF ; .......... CCAD .byte $80, $BF, $83, $AA, $95, $80, $BF, $80, $AA, $95 ; .......... CCB7 .byte $AB, $B5, $A8, $95, $AA, $95, $8B, $AF, $BD, $90 ; .......... CCC1 .byte $BF, $AA, $80, $80, $95, $97, $AF, $BE, $0A, $00 ; .......... CCCB .byte $02, $BF, $AA, $80, $AB, $95, $8A, $BF, $90, $AF ; .......... CCD5 .byte $BC, $8A, $BD, $94, $AF, $BC, $AA, $95, $80, $AF ; .......... CCDF .byte $9F, $80, $AA, $95, $BC, $BC, $BE, $85, $BF, $8A ; .......... CCE9 .byte $BD, $BE, $85, $95, $82, $BF, $0A, $0A, $0A, $00 ; .......... CCF3 .byte $10, $95, $B4, $A8, $88, $9C, $A8, $8C, $A8, $80 ; .......... CCFD .byte $94, $A8, $A8, $8C, $A8, $8C, $A8, $90, $94, $AC ; .......... CD07 .byte $84, $0A, $00, $10, $95, $97, $AF, $80, $95, $AA ; .......... CD11 .byte $B1, $AA, $90, $B5, $AA, $AA, $BA, $AA, $B1, $AA ; .......... CD1B .byte $8B, $95, $AA, $0A, $0A, $00, $11, $82, $97, $A8 ; .......... CD25 .byte $8C, $A8, $80, $9C, $84, $94, $94, $94, $9C, $84 ; .......... CD2F .byte $94, $9C, $94, $B4, $A8, $0A, $00, $12, $95, $AA ; .......... CD39 .byte $B1, $AA, $90, $B7, $90, $A5, $85, $95, $B3, $95 ; .......... CD43 .byte $95, $B5, $95, $97, $AF CD48 .byte $0D, $0A, $20, $20, $3E, $20 ; .. > CD4E .byte $2E, $2E, $2E, ; ... CD51 .byte $64, $6F, $6E, $27, $74 ; don't CD56 .byte $75, $6E, $64, $65, $72, $73, $74, $61, $6E, $64 ; understand CD60 .byte $73, $65, $65, ; see CD63 .byte $63, $61, $6E, $27, $74 ; can't CD68 .byte $6C, $6F, $61, $64, $02, $24 ; load.$ CD6E .byte $73, $6F, $72, $72, $79 ; sorry CD73 .byte $77, $72, $69, $74, $65, $72 ; writer CD79 .byte $73, $74, $61, $72, $74 ; start CD7E .byte $72, $65, $73, $75, $6D, $65 ; resume CD84 .byte $65, $6A, $65, $63, $74 ; eject CD89 .byte $74, $68, $65 ; the CD8C .byte $70, $72, $6F, $67, $72, $61, $6D ; program CD93 .byte $63, $6C, $65, $61, $6E, $02, $24 ; clean.$ CD9A .byte $63, $6F, $6D, $6D, $02, $1C, $73 ; comm..s CDA1 .byte $6C, $69, $73, $74 ; list CDA5 .byte $72, $65, $74, $75, $72, $6E ; return CDAB .byte $61, $6E, $64, ; and CDAE .byte $65, $6E, $74, $65, $72 ; enter CDB3 .byte $6D, $6F, $64, $65 ; mode CDB7 .byte $68, $65, $61, $64 ; head CDBB .byte $74, $79, $70, $65 ; type CDBF .byte $20, $6F, $6E, $65, $20, $6F, $66, $20, $02, $16 ; one of .. CDC9 .byte $73, $65, $20 ; se CDCC .byte $46, $6F, $72 ; For CDCF .byte $20, $69, $6E, $64, $65, $78, $2C, $20, $02, $20 ; index, . CDD9 .byte $20, $22, $49, $22 ; "I" CDDD .byte $2C, $20, $02, $16, $6E, $20, $02, $9B ; , ..n .. CDE5 .byte $69, $6E, $67 ; ing CDE8 .byte $4B, $2E, $20, $53, $6D, $69, $74, $68 ; K. Smith CDF0 .byte $4C, $2E, $20, $5A, $77, $69, $63, $6B ; L. Zwick ;;============================================================================= ;; Tape handler ;; ;; Read in planarized data, returning it to normal format. ;; ;; Termination handled by magic $FFFE in one of the planes' dropout word. ;; ;;----------------------------------------------------------------------------- CDF8 A6 B5 LDX $B5 ; Get word index CDFA 0A ASL A ; CDFB 3E 00 02 ROL $0200,X ; \__ record bitplanes CDFE 3E 01 02 ROL $0201,X ; / (32 words, 15 bits.) CE01 98 TYA ; \__ Jump if dropout detected CE02 30 06 BMI $CE0A ; / CE04 E6 C7 INC $C7 ; \ CE06 D0 02 BNE $CE0A ; |- Count # of valid data bits CE08 E6 C8 INC $C8 ; / CE0A 05 BC ORA $BC ; Merge in... ? (perhaps other fault status) CE0C 0A ASL A ; CE0D 3E 02 02 ROL $0202,X ; \__ record dropouts CE10 3E 03 02 ROL $0203,X ; / CE13 B0 0B BCS $CE20 ; Last word in plane? CE15 8A TXA ; \ CE16 69 04 ADC #$04 ; |- Point to next word in buffer CE18 85 B5 STA $B5 ; / CE1A 68 PLA CE1B A8 TAY CE1C 68 PLA CE1D AA TAX CE1E 68 PLA CE1F 40 RTI CE20 10 1B BPL $CE3D ; N=1: more planes; N=0: last plane ; More planes coming CE22 8A TXA ; \ CE23 49 7C EOR #$7C ; |- Go back to start of this double buffer CE25 85 B5 STA $B5 ; / CE27 E6 CF INC $CF CE29 A9 B7 LDA #$B7 ; \ CE2B 8D E8 03 STA $03E8 ; |_ Set tape handler to $CEB7: Look CE2E A9 CE LDA #$CE ; | for a new sync marker 1101. CE30 8D E9 03 STA $03E9 ; / CE33 A9 00 LDA #$00 ; \_ clear dropout flag? CE35 85 BC STA $BC ; / CE37 A9 FC LDA #$FC ; \_ count from $FC to $00 CE39 85 C3 STA $C3 ; / -4 up to 0. CE3B 30 3C BMI $CE79 ; Return from interrupt (always taken) ; Last plane of buffer: Swap double buffers CE3D 8A TXA ; \ CE3E 49 FC EOR #$FC ; |- flip word pointer to other double CE40 85 B5 STA $B5 ; / buffer CE42 A5 CD LDA $CD CE44 8D F2 03 STA $03F2 CE47 18 CLC CE48 69 01 ADC #$01 CE4A 85 CD STA $CD CE4C A5 CE LDA $CE CE4E 8D F3 03 STA $03F3 CE51 69 00 ADC #$00 CE53 85 CE STA $CE CE55 A5 BD LDA $BD CE57 85 EF STA $EF CE59 A9 00 LDA #$00 CE5B 85 BD STA $BD CE5D 85 CF STA $CF CE5F 85 C7 STA $C7 CE61 85 C8 STA $C8 CE63 F0 C4 BEQ $CE29 ; Set up for new sync (always taken) ;;============================================================================= ;; Tape handler ;; ;; Write bitplane buffer ($200..) to tape. ;;----------------------------------------------------------------------------- CE65 A6 B5 LDX $B5 ; \ CE67 1E 00 02 ASL $0200,X ; | CE6A 3E 01 02 ROL $0201,X ; |- Copy next bit to transmit out CE6D 2A ROL A ; | CE6E 85 B7 STA $B7 ; / CE70 E8 INX ; Increment to next word in plane CE71 E8 INX ; CE72 8A TXA ; CE73 29 3F AND #$3F ; \_ Detect getting to end of buffer CE75 F0 08 BEQ $CE7F ; / Branch if at end of buffer CE77 86 B5 STX $B5 ; Store updated pointer ;;============================================================================= ;; Restore Y, X, A and Return from Interrupt. ;;----------------------------------------------------------------------------- CE79 68 PLA CE7A A8 TAY CE7B 68 PLA CE7C AA TAX CE7D 68 PLA CE7E 40 RTI ;;============================================================================= ;; ...cont'd from $CE77 ;; ;; Handle moving plane-to-plane and scheduling writing sync-patterns. ;;----------------------------------------------------------------------------- CE7F 8A TXA ; CE80 A4 CF LDY $CF ; \ CE82 C8 INY ; |_ See if this was last plane of bits CE83 C0 0F CPY #$0F ; | (sends 0..14). Taken if last plane. CE85 10 16 BPL $CE9D ; / CE87 84 CF STY $CF ; Store updated plane number CE89 E9 3F SBC #$3F ; \_ Rewind to start of buffer CE8B 85 B5 STA $B5 ; / (Can't AND due to double-buffer scheme) CE8D A9 39 LDA #$39 ; \ CE8F 8D E8 03 STA $03E8 ; |_ Set tape handler to $CF39 to write CE92 A9 CF LDA #$CF ; | out sync pattern CE94 8D E9 03 STA $03E9 ; / CE97 A9 E8 LDA #$E8 ; \__ Sync pattern: 11101 CE99 85 B8 STA $B8 ; / CE9B 30 DC BMI $CE79 ; (always taken) CE9D 29 7F AND #$7F ; \_ Put pointer at start of opposite CE9F 85 B5 STA $B5 ; / double buffer. CEA1 E6 CD INC $CD ; \ CEA3 D0 02 BNE $CEA7 ; |- Incr 16 bit cnt at $CD..$CE CEA5 E6 CE INC $CE ; / CEA7 A9 00 LDA #$00 ; CEA9 85 CF STA $CF ; CEAB A9 FD LDA #$FD ; \ CEAD 8D E8 03 STA $03E8 ; |_ Set tape handler to do double-buf sync CEB0 A9 CE LDA #$CE ; | CEB2 8D E9 03 STA $03E9 ; / CEB5 D0 E0 BNE $CE97 ; \_ Schedule up a sync pattern for after ; / buffer sync and leave ;;============================================================================= ;; Tape handler ;; Look for record sync (11101 or 1101) ;; ;; Presumably we look for 1101 in the case where something else consumed ;; the 1 already. ;;----------------------------------------------------------------------------- CEB7 0A ASL A ; \ CEB8 A5 B8 LDA $B8 ; | CEBA 30 0D BMI $CEC9 ; |- Accumulate bits from the tape. CEBC 2A ROL A ; | Abort to $CEC9 if a 1 gets to bit 7 CEBD 85 B8 STA $B8 ; / CEBF E6 C3 INC $C3 ; \ If init'd to -ve number count to 0 CEC1 30 14 BMI $CED7 ; |- and then check to see if we match $0D CEC3 F0 18 BEQ $CEDD ; / else match against $1D. CEC5 C9 1D CMP #$1D ; \_ Did we match $1D? CEC7 D0 1A BNE $CEE3 ; / CEC9 A9 00 LDA #$00 ; \_ Yes: reset accumulator CECB 85 B8 STA $B8 ; / CECD A9 F8 LDA #$F8 ; \ CECF 8D E8 03 STA $03E8 ; |_ Set tape handler to bit plane CED2 A9 CD LDA #$CD ; | accumulator ($CDF8) for next bit plane CED4 8D E9 03 STA $03E9 ; / CED7 68 PLA CED8 A8 TAY CED9 68 PLA CEDA AA TAX CEDB 68 PLA CEDC 40 RTI CEDD C9 0D CMP #$0D ; Did we se 1101? CEDF F0 E8 BEQ $CEC9 ; Yes! Call it a match CEE1 D0 F4 BNE $CED7 ; Return from interrupt (always taken) CEE3 29 0F AND #$0F ; \ CEE5 C9 0E CMP #$0E ; |- Are lower 4 bits 1110? CEE7 F0 0E BEQ $CEF7 ; / CEE9 E6 BD INC $BD ; \ CEEB A6 BD LDX $BD ; |_ Increment count at $BD. If it's CEED E0 04 CPX #$04 ; | more than 4, reset accum and return CEEF 10 D8 BPL $CEC9 ; / CEF1 A9 FF LDA #$FF ; \_ set dropout flag? CEF3 85 BC STA $BC ; / CEF5 D0 D2 BNE $CEC9 ; reset accum and return (always taken) CEF7 A9 FF LDA #$FF ; \_ force accumulator to 1 CEF9 85 B8 STA $B8 ; / CEFB 30 DA BMI $CED7 ; return from interrupt (always taken) ;;============================================================================= ;;============================================================================= ;; Tape handler ;; ;; Sync up with code that fills our double buffers. Once synced up, write ;; a sync pattern out and resume writing data blocks. ;; ;; At end-of-data, we shut the tape down and send the foreground state ;; machine to state 12. ;;----------------------------------------------------------------------------- CEFD A0 00 LDY #$00 ; CEFF A5 B5 LDA $B5 ; CF01 45 C2 EOR $C2 ; CF03 10 0D BPL $CF12 ; CF05 0A ASL A ; CF06 D0 0A BNE $CF12 ; CF08 B1 BE LDA ($BE),Y ; CF0A 09 80 ORA #$80 ; CF0C 91 BE STA ($BE),Y ; CF0E 84 C2 STY $C2 ; CF10 D0 11 BNE $CF23 ; CF12 A5 B5 LDA $B5 ; CF14 45 C4 EOR $C4 ; CF16 10 0B BPL $CF23 ; CF18 0A ASL A ; CF19 D0 08 BNE $CF23 ; CF1B B1 C0 LDA ($C0),Y ; CF1D 09 80 ORA #$80 ; CF1F 91 BE STA ($BE),Y ; CF21 84 C4 STY $C4 ; CF23 A5 B5 LDA $B5 CF25 45 B6 EOR $B6 CF27 10 10 BPL $CF39 CF29 0A ASL A CF2A D0 0D BNE $CF39 CF2C A9 0C LDA #$0C ; \ CF2E 85 E0 STA $E0 ; |- Indicate we're done writing. CF30 8C 02 44 STY $4402 ; / Go to state machine state 12. CF33 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts CF36 4C 85 CF JMP $CF85 ; return from interrupt ;;============================================================================= ;; Tape handler ;; ;; Write out byte stored at $B8, and then switch to writing a bitplane ;; from the 32x15 data block ;;----------------------------------------------------------------------------- CF39 06 B8 ASL $B8 ; \_ Get next bit to write CF3B F0 06 BEQ $CF43 ; / CF3D 2A ROL A ; \_ Put it in $B7 to be written CF3E 85 B7 STA $B7 ; / CF40 4C 85 CF JMP $CF85 ; return from interrupt CF43 2A ROL A ; \_ Write out last bit CF44 85 B7 STA $B7 ; / CF46 A9 65 LDA #$65 ; \ CF48 8D E8 03 STA $03E8 ; |_ Set tape handler to bitplane CF4B A9 CE LDA #$CE ; | accumulator CF4D 8D E9 03 STA $03E9 ; / CF50 D0 33 BNE $CF85 ; return from interrupt (always taken) ;;============================================================================= ;; Tape Handler ;; Look for header consisting of ;; ;; 00000000 00000000 00000000 01111110 ;; 00000000 00000000 00000000 10111101 ;; 00000000 00000000 00000000 11011011 ;; 00000000 00000000 00000000 11100111 ;; ;; Once it recognizes one of the four rows, it sets a timeout so it "knows" ;; when there should be data. That gives it four tries to acquire header ;; sync. ;;----------------------------------------------------------------------------- CF52 0A ASL A ; Data into carry bit CF53 98 TYA ; Put data-detect into A CF54 10 01 BPL $CF57 ; Branch if data detected CF56 38 SEC ; Force 1's in if no data detected CF57 26 B8 ROL $B8 ; \ CF59 26 B9 ROL $B9 ; |_ 32-bit shift, shifting in 1s CF5B 26 BA ROL $BA ; | or MSB of A depending on Y's sign CF5D 26 BB ROL $BB ; / CF5F D0 1B BNE $CF7C ; \ CF61 A5 B9 LDA $B9 ; |_ Branch if any of B9, BA, BB CF63 05 BA ORA $BA ; | are non-zero CF65 D0 15 BNE $CF7C ; / CF67 AA TAX ; X = 0 CF68 A5 B8 LDA $B8 ; look at most recent 8 bits CF6A F0 10 BEQ $CF7C ; Count down if all 0 CF6C C9 E7 CMP #$E7 ; \_ In sync if we see 1110000111 CF6E F0 24 BEQ $CF94 ; / Payload begins now. CF70 C9 7E CMP #$7E ; \_ If we see 01111110, set timeout to $60 CF72 F0 17 BEQ $CF8B ; / CF74 C9 BD CMP #$BD ; \_ If we see 10111101, set timeout to $40 CF76 F0 14 BEQ $CF8C ; / CF78 C9 DB CMP #$DB ; \_ If we see 11011011, set timeout to $20 CF7A F0 11 BEQ $CF8D ; / CF7C A6 C3 LDX $C3 ; \_ Leave if counter's expired CF7E F0 05 BEQ $CF85 ; / CF80 CA DEX ; CF81 F0 11 BEQ $CF94 ; If count is just expiring, look for sync CF83 86 C3 STX $C3 ; Store updated count CF85 68 PLA CF86 A8 TAY CF87 68 PLA CF88 AA TAX CF89 68 PLA CF8A 40 RTI CF8B E8 INX ; \ CF8C E8 INX ; | CF8D BD A8 CF LDA $CFA8,X ; |- Get one of three timeouts CF90 85 C3 STA $C3 ; | $20, $40, $60 CF92 10 F1 BPL $CF85 ; / (always taken) CF94 86 C3 STX $C3 ; Store updated timout CF96 86 B8 STX $B8 ; Clear accumulator CF98 A9 FC LDA #$FC ; \_ Set sync counter to -4 CF9A 85 C3 STA $C3 ; / CF9C A9 B7 LDA #$B7 ; \ CF9E 8D E8 03 STA $03E8 ; |_ Set tape handler to CEB7 CFA1 A9 CE LDA #$CE ; | (look for 1101 sync) CFA3 8D E9 03 STA $03E9 ; / CFA6 D0 DD BNE $CF85 ; Always taken CFA8 .byte $20, $40, $60 ; timeout values ;;============================================================================= ;; Tape Handler ;; ;; Count down 16-bit count, and then switch to handler at CFBF ;; This writes the leadin of zeros for a header block. The code ;; that sets this up appears to request a least 512 zeroes. (I only ;; saw $C5 get initialized.) ;;----------------------------------------------------------------------------- CFAB C6 C6 DEC $C6 ; \ CFAD D0 2C BNE $CFDB ; |_ Count down 16-bit count CFAF C6 C5 DEC $C5 ; | CFB1 D0 28 BNE $CFDB ; / CFB3 A9 BF LDA #$BF ; \ CFB5 8D E8 03 STA $03E8 ; |_ Set tape handler to CFBF CFB8 A9 CF LDA #$CF ; | CFBA 8D E9 03 STA $03E9 ; / CFBD D0 1C BNE $CFDB ; Return from interrupt (always taken) ;;============================================================================= ;; Write out header ;; ;; Only writes first few rows: ;; ;; 01111110 ;; 00000000 00000000 00000000 10111101 ;; 00000000 00000000 00000000 11011011 ;; 00000000 00000000 00000000 ;; ;; The 11100111 gets written out by the bitplane writing code. ;; ;;----------------------------------------------------------------------------- CFBF 06 B8 ASL $B8 ; \ CFC1 2A ROL A ; |- Write next bit from $B8 CFC2 85 B7 STA $B7 ; / CFC4 A6 C3 LDX $C3 ; \ CFC6 CA DEX ; |- count down... CFC7 86 C3 STX $C3 ; / CFC9 F0 16 BEQ $CFE1 ; CFCB 8A TXA ; CFCC 29 1F AND #$1F ; CFCE D0 0B BNE $CFDB ; CFD0 8A TXA CFD1 A2 BD LDX #$BD CFD3 29 20 AND #$20 CFD5 F0 02 BEQ $CFD9 CFD7 A2 DB LDX #$DB CFD9 86 B8 STX $B8 ;fallthru ;;============================================================================= ;; Restore Y, X, A and Return from Interrupt. ;;----------------------------------------------------------------------------- CFDB 68 PLA CFDC A8 TAY CFDD 68 PLA CFDE AA TAX CFDF 68 PLA CFE0 40 RTI ;;============================================================================= ;;============================================================================= ;; Tape Handler ;; ;; Set tape handler to $CE65 (write bitplane buffer) and return. ;;----------------------------------------------------------------------------- CFE1 A9 65 LDA #$65 ; \ CFE3 8D E8 03 STA $03E8 ; |_ Set tape handler to $CE65 CFE6 A9 CE LDA #$CE ; | Bitplane writing code CFE8 8D E9 03 STA $03E9 ; / CFEB D0 EE BNE $CFDB ; Return from interrupt. (Always taken) ;;============================================================================= ;; Tape handler routine ;; ;; Verify blocks: Reads back blocks from tape and counts number of ;; valid bits read. Does not do anything with the data. ;; ;; if (carrier_loss == 0) ;; increment 16-bit count @ $C7..C8 ;; ;; if (--$C3 > 0) ;; return; ;; ;; if (++$CF == 15) ;; { ;; zero out count at $C7..$C8 ;; zero out $CF ;; } ;; $C3 = 36; ;; ;; return; ;; ;;----------------------------------------------------------------------------- CFED 98 TYA ; \_ Is data from tape valid CFEE 30 06 BMI $CFF6 ; / CFF0 E6 C7 INC $C7 ; \ CFF2 D0 02 BNE $CFF6 ; |- Count number of valid bits CFF4 E6 C8 INC $C8 ; / CFF6 C6 C3 DEC $C3 ; Count down 36..0 CFF8 10 E1 BPL $CFDB ; Return from interrupt if count not expired CFFA A6 CF LDX $CF ; \ CFFC E8 INX ; |_ Count up to 15 CFFD E0 0F CPX #$0F ; | CFFF 30 06 BMI $D007 ; / D001 A2 00 LDX #$00 ; \ D003 86 C7 STX $C7 ; |- Reset raw-zero count D005 86 C8 STX $C8 ; / D007 86 CF STX $CF ; Store updated 0..15 count D009 A9 24 LDA #$24 ; \_ Reset count @ $C3 to #$24 (36) D00B 85 C3 STA $C3 ; / D00D D0 CC BNE $CFDB ; Return from interrupt. (Always taken) ;;============================================================================= ;;============================================================================= ;; ;;----------------------------------------------------------------------------- D00F A5 C9 LDA $C9 D011 2C 03 40 BIT $4003 ; \_ Tape present? D014 10 08 BPL $D01E ; / (taken if tape is present.) D016 29 F8 AND #$F8 D018 A0 0F LDY #$0F D01A 84 A0 STY $A0 D01C D0 1A BNE $D038 ; (always taken) D01E A4 A0 LDY $A0 D020 30 1C BMI $D03E D022 D0 14 BNE $D038 D024 29 CF AND #$CF D026 84 CA STY $CA D028 8C CB 03 STY $03CB D02B 84 F7 STY $F7 D02D 2C 02 40 BIT $4002 ; 1==Leader or 0==tape D030 10 06 BPL $D038 ; jump if tape D032 84 CB STY $CB D034 84 CC STY $CC D036 09 42 ORA #$42 D038 85 C9 STA $C9 D03A 8D 4C 03 STA $034C ; set flag to be polled from CP-1600 D03D 60 RTS ;;============================================================================= D03E 09 01 ORA #$01 D040 2C 02 40 BIT $4002 ; \_ Tape or leader D043 10 15 BPL $D05A ; / (taken if tape) D045 85 90 STA $90 D047 29 06 AND #$06 D049 D0 5C BNE $D0A7 D04B A5 E0 LDA $E0 D04D 0A ASL A D04E 0A ASL A D04F 0A ASL A D050 A5 90 LDA $90 D052 09 42 ORA #$42 D054 90 53 BCC $D0A9 D056 49 06 EOR #$06 D058 D0 4F BNE $D0A9 D05A 29 F9 AND #$F9 D05C 85 90 STA $90 D05E A5 E0 LDA $E0 D060 10 45 BPL $D0A7 D062 24 9C BIT $9C D064 10 41 BPL $D0A7 D066 0A ASL A D067 10 0B BPL $D074 D069 A5 90 LDA $90 D06B 2C 04 40 BIT $4004 ; \_ Tape playing / recording? D06E 10 33 BPL $D0A3 ; / (taken if tape not playing) D070 29 BF AND #$BF D072 D0 35 BNE $D0A9 D074 29 20 AND #$20 D076 D0 2F BNE $D0A7 D078 A4 CF LDY $CF D07A C0 0A CPY #$0A D07C 90 29 BCC $D0A7 D07E A9 05 LDA #$05 D080 85 9C STA $9C D082 A0 00 LDY #$00 D084 A5 C8 LDA $C8 D086 D0 08 BNE $D090 D088 A5 C7 LDA $C7 D08A C9 96 CMP #$96 D08C 90 00 BCC $D08E D08E A0 FF LDY #$FF D090 8C 01 44 STY $4401 D093 A5 E0 LDA $E0 D095 05 DF ORA $DF D097 2D 00 44 AND $4400 D09A 29 02 AND #$02 D09C F0 09 BEQ $D0A7 D09E A5 90 LDA $90 D0A0 C8 INY D0A1 D0 CD BNE $D070 D0A3 09 40 ORA #$40 D0A5 85 90 STA $90 D0A7 A5 90 LDA $90 D0A9 A6 C9 LDX $C9 D0AB 20 38 D0 JSR $D038 D0AE 24 C9 BIT $C9 D0B0 50 06 BVC $D0B8 D0B2 A9 00 LDA #$00 D0B4 85 CD STA $CD D0B6 85 CE STA $CE D0B8 8A TXA D0B9 45 C9 EOR $C9 D0BB 29 40 AND #$40 D0BD F0 1B BEQ $D0DA D0BF 24 C9 BIT $C9 D0C1 A5 E0 LDA $E0 D0C3 29 20 AND #$20 D0C5 D0 0B BNE $D0D2 D0C7 70 11 BVS $D0DA D0C9 A6 CB LDX $CB D0CB D0 02 BNE $D0CF D0CD C6 CC DEC $CC D0CF C6 CB DEC $CB D0D1 60 RTS D0D2 50 06 BVC $D0DA D0D4 E6 CB INC $CB D0D6 D0 02 BNE $D0DA D0D8 E6 CC INC $CC D0DA 60 RTS ;;============================================================================= ;; Tape handler ;; Set up tape mode? ;;----------------------------------------------------------------------------- D0DB A5 E0 LDA $E0 ; \ D0DD 05 DF ORA $DF ; | A = ($DE) xor (($E0) or ($DF)) ?????? D0DF 45 DE EOR $DE ; / D0E1 30 04 BMI $D0E7 ; D0E3 A0 0A LDY #$0A ; D0E5 84 9F STY $9F ; D0E7 24 9F BIT $9F ; D0E9 30 02 BMI $D0ED ; D0EB 09 0C ORA #$0C ; D0ED AA TAX ; D0EE 4D F4 03 EOR $03F4 ; D0F1 F0 E7 BEQ $D0DA ; ; fall-thru ; ;;============================================================================= ;; Write 'X' to tape control bits at $4020 - $4027, modulated by mask in 'A' ;; ;; Algorithm: ;; ;; -- Save flags. This also saves interrupt enable ;; ;; -- If any of bits 7..5 in 'A' are non-zero, first disable interrupts ;; and write a zero to $4020. This is inverse of J3/20 to tape board. ;; ;; -- For bits 0..6: ;; -- If the bit was set in 'A', write the corresponding bit from 'X' ;; to location $4027 - bit #. ;; ;; -- Write bit 7 of 'X' to $4020. ;; ;; -- Restore flags (includes interrupt enable). ;;----------------------------------------------------------------------------- D0F3 08 PHP ; Save flags. D0F4 8E F4 03 STX $03F4 ; Remember X D0F7 85 90 STA $90 ; Remember A D0F9 29 E0 AND #$E0 ; Keep only three MSBs of A D0FB F0 06 BEQ $D103 ; D0FD 78 SEI ; \ If three MSBs weren't zero, mask ints D0FE A9 00 LDA #$00 ; |-- and clear tape cmd enable D100 8D 20 40 STA $4020 ; / D103 8A TXA ; Prepare to bit-expand $90 into $4021..$4027. D104 A2 07 LDX #$07 ; Iterate for 7 bits D106 46 90 LSR $90 ; Shift original value of A right. D108 90 03 BCC $D10D ; D10A 9D 20 40 STA $4020,X ; Hit $402x with value if bit was set. D10D 4A LSR A ; Shift value right D10E CA DEX ; D10F D0 F5 BNE $D106 ; Iterate over 7 bits. D111 8D 20 40 STA $4020 ; Store remaining bit to command enable D114 28 PLP ; Restore flags. D115 60 RTS ;;============================================================================= D116 AE EB 03 LDX $03EB D119 E8 INX D11A E8 INX D11B E0 06 CPX #$06 D11D 30 02 BMI $D121 D11F A2 00 LDX #$00 D121 EC EA 03 CPX $03EA D124 18 CLC D125 F0 0E BEQ $D135 D127 A5 94 LDA $94 D129 9D EC 03 STA $03EC,X D12C A5 95 LDA $95 D12E 9D ED 03 STA $03ED,X D131 8E EB 03 STX $03EB D134 60 RTS D135 A9 06 LDA #$06 D137 85 E7 STA $E7 D139 60 RTS ;;============================================================================= ;; ?? ;;----------------------------------------------------------------------------- D13A A5 D1 LDA $D1 D13C 30 0F BMI $D14D D13E 05 D0 ORA $D0 D140 F0 0C BEQ $D14E D142 A5 D0 LDA $D0 D144 38 SEC D145 E9 01 SBC #$01 D147 85 D0 STA $D0 D149 B0 02 BCS $D14D D14B C6 D1 DEC $D1 D14D 60 RTS D14E A6 E4 LDX $E4 D150 F0 30 BEQ $D182 D152 A5 E5 LDA $E5 D154 85 94 STA $94 D156 A5 E6 LDA $E6 D158 85 95 STA $95 D15A BD 14 D3 LDA $D314,X D15D 10 12 BPL $D171 D15F 2C 03 40 BIT $4003 ; Tape present? D162 10 0D BPL $D171 ; 0 == yes D164 A9 05 LDA #$05 D166 85 E7 STA $E7 D168 20 FB D4 JSR $D4FB D16B A2 09 LDX #$09 D16D 86 E4 STX $E4 D16F D0 E9 BNE $D15A D171 0A ASL A D172 30 05 BMI $D179 D174 BD F4 D2 LDA $D2F4,X D177 85 E0 STA $E0 D179 8A TXA D17A 20 FB D1 JSR $D1FB ; invoke state handler for state mach D17D 86 E4 STX $E4 D17F 8A TXA D180 D0 46 BNE $D1C8 D182 A5 D5 LDA $D5 D184 29 3F AND #$3F D186 05 D4 ORA $D4 D188 D0 1D BNE $D1A7 D18A AE EA 03 LDX $03EA D18D EC EB 03 CPX $03EB D190 F0 37 BEQ $D1C9 D192 E8 INX D193 E8 INX D194 E0 06 CPX #$06 D196 30 02 BMI $D19A D198 A2 00 LDX #$00 D19A BD EC 03 LDA $03EC,X D19D 85 D4 STA $D4 D19F BD ED 03 LDA $03ED,X D1A2 85 D5 STA $D5 D1A4 8E EA 03 STX $03EA D1A7 A5 D5 LDA $D5 D1A9 0A ASL A D1AA 30 01 BMI $D1AD D1AC 38 SEC D1AD 66 F0 ROR $F0 D1AF 0A ASL A D1B0 66 F0 ROR $F0 D1B2 4A LSR A D1B3 4A LSR A D1B4 85 E6 STA $E6 D1B6 A5 D4 LDA $D4 D1B8 85 E5 STA $E5 D1BA 05 E6 ORA $E6 D1BC F0 CC BEQ $D18A D1BE A9 00 LDA #$00 D1C0 85 D4 STA $D4 D1C2 85 D5 STA $D5 D1C4 A9 11 LDA #$11 D1C6 85 E4 STA $E4 D1C8 60 RTS ;;============================================================================= ;;============================================================================= ;; Shut down tape with varying levels of orderliness? ;; ;; Perhaps this is a sort of pause vs. stop routine? ;;----------------------------------------------------------------------------- D1C9 A5 F0 LDA $F0 D1CB 46 F0 LSR $F0 D1CD 46 F0 LSR $F0 D1CF 0A ASL A D1D0 30 0E BMI $D1E0 ; Shut down tape immediately? D1D2 90 1C BCC $D1F0 D1D4 20 74 DA JSR $DA74 ; set dbl buf ptr to second half D1D7 A9 04 LDA #$04 ; \_ Set high-level state machine to D1D9 85 E4 STA $E4 ; / state 4: Shut down tape. D1DB A9 14 LDA #$14 D1DD 85 D0 STA $D0 D1DF 60 RTS D1E0 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts D1E3 A9 00 LDA #$00 D1E5 8D 23 BE STA $BE23 D1E8 8D 24 BE STA $BE24 D1EB 8D 25 BE STA $BE25 D1EE 85 F3 STA $F3 D1F0 A9 0C LDA #$0C D1F2 85 E0 STA $E0 D1F4 A5 C9 LDA $C9 D1F6 29 7F AND #$7F D1F8 4C 38 D0 JMP $D038 ;;============================================================================= ;; Dispatch to state handler in high-level tape state machine ;;----------------------------------------------------------------------------- D1FB 0A ASL A ; \ D1FC AA TAX ; | D1FD BD AF D2 LDA $D2AF,X ; |__ Use A as index into jump table at $D2AF D200 85 98 STA $98 ; | Store jump vector into ($98) D202 BD B0 D2 LDA $D2B0,X ; | D205 85 99 STA $99 ; / D207 A5 C9 LDA $C9 ; \ D209 09 80 ORA #$80 ; |-- Set bit 7 of $C9, copy to $034C. D20B 20 38 D0 JSR $D038 ; / D20E A9 01 LDA #$01 ; \___ Set "there was input recently" flag D210 8D 07 03 STA $0307 ; / (unblank the screen as appropriate) D213 20 21 D2 JSR $D221 ; Dispatch to jump vector from table. D216 B0 08 BCS $D220 ; C == 1 means "stay in same state." D218 A6 E4 LDX $E4 ; \ D21A BD 14 D3 LDA $D314,X ; |__ Decode next state number and shift D21D 29 3F AND #$3F ; | to that state. D21F AA TAX ; / D220 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Dispatch to vector in ($0098) ;;----------------------------------------------------------------------------- D221 6C 98 00 JMP ($0098) ;;============================================================================= ;;============================================================================= ;; Initialize ?TAPE?. Called from RESET init routine. ;;----------------------------------------------------------------------------- D224 A9 5E LDA #$5E ; \ D226 85 94 STA $94 ; | D228 A9 D2 LDA #$D2 ; | Copy $D25E-$D269 => $34C - $3D3. D22A 85 95 STA $95 ; |- ( $00, $07, $00, $00, D22C A9 01 LDA #$01 ; | $00, $00, $C9, $00, D22E 85 90 STA $90 ; | $20, $E1, $C1, $A5 ) D230 20 63 C3 JSR $C363 ; / D233 A9 05 LDA #$05 ; Initialization: D235 85 D6 STA $D6 ; D237 A9 03 LDA #$03 ; Loc Value D239 85 D7 STA $D7 ; $D6 $05 D23B A9 85 LDA #$85 ; $D7 $03 D23D 85 DB STA $DB ; $DB $85 D23F A9 FF LDA #$FF ; $DC $FF D241 85 DC STA $DC ; $DD $BF D243 A9 BF LDA #$BF ; $D3 $80 D245 85 DD STA $DD ; $C9 $00 D247 A9 80 LDA #$80 ; $DF $0E D249 85 D3 STA $D3 ; $A0 $0E D24B A9 00 LDA #$00 ; D24D 85 C9 STA $C9 ; D24F A2 0E LDX #$0E ; D251 86 DF STX $DF ; D253 86 A0 STX $A0 ; D255 A9 FF LDA #$FF D257 20 F3 D0 JSR $D0F3 ; Some bizarre $4020 init (TAPE?) D25A 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts D25D 60 RTS ;;============================================================================= ; Data from $D25F to $D265 (7 bytes) D25E .byte $00, $07, $00, $00, $00, $00, $C9, $00 ; ....... ;;============================================================================= ;; Tape state machine support code ;; ;; -- shut off tape interrupts and bit-level state machine ;; -- initialize receive block ;;----------------------------------------------------------------------------- D266 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts D269 A5 94 LDA $94 ; \ D26B 48 PHA ; |_ save $94/$95 D26C A5 95 LDA $95 ; | D26E 48 PHA ; / D26F A9 00 LDA #$00 ; \ D271 85 94 STA $94 ; | D273 A9 02 LDA #$02 ; | D275 85 95 STA $95 ; |- Init $200 - $2FF to 0 D277 A9 00 LDA #$00 ; | D279 85 90 STA $90 ; | D27B 20 D2 DF JSR $DFD2 ; / D27E 68 PLA ; \ D27F 85 95 STA $95 ; |_ restore $94/$95 D281 68 PLA ; | D282 85 94 STA $94 ; / D284 A9 FF LDA #$FF ; \ D286 8D 7F 02 STA $027F ; | D289 8D FF 02 STA $02FF ; |_ Put $FFFE into last 16-bit D28C 0A ASL A ; | word in each half of receive D28D 8D 7E 02 STA $027E ; | double-buffer? (this is where D290 8D FE 02 STA $02FE ; / dropouts get recorded) D293 A9 00 LDA #$00 ; D295 85 B5 STA $B5 ; Word pointer in bitplane (lo-lev dbl buf) D297 85 B6 STA $B6 ; Word pointer in bitplane (hi-lev dbl buf) D299 8D 21 BE STA $BE21 ; D29C 8D 22 BE STA $BE22 ; D29F 85 BD STA $BD ; D2A1 85 CF STA $CF ; D2A3 85 C3 STA $C3 ; D2A5 85 C7 STA $C7 ; \_ Valid-bits-in-block counter D2A7 85 C8 STA $C8 ; / D2A9 A2 03 LDX #$03 ; \ D2AB 95 B8 STA $B8,X ; |_ Header sync delay line D2AD CA DEX ; | D2AE 10 FB BPL $D2AB ; / D2B0 60 RTS ; Data from $D2B1 to $D336 (134 bytes) ; jump vector for tape commands (?) D2B1 .byte $4A, $D3 ; D34A D2B3 .byte $56, $D3 ; D356 D2B5 .byte $16, $D1 ; D116 D2B7 .byte $37, $D3 ; D337 D2B9 .byte $68, $D4 ; D468 D2BB .byte $74, $D3 ; D374 D2BD .byte $74, $D3 ; D374 D2BF .byte $74, $D3 ; D374 D2C1 .byte $37, $D3 ; D337 D2C3 .byte $8D, $D3 ; D38D D2C5 .byte $C4, $D3 ; D3C4 D2C7 .byte $DA, $D3 ; D3DA D2C9 .byte $E7, $D3 ; D3E7 D2CB .byte $85, $D3 ; D385 D2CD .byte $74, $D3 ; D374 D2CF .byte $68, $D4 ; D468 D2D1 .byte $96, $D4 ; D496 D2D3 .byte $9D, $D3 ; D39D D2D5 .byte $A4, $D3 ; D3A4 D2D7 .byte $11, $D4 ; D411 D2D9 .byte $15, $D4 ; D415 D2DB .byte $6B, $D3 ; D36B D2DD .byte $6D, $D4 ; D46D D2DF .byte $76, $D4 ; D476 D2E1 .byte $89, $D4 ; D489 D2E3 .byte $6F, $D3 ; D36F D2E5 .byte $28, $D7 ; D728 D2E7 .byte $21, $D6 ; D621 D2E9 .byte $43, $D8 ; D843 D2EB .byte $86, $D7 ; D786 D2ED .byte $81, $D9 ; D981 D2EF .byte $AC, $D9 ; D9AC D2F1 .byte $73, $D6 ; D673 D2F3 .byte $76, $D6 ; D676 ; Tape mode words? These pair up with table below. D2F5 .byte $00, $00, $00, $0C, $A2, $EE, $CE, $BD, $8C, $CE D2FF .byte $EE, $CE, $00, $00, $BC, $A3, $00, $CE, $0C, $EE D309 .byte $CE, $EE, $AE, $AE, $AE, $00, $A0, $A0, $A0, $A0 D313 .byte $BD, $BD ; .......... ; another decode table from tape. ;; =========================================================================== ;; bit 7: 0 == execute always, 1 == execute if tape present ;; bit 6: 0 == copy value from table above into $E0: Tape mode? ;; bit 5..0: Next state number (stored in $E4) ; State When Copy E0 Next Addr D315 .byte $61 ; 1 Always No 33 D34A .byte $61 ; 2 Always No 33 D356 .byte $61 ; 3 Always No 33 D116 .byte $22 ; 4 Always Yes 34 D337 Shut down tape .byte $1A ; 5 Always Yes 26 D468 .byte $21 ; 6 Always Yes 33 D374 .byte $21 ; 7 Always Yes 33 D374 .byte $21 ; 8 Always Yes 33 D374 .byte $21 ; 9 Always Yes 33 D337 .byte $92 ; 10 Tape Yes 18 D38D D31F .byte $CD ; 11 Tape No 13 D3C4 .byte $CD ; 12 Tape No 13 D3DA After done writing .byte $CD ; 13 Tape No 13 D3E7 .byte $E1 ; 14 Tape No 33 D385 .byte $21 ; 15 Always Yes 33 D374 .byte $1A ; 16 Always Yes 26 D468 .byte $40 ; 17 Always No 0 D496 .byte $92 ; 18 Tape Yes 18 D39D .byte $A1 ; 19 Tape Yes 33 D3A4 .byte $96 ; 20 Tape Yes 22 D411 D329 .byte $97 ; 21 Tape Yes 23 D415 .byte $97 ; 22 Tape Yes 23 D36B .byte $98 ; 23 Tape Yes 24 D46D .byte $99 ; 24 Tape Yes 25 D476 Verify blocks .byte $A1 ; 25 Tape Yes 33 D489 Wait until complete? .byte $61 ; 26 Always No 33 D36F .byte $DB ; 27 Tape No 27 D728 .byte $DB ; 28 Tape No 27 D621 .byte $DB ; 29 Tape No 27 D843 .byte $DE ; 30 Tape No 30 D786 D333 .byte $A0 ; 31 Tape Yes 32 D981 Write tape header .byte $A0 ; 32 Tape Yes 32 D9AC .byte $40 ; 33 Always No 0 D673 Twiddle flags ($D2) .byte $40 ; 34 Always No 0 D676 Twiddle flags ($D2) ;;============================================================================= ;; Shut down tape ;;----------------------------------------------------------------------------- D337 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts D33A 8C EA 03 STY $03EA ; D33D 8C EB 03 STY $03EB ; D340 84 D4 STY $D4 ; D342 84 D5 STY $D5 ; D344 84 F3 STY $F3 ; D346 A9 0F LDA #$0F ; D348 D0 37 BNE $D381 ; (always taken) D34A A5 94 LDA $94 D34C 29 03 AND #$03 D34E 0A ASL A D34F 0A ASL A D350 85 91 STA $91 D352 A9 F3 LDA #$F3 D354 D0 0D BNE $D363 ; (always taken) D356 A9 00 LDA #$00 D358 85 F0 STA $F0 D35A A5 94 LDA $94 D35C 29 01 AND #$01 D35E 0A ASL A D35F 85 91 STA $91 D361 A9 FD LDA #$FD D363 25 DF AND $DF D365 05 91 ORA $91 D367 85 DF STA $DF D369 18 CLC D36A 60 RTS D36B A9 04 LDA #$04 D36D D0 12 BNE $D381 D36F 20 80 D4 JSR $D480 D372 90 03 BCC $D377 D374 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts D377 A9 00 LDA #$00 D379 85 F0 STA $F0 D37B A5 E6 LDA $E6 D37D 85 D1 STA $D1 D37F A5 E5 LDA $E5 D381 85 D0 STA $D0 D383 18 CLC D384 60 RTS D385 A5 E5 LDA $E5 D387 09 80 ORA #$80 D389 85 F3 STA $F3 D38B 18 CLC D38C 60 RTS D38D A5 C9 LDA $C9 D38F 20 B2 D3 JSR $D3B2 D392 20 66 D2 JSR $D266 ; Initialize tape receive D395 A9 08 LDA #$08 D397 85 9C STA $9C D399 A9 3C LDA #$3C D39B D0 E4 BNE $D381 D39D A2 13 LDX #$13 D39F AD 02 40 LDA $4002 D3A2 0A ASL A D3A3 60 RTS D3A4 A9 14 LDA #$14 D3A6 85 D0 STA $D0 D3A8 18 CLC D3A9 A9 00 LDA #$00 D3AB 85 CB STA $CB D3AD 85 CC STA $CC D3AF 60 RTS D3B0 A2 21 LDX #$21 D3B2 A5 C9 LDA $C9 D3B4 29 CF AND #$CF D3B6 20 38 D0 JSR $D038 D3B9 A9 00 LDA #$00 D3BB 85 CA STA $CA D3BD 85 F0 STA $F0 D3BF 8D 25 BE STA $BE25 D3C2 38 SEC D3C3 60 RTS D3C4 A5 E5 LDA $E5 D3C6 05 E6 ORA $E6 D3C8 F0 E6 BEQ $D3B0 D3CA 18 CLC D3CB A5 CB LDA $CB D3CD 65 E5 ADC $E5 D3CF 85 E5 STA $E5 D3D1 A5 CC LDA $CC D3D3 65 E6 ADC $E6 D3D5 85 E6 STA $E6 D3D7 4C E7 D3 JMP $D3E7 D3DA A5 CB LDA $CB D3DC 38 SEC D3DD E5 E5 SBC $E5 D3DF 85 E5 STA $E5 D3E1 A5 CC LDA $CC D3E3 E5 E6 SBC $E6 D3E5 85 E6 STA $E6 D3E7 20 B2 D3 JSR $D3B2 D3EA 20 66 D2 JSR $D266 ; Initialize tape receive D3ED 24 C9 BIT $C9 D3EF A2 15 LDX #$15 D3F1 A5 CC LDA $CC D3F3 C5 E6 CMP $E6 D3F5 D0 04 BNE $D3FB D3F7 A5 CB LDA $CB D3F9 C5 E5 CMP $E5 D3FB F0 0E BEQ $D40B D3FD B0 01 BCS $D400 D3FF CA DEX D400 A9 14 LDA #$14 D402 8D F5 03 STA $03F5 D405 A9 09 LDA #$09 D407 85 9C STA $9C D409 38 SEC D40A 60 RTS D40B 50 F3 BVC $D400 D40D A2 21 LDX #$21 D40F 38 SEC D410 60 RTS D411 A0 0E LDY #$0E D413 D0 02 BNE $D417 D415 A0 07 LDY #$07 D417 A6 E4 LDX $E4 D419 A5 E6 LDA $E6 D41B C5 CC CMP $CC D41D D0 04 BNE $D423 D41F A5 E5 LDA $E5 D421 C5 CB CMP $CB D423 D0 12 BNE $D437 D425 24 C9 BIT $C9 D427 50 0E BVC $D437 D429 A5 E0 LDA $E0 D42B 49 20 EOR #$20 D42D 85 E0 STA $E0 D42F 84 D0 STY $D0 D431 A9 7F LDA #$7F D433 85 9C STA $9C D435 18 CLC D436 60 RTS D437 20 51 D4 JSR $D451 D43A 90 2A BCC $D466 D43C 20 A9 D3 JSR $D3A9 D43F E0 15 CPX #$15 D441 F0 A4 BEQ $D3E7 D443 A5 E5 LDA $E5 D445 85 CB STA $CB D447 A5 E6 LDA $E6 D449 85 CC STA $CC D44B 20 D4 D0 JSR $D0D4 D44E 4C E7 D3 JMP $D3E7 ;;============================================================================= ;; Look for recordable / readable surface... with timeout? ;;----------------------------------------------------------------------------- D451 18 CLC D452 2C 02 40 BIT $4002 ; Recordable surface detected? D455 10 10 BPL $D467 ; Yes: return w/ C==0 D457 CE 03 44 DEC $4403 ; \ D45A AD 03 44 LDA $4403 ; D45D 29 03 AND #$03 ; D45F D0 06 BNE $D467 ; ... return w/ C==0. (why?) D461 CE F5 03 DEC $03F5 ; D464 D0 01 BNE $D467 ; ... return w/ C==0. (why?) D466 38 SEC ; No recordable media D467 60 RTS ;;============================================================================= D468 2C F4 03 BIT $03F4 D46B 30 04 BMI $D471 D46D A9 0A LDA #$0A D46F 85 D0 STA $D0 D471 20 66 D2 JSR $D266 ; Initialize tape receive D474 18 CLC ; move to next state D475 60 RTS ;;============================================================================= ;; High-level tape control state machine ;; Verify block(s)? ;;----------------------------------------------------------------------------- D476 A9 00 LDA #$00 D478 85 9C STA $9C D47A 8D 01 44 STA $4401 D47D 8D 00 44 STA $4400 D480 A9 ED LDA #$ED ; \ D482 A2 CF LDX #$CF ; |- Set ISR to $CFED (verify block) D484 20 EC C1 JSR $C1EC ; / D487 18 CLC ; return "done" D488 60 RTS ;;============================================================================= ;;============================================================================= ;; High-level tape control state machine ;; Wait until verify complete ;;----------------------------------------------------------------------------- D489 A2 19 LDX #$19 D48B AD 01 44 LDA $4401 D48E 4A LSR A D48F 90 D5 BCC $D466 ; return "not done" (e.g. "stay in state") D491 20 E1 C1 JSR $C1E1 ; Turn off and NOP tape interrupts D494 18 CLC ; return "done" D495 60 RTS ;;============================================================================= D496 A5 94 LDA $94 D498 85 D2 STA $D2 D49A A5 95 LDA $95 D49C 85 D3 STA $D3 D49E C9 05 CMP #$05 D4A0 24 C9 BIT $C9 D4A2 B0 05 BCS $D4A9 D4A4 50 03 BVC $D4A9 D4A6 4C F2 D5 JMP $D5F2 D4A9 20 33 D6 JSR $D633 D4AC A5 E8 LDA $E8 D4AE 29 DF AND #$DF D4B0 09 18 ORA #$18 D4B2 85 E8 STA $E8 D4B4 0A ASL A D4B5 25 E8 AND $E8 D4B7 30 4A BMI $D503 D4B9 A5 E8 LDA $E8 D4BB 29 7F AND #$7F D4BD 85 E8 STA $E8 D4BF 20 8D D6 JSR $D68D D4C2 A5 E8 LDA $E8 D4C4 29 02 AND #$02 D4C6 F0 09 BEQ $D4D1 D4C8 20 65 DA JSR $DA65 D4CB A9 10 LDA #$10 D4CD 24 C9 BIT $C9 D4CF D0 3E BNE $D50F D4D1 A5 E8 LDA $E8 D4D3 4A LSR A D4D4 90 3D BCC $D513 D4D6 20 65 DA JSR $DA65 D4D9 A5 E9 LDA $E9 D4DB 85 E4 STA $E4 D4DD A5 EA LDA $EA D4DF 85 E5 STA $E5 D4E1 A5 EB LDA $EB D4E3 85 E6 STA $E6 D4E5 68 PLA D4E6 68 PLA D4E7 68 PLA D4E8 68 PLA D4E9 4C 4E D1 JMP $D14E D4EC A9 02 LDA #$02 D4EE 2C A9 08 BIT $08A9 ; alt entry LDA #$08 D4F1 2C A9 10 BIT $10A9 ; alt entry LDA #$10 D4F4 48 PHA D4F5 20 87 D6 JSR $D687 D4F8 68 PLA D4F9 D0 11 BNE $D50C ; (always taken?) D4FB A9 01 LDA #$01 D4FD D0 0D BNE $D50C ; (always taken) D4FF A9 04 LDA #$04 D501 D0 09 BNE $D50C ; (always taken) D503 20 65 DA JSR $DA65 D506 A9 80 LDA #$80 D508 D0 02 BNE $D50C ; (always taken) D50A A9 40 LDA #$40 D50C 20 68 D6 JSR $D668 D50F A2 04 LDX #$04 D511 38 SEC D512 60 RTS D513 A9 00 LDA #$00 D515 85 E9 STA $E9 D517 85 EA STA $EA D519 20 8D D6 JSR $D68D D51C 24 C9 BIT $C9 D51E 50 03 BVC $D523 D520 4C F2 D5 JMP $D5F2 D523 A5 ED LDA $ED D525 05 EE ORA $EE D527 F0 2F BEQ $D558 D529 2C 25 BE BIT $BE25 D52C 70 2F BVS $D55D D52E A5 F0 LDA $F0 D530 0A ASL A D531 0A ASL A D532 29 C0 AND #$C0 D534 F0 10 BEQ $D546 D536 45 F0 EOR $F0 D538 0A ASL A D539 30 0B BMI $D546 D53B 24 F0 BIT $F0 D53D 50 03 BVC $D542 D53F 4C EB D5 JMP $D5EB D542 A2 20 LDX #$20 D544 38 SEC D545 60 RTS D546 20 65 DA JSR $DA65 D549 20 09 D7 JSR $D709 D54C A9 01 LDA #$01 D54E 85 E5 STA $E5 D550 A9 00 LDA #$00 D552 85 E6 STA $E6 D554 A2 0B LDX #$0B D556 38 SEC D557 60 RTS D558 20 73 D6 JSR $D673 D55B 18 CLC D55C 60 RTS D55D 24 F0 BIT $F0 D55F 70 55 BVS $D5B6 D561 A9 00 LDA #$00 D563 8D 25 BE STA $BE25 D566 AD E3 04 LDA $04E3 D569 85 E3 STA $E3 D56B 85 90 STA $90 D56D AD E2 04 LDA $04E2 D570 85 E2 STA $E2 D572 A6 E3 LDX $E3 D574 D0 04 BNE $D57A D576 C9 0E CMP #$0E D578 90 90 BCC $D50A D57A 46 90 LSR $90 D57C 6A ROR A D57D 46 90 LSR $90 D57F 6A ROR A D580 46 90 LSR $90 D582 6A ROR A D583 49 FF EOR #$FF D585 38 SEC D586 69 00 ADC #$00 D588 18 CLC D589 65 E2 ADC $E2 D58B 85 E2 STA $E2 D58D A5 E3 LDA $E3 D58F E5 90 SBC $90 D591 85 E3 STA $E3 D593 38 SEC D594 A5 E2 LDA $E2 D596 E9 0D SBC #$0D D598 85 E2 STA $E2 D59A B0 02 BCS $D59E D59C C6 E3 DEC $E3 D59E 20 66 D2 JSR $D266 ; Initialize tape receive D5A1 A9 00 LDA #$00 D5A3 85 CD STA $CD D5A5 85 CE STA $CE D5A7 A9 AD LDA #$AD D5A9 85 E0 STA $E0 D5AB A9 2B LDA #$2B D5AD 85 D0 STA $D0 D5AF 8D 02 44 STA $4402 D5B2 A2 1F LDX #$1F D5B4 38 SEC D5B5 60 RTS D5B6 A0 A0 LDY #$A0 D5B8 84 E0 STY $E0 D5BA A5 DF LDA $DF D5BC 29 02 AND #$02 D5BE F0 55 BEQ $D615 D5C0 AD FF 44 LDA $44FF D5C3 18 CLC D5C4 6D FF 04 ADC $04FF D5C7 29 03 AND #$03 D5C9 AA TAX D5CA 29 02 AND #$02 D5CC D0 06 BNE $D5D4 D5CE 24 F3 BIT $F3 D5D0 10 02 BPL $D5D4 D5D2 A6 F3 LDX $F3 D5D4 A9 02 LDA #$02 D5D6 24 DF BIT $DF D5D8 D0 02 BNE $D5DC D5DA A2 00 LDX #$00 D5DC 86 F3 STX $F3 D5DE 8A TXA D5DF 29 01 AND #$01 D5E1 05 E0 ORA $E0 D5E3 85 E0 STA $E0 D5E5 A9 00 LDA #$00 D5E7 85 F2 STA $F2 D5E9 85 E1 STA $E1 D5EB 20 BE D6 JSR $D6BE D5EE A2 1B LDX #$1B D5F0 38 SEC D5F1 60 RTS D5F2 A9 80 LDA #$80 D5F4 8D 25 BE STA $BE25 D5F7 A9 A2 LDA #$A2 D5F9 85 E0 STA $E0 D5FB A5 CB LDA $CB D5FD 8D E2 03 STA $03E2 D600 A5 CC LDA $CC D602 8D E3 03 STA $03E3 D605 A9 61 LDA #$61 D607 85 94 STA $94 D609 A9 D6 LDA #$D6 D60B 85 95 STA $95 D60D 20 33 D6 JSR $D633 D610 20 09 D7 JSR $D709 D613 A9 E7 LDA #$E7 D615 18 CLC D616 69 28 ADC #$28 D618 85 D0 STA $D0 D61A 20 66 D2 JSR $D266 ; Initialize tape receive D61D A2 1C LDX #$1C D61F 38 SEC D620 60 RTS D621 A9 52 LDA #$52 ; \ D623 A2 CF LDX #$CF ; |- Set ISR to $CF52 D625 20 EC C1 JSR $C1EC ; / D628 A2 1B LDX #$1B D62A A9 96 LDA #$96 D62C 85 F1 STA $F1 D62E 8D F5 03 STA $03F5 D631 38 SEC D632 60 RTS D633 A0 00 LDY #$00 D635 B1 94 LDA ($94),Y D637 99 E8 00 STA $00E8,Y D63A C8 INY D63B C0 07 CPY #$07 D63D D0 F6 BNE $D635 D63F A5 EC LDA $EC D641 29 3F AND #$3F D643 85 EC STA $EC D645 A9 01 LDA #$01 D647 24 E8 BIT $E8 D649 F0 02 BEQ $D64D D64B A0 04 LDY #$04 D64D B1 94 LDA ($94),Y D64F 85 D4 STA $D4 D651 C8 INY D652 B1 94 LDA ($94),Y D654 0A ASL A D655 0A ASL A D656 85 D5 STA $D5 D658 A5 F0 LDA $F0 D65A 0A ASL A D65B 66 D5 ROR $D5 D65D 0A ASL A D65E 66 D5 ROR $D5 D660 60 RTS ; Data from $D661 to $D667 (7 bytes) ; This data is copied to $E8..$EE by routine at $D633, called from $D60D D661 .byte $00, $00, $00, $E0, $04, $01, $00 ; ....... D668 05 CA ORA $CA D66A 85 CA STA $CA D66C A5 C9 LDA $C9 D66E 09 20 ORA #$20 D670 4C 38 D0 JMP $D038 ;; =========================================================================== ;; Prepare to go idle by setting/clearing flags: ;; State 33 enters at D673: Clears bits 4, 3, sets bit 7 ;; State 34 enters at D676: Clears bit 3, sets bit 7 ;; ;; Either tries to toggle the bits at the location pointed to by $D2-$D3. ;; Prevents multiple toggles with a flag in bit 7 of $D3. ;; --------------------------------------------------------------------------- D673 A9 E7 LDA #$E7 D675 2C A9 F7 BIT $F7A9 ; Alt entry D676: LDA #$F7 ; A == $E7 or $F7 D678 24 D3 BIT $D3 D67A 30 0A BMI $D686 D67C A0 00 LDY #$00 D67E 31 D2 AND ($D2),Y D680 09 80 ORA #$80 D682 91 D2 STA ($D2),Y D684 85 D3 STA $D3 D686 60 RTS ;; =========================================================================== D687 A5 E8 LDA $E8 D689 09 20 ORA #$20 D68B 85 E8 STA $E8 D68D 24 D3 BIT $D3 D68F 30 F5 BMI $D686 D691 A0 00 LDY #$00 D693 A5 E8 LDA $E8 D695 91 D2 STA ($D2),Y D697 C8 INY D698 A5 E9 LDA $E9 D69A 91 D2 STA ($D2),Y D69C C8 INY D69D A5 EA LDA $EA D69F 91 D2 STA ($D2),Y D6A1 60 RTS D6A2 A5 E9 LDA $E9 D6A4 85 94 STA $94 D6A6 A5 EA LDA $EA D6A8 85 95 STA $95 D6AA A0 05 LDY #$05 D6AC 46 95 LSR $95 D6AE 66 94 ROR $94 D6B0 88 DEY D6B1 D0 F9 BNE $D6AC D6B3 A5 95 LDA $95 D6B5 C5 EE CMP $EE D6B7 D0 04 BNE $D6BD D6B9 A5 94 LDA $94 D6BB C5 ED CMP $ED D6BD 60 RTS D6BE A9 04 LDA #$04 D6C0 24 E8 BIT $E8 D6C2 D0 3F BNE $D703 D6C4 A5 EB LDA $EB D6C6 18 CLC D6C7 65 E9 ADC $E9 D6C9 85 94 STA $94 D6CB AA TAX D6CC A5 EC LDA $EC D6CE 65 EA ADC $EA D6D0 85 95 STA $95 D6D2 C9 05 CMP #$05 D6D4 D0 04 BNE $D6DA D6D6 E4 D9 CPX $D9 D6D8 90 29 BCC $D703 D6DA A5 DB LDA $DB D6DC 29 7F AND #$7F D6DE C5 95 CMP $95 D6E0 D0 06 BNE $D6E8 D6E2 A5 DA LDA $DA D6E4 C5 94 CMP $94 D6E6 F0 02 BEQ $D6EA D6E8 B0 1A BCS $D704 D6EA 18 CLC D6EB A9 1F LDA #$1F D6ED 65 94 ADC $94 D6EF 85 94 STA $94 D6F1 90 02 BCC $D6F5 D6F3 E6 95 INC $95 D6F5 A5 DD LDA $DD D6F7 29 7F AND #$7F D6F9 C5 95 CMP $95 D6FB D0 04 BNE $D701 D6FD A5 DC LDA $DC D6FF C5 94 CMP $94 D701 90 01 BCC $D704 D703 60 RTS D704 68 PLA D705 68 PLA D706 4C FF D4 JMP $D4FF D709 A5 D2 LDA $D2 D70B 85 D4 STA $D4 D70D A5 D3 LDA $D3 D70F A0 80 LDY #$80 D711 84 D3 STY $D3 D713 4C 54 D6 JMP $D654 D716 A5 D4 LDA $D4 D718 85 94 STA $94 D71A 85 D2 STA $D2 D71C A5 D5 LDA $D5 D71E 29 3F AND #$3F D720 85 95 STA $95 D722 85 D3 STA $D3 D724 20 33 D6 JSR $D633 D727 60 RTS D728 2C 25 BE BIT $BE25 D72B 50 05 BVC $D732 D72D AD 24 BE LDA $BE24 D730 D0 42 BNE $D774 D732 20 28 D9 JSR $D928 D735 A5 B5 LDA $B5 D737 45 B6 EOR $B6 D739 10 0B BPL $D746 D73B 20 B1 D7 JSR $D7B1 D73E 08 PHP D73F 20 8D D6 JSR $D68D D742 28 PLP D743 A2 1D LDX #$1D D745 60 RTS D746 AD E9 03 LDA $03E9 ; \ D749 C9 CF CMP #$CF ; | D74B D0 05 BNE $D752 ; |_ If low-level tape handler isn't $CF52, D74D AD E8 03 LDA $03E8 ; | move to next state. CF52 is block header D750 C9 52 CMP #$52 ; | search handler. D752 D0 18 BNE $D76C ; / D754 20 51 D4 JSR $D451 ; Look for recordable media D757 B0 15 BCS $D76E ; Taken if none: End-Of-Tape error? D759 A5 F1 LDA $F1 D75B F0 0F BEQ $D76C D75D C6 F1 DEC $F1 D75F D0 0B BNE $D76C D761 A5 E0 LDA $E0 D763 05 DF ORA $DF D765 29 02 AND #$02 D767 D0 03 BNE $D76C D769 4C 0A D5 JMP $D50A D76C 18 CLC D76D 60 RTS D76E 20 D4 D0 JSR $D0D4 D771 4C 18 D9 JMP $D918 D774 4E 25 BE LSR $BE25 D777 AD E5 03 LDA $03E5 D77A D0 06 BNE $D782 D77C AE E4 03 LDX $03E4 D77F CA DEX D780 F0 B0 BEQ $D732 D782 A9 1E LDA #$1E ; \_ transition to state 30 D784 85 E4 STA $E4 ; / ; state 30 D786 20 28 D9 JSR $D928 D789 A5 B5 LDA $B5 D78B 45 B6 EOR $B6 D78D 0A ASL A D78E 90 B5 BCC $D745 D790 20 B9 D7 JSR $D7B9 D793 90 B0 BCC $D745 D795 A5 CE LDA $CE D797 CD E5 03 CMP $03E5 D79A D0 05 BNE $D7A1 D79C A5 CD LDA $CD D79E CD E4 03 CMP $03E4 D7A1 90 A2 BCC $D745 D7A3 AD E6 03 LDA $03E6 D7A6 85 E9 STA $E9 D7A8 AD E7 03 LDA $03E7 D7AB 85 EA STA $EA D7AD A2 1B LDX #$1B D7AF 38 SEC D7B0 60 RTS D7B1 A0 00 LDY #$00 ; D7B3 A5 E8 LDA $E8 ; \ D7B5 29 04 AND #$04 ; |- decode 4 words if E8 bit 2 == 0 D7B7 F0 18 BEQ $D7D1 ; / D7B9 A5 B6 LDA $B6 ; get offset for... ? D7BB A0 04 LDY #$04 ; Iterate for four words D7BD 18 CLC ; (C==0 for ADC below) D7BE AA TAX ; (hmm... why wasn't that LDX $B6 again?) D7BF A9 00 LDA #$00 ; \ D7C1 9D 02 02 STA $0202,X ; |_ Zero out carrier-loss bitmap for D7C4 9D 03 02 STA $0203,X ; | word pointed to by $B6 D7C7 8A TXA ; / D7C8 69 04 ADC #$04 ; Point to next carrier loss bitmap D7CA 88 DEY ; \_ Repeat for four words D7CB D0 F1 BNE $D7BE ; / D7CD 85 B6 STA $B6 ; Store final offset D7CF F0 43 BEQ $D814 ; skip down to D814 (always taken) D7D1 A5 EB LDA $EB D7D3 18 CLC D7D4 65 E9 ADC $E9 D7D6 85 98 STA $98 D7D8 A5 EC LDA $EC D7DA 65 EA ADC $EA D7DC 85 99 STA $99 D7DE 20 7B DA JSR $DA7B D7E1 A5 99 LDA $99 D7E3 18 CLC D7E4 69 40 ADC #$40 D7E6 85 97 STA $97 D7E8 A5 98 LDA $98 D7EA 85 96 STA $96 D7EC 2C 25 BE BIT $BE25 D7EF 30 06 BMI $D7F7 D7F1 24 F0 BIT $F0 D7F3 10 02 BPL $D7F7 D7F5 70 39 BVS $D830 D7F7 A5 94 LDA $94 D7F9 91 98 STA ($98),Y D7FB A5 95 LDA $95 D7FD 91 96 STA ($96),Y D7FF A6 B6 LDX $B6 D801 A9 00 LDA #$00 D803 9D 02 02 STA $0202,X D806 9D 03 02 STA $0203,X D809 8A TXA D80A 18 CLC D80B 69 04 ADC #$04 D80D 85 B6 STA $B6 D80F C8 INY D810 C0 04 CPY #$04 D812 D0 CA BNE $D7DE D814 18 CLC D815 A9 04 LDA #$04 D817 65 E9 ADC $E9 D819 85 E9 STA $E9 D81B 90 02 BCC $D81F D81D E6 EA INC $EA D81F A5 B6 LDA $B6 D821 29 7F AND #$7F D823 18 CLC D824 D0 09 BNE $D82F D826 A9 FF LDA #$FF D828 9D 03 02 STA $0203,X D82B 0A ASL A D82C 9D 02 02 STA $0202,X D82F 60 RTS D830 A5 94 LDA $94 D832 D1 98 CMP ($98),Y D834 D0 08 BNE $D83E D836 A5 95 LDA $95 D838 51 96 EOR ($96),Y D83A 29 03 AND #$03 D83C F0 C1 BEQ $D7FF D83E EE 22 BE INC $BE22 D841 10 BC BPL $D7FF D843 20 28 D9 JSR $D928 D846 4E 25 BE LSR $BE25 D849 A9 04 LDA #$04 D84B 24 E8 BIT $E8 D84D D0 22 BNE $D871 D84F AD 21 BE LDA $BE21 D852 D0 46 BNE $D89A D854 A5 EF LDA $EF D856 C9 04 CMP #$04 D858 10 40 BPL $D89A D85A AD 22 BE LDA $BE22 D85D F0 12 BEQ $D871 D85F 4C F2 D4 JMP $D4F2 D862 A9 00 LDA #$00 D864 8D F3 00 STA $00F3 D867 A5 C9 LDA $C9 D869 09 10 ORA #$10 D86B 20 38 D0 JSR $D038 D86E 20 87 D6 JSR $D687 D871 20 A2 D6 JSR $D6A2 D874 B0 13 BCS $D889 D876 A9 00 LDA #$00 D878 8D 24 BE STA $BE24 D87B AD 01 44 LDA $4401 D87E 4A LSR A D87F 90 03 BCC $D884 D881 4C 0A D5 JMP $D50A D884 20 BE D6 JSR $D6BE D887 18 CLC D888 60 RTS D889 2C 25 BE BIT $BE25 D88C 70 5D BVS $D8EB D88E A9 00 LDA #$00 D890 8D 24 BE STA $BE24 D893 20 73 D6 JSR $D673 D896 A2 00 LDX #$00 D898 38 SEC D899 60 RTS D89A 2C 25 BE BIT $BE25 D89D 50 0D BVC $D8AC D89F AE 23 BE LDX $BE23 D8A2 E4 D6 CPX $D6 D8A4 10 7C BPL $D922 D8A6 E8 INX D8A7 8E 23 BE STX $BE23 D8AA D0 31 BNE $D8DD D8AC 24 D7 BIT $D7 D8AE 30 B2 BMI $D862 D8B0 A5 E9 LDA $E9 D8B2 38 SEC D8B3 E9 20 SBC #$20 D8B5 85 E9 STA $E9 D8B7 8D E6 03 STA $03E6 D8BA A5 EA LDA $EA D8BC E9 00 SBC #$00 D8BE 85 EA STA $EA D8C0 8D E7 03 STA $03E7 D8C3 AE 24 BE LDX $BE24 D8C6 E4 D7 CPX $D7 D8C8 10 5B BPL $D925 D8CA E8 INX D8CB 8E 24 BE STX $BE24 D8CE AD F2 03 LDA $03F2 D8D1 8D E4 03 STA $03E4 D8D4 AD F3 03 LDA $03F3 D8D7 8D E5 03 STA $03E5 D8DA 20 09 D7 JSR $D709 D8DD AD E2 03 LDA $03E2 D8E0 85 E5 STA $E5 D8E2 AD E3 03 LDA $03E3 D8E5 85 E6 STA $E6 D8E7 A2 0D LDX #$0D D8E9 38 SEC D8EA 60 RTS D8EB A2 1F LDX #$1F D8ED A9 00 LDA #$00 D8EF 18 CLC D8F0 7D E0 04 ADC $04E0,X D8F3 CA DEX D8F4 10 F9 BPL $D8EF D8F6 AA TAX D8F7 D0 A6 BNE $D89F D8F9 A5 CC LDA $CC D8FB CD E1 04 CMP $04E1 D8FE D0 05 BNE $D905 D900 A5 CB LDA $CB D902 CD E0 04 CMP $04E0 D905 D0 07 BNE $D90E D907 A9 00 LDA #$00 D909 8D 23 BE STA $BE23 D90C F0 85 BEQ $D893 D90E AD E0 04 LDA $04E0 D911 85 CB STA $CB D913 AD E1 04 LDA $04E1 D916 85 CC STA $CC D918 AE 23 BE LDX $BE23 D91B E4 D6 CPX $D6 D91D 30 87 BMI $D8A6 D91F 4C EC D4 JMP $D4EC D922 20 16 D7 JSR $D716 D925 4C EF D4 JMP $D4EF D928 2C 25 BE BIT $BE25 D92B 30 53 BMI $D980 D92D A6 CE LDX $CE D92F D0 4F BNE $D980 D931 A5 CD LDA $CD D933 C9 07 CMP #$07 D935 90 49 BCC $D980 D937 C9 30 CMP #$30 D939 F0 32 BEQ $D96D D93B B0 43 BCS $D980 D93D CA DEX D93E BD 02 3F LDA $3F02,X D941 AA TAX D942 45 F2 EOR $F2 D944 30 19 BMI $D95F D946 E6 F2 INC $F2 D948 A5 F2 LDA $F2 D94A 29 3F AND #$3F D94C C9 07 CMP #$07 D94E 90 1C BCC $D96C D950 C6 F2 DEC $F2 D952 8A TXA D953 4A LSR A D954 45 F2 EOR $F2 D956 0A ASL A D957 10 13 BPL $D96C D959 E6 E1 INC $E1 D95B 8A TXA D95C 4A LSR A D95D 85 F2 STA $F2 D95F A5 F2 LDA $F2 D961 29 40 AND #$40 D963 85 F2 STA $F2 D965 8A TXA D966 29 80 AND #$80 D968 05 F2 ORA $F2 D96A 85 F2 STA $F2 D96C 60 RTS D96D A5 F3 LDA $F3 D96F 4A LSR A D970 4A LSR A D971 86 F3 STX $F3 D973 90 0B BCC $D980 D975 A5 E1 LDA $E1 D977 E9 03 SBC #$03 D979 C9 26 CMP #$26 D97B 90 03 BCC $D980 D97D CE CB 03 DEC $03CB D980 60 RTS ;; Prepare to write block header D981 A9 00 LDA #$00 ; Feed out zeros D983 85 B7 STA $B7 D985 A9 7E LDA #$7E ; \_ Initial pattern in header 0111 1110 D987 85 B8 STA $B8 ; / D989 A9 60 LDA #$60 ; \_ Header count-down D98B 85 C3 STA $C3 ; / D98D A9 E7 LDA #$E7 ; Last pattern in header D98F A0 70 LDY #$70 ; \ D991 84 B5 STY $B5 ; |- Arrange for bitplane shifter to write D993 99 01 02 STA $0201,Y ; / last row of header (sneaky!) D996 C8 INY ; \ D997 C8 INY ; |_ First plane shifted out will be D998 0A ASL A ; | 1110 0111, which is last row of hdr D999 D0 F8 BNE $D993 ; / D99B A9 0E LDA #$0E D99D 85 CF STA $CF D99F A9 02 LDA #$02 ; \_ Send 512 0s .. plenty of time for D9A1 85 C5 STA $C5 ; / hardware to sync up. D9A3 A9 AB LDA #$AB ; \ D9A5 A2 CF LDX #$CF ; |- Set tape handler to CFAB: Write block D9A7 20 EC C1 JSR $C1EC ; / header D9AA 18 CLC D9AB 60 RTS D9AC A5 B6 LDA $B6 D9AE 45 B5 EOR $B5 D9B0 0A ASL A D9B1 0A ASL A D9B2 90 1E BCC $D9D2 D9B4 20 EF D9 JSR $D9EF D9B7 08 PHP D9B8 20 8D D6 JSR $D68D D9BB 28 PLP D9BC 90 14 BCC $D9D2 D9BE 20 A2 D6 JSR $D6A2 D9C1 90 10 BCC $D9D3 D9C3 A5 E8 LDA $E8 D9C5 29 E7 AND #$E7 D9C7 85 E8 STA $E8 D9C9 20 8D D6 JSR $D68D D9CC 20 4E DA JSR $DA4E D9CF A2 00 LDX #$00 D9D1 38 SEC D9D2 60 RTS D9D3 A5 CE LDA $CE D9D5 C5 E3 CMP $E3 D9D7 D0 04 BNE $D9DD D9D9 A5 CD LDA $CD D9DB C5 E2 CMP $E2 D9DD 90 CB BCC $D9AA D9DF A9 40 LDA #$40 D9E1 20 68 D6 JSR $D668 D9E4 20 74 DA JSR $DA74 ; set dbl buf ptr to second half D9E7 A9 14 LDA #$14 D9E9 85 D0 STA $D0 D9EB A2 04 LDX #$04 D9ED 38 SEC D9EE 60 RTS D9EF A0 00 LDY #$00 D9F1 A5 EB LDA $EB D9F3 18 CLC D9F4 65 E9 ADC $E9 D9F6 85 96 STA $96 D9F8 85 98 STA $98 D9FA A5 EC LDA $EC D9FC 65 EA ADC $EA D9FE 85 97 STA $97 DA00 18 CLC DA01 69 40 ADC #$40 DA03 85 99 STA $99 DA05 A9 04 LDA #$04 DA07 24 E8 BIT $E8 DA09 F0 08 BEQ $DA13 DA0B A9 00 LDA #$00 DA0D 85 94 STA $94 DA0F 85 95 STA $95 DA11 F0 0D BEQ $DA20 DA13 B1 96 LDA ($96),Y DA15 85 94 STA $94 DA17 B1 98 LDA ($98),Y DA19 29 03 AND #$03 DA1B 85 95 STA $95 DA1D 20 19 DB JSR $DB19 ; add ECC code to word before writing DA20 A6 B6 LDX $B6 DA22 A5 94 LDA $94 ; \ DA24 9D 00 02 STA $0200,X ; |_ Put ECC-protected word into DA27 A5 95 LDA $95 ; | bitplane buffer DA29 9D 01 02 STA $0201,X ; / DA2C E8 INX DA2D E8 INX DA2E 86 B6 STX $B6 DA30 C8 INY DA31 C0 04 CPY #$04 DA33 D0 D0 BNE $DA05 DA35 18 CLC DA36 A9 04 LDA #$04 DA38 65 E9 ADC $E9 DA3A 85 E9 STA $E9 DA3C 90 02 BCC $DA40 DA3E E6 EA INC $EA DA40 8A TXA DA41 29 3F AND #$3F DA43 18 CLC DA44 D0 07 BNE $DA4D DA46 A5 B6 LDA $B6 DA48 29 7F AND #$7F DA4A 85 B6 STA $B6 DA4C 38 SEC DA4D 60 RTS DA4E A2 00 LDX #$00 DA50 24 C2 BIT $C2 DA52 10 02 BPL $DA56 DA54 A2 02 LDX #$02 DA56 A5 D2 LDA $D2 DA58 95 BE STA $BE,X DA5A A5 D3 LDA $D3 DA5C 95 BF STA $BF,X DA5E A5 B6 LDA $B6 DA60 09 80 ORA #$80 DA62 95 C2 STA $C2,X DA64 60 RTS DA65 AD 02 44 LDA $4402 DA68 4A LSR A DA69 90 08 BCC $DA73 DA6B 20 74 DA JSR $DA74 ; set dbl buf ptr to second half DA6E 68 PLA DA6F 68 PLA DA70 A6 E4 LDX $E4 DA72 38 SEC DA73 60 RTS ;;============================================================================= ;; ;; Set double-buffer pointer for macro-level tape state machine to ;; point to second half of the buffer ;;----------------------------------------------------------------------------- DA74 A5 B6 LDA $B6 DA76 09 80 ORA #$80 DA78 85 B6 STA $B6 DA7A 60 RTS ;;============================================================================= ;; Error-correct encoded tape data. ;;----------------------------------------------------------------------------- DA7B A6 B6 LDX $B6 ; get index DA7D A5 F7 LDA $F7 ; Get ? DA7F 5D 00 02 EOR $0200,X ; Merge with low half of 15-bit word DA82 85 94 STA $94 ; save lower half to $94 DA84 85 96 STA $96 ; save lower half to $96 DA86 BD 01 02 LDA $0201,X ; Get upper half of 15-bit word DA89 29 7F AND #$7F ; Make sure it's 15 bits DA8B 85 95 STA $95 ; save upper half to $95 DA8D 85 97 STA $97 ; save upper half to $97 DA8F 29 03 AND #$03 ; Keep only bits 8, 9 of word DA91 85 91 STA $91 ; save to $91 DA93 20 F6 DA JSR $DAF6 ; Error-correct 10-bit word + 5-bit parity DA96 85 F4 STA $F4 ; Store A (syndrome) to $F4 DA98 AA TAX ; \__ Use A to index into table at $DBA1 DA99 BD A1 DB LDA $DBA1,X ; / (this is the "number of errors" table) DA9C 85 F5 STA $F5 ; store number of errors to $F5 DA9E F0 51 BEQ $DAF1 ; If it came up zero, all done, so return? ; there was an error or incomplete word? DAA0 A6 B6 LDX $B6 ;\ DAA2 BD 02 02 LDA $0202,X ; | DAA5 45 94 EOR $94 ; |__ Try toggling bits in the places DAA7 85 94 STA $94 ; | where we had loss of carrier. DAA9 BD 03 02 LDA $0203,X ; | DAAC 45 95 EOR $95 ; | DAAE 85 95 STA $95 ;/ DAB0 29 03 AND #$03 ; keep only bits 8, 9 of word DAB2 85 91 STA $91 ; save to $91 DAB4 20 F6 DA JSR $DAF6 ; Decode merged word DAB7 85 F6 STA $F6 ; store new syndrome to $F6 DAB9 AA TAX ; DABA BD A1 DB LDA $DBA1,X ; how many errors according to syndrome? DABD F0 32 BEQ $DAF1 ; if it came up zero, all done, so return? ; error correction. DABF C5 F5 CMP $F5 ; fewer errors in second version? DAC1 30 0E BMI $DAD1 ; Yes: Keep second version. DAC3 A5 F4 LDA $F4 ;\ DAC5 85 F6 STA $F6 ; | DAC7 A5 96 LDA $96 ; | DAC9 85 94 STA $94 ; |-- No: copy original to working buffer DACB A5 97 LDA $97 ; | DACD 85 95 STA $95 ; | DACF A5 F5 LDA $F5 ;/ DAD1 C9 02 CMP #$02 ; can we fix it? DAD3 10 1D BPL $DAF2 ; no, incr unfixed error count and leave? DAD5 EE 20 BE INC $BE20 ; yes, incr corrected error count DAD8 A6 F6 LDX $F6 ; get syndrome from $F6 DADA A5 94 LDA $94 ; Get data for lower half to fix DADC 5D 81 DB EOR $DB81,X ; Fix the broken bits in lower half DADF 85 94 STA $94 ; Store it. DAE1 A5 95 LDA $95 ; get upper half DAE3 E0 19 CPX #$19 ;\ DAE5 D0 02 BNE $DAE9 ; |-- if syndrome == 0x19, then toggle bit 9. DAE7 49 02 EOR #$02 ;/ DAE9 E0 1C CPX #$1C ;\ DAEB D0 02 BNE $DAEF ; |-- if syndrome == 0x1C, then toggle bit 10. DAED 49 01 EOR #$01 ;/ DAEF 85 95 STA $95 ; store upper half. DAF1 60 RTS DAF2 EE 21 BE INC $BE21 ; increment tape unfixable error count? DAF5 60 RTS ;;============================================================================= ;; Check the checksum of a 15-bit number and return a syndrome ;;----------------------------------------------------------------------------- ; C 7 6 5 4 3 2 1 0 DAF6 A5 95 LDA $95 ; x - WE WD WC WB WA W9 W8 DAF8 4A LSR A ; x - - WE WD WC WB WA W9 DAF9 4A LSR A ; x - - - WE WD WC WB WA DAFA 85 90 STA $90 ; x - - - WE WD WC WB WA DAFC A5 94 LDA $94 ; x W7 W6 W5 W4 W3 W2 W1 W0 DAFE 29 1F AND #$1F ;\ x - - - W4 W3 W2 W1 W0 DB00 AA TAX ; |- Look up ECC code for lower 5 bits DB01 BD 41 DB LDA $DB41,X ;/ DB04 45 90 EOR $90 ; add it to bits 12 thru 15 DB06 85 90 STA $90 ; and store it in $90 temporarily ; C 7 6 5 4 3 2 1 0 DB08 A5 94 LDA $94 ; x W7 W6 W5 W4 W3 W2 W1 W0 DB0A 29 E0 AND #$E0 ; x W7 W6 W5 - - - - - DB0C 0A ASL A ; W7 W6 W5 - - - - - - DB0D 05 91 ORA $91 ; W7 W6 W5 - - - - W9 W8 DB0F 2A ROL A ; W6 W5 - - - - W9 W8 W7 DB10 2A ROL A ; W5 - - - - W9 W8 W7 W6 DB11 2A ROL A ; - - - - W9 W8 W7 W6 W5 DB12 AA TAX ; \ DB13 BD 61 DB LDA $DB61,X ; |- Look up ECC code for upper 5 bits DB16 45 90 EOR $90 ; / DB18 60 RTS ; and return ;;============================================================================= ;;============================================================================= ;; Generate the checksum for a 10-bit number, returning a 15-bit number. ;;----------------------------------------------------------------------------- DB19 A5 94 LDA $94 ; \ DB1B 29 1F AND #$1F ; | DB1D AA TAX ; |-- Bits 0..4 into X, DB1E 45 94 EOR $94 ; | Bits 5..7 into $91 DB20 85 91 STA $91 ; / DB22 BD 41 DB LDA $DB41,X ; Get checksum for bits 0..4 into A DB25 85 90 STA $90 ; Store initial cksum to $90 ; C 7 6 5 4 3 2 1 0 DB27 A5 95 LDA $95 ; 0 0 0 0 0 0 0 W9 W8 DB29 4A LSR A ; W8 0 0 0 0 0 0 0 W9 DB2A 05 91 ORA $91 ; W8 W7 W6 W5 0 0 0 0 W9 DB2C 2A ROL A ; W7 W6 W5 0 0 0 0 W9 W8 DB2D 2A ROL A ; W6 W5 0 0 0 0 W9 W8 W7 DB2E 2A ROL A ; W5 0 0 0 0 W9 W8 W7 W6 DB2F 2A ROL A ; 0 0 0 0 W9 W8 W7 W6 W5 DB30 AA TAX DB31 BD 61 DB LDA $DB61,X ; Get checksum for bits 5..9 into A ; C 7 6 5 4 3 2 1 0 DB34 45 90 EOR $90 ; Merge w/ initial cksum into A ; 0 0 0 0 WE WD WC WB WA DB36 0A ASL A ; 0 0 0 WE WD WC WB WA 0 DB37 0A ASL A ; 0 0 WE WD WC WB WA 0 0 DB38 05 95 ORA $95 ; 0 0 WE WD WC WB WA W9 W8 DB3A 18 CLC ; DB3B 26 94 ROL $94 ; shift lower-half left, bring in 0 DB3D 2A ROL A ; 0 WE WD WC WB WA W9 W8 W7 DB3E 85 95 STA $95 ; store upper half to $95 DB40 60 RTS ; WE thru W0 are in upper 15 bits of $94-$95 ;;============================================================================= ; Data from $DB41 to $DBC0 (128 bytes) DB41 .byte $00, $0D, $1A, $17, $15, $18, $0F, $02 DB49 .byte $0B, $06, $11, $1C, $1E, $13, $04, $09 DB51 .byte $16, $1B, $0C, $01, $03, $0E, $19, $14 DB59 .byte $1D, $10, $07, $0A, $08, $05, $12, $1F DB61 .byte $00, $13, $07, $14, $0E, $1D, $09, $1A DB69 .byte $1C, $0F, $1B, $08, $12, $01, $15, $06 DB71 .byte $19, $0A, $1E, $0D, $17, $04, $10, $03 DB79 .byte $05, $16, $02, $11, $0B, $18, $0C, $1F DB81 .byte $00, $00, $00, $00, $00, $00, $00, $40 DB89 .byte $00, $00, $00, $08, $00, $01, $80, $00 DB91 .byte $00, $00, $00, $20, $00, $04, $10, $00 DB99 .byte $00, $00, $02, $00, $00, $00, $00, $00 DBA1 .byte $00, $01, $01, $02, $01, $02, $02, $01 DBA9 .byte $01, $02, $02, $01, $02, $01, $01, $02 DBB1 .byte $01, $02, $02, $01, $02, $01, $01, $02 DBB9 .byte $02, $01, $01, $02, $01, $02, $02, $02 ;;============================================================================= ;; Initialize a soft-vector table of some sort: ;; (actual entry point is at $DBCB) ;; ;; $0400 - $0400+X-1 become repeating sequence: ;; ;; 4C 71 C0 JMP $C071 ;; BD 44 03 LDA $0344,X ;; ;; Suspect LDA is just filler code. ;; ;; Once $0400... is initialized: ;; -- Set $0432 - $0434 to JMP $C0D3 ;; -- Set $042D - $0431 to INX ($E8). ;; -- Set $FA - $FD to self-modifying code "STA $xxxx; RTS" ;; -- Point vector at $F8 to $0400 ;; ;;----------------------------------------------------------------------------- DBC1 B9 0B C1 LDA $C10B,Y ; \ DBC4 9D 00 04 STA $0400,X ; | DBC7 CA DEX ; | DBC8 88 DEY ; |__ Copy a repeating pattern of 6 bytes DBC9 10 F6 BPL $DBC1 ; | from $C10B to $0400...$0400+X-1 ;; entry point ; | JMP $C071/LDA $0344,X DBCB A0 05 LDY #$05 ; | DBCD CA DEX ; | DBCE 10 F1 BPL $DBC1 ; / DBD0 8D 32 04 STA $0432 ; \ (A holds JMP opcode) DBD3 A9 D3 LDA #$D3 ; | DBD5 8D 33 04 STA $0433 ; |-- $0432-$0434 becomes JMP $C0D3 DBD8 A9 C0 LDA #$C0 ; | DBDA 8D 34 04 STA $0434 ; / DBDD A9 E8 LDA #$E8 ; \ DBDF 99 2C 04 STA $042C,Y ; |__ Store #$E8 over $042D .. $0431 DBE2 88 DEY ; | $E8 == INX opcode DBE3 D0 FA BNE $DBDF ; / DBE5 A9 8D LDA #$8D ; \ DBE7 85 FA STA $FA ; |__ Write self-modifying code segment DBE9 A9 60 LDA #$60 ; | "STA $xxxx; RTS" to $FA..$FD. DBEB 85 FD STA $FD ; / Address in $FB/$FC DBED A9 00 LDA #$00 ; \ DBEF 85 F8 STA $F8 ; |__ Point ($F8) at $0400 to start DBF1 A9 04 LDA #$04 ; | DBF3 85 F9 STA $F9 ; / DBF5 A9 02 LDA #$02 ; Initial argument to $DC21 routine DBF7 8D D2 03 STA $03D2 ; Pass argument of "2" to $DC21 routine below DBFA B9 B5 DC LDA $DCB5,Y ; \ DBFD 85 94 STA $94 ; |__ Get jump vector from jump table DBFF B9 B6 DC LDA $DCB6,Y ; | DC02 85 95 STA $95 ; / DC04 20 73 DC JSR $DC73 ; Jump to table ptr. (Initializes something?) DC07 D0 11 BNE $DC1A ; Taken on first iter, not taken subsequently DC09 B9 E9 DC LDA $DCE9,Y ; \ DC0C 85 94 STA $94 ; |__ Get some other vector. DC0E B9 EA DC LDA $DCEA,Y ; | DC11 85 95 STA $95 ; / DC13 98 TYA ; \ DC14 48 PHA ; / Save Y DC15 20 21 DC JSR $DC21 ; ?? DC18 68 PLA ; \ DC19 A8 TAY ; / Restore Y DC1A C8 INY ; \ DC1B C8 INY ; |__ Call all four jump table entries in DC1C C0 08 CPY #$08 ; | turn. DC1E D0 DA BNE $DBFA ; / DC20 60 RTS ;;============================================================================= ;;============================================================================= ;; ?? ;;----------------------------------------------------------------------------- DC21 AD D2 03 LDA $03D2 ; Load argument from above DC24 20 63 C3 JSR $C363 ; Copy 12 bytes from lookup table to $340+12*A DC27 20 81 DC JSR $DC81 ; ? DC2A B1 94 LDA ($94),Y ; Get byte 12 from table DC2C 48 PHA ; Save it DC2D 98 TYA ; A == 12 DC2E 38 SEC ; \ DC2F 65 94 ADC $94 ; | DC31 85 94 STA $94 ; |__ Add 13 to vector at ($94) DC33 A5 95 LDA $95 ; | DC35 69 00 ADC #$00 ; | DC37 85 95 STA $95 ; / DC39 68 PLA ; \ DC3A A8 TAY ; / Recall byte 12 from table into Y DC3B AD D2 03 LDA $03D2 ; \__ Save argument from $03D2 DC3E 99 CC 03 STA $03CC,Y ; / into location indexed by table byte 12 DC41 EE D2 03 INC $03D2 ; Increment argument in $03D2 DC44 BD 41 03 LDA $0341,X ; \ ? DC47 29 08 AND #$08 ; |-- Return if magic bit isn't set? DC49 F0 49 BEQ $DC94 ; / DC4B A0 00 LDY #$00 ; \ DC4D B1 94 LDA ($94),Y ; | DC4F 91 F8 STA ($F8),Y ; |__ Copy 6 more bytes from table to ($F8) DC51 C8 INY ; | DC52 C0 06 CPY #$06 ; | DC54 D0 F7 BNE $DC4D ; / DC56 A9 2E LDA #$2E ; \ DC58 E5 F8 SBC $F8 ; |__ Store ?? at "($F8), 6". DC5A ED D2 03 SBC $03D2 ; | DC5D 91 F8 STA ($F8),Y ; / DC5F A5 F8 LDA $F8 ; \ DC61 69 06 ADC #$06 ; |-- Advance ptr at ($F8) by 6 DC63 85 F8 STA $F8 ; / DC65 18 CLC ; \ DC66 A9 06 LDA #$06 ; | DC68 65 94 ADC $94 ; |__ Advance table ptr at ($94) by 6 DC6A 85 94 STA $94 ; | DC6C 90 02 BCC $DC70 ; | DC6E E6 95 INC $95 ; / DC70 20 76 DC JSR $DC76 ; Copy 16-bits from $0346+X to $FB/$FC ;fallthru ; Calls to either JMP DDCD or DDC1 ;;============================================================================= ;; Jump to jump vector in ($0094) ;;----------------------------------------------------------------------------- DC73 6C 94 00 JMP ($0094) ; Jump to jump vector in ($94) ;;============================================================================= ;;============================================================================= ;; Set self-modifying code @ $FA ("STA $xxxx; RTS") to pointer from $346,X ;;----------------------------------------------------------------------------- DC76 BD 46 03 LDA $0346,X ; \ DC79 85 FB STA $FB ; |__ Set 16 bit address that's arg to DC7B BD 47 03 LDA $0347,X ; | STA instr @ $FA from $346,X DC7E 85 FC STA $FC ; / DC80 60 RTS ; return. ;;============================================================================= ;;============================================================================= ;; Initialize a FIFO-managed driver ;; Driver record offset in X. ;;----------------------------------------------------------------------------- DC81 BD 41 03 LDA $0341,X ; Get channel flags DC84 4A LSR A ; \_ bit 0 indicates whether there's xmit DC85 90 03 BCC $DC8A ; / associated with this driver DC87 20 95 DC JSR $DC95 ; initialize xmit FIFO DC8A 4A LSR A ; \_ bit 1 indicates whether there's recv DC8B 90 07 BCC $DC94 ; / associated with this driver DC8D E8 INX DC8E E8 INX DC8F 20 95 DC JSR $DC95 ; initialize recv FIFO DC92 CA DEX DC93 CA DEX DC94 60 RTS ;;============================================================================= ;;============================================================================= ;; Initialize FIFO $0342,X to a size pointed to by ($94),Y. ;;----------------------------------------------------------------------------- DC95 48 PHA DC96 B1 94 LDA ($94),Y DC98 C8 INY DC99 84 90 STY $90 DC9B BC 42 03 LDY $0342,X DC9E 84 98 STY $98 DCA0 BC 43 03 LDY $0343,X DCA3 84 99 STY $99 DCA5 A0 02 LDY #$02 DCA7 91 98 STA ($98),Y DCA9 88 DEY DCAA A9 03 LDA #$03 DCAC 91 98 STA ($98),Y DCAE 88 DEY DCAF 91 98 STA ($98),Y DCB1 A4 90 LDY $90 DCB3 68 PLA DCB4 60 RTS ;;============================================================================= ; Data from $DCB5 to $DCBC (8 bytes) JUMP TABLE DCB5 .byte $BD, $DC ; DCBD DCB7 .byte $C8, $DC ; DCC8 DCB9 .byte $D3, $DC ; DCD3 DCBB .byte $DE, $DC ; DCDE DCBD A9 00 LDA #$00 DCBF 8D FE B7 STA $B7FE DCC2 AD FE B7 LDA $B7FE DCC5 29 E0 AND #$E0 DCC7 60 RTS DCC8 A9 03 LDA #$03 DCCA 8D FC B7 STA $B7FC DCCD A9 F3 LDA #$F3 DCCF 2D FC B7 AND $B7FC DCD2 60 RTS DCD3 A9 03 LDA #$03 DCD5 8D FA B7 STA $B7FA DCD8 A9 F3 LDA #$F3 DCDA 2D FA B7 AND $B7FA DCDD 60 RTS DCDE A9 03 LDA #$03 DCE0 8D F8 B7 STA $B7F8 DCE3 A9 F3 LDA #$F3 DCE5 2D F8 B7 AND $B7F8 DCE8 60 RTS ; Data from $DCE9 to $DD04 (28 bytes) ; Data / code state machine crap. DCE9 .byte $F1, $DC ; DCF1 DCEB .byte $08, $DD ; DD08 DCED .byte $20, $DD ; DD20 DCEF .byte $38, $DD ; DD38 DCF1 .byte $00 ; BRK DCF2 .byte $0A ; ASL A DCF3 .byte $00 ; BRK DCF4 .byte $00 ; BRK DCF5 .byte $60 ; RTS DCF6 .byte $BE, $FE, $B7 ; LDX $B7FE, Y DCF9 .byte $65, $DD ; ADC $DD DCFB .byte $00 ; BRK DCFC .byte $00 ; BRK DCFD .byte $08 ; PHP DCFE .byte $00 ; BRK DCFF .byte $AD, $FE, $B7 ; LDA $B7FE DD02 .byte $29, $80 ; AND #$80 DD04 .byte $D0 ; BNE ...? DD05 4C CD DD JMP $DDCD ; Data from $DD08 to $DD1C (21 bytes) DD08 .byte $95, $0B ; STA $0B,X DD0A .byte $A0, $BE ; LDY #$BE DD0C .byte $E0, $BE ; CPX #$BE DD0E .byte $FC, $B7, $50, $DD ; ........P. DD12 .byte $00, $00, $08, $08, $01, $AD, $FC, $B7, $29, $80 ; ........). DD1C .byte $D0 ; . DD1D 4C C1 DD JMP $DDC1 ; Data from $DD20 to $DD34 (21 bytes) DD20 .byte $95, $0B, $20, $BF, $60, $BF, $FA, $B7, $50, $DD ; .. .`...P. DD2A .byte $00, $00, $08, $08, $02, $AD, $FA, $B7, $29, $80 ; ........). DD34 .byte $D0 ; . DD35 4C C1 DD JMP $DDC1 ; Data from $DD38 to $DD4C (21 bytes) DD38 .byte $95, $0B, $A0, $BF, $E0, $BF, $F8, $B7, $50, $DD ; ........P. DD42 .byte $00, $00, $08, $08, $03, $AD, $F8, $B7, $29, $80 ; ........). DD4C .byte $D0 ; . DD4D 4C C1 DD JMP $DDC1 ; This jump table appears reachable from the code unpacked above (?) DD50 4C 71 DD JMP $DD71 DD53 4C 92 DD JMP $DD92 DD56 4C 9D DD JMP $DD9D DD59 4C A7 DD JMP $DDA7 DD5C 4C AE DD JMP $DDAE DD5F 4C B5 DD JMP $DDB5 DD62 4C BA DD JMP $DDBA DD65 4C 8F DD JMP $DD8F DD68 4C 92 DD JMP $DD92 DD6B 4C 9D DD JMP $DD9D DD6E 4C A7 DD JMP $DDA7 DD71 BD 40 03 LDA $0340,X ; DD74 10 19 BPL $DD8F ; DD76 A0 00 LDY #$00 ; DD78 B1 FB LDA ($FB),Y ; DD7A 6A ROR A ; DD7B 90 0F BCC $DD8C ; DD7D 29 10 AND #$10 ; DD7F F0 0F BEQ $DD90 ; DD81 A0 01 LDY #$01 ; DD83 B1 FB LDA ($FB),Y ; DD85 A9 40 LDA #$40 ; DD87 85 90 STA $90 ; DD89 24 90 BIT $90 ; DD8B 60 RTS ; DD8C 6A ROR A ; DD8D 90 F6 BCC $DD85 ; DD8F 18 CLC ; DD90 B8 CLV ; DD91 60 RTS ; DD92 BD 40 03 LDA $0340,X ; \ DD95 29 DF AND #$DF ; |-- Clear bit 5 of $0340,X DD97 9D 40 03 STA $0340,X ; / DD9A 4C FA 00 JMP $00FA ; Call self-modifying code at $FA w/ value DD9D A5 90 LDA $90 ; DD9F E6 FB INC $FB ; DDA1 20 FA 00 JSR $00FA ; DDA4 C6 FB DEC $FB ; DDA6 60 RTS DDA7 BD 40 03 LDA $0340,X ; DDAA 09 20 ORA #$20 ; DDAC D0 E9 BNE $DD97 ; DDAE BD 40 03 LDA $0340,X ; DDB1 29 7F AND #$7F ; DDB3 D0 E2 BNE $DD97 ; DDB5 A0 01 LDY #$01 ; DDB7 B1 FB LDA ($FB),Y ; DDB9 60 RTS DDBA BD 40 03 LDA $0340,X ; DDBD 09 80 ORA #$80 ; DDBF D0 D6 BNE $DD97 ; DDC1 A0 00 LDY #$00 ; DDC3 A9 03 LDA #$03 ; DDC5 91 FB STA ($FB),Y ; DDC7 BD 40 03 LDA $0340,X ; DDCA 91 FB STA ($FB),Y ; DDCC 60 RTS DDCD A9 00 LDA #$00 ; DDCF 8D FF B7 STA $B7FF ; DDD2 AD FE B7 LDA $B7FE ; DDD5 29 10 AND #$10 ; DDD7 D0 0A BNE $DDE3 ; DDD9 A9 1E LDA #$1E ; DDDB 8D FF B7 STA $B7FF ; DDDE A9 0D LDA #$0D ; DDE0 8D FF B7 STA $B7FF ; DDE3 60 RTS ; Data from $DDE4 to $DE23 (64 bytes) ; shh... this is top secret data here. don't tell anyone. DDE4 .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ; .......... DDEE .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ; .......... DDF8 .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ; .......... DE02 .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ; .......... DE0C .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ; .......... DE16 .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ; .......... DE20 .byte $FF, $FF, $FF, $FF ; .... DE24 BA TSX DE25 BD 03 01 LDA $0103,X DE28 38 SEC DE29 69 00 ADC #$00 DE2B 85 94 STA $94 DE2D 9D 03 01 STA $0103,X DE30 BD 04 01 LDA $0104,X DE33 69 00 ADC #$00 DE35 85 95 STA $95 DE37 9D 04 01 STA $0104,X DE3A A2 00 LDX #$00 DE3C A1 94 LDA ($94,X) DE3E 60 RTS DE3F 20 48 DE JSR $DE48 DE42 20 24 DE JSR $DE24 DE45 D0 F8 BNE $DE3F DE47 60 RTS DE48 48 PHA DE49 AD 36 04 LDA $0436 DE4C D0 FB BNE $DE49 DE4E 68 PLA DE4F 8D 36 04 STA $0436 DE52 60 RTS DE53 85 90 STA $90 DE55 8A TXA DE56 48 PHA DE57 98 TYA DE58 48 PHA DE59 A6 90 LDX $90 DE5B AC CC 03 LDY $03CC DE5E D0 0C BNE $DE6C DE60 AC CF 03 LDY $03CF DE63 D0 12 BNE $DE77 DE65 68 PLA DE66 A8 TAY DE67 68 PLA DE68 AA TAX DE69 A5 90 LDA $90 DE6B 60 RTS DE6C AD FE B7 LDA $B7FE DE6F 29 10 AND #$10 DE71 D0 04 BNE $DE77 DE73 E0 0D CPX #$0D DE75 F0 EE BEQ $DE65 DE77 8A TXA DE78 20 8B DF JSR $DF8B DE7B B0 FB BCS $DE78 DE7D 90 E6 BCC $DE65 DE7F AD 35 04 LDA $0435 DE82 F0 07 BEQ $DE8B DE84 48 PHA DE85 A9 00 LDA #$00 DE87 8D 35 04 STA $0435 DE8A 68 PLA DE8B 60 RTS DE8C 8D 02 03 STA $0302 ; \ DE8F 8E 03 03 STX $0303 ; |-- Save A, X, Y DE92 8C 04 03 STY $0304 ; / DE95 20 24 DE JSR $DE24 ; Pluck something from the stack into 'A' DE98 8D 01 03 STA $0301 ; Store it to semaphore. DE9B AD 01 03 LDA $0301 ; \___ spin until CP-1600 lets us out? DE9E D0 FB BNE $DE9B ; / DEA0 60 RTS ;;============================================================================= ;; Get a DECLE from a FIFO buffer at ($98). ;; ;; Offset 0: Head of FIFO (where data comes out) ;; Offset 1: Tail of FIFO (where new data goes in) ;; Offset 2: End of FIFO offset. ;; Offset 3 .. End: Data. ;; ;; When the CP-1600 has something to send to the 6502, it will FIFO it up ;; in a FIFO buffer of this format. This function will drain one decle ;; from such a FIFO into locations $90/$91, with the lower 8 bits going ;; to location $90 and the upper two bits (if any) going to $91. If no ;; data is ready, location $90 is set to #$00. ;; ;; Another FIFO is used for queuing keystrokes from the keyboard. ;;----------------------------------------------------------------------------- DEA1 A0 00 LDY #$00 ; \ DEA3 84 91 STY $91 ; / Default upper half to $00 DEA5 B1 98 LDA ($98),Y ; Get head of FIFO DEA7 C8 INY ; DEA8 D1 98 CMP ($98),Y ; Is head == tail? DEAA F0 2A BEQ $DED6 ; Yes: Zero out location $90 and return. DEAC 18 CLC ; DEAD 69 01 ADC #$01 ; Ok, increment the head pointer. DEAF C8 INY ; DEB0 D1 98 CMP ($98),Y ; Is head > end_of_buffer? DEB2 D0 03 BNE $DEB7 ; DEB4 A9 03 LDA #$03 ; \ Yes: Wraparound to beginning of buffer. DEB6 18 CLC ; / DEB7 A8 TAY ; DEB8 B1 98 LDA ($98),Y ; Load value from head of FIFO. DEBA 85 90 STA $90 ; Store it to $90 (low half) DEBC A5 98 LDA $98 ; \ Add #$4000 from address in $98/$99 DEBE 85 96 STA $96 ; | into $96/$97. If it gets > $7FFF DEC0 A5 99 LDA $99 ; |__ don't store high half and exit early. DEC2 69 40 ADC #$40 ; | (We're building 10-bit value from DEC4 30 08 BMI $DECE ; | low half of memory if we don't exit DEC6 85 97 STA $97 ; / early from here, that's why.) DEC8 B1 96 LDA ($96),Y ; Get bits for upper half DECA 29 03 AND #$03 ; Mask away the noise. DECC 85 91 STA $91 ; Store upper two bits to $91 DECE 98 TYA ; Remember our index in 'A'. DECF A0 00 LDY #$00 ; DED1 91 98 STA ($98),Y ; Store it out the new FIFO head. DED3 A5 90 LDA $90 ; Get low byte of what we read into 'A'. DED5 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; Decrement Y and store in $90 ;;----------------------------------------------------------------------------- DED6 88 DEY ; Decrement Y DED7 98 TYA ; Put it in the accumulator DED8 85 90 STA $90 ; Store to location $90 DEDA 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; Put a DECLE in 'A', $91 into a FIFO pointed to by ($98). ;;----------------------------------------------------------------------------- DEDB 85 90 STA $90 DEDD 4C E6 DE JMP $DEE6 ;;============================================================================= ;; Put a BYTE in 'A' into a FIFO pointed to by ($98). ;;----------------------------------------------------------------------------- DEE0 85 90 STA $90 ;fallthru ;;============================================================================= ;; Put a BYTE in $90 into a FIFO pointed to by ($98). ;;----------------------------------------------------------------------------- DEE2 A9 00 LDA #$00 DEE4 85 91 STA $91 ;fallthru ;;============================================================================= ;; Put a DECLE in $90/$91 into a FIFO pointed to by ($98). ;;----------------------------------------------------------------------------- DEE6 A0 01 LDY #$01 DEE8 B1 98 LDA ($98),Y ; Get the tail pointer of the FIFO DEEA 18 CLC DEEB 69 01 ADC #$01 ; Increment it. DEED C8 INY ; \ DEEE D1 98 CMP ($98),Y ; |__ Wrap around end-of-FIFO DEF0 D0 02 BNE $DEF4 ; | if necessary. DEF2 A9 03 LDA #$03 ; / DEF4 A0 00 LDY #$00 ; Does tail == head? DEF6 D1 98 CMP ($98),Y ; DEF8 F0 20 BEQ $DF1A ; Yes: FIFO is full, set carry and leave. DEFA A8 TAY ; DEFB A5 90 LDA $90 ; Get lower 8 bits of value to enqueue. DEFD 91 98 STA ($98),Y ; Store it to the FIFO. DEFF A5 98 LDA $98 ; \ DF01 85 96 STA $96 ; | Add $4000 to the FIFO address so tha DF03 A5 99 LDA $99 ; | we can enqueue the upper two bits. DF05 18 CLC ; |-- If the resulting address > $7FFF, then DF06 69 40 ADC #$40 ; | don't enqueue the upper half, as it's DF08 30 06 BMI $DF10 ; | not in 10-bit memory. DF0A 85 97 STA $97 ; / DF0C A5 91 LDA $91 ; Get the upper 2 bits of value to enqueue DF0E 91 96 STA ($96),Y ; Store it to the upper two bits of 10-bit RAM DF10 98 TYA ; \ DF11 A0 01 LDY #$01 ; |-- Store the new tail pointer. DF13 91 98 STA ($98),Y ; / DF15 88 DEY ; Clear Y. DF16 A5 90 LDA $90 ; Restore the byte that we just enqueued. DF18 18 CLC ; Clear carry to report success. DF19 60 RTS DF1A A5 90 LDA $90 ; Restore byte that we didn't enqueue. DF1C 38 SEC ; Set Carry to report failure-to-enqueue. DF1D 60 RTS ; Return. ;;============================================================================= ;;============================================================================= ;; Check to see if a FIFO is full. ;;----------------------------------------------------------------------------- DF1E A0 01 LDY #$01 DF20 B1 98 LDA ($98),Y ; Get the tail of FIFO. DF22 18 CLC DF23 69 01 ADC #$01 ; Add 1 to the tail. DF25 C8 INY DF26 D1 98 CMP ($98),Y ; \ DF28 D0 02 BNE $DF2C ; |-- Wrap around if necessary. DF2A A9 03 LDA #$03 ; / DF2C A0 00 LDY #$00 ; DF2E D1 98 CMP ($98),Y ; Compare new tail to head. DF30 F0 01 BEQ $DF33 ; If equal, FIFO full: set carry and return. DF32 18 CLC ; Else, clear carry, FIFO not full. DF33 60 RTS ;;============================================================================= ;;============================================================================= ;; Check to see if a FIFO is empty. ;;----------------------------------------------------------------------------- DF34 A0 01 LDY #$01 DF36 B1 98 LDA ($98),Y ; Get theo tail of FIFO DF38 88 DEY ; DF39 D1 98 CMP ($98),Y ; Compare to the head of the FIFO DF3B F0 F6 BEQ $DF33 ; If equal, FIFO empty: set carry and return DF3D 18 CLC ; Else, clear carry, FIFO not full. DF3E 60 RTS ;;============================================================================= ;;============================================================================= ;; Get DECLE from FIFO, recording previous fullness in V bit. ;;----------------------------------------------------------------------------- DF3F 20 1E DF JSR $DF1E ; Is FIFO full? DF42 B0 02 BCS $DF46 ; Yes: Clear location $92 DF44 A0 40 LDY #$40 ; No: Set location $92 to #$40. DF46 84 92 STY $92 ; DF48 20 A1 DE JSR $DEA1 ; Get decle from FIFO. DF4B 24 92 BIT $92 ; Set "V" bit if FIFO was previously not full DF4D 60 RTS ;;============================================================================= ;;============================================================================= ;; Put BYTE into FIFO, recording previous empty status in V bit. ;;----------------------------------------------------------------------------- DF4E 85 90 STA $90 ; Remember byte to enqueue in FIFO. DF50 20 34 DF JSR $DF34 ; Is FIFO empty? DF53 B0 02 BCS $DF57 ; Yes: Clear location $92 DF55 A0 40 LDY #$40 ; No: Set location $92 to #$40 DF57 84 92 STY $92 ; DF59 20 E2 DE JSR $DEE2 ; Put byte into FIFO. DF5C 24 92 BIT $92 ; Set "V" bit if FIFO was previously not empty DF5E 60 RTS ; ;;============================================================================= ;;============================================================================= ;; Some sort of "Get from numbered FIFO" ;;----------------------------------------------------------------------------- DF5F C0 02 CPY #$02 ; DF61 30 B9 BMI $DF1C ; If Y < 2, set carry and return. DF63 98 TYA ; DF64 48 PHA ; DF65 20 EE DF JSR $DFEE ; X = A*12. DF68 BD 42 03 LDA $0342,X ; Point ($98) at some FIFO? (Which one?) DF6B 85 98 STA $98 ; DF6D BD 43 03 LDA $0343,X ; DF70 85 99 STA $99 ; DF72 20 B5 DF JSR $DFB5 ; Set $4042 to 1 (why?) DF75 20 3F DF JSR $DF3F ; Get DECLE from FIFO DF78 70 09 BVS $DF83 ; Was FIFO full? No: Skip to $DF83. DF7A 20 76 DC JSR $DC76 ; Set ($FB) to point to $346,X. (X==12*A) DF7D A9 12 LDA #$12 ; \___ JSR ($348,X),12 DF7F 20 2D C1 JSR $C12D ; / DF82 18 CLC ; DF83 20 B8 DF JSR $DFB8 ; Set $4042 to 0 (why?) DF86 68 PLA ; DF87 A8 TAY ; Restore Y DF88 A5 90 LDA $90 ; Return byte read from FIFO. DF8A 60 RTS ;;============================================================================= ;;============================================================================= ;; Some sort of "Put to numbered FIFO" ;;----------------------------------------------------------------------------- DF8B C0 02 CPY #$02 ; DF8D 30 8D BMI $DF1C ; If Y < 2, set carry and return DF8F 85 91 STA $91 ; DF91 98 TYA ; DF92 48 PHA ; DF93 20 A7 DF JSR $DFA7 ; DF96 20 B5 DF JSR $DFB5 ; Set $4042 to 1 DF99 A5 91 LDA $91 ; DF9B 20 4E DF JSR $DF4E ; Put BYTE into FIFO. DF9E 70 E3 BVS $DF83 ; If FIFO wasn't empty, clear $4042 and leave DFA0 20 76 DC JSR $DC76 ; \ DFA3 A9 09 LDA #$09 ; |-- Yes: Do something? DFA5 D0 D8 BNE $DF7F ; / ALWAYS TAKEN?? DFA7 20 EE DF JSR $DFEE ; X = A * 12 DFAA BD 44 03 LDA $0344,X ; \ DFAD 85 98 STA $98 ; |__ Get FIFO address from $344 table DFAF BD 45 03 LDA $0345,X ; | DFB2 85 99 STA $99 ; / DFB4 60 RTS ; ;;============================================================================= ;;============================================================================= ;; DFB5: Set $4042 to 1 ;; DFB8: Set $4042 to 0 ;;----------------------------------------------------------------------------- DFB5 A9 01 LDA #$01 ; DFB7 2C A9 00 BIT $00A9 ; Alt entry: $DFB8: LDA #$00. DFBA 8D 42 40 STA $4042 DFBD 60 RTS ;;============================================================================= ;;============================================================================= ;; Block fill >256 locations with zero. Address in ($94). ;; Count in $96/$97. Location $90 used as a temp. ;;----------------------------------------------------------------------------- DFBE A9 00 LDA #$00 ; Fill with zero ;;============================================================================= ;; Block fill >256 locations with 'A' ;;----------------------------------------------------------------------------- DFC0 A4 96 LDY $96 ; Get low byte of count. DFC2 F0 09 BEQ $DFCD ; If zero, just fill by 256-byte pages. DFC4 84 90 STY $90 ; Store byte count to $90. DFC6 20 D4 DF JSR $DFD4 ; Call "fill less than one page" routine. DFC9 E6 95 INC $95 ; Increment the page number. DFCB A0 00 LDY #$00 ; Force to fill by pages. DFCD C6 97 DEC $97 ; Decrement the page count. DFCF 10 F3 BPL $DFC4 ; Iterate until all pages are full. DFD1 60 RTS ;;============================================================================= ;;============================================================================= ;; Block fill up to 256 locations with zero. Count in $90, address in ($94). ;;----------------------------------------------------------------------------- DFD2 A9 00 LDA #$00 ; Fill with zero. ;;============================================================================= ;; Block fill up to 256 locations with 'A'. Count in $90, address in ($94). ;;----------------------------------------------------------------------------- DFD4 A0 00 LDY #$00 DFD6 91 94 STA ($94),Y DFD8 C8 INY DFD9 C6 90 DEC $90 DFDB D0 F9 BNE $DFD6 DFDD 60 RTS ;;============================================================================= ;; Copy 6 bytes from ($94) to ($96) ;;----------------------------------------------------------------------------- DFDE A0 06 LDY #$06 ;fallthru ;;============================================================================= ;; Copy 'Y' bytes from ($94) to ($96). Leaves 'Y' unchanged. ;;----------------------------------------------------------------------------- DFE0 84 90 STY $90 DFE2 A0 00 LDY #$00 DFE4 B1 94 LDA ($94),Y DFE6 91 96 STA ($96),Y DFE8 C8 INY DFE9 C6 90 DEC $90 DFEB D0 F7 BNE $DFE4 DFED 60 RTS ;;============================================================================= ;;============================================================================= ;; Multiply A by 12, put result into X. Leaves original A in $90. ;;----------------------------------------------------------------------------- DFEE 85 90 STA $90 DFF0 0A ASL A DFF1 65 90 ADC $90 DFF3 0A ASL A DFF4 0A ASL A DFF5 AA TAX DFF6 60 RTS ;;============================================================================= ; Data from $DFF7 to $DFFF (9 bytes) DFF7 .byte $FF, $58, $32, $00, $C0, $00, $C0, $09, $C0 ; .X2...... ; End of disassembly.