Thursday, 20 July 2017

Game On!

Excellent progress today - in fact it's in good enough shape to demo at WOzFest now although it would be nice to take it along even further if I get the chance!

The bulk of the rendering (sans exploding ship and thrust) and the erasing has been done. I've also managed to pilfer the joystick read routine from Lode Runner and as a result the game is actually playable, albeit slightly slower than the arcade original at this point.

video


I've still got some optimisations up my sleeve, from simple changes to the display list entry format through to stack-blasting hand-compiled sprites, so I'm still holding out hope that I can get it running fast enough to require being throttled by a IIGS interrupt. And I still haven't worked out the whole video shadowing mechanism; a bug in my code meant that I was never shadowing the SHR screen in the first place - and now when I turn it on, it can't read the keyboard... so there's that to play with as well.

I guess if all else fails I can revert to the legacy hires screen which is a lot less data to move.

From the video it's obvious I've got some graphics tweaks to do, including bit-shifting plus offsets from CUR for each object. There's flickering of course, and the odd glitch and then the minor matter of a complete crash at the end of the game.

As an aside, I got stuck on the joystick not working in the IIGS emulation under MAME. I could move left/up, but centering the joystick read back as $FF, so I couldn't move right/down. That forced my hand in trying to get the disk booting in GSPort, and I eventually realised the floppy disk image should be in slot 5, not slot 7. However GSPort had the same issue...

Then it finally twigged; the routine was written for a 1MHz machine and was running on a 2.8MHz machine. The counter was overflowing before even the centre position was detected! After slowing down the CPU it all started working!

So - finish off the graphics, tweak the display positions, optimise the erase/rendering, fix the Game Over bug. Then add sound, title screen, and release! I've got - realistically - only one more night to work on it before its debut.

Wednesday, 19 July 2017

IIGS Take 2

The experimental work I'd done on the IIGS port prior to starting on the port proper has certainly paid off; as of tonight it's rendering the characters, lives, copyright, asteroids and player ship (and the latter only when it should be). I should note that I'm yet to generate or code for the bit-shifted graphics.

It may look no different to the previous version, but the display list is greatly simplified - effectively tokenised - and all the dead code has been removed from the 6502 core, giving me more headroom on the IIGS. And I've still got a little more optimisation to do in my rendering routines.

IIGS Asteroids Take 2 - optimal display list

When I next get the chance I'll continue with the saucer, the shots and the shrapnel which should be as straightforward as the other objects have been until now.  That'll just leave the exploding ship, which I am yet to work on at all.

I think that'll be a good point to research reading the IIGS keyboard; I've been encouraged by reading vague suggestions that it's possible to read the IIGS keyboard directly from the ADB. If that pans out I'll be able to make the game playable, if slow.

Then it'll be time to work on the bit-shifted graphics and erase logic (right now it's clearing the entire screen every frame). That should bring the game back up to speed and I'm hoping it'll actually then be too fast!

I'll be happy if I get to this point by the weekend for WOzFest Slot 7!

Beyond that, there'll be the addition of the exploding ship, sound (samples), support for variable beam brightness, and spit & polish and bells & whistles, such as a title screen, joystick/paddle support etc etc.

Tuesday, 18 July 2017

A token effort

I have to admit, I haven't been able to tear myself away from the C port to make any further progress on the IIGS port. However, it hasn't all been for nought as it has definitely reinforced my understanding of the arcade code, and cemented my decision regarding tokenising (optimising) the display list for the 8-bit ports.

Before I get to that; most of the work on the C code has been 'infrastructure work' and low-level DVG interface routines, which necessarily support both the new abstract display list and the original in parallel - to facilitate debugging and development. What that leaves, then, is the game logic and housekeeping code which generally tends to be easier to translate to C; the upshot of all this is that I don't think the C port is going to take very long to complete at all!

[Just for the record, I have the C port rendering all the text, including scores, and rendering and animating the asteroids themselves. The pseudo-random number generator is also in lock-step with the arcade machine and produces the same output at the appropriate times].

Keep in mind that the arcade code is only 6KB of 6502 - a lot of that munging 16-bit numbers - and it's not surprising that the C port isn't huge. From memory, Knight Lore was ~12KB of Z80 code and translated to ~5K lines of C. I'm around 1,300 lines for Asteroids already, and you could estimate it'll be in the vicinity of 2,500 lines.

