This is a somewhat technical post, so look at the pictures if you're only interested in the good stuff!
Scorched Earth Clone
Anyway, I decided to have a bit of a play, and learn C89, along with 65c02 assembly, and how the VERA works. I thought a GORILLA.BAS/Scorched Earth clone would be a fun challenge:
All the recordings in this post are *real-time*
It was a great way to learn, I was forced to write some parts in assembly, because C code is just way too slow for any graphics. It's really just a proof of concept. I have bigger plans
Features include:
- 4-bit 320x240 mode Layer 0 Bitmap, Layer 1 Text, and Sprites
- Custom Font (I ripped from Sierra SCI Engine)
- Animated explosions
- 10 Procedurally generated levels
Sierra AGI Interpreter
Whilst that was fun, I had my sights set on making a Sierra AGI Interpreter for the system. I've been apart of the "Sierra modding" community since 1997, before we had even completely reverse engineered the format of AGI. Check out my profile on the sciprogramming forum: https://sciprogramming.com/community/index.php
To my surprise Manannan had already begun to make one as well. Theirs appears to be based on Lance Ewings interpreter (MEKA). However, I have different goals in mind, so I continued to develop it. I again learned a LOT more about the system, including the memory limitations. My code is 32kb, pretty much maxing out the available code space, and I'm not even finished yet! I've done all kinds of tricks to minimise memory usage:
- reduce stack size
- utilise memory at $400 for lookup tables
- inline a lot of one time code
- convert "All the things!" to assembly!
- Full resource loader (any resource from version 2 games) - resources are loaded into a simulated "Heap" space in banked ram.
- Relatively fast pic (background) drawing routines - probably close to the Tandy or 8088 version speed (faster than the Apple II)
- Text display, menus, and other text functions
- Sound routines (all 3 voices and noise channel on the PSG!) It sounds great - I'll try to upload a sample, just gotta work out how to record it and find a place to upload.
- about 50% of Logic opcodes implemented before I ran out of space.
Currently I'm optimising the hell out of it (I know you shouldn't optimise early) to try to squeeze out more space in RAM.
Still to do are:
- Views (sprites) - I will use the sprite layer. I'm thinking each view will have two sprites: 1 for the visible part, and 1 for a "Z-buffer". As the sprite is moved, it will update the buffer and draw as needed, drawing in front or behind based on the priority screen.
- Input controls
- Remaining opcodes. Some are system specific so can be left out, but there's quite a few that I haven't yet implemented.
- Version 3 games (later games, Gold Rush, Manhunter 2, etc)
I've uploaded my work in progress here: https://github.com/cosmicr/astral_body
Another World
My AGI interpreter is going ok, but it will continue to be a challenge to get it all in less than 32k. I'm not sure I'll be able to complete it. Plus Manannan has made much better progress on their version than me anyway.
I'm a big fan of the Amiga 500 game "Another World". I knew that it had been reverse engineered and documented quite well. So that's my current project. Actually, there isn't much documentation on the formats of AW - more on that below. The game code is a lot simpler than AGI, with fewer instructions and simpler opcodes. I already have 99% of them implemented (mostly).
But where the opcodes are simple, the graphics system is quite the opposite. It seems that one of the goals of the original version was to cram as much data into the files as possbile. The compression format is an archaic type called "bytekiller". A500 afficionados would probably scoff at me, but I had never heard of it. I managed to reverse engineer it based on some code and have now documented it. The decompression on the CX16 is quite slow (it's written in C) so I've actually preprocessed the datafiles and decompressed everything. However if you want an authentic experience it does work. The next thing is the graphics use a LOT of bit manipulation to handle how the polygons are drawn. The graphics in Another World are all polygon based (except for text). Here is a good explanation: https://fabiensanglard.net/another_worl ... index.html. There's two things that stand out to me:
- The actual file formats of the graphics aren't discussed - that's because they are COMPLICATED! The polygons are setup as immediate polygons to be drawn, or polygon groups. These are set by bit flags in the files. Sounds simple enough. Except the logic behind which bitflags are used make no sense at all. It seems like the original author (Eric Chahi) might have had plans to expand the engine. As an example, if bit 6 and 7 are set then a color is defined on an immediate polygon by the lower 6 bits, but if only bit 7 is set then the color is inherited by it's parent, but if bit 6 or 7 isn't set and bit 2 is, then the next polygon is a group??? Very weird and confusing. This sort of stuff is all through the data formats.
- The game uses 4 pages of screen buffers. This is a HUGE problem for the Commander X16. I have been able to absolutely max out the VERA RAM with 4x 32000 bytes. Seems simple enough right? It's only 128000 bytes and the VERA has 131072 bytes(128k) right? Except that some of that memory is reserved for VERA registers (640 bytes), and then you need some memory for text mode, and the text character set, and all of the sudden there's not enough. Also memory space for layers in VERA RAM is only given in 2kb blocks, which 128000 does not fit into neatly. I ended up sacrificing text mode and layer 1.
The polygon filling routine is a scanline routine which I copied from other implementations of the game, which was a pain because they are all 32-bit or higher. It uses fixed point maths to calculate the stepping along polygon edges. At the moment it's very slow because it's in C. I'm going to see if it might be fast to use the VERA FX, but I feel like the setup code time reduces the advantage gained by the extensions. There is heaps of room for optimisation
At the moment you can see there are several issues. But it's working. It's about 0.5 frames per second. The game uses "dirty buffering" combined with double buffering. The double buffering is slow because no DMA. The dirty buffering will be quite fast once I have optimised the polygon filling. Dirty buffering is when it copies only the part replaced from behind the polygon, rather than the whole screen. With a lot of optimisation I reckon I could get it to about 10fps (at most). If I have to I may end up reducing the resolution. Currently it's at the original 320x200 res but with double pixels.
Features implemented so far:
- Every opcode, bytecode loading
- Game data loading and unpacking (decompression).
- Palette loading
- Polygon loading and rendering (about 80% implemented - need to do single pixel plotting)
- Bitmap loading and drawing (not sure where it's implemented in the bytecode, but the data is there)
- Transparency (fairly easy to do, just haven't got around to it yet)
- "Dirty buffering" - I don't know what the actual term is. Also fairly easy.
- Player controls.
- Sound and Music
Sierra SCI Interpreter
The SCI Interpreter ran on the same specs as the AGI Interpreter, but had enhanced graphics and sound. I don't see any reason why it couldn't be done. SCI Games are the EGA higher resolution era games, such as Space Quest 3, and Police Quest 2. I will set my sights on it soon. I have already had a play with the picture resource format, and it's very similar to the AGI one. The main differences are in the bytecode - whilst AGI is interpreted, the SCI system is a full Virtual Machine. It uses a object oriented system similar to SmallTalk from the 70's/80's. Views (sprites) are similar to AGI, and music is similar to midi which could be translated to use the YM2151 or at worst the PSG. The resources are larger, so memory management would be even trickier, especially since the VM is expecting things to be in specific locations.
Future Plans
I've been really enjoying my experiments with the CX16, and trying to port my favourite engines. I like to think I've gotten pretty good at understanding the system in the last 4 months. I'd also be interested in doing a full original project too. But I'm not very creative, and suck at drawing too lol. I'll probably look at other old game engines from the DOS era and see what I can do.
If anyone wants to know any more about what I've shown here, feel free to ask. I reckon the more we share and get people learning the more good content we're likely to see.
I'll post an update again after I've made more progress!