; Compiler: Vasm-6502

;- - - - - - - - - - - - - - KIM.ASM - - - - - - - - - - -
; COPYRIGHT MOS TECHNOLOGY, INC
; DATE: OCT 18, 1975 REV-D
;************************ 6530-003 I.C. ******************
; 6530-003 I.C. IS AN AUDIO CASSETTE TAPE RECORDER
; EXTENSION OF THE BASIC KIM MONITOR.  IT FEATURES
; TWO ROUTINES:
;   LOADT - LOAD MEMORY FROM AUDIO TAPE
;     ID=00     IGNORE ID
;     ID=FF     IGNORE ID, USE SA FOR START ADDR
;     ID=01-FE  USE ADDRESS ON TAPE
;
;   DUMPT - STORE MEMORY ONTO AUDIO TAPE
;     ID=00     SHOULD NOT BE USED
;     ID=FF     SHOULD NOT BE USED
;     ID=01-FE  NORMAL ID RANGE
;     SAL       LSB STARTING ADDRESS OF PROGRAM
;     SAH       MSB
;     EAL       ENDING ADDRESS OF PROGRAM
;     EAH       MSB
;
        .org  $1800
SAD     =     $1740     ; 6530 A DATA
PADD    =     $1741     ; 6530 A DATA DIRECTION
SBD     =     $1742     ; 6530 B DATA
PBDD    =     $1743     ; 6530 B DATA DIRECTION
CLK1T   =     $1744     ; DIV BY 1 TIME
CLK8T   =     $1745     ; DIV BY 8 TIME
CLK64T  =     $1746     ; DIV BY 64 TIME
CLKKT   =     $1747     ; DIV BY 1024 TIME
CLKRDI  =     $1747     ; READ TIME OUT BIT
CLKRDT  =     $1746     ; READ TIME
;       ** MPU REG.  SAVX AREA IN PAGE 0 **
PCL     =     $EF       ; PROGRAM CNT LOW
PCH     =     $F0       ; PROGRAM CNT HI
PREG    =     $F1       ; CURRENT STATUS REG
SPUSER  =     $F2       ; CURRENT STACK POINTER
ACC     =     $F3       ; ACCUMULATOR
YREG    =     $F4       ; Y INDEX
XREG    =     $F5       ; X INDEX
;       ** KIM FIXED AREA IN PAGE 0  **
CHKHI   =     $F6
CHKSUM  =     $F7
INL     =     $F8       ; INPUT BUFFER
INH     =     $F9       ; INPUT BUFFER
POINTL  =     $FA       ; LSB OF OPEN CELL
POINTH  =     $FB       ; MSB OF OPEN CELL
TEMP    =     $FC
TMPX    =     $FD
CHAR    =     $FE
MODE    =     $FF
;       ** KIM FIXED AREA IN PAGE 23 **
CHKL    =     $17E7
CHKH    =     $17E8     ; CHKSUM
SAVX    =     $17E9     ; (3-BYTES)
VEB     =     $17EC     ; VOLATILE EXEC BLOCK (6-B)
CNTL30  =     $17F2     ; TTY DELAY
CNTH30  =     $17F3     ; TTY DELAY
TIMH    =     $17F4
SAL     =     $17F5     ; LOW STARTING ADDRESS
SAH     =     $17F6     ; HI STARTING ADDRESS
EAL     =     $17F7     ; LOW ENDING ADDRESS
EAH     =     $17F8     ; HI ENDING ADDRESS
ID      =     $17F9     ; TAPE PROGRAM ID NUMBER
;       ** INTERRUPT VECTORS **
NMIV    =     $17FA     ; STOP VECTOR (STOP=1C00)
RSTV    =     $17FC     ; RST VECTOR
IRQV    =     $17FE     ; IRQ VECTOR (BRK=1C00)

;
;       ** DUMP MEMORY TO TAPE **
DUMPT   LDA   #$AD      ; LOAD ABSOLUTE INST            1800
        STA   VEB   
        JSR   INTVEB
        LDA   #$27      ; TURN OFF DATAIN PB5
        STA   SBD   
        LDA   #$BF      ; CONVERT PB7 TO OUTPUT
        STA   PBDD  
        LDX   #$64      ; 100 CHARS 
DUMPT1  LDA   #$16      ; SYNC CHARS
        JSR   OUTCHT
        DEX         
        BNE   DUMPT1
        LDA   #$2A      ; START CHAR
        JSR   OUTCHT
        LDA   ID        ; OUTPUT ID 
        JSR   OUTBT 
        LDA   SAL       ; OUTPUT STARTING
        JSR   OUTBTC    ; ADDRESS 
        LDA   SAH   
        JSR   OUTBTC
