Pages

Thursday, 11 June 2020

Less magic, more explosions!

Not much time to work on it as I have a sneaking suspicion that getting Space Inavders working on the CoCo3 is pretty low on my employer's priority list.

Fixed the player explosion, UFO explosion and the UFO score when hit.

A number of 'magic numbers' in the disassembly have been fixed, including instances in both code and data. In order to get things working properly I've also had to ensure certain groups of data structures - such as various tables for the UFO - don't span 256-byte boundaries.

Getting closer now to finishing the coding, mainly shields. Then I'll be moving onto optimising and cleaning up (removing old and duplicate code) before debugging and tweaking alignment. The most obvious glitch is hitting an alien just as they're dropping down and not erasing it.

Tuesday, 9 June 2020

Things are about to explode!

Two very brief sessions over the last few days.

Player lasers and alien explosions are all-but-fixed now. I've realised that I need to go back and review all the reference points used for the rotation again. But it's something I'll leave until all the rendering routines at least look correct, even if there are some minor alignment issues.

I've also been able to re-use some of the object-specific rendering routines for multiple objects, so I'll have to go back and rename some of them at least.

The game is playable now, albeit with occasional graphics glitches. The oustanding issues are UFO explosion, player explosion and invader bomb explosion (hitting shields and/or bottom of the screen). And shield orientation of course.

I would hope to have these issues sorted by the end of the week, though it depends on work/family/exercise/sleep commitments.

Saturday, 6 June 2020

This is Da bomb!!!

Unexpectedly got a bit more time tonight to work on Space Invaders.

Started to look at the invader bomb rendering code. The routine that renders a bomb also checks for collision with other objects; namely shields and player laser base. I decided to concentrate on the rendering for now and worry about collisions later.

Turns out what I had already coded was only missing a single instruction once I added the requisite bomb sprite data. But the invaders would drop a bomb, it would animate correctly for the 4 different frames in the table, then produce garbage. And then they'd stop dropping bombs. It was time to examine the logic beyond the rendering routine.

Ahh, "magic numbers". Not Tomohiro Nishikado's fault of course, but rather that of the person reverse-engineering the code, though perhaps Tomohiro doesn't get away completely unscathed because he does make an assumption about tables not spanning 256-byte boundaries.

In order to save space and time, several data structures store the LSB of the last entry in a table. And in several places, the code compares that value with a hard-coded value to determine if the end of a table has been reached. So when rotating the graphics data and hence shifting data structures throughout memory, those hard-coded values are invariably then incorrect. Oops. The fix of course was to use the label of the table and appropriate arithmetic to calculate the LSB at assembly time.

And as mentioned, in a couple of instances (other) tables were traversed and reset using arithmetic on the LSB only, which obviously worked for the original code as-is but again, after rotating graphics, some of those tables actually spanned a 256-byte boundary and things subsequently went haywire. Fortunately I have copious amounts of memory on the CoCo3 and aligning those tables was trouble-free.

Incidentally during this process I found a minor bug in my original transcode; I was only displaying 3 of the 4 frames of animation for the "squiggly" bomb.

Once all that was sorted, the bombs pretty much worked correctly. I say "pretty much" at this point because there do seem to be times when an inordinate number of "squiggly" bombs are being dropped, and no others. That doesn't appear to happen on the arcade game under MAME. So I need to do further testing on that.

Explosions are a bit messy, but bombs seem to work now!

Now I mentioned that I hadn't taken any notice of the collision logic. So I was somewhat surpised when I was hit by an invader bomb and duly exploded! The shields are similarly damaged, though I haven't visited the explosion routine(s) yet; something I'd negelected to mention in previous posts. As you can see, they currently wreak havoc on the graphics below the laser base.

I'll probably tackle them next, before moving on to player lasers.

Friday, 5 June 2020

Unidentified Fixed Object!

Not a lot of time to work on it today so a quick update - UFO fixed!

The UFO sprite has 4 blank pixels on each side in order to self-erase when flying across the top of the screen, for a total of 24 pixels across. However, when displayed in the score advance table, the code points to the 5th pixel and only draws 16 pixels.

As a result, I had to separately rotate and store both 16- and 24-bit versions of the sprite. The former is rendered by the generic simple (aligned) sprite routine, the latter by a (new) routine to display a 24-pixel sprite.

UFO is rendered correctly now. Getting closer!
Bombs and lasers next!

Thursday, 4 June 2020

Being a bit more specific

Another session tonight and very good progress. Coding object-specific rendering routines is definitely the way to go.

First cab off the rank was the player base. Once I had that sorted, to render the invader it was simply a case of writing a small loop to erase the area above, then branch to the player base render routine, since both objects are the same size.

As a consequence, the invaders now march across and down the screen correctly, as you 'd expect in the finished game.

Player moving, invaders marching. UFO TBD.

