Tuesday 7 September 2021

Galaxian Part 7 - Preliminary Impressions

Whilst I've been waiting for Miro to digest the previous posts and hopefully develop his framework to the point I have described, I've actually been doing a little bit of the transcode. I'm not going to go into any specifics here as I'd like to document it in some form of ordered fashion, but I will make a few observations, if for no reason other than hinting that I haven't yet abandoned the project.

If there was ever any shadow of a doubt that Scramble was based on the Galaxian codebase (and there really wasn't), it is beyond question in my mind now.

It of course helps that Scott Tunstall reverse-engineered both games - and hence the disassemblies use common terminologies and labels - but there are plenty of instances where those identically-named variables actually share the same address in both games.

Despite having transcoded only a handful of routines thus far, I've already encountered common code. And it's very clear that both games also share the overall architecture of the code. It's an absolute certainty that Scramble code was derived from the Galaxian codebase.

Now that bodes well for the project. Aside from the obvious advantages that a familarity with the architecture presents, I can also say with confidence that the assembler code lends itself very nicely to a higher level implementaion. And that's certainly not true of all assembly code.

And touching on the subject of process I discussed in Part 5, I'm happy so far with how things are turning out when preserving the original assembly code interleaved with the C code. During the course of this blog I'll be posting examples to illustrate various aspects of the transcode, and you can make your own mind up, but I think it adds more than it detracts from, for example, the 'cleanliness' of the higher level source file.

At this stage of the transcode, particularly given the architecture of Galaxian, there is a lot of tedious typing to be done; defining functions and their prototypes, adding variables to the working RAM structure, defining tables etc. I'll likely press on with this aspect of the transcode whilst waiting for Miro, so I can't at this point say when I'll post the next blog entry.

Thursday 2 September 2021

Galaxian Part 6 - Verifying the framework

Before we start on the transcode proper, it would be prudent to test the display output portion of the framework, as this is what we will be using to verify the transcode itself. The purpose is to verify the conversion of the graphics palette, tile and sprite data, the ability to display tiles and sprites, and that the correct output is displayed from the tile memory and attribute areas. Correct output from the sprite registers would also be nice, but is also slightly more complicated and not critical at this point.

First step is to simply dump the tiles and sprites to the display, using the same mechanisms that the ported game will employ. For my Allegro prototype platform, that's copying a region of my sprite sheets for each of the 256 8x8 tiles or 64 16x16 sprites from a memory bitmap to the display. The output for Galaxian looks like this:

Galaxian Tiles and Sprites

Next step is to render a display directly from the Galaxian tile memory (character RAM or CRAM at 5000h) and tile attribute memory (object RAM or OBJRAM at 5800h). Note that the OBJRAM also contains the sprite registers, so these could also be rendered. This is essentially implementing the function that will update the Galaxian display as the game is running, and requires detailed knowledge of the CRAM and OBJRAM structures and mappings; an exercise I'll leave to the reader.

We of course need some (sensible) data in the CRAM and OJBRAM memory blocks, and the easiest way to do this is to run MAME with the debugger enabled, invoke the debugger at an aesthetically interesting point in the game, and SAVE the entire Z80 address space to a file. Then it's simply a matter of reading the binary dump at startup, copying the RAM and OBJRAM areas to suitable buffers if required, and calling the display routine. You should see something like this:

Eye candy before we've even started!

I think the only sprite visible (active) in this dump was the player's laser atop the ship - it's not visible here for reasons unknown at this point. But quite obviously this is pretty close to the actual output, although there will be further enhancements required to the display routine later in the process.

Now we can be reasonably confident that once we implement any code that writes to CRAM and/or OBJRAM, it will be faithfully rendered on the host platform display. Take a good look now, because it's likely going to be quite a few weeks before we see anything like this particular output again!

And that's it for the preliminary work. Next up is to start the actual transcode. No better place to start than the Z80 reset address, 0000h, which we'll implement in the galaxian () function called when the framework has been initialised and we're ready to execute the game.