This is not the first time I’ve looked into porting Adventure. However, for a long time, the various implementations were all based on the original FORTRAN code, which doesn’t make porting a very pleasant experience. Furthermore, they generally required a large text database that would be difficult to get onto a calculator, and would be needlessly inefficient space-wise. Then I found Open Adventure, which completely reworked the text database system into native C arrays. Not only that, but the code was written in fairly idiomatic C, not machine-translated from Fortran!
However, given the constraints and conventions of the platform,
it made sense to split the dungeon data back into a separate data file---but this time,
there was a convenient make_dungeon.py
that could be modified to generate the data file,
instead of trying to write my own code to parse the input data.
Helpfully, ESR wrote a comprehensive test suite to compare his new C code against the original.
This made it easy for me to check that my completely reworked dungeon loader didn’t break the game.
Unfortunately, keeping tests working requires some akward `#ifdef`s scattered around the code,
but it’s worth it to keep the tests working.
The decision to move the dungeon into a readable database
and then use a Python program to convert it into a more usable form was extremely helpful.
The make_dungeon.py
file has been extensively modified so that instead of generating a set
of static C arrays, it instead generates an external file.
This is particularly useful for the calculator, which maps not only RAM into the CPU’s address space,
but also maps all of its flash memory, too, allowing unchanging data to be read directly from flash.
I wrote all of the code that deals with the dungeon file before ever writing any calculator code. I wanted to verify that the semicompressed dungeon file worked before any actual porting. The text is compressed with basic Huffman coding, though most of the space saving actually comes from string deduplication.
Having a separate dungeon file reduces the program’s RAM footprint. While it would have been possible to keep all the data in the program binary, it would double the program’s RAM footprint, essentially requiring all of user memory to run the program. Reading the data from the archive makes the program a bit less efficient, but significantly reduces the RAM footprint, making it more user friendly.
The accessor routines for reading data out of the arrays have been left it. They slightly reduce code size, and even though our little eZ80 is encumbered by an atrocious number of wait states, we still don’t need the extra speed.
Open Adventure CE has been extended with quite a bit of platform-specific code, because the TI-84 Plus CE does not have a native console feature. (Well, not one I’d want to use, anyway.)
calc.c
contains:
-
The main menu
-
Resume menu
-
Error routines
-
File name validation routine
-
safe_malloc()
so as to prevent writing to NULL pointers
editor.c
contains:
-
The command history buffer
-
The string input routine
style.c
contains:
-
The routine for decompressing the splash screen
-
Font selection routines
-
Some draw-text-with-specific-alignment routines
-
The console replacement routines
The console replacement does not currently handle any scroll back, but it does handle basic formatting: word-wrap and centered text when selected.
ez80.asm
contains native eZ80 assembly routines:
-
_decompress_string
a semioptimized Huffman decompression routine -
LCD dimming control
-
Optimized time routines for the idle-timeout feature
-
Key input wrappers that check for the ON+CLEAR abort combo