Dynamic Sprites and You!
Hey there everyone! This is a dynamic sprite tutorial, which Iím sure you know since you clicked on the link to get in here. So yeah, here we go into the exciting world of Dynamic Sprites!
What you need:
Patience (found at your nearest virtue retailer)
What is a Dynamic Sprite?
There seems to be quite a stigma surrounding dynamic sprites, and most of that seems to stem from people having no idea what I dynamic sprite really is. So what is it? Itís just a sprite with an over glorified graphics routine. More specifically, it allows dynamic uploads to VRAM, allowing you basically as many frames in a sprite as you like.
What does this tutorial cover?
As the only difference between a dynamic sprite and a regular sprite is the graphics routine, I will only be covering the graphics routine. And, beyond that, I will only be covering the differences between a regular one and a dynamic one. This is why you need some spriting experience, or at least have a basic idea of how to sprite, because I wonít be explaining anything that is done in a normal sprite because that would get repetitive.
SO HOW DO I FREAKING MAKE ONE ALREADY!?
Well fine, settle down, just needed to get the semantics and warnings out of the way. Hereís the real tutorial:
The first thing you want to do is apply DSX.asm, available in the patches section. If you donít, you are going to ask someone for help, they are going to get confused for about 20 minutes trying to figure out what is wrong with the code, and then you will finally remember that you hadnít applied it yet, then youíll feel real embarrassed. Yep.
The most important part of dynamic sprites. Basically you want it laid out so that each frame takes up 1 32x32 square. You can also do less, but Iím sure you can figure that out for your self. In case you are too lazy to make your own GFX, here
is a gfx file that works, and it is the one I will be using in my demonstration.
New library routines:
This is the hard part of dynamic spriting, but, luckily, itís already been done for us. Thank smkdan and edit1754 for getting this out of the way for us, now all we need to do is copy and paste them. The new routines can be found here
if you are assembling with xkas, or here
if you are assembling with TRASM. (You are still going to want all the same library routines as you would have in a normal sprite). What you want to do is copy all of that code into your sprite and NEVER TOUCH IT AGAIN!
TO THE FREAKING CODE ALREADY!
Alright, here goes. A dynamic GFX routine starts out just like a regular one. You need tilemaps, offsets, etc. The difference mainly comes in the fact that you tile numbers will ALWAYS be the same, no matter what frame you are on or where you get your GFX from in the original file, they will always look like this:
(Obviously replace db with dcb if you are using TRASM)
00 is the top left of the dynamic sprite upload, 02 the top right, etc. If you want to grab less tiles just change this accordingly.
Offset tables are essentially the same as in a normal sprite, just set those up however you like. Telling it where to grab from is where it gets a bit weird. Instead of everything being 2 apart, itís only 1 apart, since everything is apparently set up in 32x32 tiles. So the top left of the file is $00, 32 pixels to the right is $01, down 32 pixels is $11, etc., so a 16 frame sprite (like the one in the file I linked) would have a table like so:
(Once again, thatís Xkas, adjust accordingly for TRASM)
So, now that weíve got the pesky tables out of the way, time to start writing the routine. It starts just like any other routine, as Iíve said before.
SUB_GFX: JSR GET_DRAW_INFO
LDA $157C,x ; $02 = sprite direction
STA !TempDir ;Pretty simple, just like you would normally set a sprites direction.
STZ !TilesTemp ;Used to keep track of the number of tiles drawn
LDA !FrameNum,x ;You can also load a static value to here,
;this is used as an index for the frames
;table. This is freeRAM
PHX ;\Get the place to grab from into the accumulator
LDA Frames,x ;|
So thatís all pretty simple I would suppose, this is where it really starts being different:
JSR GETSLOT ;This is that part we should thank smkdan for
BEQ EndIt ;Donít draw if there is no empty dynamic sprite slot
STA !OneTileTemp ;Store the tile into scratch RAM, I use $07
And then we get into a normal sprite writing loop, just like in any other sprite, Iíll comment on whatís important:
LDA !OneTileTemp ;remember the tile we stored earlier?
;Now we get it back and store it
;like we would a normal tile, except
;we add the value from the Tiles table to it.
LDX $15E9 ;Get sprite index back
LDA $15F6,x ;You know the drill here
CPX #$04 ;Tells it to draw 4 tiles, which is the max
;allowed. Less is fine though,
;just set up your tables accordingly.
LDA !TilesTemp ;The number of tiles drawn
BEQ EndIt ;Donít draw if we didnít get any
DEC ;\Yada, yada, normal drawing routine
LDY #$02 ;|16x16 tiles
JSL $01B7B3 ;/
Notice how the only difference really (Besides my few quirks I have going on), is that you load the tile that it finds for you? Yeah, thatís really it, it is that simple. Everything hard has been done for us. The only thing left for you to do is feed a value into !FrameNum and jump to the routine like normal. You can change it however you like it to be once you understand it.
To use this graphics routine:
The easiest thing to do is to make the sucker spin. To do that itís just some simple code:
AND #$10 ;Check if the 4th (from right, 0 indexed) is set
LSR ;If it is, flip it, if not, donít flip it, simple as that
STA $157C,x ;Store to the direction RAM
LDA !FrameNum,x ;\Only allow 16 frames
AND #$1F ;|
STA !FrameNum,x ;/
Oh and one more important thing, at the very bottom of the file you need:
INCBIN sprites\barrel.bin ;included graphics file
The first two lines are unnecessary if you are using TRASM, and replace barrel.bin with the name of the gfx file you are using.
And the final product would be a little something like this
(once again, it uses xkas, should be quite similar with TRASM though).
Oh, and all dynamic sprites need to use sp4, so set that up in the cgf.
And one more thing: Sprite graphics that take up more than 1 bank in ROM (over 64000 bytes), it takes a different dynamic sprite routine which you can get here
, then follow these instructions for manual GFX insertion:
Originally posted by edit1754
Steps to inserting GFX:
1. BACK UP YOUR ROM!!! You will always want an up-to-date copy if you corrupt it accidentally
2. Open your SMW ROM in translhextion
3. Keep scrolling down until you find a large blank area full of zeros.
4. Look for an address that ends in "0200" or "8200" (these are beginnings of ROM banks) ...or you can overwrite the old blowhard GFX. Also, make sure there are at least 8 zeros before that, for the RATS tag. (unless the space is used by the old RATS tag)
5. To make sure there is enough space, use the select block feature to select an area that is 0x7F80 (32640) bytes long. To do this, go to Selection > Select Block, click "number of bytes to select", and type the decimal value of the space required. (in this case, it's 40960, which is 1 and 1/4 ROM banks)
6. If there are only zeros in the space, go to the next step, otherwise repeat from step 3 to find another space.
7. Go back to the address at the start and write it down (the PC offset)
8. Open "blowhardgfx.bin" in another translhextion window and copy/paste the data into the starting address in the SMW ROM's blank space you found. When the paste dialog box comes up, make sure you select "overwrite" and NOT "insert".
9. go back 8 bytes before your starting address and type 53 54 41 52 00 A0 FF 5F for your RATS tag
10. Open Lunar Address and select "LoRom - PC". If it doesn't automatically say PC and SNES under the text boxes at the bottom of the window, clear out one or both until it shows the labels so you know which is which.
11. Type the first address you wrote down into Lunar Address where it says PC and write down the address it says in "SNES".
12. Open blowhard.asm in notepad and search for "GFXADDR", it should be near the top.
When you find it, you will see something like this:
GFXADDR = $XXXXXX
13. Go back to the last address you wrote down (the converted address), it should look something like this: $12:3456.
14. For the converted address, enter it in like this:
GFXADDR = $123456
15. save the ASM file and insert the sprite (yiblowhardv2.asm, yiblowhardv2.cfg) like you would any sprite.
(Obviously create your own GFXADDR at the beginning of your sprite if you don't have one)
And that should basically be your first dynamic sprite right there. You have fun now.