Last active
February 11, 2024 18:12
-
-
Save OrionNavattan/6e0a6be89096d2b9593557f759b214ef to your computer and use it in GitHub Desktop.
Macro file for Hivebrain's Sonic sprite mappings/DPLC format, modified/expanded by OrionNavattan to theoretically support all three formats. Includes examples of how these macros are used.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MappingsFormat: equ 1 ; 1 = Sonic 1/CD, 2 = Sonic 2, 3 = Sonic 3K | |
; --------------------------------------------------------------------------- | |
; Test if argument is used | |
; --------------------------------------------------------------------------- | |
ifarg: macros | |
if strlen("\1")>0 | |
; --------------------------------------------------------------------------- | |
; Create a pointer index. | |
; input: start location (usually * or 0; leave blank to make pointers | |
; relative to themselves), id start (default 0), id increment (default 1) | |
; --------------------------------------------------------------------------- | |
index: macro start,idstart,idinc | |
ifarg \start ; check if start is defined | |
index_start: = \start | |
else | |
index_start: = -1 | |
endc | |
ifarg \0 ; check if width is defined (b, w, l) | |
index_width: equs "\0" | |
else | |
index_width: equs "w" ; use w by default | |
endc | |
ifarg \idstart ; check if first pointer id is defined | |
ptr_id: = \idstart | |
else | |
ptr_id: = 0 ; use 0 by default | |
endc | |
ifarg \idinc ; check if pointer id increment is defined | |
ptr_id_inc: = \idinc | |
else | |
ptr_id_inc: = 1 ; use 1 by default | |
endc | |
endm | |
; --------------------------------------------------------------------------- | |
; Item in a pointer index. | |
; input: pointer target, optional alias (useful if multiple pointers point | |
; to same location, such as the bubble mappings or deleted objects | |
; --------------------------------------------------------------------------- | |
ptr: macro | |
if index_start=-1 | |
dc.\index_width \1-* | |
else | |
dc.\index_width \1-index_start | |
endc | |
if ~def(prefix_id) | |
prefix_id: equs "id_" | |
endc | |
if instr("\1",".")=1 ; check if pointer is local | |
else | |
ifarg \2 | |
\prefix_id\\2: equ ptr_id ; create id for pointer using explicitly specified alias | |
elseif ~def(\prefix_id\\1) | |
\prefix_id\\1: equ ptr_id ; create id for pointer (this is used to build animation scripts) | |
else | |
\prefix_id\\1_\$ptr_id: equ ptr_id ; if id already exists, append number | |
endc | |
endc | |
ptr_id: = ptr_id+ptr_id_inc ; increment id | |
endm | |
; --------------------------------------------------------------------------- | |
; Sprite mappings header and footer | |
; --------------------------------------------------------------------------- | |
spritemap: macro | |
if ~def(current_sprite) | |
current_sprite: = 1 | |
endc | |
sprite_start: = *+1 | |
if MappingsFormat=1 | |
dc.b (sprite_\#current_sprite-sprite_start)/5 ; Sonic 1/CD | |
elseif MappingsFormat=2 | |
dc.w (sprite_\#current_sprite-sprite_start-1)/8 ; Sonic 2 | |
else | |
dc.w ((sprite_\#current_sprite-sprite_start)/6)-1 ; Sonic 3 | |
endc | |
endm | |
endsprite: macro | |
sprite_\#current_sprite: equ * | |
current_sprite: = current_sprite+1 | |
endm | |
; --------------------------------------------------------------------------- | |
; Sprite mappings piece | |
; input: xpos, ypos, size, tile index | |
; optional: xflip, yflip, pal2|pal3|pal4, hi (any order) | |
; --------------------------------------------------------------------------- | |
piece: macro xpos,ypos,dimensions,tileindex,pal_flip_pri | |
spritemap_xpos: = \xpos | |
spritemap_ypos: = \ypos | |
spritemap_width: substr 1,1,"\dimensions" ; width | |
spritemap_height: substr 3,3,"\dimensions" ; height | |
if \tileindex<0 ; is tile index negative? | |
spritemap_tile: = $10000+(\tileindex) ; convert signed to unsigned | |
else | |
spritemap_tile: = \tileindex | |
endc | |
spritemap_xflip: = 0 | |
spritemap_yflip: = 0 | |
spritemap_hi: = 0 | |
spritemap_pal: = 0 | |
rept narg-4 ; parse optional arguments | |
if strcmp("\pal_flip_pri","xflip") | |
spritemap_xflip: = $800 | |
elseif strcmp("\pal_flip_pri","yflip") | |
spritemap_yflip: = $1000 | |
elseif strcmp("\pal_flip_pri","hi") | |
spritemap_hi: = $8000 | |
elseif strcmp("\pal_flip_pri","pal2") | |
spritemap_pal: = $2000 | |
elseif strcmp("\pal_flip_pri","pal3") | |
spritemap_pal: = $4000 | |
elseif strcmp("\pal_flip_pri","pal4") | |
spritemap_pal: = $6000 | |
else | |
endc | |
shift | |
endr | |
dc.w (spritemap_ypos<<8)|((spritemap_width-1)<<2)|(spritemap_height-1) ; y pos, width, and height | |
dc.w (spritemap_tile+spritemap_xflip+spritemap_yflip+spritemap_hi+spritemap_pal)&$FFFF ; tile, priority, xflip, yflip, and pal | |
if MappingsFormat=2 | |
dc.w ((spritemap_tile>>1)+spritemap_xflip+spritemap_yflip+spritemap_hi+spritemap_pal)&$FFFF ; Sonic 2 2P mode tile, priority, xflip, yflip, and pal | |
endc | |
if MappingsFormat=1 | |
dc.b spritemap_xpos ; Sonic 1/CD x pos | |
else | |
dc.w spritemap_xpos ; Sonic 2/3K x pos | |
endc | |
endm | |
; --------------------------------------------------------------------------- | |
; DPLC headers | |
; --------------------------------------------------------------------------- | |
dplcheader: macro | |
if MappingsFormat=1 | |
dc.b (.end-*-1)/2 | |
elseif MappingsFormat=2 | |
dc.w (.end-*-2)/2 | |
else; MappingsFormat=3 | |
dc.w (.end-*-4)/2 | |
endc | |
endm | |
dplcheader_s3kp: macros ; for S3K player objects | |
dc.w (.end-*-2)/2 | |
; --------------------------------------------------------------------------- | |
; DPLC entry | |
; input: name of individual frame in block (e.g., Wait_2) | |
; --------------------------------------------------------------------------- | |
dplc: macro gfx | |
if MappingsFormat<3 | |
ifarg \2 | |
dc.w ((\art_start\_\gfx\-\art_start\)/sizeof_cell)+((\2-1)<<12) ; possibly a hack to accommodate bugged DPLCs in Sonic 1? | |
else | |
dc.w ((\art_start\_\gfx\-\art_start\)/sizeof_cell)+(((sizeof_\art_start\_\gfx\/sizeof_cell)-1)<<12) | |
endc | |
else | |
dc.w (((sizeof_\art_start\_\gfx\/sizeof_cell)-1)<<4)+((\art_start\_\gfx\-\art_start\)/sizeof_cell) | |
endc | |
endm | |
dplc_s3kp: macro gfx ; for S3K player objects | |
dc.w ((\art_start\_\gfx\-\art_start\)/sizeof_cell)+(((sizeof_\art_start\_\gfx\/sizeof_cell)-1)<<12) | |
endm | |
; --------------------------------------------------------------------------- | |
; Include all frames in a block | |
; input: name of block (e.g.; Wait1), number of first frame, number of last | |
; frame | |
; --------------------------------------------------------------------------- | |
dplcgfxblock: macro name,start,finish | |
i: = \start | |
rept \finish-\start+1 | |
dplcgfx \name\_\#i | |
i: = i+1 | |
endr | |
endm | |
; --------------------------------------------------------------------------- | |
; Include an individual frame and make the filesize constant used to | |
; generate its DPLC | |
; --------------------------------------------------------------------------- | |
dplcgfx: macro gfx | |
\art_start\_\gfx\: incbin "\art_loc\/\gfx\.bin" ; include the frame | |
sizeof_Art_Sonic_\gfx\: equ filesize("\art_loc\/\gfx\.bin") ; make filesize constant | |
endm | |
; --------------------------------------------------------------------------- | |
; Examples | |
; --------------------------------------------------------------------------- | |
Map_Sonic: index * | |
ptr frame_Blank | |
ptr frame_Stand | |
ptr frame_Wait1 | |
; The above is for illustration only; in the actual implementation, it is a macro thusly: | |
;sonic_sprites: macro ; this is a macro so it can be reused for DPLCs | |
; index * | |
; ptr \1_Blank | |
; ptr \1_Stand | |
; ptr \1_Wait1 | |
; endm | |
; Map_Sonic: sonic_sprites frame | |
frame_Blank: spritemap | |
endsprite | |
frame_Stand: spritemap | |
piece -$10, -$14, 3x1, 0 | |
piece -$10, -$C, 4x2, 3 | |
piece -$10, 4, 3x1, $B | |
piece -8, $C, 3x1, $E | |
endsprite | |
frame_Wait1: spritemap | |
piece -$10, -$14, 3x2, 0 | |
piece -$10, -4, 3x2, 6 | |
piece -8, $C, 3x1, $C | |
endsprite | |
frame_Wait2: spritemap | |
piece -$10, -$14, 3x2, 0 | |
piece -$10, -4, 3x2, 6 | |
piece -8, $C, 3x1, $C | |
endsprite | |
frame_Wait3: spritemap | |
piece -$10, -$14, 3x2, 0 | |
piece -$10, -4, 3x2, 6 | |
piece -8, $C, 3x1, $C | |
endsprite | |
; =========================================================================== | |
art_start: equs "Art_Sonic" ; string equate with label of start of GFX block | |
SonicDynPLC: index * | |
ptr dplc_Blank | |
ptr dplc_Stand | |
ptr dplc_Wait1 | |
; The above is for illustration only; in the actual implementation, it is a macro thusly: | |
;SonicDynPLC: sonic_sprites dplc | |
dplc_Blank: | |
dplcheader | |
.end: | |
dplc_Stand: | |
dplcheader | |
dplc Stand_0 | |
dplc Stand_1 | |
dplc Stand_2 | |
dplc Stand_3 | |
;dc.w $2000, $7003, $200B, $200E | |
.end: | |
dplc_Wait1: | |
dplcheader | |
dplc Wait_0 | |
dplc Wait_1 | |
dplc Wait_2 | |
;dc.w $5011, $5017, $201D | |
.end: | |
dplc_Wait2: | |
dplcheader | |
dplc Wait_3 | |
dplc Wait_1 | |
dplc Wait_2 | |
;dc.w $5020, $5017, $201D | |
.end: | |
dplc_Wait3: | |
dplcheader | |
dplc Wait_3 | |
dplc Wait_1 | |
dplc Wait_4 | |
;dc.w $5020, $5017, $2026 | |
.end: | |
; =========================================================================== | |
art_loc: equs "Graphics Sonic" ; string equate with path to directory containing individual uncompressed graphics | |
Art_Sonic: | |
dplcgfxblock Stand,0,3 | |
dplcgfxblock Wait,0,4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment