; ;################################# ;# ROM Template # ;# public domain # ;# by B.W. van Schooten # ;################################# ;initializes video: ; Standard screen, upper case ROM font. ; Screen start=$1e00 Colour memory start=$9600 ;Initializes IRQ interrupts: ; Timer 1 underflow(120Hz): irqtimer is incremented. ; Timer 2 underflow(60Hz): keyboard is scanned ;------------------------------- VARIABLES ---------------------------------- keymap_arr equ $308 ;8 bytes, updated by irq on T2 ;The location of keys in keymap_arr. ;bit is 0 <=> its corresponding key is being pressed. ; |bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 ;______|______ _______ _______ _______ _______ _______ _______ _______ ;byte0 |DEL POUND + 9 7 5 3 1 ;byte1 |RETURN * P I Y R W ARR.LF ;byte2 |CRSRRT ; L J G D A CTRL ;byte3 |CRSRDN / , N V X LFSHIFT STOP ;byte4 |F1 RTSHIFT . M B C Z SPACE ;byte5 |F3 = : K H F S CBM ;byte6 |F5 ARR.UP @ O U T E Q ;byte7 |F7 HOME - 0 8 6 4 2 irqtimer_l equ $310 ;32-bits timer, incremented every T1-underflow intvector_arr equ $314 ;3 word vectors:IRQ, BRK, NMI ;--------------------------- NUMERIC CONSTANTS ------------------------------ timer2speed_c equ $4289 ;60 times/second timer1speed_c equ $2144 ;120 times/second ;----------------------------------------------------------------------------- ;------------------------------ MAIN PROGRAM --------------------------------- ;----------------------------------------------------------------------------- ;------------------------------ BOOT HEADER ---------------------------------- org $9ffe db 0,160 ;StartAdr=$a000 db lo entry, hi entry ;entry point db lo entry, hi entry ;padding? db $41,$30,$c3,$c2,$cd ;A0CBM boot code ;----------------------------- INIT HARDWARE -------------------------------- vic_tbl: db $05 ;0..6=Hcentering 7=interlace db $19 ;0..6=Vcentering db $96 ;0..6=#columns 7=low bit of screen start&colour start db $2e ;0=16 high chars enabled 1..6=#rows 7=low bit TV beam db 0 ;TV beam (read only) db $f0 ;0..3=char definitions start 4..7=screen start db 0,0 ;light pen(read only) db 0,0 ;paddles (read only) db 0,0,0,0 ;voices db 0 ;0..3=volume 4..7=aux colour db $08 ;0=inverse mode 1..3=border colour 4..7=backgr.col. via2_tbl: db 0,0 ;port B; port A db $ff,0 ;DDR B; DDR A db lo timer1speed_c,hi timer1speed_c db lo timer1speed_c,hi timer1speed_c ;Timer 1 count lo hi ;latch lo hi db lo timer2speed_c,hi timer2speed_c ;Timer 2 count lo hi db 0 ;shift register db $40 ;aux ctrl: T1=continous; T2=one-shot. Disable all else db $de ;CA and CB signal control (not used). Default value. db $7f ;int flags: clear all db $7f ;int enable:disable: all db 0 ;shadow of port A vectorval_tbl: db lo doirq,hi doirq db lo dobrk,hi dobrk db lo donmi,hi donmi ;The real program starts here entry: inithardware: lda #$7f sta $911e ;Disable NMI sei cld ldx #5 setintvec: lda vectorval_tbl,x sta intvector_arr,x dex bpl setintvec ldx #15 setchipregs: lda vic_tbl,x ;initialize screen, turn off sound sta $9000,x lda via2_tbl,x ;init data direction&timers, disable INTs sta $9120,x dex bpl setchipregs startinterrupts: lda #$e0 sta $912e ;enable T1 and T2 as interrupt source jsr clrirqtimer cli ;Warning: Enabling T2 as interrupt MUST ;occur before T2 counts down, because ;T2 is one-shot and is only restarted by the ;interrupt handler. ;---------------------------------- MAIN ------------------------------------- cycletimer equ $7f demonstration: ldx #0 cls: lda #' ' ;space sta $1e00,x sta $1f00,x dex bne cls ldx #22*5-1 drawtext: lda test_txt,x and #$3f ;crude ASCII->ROM font conversion sta $1e00+44,x dex bpl drawtext lda #0 sta cycletimer main: wait: lda irqtimer_l cmp #10 ;Ignore the high bytes;only look at low byte. bcc wait ;wait for 10 timer ticks=1/12 second jsr clrirqtimer ldx #0 ldy cycletimer cyclecolours: lda cycle_tbl,y sta $9600,x sta $9700,x iny tya and #7 tay inx bne cyclecolours lda cycletimer clc adc #1 and #7 sta cycletimer ldx #7 showkeymap: lda keymap_arr,x sta $1e00,x dex bpl showkeymap jmp main ;0 1 2 3 4 5 6 7 ;BLK WHT RED CYN PUR GRN BLU YEL cycle_tbl: db 0,6,4,2, 7,1,3,5 test_txt: db ' ^^^^^^ KEYMAP DISPLAY' db ' ROM TEMPLATE(TM) ' db ' PUBLIC DOMAIN ' db ' INITS VIDEO & TIMERS ' db ' AND SCANS KEYBOARD ' ;----------------------------------------------------------------------------- ;-------------------------------- INTERRUPT ---------------------------------- ;----------------------------------------------------------------------------- ;the routine is entered with A,X,Y already pushed doirq: cld lda $912d pha and #$40 beq doirq_not1 jsr incirqtimer lda #$40 sta $912d ;Clear T1 flag doirq_not1: pla pha and #$20 beq doirq_not2 lda #$20 sta $912d ;Clear T2 flag lda #lo timer2speed_c sta $9128 lda #hi timer2speed_c sta $9129 jsr scankbd doirq_not2: pla lda #$1f sta $912d ;Clear any spurious flags jmp returnfromint ;the routine is entered with A,X,Y already pushed ;This is a dummy interrupt handler dobrk: donmi: cld inc $900f returnfromint: pla tay pla tax pla rti ;----------------------------------------------------------------------------- ;--------------------------------- IRQ TIMER --------------------------------- ;----------------------------------------------------------------------------- ;I:irqtimer_l ;u:P ;O:irqtimer_l incirqtimer: inc irqtimer_l bne incirqtimer_nocarry inc irqtimer_l+1 bne incirqtimer_nocarry inc irqtimer_l+2 bne incirqtimer_nocarry inc irqtimer_l+3 incirqtimer_nocarry: rts ;u:P ;O:irqtimer_l clrirqtimer: ldx #3 lda #0 clrirqtimer_loop: sta irqtimer_l,x dex bpl clrirqtimer_loop rts ;----------------------------------------------------------------------------- ;-------------------------------- KEYBOARD ----------------------------------- ;----------------------------------------------------------------------------- ;u: P A X ;O:keymap_arr scankbd: lda #$7f sta $9120 ;scan highest row ldx #$07 scankbd_loop: nop lda $9121 nop cmp $9121 bne scankbd_loop ;wait until output stabilizes sta keymap_arr,x sec ror $9120 ;scan next row dex bpl scankbd_loop rts