Soulstar – Under The Hood – Part 1
Since there is some interested, I decided to write some blog posts about one of my old games a Mega-CD game named Soulstar.
For anyone who doesn’t know about the Mega-CD, it was a CD add-on to Sega’s Megadrive which also added some new hardware. First, it added more RAM and another 68000 (Sub) CPU, one clocked at 12.5Mhz. It also added a scaling and rotation chip, one I do believe was derived from Sega’s arcade hardware. Another sound chip was added too, but my attention was drawn to the new graphics chip. The Sub CPU had an additional 512K of RAM, while the new graphics chip had 256K of Word RAM (WRAM), usable in one of two modes: 1M mode split the WRAM into two banks of 128K, one accessible by the Main CPU while the Sub CPU accessed the other bank. 2M mode gave either the Main CPU or the Sub CPU full access to the WRAM, and was the mode used by the new graphics chip.
Before Soulstar, the other games I’d coded for the Mega-CD were Jaguar XJ220 and Thunderhawk (Thunderstrike in the US). Jaguar XJ220 was my first game for the Mega-CD, a version of the Amiga game (also coded by me). Being new to the Mega-CD, I ran some tests of the new hardware and discovered I could render scaled sprites faster in software than in hardware! I used a special memory mapping mode where bytes could be written to a 256K memory range that corresponded to a 128K nybble version. Quite handy, as CPUs generally don’t like messing about with nybbles when storing bytes is so much easier, simpler, thus faster! So Jaguar XJ220 was coded, and I think it turned out pretty good! I could build an image of the screen using the WRAM on the Mega-CD side, then flip the WRAM over to the Megadrive side so the image could be DMA’ed into VRAM.
[image error]Jaguar XJ220 – All sprites are software rendered.
It was only afterwards I discovered there was a mistake in my timings, one meaning the hardware was actually faster than my software routines… Oh well, live and learn…
As for Thunderhawk, my first thought was to make the game a port of the Amiga version, so rendering everything as polygons. I already had a Megadrive port of Thunderhawk, (one put on hold so I could code the Mega-CD jaguar XJ220). Problem with the scaling/rotation chip was it could only render 3D in one direction, making it impossible to render a floor and “bank” it.
But then I had an idea, a rather crazy, wacky (perhaps even brilliant) idea. If I overdrew the screen vertically, then when copying the screen from WRAM to the Megadrive side, if I copied the screen as vertical strips, I could offset each strip vertically, thus shearing the whole screen! Okay, so not quite a full screen rotation, but good enough for a game! (This is the reason Mega-CD Thunderhawk doesn’t bank very much).
[image error]No sprite rotation here, just vertical/horizontal shearing!
Since the whole screen was basically a bitmap, the whole thing had to use one palette of 16 colours, the sky being on a separate playfield. I didn’t actually rotate any sprites for Thunderhawk; with the whole screen being sheared vertically, to simulate sprite rotation all I had to do was shear all the sprites horizontally. Worked out pretty good, and fooled a lot of people!
So that was Thunderhawk, my first proper use of the new hardware.
One of my favourite games was the arcade game Galaxy Force II. I can remember the first time I was that and was wowed by how the background scales throughout the first level, to the point you end up flying into a tunnel entrance! I always wanted to code a game like that, but there didn’t exist any hardware outside an arcade that could replicate anything like that.
Until the Mega-CD came along.
Once Thunderhawk was complete, I so wanted to code a space game like GF-II. Along with my Italian artist friend, we set about designing such a game. The result was Soulstar.
For the new game, I had to push things as far as possible. Thunderhawk used a bitmapped screen of 16 colours, with a 16 colour background. But for Soulstar I wanted to use all the Megadrive’s palettes. The Megadrive had 4 palettes of 16 colours. Sprites and characters could use any of the 4 palettes, so I decided early on the only way to get more colours on screen was to use hardware sprites.
The Mega-CD’s graphics chip worked by rendering a rectangular block arranged in the same pattern as hardware sprites. The destination rectangle was rendered one line at a time, each line given a start position and delta to trace across a source image. The source image was a map made of blocks (which were described in the manual as “stamps”). Stamps could be either 16×16 or 32×32 pixels, and were indexed by an area of WRAM known as a “stamp map”. The stamp maps could be either 16×16 (with 16×16 stamps) or 8×8 (using 32×32 stamps). Whatever, the pixel size of the map was 256×256 pixels.
Sprites in the game were built from the stamp maps and rendered into WRAM to form hardware sprites for the Megadrive to display. A hardware display list was also built, up to a maximum of 80 sprites, the Megadrive’s display limit. The game did suffer from sprite dropout at times when the screen became busy, either by exceeding the limit on sprites per line, or the maximum limit. Since hardware sprites were allocated front to back, only sprites in the distance were lost first.
One trick I did use was to do deal with sprite popping. I built several depth-fade tables, each table blending bit-by-bit into a single colour; for space this was black, but for some planets (like the surface of Guha), this was the surface colour. This meant I could fade the sprites into existence. Now, I couldn’t use the hardware to do this, so instead I first rendered the sprites into WRAM, then used the CPU to modify the data afterwards. Since I usually only applied this to distant sprites (typically the last 8×8 sprite), it didn’t take much CPU time to do this.
I think the end result was quite pleasing:
[image error]Showing the software depth-fading of hardware sprite data.
I used the same trick on the landscape, as you can see in the above image. Again, the ground was rendered into WRAM using the hardware, then the CPU modified the top few lines of the data to fade the ground into the distance. As you can see, I used different tables for different sprites; the ground objects blend into a sandy colour, while the sprites in the sky are blending into a much darker colour, one that blends with the sky.
Here’s another example, inside the Warpship:
[image error]Warpship interior – note the floor fading into the distance.
You can clearly see the background fading into the distance.
Before I go any further, thought I’d mention another aspect of the game. On the linear sections, the game was synced to the music. As the music played, I could read the current time code, thus keep the scrolling in sync. It wasn’t precise, but it didn’t need to be; if the game lagged behind, the ground scrolling would speed up to catch up, then slow down once it had caught up. We designed all the linear levels to be in sync with the music. to do this, we first worked out all the attack patterns in terms of time, then gave Nathan McCree (our brilliant musician) all the times so he could work his magic. I have to say, the music to Soulstar is awesome. I still listen to it from time to time.
Where possible, I used standard Megadrive playfields to do the background, purely to reduce the amount of data that had to be DMA’ed to VRAM. There’s a finite amount of bandwidth on the DMA, so the method I used was to render the data on the Sub-side, flip the WRAM from Sub-side to Main-side, copy the necessary data into the Megadrive’s scratch RAM, then flip the ram back to the Sub-side so it could render the next frame. While the next frame was being rendered on the Sub-side, I could DMA transfer the data from Scratch RAM to the Megadrive’s VRAM over several video frames. VRAM use was double-buffered to prevent glitching.
I used several tricks to minimise the data, so I’ll detail these in the next part, going over each level and explaining all the tricks used.


