A simple 3D demo for the Sega Master System and Game Gear.
The zip archive contains three binaries - one for Game Gear, one for Master System (normal) and a variation for the Master System (supports the 3D glasses).
3D Master System version displayed as a stereo pair.
3D Master System version displayed as an anaglpyh.
The Game Gear version has a lower resolution display but takes advantage of the improved colour depth.
The 3D glasses version displays in real 3D on an emulator equipped with 3D glasses. Some emulators have modes that can be used to simulate this effect, be it an anaglyph mode (red/green 3D specs) or a stereo pair mode.
I've tested the Game Gear version on hardware, and the SMS version on the Game Gear's SMS compatibility mode.
Pressing  advances to the next 'model'. Pressing  freezes rotation. Direction pad can be used to adjust the rotation speed.
Working emulators (in no particular order):
- Kega Fusion
- Dega (corrupted background, small sprites).
Source is, naturally, included.
Thanks and greets to the following (again, in no particular order);
- Charles MacDonald
- All the SMS Power! regulars
- Z80 Bits
- #gamedev/#tcpa regulars
An earlier version had a slightly different palette and had a static background image.
- Early video - lower precision arithmetic causes jerky, popping sprites (WMV).
- Later video - smoother movement and large sprites (WMV).
This is in the off chance anyone is interested in what this demo is attempting to do. (I used a lot of homebrew released when developing my SMS emulator!) I don't really use comments... (I'll admit the code is very ugly).
The background is the easy bit. That's a simple plasma-by-palette-shift job, writing out a whole new palette by shifting it all downwards and adding a new colour (using trig to get the R, G and B elements for smooth changes) at the top end.
The only oddity, and possible reason it doesn't work in DEGA, is that the background resource file only holds the top-left corner of the background pattern (see the .GIF files). The program then mirrors this twice, first vertically then horizontally. It reads the data back from the VDP then writes back out to it, storing the read data in a temporary buffer for the vertical flip and on the stack for the horizontal flip. It also flips the tile flip flags to mirror properly.
The 3D blobs in the foreground are done using brute force; no precomputation is used beyond the trig tables. The transformation is:
SinRotX = Sin(RotX) SinRotY = Sin(RotY) CosRotX = Cos(RotX) CosRotY = Cos(RotY) rX = (x * SinRotX) + (y * CosRotX) rY = (x * CosRotX * SinRotY) - ((y * SinRotX * SinRotY) + (z * CosRotY)) rZ = (x * CosRotX * CosRotY) - ((y * SinRotX * CosRotY) - (z * SinRotY))
(Now we have a rotated x, rotated y and rotated z from the original x, y, x).
At this point a crude insertion sort on z is performed to arrange the points into front→back order and the rotated point is stored in the output buffer along with its correctly sized and coloured blob sprite number.
$6800 is divided by rotated Z, and the result is multiplied to rotated X and rotated Y to get the translated-to-screen coordinates after having an offset added to centre them on the display.
If we're in the 3D glasses mode, the translation to screen is performed twice, with the rotated X being given an offset to the left for one eye and to the right for the other, and a constant is added to the '2D' coordinate to shunt the point back to the centre of the screen.
The vblank interrupt handler is used to check if we have newly transformed points to display (and to cycle the background palette, if needed) in 2D mode, and to flicker between left and right eyes in 3D mode.
There are two pointers - a write pointer which points to the buffer that we're filling with new point data, and a read pointer which points to the buffer that holds the point data for the sprites on-screen at the moment. In 2D mode the read pointer is cleared once the sprites have been copied to the display to reduce redundant writes, but in 3D mode this luxury is not available to us.
That's about all I can think of off the top of my head.