ca65 V2.19 - Git e5f4ca6 Main file : KIM-1_Firmware.ca65 Current file: KIM-1_Firmware.ca65 000000r 1 ; KIM-1 Source Code 000000r 1 ; 000000r 1 ; Formated for the CA65 Assembler 000000r 1 ; Based on original MOS Source 000000r 1 ; 000000r 1 ; Chris Oddy December 2025 000000r 1 ; 000000r 1 ; *** MPU Registers Save Area in Page 0 *** 000000r 1 PCL := $EF ; Program Counter low 000000r 1 PCH := $F0 ; Program Counter high 000000r 1 PREG := $F1 ; Current Status Register 000000r 1 SPUSER := $F2 ; Current Stack Pointer 000000r 1 ACC := $F3 ; Accumulator 000000r 1 YREG := $F4 ; Y Index 000000r 1 XREG := $F5 ; X Index 000000r 1 ; 000000r 1 ; *** KIM Fixed Area in Page 0 *** 000000r 1 CHKHI := $F6 000000r 1 CHKSUM := $F7 000000r 1 INL := $F8 ; input buffer low 000000r 1 INH := $F9 ; input buffer high 000000r 1 POINTL := $FA ; address L on display 000000r 1 POINTH := $FB ; address H on display 000000r 1 TEMP := $FC 000000r 1 TMPX := $FD 000000r 1 CHAR := $FE 000000r 1 MODE := $FF 000000r 1 ; 000000r 1 ; *** Hardware Address's *** 000000r 1 ; 6530-002 000000r 1 SAD := $1740 ; 6530 A Data 000000r 1 PADD := SAD+1 ; 6530 A Data Direction 000000r 1 SBD := SAD+2 ; 6530 B Data 000000r 1 PBDD := SAD+3 ; 6530 B Data Direction 000000r 1 CLK1T := SAD+4 ; Div by 1 time 000000r 1 CLK8T := SAD+5 ; Div by 8 time 000000r 1 CLK64T := SAD+6 ; Div by 64 time 000000r 1 CLKKT := SAD+7 ; Div by 1024 time 000000r 1 CLKRDI := SAD+7 ; Read timeout bit 000000r 1 CLKRDT := SAD+6 ; Read time 000000r 1 ; 000000r 1 ; ; *** Fixed Area in Page 23 *** 000000r 1 CHKL := $17E7 ; Checksum low 000000r 1 CHKH := CHKL+1 ; Checksum High 000000r 1 SAVX := CHKL+2 ; 000000r 1 VEB := CHKL+5 ; Volatile Execution Block 000000r 1 CNTL30 := CHKL+11 ; TTY Delay 000000r 1 CNTH30 := CHKL+12 ; TTY Delay 000000r 1 TIMH := CHKL+13 ; 000000r 1 SAL := CHKL+14 ; Starting Address Low 000000r 1 SAH := CHKL+15 ; Starting Address High 000000r 1 EAL := CHKL+16 ; Ending Address Low 000000r 1 EAH := CHKL+17 ; Ending Address High 000000r 1 ID := CHKL+18 000000r 1 ; 000000r 1 ; ; *** Interrupt Vectors *** 000000r 1 NMIV := CHKL+19 ; Stop Vector (NMI) (Stop=$1C00) 000000r 1 RSTV := CHKL+21 ; RESET vector 000000r 1 IRQV := CHKL+23 ; IRQ vector (BRK=$1C00) 000000r 1 ; 000000r 1 ; ****** PART 1 - Audio Cassette Recorder Extension (6530 Z3) ****** 000000r 1 ; 000000r 1 ; Features two basic routines: 000000r 1 ; LOADT - Load memory from audio tape 000000r 1 ; DUMPT - Store memory onto audio tape 000000r 1 ; 000000r 1 ; LOADT 000000r 1 ; ID=$00 Ignore ID 000000r 1 ; ID=$FF Ignore ID use $A for start address 000000r 1 ; ID=$01 to $FE Ignore ID use address on tape 000000r 1 ; 000000r 1 ; DUMPT 000000r 1 ; ID=$00 Should not be used 000000r 1 ; ID=$FF Should not be used 000000r 1 ; ID=$01 to $FE Normal ID range 000000r 1 ; SAL LSB starting address 000000r 1 ; SAH MSB starting address 000000r 1 ; EAL LSB ending address 000000r 1 ; EAH MSB ending address 000000r 1 ; 000000r 1 .org $1800 001800 1 ; 001800 1 ; Dump memory on tape 001800 1 A9 AD DUMPT: lda #$AD ; load absolute instruction 001802 1 8D EC 17 sta VEB 001805 1 20 32 19 jsr INTVEB 001808 1 ; 001808 1 A9 27 lda #$27 ; turn off data input PB5 00180A 1 8D 42 17 sta SBD 00180D 1 A9 BF lda #$BF ; convert PB7 to output 00180F 1 8D 43 17 sta PBDD 001812 1 ; 001812 1 A2 64 ldx #100 ; 100 characters 001814 1 A9 16 DUMPT1: lda #$16 ; sync characters 001816 1 20 7A 19 jsr OUTCHT 001819 1 CA dex 00181A 1 D0 F8 bne DUMPT1 00181C 1 ; 00181C 1 A9 2A lda #'*' ; start character 00181E 1 20 7A 19 jsr OUTCHT 001821 1 ; 001821 1 AD F9 17 lda ID ; output ID 001824 1 20 61 19 jsr OUTBT 001827 1 ; 001827 1 AD F5 17 lda SAL ; output starting address 00182A 1 20 5E 19 jsr OUTBTC 00182D 1 AD F6 17 lda SAH 001830 1 20 5E 19 jsr OUTBTC 001833 1 ; 001833 1 AD ED 17 DUMPT2: lda VEB+1 ; check for last data byte 001836 1 CD F7 17 cmp EAL 001839 1 AD EE 17 lda VEB+2 00183C 1 ED F8 17 sbc EAH 00183F 1 90 24 bcc DUMPT4 001841 1 ; 001841 1 A9 2F lda #'/' ; output End Of Data Character 001843 1 20 7A 19 jsr OUTCHT 001846 1 AD E7 17 lda CHKL ; last byte has been output 001849 1 20 61 19 jsr OUTBT ; now output checksum 00184C 1 ; 00184C 1 AD E8 17 lda CHKH 00184F 1 20 61 19 jsr OUTBT 001852 1 A2 02 ldx #$02 ; 2 characters 001854 1 A9 04 DUMPT3: lda #$04 ; EOT Character 001856 1 20 7A 19 jsr OUTCHT 001859 1 CA dex 00185A 1 D0 F8 bne DUMPT3 00185C 1 ; 00185C 1 A9 00 lda #$00 ; display 0000 00185E 1 85 FA sta POINTL ; for normal exit 001860 1 85 FB sta POINTH 001862 1 4C 4F 1C jmp START 001865 1 ; 001865 1 20 EC 17 DUMPT4: jsr VEB ; data byte output 001868 1 20 5E 19 jsr OUTBTC 00186B 1 20 EA 19 jsr INCVEB 00186E 1 4C 33 18 jmp DUMPT2 001871 1 ; 001871 1 ; Load Memory from Tape 001871 1 0F 19 TAB: .word LOAD12 001873 1 A9 8D LOADT: lda #$8D ; initialise volatile execution 001875 1 8D EC 17 sta VEB ; block with STA abs 001878 1 20 32 19 jsr INTVEB 00187B 1 ; 00187B 1 A9 4C lda #$4C ; jump type return 00187D 1 8D EF 17 sta VEB+3 001880 1 AD 71 18 lda TAB 001883 1 8D F0 17 sta VEB+4 001886 1 AD 72 18 lda TAB+1 001889 1 8D F1 17 sta VEB+5 00188C 1 ; 00188C 1 A9 07 lda #$07 ; reset PB5=0 (Data In) 00188E 1 8D 42 17 sta SBD 001891 1 ; 001891 1 A9 FF SYNC: lda #$FF ; clear save X for SYNC area 001893 1 8D E9 17 sta SAVX 001896 1 ; 001896 1 20 41 1A SYNC1: jsr RDBIT ; get a bit 001899 1 4E E9 17 lsr SAVX ; shift bit into character 00189C 1 0D E9 17 ora SAVX 00189F 1 8D E9 17 sta SAVX 0018A2 1 AD E9 17 lda SAVX ; get new character 0018A5 1 C9 16 cmp #$16 ; SYNC Character ? 0018A7 1 D0 ED bne SYNC1 0018A9 1 A2 0A ldx #$0A ; test for 10 SYNC Character 0018AB 1 ; 0018AB 1 20 24 1A SYNC2: jsr RDCHT 0018AE 1 C9 16 cmp #$16 ; if not $10 character resync 0018B0 1 D0 DF bne SYNC 0018B2 1 CA dex 0018B3 1 D0 F6 bne SYNC2 0018B5 1 ; 0018B5 1 20 24 1A LOADT4: jsr RDCHT ; look for start of data character 0018B8 1 C9 2A cmp #'*' 0018BA 1 F0 06 beq LOAD11 0018BC 1 C9 16 cmp #$16 ; if not * should be sync 0018BE 1 D0 D1 bne SYNC 0018C0 1 F0 F3 beq LOADT4 0018C2 1 ; 0018C2 1 20 F3 19 LOAD11: jsr RDBYT ; read ID from tape 0018C5 1 CD F9 17 cmp ID ; compare with requested ID 0018C8 1 F0 0D beq LOADT5 0018CA 1 AD F9 17 lda ID ; default 00 read record 0018CD 1 C9 00 cmp #$00 ; anyway 0018CF 1 F0 06 beq LOADT5 0018D1 1 C9 FF cmp #$FF ; default $FF ignore Start Address on tape 0018D3 1 F0 17 beq LOADT6 0018D5 1 D0 9C bne LOADT 0018D7 1 ; 0018D7 1 20 F3 19 LOADT5: jsr RDBYT ; get Start Address from tape 0018DA 1 20 4C 19 jsr CHKT 0018DD 1 8D ED 17 sta VEB+1 ; save X in VEB+1,2 0018E0 1 20 F3 19 jsr RDBYT 0018E3 1 20 4C 19 jsr CHKT 0018E6 1 8D EE 17 sta VEB+2 0018E9 1 4C F8 18 jmp LOADT7 0018EC 1 ; 0018EC 1 20 F3 19 LOADT6: jsr RDBYT ; get Start Address but ignore 0018EF 1 20 4C 19 jsr CHKT 0018F2 1 20 F3 19 jsr RDBYT 0018F5 1 20 4C 19 jsr CHKT 0018F8 1 ; 0018F8 1 A2 02 LOADT7: ldx #$02 ; get 2 characters 0018FA 1 20 24 1A LOAD13: jsr RDCHT ; get character (X) 0018FD 1 C9 2F cmp #'/' ; look for last character 0018FF 1 F0 14 beq LOADT8 001901 1 20 00 1A jsr PACKT ; convert to hex 001904 1 D0 23 bne LOADT9 ; Y=1 non-hex character 001906 1 CA dex 001907 1 D0 F1 bne LOAD13 001909 1 ; 001909 1 20 4C 19 jsr CHKT ; compute checksum 00190C 1 4C EC 17 jmp VEB ; save X data in memory 00190F 1 20 EA 19 LOAD12: jsr INCVEB ; increment data pointer 001912 1 4C F8 18 jmp LOADT7 001915 1 ; 001915 1 20 F3 19 LOADT8: jsr RDBYT ; End Of Data compare checksum 001918 1 CD E7 17 cmp CHKL 00191B 1 D0 0C bne LOADT9 00191D 1 20 F3 19 jsr RDBYT 001920 1 CD E8 17 cmp CHKH 001923 1 D0 04 bne LOADT9 001925 1 A9 00 lda #$00 ; normal exit 001927 1 F0 02 beq LOAD10 001929 1 ; 001929 1 A9 FF LOADT9: lda #$FF ; error exit 00192B 1 85 FA LOAD10: sta POINTL 00192D 1 85 FB sta POINTH 00192F 1 4C 4F 1C jmp START 001932 1 ; 001932 1 ; *** Subroutines Follow *** 001932 1 ; 001932 1 ; Subroutine to Move Start Address to VEB+1,2 001932 1 AD F5 17 INTVEB: lda SAL 001935 1 8D ED 17 sta VEB+1 001938 1 AD F6 17 lda SAH 00193B 1 8D EE 17 sta VEB+2 00193E 1 A9 60 lda #$60 ; RTS instruction 001940 1 8D EF 17 sta VEB+3 001943 1 A9 00 lda #$00 ; clear checksum area 001945 1 8D E7 17 sta CHKL 001948 1 8D E8 17 sta CHKH 00194B 1 60 rts 00194C 1 ; 00194C 1 ; Compute checksum for tape load 00194C 1 ; Return uses Y to save X A 00194C 1 A8 CHKT: tay 00194D 1 18 clc 00194E 1 6D E7 17 adc CHKL 001951 1 8D E7 17 sta CHKL 001954 1 AD E8 17 lda CHKH 001957 1 69 00 adc #$00 001959 1 8D E8 17 sta CHKH 00195C 1 98 tya 00195D 1 60 rts 00195E 1 ; 00195E 1 ; Output One Byte use Y to Save X byte 00195E 1 20 4C 19 OUTBTC: jsr CHKT ; compare checksum 001961 1 A8 OUTBT: tay ; save X data byte 001962 1 4A lsr ; shift off LSD 001963 1 4A lsr 001964 1 4A lsr 001965 1 4A lsr 001966 1 20 6F 19 jsr HEXOUT ; output MSD 001969 1 98 tya 00196A 1 20 6F 19 jsr HEXOUT ; output LSD 00196D 1 98 tya 00196E 1 60 rts 00196F 1 ; 00196F 1 ; Convert LSD of A to ASCII and Output to Tape 00196F 1 29 0F HEXOUT: and #$0F 001971 1 C9 0A cmp #$0A 001973 1 18 clc 001974 1 30 02 bmi HEX1 001976 1 69 07 adc #$07 001978 1 69 30 HEX1: adc #$30 00197A 1 ; 00197A 1 ; Output to tape one ASCII character use subroutines ONE and ZERO 00197A 1 8E E9 17 OUTCHT: stx SAVX 00197D 1 8C EA 17 sty SAVX+1 001980 1 A0 08 ldy #$08 ; start bit 001982 1 20 9E 19 CHT1: jsr ONE 001985 1 4A lsr ; get data bit 001986 1 B0 06 bcs CHT2 001988 1 20 9E 19 jsr ONE ; data bit=1 00198B 1 4C 91 19 jmp CHT3 00198E 1 20 C4 19 CHT2: jsr ZRO ; data bit=0 001991 1 20 C4 19 CHT3: jsr ZRO 001994 1 88 dey 001995 1 D0 EB bne CHT1 001997 1 AE E9 17 ldx SAVX 00199A 1 AC EA 17 ldy SAVX+1 00199D 1 60 rts 00199E 1 ; 00199E 1 ; Output 1 to Tape: 9 Pulses of 138us each 00199E 1 A2 09 ONE: ldx #$09 0019A0 1 48 pha ; save X 0019A1 1 2C 47 17 ONE1: bit CLKRDI ; wait for timeout 0019A4 1 10 FB bpl ONE1 0019A6 1 A9 7E lda #126 0019A8 1 8D 44 17 sta CLK1T 0019AB 1 A9 A7 lda #$A7 0019AD 1 8D 42 17 sta SBD ; set PB7=1 0019B0 1 2C 47 17 ONE2: bit CLKRDI 0019B3 1 10 FB bpl ONE2 0019B5 1 A9 7E lda #126 0019B7 1 8D 44 17 sta CLK1T 0019BA 1 A9 27 lda #$27 0019BC 1 8D 42 17 sta SBD ; reset PB7=0 0019BF 1 CA dex 0019C0 1 D0 DF bne ONE1 0019C2 1 68 pla 0019C3 1 60 rts 0019C4 1 ; 0019C4 1 ; Output 0 to Tape: 6 Pulses of 207us each 0019C4 1 A2 06 ZRO: ldx #$06 0019C6 1 48 pha ; save X 0019C7 1 2C 47 17 ZRO1: bit CLKRDI ; wait for timeout 0019CA 1 10 FB bpl ZRO1 0019CC 1 A9 C3 lda #195 0019CE 1 8D 44 17 sta CLK1T 0019D1 1 A9 A7 lda #$A7 0019D3 1 8D 42 17 sta SBD ; set PB7=1 0019D6 1 2C 47 17 ZRO2: bit CLKRDI 0019D9 1 10 FB bpl ZRO2 0019DB 1 A9 C3 lda #195 0019DD 1 8D 44 17 sta CLK1T 0019E0 1 A9 27 lda #$27 0019E2 1 8D 42 17 sta SBD ; reset PB7=0 0019E5 1 CA dex 0019E6 1 D0 DF bne ZRO1 0019E8 1 68 pla ; restore A 0019E9 1 60 rts 0019EA 1 ; 0019EA 1 ; Subroutine to Increment VEB+1,2 0019EA 1 EE ED 17 INCVEB: inc VEB+1 0019ED 1 D0 03 bne INCVE1 0019EF 1 EE EE 17 inc VEB+2 0019F2 1 60 INCVE1: rts 0019F3 1 ; 0019F3 1 ; Subroutine to Read byte from tape 0019F3 1 20 24 1A RDBYT: jsr RDCHT 0019F6 1 20 00 1A jsr PACKT 0019F9 1 20 24 1A RDBYT2: jsr RDCHT 0019FC 1 20 00 1A jsr PACKT 0019FF 1 60 rts 001A00 1 ; 001A00 1 ; Pack ASCII into SAVX as hex data 001A00 1 C9 30 PACKT: cmp #$30 001A02 1 30 1E bmi PACKT3 001A04 1 C9 47 cmp #'G' 001A06 1 10 1A bpl PACKT3 001A08 1 C9 40 cmp #'@' 001A0A 1 30 03 bmi PACKT1 001A0C 1 18 clc 001A0D 1 69 09 adc #$09 001A0F 1 2A PACKT1: rol 001A10 1 2A rol 001A11 1 2A rol 001A12 1 2A rol 001A13 1 A0 04 ldy #$04 001A15 1 2A PACKT2: rol 001A16 1 2E E9 17 rol SAVX 001A19 1 88 dey 001A1A 1 D0 F9 bne PACKT2 001A1C 1 AD E9 17 lda SAVX 001A1F 1 A0 00 ldy #$00 ; Y=0 valid hex character 001A21 1 60 rts ; Y=1 valid hex 001A22 1 C8 PACKT3: iny ; Y=1 not hex 001A23 1 60 rts 001A24 1 ; 001A24 1 ; Get one character from Tape and return with character in A 001A24 1 ; Use SAVX+1 to assemble character 001A24 1 8E EB 17 RDCHT: stx SAVX+2 001A27 1 A2 08 ldx #$08 ; read 8-bits 001A29 1 20 41 1A RDCHT1: jsr RDBIT ; get next data bit 001A2C 1 4E EA 17 lsr SAVX+1 ; right shift character 001A2F 1 0D EA 17 ora SAVX+1 ; OR in sign bit 001A32 1 8D EA 17 sta SAVX+1 ; replace character 001A35 1 CA dex 001A36 1 D0 F1 bne RDCHT1 001A38 1 AD EA 17 lda SAVX+1 ; move character into A 001A3B 1 2A rol ; shift off parity 001A3C 1 4A lsr 001A3D 1 AE EB 17 ldx SAVX+2 001A40 1 60 rts 001A41 1 ; 001A41 1 ; This subroutine Gets 1-bit from tape and returns it Sign of A 001A41 1 2C 42 17 RDBIT: bit SBD ; wait for end of start bit 001A44 1 10 FB bpl RDBIT 001A46 1 AD 46 17 lda CLKRDT ; get start bit time 001A49 1 A0 FF ldy #$FF ; A=256-T1 001A4B 1 8C 46 17 sty CLK64T ; set up times 001A4E 1 A0 14 ldy #$14 001A50 1 88 RDBIT3: dey ; delay 100us 001A51 1 D0 FD bne RDBIT3 001A53 1 2C 42 17 RDBIT2: bit SBD 001A56 1 30 FB bmi RDBIT2 ; wait for next start bit 001A58 1 38 sec 001A59 1 ED 46 17 sbc CLKRDT ; (256-T1)-(256-T2)=T2-T1 001A5C 1 A0 FF ldy #$FF 001A5E 1 8C 46 17 sty CLK64T ; set up timer for next bit 001A61 1 A0 07 ldy #$07 001A63 1 88 RDBIT4: dey ; delay 50us 001A64 1 D0 FD bne RDBIT4 001A66 1 49 FF eor #$FF ; complement sign of A 001A68 1 29 80 and #$80 ; mask all except sign 001A6A 1 60 rts 001A6B 1 ; 001A6B 1 ; *** Diagnostics *** 001A6B 1 ; 001A6B 1 ; MEMORY 001A6B 1 ; PLLCAL 001A6B 1 ; 001A6B 1 ; PLLCAL - output 166us pulse string 001A6B 1 A9 27 PLLCALL:lda #$27 001A6D 1 8D 42 17 sta SBD ; turn off datain PB5=1 001A70 1 A9 BF lda #$BF ; convert PB7 to output 001A72 1 8D 43 17 sta PBDD 001A75 1 ; 001A75 1 2C 47 17 PLL1: bit CLKRDI 001A78 1 10 FB bpl PLL1 001A7A 1 A9 9A lda #154 ; wait 166us 001A7C 1 8D 44 17 sta CLK1T 001A7F 1 A9 A7 lda #$A7 ; output PB7=1 001A81 1 8D 42 17 sta SBD 001A84 1 ; 001A84 1 2C 47 17 PLL2: bit CLKRDI 001A87 1 10 FB bpl PLL2 001A89 1 A9 9A lda #154 001A8B 1 8D 44 17 sta CLK1T 001A8E 1 A9 27 lda #$27 ; PB7=0 001A90 1 8D 42 17 sta SBD 001A93 1 4C 75 1A jmp PLL1 001A96 1 ; 001A96 1 FF FF FF FF .res $164,$FF ; Packing 001A9A 1 FF FF FF FF 001A9E 1 FF FF FF FF 001BFA 1 ; 001BFA 1 ; *** Interrupts Page 27 *** 001BFA 1 ; Reserved for Test 001BFA 1 ; .org $1BFA 001BFA 1 ; 001BFA 1 6B 1A NMIP27: .word PLLCALL 001BFC 1 6B 1A RSTP27: .word PLLCALL 001BFE 1 6B 1A IRQP27: .word PLLCALL 001C00 1 ; 001C00 1 ; ****** PART 2 - KIM-1_Keyboard_Interface_Monitor (6530 Z2) ****** 001C00 1 ; 001C00 1 ; KIM: TTY Interface 001C00 1 ; Keyboard Interface 001C00 1 ; 7-Segment Digit Display 001C00 1 ; 001C00 1 ; TTY Commands: 001C00 1 ; G GOEXEC 001C00 1 ; CR Open Next Cell 001C00 1 ; LF Open Previous Cell 001C00 1 ; . Modify Open Cell 001C00 1 ; SP Open New Cell 001C00 1 ; L Load (Object Format) 001C00 1 ; Q Dump from open cell address to high limit 001C00 1 ; RO Rubout - return to start (KIM) 001C00 1 ; (all illegal characters are ignored) 001C00 1 ; 001C00 1 ; Keyboard Commands: 001C00 1 ; ADDR Sets mode to modify cell address 001C00 1 ; DATA Sets mode to modify data in open cell 001C00 1 ; STEP increment to next cell 001C00 1 ; RST systme reset 001C00 1 ; RUN GOEXEC 001C00 1 ; STOP $1C00 can be loaded into NMIV to use stop feature 001C00 1 ; PC Display PC 001C00 1 ; 001C00 1 ; CLOCK clock is disabled in SIGMA 1 001C00 1 ; 001C00 1 ; .org $1C00 001C00 1 ; 001C00 1 85 F3 SAVE: sta ACC ; KIM entry via Stop (NMI) or BRK (IRQ) 001C02 1 68 pla 001C03 1 85 F1 sta PREG 001C05 1 ; KIM-entry via JSR (A lost) 001C05 1 68 SAVE1: pla 001C06 1 85 EF sta PCL 001C08 1 85 FA sta POINTL 001C0A 1 68 pla 001C0B 1 85 F0 sta PCH 001C0D 1 85 FB sta POINTH 001C0F 1 84 F4 SAVE2: sty YREG 001C11 1 86 F5 stx XREG 001C13 1 BA tsx 001C14 1 86 F2 stx SPUSER 001C16 1 20 88 1E jsr INITS 001C19 1 4C 4F 1C jmp START 001C1C 1 ; 001C1C 1 6C FA 17 NMIT: jmp (NMIV) ; Non-Maskable Interrupt trap 001C1F 1 6C FE 17 IRQT: jmp (IRQV) ; Interrupt trap 001C22 1 ; 001C22 1 ; KIM entry via reset 001C22 1 A2 FF RESET: ldx #$FF 001C24 1 9A txs 001C25 1 86 F2 stx SPUSER 001C27 1 20 88 1E jsr INITS 001C2A 1 ; 001C2A 1 A9 FF DETCPS: lda #$FF ; count start bit 001C2C 1 8D F3 17 sta CNTH30 ; zero CNTH30 001C2F 1 A9 01 lda #$01 ; mask high order bits 001C31 1 2C 40 17 DET1: bit SAD ; test 001C34 1 D0 19 bne START ; keyboard SSW test 001C36 1 30 F9 bmi DET1 ; start bit test 001C38 1 A9 FC lda #$FC 001C3A 1 18 DET3: clc ; this loop counts the start bit time 001C3B 1 69 01 adc #$01 001C3D 1 90 03 bcc DET2 001C3F 1 EE F3 17 inc CNTH30 001C42 1 AC 40 17 DET2: ldy SAD ; check for end of start bit 001C45 1 10 F3 bpl DET3 001C47 1 8D F2 17 sta CNTL30 001C4A 1 A2 08 ldx #$08 001C4C 1 20 6A 1E jsr GET5 ; get rest of the character 001C4F 1 ; 001C4F 1 ; Make TTY/KB selection 001C4F 1 20 8C 1E START: jsr INIT1 001C52 1 A9 01 lda #$01 001C54 1 2C 40 17 bit SAD 001C57 1 D0 1E bne TTYKB 001C59 1 20 2F 1E jsr CRLF ; print carriage return, linefeed 001C5C 1 A2 0A ldx #$0A ; type output 'KIM' 001C5E 1 20 31 1E jsr PRTST 001C61 1 4C AF 1D jmp SHOW1 001C64 1 ; 001C64 1 A9 00 CLEAR: lda #$00 001C66 1 85 F8 sta INL ; clear input buffer 001C68 1 85 F9 sta INH 001C6A 1 ; 001C6A 1 20 5A 1E READ: jsr GETCH ; get character 001C6D 1 C9 01 cmp #$01 001C6F 1 F0 06 beq TTYKB 001C71 1 20 AC 1F jsr PACK 001C74 1 4C DB 1D jmp SCAN 001C77 1 ; 001C77 1 ; Main routine for keyboard and display 001C77 1 20 19 1F TTYKB: jsr SCAND ; if A=0 no key 001C7A 1 D0 D3 bne START 001C7C 1 A9 01 TTYKB1: lda #$01 001C7E 1 2C 40 17 bit SAD 001C81 1 F0 CC beq START 001C83 1 20 19 1F jsr SCAND 001C86 1 F0 F4 beq TTYKB1 001C88 1 20 19 1F jsr SCAND 001C8B 1 F0 EF beq TTYKB1 001C8D 1 ; 001C8D 1 20 6A 1F GETK: jsr GETKEY 001C90 1 C9 15 cmp #$15 001C92 1 10 BB bpl START 001C94 1 C9 14 cmp #$14 001C96 1 F0 44 beq PCCMD ; display Program Counter 001C98 1 C9 10 cmp #$10 ; address mode=1 001C9A 1 F0 2C beq ADDRM 001C9C 1 C9 11 cmp #$11 ; data mode=1 001C9E 1 F0 2C beq DATAM 001CA0 1 C9 12 cmp #$12 ; Step 001CA2 1 F0 2F beq STEP 001CA4 1 C9 13 cmp #$13 ; Run 001CA6 1 F0 31 beq GOV 001CA8 1 0A DATA: asl ; shift character into high order nibble 001CA9 1 0A asl 001CAA 1 0A asl 001CAB 1 0A asl 001CAC 1 85 FC sta TEMP ; store in temp 001CAE 1 A2 04 ldx #$04 001CB0 1 A4 FF DATA1: ldy MODE ; test mode 1=ADDR 001CB2 1 D0 0A bne ADDR ; mode=0 DATA 001CB4 1 B1 FA lda (POINTL),Y ; set data 001CB6 1 06 FC asl TEMP ; shift character 001CB8 1 2A rol A ; shift data 001CB9 1 91 FA sta (POINTL),Y ; store out data 001CBB 1 4C C3 1C jmp DATA2 001CBE 1 ; 001CBE 1 0A ADDR: asl A ; shift character 001CBF 1 26 FA rol POINTL ; shift address 001CC1 1 26 FB rol POINTH ; shift address high 001CC3 1 CA DATA2: dex 001CC4 1 D0 EA bne DATA1 ; do four times 001CC6 1 F0 08 beq DATAM2 ; exit here 001CC8 1 ; 001CC8 1 A9 01 ADDRM: lda #$01 001CCA 1 D0 02 bne DATAM1 ; -> always 001CCC 1 ; 001CCC 1 A9 00 DATAM: lda #$00 001CCE 1 85 FF DATAM1: sta MODE 001CD0 1 4C 4F 1C DATAM2: jmp START 001CD3 1 ; 001CD3 1 20 63 1F STEP: jsr INCPT 001CD6 1 4C 4F 1C jmp START 001CD9 1 ; 001CD9 1 4C C8 1D GOV: jmp GOEXEC 001CDC 1 ; 001CDC 1 ; Display PC by moving PC to POINT 001CDC 1 A5 EF PCCMD: lda PCL 001CDE 1 85 FA sta POINTL 001CE0 1 A5 F0 lda PCH 001CE2 1 85 FB sta POINTH 001CE4 1 4C 4F 1C jmp START 001CE7 1 ; 001CE7 1 ; Load Paper Tape from TTY 001CE7 1 20 5A 1E LOAD: jsr GETCH ; look for first character 001CEA 1 C9 3B cmp #';' ; semicolon 001CEC 1 D0 F9 bne LOAD 001CEE 1 001CEE 1 A9 00 LOADS: lda #$00 001CF0 1 85 F7 sta CHKSUM 001CF2 1 85 F6 sta CHKHI 001CF4 1 20 9D 1F jsr GETBYT ; get byte count 001CF7 1 AA tax ; save in X index 001CF8 1 20 91 1F jsr CHK ; compute checksum 001CFB 1 20 9D 1F jsr GETBYT ; get address high 001CFE 1 85 FB sta POINTH 001D00 1 20 91 1F jsr CHK 001D03 1 20 9D 1F jsr GETBYT ; get address low 001D06 1 85 FA sta POINTL 001D08 1 20 91 1F jsr CHK ; Compute checksum 001D0B 1 ; 001D0B 1 8A txa ; if count=0 don't get any data 001D0C 1 F0 0F beq LOAD3 001D0E 1 ; 001D0E 1 20 9D 1F LOAD2: jsr GETBYT ; get DATA 001D11 1 91 FA sta (POINTL),y ; store data 001D13 1 20 91 1F jsr CHK 001D16 1 20 63 1F jsr INCPT ; next address 001D19 1 CA dex 001D1A 1 D0 F2 bne LOAD2 001D1C 1 E8 inx ; X=1 data record 001D1D 1 ; X=0 last record 001D1D 1 20 9D 1F LOAD3: jsr GETBYT ; compare checksum 001D20 1 C5 F6 cmp CHKHI 001D22 1 D0 17 bne LOADE1 001D24 1 20 9D 1F jsr GETBYT 001D27 1 C5 F7 cmp CHKSUM 001D29 1 D0 13 bne LOADER 001D2B 1 8A txa ; X=0 last record 001D2C 1 D0 B9 bne LOAD 001D2E 1 A2 0C LOAD7: ldx #$0C ; X-OFF KIM 001D30 1 A9 27 LOAD8: lda #$27 001D32 1 8D 42 17 sta SBD ; disable data in 001D35 1 20 31 1E jsr PRTST 001D38 1 4C 4F 1C jmp START 001D3B 1 20 9D 1F LOADE1: jsr GETBYT ; dummy 001D3E 1 A2 11 LOADER: ldx #$11 ; X-OFF error KIM 001D40 1 D0 EE bne LOAD8 001D42 1 ; 001D42 1 ; Dump to TTY from Open Cell Address to LIMHL, LIMHH 001D42 1 A9 00 DUMP: lda #$00 001D44 1 85 F8 sta INL 001D46 1 85 F9 sta INH ; clear record count 001D48 1 A9 00 DUMP0: lda #$00 001D4A 1 85 F6 sta CHKHI ; clear checksum 001D4C 1 85 F7 sta CHKSUM 001D4E 1 ; 001D4E 1 20 2F 1E DUMP1: jsr CRLF ; print carriage return, linefeed 001D51 1 A9 3B lda #';' ; print semicolon 001D53 1 20 A0 1E jsr OUTCH 001D56 1 A5 FA lda POINTL ; test point greater or equal 001D58 1 CD F7 17 cmp EAL ; high limit go to exit 001D5B 1 A5 FB lda POINTH 001D5D 1 ED F8 17 sbc EAH 001D60 1 90 18 bcc DUMP4 001D62 1 ; 001D62 1 A9 00 lda #$00 ; print last record 001D64 1 20 3B 1E jsr PRTBYT ; 0 bytes 001D67 1 20 CC 1F jsr OPEN 001D6A 1 20 1E 1E jsr PRTPNT 001D6D 1 ; 001D6D 1 A5 F6 lda CHKHI ; print checksum 001D6F 1 20 3B 1E jsr PRTBYT ; for last record 001D72 1 A5 F7 lda CHKSUM 001D74 1 20 3B 1E jsr PRTBYT 001D77 1 4C 64 1C jmp CLEAR 001D7A 1 ; 001D7A 1 A9 18 DUMP4: lda #$18 ; print 24-byte count 001D7C 1 AA tax ; save as index 001D7D 1 20 3B 1E jsr PRTBYT 001D80 1 20 91 1F jsr CHK 001D83 1 20 1E 1E jsr PRTPNT 001D86 1 ; 001D86 1 A0 00 DUMP2: ldy #$00 ; print 24 bytes 001D88 1 B1 FA lda (POINTL),y ; get data 001D8A 1 20 3B 1E jsr PRTBYT ; print data 001D8D 1 20 91 1F jsr CHK ; compare checksum 001D90 1 20 63 1F jsr INCPT ; increment point 001D93 1 CA dex 001D94 1 D0 F0 bne DUMP2 001D96 1 A5 F6 lda CHKHI ; print checksum 001D98 1 20 3B 1E jsr PRTBYT 001D9B 1 A5 F7 lda CHKSUM 001D9D 1 20 3B 1E jsr PRTBYT 001DA0 1 E6 F8 inc INL ; increment record counter 001DA2 1 D0 02 bne DUMP3 001DA4 1 E6 F9 inc INH 001DA6 1 4C 48 1D DUMP3: jmp DUMP0 001DA9 1 ; 001DA9 1 20 CC 1F SPACE: jsr OPEN ; open new cell 001DAC 1 20 2F 1E SHOW: jsr CRLF ; print carriage return, linefeed 001DAF 1 20 1E 1E SHOW1: jsr PRTPNT 001DB2 1 20 9E 1E jsr OUTSP ; print space 001DB5 1 A0 00 ldy #$00 ; print data specified 001DB7 1 B1 FA lda (POINTL),y ; by POINT AD=LDA EXT 001DB9 1 20 3B 1E jsr PRTBYT 001DBC 1 20 9E 1E jsr OUTSP ; print space 001DBF 1 4C 64 1C jmp CLEAR 001DC2 1 ; 001DC2 1 20 63 1F RTRN: jsr INCPT ; open next cell 001DC5 1 4C AC 1D jmp SHOW 001DC8 1 ; 001DC8 1 A6 F2 GOEXEC: ldx SPUSER 001DCA 1 9A txs 001DCB 1 A5 FB lda POINTH ; program runs from 001DCD 1 48 pha ; open cell address 001DCE 1 A5 FA lda POINTL 001DD0 1 48 pha 001DD1 1 A5 F1 lda PREG 001DD3 1 48 pha 001DD4 1 A6 F5 ldx XREG ; restore registers 001DD6 1 A4 F4 ldy YREG 001DD8 1 A5 F3 lda ACC 001DDA 1 40 rti 001DDB 1 ; 001DDB 1 C9 20 SCAN: cmp #$20 ; open cell 001DDD 1 F0 CA beq SPACE 001DDF 1 C9 7F cmp #$7F ; rub out (KIM) 001DE1 1 F0 1B beq STV 001DE3 1 C9 0D cmp #$0D ; next cell 001DE5 1 F0 DB beq RTRN 001DE7 1 C9 0A cmp #$0A ; previous cell 001DE9 1 F0 1C beq FEED 001DEB 1 C9 2E cmp #'.' ; modify cell 001DED 1 F0 26 beq MODIFY 001DEF 1 C9 47 cmp #'G' ; execute program 001DF1 1 F0 D5 beq GOEXEC 001DF3 1 C9 51 cmp #'Q' ; dump from open cell to high limit 001DF5 1 F0 0A beq DUMPV 001DF7 1 C9 4C cmp #'L' ; load tape 001DF9 1 F0 09 beq LOADV 001DFB 1 4C 6A 1C jmp READ ; ignore illegal character 001DFE 1 ; 001DFE 1 4C 4F 1C STV: jmp START 001E01 1 4C 42 1D DUMPV: jmp DUMP 001E04 1 4C E7 1C LOADV: jmp LOAD 001E07 1 ; 001E07 1 38 FEED: sec 001E08 1 A5 FA lda POINTL ; decrement double byte 001E0A 1 E9 01 sbc #$01 ; at POINTL and POINTH 001E0C 1 85 FA sta POINTL 001E0E 1 B0 02 bcs FEED1 001E10 1 C6 FB dec POINTH 001E12 1 4C AC 1D FEED1: jmp SHOW 001E15 1 ; 001E15 1 A0 00 MODIFY: ldy #$00 ; get contents of input buffer 001E17 1 A5 F8 lda INL ; INL and store in location 001E19 1 91 FA sta (POINTL),y ; specified by POINT 001E1B 1 4C C2 1D jmp RTRN 001E1E 1 ; 001E1E 1 ; Subroutines Follow 001E1E 1 ; 001E1E 1 ; Subroutine to print POINTL, POINTH 001E1E 1 A5 FB PRTPNT: lda POINTH 001E20 1 20 3B 1E jsr PRTBYT 001E23 1 20 91 1F jsr CHK 001E26 1 A5 FA lda POINTL 001E28 1 20 3B 1E jsr PRTBYT 001E2B 1 20 91 1F jsr CHK 001E2E 1 60 rts 001E2F 1 ; 001E2F 1 ; Print String of ASCII characters from TOP+X to TOP 001E2F 1 A2 07 CRLF: ldx #$07 001E31 1 BD D5 1F PRTST: lda TOP,x 001E34 1 20 A0 1E jsr OUTCH 001E37 1 CA dex 001E38 1 10 F7 bpl PRTST ; stop on index 0 001E3A 1 60 PRT1: rts 001E3B 1 ; 001E3B 1 ; Print one Hexadecimal Byte as two ASCII Characters 001E3B 1 85 FC PRTBYT: sta TEMP 001E3D 1 4A lsr ; shift A right 4-bits 001E3E 1 4A lsr 001E3F 1 4A lsr 001E40 1 4A lsr 001E41 1 20 4C 1E jsr HEXTA ; convert to HEX and print 001E44 1 A5 FC lda TEMP ; get other half 001E46 1 20 4C 1E jsr HEXTA ; convert to HEX and print 001E49 1 A5 FC lda TEMP ; restore byte in A and return 001E4B 1 60 rts 001E4C 1 ; 001E4C 1 29 0F HEXTA: and #$0F ; mask high 4-bits 001E4E 1 C9 0A cmp #$0A 001E50 1 18 clc 001E51 1 30 02 bmi HEXTA1 001E53 1 69 07 adc #$07 ; alpha hex 001E55 1 69 30 HEXTA1: adc #$30 ; decimal hex 001E57 1 4C A0 1E jmp OUTCH ; print character 001E5A 1 ; 001E5A 1 ; Get One Character from TTY 001E5A 1 ; return from subroutine with character in A 001E5A 1 ; X is preserved and Y returned=$FF 001E5A 1 86 FD GETCH: stx TMPX ; save X register 001E5C 1 A2 08 ldx #$08 ; set up 8-bit counter 001E5E 1 A9 01 lda #$01 001E60 1 2C 40 17 GET1: bit SAD 001E63 1 D0 22 bne GET6 001E65 1 30 F9 bmi GET1 ; wait for start bit 001E67 1 20 D4 1E jsr DELAY ; delay 1-bit 001E6A 1 20 EB 1E GET5: jsr DEHALF ; delay 1/2 bit time 001E6D 1 AD 40 17 GET2: lda SAD ; get 8 bits 001E70 1 29 80 and #$80 ; mask off low order bits 001E72 1 46 FE lsr CHAR ; shift right character 001E74 1 05 FE ora CHAR 001E76 1 85 FE sta CHAR 001E78 1 20 D4 1E jsr DELAY ; delay 1-bit time 001E7B 1 CA dex 001E7C 1 D0 EF bne GET2 ; get next character 001E7E 1 20 EB 1E jsr DEHALF ; exit this return 001E81 1 ; 001E81 1 A6 FD ldx TMPX 001E83 1 A5 FE lda CHAR 001E85 1 2A rol A ; shift off parity 001E86 1 4A lsr 001E87 1 60 GET6: rts 001E88 1 ; 001E88 1 ; Initialisation for SIGMA 001E88 1 A2 01 INITS: ldx #$01 ; set keyboard mode to address 001E8A 1 86 FF stx MODE 001E8C 1 ; 001E8C 1 A2 00 INIT1: ldx #$00 001E8E 1 8E 41 17 stx PADD ; for SIGMA use SADD 001E91 1 A2 3F ldx #$3F 001E93 1 8E 43 17 stx PBDD ; for SIGMA use SADD 001E96 1 ; PB6,PB7=input 001E96 1 A2 07 ldx #$07 ; enable data in 001E98 1 8E 42 17 stx SBD ; output 001E9B 1 D8 cld 001E9C 1 78 sei 001E9D 1 60 rts 001E9E 1 ; 001E9E 1 ; Output One Character, Character=A 001E9E 1 ; X is preserved, Y returned=$FF 001E9E 1 ; OUTSP prints one space 001E9E 1 A9 20 OUTSP: lda #' ' ; print space 001EA0 1 85 FE OUTCH: sta CHAR 001EA2 1 86 FD stx TMPX 001EA4 1 20 D4 1E jsr DELAY ; 10/11 bit code sync 001EA7 1 AD 42 17 lda SBD ; start bit 001EAA 1 29 FE and #$FE 001EAC 1 8D 42 17 sta SBD 001EAF 1 20 D4 1E jsr DELAY 001EB2 1 A2 08 ldx #$08 001EB4 1 AD 42 17 OUT1: lda SBD ; data bit 001EB7 1 29 FE and #$FE 001EB9 1 46 FE lsr CHAR 001EBB 1 69 00 adc #$00 001EBD 1 8D 42 17 sta SBD 001EC0 1 20 D4 1E jsr DELAY 001EC3 1 CA dex 001EC4 1 D0 EE bne OUT1 001EC6 1 AD 42 17 lda SBD ; stop bit 001EC9 1 09 01 ora #$01 001ECB 1 8D 42 17 sta SBD 001ECE 1 20 D4 1E jsr DELAY ; stop bit 001ED1 1 A6 FD ldx TMPX ; restore index 001ED3 1 60 rts 001ED4 1 ; 001ED4 1 ; Delay 1-bit time as determined by DETCPS 001ED4 1 AD F3 17 DELAY: lda CNTH30 ; this loop simulates the DETOPS section and will delay 1-bit time 001ED7 1 8D F4 17 sta TIMH 001EDA 1 AD F2 17 lda CNTL30 001EDD 1 38 DE2: sec 001EDE 1 E9 01 DE4: sbc #$01 001EE0 1 B0 03 bcs DE3 001EE2 1 CE F4 17 dec TIMH 001EE5 1 AC F4 17 DE3: ldy TIMH 001EE8 1 10 F3 bpl DE2 001EEA 1 60 rts 001EEB 1 ; 001EEB 1 ; Delay Half a Bit Time 001EEB 1 AD F3 17 DEHALF: lda CNTH30 ; double right shift of delay 001EEE 1 8D F4 17 sta TIMH ; constant for A divided by 2 001EF1 1 AD F2 17 lda CNTL30 001EF4 1 4A lsr 001EF5 1 4E F4 17 lsr TIMH 001EF8 1 90 E3 bcc DE2 001EFA 1 09 80 ora #$80 001EFC 1 B0 E0 bcs DE4 001EFE 1 ; 001EFE 1 ; Subroutine to Determine if Key is depressed or Condition of SSW 001EFE 1 ; Key not depressed or TTY mode A=0 001EFE 1 ; Key depressed or Keyboard mode A<>0 001EFE 1 A0 03 AK: ldy #$03 ; three rows 001F00 1 A2 01 ldX #$01 ; digit 0 001F02 1 ; 001F02 1 A9 FF ONEKEY: lda #$FF 001F04 1 8E 42 17 AK1: stx SBD ; output digit 001F07 1 E8 inx ; get next digit 001F08 1 E8 inx 001F09 1 2D 40 17 and SAD ; input segments 001F0C 1 88 dey 001F0D 1 D0 F5 bne AK1 001F0F 1 A0 07 ldy #$07 001F11 1 8C 42 17 sty SBD 001F14 1 09 80 ora #$80 001F16 1 49 FF eor #$FF 001F18 1 60 rts 001F19 1 ; 001F19 1 ; Subroutine Output to 7-Segment Display 001F19 1 A0 00 SCAND: ldy #$00 ; get data specified 001F1B 1 B1 FA lda (POINTL),Y ; by POINT 001F1D 1 85 F9 sta INH ; set up display buffer 001F1F 1 A9 7F SCANDS: lda #$7F ; change segment 001F21 1 8D 41 17 sta PADD ; to output 001F24 1 ; 001F24 1 A2 09 ldX #$09 ; initialise digit number 001F26 1 A0 03 ldy #$03 ; output 3-bytes 001F28 1 B9 F8 00 SCAND1: lda INL,y ; get byte 001F2B 1 4A lsr ; get MSD 001F2C 1 4A lsr 001F2D 1 4A lsr 001F2E 1 4A lsr 001F2F 1 20 48 1F jsr CONVD ; output character 001F32 1 B9 F8 00 lda INL,y ; get byte again 001F35 1 29 0F and #$0F ; get LSD 001F37 1 20 48 1F jsr CONVD ; output character 001F3A 1 88 dey ; setup for next byte 001F3B 1 D0 EB bne SCAND1 001F3D 1 8E 42 17 stx SBD ; all digits off 001F40 1 A9 00 lda #$00 ; change segments 001F42 1 8D 41 17 sta PADD ; to inputs 001F45 1 4C FE 1E jmp AK ; get any key 001F48 1 ; 001F48 1 ; Convert and Display Hex 001F48 1 ; used by SCAND only 001F48 1 84 FC CONVD: sty TEMP ; save Y 001F4A 1 A8 tay ; use character as index 001F4B 1 B9 E7 1F lda TABLE,Y ; lookup conversion 001F4E 1 A0 00 ldy #$00 ; turn off segments 001F50 1 8C 40 17 sty SAD 001F53 1 8E 42 17 stx SBD ; output digit enable 001F56 1 8D 40 17 sta SAD ; output segments 001F59 1 A0 7F ldy #$7F ; delay ~500 cycles 001F5B 1 88 CONVD1: dey 001F5C 1 D0 FD bne CONVD1 001F5E 1 ; 001F5E 1 E8 inx ; get next digit number 001F5F 1 E8 inx ; add two 001F60 1 A4 FC ldy TEMP ; restore Y 001F62 1 60 rts 001F63 1 ; 001F63 1 ; Subroutine to Increment POINT 001F63 1 E6 FA INCPT: inc POINTL 001F65 1 D0 02 bne INCPT2 001F67 1 E6 FB inc POINTH 001F69 1 60 INCPT2: rts 001F6A 1 ; 001F6A 1 ; Get Key from Keyboard 001F6A 1 ; return with A=key value 001F6A 1 ; A greater than 15 then illegal or no key 001F6A 1 A2 21 GETKEY: ldx #$21 ; start at digit 0 001F6C 1 A0 01 GETKE5: ldy #$01 ; get one row 001F6E 1 20 02 1F jsr ONEKEY 001F71 1 D0 07 bne KEYIN ; A=0 no key 001F73 1 E0 27 cpx #$27 ; test for digit 2 001F75 1 D0 F5 bne GETKE5 001F77 1 A9 15 lda #$15 ; 15 = no key 001F79 1 60 rts 001F7A 1 A0 FF KEYIN: ldy #$FF 001F7C 1 0A KEYIN1: asl ; shift left 001F7D 1 B0 03 bcs KEYIN2 ; until Y=key number 001F7F 1 C8 iny 001F80 1 10 FA bpl KEYIN1 001F82 1 8A KEYIN2: txa 001F83 1 29 0F and #$0F ; mask MSD 001F85 1 4A lsr ; divide by two 001F86 1 AA tax 001F87 1 98 tya 001F88 1 10 03 bpl KEYIN4 001F8A 1 18 KEYIN3: clc 001F8B 1 69 07 adc #$07 ; multiply (X-1) times A 001F8D 1 CA KEYIN4: dex 001F8E 1 D0 FA bne KEYIN3 001F90 1 60 rts 001F91 1 ; 001F91 1 ; Subroutine to Compute Checksum 001F91 1 18 CHK: clc 001F92 1 65 F7 adc CHKSUM 001F94 1 85 F7 sta CHKSUM 001F96 1 A5 F6 lda CHKHI 001F98 1 69 00 adc #$00 001F9A 1 85 F6 sta CHKHI 001F9C 1 60 rts 001F9D 1 ; 001F9D 1 ; Get Two Hexadecimal Characters and Pack into INL and INH 001F9D 1 ; X preserved, Y retuned=0 001F9D 1 ; Non-hexadecimal charaters will be loaded as nearest hex equivalent 001F9D 1 20 5A 1E GETBYT: jsr GETCH 001FA0 1 20 AC 1F jsr PACK 001FA3 1 20 5A 1E jsr GETCH 001FA6 1 20 AC 1F jsr PACK 001FA9 1 A5 F8 lda INL 001FAB 1 60 rts 001FAC 1 ; 001FAC 1 ; Shift Character in A into INL and INH 001FAC 1 C9 30 PACK: cmp #$30 ; check for hex 001FAE 1 30 1B bmi UPDAT2 001FB0 1 C9 47 cmp #$47 ; not hex exit 001FB2 1 10 17 bpl UPDAT2 001FB4 1 C9 40 HEXNUM: cmp #$40 ; convert to hex 001FB6 1 30 03 bmi UPDATE 001FB8 1 18 HEXALP: clc 001FB9 1 69 09 adc #$09 001FBB 1 2A UPDATE: rol 001FBC 1 2A rol 001FBD 1 2A rol 001FBE 1 2A rol 001FBF 1 A0 04 ldy #$04 ; shift into I/O buffer 001FC1 1 2A UPDAT1: rol A 001FC2 1 26 F8 rol INL 001FC4 1 26 F9 rol INH 001FC6 1 88 dey 001FC7 1 D0 F8 bne UPDAT1 001FC9 1 A9 00 lda #$00 ; A=0 if hex number 001FCB 1 60 UPDAT2: rts 001FCC 1 ; 001FCC 1 A5 F8 OPEN: lda INL ; move I/O Buffer to POINT 001FCE 1 85 FA sta POINTL 001FD0 1 A5 F9 lda INH ; transfer INH=POINTH 001FD2 1 85 FB sta POINTH 001FD4 1 60 rts 001FD5 1 ; End of Subroutines 001FD5 1 ; 001FD5 1 ; Tables 001FD5 1 ; 001FD5 1 00 00 00 00 TOP: .byte 0,0,0,0,0,0,10,13 001FD9 1 00 00 0A 0D 001FDD 1 4D 49 4B .byte "MIK" 001FE0 1 20 13 .byte " ",$13 001FE2 1 52 52 45 20 .byte "RRE " 001FE6 1 13 .byte $13 001FE7 1 ; 001FE7 1 ; Hex -> 7-segment 001FE7 1 ;0 1 2 3 4 5 6 7 8 9 A B C D E F 001FE7 1 BF 86 DB CF TABLE: .byte $BF,$86,$DB,$CF,$E6,$ED,$FD,$87,$FF,$EF,$F7,$FC,$B9,$DE,$F9,$F1 001FEB 1 E6 ED FD 87 001FEF 1 FF EF F7 FC 001FF7 1 ; 001FF7 1 FF FF FF .byte $FF,$FF,$FF ; Packing 001FFA 1 ; 001FFA 1 ; *** Interrupt Vectors *** 001FFA 1 1C 1C NMIENT: .word NMIT 001FFC 1 22 1C RSTENT: .word RESET 001FFE 1 1F 1C IRQENT: .word IRQT 002000 1 002000 1