2018-10-13

Professor Sinister v20181013

PypeBros kindly created a title screen for Professor Sinister, so here’s a new release:

In addition to the title screen, this latest version includes some bugfixes, tweaks to the music and improved audio quality.

Get in touch if you have a way of getting the ROM onto one of those cheap reproduction carts that folks sell on Etsy. I’d love to have a physical copy of this on a dedicated cart.

2018-08-05

Professor Sinister v20180805

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:

Professor Sinister Original GBA

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:

Professor Sinister Screenshot

2018-03-19

Amy Zing Update

A while back I released a very simple game called AmyZing and the Amazing Mazes. Somehow this ultra-minimalist game attracted the attention of a DS homebrewer called PypeBros, who offered to put together a sprite of Amy herself. You can download an updated version with his sprite here:

I dug out a tracker for the first time in over a decade to add a little chiptune to the game. Only DS and PSP users get music as I still haven’t found good audio libraries for the Dreamcast or 3DS.

2017-11-28

Amy Zing and the Amazing Mazes

This is a very little game created solely for one very little toddler who kept harrassing me to draw mazes for him to solve. The effort involved in creating the mazes vastly outweighed the effort it took him to solve them, so I figured I needed to automate it. The game is loosely based on the snail maze built into some revisions of the Sega Master System BIOS but it isn’t a remake. Like the snail maze, the objective is to guide the red square through the maze from the starting point to the finishing point.

Here’s a screenshot:

AmyZing

I used the Kruskal algorithm to generate the mazes. On the linked page the author complains that the algorithm “tends to create a lot of short dead-ends”, but that property makes it perfect for toddlers who don’t have the patience for extensive backtracking when they take the wrong path.

The game itself took almost no time at all to write; excluding libraries and presentation fluff the game weighs in at around 600 lines of C. The most complex tasks were fixing a weird rendering bug (that turned out to be a missing conversion between co-ordinate systems in the layer library) and writing a bunch of transitions between scenes. The first, and most troublesome, transition looks just like this one I made 7 years ago in JavaScript (hit refresh if the image doesn’t show up; the script doesn’t preload the image), but with the addition of fade out as the image disappears. Unfortunately that proved too complex for both the DS and the 3DS to render at 60fps so I replaced it with a simpler cross-fade transition.

There’s no title screen bitmap and the player’s character is just a red box. I’d intended to come up with a pixel art title screen showing Amy Zing herself, and an Amy Zing sprite that would wander around the mazes, but that’s beyond the limit of my drawing ability (if anyone is interested in contributing a title screen and a sprite in 3 sizes, let me know).

Tinkering with menu systems, transitions, difficulty levels, presentation and general polish took long enough that the toddler in question has long since lost interest in solving mazes.

Download it here:

2017-10-15

SZLib 3DS

Just in time for it to be killed off by Nintendo in favour of the Switch (if you could ever find them in the shops; grumble grumble), Hanky Alien and Chuckie Egg now run on the 3DS. Getting the new platform up and running was pretty easy. Input was straightforward: the d-pad required switching to a couple of new functions for reading the button state but otherwise the constants are the same in libctru as those in libnds. Touch somehow just worked, which was surprising.

The hardest part was getting the graphics up and running. Not only does the 3DS introduce yet another set of RGB encodings, but the output of the LCDs is rotated 90 degrees from the VRAM. What’s that? You have a bunch of 2D graphics functions that are all optimized around VRAM being laid out in rows, from left to right? Bwahaha! Now VRAM is organized into columns, from bottom to top.

Though graphics were the trickiest part, the most laborious exercise was checking that the projects continued to build correctly for all 5 of the currently supported platforms (DS, 3DS, PSP, Dreamcast and SDL). I really need to come up with a better build system for the PSP and Dreamcast, and it’d be neat if devKitARM supported makefile names other than “makefile”.

There are a few things still to do:

  • libctru introduces yet another sound API, so there’s no sound yet;
  • SZLib doesn’t cater for the possibility that a device has multiple screens with different dimensions, so the bottom screen is off-center.

Anyhow, here are early 3DS builds, which I’ve tested out on my old 3DS XL and Citra (which is shaping up to be a great homebrew tool):

2017-04-10

Chuckie Egg 20170410

With egg hunting season almost upon us, it seems appropriate to release a little update for my favorite egg hunting game. Grab it now:

I’d hoped to get a level editor into the next release, but it’s not finished. This version fixes a few bugs and adds a couple of minor new features.

