This blog chronicles my progress porting various retro games to other retro platforms. The goal in each project - at least when targeting a new CPU - is to effectively replicate the original graphics and the original code line-by-line, to produce a 100% accurate port of the original game.
I'm starting to get into territory that I haven't fully reverse-engineered yet, which makes debugging the 6809 port just that little bit more difficult. On the plus side, it forces me to understand the original code and therefore I can subsequently go back and comment the arcade disassembly.
Most recently I've been adding the code for thrust and as a result once you start a game, your ship appears and you can move around.
One nuance of porting is the distinction between zero-page accesses and memory accesses. Looking at the original 6502 source listing, there's no indication which is which. On the 6809, all labels for direct page variables are .EQU statements, and the operand prefix is '*'. If you forget the asterisk, the code assembles but doesn't work as planned. Somewhat fortuitously though, the way I have the memory map configured, you'll get stray pixels on the top few lines of the video, and that's easily trapped in the MAME debugger since - atm - Asteroids never renders there (see below).
The other issue I touched on last post is the vertical resolution. After some experimentation in the C port, which is rendering 'vectors' in 1024x1024 coordinate space, I've confirmed that Asteroids uses approximately 788 "lines" of the display space, effectively leaving the top and bottom 118 lines (or 10% each) blank. When you reduce the resolution to 192 pixels, that 20% blank space is quite significant.
Unfortunately 192 doesn't quite divide into 788 nicely, and 192*4 (768) crops the score and copyright messages. The Coco3, however, conveniently has a 200-line mode, which would greatly simplify the scaling (right-shift by 2) and allow use of most of the display. The only issue is that the graphics were, IIUC, originally designed by Norbet for a 192-line display. I'll have to experiment to see if and how they could be adapted for a higher resolution.
But back to porting code for now...
UPDATE: Tonight I ported the code that handles all the collisions. I need to update my disassembly comments in a few areas here, as the routines actually handle all collisions between all objects, whilst my comments suggest it's only the collisions between shots and other objects.
There's a decent chunk of code involved, so not surprisingly it doesn't yet work. Worse yet, I've actually broken what was working before, in the process of 'fixing' a few bugs that I discovered porting the new code. It's too easy to forget that the 6502 X,Y registers are 8-bit vs 16-bit on the 6809...
Looking purely at object (binary) code size, the porting is now roughly 50% complete.
One thing I like about Asteroids is that it's completely deterministic. Each time you turn it on, it will behave in exactly the same way, until you start messing with the controls. Makes it easier to test my ports...
I was looking into why the movement of the first saucer in attract mode was seemingly mirrored on the Coco3 port. With the above-mentioned in mind, it came down to a BIT instruction, followed by a BVS (branch on overflow set) which was branching on the 6502 but not on the 6809. In my haste I (obviously) didn't pay careful enough attention to the descriptions in the 6502 and 6809 Zaks instruction references and decided they operated in the same way, at least as far as the V (overflow) flag was concerned.
Turns out the 6502 transfers bit 6 of the memory operand into the V flag, whilst the 6809 simply clears the V flag. I'm struggling to relate the 6502 behaviour to a real-world operation. Followed by a BVS, the 6502 code is effectively testing bit 6 of the memory operand (which incidentally is one byte of a 16-bit pseudo-random number) without having to load the value first into the accumulator. It of course simply required an extra instruction on the 6809.
Moving on, you can now start a game and (hacked) code to render the player ship is in place. However it turns out that the game simulates the player coming out of hyperspace when the wave starts (to enable the logic that waits for a clear break in the asteroids) and I've yet to code up the associated routines on the Coco3. That'll have to wait for another night.
Starting a game after coining-up
I have noticed, doing the IIGS, C and Coco3 ports, that the scores and copyright messages don't extend to the top and bottom of the screen respectively as the MAME emulation of the arcade game suggests they should. It has puzzled me somewhat, but now I believe I know the answer. The DVG operates on 10-bit coordinates, so I've been basing everything on a 1024x1024 display, and scaling accordingly. And to note, it's relatively easy to scale down to 256x192.
However, I was reading today about an FPGA emulation of Asteroids Deluxe, and it mentioned the vertical display resolution was in the vicinity of 800 (I need to look it up again) which would explain the discrepancy. The issue of course, is that scaling becomes more of a chore, i.e. inefficient. But I do seem to recall that Norbert's scaling was different to mine... so I need to go back and study his again, as well as the MAME emulation of the DVG.
UPDATE: Both the FPGAArcade page and the Asteroids MAME driver suggest the vertical resolution is 788. Note that 192*4 = 768. Damn... can we get away with it though? OTOH the Coco3 does have a 256x200 video mode...
I also did some work on the C port yesterday lunchtime, adding the saucer to bring it in line with the 6809 port. Interestingly it has the same bug - or more accurately the same side-effect - as the Coco3 version, but for a completely different reason!
Firstly, the Apple II/IIGS version is temporarily on ice, but rest assured I will get back to it in the not-too-distant future. The current status is that it's all-but complete - if quite flickery - but I haven't figured out banking for direct page and stack registers yet, which is preventing the use of PEI slamming for the IIGS. I (also) plan on returning to legacy hires mode, and doing an accelerated II/IIC+ version, but this will probably come later.
In the mean time I started on the Coco3 port whilst waiting for some assistance on the aforementioned IIGS issue, and as a result I'm now on a roll and loathe to put it aside. Looking purely at code volume, I'd estimate it's about 30% complete now, with all text, asteroids and saucer rendering complete (saucer movement is a bit off). You can coin-up but not a lot else happens.
Rendering is far from optimal; the aim of the exercise is to complete the porting of the arcade 6502 core with the simplest and smallest amount of graphics data required.
Oh and together with a possible Vectrex port (proof-of-concept at least) I'm also considering a port to the arcade Star Wars hardware - another 6809-based vector platform!
The C port will probably progress in step with the Coco3 port, and they will probably both be used to debug the other at various points. Again, that's probably for Neo Geo and Amiga.
And now for something completely different...
I don't recall exactly how, but I recently stumbled across reports of a port of the arcade game Xevious to the Atari Jaguar. From what I can gather, it's close to completion and will be released on cartridge for sale. It is particularly interesting to me because Xevious is my all-time favourite arcade game! I do have some knowledge of its internals, as I have in the dim dark past done some preliminary reverse-engineering for the purposes of both software (MAME) and hardware (FPGA) emulation. In both cases I was beaten to the punch by someone else, but it's not for nought as it is knowledge that I plan to use again one day.
There's scant information on the technical details of the port; I have no idea to what extent - if any - the original arcade code has been reverse-engineered, nor whether the port involves any sort of emulation (doubtful) or how faithful the Jaguar code is to the original. In any case, I'd be very interested in learning about the process, and getting my hands on any RE work already done. Not sure how likely any of that will be. For now, I plan on buying the cart.
Of course I started to look into the specifications of the Jaguar, and the resources and toolchains available for homebrew development. To my surprise the homebrew scene is quite active and, compared to similar platforms, the output is quite prolific - and that is due in no small part to the comparatively large number of Atari ST games ported to the platform!
As it turns out, a decent number of Atari ST games lend themselves to being quite easily patched to at least run on the Jaguar, and the architecture of the console - with no less than 3 decent CPU's - gives it the capability to screen-scrape the (largely incompatible format of) ST video memory!
[This is of course exactly what I have recently done with Asteroids on the Apple IIGS; patching as little as two instructions allows the core 6502 code to run on the IIGS, and the processing of the display list is perfectly analogous to screen-scraping!]
Developing for the Jaguar appears to be a tad more complicated than other platforms, though it is suggested that most homebrew development primarily commandeers the 68K 'management' CPU and the pair of purpose-built GPU/DSP devices are under-utilised. Also the toolchain involves the installation of a complete Ubuntu distribution - a far cry from simply having a makefile and AS6809.EXE and ASLINK.EXE in your path for the Coco3, for example!
Of course now I want to get my hands on some Jaguar hardware (not to mention Xevious!) Unfortunately - not unlike other platforms - the so-called SkunkBoard (basically a flash cartridge designed for homebrew developers on the Jaguar) doesn't appear to be currently in production. It's going to be an expensive foray...
The retro gaming scene is alive and never ceases to amaze me!
Slow going on the Apple IIGS front, but I've finally figured out my half-screen issue when shadowing is enabled. After banging my head against a brick wall for a few days, I decided to look at the MAME driver source for the IIGS and immediately found the issue. Because the legacy Apple II hires screen memories overlap the SHR screen memory, you also need to disable the respective bits for those in the SHADOW register. And voila - a blank screen!
Now I've hit another snag. I was intending to use so-called PEI-slamming to update the modified areas of the SHR screen, which require that the direct page and stack are located in BANK1. However, I can't make any sense of the soft switches that control the bank for these and the current state doesn't make sense either. After putting out a call for help I've had a couple of responses but I'm still none-the-wiser.
Somewhat discouragingly, I did a quick experiment double-rendering the frame (one with shadowing disabled, the other enabled) and it's running a bit slower than the arcade game. Granted PEI-slamming will help, but it's going to be tight!
Whilst I'm struggling with IIGS technical issues I got impatient and started on the Coco3 (6809) port. Thus far I have a skeleton main loop that initialises the object table and adds the extra lives to the display list. I've coded up a skeleton rendering routine and fleshed out the CUR command and the tokenised command to display an extra life. It's far from optimal but it works!
First rendering on the Coco3
It's been mostly cut-and-paste from 6502 until this point. Again, the one thorn is the indirect indexed addressing mode of the 6502 but, unlike Lode Runner, it's not as extensively used in Asteroids. Other than that, there's endianity to be mindful of and I've actually swapped the byte order of words in the display list for more efficient rendering. I think this port is going to fall out relatively easily!
I did, however, take preliminary steps towards eliminating flicker. The plan is to utilise video shadowing, as described in this article here, by one of the authors of the IIGS port of Wolfenstein 3D.
Currently, I've got shadowing permanently enabled and simply write to bank $01, which is shadowed on-the-fly to the SHR memory in bank $E1. Slow and flickering, but no trickery to implement and of course easier to debug. But now it's time to up my game.
So in preparation, I simply changed my initialisation routine to disable shadowing, rather than enable it. As expected, I now get a blank screen as writes to bank $01 are not copied to the SHR screen at all. So far so good.
Next step is to disable shadowing at the start of every frame render. Since I've never actually enabled it anywhere, I should still get a blank screen - right? However, when I run it, I now see the top half of the screen! And it happens in both MAME and GSPort, so it's not likely to be an emulation bug.
My first thought was Alternate Display Mode, which can be activated from the Control Panel. I can only access it in GSPort, but it's already turned off. Toggling the value regardless doesn't make any difference. And for good measure, I also disabled interrupts.
It has me completely stumped. I've fielded some queries out there but for now, no responses.
With a little more spare time tonight, but no path forward on the IIGS port, I returned to the C port. I fixed the object update and now the asteroids move as expected in attract mode. Next I added some inputs, so you can coin-up and start a game. The next bit will be tricky, rendering the player ship, as that's quite involved.
I don't really have to go through the exercise of emulating the DVG anymore; with my tokenised display list I can simply back-port that to the C version and it'll be sufficient for all platforms that it'll be running on. However I figured there wasn't too much more work to do, and it may help in understanding some nuance at some point (eg. exploding ship), so I'll persist for now.
Hopefully soon I'll learn of my stupid mistake and I can get back to finishing off the IIGS port...
I've been digging into Norbert's Atari 800XL Asteroids Emulator and trying to ascertain if/where offsets are used for various objects. To re-iterate; the position of an object is relative to the first point in the draw list of vectors that comprise the object. OTOH the position of a bitmap is (always) relative to one corner of the bounding rectangle. So in theory, displaying bitmaps in place of vector objects should require an offset for each object.
I had luck with the player ship and (all) shots. The ship appears to be a lot closer to its true location now, as evidenced by the much reduced incidence of asteroids merely passing close-by and destroying your ship. Shots are definitely much more accurate - if not perfect - as hitting the smaller asteroids requires you to, well, actually hit them!
In order to maintain the current performance, the offsets are coded directly into the compiled sprites, rather than simply offsetting the object's coordinates and thus requiring additional calculations. It did unfortunately necessitate one extra conditional branch in the ship rendering dispatcher because of an odd-valued X offset, but there was no avoiding it.
Characters don't appear to have any offsets applied, as far as I can see. As for asteroids & saucers - eek! There's a few tables with small values that could feasibly contain offsets (one, for example, is indexed by asteroid shape and size) but I'm not sure I'm going to be able to reverse-engineer exactly how it all works as it looks to my untrained eye that it starts to get into display lists. And those routines appear to be working directly on the vector hardware 1024x1024 coordinates as well.
To further add a spanner in the works, played against the Atari version there do still appear to be some inaccuracies between ship and shot and ship and asteroid, albeit subtle. They'll be fun to track down...
Anyway, I'm happy with the progress thus far, and to be honest, it's probably not going to be noticeable to any but the hard-core Asteroids experts out there... and they're not likely to be playing it on the IIGS I wouldn't think. I will look further into it, and perhaps it's a good excuse to crack open Norbert's C64 version which might be a little easier (for me) to follow.
However, I might actually move on now to the ship explosion and then flicker and sound before returning to this issue. I did notice tonight that with only a few small asteroids on the screen, the game is definitely running way too fast, so I'll look at throttling as well.
Discussions on the IIGS FB page tonight have me interested already in another project, though I would only consider it after I've done a proper feasibility study and I have collaborators. I have to admit that I even loaded up the ROM in IDAPro and had a quick look at the start-up code in my lunch break.
But at this stage it's still only a slight possibility and I still have other plans for Asteroids before I put it to bed.