// Shows that c64-bitmap.kc line() does not have the same problem as bitmap-draw.kc // See bitmap-line-anim-1.kc // Commodore 64 PRG executable file .file [name="bitmap-line-anim-2.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) /// $D011 Control Register #1 Bit#5: BMM Turn Bitmap Mode on/off .const VICII_BMM = $20 /// $D011 Control Register #1 Bit#4: DEN Switch VIC-II output on/off .const VICII_DEN = $10 /// $D011 Control Register #1 Bit#3: RSEL Switch betweem 25 or 24 visible rows /// RSEL| Display window height | First line | Last line /// ----+--------------------------+-------------+---------- /// 0 | 24 text lines/192 pixels | 55 ($37) | 246 ($f6) /// 1 | 25 text lines/200 pixels | 51 ($33) | 250 ($fa) .const VICII_RSEL = 8 .const WHITE = 1 .const PURPLE = 4 /// $D020 Border Color .label BORDER_COLOR = $d020 /// $D021 Background Color 0 .label BG_COLOR = $d021 /// $D011 Control Register #1 /// @see #VICII_CONTROL1 .label D011 = $d011 /// $D018 VIC-II base addresses /// - Bit#0: not used /// - Bit#1-#3: CB Address Bits 11-13 of the Character Set (*2048) /// - Bit#4-#7: VM Address Bits 10-13 of the Screen RAM (*1024) /// Initial Value: %00010100 .label VICII_MEMORY = $d018 .label SCREEN = $400 .label BITMAP = $2000 .label next = $14 .segment Code main: { // *BORDER_COLOR = 0 lda #0 sta BORDER_COLOR // *BG_COLOR = 0 sta BG_COLOR // *D011 = VICII_BMM|VICII_DEN|VICII_RSEL|3 lda #VICII_BMM|VICII_DEN|VICII_RSEL|3 sta D011 // *VICII_MEMORY = (byte)((((word)SCREEN&$3fff)/$40)|(((word)BITMAP&$3fff)/$400)) lda #(SCREEN&$3fff)/$40|(BITMAP&$3fff)/$400 sta VICII_MEMORY // bitmap_init(BITMAP, SCREEN) jsr bitmap_init // bitmap_clear(PURPLE, WHITE) jsr bitmap_clear lda #<0 sta.z next sta.z next+1 __b1: // bitmap_line(0,0,next,100) jsr bitmap_line // next++; inc.z next bne !+ inc.z next+1 !: // if(next==320) lda.z next+1 cmp #>$140 bne __b1 lda.z next cmp #<$140 bne __b1 lda #<0 sta.z next sta.z next+1 jmp __b1 } // Initialize bitmap plotting tables // void bitmap_init(char *gfx, char *screen) bitmap_init: { .label __7 = $18 .label yoffs = $14 ldx #0 lda #$80 __b1: // bitmap_plot_bit[x] = bits sta bitmap_plot_bit,x // bits >>= 1 lsr // if(bits==0) cmp #0 bne __b2 lda #$80 __b2: // for(char x : 0..255) inx cpx #0 bne __b1 lda #BITMAP sta.z yoffs+1 ldx #0 __b3: // y&0x7 lda #7 sax.z __7 // BYTE0(yoffs) lda.z yoffs // y&0x7 | BYTE0(yoffs) ora.z __7 // bitmap_plot_ylo[y] = y&0x7 | BYTE0(yoffs) sta bitmap_plot_ylo,x // BYTE1(yoffs) lda.z yoffs+1 // bitmap_plot_yhi[y] = BYTE1(yoffs) sta bitmap_plot_yhi,x // if((y&0x7)==7) lda #7 cmp.z __7 bne __b4 // yoffs = yoffs + 40*8 lda.z yoffs clc adc #<$28*8 sta.z yoffs lda.z yoffs+1 adc #>$28*8 sta.z yoffs+1 __b4: // for(char y : 0..255) inx cpx #0 bne __b3 // } rts } // Clear all graphics on the bitmap // bgcol - the background color to fill the screen with // fgcol - the foreground color to fill the screen with // void bitmap_clear(char bgcol, char fgcol) bitmap_clear: { .const col = WHITE*$10+PURPLE // memset(bitmap_screen, col, 1000uw) ldx #col lda #SCREEN sta.z memset.str+1 lda #<$3e8 sta.z memset.num lda #>$3e8 sta.z memset.num+1 jsr memset // memset(bitmap_gfx, 0, 8000uw) ldx #0 lda #BITMAP sta.z memset.str+1 lda #<$1f40 sta.z memset.num lda #>$1f40 sta.z memset.num+1 jsr memset // } rts } // Draw a line on the bitmap using bresenhams algorithm // void bitmap_line(unsigned int x1, unsigned int y1, __zp($14) unsigned int x2, unsigned int y2) bitmap_line: { .const x1 = 0 .const y1 = 0 .const y2 = $64 .label dx = $12 .label dy = $e .label sx = $16 .label sy = $10 .label e1 = $c .label e = $a .label y = 8 .label x = 6 .label x2 = $14 // unsigned int dx = abs_u16(x2-x1) lda.z x2 sta.z abs_u16.w lda.z x2+1 sta.z abs_u16.w+1 jsr abs_u16 // unsigned int dx = abs_u16(x2-x1) lda.z abs_u16.return sta.z dx lda.z abs_u16.return+1 sta.z dx+1 // unsigned int dy = abs_u16(y2-y1) lda #y2 sta.z abs_u16.w+1 jsr abs_u16 // unsigned int dy = abs_u16(y2-y1) // if(dx==0 && dy==0) lda.z dx ora.z dx+1 bne __b1 lda.z dy ora.z dy+1 bne !__b4+ jmp __b4 !__b4: __b1: // unsigned int sx = sgn_u16(x2-x1) lda.z x2 sta.z sgn_u16.w lda.z x2+1 sta.z sgn_u16.w+1 jsr sgn_u16 // unsigned int sx = sgn_u16(x2-x1) lda.z sgn_u16.return sta.z sx lda.z sgn_u16.return+1 sta.z sx+1 // unsigned int sy = sgn_u16(y2-y1) lda #y2 sta.z sgn_u16.w+1 jsr sgn_u16 // unsigned int sy = sgn_u16(y2-y1) // if(dx > dy) lda.z dy+1 cmp.z dx+1 bcc __b2 bne !+ lda.z dy cmp.z dx bcc __b2 !: // unsigned int e = dx/2 // Y is the driver lda.z dx+1 lsr sta.z e+1 lda.z dx ror sta.z e lda #y1 sta.z y+1 lda #x1 sta.z x+1 __b6: // bitmap_plot(x,(char)y) ldx.z y jsr bitmap_plot // y += sy clc lda.z y adc.z sy sta.z y lda.z y+1 adc.z sy+1 sta.z y+1 // e += dx clc lda.z e adc.z dx sta.z e lda.z e+1 adc.z dx+1 sta.z e+1 // if(dyy2 bne __b6 lda.z y cmp #y1 sta.z y+1 lda #x1 sta.z x+1 __b9: // bitmap_plot(x,(char)y) ldx.z y jsr bitmap_plot // x += sx clc lda.z x adc.z sx sta.z x lda.z x+1 adc.z sx+1 sta.z x+1 // e += dy clc lda.z e1 adc.z dy sta.z e1 lda.z e1+1 adc.z dy+1 sta.z e1+1 // if(dx < e) cmp.z dx+1 bne !+ lda.z e1 cmp.z dx beq __b10 !: bcc __b10 // y += sy clc lda.z y adc.z sy sta.z y lda.z y+1 adc.z sy+1 sta.z y+1 // e -= dx lda.z e1 sec sbc.z dx sta.z e1 lda.z e1+1 sbc.z dx+1 sta.z e1+1 __b10: // while (x != x2) lda.z x+1 cmp.z x2+1 bne __b9 lda.z x cmp.z x2 bne __b9 jmp __b3 __b4: // bitmap_plot(x,(char)y) lda #x1 sta.z bitmap_plot.x+1 ldx #0 jsr bitmap_plot rts } // Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str. // void * memset(__zp(6) void *str, __register(X) char c, __zp($a) unsigned int num) memset: { .label end = $a .label dst = 6 .label num = $a .label str = 6 // if(num>0) lda.z num bne !+ lda.z num+1 beq __breturn !: // char* end = (char*)str + num clc lda.z end adc.z str sta.z end lda.z end+1 adc.z str+1 sta.z end+1 __b2: // for(char* dst = str; dst!=end; dst++) lda.z dst+1 cmp.z end+1 bne __b3 lda.z dst cmp.z end bne __b3 __breturn: // } rts __b3: // *dst = c txa ldy #0 sta (dst),y // for(char* dst = str; dst!=end; dst++) inc.z dst bne !+ inc.z dst+1 !: jmp __b2 } // Get the absolute value of a 16-bit unsigned number treated as a signed number. // __zp($e) unsigned int abs_u16(__zp($e) unsigned int w) abs_u16: { .label w = $e .label return = $e // BYTE1(w) lda.z w+1 // BYTE1(w)&0x80 and #$80 // if(BYTE1(w)&0x80) cmp #0 bne __b1 rts __b1: // return -w; sec lda #0 sbc.z return sta.z return lda #0 sbc.z return+1 sta.z return+1 // } rts } // Get the sign of a 16-bit unsigned number treated as a signed number. // Returns unsigned -1 if the number is // __zp($10) unsigned int sgn_u16(__zp(2) unsigned int w) sgn_u16: { .label w = 2 .label return = $10 // BYTE1(w) lda.z w+1 // BYTE1(w)&0x80 and #$80 // if(BYTE1(w)&0x80) cmp #0 bne __b1 lda #<1 sta.z return lda #>1 sta.z return+1 rts __b1: lda #<-1 sta.z return sta.z return+1 // } rts } // Plot a single dot in the bitmap // void bitmap_plot(__zp(6) unsigned int x, __register(X) char y) bitmap_plot: { .label __1 = 4 .label plotter = 2 .label x = 6 // MAKEWORD( bitmap_plot_yhi[y], bitmap_plot_ylo[y] ) lda bitmap_plot_yhi,x sta.z plotter+1 lda bitmap_plot_ylo,x sta.z plotter // x & 0xfff8 lda.z x and #<$fff8 sta.z __1 lda.z x+1 and #>$fff8 sta.z __1+1 // plotter += ( x & 0xfff8 ) clc lda.z plotter adc.z __1 sta.z plotter lda.z plotter+1 adc.z __1+1 sta.z plotter+1 // BYTE0(x) ldx.z x // *plotter |= bitmap_plot_bit[BYTE0(x)] lda bitmap_plot_bit,x ldy #0 ora (plotter),y sta (plotter),y // } rts } .segment Data // Tables for the plotter - initialized by calling bitmap_init(); bitmap_plot_ylo: .fill $100, 0 bitmap_plot_yhi: .fill $100, 0 bitmap_plot_bit: .fill $100, 0