DUMPT2  LDA   VEB+1     ; CHECK FOR LAST
        CMP   EAL       ; DATA BYTE
        LDA   VEB+2 
        SBC   EAH   
        BCC   DUMPT4
        LDA   #'/'      ; OUTPUT END-OF-DATA CHAR
        JSR   OUTCHT
        LDA   CHKL      ; LAST BYTE HAS BEEN 
        JSR   OUTBT     ; OUTPUT  NOW OUTPUT
        LDA   CHKH      ; CHKSUM
        JSR   OUTBT 
        LDX   #$02      ; 2 CHARS
DUMPT3  LDA   #$04      ; EOT CHAR       
        JSR   OUTCHT 
        DEX          
        BNE   DUMPT3    
        LDA   #$00      ; DISPLAY 0000
        STA   POINTL    ; FOR NORMAL EXIT
        STA   POINTH  
        JMP   START
DUMPT4  JSR   VEB       ; DATA BYTE OUTPUT
        JSR   OUTBTC
        JSR   INCVEB
        JMP   DUMPT2
;
;       ** LOAD MEMORY FROM TAPE **
;
TAB     .WORD LOAD12    ; 'LOAD12' ADDRESS            1871
;
LOADT   LDA   #$8D      ; INIT VOLATILE EXECUTION       1873
        STA   VEB       ; BLOCK WITH STA ABS.
        JSR   INTVEB
        LDA   #$4C      ; JUMP TYPE RTRN
        STA   VEB+3
        LDA   TAB  
        STA   VEB+4
        LDA   TAB+1
        STA   VEB+5
        LDA   #$07      ; RESET PB5=0 (DATA-IN)
        STA   SBD
SYNC    LDA   #$FF      ; CLEAR SAVX FOR SYNC CHAR      1891
        STA   SAVX 
SYNC1   JSR   RDBIT     ; GET A BIT        
        LSR   SAVX      ; SHIFT BIT INTO CHAR
        ORA   SAVX
        STA   SAVX
        LDA   SAVX      ; GET NEW CHAR
        CMP   #$16      ; SYNC CHAR
        BNE   SYNC1
        LDX   #$0A      ; TEST FOR 10 SYNC CHARS
SYNC2   JSR   RDCHT                      
        CMP   #$16  
        BNE   SYNC      ; IF NOT 10 CHAR, RE-SYNC
        DEX     
        BNE   SYNC2
LOADT4  JSR   RDCHT     ; LOOK FOR START OF
        CMP   #$2A      ; DATA CHAR
        BEQ   LOAD11
        CMP   #$16      ; IF NOT , SHOULD BE SYNC
        BNE   SYNC
        BEQ   LOADT4
LOAD11  JSR   RDBYT     ; READ ID FROM TAPE
        CMP   ID        ; COMPARE WITH REQUESTED ID
        BEQ   LOADT5
        LDA   ID        ; DEFAULT 00, READ RECORD
        CMP   #$00      ; ANYWAY
        BEQ   LOADT5
        CMP   #$FF      ; DEFAULT FF, IGNORE SA ON
        BEQ   LOADT6    ; TAPE
        BNE   LOADT
LOADT5  JSR   RDBYT     ; GET SA FROM TAPE
        JSR   CHKT
        STA   VEB+1     ; SAVX IN VEB+1,2
        JSR   RDBYT
        JSR   CHKT
        STA   VEB+2
        JMP   LOADT7
;
LOADT6  JSR   RDBYT     ; GET SA BUT IGNORE             18EC
        JSR   CHKT
        JSR   RDBYT
        JSR   CHKT
LOADT7  LDX   #$02      ; GET 2 CHARS 
LOAD13  JSR   RDCHT     ; GET CHAR (X)
        CMP   #$2F      ; LOOK FOR LAST CHAR
        BEQ   LOADT8
        JSR   PACKT     ; CONVERT TO HEX
        BNE   LOADT9    ; Y=1 NON-HEX CHAR
        DEX                         
        BNE   LOAD13
        JSR   CHKT      ; COMPARE CHECKSUM
        JMP   VEB       ; SAVX DATA IN MEMORY
LOAD12  JSR   INCVEB    ; INCR DATA POINTER
        JMP   LOADT7
;
LOADT8  JSR   RDBYT     ; END OF DATA, COMPARE CHKSUM   1915
        CMP   CHKL
        BNE   LOADT9
        JSR   RDBYT
        CMP   CHKH
        BNE   LOADT9
        LDA   #$00      ; NORMAL EXIT
        BEQ   LOAD10
LOADT9  LDA   #$FF      ; ERROR EXIT 
LOAD10  STA   POINTL               
        STA   POINTH
        JMP   START
;
;       ** SUBROUTINES BELOW **
INTVEB  LDA   SAL       ; MOVE SA TO VEB+1,2            1932
        STA   VEB+1
        LDA   SAH
        STA   VEB+2
        LDA   #$60      ; RTS INST
        STA   VEB+3
        LDA   #$00      ; CLEAR CHKSUM AREA
        STA   CHKL
        STA   CHKH
        RTS