Getting back to the IIGS (and 8-bit) ports; aside from the existing CUR (which sets the current beam coordinates) and HALT display list commands, there'll be a distinct command for the rendering of each object in the game, comprising character, extra ship, copyright, asteroid, ship, saucer, shot, shrapnel and exploding ship. I may add one last command to set the brightness - something the arcade code does but Norbert doesn't bother with - simply because the IIGS has the palette to support some variance in brightness.

Some of those commands will have one or two parameters, but all will render at the current beam position. The parameters will be succinct and optimised for the bitmap display routines. What this means is that I can actually remove a lot of code that generates the display list content that is irrelevant for the port, such as DVG subroutine calls or component vector commands. This is one area where I'll be able to improve performance over Norbert's emulators, only because I effectively have the arcade 6502 source that I can modify and re-assemble at will.

I've also identified which of the bitmaps will and won't require bit-shifting, and which will require an extra byte's width to do so. Because, for example, all of the game's text message coordinates are fixed, specified on a 0-255 grid (before being scaled-up in the display list), and also happen to have even X coordinates, I don't have to bit-shift any of the character set for the IIGS 2BPP SHR graphics!

Most of the remaining bitmaps will require bit-shifting, and a few - not all - of those will require an additional byte's width to facilitate it. But that simply boils down to an extra compare and load for each object rendering, unless I need to really wring the performance out of the rendering routines.

My next task now is to generate shifted bitmap data, which is trivial, and essentially start over from scratch with the IIGS port. I'll probably have to stub out all the routines that write to the display list, and then begin work on the so-called tokenising version. None of that should be too difficult...

