Trouble Displaying Sprite
Posted: Wed Jan 17, 2024 4:01 pm
Hello,
I was messing around with an assembly program to draw tiles and sprites to the screen in CA65 assembly based on tutorials by Matt Heffernan (SlithyMatt). I got the tiles working fine on both layers. When I went to add sprites, I encountered some trouble and can't figure out what I am doing wrong. I've stripped the code down to just the sprite stuff and where I am encountering my issues.
I load 2 sprites into VRAM and set their attributes. If the mouse is enabled (default or custom cursor) the sprites are displayed as expected. (Mouse is either default or the first sprite I loaded in VRAM, and the other sprite displays at screen position $80,$80) However, if the mouse is disabled, the second sprite doesn't render.
I am still learning how to interface with the VERA, so I am sure I am doing something stupid, but appreciate any help you can provide.
I was messing around with an assembly program to draw tiles and sprites to the screen in CA65 assembly based on tutorials by Matt Heffernan (SlithyMatt). I got the tiles working fine on both layers. When I went to add sprites, I encountered some trouble and can't figure out what I am doing wrong. I've stripped the code down to just the sprite stuff and where I am encountering my issues.
I load 2 sprites into VRAM and set their attributes. If the mouse is enabled (default or custom cursor) the sprites are displayed as expected. (Mouse is either default or the first sprite I loaded in VRAM, and the other sprite displays at screen position $80,$80) However, if the mouse is disabled, the second sprite doesn't render.
I am still learning how to interface with the VERA, so I am sure I am doing something stupid, but appreciate any help you can provide.
Code: Select all
.org $080D
.segment "STARTUP"
.segment "INIT"
.segment "ONCE"
.segment "CODE"
jmp start
; MACROS
.macro VERA_SET_ADDR addr, stride
.ifnblank stride
.if stride < 0
lda #((^addr) | $08 | ((0-stride) << 4))
.else
lda #((^addr) | (stride << 4))
.endif
.else
lda #(^addr) | $10
.endif
sta VERA_addr_bank
lda #(>addr)
sta VERA_addr_high
lda #(<addr)
sta VERA_addr_low
.endmacro
.macro RAM2VRAM ram_addr, vram_addr, num_bytes
.scope
; set data port 0 to start writing to VRAM address
stz VERA_ctrl
lda #($10 | ^vram_addr) ; stride = 1
sta VERA_addr_bank
lda #>vram_addr
sta VERA_addr_high
lda #<vram_addr
sta VERA_addr_low
; ZP pointer = start of video data in CPU RAM
lda #<ram_addr
sta ZP_PTR
lda #>ram_addr
sta ZP_PTR+1
; use index pointers to compare with number of bytes to copy
ldx #0
ldy #0
vram_loop:
lda (ZP_PTR),y
sta VERA_data0
iny
cpx #>num_bytes ; last page yet?
beq check_end
cpy #0
bne vram_loop ; not on last page, Y non-zero
inx ; next page
inc ZP_PTR+1
bra vram_loop
check_end:
cpy #<num_bytes ; last byte of last page?
bne vram_loop ; last page, before last byte
.endscope
.endmacro
; Zero Page
ZP_PTR = $30
DISPLAY_SCALE = 64
; VRAM Addresses
VRAM_sprite_frames= $00000
VRAM_sprattr = $1FC00
sprite2_sprattr = VRAM_sprattr +8
; Sprite Attributes:
SPRITE_Z3 = $0C
SPRITE_16H = $40
SPRITE_16W = $10
; I/O Registers
VERA_addr_low = $9F20
VERA_addr_high = $9F21
VERA_addr_bank = $9F22
VERA_data0 = $9F23
VERA_data1 = $9F24
VERA_ctrl = $9F25
; Kerna; subroutines
MOUSE_CONFIG := $FF68
sprites:
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $00,$00,$0B,$BB,$BB,$B0,$00,$00
.byte $00,$00,$B6,$66,$66,$6B,$00,$00
.byte $00,$0B,$66,$66,$66,$66,$B0,$00
.byte $00,$0B,$66,$66,$66,$66,$B0,$00
.byte $00,$B6,$6B,$BB,$BB,$B6,$6B,$00
.byte $00,$B6,$B7,$77,$77,$7B,$6B,$00
.byte $00,$B6,$77,$B7,$7B,$77,$6B,$00
.byte $00,$B6,$77,$77,$77,$77,$6B,$00
.byte $00,$B6,$67,$77,$77,$76,$6B,$00
.byte $00,$0B,$66,$66,$66,$66,$B0,$00
.byte $00,$00,$B6,$BB,$BB,$6B,$00,$00
.byte $00,$B6,$66,$6B,$B6,$66,$6B,$00
.byte $00,$0B,$66,$66,$66,$66,$B0,$00
.byte $00,$B6,$66,$6B,$B6,$66,$6B,$00
.byte $00,$B6,$66,$6B,$B6,$66,$6B,$00
.byte $00,$0B,$66,$BB,$BB,$66,$B0,$00
end_sprites:
SPRITE_SIZE = end_sprites-sprites
frame: .word 0
frame2:.word 0
start:
; initialize
lda #<(VRAM_sprite_frames >> 5)
sta frame
lda #>(VRAM_sprite_frames >> 5)
sta frame+1
lda #<((VRAM_sprite_frames+$80) >> 5)
sta frame2
lda #>((VRAM_sprite_frames+$80) >> 5)
sta frame2+1
;------------------
; init sprite 0
;------------------
stz VERA_ctrl
VERA_SET_ADDR VRAM_sprattr, 1
; set sprite frame address
lda frame
sta VERA_data0
lda frame+1
sta VERA_data0
; leave position
lda VERA_data0
lda VERA_data0
lda VERA_data0
lda VERA_data0
; leave collision/Z/flipping
lda VERA_data0
; set to 16x16, palette offset 0
lda #(SPRITE_16H | SPRITE_16W)
sta VERA_data0
;------------------
; init sprite 1
;------------------
stz VERA_ctrl
VERA_SET_ADDR sprite2_sprattr, 1
lda frame2
sta VERA_data0
lda frame2+1
sta VERA_data0
; position $80x$80
lda #$80
sta VERA_data0
lda VERA_data0
lda #$80
sta VERA_data0
lda VERA_data0
; Z3
lda #SPRITE_Z3
sta VERA_data0
; set to 32x32, palette offset 0
lda #(SPRITE_16H | SPRITE_16W)
sta VERA_data0
; enable custom mouse
lda #$FF ; custom cursor
ldx #80
ldy #60
jsr MOUSE_CONFIG
RAM2VRAM sprites, VRAM_sprite_frames, SPRITE_SIZE
@main_loop:
wai
; do nothing in main loop, just let ISR do everything
bra @main_loop
; never return, just wait for reset