;       ** COMPUTE CHKSUM FOR TAPE LOAD **
CHKT    TAY             ;                               194C
        CLC     
        ADC   CHKL
        STA   CHKL
        LDA   CHKH
        ADC   #$00
        STA   CHKH
        TYA       
        RTS 
;       ** OUTPUT ONE BYTE **
OUTBTC  JSR   CHKT      ; COMPARE CHKSUM                195E
OUTBT   TAY             ; SAVX DATA BYTE
        LSR   A         ; SHIFT OFF LSD
        LSR   A
        LSR   A
        LSR   A
        JSR   HEXOUT    ; OUTPUT MSD
        TYA 
        JSR   HEXOUT    ; OUTPUT LSD
        TYA  
        RTS 
;       ** CONVERT LSD OF A TO ASCII, OUTPUT TO TAPE **
HEXOUT  AND   #$0F      ;                               196F
        CMP   #$0A      
        CLC   
        BMI   HEX1
        ADC   #$07
HEX1    ADC   #$30
;       ** OUTPUT TO TAPE ONE ASCII CHAR **
OUTCHT  STX   SAVX      ;                               197A
        STY   SAVX+1
        LDY   #$08      ; START BIT
CHT1    JSR   ONE                  
        LSR   A         ; GET DATA BIT
        BCS   CHT2 
        JSR   ONE       ; DATA BIT=1
        JMP   CHT3
CHT2    JSR   ZRO       ; DATA BIT=0 
CHT3    JSR   ZRO                  
        DEY
        BNE   CHT1
        LDX   SAVX
        LDY   SAVX+1
        RTS
;       ** OUTPUT 1 TO TAPE, 9 PULSES, 138 US EACH **
ONE     LDX   #$09      ;                               199E
        PHA             ; SAVX A
ONE1    BIT   CLKRDI    ; WAIT FOR TIME OUT             19A1
        BPL   ONE1
        LDA   #126
        STA   CLK1T
        LDA   #$A7 
        STA   SBD       ; SET PB7 = 1
ONE2    BIT   CLKRDI    ;                               19B0
        BPL   ONE2 
        LDA   #126
        STA   CLK1T
        LDA   #$27 
        STA   SBD       ; RESET PB7=0
        DEX   
        BNE   ONE1
        PLA  
        RTS  
;       ** OUTPUT 0 TO TAPE, 6 PULSES, 207 US EACH **
ZRO     LDX   #$06      ;                               19C4
        PHA             ; SAVX A
ZRO1    BIT   CLKRDI    ;                               19C7
        BPL   ZRO1 
        LDA   #$C3 
        STA   CLK1T
        LDA   #$A7 
        STA   SBD       ; SET PB7=1
ZRO2    BIT   CLKRDI
        BPL   ZRO2 
        LDA   #195 
        STA   CLK1T
        LDA   #$27 
        STA   SBD       ; RESET PB7=0
        DEX        
        BNE   ZRO1
        PLA             ; RESTORE A
        RTS
;       ** SUB TO INC VEB+1,2 **
INCVEB  INC   VEB+1     ;                               19EA
        BNE   INCVE1
        INC   VEB+2
INCVE1  RTS     
;       ** SUB TO READ BYTE FROM TAPE **
RDBYT   JSR   RDCHT     ;                              19F3
        JSR   PACKT
        JSR   RDCHT
        JSR   PACKT
        RTS
;       ** PACK A=ASCII INTO SAVX AS HEX DATA **
PACKT   CMP   #$30      ;                               1A00
        BMI   PACKT3
        CMP   #$47
        BPL   PACKT3
        CMP   #$40  
        BMI   PACKT1
        CLC         
        ADC   #$09  
PACKT1  ROL   A
        ROL   A
        ROL   A
        ROL   A
        LDY   #$04
PACKT2  ROL   A
        ROL   SAVX
        DEY          
        BNE   PACKT2
        LDA   SAVX
        LDY   #$00      ; Y=0 VALID HEX CHAR
        RTS
PACKT3  INY             ; Y=1 NOT HEX
        RTS
;       ** GET 1 CHAR FROM TAPE AND RETURN WITH 
;          CHAR IN A.  USE SAVX+1 TO ASM CHAR  **
RDCHT   STX   SAVX+2    ;                              1A24
        LDX   #$08      ; READ 8 BITS
RDCHT1  JSR   RDBIT     ; GET NEXT DATA BIT
        LSR   SAVX+1    ; RIGHT SHIFT CHAR
        ORA   SAVX+1    ; OR IN SIGN BIT
        STA   SAVX+1    ; REPLACE CHAR
        DEX          
        BNE   RDCHT1
        LDA   SAVX+1    ; MOVE CHAR INTO A
        ROL   A         ; SHIFT OFF PARITY
        LSR   A
        LDX   SAVX+2
        RTS
