I’ve decided to scale back Professor Sinister in order to move on to other projects. Things that didn’t make the cut:
- High score table;
- New level designs;
- New sound samples;
- Attract mode.
With the exception of new level designs, these are all minor features that aren’t important. New level designs would have been great, but I found that larger levels had the effect of overly-emphasizing the simplicity of the game. The larger the levels, the “thinner” the game feels. Redesigning levels within the existing size constraints isn’t interesting, so I’m keeping the original designs.
The last thing to do is the bitmap for the title screen. I have no idea when I’ll get around to that.
Here’s an almost-final version:
I had to check that the game wasn’t completely invisible on an original, unlit GBA-001. Here it is:
It’s no worse than any other game on the system. Thanks to the GBA-001’s horrible screen that’s the best picture I could get.
Here’s a screenshot:
In an effort to make the title music less repetitive I’ve been working on an updated version:
It has an additional section, but I’m worried that it’s now too varied. Still, this is the version I’m planning on using.
Here’s the last Professor Sinister track:
This is the title screen music.
I’d planned to put up a post with piano demo tracks of all three chiptunes, but unfortunately all but one have conversations over the top. Here’s that one, anyway:
This was the last 10 seconds of almost 3 minutes worth of piano doodling. I’d got an idea of what the tune should sound like, solidified the ideas on the piano, wrote it up in MilkyTracker, and found that I hated it. The final chiptune came almost entirely from this little snippet of music that was a throwaway accident at the end of the demo recording.
“Oh Well” and “Climb Time” both came from noodling on the piano, which I find is a much more efficient way of discovering melodic ideas than trying to come up with something directly in a tracker. “Something Sinister” on the other hand was entirely written in a tracker, except for the basic 4 chord progression that it uses. That came from another piano noodling session.
There are a few obvious changes in this build and some behind-the-scenes fixes.
There are now graphics for the duck. I went through a number of different ideas for what the duck should look like:
- A Sinistar-style skull (full face view);
- A Terminator-style skull (2/3 view);
- A demonic face;
- A modified version of the existing robots (a different color with flames coming from beneath it);
- A robot bird/pterodactyl;
- An Impossible Mission-style sphere.
I think the Terminator-style skull would have been the best option, but I couldn’t get it looking anywhere near right. The design had to be limited to what I could actually draw, which turned out to be a pulsating eyeball. It has nothing to do with the “marauding mechanicals” theme but it looks neat, so pulsating eyeball it is.
In order to change the shape of the duck I had to change how the library determined if there were collisions between Harry and other game objects. Specifically, I had to move the collision test code out of the library entirely and add a callback to the game’s delegate so that the user of the library could create its own collision test based on the shape of the sprite bitmaps. I tightened up the collisions at the same time.
On the subject of the duck, I rewrote its movement again. Now it’s pretty close to the original Chuckie Egg.
The sprites now appear behind the score indicators at the top of the screen thanks to the GBA’s ability to interleave sprites and tiled backgrounds.
The scrolling system used to support arbitrarily-large levels is now a separate class. I ripped most of the code out of the text scroller and replaced it with the new scroller class.
The ROM is 70K smaller. Most of the savings came from removing unused sounds or converting stereo sounds to mono.
Lastly, the high score music is in the game. It’s in the wrong place, however, as there’s no high score screen yet.
The todo list is getting shorter:
- New sound samples.
- New death music.
- New level designs.
- High score screen.
- Title screen bitmap.
- Title screen music.
Two of the three music tracks necessary for Professor Sinister are ready to go. Here are the completed tracks:
“Climb Time” is the in-game tune. “Oh Well” is the game over/high score tune. Both tracks are chiptunes. They’re embedded in the same XM and share instruments. Both also sound significantly less crisp on the GBA’s anemic speaker and crummy sound hardware.
I have a name for the title music, which is the last outstanding track: “Something Sinister”. I don’t have a tune yet though.
I’m thinking of adding a “disable music” option to the game.
Here’s a video of the latest build of Professor Sinister:
The most obvious change is the inclusion of the score/level/etc indicators at the top of the screen. Those are implemented as tiles in one of the GBA’s 4 background layers, giving us one layer for the text, one layer for the platforms, one layer for the parallax background, and one spare layer.
It wasn’t really noticeable in the previous video, but there was a little flickering at the top of the screen in both the sprites and the background tiles. It turns out that my belief that there was no performance work to do in the game engine was incorrect. Representing the vacuum tubes and power packs as “game objects” (essentially a data structure representing a sprite) instead of just inspecting tiles in the level data meant that the game had to iterate over them all when testing for collisions. That taxed the GBA’s tiny brain just a little too far.
The game just about got away with it until I decided to support larger levels with larger quantities of collectible items (demoed in the video above), at which point the horizontal tearing was too awful to ignore. I had to rewrite the egg/chicken feed code in the SZChuckie library, and then update both the Professor Sinister and the Chuckie Egg front-ends to match. Larger levels will let me take advantage of features of the engine that Chuckie Egg can’t use, such as arbitrary numbers of vacuum tubes, power packs, elevators and robots.
The game now has a “Simian Zombie” logo screen and horizontal scrolling text on its title screen (but it’s really inefficient so I’ll probably rewrite it), and a functioning “get ready”/“game over” screen.
I rewrote the way that the duck moves. The old code was pretty nasty and only managed to move the duck in one of 8 directions (horizontal, vertical, diagonal), whereas the new code uses vectors (correctly this time) to calculate a more direct route to the player. I still haven’t come up with a new design for the duck, though, so it’s not visible in Professor Sinister yet.
Speaking of design, here’s some more detail on Professor Sinister’s graphics. I originally wanted the robots in Professor Sinister to look like something from a 1950s sci fi movie: clunky and boxy, and covered in flashing lights. Their bodies would be separated into two distinct parts, so that when they changed direction the bottom half would spin 180˚ before the top swiveled around to match. I eventually ditched that idea because it would slow down the gameplay and would require far too many changes to the Chuckie Egg library.
I refined the pool of robotic inspirations down to just two: the robots from “Wallace and Gromit” and “Forbidden Planet”. In the former, I liked the little wheel that the robot scoots around on. In the latter I liked the bulbous design, segmented arms, and pincers.
The first design I came up with was very similar to the version that ended up in the game:
It was taller and thinner, however, so that when I tried transferring it into Aseprite I quickly realized that it was entirely the wrong shape. The robot was too tall for the 16x16 sprite and didn’t take up enough horizontal space. At that point it seemed that I’d have to ditch the design entirely, because trying to squash the robot into a wider, more cylindrical shape (from Robo to Mobo) didn’t work at all.
I gave up on the robots and switched to Professor Sinister. I was aiming for a cross between Dr Robotnik from “Sonic the Hedgeghog” and Dr Wily from “Mega Man”. Most of what I draw ends up looking like something from “The Far Side”, so that’s where I started. I knew I wanted thick, opaque glasses, a round head and body, and a lab coat, but the lab coat never looked right and neither did the body:
In pursuit of new ideas I briefly toyed with the idea of making the professor female, but I didn’t get very far with that. Instead I tried out an egg-shaped head (referencing Chuckie Egg) with feet directly attached to it, like Dizzy, and it looked pretty good:
Once I had a sketch to start from, getting the character into Aseprite was easier than I’d expected. The only feedback I got on the sprite was “it looks too much like an egg”, so I added a ring of white hair around the top of his head to hide his eggy-ness.
“Rick Dangerous 2” provided much of the palette for the professor. Its graphics are wonderfully cartoony and vibrant. I’ve always wanted to make a game that looked like Rick 2. Borrowing colors from its palette seemed like an obvious first step.
With the professor finished I realized that I could keep the egg theme for the robots. I took the egg shape, flipped it upside down, and suddenly the design worked:
It took some flipping between Aseprite and Acorn to get the sprites into a form that Grit could convert to C code. Grit of course utterly failed to produce correct palettes. I had to figure out which index Grit had assigned to each of the 60 or so colors used in the game and the set up the palette in code. Each minor edit to the graphics completely changed the layout of the palette, meaning more manual palette layout. I later discovered that although Grit can’t produce a palette from BMP, PNG or PCX files, it will correctly convert palettes from GIF files.
Testing out the graphics revealed a problem with the professor sprite. In Chuckie Egg, Harry’s feet are precisely aligned with the collision area between Harry and the floor. It’s possible to be pixel-perfectly accurate in moving him to the edge of a platform. In the new graphics I’d made the professor’s feet much larger and had completely lost that accuracy. I had to redraw the feet to line up with Harry’s.
The ladder uses some of the palette from Rick Dangerous 2, as do the background tiles (which were heavily influenced by some background tiles in one of the Rick games). The platforms are also similar to platforms in Rick 2.
I created the vacuum tube and power pack tiles, and the elevator sprite, entirely from scratch. I had a look at a couple of vacuum tubes on Google for inspiration, but otherwise I didn’t have any reference for these graphics.
As for the duck, I had a couple of ideas: a sphere (in reference to “Impossible Mission”) or a demonic robot face (like “Sinistar”). Then I remembered that it needs to be roughly the same shape as the duck or the collisions won’t work correctly, so I’m now considering some kind of robot pterodactyl thing.
The todo list doesn’t seem to be getting any shorter:
- Add a title screen bitmap.
- Write music for the title screen.
- Write music that plays when Sinister is killed.
- Create new graphics for the duck and its cage.
- Replace the sound samples.
- Add a high score screen.
- Replace all level designs.
- Add an attract mode.
I’ve given up on Chuckie Egg for the GBA. Not because it got too complicated; the opposite in fact. I wanted to play with things the GBA will allow me to try out, like parallax scrolling, chiptunes and pixel art, and remaking a four color Dragon 32 game just wasn’t cutting it. I still adore the game though. I’m keeping the engine but I’m going to do a full reskin with new graphics, music, sound, and possibly new level layouts.
The remake was drifting further and further from the original anyway. The first change I made was to eliminate the flicker. Then I added scrolling for the GBA, and then I replaced the music with XM versions. Why not just modernize the whole thing?
The new game is called “Professor Sinister and his Marauding Mechanicals”. You play Professor Sinister, an evil scientist who created robots to help him destroy the world. Unfortunately his robots have gone wrong and he’s lost control of them. The Chuckie Egg hens have become robots, the eggs have become vacuum tubes, and the chicken feed has become little power packs.
I’ve added parallax scrolling and a little chiptune. As per usual there’s a large list of things left to do, but here’s a video of the state of things so far:
Though the graphics are all original, they draw from a number of different influences. I wanted the robot to look something like a cross between the robot from “A Grand Day Out with Wallace and Gromit” and the robot from “Forbidden Planet”. The palette and background was inspired by Rick Dangerous 2. I referenced the Master System version of “Wonder Boy in Monster Land” when drawing the life indicator. The original sketches for Professor Sinister looked like something from “The Far Side”, but as a 16x16 sprite that doesn’t really come across.
Here’s a video of something old-but-new I’ve been working on:
It’s Chuckie Egg, but for the GBA.
How did I manage to squeeze the bitmap-mode UI library built for a dual-CPU 66/16MHz DS into a single-CPU 16MHz GBA? With full-screen scrolling?
I didn’t even try.
Extracting A Library
I mentioned before that the games I’ve been writing with SZLib adhere reasonably strictly to the MVC architecture. The game logic forms the “model” portion of that architecture. If done correctly, the game logic could live in an entirely separate library from the code that handles graphics, sound and user input. That’s what I’ve done to get this working: I moved the model to a new “SZChuckie” library and created a new front-end project that uses the GBA’s tile-and-sprite graphics modes.
Splitting out the game library was mostly trivial, but somehow took far longer than I expected. References to bitmaps, sounds and user input handling had all found their way into the game logic. For example, each of the sprite-esque things in the game (eggs, chicken feed, hens, ducks, Harry) stored an array of bitmaps that represented their animations. The view controller could ask for the current bitmap in order to display the correct image in a view. I had to replace the bitmap reference with a more abstract “animation frame” object, which ditched the bitmap data and stored just a size and a frame number. The view controller now stores the bitmaps and uses SZLib’s type introspection to figure out which bitmap to display for any incoming
didChangeFrame events emitted by the game object. The class that represents a level had a function for generating a bitmap from its level data which the view controller used as the game’s background; I moved that into a separate file.
Pulling the sounds into a higher layer meant adding more callbacks to the game object’s delegate. The delegate - in this case, the view controller - can respond appropriately and play the correct sounds.
Input was similarly straightforward. I added a new d-pad/button class specific to Chuckie Egg (so there’s a “jump” button instead of “A” and “B” buttons) and pass its state to the game whenever I call its
update() function. As a side-effect, this fixed a few places where the game wasn’t responding correctly to some button presses or the analog stick.
The most long-winded changes were purely administrative: renaming all of the files/classes/etc; creating makefiles and build scripts; and testing that nothing was broken.
With all that done I could move onto the GBA port, which of course started with more administrative work. I needed to get three libraries from SZLib building for the GBA: the core library, which includes reference-counted objects, boxed primitives and collections; the geometry library, which includes points, sizes and rectangles; and the hardware abstraction library, which includes abstractions for initializing the hardware, sound, vwaits and hardware division. Those all needed makefiles. I used the makefile from libgba as a template. With the makefiles in place I could add GBA support to the hardware abstraction library, which involved digging through libgba’s headers to find the appropriate function calls (where available) or disabling the functionality (where not). The core and geometry libraries just worked.
That all put the project in a very weird place. Typically when I start a game I get enough of the logic working to start pushing pixels around on the screen, and from there the logic and graphics code evolve in parallel. Somewhere near the end of the project I’ll add sound. However, in this project I just had to link the game library and hook up a few callbacks to get a fully-working and audible, but invisible, version of Chuckie Egg.
Programming the GBA isn’t particularly difficult. Well, it shouldn’t be difficult because it’s a very simple platform. It’s a little harder than it needs to be because libgba has no documentation and the canonical tonc guide references constants that don’t match libgba, so I find myself trying to interpret memory addresses rather than looking for the names of those addresses. The command line graphics conversion utility that ships with devKitARM (
grit) has a tendency to either get things wrong (it refuses to generate a correct palette for me) or be unhelpfully helpful (some combination of settings causes it to insert a blank tile at the start of a tile map, causing me to spend far too long trying to figure out why I couldn’t fill the screen with the tile I wanted).
Once I really get the hang of the GBA I’ll hide all of its features behind an abstraction library that I can make cross-platform, which will let me debug my code on my development machine. With neither a debugger nor the ability to
printf() on the GBA I’m wasting far too much time running C in my head.
The GBA’s screen is 240x160 pixels, which is about 20% smaller than the Dragon 32’s resolution of 256x192 (this is a remake of the Dragon 32 version). The DS port was very fortunate in that the DS’ resolution is also 256x192, so there was no need to scroll or scale the game to get it to fit. For the GBA port I decided to opt for scrolling as it’s so simple to achieve (just change a couple of registers). It refused to work for a while until I dug up a comment in one of the examples that noted that the registers are write-only. Duh.
I think that the scrolling works really well. The levels aren’t much larger than the GBA’s screen so it’s impossible to get disoriented or lost. It is possible to get into a “leap of faith” situation where a player might jump from the top of the level hoping that there’s something at the bottom to catch them, but it doesn’t make the game less enjoyable (at least, not for me, but then I know these levels backwards so I’m not a great test subject).
The unmodifiable parts of the levels - the floors and ladders - are implemented in a tiled background. Everything else - the hens, duck, eggs, chicken feed and Harry himself - are all sprites. That gives me around 30 sprites per level, which the GBA throws around without breaking a sweat. I’m considering changing the eggs and feed to become tiles within the background if performance becomes a problem.
Sound is powered by MaxMod. The API is slightly different to the DS’ version, but they’re similar enough that making sound work was simple.
I wasn’t particularly worried about performance. From the considerable amount of perf work I’ve done on the DS version I know that the overwhelming amount of work the game does is in the UI libraries that I’m not using.
Everything was progressing well until I hit a massive problem. The game worked perfectly in mGBA and VBA-M, but it refused to do anything but display a green screen on a real GBA. Every time I’ve encountered something like this on the DS it was caused by a memory problem. The DS emulators I use don’t accurately model the behavior of memory on a real device, so problems like allocating the wrong amount of memory, forgetting to initialize variables, and using memory after it’s freed (etc) can crash real hardware but cause no problems under emulation. I set about investigating.
First step: Code inspection. Was I allocating the wrong amount of memory for my objects? That’s a mistake I’ve made repeatedly in SZLib: allocating enough memory for a pointer to a struct rather than the struct itself. Nope. Forgetting to initialize variables? Nope. Leaking memory? Nope.
Next: Run the SDL version through a static analyzer. No problems.
Next: Run with the address sanitizer enabled. No problems.
Maybe the problem is in the GBA front-end code. I
#ifdef-ed out enough of the GBA-specific code to get it compiling on my dev machine and ran that through all of the available code/memory checking tools. No problems.
Let’s dig back through the Git history to find a version that did work on the GBA. Rolling back a few days gave me a version that worked. It seemed that I’d subsequently made a change where I stopped writing to an intermediate buffer representing the OAM (object attribute memory; for sprites) and wrote directly to it. Undoing that change didn’t fix the bug.
I started to remove arbitrary pieces of code that caused memory allocation to occur. Sometimes a change would allow the game to run; sometimes a different bug would manifest. It made no sense.
I enabled libgba’s console output and wrapped
malloc() so that it would print the address of the allocated memory. No clues there: all of the addresses were safely contained within the correct region of RAM. Then I started printing out the addresses of stack variables. It seemed that I was getting close to the end of the stack, which perhaps made sense. Stack variables are stored in a 32K block of memory (IWRAM) which is immediately adjacent to a 1K block of memory that controls I/O. Overflowing the stack would cause weird behavior. Immediately following the 1K I/O block is a 1K palette block. One of the changes I made to the game caused the palette to start cycling. Aha, that seems likely. But how am I overflowing the stack? And why doesn’t that bug show up in the emulators?
I started up mGBA and took a look at its memory viewer. According to that the game uses a tiny fraction of the 256K and 32K RAM blocks. There’s no way it should be overflowing the stack or encountering problems related to memory shortages.
Perhaps there’s something wrong with the GBA itself. I recently got hold of another backlit GBA which is the device I’ve been testing on. I haven’t used it for playing games; maybe it’s defective? Nope, same problem on another device.
At this point I’d wasted three evenings on this ridiculous problem and, although I’d learned a significant amount about how the GBA’s memory is laid out, I’d made no progress in figuring out the cause of the issue.
I put everything away and thought about the problem some more.
There’s nothing wrong with the majority of the code. It’s running on 4 other platforms without issue. I’ve tested it with every analysis tool at my disposal and can’t find any problems. The code that’s specific to the GBA amounts to less than 1,000 simple lines, and I analyzed most of that too. The fact that the game runs perfectly under emulation suggests it isn’t a library or compiler problem. It isn’t a problem with the GBA hardware because it exhibits the same behavior on two different devices. It isn’t a memory exhaustion problem. So what’s the difference between running the game in an emulator and running it on my GBA?
The flash cart.
Could it be the flash cart?
I’ve got an EZ-Flash IV (one of the older ones that uses mini-SD cards). It runs its own code and patches ROM files in order for them to work correctly. Could the flash cart be breaking the ROM? Fortunately I’ve got a couple of older flash carts lying around. Copy the ROM to my Supercard SD and…
It works. Perfectly.
The EZ-Flash is doing something bad to the ROM, causing it to write to bad memory addresses, causing bad things to happen. There’s nothing wrong with my code. And there was no way I was ever going to debug that problem.
There’s plenty of work left to do before the game is finished:
- Add a “Simian Zombie” screen.
- Add a title/high score screen.
- Add level/life/score/time/bonus indicators.
- Show the “Game over” screen when the player dies.
- Show the score increasing when the player completes a level.
- Show the “Get ready” screen before each level.
I also want to add an attract mode showing little demos of gameplay that appear after a few seconds idling on the title screen. I’m thinking of using that system to show how to perform various techniques in the game (like grabbing ladders easily, bouncing between ladders, etc). Oh, and then there’s the level editor that I didn’t finish, too, but that makes less sense on the GBA as it doesn’t have a writable file system.
While trying to come up with more optimizations for SZLib’s drawing system I came across something called “scanline coherence shape algebra”, which is an algorithm described in a book called Graphics Gems. It attempts to provide an efficient algorithm for computing “the visible regions of overlapping windows”. Aha, exactly what I’m looking for. I had to try it out.
In brief, the algorithm stores the shape as a list of “spans”. Each span consists of a y co-ordinate and a list of “segments”, which are just x co-ordinates. Spans are sorted by their y value and segments are sorted by their x value. Put together, they describe an arbitrary shape. The algorithm supports union, intersection and subtraction operations.
For the first pass at an implementation I followed the algorithm described in the book (as far as I could; the pseudocode for the special cases is too vague to implement in some places). I used linked lists to represent the spans and segments, and of course that required an overdose of
malloc() to create each node in the list. For the second pass I switched to using arrays to store the data and kept a pool of pre-allocated arrays to limit
malloc() as much as possible. That was a little faster, but still not fast enough. For the last pass I switched back to linked lists but built a version that uses a combination of a pair of pre-allocated arrays and couple of stacks to store the linked lists and eliminate all calls to
So, how does the new shape algebra code compare with the existing code? It’s really, really, amazingly bad. Really bad. On my development machine, adding rects to the damaged rect manager in my test application using the existing code averages about 5ms of CPU time per 1s of wallclock time. The new code averages about 100ms of CPU time per 1s of wallclock time. The existing code is 20x faster than the new algorithm.
At that point I gave up on it. It’s likely that rendering damaged areas would be faster using data produced by the new code as it automatically consolidates adjacent rectangles, but given that this single operation uses 20% more CPU time than the entirety of the rest of the test application it’s completely impractical.
It did give me a few ideas for other optimizations for identifying intersection failures, though:
- Sorting the rectangles within the quad tree first by their y and then their x axis;
- Maintaining a rectangle that represents the bounds of the damaged area within each quad tree node.