Red Koopa
Level: 27
Posts: 88/131
EXP: 109184
Next: 6975
Since: 10-18-09
Last post: 4669 days
Last view: 4330 days
|
This can come in handy if you want to make your SNES demo/game/hack blow everybody elses out of the water.
Use this code to software rotate sprites into ram before the level starts. It uses the PPU for data organization purposes, so it doesn't work during active display, so make sure to use a forced blanked load time before the level your using it in. If you want to use 128 kB of work ram to store the rendered sprites, you can dma it back from the PPU to the CPU side.
Sprites to use rotation need to be stored in the ROM as 256x256 8-bit bitmaps. You can store several sprites in the same bitmap, just as long as you give enough space between them so its neighbor sprites don't get rendered inside the box of rotation.
It can render up to 180 16x16 sprites per second.
!add = "clc : adc"
!sub = "sec : sbc"
!angle = "$00"
!bank = "$01"
!sine = "$02"
!cosine = "$04"
!x_pixel = "$06"
!y_pixel = "$08"
!x_displacement = "$0a"
!y_displacement = "$0c"
!width = "$0e"
!height = "$10"
!destination = "$12"
!pixel_address = "$20"
!bit_plane_1 = "$40"
!bit_plane_2 = "$41"
!bit_plane_3 = "$42"
!bit_plane_4 = "$43"
sprite_rotation:
sep #$20
lda #$84
sta $2115 ;; full graphics 4-bit v-ram loading 0aaaaaaabbbccccc -> 0aaaaaaacccccbbb
lda !bank ;; the bank that holds the 8-bit 256x256 bitmap
pha ;; of sprite being rotated
plb
rep #$30
lda !angle ;; find sine and cosine
asl
and #$01fe
tax
lda sine_table+$000000,x
sta !sine
txa
!add #$0080
and #$01fe
tax
lda sine_table+$000000,x
sta !cosine
lda !sine
!add !cosine ;; find the negative x displacement
asl #2 ;; 4 pixels up left from center
sta !x_displacement
lda !cosine ;; find the negative y displacement
!sub !sine ;; 4 pixels up left from center
asl #2
sta !y_displacement
lda !width ;; add center of sprite to x pixel coordinate
tay
asl #2
xba
!add !x_pixel
find_x_pixel:
!sub !x_displacement ;; subtract (x displacement)*width from x pixel
dey ;; coordinate
bne find_x_pixel
sta !x_pixel
lda !width ;; add center of sprite to y pixel coordinate
tay
asl #2
xba
!add !y_pixel
find_y_pixel: ;; subtract (y displacement)*width from y pixel
!sub !y_displacement ;; coordinate
dey
bne find_y_pixel
sta !y_pixel
render_sprite: ;; push x and y pixel coordinates
lda !x_pixel ;; and width onto stack to save
pha ;; for rendering the line after it
lda !y_pixel
pha
lda !width
pha
lda !destination
sta $2116
render_line:
jsr render_8_pixels
dec !width
bne render_line ;; repeat rendering 8-pixels "width" times
rep #$20
pla ;; recover x and y coordinates and width
sta !width ;; next line of pixels
pla
!add !cosine
sta !y_pixel ;; find new starting point for y coordinate
pla
!add !sine
sta !x_pixel ;; find new starting point for x coordinate
lda !destination
!add #$0020
sta !destination ;; set v-ram address reg at the next line of pixels
dec !height
bne render_sprite
rts
render_8_pixels:
rep #$30
lda !y_pixel
sta !pixel_address+2 ;; unrolled loop for finding y coordinate of 8 pixels
!sub !sine
sta !pixel_address+6
!sub !sine
sta !pixel_address+10
!sub !sine
sta !pixel_address+14
!sub !sine
sta !pixel_address+18
!sub !sine
sta !pixel_address+22
!sub !sine
sta !pixel_address+26
!sub !sine
sta !pixel_address+30
!sub !sine
sta !y_pixel
lda !x_pixel
sta !pixel_address+1 ;; unrolled loop for finding x coordinate of 8 pixels
!add !cosine ;; top byte (whole number) of x coordinate is written over
sta !pixel_address+5 ;; bottom byte (decimal) of y coordinate creating
!add !cosine ;; 16 bit pixel addresses in the form of yyyyyyyyxxxxxxxx
sta !pixel_address+9
!add !cosine
sta !pixel_address+13
!add !cosine
sta !pixel_address+17
!add !cosine
sta !pixel_address+21
!add !cosine
sta !pixel_address+25
!add !cosine
sta !pixel_address+29
!add !cosine
sta !x_pixel
sep #$20
ldx !pixel_address+2 ;; unrolled loop for fetching pixels and
lda $0000,x
ror ;; turning 8-bit packed pixel format into 4-bit planar
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+6
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+10
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+14
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+18
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+22
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+26
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !pixel_address+30
lda $0000,x
ror
rol !bit_plane_1
ror
rol !bit_plane_2
ror
rol !bit_plane_3
ror
rol !bit_plane_4
ldx !bit_plane_1
stx $2118 ;; send the 4 bytes to v-ram address port and let the PPU do the rest
ldx !bit_plane_3
stx $2118
rts
sine_table:
dw 0,6,13,19,25,31,38,44,50,56,62,68,74,80,86,92,98,104,109,115,121,126,132,137,142
dw 147,152,157,162,167,172,177,181,185,190,194,198,202,206,209,213,216,220,223,226,229
dw 231,234,237,239,241,243,245,247,248,250,251,252,253,254,255,255,256,256,256,256,256
dw 255,255,254,253,252,251,250,248,247,245,243,241,239,237,234,231,229,226,223,220,216
dw 213,209,206,202,198,194,190,185,181,177,172,167,162,157,152,147,142,137,132,126,121
dw 115,109,104,98,92,86,80,74,68,62,56,50,44,38,31,25,19,13,0,-6,-13,-19,-25,-31,-38
dw -44,-50,-56,-62,-68,-74,-80,-86,-92,-98,-104,-109,-115,-121,-126,-132,-137,-142
dw -147,-152,-157,-162,-167,-172,-177,-181,-185,-190,-194,-198,-202,-206,-209,-213,-216
dw -220,-223,-226,-229,-231,-234,-237,-239,-241,-243,-245,-247,-248,-250,-251,-252,-253
dw -254,-255,-255,-256,-256,-256,-256,-256,-255,-255,-254,-253,-252,-251,-250,-248
dw -247,-245,-243,-241,-239,-237,-234,-231,-229,-226,-223,-220,-216,-213,-209,-206,-202
dw -198,-194,-190,-185,-181,-177,-172,-167,-162,-157,-152,-147,-142,-137,-132,-126,-121
dw -115,-109,-104,-98,-92,-86,-80,-74,-68,-62,-56,-50,-44,-38,-31,-25,-19,-13,-6
|