Friday, 27 October 2017

Flicker-be-gone! (mostly)

No progress on the collision-detection bug so I decided to implement the double-buffering (page flipping) since it is almost trivial and won't be affected by any other programming issue.

The arcade machine uses a pair of so-called "ping-pong" buffers to allow the DVG to render the frame whilst the CPU is building the next frame. This comes in very handy indeed on the raster ports (Apple IIGS, Coco3) when erasing the previous frame before rendering the current frame.

Of course double-buffering requires erasing the frame prior to the previous frame. The easiest way to implement this with the current architecture is to extend the 2x buffers to 4x and modify the "ping-pong" logic slightly. No more than a handful of instructions in a few strategic locations...

At this point the game is running quite slowly due to the sub-optimal (to put it mildly) erase/render code, so there's little point synchronising the page flipping to the VBLANK and therefore the video still exhibits some flicker. However it is much improved and gives a taste for things to come...

UPDATE: Tonight I thought I'd add some profiling code before starting on any more of the optimisations. When you first start a game (with 4 asteroids on-screen) it's hovering around 55fps. When things get a lot busier, it's down around 20fps, and the lowest I've encountered is 13fps. And when there's all-but-nothing to render, it hits 89fps.

Will be interesting to see where it goes from here...

UPDATE 2: I've just optimised the copyright rendering. The copyright is unique in that it is rendered every frame, in a fixed location, and therefore never needs to be erased.

After some experimentation, and without resorting to stack blasting (which I can't see being optimal in this case due to the OR'ing operation), I came up with the following for each line of 4 words (Y is the video address):

LDD #0x1234
LDD #0x5678

That's the best I can come up with late on a Friday night (37 -> 22/24 cycles/line). Improvements welcome!

Tuesday, 24 October 2017

A progress report on lack of progress.

Today I had the chance to review the collision-detection code. The bad news is that I couldn't see anything amiss. I did find a few minor issues to do with ADC/ADD but they don't appear to be the cause of the bug. I also managed to effect a few minor optimisations.

I'm still hanging my hat on an issue with the core code, rather than the display mapping. I say that because a lot of the time the shots and objects are spot-on - even the small asteroids and small saucer - but then a shot will pass right through the middle of the large saucer. That's not just a few pixels off... more like a logic bug.

Aside from revisiting the collision-detection code again, I don't have any further theories on the matter. This might turn out to be a tough one.

I've been holding off on the optimisations up until now for a few reasons. One, it's simply nice to have the rest of the porting 100% complete. Two, it's easier to tweak things like display mapping with brain-dead code. And finally, I didn't want to find myself in the situation where I had to re-optimise certain routines because something fundamental wasn't quite right.

Having said all that, I'm wondering whether it is actually safe to press on with the optimisations now and revisit this issue down the track - assuming it doesn't have anything to do with display mapping. I don't want to get bogged down debugging this and lose momentum (again).

At least part of the optimisation - double buffering - won't be affected either way and should be relatively straight-forward. From there it gets more involved with compiled sprites, but I could get a start on objects such as text and the copyright message.

Have to think about it...

Monday, 23 October 2017

Even more display tweaks, looks even better. Still not perfect...

More tweaks to the display mapping, and it's improved even more. There was an offset added in the core (arcade) code when adding the CUR command to the DVG display list that must be peculiar to the vector hardware; I needed to remove that offset to enable objects to use the entire 192 lines of the display. Norbert didn't have this issue because he all-but ignores the display list, except for rendering text and his seemingly arbitrary offset (after scaling) accounts for it - and now makes sense of course.

