; ;################################# ;# VIC-20 BITMAP EXAMPLE # ;# AS65 source # ;# public domain # ;# by B.W. van Schooten # ;################################# ;This example contains routines for setting up a bitmapped display and ;drawing XOR'ed sprites on it. the sprite routines are optimized for use ;with multicolour mode. This program resides in ROM area. ;How it works ;------------ ;The basic idea is the following: when you enable 16-pixel-high characters, ;you can fill up the whole screen with characters without using any character ;twice. This way you can control each screen pixel individually by changing the ;definition of the corresponding character. ;A often-used mode is 22x11 (this gives you a 22*8=176 x 11*16=176 bitmap). ;The easiest way to map the characters to the screen is as follows: ;Chr0 Chr11 Chr22 .... Chr231 ;Chr1 Chr12 Chr23 .... Chr232 ;Chr2 Chr13 Chr24 .... Chr233 ;..... ..... ..... .... ...... ;Chr10 Chr21 Chr32 .... Chr241 ;This way, you can change any (non-multicolour) pixel using the following ;calculation: ; ADDRESS = Ypos + (Xpos>>3) ; VALUE = 128 >> (Xpos&7) ;Now OR the VALUE with the value already found in ADDRESS to enable the pixel. ;For multicolour mode (88x176, 4-colour packed pixel), the calculation is: ; ADDRESS = Ypos + (Xpos>>2) ; ANDMASK = 192 >> ( (Xpos&3) << 1) ; ORMASK = (Colour<<6) >> ( (Xpos&3) << 1) ;First AND the value at ADDRESS with the ANDMASK, then OR with the ORMASK. ;FILLCHRSCR arranges the characters as explained above. The whole colour ;screen is then set to 12 (multicolour mode) by FILLCOLSCR. CLEARBM clears the ;bitmap, DRAWSPR draws sprites on it. ;The memory layout used by this program is: ;$0000 - $00FF free/temporary variables ;$0100 - $01FF sprite array/stack area ;$0200 - $02F1 CHARACTER MEMORY ;$02F2 - $03FF free ;$1000 - $1F1F BITMAP ;$1F20 - $1FFF free ;-------------------------------- VARIABLES --------------------------------- ;Temp variables used by demonstration tmpcount1 equ $f4 tmpcount2 equ $f5 ;tmpval equ $f6 arradr_w equ $f7 arradr_l equ $f7 arradr_h equ $f8 ;The array of sprites sprites equ 36 xpos_arr equ $100 ypos_arr equ xpos_arr+sprites spritenr_arr equ ypos_arr+sprites ;Temp variables used by bitmapping routines bm_tmpval equ $f9 bm_jmpadr_w equ $fa bm_jmpadr_l equ $fa bm_jmpadr_h equ $fb bm_scradr1_w equ $fc bm_scradr1_l equ $fc bm_scradr1_h equ $fd bm_scradr2_w equ $fe bm_scradr2_l equ $fe bm_scradr2_h equ $ff ;------------------------------ 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,$19,$96,$17, 0 ;22 x 11, 16-pixel high characters db $8c ;screen=$0200 chars=$1000 db 0,0,0,0 ;don't care db 0,0,0,0, $80, $0a entry: cld ldx #15 setvicregs: lda vic_tbl,x sta $9000,x dex bpl setvicregs ;----------------- SETUP THE SCREEN FOR BITMAPPED GRAPHICS ------------------ jsr fillchrscr lda #12 jsr fillcolscr lda #0 jsr clearbm ;---------------------- RUN A BITMAPPED GRAPHICS DEMO ------------------------ lda #0 ldx #sprites-1 clrpos: sta xpos_arr,x sta ypos_arr,x sta spritenr_arr,x dex bpl clrpos mainloop: lda #sprites-1 sta tmpcount1 drawloop: ldy tmpcount1 lda spritenr_arr,y pha lda ypos_arr,y clc adc #12 pha lda xpos_arr,y clc adc #6 tax pla tay pla lsr a jsr drawspr ;clear old sprite by XORing over old image ldy tmpcount1 lda spritenr_arr,y clc adc #1 and #7 ;animate sta spritenr_arr,y pha lda xpos_arr,y clc adc xspeed_tbl,y and #63 sta xpos_arr,y ;move horizontally clc adc #6 tax lda ypos_arr,y clc adc yspeed_tbl,y and #127 sta ypos_arr,y ;move vertically clc adc #12 tay pla lsr a jsr drawspr ;draw sprite at new position dec tmpcount1 bpl drawloop jmp mainloop xspeed_tbl: db 1,1,1,1,1,1 db -1,-1,-1,-1,-1,-1 db 2,2,2,2,2,2 db -2,-2,-2,-2,-2,-2 db 3,3,3,3,3,3 db -3,-3,-3,-3,-3,-3 yspeed_tbl: db 1,-1,2,-2,3,-3 db 1,-1,2,-2,3,-3 db 1,-1,2,-2,3,-3 db 1,-1,2,-2,3,-3 db 1,-1,2,-2,3,-3 db 1,-1,2,-2,3,-3 ;-------------------------- SCREEN INITIALIZATION ---------------------------- ;u:P A X Y bm_scradr1_w fillchrscr: lda #2 sta bm_scradr1_h lda #22*10 sta bm_scradr1_l ldx #10 fillchrscr_line: ldy #21 fillchrscr_char: txa clc adc linevalues_tbl,y sta (bm_scradr1_w),y dey bpl fillchrscr_char lda bm_scradr1_l sec sbc #22 sta bm_scradr1_l bcs fillchrscr_noc dec bm_scradr1_h fillchrscr_noc: dex bpl fillchrscr_line rts linevalues_tbl: db 0,11,22,33, 44,55,66,77, 88,99,110,121 db 132,143,154,165, 176,187,198,209, 220,231 ;I:A=fillpattern ;u:P A X fillcolscr: ldx #0 fillcolscr_loop: sta $9600,x dex bne fillcolscr_loop rts ;------------------------- HI-RES DRAWING ROUTINES --------------------------- ;I:A=fillpattern ;u:P X Y bm_scradr1_w clearbm: ldy #$10 sty bm_scradr1_h ldy #0 sty bm_scradr1_l ldx #15 ldy #0 clearbm_page: clearbm_loop: sta (bm_scradr1_w),y dey bne clearbm_loop inc bm_scradr1_h dex bpl clearbm_page rts ;A=sprite# X=Xpos(0..87) Y=Ypos(0..175) ;u:P A X Y bm_scradr1_w bm_scradr2_w bm_tmpval bm_jmpadr drawspr: pha txa pha lsr a lsr a tax lda xpostoscrl_tbl,x sta bm_scradr1_l lda xpostoscrh_tbl,x sta bm_scradr1_h ;scradr1->top byte of left column tya clc adc bm_scradr1_l sta bm_scradr1_l bcc drawspr_noc1 inc bm_scradr1_h ;bm_scradr1->byte# in left column drawspr_noc1: lda bm_scradr1_l clc adc #11*16 sta bm_scradr2_l lda bm_scradr1_h adc #0 sta bm_scradr2_h ;bm_scradr2->byte# in right column pla and #3 tax lda shifttoadrl_tbl,x sta bm_jmpadr_l lda shifttoadrh_tbl,x sta bm_jmpadr_h ;tmpadr=jmp address pla tax lda sprindex_tbl,x clc adc #9 tax ;X=end of offset in sprite data ldy #9 ;Y=loop count drawspr_loop: lda sprite_tbl2,x sta bm_tmpval ;bm_tmpval contains bits shifted out lda sprite_tbl1,x jmp (bm_jmpadr_w) ;do shifting drawspr_shift4: lsr a ror bm_tmpval lsr a ror bm_tmpval drawspr_shift2: lsr a ror bm_tmpval lsr a ror bm_tmpval drawspr_shift0: eor (bm_scradr1_w),y sta (bm_scradr1_w),y lda bm_tmpval eor (bm_scradr2_w),y sta (bm_scradr2_w),y dex dey bpl drawspr_loop rts drawspr_shift6: asl bm_tmpval rol a rol bm_tmpval rol a rol bm_tmpval eor (bm_scradr2_w),y sta (bm_scradr2_w),y lda bm_tmpval eor (bm_scradr1_w),y sta (bm_scradr1_w),y dex dey bpl drawspr_loop rts shifttoadrl_tbl: db lo (drawspr_shift0) db lo (drawspr_shift2) db lo (drawspr_shift4) db lo (drawspr_shift6) shifttoadrh_tbl: db hi (drawspr_shift0) db hi (drawspr_shift2) db hi (drawspr_shift4) db hi (drawspr_shift6) xpostoscrl_tbl: db lo (0*176),lo (1*176), lo (2*176), lo (3*176) db lo (4*176),lo (5*176), lo (6*176), lo (7*176) db lo (8*176),lo (9*176), lo (10*176), lo (11*176) db lo (12*176),lo (13*176), lo (14*176), lo (15*176) db lo (16*176),lo (17*176), lo (18*176), lo (19*176) db lo (20*176),lo (21*176) xpostoscrh_tbl: db 16+(hi(0*176)),16+(hi(1*176)),16+(hi(2*176)),16+(hi(3*176)) db 16+(hi(4*176)),16+(hi(5*176)),16+(hi(6*176)),16+(hi(7*176)) db 16+(hi(8*176)),16+(hi(9*176)),16+(hi(10*176)),16+(hi(11*176)) db 16+(hi(12*176)),16+(hi(13*176)),16+(hi(14*176)),16+(hi(15*176)) db 16+(hi(16*176)),16+(hi(17*176)),16+(hi(18*176)),16+(hi(19*176)) db 16+(hi(20*176)),16+(hi(21*176)) sprindex_tbl: db 0,10,20,30,40, 50,60,70,80,90 db 100,110,120,130,140, 150,160,170,180,190 db 200,210,220,230,240 ;--------------------------- SPRITE DEFINITIONS ---------------------------- ;The sprites are 5 multicolour pixels wide x 10 pixels high. ;This table contains the left four columns of sprite data. sprite_tbl1: db 4#2221 db 4#2210 db 4#3100 db 4#1000 db 4#0020 db 4#0020 db 4#0000 db 4#0001 db 4#0012 db 4#0122 db 4#0100 db 4#1000 db 4#2000 db 4#2000 db 4#2131 db 4#2131 db 4#3000 db 4#1000 db 4#0000 db 4#0001 db 4#0132 db 4#0012 db 4#0001 db 4#0000 db 4#0020 db 4#0020 db 4#1000 db 4#2100 db 4#2210 db 4#2231 db 4#3222 db 4#1322 db 4#0000 db 4#0000 db 4#0010 db 4#0010 db 4#0000 db 4#0000 db 4#1223 db 4#1222 ;This table contains the right column data. sprite_tbl2: db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#1000 db 4#3000 db 4#2000 db 4#2000 db 4#0000 db 4#0000 db 4#1000 db 4#3000 db 4#2000 db 4#2000 db 4#2000 db 4#2000 db 4#1000 db 4#0000 db 4#2000 db 4#2000 db 4#2000 db 4#1000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#1000 db 4#1000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#0000 db 4#1000 db 4#3000