I should add that these object-specific routines are indeed faster than the generic routine that was to have replaced the original. Since the object size is known and fixed, there is no need for an inner loop.

I did however discover another complexity in the rotation that will require a little tweaking. The pixel coordinates of objects are actually in reference to the bottom left pixel of the object's bounding box on the original vertical display. Thus far I have been converting it on-the-fly and using a reference point of the top left pixel of the bounding box. I have to further analyze the implications but I'm thinking at this point only the invaders will matter because of the blanking described above, and this was easily remedied in a single ASM instruction.

UFO, invader bombs and player laser to go. Then the matter of the shields. I haven't revisited them this time around, but I vaguely recall there being some particular complexities with the bullets and laser hitting the shields. But if that does turn out to be the case, I have a plan of attack in mind.

One task that I've neglected to mention is the top and bottom of the screen, where the scores and credits are displayed. The vertical resolution of the original arcade monitor is greater than the CoCo3 can display. Fortunately the actual playfield dimensions will fit, and there's sufficient area to either side of the playfield to contain this information. I'm sure you've seen this type of layout on other homebrew ports of Space Invaders.

It should simply be a case of changing a few "magic numbers" in the code/data to move these strings.

And now that I can see the light at the end of the tunnel, I'm starting to think about adding sound. Definitely not one of my areas of expertise, but I think there is sufficient information in the form of blogs and sample code out there that I can leverage off. Obviously I'll be simply playing samples from the early versions of MAME; pretty sure this is a bit too heavy for the CoCo3! 😉

Vertical monitors and self-erasing sprites

In search of low-hanging fruit I decided to fix the logic for detecting the edges of the screen so that the invaders reverse direction at the right point.

I decided the quickest and most reliable process was trial-and-error. I ultimately ended up with the right magic numbers in the code; whether it was the quickest is up for debate. FTR invaders take 8 steps to the right from the starting position, and then 17 steps across thereafter.

However this fix merely revealed another complexity and subsequent shortcoming in the rotation code as-is. In short, when the invaders reach either end of the screen and drop down a line, the previous line is not erased. That had me scratching my head for a while because there is no code to erase an invader.

The further I get in this process, the more I realise how the code is designed around and optimised for a vertical display. Invaders, for example, are always byte-aligned and occupy a single column of video memory, making rendering simple and fast. Contrast that to the rotated case, where they can be shifted across 3 columns and occupy 8 rows.

The generic sprite rendering routine, however, handles non-byte-aligned sprites using the hardware shifter on the board. Thus 8-pixel-high sprites (such as invaders) are potentially able to be shifted and rendered across 2 bytes (columns). But since they're always byte-aligned, the 2nd byte (column) out of the shifter is always zero, effectively wiping the 8 pixels above the invader. This is why there's more than an 8-pixel gap above/below invaders, and why they move down by exactly 8 pixels when they hit the edges. And so when the invader drops down, it erases the old copy.

I also mentioned in the previous post that the invaders also wipe themselves as they march left/right, via 2 blank pixels on either side of the sprite. Together this means invaders never require erasing as they move.

But none of this works when you rotate the screen.

I've thought about it and on first glance it seems rather complicated, if not impossible, to incorporate this into a generic sprite rendering routine without introducing, for example, more graphics data in the form of masks. However I realised tonight that taking this approach is just making things hard for myself.

There's only a handful of objects in the game and rather than try to shoe-horn complicated logic into a generic routine, it would be far simpler - and execute faster - to simply have a rendering routine for each specific object. In fact it'll likely be faster than what I have there now, as I can optimise the order in which bytes are rendered as well.

So my next task is to write a rendering routine specifically for the invaders.

I also saw the saucer/ufo for the first time today. Aside from similar issues to the invaders and the laser base, it looks right! I guess that's not too unexpected; after all, the game should run perfectly as long as the rendering routines aren't actually trashing anything.

Tuesday, 2 June 2020

Leaving behind footsteps

As usual, it's a case of two steps forward, one step backwards.

I've 'improved' the sprite rendering but in the process have discovered a complication that is a direct result of the rotation.

Ordinarily, the invaders march 'across' the screen on a vertical monitor, which means they march 'down' 2 lines in video memory and - importantly - no two invaders share the same video memory byte. Rather than erase the invader before it is moved, the sprite data contains two blank bytes so that the two vacated lines are effectively erased when drawing the updated sprite. Clever.

Having rotated the screen however, invaders now march 'across' the video memory map, moving 2 pixels (bits) each time and the rendering algorithm potentially (usually) writes the same video byte twice. Additionally, adjacent invaders may now simultaneously occupy the same video memory byte. The upshot of all this is; simply writing the sprite data byte to video memory potentially wipes sections of itself and/or adjacent sprites, whilst ORing the sprite data leaves pixels that should otherwise have been overwritten. Catch-22.

