It all began with Bexagon.
Bexagon is a game in progress from bello games that started a couple of years ago, progressed quickly, and then was put on hiatus for various reasons. Now we’re back on track and it’s close to completion, at least on Jaguar. Here’s the latest video showcasing it:
Since its first early steps we were discussing that due to the way we implemented the game it would be relatively easy to port from Jaguar to Falcon. I worked on this idea in the back of my mind, thinking of how to implement this, but never got round to actually doing it. Whether we thought it was easy or not it would still take a lot of work!
Before going any further, a quick presentation of Raptor Basic+.
In the beginning there was Raptor library for the Atari Jaguar. This was used internally by Reboot for many years in order to reduce the time taken to develop a new project. It’s a library written mostly to manage the Jaguar’s Object Processor and let the programmer focus on more game specific stuff rather than micro managing the hardware. To this day very few people used it or even tried to use it.
So around Christmas 2014 I bit the bullet and created a Basic wrapper for Raptor. You can read more about it here but the important stuff for this article is that I used a Basic to C translator and then piped the output to a modern (for the time) gcc for 68k. Then wrote some extra commands and functions to interface with Raptor, linked everything up and miraculously everything worked! (well, sort of!)
bexa64n size optimise
While we were tossing around ideas about how to release and when, sh3 had this idea swirling in his mind to release a small teaser of bexagon for people to try. But to be extra cheeky the game’s window should be tiny, and with that the game’s size should also be small. 64x64 game window was selected (because that number is so special for Jaguar ;)) and the file size was also set to 64k. This was also encouraged by me mentioning a line of games the indie developer Aaron Steed made for Nitrome which were 48x48 in size: Gunbrick, J-j-jump, Turnament, Ice beak, Coil, and Flue. All these are great and I do recommend playing them! Also these games strengthened our plan to go ahead with it.
After the initial work was done and the game was running, our file size was around 80k plus, and that was without sound. Oops! We started looking at some obvious things like removing all unused pieces of graphics or anything else - that only saved us 1 or 2k. It was time to do some under the hood work! First stop was the u-235 sound engine which is a hard dependency the version of Raptor rb+ uses has. However we didn’t even have any sound at this stage, so it had to go! I had an idea how to achieve this for a long time so I went ahead and tried it. It worked the first time! This brought us down to about 68k - woohoo!
Then I started looking into packing some of the graphics. Since the assets were small anyway this didn’t yield much difference but at least it shaved off some more bytes.
Next up, trimming the code down and trying to use loops as much as possible to reduce code size. After I exhausted this path I remembered that by default the compiler is set to produce the most optimal code in speed. It’s not like we need much speed for this game so it wouldn’t be a problem! This also usually means bloating up the code size, so changing the switch from “optimise for speed” to “optimise for size” did the trick! We were now at about 100 bytes short of 64k - job done!
…However I was still a bit bummed we couldn’t include any audio. It just didn’t feel right. So I took a look at the outputted binary with a hex editor… to realise that the debugging symbols were actually included. D’oh! And it turns out that the latest version of the linker we use (rln) actually strips the symbols from the final binary. Double d’oh! But yay, we got down to 55k! So a small sample loop was possible and was added. Release time!
Just when we were about to release the game that creeping thought came to our minds again: “What about a Falcon version?”
Plenty of groaning from my side later, I decided to have a go at it.
My main goal was to use pretty much the same basic code to create two different versions. I was confident this could happen, and it would pave the way for its bigger brother, bexagon, to be ported over so…
Luckily the Jaguar and Falcon share the same family of main CPUs - the 680x0. So at least the basic code is interchangeable between Jaguar and Falcon without too much hassle. But from there the differences are huge. Here’s a list outlining the differences:
CPU (68000 on Jaguar vs 68030 on Falcon - not a biggie)
Pixel format (chunky on Jaguar vs planar on Falcon)
Palette format (RBG556 on Jaguar vs RGB666 on Falcon)
Audio systems (custom DSP on Jaguar vs Motorola DSP56001 plus DMA on Falcon)
Operating system (bare metal on Jaguar vs TOS on Falcon)
This all means that a lot of work had to be done to accomodate both platforms. Fortunately all of the work was done on Jaguar and since bcx doesn’t care about external command implementation as long as one knows what he/she does, it meant we could easily strip out the Jaguar specific stuff and gradually replace them with Falcon specific.
17th March 2018
Which is pretty much what happened during the first day: A very small startup program was written (well, “adopted” from an older game, Downfall) that did some hardware set up and then called the basic code. Also some common code was copied around and some relatively easy commands were implemented (such as palette fade). But before anything could be tested the whole thing had to compile and build. For Jaguar I used what was available and tested for that time, gcc 4.6.4. This has been brought up to speed and made to produce Atari executables by Vincent Riviere. So that was my first thought, try to use that instead of trying newer versions.
Unfortunately after the usual linking errors were solved (unreferenced labels etc), the linker would simply crash instead of producing a binary! Grrrrr! Okay, maybe the assembler (rmac) object files are bad? Let’s switch to another assembler (vasm)! Boom - Same thing again!
I decided I had enough, so I switched to my own cooked (with dml) version of gcc (read this and this for more info), v7.2 with elf to prg bridge (brownout). This of course meant that I had to do the very risky thing and switch intermediate binary formats (aout to elf) but I was running out of options at that point. To my absolute delight, linking worked first time!
However I didn’t dare test anything on the real machine at this point as it wouldn’t do anything, except set up the video and display a black screen. But that was more than enough for a first day!
18th March 2018
Nothing much happened that day: some cleaning to the build system happened in order to prepare the ground for dual platform compilation.
19th March 2018
Slowly getting back into action I was trying to think of ways to have as little different code paths inside the basic program as possible. One of the main problems that I was facing was that the game relied on poking the Jaguar’s palette registers a lot. As mentioned above this was a problem not only because the palette format is different, but also because it’s of different size - 2 bytes per index on Jaguar and 4 on the Falcon. So there would be lots of parts inside the source like this:
if pal_mul=1 then
FOR i=0 TO 32 STEP 2
FOR i=0 TO 64 STEP 4
If this was kept we might as well had two different sources as there would be duplicated code all over the place! Luckily I found that bcx is more powerful than I anticipated - it allows macros to be defined! So depending on the platform different definitions of poke and peek exist at the top of the basic file. So the codebase became uncluttered again.
On the integration part, Falcon module/sfx player (by TCE) was added.
20th March 2018
A few more functions were added and Jaguar compatible calling schemes were added. Note that up till now nothing was tested on real hardware or emulation, so it was coding at blind!
At this point I made the decision to not use my own tool for converting graphics (in bmp format) to Falcon format, but instead use dml’s Photochrome for this. Also at this stage it was high time that the code be ran on the real hardware, just to see if it would at least get to running the Basic code. Some nasty typos aside, that went pretty smooth. However, no audio/video yet!
21st March 2018
Focus now had to shift to tools again - it was time to get something on screen and speakers! First of all there was lots of technical debt gathered up in the tool that converts assets for use in Jaguar, and extending it as it stood would mean even more pain. So quite some time was spent in refactoring it and making sure nothing broke in the process.
Adding Falcon support to the audio part was easy as the file was pretty much the same as the Jaguar’s - 8bit, signed PCM. Of course I had to ditch the ADPCM player that the Jaguar uses for simplicity’s sake. There was a small “gotcha” on the real hardware as I was using the wrong version of the audio player and the machine would lock up after a few moments - oops! Thankfully switching to the proper version of the player fixed everything up!
Video was turning more and more troublesome as I could not get Photochrome to output the graphics in the way I needed. Unfortunately there was no support for it so I was on my own, trying out the many command line switch combinations, see if I could get it to behave. After a lot of experimentation I gave up for the day and focused on other things.
For example there was the matter of how to add something compatible to the Jaguar’s Object Processor (that handles displaying the graphics on screen) on the Falcon’s Videl chip. Adding such a layer on such a short period would be suicide! Plus it’s not that good of an idea as there will have to be a lot of compromises done on the Falcon side which would degrade performance even more. So a decision was taken: since this game was only going to show up 2 static images I wrote two tiny routines that would display one or the other graphic. As long as the pixels were in the correct format of course….
Other things were added too, like code reading the powerpad/jagpad and functions converting RGB values to either Jaguar or Falcon palette format.
22nd March 2018
After some work done to convert all palette values inside the source to both formats a lot of time was spent yet again on getting Photochrome to output the desired format again - to no avail!
23rd March 2018
As you can imagine at this point I was getting a bit burned out with all these issues so I mostly took the day off, relaxing to some other things and only fixing some very minor compiling stuff. There’s always tomorrow :).
24th March 2018
One day was enough loafing - time to get back on track!
At this point I got confirmation from dml: Photochrome didn’t have support for the exact output I wanted! So I sighed a sigh of relief (I wasn’t going insane!), rolled up my sleeves and proceeded into adding Falcon graphics output in my own tool. Quite happy with myself I sent the resulting program to the Falcon… only to be greeted with another weird freeze. I’ll spare you the horror that ensued and will just mention that the fault was tracked down to our tool for linking the programs was compiled wrong and it was misbehaving! That was a fun 2 hours, I’ll say!
After that a few bugs were fixed in the Falcon library code, adding support for more Falcon modes to my graphics converter tool, making the print routine actually write numbers instead of splodges and fixing some code I’ve forgotten about in the basic file. If you kept track, by now the basic file was pretty much not changed and only the supporting code was added.
All these fixes resulted in the game actually being playable on Falcon for the first time - hooray!
25th March 2018
The final stretch!
The last day was spent in getting all the little details just right: Importing the font correctly, changing the print routine to reflect this, debugging all audio issues and finding the right pitch, fixing the graphics converter for 4bpp images, and finally measuring the program size. I think it was around 45k so there was 20k free for audio. So I bumped up the sample frequency (for Jaguar we had to settle for 2kHz, I went for 8kHz on Falcon) and changed the player frequency….
And that was it.
After this it was a matter of packaging it up, syncing with the Jaguar version (it was only at this point I found out that sh3 had created a 2Mb rom with much larger sample and quality. Too late for me to make a bigger version at that point ;), making a video and then releasing it out to the wild. Job done?
Falcon programming is fun!
Obviously I could have taken it much easier and not force myself to do it so fast but… one issue solved was leading to another and from one point onwards the gravity pull became much too strong for me to be able to pull out!
Porting bexagon now seems much less daunting than it did on week ago!
This also paved the way for even more cross-platform fun!