[UPDATE: I've regenerated the 6502 ASM file from my disassembly, starting the IIGS port from scratch. All of the DVG write routines have been stubbed-out so that only the CUR command is now written to display list. Next is tokenising the character command and then rendering it on the IIGS.]

As for the erasure; I'm planning on (eventually) making use of the ping-pong display list buffer. Immediately before rendering the new list, I'll simply re-parse the old buffer and use it essentially as dirty rectangles. I do have more sophisticated optimisation possibilities up my sleeve; it's useful to know, for example, that all objects are written to the display list in a fixed order. I'll leave all that, however, until I need it - if ever.

Wednesday, 12 July 2017

Asteroids with a 'C'

On Friday nights my wife & I traditionally watch a show together with which I've become rather bored in recent times. Rather than waste that hour last week I decided to set up the laptop in front of the TV and work on some aspect of Asteroids that required a minimum level of concentration. Ultimately I decided to start work on the C port of Asteroids, mainly because it required a lot of crank-the-handle type coding up front before any real work was required. Like defining data structures for zero page variables and player RAM.

Aside from the aforementioned, I manage to also code the main routine and stubs for all the subroutines called from there. Then over the next few nights I was keen to take it a little further; implementing a rather more 'abstract' display list to aid not only in development and debugging, but also to facilitate the so-called tokenising I'd be doing in the 8-bit ports. That entailed a DVG 'disassembler' of sorts which subsequently morphed itself into a DVG interpreter/emulator which was soon rendering a few vectors on the display.

Of course time is ticking for WOzFest and I do need to bite the bullet on the tokenised display list and optimisations for the IIGS. However it has been a very useful exercise and I've discovered a few subtleties of the DVG which had escaped me until now. Regardless, I really need to put it aside for now and continue on with the IIGS port. In the mean-time, here's a sample rendering of what I have thus far.

Asteroids C port (Win7, GCC, Allegro)

Like my other C ports (Lode Runner and Knight Lore), the C code is as faithful to the original assembler source as practical, whilst optimising aspects of the original code such as using 16- and 32-bit variables rather than multiple bytes for things like addresses, scores, coordinates, etc. I retain all the same subroutines with the same names, albeit adding parameters for values passed in registers, etc. The logic within each routine is representative of the assembly code, differing only to accommodate the aforementioned optimisations and/or clarify the intent, without changing the underlying algorithm or compromising accuracy.

The end result is the same as the 8-bit assembler ports; a game that plays exactly - and looks as far as practical on the target hardware - the same as the original. And as I've discovered in the past, I've even been able to debug aspects of the assembler ports on the C version! In the case of Asteroids, I think the ability to inspect the display list so easily will come in handy down the track.

The C version should be portable to the Amiga and the Neo Geo at the very least. For Lode Runner the C port was an after-thought of the Coco3 (6809) port, but for Knight Lore, I developed it in parallel the with Coco3 port and it was, as I mentioned, very helpful. This time 'round, I'm undecided how I'll proceed once the IIGS port is finished...

Friday, 7 July 2017

To SNES or not to SNES?

No opportunity for any development today but time to ponder random aspects of the project. I was also prompted by gp2000 to look a little further into specific aspects of the code, and discovered something that should have been obvious from the start, but escaped me until today - so thanks George for that inadvertent trigger!

I did tweak some of the coordinate transformation and video address calculations today, converting my 6502 code into 65816 and improving the resolution of some of the calculations. Always good to see a half-page of 8-bit code reduce to a few lines of 16-bit code!

And in the comments of a previous post I pondered the feasibility of porting this to the TRS-80 Model 4. Aside from the effort of porting to yet another CPU (Z80) there's also the fact that the hires board is all-but-crippled by not only port-mapping the hires video memory, but also restricting access to (vertical?) blanking periods. George suggested a hybrid mode mixing the text and hires graphics screens... very interesting but a lot of work none-the-less. I'll put this in the 'maybe' basket.

And on the subject of alternate ports, the SNES sprung to mind! I know little about the technical specifications except for the fact that it is powered by a 65816 (clone). A quick Google reveals it supports 256x224 resolution, allows 128 sprites (up to 32/line) and has the usual tilemap(s).

I'm thinking this would be a no-brainer; text would appear on the tilemap layer, with 27 asteroids, player ship, saucer and 6 shots making up a maximum of 35 sprites on-screen. Extremely unlikely that they'd all appear on the same scan line, but if I was really pedantic about it I could implement a software priority scheme. But with all the arcade 6502 code running, plus the bulk of the IIGS 65816 code available, it wouldn't be a lot of work at all. I'm going to put this in the 'almost certainly' basket, and I might be tempted to tackle it immediately after the IIGS port is done.

EDIT: Doh! It's already been ported to the SNES by Digital Eclipse!

[Makes me wonder if I should be porting that version to IIGS!?!]

That's about it for random musings. A parting fact: whilst the vector display coordinates range from 0-1023, the game's virtual playfield coordinates actually range from 0-8191. Somehow that escaped me... now consider it's all scaled down to 256x192... or in the case of the TRS-80 text mode graphics, 128x48 (128x72 if I get really tricky).

Thursday, 6 July 2017

Use the source, Luke!

In my third blog update for the day, I can report that I've all-but-finished the reverse-engineering of the arcade Asteroids 6502 code.

Aside from temporary storage, all zero page and player RAM variables have been documented. There are no variable addresses remaining for which I do not know the purpose.

About 95% of the code has been commented. There's some particularly nasty code in a few places throughout the ROM that remains uncommented at this stage; aside from some physics there's the exploding ship routine - which seems unnecessarily complex in my opinion - for example.

Importantly, I know what all the code is meant to achieve, even if I don't understand the nitty-gritty of every line in some isolated cases. It's something I'll probably have to rectify once I start transcoding to 6809 and/or C, but for now I'm satisfied that I have a well-enough commented source file on which to base my official Apple IIGS port.

From here I need to re-generate the core .ASM file and re-apply my patches for running on the IIGS. Since I annotated those patches in IDAPro, it should only take about 10 minutes before it's running again with the new source. And thereafter, I can start modifying the code 'for real' this time, including optimising for performance and incorporating pixel-shifted bitmaps.

It'll probably be a few days before I have anything rendering again, and the still screen shots will probably look no different to those I have posted already. The video should look a lot better though...

Wednesday, 5 July 2017

Great minds think alike (or fools never differ).

Interesting to dissect Norbert's Atari800XL Asteroids emulator.

The aforementioned patches to the rendering routines actually implement an alternate display list, of sorts. For all the (alpha-numeric) characters and the extra ships, Norbert adds an entry to his own display list, using the character code directly (no reverse-lookup on JSR address required). He also assigns character code $FF for the DVG CUR command, and inserts the pre-scaled Atari display coordinates. This is essentially what I had in mind for 'tokenising' the display list to optimise for the Apple IIGS.

As described in my last post, the emulator hooks the main loop and calls out to three (3) subroutines.

The first routine is (as I subsequently discovered) the rendering routine and it only renders the display every 3rd call. It does something with self-modifying code that I'm yet to reverse-engineer, before rendering the asteroids directly from the player status RAM area. Next is rendering the player ship or explosion, depending again on the player status - something I'm actually doing now as a 'quick hack'... not so much of a hack as it turns out! And as I suspected, the relative coordinates (offset) of the thrust pixel is stored in a lookup table and plotted discretely. After that, the saucer is rendered, and then the shots (saucer and player), before the alternate display list (characters) is finally rendered. At the end of the routine it appears to handle the high score entry, and then mess with ANTIC registers - and I'm way out of my depth here!

I've missed the copyright message in there somewhere, but perhaps it's done at startup and never deleted from the ANTIC display list? Not worth pursuing further since it's not relevant to the IIGS or likely any other hardware I'll be porting to.

The second hook routine emulates the inputs, and the third the sound.

And as I suspected, when the player status RAM bank switch is hit (changed), the emulator simply swaps 256 bytes between $200 and $300.

So what will I be taking away from this?

I like the idea of the alternate display list, though perhaps with the arcade 'source' it'll be easier for me to simply re-purpose the DVG shared RAM. Certainly it would appear that 'tokenising' the display list is the way to go. I would also eliminate all the dead code that makes up the current display list. And not having to iterate over player status RAM - essentially for the 2nd time each frame - should speed things up a little too.

I'll use Norbert's lookup table for the thrust, but instead use it to pre-render a 2nd set of bitmaps for the player ship. Again, not having the extra look-up and calculations to render a single pixel will increase performance further.

I should also be able to find the ship explosion bitmap(s) in there somewhere, if I can navigate the eccentricities of the Atari 800XL display hardware!

Standing on the shoulders of giants...

Undecided on how best to proceed with the remaining rendering tasks, today at lunchtime I downloaded Norbert's (Atari 800XL) emulator and fired it up in MAME, intending to plot the 'thrust' pixel in each of the 24 player ship bitmaps based purely on observation.

I've documented 12/24 but not surprisingly, it got old pretty quickly and, curiosity getting the better of me, I dumped the first 16KB of the Atari's memory into a binary file and loaded it up into IDAPro.

Before transferring control to the arcade code, Norbert's emulator patches a bunch of addresses in the ROM. Aside from those critical for running on non-Asteroids hardware (ie. the same patches I made) it also patches routines such as the 'CUR' (current) DVG command, character display, display of extra ships, etc.

It also installs a hook in the main game loop. The hook itself calls three subroutines; one to read the Atari joystick inputs and seed the memory-mapped Asteroids inputs, one to play the sounds based on the memory-mapped outputs, and the third I'm yet to ascertain.

Most importantly though, I'm still yet to determine how the emulator goes about rendering the display. From what little I've seen, the display list is somewhat 'corrupted' by the patched routines. However there are other unpatched routines that must still provide data to the emulator via the display list - so I'm not sure how it all works just yet. The waters could also be further muddied by the Atari 800XL's unique display hardware... I'm sure I'll work it all out next session.

Tuesday, 4 July 2017

Ship-shape!

I converted Norbert's ship data to my IIGS format and checked out exactly what he has rendered. There are 24 bitmaps in total, covering 360 degrees of rotation.

That is contrasted with 64 different renderings of the player ship in the arcade game. However again, at this resolution, it'd be pointless to attempt to render that many different bitmaps.

One interesting thing to note is that the player ship direction is stored as a single byte, the value varying the full range of 0-255 to represent 360 degrees. Each tap of the rotation changes the direction by +/-3, which means that coming full circle, you don't actually end up at 0 again, but rather at 255 or 2 first time 'round, and 254 or 1 next time. Not terribly important, because your direction is effectively right-shifted by 2 bits to determine which ship to render - IOW each tap of the rotation button does not necessarily change the ship rendering.

In the IIGS case, the direction needs to be divided by 24, which is equivalent to right-shifting by 4 and 5 and adding the results, although the resolution of the operation needs to be increased (easily done in 16-bit mode using the XBA instruction) to get all 24 outcomes.

Unfortunately identifying the ship in the display list is practically impossible. Rather than work out how/where to patch the arcade code, as a quick hack I simply added a routine at the end of the DVG emulation code to (always) render the player ship. Fortunately the arcade code always ends the display list with a CUR command corresponding to the center of the screen, so at least it's always rendered there and the game can be 'played' (more-or-less) as long as you don't use the thrust button!

Player ship is now rendered... sort of...

I should add that I'm yet to implement the 'thrust' indicator on the player ship; Norbert hasn't supplied me with any rendering details for this but from a quick look at his emulator video, it looks like a single pixel is illuminated for each bitmap - I just need to work out exactly which pixel!

That really just leaves the player ship explosion, another list of component vectors patched by the arcade code as it is copied to the display list. Again, there won't be any way to identify it in the display list, so I'll likely extend my quick hack to detect when the ship is exploding and render it there; enough to ensure my rendering algorithm is correct.

And that should be everything that needs to be rendered! From that point on, it's a matter of producing pixel-shifted bitmaps where required, updating the rendering routines to use them, and then finally optimise it all to eliminate the flicker and get it running at full frame rate. There'll be some use of the IIGS interrupts to throttle the frame rate, and of course hooking up proper keyboard/joystick/paddle controls and adding a fancy menu. Unlikely it'll all happen before WOzFest, but I should have a decent demo by then at least!?!

(C)1979 ATARI INC

Picked some low-hanging fruit in my lunch break today; rendering the copyright message at a more appropriate size.

Although Norbert didn't supply the source data for the copyright message, it was a trivial matter to load a screen shot from his emulator page into a graphics editor, crop the message, reduce the colour depth and save it as a Portable Bitmap File - a text-based format perfectly suited to turning into assembler source data statements.

And while I was at it, I centered the screen on the IIGS display. Again, trivial, since screen accesses are all performed via an index register relative to the start of SHR memory - a constant defined in my IIGS .inc file. Simply adjusting the constant by 4 lines and 32 pixels ($290) was sufficient to center the display for each and every rendering routine.

Centered and a less obtrusive copyright message

Now for the player ship...

Monday, 3 July 2017

A shot in the dark

Shots, as it turns out, are rendered in the display list as zero-length vectors with scale=7 and maximum brightness and thus can be uniquely identified.

So I simply added a check for such in my DVG emulation code and now have shots being displayed for both player and saucer. I added some crude keyboard mappings for fire and left/right rotate, and I can coin up, start a game and take aim at asteroids and destroy them.

Player's ship is yet to be rendered, but asteroids can still be destroyed

That leaves player ship and player explosion. The latter consists of component vector commands copied and patched from the DVG ROM routine. In theory, they are the only two remaining objects in the display list, and it may yet be possible to distinguish between the two... something I need to experiment with in order to confirm. It would be really, really nice if I didn't have to patch the original game - even if just for this exercise - and be able to render all the game graphics!

But next task is to get Norbert's player ship bitmaps converted and displayed in the correct orientation.

Sunday, 2 July 2017

Where's the kaboom? There was supposed to be an earth-shattering kaboom!

It turns out that, as suggested on the Computer Archeology page on the DVG ROM, Asteroids does indeed use the global scale in the animation of the explosion. In fact all-up there are 21 different frames of animation of the explosion, all based on the 4 shrapnel pattern routines in the ROM.

Understandably though, Norbert appears to make do without scaling at all, using 4 patterns as-is. In truth, at 256x192 resolution 21 frames of animation of exploding particles is overkill, and half the frames would probably look the same anyway. The shrapnel bitmaps, like the other objects, are confined to 16x16 pixels and likely don't render quite as large as the shrapnel on the original, but it's not noticeable at all except perhaps for the number of frames each pattern persists for. Either way it doesn't affect game play in any way.

Throughout the original animation, the global scale is changed in 6 steps from 11 thru 15 and finally to 0. What I do is simply ignore the shrapnel pattern number and instead use the global scale to display pattern 0, 1, 2, 2, 3 & 3 since the latter scales are displayed for more frames (somewhat realistically the explosion slows down).

Kaboom! A saucer hits an asteroid.

Next I'll look at the (saucer) shots, and see if they can be unambiguously identified in the display list... perhaps via their brightness and/or vector length??? If not, it's time for some 'less benign' changes to the original code!