Changelog:

  • Scores are persisted on DS and PSP.
  • PSP analog stick can control Harry.
  • Fixed crash when completing a level if a cheat label is showing.
  • Fixed crash when switching to high score table.
  • Harry dismounts ladders correctly when climbing and jump is pressed.
  • Player does not get points when hens eat grain.
  • Bonus cannot be negative.

I haven’t looked into working with the Dreamcast’s VMU yet.

2016-11-19

Chuckie Egg Releases

Just in time for the holidays, here are final versions of Chuckie Egg for DS and PSP, and an almost-final version for the Dreamcast:

Chuckie Egg DS

Post Mortem

PSP

The PSP has a huge screen. Well, relative to the DS; maybe not so huge if you compare it to a modern phone. What do you do with all that space if you’re remaking a game that fits in 256x192 pixels? The obvious thing to do is double up the pixels and make the graphics twice the size. But wait; at 272 pixels tall the PSP’s screen is only 70% larger vertically than the Dragon 32, which means we can’t double up the resolution without losing 30% of the game’s display. I imagine it’s possible to wrap the game’s bitmap onto a quad and get the GPU to stretch it, but I eventually decided just to centre the game at its native resolution.

The PSP’s screen is 480 pixels wide but its default framebuffer is 512 pixels wide. Trying to change the width of the framebuffer to match the screen does not work (it results in the display being smeared horizontally, which always means “the dimensions of your bitmap do not match the layout of memory”). I had to add in the concept of “usable” vs “available” framebuffer space (“physical” vs “logical”, I suppose) and base the layout of the various screens on that.

It’s possible to push the PSP’s “home” button and quit from a game back to the launcher. Making this work entails creating a background thread and wiring up a callback that the OS can use to signal to the game that it needs to quit. It’s very simplistic; if the game doesn’t implement the callback then the system just hangs forever. The OS doesn’t appear to forcibly quit rogue processes. I’m not even sure that it’s really a multi-process system. I imagine Sony handled errors like this in their QA process so they didn’t bother with anything more elaborate to catch badly-implemented games.

Different geographic regions have different PSP button layouts. I don’t quite know what Sony thought the advantage of swapping the O and X buttons was, but it means well-behaved homebrew has to work around it. Games typically either allow the buttons to be remapped or come in different builds for different layouts. Official games were region-locked so that wasn’t an issue; it was probably fixed during localization. I’m too lazy to deal with it.

Getting sound working was troublesome. The basic PSPSDK libraries offer a way - I think - to craft PCM data and play it back, which really doesn’t help if you just want to play a WAV and not put any thought into it. I ended up using libmikmod, which has some peculiarities. Its MikMod_Update() function must be called regularly in order for sounds to work, but that can be stuffed into another background thread and forgotten about. It offers two ways to play back samples: Sample_Play(), which will automatically choose a channel to play back on, and Voice_Play() which lets you choose the channel. I found that Sample_Play() always chose exactly the wrong channel and ended up stopping sounds that I wanted to continue playing, so I switched to the alternative function. Voice_Play() doesn’t have any useful documentation. Inspecting the library’s code reveals that the trick is to set the volume, frequency and panning of the voice each time a new sample begins:

Voice_Play(channel, sound, 0);
Voice_SetVolume(channel, sound->volume << 2);
Voice_SetPanning(channel, PAN_CENTER);
Voice_SetFrequency(channel, sound->speed);

DS

The DS has a second screen. What do you do with two screens when remaking a game designed for one? I had a few ideas:

  • Level editor;
  • Chuckie Egg title screen;
  • Simian Zombie logo;
  • Dragon 32 image.

In the end the SZ logo was simplest, so I went with that. Otherwise, the DS is my default platform, so there aren’t any surprises here.

Dreamcast

It appears that calling snd_sfx_stop() on a channel playing a stereo WAV file will only stop one of the channels, which explains why sounds weren’t behaving themselves in the beta. Switching to mono files fixed it. Another problem was caused by limitations of the audio hardware: the Dreamcast can only play back the first 65534 samples in a WAV file, which is far shorter than several of the sounds in the game. To work around this I halved the sample rates of the longer samples. That fixed most of them, but the title song and Spectrum loading sound were still too long. I converted those to MP3 and used the streaming API, but that created problems of its own. Sounds still cut out or don’t play, and the emulator I’ve been using to help development crashes whenever I call mp3_stop(). There’s still some work to do there.

The DC has a similar problem to the PSP: I’m using the 320x240 NTSC graphics mode, but a good portion of that is off-screen on my TV. The “usable” framebuffer space concept helped out here.

The DC feels noticeably faster than the other two platforms, which is odd, as I’d expect them to run at identical framerates. Perhaps it’s just because it runs on such a massive display.

