Ruud Baltissen's KIM-1 Source Code
[Up to Build Your Own KIM-1]
; KIM-1 Source Code from Ruud Baltissen ; Last update: 19 October 1997 ; ; ; The sourcecode is copied from 'KIM-1 MANUAL' released by MOS Technologies ; and this means that someone probably has the copyrights of it. Until ; someone clears the mess around 'who owns what from Commodore', leave this ; remark in the sourcecode as a sign of acknowledgement and respect in case ; you intend to use it for your own purposes. ; ; ; I have checked the SRC line by line and added some comment of my own. At ; this moment it does not mean that it is without faults. I only will be ; sure about that until I have compiled the SRC and found no differences ; with the original BIN. ; ; ; The SRC can be assembled with my own programmed assembler. This assembler ; for the PC is available as freeware, including sourcecode for Turbo Pascal. ; ; ; Sourcode of the KIM-1 ; .eq PCL = $EF ; programcounter low .eq PCH = $F0 ; programcounter high .eq PREG = $F1 ; statusregister .eq SPUSER = $F2 ; stackpointer .eq ACC = $F3 .eq YREG = $F4 .eq XREG = $F5 .eq CHKHI = $F6 .eq CHKSUM = $F7 .eq INL = $F8 ; inputbuffer low .eq INH = $F9 ; inputbuffer high .eq POINTL = $FA ; addressL on display .eq POINTH = $FB ; addressH on display .eq TEMP = $FC .eq TMPX = $FD .eq CHAR = $FE .eq MODE = $FF .eq INL_A = $00F8 ; INL as absolute address ; .eq CHKL = $17E7 .eq CHKH = CHKL+1 .eq SAVX = CHKL+2 .eq VEB = CHKL+5 .eq CNTL30 = CHKL+11 .eq CNTH30 = CHKL+12 .eq TIMH = CHKL+13 .eq SAL = CHKL+14 .eq SAH = CHKL+15 .eq EAL = CHKL+16 .eq EAH = CHKL+17 .eq ID = CHKL+18 .eq NMIV = CHKL+19 ; NMI-vector .eq RSTV = CHKL+21 ; RESET-vector .eq IRQV = CHKL+23 ; IRQ-vector ; .eq SAD = $1740 .eq PADD = SAD+1 .eq SBD = SAD+2 .eq PBDD = SAD+3 .eq CLK1T = SAD+4 .eq CLK8T = SAD+5 .eq CLK64T = SAD+6 .eq CLKRDT = SAD+7 ; Read time .eq CLKKT = SAD+7 .eq CLKRDI = SAD+7 ; Read time out bit ; ; .ba $1800 ; ; Dump memory on tape DUMPT lda #$AD ; load absolute inst sta VEB jsr INTVEB ; lda #$27 ; turn off datainput PB5 sta SBD lda #$BF ; PB7 := output sta PBDD ; ldx #100 ; 100 characters 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 start address jsr OUTBTC lda SAH jsr OUTBTC ; DUMPT2 lda VEB+1 ; compare for last data byte cmp EAL lda VEB+2 sbc EAH bcc DUMPT4 ; lda #$2F ; output EndOfData-char jsr OUTCHT lda CHKL ; output checksum jsr OUTBT lda CHKH jsr OUTBT ; ldx #2 ; 2 chars DUMPT3 lda #4 ; EOT-char jsr OUTCHT dex bne DUMPT3 ; lda #0 ; display 0000 sta POINTL sta POINTH jmp START ; DUMPT4 jsr VEB ; output data byte jsr OUTBTC jsr INCVEB jmp DUMPT2 ; ; Load from tape into memory TAB .wo LOAD12 LOADT lda #$8D ; initialise volatile execution sta VEB ; block with sta abs jsr INTVEB ; lda #$4C ; code for JMP sta VEB+3 lda TAB sta VEB+4 lda TAB+1 sta VEB+5 ; ; result: jmp LOAD12 (= $190F) ; lda #7 ; reset PB5 sta SBD ; SYNC lda #$FF ; clear SAVX for SYNC-area sta SAVX ; SYNC1 jsr RDBIT ; get a bit lsr SAVX ora SAVX sta SAVX lda SAVX ; get new char cmp #$16 ; SYNC-char? bne SYNC1 ; ldx #10 ; test for 10 SYNC-char SYNC2 jsr RDCHT cmp #$16 ; SYNC-char? bne SYNC dex bne SYNC2 LOADT4 jsr RDCHT ; look for start of cmp #$2A ; start char beq LOAD11 ; yes -> cmp #$16 ; SYNC-char? bne SYNC ; no -> beq LOADT4 ; always -> ; LOAD11 jsr RDBYT ; read ID cmp ID ; requested ID? beq LOADT5 ; yes -> lda ID cmp #0 ; ignore ID? beq LOADT5 ; yes -> cmp #$FF ; ignore start address? beq LOADT6 ; yes -> bne LOADT ; next program, always -> ; LOADT5 jsr RDBYT ; get SA from tape jsr CHKT sta VEB+1 jsr RDBYT jsr CHKT sta VEB+2 jmp LOADT7 ; LOADT6 jsr RDBYT ; get SA from tape jsr CHKT ; but ignore jsr RDBYT jsr CHKT ; LOADT7 ldx #2 LOAD13 jsr RDCHT cmp #$2F ; last char? beq LOADT5 ; yes -> jsr PACKT ; convert to hex bne LOADT9 ; Y=1, non-hex char dex ; 2 chars? bne LOAD13 ; no -> next one jsr CHKT ; compute checksum jmp VEB ; LOAD12 jsr INCVEB ; increment datapointer jmp LOADT7 ; LOADT8 jsr RDBYT ; EOD compare checksum cmp CHKL bne LOADT9 jsr RDBYT cmp CHKH bne LOADT9 lda #0 beq LOAD10 ; normal exit, always -> ; LOADT9 lda #$FF ; error exit LOAD10 sta POINTL sta POINTH jmp START ; display values ; ; Move start address to VEB+1,2 INTVEB lda SAL sta VEB+1 lda SAH sta VEB+2 lda #$60 ; code for RTS sta VEB+3 lda #0 sta CHKL sta CHKH rts ; ; Compute checksum for tape load CHKT tay clc adc CHKL sta CHKL lda CHKH adc #0 sta CHKH tya rts ; ; Output one byte OUTBTC jsr CHKT OUTBT tay lsr lsr lsr lsr jsr HEXOUT ; output MSD tya jsr HEXOUT ; output LSD tya rts ; ; Convert LSD of A to ASCII HEXOUT and #$0F cmp #10 clc bmi HEX1 adc #7 HEX1 adc #$30 ; ; Output to tape 1 ASCII OUTCHT stx SAVX sty SAVX+1 ldy #8 ; startbit CHT1 jsr ONE lsr ; get data bit bcs CHT2 jsr ONE jmp CHT3 CHT2 jsr ZRO CHT3 jsr ZRO dey ; all bits? bne CHT1 ; no -> ldx SAVX ldy SAVX+1 rts ; ; Output a 1 to tape: 9 pulses of 138 us each ONE ldx #9 pha ONE1 bit CLKRDI ; wait for timeout bpl ONE1 lda #126 sta CLK1T lda #$A7 sta SBD ; PB7 := 1 ONE2 bit CLKRDI ; wait for timeout bpl ONE2 lda #126 sta CLK1T lda #$27 sta SBD ; PB7 := 0 dex ; all pulses? bne ONE1 ; no -> pla rts ; ; Output a 0 to tape: 6 pulses of 207 us each ZRO ldx #6 pha ZRO1 bit CLKRDI ; wait for timeout bpl ZRO1 lda #195 sta CLK1T lda #$A7 sta SBD ; PB7 := 1 ZRO2 bit CLKRDI ; wait for timeout bpl ZRO2 lda #195 sta CLK1T lda #$27 sta SBD ; PB7 := 0 dex ; all pulses? bne ZRO1 ; no -> pla rts ; ; Increment VEB+1,2 INCVEB inc VEB+1 bne INCVE1 inc VEB+2 INCVE1 rts ; ; Read byte from tape RDBYT jsr RDCHT jsr PACKT RDBYT2 jsr RDCHT jsr PACKT rts ; ; Pack ASCII in A as hex data PACKT cmp #$30 ; ASCII ? bmi PACKT3 ; no -> cmp #$47 bpl PACKT3 ; no -> cmp #$40 ; >'9' ? bmi PACKT1 ; no -> clc adc #9 PACKT1 rol rol rol rol ldy #4 PACKT2 rol rol SAVX dey bne PACKT2 lda SAVX ; ; At this point Y already is 0 (= valid hex char) ldy #0 ; set the zero-flag rts ; ; Y=0 at this point, done in label RDBIT4 PACKT3 iny ; Y:=1 = invalid hex char rts ; ; Get 1 char from tape in A RDCHT stx SAVX+2 ldx #8 ; read 8 bits RDCHT1 jsr RDBIT lsr SAVX+1 ora SAVX+1 sta SAVX+1 dex bne RDCHT1 ; lda SAVX+1 rol lsr ldx SAVX+2 rts ; ; Get 1 bit from tape and return it in bit 7 of A RDBIT bit SBD ; wait for end of startbit bpl RDBIT lda CLKRDT ; get start bit time ldy #$FF ; A := 256 - T1 sty CLK64T ; ldy #$14 RDBIT3 dey ; delay 100 us bne RDBIT3 RDBIT2 bit SBD bmi RDBIT2 ; wait for next start bit ; sec sbc CLKRDT ldy #$FF sty CLK64T ; ldy #7 RDBIT4 dey ; delay 50 us bne RDBIT4 ; eor #$FF ; complement sign and #$80 ; mask sign rts ; ; output 166 us pulse string for testing purposes ; No documentation found about this. I think it is used to ; calibrate the 565 PLLCALL lda #$27 sta SBD ; turn off datin PB5=1 lda #$BF sta PBDD ; PLL1 bit CLKRDI bpl PLL1 lda #154 ; wait 166 us sta CLK1T lda #$A7 ; output PB7=1 sta SBD ; PLL2 bit CLKRDI bpl PLL2 lda #154 sta CLK1T lda #$27 ; output PB7=0 sta SBD jmp PLL1 ; .ba $1BFA NMIP27 .wo PLLCALL RSTP27 .wo PLLCALL IRQP27 .wo PLLCALL ; ; ; ; KIM-entry via NMI or IRQ SAVE sta ACC pla sta PREG ; ; KIM-entry via JSR SAVEA pla sta PCL sta POINTL pla sta PCH sta POINTH ; SAVEB sty YREG stx XREG tsx stx SPUSER jsr INITS jmp START ; ; NMI and IRQ are called via RAM-vector. This enables the programmer ; to insert his own routines. ; Comment: is not initialised anywhere, so any accidental NMI or IRQ ; can lead to disaster ! NMIT jmp (NMIV) IRQT jmp (IRQV) ; ; The KIM starts here after a reset RESET ldx #$FF txs ; set stack stx SPUSER jsr INITS ; ; Determine characters per second DETCPS lda #$FF ; count startbit sta CNTH30 ; zero CNTH30 ; ; Test first keyboard or teleprinter lda #1 ; mask bit 0 DET1 bit SAD ; test for teleprinter bne START ; no -> bmi DET1 ; no startbit, wait for it -> lda #$FC DET3 clc ; this loop counts startbit time adc #1 ; A=0 ? bcc DET2 ; no -> inc CNTH30 DET2 ldy SAD ; check for end of startbit bpl DET3 ; no -> sta CNTL30 ldx #8 jsr GET5 ; get rest of char ; ; Make TTY/KB selection START jsr INIT1 lda #1 ; read jumper bit SAD ; TTY ? bne TTYKB ; no -> keyboard/display-routine jsr CRLF ; print return/linefeed ldx #$0A jsr PRTST ; print 'KIM' jmp SHOW1 ; ; CLEAR lda #0 sta INL ; clear inputbuffer sta INH ; READ jsr GETCH ; get char from TTY cmp #1 ; 1 has no meaning for TTY beq TTYKB ; 1 = KB-mode -> jsr PACK jmp SCAN ; ; Main routine for keyboard and display TTYKB jsr SCAND ; wait until NO key pressed bne START ; if pressed, wait again -> TTYKB1 lda #1 ; check KB/TTY mode bit SAD ; TTY? beq START ; yes -> jsr SCAND ; Wait for key... beq TTYKB1 ; no key -> jsr SCAND ; debounce key beq TTYKB1 ; no key -> ; GETK jsr GETKEY cmp #$15 ; >= $15 = illegal bpl START ; yes -> cmp #$14 beq PCCMD ; display Program Counter cmp #$10 beq ADDRM ; addresmode cmp #$11 beq DATAM ; datamode cmp #$12 beq STEP ; step cmp #$13 beq GOV ; execute program ; ; One of the hexidecimal buttons has been pushed DATA asl ; move LSB key number to MSB asl asl asl sta TEMP ; store for datamode ldx #4 DATA1 ldy MODE ; part of address? bne ADDR ; yes -> lda (POINTL),Y ; get data asl TEMP rol ; MSB-TEMP = MSB-key -> A sta (POINTL),Y ; store new data jmp DATA2 ADDR asl ; TEMP not needed here rol POINTL ; MSB-key -> POINTL rol POINTH ; POINTL -> POINTH DATA2 dex ; 4 times = complete nibble? bne DATA1 ; no -> beq DATAM2 ; -> always ; ; Switch to address mode ADDRM lda #1 bne DATAM1 ; -> always ; ; Switch to data mode DATAM lda #0 DATAM1 sta MODE DATAM2 jmp START ; ; Increment address on display STEP jsr INCPT jmp START ; GOV jmp GOEXEC ; ; Display PC by moving it to POINT PCCMD lda PCL sta POINTL lda PCH sta POINTH jmp START ; ; Load papertape from TTY LOAD jsr GETCH cmp #$3B ; ":", semicolon? bne LOAD ; No -> again LOADS lda #0 sta CHKSUM sta CHKHI ; jsr GETBYT ; get byte CNT tax jsr CHK ; Compute checksum ; jsr GETBYT ; get address HI sta POINTH jsr CHK ; Compute checksum ; jsr GETBYT ; get address LO sta POINTL jsr CHK ; Compute checksum ; txa ; CNT = 0 ? beq LOAD3 ; LOAD2 jsr GETBYT ; get DATA sta (POINTL),y ; store data jsr CHK jsr INCPT dex bne LOAD2 inx ; X=1 = data record ; X=0 = last record ; LOAD3 jsr GETBYT ; compare checksum cmp CHKHI bne LOADE1 jsr GETBYT cmp CHKSUM bne LOADER ; txa ; X=0 = last record bne LOAD ; LOAD7 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 error KIM bne LOAD8 ; always -> ; ; Dump to TTY from open cell address to LIMHL, LIMHH DUMP lda #0 sta INL sta INH ; clear record count DUMP0 lda #0 sta CHKHI ; clear checksum sta CHKSUM ; DUMP1 jsr CRLF lda #$3B ; ":" jsr OUTCH ; ; Check if POINTL/H >= EAL/H lda POINTL cmp EAL ; lda POINTH sbc EAH bcc DUMP4 ; no -> ; lda #0 ; print last record jsr PRTBYT ; 0 bytes jsr OPEN jsr PRTPNT ; lda CHKHI ; print checksum jsr PRTPNT ; for last record lda CHKSUM jsr PRTBYT jsr CHK jmp CLEAR ; DUMP4 lda #$18 ; print 24 bytes tax ; save as index jsr PRTBYT jsr CHK jsr PRTPNT ; DUMP2 ldy #0 lda (POINTL),y jsr PRTBYT ; print data jsr CHK jsr INCPT dex ; Printed everything? bne DUMP2 ; No -> ; lda CHKHI jsr PRTBYT ; print checksum lda CHKSUM jsr PRTBYT inc INL ; increment recourd counter bne DUMP3 inc INH DUMP3 jmp DUMP0 ; SPACE jsr OPEN ; open new cell SHOW jsr CRLF SHOW1 jsr PRTPNT jsr OUTSP ; print space ldy #0 lda (POINTL),y ; print data jsr PRTBYT jsr OUTSP ; print space jmp CLEAR ; RTRN jsr INCPT ; next address jmp SHOW ; Start a program at displayed address. RTI is used as a comfortable ; way to define all flags in one move. GOEXEC ldx SPUSER ; user user defined stack txs lda POINTH ; program runs from pha ; displayed address lda POINTL pha lda PREG ; user defined Flag register pha ldx XREG ldy YREG lda ACC rti ; start program ; ; Take care if TTY-input SCAN cmp #$20 ; open new cell beq SPACE cmp #$7F ; rub out, restart KIM beq STV cmp #$0D ; next cell beq RTRN cmp #$0A ; prev cell beq FEED cmp #$2E ; "." = modify cell beq MODIFY cmp #$47 ; "G" = exec program beq GOEXEC cmp #$51 ; "Q" = dump from open cell beq DUMPV ; to HI limit cmp #$4C ; "L" = load tape beq LOADV jmp READ ; ignore illegal CHAR ; STV jmp START DUMPV jmp DUMP LOADV jmp LOAD ; FEED sec lda POINTL ; decrement POINTL/H sbc #1 sta POINTL bcs FEED1 dec POINTH FEED1 jmp SHOW ; MODIFY ldy #0 ; get contents of input buffer lda INL ; INL and store in location sta (POINTL),y ; specified by POINT jmp RTRN ; ; Subroutine to print POINT = address PRTPNT lda POINTH jsr PRTBYT jsr CHK lda POINTL jsr PRTBYT jsr CHK rts ; ; Print ASCII-string from TOP+X to TOP CRLF ldx #7 ; output <RETURN> and <LF> PRTST lda TOP,x jsr OUTCH dex ; everything? bpl PRTST ; no -> PRT1 rts ; ; Print 1 hex byte as 2 ASCII chars PRTBYT sta TEMP ; save A lsr ; shift A 4 times lsr lsr lsr jsr HEXTA ; convert bit 4..7 to HEX and print lda TEMP jsr HEXTA ; convert bit 0..7 to HEX and print lda TEMP ; restore A rts ; HEXTA and #$0F ; mask bit 0..4 cmp #$0A ; >10 ? clc bmi HEXTA1 ; no -> adc #7 ; A..F HEXTA1 adc #$30 ; convert to ASCII-char... jmp OUTCH ; ...and print it ; ; Get char from TTY in A GETCH stx TMPX ldx #8 ; count 8 bits lda #1 GET1 bit SAD ; check if TTY-mode bne GET6 ; no -> ; PA7 is input TTY bmi GET1 ; wait for startbit jsr DELAY ; delay 1 bit ; ; By delaying another half bit time, you read the bit in the middle ; of every bit. GET5 jsr DEHALF ; delay 1/2 bit time GET2 lda SAD and #$80 ; mask bit 7 lsr CHAR ; shift last result ora CHAR ; OR it with new bit sta CHAR ; and store it again jsr DELAY dex bne GET2 ; next bit jsr DEHALF ; why ???? ; ldx TMPX lda CHAR rol ; shift off stopbit lsr GET6 rts ; ; Initialization 6530 $1E88 INITS ldx #1 ; set display to address mode stx MODE ; INIT1 ldX #0 stx PADD ; PA0..PA7 = input ldX #$3F stx PBDD ; PB0..PB5 = output ; PB6, PB7 = input ldx #7 ; enable 74145 output 3 to stx SBD ; check KB/TTY-mode cld sei rts ; ; Output char in A to TTY $1E9E OUTSP lda #" " ; print space OUTCH sta CHAR stx TMPX jsr DELAY lda SBD and #$FE ; send startbit sta SBD ; PB0 = 0 -> TTY := (H) jsr DELAY ; ldx #8 ; send character OUT1 lda SBD and #$FE ; clear bit 0 lsr CHAR ; shift byte adc #0 ; add Carry = former bit 0 sta SBD ; output bit jsr DELAY dex ; all bits? bne OUT1 ; no -> lda SBD ora #1 sta SBD ; stop bit jsr DELAY ldx TMPX rts ; ; Delay 1 bit time as determined by DETCPS DELAY lda CNTH30 sta TIMH lda CNTL30 DE2 sec DE4 sbc #1 bcs DE3 ; A<>$FF -> dec TIMH DE3 ldy TIMH ; TIMH > 0 ? bpl DE2 ; yes -> rts ; ; Delay half a bit time DEHALF lda CNTH30 sta TIMH lda CNTL30 lsr lsr TIMH bcc DE2 ora #$80 bcs DE4 ; always -> ; Why not: ; lsr TIMH ; ror ; jmp DE2 ; ???? ; ; ; Determine if key is depressed: NO -> A=0, YES -> A>0 AK ldy #3 ; 3 rows ldX #1 ; select 74145 output 0 ONEKEY lda #$FF ; initial value ; AKA stx SBD ; enable output = select row inx inx ; prepare for next row and SAD ; A := A && (PA0..PA7) dey ; all rows? bne AKA ; no -> ldy #7 sty SBD ; select 74145 output 3 (not used) ; ora #$80 ; mask bit 7 of A eor #$FF ; if A still is $FF -> A := 0 rts ; ; Output to 7-segment-display SCAND ldy #0 ; POINTL/POINTH = address on display lda (POINTL),Y ; get data from this address sta INH ; store in INH = SCANDS lda #$7F ; PA0..PA6 := output sta PADD ldX #9 ; Start with display at output 4 ldy #3 ; 3 bytes to be shown ; SCAND1 lda INL_A,y ; get byte lsr ; get MSD by shifting A lsr lsr lsr jsr CONVD lda INL_A,y ; get byte again and #$0F ; get LSD jsr CONVD dey ; all ? bne SCAND1 ; no -> sty SBD ; all digits off lda #0 sta PADD ; PA0..PA7 := input jmp AK ; ; Convert digit into 7-segment-value CONVD sty TEMP tay lda TABLE,Y ldy #0 sty SAD ; turn off segments stx SBD ; select 7-s-display sta SAD ; output code on display ldy #$7F ; delay ~500 cycles CONVD1 dey bne CONVD1 inx ; next display inx ldy TEMP rts ; ; Increment POINT = address on display INCPT inc POINTL bne INCPT2 inc POINTH INCPT2 rts ; ; Get key from keyboard in A GETKEY ldx #$21 ; row 0 / disable input TTY GETKE5 ldy #1 ; only one row in the time jsr ONEKEY ; key? bne KEYIN ; yes -> cpx #$27 ; last row? bne GETKE5 ; no, next one -> lda #$15 ; 15 = no key rts ; KEYIN ldy #$FF ; Y := key number KEYIN1 asl ; shift A until bcs KEYIN2 ; bit = 1 -> ; ; Comment: bit 7 is always 0 so Carry is always 0 the first time ; and allowing Y to become 0 (key $FF does not exist) iny bpl KEYIN1 ; always -> KEYIN2 txa and #$0F ; strip bit4..7 lsr ; A := row+1 tax ; X := actual row+1 tya bpl KEYIN4 ; always, because Y<7 -> ; ; Add 7 to A for every row above 0 to get actual key number KEYIN3 clc adc #7 ; add (X-1) times 7 to A KEYIN4 dex ; countdown to 0 bne KEYIN3 rts ; A is always < 21 eg. < $15 ; ; Compute checksum CHK clc adc CHKSUM sta CHKSUM lda CHKHI adc #0 sta CHKHI rts ; ; Get 2 hex-chars and pack into INL and INH ; Non hex char will be loaded as nearsest hex equivalent GETBYT jsr GETCH jsr PACK lsr GETCH jsr PACK lda INL rts ; ; Shift char in A into INL and INH PACK cmp #$30 ; is hex? bmi UPDAT2 ; < = no -> cmp #$47 bpl UPDAT2 ; > = no -> HEXNUM cmp #$40 ; A..F ? bmi UPDATE ; no -> HEXALP clc adc #9 UPDATE rol ; shift to bit 4..7 rol rol rol ldy #4 ; shift into INL/INH UPDAT1 rol rol INL rol INH dey ; 4 times? bne UPDAT1 ; no -> lda #0 ; if hex number -> A := 0 UPDAT2 rts ; OPEN lda INL ; move I/O-buffer to POINT sta POINTL lda INH sta POINTH rts ; ; Tabels TOP .by 0, 0, 0, 0, 0, 0, 10, 13 .tx "MIK" .by " ", $13 .tx "RRE " .by $13 ; Hex -> 7-segment 0 1 2 3 4 5 6 7 TABLE .by $BF, $86, $DB, $CF, $E6, $ED, $FD, $87 ; 8 9 A B C D E F .by $FF, $EF, $F7, $FC, $B9, $DE, $F9, $F1 ; ; Comment: if everything is compiled right, next vectors should ; start at $FFFA NMIENT .wo NMIT RSTENT .wo RESET IRQENT .wo IRQT .en