I've also added clipping to the screen for all objects except the exploding ship. My explosion rendering code differs quite a bit from Norbert's; he uses a generic pixel-plot routine that handles the clipping (it'll render pixels outside the visible display on line 191, which is odd). I will probably not bother with clipping until I optimise the graphics for the Coco3.

After a few more hours of coding and comparing the Atari and Coco3 versions, I'm convinced there's still an issue with collision-detection (apparent in the video below). I'm reasonably sure it's not the display mapping now as sometimes the shots go straight through the middle of the large saucer, and occasionally you can't seem to hit the smallest asteroids. I simply cannot reproduce either bug on Norbert's emulator.

So now I need to go back and review the collision code which is not altogether surprising since it pretty much "worked" straight away. In fact I'm hoping that is the issue because otherwise everything else seems spot-on now, and I can definitely move on to Coco3 optimisations once this issue is sorted - something I've been itching to do for some time now.

A few more fixes and it's looking good... but not perfect.

Another brief update; I seem to only get to work on it in snippets atm...

I've fixed the ship explosion offset (same as ship offset). I also fixed a long-standing bug in the erase routine for the extra life indicators.

It's looking pretty spot-on now as far as object placement goes, although occasionally a shot appears to pass right through an object. I've played a bit of Norbert's Atari emulator, and it doesn't appear to have this issue. So either there's a subtle bug in the 6809 core code, or there are some more offsets that I haven't noticed yet. Tonight I went through the rendering routines in Norbert's code again, and I don't see any more offsets applied.

From here I'll likely render the 1st frame in attract mode and compare all the plot positions for each object on Atari/Coco3. If they match (they're all large asteroids of course) I'll let it run for a fixed number of frames until a few get split and try again. Fortunately the attract mode is completely deterministic from a cold start.

After closer scrutinisation of Norbert's emulator, a few warts become more apparent.

Norbert has the same bug as I had; the first game from a cold start has 3 lives, and subsequent games start with 4. That's because the original code right-shifts a hardware I/O location mapped to a dipswitch, and checks for carry. Under emulation, that's simply a RAM location so although it's seeded with the correct dipswitch value (bit0=1) at initialisation, it's shifted out after the first game starts. I fixed this in the code (also on the Apple version), since unlike Norbert, I have the luxury of assembling the core.