The Dreamcast’s reversed ARGB ordering means I’ve had to convert bitmaps into both DS and DC sourcecode and use #ifdefs to choose the right version of the data for the current target platform at compile time.

Cross Platform

What was most surprising was how little effort I had to put into Chuckie Egg in order to make it performant on these different platforms. The effort that went into Hanky Alien presumably helped a lot. I was testing HankyAlien with up to ~140 views on screen at once and up to ~45 of those updating simultaneously. In contrast, despite superficially being a more complex game, Chuckie Egg has ~45 views on screen at once and only ~10 updating simultaneously. (It’s interesting to note that, while both the DS and DC struggled with the HankyAlien test scenario and their framerates suffered, the PSP sauntered through it without a hitch. I really must write something specifically for the PSP in future.)

Writing object-oriented C is fun, but sometimes I look at the amount of boilerplate necessary to create a new “class” and decide to do things another way, particularly if I’m creating a base class. The most simple class requires:

  • A static metaclass struct, which forms a linked list back through the chain of superclasses (it enables the program to determine the type of an object at runtime).
  • A static callback struct that includes pointers to equality/comparison/hash/copy/dealloc functions.
  • Declarations of those functions.
  • Implementations of those functions.
  • A struct with the member variables of the class.
  • A typedef that defines a pointer to the struct, allowing the struct to be hidden.
  • A constructor that calls the allocator and initializer methods of the class.
  • An initializer function that sets up the members of class instances and calls back to the superclass’ initializer.
  • A convenience release method that wraps the basic release method.

If the class is intended to be subclassed it must also:

  • Provide an additional private header including:
    • A callback struct definition that nests the superclass’ callback struct and enables “methods” to be “overridden” (really it’s the template pattern with function pointers).
    • The struct itself, so subclasses can directly access properties of the struct and include the struct as the first item in their own structs.
  • Call the functions in the callback struct when appropriate (including those for the superclass).

Every time I create a new class I do so by copying-and-pasting an existing class and modifying it rather than start it from scratch and have to retype all of the boilerplate. Sometimes I’ll think about the work involved in setting one of these things up, pine for C++ or Objective-C, and then use a different structure that’s less “correct” but will still get the job done without smelling too badly. The grain and eggs, for example, should really inherit from a single “collectible item” class, but the correctness of that design doesn’t in any way compensate for the amount of work involved in setting it all up.

Keeping a strict separation between the model (game logic), the views (the stuff you see on screen) and the view controller (delegate of the model; updates the views to match incoming events) results in some beautifully clean code but makes prototyping difficult, especially early on when none of the infrastructure is in place. I did most of the early prototyping in the view controller before moving it into a separate model.

Each level renders its static content (ladders, platforms and bird cage) as a bitmap when it begins. It passes that up through the model to the view controller, which uses the bitmap as the background view for the game. That eliminated the need to create dozens of views to represent tiles that never change during the course of a level.

There are now 134,000 lines of code in the project, but a sizable number of those are included in bitmaps that have been converted to C.

2016-11-10

Chuckie Egg

Back in the early eighties, when the home computer boom was booming, my parents decided to buy themselves a computer. Following the advice of various computing magazines of the era they ended up with what was supposedly the best of the bunch: the Dragon 32. It featured 32K of RAM, a real keyboard and a Centronics parallel port. It was powered by Bill Gates’ favourite 8-bit CPU, the Motorola 6809. Unfortunately for my parents and their new Dragon, the manufacturer ran into financial troubles and collapsed not long after.

The unusual choice of the 6809 CPU meant very little software was written for or ported to the platform. One of the few games that made it was the BBC and Spectrum classic “Chuckie Egg”. This obscure port (the World of Spectrum doesn’t list it) is by far my favourite version, and it’s the game I spent the most time playing on our Dragon. There has never been a remake of it. Worse, neither the Dreamcast nor the Nintendo DS has a native version of Chuckie Egg. Let’s fix that.

Here’s a beta version of my remake of the Dragon 32 version of Chucky Egg for Nintendo DS and Dreamcast:

A couple of screenshots:

Chuckie Egg Logo Chuckie Egg Game

The game itself is fully playable, but there’s still some polishing to do:

  • Sound on the Dreamcast is misbehaving;
  • The Dreamcast version runs faster than the DS, so some timings are off;
  • Later levels do not have increased numbers of hens or faster moving hens;
  • Hens don’t eat grain;
  • The high score table is not functional (it’s just a bitmap);
  • There’s no “game over” screen;
  • The score/timer/etc display layout and font is all wrong;
  • Remaining lives aren’t displayed;
  • The font in the title screen scroller is wrong.

