The routine is still pretty long. This is how it looked a several months ago,
and I've been trying to squeeze the code down with macros so that it's less intimidating. But, I've also added a "single 32x32 sprite" and "single 16x16 sprite" mode so that single sprite objects don't need large data tables. In order to shrink data, I had to use more code.
Code: Select all
animation:
-;
jsr do_animation
lda {next_slot}
bne -
lda {active_slot_pointer}
cmp {last_object_to_dma}
beq +
-;
jsr do_animation
lda {next_slot}
cmp {last_object_to_dma}
bne -
+;
rts
do_animation:
tcd
ldy {metasprite_request}
bne + //no animation, if "metasprite_request" is blank
jsr clear_vram_slot
stz {frame_id}
rts
+;
lda {animation_update} //sprite is animated if "metapsprite" is different from
bne + //"metasprite_request" or "animation_update" is set
rts
+;
lda $000c,y
sta {vram_size}
clc
adc {total_dma_legnth} //check if there is enough DMA time for sprite
cmp #$0081
bcc ++
lda {first_object_to_dma}
bne +
tdc
sta {first_object_to_dma}
+;
rts
+;
jsr clear_vram_slot //clear previous animation frame
lda #$0002
trb {object_traits}
cmp {animation_update} //if "animation_update" is 2, then frame is rotated 180 degrees
bne +
tsb {object_traits}
+;
stz {animation_update}
ldy {metasprite_request}
lda $000e,y
clc
adc {animation_index}
inc #2
sta {frame_id}
tax
lda.w {animation_copies},x
inc
sta.w {animation_copies},x
dec
beq + //if animation_copies is not 0, then no further processing is needed
rts
+;
ldx #$ffff
lda $0008,y
sta {temp2} //"temp2" is ROM bank
bpl +
jmp single_sprite
+;
cmp #$4000
bcc +
jmp single_small_sprite
+;
lda $000a,y //find the ROM address of sprite graphics
asl #5 //ROM address = metasprite ROM address + (animation frame)*(metasprite ROM size)
sta {vram_width}
sep #$20
lda {animation_index}
lsr
sta $4202
lda $000c,y
sta $4203
rep #$20
lda $4216
asl #5
adc $0006,y
sta {temp3} //"temp3" is ROM address
lda $0010,y
bpl + //if $0010,y is $7fff or less, it is the metasprite data itself
tya //if $0010,y is $8000 or more, it is the address pointing to metasprite data
clc
adc {animation_index}
tax
ldy $0010,x
+;
phd
lda #$0000
tcd
ldx #$ffff
-;
lda $0010,y
bne +
jmp invalid_chr
+;
sty.b {temp5}
lda $0012,y
sta.b {temp_x}
lda $0011,y
and #$0070
lsr #4
sta.b {temp8} //"temp8" counts down the horizontal sprite run
lda $0018,y
xba
lsr #2
adc.b {temp3}
-;
sta.b {temp} //"temp" is the ROM address of the sprite being added
sta.b {temp9} //"temp9" is the ROM address of the top sprite in a vertical run
lda $0014,y
sta.b {temp_y}
lda $0011,y
and #$000f
sta.b {temp7} //"temp7" counts down the vertical sprite run
jmp find_vram_slot
find_vram_slot_done:
ldy.b {temp5} //this puts all the "OAM" information
ora $0016,y
sta {sprite_attributes},x
lda.b {temp_y}
sta {sprite_y},x
clc
adc.b {temp10}
sta.b {temp_y}
lda.b {temp_x}
sta {sprite_x},x
dec.b {temp7} //decreases "temp 7" until all sprites
bpl find_vram_slot //in the vertical run are put on linked list
dec.b {temp8} //decreases "temp 8" until all sprites
bmi + //in the horizontal run are put on linked list
clc
adc.b {temp10}
sta.b {temp_x}
lda.b {temp10}
asl #2
adc.b {temp9}
jmp -
+;
stx.b {temp6}
tya
clc
adc #$000a
tay
jmp --
macro find_slot(stack_index,stack,label) {
ldy {stack_index}
dey
dey
bmi {label}
txa
ldx {stack}-$a00000,y
sty {stack_index}
sta {next_sprite},x //adds slot to linked list
lda x16_lut,x
ora #$4000
ldy {dma_updates}
clc
}
macro add_and_store_2x(a,b) {
sta {b},y
adc {a}
sta {b}+8,y
}
macro add_and_store_4x(a,b) {
add_and_store_2x({a},{b})
adc {a}
add_and_store_2x({a},{b}+16)
}
small_slot: //this finds 16x16 VRAM slot
find_slot({small_slot_stack_index},{small_slot_stack},invalid_chr)
add_and_store_2x(#$0100,{dma_destination})
lda.b {temp}
add_and_store_2x({vram_width},{dma_address})
adc {vram_width}
sta.b {temp}
lda.b {temp2}
ora #$4000
sta {dma_bank},y
sta {dma_bank}+8,y
stz.b {temp4}
stz.w {sprite_size},x
lda #$0010
jmp +
invalid_chr:
pld
done_with_animation_routine:
txa
ldx {frame_id}
sta.w {animation_chr},x
lda {vram_size}
clc
adc {total_dma_legnth}
sta {total_dma_legnth}
rts //this is where the game exits the routine
find_vram_slot:
lda $0010,y
and #$0003
dec
beq small_slot
cmp #$0001
beq large_slot
repeat_slot: //this finds repeat slots
ldy {repeat_slot_stack_index}
dey
dey
bmi invalid_chr
txa
ldx {repeat_slot_stack}-$a00000,y
sty {repeat_slot_stack_index}
sta {next_sprite},x //puts it on linked list
lda.b {temp4}
ora #$0002
sta {sprite_size},x
lda.b {temp6}
jmp find_vram_slot_done
large_slot: //finds open 32x32 VRAM slot
find_slot({large_slot_stack_index},{large_slot_stack},invalid_chr)
add_and_store_4x(#$0100,{dma_destination})
lda.b {temp}
add_and_store_4x({vram_width},{dma_address})
adc {vram_width}
sta.b {temp}
lda.b {temp2}
ora #$8000
sta {dma_bank},y
sta {dma_bank}+8,y
sta {dma_bank}+16,y
sta {dma_bank}+24,y
lda #$0001
sta.b {temp4}
sta {sprite_size},x
lda #$0020
+;
sta.b {temp10}
clc
adc.b {dma_updates}
sta.b {dma_updates}
txa
jmp find_vram_slot_done
x16_lut:
dw $0000,$0020,$0040,$0060,$0080,$00a0,$00c0,$00e0,$0110,$0120,$0140,$0160,$0180,$01a0,$01c0,$01e0
dw $0200,$0220,$0240,$0260,$0280,$02a0,$02c0,$02e0,$0310,$0320,$0340,$0360,$0380,$03a0,$03c0,$03e0
dw $0400,$0420,$0440,$0460,$0480,$04a0,$04c0,$04e0,$0510,$0520,$0540,$0560,$0580,$05a0,$05c0,$05e0
dw $0600,$0620,$0640,$0660,$0680,$06a0,$06c0,$06e0,$0710,$0720,$0740,$0760,$0780,$07a0,$07c0,$07e0
dw $0800,$0820,$0840,$0860,$0880,$08a0,$08c0,$08e0,$0910,$0920,$0940,$0960,$0980,$09a0,$09c0,$09e0
dw $0a00,$0a20,$0a40,$0a60,$0a80,$0aa0,$0ac0,$0ae0,$0b10,$0b20,$0b40,$0b60,$0b80,$0ba0,$0bc0,$0be0
dw $0c00,$0c20,$0c40,$0c60,$0c80,$0ca0,$0cc0,$0ce0,$0d10,$0d20,$0d40,$0d60,$0d80,$0da0,$0dc0,$0de0
dw $0e00,$0e20,$0e40,$0e60,$0e80,$0ea0,$0ec0,$0ee0,$0f10,$0f20,$0f40,$0f60,$0f80,$0fa0,$0fc0,$0fe0
dw $1000,$1020,$1040,$1060,$1080,$10a0,$10c0,$10e0,$1110,$1120,$1140,$1160,$1180,$11a0,$11c0,$11e0
dw $1200,$1220,$1240,$1260,$1280,$12a0,$12c0,$12e0,$1310,$1320,$1340,$1360,$1380,$13a0,$13c0,$13e0
dw $1400,$1420,$1440,$1460,$1480,$14a0,$14c0,$14e0,$1510,$1520,$1540,$1560,$1580,$15a0,$15c0,$15e0
dw $1600,$1620,$1640,$1660,$1680,$16a0,$16c0,$16e0,$1710,$1720,$1740,$1760,$1780,$17a0,$17c0,$17e0
dw $1800,$1820,$1840,$1860,$1880,$18a0,$18c0,$18e0,$1910,$1920,$1940,$1960,$1980,$19a0,$19c0,$19e0
dw $1a00,$1a20,$1a40,$1a60,$1a80,$1aa0,$1ac0,$1ae0,$1b10,$1b20,$1b40,$1b60,$1b80,$1ba0,$1bc0,$1be0
dw $1c00,$1c20,$1c40,$1c60,$1c80,$1ca0,$1cc0,$1ce0,$1d10,$1d20,$1d40,$1d60,$1d80,$1da0,$1dc0,$1de0
dw $1e00,$1e20,$1e40,$1e60,$1e80,$1ea0,$1ec0,$1ee0,$1f10,$1f20,$1f40,$1f60,$1f80,$1fa0,$1fc0,$1fe0
macro clear_slot(stack_index,stack) {
ldx {stack_index}
sta.w {stack},x
inx
inx
stx {stack_index}
lda {next_sprite}-$a00000,y
cmp #$ffff
bne -
rts
}
-;
rts
clear_vram_slot: //this routine clears the VRAM slots of the previous animation frame
ldx {frame_id}
beq -
lda.w {animation_copies},x
beq -
dec
sta.w {animation_copies},x
bne -
lda.w {animation_chr},x
cmp #$ffff
beq -
-;
tay
ldx {sprite_size}-$a00000,y
beq clear_small_slot
dex
beq clear_large_slot
clear_slot({repeat_slot_stack_index},{repeat_slot_stack})
clear_small_slot:
clear_slot({small_slot_stack_index},{small_slot_stack})
clear_large_slot:
clear_slot({large_slot_stack_index},{large_slot_stack})
//////////////////////////////////////////////////////////////////////////////////
sram_bank_crossing:
lda {animation_index}
xba
and #$ff00
-;
cmp #$2000
bcc +
sbc #$2000
inc {temp2}
clc
bra -
single_sprite:
lda $0002,y
bmi sram_bank_crossing
lda {animation_index}
xba
and #$ff00
clc
+;
adc $0006,y
sta {temp3} //"temp3" is ROM address
lda $0010,y
sta {temp5}
find_slot({large_slot_stack_index},{large_slot_stack},invalid_single_chr)
add_and_store_4x(#$0100,{dma_destination})
lda {temp3}
add_and_store_4x(#$0080,{dma_address})
lda {temp2}
sta {dma_bank},y
sta {dma_bank}+8,y
sta {dma_bank}+16,y
sta {dma_bank}+24,y
tya
clc
adc #$0020
sta {dma_updates}
lda #$0001
sta {sprite_size},x
lda #$fff0
-;
sta {sprite_y},x
sta {sprite_x},x
txa
ora {temp5}
sta {sprite_attributes},x
invalid_single_chr:
jmp done_with_animation_routine
single_small_sprite:
lda {animation_index}
xba
and #$ff00
lsr #2
clc
adc $0006,y
sta {temp3} //"temp3" is ROM address
lda $0010,y
sta {temp5} //finds open 32x32 VRAM slot
find_slot({small_slot_stack_index},{small_slot_stack},invalid_single_chr)
add_and_store_2x(#$0100,{dma_destination})
lda {temp3}
add_and_store_2x(#$0040,{dma_address})
lda {temp2}
sta {dma_bank},y
sta {dma_bank}+8,y
tya
clc
adc #$0010
sta {dma_updates}
stz.w {sprite_size},x
lda #$fff8
bra -