超級任天堂程式設計/動畫精靈
外觀
本文件面向略微高階的 ASM 程式設計師,比本網站其他內容更高階。
預設情況下,SNES 的精靈模式限制為 16kB,相當於:512 個 8x8 精靈 128 個 16x16 精靈 32 個 32x32 精靈 8 個 64x64 精靈
如您所見,動畫精靈會很快消耗掉可用記憶體。這就是 DMA 的用武之地。唯一的問題是 DMA 並不快。您只有在垂直消隱期間最多有時間進行 6kB 的 DMA 傳輸,如果考慮滾動和 OAM 更新,時間甚至更短。為了本文的目的,我們假設為 4kB。
如何無論我們向螢幕傳送什麼資料,都防止 DMA 傳輸超過 4kB?我們需要讓系統知道何時停止,並在下一幀繼續 DMA 載入。怎麼做?我的解決方案是將 vram 分割成 1kB 的插槽。我選擇 1kB,因為 1kB 恰好是一行 8 個 16x16 的精靈。
!apple = "$0000"
!banana = "$0001"
!table = "$0080"
!update_flag = "$0100"
!vram = "$0101"
!source = "$0102"
;================================================================
macro change_vram(source, vram)
php
rep #$20
sep #$10
lda <source>
ldy <vram>
jsr change_slot
plp
endmacro
;================================================================
change_slot:
cmp !table,y
beq redundant_vram_load
sta !table,y
ldx !apple ;; apple is just a stupid name I chose for a temporary register
sta !source,x
phy
ldy #$01
phy
pla
sta !update_flag,x
inx #4
stx !apple
redundant_vram_load:
rts
;=============================================================
update_vram_slots:
php
sep #$30
ldx !banana ;; banana is just another stupid name I chose
ldy #$04 ;; to name another temporary register
lda #$80
sta $2115
lda #$01
sta $4300
lda #$18
sta $4301
vram_loop:
lda !update_flag,x
beq finish
stz $2116
lda !vram,x
sta $2117
stz $4302
lda !source,x
sta $4303
lda !source+1,x
sta $4304
stz $4305
lda #$04
sta $4306
lda #$01
sta $420b
lda #$00
sta !update_flag,x
inx #4
dey
bne vram_loop
finish:
stx !banana
sep #$30
lda !apple
sec
sbc !banana
cmp #$10
bcc lag
jmp end_of_game_code
lag:
plp
rts
您只需在垂直消隱期間跳轉到 "update_vram_slot" 子例程,並在需要更新動畫插槽時使用 "change_vram" 宏。
例如,如果您想從地址 $98a300 更新 vram 中的插槽 $0400,請使用此宏
%change_vram(#$98a3,#$04)
此程式碼不僅限於精靈動畫,還可以用於背景動畫和滾動。