;       ** THIS SUB GETS ONE BIT FROM TAPE AND
;          RETURNS IT IN SIGN OF A  **
RDBIT   BIT   SBD       ; WAIT FOR END OF START BIT     1A41
        BPL   RDBIT
        LDA   CLKRDT    ; GET START BIT TIME
        LDY   #$FF      ; A=256-T1    
        STY   CLK64T    ; SET UP TIMER
        LDY   #$14  
RDBIT3  DEY             ; DELAY 100 MICRO SEC
        BNE   RDBIT3
RDBIT2  BIT   SBD
        BMI   RDBIT2    ; WAIT FOR NEXT START BIT
        SEC   
        SBC   CLKRDT    ; (256-T1)-(256-T2)=T2-T1
        LDY   #$FF
        STY   CLK64T    ; SET UP TIMER FOR NEXT BIT
        LDY   #$07
RDBIT4  DEY             ; DELAY 50 MICROSEC
        BNE   RDBIT4
        EOR   #$FF      ; COMPLEMENT SIGN OF A
        AND   #$80      ; MASK ALL EXCEPT SIGN
        RTS 
;       ** PLLCAL OUTPUT 166 MICROSEC (6024 HZ)
;          PULSE STRING 
PLLCAL  LDA   #$27      ;                              1A6B
        STA   SBD       ; TURN OFF DATIN PB5=1
        LDA   #$BF      ; CONVERT PB7 TO OUTPUT
        STA   PBDD
PLL1    BIT   CLKRDI
        BPL   PLL1  
        LDA   #154      ; WAIT 166 MICROSEC
        STA   CLK1T
        LDA   #$A7      ; OUTPUT PB7=1
        STA   SBD
PLL2    BIT   CLKRDI
        BPL   PLL2 
        LDA   #154
        STA   CLK1T
        LDA   #$27      ; PB7=0
        STA   SBD
        JMP   PLL1

; Fill unused locations with $FF
;        .res 356, $FF

;
;       ** INTERRUPTS **
        .org  $1BFA
NMIP27  .WORD PLLCAL
RSTP27  .WORD PLLCAL
IRQP27  .WORD PLLCAL

;
;******************* 6530-002 I.C. *****************
;       ** COPYRIGHT MOS TECHNOLOGY INC.
;          DATE OCT 13, 1975 REV E
;
;       ** KIM **
;         TTY INTERFACE   6530-002
;         KEYBOARD INTERFACE,
;         7-SEGMENT 6-DIGIT DISPLAY
;
;       TTY COMANDS:
;         G    GOEXEC
;         CR   OPEN NEXT CELL
;         LF   OPEN PREVIOUS CELL
;         .    MODIFY OPEN CELL
;         SP   OPEN NEW CELL
;         L    LOAD (OBJECT FORMAT)
;         Q    DUMP FROM OPEN CELL ADDR TO HI LIMIT
;         RO   RUB OUT - RETURN TO START KIM
;               (ALL ILLEGAL CHARS ARE IGNORED)
;
;       KEYBOARD COMMANDS:
;         ADDR  SETS MODE TO MODIFY CELL ADDRESS
;         DATA  SETS MODE TO MODIFY DATA IN OPEN CELL
;         STEP  INCREMENTS TO NEXT CELL
;         RST   SYSTEM RESET
;         RUN   GOEXEC
;         STOP  $1C00 CAN BE LOADED INTO NMIV TO USE
;         PC    DISPLAY PC (PROGRAM COUNTER)
;         
        .org  $1C00
SAVE    STA   ACC       ; KIM ENTRY VIA STOP (NMI)      1C00
        PLA             ; OR BRK (IRQ)
        STA   PREG
        PLA             ; KIM ENTRY VIA JSR (A LOST)    1C05
        STA   PCL
        STA   POINTL
        PLA         
        STA   PCH
        STA   POINTH
        STY   YREG
        STX   XREG
        TSX   
        STX   SPUSER
        JSR   INITS
        JMP   START
;
NMIT    JMP   (NMIV)    ; NON-MASKABLE INTERRUPT TRAP   1C1C
IRQT    JMP   (IRQV)    ; INTERRUPT TRAP                1C1F
RST     LDX   #$FF      ; KIM ENTRY VIA RST             1C22
        TXS
        STX   SPUSER
        JSR   INITS
        LDA   #$FF      ; COUNT START BIT
        STA   CNTH30    ; ZERO CNTH30
        LDA   #$01      ; MASK HI ORDER BITS
DET1    BIT   SAD       ; TEST                          1C31
        BNE   START     ; KEYBD SSW TEST
        BMI   DET1      ; START BIT TEST
        LDA   #$FC
DET3    CLC             ; THIS LOOP COUNTS              1C3A
        ADC   #$01      ; THE START BIT TIME
        BCC   DET2
        INC   CNTH30
DET2    LDY   SAD       ; CHECK FOR END OF START BIT    1C42
        BPL   DET3
        STA   CNTL30
        LDX   #$08
        JSR   GET5      ; GET REST OF THE CHAR, TEST CHAR
