Skip to content

Instantly share code, notes, and snippets.

@reltham
Created October 25, 2022 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reltham/cb607cb91eae8bc8a7a1609e791fe6ea to your computer and use it in GitHub Desktop.
Save reltham/cb607cb91eae8bc8a7a1609e791fe6ea to your computer and use it in GitHub Desktop.
sprite test code
%import textio
%import syslib
%import cx16diskio
%zeropage basicsafe
main {
sub start() {
txt.chrout(19) ; HOME
txt.print("\nsprite test\n\n")
; load our sprites into VERA
void cx16diskio.vload("birdsprites.bin", 8, 0, $a000)
; enable sprites
cx16.VERA_DC_VIDEO = cx16.VERA_DC_VIDEO | %01000000
; setup sprite 1
sprite.setup(1, %00000101, %00011000, 0)
set_sprite_frame(1, 0)
uword birdX = 50
uword birdY = 50
sprite.position(1, birdX, birdY)
bool xDir = true
bool yDir = true
sprite.flips(1, xDir)
ubyte i = 0
repeat {
set_sprite_frame(1, i)
i++
if (i > 7) i = 0
sprite.position(1, birdX, birdY)
if (xDir) birdX++ else birdX--
if (yDir) birdY++ else birdY--
if (birdX > 300 or birdX < 10)
{
xDir = not xDir
sprite.flips(1, xDir)
}
if (birdY > 100 or birdY < 30) yDir = not yDir
sys.wait(mkword(0,1))
}
}
; select which sprite image to display using sprite 1 (second sprite)
sub set_sprite_frame(ubyte spriteNum, ubyte index) {
; sprites are in VERA memory at $a000
uword sprite_data_addr = $a000
; each sprite is 256 bytes so incrementing the upper byte of the uword advances to the next sprite image
sprite_data_addr += mkword(index, 0)
sprite.set_address(spriteNum, 0, sprite_data_addr)
}
}
sprite {
; widthHeight = (width << 2) | (height)
; width and height are o to 3 for 0 = 8, 1 = 16, 2 = 32, 3 = 64.
; modeZDepthVHFlips = (mode << 4) | (zDepth << 2) | (vFlip << 1) | hFlip
; mode is 0 = 4bpp and 1 = 8bpp
; zDepth is 0 to 3, 0 = disabled, 1 = behind layer0, 2 = between layer0 and layer1, 3 = in front of layer1
; vFlip and hFlip are 0 = not flipped, 1 = flipped
; collisionMaskPaletteOffset
; paletteOffset lower 4 bits
; collisionMask upper 4 bits
sub setup(ubyte spriteNum, ubyte widthHeight, ubyte modeZDepthVHFlip, ubyte collisionMaskPaletteOffset) {
uword offset = spriteNum << 3
ubyte temp1 = (widthHeight << 4) | (collisionMaskPaletteOffset & $0F)
ubyte temp2 = (collisionMaskPaletteOffset & $F0) | (modeZDepthVHFlip & $0F)
ubyte temp3 = ((modeZDepthVHFlip & $F0) << 3) | (cx16.vpeek(1, $fc01 + offset) & $7F)
cx16.vpoke(1, $fc01 + offset, temp3)
cx16.vpoke(1, $fc06 + offset, temp2)
cx16.vpoke(1, $fc07 + offset, temp1)
}
sub flips(ubyte spriteNum, ubyte VHFlips) {
uword offset = spriteNum << 3
cx16.vpoke_and(1, $fc06 + offset, %11111100)
cx16.vpoke_or(1, $fc06 + offset, (VHFlips & $03))
}
; xPos and yPox only use the lower 10 bits, the upper bits are ignored
sub position(ubyte spriteNum, uword xPos, uword yPos) {
uword offset = spriteNum << 3
cx16.vpoke(1, $fc02 + offset, lsb(xPos))
cx16.vpoke(1, $fc03 + offset, msb(xPos))
cx16.vpoke(1, $fc04 + offset, lsb(yPos))
cx16.vpoke(1, $fc05 + offset, msb(yPos))
}
; sprites have to be 32 byte aligned, so the lower 5 bits of spriteAddress are ignored
sub set_address(ubyte spriteNum, ubyte spriteBank, uword spriteAddress) {
uword offset = spriteNum << 3
uword addr = (spriteAddress >> 5) | ((spriteBank as uword & 1) << 11)
cx16.vpoke(1, $fc00 + offset, lsb(addr))
ubyte currentModeValue = cx16.vpeek(1, $fc01 + offset) & %10000000
cx16.vpoke(1, $fc01 + offset, currentModeValue | msb(addr))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment