Sega Master System / Mark III / Game Gear|
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew
alternate color sprites on SMS?Posted: Wed Jul 13, 2022 6:24 pm
Hi everyone. This is Mike from BitBeamCannon and we make Youtube videos about pixel art, retro systems, and indie game dev.
We were recently asked a great question on our "Forensic Pixology" video featuring the Sega Master System. (A system I have very fond feelings of)
Here's their question:
" I've been staring at Wonderboy 3 footage trying to work out how they approach palette swapping for the enemies to get colour variants on the same enemy artwork. The SNES approach to this is intuitive, each sprite could reference one of 16 palettes. But the SEGA Master System just had one palette for sprites, one palette for backgrounds. So far all I can tell (in Wonderboy 3) is you never see the same enemy sprite on screen with more than 1 colour variant. So in the desert you may see a green snake and a blue antlion on the same screen together, but never (for example) a green snake and a blue snake together. There is always a scene change before you get a different colour variation on the same enemy.
I thought they might have a few clusters of pixel shades reserved for enemies to use different clusters but they would have to plan this ahead of time and know which enemies they wanted to appear together, eg. snake uses cluster 1 and antlion uses cluster 2, so they can write new colours to those clusters on a scene change. But it seems wasteful and would require a lot of careful planning..."
Here are my thoughts so far:
While each 8x8 background tile can be set to use either 16 color palette, it's true that sprites can only be displayed using the second set of 16 colors (indexes 16 through 31)
So, to have the same enemy display in different colors, here are the options I can think of:
- For enemies that don't need to move around screen, or if you don't mind them moving in 8 pixel increments, you can display them as tiles instead of sprites, thereby letting you pick which 16 color palette to use per 8x8 tile.
- Although cartridge memory back then was very costly and limited, work-hours were also costly, especially back then with hyper-primitive pixel art tools. so it's possible the art was literally on the cartridge for each color variant, BUT there is a much better option, which I'm about to mention.
- Any system, including the SMS is capable of manipulating graphics data (or any other kind of data) with its processor, and therefore, you could use logic to replace any color with any other color in the memory that holds the graphics data for any tile or sprite. This world by its nature force ALL instances of that particular sprite (enemy for example) to display with these new colors until either you re-load the original graphics directly from the cartridge or you use logic to once again replace colors with other colors.
I believe and hope they used option 3, because it's pretty bad-ass!
Do any of you SMS hardware masters have any other thoughts or did I get anything wrong?
We'll likely make a new video on this topic after we've had a chance to hear back from you all.
Here's our SMS video which spawned this great question:
||Posted: Wed Jul 13, 2022 8:32 pm|
You could look to the contemporary competition for ideas. Draw your enemies in 2 bits per pixel, and make a routine that expands them from 2bpp to 4bpp when copying them to VRAM. I've written a couple different BPP expansion routines that take a horizontal flip state (identity or flipped) and a color parameter. Then to have the same enemy tile set use different palette entries, expand the sprite cel into VRAM using different base colors.
One routine, which I've posted to the topic "Sprite loading, flipping, and expansion routines" as "load_2bpp_cel", expands the sprite using a competing console's rules, which provide for four subpalettes (0, 4, 8, and 12).
0: output uses transparency and colors 1, 2, and 3
4: output uses transparency and colors 5, 6, and 7
8: output uses transparency and colors 9, 10, and 11
12: output uses transparency and colors 13, 14, and 15
Another routine provides seven subpalettes and one common color, for a feel more like the competing color handheld.
2: output uses transparency and colors 1, 2, and 3
4: output uses transparency and colors 1, 4, and 5
6: output uses transparency and colors 1, 6, and 7
14: output uses transparency and colors 1, 14, and 15
The same principle can be applied to expand 3bpp to 4bpp, either as 1-7 and 9-15 or as 1-3 common plus 4-7, 8-11, and 12-15. You can mix and match, such as having the player character in 1-7 (with 1 the common outline color), the player's projectile in 6-7, and enemies in 8-9, 10-11, 12-13, and 14-15.
There are two paradigms to load sprite animation cels into VRAM: load them before the scene starts and park them there, or stream each cel into VRAM right before it is displayed. Streaming makes more sense on SMS than on a competing platform because SMS and GG VDP accepts writes to VRAM at any time so long as bytes are spaced at least 28 T-states apart. This gives the loader plenty of time to read, horizontally flip, upconvert, and write each byte while still nearly saturating available bandwidth. Loading a new 16x32-pixel (8 tiles) sprite cel takes between 32 and 40 scanlines' worth of CPU time, so if time is tight, you might want to prioritize different actors to load the next cel. If you really want to get fancy, you could try proactive streaming: predict what cel an actor is most likely to request after the currently displayed one, such as the next cel in a walk cycle or attack animation, to have it already loaded when the actor's movement code wants to display it.
I wrote the above from the perspective of developing new original software for SMS and GG. If you're interested in what a particular commercial game does, you could buy the game, dump it, and play it in an emulator with a VRAM viewer.
||Posted: Thu Jul 14, 2022 7:48 am|
as sprite palette can be redefined (it's 16 colors out of system's 64 available) it can simply be that they reserved two colors for enemies (say color 14 and 15 but any would do) and they just redefine the sprite palette at some point? So you have enemies using color 14 and some other using color 15 and you can have them red and green or viceversa or whatever
also of course, as PinoBatch said, ROM assets could be 2bpp (or 3bpp) and 'expanded' to a 4bpp palette in different ways
let's see the ROM...
edit: no, it's definitely loading the same asset twice with different colors, at least observing the loaded tileset for the snakes in the first level. Try using any emulator that shows that, like Emulicious or MEKA.
||Posted: Fri Jul 15, 2022 2:16 pm|
The most important thing to keep in mind is that those games ALL required careful planning to be made.
In the specific case of Wonder Boy III, the sprite palette is essentially fixed for the whole game. The constraint of "number of enemy type per scene" is not due to palette constraint but due to VRAM storage for enemy tiles. I don't recall a reason for the engine not being able to have a blue green and a green snake in the same screen.
Btw, the game engine handle the Yellow variant but it is unused in game (we used it in the remake).
||Posted: Fri Jul 15, 2022 11:05 pm|
|So does it store all three/four times or does it convert the data? Is the data 4bpp or less?|
||Posted: Sat Jul 16, 2022 3:16 am|
Thanks everyone for the fantastic replies and info.
We'll likely make a new video on this topic, and if we do, would you prefer we show your post replies directly (including your usernames here) or not?
||Posted: Sat Jul 16, 2022 6:53 am|
The sprites are uncompressed in the rom and i only found the snake once in red. The graphics are 4bpp.
While a green and blue snake are in VRAM at the same time. The pixel source (offset) is unknown, which i guess is normal when the pixels are changed by code.
The pixel source of wonderboy is known (2e000) and spot-on.
||Posted: Tue Aug 09, 2022 4:40 pm|
We finally made the follow up video on this topic in case anyone is interested in checking it out!
||Posted: Tue Aug 09, 2022 10:05 pm|
|If you want an example of game which changes palette indexes on the fly, there is Knuckles in Sonic 2 for the Mega Drive / Genesis. But I don't want to go off-topic so this is all I'm going to say unless you want me to say more.|