;                                     ** MAKE TTY/KB SELECTION **
START   JSR   INIT1     ;                               1C4F
        LDA   #$01
        BIT   SAD
        BNE   TTYKB
        JSR   CRLF      ; PRT CR LF
        LDX   #$0A      ; TYPE OUT KIM
        JSR   PRTST
        JMP   SHOW1
;
CLEAR   LDA   #$00
        STA   INL       ; CLEAR INPUT BUFFER
        STA   INH
READ    JSR   GETCH     ; GET CHAR
        CMP   #$01      
        BEQ   TTYKB
        JSR   PACK
        JMP   SCAN
;                                     ** MAIN ROUTINE FOR KEYBOARD AND DISPLAY **
TTYKB   JSR   SCAND     ; IF A=0 NO KEY                 1C77
        BNE   START
TTYKB1  LDA   #$01
        BIT   SAD 
        BEQ   START
        JSR   SCAND
        BEQ   TTYKB1
        JSR   SCAND
        BEQ   TTYKB1
        JSR   GETKEY    ; KEY PRESSED    <-----
        CMP   #$15  
        BPL   START
        CMP   #$14
        BEQ   PCCMD     ; DISPLAY PC
        CMP   #$10      ; ADDR MODE=1
        BEQ   ADDRM
        CMP   #$11      ; DATA MODE=1
        BEQ   DATAM
        CMP   #$12      ; STEP
        BEQ   STEP
        CMP   #$13      ; RUN
        BEQ   GOV
        ASL   A         ; SHIFT CHAR INTO HIGH
        ASL   A         ; ORDER NIBBLE
        ASL   A
        ASL   A
        STA   TEMP      ; STORE IN TEMP
        LDX   #$04
DATA1   LDY   MODE      ; TEST MODE 1=ADDR
        BNE   ADDR      ; MODE=0 DATA
        LDA   (POINTL),Y ; GET DATA
        ASL   TEMP      ; SHIFT CHAR
        ROL   A         ; SHIFT DATA
        STA   (POINTL),Y ; STORE OUT DATA
        JMP   DATA2
;
ADDR    ASL   A         ; SHIFT CHAR
        ROL   POINTL    ; SHIFT ADDR
        ROL   POINTH    ; SHIFT ADDR HI
DATA2   DEX   
        BNE   DATA1     ; DO 4 TIMES
        BEQ   DATAM2    ; EXIT HERE
ADDRM   LDA   #$01
        BNE   DATAM1
DATAM   LDA   #$00 
DATAM1  STA   MODE 
DATAM2  JMP   START
;
STEP    JSR   INCPT     ;                               1CD3
        JMP   START
;                              
GOV     JMP   GOEXEC    ;                               1CD9
;                                     ** DISPLAY PC BY MOVING PC TO POINT **
PCCMD   LDA   PCL       ;                               1CDC
        STA   POINTL
        LDA   PCH
        STA   POINTH
        JMP   START
;                                     ** LOAD PAPER TAPE FROM TTY **
LOAD    JSR   GETCH     ; LOOK FOR FIRST CHAR           1CE7
        CMP   #$3B      ; SEMICOLON
        BNE   LOAD
        LDA   #$00
        STA   CHKSUM
        STA   CHKHI
        JSR   GETBYT    ; GET BYTE COUNT
        TAX             ; SAVE IN X INDEX
        JSR   CHK       ; COMPUTE CHECKSUM
        JSR   GETBYT    ; GET ADDRESS HI
        STA   POINTH
        JSR   CHK
        JSR   GETBYT    ; GET ADDRESS LO
        STA   POINTL
        JSR   CHK
        TXA             ; IF CNT=0 DONT
        BEQ   LOAD3     ; GET ANY DATA
LOAD2   JSR   GETBYT    ; GET DATA
        STA   (POINTL),Y ; STORE DATA
        JSR   CHK
        JSR   INCPT     ; NEXT ADDRESS
        DEX    
        BNE   LOAD2
        INX             ; X=1 DATA RCD X=0 LAST RCD
LOAD3   JSR   GETBYT    ; COMPARE CHKSUM
        CMP   CHKHI
        BNE   LOADE1
        JSR   GETBYT
        CMP   CHKSUM
        BNE   LOADER
        TXA             ; X=0 LAST RECORD
        BNE   LOAD
        LDX   #$0C      ; X-OFF KIM
LOAD8   LDA   #$27
        STA   SBD       ; DISABLE DATA IN
        JSR   PRTST
        JMP   START
;
LOADE1  JSR   GETBYT    ; DUMMY
LOADER  LDX   #$11      ; X-OFF ERR KIM
        BNE   LOAD8
;                                     ** DUMP TO TTY FROM OPEN CELL ADDRESS TO 
;          LIMHL, LIMHH **
DUMP    LDA   #$00      ;                               1D42
        STA   INL
        STA   INH       ; CLEAR RECORD COUNT
