Castle Defender is my latest game created for Abbuc Software Contest 2019.
This game itself has lot of quite unique features but also the development/conversion process was unique for me as well. I have been searching for something interesting around Christmas 2018 and I have found Castle Defender for BBC Micro, the tower defence game that is the closest cousin of games like Kingdom Rush on PC that I have seen on 8-bit computer. There is also another tower defence game for ZX called Captain Drexx, but Castle Defender was much closer to what I was looking for… and the graphics was simply great.
This blog post is a rather long one, describing the actual conversion/implementation process. There are no sub headers, I just separated paragraphs by screenshots. I know the readability is not very good, but that’s the way it is. I hope someone will read it till the end and hopefully enjoy.
I have read some brief info about this computer called BBC Micro written in Fandal’s blog before so I already knew the machine runs on 6502 and it has no hardware sprites, so everything is made by software sprites… hence possible to convert to our 8-bit Atari without need to emulate some special gfx features. Fandal did several game conversions from this platform which of course proved that it is possible so I decided to do one on my own.
First of all I had to understand the differences between Atari XL/XE and BBC Micro. Since the CPU is the same, the main logic was supposed to be simply “copied”… and it was more less true assumption. The difference is that BBC Micro has nothing like our displaylist, just several graphic modes … and some of them are different to Atari ones. On Atari by using DisplayList you can define how each line of data is represented on display and from which memory pointer is the videodata loaded. On BBC Micro there are fixed memory areas that are acting as videoram, and the placement and lenght is dependant on the graphics mode selected.
Castle Defender is using mode 1 which is 320×256 pixels in 4 colours and that is something that Atari cannot do.
First of all the videoram in such mode is 20kB which is quite something, but on the other hand the game itself is using “only” 256×256 pixels (16kB videoram) for on-screen video data, the rest of the pixels are not used hence there are black columns on both sides of the game screen – so something like Atari narrow playfield option is also present on BBC Micro.
Other thing to consider was that atari has no 256 line graphic mode. Fortunately not whole area from the top to bottom is used for actual playfield, there is statusbar at the bottom… so I knew I need to remove that one to fit the game in Atari screen boundaries, but it would require some workaround, because the statusbar has to be shown since it is providing vital data for the player during the gameplay.
There is also other non trivial difference. The videodata is not stored in lines but in small chunks of 8×8 pixels that can be emulated by Atari charsets… which would be quite simple to do in case if mode 4 (1 bit per pixel) would be used. Issue was that we have 8×8 pixels in 4 colors … so “1 char” is represented by 16 bytes, where first 8 bytes are representing left 4×8 part and latter 8 bytes are representing right 4×8 part. This means that 1 character line is represented by 64 bytes instead of Atari usual 32 bytes in narrow playfield mode. In fact that means that BBC Micro has 64 characters in single line, so it would be required to emulate 64 horizontal positions from BBC Micro into 32 horizontal positions on Atari. This seems to be quite straightforward on first (or second) look, but in fact it adds a lot of complexity (that I realized in next phases of this project).
First of all I have downloaded the original game from Here and BeebEm emulator from Here. Exported disk contents and started reverse engineering the files. I have discovered that BBC Micro has something like teletext mode, which is used for info/title screens… and in this case it was operated by Basic program instead of expected machine language. So only the game itself is written in assembler, instructions and score screen is Basic… so I was able to abstract from that and focus simply on gameplay code.
Shortly after first disasseblies and tests I realised that the game is quite new and maybe it could be easier to contact the author and ask for the sourcecode. At least it could contain named labels and some inline comments that might make the whole process easier and faster. Issue was that even there is a website url written in the game, there is no email address or any comment form on the website which could be used to contact the author. So my only option was to create account on stardot forum, where the BBC Micro game was originally announced, discussed and released. Since I was new member, I had no privilege to contact other members by PM (private message) so I had to think about how to solve this situation. Then I quoted Chris (the author) in his original thread hoping the quote notification will find him and he sends me PM. I received his PM, but I had no option to reply 😀 … what a wtf moment. Then I created my own thread and asked forum admins to promote me. They were very kind and suddenly I was able to PM Chris back. He sent me source file, binary data files (that I already extrected from the game disk) and Basic sources of the teletext menu part.
I have already written several posts on stardot forum uncovering the development progress, I will use the contents here as well.
Syntax of assembler for BBC Micro is different to MADS so I had to do lot of text editing (regex find and replace) to change the code to look compatible with MADS. For instance they are not using #$20 as a representation of hexadecimal number, but their syntax is #&20 – that was the easy one. Labels are defined differently using dots and indentation is different as well. Then I had to remove all calls to disk loads, sound calls and interrupts whilst reserving space for my own routines. Some data were added inline from my first disassembled attempts, some were included. There were also several parts of code using absolute addressing with address number instead of some label (which I did not initially spotted so it was responsible for some weird behavior later during the development). Finally I was able to compile this code, so it was time to see if it does something or dies instantly. I don’t remember exactly how long did it take to not crash, but it was surprisingly very soon. Then I added DisplayList showing 2-color character lines in narrow mode starting from $4000 and this is how it looked:
I know it’s not as nice as you might expected, but it is actually correct. Remember that single line in such graphics mode on BBC Micro is 64 byte long… which means that 1 BBC Micro line is represented by 2 Atari lines. If I would skip every odd line, it would look more similar to original… This is just static picture, but I saw the way how it been constructed so I was 100% sure the game is working. Enemies or more precisely their sprite data was originally loaded dynamically from disk, so I had to grab their data set for first level and put it to the correct location… here is the result of that:
This time I have moved the LMS bit further so the lower screen is shown including part of the statusbar. This was the status of the game 3 days after I received the codebase from Chris. It was pretty impressive.
Now was time to convert the bitmap data. I was initially using a PHP disassembler so I decided to use PHP for binary data manipulation. I don’t think it was very good choice, but it was defintely better to use some scripting language rather than compiled .net C# code, because I was expecting lot of variations of the code for the game elements. Then it is easier to copy some script, do some changes and run it instead of compiling every variation. I have tried several options to convert the graphics to 1bit per pixel mode to lose as little details as possible. I was simply omitting the additional colors and ORing into single byte… something like this:
outByte = ([sourceByte] AND #$f0) OR (([sourceByte+8] AND #$f0) >> 4)
That did the trick, black and red were black … green and blue were white. Then I had to do the same for sprites. When game starts, playfield is displayed and then each empty place for tower is shown one by one… so the first converted sprite was logically the sprite of empty tower place:
This required to convert the sprite data using same formula as used for the background, then modify the sprite drawing routine used for towers which also required masking, because horizontal position of all towers in this level was odd … that means mid-char. As I partially indirectionally mentioned earlier, this game uses 64×64 coordinates for game elements so all elements drawn that have odd horizontal position need to be masked and emulated on Atari. That eventually means that all drawing routines are coded twice, once for even and once for odd positions (but I did not know/decided that yet in this phase of conversion).
Next step was the sprite drawing routine. This was quite a task, all sprites on BBC Micro were preshifted to 4 horizontal positions… because 1 byte contained data of 4 pixels. This is not the case for Atari, so I had to modify the sprite drawing code and sprite data converter to contain and handle 8 preshifted positions:
I have reused the empty tower place sprite conversion script for other tower sprites, replaced keyboard handling routines and modified the cursor drawing routine:
This version already contained explosion sprites, buggy hit sprite and super buggy bullets. In the meantime all 4 level backgrounds were converted and deflated using zopfli. That was the time when I calculated that the whole game including all the levels would fit into memory of stock Atari 800 XL/XE with 64kB memory without need to load additional levels later as separate data blocks. It took me month until I wrote version with working bullets and hit sprites. It was so nasty to recode the bullet drawing routines including the masking (they are still not 100% perfect even in the final Abbuc version):
These early stages show lot of progress, but fixing, bughunting and polishing the game to have final look took a lot of time. I decided to preshift enemy sprites directly in code to reduce the data footprint and I also designed 12 more enemy sprites for the advanced levels (original game had less enemy sprite variations, but included color replacement routine… so single sprite could be green and red in one level… it was required to workaround this, because there would otherwise be same looking enemies on Atari with different health and shield values).
Then I was fixing the statusbar (number drawing routine):
Also I was working on a way to display more colors in the playfield. PMGs were not used so PMG overlay was a way to achieve this. There were several options by hand, but I decided to go with this one:
I wrote an editor for this purpose and designed PMG overlays for all 4 levels by myself:
Then I added 2 missile-based columns on both sides of playfield which display values from statusbar:
I was reading through Abbuc SWC 2019 rules in April and I realized the game could take part in the competition if original authors Chris Bradburne and John Blythe agree on that. I asked them, they were both fine with this and I decided to list them as co-authors of the Atari version … which is practically true even though they did not participate during the process at all.
Ok, back to the implementation… I decided to flush down the small fonts because they were barely readable on real HW and I replaced all the routines and fonts which eventually look much better:
This version contains dynamically placed selection bar which displays tower build/upgrade options and parameters. It appears either on the bottom part of the screen or at the top part, depening on the position of currently selected tower. This is done by dynamic DisplayList which consists of several parts being linked in right order.
Even though I mentioned deflate compression somewhere at the beginning of this post, the inflater (decompression) routine was included only since revision 82. Before that nothing was being decompressed at runtime, all the data was included in normal uncompressed state.
Level 4 required some manual graphical tweaks. If you played it on BBC Micro, you would see the level has lot of red colors and diagonal stripes. This looked like a rubbish after I converted the background to 1bit per pixel mode. I had to adjust bitmap conversion routine specifically for this level, so source colors are handled differently during conversion. This ended up with different looking trees compared to other 3 levels, so I have manually redrawn all the trees in level 4 to look consistent with previous 3 levels.
All the functionality testing was done on level 1 and now when I had other levels designed, I discovered there are lot of bugs still present. There was sprite scrolling leftover appearing when enemy moved from right to left. Level 1 was the only one level that has all towers placed to odd horizontal positions, every other level has it mixed… and my tower drawing routine needed to be adjusted for that case. Also the cursor was drawn incorrectly, so another code needed to be copied and adjusted for such case. What I did not mention is that each tower sprite has two graphical representations (two data sets), one adjusted to characters and one mid-char with masking.
I have also placed the level and phase info line to the very top of the screen. This text line is shown for couple of seconds at the beginning of game and after each completed phase. Funny thing was that in level 3 there is one tower at the top of the screen coliding with this text line. I originally thought this would not be a problem to handle, however it required several attempts to fix this and I struggled here for some time looking at it not working… not understanding what am I doing wrong.
Revision 96 from end of June contains gazillion changes in memory management. Lot of explicitly defined addresses were replaced by relative ones, lot of data deflated. Then I worked on parametrized inflater which allowed to inflate the data of specific level from OS ROM and Basic ROM memory areas to memory areas of the game. Afterwards I was able to properly advance from one level to the next one. I replaced the “Defeat”, “Victory” and “Level complete” logos with my own, because these were originally stored quite strangely in some weird format. I designed them to look almost same as original ones, but I saved them as deflated bitmaps. I spend unreasonable amount of time on developing some animation of these logos. BBC Micro version of the game performs some flickering colour changes, but all my attempts to emulate this on Atari looked quite cheap, so I removed the animation completely and kept to logos static … but on the other hand I coloured them by PMG overlay. Also some fade-in and fade-out effects were implemented and every level got its own color:
Game was more less done and it was July 16th (after rev 112) when I started working on the title screen and overal game loop, this went relatively well:
Instructions text fit into 4kB and it is being deflated directly into game video ram area, which is basically the only place which can be used. All the other memory space contains either code or deflated data.
Couple days after I received the work-in-progress G2F title screen from Piesiu and music from StRing. At that time I was convinced that I will not be able to fit all together into memory (including the title G2F picture). Abbuc SWC deadline was near, and I had still lot of work to do and it was already June 26th. From now on the work was very intense, I spent a lot of time finishing the game putting all pieces together. RMT music and player were added to the code. I did modify the RMT player routine with my own stereo mode, so the music is playing stereo (if stereo extension is present) and ingame special effects are playing mono with output to both speakers in case of stereo extension available. I was even able to fit the G2F title screen into the memory and that was really nasty. I had to rearrange lot of memory in order to make it real. At this moment the game was using all possible memory starting at $0200 until $fffd excluding the OS vectors space from $d000-$d7ff. Load address was $2000 and everything that occupied lower memory areas was either inflated or used as temporary or variable space. I was freaking proud on myself, the game includes 4 full screen bitmap levels each has 5 phases with 20 different enemies. There are instructions, stereo music and G2F picture all fit into memory of stock Atari 800 XL with 64kB without need to load additional data blocks during the game.
That remained until I received final G2F picture from Piesiu. Its DisplayList interrupt routines were much longer than before, also PMGs were used a lot compared to the previous (already implemented) picture. It took me a moment to realize that eventually I will not be able to fit the picture in the memory so I had to use it as splash screen displayed once before the main game finishes the loading. I was struggling with this during the last day before the deadline at midnight and it was mind boggling because the game kept crashing unmercifully after this change.
I did not want to bother player waiting long time during loading between G2F splash picture and title screen. So I loaded almost everyting upfront and then displayed the G2F splash screen. Afterwards the loading should continue very shortly until finished and game should start by showing the title screen. Problem was that the final loading was crashing. Eventually I realized that I was using some lower memory area which rewrote the DOS and that was responsible for the crashing..so I once again rearranged the memory which fixed the crashing. I had only short time to test the loading in emulator by unchecking burst loads and SIO patches. It sometimes finished okay, sometimes not entirely, but I did not have time to elaborate and I was really quite tired… it was already past 10PM and I had no high score implemented yet. Fortunately it took me around an hour to code it and shortly before 11:30PM the final build saw the light of the world. I quickly filled up the submission form on Abbuc page and clicked the submit button.
Finally I could rest, work has been done.