Page 1 of 2

Trouble Displaying Sprite

Posted: Wed Jan 17, 2024 4:01 pm
by maikaione
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.

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



Re: Trouble Displaying Sprite

Posted: Wed Jan 17, 2024 5:49 pm
by edrive
Hello

I'm new myself, started learning the X16 last October - so I might be wrong also.

As far as I can see, you are going for 4bit per pixel sprites?
This would mean that the first sprite is completely grey: color index $F, offset $0 (using the standard palette).

What I'm kind of missing (or maybe it's in your not shown part of the program) is to set the VERA's DC_VIDEO register.
See register $9F29 (-> VERA programmer's reference).
This register has some bits to turn on or off sprites, layers and the screen in total.

Re: Trouble Displaying Sprite

Posted: Wed Jan 17, 2024 6:08 pm
by maikaione
edrive wrote: Wed Jan 17, 2024 5:49 pm As far as I can see, you are going for 4bit per pixel sprites?
This would mean that the first sprite is completely grey: color index $F, offset $0 (using the standard palette).
Yes, 4BPP. Just a grey box so I could get something on screen.
edrive wrote: Wed Jan 17, 2024 5:49 pm What I'm kind of missing (or maybe it's in your not shown part of the program) is to set the VERA's DC_VIDEO register.
See register $9F29 (-> VERA programmer's reference).
This register has some bits to turn on or off sprites, layers and the screen in total.
Yeah, I had originally started by storing zero there at the beginning of start label, and then setting the bits at the end right before entering the endless loop. I took it out while debugging and it didn't seem to affect anything. However, I added it back in after your suggestion, and I see that I did not have the 7th bit set (I was passing $31 instead of $71) so sprites were disabled. Thank you.

Although now I am wondering why both the sprites showed up (though they were disabled) when I tried to show the mouse. I guess since the mouse is a sprite, enabling it automatically enables sprites.

Re: Trouble Displaying Sprite

Posted: Wed Jan 17, 2024 8:27 pm
by DragWx
Yes, I checked just now, and when the X16 boots, the sprite layer is disabled. Enabling the mouse cursor will enable the sprite layer, which will stay enabled even after you disable the mouse cursor again.

Mouse Sprite

Posted: Fri Jan 19, 2024 2:57 am
by mortarm
Bit of a tangent: Since the mouse pointer is a sprite, would it be possible to customize it?

Re: Mouse Sprite

Posted: Fri Jan 19, 2024 3:15 am
by ahenry3068
mortarm wrote: Fri Jan 19, 2024 2:57 am Bit of a tangent: Since the mouse pointer is a sprite, would it be possible to customize it?
Yes....

Re: Mouse Sprite

Posted: Fri Jan 19, 2024 3:26 am
by mortarm
ahenry3068 wrote: Fri Jan 19, 2024 3:15 am Yes....
Cool. I suppose that's documented somewhere?

Re: Trouble Displaying Sprite

Posted: Fri Jan 19, 2024 4:52 am
by ahenry3068
Should be in the VERA Docs somewhere.

Re: Trouble Displaying Sprite

Posted: Fri Jan 19, 2024 5:50 am
by DragWx
Sorry, it's not actually documented very well.

If you use the Kernal's mouse handling routines, the mouse cursor is always sprite 0. That goes both for BASIC statements and for when you're writing to the VERA directly. At the moment, the Kernal's VERA memory map has sprite 0's pixel data at $13000, so that's where the mouse cursor's graphics will be by default, but you're free to change that to wherever you want by modifying sprite 0's attribute data.

Re: Trouble Displaying Sprite

Posted: Fri Jan 19, 2024 6:48 pm
by mortarm
Thanks for the info.

If this isn't documented well, perhaps it's something the author should know about.