Thanks everyone for the nice reception!
Long post incoming!!
Dynamic Spriteset System details
The Dynamic Spriteset System (DSS) is a compilation of several ASM hacks and edits to existing sprites to allow dynamically filling the VRAM at SP3/SP4 regions via requests of sprites loaded in memory. This means that any non visible sprite on the screen will not have their graphics on SP3/SP4 and you won't have to waste time messing with disassemblies, hex edits or small patches to manage your spriteset for each level you want to make.
The system is separated in three different and smaller systems: the request/queue GFX routine, the VRAM queue system, the new sprite detector and the garbage collector. This system relies on ExGFX files which are inserted via Lunar Magic.
Request/Queue GFX routine
This routine has two primary functions which depends on wheter the sprite has been its needed graphics on VRAM and accesible at the current frame (more on this later).
The first function is the one that puts the necessary tiles which are not present nor accessible
in a queue to upload them to VRAM at the start of the next frame/NMI interrupt. This function also covers other aspects of the whole system:
- Decompress ExGFX file (which can be up to 3KiB)
- Mark tiles in SP3/SP4 as used so any other sprite which requests their graphics to be uploaded to VRAM don't overwrite these used slots
- Save the tiles used to two buffers: a temporal one which will be overwritten the next time the routine is called and a persistent one that holds the same data as the temporal one as long the sprite remains in memory/in screen and can be requested at any time. The persistent buffer is actually a big buffer that holds the information for up to 32 different ExGFX's tile number data, basically an array of arrays.
The second function is far less complex but still very important, it requests the tile data from the persistent buffer which is copied into the temporal buffer for easy access in the sprite code. The routine won't provide any data if the tiles haven't been uploaded to VRAM.
There are moments in the video where you can see a lot of duplicated graphics which ends up looking really bad. This was due to them being marked as "not accessible" or "unused" since no sprite or any other code tried to use these graphics in the previous frames, thus making necessary to put the tiles into the VRAM queue again.
The graphics will be marked as "unused" once a certain amount of frames have passed since the last time their tile data was requested. The default duration is 16 frames, I'm still experimenting with this so it may change later (presumably to a little higher value).
VRAM queue system
A queue system to upload graphics to VRAM was pretty much needed to upload the needed graphics in small chunks every frame to avoid any kind of flickering/overflow.
I designed the system to be a ring/circular buffer with 64 possible entries while each entry holds 4 bytes worth of data. The data stored is a VRAM destination (2 bytes) and the RAM buffer location (2 bytes, bank byte hardcoded to $41). It being a ring buffer helps to avoid making complex calculations when it comes to update the index used in the routine.
Every frame it will try to upload a fixed amount of 16x16 tiles (7 at this moment) in the quickest way I could come up with. I haven't measured the routine in regards of its cycle usage yet, so the amount of tiles uploaded each frame may be reduced depending on how demanding this is.
The system may be used to upload different things to other VRAM regions, but I haven't done anything with that :
New sprite detector
Kinda misleading title, but it isn't a new version of some sprite detector, it detects sprites which where spawned in the current frame.
It sounds like a kinda unnecessary thing, but it was needed to avoid an extra frame of delay for sprie graphics to appear in some cases where sprites were spawned in the same frame and their slot wasn't executed, thus not putting their graphics into the VRAM queue (if needed). It also helps to upload graphics for extended and cluster sprites. And finally, it helps to avoid hijacking every single spawn routine in the whole game.
This routine it's just a bunch of loops and it's quite slow... but if it helps me to not hijack a lot of places (more than I actually have lol), then it's a good trade.
The garbage collector is the routine in charge of marking tiles as unused every frame. It doesn't do much, but it's still quite important part of the whole system.
It was already explained, but again with a little extra details: to get sprite graphics to be marked as unused, the ExGFX file should not be called for a fixed amount of frames. Once a sprite GFX is marked as unused, everything about them will be marked as unused, this includes their data in the persistent buffer, making the tiles in VRAM not accesible, even if they're present.
You can simply avoid getting graphics marked as unused if you request their data from the persistent buffer using the included routine (or just reset their timer), this isn't limited to sprites, you can also do this via UberASM or custom blocks!
- I decided to use Lunar Magic's ExGFX system since it was quite manageable to decompress graphics via SA-1
- It took me about a third of a year to design the whole thing, I have a hard time coming up with ideas
- I did make something similar and showcased it some time ago, the main diference is that the spriteset was built at level load and NOT during actual gameplay, which didn't allow for a varied cast of enemies in a level
- The current system doesn't play very well with reskins of sprites, I haven't come up with a good method to allow them
- Adding more ExGFX files is actually quite tedious, as you have to edit at least 2 different files: you need make a define which points to the ExGFX and you have to edit a table with the amount of 16x16 tiles your ExGFX has.
- It will require a fair amount of ASM knowledge to get this to work with custom resources. The system is fairly simple to use, but you have to know which parts of the GFX routine you have to edit and I'm sure I can't assist everyone to examine every single one of their sprites.
- Every single original sprite will be modified to use this system, it's a long and tedious work, but it will be worth.
- I will try including .ssc, .s16, .mwt files to fix the look of sprites and have them show fine in Lunar Magic regardless of the loaded graphics in the level.
Originally posted by Ninja Boy
Even if this system doesn't extend to custom sprites if you can say use 2 of the 4 files for the dynamic system and 2 for non-dynamic stuff that opens so many possibilities for sprite combos.
This is quite possible! You can limit how many sprite tiles will be used for the dynamic spriteset system via uberasm, as there is a RAM address that controls exactly that. It will be removing the posibility to use sprites from the bottom of SP4 to the top of SP3. This is particularly useful for dynamic sprites made for DSX.
Originally posted by TheLegendaryOrb
What can the Dynamic Spriteset System do? Am I understanding it correctly that it can change the SP1-4 dynamically?
Just SP3 and SP4; SP1 and SP2 will remain the same, SP2 will now have a lot of blank areas due to every enemy from there is now part of the dynamic spriteset system.
Originally posted by qantuum
I expect the syntax of the message writing to be easier, but I'll find out in the github repo
It's pretty much the same as the original version, it just doesn't require ActivePerl :
The main feature of my update is that it now includes a ton of new commands to play with.
Originally posted by Final Theory
I really like the Modernized Romi's VWF Cutscene tool. Can you load custom sprites in it instead of just vanilla sprites?
The VWF cutscene system (both old and modern) allow for any sprite graphic in SP1, SP2, SP3 and SP4 to be displayed in screen at any position. You can load any ExGFX in these slots via Lunar Magic and you can use them just fine! In fact, that's how SMWCP1 did their fancy cutscenes
Originally posted by Final Theory
Also how do you trigger these cut scenes. Is it after you beat a particular level?
You place vwf.json and vwf_data.json (this name may vary) in the level and a cutscene will play.
Originally posted by Final Theory
This is an excellent way to tell an actual story and such. It would be great if there was a way to make sprites and such act out stuff like in FF3 or Chrono Trigger.
It may be possible, but it will certainly require ASM knowledge! (You can hijack your own ASM into the cutscenes).
Originally posted by Final Theory
Can you talk to an NPC in a level and also trigger this dialogue?
If you teleport to another level, yes.
Originally posted by imamelia
I know I asked before, but have you tested the spriteset system both with and without SA-1? Is there an option for the latter, at least, to have the graphics uncompressed to save processing time??
I really don't have plans to make a non SA-1 version as I want to stick with the ExGFX approach I have. However, as I've mentioned in discord, this function it's pretty much isolated and you can modify it to use pointers to ROM instead of ExGFX files; the easiest way would copying the GFX data to a RAM buffer so you don't have to modify the inner workings of the VRAM queue system, very similar to how DSX works.
That said, the code already includes the necessary stuff to make a non SA-1 version, I'm way too used to append |!dp and |!addr to anything I program.
Originally posted by Atari2.0
as for the VWF tool, I can't say I'm surprised because I helped you revamp it quite a bit, sooooo I'm gonna comment on the last thing, the syntax highlighter is amazing, I've been using it since you made it and honestly it improved my asm experience by a lot, it's so nice being able to distinguish things by color and not have to look at a wall of black and white text.
Here's to more projects!
You were VERY helpful in the VWF tool modernizations! I'm glad you wanted to revamp the code without me asking lmao.
I'm super glad people have found my highlighter useful! It was a good excuse to learn regex haha.
Originally posted by RPG Hacker
Pretty great seeing another syntax highlighter for Asar. Admittedly, some things are highlighted in a way that seems a bit weird to me, but I'm guessing it was probably easier to do that way, and in any case, having different highlighting options is always good.
I have weird color preferences haha. Everything is super customizable though. Almost every part has its own scope which can be colored or stylized in a different way.
There was an exising highlighter in the Extensions Marketplace, but it was quite bad and didn't support asar's functions which annoyed me a bit. Basically: