Skip to content

Instantly share code, notes, and snippets.

@OrionNavattan
Last active February 11, 2024 18:12
Show Gist options
  • Save OrionNavattan/6e0a6be89096d2b9593557f759b214ef to your computer and use it in GitHub Desktop.
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.
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