Porting Eamon Adventures – First challenges, characters.

In unraveling the code for Eamon the first thing I looked at was the startup procedure which did character selection. There is a bunch of text to give a great flavor which I have so far skipped over, as it is just a straight copy and past into WriteLine statements and instead looked at the structure of the the character data file.

The file presented me with my first challenge. It turns out that text files in Apple II DOS 3.3 are not stored in ASCII as we know it on the PC. It uses something called “high-ascii” instead which basically means that the high bit of each ASCII value is set to 1 on the Apple when it would be 0 on the PC. The utility I use to extract the files from the disk images has an option to convert text files for consumption on PC which is nice but it changes the line endings from the Apple II ending to the PC’s \r\n line ending. This seems great, and for sequential text files it is, but the Eamon data is all written in random access record based text files. The structure of these files is a series of fixed length records with the data fields in the record separated by a line ending character. If there were the same number of fields in every record I could adjust the length I use and just go with using a two bite line ending instead of one byte but it turns out that there are a variable number of fields in a record which means after conversion they would no longer be fixed length.

After thinking a while about what to do I decided to stick with fixed length records and write my own conversion tool that changes high-ascii to normal ascii and uses just \n as the line ending character. This worked perfectly.

Once that was done I was able to write a short method in my code to read records from the file and discovered the structure of the character data. In BASIC the data was spread between a handful of variables and arrays but I decided that in C or C# it would be better to place this in a structure and came up with:

struct Character
public int hardiness; //HD
public int agility; //AG
public int charisma; //CH
public int[] spellAbility; //SA%() 4 Values
public int[] weaponAbility; //WA%() 5 values
public int armorExpertise; //AE
public string sex; //SEX$
public int gold; //GOLD
public int bank; //BANK
public int armor; //AC
public string[] weaponName; //WNAME$() 4 values
public int[] weaponType; //WTYPE$() 4 values
public int[] weaponOdds; //WODDS%() 4 values
public int[] weaponDice; //WDICE%() 4 values
public int[] weaponSides; //WSIDES%() 4 values

The order in the struct matches the order of the values in the data record. The next step for me is to write a method that parses the string record and fills in the struct above.