Example: Asteroid Deluxe

There is only one nvram file nativly saved for this game, without any location.dat entry.
Get the nvram file size: <mame>/nvram/astdelux/earom => size: 64 bytes

[XML]
<structure>...
  <check>...
    <size>64</size>
  </check>
</structure>

Let's take a snapshot of the ingame high scores, after some trials.


We are seeing X high scores:
1: 2240    VA
2: 1880   C B
3: 1580   YAA
4:  610   QAE

Let's have a look inside the nvram.


By chance, sometimes seems quite obvious about the scores, confirmed after some other trials.


First, only 3 high scores are stored in the nvram.
Then, the hexa decimal value is the decimal value to display, meaning that attributes type = INT and base =16 must be used.
So, each score are stored on 3 bytes (attibute size = 3).
Finally, the 3 bytes are inverted, i.e. stored in little endian, driving the attribute endianness = little_endian.
And.. perhaps names are between, allowing us to use a loop?
[XML]
<loop count="3">
  <elt size="3" type="int"  id="SCORE" endianness="little_endian" base="16"/>
  <elt size="4" type="raw" id="UNKNWON"/> <!-- name here? //-->
</loop>


Our target names are: <space>VA, C<space>B, YAA
As the last 'unknwon' data has two 0x0B, so 0x0B means perhaps 'A' and letters seem to be in the natural order.
Let put the letters in front of their hexa and decimal codes, as well as the targeted ascii decimal, to see if some transformations can be highlighted.

Letter ->hexa ->decimal ->all decimal -> transformation 1 -> ascii decimal -> target ascii decimal
A 0B 11 11 +54
65 65
B 0C
12
12 +54 66 66
C 0D
13
13 +54 67 67
D

14 +54 68 68
...

... +54 ... ...
<space> 00
0
0 +32 32 32

So, 1 transformation can be applied: ascii offset = 54, expect for <space>.
And last byte seems to be no part of the name, meaning size = 3.



[XML]
<loop count="3">
  <elt size="3" type="int"  id="SCORE" endianness="little_endian" base="16"/>
  <elt size="3" type="text" id="NAME"  ascii-offset="54"/>
  <elt size="1" type="raw"  id="UNKNWON"/>
</loop>


If we modify directly a score inside the nvram and reload the game, the new score is not accepted.
So, the guess is that the last unknwon byte is a control byte, some sort of checksum, preventing easy hack in memory or nvram.



[XML]
<loop count="3">
  <elt size="3" type="int"  id="SCORE" endianness="little_endian" base="16"/>
  <elt size="3" type="text" id="NAME"   ascii-offset="54"/>
  <elt size="1" type="raw"  id="CHECKSUM"/>
</loop>


Testing all possible hexadecimal positions and specifically 'space' leads to the following additional charset and decoding.



 [XML]
<structure>
  ...
  <loop count="3">
    <elt size="3" type="int"  id="SCORE" endianness="little_endian" base="16"/>
    <elt size="3" type="text" id="NAME"  charset="astdelux" ascii-offset="54"/>
    <elt size="1" type="raw"  id="CHECKSUM"/>
  </loop>
</structure>
<charset id="astdelux">
  <char src="0x00" dst=" "/>
  <char src="0xFF" dst=" "/>
</charset>


Now we need to display the decoded elements into the output part.
The 'loop' will turn into a 'table', 'elements' into 'columns'.

[XML]
<output>
  <table>
    <column id="SCORE"/>
    <column id="NAME"/>
    <column id="CHECKSUM"/>
  </table>
</output>


Let's make explicit in the output that checksum has been kept in hexa (default behavior of the RAW type), by adding the "0x" prefix, using the implicit special format dedicated.
We will also display it only if debug mode is activated (-rd), as having a checksum is not really displaying high scores, by using display = "debug" :)

[XML]
<column id="CHECKSUM" format="0x" display="debug"/>

Finally, adding a rank column is always welcome to mimic a high score table, using the current index of each line inside the table (src = "index"), starting from 1 instead of 0 (format = "+1", another direct implicit format)

[XML]
<output>
  <table>
    <column id="RANK" src="index" format="+1"/>
    <column id="SCORE"/>
    <column id="NAME"/>
    <column id="CHECKSUM" format="0x" display="debug"/>
  </table>
</output>


And that's all! Here is the final XML description:

[XML]
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE hi2txt SYSTEM "hi2txt.dtd">
<hi2txt>
  <!--
    tested with mame 0.148 and related hiscore.dat
      source: HiToText
  //--> 
  <structure file="earom">
    <check>
      <!-- optional: if defined, it allows to select the good structure versus the provided file
                     useful if multiple structures are defined but hiscore.dat not provided //-->
      <size>64</size>
    </check>
    <loop count="3">
      <elt size="3" type="int"  id="SCORE" endianness="little_endian" base="16"/>
      <elt size="3" type="text" id="NAME"  charset="astdelux" ascii-offset="54"/>
      <elt size="1" type="raw"  id="CHECKSUM"/>
    </loop>
  </structure>
  <output>
    <table>
      <column id="RANK" src="index" format="+1"/>
      <column id="SCORE"/>
      <column id="NAME"/>
      <column id="CHECKSUM" format="0x" display="debug"/>
    </table>
  </output>
  <charset id="astdelux">
    <char src="0x00" dst=" "/>
    <char src="0xFF" dst=" "/>
  </charset>
</hi2txt>

...leading to such display, using -ra parameter:
RANK|SCORE|NAME
1|2240| VA
2|1880|C B
3|1580|YAA


or this one, using -rd parameter:
RANK|SCORE|NAME|CHECKSUM
1|2240| VA|0x8D
2|1880|C B|0xB1
3|1580|YAA|0xCE

A front-end can then easily display (with some fancy colors):
RANK SCORE NAME
   1  2240   VA
   2  1880  C B
   3  1580  YAA