DUMP0   LDA   #$00
        STA   CHKHI     ; CLEAR CHKSUM
        STA   CHKSUM
        JSR   CRLF      ; PRINT CR LF
        LDA   #$3B      ; PRINT SEMICOLON
        JSR   OUTCH
        LDA   POINTL    ; TEST POINT GT OR ET
        CMP   EAL       ; HI LIMIT GOTO EXIT
        LDA   POINTH
        SBC   EAH
        BCC   DUMP4
        LDA   #$00      ; PRINT LAST RECORD
        JSR   PRTBYT    ; 0 BYTES
        JSR   OPEN
        JSR   PRTPNT
        LDA   CHKHI     ; PRINT CHKSUM
        JSR   PRTBYT    ; FOR LAST RECORD
        LDA   CHKSUM
        JSR   PRTBYT
        JMP   CLEAR
;
DUMP4   LDA   #$18      ; PRINT 24 BYTE COUNT           1D7A
        TAX             ; SAVE AS INDEX
        JSR   PRTBYT
        JSR   CHK
        JSR   PRTPNT
DUMP2   LDY   #$00      ; PRINT 24 BYTES
        LDA   (POINTL),Y ; GET DATA
        JSR   PRTBYT    ; PRINT DATA
        JSR   CHK       ; COMPUTE CHKSUM
        JSR   INCPT     ; INCREMENT POINT
        DEX
        BNE   DUMP2
        LDA   CHKHI     ; PRINT CHKSUM
        JSR   PRTBYT
        LDA   CHKSUM
        JSR   PRTBYT
        INC   INL       ; INCR RECORD COUNT
        BNE   DUMP3
        INC   INH
DUMP3   JMP   DUMP0
;
SPACE   JSR   OPEN      ; OPEN NEW CELL                 1DA9
SHOW    JSR   CRLF      ; PRINT CR LF
SHOW1   JSR   PRTPNT
        JSR   OUTSP     ; PRINT SPACE
        LDY   #$00      ; PRINT DATA SPECIFIED
        LDA   (POINTL),Y ; BY POINT AD=LDA EXT
        JSR   PRTBYT
        JSR   OUTSP     ; PRINT SPACE
        JMP   CLEAR
;
RTRN    JSR   INCPT     ; OPEN NEXT CELL                1DC2
        JMP   SHOW
;
GOEXEC  LDX   SPUSER    ;                               1DC8
        TXS   
        LDA   POINTH    ; PROGRAM RUNS FROM
        PHA             ; OPEN CELL ADDRESS
        LDA   POINTL
        PHA      
        LDA   PREG
        PHA       
        LDX   XREG      ; RESTORE REGS
        LDY   YREG
        LDA   ACC
        RTI
;
SCAN    CMP   #$20      ; OPEN CELL
        BEQ   SPACE
        CMP   #$7F      ; RUB OUT (KIM)
        BEQ   STV
        CMP   #$0D      ; NEXT CELL
        BEQ   RTRN
        CMP   #$0A      ;PREV CELL
        BEQ   FEED
        CMP   #'.'      ; MODIFY CELL
        BEQ   MODIFY
        CMP   #'G'      ; GO EXEC
        BEQ   GOEXEC
        CMP   #'Q'      ; DUMP FROM OPEN CELL TO HI LIMIT
        BEQ   DUMPV
        CMP   #'L'      ; LOAD TAPE
        BEQ   LOADV
        JMP   READ      ; IGNORE ILLEGAL CHAR
;
STV     JMP   START
DUMPV   JMP   DUMP
LOADV   JMP   LOAD 
;
FEED    SEC             ;                               1E07
        LDA   POINTL    ; DEC DOUBLE BYTE
        SBC   #$01      ; AT POINTL AND POINTH
        STA   POINTL
        BCS   FEED1
        DEC   POINTH
FEED1   JMP   SHOW
;
MODIFY  LDY   #$00      ; GET CONTENTS OF INPUT BUFF 
        LDA   INL       ; INL AND STORE IN LOC
        STA   (POINTL),Y ; SPECIFIED BY POINT
        JMP   RTRN 
;
;                                     ** SUBROUTINES FOLLOW **
PRTPNT  LDA   POINTH    ; PRINT POINTL, POINTH          1E1E
        JSR   PRTBYT
        JSR   CHK
        LDA   POINTL
        JSR   PRTBYT
        JSR   CHK
        RTS
;                                     **PRINT STRING OF ASCII CHARS FROM TOP+X TO TOP
CRLF    LDX   #$07    
PRTST   LDA   TOP,X 
        JSR   OUTCH
        DEX 
        BPL   PRTST     ; STOP ON INDEX ZERO
        RTS
