ca65 V2.19 - Git e5f4ca6 Main file : AIM_65_Monitor.ca65 Current file: AIM_65_Monitor.ca65 000000r 1 ; 000000r 1 ; Rockwell AIM 65 Monitor 000000r 1 ; 000000r 1 ; recreated source listing in ca65 format 000000r 1 ; based on the source listed in the manual Revision A August 1978 000000r 1 ; 000000r 1 ; Chris Oddy December 2025 000000r 1 ; 000000r 1 ; (Note there are many typos in the comments due to the OCR transfer, one day I'll get around to fixing them ! 000000r 1 ; It does though produce 100% correct code) 000000r 1 ; 000000r 1 .org $E000 00E000 1 ; 00E000 1 ; ****** USER 6522 I/O ****** 00E000 1 ; 00E000 1 ; USER 6522 ADDRESSES (A000-A00F) 00E000 1 ; 00E000 1 UDRB := $A000 ; Data Register B 00E000 1 UDRAH := $A001 ; Data Register A 00E000 1 UDDRB := $A002 ; Data Direction Register B 00E000 1 UDDRA := $A003 ; Data Direction Register A 00E000 1 UT1L := $A004 ; Timer 1 Counter Low 00E000 1 UT1CH := $A005 ; Timer 1 Counter High 00E000 1 UT1LL := $A006 ; Timer 1 Latch Low 00E000 1 UT1LH := $A007 ; Timer 1 Latch High 00E000 1 UT2L := $A008 ; Timer 2 Latch & Counter Low 00E000 1 UT2CH := $A009 ; Timer 2 Counter High 00E000 1 USR := $A00A ; Shift Register 00E000 1 UACR := $A00B ; Auxiliary Control Register 00E000 1 UPCR := $A00C ; Peripheral Control Register 00E000 1 UIFR := $A00D ; Interrupt Flag Register 00E000 1 UIER := $A00E ; Interrupt Enable Register 00E000 1 UDRA := $A00F ; Data Register A 00E000 1 ; 00E000 1 ; ****** MONITOR VARIABLES ****** 00E000 1 ; 00E000 1 ASSEM := $D000 ; Assembler Entry 00E000 1 BASIEN := $B000 ; BASIC Entry (Cold) 00E000 1 BASIRE := $B003 ; BASIC Re-entry (Warm) 00E000 1 ; 00E000 1 ; *** Monitor RAM *** 00E000 1 ; Text Editor Equates (Page 0) 00E000 1 ; Overlaps IABUF2+50 (Tape Output Buffer $AD-$FF) 00E000 1 ; 00E000 1 NOWLN := $00DF ; Current Line 00E000 1 BOTLN := $00E1 ; Last active, so far 00E000 1 TEXT := $00E3 ; Limits of buffer (start) 00E000 1 END := $00E5 ; Limits of buffer (end) 00E000 1 SAVE := $00E7 ; Used by REPLACE 00E000 1 OLDLEN := $00E9 ; Original length 00E000 1 LENGTH := $00EA ; New length 00E000 1 STRING := $00EB ; Find string 00E000 1 ; 00E000 1 ; *** Breakpoints and User I/O Handlers *** 00E000 1 BKS := $0100 ; BRK Locations 00E000 1 UIN := $0108 ; User input handler (vector) 00E000 1 UOUT := $010A ; User output handler (vector) 00E000 1 ; 00E000 1 ; *** Unused keys to go to user routine *** 00E000 1 KEYF1 := $010C ; User puts a JMP instruction to... 00E000 1 KEYF2 := $010F ; Go to his routine on either key.. 00E000 1 KEYF3 := $0112 ; Entry 00E000 1 ; 00E000 1 ; *** Equates for Disassembler (Page 1) *** 00E000 1 ; Same as tape buffer I/O (TARBUFF) 00E000 1 FORMA := $0116 00E000 1 LMNEM := $0117 00E000 1 RMNEM := $0118 00E000 1 ; *** Equates for mnemonic entry *** 00E000 1 MOVAD := $0126 00E000 1 TYPE := $012E 00E000 1 TMASK1 := MOVAD 00E000 1 TMASK2 := MOVAD+1 00E000 1 CH := $0130 00E000 1 ADFLD := $0133 00E000 1 HISTM := $A42E ; Share with name & history 00E000 1 BYTESM := HISTM+1 00E000 1 TEMPX := HISTM+3 00E000 1 TEMPA := HISTM+5 00E000 1 OPCODE := HISTM+6 00E000 1 CODFLG := HISTM+9 00E000 1 ; 00E000 1 ; ****** 6532 Addresses (A400-A7FF) ****** 00E000 1 ; 00E000 1 MONRAM := $A400 00E000 1 ; *** Jump vectors *** 00E000 1 IRQV4 := $A400 ; IRQ after monitor (no BRK) 00E000 1 NMIV2 := $A402 ; NMI 00E000 1 IRQV2 := $A404 ; IRQ 00E000 1 ; 00E000 1 ; *** I/O devices *** 00E000 1 DILINK := $A406 ; Display linkage (to echo to display) 00E000 1 TSPEED := $A408 ; Tape speed (C7,5B,5A) 00E000 1 GAP := $A409 ; Timing gap between blocks 00E000 1 ; 00E000 1 ; *** End of user alterable locations *** 00E000 1 NPUL := $A40A ; Number of half pulses... 00E000 1 TIMG := $A40B ; For tape 00E000 1 REGF := $A40E ; Register Flag for single step mode 00E000 1 DISFLG := $A40F ; Disassemble Flag for single step mode 00E000 1 BKFLG := $A410 ; Enable or disable breakpoints 00E000 1 PRIFLG := $A411 ; Enable or disable printer 00E000 1 INFLG := $A412 ; Input device 00E000 1 OUTFLG := $A413 ; Output device 00E000 1 HISTP := $A414 ; History pointer (single step) (y) 00E000 1 CURPO2 := $A415 ; Display pointer 00E000 1 CURPOS := $A416 ; Printer pointer 00E000 1 CNTH30 := $A417 ; Baud rate & ... 00E000 1 CNTL30 := $A418 ; Delay for TTY 00E000 1 COUNT := $A419 ; Number of lines (0-99) 00E000 1 S1 := $A41A ; Start address 00E000 1 ADDR := $A41C ; End address 00E000 1 CKSUM := $A41E ; Checksum 00E000 1 S2 := BKS+6 ; Vertical count (only on DUMP) 00E000 1 ; 00E000 1 ; *** Monitor Registers *** 00E000 1 SAVPS := $A420 ; Status 00E000 1 SAVA := $A421 ; Accumulator 00E000 1 SAVX := $A422 ; X Register 00E000 1 SAVY := $A423 ; Y Register 00E000 1 SAVS := $A424 ; Stack Pointer 00E000 1 SAVPC := $A425 ; Program Counter 00E000 1 ; 00E000 1 ; *** Work Areas for Page Zero Simulation *** 00E000 1 ; simulate lda (nnnn),y ,where nnnn is absolute 00E000 1 STIY := $A427 ; sta nm,y 00E000 1 CPIY := $A42A ; cmp nm,y or lda nm,y 00E000 1 ; := $0255 ; rts 00E000 1 LDIY := CPIY 00E000 1 ; 00E000 1 ; *** Variables for Tape *** 00E000 1 NAME := $A42E ; Filename 00E000 1 TAPIN := $A434 ; In flag (Tape 1 OR 2) 00E000 1 TAPOUT := $A435 ; Out flag (Tape 1 OR 2) 00E000 1 TAPTR := $A436 ; Tape buffer pointer 00E000 1 TAPTR2 := $A437 ; Tape Output buffer pointer 00E000 1 HIST := NAME ; Four last address + next (single step) 00E000 1 BLK := $0115 ; Block count 00E000 1 TABUFF := $0116 ; Tape buffer (I/O) 00E000 1 BLKO := $0168 ; Output block Count 00E000 1 TABUF2 := $00AD ; Output buffer when assembling (page 0) 00E000 1 DIBUFF := $A438 ; Display buffer 00E000 1 ; 00E000 1 ; *** Variables used in Printing *** 00E000 1 IBUFM := $A460 ; Printer buffer 00E000 1 IDIR := $A474 ; Direction: 0=>+, FF=>- 00E000 1 ICOL := $A475 ; Column leftmost=0,rightmost=4 00E000 1 IOFFST := $A476 ; Offset 0=left dgt, 1=right dot 00E000 1 IDOT := $A477 ; Number of last dot encountered 00E000 1 IOUTL := $A478 ; Lower 8 outputs(9 columns on right) 00E000 1 IOUTU := $A479 ; Upper 2 digits 00E000 1 IBITL := $A47A ; 1-bit mask for current output 00E000 1 IBITU := $A47B 00E000 1 IMASK := $A47C ; Mask for current row 00E000 1 JUMP := $A47D ; Indirect and address of table for current row 00E000 1 ; 00E000 1 ; *** Variables for Keyboard *** 00E000 1 ROLLFL := $A47F ; Save last strobe for rollover 00E000 1 KMASK := CPIY ; To mask off ctrl or shift 00E000 1 STBKEY := CPIY+1 ; Strobe key (1-8 columns) 00E000 1 00E000 1 ; *** I/O Assignment *** 00E000 1 DRA2 := $A480 ; Data Register A 00E000 1 DDRA2 := $A481 ; Data Direction Register A 00E000 1 DRB2 := $A482 ; Data Register B 00E000 1 DDRB2 := $A483 ; Data Direction Register B 00E000 1 ; 00E000 1 ; *** Write Edge Detect Control (not used because of keyboard) *** 00E000 1 DNPA7 := $A484 ; Disable PA7 INT. negative edge detect 00E000 1 DPPA7 := $A485 ; Disable PA7 INT, positive edge detect 00E000 1 ENPA7 := $A486 ; Enable PA7 INT, negative edge detect 00E000 1 EPPA7 := $A487 ; Enable PA7 INT, positive edge detect 00E000 1 ; 00E000 1 ; *** Read and Clear Interrupt *** 00E000 1 RINT := $A485 ; Bit 7=Timer Flag, Bit 6=PA7 Flag 00E000 1 ; 00E000 1 ; *** Timer Interrupt ***; 00E000 1 ; Write count to interval timer 00E000 1 ; Interrupt disable for these addresses 00E000 1 DIV1 := $A494 ; Divide by 1 (disable), add 8 to enable 00E000 1 DIVB := $A495 ; Divide by 8 (disable), add 8 to enable 00E000 1 DIV64 := $A496 ; Divide by 64 (disable), add 8 to enable 00E000 1 DI1024 := $A497 ; Divide by 1024 (disable), add 8 to enable 00E000 1 ; 00E000 1 ; ****** 6522 Addresses (Monitor) (A800-ABFF) ****** 00E000 1 ; 00E000 1 DRB := $A800 ; Data Register B 00E000 1 DRAH := $A801 ; Data Register A 00E000 1 DDRB := $A802 ; Data Direction Register B 00E000 1 DDRA := $A803 ; Data Direction Register B 00E000 1 T1L := $A804 ; Timer 1 Counter Low 00E000 1 T1CH := $A805 ; Timer 1 Counter High 00E000 1 T1LL := $A806 ; Timer 1 Latch Low 00E000 1 T1LH := $A807 ; Timer 1 Latch High 00E000 1 T2L := $A808 ; Timer 2 Latch & Counter Low 00E000 1 T2H := $A809 ; Timer 2 Counter High 00E000 1 SR := $A80A ; Shift Register 00E000 1 ACR := $A80B ; Auxiliary Control Register 00E000 1 PCR := $A80C ; Peripheral Control Register 00E000 1 IFR := $A80D ; Interrupt Flag Register 00E000 1 IER := $A80E ; Interrupt Enable Register 00E000 1 DRA := $A80F ; Data Register A 00E000 1 ; 00E000 1 ; *** Define I/O Control for Program (CA1,CA2,CB1,CB2) *** 00E000 1 DATIN := $0E ; Data In CA2=1 00E000 1 DATOUT := $0C ; Data Out DA2=0 00E000 1 PRST := $00 ; Print start (CB1), negative detect 00E000 1 SP12 := $01 ; Strobe P1, P2 (CA1), positive detect 00E000 1 MON := $C0 ; Motor on (CB2 = 0) 00E000 1 MOFF := $E0 00E000 1 ; 00E000 1 ; *** Masks to Obtain Each Interrupt *** 00E000 1 MPRST := $10 ; Interrupt Flag for DB1 00E000 1 MSP12 := $02 ; Interrupt Flag for CA1 00E000 1 MT2 := $20 ; Interrupt Flag for T2 00E000 1 ; 00E000 1 ; *** Define I/O Control for ACR (Timers,SR) *** 00E000 1 PRTIME := 1700 ; Printing time = 1.7msec 00E000 1 DEBTIM := 5000 ; Debounce time (5msec) 00E000 1 T2I := $00 ; T2 as one shot (PRI,KB,TTY,Tape) 00E000 1 T1I := $00 ; T1 as one shot PB7 disable (Tape) 00E000 1 T1FR := $C0 ; T1 in free running (Tape) 00E000 1 ; 00E000 1 ; ****** DISPLAY (AC00-AFFF) ****** 00E000 1 ; 00E000 1 ; *** Registers for Display (6520) *** 00E000 1 RA := $AC00 ; Register A 00E000 1 CRA := $AC01 ; Control Register A 00E000 1 RB := $AC02 ; Register B 00E000 1 CRB := $AC03 ; Control Register B 00E000 1 ; 00E000 1 ; Character 00-03 enabled by $AC04-AC07 00E000 1 ; Character 04-07 enabled by $AC08-AC0B 00E000 1 ; Character 08-11 enabled by $AC10-AC13 00E000 1 ; Character 12-15 enabled by $AC20-AC23 00E000 1 ; Character 16-20 enabled by $AC40-AC43 00E000 1 ; 00E000 1 NULLC := $FF 00E000 1 CR := $0D 00E000 1 LF := $0A 00E000 1 ESCAPE := $1B 00E000 1 RUB := $08 00E000 1 EQS := $BD 00E000 1 SPACE := $20 00E000 1 ; 00E000 1 ; ****** Start of ROM R3223 ****** 00E000 1 ; 00E000 1 ; E = Enter Editor 00E000 1 ; T = Re-enter Editor to re-edit source 00E000 1 ; R = Show Registers 00E000 1 ; M = Display memory 00E000 1 ; = Show next 4 addresses 00E000 1 ; G = Go at current Program Counter (count) 00E000 1 ; / = Alter current memory 00E000 1 ; L = Load object 00E000 1 ; D = Dump objecT 00E000 1 ; N = Assemble 00E000 1 ; * = Alter Program Counter 00E000 1 ; A = Alter accumulator 00E000 1 ; X = Alter X Register 00E000 1 ; Y = Alter Y Register 00E000 1 ; P = Alter Processor Status 00E000 1 ; G = Alter Stack Pointer 00E000 1 ; B = Set Break address 00E000 1 ; ? = Show Break addresses 00E000 1 ; $ = Clear break addresses 00E000 1 ; H = Show trace history stack 00E000 1 ; V = Toggle register print with disassembler 00E000 1 ; Z = Toggle disassembler trace 00E000 1 ; \ = Turn on/off printer 00E000 1 ; = Advance paper 00E000 1 ; I = Mnemonic enter 00E000 1 ; K = Disassemble memory 00E000 1 ; 1 = Toggle tape 1 control (on or off) 00E000 1 ; 2 = Toggle tape 2 control 00E000 1 ; 3 = Verify checksum for tapes 00E000 1 ; 4 = Enable breaks 00E000 1 ; 5 = BASIC entry (cold) 00E000 1 ; 6 = BASIC re-entry (warm) 00E000 1 ; 00E000 1 ; Following keys are unused but 'hooks" are provided in locations 010c-0114 00E000 1 ; KEYF1,KEYF2,KEYF3 00E000 1 ; 00E000 1 ; All messages have MSB=1 of last character to end it 00E000 1 46 52 4F 4D M1: .byte "FROM",EQS 00E004 1 BD 00E005 1 54 4F BD M3: .byte "TO",EQS 00E008 1 20 2A 2A 2A M4: .byte " **** PS AA XX YY S",$D3 00E00C 1 2A 20 50 53 00E010 1 20 41 41 20 00E01C 1 4D 4F 52 45 M5: .byte "MORE",$BF 00E020 1 BF 00E021 1 4F 4E A0 M6: .byte "ON",$A0 ; 'ON ' 00E024 1 4F 46 C6 M7: .byte "OF",$C6 ; 'OFF' 00E027 1 42 52 CB M8: .byte "BR",$CB ; 'BRK' 00E02A 1 49 4E BD M9: .byte "IN",EQS 00E02D 1 4F 55 54 BD M10: .byte "OUT",EQS 00E031 1 20 4D 45 4D M11: .byte " MEM FAIL",$A0 00E035 1 20 46 41 49 00E039 1 4C A0 00E03B 1 20 50 52 49 M12: .byte " PRINTER DOW",$CE 00E03F 1 4E 54 45 52 00E043 1 20 44 4F 57 00E048 1 20 53 52 43 TMSG0: .byte " SRCH" 00E04C 1 48 00E04D 1 20 46 BD TMSG1: .byte " F",EQS 00E050 1 54 BD TMSG2: .byte 'T',EQS 00E052 1 A0 C5 D2 D2 TMSG3: .byte $A0,$C5,$D2,$D2 ; PRINT ' ERROR' ,MSB=1 00E056 1 CF D2 A0 A0 .byte $CF,$D2,$A0,$A0,$A0,$A0,$A0,$A0,';' 00E05A 1 A0 A0 A0 A0 00E05E 1 3B 00E05F 1 41 BD TMSG5: .byte 'A',EQS 00E061 1 42 4C 4B 3D TMSG6: .byte "BLK=",$A0 00E065 1 A0 00E066 1 A0 CC CF C1 TMSG7: .byte $A0,$CC,$CF,$C1,$C4,';' 00E06A 1 C4 3B 00E06C 1 45 44 49 54 EMSG1: .byte "EDITO",$D2 ; EDITOR MESSAGES 00E070 1 4F D2 00E072 1 45 4E C4 EMSG2: .byte "EN",$C4 00E075 1 ; 00E075 1 ; ****** Interrupt Handling ****** 00E075 1 ; 00E075 1 ; Vectors come here first after jump through FFFA-FFFF 00E075 1 6C 02 A4 NMIV1: jmp (NMIV2) ; NMIV2 is a vector to NMIV3 00E078 1 6C 04 A4 IRQV1: jmp (IRQV2) ; IRQV2 is a vector to IRQV3 00E07B 1 ; 00E07B 1 ; single step entry point (NMI) 00E07B 1 8D 21 A4 NMIV3: sta SAVA ; save A 00E07E 1 68 pla 00E07F 1 8D 20 A4 sta SAVPS ; save processor status 00E082 1 D8 cld 00E083 1 8E 22 A4 stx SAVX ; save X 00E086 1 8C 23 A4 sty SAVY 00E089 1 68 pla 00E08A 1 8D 25 A4 sta SAVPC ; program counter 00E08D 1 68 pla 00E08E 1 8D 26 A4 sta SAVPC+1 00E091 1 BA tsx ; get stack pointer & save it 00E092 1 8E 24 A4 stx SAVS 00E095 1 ; trace the address 00E095 1 AC 14 A4 ldy HISTP ; get pointer to history stack 00E098 1 AD 26 A4 lda SAVPC+1 ; save halt address in history stack 00E09B 1 99 2E A4 sta HIST,y 00E09E 1 AD 25 A4 lda SAVPC 00E0A1 1 99 2F A4 sta HIST+1,y 00E0A4 1 20 88 E6 jsr NHIS ; update pointer 00E0A7 1 AD 10 A4 lda BKFLG ; soft brakes on ? 00E0AA 1 F0 08 beq NMI5 ; no, don't check breakpoint list 00E0AC 1 20 6B E7 jsr CKB ; check breakpoint list 00E0AF 1 90 03 bcc NMI5 00E0B1 1 4C 7F E1 NMI4: jmp IRQ2 ; hit a break-trap to monitor 00E0B4 1 20 90 E7 NMI5: jsr DONE ; count =0 ? 00E0B7 1 F0 F8 beq NMI4 ; yes, trap to monitor 00E0B9 1 20 07 E9 jsr RCHEK ; check if he wants to ITNERR 00E0BC 1 4C 6D E2 jmp GOBK ; not done-resume execution 00E0BF 1 ; 00E0BF 1 ; power up and reset entry point (reset transfers here) 00E0BF 1 D8 RSET: cld ; clear decimal mode 00E0C0 1 78 sei ; disable interrupts 00E0C1 1 A2 FF ldx #$FF ; initialise stack pointer 00E0C3 1 9A txs 00E0C4 1 8E 24 A4 stx SAVS ; also initialise saved stack pointer 00E0C7 1 ; initialise 6522 00E0C7 1 A2 0E ldx #14 00E0C9 1 BD 43 E7 RS1: lda INTAB1,x ; PB1-PB0,PA7-PA0 for printer 00E0CC 1 9D 00 A8 sta DRB,x ; PB2=TTO,PB6=TTI 00E0CF 1 CA dex ; PB4-PB5=tape control,PB7=Data 00E0D0 1 10 F7 bpl RS1 ; PB3=switch KB/TTY 00E0D2 1 ; initialise 6532 00E0D2 1 A2 03 ldx #$03 ; ports used for keyboard 00E0D4 1 BD 52 E7 RS2: lda INTAB2,x ; PA0-PA7 as output 00E0D7 1 9D 80 A4 sta DRA2,x ; PB0-PB7 as input 00E0DA 1 CA dex 00E0DB 1 10 F7 bpl RS2 00E0DD 1 ; initialise monitor RAM (6532) 00E0DD 1 AD 56 E7 lda INTAB3 ; check if NMIV2 has been changed 00E0E0 1 CD 02 A4 cmp NMIV2 ; if it has then assume a cold reset 00E0E3 1 D0 0C bne RS3A ; start and initialise everything 00E0E5 1 AD 57 E7 lda INTAB3+1 00E0E8 1 CD 03 A4 cmp NMIV2+1 00E0EB 1 D0 04 bne RS3A 00E0ED 1 A2 10 ldx #16 ; they are equal, it's a warm reset 00E0EF 1 D0 02 bne RS3 00E0F1 1 A2 00 RS3A: ldx #$00 ; initialise everything (power up) 00E0F3 1 BD 56 E7 RS3: lda INTAB3,x 00E0F6 1 9D 02 A4 sta NMIV2,x 00E0F9 1 E8 inx 00E0FA 1 E0 15 cpx #21 00E0FC 1 90 F5 bcc RS3 00E0FE 1 ; initialise display (6520) 00E0FE 1 A9 00 lda #$00 ; set control register for data direction register 00E100 1 A2 01 ldx #$01 00E102 1 20 13 E1 jsr SETREG 00E105 1 A9 FF lda #$FF ; set data direction register for output 00E107 1 CA dex 00E108 1 20 13 E1 jsr SETREG 00E10B 1 A9 04 lda #$04 ; set control register for ports 00E10D 1 E8 inx 00E10E 1 20 13 E1 jsr SETREG 00E111 1 D0 07 bne RS3B 00E113 1 9D 00 AC SETREG: sta RA,x 00E116 1 9D 02 AC sta RB,x 00E119 1 60 rts 00E11A 1 58 RS3B: cli ; clear interrupts 00E11B 1 ; 00E11B 1 ; KB/TTY switch test and bit rate measurement 00E11B 1 A9 08 lda #$08 ; PB3=switch KB/TTY 00E11D 1 2C 00 A8 RS4: bit DRB ; A^M, PB6-> V (overflow flag) 00E120 1 D0 22 bne RS7 ; branch on keyboard 00E122 1 70 F9 BVS RS4 ; start bit = PB6=0 ? 00E124 1 A9 FF lda #$FF ; yes ,initialise timer T2 00E126 1 8D 09 A8 sta T2H 00E129 1 2C 00 A8 RS5: bit DRB ; end of start bit ? 00E12C 1 50 FB bvc RS5 ; no, wait until PB6 back to 1 00E12E 1 AD 09 A8 lda T2H ; store timing 00E131 1 49 FF eor #$FF ; complement 00E133 1 8D 17 A4 sta CNTH30 00E136 1 AD 08 A8 lda T2L 00E139 1 49 FF eor #$FF 00E13B 1 20 7C FE jsr PATCH1 ; adjust it 00E13E 1 20 13 EA RS6: jsr CRLOW ; clear display 00E141 1 4C 72 FF jmp PAT21 00E144 1 A2 13 RS7: ldx #19 ; clear hardware cursors 00E146 1 8A RS8: txa 00E147 1 48 pha 00E148 1 A9 00 lda #$00 00E14A 1 20 7B EF jsr OUTDD1 00E14D 1 68 pla 00E14E 1 AA tax 00E14F 1 CA dex 00E150 1 10 F4 bpl RS8 00E152 1 30 EA bmi RS6 00E154 1 ; 00E154 1 ; break instruction (00) or IRQ entry point 00E154 1 8D 21 A4 IRQV3: sta SAVA 00E157 1 68 pla 00E158 1 48 pha ; get status 00E159 1 29 10 and #$10 ; see if 'BRK', isolate B flag 00E15B 1 D0 06 bne IRQ1 ; trap was caused by 'BRK' instruction 00E15D 1 AD 21 A4 lda SAVA ; trap caused by IRQ so transfer 00E160 1 6C 00 A4 jmp (IRQV4) ; control to user thru vector 00E163 1 ; is 'BRK' instruction, show PC & data 00E163 1 ; PC is off by one, so adjust it 00E163 1 68 IRQ1: pla 00E164 1 8D 20 A4 sta SAVPS ; save processor status 00E167 1 8E 22 A4 stx SAVX 00E16A 1 8C 23 A4 sty SAVY 00E16D 1 D8 cld 00E16E 1 68 pla ; program counter 00E16F 1 38 sec ; subtract one from return address 00E170 1 E9 01 sbc #$01 00E172 1 8D 25 A4 sta SAVPC 00E175 1 68 pla 00E176 1 E9 00 sbc #$00 00E178 1 8D 26 A4 sta SAVPC+1 00E17B 1 BA tsx ; get stack pointer & save it 00E17C 1 8E 24 A4 stx SAVS 00E17F 1 ; show PC and data 00E17F 1 20 61 F4 IRQ2: jsr REGQ ; show next instruction & continue 00E182 1 ;.PAGE 'INTERPRET COMMANDS' 00E182 1 ; this routine will get a character with '( )' from 00E182 1 ; KB/TTY & then will go to the respective command 00E182 1 4C 59 FF START: jmp PAT19 ; clear decimal mode & (CR) 00E185 1 A9 BC STA1: lda #$BC ; '(' character with MRB=1 for display 00E187 1 20 7A E9 jsr OUTPUT 00E18A 1 20 96 FE jsr RED1 ; get character & echo from KB/TTY 00E18D 1 48 pha 00E18E 1 A9 3E lda #'>' 00E190 1 20 7A E9 jsr OUTPUT 00E193 1 68 pla ; scan list of commands for entered character 00E194 1 A2 20 ldx #MCNT ; count of commands 00E196 1 DD C4 E1 MCM2: cmp COMB,x ; check next command in list 00E199 1 F0 11 beq MCM3 ; match, so process this command 00E19B 1 CA dex 00E19C 1 10 F8 bpl MCM2 00E19E 1 ; is bad command 00E19E 1 20 D4 E7 jsr QM 00E1A1 1 D8 COMIN: cld 00E1A2 1 20 FE E8 jsr LL 00E1A5 1 AE 24 A4 ldx SAVS 00E1A8 1 9A txs 00E1A9 1 4C 82 E1 jmp START 00E1AC 1 ; have valid command 00E1AC 1 8A MCM3: txa ; convert to word (multiply by 2) 00E1AD 1 0A asl a ; 2-bytes (address) 00E1AE 1 AA tax 00E1AF 1 BD E5 E1 lda MONCOM,x ; get address of command processor 00E1B2 1 8D 7D A4 sta JUMP 00E1B5 1 BD E6 E1 lda MONCOM+1,x 00E1B8 1 8D 7E A4 sta JUMP+1 00E1BB 1 20 C1 E1 jsr JMPR ; command processor can exit with RTS 00E1BE 1 4C 82 E1 jmp START 00E1C1 1 6C 7D A4 JMPR: jmp (JUMP) ; goto command 00E1C4 1 ; 00E1C4 1 ; valid commands 00E1C4 1 MCNT=32 ; count 00E1C4 1 45 54 52 4D COMB: .byte "ETRMG/LDN*AXYPS " 00E1C8 1 47 2F 4C 44 00E1CC 1 4E 2A 41 58 00E1D4 1 42 3F 23 48 .byte "B?#HVZIK123456[]",$5E 00E1D8 1 56 5A 49 4B 00E1DC 1 31 32 33 34 00E1E5 1 00E1E5 1 39 F6 CF F6 MONCOM: .word EDIT,REENTR,REG,MEM,GO 00E1E9 1 27 E2 48 E2 00E1ED 1 61 E2 00E1EF 1 A0 E2 E6 E2 .word CHNGG,LOAD,DUMP,ASSEM,CGPC,CGA 00E1F3 1 3B E4 00 D0 00E1F7 1 D4 E5 EE E5 00E1FB 1 F2 E5 F6 E5 .word CGX,CGY,CGPS,CGS,NXT5,BRKA 00E1FF 1 EA E5 FA E5 00E203 1 0D E6 1B E6 00E207 1 4D E6 FE E6 .word SHOW,CLRBK,SHIS,REGT,TRACE 00E20B 1 65 E6 D9 E6 00E20F 1 DD E6 00E211 1 9E FB 0A E7 .word MNEENT,KDISA,TOGTA1,TOGTA2,VECKSM 00E215 1 BD E6 CB E6 00E219 1 94 E6 00E21B 1 E5 E6 00 B0 .word BRKK,BASIEN,BASIRE 00E21F 1 03 B0 00E221 1 ; user defined functions 00E221 1 0C 01 0F 01 .word KEYF1,KEYF2,KEYF3 00E225 1 12 01 00E227 1 ;.PAGE 'COMMANDS' 00E227 1 ; ***** R Command - Display Registers ***** 00E227 1 20 13 EA REG: jsr CRLOW ; clear display if keyboard 00E22A 1 A0 08 ldy #M4-M1 ; message & (CR) 00E22C 1 20 AF E7 jsr KEP 00E22F 1 20 24 EA jsr CRCK 00E232 1 20 3E E8 REG1: jsr BLANK 00E235 1 A0 09 ldy #<(SAVPC-ADDR) ; output Program Counter (SAVPC) 00E237 1 20 DD E2 jsr WRITAD 00E23A 1 A9 20 lda #SAVPS 00E241 1 8D 1D A4 sta ADDR+1 00E244 1 A2 05 ldx #$05 ; count 00E246 1 D0 07 bne MEM1 ; share code 00E248 1 ; 00E248 1 ; ***** M Command - Display Memory ***** 00E248 1 20 AE EA MEM: jsr ADDIN ; GET START ADDRESS IN ADDR 00E24B 1 B0 13 bcs MEM3 00E24D 1 A2 04 MEIN: ldx #$04 00E24F 1 A0 00 MEM1: ldy #$00 00E251 1 20 3E E8 MEM2: jsr BLANK 00E254 1 A9 1C lda # 24 ? 00E49B 1 90 05 bcc DU8 ; no, only output remaining bytes 00E49D 1 B0 01 bcs DU7 ; yes, 24 bytes in next record 00E49F 1 68 DU6: pla 00E4A0 1 A9 18 DU7: lda #24 00E4A2 1 ; output ";", number of bytes and start address 00E4A2 1 48 DU8: pha 00E4A3 1 20 BA E9 jsr SEMI ; semicolon 00E4A6 1 68 pla 00E4A7 1 8D 19 A4 sta COUNT ; save number of bytes 00E4AA 1 20 38 E5 jsr OUTCK ; output number of bytes 00E4AD 1 AD 1B A4 lda S1+1 ; output address 00E4B0 1 20 38 E5 jsr OUTCK 00E4B3 1 AD 1A A4 lda S1 00E4B6 1 20 38 E5 jsr OUTCK 00E4B9 1 ; output data 00E4B9 1 20 31 E5 DU9: jsr OUTCKS ; get character specified by S1 (no page 0) 00E4BC 1 A9 00 lda #$00 ; clear display pointer 00E4BE 1 8D 15 A4 sta CURPO2 00E4C1 1 20 5D E5 jsr ADDS1 ; increment S1+1,S1 00E4C4 1 CE 19 A4 dec COUNT ; decrement byte count 00E4C7 1 D0 F0 bne DU9 ; not done with this record 00E4C9 1 ; output checksum 00E4C9 1 AD 1F A4 lda CKSUM+1 00E4CC 1 20 3B E5 jsr OUTCK1 ; without check 00E4CF 1 AD 1E A4 lda CKSUM 00E4D2 1 20 3B E5 jsr OUTCK1 00E4D5 1 20 66 E5 jsr INCS2 ; increment vertical count 00E4D8 1 4C 7D E4 jmp DU2 ; next record 00E4DB 1 ; all done 00E4DB 1 A0 1C DU10: ldy #M5-M1 ; print 'MORE ?' 00E4DD 1 20 70 E9 jsr KEPR ; output message and get an answer 00E4E0 1 C9 59 cmp #'Y' 00E4E2 1 D0 03 bne *+5 00E4E4 1 4C 44 E4 jmp DU1 ; dump more data 00E4E7 1 68 pla ; restore flag 00E4E8 1 8D 10 A4 sta BKFLG 00E4EB 1 ; output last record 00E4EB 1 20 66 E5 jsr INCS2 00E4EE 1 20 BA E9 jsr SEMI ; output ';' 00E4F1 1 A2 02 ldx #$02 00E4F3 1 A9 00 lda #$00 ; output number of bytes (0=last record) 00E4F5 1 20 3B E5 jsr OUTCK1 00E4F8 1 AD 07 01 DU10A: lda S2+1 ; output record count 00E4FB 1 20 3B E5 jsr OUTCK1 ; checksum is the same 00E4FE 1 AD 06 01 lda S2 00E501 1 20 3B E5 jsr OUTCK1 00E504 1 CA dex 00E505 1 D0 F1 bne DU10A 00E507 1 20 F0 E9 jsr CRLF 00E50A 1 ; close tape block if active 00E50A 1 AD 13 A4 DU11: lda OUTFLG 00E50D 1 C9 54 cmp #'T' 00E50F 1 D0 0F bne DU13 ; no, branch 00E511 1 AD 37 A4 DU12: lda TAPTR2 ; tape output buffer pointer 00E514 1 C9 01 cmp #$01 ; because first one is block count 00E516 1 F0 08 beq DU13 ; no data to write 00E518 1 A9 00 lda #$00 ; fill rest buffer zeros 00E51A 1 20 8B F1 jsr TOBYTE ; output to buffer 00E51D 1 4C 11 E5 jmp DU12 ; finish this block 00E520 1 20 13 EA DU13: jsr CRLOW 00E523 1 18 clc ; enable interrupts 00E524 1 A9 00 lda #T1I ; T1 from free running one shot 00E526 1 8D 0B A8 sta ACR 00E529 1 A9 34 DU14: lda #$34 ; set both tapes on 00E52B 1 8D 00 A8 sta DRB 00E52E 1 4C FE E8 jmp LL 00E531 1 ; 00E531 1 ; get character specified by start ADDR (S1) 00E531 1 A9 1A OUTCKS: lda # 1 byte 00E54E 1 48 CHEKA: pha ; add to checksum 00E54F 1 18 clc 00E550 1 6D 1E A4 adc CKSUM 00E553 1 8D 1E A4 sta CKSUM 00E556 1 90 03 bcc *+5 00E558 1 EE 1F A4 inc CKSUM+1 00E55B 1 68 pla 00E55C 1 60 rts 00E55D 1 ; 00E55D 1 ; add one to start ADDR (S1) 00E55D 1 EE 1A A4 ADDS1: inc S1 00E560 1 D0 03 bne ADD1 00E562 1 EE 1B A4 inc S1+1 00E565 1 60 ADD1: rts 00E566 1 ; 00E566 1 EE 06 01 INCS2: inc S2 ; increment vertical count 00E569 1 D0 03 bne *+5 00E56B 1 EE 07 01 inc S2+1 00E56E 1 60 rts 00E56F 1 ; 00E56F 1 ; Open a file for output to tape by blocks 00E56F 1 ; output filename given by JSR where to tape buffer 00E56F 1 A2 00 DUMPTA: ldx #$00 ; initialise TAPTR 00E571 1 8A txa ; to output 00E572 1 8E 68 01 stx BLKO ; block counter 00E575 1 8E 37 A4 stx TAPTR2 ; tap output buffer pointer 00E578 1 20 8B F1 jsr TOBYTE ; two start of file characters 00E57B 1 BD 2E A4 DUMPT1: lda NAME,x ; output filename 00E57E 1 20 8B F1 jsr TOBYTE 00E581 1 E8 inx 00E582 1 E0 05 cpx #$05 ; 5 filename characters ? 00E584 1 D0 F5 bne DUMPT1 00E586 1 60 rts 00E587 1 ; 00E587 1 ; Dump routine to tape with KIM-1 format 00E587 1 20 1D F2 DUMPKI: jsr TAOSET ; set tape for output 00E58A 1 A9 2A lda #'*' ; to either 1 or 2 00E58C 1 20 4A F2 jsr OUTTAP ; directly to tape 00E58F 1 ; ID from last two characters of filename 00E58F 1 20 25 E4 jsr GETID 00E592 1 20 3B E5 jsr OUTCK1 00E595 1 20 4D EB jsr CLRCK 00E598 1 ; starting address 00E598 1 AD 1A A4 lda S1 00E59B 1 20 38 E5 jsr OUTCK ; with checksum 00E59E 1 AD 1B A4 lda S1+1 00E5A1 1 20 38 E5 jsr OUTCK 00E5A4 1 ; output data 00E5A4 1 20 31 E5 DUK2: jsr OUTCKS ; output characters specified by S1+1,S1 00E5A7 1 20 5D E5 jsr ADDS1 ; increment S1+1, S1 00E5AA 1 AD 1A A4 lda S1 ; check for last byte 00E5AD 1 CD 1C A4 cmp ADDR ; LSB of end address 00E5B0 1 AD 1B A4 lda S1+1 00E5B3 1 ED 1D A4 sbc ADDR+1 00E5B6 1 90 EC bcc DUK2 ; next character 00E5B8 1 ; now send end character '/' 00E5B8 1 A9 2F lda #$2F 00E5BA 1 20 4A F2 jsr OUTTAP ; directly to tape 00E5BD 1 ; checksum 00E5BD 1 AD 1E A4 lda CKSUM 00E5C0 1 20 46 EA jsr NUMA ; ASCII representation 00E5C3 1 AD 1F A4 lda CKSUM+1 00E5C6 1 20 46 EA jsr NUMA 00E5C9 1 ; two EOT characters 00E5C9 1 A9 04 lda #$04 00E5CB 1 20 4A F2 jsr OUTTAP 00E5CE 1 20 4A F2 jsr OUTTAP 00E5D1 1 ; turn tapes on 00E5D1 1 4C 20 E5 jmp DU13 00E5D4 1 ; 00E5D4 1 ; ****** Command - Alter Program Counter ***** 00E5D4 1 20 AE EA CGPC: jsr ADDIN ; ADDR <= address entered from keyboard 00E5D7 1 20 DD E5 CGPC0: jsr CGPC1 ; transfer ADDR TO SAVPC 00E5DA 1 4C 13 EA jmp CRLOW 00E5DD 1 AD 1D A4 CGPC1: lda ADDR+1 ; this way mnemonics can use it 00E5E0 1 8D 26 A4 sta SAVPC+1 00E5E3 1 AD 1C A4 lda ADDR 00E5E6 1 8D 25 A4 sta SAVPC 00E5E9 1 60 rts 00E5EA 1 ; 00E5EA 1 ; ***** P Command - Alter Processor Status ***** 00E5EA 1 A2 00 CGPS: ldx #$00 00E5EC 1 F0 0E beq CGALL 00E5EE 1 ; 00E5EE 1 ; ***** A Command - Alter Accumulator ***** 00E5EE 1 A2 01 CGA: ldx #$01 00E5F0 1 D0 0A bne CGALL 00E5F2 1 ; 00E5F2 1 ; ***** X Command - Alter X Register ***** 00E5F2 1 A2 02 CGX: ldx #$02 00E5F4 1 D0 06 bne CGALL 00E5F6 1 ; 00E5F6 1 ; ***** Y Command - Alter Y Register ***** 00E5F6 1 A2 03 CGY: ldx #$03 00E5F8 1 D0 02 bne CGALL 00E5FA 1 ; 00E5FA 1 ; ***** S Command - Alter Stack Pointer ***** 00E5FA 1 A2 04 CGS: ldx #$04 00E5FC 1 20 D8 E7 CGALL: jsr EQUAL ; print prompt 00E5FF 1 20 5D EA jsr RD2 ; get value form keyboard 00E602 1 B0 04 bcs GOERR 00E604 1 9D 20 A4 sta SAVPS,x 00E607 1 60 rts 00E608 1 20 D4 E7 GOERR: jsr QM 00E60B 1 D0 EF bne CGALL 00E60D 1 ; 00E60D 1 ; ***** (SPACE) Command - Show Next Five Memory Locations ***** 00E60D 1 20 3E E8 NXT5: jsr BLANK 00E610 1 A0 04 ldy #$04 ; update ADDR from 00E612 1 20 CD E2 jsr NXTADD ; (M)=XXXX 00E615 1 20 DB E2 jsr WRITAZ ; output address 00E618 1 4C 4D E2 jmp MEIN ; display context of next four locations 00E61B 1 ; 00E61B 1 ; ***** B Command - Set Breakpoint Address ***** 00E61B 1 A0 27 BRKA: ldy #M8-M1 ; print BRK 00E61D 1 20 AF E7 jsr KEP 00E620 1 20 37 E8 BRK1: jsr PSL1 ; print '/' 00E623 1 20 73 E9 jsr REDOUT ; get break number 00E626 1 38 sec 00E627 1 E9 30 sbc #$30 ; 0 through 3 00E629 1 30 04 bmi BKERR ; character < '0' - illegal 00E62B 1 C9 04 cmp #$04 ; four breakpoints 00E62D 1 30 05 bmi BKOK ; 0 < character < 4 - OK 00E62F 1 20 D4 E7 BKERR: jsr QM ; error 00E632 1 D0 EC bne BRK1 ; allow re-entry of break number 00E634 1 0A BKOK: asl a ; *2 to form word offset 00E635 1 48 pha ; save it 00E636 1 20 AE EA jsr ADDIN ; get address for breakpoint 00E639 1 68 pla 00E63A 1 B0 10 bcs BK02 ; bad address entered 00E63C 1 20 3D FF jsr PATC18 ; CR & clear buffers 00E63F 1 AA tax ; number of BRK 00E640 1 AD 1C A4 lda ADDR ; store entered address in breakpoint list 00E643 1 9D 00 01 sta BKS,x 00E646 1 AD 1D A4 lda ADDR+1 00E649 1 9D 01 01 sta BKS+1,x 00E64C 1 60 BK02: rts ; all done 00E64D 1 ; 00E64D 1 ; ***** ? Command - Show Current Breakpoints ***** 00E64D 1 A0 00 SHOW: ldy #$00 00E64F 1 20 13 EA jsr CRLOW 00E652 1 20 3E E8 SH1: jsr BLANK 00E655 1 BE 00 01 ldx BKS,y ; address of next breakpoint 00E658 1 B9 01 01 lda BKS+1,y 00E65B 1 20 42 EA jsr WRAX ; show breakpoitn address 00E65E 1 C8 iny 00E65F 1 C8 iny 00E660 1 C0 08 cpy #$08 00E662 1 D0 EE bne SH1 00E664 1 60 rts 00E665 1 ; 00E665 1 ; ***** H Command - Show Trace Stack History ***** 00E665 1 ; last five instruction address 00E665 1 A2 05 SHIS: ldx #$05 ; number of entries 00E667 1 8E 29 A4 stx STIY+2 00E66A 1 AC 14 A4 SHI1: ldy HISTP ; pointer to latest entry 00E66D 1 20 13 EA jsr CRLOW 00E670 1 20 3E E8 jsr BLANK 00E673 1 B9 2E A4 lda HIST,y ; output address of entry 00E676 1 20 46 EA jsr NUMA 00E679 1 B9 2F A4 lda HIST+1,y 00E67C 1 20 46 EA jsr NUMA 00E67F 1 20 88 E6 jsr NHIS ; update pointer 00E682 1 CE 29 A4 dec STIY+2 00E685 1 D0 E3 bne SHI1 00E687 1 60 rts 00E688 1 ; 00E688 1 ; update history pointer (part of H) 00E688 1 C8 NHIS: iny 00E689 1 C8 iny 00E68A 1 C0 0A cpy #10 00E68C 1 D0 02 bne NH1 00E68E 1 A0 00 ldy #$00 ; wraparound at 10 00E690 1 8C 14 A4 NH1: sty HISTP 00E693 1 60 rts 00E694 1 ; 00E694 1 ; ***** 3 Command - Verify Tapes ***** 00E694 1 ; verify checksum of blocks 00E694 1 20 48 E8 VECKSM: jsr WHEREI ; get the file 00E697 1 20 93 E9 jsr INALL ; check object or source 00E69A 1 C9 0D cmp #CR ; first character is CR if object 00E69C 1 D0 0E bne VECK2 ; assume source code 00E69E 1 20 93 E9 VECK1: jsr INALL ; object file 00E6A1 1 C9 3B cmp #';' 00E6A3 1 D0 F9 bne VECK1 ; ignore all chars before ';' 00E6A5 1 20 93 E9 jsr INALL 00E6A8 1 4C 60 FF jmp PAT20 00E6AB 1 EA nop 00E6AC 1 20 93 E9 VECK2: jsr INALL ; it is text 00E6AF 1 C9 0D cmp #CR 00E6B1 1 D0 F9 bne VECK2 00E6B3 1 20 93 E9 jsr INALL ; need two CR to finish 00E6B6 1 C9 0D cmp #CR 00E6B8 1 D0 F2 bne VECK2 00E6BA 1 4C 20 E5 jmp DU13 ; close file, it is ok 00E6BD 1 ; 00E6BD 1 ; ***** 1 Command - Toggle Tape 1 Control ***** 00E6BD 1 AD 00 A8 TOGTA1: lda DRB 00E6C0 1 49 10 eor #$10 ; invert PB4 00E6C2 1 8D 00 A8 sta DRB 00E6C5 1 29 10 and #$10 00E6C7 1 F0 28 beq BRK3 ; if 0 tape control is on 00E6C9 1 D0 2F bne BRK4 ; if $10 tape control is off 00E6CB 1 ; 00E6CB 1 ; ***** 2 Command - Toggle Tape 2 Control 00E6CB 1 AD 00 A8 TOGTA2: lda DRB 00E6CE 1 49 20 eor #$20 ; invert PB5 00E6D0 1 8D 00 A8 sta DRB 00E6D3 1 29 20 and #$20 00E6D5 1 F0 1A beq BRK3 00E6D7 1 D0 21 bne BRK4 00E6D9 1 ; 00E6D9 1 ; ***** V Command - Toggle Register Display Flag ***** 00E6D9 1 ; display register before execution 00E6D9 1 A2 0E REGT: ldx # $2C, CR -> $01 00E78C 1 8D 19 A4 GCN1: sta COUNT 00E78F 1 60 rts 00E790 1 ; 00E790 1 ; check if count has reached zero 00E790 1 ; COUNT = $2C means forever 00E790 1 AD 19 A4 DONE: lda COUNT ; if count = 0 we are done 00E793 1 C9 2C cmp #$2C ; this means forever 00E795 1 F0 09 beq DON1 ; set accumulator difference from zero 00E797 1 F8 sed ; decrement count in decimal 00E798 1 38 sec 00E799 1 E9 01 sbc #$01 00E79B 1 D8 cld 00E79C 1 8D 19 A4 sta COUNT 00E79F 1 60 rts 00E7A0 1 A9 2C DON1: lda #$2C 00E7A2 1 60 rts 00E7A3 1 ; 00E7A3 1 A0 00 FROM: ldy #$00 ; print 'FR=' 00E7A5 1 F0 02 beq TO1 00E7A7 1 ; 00E7A7 1 A0 05 TO: ldy #M3-M1 ; print 'TO=' 00E7A9 1 20 AF E7 TO1: jsr KEP 00E7AC 1 4C B1 EA jmp ADDNE ; get address 00E7AF 1 ; 00E7AF 1 ; print message pointed to by Y register 00E7AF 1 B9 00 E0 KEP: lda M1,y 00E7B2 1 48 pha 00E7B3 1 29 7F and #$7F ; strip off MSB 00E7B5 1 20 7A E9 jsr OUTPUT 00E7B8 1 C8 iny 00E7B9 1 68 pla 00E7BA 1 10 F3 bpl KEP ; MSB = 1 ? 00E7BC 1 60 rts 00E7BD 1 ; 00E7BD 1 ; print '*', but not to tape recorder, nor loading.... 00E7BD 1 ; paper tape or to display 00E7BD 1 AD 12 A4 PROMPT: lda INFLG ; which device (for editor) 00E7C0 1 C9 54 cmp #'T' ; no prompt if 'T' OR 'L' 00E7C2 1 4C EF FE jmp PATC11 00E7C5 1 20 42 E8 PROMP1: jsr TTYTST ; prompt only to TTY 00E7C8 1 D0 05 bne PR2 ; branch on keyboard 00E7CA 1 A9 2A lda #'*' 00E7CC 1 4C 7A E9 PR1: jmp OUTPUT ; only to terminal 00E7CF 1 A9 0D PR2: lda #CR ; clear display 00E7D1 1 4C 05 EF jmp OUTDIS 00E7D4 1 ; 00E7D4 1 A9 3F QM: lda #'?' ; print ? 00E7D6 1 D0 F4 bne PR1 00E7D8 1 ; 00E7D8 1 A9 3D EQUAL: lda #'=' ; print = 00E7DA 1 D0 F0 bne PR1 00E7DC 1 ; on delete key output slash if TTY & .... 00E7DC 1 ; back up cursor if keyboard (may need scrolling) 00E7DC 1 20 42 E8 PSLS: jsr TTYTST ; TTY or keyboard ? 00E7DF 1 F0 56 beq PSL1 ; branch on TTY 00E7E1 1 20 9E EB jsr PHXY ; save X,Y 00E7E4 1 CE 15 A4 dec CURPO2 ; decrement display pointer 00E7E7 1 AE 15 A4 ldx CURPO2 00E7EA 1 E0 14 cpx #20 ; if more than 20 just scroll them 00E7EC 1 B0 0D bcs PSL0 00E7EE 1 A9 20 lda #SPACE ;< 20, so clear cursor 00E7F0 1 20 02 EF jsr OUTDP1 00E7F3 1 CE 15 A4 dec CURPO2 00E7F6 1 4C 02 E8 jmp PSLO0 00E7F9 1 EA nop 00E7FA 1 EA nop 00E7FB 1 20 F8 FE PSL0: jsr PATC12 ; clear PRIFLG 00E7FE 1 CA dex ; one chracter less 00E7FF 1 20 2F EF jsr OUTD2A ; scroll them 00E802 1 AD 15 A4 PSLO0: lda CURPO2 ; DISBUFF -> PRIBUFF 00E805 1 C9 15 cmp #21 00E807 1 90 13 bcc PSLOB 00E809 1 C9 29 cmp #41 00E80B 1 90 07 bcc PSLOA 00E80D 1 A0 28 ldy #40 ; character 40-59 00E80F 1 E9 28 sbc #40 00E811 1 4C 1E E8 jmp PSLOC 00E814 1 A0 14 PSLOA: ldy #20 ; character 20-39 00E816 1 38 sec 00E817 1 E9 14 sbc #20 00E819 1 4C 1E E8 jmp PSLOC 00E81C 1 A0 00 PSLOB: ldy #$00 ; character 00-19 00E81E 1 8D 16 A4 PSLOC: sta CURPOS 00E821 1 A2 00 ldx #$00 00E823 1 B9 38 A4 PSLOD: lda DIBUFF,y ; transfer them 00E826 1 9D 60 A4 sta IBUFM,x 00E829 1 E8 inx 00E82A 1 C8 iny 00E82B 1 EC 16 A4 cpx CURPOS ; print pointer 00E82E 1 90 F3 bcc PSLOD 00E830 1 20 38 F0 jsr OUTPR ; clear printer buffer to the right 00E833 1 20 AC EB jsr PLXY ; restore X,Y 00E836 1 60 rts 00E837 1 A9 2F PSL1: lda #'/' ; print / 00E839 1 D0 91 bne PR1 00E83B 1 ; 00E83B 1 20 3E E8 BLANK2: jsr BLANK ; two space 00E83E 1 A9 20 BLANK: lda #SPACE 00E840 1 D0 8A bne PR1 00E842 1 ; 00E842 1 ; check TTY/keyboard switch (Z=1 FOR TTY) 00E842 1 A9 08 TTYTST: lda #$08 ; check if TTY OR keyboard 00E844 1 2C 00 A8 bit DRB ; TTY or keyboard switch = PB3 00E847 1 60 rts 00E848 1 ; 00E848 1 ; where is input coming from ? 00E848 1 ; set up for input active device 00E848 1 A0 2A WHEREI: ldy #M9-M1 ; print 'IN' 00E84A 1 20 70 E9 jsr KEPR ; output message and input character 00E84D 1 8D 12 A4 sta INFLG 00E850 1 C9 54 cmp #'T' 00E852 1 D0 08 bne WHE1 00E854 1 A2 00 ldx #$00 ; for input file flag 00E856 1 20 A2 E8 jsr FNAM ; open file for tape (1 or 2) 00E859 1 4C 2F E3 jmp LOADTA ; get file 00E85C 1 C9 4B WHE1: cmp #'K' ; tape with KIM format 00E85E 1 D0 08 bne WHE2 00E860 1 A2 00 ldx #$00 ; for input file flag 00E862 1 20 A2 E8 jsr FNAM ; open file for tape (1 or 2) 00E865 1 4C A4 E3 jmp LOADKI ; the whole file 00E868 1 C9 55 WHE2: cmp #'U' ; user RTN ? 00E86A 1 D0 04 bne WHE3 00E86C 1 18 clc ; set flag for initialisation 00E86D 1 6C 08 01 jmp (UIN) ; user input setup 00E870 1 60 WHE3: rts 00E871 1 ; 00E871 1 ; where is output going to ? 00E871 1 ; setup for output active device 00E871 1 A0 2D WHEREO: ldy #M10-M1 ; print 'OUT' 00E873 1 20 70 E9 jsr KEPR ; output message and input character 00E876 1 8D 13 A4 sta OUTFLG ; device flag 00E879 1 ; tapes 00E879 1 C9 54 cmp #'T' 00E87B 1 D0 08 bne WHRO1 00E87D 1 A2 01 ldx #$01 ; for output file flag 00E87F 1 20 A2 E8 jsr FNAM ; filename & tape (1 or 2) 00E882 1 4C 6F E5 jmp DUMPTA ; initialise file 00E885 1 C9 4B WHRO1: cmp #'K' ; tape with KIM format 00E887 1 D0 05 bne WHRO2 00E889 1 A2 01 ldx #$01 ; for output file flag 00E88B 1 4C A2 E8 jmp FNAM 00E88E 1 ; printer 00E88E 1 C9 50 WHRO2: cmp #'P' ; printer ? 00E890 1 D0 05 bne WHRO3 00E892 1 A9 0D lda #CR ; output last lien if on 00E894 1 4C 00 F0 jmp OUTPRI ; & clear printer pointer 00E897 1 ; user setup 00E897 1 C9 55 WHRO3: cmp #'U' ; user return ? 00E899 1 D0 04 bne WHRO4 00E89B 1 18 clc ; clear flag for initialisation 00E89C 1 6C 0A 01 jmp (UOUT) ; user output setup 00E89F 1 ; any other 00E89F 1 4C 13 EA WHRO4: jmp CRLOW 00E8A2 1 ; 00E8A2 1 ; get filename & tape unit 00E8A2 1 20 9E EB FNAM: jsr PHXY ; save in/out flag (X) 00E8A5 1 20 CF E8 jsr NAMO ; get name 00E8A8 1 A0 50 WHICHT: ldy #TMSG2-M1 ; print 'T=' 00E8AA 1 20 70 E9 jsr KEPR ; output message & input character 00E8AD 1 C9 0D cmp #CR 00E8AF 1 D0 02 bne TAP1 00E8B1 1 A9 31 lda #$31 ; CR => tape 1 00E8B3 1 38 TAP1: sec 00E8B4 1 E9 31 sbc #$31 ; subtract 31 00E8B6 1 30 04 bmi TAP2 ; only 1,2 OK 00E8B8 1 C9 02 cmp #$02 00E8BA 1 30 06 bmi TAP3 ; OK 00E8BC 1 20 D4 E7 TAP2: jsr QM ; error 00E8BF 1 4C A8 E8 jmp WHICHT 00E8C2 1 20 AC EB TAP3: jsr PLXY ; in/out flag 00E8C5 1 9D 34 A4 sta TAPIN,x ; if X=0 ->TAPIN (tape 1 or 2) 00E8C8 1 20 83 FE jsr CUREAD ; get anything 00E8CB 1 20 24 EA jsr CRCK ; CR 00E8CE 1 60 rts ; if X=1 ->TAPOUT (tape 1 or 2) 00E8CF 1 ; 00E8CF 1 ; get filename 00E8CF 1 A0 4D NAMO: ldy #TMSG1-M1 ; print 'F=' 00E8D1 1 20 AF E7 jsr KEP ; no CRLF 00E8D4 1 A0 00 ldy #$00 00E8D6 1 20 5F E9 NAMO1: jsr RDRUB ; get character 00E8D9 1 C9 0D cmp #CR ; done ? 00E8DB 1 F0 0C beq NAMO2 00E8DD 1 C9 20 cmp #SPACE 00E8DF 1 F0 08 beq NAMO2 00E8E1 1 99 2E A4 sta NAME,y ; store 00E8E4 1 C8 iny 00E8E5 1 C0 05 cpy #$05 00E8E7 1 D0 ED bne NAMO1 00E8E9 1 ; blank rest of name 00E8E9 1 A9 20 NAMO2: lda #SPACE 00E8EB 1 C0 05 NAMO3: cpy #$05 00E8ED 1 F0 06 beq NAMO4 00E8EF 1 99 2E A4 sta NAME,y 00E8F2 1 C8 iny 00E8F3 1 D0 F6 bne NAMO3 00E8F5 1 4C 3E E8 NAMO4: jmp BLANK 00E8F8 1 ; 00E8F8 1 ; set input from terminal (keyboard OR TTY) 00E8F8 1 A9 0D INLOW: lda #CR 00E8FA 1 8D 12 A4 sta INFLG 00E8FD 1 60 rts 00E8FE 1 ; 00E8FE 1 ; set I/O to terminal (keyboard & display/printer, or TTY) 00E8FE 1 20 F8 E8 LL: jsr INLOW 00E901 1 ; 00E901 1 ; set output to terminal (display/printer or TTY) 00E901 1 A9 0D OUTLOW: lda #CR 00E903 1 8D 13 A4 sta OUTFLG 00E906 1 60 OUTL1: rts 00E907 1 ; 00E907 1 ; on (escape) stops execution & back to monitor 00E907 1 ; on (space) stops execution & continue on any other key 00E907 1 20 42 E8 RCHEK: jsr TTYTST ; TTY or keyboard ? 00E90A 1 F0 1A beq RCHTTY 00E90C 1 20 EF EC jsr ROONEK ; clear mask & get a key 00E90F 1 88 dey 00E910 1 30 13 bmi RCH3 ; return on no key 00E912 1 A2 00 ldx #$00 00E914 1 20 82 EC jsr GETK2 ; get the key 00E917 1 C9 1B cmp #ESCAPE 00E919 1 F0 3B beq REA1 ; to command & set I/O to terminal 00E91B 1 C9 20 cmp #SPACE ; wait key 00E91D 1 D0 06 bne RCH3 ; return, ignore other keys 00E91F 1 20 EF EC RCH2: jsr ROONEK ; wait till he releases it & 00E922 1 88 dey ; quit waiting on next key 00E923 1 30 FA bmi RCH2 00E925 1 60 RCH3: rts 00E926 1 70 13 RCHTTY: BVS RCHT1 ; TTI=PB6 -> V (overflow flag) 00E928 1 2C 00 A8 RCHT2: bit DRB ; wait till he release it 00E92B 1 50 FB bvc RCHT2 00E92D 1 20 0F EC jsr DELAY 00E930 1 20 DB EB jsr GETTTY ; get a character 00E933 1 C9 1B cmp #ESCAPE 00E935 1 F0 1F beq REA1 ; to command 00E937 1 C9 20 cmp #SPACE 00E939 1 D0 ED bne RCHT2 00E93B 1 60 RCHT1: rts ; quit waiting on any key 00E93C 1 ; 00E93C 1 ; read one character from keyboard/TTY and preserve X,Y 00E93C 1 20 9E EB READ: jsr PHXY ; push X & Y 00E93F 1 20 42 E8 jsr TTYTST ; TTY or keyboard ? 00E942 1 D0 06 bne READ1 00E944 1 20 DB EB jsr GETTTY 00E947 1 4C 4D E9 jmp READ2 00E94A 1 20 40 EC READ1: jsr GETKEY 00E94D 1 20 AC EB READ2: jsr PLXY ; pull X & Y 00E950 1 29 7F and #$7F ; strip parity 00E952 1 C9 1B cmp #ESCAPE 00E954 1 D0 E5 bne RCHT1 ; return 00E956 1 20 3D FF REA1: jsr PATC18 ; CR and clear buffers 00E959 1 4C A1 E1 jmp COMIN ; both I/O to terminal 00E95C 1 ; 00E95C 1 ; read with rubout or delete possible 00E95C 1 20 DC E7 RB2: jsr PSLS ; slash or back space 00E95F 1 20 83 FE RDRUB: jsr CUREAD 00E962 1 C9 08 cmp #RUB ; rubout 00E964 1 F0 04 beq RDR1 00E966 1 C9 7F cmp #$7F ; also delete 00E968 1 D0 0C bne RED2 ; echo if not CR 00E96A 1 ; rubout to delete character 00E96A 1 88 RDR1: dey 00E96B 1 10 EF bpl RB2 00E96D 1 C8 iny 00E96E 1 F0 EF beq RDRUB 00E970 1 ; 00E970 1 ; output message then input character 00E970 1 20 AF E7 KEPR: jsr KEP 00E973 1 ; 00E973 1 ; read and echo a char from keyboard or TTY 00E973 1 20 83 FE REDOUT: jsr CUREAD 00E976 1 C9 0D RED2: cmp #CR 00E978 1 F0 C1 beq RCHT1 ; do not echo CR 00E97A 1 ; 00E97A 1 ; outputs a character to either TTY or display/printer 00E97A 1 48 OUTPUT: pha ; save it 00E97B 1 AD 11 A4 OUT1: lda PRIFLG ; if LSB=1 output only to display 00E97E 1 29 01 and #$01 00E980 1 F0 04 beq OUT1A 00E982 1 68 pla 00E983 1 4C 02 EF jmp OUTDP1 ; only to display 00E986 1 20 42 E8 OUT1A: jsr TTYTST ; TTY or keyboard ? 00E989 1 D0 04 bne OUT2 00E98B 1 68 pla 00E98C 1 4C A8 EE jmp OUTTTY ; to TTY 00E98F 1 68 OUT2: pla 00E990 1 4C FC EE jmp OUTDP ; to display & printer 00E993 1 ; 00E993 1 ; get a character from current input device (set on INFLG) 00E993 1 AD 12 A4 INALL: lda INFLG 00E996 1 C9 54 cmp #'T' 00E998 1 D0 03 bne *+5 00E99A 1 4C 3B ED jmp TIBYTE ; character from buffer 00E99D 1 C9 4B cmp #'K' ; with KIM format 00E99F 1 D0 03 bne *+5 00E9A1 1 4C 29 EE jmp GETTAP ; directly from tape 00E9A4 1 C9 4D cmp #'M' ; memory for assembler ? 00E9A6 1 D0 03 bne *+5 00E9A8 1 4C D0 FA jmp MREAD 00E9AB 1 C9 55 cmp #'U' ; user routine ? 00E9AD 1 D0 04 bne *+6 00E9AF 1 38 sec ; set flag for normal input 00E9B0 1 6C 08 01 jmp (UIN) 00E9B3 1 C9 4C cmp #'L' ; to load paper tape 00E9B5 1 D0 A8 bne RDRUB 00E9B7 1 4C DB EB jmp GETTTY ; from TTY 00E9BA 1 ; 00E9BA 1 A9 3B SEMI: lda #';' ; output a ';' 00E9BC 1 ; write a character to output device (set on OUTFLG) 00E9BC 1 48 OUTALL: pha 00E9BD 1 AD 13 A4 lda OUTFLG 00E9C0 1 ; tape by blocks 00E9C0 1 C9 54 cmp #'T' ; tapes ? 00E9C2 1 D0 04 bne OUTA1 00E9C4 1 68 pla 00E9C5 1 4C 8B F1 jmp TOBYTE ; output one character to tape buffer 00E9C8 1 ; tape KIM format 00E9C8 1 C9 4B OUTA1: cmp #'K' ; KIM-1 ? 00E9CA 1 D0 04 bne OUTA2 00E9CC 1 68 pla 00E9CD 1 4C 4A F2 jmp OUTTAP 00E9D0 1 ; printer 00E9D0 1 C9 50 OUTA2: cmp #'P' ; printer ? 00E9D2 1 D0 0E bne OUTA3 00E9D4 1 38 sec ; turn printer on 00E9D5 1 6E 11 A4 ROR PRIFLG 00E9D8 1 68 pla 00E9D9 1 08 PHP 00E9DA 1 20 00 F0 jsr OUTPRI 00E9DD 1 28 PLP 00E9DE 1 2E 11 A4 ROL PRIFLG ; restore flag 00E9E1 1 60 rts 00E9E2 1 ; user defined 00E9E2 1 C9 55 OUTA3: cmp #'U' ; user routine ? 00E9E4 1 D0 04 bne OUTA4 00E9E6 1 38 sec ; set flag for normal output 00E9E7 1 6C 0A 01 jmp (UOUT) ; yes 00E9EA 1 ; nowhere or to TTY, display/printer 00E9EA 1 C9 58 OUTA4: cmp #'X' ; eat it ? 00E9EC 1 D0 8D bne OUT1 ; output to TTY or display/printer 00E9EE 1 68 pla 00E9EF 1 60 rts 00E9F0 1 ; 00E9F0 1 ; This routine outputs a CRLF to any output device 00E9F0 1 ; LF and NULL is sent only to TTY 00E9F0 1 A9 0D CRLF: lda #CR 00E9F2 1 20 BC E9 jsr OUTALL 00E9F5 1 20 42 E8 jsr TTYTST ; TTY or keyboard ? 00E9F8 1 D0 29 bne CR2J 00E9FA 1 AD 13 A4 lda OUTFLG ; LF only to TTY 00E9FD 1 C9 54 cmp #'T' 00E9FF 1 F0 22 beq CR2J 00EA01 1 C9 4B cmp #'K' 00EA03 1 F0 1E beq CR2J 00EA05 1 C9 50 cmp #'P' 00EA07 1 F0 1A beq CR2J 00EA09 1 A9 0A lda #LF 00EA0B 1 20 BC E9 jsr OUTALL 00EA0E 1 A9 FF lda #NULLC 00EA10 1 4C BC E9 jmp OUTALL 00EA13 1 ; 00EA13 1 ; CR LF to terminal (TTY or display/printer) only 00EA13 1 48 CRLOW: pha ; save A 00EA14 1 AD 13 A4 lda OUTFLG 00EA17 1 48 pha 00EA18 1 20 01 E9 jsr OUTLOW 00EA1B 1 20 F0 E9 jsr CRLF 00EA1E 1 68 pla 00EA1F 1 8D 13 A4 sta OUTFLG 00EA22 1 68 pla 00EA23 1 60 CR2J: rts 00EA24 1 ; 00EA24 1 ; Output (CR) to TTY if switch on TTY & INFLG not 1 00EA24 1 ; don't clear display but clear pointers for next line 00EA24 1 ; if printer has printed on 21st character don't output CR 00EA24 1 AD 12 A4 CRCK: lda INFLG ; no CR if 'L' 00EA27 1 C9 4C cmp #'L' 00EA29 1 D0 01 bne CRCK1 00EA2B 1 60 rts 00EA2C 1 20 42 E8 CRCK1: jsr TTYTST ; check if TTY OR keyboard 00EA2F 1 F0 E2 beq CRLOW ; branch if TTY 00EA31 1 ; if printer PTR=0, do not clear printer 00EA31 1 AD 16 A4 lda CURPOS 00EA34 1 F0 05 beq CRCK2 ; if PTR=0, no CR 00EA36 1 A9 0D lda #CR 00EA38 1 20 00 F0 jsr OUTPRI 00EA3B 1 A9 8D CRCK2: lda #$8D ; CR only for TV 00EA3D 1 4C 02 EF jmp OUTDP1 00EA40 1 EA nop 00EA41 1 EA nop 00EA42 1 ; 00EA42 1 ; write A then X in ASCII to the output device 00EA42 1 20 46 EA WRAX: jsr NUMA 00EA45 1 8A txa 00EA46 1 ; 00EA46 1 ; Print one byte = two ASCII characters to output device 00EA46 1 48 NUMA: pha 00EA47 1 4A lsr a 00EA48 1 4A lsr a 00EA49 1 4A lsr a 00EA4A 1 4A lsr a 00EA4B 1 20 51 EA jsr NOUT 00EA4E 1 68 pla 00EA4F 1 29 0F and #$F 00EA51 1 18 NOUT: clc 00EA52 1 69 30 adc #$30 00EA54 1 C9 3A cmp #$3A 00EA56 1 90 02 bcc LT10 00EA58 1 69 06 adc #$06 ; carry is set 00EA5A 1 4C BC E9 LT10: jmp OUTALL 00EA5D 1 ; 00EA5D 1 ; read two characters & pack them into one byte 00EA5D 1 ; part of alter memory , / command 00EA5D 1 20 73 E9 RD2: jsr REDOUT 00EA60 1 C9 0D cmp #CR ; CR ? 00EA62 1 F0 17 beq RSPAC 00EA64 1 C9 20 cmp #' ' ; for memory alter 00EA66 1 F0 13 beq RSPAC 00EA68 1 C9 2E cmp #'.' ; treat '.' as (SPACE) 00EA6A 1 D0 04 bne RD1 00EA6C 1 A9 20 lda #$20 00EA6E 1 D0 0B bne RSPAC 00EA70 1 20 84 EA RD1: jsr PACK 00EA73 1 B0 06 bcs RSPAC 00EA75 1 20 73 E9 jsr REDOUT 00EA78 1 4C 84 EA jmp PACK 00EA7B 1 ; was SPACE or CR 00EA7B 1 38 RSPAC: sec 00EA7C 1 60 rts 00EA7D 1 ; 00EA7D 1 ; convert A in ASCII to A in hex (4 MSB=0) 00EA7D 1 48 HEX: pha ; save A 00EA7E 1 A9 00 lda #$00 ; clear STIY if hex 00EA80 1 8D 29 A4 sta STIY+2 ; because only once 00EA83 1 68 pla 00EA84 1 ; pack two ASCII into one hex (call subroutine twice) 00EA84 1 ; result is given on A with first character into 4 MSB 00EA84 1 C9 30 PACK: cmp #$30 ; < 30 ? 00EA86 1 90 F3 bcc RSPAC 00EA88 1 C9 47 cmp #$47 ; > 47 ? 00EA8A 1 B0 EF bcs RSPAC 00EA8C 1 C9 3A cmp #$3A ; < #10 00EA8E 1 90 06 bcc PAK1 00EA90 1 C9 40 cmp #$40 ; > #10 ? 00EA92 1 90 E7 bcc RSPAC 00EA94 1 69 08 adc #$08 ; add 0 is letter (C is set) 00EA96 1 2A PAK1: ROL a ; shift A 4 times 00EA97 1 2A ROL a 00EA98 1 2A ROL a 00EA99 1 2A ROL a 00EA9A 1 8E 2D A4 stx CPIY+3 ; save X 00EA9D 1 A2 04 ldx #$04 00EA9F 1 2A PAK2: ROL a ; transfer A to STIY 00EAA0 1 2E 29 A4 ROL STIY+2 ; thru carry 00EAA3 1 CA dex 00EAA4 1 D0 F9 bne PAK2 00EAA6 1 AE 2D A4 ldx CPIY+3 ; restore X 00EAA9 1 AD 29 A4 lda STIY+2 00EAAC 1 18 clc 00EAAD 1 60 rts 00EAAE 1 ; 00EAAE 1 ; Get four byte address, take last four characters to 00EAAE 1 ; calculate address allow delete also 00EAAE 1 20 D8 E7 ADDIN: jsr EQUAL 00EAB1 1 AD 15 A4 ADDNE: lda CURPO2 ; save position 00EAB4 1 48 pha 00EAB5 1 A0 00 ldy #$00 00EAB7 1 20 5F E9 ADDN1: jsr RDRUB 00EABA 1 C9 0D cmp #CR 00EABC 1 F0 09 beq ADDN2 00EABE 1 C9 20 cmp #' ' 00EAC0 1 F0 05 beq ADDN2 00EAC2 1 C8 iny 00EAC3 1 C0 0B cpy #11 ; allow 10 00EAC5 1 90 F0 bcc ADDN1 00EAC7 1 68 ADDN2: pla 00EAC8 1 8D 2D A4 sta CPIY+3 ; save 00EACB 1 C0 00 cpy #$00 ; if first character put default values 00EACD 1 D0 0D bne ADDN3 00EACF 1 A9 02 lda #$02 00EAD1 1 8D 1D A4 sta ADDR+1 ; default of 0200 00EAD4 1 8D 1E A4 sta CKSUM ; default 00EAD7 1 8C 1C A4 sty ADDR 00EADA 1 18 clc 00EADB 1 60 rts 00EADC 1 A2 00 ADDN3: ldx #$00 00EADE 1 88 dey ; Y-4 00EADF 1 88 dey 00EAE0 1 88 dey 00EAE1 1 88 dey 00EAE2 1 10 13 bpl ADDN5 ; branch if > 4 CHR 00EAE4 1 98 tya 00EAE5 1 49 FF eor #$FF 00EAE7 1 A8 TAY ; number of leading 0 00EAE8 1 A9 30 ADDN4: lda #$30 00EAEA 1 9D 1C A4 sta ADDR,x 00EAED 1 E8 inx 00EAEE 1 88 dey 00EAEF 1 10 F7 bpl ADDN4 00EAF1 1 AC 2D A4 ldy CPIY+3 ; now the character 00EAF4 1 4C FD EA jmp ADDN6 00EAF7 1 98 ADDN5: tya ; put character 00EAF8 1 18 clc 00EAF9 1 6D 2D A4 adc CPIY+3 00EAFC 1 A8 TAY 00EAFD 1 B9 38 A4 ADDN6: lda DIBUFF,y ; from display buffer 00EB00 1 9D 1C A4 sta ADDR,x 00EB03 1 C8 iny 00EB04 1 E8 inx 00EB05 1 E0 04 cpx #$04 00EB07 1 D0 F4 bne ADDN6 00EB09 1 A2 01 ldx #$01 00EB0B 1 A0 00 ldy #$00 ; convert character to hex 00EB0D 1 B9 1C A4 ADDN7: lda ADDR,y 00EB10 1 20 7D EA jsr HEX 00EB13 1 B0 16 bcs ADDN8 00EB15 1 C8 iny 00EB16 1 B9 1C A4 lda ADDR,y 00EB19 1 C8 iny 00EB1A 1 20 84 EA jsr PACK ; pack two characters into one byte 00EB1D 1 B0 0C bcs ADDN8 ; branch if error 00EB1F 1 9D 1C A4 sta ADDR,x 00EB22 1 CA dex 00EB23 1 10 E8 bpl ADDN7 00EB25 1 E8 inx ; X=0 00EB26 1 8E 1E A4 stx CKSUM ; to indicate we got an address 00EB29 1 18 clc ; no invalid characters 00EB2A 1 60 rts 00EB2B 1 20 94 E3 ADDN8: jsr CKERO0 ; output error message 00EB2E 1 20 24 EA jsr CRCK ; CR 00EB31 1 38 sec ; set Carry for invalid character 00EB32 1 60 rts 00EB33 1 ; 00EB33 1 ; memory fail to write message & specific address 00EB33 1 20 24 EA MEMERR: jsr CRCK 00EB36 1 20 CD E2 jsr NXTADD ; add Y to ADDR+1,ADDR 00EB39 1 A0 31 ldy #M11-M1 ; print 'MEM FAIL' 00EB3B 1 20 AF E7 jsr KEP ; fail message 00EB3E 1 20 DB E2 jsr WRITAZ ; print ADDR+1, ADDR 00EB41 1 4C A1 E1 jmp COMIN 00EB44 1 ; 00EB44 1 ; clear display & printer pointers 00EB44 1 A9 00 CLR: lda #$00 00EB46 1 8D 15 A4 sta CURPO2 ; display pointer 00EB49 1 8D 16 A4 sta CURPOS ; printer pointer 00EB4C 1 60 rts 00EB4D 1 ; 00EB4D 1 ; clear checksum 00EB4D 1 A9 00 CLRCK: lda #$00 00EB4F 1 8D 1F A4 sta CKSUM+1 00EB52 1 8D 1E A4 sta CKSUM 00EB55 1 60 rts 00EB56 1 ; 00EB56 1 ; Code for page zero simulation 00EB56 1 ; subroutine lLDAY simulates lda (n),y instruction without page 0 00EB56 1 ; by putting indirect address into RAM & then exec lda nm,y 00EB56 1 A9 25 PCLLD: lda #V 00EBE5 1 70 FB BVS GET1 ; wait for start bit 00EBE7 1 20 0F EC jsr DELAY ; delay one bit 00EBEA 1 20 23 EC jsr DEHALF ; delay 1/2 bit time 00EBED 1 AD 00 A8 GET3: lda DRB ; get 8-bits 00EBF0 1 29 40 and #$40 ; mask off other bits, only PB6 00EBF2 1 4E 2A A4 LSR CPIY ; shift right character 00EBF5 1 0D 2A A4 ORA CPIY 00EBF8 1 8D 2A A4 sta CPIY 00EBFB 1 20 0F EC jsr DELAY ; delay one bit time 00EBFE 1 CA dex 00EBFF 1 D0 EC bne GET3 ; get next bit 00EC01 1 20 0F EC jsr DELAY ; do not care for parity bit 00EC04 1 20 23 EC jsr DEHALF ; until we get back to one again 00EC07 1 68 pla ; restore X 00EC08 1 AA tax 00EC09 1 AD 2A A4 lda CPIY 00EC0C 1 29 7F and #$7F ; clear parity bit 00EC0E 1 60 rts 00EC0F 1 ; 00EC0F 1 ; delay one bit time as given by baud rate 00EC0F 1 AD 18 A4 DELAY: lda CNTL30 ; start timer T2 00EC12 1 8D 08 A8 sta T2L 00EC15 1 AD 17 A4 lda CNTH30 00EC18 1 8D 09 A8 DE1: sta T2H 00EC1B 1 AD 0D A8 DE2: lda IFR ; get interrupt flag for T2 00EC1E 1 29 20 and #MT2 00EC20 1 F0 F9 beq DE2 ; timeout ? 00EC22 1 60 rts 00EC23 1 ; 00EC23 1 ; delay half bit time 00EC23 1 ; total time divided by 2 00EC23 1 AD 17 A4 DEHALF: lda CNTH30 00EC26 1 4A lsr a ; LSB to carry 00EC27 1 AD 18 A4 lda CNTL30 00EC2A 1 6A ror a ; shift with carry 00EC2B 1 8D 08 A8 sta T2L 00EC2E 1 AD 17 A4 lda CNTH30 00EC31 1 4A lsr a 00EC32 1 8D 09 A8 sta T2H 00EC35 1 4C 1B EC jmp DE2 00EC38 1 ; 00EC38 1 A9 00 GETKDO: lda #$00 00EC3A 1 8D 77 A4 sta IDOT ; go another 90 dots 00EC3D 1 20 50 F0 jsr IPO0 ; output 90 dots to printer (zeros) 00EC40 1 ; 00EC40 1 ; get character from keyboard subroutine 00EC40 1 ; from keyboard y=row ,stbkey=columns (strobe) 00EC40 1 ; x=Ctrl or Shift, otherwise x=0 00EC40 1 20 EF EC GETKEY: jsr ROONEK ; wait if last key still down 00EC43 1 20 2A ED GETKY: jsr DEBKEY ; debounce key (5msec) 00EC46 1 ; Ctrl or Shift ? 00EC46 1 A9 8F lda #$8F ; check column 5,6,7 00EC48 1 8D 80 A4 sta DRA2 00EC4B 1 AD 82 A4 lda DRB2 ; check row 1 00EC4E 1 4A lsr a 00EC4F 1 B0 20 bcs GETK1 ; if=1, no ctrl or shift 00EC51 1 A2 03 ldx #$03 ; column 5,6,7 (Ctrl, ShiftL, ShiftR) 00EC53 1 A9 7F lda #$7F ; Ctrl or Shift, so which one ? 00EC55 1 38 GETKO: sec 00EC56 1 6A ror a 00EC57 1 48 pha 00EC58 1 20 0B ED jsr ONEK2 ; lets get Ctrl or Shift into X 00EC5B 1 AD 82 A4 lda DRB2 00EC5E 1 4A lsr a ; only one row 00EC5F 1 90 06 bcc GETKOO ; got you 00EC61 1 68 pla 00EC62 1 CA dex 00EC63 1 D0 F0 bne GETKO 00EC65 1 F0 DC beq GETKY ; there is a mistake check again 00EC67 1 68 GETKOO: pla ; now get stbkey into X 00EC68 1 AD 2B A4 lda STBKEY ; column into X 00EC6B 1 49 FF eor #$FF ; complement because strobes are 0 00EC6D 1 AA tax ; Ctrl or Shift to X 00EC6E 1 EE 2A A4 inc KMASK ; set mask=$01 00EC71 1 ; now get any key 00EC71 1 20 05 ED GETK1: jsr ONEKEY ; get a key 00EC74 1 88 dey ; check the row (1-8) 00EC75 1 D0 09 bne GETK1B ; check if Ctrl or Shift 00EC77 1 AD 2B A4 lda STBKEY ; were entered at the last moment 00EC7A 1 C9 F7 cmp #$F7 ; if column 5,6,7,8 do it again 00EC7C 1 B0 04 bcs GETK2 00EC7E 1 90 C3 bcc GETKY ; send it to get Ctrl or Shift 00EC80 1 30 C1 GETK1B: bmi GETKY ; no key, clear mask 00EC82 1 ; we have a key, decode it 00EC82 1 20 2C ED GETK2: jsr DEBK1 ; debounce key (5msec) 00EC85 1 98 tya ; multiply by 8 00EC86 1 0A asl a 00EC87 1 0A asl a 00EC88 1 0A asl a 00EC89 1 A8 tay ; now Y has row address from row one 00EC8A 1 AD 2B A4 lda STBKEY ; add column to Y 00EC8D 1 4A GETK3: lsr a 00EC8E 1 90 03 bcc GETK4 00EC90 1 C8 iny 00EC91 1 D0 FA bne GETK3 00EC93 1 B9 21 F4 GETK4: lda ROW1,y ; get the character 00EC96 1 48 pha 00EC97 1 8A txa ; see if Ctrl or Shift was used 00EC98 1 F0 24 beq GETK7 ; barch if no Ctrl or Shift 00EC9A 1 29 10 and #$10 ; Ctrl ? 00EC9C 1 F0 06 beq GETK5 ; no, go GETK5 00EC9E 1 68 pla 00EC9F 1 29 3F and #$3F ; mask off two MSB from control 00ECA1 1 4C BF EC jmp GETK8 ; exit 00ECA4 1 68 GETK5: pla 00ECA5 1 48 pha ; save it 00ECA6 1 29 40 and #$40 ; if alpha characters do not Shift 00ECA8 1 D0 14 bne GETK7 00ECAA 1 68 pla 00ECAB 1 48 pha 00ECAC 1 29 0F and #$0F ; only LSB 00ECAE 1 F0 0E beq GETK7 ; do not interchange SPACE or 0 00ECB0 1 C9 0C cmp #$0C ; A >= $0C ? 00ECB2 1 B0 05 bcs GETK6 ; yes A >= $0C 00ECB4 1 68 pla ; no, A < $0C 00ECB5 1 29 EF and #$EF ; strip off bit 4 00ECB7 1 D0 06 bne GETK8 ; exit 00ECB9 1 68 GETK6: pla ; A >= $0C 00ECBA 1 09 10 ora #$10 ; bit 4 = 1 00ECBC 1 D0 01 bne GETK8 ; exit 00ECBE 1 68 GETK7: pla 00ECBF 1 ; check for "ADV PAP", "PRI LINE", or "TOGL PRIFLG" 00ECBF 1 ; in this way we don't have to check for this command 00ECBF 1 C9 60 GETK8: cmp #$60 ; advance paper command 00ECC1 1 D0 06 bne GETK11 00ECC3 1 E0 00 cpx #$00 ; if Shift is not advance paper 00ECC5 1 F0 25 beq GETK10 ; no Shift, so advance paper 00ECC7 1 29 4F and #$4F ; convert to "@" 00ECC9 1 C9 1C GETK11: cmp #$1C ; see if toggle PRIFLG (control printer) 00ECCB 1 D0 14 bne GETK13 00ECCD 1 20 E1 E6 jsr PRITR ; go toggle flag 00ECD0 1 A0 01 ldy #$01 ; get the pointers back 3 spaces 00ECD2 1 B9 15 A4 GETK12: lda CURPO2,y 00ECD5 1 38 sec 00ECD6 1 E9 03 sbc #$03 ; because 'ON,OFF' messages 00ECD8 1 99 15 A4 sta CURPO2,y 00ECDB 1 88 dey 00ECDC 1 10 F4 bpl GETK12 00ECDE 1 4C 40 EC jmp GETKEY 00ECE1 1 C9 5C GETK13: cmp #'\' ; print line command 00ECE3 1 D0 06 bne GETK14 00ECE5 1 20 4A F0 jsr IPSO ; print whatever is in buffer 00ECE8 1 4C 40 EC jmp GETKEY 00ECEB 1 60 GETK14: rts 00ECEC 1 4C 38 EC GETK10: jmp GETKDO 00ECEF 1 ; 00ECEF 1 ; wait if last key still down (rollover) 00ECEF 1 AD 82 A4 ROONEK: lda DRB2 ; see if key still down 00ECF2 1 C9 FF cmp #$FF 00ECF4 1 F0 0A beq R001 ; no key at all, clear ROLLFL 00ECF6 1 0D 7F A4 ora ROLLFL ; accept only last key 00ECF9 1 49 FF eor #$FF ; strobes are zero so iner 00ECFB 1 D0 F2 bne ROONEK 00ECFD 1 20 2A ED jsr DEBKEY ; clear KMASK & debounce release 00ED00 1 A9 00 R001: lda #$00 ; clear KMASK 00ED02 1 8D 2A A4 sta KMASK 00ED05 1 ; go through keyboard once and return, if any 00ED05 1 ; key Y=row (1-8) & STRBKEY=column 00ED05 1 ; if no key Y=0, STBKEY=$FF 00ED05 1 A9 7F ONEKEY: lda #$7F ; first strobe to MSB 00ED07 1 D0 02 bne ONEK2 ; start at ONEK2 00ED09 1 38 ONEK1: sec ; only one pulse (zero) 00ED0A 1 6A ror a ; shift to right 00ED0B 1 8D 80 A4 ONEK2: sta DRA2 ; output column strobe 00ED0E 1 8D 2B A4 sta STBKEY ; save it 00ED11 1 A0 08 ldy #$08 ; check 8 rows 00ED13 1 AD 82 A4 lda DRB2 ; any key ? 00ED16 1 0D 2A A4 ora KMASK ; disable row 1 if Ctrl or Shift 00ED19 1 8D 7F A4 sta ROLLFL ; save which key it was 00ED1C 1 0A ONEK3: asl a 00ED1D 1 90 0A bcc ONEK4 ; jump if key (zero) 00ED1F 1 88 dey 00ED20 1 D0 FA bne ONEK3 00ED22 1 AD 2B A4 lda STBKEY 00ED25 1 C9 FF cmp #$FF ; last column ? 00ED27 1 D0 E0 bne ONEK1 ; no, do next column 00ED29 1 60 ONEK4: rts 00ED2A 1 ; 00ED2A 1 A2 00 DEBKEY: ldx #$00 ; clear Ctrl or Shift 00ED2C 1 A9 00 DEBK1: lda #$00 ; clear mask 00ED2E 1 8D 2A A4 sta KMASK 00ED31 1 A9 88 lda #DEBTIM 00ED38 1 4C 18 EC jmp DE1 ; wait for 5msec 00ED3B 1 ; 00ED3B 1 ; Get a character from tape subroutine 00ED3B 1 ; a buffer is used to get blocks of data 00ED3B 1 ; from tape, except when format equal to 00ED3B 1 ; KIM-1 (the whole file is loaded at one time) 00ED3B 1 20 9E EB TIBYTE: jsr PHXY ; push X 00ED3E 1 AE 36 A4 ldx TAPTR ; pointer for buffer 00ED41 1 E0 50 cpx #80 ; is buffer empty ? 00ED43 1 D0 03 bne TIB1 00ED45 1 20 53 ED jsr TIBY1 ; load another block 00ED48 1 BD 16 01 TIB1: lda TABUFF,x 00ED4B 1 E8 inx 00ED4C 1 8E 36 A4 stx TAPTR 00ED4F 1 20 AC EB jsr PLXY ; pull X 00ED52 1 60 rts 00ED53 1 ; load a block from tape into buffer 00ED53 1 20 EA ED TIBY1: jsr TAISET ; set tape for input 00ED56 1 20 29 EE TIBY3: jsr GETTAP ; get a character from tape 00ED59 1 C9 23 cmp #'#' ; check first character for 00ED5B 1 F0 06 beq TIBY4 ; start of block 00ED5D 1 C9 16 cmp #$16 ; if not should be sync 00ED5F 1 D0 F2 bne TIBY1 00ED61 1 F0 F3 beq TIBY3 00ED63 1 A2 00 TIBY4: ldx #$00 00ED65 1 20 29 EE TIBY5: jsr GETTAP ; now load into buffer 00ED68 1 9D 16 01 sta TABUFF,x 00ED6B 1 E8 inx 00ED6C 1 E0 52 cpx #82 00ED6E 1 D0 F5 bne TIBY5 00ED70 1 AD 00 A8 lda DRB 00ED73 1 29 CF and #$CF 00ED75 1 8D 00 A8 sta DRB ; turn off tapes 00ED78 1 58 cli ; enable interrupts 00ED79 1 20 BD ED jsr ADDBK1 ; display block count 00ED7C 1 A2 00 ldx #$00 ; to clear pointer in TIBYTE 00ED7E 1 AD 15 01 lda BLK ; check the block count 00ED81 1 F0 05 beq TIBY5A ; if first block, do not compare 00ED83 1 DD 16 01 cmp TABUFF,x 00ED86 1 D0 28 bne TIBY7 ; branch if we missed one block 00ED88 1 E8 TIBY5A: inx 00ED89 1 8E 36 A4 stx TAPTR 00ED8C 1 EE 15 01 inc BLK ; increment block count 00ED8F 1 AD 67 01 lda TABUFF+81 ; store this block checksum 00ED92 1 48 pha 00ED93 1 AD 66 01 lda TABUFF+80 00ED96 1 48 pha 00ED97 1 CE 12 A4 dec INFLG ; set INFLG diff from OUTFLG 00ED9A 1 20 E7 F1 jsr BKCKSM ; compute block checksum for this block 00ED9D 1 68 pla 00ED9E 1 CD 66 01 cmp TABUFF+80 ; do they agree ? 00EDA1 1 D0 0C bne TIBY6 00EDA3 1 68 pla 00EDA4 1 CD 67 01 cmp TABUFF+81 00EDA7 1 D0 07 bne TIBY7 00EDA9 1 EE 12 A4 inc INFLG ; restore input device 00EDAC 1 A2 01 ldx #$01 ; to get first character in TIBYTE 00EDAE 1 60 rts 00EDAF 1 68 TIBY6: pla ; restore stack pointer 00EDB0 1 68 TIBY7: pla 00EDB1 1 68 pla 00EDB2 1 68 pla 00EDB3 1 68 pla 00EDB4 1 20 8E E3 jsr CKERO 00EDB7 1 4C A1 E1 jmp COMIN 00EDBA 1 ; 00EDBA 1 ; add 1 to block count and output it 00EDBA 1 EE 15 01 ADDBLK: inc BLK ; increment block count 00EDBD 1 EE 11 A4 ADDBK1: inc PRIFLG ; so don't output to printer 00EDC0 1 A9 12 lda #18 ; only output in this position 00EDC2 1 8D 15 A4 sta CURPO2 00EDC5 1 AD 4A A4 lda DIBUFF+18 ; save DISBUFF (for edit) 00EDC8 1 48 pha 00EDC9 1 AD 4B A4 lda DIBUFF+19 00EDCC 1 48 pha 00EDCD 1 AE 13 A4 ldx OUTFLG ; save OUTFLG 00EDD0 1 A9 0D lda #CR 00EDD2 1 8D 13 A4 sta OUTFLG ; to output to terminal 00EDD5 1 AD 16 01 lda BLK+1 ; blk count coming from tape 00EDD8 1 20 46 EA jsr NUMA ; output in ASCII 00EDDB 1 8E 13 A4 stx OUTFLG ; restore OUTFLG 00EDDE 1 68 pla 00EDDF 1 8D 4B A4 sta DIBUFF+19 00EDE2 1 68 pla 00EDE3 1 8D 4A A4 sta DIBUFF+18 00EDE6 1 CE 11 A4 dec PRIFLG ; restore PRIFLG 00EDE9 1 60 rts 00EDEA 1 ; 00EDEA 1 ; set tape (1 or 2) for input 00EDEA 1 A9 37 TAISET: lda #$37 ; set PB7 for input 00EDEC 1 8D 02 A8 sta DDRB 00EDEF 1 AD 34 A4 lda TAPIN ; input flag (tape 1=0 or tape 2=1) 00EDF2 1 20 1C EE jsr TIOSET ; reset PB4 or PB5 00EDF5 1 A9 EE lda #MOFF+DATIN ; set CA2=1 (data in) 00EDF7 1 8D 0C A8 sta PCR 00EDFA 1 A9 FF lda #$FF ; prepare T2 00EDFC 1 8D 08 A8 sta T2L ; latch 00EDFF 1 ; check bit by bit until $16 00EDFF 1 20 3B EE SYNC: jsr RDBIT ; get a bit in MSB 00EE02 1 4E 2A A4 lsr CPIY ; make room for bit 00EE05 1 0D 2A A4 ora CPIY ; put bit in MSB 00EE08 1 8D 2A A4 sta CPIY 00EE0B 1 C9 16 cmp #$16 ; sync character ? 00EE0D 1 D0 F0 bne SYNC 00EE0F 1 A2 05 ldx #$05 ; test for five sync characters 00EE11 1 20 29 EE SYNC1: jsr GETTAP 00EE14 1 C9 16 cmp #$16 00EE16 1 D0 E7 bne SYNC ; if not two character re-sync 00EE18 1 CA dex 00EE19 1 D0 F6 bne SYNC1 00EE1B 1 60 rts 00EE1C 1 ; 00EE1C 1 ; set PB4 or PB5 off 00EE1C 1 ; used by in/out set ups 00EE1C 1 D0 04 TIOSET: bne TIOS1 ; branch if tape1 00EE1E 1 A9 14 lda #$14 ; set tape 2 off (PB5=0) 00EE20 1 D0 02 bne TIOS2 00EE22 1 A9 24 TIOS1: lda #$24 ; set tape 1 off (PB4=0) 00EE24 1 8D 00 A8 TIOS2: sta DRB 00EE27 1 78 sei ; disable interrupts while taping 00EE28 1 60 rts 00EE29 1 ; 00EE29 1 ; get 1 char form tape and return 00EE29 1 ; with character in A, use CPIY to assemble character, uses Y 00EE29 1 A0 08 GETTAP: ldy #$08 ; read 8-bits 00EE2B 1 20 3B EE GETA1: jsr RDBIT ; get next data bit 00EE2E 1 4E 2A A4 lsr CPIY ; make room for MSB 00EE31 1 0D 2A A4 ora CPIY ; or in sign bit 00EE34 1 8D 2A A4 sta CPIY ; replace character 00EE37 1 88 dey 00EE38 1 D0 F1 bne GETA1 00EE3A 1 60 rts 00EE3B 1 ; get one bit from tape and 00EE3B 1 ; return it in sign of MSB 00EE3B 1 AD 08 A4 RDBIT: lda TSPEED ; are we in C7 or 5b,5a frequency 00EE3E 1 30 27 bmi RDBIT4 ; jump to c7 frequency format 00EE40 1 20 75 EE jsr CKFREQ ; start bit in high frequency 00EE43 1 20 75 EE RDBIT1: jsr CKFREQ ; high to low frequency trans 00EE46 1 B0 FB bcs RDBIT1 00EE48 1 AD 96 A4 lda DIV64 ; get high frequency timing 00EE4B 1 48 pha 00EE4C 1 A9 FF lda #$FF ; set up timer 00EE4E 1 8D 96 A4 sta DIV64 00EE51 1 20 75 EE RDBIT2: jsr CKFREQ ; low to high frequency trans 00EE54 1 90 FB bcc RDBIT2 ; wait till frequency is high 00EE56 1 68 pla 00EE57 1 38 sec 00EE58 1 ED 96 A4 sbc DIV64 ; (256-T1) - (256-T2) =T2-T1 00EE5B 1 48 pha ; low frequency time-high frequency time 00EE5C 1 A9 FF lda #$FF 00EE5E 1 8D 96 A4 sta DIV64 ; set up timer 00EE61 1 68 pla 00EE62 1 49 FF eor #$FF 00EE64 1 29 80 and #$80 00EE66 1 60 rts 00EE67 1 ; Each bit starts with half pulse of 2400 & then 00EE67 1 ; three half pulses of 1200Hz for a 0, three pulses of 2400 for a 1 00EE67 1 ; the reading is made on the fourth 1/2 pulse, when the signal has stabilised 00EE67 1 20 75 EE RDBIT4: jsr CKFREQ ; see which frequency 00EE6A 1 90 FB bcc RDBIT4 00EE6C 1 20 75 EE jsr CKFREQ 00EE6F 1 20 75 EE jsr CKFREQ 00EE72 1 4C B5 FF jmp PATC24 ; now read the bit 00EE75 1 ; 00EE75 1 2C 00 A8 CKFREQ: bit DRB ; are we high or low ? 00EE78 1 30 27 bmi CKF4 00EE7A 1 2C 00 A8 CKF1: bit DRB ; wait till high 00EE7D 1 10 FB bpl CKF1 00EE7F 1 65 00 adc $00 ; equaliser 00EE81 1 AD 09 A8 CKF2: lda T2H ; save centre 00EE84 1 48 pha 00EE85 1 AD 08 A8 lda T2L 00EE88 1 48 pha 00EE89 1 A9 FF lda #$FF 00EE8B 1 8D 09 A8 sta T2H ; start centre 00EE8E 1 AD 08 A4 lda TSPEED 00EE91 1 30 06 bmi CKF3 ; super speed ? 00EE93 1 68 pla 00EE94 1 CD 08 A4 cmp TSPEED ; high or low frequency 00EE97 1 68 pla ; C=1 if high ,C=0 if low 00EE98 1 60 rts 00EE99 1 68 CKF3: pla 00EE9A 1 CD 08 A4 cmp TSPEED ; centre frequency 00EE9D 1 68 CKF3A: pla 00EE9E 1 E9 FE sbc #$FE 00EEA0 1 60 rts 00EEA1 1 2C 00 A8 CKF4: bit DRB ; wait till low 00EEA4 1 30 FB bmi CKF4 00EEA6 1 10 D9 bpl CKF2 ; go get timing 00EEA8 1 ; 00EEA8 1 ; Output A to TTY subroutine 00EEA8 1 ; X,Y are preserved 00EEA8 1 48 OUTTTY: pha ; save A 00EEA9 1 20 9E EB jsr PHXY ; push X 00EEAC 1 8D 27 A4 sta STIY ; put character here 00EEAF 1 20 0F EC jsr DELAY ; stop bit from last character 00EEB2 1 AD 00 A8 lda DRB 00EEB5 1 29 FB and #$FB ; start bit PB2=0 00EEB7 1 8D 00 A8 sta DRB ; TTO=PB2 00EEBA 1 8D 28 A4 sta STIY+1 ; save this pattern 00EEBD 1 20 0F EC jsr DELAY 00EEC0 1 A2 08 ldx #$08 ; 8-bits 00EEC2 1 2E 27 A4 rol STIY ; get first LSB into bit-2 00EEC5 1 2E 27 A4 rol STIY 00EEC8 1 2E 27 A4 rol STIY 00EECB 1 6E 27 A4 OUTT1: ror STIY 00EECE 1 AD 27 A4 lda STIY 00EED1 1 29 04 and #$04 ; get only bit-2 for PB2 00EED3 1 0D 28 A4 ora STIY+1 ; put bit into pattern 00EED6 1 8D 00 A8 sta DRB ; now to TTY 00EED9 1 08 php ; preserve carry for rotate 00EEDA 1 20 0F EC jsr DELAY 00EEDD 1 28 plp 00EEDE 1 CA dex 00EEDF 1 D0 EA bne OUTT1 00EEE1 1 A9 04 lda #$04 ; stop bit 00EEE3 1 0D 28 A4 ora STIY+1 00EEE6 1 8D 00 A8 sta DRB 00EEE9 1 20 0F EC jsr DELAY ; stop bit 00EEEC 1 20 AC EB jsr PLXY ; pull X 00EEEF 1 68 pla 00EEF0 1 C9 0A cmp #LF 00EEF2 1 F0 07 beq OUTT2 00EEF4 1 C9 FF cmp #NULLC 00EEF6 1 F0 03 beq OUTT2 00EEF8 1 4C 05 EF jmp OUTDIS ; use that buffer 00EEFB 1 60 OUTT2: rts 00EEFC 1 ; 00EEFC 1 ; output a character to display/printer subroutine (single entry for both subroutines) 00EEFC 1 ; if character = CR clear display & printer 00EEFC 1 20 00 F0 OUTDP: jsr OUTPRI ; first to print then to display 00EEFF 1 EA nop 00EF00 1 EA nop 00EF01 1 EA nop 00EF02 1 6C 06 A4 OUTDP1: jmp (DILINK) ; here he could echo somewhere else 00EF05 1 ; 00EF05 1 ; Output A to display subroutine 00EF05 1 ; if sign bit (MSB)=1 display do not clear to the right 00EF05 1 48 OUTDIS: pha ; save A 00EF06 1 20 9E EB jsr PHXY ; push X 00EF09 1 C9 0D cmp #CR ; CR ? 00EF0B 1 D0 07 bne OUTD1 00EF0D 1 A2 00 ldx #$00 ; yes 00EF0F 1 8E 15 A4 stx CURPO2 ; clear display pointer 00EF12 1 F0 42 beq OUTD5 ; go clear display 00EF14 1 4C 9C FE OUTD1: jmp PATCH4 00EF17 1 E0 3C OUTD1A: cpx #60 ; last character for display ? 00EF19 1 90 05 bcc OUTD2 00EF1B 1 20 AC EB jsr PLXY ; go back 00EF1E 1 68 pla ; do not store 00EF1F 1 60 rts 00EF20 1 9D 38 A4 OUTD2: sta DIBUFF,x ; put character in buffer 00EF23 1 EE 15 A4 inc CURPO2 ; inc pointer 00EF26 1 E0 14 cpx #20 ; display full ? 00EF28 1 90 1E bcc OUTD4 00EF2A 1 20 2F EF jsr OUTD2A ; this way scroll is a subroutine 00EF2D 1 30 47 bmi OUTD7 ; exit display 00EF2F 1 ; yes, scroll chars to the left 00EF2F 1 8A OUTD2A: txa ; X -> Y 00EF30 1 A8 tay 00EF31 1 A2 13 ldx #19 ; address for display do not 00EF33 1 8E 27 A4 OUTD3: stx STIY ; decrement in binary 00EF36 1 B9 38 A4 lda DIBUFF,y ; from buffer to display 00EF39 1 09 80 ora #$80 ; no cursor 00EF3B 1 20 7B EF jsr OUTDD1 ; convert X to real address 00EF3E 1 88 dey 00EF3F 1 CE 27 A4 dec STIY 00EF42 1 AE 27 A4 ldx STIY 00EF45 1 10 EC bpl OUTD3 ; again until whole display 00EF47 1 60 rts 00EF48 1 48 OUTD4: pha 00EF49 1 09 80 ora #$80 ; no cursor 00EF4B 1 20 7B EF jsr OUTDD1 ; X=<$19, convert to real address 00EF4E 1 68 pla 00EF4F 1 29 80 and #$80 ; if MSB=0 clear rest of display 00EF51 1 D0 23 bne OUTD7 00EF53 1 AE 15 A4 ldx CURPO2 00EF56 1 ; clear display to the right 00EF56 1 E0 14 OUTD5: cpx #20 00EF58 1 B0 1C bcs OUTD7 00EF5A 1 8E 27 A4 stx STIY 00EF5D 1 A9 A0 lda #$A0 ; SPACE 00EF5F 1 20 7B EF jsr OUTDD1 ; convert to real address 00EF62 1 EE 27 A4 inc STIY 00EF65 1 AE 27 A4 ldx STIY 00EF68 1 D0 EC bne OUTD5 ; go next 00EF6A 1 4C 76 EF jmp OUTD7 00EF6D 1 EA nop 00EF6E 1 EA nop 00EF6F 1 EA nop 00EF70 1 EA nop 00EF71 1 EA nop 00EF72 1 EA nop 00EF73 1 EA nop 00EF74 1 EA nop 00EF75 1 EA nop 00EF76 1 20 AC EB OUTD7: jsr PLXY ; rest, so printer independent 00EF79 1 68 pla 00EF7A 1 60 rts 00EF7B 1 ; 00EF7B 1 ; convert X into real address for display 00EF7B 1 ; and output it PB=data ; PA=W,CE A0,A1 (6520) 00EF7B 1 48 OUTDD1: pha ; save data 00EF7C 1 8A txa 00EF7D 1 48 pha ; save X 00EF7E 1 4A lsr a ; divide X by 4 00EF7F 1 4A lsr a ; to get chip select 00EF80 1 AA tax ; back to X 00EF81 1 A9 04 lda #$04 ; first chip select 00EF83 1 E0 00 cpx #$00 ; first chip ? 00EF85 1 F0 04 beq OUTDD3 00EF87 1 0A OUTDD2: asl a 00EF88 1 CA dex 00EF89 1 D0 FC bne OUTDD2 ; back till right CS 00EF8B 1 8D 28 A4 OUTDD3: sta STIY+1 ; save CS temporarily 00EF8E 1 68 pla ; get X again for character 00EF8F 1 29 03 and #$03 ; in that chip 00EF91 1 0D 28 A4 ora STIY+1 ; or in CS and character 00EF94 1 ; store address and data into display 00EF94 1 49 FF eor #$FF ; W=1,CE=0 & A1,A0 00EF96 1 8D 00 AC sta RA 00EF99 1 AA tax ; save A in X 00EF9A 1 68 pla ; get data 00EF9B 1 48 pha 00EF9C 1 8D 02 AC sta RB 00EF9F 1 8A txa 00EFA0 1 49 80 eor #$80 ; set W=0 00EFA2 1 8D 00 AC sta RA 00EFA5 1 EA nop 00EFA6 1 09 7C ora #$7C ; set CE=1 00EFA8 1 8D 00 AC sta RA 00EFAB 1 A9 FF lda #$FF ; set W=1 00EFAD 1 8D 00 AC sta RA 00EFB0 1 68 pla ; return data 00EFB1 1 60 rts 00EFB2 1 ; 00EFB2 1 ; A load of random text that fills the end of the ROM ? 00EFB2 1 4E 20 49 54 .byte "N IT IN SIGN OF A (MSB)",CR,"RDBIT LDA TSPEED ;ARE WE IN 0 OR 1-6 SPEEDS",CR,"BMI",$EA,"RDBIT4" 00EFB6 1 20 49 4E 20 00EFBA 1 53 49 47 4E 00F000 1 ; 00F000 1 ; ****** Start of R3222 ****** 00F000 1 ; 00F000 1 ; OUTPUT ACC TO PRINTER SUBROUTINE 00F000 1 ; prints on 21st character or when CR 00F000 1 ; it will put it on buffer but won't print if 00F000 1 ; PRIFLG=0 00F000 1 48 OUTPRI: pha ; save character to be output 00F001 1 20 9E EB jsr PHXY ; save X 00F004 1 C9 0D cmp #CR ; see if CR 00F006 1 F0 07 beq OUTO1 ; yes so print the buffer 00F008 1 AE 16 A4 ldx CURPOS ; pointer to next position in buffer 00F00B 1 E0 14 cpx #20 ; see if buffer full 00F00D 1 D0 16 bne OUT04 ; not full so return 00F00F 1 ; CR so fill rest of buffer with blanks 00F00F 1 48 OUTO1: pha 00F010 1 A9 00 lda #$00 ; CURPOS=0 00F012 1 AE 16 A4 ldx CURPOS ; see if anything in buffer 00F015 1 8D 16 A4 sta CURPOS 00F018 1 20 38 F0 jsr OUTPR ; clear PRIBUFF to right 00F01B 1 ; buffer filled so print it 00F01B 1 20 45 F0 jsr IPST ; start the print 00F01E 1 A2 00 ldx #$00 ; store character in buffer (first location) 00F020 1 68 pla ; get it 00F021 1 C9 0D cmp #CR ; don't store if CR 00F023 1 F0 0E beq OUT05 00F025 1 9D 60 A4 OUT04: sta IBUFM,x ; store character in buffer 00F028 1 EE 16 A4 inc CURPOS ; increment buffer pointer 00F02B 1 E8 inx 00F02C 1 29 80 and #$80 00F02E 1 D0 03 bne OUT05 ; don't clear is MSB=1 00F030 1 20 38 F0 jsr OUTPR ; clear printer buffer to the right 00F033 1 20 AC EB OUT05: jsr PLXY ; restore registers 00F036 1 68 pla 00F037 1 60 rts 00F038 1 A9 20 OUTPR: lda #SPACE ; fill rest of buffer with blanks 00F03A 1 E0 14 OUTPR1: cpx #20 ; see if end of buffer 00F03C 1 F0 06 beq OUTPR2 00F03E 1 9D 60 A4 sta IBUFM,x ; no so store blank 00F041 1 E8 inx ; increment buffer pointer 00F042 1 10 F6 bpl OUTPR1 00F044 1 60 OUTPR2: rts 00F045 1 ; 00F045 1 ; Subroutine to output buffer, 70 dots (10 dots at 00F045 1 ; a time by 7 rows) for each line of printing 00F045 1 2C 11 A4 IPST: bit PRIFLG ; printer flag on ? 00F048 1 10 2E bpl IPO4 00F04A 1 20 CB F0 IPSO: jsr PINT ; initialise values 00F04D 1 20 E3 F0 jsr IPSU ; set up first output pattern 00F050 1 A9 C1 IPO0: lda #PRST+SP12+MON ; turn motor on 00F052 1 8D 0C A8 sta PCR 00F055 1 20 A0 FF jsr PAT23 ; time out ? 00F058 1 D0 0C bne IPO2 ; no, start signal received 00F05A 1 20 A0 FF jsr PAT23 ; yes, try again 00F05D 1 D0 07 bne IPO2 00F05F 1 4C 79 F0 jmp PRIERR ; two timeout - error 00F062 1 EA nop 00F063 1 EA nop 00F064 1 EA nop 00F065 1 EA nop 00F066 1 20 87 F0 IPO2: jsr PRNDOT ; strobe P1=1 print dots (1.7msec) 00F069 1 20 87 F0 jsr PRNDOT ; strobe P2=1 print dots (1.7msec) 00F06C 1 ; check for 90, when 70 PRNDOT will output zeros 00F06C 1 AD 77 A4 lda IDOT 00F06F 1 C9 5A cmp #90 00F071 1 90 F3 bcc IPO2 ; less than 90 then goto strobe P1 00F073 1 A9 E1 IPO3: lda #PRST+SP12+MOFF ; turn motor off 00F075 1 8D 0C A8 sta PCR 00F078 1 60 IPO4: rts 00F079 1 ; 00F079 1 20 44 EB PRIERR: jsr CLR ; clear printer pointer 00F07C 1 20 B1 FE jsr PATCH5 ; turn printer off 00F07F 1 A0 3B ldy #M12-M1 00F081 1 20 AF E7 jsr KEP 00F084 1 4C A1 E1 jmp COMIN ; back where subroutine OUTINE was called 00F087 1 ; 00F087 1 ; Subroutine to increment dot counter, when 00F087 1 ; neg trans output character for 1.7msec 00F087 1 ; clear & set up next pattern 00F087 1 A9 00 PRNDOT: lda #$00 ; clear interrupts 00F089 1 8D 01 A8 sta DRAH 00F08C 1 AD 0D A8 PRDOT0: lda IFR 00F08F 1 29 02 and #MSP12 ; any strobes 00F091 1 F0 F9 beq PRDOT0 00F093 1 AD 0C A8 lda PCR 00F096 1 49 01 eor #$01 00F098 1 8D 0C A8 sta PCR 00F09B 1 EE 77 A4 inc IDOT 00F09E 1 AD 79 A4 lda IOUTU ; two left elements 00F0A1 1 0D 00 A8 ora DRB ; do not turn TTY output off 00F0A4 1 8D 00 A8 sta DRB 00F0A7 1 AD 78 A4 lda IOUTL ; two right elements, clear CA1 inter flag 00F0AA 1 8D 01 A8 sta DRAH 00F0AD 1 A9 A4 lda #PRTIME ; start T2 for 1.7msec 00F0B4 1 8D 09 A8 sta T2H 00F0B7 1 20 E3 F0 jsr IPSU ; set next pattern while waiting 00F0BA 1 20 1B EC jsr DE2 ; wait till time out 00F0BD 1 A9 00 lda #$00 ; thermal element off 00F0BF 1 8D 01 A8 sta DRAH 00F0C2 1 AD 00 A8 lda DRB ; but don't change tape controls 00F0C5 1 29 FC and #$FC 00F0C7 1 8D 00 A8 sta DRB 00F0CA 1 60 rts 00F0CB 1 ; 00F0CB 1 ; subroutine print -- initialise variables for printer 00F0CB 1 A9 FF PINT: lda #$FF 00F0CD 1 8D 74 A4 sta IDIR ; direction <= 00F0D0 1 A9 05 lda #$05 00F0D2 1 8D 75 A4 sta ICOL ; column <= leftmost +1 00F0D5 1 A9 01 lda #$01 00F0D7 1 8D 76 A4 sta IOFFST ; offset <= left character 00F0DA 1 8D 7C A4 sta IMASK 00F0DD 1 A9 00 lda #$00 00F0DF 1 8D 77 A4 sta IDOT ; doc counter <= 0 00F0E2 1 60 rts 00F0E3 1 ; 00F0E3 1 ; the variables for the printer are as follows: 00F0E3 1 ; 00F0E3 1 ; IDIR direction head is currently moving (0=+, $FF=-) 00F0E3 1 ; ICOL column to be printed next (leftmost=0,rightmost=4 00F0E3 1 ; IOFFST offset n print buffer (0=left character, 1=right character) 00F0E3 1 ; IDOT count of number of dots printed thus far 00F0E3 1 ; IOUTL solenoid pattern (8 characters on right) 00F0E3 1 ; IOUTU solenoid pattern (2 characters on left) 00F0E3 1 ; IBITL 1-bit mask used in setting next solenoid value 00F0E3 1 ; IBITU start of print buffer 00F0E3 1 ; IBUFM start of print buffer (left most character first) 00F0E3 1 ; IMASK mark for current row being printed 00F0E3 1 ; JUMP address of table for current column 00F0E3 1 ; 00F0E3 1 ; The dot patterns for the characters are stored to that each byte 00F0E3 1 ; contains the dots for one column of one character. 00F0E3 1 ; Since each column contains seven dots, this means that one bit per byte is used. 00F0E3 1 ; The patterns are organised into 5 tables of 64-bytes where each table 00F0E3 1 ; contains all the dot patterns for a particular column. 00F0E3 1 ; The bytes in each table are ordered according to the character code of 00F0E3 1 ; the character being referenced. the character code can thus be used 00F0E3 1 ; to directly index into the table. 00F0E3 1 ; 00F0E3 1 ; Subroutine IPSU - set up output pattern for printer 00F0E3 1 ; this routine is called in order to set up the next group of solenoids to 00F0E3 1 ; be output to the printer on entry the contents of all registers are 00F0E3 1 ; arbitrary on exit the contents of A,X,Y are undefined 00F0E3 1 A2 00 IPSU: ldx #$00 ; X points to variable block for printer 00F0E5 1 20 21 F1 jsr INCP ; advance pointers to next dot position 00F0E8 1 ; X now contains index into print buffer 00F0E8 1 BD 60 A4 IPS1: lda IBUFM,x ; load next character from buffer 00F0EB 1 29 3F and #$3F 00F0ED 1 A8 tay 00F0EE 1 A9 7D lda # 60 characters 00F799 1 A0 3C INO3B: ldy #60 ; set yYto max of 60 00F79B 1 A9 01 lda #$01 00F79D 1 0D 11 A4 ora PRIFLG ; do not output to printer any more 00F7A0 1 8D 11 A4 sta PRIFLG ; otherwise clobbers buffer 00F7A3 1 8C 15 A4 sty CURPO2 00F7A6 1 D0 D2 bne INO2 ; go back 00F7A8 1 84 EA INO3: sty LENGTH 00F7AA 1 C0 00 cpy #$00 ; first character ? 00F7AC 1 D0 17 bne INO5 00F7AE 1 AD 19 A4 lda COUNT ; K or I command flag ? 00F7B1 1 D0 12 bne INO5 ; branch if C command 00F7B3 1 20 24 EA jsr CRCK ; CR if printer pointer different from 0 00F7B6 1 20 03 FF jsr PATC13 ; turn on tapes & set default device 00F7B9 1 20 27 F7 INO3A: jsr PLNE ; display next line down 00F7BC 1 20 09 F7 jsr UPNO ; print 'END' if bottom 00F7BF 1 20 D8 F6 jsr DNNO 00F7C2 1 4C 78 FA jmp ERRO 00F7C5 1 20 3F F9 INO5: jsr REPLAC ; insert the line 00F7C8 1 4C 24 EA jmp CRCK ; CR if printer pointer not 0 00F7CB 1 ; 00F7CB 1 ; ***** R Command - Read Line ***** 00F7CB 1 ; read text from any input device until 00F7CB 1 ; two consecutive CR are encountered 00F7CB 1 20 48 E8 INPU: jsr WHEREI 00F7CE 1 AC 12 A4 ldy INFLG ; if tape do not erase buffer 00F7D1 1 C0 54 cpy #'T' 00F7D3 1 F0 03 beq INPU1 00F7D5 1 20 13 EA jsr CRLOW 00F7D8 1 20 6D F7 INPU1: jsr INL 00F7DB 1 20 09 F7 jsr UPNO ; next line 00F7DE 1 4C D8 F7 jmp INPU1 00F7E1 1 ; 00F7E1 1 ; ***** L Command - List Lines ***** 00F7E1 1 ; print from here n lines to active output device 00F7E1 1 20 37 E8 LST: jsr PSL1 ; print '/' 00F7E4 1 20 85 E7 jsr GCNT ; get lines count 00F7E7 1 20 13 EA jsr CRLOW 00F7EA 1 20 71 E8 jsr WHEREO ; where to 00F7ED 1 4C F8 F7 jmp LSTO2 ; one more line 00F7F0 1 20 07 E9 LSTO1: jsr RCHEK 00F7F3 1 20 90 E7 jsr DONE 00F7F6 1 F0 0B beq LST3 00F7F8 1 20 27 F7 LSTO2: jsr PLNE 00F7FB 1 ; (one of my machines has the Monitor in EPROM and this jsr goes to $F70B rather than $F709 ?) 00F7FB 1 20 09 F7 jsr UPNO ; next line 00F7FE 1 20 E9 F8 jsr ATBOT 00F801 1 90 ED bcc LSTO1 ; no 00F803 1 20 3F F7 LST3: jsr PO3 ; one more CR LF for tape 00F806 1 20 0D FF jsr PATC14 ; close tape if needed 00F809 1 4C 5C FA jmp ENDERR 00F80C 1 ; 00F80C 1 ; ***** F Command - Find String ***** 00F80C 1 ; find string and print line to terminal 00F80C 1 20 1E F8 FCHAR: jsr FCH 00F80F 1 AD 15 A4 FCHA1: lda CURPO2 ; save buffer pointer 00F812 1 48 pha 00F813 1 20 44 EB jsr CLR ; clear display pointer 00F816 1 20 27 F7 jsr PLNE 00F819 1 68 pla 00F81A 1 8D 15 A4 sta CURPO2 00F81D 1 60 rts 00F81E 1 ; find a character string 00F81E 1 A0 00 FCH: ldy #$00 00F820 1 20 BD E7 jsr PROMPT 00F823 1 20 5F E9 FC1: jsr RDRUB ; get the character 00F826 1 C9 0D cmp #$0D ; reuse old argument ? 00F828 1 D0 0A bne FC3 00F82A 1 C0 00 cpy #$00 ; first characater ? 00F82C 1 D0 06 bne FC3 00F82E 1 20 09 F7 FC2: jsr UPNO ; next line down 00F831 1 4C 49 F8 jmp FC5 00F834 1 C9 0D FC3: cmp #CR ; done 00F836 1 F0 0B beq FC4 00F838 1 99 EB 00 sta STRING,y 00F83B 1 C8 iny 00F83C 1 C0 14 cpy #20 ; max length 00F83E 1 D0 E3 bne FC1 00F840 1 4C 72 FA jmp ERROR 00F843 1 20 24 EA FC4: jsr CRCK ; clear display 00F846 1 8C 29 A4 sty STIY+2 ; count of characters 00F849 1 A0 00 FC5: ldy #$00 00F84B 1 8C 15 A4 sty CURPO2 ; start at beginning of line 00F84E 1 AC 15 A4 FC6: ldy CURPO2 ; clobber 00F851 1 A2 00 ldx #$00 00F853 1 B1 DF FC7: lda (NOWLN),y ; get the character 00F855 1 D0 03 bne FC8 ; not at end 00F857 1 4C 5C FA jmp ENDERR 00F85A 1 C9 0D FC8: cmp #CR ; end of line 00F85C 1 F0 D0 beq FC2 00F85E 1 D5 EB cmp STRING,x 00F860 1 F0 06 beq FC9 00F862 1 EE 15 A4 inc CURPO2 00F865 1 4C 4E F8 jmp FC6 00F868 1 C8 FC9: iny 00F869 1 E8 inx 00F86A 1 EC 29 A4 cpx STIY+2 ; done ? 00F86D 1 D0 E4 bne FC7 00F86F 1 60 rts 00F870 1 ; 00F870 1 ; ***** Q Command - Exit Editor ***** 00F870 1 ; exit the text editor neatly 00F870 1 20 13 EA STOP: jsr CRLOW 00F873 1 4C A1 E1 jmp COMIN 00F876 1 ; 00F876 1 ; ***** C Command - Change String ***** 00F876 1 ; change string to another string in a line 00F876 1 20 B2 F8 CHNG: jsr CFLG ; set C command flag 00F879 1 20 0C F8 jsr FCHAR ; find correct line 00F87C 1 20 3C E9 CHN1: jsr READ ; is CR if OK 00F87F 1 C9 0D cmp #CR 00F881 1 F0 09 beq CHN2 00F883 1 20 2E F8 jsr FC2 ; try next one 00F886 1 20 0F F8 jsr FCHA1 ; show line 00F889 1 4C 7C F8 jmp CHN1 00F88C 1 AD 29 A4 CHN2: lda STIY+2 ; get char count 00F88F 1 85 E9 sta OLDLEN ; get ready for replace 00F891 1 AD 15 A4 lda CURPO2 ; pointer to beginning of string 00F894 1 48 pha ; save it 00F895 1 20 2A F9 jsr ADDA ; add to NOWLN (line pointer) 00F898 1 20 44 EB jsr CLR ; clear display 00F89B 1 A0 05 ldy #M3-M1 ; print 'TO' 00F89D 1 20 AF E7 jsr KEP 00F8A0 1 A0 00 ldy #$00 00F8A2 1 20 7A F7 jsr INO2 ; get new string & replace 00F8A5 1 68 pla 00F8A6 1 AA tax 00F8A7 1 F0 06 beq CHN4 00F8A9 1 20 1D F9 CHN3: jsr SUB ; restore NOWLN where it waS 00F8AC 1 CA dex 00F8AD 1 D0 FA bne CHN3 00F8AF 1 4C 27 F7 CHN4: jmp PLNE ; display the changed line 00F8B2 1 ; 00F8B2 1 ; the following are subroutines used by commands 00F8B2 1 A9 01 CFLG: lda #$01 ; set flag for C command 00F8B4 1 D0 02 bne KI2 00F8B6 1 A9 00 KIFLG: lda #$00 ; clear K or I command flag 00F8B8 1 8D 19 A4 KI2: sta COUNT 00F8BB 1 60 rts 00F8BC 1 ; 00F8BC 1 A5 E3 TOPNO: lda TEXT ; set current line to top 00F8BE 1 A6 E4 ldx TEXT+1 00F8C0 1 85 DF TPO1: sta NOWLN 00F8C2 1 86 E0 stx NOWLN+1 00F8C4 1 60 rts 00F8C5 1 ; 00F8C5 1 A5 E1 SETBOT: lda BOTLN ; set current line to bottom 00F8C7 1 A6 E2 ldx BOTLN+1 00F8C9 1 85 E7 sta SAVE 00F8CB 1 86 E8 stx SAVE+1 00F8CD 1 4C C0 F8 jmp TPO1 00F8D0 1 ; 00F8D0 1 AD 1C A4 RESNOW: lda ADDR ; restore current line address 00F8D3 1 85 DF sta NOWLN 00F8D5 1 AD 1D A4 lda ADDR+1 00F8D8 1 85 E0 sta NOWLN+1 00F8DA 1 60 rts 00F8DB 1 ; 00F8DB 1 ; see current line at top (C set if so) 00F8DB 1 A5 DF ATTOP: lda NOWLN 00F8DD 1 C5 E3 cmp TEXT 00F8DF 1 D0 16 bne ATO1 00F8E1 1 A5 E0 lda NOWLN+1 00F8E3 1 C5 E4 cmp TEXT+1 00F8E5 1 D0 10 bne ATO1 00F8E7 1 38 sec 00F8E8 1 60 rts 00F8E9 1 ; 00F8E9 1 ; see if current line at bottom (C set if so) 00F8E9 1 A5 DF ATBOT: lda NOWLN 00F8EB 1 A6 E0 ldx NOWLN+1 00F8ED 1 C5 E1 cmp BOTLN 00F8EF 1 D0 06 bne ATO1 00F8F1 1 E4 E2 cpx BOTLN+1 00F8F3 1 D0 02 bne ATO1 00F8F5 1 38 ATO2: sec 00F8F6 1 60 rts 00F8F7 1 18 ATO1: clc 00F8F8 1 60 rts 00F8F9 1 ; 00F8F9 1 ; see if we ran past end of buffer limit 00F8F9 1 A5 E1 ATEND: lda BOTLN 00F8FB 1 A6 E2 ldx BOTLN+1 00F8FD 1 E4 E6 cpx END+1 ; high byte > or = ? 00F8FF 1 90 F6 bcc ATO1 00F901 1 D0 F2 bne ATO2 00F903 1 C5 E5 cmp END ; low byte > or = ? 00F905 1 90 F0 bcc ATO1 00F907 1 B0 EC bcs ATO2 00F909 1 ; 00F909 1 ; save current line (NOWLN) in S1 00F909 1 A5 DF NOWS1: lda NOWLN 00F90B 1 A6 E0 ldx NOWLN+1 00F90D 1 4C 16 F9 jmp ADDS1A 00F910 1 ; 00F910 1 ; move ADDR into S1 00F910 1 AD 1C A4 ADDRS1: lda ADDR 00F913 1 AE 1D A4 ldx ADDR+1 00F916 1 8D 1A A4 ADDS1A: sta S1 00F919 1 8E 1B A4 stx S1+1 00F91C 1 60 rts 00F91D 1 ; 00F91D 1 ; subtract one from current line (NOWLN) 00F91D 1 C6 DF SUB: dec NOWLN 00F91F 1 A5 DF lda NOWLN 00F921 1 C9 FF cmp #$FF 00F923 1 D0 02 bne SUB1 00F925 1 C6 E0 dec NOWLN+1 00F927 1 60 SUB1: rts 00F928 1 ; 00F928 1 ; add A to current line (NOWLN) 00F928 1 A9 01 AD1: lda #$01 00F92A 1 18 ADDA: clc 00F92B 1 65 DF adc NOWLN 00F92D 1 85 DF sta NOWLN 00F92F 1 90 02 bcc ADDA1 00F931 1 E6 E0 inc NOWLN+1 00F933 1 60 ADDA1: rts 00F934 1 ; 00F934 1 A5 DF SAVNOW: lda NOWLN ; save current line into ADDR 00F936 1 8D 1C A4 sta ADDR 00F939 1 A5 E0 lda NOWLN+1 00F93B 1 8D 1D A4 sta ADDR+1 00F93E 1 60 REP2: rts 00F93F 1 ;.PAGE 'MAIN MEMORY MOVER' 00F93F 1 ; move current text around to have 00F93F 1 ; space to put in the new buffer 00F93F 1 A4 EA REPLAC: ldy LENGTH 00F941 1 C4 E9 cpy OLDLEN ; compare old and new lengths 00F943 1 D0 1A bne R2W ; branch if different 00F945 1 F0 07 beq R87 ; lengths are equal - just replace 00F947 1 A9 0D R8: lda #CR 00F949 1 91 DF sta (NOWLN),y 00F94B 1 20 4A FA jsr GOGO 00F94E 1 ; 00F94E 1 ; LENGTH = OLDLEN 00F94E 1 88 R87: dey 00F94F 1 C0 FF cpy #$FF 00F951 1 F0 EB beq REP2 00F953 1 B9 38 A4 R88: lda DIBUFF,y 00F956 1 91 DF sta (NOWLN),y 00F958 1 20 4A FA jsr GOGO 00F95B 1 88 dey 00F95C 1 10 F5 bpl R88 00F95E 1 60 rts 00F95F 1 B0 6E R2W: bcs R100 ; LENGTH > OLDLEN 00F961 1 ; 00F961 1 ; LENGTH < OLDLEN 00F961 1 20 34 F9 jsr SAVNOW ; put NOWLN into ADDR 00F964 1 20 10 F9 jsr ADDRS1 ; put it in S1 also 00F967 1 A5 E9 lda OLDLEN 00F969 1 38 sec 00F96A 1 E5 EA sbc LENGTH ; get difference in lengths 00F96C 1 A4 EA ldy LENGTH 00F96E 1 D0 07 bne RQP 00F970 1 AE 19 A4 ldx COUNT ; C Command ? 00F973 1 D0 02 bne RQP ; yes, jump 00F975 1 69 00 adc #$00 ; include CR 00F977 1 48 RQP: pha 00F978 1 18 clc 00F979 1 6D 1A A4 adc S1 00F97C 1 8D 1A A4 sta S1 00F97F 1 90 03 bcc R6 00F981 1 EE 1B A4 inc S1+1 00F984 1 A9 1A R6: lda # OLDLEN 00F9CF 1 A5 EA R100: lda LENGTH ; new line is longer 00F9D1 1 38 sec 00F9D2 1 E5 E9 sbc OLDLEN 00F9D4 1 A4 E9 ldy OLDLEN 00F9D6 1 D0 02 bne R101 ; already have room for CR 00F9D8 1 69 00 adc #$00 ; add one to difference 00F9DA 1 48 R101: pha 00F9DB 1 20 34 F9 jsr SAVNOW ; NOWLN intoO S1 00F9DE 1 20 C5 F8 jsr SETBOT 00F9E1 1 A0 00 ldy #$00 00F9E3 1 B1 DF R102: lda (NOWLN),y 00F9E5 1 C9 00 cmp #$00 00F9E7 1 F0 06 beq R108 00F9E9 1 20 28 F9 jsr AD1 00F9EC 1 4C E3 F9 jmp R102 00F9EF 1 68 R108: pla 00F9F0 1 48 pha 00F9F1 1 18 clc 00F9F2 1 65 E1 adc BOTLN ; add difference to end 00F9F4 1 85 E1 sta BOTLN ; store new end 00F9F6 1 90 02 bcc R103 00F9F8 1 E6 E2 inc BOTLN+1 00F9FA 1 20 F9 F8 R103: jsr ATEND 00F9FD 1 90 0B bcc R107 00F9FF 1 A5 E7 lda SAVE ; restore old bottom 00FA01 1 85 E1 sta BOTLN 00FA03 1 A5 E8 lda SAVE+1 00FA05 1 85 E2 sta BOTLN+1 00FA07 1 4C 5C FA jmp ENDERR ; ran past buffer end 00FA0A 1 20 09 F9 R107: jsr NOWS1 ; save current end 00FA0D 1 68 pla 00FA0E 1 18 clc 00FA0F 1 65 DF adc NOWLN 00FA11 1 85 DF sta NOWLN 00FA13 1 90 02 bcc R104 00FA15 1 E6 E0 inc NOWLN+1 00FA17 1 A9 1A R104: lda # X 00FE26 1 FE 30 01 inc CH,x ; format to match disassembler table 00FE29 1 C8 iny 00FE2A 1 C0 03 cpy #$03 ; repeat for each of three characters 00FE2C 1 D0 E6 bne RDLUP 00FE2E 1 ; 00FE2E 1 ; compress three formatted characters to MOVAD & MOVAD+1 00FE2E 1 A0 03 ldy #$03 ; setup outer loop 00FE30 1 B9 2F 01 OUTLUP: lda CH-1,y ; compress three characters 00FE33 1 A2 05 ldx #$05 ; set up inner loop 00FE35 1 4A INLUP: lsr a ; shift 5-bits A to MOVAD,MOVAD+1 00FE36 1 6E 26 01 ror MOVAD 00FE39 1 6E 27 01 ror MOVAD+1 00FE3C 1 CA dex 00FE3D 1 D0 F6 bne INLUP 00FE3F 1 88 dey 00FE40 1 D0 EE bne OUTLUP 00FE42 1 ; 00FE42 1 ; search for matching compressed code 00FE42 1 A2 40 ldx #$40 00FE44 1 AD 26 01 SRCHLP: lda MOVAD 00FE47 1 DD B8 F5 SRCHM: cmp MNEML-1,x ; match left half 00FE4A 1 F0 05 beq MATCH 00FE4C 1 CA dex 00FE4D 1 D0 F8 bne SRCHM 00FE4F 1 F0 0B beq MATCH1 00FE51 1 AD 27 01 MATCH: lda MOVAD+1 00FE54 1 DD F8 F5 cmp MNEMR-1,x 00FE57 1 F0 06 beq GOTIT 00FE59 1 CA dex 00FE5A 1 D0 E8 bne SRCHLP 00FE5C 1 4C C5 FC MATCH1: jmp ERRORM 00FE5F 1 ; 00FE5F 1 ; get instruction type from type table 00FE5F 1 BD 5D FB GOTIT: lda TYPTB-1,x 00FE62 1 8D 2E 01 sta TYPE 00FE65 1 ; 00FE65 1 ; get opcode from op code 00FE65 1 BD 1D FB lda STCODE-1,x 00FE68 1 8D 34 A4 sta OPCODE 00FE6B 1 4C C1 FB jmp MODEM 00FE6E 1 ; 00FE6E 1 ; this section sets the current address pointer 00FE6E 1 A9 2A STLO: lda #'*' 00FE70 1 20 7A E9 jsr OUTPUT 00FE73 1 20 AE EA STLOAD: jsr ADDIN ; get address 00FE76 1 B0 F6 bcs STLO ; in case of error 00FE78 1 4C 24 FF jmp PATC16 ; ADDR to PC then to start 00FE7B 1 ; 00FE7B 1 ; patches to correct problems without 00FE7B 1 ; changing entry points to the routines 00FE7B 1 41 .byte 'A' 00FE7C 1 38 PATCH1: sec ; adjust baud 00FE7D 1 E9 2C sbc #44 00FE7F 1 8D 18 A4 sta CNTL30 00FE82 1 60 rts 00FE83 1 ; 00FE83 1 8A CUREAD: txa ; save X, output current 00FE84 1 48 pha 00FE85 1 AE 15 A4 ldx CURPO2 00FE88 1 E0 14 cpx #20 ; only if < 20 00FE8A 1 B0 05 bcs PAT2A 00FE8C 1 A9 DE lda #$DE 00FE8E 1 20 7B EF jsr OUTDD1 00FE91 1 68 PAT2A: pla 00FE92 1 AA tax 00FE93 1 4C 3C E9 jmp READ ; continue 00FE96 1 ; 00FE96 1 20 3C E9 RED1: jsr READ ; read & echo without cursor 00FE99 1 4C 76 E9 jmp RED2 00FE9C 1 ; 00FE9C 1 AE 15 A4 PATCH4: ldx CURPO2 ; don't do anything if '8D' 00FE9F 1 C9 8D cmp #$8D ; so CR for tv & not for display 00FEA1 1 D0 0B bne PAT4A 00FEA3 1 A9 A0 lda #$A0 ; clear cursor 00FEA5 1 20 7B EF jsr OUTDD1 00FEA8 1 20 44 EB jsr CLR ; clear pointers 00FEAB 1 4C 76 EF jmp OUTD7 ; exit 00FEAE 1 4C 17 EF PAT4A: jmp OUTD1A ; continue 00FEB1 1 ; 00FEB1 1 8D 11 A4 PATCH5: sta PRIFLG ; turn printer off 00FEB4 1 4C 73 F0 jmp IPO3 00FEB7 1 ; 00FEB7 1 A9 1C PATCH6: lda #' 00FED3 1 20 7A E9 jsr OUTPUT 00FED6 1 68 pla 00FED7 1 60 rts 00FED8 1 ; 00FED8 1 C9 F7 PATCH9: cmp #$F7 ; check lower transition of timer 00FEDA 1 B0 06 bcs PAT9A 00FEDC 1 CD 08 A4 cmp TSPEED 00FEDF 1 4C 9D EE jmp CKF3A 00FEE2 1 CD 08 A4 PAT9A: cmp TSPEED 00FEE5 1 68 pla 00FEE6 1 C9 FF cmp #$FF 00FEE8 1 60 PAT9B: rts 00FEE9 1 ; 00FEE9 1 20 F0 E9 PATC10: jsr CRLF ; clear display (only CR) 00FEEC 1 4C 85 E1 jmp STA1 00FEEF 1 ; 00FEEF 1 F0 F7 PATC11: beq PAT9B ; go output prompt 00FEF1 1 C9 4C cmp #'L' ; no prompt for 'T' or 'L' 00FEF3 1 F0 F3 beq PAT9B 00FEF5 1 4C C5 E7 jmp PROMP1 00FEF8 1 ; 00FEF8 1 48 PATC12: pha ; clear PRIFLG so we can output 00FEF9 1 AD 11 A4 lda PRIFLG ; to printer if flag was on (MSB) 00FEFC 1 29 F0 and #$F0 00FEFE 1 8D 11 A4 sta PRIFLG 00FF01 1 68 pla 00FF02 1 60 rts 00FF03 1 ; 00FF03 1 AD 12 A4 PATC13: lda INFLG ; turn tapes on only if tapes 00FF06 1 C9 54 cmp #'T' 00FF08 1 D0 DE bne PAT9B 00FF0A 1 4C 29 E5 jmp DU14 ; turn on tapes & set default device 00FF0D 1 ; 00FF0D 1 AD 13 A4 PATC14: lda OUTFLG ; turn on tapes only if tapes 00FF10 1 C9 54 cmp #'T' 00FF12 1 D0 D4 bne PAT9B 00FF14 1 4C 0A E5 jmp DU11 00FF17 1 ; 00FF17 1 20 F0 E9 PATC15: jsr CRLF ; decode command 00FF1A 1 8A txa ; save index 00FF1B 1 0A asl a 00FF1C 1 AA tax 00FF1D 1 BD B8 FA lda HTBL,x ; part of entry 00FF20 1 8D 1A A4 sta S1 00FF23 1 60 rts 00FF24 1 ; 00FF24 1 20 DD E5 PATC16: jsr CGPC1 ; ADDR to PC 00FF27 1 4C AA FB jmp STARTM ; back to mnemonic start 00FF2A 1 ; 00FF2A 1 F0 0E PATC17: beq PAT17B ; rub, so read another 00FF2C 1 C9 00 cmp #$00 00FF2E 1 F0 03 beq PAT17A 00FF30 1 4C 85 F7 jmp INO2A ; neither, continue 00FF33 1 20 93 E9 PAT17A: jsr INALL ; skip on zeros 00FF36 1 C9 7F cmp #$7F ; until rub 00FF38 1 D0 F9 bne PAT17A 00FF3A 1 4C 7A F7 PAT17B: jmp INO2 ; go back 00FF3D 1 ; 00FF3D 1 20 F8 FE PATC18: jsr PATC12 ; reset PRIFLG 00FF40 1 48 pha 00FF41 1 20 42 E8 jsr TTYTST ; if TTY just return 00FF44 1 D0 02 bne PAT18A 00FF46 1 68 pla 00FF47 1 60 rts 00FF48 1 20 FE E8 PAT18A: jsr LL ; set to low speed 00FF4B 1 20 45 F0 jsr IPST ; print what is in buffer 00FF4E 1 20 44 EB jsr CLR ; clear printer buffer by outputting 00FF51 1 20 3E E8 jsr BLANK ; a SPACE 00FF54 1 20 44 EB jsr CLR 00FF57 1 68 pla ; return accumulator 00FF58 1 60 rts 00FF59 1 ; 00FF59 1 D8 PAT19: cld 00FF5A 1 20 24 EA jsr CRCK 00FF5D 1 4C 85 E1 jmp STA1 00FF60 1 ; 00FF60 1 F0 0D PAT20: beq VECK4 ; end (data bytes=0) 00FF62 1 18 clc 00FF63 1 69 04 adc #$04 00FF65 1 AA tax 00FF66 1 20 93 E9 VECK5: jsr INALL ; skip over data 00FF69 1 CA dex 00FF6A 1 D0 FA bne VECK5 00FF6C 1 4C 9E E6 jmp VECK1 ; process next rcd 00FF6F 1 4C 20 E5 VECK4: jmp DU13 00FF72 1 ; 00FF72 1 A0 00 PAT21: ldy #$00 00FF74 1 B9 88 FF PAT12A: lda POMSG,y ; reset message 00FF77 1 F0 06 beq PAT12B 00FF79 1 20 7A E9 jsr OUTPUT 00FF7C 1 C8 iny 00FF7D 1 D0 F5 bne PAT12A 00FF7F 1 20 F0 E9 PAT12B: jsr CRLF 00FF82 1 20 F0 E9 jsr CRLF 00FF85 1 4C 82 E1 jmp START 00FF88 1 ; 00FF88 1 20 20 52 4F POMSG: .byte " ROCKWELL AIM 65" 00FF8C 1 43 4B 57 45 00FF90 1 4C 4C 20 41 00FF99 1 00 .byte $00 00FF9A 1 ; 00FF9A 1 EE 68 01 PAT22: inc BLKO 00FF9D 1 4C BD ED jmp ADDBK1 00FFA0 1 ; 00FFA0 1 A9 FF PAT23: lda #$FF ; start timer 00FFA2 1 8D 97 A4 sta DI1024 00FFA5 1 AD 85 A4 PAT23A: lda RINT ; timeout ? 00FFA8 1 30 08 bmi PAT23B ; yes 00FFAA 1 AD 0D A8 lda IFR ; start signal ? 00FFAD 1 29 10 and #MPRST 00FFAF 1 F0 F4 beq PAT23A ; no 00FFB1 1 60 rts ; yes 00FFB2 1 A9 00 PAT23B: lda #$00 ; timeout return 00FFB4 1 60 rts 00FFB5 1 ; 00FFB5 1 20 75 EE PATC24: jsr CKFREQ ; read bit from fourth half-pulse 00FFB8 1 6A ROR A 00FFB9 1 29 80 and #$80 00FFBB 1 60 rts 00FFBC 1 ; 00FFBC 1 2C 0D A8 PATC25: bit IFR ; wait till times out 00FFBF 1 50 FB bvc PATC25 00FFC1 1 AD 04 A8 lda T1L ; clear interrupt flag 00FFC4 1 60 rts 00FFC5 1 ; 00FFC5 1 ; A load of random text that fills the end of the ROM up to the reset/interrupt vectors ? 00FFC5 1 3B 3B 3B 3B .byte ";;;;;;;;;;;;;;;;;;",CR,";OUTPUT CHAR IN A TO PRINTER",CR,"OUTP",$FA 00FFC9 1 3B 3B 3B 3B 00FFCD 1 3B 3B 3B 3B 00FFFA 1 ; 00FFFA 1 ; *** INTERRUPT VECTORS *** 00FFFA 1 ; 00FFFA 1 75 E0 BF E0 .word NMIV1,RSET,IRQV1 ; Setup Vectors 00FFFE 1 78 E0 010000 1 010000 1