Viability of Porting Sonic Mania

How would you get the individual sprite frames out of the sprite sheets without texture coordinates? They're not stored like your typical sprite sheet on the Saturn where each frame is it's own individual image concatenated together. It's one giant 512x512 image with all the frames stored in it:
View attachment 10402View attachment 10403

At the very minimum we'd need to rework these to be in a format that can actually work on Saturn. You could possibly do software texture coordinates on the CPU to cut each frame out and send to VRAM, but that could add a lot of unnecessary overhead on the CPU.
you pre-process it into an asset that fits into VRAM. that can all be done before on a computer instead of doing it on the Saturn (maybe the source code can help since it probably has the coordinates for the UV mapping already). each of those animation sets can be made into a tilemap that works on the Saturn. I don't think they even need to be the same size, they just need to match the Saturn's resolution constraints for VDP1.

actually, all of the coordinates for the animations are probably stored in the .bin files in the assets folder. working out how those define the animations would be the place to start (rather than trying to manually cut up the files by hand, which won't work for distributing a "patch" or having people compile their own).
 
Last edited:
you pre-process it into an asset that fits into VRAM. that can all be done before on a computer instead of doing it on the Saturn (maybe the source code can help since it probably has the coordinates for the UV mapping already). each of those animation sets can be made into a tilemap that works on the Saturn. I don't think they even need to be the same size, they just need to match the Saturn's resolution constraints for VDP1.

actually, all of the coordinates for the animations are probably stored in the .bin files in the assets folder. working out how those define the animations would be the place to start (rather than trying to manually cut up the files by hand, which won't work for distributing a "patch" or having people compile their own).
Again, this is exactly what I've been saying. You'd need to modify the assets before hand to get them into a Saturn friendly format that doesn't rely on texture coordinates to work.
 
forgive me if this is a stupid comment, but wouldnt it be easier to port chaotix and then sprite hack it to resemble mania?
There's a couple of issues with that:
  1. We'd have to make and wait for a complete-enough disassembly in order to use it's engine, and since it's not based on the original series' engine (meaning symbols from the original games can't be easily spotted and put in) it could take quite a while.

  2. Of course, the graphics pipeline would need to be reworked to work with the Saturn.

  3. You'd be working with Assembly, which is fine for some but not for most.

  4. It might not seem like it, but there's quite a lot differences in the engine compared to the usual sonic games, the physics have been reworked to tether between two characters, there's no collision layer-swapping (for things such as loops) in the game, and possibly a lot more I didn't think of.

  5. Chaotix utilizes the M68k for a fair amount of code, so code conversion would be needed, and a bit of restructuring needs to be made to the code as the CPU might be utilized as some kind of extra thread for the CPU's (although as far as I know, it's only real purpose is booting the game and some background layers)

  6. Mania has direct object -> object collisions, meaning badniks can walk over collapsible terrain, stand on moving platforms and other things, meaning the object engine would need to be reworked a bit to handle this.

  7. Sonic Mania uses a completely different level format compared to the classic games, with each tile having it's own separate collision array, 4 angles for each side of a tile, and a whole byte just for collision types, so the collision handler would need to be reworked.
In all honesty, it might be best to just make a brand new engine that fully uses every corner of the Saturn hardware, then make some reference to Mania's object system during implementation (Wouldn't suggest a direct copy over as from the looks of it Mania has it's own memory allocation system, and the last Saturn Sonic game to have memory allocators ended up running poorly...)
 
Last edited:
How would you get the individual sprite frames out of the sprite sheets without texture coordinates? They're not stored like your typical sprite sheet on the Saturn where each frame is it's own individual image concatenated together. It's one giant 512x512 image with all the frames stored in it:
View attachment 10402View attachment 10403

At the very minimum we'd need to rework these to be in a format that can actually work on Saturn. You could possibly do software texture coordinates on the CPU to cut each frame out and send to VRAM, but that could add a lot of unnecessary overhead on the CPU.
A simple conversion script should do the trick, read the UV file, grab the sprite frame in a raw index-bitmap format, correct the width to the closest 8px, append the data to some file, and keep track of it's offset, width and height in another (already have a basic C BMP -> Saturn graphic converter, might rework into something like this later!).

The bigger issue would be coming up with a good scheme to have keep minimal amount of graphics loaded at one time. The minimum needed at one given time is running, spinning, idle and some miscellaneous poses, which could remain fixed in memory. Other animations like bubble grabbing, latching, and 360 ones are level/object specific, and could be loaded in during some extra cycles in a frame whenever the object that would enable this animation gets loaded in, which would definitely require some dynamic graphic allocator, but it's a system Sonic 3 (kind of) uses it's object graphics.

In terms of compression, I'm not sure if sprite parts would be all that of a viable option, as the animations themselves are quite fluid compared to the original games, with little crossover with sprites with anything but a few head poses, the most that could really be done is RLE possibly some LZSS compression combined.
 
Last edited:
A simple conversion script should do the trick, read the UV file, grab the sprite frame in a raw index-bitmap format, correct the width to the closest 8px, append the data to some file, and keep track of it's offset, width and height in another (already have a basic C BMP -> Saturn graphic converter, might rework into something like this later!).

The bigger issue would be coming up with a good scheme to have keep minimal amount of graphics loaded at one time. The minimum needed at one given time is running, spinning, idle and some miscellaneous poses, which could remain fixed in memory. Other animations like bubble grabbing, latching, and 360 ones are level/object specific, and could be loaded in during some extra cycles in a frame whenever the object that would enable this animation gets loaded in, which would definitely require some dynamic graphic allocator, but it's a system Sonic 3 (kind of) uses it's object graphics.

In terms of compression, I'm not sure if sprite parts would be all that of a viable option, as the animations themselves are quite fluid compared to the original games, with little crossover with sprites with anything but a few head poses, the most that could really be done is RLE possibly some LZSS compression combined.
Yes, a script could get the individual frames out and align them, but we'd probably need to do more work than that to get everything to fit in RAM. Don't forget you'd also have to modify the binary data that defines the sprites and animations to work with the new graphics format that doesn't use texture coordinates.

Loading animations in off the disc wouldn't really be viable. It would be way too slow to keep up with the game running at 60fps. We'd need to have all the sprites in RAM somewhere and then copy frames over to VRAM when needed. Sonic's sprite alone at 8bpp without compression would require more RAM than we have on a stock Saturn. So something would need to be done get that all to fit in RAM, either compression, breaking the sprites down into smaller chunks to remove duplicate frame pieces, lowering the color depth to 4bpp, or all of the above.
 
Yes, a script could get the individual frames out and align them, but we'd probably need to do more work than that to get everything to fit in RAM. Don't forget you'd also have to modify the binary data that defines the sprites and animations to work with the new graphics format that doesn't use texture coordinates.

Loading animations in off the disc wouldn't really be viable. It would be way too slow to keep up with the game running at 60fps. We'd need to have all the sprites in RAM somewhere and then copy frames over to VRAM when needed. Sonic's sprite alone at 8bpp without compression would require more RAM than we have on a stock Saturn. So something would need to be done get that all to fit in RAM, either compression, breaking the sprites down into smaller chunks to remove duplicate frame pieces, lowering the color depth to 4bpp, or all of the above.
You could also splitting the sprite into 2 separate 4bpp sprites, having the skin and shoes on one and the rest on the other, you could probably save 5 - 8 lines worth of color depending on the frame (and whatever many lines you'd also remove with sprite pieces). Reducing the color palette would end up removing quite a bit of detail, and you would need some people helping out with cleaning up the sprites, some sprites might look fine while others are a lot more noticeable.

1780173824928.png
1780173924046.png

You might be able to get away with having most animations compressed while there not utilized in VRAM, and un-compress them on the fly with the SH2 sub-CPU, and depending on the type of animation (i.e. if it's not the kind of animation to only happen once in any given moment) keep them in some cache incase it's needed again (although that might be a bit overkill)

One thing that should also be considered is how much RAM would the game actually need to run, so lets try with a guesstimated example;
  • Our average total amount of 8bpp sprites equates to about 3 512x512 pixel pages (768 KB)
  • 1024 16x16 8bpp tiles (without equating 8x8 duplicates, < 256 KB)
  • Tile collision data (1024 * (16 nybbles for height + 2 byte line enables + 4 byte directions + 1 byte collision type, 23 KB)
  • PCM sound (if mostly compressed and half being their FM counterparts, ~72 KB)
We can take out tiles from the equation, we can ship them off to the VDP2 and write over our copy in work RAM, you could also do this with some of the SFX, so we'll say that cut's that down around 32 KB, so in total lets say we're looking at around ~831 KB of loaded data in work-RAM. Considering the fact that I've definitely missed something and low-balled the guesstimate, I'd say that's the minimum, and the max could easily be ~1.2 MB or higher, which would leave one Work-RAM bank maxed out and the other with 4/5th's of memory left for program code, constants and the stack.

From the top of my I can think of a couple of solutions or altercations that could be made to help with this:
  • Use a heightmap lookup table to remove duplicates (a good portion of tiles are either full solid blocks or completely blank)
  • Use a memory expansion cart (Viable, but I'm not sure how common these are for people wanting to play on real hardware who don't have one already)
  • Some graphics like HUD elements could be permanently written into VDP1's RAM (but could waste extra space that might be necessary)
  • Push lesser-used sprites into any kind of any unused portion of R/W RAM (Would be really slow, and a pain to work with)

If there's one thing for certain, it's that it's gonna be a hell of a thing to properly demake this game...
 
You could also splitting the sprite into 2 separate 4bpp sprites, having the skin and shoes on one and the rest on the other, you could probably save 5 - 8 lines worth of color depending on the frame (and whatever many lines you'd also remove with sprite pieces). Reducing the color palette would end up removing quite a bit of detail, and you would need some people helping out with cleaning up the sprites, some sprites might look fine while others are a lot more noticeable.

View attachment 12669View attachment 12670
You might be able to get away with having most animations compressed while there not utilized in VRAM, and un-compress them on the fly with the SH2 sub-CPU, and depending on the type of animation (i.e. if it's not the kind of animation to only happen once in any given moment) keep them in some cache incase it's needed again (although that might be a bit overkill)

One thing that should also be considered is how much RAM would the game actually need to run, so lets try with a guesstimated example;
  • Our average total amount of 8bpp sprites equates to about 3 512x512 pixel pages (768 KB)
  • 1024 16x16 8bpp tiles (without equating 8x8 duplicates, < 256 KB)
  • Tile collision data (1024 * (16 nybbles for height + 2 byte line enables + 4 byte directions + 1 byte collision type, 23 KB)
  • PCM sound (if mostly compressed and half being their FM counterparts, ~72 KB)
We can take out tiles from the equation, we can ship them off to the VDP2 and write over our copy in work RAM, you could also do this with some of the SFX, so we'll say that cut's that down around 32 KB, so in total lets say we're looking at around ~831 KB of loaded data in work-RAM. Considering the fact that I've definitely missed something and low-balled the guesstimate, I'd say that's the minimum, and the max could easily be ~1.2 MB or higher, which would leave one Work-RAM bank maxed out and the other with 4/5th's of memory left for program code, constants and the stack.

From the top of my I can think of a couple of solutions or altercations that could be made to help with this:
  • Use a heightmap lookup table to remove duplicates (a good portion of tiles are either full solid blocks or completely blank)
  • Use a memory expansion cart (Viable, but I'm not sure how common these are for people wanting to play on real hardware who don't have one already)
  • Some graphics like HUD elements could be permanently written into VDP1's RAM (but could waste extra space that might be necessary)
  • Push lesser-used sprites into any kind of any unused portion of R/W RAM (Would be really slow, and a pain to work with)

If there's one thing for certain, it's that it's gonna be a hell of a thing to properly demake this game...

Your calculation for uncompressed sprite data is off. Sonic alone requires 4 512x512 8bpp sprite sheets for all his frames of animation. That alone would be about 1MB of data. But we also need to have enough space for Tails since the game also has a Sonic and Tails mode. That would add about another 512KB. So we're at 1.5MB of RAM used just for Sonic and Tails sprites, we haven't gotten into the enemy sprites or the the common entity sprites like rings, text, HUD, etc.

So compression is a must for the sprites. If we had to go down the road cutting sprites down into pieces to get to 4bpp, then I think the best bet would be to take a page out of the way the Genesis stores it's sprite data and break them down into 8x8 4bpp tiles. That hopefully would allow you to go to 4bpp without losing detail and might cut down the sprite data by eliminating duplicate 8x8 tiles. Then of course the game would need to be modified to work with this kind of sprite data.

The main executable would also need to be broken up into overlays if the program is to have any chance of fitting in RAM. Probably the best starting point would be to try modifying the PC version of the game to prototype out these ideas and see how it works.
 
Your calculation for uncompressed sprite data is off. Sonic alone requires 4 512x512 8bpp sprite sheets for all his frames of animation. That alone would be about 1MB of data. But we also need to have enough space for Tails since the game also has a Sonic and Tails mode. That would add about another 512KB. So we're at 1.5MB of RAM used just for Sonic and Tails sprites, we haven't gotten into the enemy sprites or the the common entity sprites like rings, text, HUD, etc.

So compression is a must for the sprites. If we had to go down the road cutting sprites down into pieces to get to 4bpp, then I think the best bet would be to take a page out of the way the Genesis stores it's sprite data and break them down into 8x8 4bpp tiles. That hopefully would allow you to go to 4bpp without losing detail and might cut down the sprite data by eliminating duplicate 8x8 tiles. Then of course the game would need to be modified to work with this kind of sprite data.

The main executable would also need to be broken up into overlays if the program is to have any chance of fitting in RAM. Probably the best starting point would be to try modifying the PC version of the game to prototype out these ideas and see how it works.
Most if not all of the animations in the second character sprite sheets relate to zone-specific animations (aside from the victory animations), so those could be split off into separate files on the disk and loaded into RAM during level boot. The other half of Sonic's sheets is just the super variants, which you could load in from disc while the transformation animation is playing or once the player reaches 50 rings whence they have all the chaos emeralds. There would be lag when loading the regular form back once the ability has ran out, but I it's a fair tradeoff from having to use 2x more memory than needed (I mean, Sonic CD halts for a few seconds between bosses, speedup, and invincibility because of the music alone!).

Objects would take up around 2 1/2 512x512s, considering the fact that the few global and level specific sheets we need are usually 128px or 256px in width or height, and contain a whole lot of blank space which won't exist once converted. I did pretty much forget about tails lol, so in total you'd have somewhere around 3 1/2 to 4 512x512's in RAM at once, most of which could easily be just compressed data, loaded in JIT via the sub-CPU.

I don't think using 8x8's is going to be all that efficient, considering you're going to need the overhead of assembling the sprites together, loading each tile off to the VDP1 with it's own draw call. Plus if it's only being done for the sake of more colors, then you're going to need duplicates of the same colors in different combinations in order to really pull it off, which could eat into other necessary palette data. You'd be better off taking a page from the NES and just overlaying the extra colors needed with another sprite.
 
Having a pause of over 1 second every time the player transformed into Super Sonic would not be an acceptable compromise at all, especially considering we'd also be streaming music off the disc. Players would probably avoid getting Super Sonic all together if we did that.

As for 8x8 tiles being inefficient, you do realize almost all your older systems worked like this for their sprites right? Go look at just about any 16-bit game, you're going to see all the sprites are made up of smaller sprites. If you look at the Saturn ports of Sonic 1-3K you'll see they're doing the same thing, the sprites are all actually made up of smaller 8x8 sprites. Most of Capcom's CPS1 and CPS2 ports on Saturn also do a similar thing where the sprites are actually made up of smaller 16x16 sprites. And all those games maintain performance just fine. VDP1 should be able to handle it and the SH-2s should be more than capable of keeping up with it. It wouldn't be done for the sake of more colors, it would be done to eliminate duplicate data in the sprite sheet and possibly allow you to go down to 4bpp. I don't see how that would eat into palette data as you'd still only have the ~20-30 colors the original sprite sheets use.

The other thing to keep in mind is if the game does anything that would require gouraud shading or half-transparency. 8bpp wouldn't work for sprites in that case as we can only do those effects on Saturn with 4bpp CLUTs or 15-bit RGB textures.

But again this idea is only something that would need to be explored if we determined compression alone wasn't good enough to get everything we'd need in RAM.
 
Last edited:
Back
Top