Let me preface this whole thing by saying, I have no idea how to format this information well, so it may be a little tough on the eyes, and possibly a little confusing. I'll do my best to ask questions if you've read multiple times and still have no answer. =)
First, this is a link to the XML file:
http://www.the-elitists.com/HiToText/HiToText.xmlPut this in the same folder as HiToText.exe
So, here's a small tutorial on the XML format. I've added about a dozen drivers to this thing so far, and it works very well. Bagman for example took about 3 minutes to add. In the near future I do plan on making some sort of application that will generate the XML for you, but for now you can manually do it.
The first thing to know is what's currently in it's own class now is separated as entries in the XML. So you can see there are 15 entries in the file I've included here. Each entry element always has 4 elements: Header, FileStructure, SetStructure, and DisplayStructure. Order does not matter.
The header element contains 3 required elements: Games, Fields, and Extensions and one optional element: TextParameters. Order does not matter.
Games is a list of Name elements where each element is the rom name which corresponds to the mapping. Order does not matter.
Fields is a list of Name elements where each element is a field displayed. The order matters here, so put them in the order in which you'd like to see it displayed.
Extensions is a list of Name elements where each element is a file type associated with the data you're receiving. Of the 15 entries I have here, all of them just contain .hi, however later some will contain .nv, and possibly others. Order does not matter.
TextParameters is used to describe getting text information, mostly for name fields (so far), and contains 1 required entry: Formats (if TextParameters exists), 2 potentially required entries: SpecialMapping, and Offsets, which depends on which Format elements exist, and 1 optional entry: SwitchMaps. Order does not matter.
Formats contains a list of Name elements that correspond to one of (currently) 5 possible formats: NeedsSpecialMapping, ASCIIUpper, ASCIILower, ASCIINumbers, ASCIIStandard. For anyone who looked at the older code and saw some of the changes I was making will recognize these 5 formats. NeedsSpecialMapping will require the SpecialMapping element. ASCIIUpper, ASCIILower, and ASCIINumbers will require the Offsets element. ASCIIStandard requires nothing. These 5 formats will be explained below. Order does not matter.
SpecialMapping is a list of mappings with characters to bytes, these are Map elements with two required attributes Char, and Byte where char is a character (only one key allowed here), byte is the byte that it would map too. You can have multiple bytes assigned to a char, but not the other way around, and HiToText will always use the first value assigned to a character when there are multiple options.
Offsets is a list of Offset elements with two required attribtes: Type, and StartByte. Type corresponds to the format element earlier, and can only be one of 3 values: Upper, Lower, and Numbers. StartByte is the byte for which a, A, or 0 will start at when being encoded/decoded in any function involving names. You need an Offset element for each of the 3 ASCII formats mentioned earlier. Order does not matter.
SwitchMaps is a list of SwitchMap elements that are used for special "switch" functions such as mapping the characters in Asterix. I would take a look at that entry for an example as what I'm about to say may be a bit confusing... here goes. Each SwitchMap has 3 required attributes: Name, DefaultOne, and DefaultMany. The switchmaps use a one to many relationship so you can have many strings mapped to one byte array. The Default attributes are if nothing can be found matching your Mapping elements within the current SwitchMap element. If multiple bytes are required for the byte array they can be separated by pipes. (i.e. 0x01|0x02). The name element must match the Name attribute (case insensitive) of the FieldName element in DisplayStructure that is using the Switch ConversionType attribute. (Asterix is an example of this)
Each SwitchMap has multiple Mapping elements, that have 2 attributes: One, and Many. One is a byte array, and many is a string. They work just like the default elements except these are checked first, so if a switch function (explained a bit later) is looking for the byte that corresponds to the string "ASTERIX" it will search the mappings first and find 0x01 before it goes to the DefaultOne. The Many fields are NOT case sensitive, so if you wish for them to be displayed differently, or as was requested a web address to an image or something for a FE to use, then go for it. I prefer all caps, so that's how the file will look. =)
Okay, now that we're done with the Header element, I'd like to note that a lot of what's in the header will relate to what's in the other three elements as well.
The FileStructure element is where the byte mapping actually is stored, it contains only mapping elements, and may contain as many as required to fully define each of the bytes in the source file.
The Mapping element contains 2 required attributes: NumberOfBlocks, and Ordering, and 1 optional attribute: Start. NumberOfBlocks is the number of times to go through the Entry elements of that particular Mapping element. I'll provide an example shortly that should explain that better. The Ordering attribute determines the numerical increment/decrement that will occur as you go through each block. Start is the number to start with when going through ordering.
Each entry has 2 required elements: Name, and Length. Name is the name that will be used for many other portions of the XML from setting scores, to reading scores, and will need to be the same as names for those other elements which will be explained a little later. Length is the number of bytes that make up that entry. These names ARE case sensitive, so be careful!
If none of that made sense, hopefully this example from arkretrn helps:
<FileStructure>
<Mapping NumberOfBlocks="5" Ordering="Ascending">
<Entry Name="Score" Length="4"/>
</Mapping>
<Mapping NumberOfBlocks="4" Ordering="Ascending">
<Entry Name="Name" Length="3"/>
<Entry Name="Space" Length="1"/>
</Mapping>
<Mapping NumberOfBlocks="1" Ordering="Ascending" Start="5">
<Entry Name="Name" Length="3"/>
</Mapping>
</FileStructure>
So when HiToText goes to read the .hi file (in this case) it will start with the first map, and it sees an ascending mapping of 5 blocks that are called Score of 4 bytes each. So the first 20 bytes make up the first 5 scores(Score1, Score2, Score3, Score4, Score5). Then it will move to the next mapping, which is 4 blocks of ascending order containing two entries: Name, and Space. So it will read the next 16 bytes as (Name1, Space1, Name2, Space2, Name3, Space3, Name4, Space4). Then it will move to the last mapping, which is 1 block of ascending order that starts at 5 containing one entry: Name. So it will read the last 3 bytes as (Name5).
This is what HiToText will see for the mapping:
Score1 - Bytes 1-4
Score2 - Bytes 5-8
Score3 - Bytes 9-12
Score4 - Bytes 13-16
Score5 - Bytes 17-20
Name1 - Bytes 21-23
Space1 - Byte 24
Name2 - Bytes 25-27
Space2 - Byte 28
Name3 - Bytes 29-31
Space3 - Byte 32
Name4 - Bytes 33-35
Space4 - Byte 36
Name5 - Bytes 37-39
arkretrn.hi is 39 bytes so we have a complete map.
The DisplayStructure element is how HiToText determines how to display the scores when trying to display them. It has one optional element: NumOfDisplayedEntries which is a way to limit the amount of entries to display for scores. Currently only 10yard is using this as there are 23 scores/Names in the .hi file, however you only ever see 10. This number can be safely changed to anything from 1-23 (for 10yard) if you wish to see more or less than the 10 the game shows. The DisplayStructure element contains as many FieldName elements as required for display. Order matters, and the first FieldName will be the first value per line. The first FieldName is almost always going to be Rank.
The FieldName element has 2 required attributes: Name, and ConversionType, and 1 optional attribute: Operator.
Name is linked to the Name in the Entry elements in the FileStructure/Mapping element. So if you want to display Name, you better have Entry Name="Name", and FieldName Name="Name" in the appropriate place. Name also matches to the SwitchMap Name attribute if it exists.
ConversionType is the function used to convert the byte array data into a string, there are some constant values such as CanndedDisplay.AscendingFrom1 which just counts from 1 for that field (perfect for Rank). There are other conversion types such as Standard which converts the byte array as an integer, so 0x10 0x00 0x00 will come back as 100000. There are others: Reversed, Hex, HexReversed, BCD, BCDReversed which you can research in the code. There are also some custom one-off functions, in particular 8ballact has some custom functions for decoding/encoding scores. They should be named as the parent rom name, and if the rom starts with a number, put an underscore before the name. As you can see for 8ballact, it's _8ballact. Pretty easy. Name functions (if setup) should just use a conversion type of "Name".
Operator is a mathematical function used to modify the data for display. Usually it's something like "+1" or "*10" so the displayed data more correctly matches what the game would display instead of what the game stores. Often games will not store data with known values and display it with the assumed values. That's basically what this will do. For example, a game like 005 stores it's scores divided by 10, so when we read something like 0x02|0x50 it would normally display as 250, however the game would display that as 2500. So we have a "*10" operator to get it to display how the game would display it. This is used in conjunction with a similar field in SetStructure which will be explained later.
All right, now onto the most complicated... SetStructure. It contains as many FieldName elements as required to set a new score.
The FieldName element contains 4 required attributes: Name, FieldType, ConversionType, and Position, and 2 optional attributes: Constant, and ExternalWrapper. It can also contain as many SpecialUtilization elements as needed. These aren't required, but almost certainly will be needed to set something correctly.
Let's start with the attributes. Name is pretty self-explainatory at this point, but this is what links up with the header names, filestructure names, and display names, so be consistent here. FieldType is the type of the field, such as string, int, or long, etc... ConversionType is the method used to convert the data of type FieldType into a byte array to be placed in the file. These are usually constant functions such as IntToByteArrayHex which converts an integer 100000 into a byte array that corresponds with the length of the FileStructure/Mapping/Entry attribute's name. So for example our 100000 above would convert to a byte array of length 3 for 4dwarrio as 0x10|0x00|0x00. There are other methods such as IntToByteArrayHexAsHex, Name, or Switch. Custom names like those described for 8ballact can also be used here. Position is the position in the arguments array this field will be linked to. So for 4dwarrio, the score is in the 1 position (0 is the first position). So when you type HiToText -w 4dwarrio.hi 1 40000 NLA, the 1 is in the 0 position the 40000 is in the 1 position...
The two option attributes are used for other special situations, Constant is just a byte value that will be the value set for that particular fieldname. It's currently only used for ajax for the "Unknown" field that is always 0x11 for player created entries. The other attribute, ExternalWrapper, is mostly used for when a byte array needs to be reversed, or if some other functionality needs to occur, like ByteSwapping (not currently implemented, but will be soon). In all the examples, only ReverseByteArray is currently used or accepted.
The SpecialUtilization element can contain one of (currently) 6 values: EmptyScores, ModifyName, IsHiScore, DetermineRank, IsAdjusted, and IncomingModified. There can be more than one type special utilization per FieldName. Some of these types of elements also require that the SpecialUtilization have an attribute, which I'll get into shortly.
EmptyScores will flag a field for usage in the EmptyScores function which will 0 out the field. It's used mostly for Score, and HiScore fields, but can be used for stages, or coins, or whatever else.
ModifyName will flag a field for usage in the ModifyName function which will allow that field to have a name changed based on the rank given.
IsHiScore will flag a field as the HiScore entry for the SetScore function. Anything that you wish to only be changed when it's the top score should have this SpecialUtilization.
DetermineRank will flag a field as being the data used for determining how that value ranks against existing values. It requires an attribute of Function, which can be Standard, Reversed, Hex, etc... or a custom function named as described the other custom functions (i.e. _8ballact). Currently, only one field may have this SpecialUtilization, but it will be implemented to allow multiples soon.
IsAdjusted will flag a field as being adjustable when a new score comes in. Use this for anything where you want the data to move down a rank if a new score coming in is higher. Things like HiScores and Unuseds, or separators should NOT have this SpecialUtilization whereas things like Name, Round, and Score should.
IncomingModified will flag a field as needing to be modified before being used for anything else. It requires a function that is similar to the operator attribute. The function attribute should be "/10" or "*45" or something mathematical. Certain games save scores without a trailing 0, so 25,000 will be stored as 0x25|0x00 to save space. Using IncomingModified will abstract this from the user so they can type "HiToText -w 005.hi 25000" which is what the game will show, instead of 2500 which is what's actually stored.
I know this is a LOT of writing, so I don't expect everyone to read it, but if you really wish to dig into the XML format, you probably should look at some of it, or just play around with the existing entries so you can see how it all works. Enjoy! I will be putting out a new version (source too!) shortly after I post this message.