A rough and possibly rambling blog of developing the C version of Dungeon Raider.
Initially targeting the Apple II range of computers.
Why C?
The BBC version of this game was made in Basic. The reason for this was the challenge of making something playable but with more depth in Basic. Most Basic games last 5 mins if your lucky and are typically a bit naff. It would also mean an easier tool chain as could use the amazing BBC BASIC for SDL which works very well and has debugging etc. Having used CC65 before with mixed success it was a tricky decision. As development on the Basic version finished the result was a playable game that worked nicely, but with some performance issues and limited headroom for improvement. The main issue here was that each level was shown in its entirety when it loaded:
It worked well enough and was pleased with the sound effects on the BBC. The problem was that from a game play perspective it literally revealed too much! There was no mystery or challenge sometimes as you could easily find a way through the level. What was needed was a slow reveal of the map. That proved to be FAR too big an ask for Basic, even the turbo charged one you get on the BBC! Rather at an impasse here since I wanted badly to write this for the BBC first and then other machines later. What options exist, that include the BBC?
BBC Basic
Limitations and too slow for more complex level reveal. Also would require extensive cross-compilation to work on other machines.
Compiled Basic
Some of these do exist and did take some for a spin. Some of them seem cool but they vary too much in syntax and would be painful to cross-compile between machines.
CC65
No official support for BBC (amazing but true) with some seemingly abandoned attempts as providing the required libraries and includes.
Assembler
I have in fact ported a good deal of this to 6502 assembler but the disc IO routines if I wanted to get this work on real machines would cause too many sleepless nights
So abandon the BBC it is for now at least. Hopefully can get a version to compile on CC65 and perhaps contribute to the CC65 project in the future.
There is a Python compiler that was designed to compile C for the BBC.
Also there are some native C compilers out there for BBC so perhaps that could be a path.
For now it will switch to CC65 targeting the Apple II
Development environment
Going to cc65 – a freeware C compiler for 6502 based systems provides all the information needed.
Having setup the environment the next step is to sort out an emulator for the various systems.
There are many emulators out there for the various 6502 based platforms. The main issue is how the boot images are created so it can be tested. They vary in complexity wildly but once working it is relatively straight forward to compile the problem and then boot up the emulator to show you the next error/bug you have to fix!
Porting from Basic (or something else)
An advantage of a port is that there is a working baseline to create code against. You know what your new C code should do because you have a working example. Also you have a bunch of source files you can re-use, such as information screens and levels/maps. In the case of Dungeon Raider there are a bunch of text VDU files that drive the menus. They were not included in the Basic code and were loaded as external files. That makes the entire project smaller and easier to read/modify.
The files were given very simple names.
VDU Files
m.txt is the main menu screen and looked like this:
Using a Text to Ascii banner maker to spice it up a little bit.
The code simply loaded the data into and dumped it to screen so super simple.
BBC Code looks like this:
1900 GOSUB 1840
1910 PRINT TAB(0,1)
1920 FIN=OPENIN K$
1930 IF FIN=0 THEN MODE 7:PRINT “ERROR LOADING SCREEN.”:PRINT”CHECK YOUR DISC AND TRY AGAIN”:PRINT “@2023 www.retroginger.com”:END
1940 REPEAT
1950 INPUT #FIN,K$
1960 PRINT K$
1970 UNTIL EOF #FIN
1980 CLOSE #FIN
1990 RETURN
The 1840 line set the screen mode 6 and hides the cursor
It is easy with BBC Basic. The C version has various intirations.
Initial version:
unsigned char line[38];
FILE *fp;
fp = fopen(filename, "r");
while (fgets(line, 38, fp) != NULL) {
puts(line);
}
fclose(fp);
It opens the file for reading. The screen files are set to a length of 38 and then loads a string line at a time.
When each line is loaded into the LINE buffer is it dumped to screen. The end-line character is set to LF and it displays fine. It is not massively quick but works and it compatible.
Optimized version:
Using the 8-bit unity code there are simple to use utility functions that can be used:
unsigned char screenBuffer[960];
memset(screenBuffer, 0, 960);
if (FileOpen(filename)) {
FileRead(screenBuffer, 960);
FileClose();
}
puts(screenBuffer);
The code reads everything into a buffer in one go and then dumps to the screen.
It is quicker that the first one but there are of course much larger memory overheads.
Map files