The Atari version is also only rendered every 3rd frame, because the CPU is simply too slow to render every frame and have the game run at full speed (which I must admit, I still don't have a value for). At least, Norbert's code isn't anywhere near as optimised as it could be (an observation, not a criticism). That's fine for a busy screen, but when you're down to only a few small asteroids, the game is obviously too fast. There's no periodic interrupt throttling the game speed.

With any luck, I'm not too far off being in a position to start the Coco3 optimisations...

Saturday, 21 October 2017


Super-brief update... I've fixed the ship/shot offset issue. Nothing sinister at all - simply forgot the '#' character when adding the fixed pixel offsets to the accumulator!

Need to re-check the other offsets now, and fix the display issue at the bottom of the screen, and possibly add Y clipping - and I can then move on to optimisation for the Coco3!

Friday, 20 October 2017

Code that isn't executed has no bugs!

Very brief update.

After five days away from the keyboard I decided there was only one possible reason for the erase ship routine not working... and I was right! Because I cut-and-paste the render routine and used it for the erase by replacing the video writes with CLR, it simply wasn't possible for it to fail. And it wasn't actually failing at all - I simply wasn't calling it!

I have a jump table for the (tokenised) DVG commands, and for the previous iteration without any constant offsets, the ship was erased (for now) by a call to the generic erase_chr routine, since the ship is no larger than a character. So when I added new code to the render_ship routine that moved it...

Right now I'm where I was at with the IIGS version, with the exploding ship graphics as well. In short, all the rendering is done - it's just not done at exactly the right position on the screen. The shots are coming out near the nose of the ship, but it's still offset by a pixel or two in some orientations. Why is a complete mystery to me, as both the ship and shot appear to have a constant offset applied to them.

Most of the asteroid hits seem spot-on too, but occasionally I've seen a shot pass right through the middle of a saucer.

I was hoping things would "just work" with the scaling sorted but it appears there's something still amiss. I just hope it's not buried in the Atari display list code, because that's all Greek to me...

I'm tempted to forge ahead with the Coco3 optimisations at this point, but something is nagging at me to get it exactly right this time before moving on. At least once all the offsets are deduced and coded I can back-port to any Apple version(s)!

Thursday, 12 October 2017

Size does matter

Finally, I've implemented the exploding ship routine! I had even avoided it on the Apple IIGS version which, of course, remains incomplete at this point. It's complicated, it's messy, it's slow - but I get the same results as Norbert, sans graphical bugs.

When it comes time to implement it 'properly' (optimised) on the Coco, I'll likely generate bitmaps of the pieces rather than use a table of pixel coordinates so I can use compiled sprites.

One thing that I did notice, however, on both the Apple IIGS version and the Coco version, is that the screen appears 'compressed' vertically compared to the Atari 800XL version, despite the screen resolution being similar.

Atari 800XL version by Norbert Kehrer

Note particularly the space between rows of text in the high score table.

Coco3 version (WIP) by yours truly

Although, as I said, I had noticed it before, I didn't give it much thought until now, attributing it to larger border areas on both platforms. Aside from reducing the playing area, it does cause the high score table text to overlap. In fact, on the high score entry screen, I (also) patched the message text coordinates to space them out a bit more.

I have confirmed that Norbert hasn't patched the high score display routine at all, so something is amiss. Far from being bad news though, this is actually encouraging, because on the IIGS version I did notice some subtle pixel offsets that didn't look quite right when compared to Norbert's version. I'm hoping then that fixing this issue will not only decompress the screen - and playing area - but also fix those subtle issues!

UPDATE: I've identified the issue with the screen compression, and it's both simpler and a little more complicated than I'd guessed. Asteroids world coordinates are 13 bits (0..8191) which are shifted down to 10 bits (0..1023) - with an X offset - when inserted into the display list for rendering. My rendering routine then takes the Y coordinate, for example, and scales it to (0..191). Norbert, however, doesn't scale the Y coordinate accordingly, but simply shifts it down to 0..255 and adds an offset for rendering, even though the Atari vertical resolution is also 192. That works because the visible vertical resolution on Asteroids isn't the full range 0..1023, but rather closer to 800.

Norbert also handles the objects and text slightly differently, adding a (different) Y offset for the text. It will take some further analysis before I can implement all the subtleties, and I also (now) have to add Y-axis clipping since it's now possible some objects may have a few lines off-screen. At least I've solved the mystery.

UPDATE #2: I've sorted the scaling issue, and the game now uses the full extent of the visible area, and removed my hack for the multi-line high score entry message. I've tweaked a few things to place the score at the very top, and the copyright at the very bottom, like the arcade game. It has, however, introduced a new bug with objects rendered near the bottom of the screen...

Re-scaled Coco3 version, using all 192 lines

I've decided to add all the tweaks before I start optimisations, since it will likely be more difficult to debug/modify once I add things like doulbe-buffering and compiled sprites. I also started to add the ship & shot offsets, but can't for the life of me get the ship erasing properly. I don't really understand why not, since - for now - I've cut-and-paste the render routine, replacing the instructions that write bitmap data with a CLR instruction... simply shouldn't be possible to not work. :(

I'm off interstate for a few days - sans computer - so no new updates for a while...

Wednesday, 11 October 2017

Another last word on explosions

After adding the thrust (pixel) rendering, I decided to bite the bullet and implement the ship explosion to round off the port before I move on to optimisations for the Coco3.

I've ported all the original code, despite the fact that one of the routines isn't required for the Coco3 (or any other raster/bitmap platform) port. That latter routine is, of course, completely untested.

I've taken a slightly different approach to Norbert, who renders his graphics by referencing the player data directly. Norbert hooks into the arcade explosion rendering routine to build a table of piece offsets, which he uses in his end-of-frame rendering, together with the player ship position data.

Rather, my (tokenised) display list command for a ship explosion (piece) comprises the piece number and piece X,Y offsets, which together with the current beam position (the last CUR command) is sufficient to position the piece bitmap.

Right now it's WIP; I am plotting a single pixel per piece rather than rendering the entire piece as I debug the ported code. It's sort-of working but there's a bug or two to iron out before I can complete the piece rendering.

Interestingly the explosion is somewhat non-deterministic. The code (re)intialises a table of piece X,Y offsets in the first few frames of the explosion - but only the high byte. So each explosion may, in theory, be subtly different. Not sure if that was intended or not.

Hopefully I'll have another update tonight.

UPDATE: I forged ahead with the explosion rendering, and managed to get something that resembles the arcade, or at least Norbert's version of it. It's not quite there, so a little debugging to do yet. But it's certainly close.

Note that I have a .define for the number of starting lives, to make debugging easier - and for the video above, it's set to 1.

To summarise, once the explosion is debugged - aside from sound - that's the porting process complete! I just need to optimised the rendering and eliminate the flicker on the Coco3. Then perhaps I can look at a Star Wars port...

UPDATE: Ship explosion is now fully debugged!

A last word on explosions.

I've finished the RE of the exploding ship routines, both in the original and Norbert's emulator.

Norbert patches the explosion routine to call his routine to render a piece - using intermediate results from the caller - and then jumps back to the original routine. There's a decent amount of code that doesn't have to be executed on the emulator, but the game at that point doesn't need to be fast.

By necessity, Norbert grabs the player ship location and derives the explosion offsets from it again (since the vector commands are all relative to the ship position). He also maintains his own table of piece locations rather than use the original table, presumably because he requires less resolution.

In short, there's a non-trivial amount of code involved, even in Norbert's emulator. Since all the pieces follow a fixed trajectory it would be possible to replace all the calculations with simple look-up tables for either piece positions, or even simply a bitmap for each frame. At this point I'm undecided on how I'll approach it, but likely simply port Norbert's code.

Thus far I've ported the arcade explosion code up until the point where Norbert hooks it to render a piece. And in theory, that's all the original code that is required; the remainder is concerned only with moving the beam back to the ship position ready to render the next piece.

To re-iterate, the only outstanding bits of code on the Coco are: rendering the thrust pixel, rendering the ship explosion pieces, and the sound. Aside from those, the graphics display needs tweaking (pixel offsets adjusted) and the flicker is to be eliminated.

I'm undecided in which order I'll tackle the above-mentioned tasks. The ship explosion is tedious, the thrust isn't too bad since I've done it on the Apple IIGS already, and the sound will definitely be the last thing I do - so fixing the display on the Coco3 is looking tempting.

UPDATE: thrust rendering is done

This also means that the RE of the original is more-or-less complete, and fully-documented. I'll probably hold off releasing that until the 6809 version is fully ported and debugged, just in case...

Monday, 9 October 2017

High scores and exploding ships

Some progress in a couple of areas.

Firstly, the high score display/entry is now fully debugged. IIRC there were at least 5 bugs in the code; not completely unexpected since - by necessity - I ported pretty much all of the code in one go before being able to test any of it. It did take a little longer than I'd hoped, but nothing too nasty in there.

The game is, arguably, fully playable now, missing only the exploding ship graphics and subtle positioning tweaks. IOW the 6809 core is complete, aside from the aforementioned exploding ship. I still need to compare a running attract mode against the original, but it appears on the surface to be 100% faithful. Now the fun bits can begin; getting the display right on various platforms!

Secondly, I took a closer look at the exploding ship routine. There's a curious amount of code for such a seemingly minor aesthetic, but after a second look I understand most of what's happening now. I was actually tipped-off when I revisited the DVG ROM listing on Computer Archeology; I'm sure it has been updated recently with more information! The extra snippet of information that put the pieces together for me was the 'Ship explosion pieces velocity' table.

There are six (6) pieces of ship that expand, dissipate and disappear one-by-one - hence the relative complexity of the code. The first (few) times the code is visited in an explosion, it creates an array of piece data in zeropage memory. This is the data that is updated each iteration (frame) of the explosion as the code moves and scales the pieces.

When rendering a given piece, a VECT command is added to the display list (with Z=0) to place the beam for the start of the piece, relative to the ship position. The SVEC command is then copied from the table in the DVG ROM to render the actual piece. And here's the interesting bit. The same SVEC is then copied again, but negating the dX,dY signs to position the beam back at the start of the piece. And finally, the first VECT command is similarly copied right out of the display list itself, again negating dX,dY to put the beam back at the ship position. And then on to the next piece...

I'd like to see how Norbet rendered the explosion; it seems awfully complicated for what could be done in a few pre-rendered bitmaps. If he took some short-cuts, it may not be necessary to port this code at all. However, I will need to port it for the Star Wars port anyway, so perhaps I will tackle it regardless. It'll be a little messy as there's copious instances of shuffling data to/from index registers and zeropage memory - doesn't translate well to the 6809's 16-bit index registers of course. At least it's not absolutely critical that this code run quickly...

UPDATE: I've taken a look at Norbert's code for the exploding ship, and have identified the graphics data - stored as individual pixel offsets - for the ship explosion pieces. He uses the same mechanism and rendering routine for the thrust (which reminds me, I haven't implemented the thrust graphic on the Coco version).

I'm yet to RE his code for moving the exploding pieces... that'll have to be another time.

Interestingly I've found a bug in his emulator. He overwrites part of the ship explosion pixel data table sometime during initialisation; I've haven't RE'd that routine but I suspect it's preparing memory for the control input shadow values. Why? Because he's also using 2 of those bytes from the pixel data table for the hyperspace and fire shadow values, and they're in a different memory area than the others. So he likely moved variables around and didn't finish the job...

And when you know it's there; the bug is apparent (extraneous pixels) in the YouTube video of his Atari emulator at 0:53.

Saturday, 7 October 2017

The Universe conspires!

I've ported the remaining high score routines, which leaves just two 'core' routines remaining - those concerned with the explosion of the player ship. The high score routines are almost functional; they just need a bit of debugging but don't adversely affect anything else.

So back to the mysterious end of game issue. After the addition of the high score entry routines, the nature of the issue has changed. In retrospect, the original problem was likely the very lack of the high score routines - particularly the routine that checks for a new high score - since it does change some of the state information.

The issue then manifested itself as the high score entry screen appearing briefly, then a new game starting immediately. After an hour or so of static code review and then moving on to debugging in MAME, I'd stumbled upon something that in itself didn't appear to cause the issue, but still wasn't right - a seemingly arbitrary value in the current number of credits.

However, setting a watchpoint in MAME and running not only refused to reproduce the problem, but the game started behaving correctly on the high score entry screen! Running again without the watchpoint, and it would fail. Run it again with - all OK. Inexplicable.

And then, I finally caught it. Not part of the 'core' code, but in the Coco-specific portion, I poll the keyboard every frame and increment, amongst other things, coin counters when appropriate. FTR the arcade code does this in an NMI, but for now I'm doing it once per frame. Anyway, turns out I wasn't detecting depress properly and holding down the <5> key adds multiple credits. And whilst running the debugger and watchpoint, it's slow enough to detect just one coin if you press <5> quickly.

But the universe wasn't done with me yet. In the same portion of code, I also handle the start button. In this case I was polling the keyboard correctly, but never clearing the state of the button, so once pressed, it remained in that state permanently.

And finally, to muddy the waters even further, it turns out that pressing the start button with credits in the machine will actually abort the high score entry screen altogether and start a new game!

Here I was thinking that somewhere in the core code it was exiting the high score entry state erroneously, when in fact a combination of multiple credits and a 'stuck' start button - all in my code - were to blame! At least I finally found it...

Next, debugging high score entry (which shouldn't take long) and then the exploding player ship.

Thursday, 5 October 2017

Getting close

Today I did a quick audit of what was outstanding in the 'core':
  • 7x routines for high score display/entry
  • 2x routines to display exploding player ship

There's also a few routines not strictly necessary for game play, but will likely be implemented at some stage to round off the port:
  • 4x sound routines
  • 4x sundry routines, such as NMI

I could probably knock over the high score routines in a single session. The exploding ship was the one aspect of the Apple IIGS port I hadn't addressed, for two reasons; I don't (yet) understand the code and I don't have Norbert's graphics for it (nor do I understand - yet - how he implemented it).

UPDATE: I've done 4 of the remaining 7 high score routines; namely those that display the high score table. The remaining 3 comprise the high score initials entry.

I might finish off the high score and then have another look at the exploding ship code for the arcade. If it's still incomprehensible to me, I might move on to optimising the rendering for the Coco3 before returning to it in earnest.

Today I did manage to completely break the asteroids though when adding a few tweaks... so fixing that is first on the agenda.

UPDATE: I also fixed this, however although it detects the end of the game (and displays GAME OVER) it still doesn't actually end the game - you can still play. I had a look for this earlier, and it still eludes me.

Wednesday, 4 October 2017

Mostly Playable.

Quick update on the Coco3 port of Asteroids tonight.

Have managed a few sessions over the last few days...
  • Fixed score display
  • Fixed end-of-wave detection
  • Added shots (player & saucer) and fixed shot direction
  • Added shrapnel (explosion) rendering
  • Added end-of-game detection
  • Added hyperspace

The game is all-but-playable now. Although it detects and displays Game Over, it still continues the game and subsequently dying results in a crash as it tries to display (presumably) 255 remaining lives.

Going purely on generated code size, it's roughly 67% complete now. I'm yet to do a formal audit, but I can't actually think of a lot that is yet to be ported, aside from the high score handling and player ship explosions, plus snippets of sound code. There's certainly some AVG display list management code that will not need to be ported for the Coco3 version, plus the non-English message tables that I'm not going to support, so it could well be closer to 80% or even 85% complete in reality.

Once the 'core' code has been ported, the next task is optimising the rendering for the Coco3. That means adding compiled sprites and page-flipping for starters. Nothing too complex in there, and I've already been through the exercise for the (unfinished) Apple IIGS port.

Here is where I hope the slightly higher clock speed and 1BPP graphics mode will give it the edge over the IIGS SHR mode graphics, which still crawled despite my best efforts.

Time will tell...