The left column of marching invaders show the rendering issue

The solution would likely involve some sort of algoithm and a mask to specifically wipe the leading two columns of pixels. At least that's what I've come up with - in theory. Time will tell.

The original code also has a routine for rendering 'simple sprites' that are always byte-aligned (i.e. the object only moves left/right). A case in point is the player base. After rotating the screen, however, this will not be the case in this example. All that is required for the base, however, is to instead call the more generic sprite rendering routine, so it's an easy fix.

The to-do list also contains; restoring logic to detect edge of screen for the invaders, rendering invader bombs correctly, rendering player lasers correctly and having them not crash the game. And who knows what the saucer/UFO looks like?!?

At this point I'm still looking for 'low-hanging fruit'. In other words, routines that have simple fixes. There are a bunch of sprites that have yet to have their pixel data rotated (the shields being an obvious example in the screenshot above) and that would involve firing up my quick hack rotating software and remembering how it all works...

But all-in-all, it shouldn't be a mammoth task, and I'd like to knock it all off this month!

Addressing some issues

I think I've just doubled the number of posts from last year in just 2 days this year!?!

At lunchtime today I continued where I left off last night. A few red herrings along the way but I've managed to identify a couple of issues that explain the crashes, and even fix one of them.

The game determines whether or not the invaders have reached the left/right side of the screen by simply examing video memory at either extreme of the display, depending on the current direction of the so-called "rack" movement. Any set pixel on the extremity will cause the invaders to reverse direction and drop down (8 pixels) on the screen.

Because the screen is now rotated the video memory addresses of the left/right sides have changed, and it just so happens that the areas in question now both contain pixels. So the logic was reversing the direction and dropping down the invaders every frame, which quickly crashed the game.

This wasn't apparent to me though, because I didn't see the invaders move at all. That's because there was a bug in the algorithm for calculating the invader video memory address; it worked for 'byte-aligned' sprites (as they all are when first drawn) but for non-aligned sprites it stamped all over memory. And that in itself made things even more difficult to debug because the behaviour wasn't always the same.

I've temporarily disabled the 'edge of screen' detection logic so at least I can see the invaders march across the screen. I've debugged - or at least improved - the sprite video memory address calculation routine so the invaders (and incidentally, the player base) appear at roughly the correct location on the display. However it has also become apparent that I need to further 'improve' the routine for rendering a non-aligned sprite, but that's not too surprising given the bugs I've just found.

That aside, the game is running; invaders are marching and dropping bombs and you can move your base left/right. Firing your laser, however, crashes the game. Again, not surprising.

I am happy with the progress and although the rotation is perhaps a little more complex than I originally thought (or recall thinking), I don't think there's much more to be done other than debug and a few extra patches here & there (like edge-detect, which upon reflection is going to run a lot slower than the original). Although I still have graphics data that needs to be rotated.

FWIW my CoCo3 source code can be built either rotated, or not, with a single .define.

Oh and one last thing that I'm a little embarrassed to mention. For years I've been documenting how to run/debug these little projects in various places because I invarably forgot how (MAME command-line options, etc). Only last night it actually occurred to me that I could add various (new) targets to the makefile and have it launch MAME... 😳

A ghost from the past!

Well here we are 18 months on from my last "I'm going to get back into it" post with another optimistic post not worth the electrons it was transmitted with.

This time I make no claims but will report that tonight, for the first time since the abovementioned post, I have actually cracked open one of my unfinished projects.

Of course it took me about 2 hrs to locate the latest source and put together a working development environment that allowed me to simply build the project. At least I took steps to document the process; a lesson I learned in projects subsequent to me starting this one a few years back.

I also got time tonight to take a look at where I was at, refresh my memory on how things work, and start to progress on finishing it off. One bug squashed, but ultimately little effect on progress.

The project in question is the 6809 port of Space Invaders to the TRS-80 Color Computer 3 (aka CoCo3). I have transcoded the original 8080 code to 6809 and have it fully playable on the CoCo3, albeit rotated (sideways).

I had started rotating the graphics by hand, then abandoned that to attempt to do it programmatically on-the-fly, then ultimately backed all that out and continued with my first plan. But I got to the point where most of the graphics were at least rotated, if not displaying in exactly the right location, but the game was crashing after drawing all the aliens. And this is where I picked it up tonight.

As I mentioned, I did find one bug which was sending it off into la-la land but unfortunately fixing it didn't improve the situation to any discernable degree. Another hour or two of debugging and I can see what is going wrong, but not why at this point.

I'll update if/when I make any significant progress.

As an aside, in the last 18 months my transcode (port) of Knight Lore to the CoCo3 has seen a physical release on both floppy disk and cartridge by Neil Blanchard of the CoCo Crew Podcast fame. They look pretty snazzy and I'd post a photo of them here but I can't locate one atm.