Cracking the Questron Save Files

My original goal for Retrochallenge was to create a character editor for Questron, and while I’ve discovered and posted about some interesting things related to the game, I haven’t really made much progress. The save game files turned out to be much trickier to figure out than I thought, and it was just last night that I made the leap that helped me figure out what was going on.

Questron supports up to 4 characters – basically, completely separate sets of game state. Each character is represented by two files on side one of the disk. For a while, I was suspicious that data was being saved somewhere else, so I did a test. I’ve been using some Python code I wrote to analyze the structure of .g64 disk image files. I added a routine to compare two .g64 files (before and after making some trivial changes and saving the game) that would list the disk sectors that had changed and which files they belonged to. With that, I was able to verify that the changes were limited to two files.

I expected the save game files to be short and simple because the game itself is fairly simple. The character has five attributes, plus hit points, gold, food, location in the world map, inventory, and maybe some quest flags. I figured I could just look at the hex data for the two files and find values that matched some of those numbers. I was very wrong.

… And so on. Overall, “coronax-v” is 4354 bytes, which is huge by C64 standards. The section with all the text strings seems to include all the monster and location names for the current continent (there are two continents in the game). But why would you need to put that in the save file? What was the format of this data?

I tried looking for bytes in the file that corresponded to known values for hit points, gold, and so forth, and I came up blank. I also tried loading up the game, moving one step in one direction, and then saving, and looking at the save files to see what had changed – but surprisingly there were changes scattered throughout the “coronax-v” file. I was getting really confused and more than a little frustrated, and that’s when I turned my attention to tracing through the game’s startup routines, trying to figure out when these files were loaded and where in the computer’s memory they were loaded. Once I figured that out, the answer was practically slapping me in the face.

Really, this is a case where I was missing something that could have been really obvious. I was focused on the idea of figuring out the format of the data, and reading it the way you’d read a data file on a modern computer. It turns out I should have just been treating it like a common C64 binary file, where the first two bytes of the file give the address in memory that the data should be loaded into.

The big file, “coronax-v”, gets loaded into memory starting at $8A00, which is in the middle of the memory block set aside for BASIC programs. Remember that a lot of the Questron game logic is in BASIC, so that block should still be reserved.

The little file, “coronax-p”, is a little more complicated. The loader actually temporarily loads it into the C64’s tape buffer, but that’s just to keep it out of the way until the big file is loaded. After that, the 12 bytes of data in “coronax-p” are copied into their permanent home starting at $002D.

It turns out that in the C64 memory map, that section starting at $002D is used to store pointers that are used by the BASIC interpreter. Specifically, they say where the storage for variables and strings and so forth begin. When I saw that, it all became clear.

The big file, “coronax-v”, isn’t a save file per se. It’s a memory dump of all the variables defined in the BASIC interpreter!

Now that I know what I’m looking at, my next step will be to write some code to extract the data from these files. There’s some information about accessing BASIC variables in Jim Butterfield’s Machine Language for the Commodore 64, so hopefully that’ll be enough to help me interpret the memory dump file.