Ghost of bugs past


There are ghosts haunting the place now!


The vertical ghosts are simple hi-res sprites. The horizontal ghosts have a dark grey overlay. The animation is four frames.


And now for an interesting bug...

First, to give a bit of background for people who are not familiar with C64 sprites: The C64 screen is 320 pixels wide. Moreover, due to the borders, the (X, Y) sprite coordinates of the upper corner of the screen is not (0, 0), but (24, 50). This means the X coordinate of the sprite can be as big as 343 and the sprite will still be visible (and even more, if the side borders are opened, but let's ignore that for now).

However, the VIC registers are all 8 bits in size, meaning they can only hold values between 0 and 255; but you need at least 9 bits (0-511) to fit the X coordinates of the sprites. To remedy this, in addition to the 8-bit X register for each sprite, there is an extra bit in another register that is set if the sprite has crossed the 256th-pixel boundary, effectively making X a 9-bit value. Without this bit any sprite trying to go past the 255th pixel will simply wrap around to 0 and disappear behind the left border. 

There are 8 sprites in the system, each one with its own extra bit. All these are gathered in a special register at address $D010. This register is effectively a bitmap; so for example if its value is 5 (%00000101 in binary), it means sprites 0 and 2 are on the right side of the screen.

Ooze never had to deal with this because of the UI on the right side prevented the sprites from crossing the 256th pixel. Shift, on the other hand, had to handle this bit because the Shift Guy could run around anywhere on the screen. Nixy's code is basically Ooze and Shift merged together, so Nixy can run and jump everywhere on the screen too. So far so good.

Now there is another piece of code that converts Nixy's sprite coordinates to the screen tile coordinates (yes they are different, and so are their binary representations...welcome to C64). The game uses this to read the tiles around Nixy and decide how she should interact with the world (is Nixy standing on solid ground, is her way forward blocked, etc.). This code needs to be mindful of this extra bit, because if it is set it means the sprite is an extra 32 tiles (tiles are 8x8, and 32 * 8 = 256) further down the screen (the tiles are arranged sequentially).

And this is were the bug happened: In Shift there were no enemies, just the player sprite. So as a simplification the conversion code assumed that any non-zero value of the $D010 register meant the player was on the right side of the screen. But this is not the case for Nixy; the player can be on the left side, but if there are any enemy sprites on the right side of the screen that register will have a non-zero value. This confused the code by sometimes making it think Nixy was 32 tiles further than she really was, and led to amusing results.

In the image below, due to the ghost on the right side, the register at $D010 is non-zero. See how Nixy suddenly "snaps" to the plant when walking left, and then refuses to walk any further. This is because the code thinks she is 32 tiles ahead and has effectively sunk into the ground!


And in the image below see how Nixy happily walks to the left until the ghost reaches that boundary, after which she seems to get stuck on thin air. Once the ghost is back to the left side of the boundary, Nixy continues. Also notice that when the ghost on the right Nixy walks out of the boundary instead of going to the next screen:


This is all because where the code thinks Nixy is not always where she actually is. 

Finding the root cause was confusing and tricky at the beginning, since all the variables and VIC registers looked correct. But once I had found it, I fixed it by adding a single "AND" instruction to mask out the enemy bits before using the value in the calculations. Typical of most bugs; taking a long time to find the root cause and a few seconds to fix.

Get Nixy and the Seeds of Doom (C64)

Download NowName your own price

Comments

Log in with itch.io to leave a comment.

Looking awesome...!!!  Can't wait til this comes out...!!!  : )

Interesting background info.. thanks for sharing