This is an inexhaustive list of bugs I spotted in the original game while making this:

  • On the first level, climb the largest ladder to the third platform on the right (the start of the staircase). Stand on the ladder just below the top of the floor and jump right. Instead of bouncing off the first step in the staircase, Harry lands inside it. Now press right and Harry will fall through the platform on the right. (The remake fixes this.)

  • On level 7, stand next to the two blocks immediately on the right when the level starts. Face them, hold “right”, and jump. Harry stands in the middle of the upper block. (The remake reproduces this.)

  • Animation frame doesn’t reset when Harry stands on an elevator. (The remake fixes this.)

  • When a new level rolls in the remaining time is set to 999; it immediately jumps to 898 when the level starts. After dying it resets to 899.

  • Harry gets killed if the elevator he is standing on hits the top of the screen, but if he is jumping then he falls through the elevator. (The remake doesn’t kill Harry; he just drops down when the elevator disappears.)

  • There are a bunch of inconsistencies with ladder behavior. Sometimes it is possible to walk from a platform all the way across a ladder; sometimes Harry falls through half-way along the ladder. This looks more like a bug than desired behavior.

  • One of the extra hens on level 3 (at the bottom of the twin ladders) starts one block below where it should do.

Here are some of the differences between the remake and the original:

  • Jump isn’t quite the same.
  • Frame rate is much better.
  • No flickering.
  • Hen patterns aren’t the same (but the Dragon doesn’t match the BBC or ZX, and they don’t match each other, so that’s OK).
  • Duck moves smoothly.
  • Hens move more smoothly.

I think this will be the last remake for a while. This is the list of remakes I’ve managed to complete (more or less) so far:

  • Pong (Blitz Basic/C/C++/Java/Flash; Amiga/Cybiko/GBA/DS)
  • Asteroids (Flash)
  • Mario Bros (Flash)
  • Tetris (Flash)
  • IK+ (Flash)
  • PacMan (Java; Linux)
  • Space War (Java; web applet)
  • Earth Shaker (C++; DS/SDL)
  • Super Foul Egg (C++/Objective-C; DS/SDL/OSX/iOS)
  • BioShock sub game (C++; DS/SDL)
  • Space Invaders (C; DS/SDL/DC)
  • Chuckie Egg (C; DS/SDL/DC)

This is the list of remakes I started but abandoned:

  • World Grand Prix (Flash)
  • Trick or Treat (Java; web applet)
  • Atic Atac (C/C++; Cybiko/DS/SDL)
  • Defender (C/C++; DS)
  • Dan Dare (C; DS/SDL)

2016-10-13

HankyAlien v20161013

New releases of HankyAlien for Dreamcast and Nintendo DS!

Changes for Dreamcast are:

  • Added sound;
  • Fixed palette;
  • Improved performance;
  • Fixed layout for NTSC TVs.

Note that the sound doesn’t work at all well with lxdream.

Aside from the massive behind-the-scenes rewrite, there shouldn’t be anything noticeably different between this DS version and the last release.

2016-10-10

HankyAlienDC

A few more evenings of reorganising things for the Dreamcast and here’s HankyAlienDC:

HankyAlienDC

The archive contains a .elf version that will run in lxdreams, and presumably other emulators, and a .bin version that will run via an SD adaptor and DreamShell RC4. It will presumably run if you somehow burn it to a CD, but it’s been so long since I’ve made a CD of Dreamcast homebrew that I’ve completely forgotten how to do it. Plus I’m on a different OS and don’t have an optical drive any more.

There are still a few issues to be fixed:

  • The colors are wrong. The components in DS pixels are ordered ABGR; DC pixels are ordered ARGB.
  • Elements at the top and bottom of the screen are cropped out. The display is set to 320x240@60Hz, but of course NTSC TVs don’t display 240 vertical pixels; they display 200.
  • There’s no sound yet.

Here’s my Dreamcast test hardware, acquired from Amazon and eBay:

Dreamcast

Things I was surprised to learn about the Dreamcast:

  • There were multiple revisions of the hardware. The final US revision doesn’t support homebrew because Sega removed support for the “Mil-CD” multimedia disc format that had enabled all piracy on the system. There was only one PAL revision, which did support Mil-CD, which explains why I’d never heard of incompatible hardware before.
  • On a modern flatscreen TV - or at least, on my TV - the quality of the composite video output is awful. Really, really awful.
  • The performance of the emulator isn’t at all representative of the performance of the hardware.