diff --git a/compiler/res/prog8lib/c64/graphics.p8 b/compiler/res/prog8lib/c64/graphics.p8 index 9d42e4bb7..698a7df69 100644 --- a/compiler/res/prog8lib/c64/graphics.p8 +++ b/compiler/res/prog8lib/c64/graphics.p8 @@ -10,15 +10,16 @@ graphics { const uword WIDTH = 320 const ubyte HEIGHT = 200 - const uword BITMAP_ADDRESS = $6000 ; MUST BE IN REGULAR RAM if you are not messing with ROM/RAM banking. - const uword CHARS_ADDRESS = $5c00 ; must be in same vic bank as the bitmap + const uword BITMAP_ADDRESS = $6000 ; MUST BE IN REGULAR RAM if you are not messing with ROM/RAM banking. (and $2000-aligned) + ; note: this constant is also used in a asm multiplication table below! + const uword CHARS_ADDRESS = $5c00 ; must be in same vic memory bank as the bitmap. sub enable_bitmap_mode() { ; enable bitmap screen, erase it and set colors to black/white. clear_screen(1, 0) c64.SCROLY = %00111011 ; enable bitmap graphics mode c64.SCROLX = %00001000 ; 40 column mode, no scrolling, multicolor bitmap off - c64.VMCSB = (lsb(CHARS_ADDRESS >> 6) & $F0) | (((BITMAP_ADDRESS & $3fff) / $0800) << 1) ; set bitmap address + c64.VMCSB = (lsb(CHARS_ADDRESS >> 6) & $F0) | (lsb((BITMAP_ADDRESS & $3fff) / $0800) << 1) ; set bitmap address c64.CIA2DDRA |= %11 c64.CIA2PRA = lsb(BITMAP_ADDRESS >> 14) ^ 3 ; set VIC bank. } diff --git a/compiler/res/prog8lib/c64/syslib.p8 b/compiler/res/prog8lib/c64/syslib.p8 index 66ef9acf5..a13599bd5 100644 --- a/compiler/res/prog8lib/c64/syslib.p8 +++ b/compiler/res/prog8lib/c64/syslib.p8 @@ -136,7 +136,8 @@ c64 { %option no_symbol_prefixing ; the default locations of the 8 sprite pointers (store address of sprite / 64) - ; (depending on the VIC bank and screen ram address selection these can be shifted around though) + ; (depending on the VIC bank and screen ram address selection these can be shifted around though, + ; see the two routines after this for a dynamic way of determining the correct memory location) &ubyte SPRPTR0 = 2040 &ubyte SPRPTR1 = 2041 &ubyte SPRPTR2 = 2042 @@ -285,6 +286,39 @@ c64 { ; ---- end of SID registers ---- + + sub get_vic_memory_base() -> uword { + ; one of the 4 possible banks. $0000/$4000/$8000/$c000. + c64.CIA2DDRA |= %11 + return ((c64.CIA2PRA & 3) ^ 3) as uword << 14 + } + + sub get_char_matrix_ptr() -> uword { + ; Usually the character screen matrix is at 1024-2039 (see above) + ; However the vic memory configuration can be altered and this moves these registers with it. + ; So this routine determines it dynamically from the VIC memory setup. + uword chars_matrix_offset = (c64.VMCSB & $f0) as uword << 6 + return get_vic_memory_base() + chars_matrix_offset + } + + sub get_bitmap_ptr() -> uword { + return get_vic_memory_base() + ((c64.VMCSB & %00001000) as uword << 10) + } + + sub get_sprite_addr_ptrs() -> uword { + ; Usually the sprite address pointers are at addresses 2040-2047 (see above) + ; However the vic memory configuration can be altered and this moves these registers with it. + ; So this routine determines it dynamically from the VIC memory setup. + return get_char_matrix_ptr() + 1016 + } + + sub set_sprite_ptr(ubyte sprite_num, uword sprite_data_address) { + ; Sets the sprite data pointer to the given address. + ; Because it takes some time to calculate things based on the vic memory setup, + ; its only suitable if you're not continuously changing the data address. + ; Otherwise store the correct sprite data pointer location somewhere yourself and reuse it. + @(get_sprite_addr_ptrs() + sprite_num) = lsb(sprite_data_address / 64) + } } sys { diff --git a/examples/c64/balloonflight.p8 b/examples/c64/balloonflight.p8 index 209c32795..5086186df 100644 --- a/examples/c64/balloonflight.p8 +++ b/examples/c64/balloonflight.p8 @@ -15,7 +15,7 @@ main { ubyte perform_scroll = false sub start() { - c64.SPRPTR[0] = $0f00 / 64 + c64.set_sprite_ptr(0, $0f00) ; alternatively, set directly: c64.SPRPTR[0] = $0f00 / 64 c64.SPENA = 1 c64.SP0COL = 14 c64.SPXY[0] = 80 diff --git a/examples/c64/cube3d-sprites.p8 b/examples/c64/cube3d-sprites.p8 index 9486a4025..4e562d34f 100644 --- a/examples/c64/cube3d-sprites.p8 +++ b/examples/c64/cube3d-sprites.p8 @@ -171,6 +171,7 @@ main { c64.SPXYW[i] = mkword(sy, sx) + ; because we want speed, we don't use the dynamic c64.set_sprite_ptr() here if(zc < 30*128) c64.SPRPTR[i] = $2000/64 +1 ; large ball else diff --git a/examples/c64/sprites.p8 b/examples/c64/sprites.p8 index 24b16b944..ffa87c5ef 100644 --- a/examples/c64/sprites.p8 +++ b/examples/c64/sprites.p8 @@ -40,7 +40,7 @@ main { ubyte @zp i for i in 0 to 7 { - c64.SPRPTR[i] = $0a00 / 64 + c64.set_sprite_ptr(i, $0a00) ; alternatively, set directly: c64.SPRPTR[i] = $0a00 / 64 c64.SPXY[i*2] = 50+25*i c64.SPXY[i*2+1] = math.rnd() } diff --git a/examples/c64/turtle-gfx.p8 b/examples/c64/turtle-gfx.p8 index 6ba860dbd..6e11dea4d 100644 --- a/examples/c64/turtle-gfx.p8 +++ b/examples/c64/turtle-gfx.p8 @@ -30,19 +30,18 @@ turtle { float angle bool pendown + const uword SPRITE_MEMORY = $5800 + sub init() { xpos = 160.0 ypos = 100.0 angle = 0.0 pendown = true - const uword SPRITE_MEMORY = $5800 - const uword SPRITE_ADDR_POINTERS = (graphics.CHARS_ADDRESS & $fc00) + 1016 ; no longer the default location 2040! - - sys.memcopy(&turtlesprite, SPRITE_MEMORY, len(turtlesprite)) - @(SPRITE_ADDR_POINTERS) = (SPRITE_MEMORY & $3fff) / 64 - c64.SPENA = 1 - c64.SP0COL = 5 + sys.memcopy(&turtlesprite, SPRITE_MEMORY, len(turtlesprite)) ; copy the sprite pixel data + c64.set_sprite_ptr(0, SPRITE_MEMORY) ; use dynamic setter because of changed vic memory layout + c64.SPENA = 1 ; sprites on + c64.SP0COL = 5 ; green sprite update_turtle_sprite() } diff --git a/examples/c64/wizzine.p8 b/examples/c64/wizzine.p8 index 00b6ce108..06ac80079 100644 --- a/examples/c64/wizzine.p8 +++ b/examples/c64/wizzine.p8 @@ -35,7 +35,7 @@ main { sub start() { ubyte i for i in 0 to 7 { - c64.SPRPTR[i] = $0a00/64 + c64.set_sprite_ptr(i, $0a00) ; alternatively, set directly: c64.SPRPTR[i] = $0a00 / 64 } c64.SPENA = 255 ; enable all sprites sys.set_rasterirq(&irq.irqhandler, 230, true) ; enable animation