;       ** PRINT 1 HEX BYTE AS 2 ASCII CHARS **
PRTBYT  STA   TEMP      ;                               1E3B
        LSR   A         ; SHIFT CHAR RIGHT 4 BITS
        LSR   A
        LSR   A
        LSR   A
        JSR   HEXTA     ; CONVERT TO HEX AND PRINT
        LDA   TEMP      ; GET OTHER HALF
        JSR   HEXTA     ; CONVERT TO HEX AND PRINT
        LDA   TEMP      ; RESTORE BYTE IN A AND RETURN
        RTS   
HEXTA   AND   #$0F      ; MASK HI 4 BITS
        CMP   #$0A
        CLC       
        BMI   HEXTA1
        ADC   #$07      ; ALPHA HEX
HEXTA1  ADC   #$30      ; DEC HEX
        JMP   OUTCH     ; PRINT CHAR
;       ** GET 1 CHAR FROM TTY, CHAR IN A
GETCH   STX   TMPX      ; SAVE X REG     1E5A
        LDX   #$08      ; SET UP 8-BIT COUNT
        LDA   #$01
GET1    BIT   SAD
        BNE   GET6 
        BMI   GET1      ; WAIT FOR START BIT
        JSR   DELAY     ; DELAY 1 BIT
GET5    JSR   DEHALF    ; DELAY 1/2 BIT TIME
GET2    LDA   SAD       ; GET 8 BITS
        AND   #$80      ; MASK OFF LOW ORDER BITS
        LSR   CHAR      ; SHIFT RIGHT CHAR
        ORA   CHAR
        STA   CHAR
        JSR   DELAY     ; DELAY 1 BIT TIME
        DEX  
        BNE   GET2      ; GET NEXT CHAR
        JSR   DEHALF    ; EXIT THIS ROUTINE
        LDX   TMPX
        LDA   CHAR
        ROL   A         ; SHIFT OFF PARITY
        LSR   A
GET6    RTS   
;                                     ** INITIALIZATION FOR SIGMA **
INITS   LDX   #$01      ; SET KB MODE TO ADDR           1E88
        STX   MODE
INIT1   LDX   #$00      
        STX   PADD      ; FOR SIGMA USE SADD
        LDX   #$3F
        STX   PBDD      ; FOR SIGMA USE SBDD
        LDX   #$07      ; ENABLE DATA IN
        STX   SBD       ; OUTPUT
        CLD    
        SEI    
        RTS
;                                     ** PRINT ONE CHAR IN A **
OUTSP   LDA   #$20      ; PRINT SPACE                   1E9E
OUTCH   STA   CHAR
        STX   TMPX
        JSR   DELAY     ; DELAY 10/11 BIT CODE SYNC
        LDA   SBD       ; START BIT
        AND   #$FE
        STA   SBD
        JSR   DELAY
        LDX   #$08 
OUT1    LDA   SBD       ; DATA BIT
        AND   #$FE 
        LSR   CHAR
        ADC   #$00
        STA   SBD  
        JSR   DELAY
        DEX  
        BNE   OUT1
        LDA   SBD       ; STOP BIT
        ORA   #$01
        STA   SBD
        JSR   DELAY     ; STOP BIT
        LDX   TMPX      ; RESTORE INDEX
        RTS
;                                     ** DELAY 1 BIT TIME **
DELAY   LDA   CNTH30    ;                               1ED4
        STA   TIMH
        LDA   CNTL30
DE2     SEC   
DE4     SBC   #$01 
        BCS   DE3  
        DEC   TIMH
DE3     LDY   TIMH
        BPL   DE2
        RTS
;                                     ** DELAY 1/2 BIT TIME **
DEHALF  LDA   CNTH30    ;                               1EEB  
        STA   TIMH
        LDA   CNTL30
        LSR   A
        LSR   TIMH
        BCC   DE2
        ORA   #$80
        BCS   DE4
;                                     ** SUB TO DETERMINE IF KEY IS DEPRESSED OR 
;                                        CONDITION OF SSW KEY NOT DEPRESSED OR
;                                        TTY MODE  A=0
;                                        KEY DEPRESSED OR KB MODE  A NOT ZERO
AK      LDY   #$03      ; 3 ROWS
        LDX   #$01      ; DIGIT 0
ONEKEY  LDA   #$FF
AK1     STX   SBD       ; OUTPUT DIGIT
        INX             ; GET NEXT DIGIT
        INX 
        AND   SAD       ; INPUT SEGMENTS
        DEY 
        BNE   AK1
        LDY   #$07
        STY   SBD
        ORA   #$80
        EOR   #$FF
        RTS 
;                                     ** OUTPUT TO 7-SEGMENT DISPLAY **
SCAND   LDY   #$00      ; GET DATA                      1F19 
        LDA   (POINTL),Y ; SPECIFIED BY POINT
        STA   INH       ; SET UP DISPLAY BUFFER
        LDA   #$7F      ; CHANGE SEG
        STA   PADD      ; TO OUTPUT
        LDX   #$09      ; INIT DIGIT NUMBER
        LDY   #$03      ; OUTPUT 3 BYTES
SCAND1  LDA   INL,Y     ; GET BYTE
        LSR   A         ; GET MSD
        LSR   A
        LSR   A
        LSR   A
        JSR   CONVD     ; OUTPUT CHAR
        LDA   INL,Y     ; GET BYTE AGAIN
        AND   #$0F      ; GET LSD
        JSR   CONVD     ; OUTPUT CHAR
        DEY             ; SET UP FOR NEXT BYTE
        BNE   SCAND1
        STX   SBD       ; ALL DIGITS OFF
        LDA   #$00      ; CHANGE SEGMENT
        STA   PADD      ; TO INPUTS
        JMP   AK        ; GET ANY KEY
;                                     ** CONVERT AND DISPLAY HEX (USED BY SCAND ONLY)**
CONVD   STY   TEMP
        TAY             ; SAVE Y
        LDA   TABLE,Y   ; USE CHAR AS INDEX
        LDY   #$00      ; LOOKUP CONVERSION
        STY   SAD       ; TURN OFF SEGMENTS
        STX   SBD       ; OUTPUT DIGIT ENABLE
        STA   SAD       ; OUTPUT SEGMENTS
        LDY   #$7F      ; DELAY 500 CYCLES
CONVD1  DEY   
        BNE   CONVD1
        INX             ; GET NEXT DIGIT NUMBER
        INX             ; ADD 2
        LDY   TEMP      ; RESTORE Y
        RTS
;       ** INCREMENT POINT **
INCPT   INC   POINTL
        BNE   INCPT2
        INC   POINTH
INCPT2  RTS   
;                                     ** GET KEY FROM KEYPAD A=KEYVALUE **
GETKEY  LDX   #$21      ; START AT DIGIT 0              1F6A 
GETKE5  LDY   #$01      ; GET 1 ROW
        JSR   ONEKEY
        BNE   KEYIN     ; A=0 NO KEY
        CPX   #$27      ; TEST FOR DIGIT 2
        BNE   GETKE5
        LDA   #$15      ; 15=NOKEY
        RTS
KEYIN   LDY   #$FF      
KEYIN1  ASL   A         ; SHIFT LEFT
        BCS   KEYIN2    ; UNTIL Y=KEY NO
        INY   
        BPL   KEYIN1
KEYIN2  TXA  
        AND   #$0F      ; MASK MSD
        LSR   A         ; DIVIDE BY 2
        TAX   
        TYA   
        BPL   KEYIN4
KEYIN3  CLC   
        ADC   #$07      ; MULT (X-1 TIMES A
KEYIN4  DEX   
        BNE   KEYIN3
        RTS
;                                     ** COMPUTE CHECKSUM **
CHK     CLC   
        ADC   CHKSUM
        STA   CHKSUM
        LDA   CHKHI
        ADC   #$00
        STA   CHKHI
        RTS
;                                     ** GET 2 HEX CHARS AND PACK INTO INL AND INH **
GETBYT  JSR   GETCH
        JSR   PACK
        JSR   GETCH
        JSR   PACK
        LDA   INL
        RTS
;                                     ** SHIFT CHAR IN A INTO INL AND INH **
PACK    CMP   #$30      ; CHECK FOR HEX  1FAC
        BMI   UPDAT2
        CMP   #$47      ; NOT HEX EXIT
        BPL   UPDAT2
        CMP   #$40      ; CONVERT TO HEX
        BMI   UPDATE
        CLC   
        ADC   #$09
UPDATE  ROL   A
        ROL   A
        ROL   A
        ROL   A
        LDY   #$04      ; SHIFT INTO I/O BUFFER
UPDAT1  ROL   A 
        ROL   INL
        ROL   INH
        DEY   
        BNE   UPDAT1
        LDA   #$00      ; A=0 IF HEX NUM
UPDAT2  RTS   
;
OPEN    LDA   INL       ; MOVE I/O BUFFER TO POINT
        STA   POINTL
        LDA   INH       ; TRANSFER INH- POINTH
        STA   POINTH
        RTS
;
;       ** TABLES **
TOP     .BYTE $00,$00,$00,$00,$00,$00,$0A,$0D ;       1FD5
        .BYTE  'M','I','K',$20,$13         ; KIM
        .BYTE  'R','R','E',$20,$13         ; ERR
TABLE   .BYTE $BF,$86,$DB,$CF,$E6,$ED,$FD,$87 ;0-7           1FE7
        .BYTE $FF,$EF,$F7,$FC,$B9,$DE,$F9,$F1 ;8-F HEX TO 7-SEG
;

; Fill unused locations with $FF
;        .res 3, $FF

;       ** INTERRUPT VECTORS **
        .org  $1FFA
NMIENT  .WORD NMIT
RSTENT  .WORD RST
IRQENT  .WORD IRQT
        .END

