don't click here

Micro Machines Military SRAM Documentation

Discussion in 'Technical Discussion' started by Overlord, Aug 20, 2023.

  1. Overlord

    Overlord

    Now playable in Smash Bros Ultimate Moderator
    19,238
    969
    93
    Long-term happiness
    Post 19,000! =P

    So you may or may not remember https://forums.sonicretro.org/index...tation-and-a-md-ram-comparison-utility.39969/ , where I posted documentation on the SRAM format for Micro Machines 2 - well, I've now skipped ahead a game in the series to Micro Machines Military; for two reasons:

    1) I don't know '96 all that well, I never owned it at the time.
    2) '96 had a track editor and as such the SRAM size is far, FAR larger.

    Military's SRAM layout is very similar to 2's, as it works out - I only had to change a few locations around and for the most part, everything all lines up nicely. Below is the results of my work. Enjoy!

    Code (Text):
    1. 0x00: lowercase ASCII string "hasreset" (8 bytes)
    Code (Text):
    1.  
    2. All bytes ending in 0, 2, 4, 6, 8, A, C, E between 0x08 and 0x149: 00, not used for anything
    3. All bytes ending in 1, 3, 5, 7, 9, B, D, F between 0x08 and 0x149: if FF, no value set for the records detailed below, or not used for anything if outside the specified ranges
    4. 0x09: Always 00? (1 byte)
    5.  
    6.  
    7. 0x0B: Highest Challenge beaten for JEREMY (1 byte)
    8. 0x0D: Highest TT Challenge beaten for JEREMY (1 byte)
    9. 0x0F: Highest Battle Arena beaten for JEREMY (1 byte)
    10. 0x11: Highest Pro Challenge beaten for JEREMY (1 byte)
    11. 0x13: Highest Pro TT Challenge beaten for JEREMY (1 byte)
    12. 0x15: Highest Pro Battle Arena beaten for JEREMY (1 byte)
    13.  
    14. 0x1F: Highest Challenge beaten for WALTER (1 byte)
    15. 0x21: Highest TT Challenge beaten for WALTER (1 byte)
    16. 0x23: Highest Battle Arena beaten for WALTER (1 byte)
    17. 0x25: Highest Pro Challenge beaten for WALTER (1 byte)
    18. 0x27: Highest Pro TT Challenge beaten for WALTER (1 byte)
    19. 0x29: Highest Pro Battle Arena beaten for WALTER (1 byte)
    20.  
    21. 0x33: Highest Challenge beaten for SARA (1 byte)
    22. 0x35: Highest TT Challenge beaten for SARA (1 byte)
    23. 0x37: Highest Battle Arena beaten for SARA (1 byte)
    24. 0x39: Highest Pro Challenge beaten for SARA (1 byte)
    25. 0x3B: Highest Pro TT Challenge beaten for SARA (1 byte)
    26. 0x3D: Highest Pro Battle Arena beaten for SARA (1 byte)
    27.  
    28. 0x47: Highest Challenge beaten for EMILE (1 byte)
    29. 0x49: Highest TT Challenge beaten for EMILE (1 byte)
    30. 0x4B: Highest Battle Arena beaten for EMILE (1 byte)
    31. 0x4D: Highest Pro Challenge beaten for EMILE (1 byte)
    32. 0x4F: Highest Pro TT Challenge beaten for EMILE (1 byte)
    33. 0x51: Highest Pro Battle Arena beaten for EMILE (1 byte)
    34.  
    35. 0x5B: Highest Challenge beaten for DAVEY (1 byte)
    36. 0x5D: Highest TT Challenge beaten for DAVEY (1 byte)
    37. 0x5F: Highest Battle Arena beaten for DAVEY (1 byte)
    38. 0x61: Highest Pro Challenge beaten for DAVEY (1 byte)
    39. 0x63: Highest Pro TT Challenge beaten for DAVEY (1 byte)
    40. 0x65: Highest Pro Battle Arena beaten for DAVEY (1 byte)
    41.  
    42. 0x6F: Highest Challenge beaten for DELORA (1 byte)
    43. 0x71: Highest TT Challenge beaten for DELORA (1 byte)
    44. 0x73: Highest Battle Arena beaten for DELORA (1 byte)
    45. 0x75: Highest Pro Challenge beaten for DELORA (1 byte)
    46. 0x77: Highest Pro TT Challenge beaten for DELORA (1 byte)
    47. 0x79: Highest Pro Battle Arena beaten for DELORA (1 byte)
    48.  
    49. 0x83: Highest Challenge beaten for CHEN (1 byte)
    50. 0x85: Highest TT Challenge beaten for CHEN (1 byte)
    51. 0x87: Highest Battle Arena beaten for CHEN (1 byte)
    52. 0x89: Highest Pro Challenge beaten for CHEN (1 byte)
    53. 0x8B: Highest Pro TT Challenge beaten for CHEN (1 byte)
    54. 0x8D: Highest Pro Battle Arena beaten for CHEN (1 byte)
    55.  
    56. 0x97: Highest Challenge beaten for SPIDER (1 byte)
    57. 0x99: Highest TT Challenge beaten for SPIDER (1 byte)
    58. 0x9B: Highest Battle Arena beaten for SPIDER (1 byte)
    59. 0x9D: Highest Pro Challenge beaten for SPIDER (1 byte)
    60. 0x9F: Highest Pro TT Challenge beaten for SPIDER (1 byte)
    61. 0xA1: Highest Pro Battle Arena beaten for SPIDER (1 byte)
    62.  
    63. 0xAB: Highest Challenge beaten for BRUNO (1 byte)
    64. 0xAD: Highest TT Challenge beaten for BRUNO (1 byte)
    65. 0xAF: Highest Battle Arena beaten for BRUNO (1 byte)
    66. 0xB1: Highest Pro Challenge beaten for BRUNO (1 byte)
    67. 0xB3: Highest Pro TT Challenge beaten for BRUNO (1 byte)
    68. 0xB5: Highest Pro Battle Arena beaten for BRUNO (1 byte)
    69.  
    70. 0xBF: Highest Challenge beaten for DWAYNE (1 byte)
    71. 0xC1: Highest TT Challenge beaten for DWAYNE (1 byte)
    72. 0xC3: Highest Battle Arena beaten for DWAYNE (1 byte)
    73. 0xC5: Highest Pro Challenge beaten for DWAYNE (1 byte)
    74. 0xC7: Highest Pro TT Challenge beaten for DWAYNE (1 byte)
    75. 0xC9: Highest Pro Battle Arena beaten for DWAYNE (1 byte)
    76.  
    77. 0xD3: Highest Challenge beaten for CHERRY (1 byte)
    78. 0xD5: Highest TT Challenge beaten for CHERRY (1 byte)
    79. 0xD7: Highest Battle Arena beaten for CHERRY (1 byte)
    80. 0xD9: Highest Pro Challenge beaten for CHERRY (1 byte)
    81. 0xDB: Highest Pro TT Challenge beaten for CHERRY (1 byte)
    82. 0xDD: Highest Pro Battle Arena beaten for CHERRY (1 byte)
    83.  
    84. 0xE7: Highest Challenge beaten for RAY (1 byte)
    85. 0xE9: Highest TT Challenge beaten for RAY (1 byte)
    86. 0xEB: Highest Battle Arena beaten for RAY (1 byte)
    87. 0xED: Highest Pro Challenge beaten for RAY (1 byte)
    88. 0xEF: Highest Pro TT Challenge beaten for RAY (1 byte)
    89. 0xF1: Highest Pro Battle Arena beaten for RAY (1 byte)
    90.  
    91. 0xFB: Highest Challenge beaten for INDRA (1 byte)
    92. 0xFD: Highest TT Challenge beaten for INDRA (1 byte)
    93. 0xFF: Highest Battle Arena beaten for INDRA (1 byte)
    94. 0x101: Highest Pro Challenge beaten for INDRA (1 byte)
    95. 0x103: Highest Pro TT Challenge beaten for INDRA (1 byte)
    96. 0x105: Highest Pro Battle Arena beaten for INDRA (1 byte)
    97.  
    98. 0x10F: Highest Challenge beaten for VIOLET (1 byte)
    99. 0x111: Highest TT Challenge beaten for VIOLET (1 byte)
    100. 0x113: Highest Battle Arena beaten for VIOLET (1 byte)
    101. 0x115: Highest Pro Challenge beaten for VIOLET (1 byte)
    102. 0x117: Highest Pro TT Challenge beaten for VIOLET (1 byte)
    103. 0x119: Highest Pro Battle Arena beaten for VIOLET (1 byte)
    104.  
    105. 0x123: Highest Challenge beaten for EDINA (1 byte)
    106. 0x125: Highest TT Challenge beaten for EDINA (1 byte)
    107. 0x127: Highest Battle Arena beaten for EDINA (1 byte)
    108. 0x129: Highest Pro Challenge beaten for EDINA (1 byte)
    109. 0x12B: Highest Pro TT Challenge beaten for EDINA (1 byte)
    110. 0x12D: Highest Pro Battle Arena beaten for EDINA (1 byte)
    111.  
    112. 0x137: Highest Challenge beaten for JOLINE (1 byte)
    113. 0x139: Highest TT Challenge beaten for JOLINE (1 byte)
    114. 0x13B: Highest Battle Arena beaten for JOLINE (1 byte)
    115. 0x13D: Highest Pro Challenge beaten for JOLINE (1 byte)
    116. 0x13F: Highest Pro TT Challenge beaten for JOLINE (1 byte)
    117. 0x141: Highest Pro Battle Arena beaten for JOLINE (1 byte)
    118.  
    Values for the above: Goes from FF (not set), starting at 01 (1 course), up to the number of courses that mode has (0A for all 10 Challenge completed for example).

    Code (Text):
    1. 0x14A: Checksum of 1P record data to this point? (2 bytes)
    Code (Text):
    1.  
    2. 0x14C: Driver name for JEREMY (6 bytes)
    3. 0x152: Driver name for WALTER (6 bytes)
    4. 0x158: Driver name for SARA   (6 bytes) (replaced Lisa?)
    5. 0x15E: Driver name for EMILE  (6 bytes)
    6. 0x164: Driver name for DAVEY  (6 bytes)
    7. 0x16A: Driver name for DELORA (6 bytes)
    8. 0x170: Driver name for CHEN   (6 bytes)
    9. 0x176: Driver name for SPIDER (6 bytes)
    10. 0x17C: Driver name for BRUNO  (6 bytes)
    11. 0x182: Driver name for DWAYNE (6 bytes)
    12. 0x188: Driver name for CHERRY (6 bytes)
    13. 0x18E: Driver name for RAY    (6 bytes) (replaced Jethro?)
    14. 0x194: Driver name for INDRA  (6 bytes) (replaced Maria?)
    15. 0x19A: Driver name for VIOLET (6 bytes)
    16. 0x1A0: Driver name for EDINA  (6 bytes)
    17. 0x1A6: Driver name for JOLINE (6 bytes) (replaced Suelee?)
    18.  
    Values for the above: ASCII caps & space only.

    Code (Text):
    1. 0x1AC: Checksum of the names data? (2 bytes)
    Code (Text):
    1.  
    2. 0x1AE to 0x29D: Initially set to 3A 97 DE F7 BD EC, repeated: blank time trial times. (240 bytes)
    3.  
    4. 0x1AE: 1 Funny Farm - 3-lap time trial record (6 bytes)
    5. 0x1B4: 1 Funny Farm - 1-lap time trial record (6 bytes)
    6. 0x1BA: 2 Ski Lift Larks - 3-lap time trial record (6 bytes)
    7. 0x1C0: 2 Ski Lift Larks - 1-lap time trial record (6 bytes)
    8. 0x1C6: 3 Cricket Capers - 3-lap time trial record (6 bytes)
    9. 0x1CC: 3 Cricket Capers - 1-lap time trial record (6 bytes)
    10. 0x1D2: 4 Tunnel Vision - 3-lap time trial record (6 bytes)
    11. 0x1D8: 4 Tunnel Vision - 1-lap time trial record (6 bytes)
    12. 0x1DE: 5 Measure Up - 3-lap time trial record (6 bytes)
    13. 0x1E4: 5 Measure Up - 1-lap time trial record (6 bytes)
    14. 0x1EA: 6 Tongue Tied - 3-lap time trial record (6 bytes)
    15. 0x1F0: 6 Tongue Tied - 1-lap time trial record (6 bytes)
    16. 0x1F6: 7 Fire Flyer - 3-lap time trial record (6 bytes)
    17. 0x1FC: 7 Fire Flyer - 1-lap time trial record (6 bytes)
    18. 0x202: 8 Speed Special - 3-lap time trial record (6 bytes)
    19. 0x208: 8 Speed Special - 1-lap time trial record (6 bytes)
    20. 0x20E: 9 Bee Bother - 3-lap time trial record (6 bytes)
    21. 0x214: 9 Bee Bother - 1-lap time trial record (6 bytes)
    22. 0x21A: 10 Mine Enemy - 3-lap time trial record (6 bytes)
    23. 0x220: 10 Mine Enemy - 1-lap time trial record (6 bytes)
    24. 0x226: 11 Pecking Pains - 3-lap time trial record (6 bytes)
    25. 0x22C: 11 Pecking Pains - 1-lap time trial record (6 bytes)
    26. 0x232: 12 Bird Bath Blues - 3-lap time trial record (6 bytes)
    27. 0x238: 12 Bird Bath Blues - 1-lap time trial record (6 bytes)
    28. 0x23E: 13 Pump Panic - 3-lap time trial record (6 bytes)
    29. 0x244: 13 Pump Panic - 1-lap time trial record (6 bytes)
    30. 0x24A: 14 Spud Gun Run - 3-lap time trial record (6 bytes)
    31. 0x250: 14 Spud Gun Run - 1-lap time trial record (6 bytes)
    32. 0x256: 15 Desert Storm - 3-lap time trial record (6 bytes)
    33. 0x25C: 15 Desert Storm - 1-lap time trial record (6 bytes)
    34. 0x262: 16 Fish Face - 3-lap time trial record (6 bytes)
    35. 0x268: 16 Fish Face - 1-lap time trial record (6 bytes)
    36. 0x26E: 17 Sparkler Slalom - 3-lap time trial record (6 bytes)
    37. 0x274: 17 Sparkler Slalom - 1-lap time trial record (6 bytes)
    38. 0x27A: 18 Water Spurts - 3-lap time trial record (6 bytes)
    39. 0x280: 18 Water Spurts - 1-lap time trial record (6 bytes)
    40. 0x286: 19 Windy Woes - 3-lap time trial record (6 bytes)
    41. 0x28C: 19 Windy Woes - 1-lap time trial record (6 bytes)
    42. 0x292: 20 Spike Spinner - 3-lap time trial record (6 bytes)
    43. 0x298: 20 Spike Spinner - 1-lap time trial record (6 bytes)
    44.  
    This is the same insanity as how MM2 saved it, so let's tl;dr the explanation of that format, with this example 6 bytes and the data it contains:

    Code (Text):
    1.  
    2. 03 0A 7B 00 00 00
    3. 0:15:56 OL (Jeremy)
    4.  
    * Firstly: First 2 bits of first byte, last 2 bits of last byte: two separate 2-bit bit-fields which together indicate the character. Why did Supersonic Software feel the need to split them like this to each end of the save data, rather than put them together into a single nybble? I have no idea.
    Code (Text):
    1.  
    2. 0         0
    3. 0000   0000
    4. 4         1
    5. 0100   0001
    6. 8         2
    7. 1000   0010
    8. C         3
    9. 1100   0011
    10. 00 00   JEREMY
    11. 00 01   WALTER
    12. 00 10   SARA
    13. 00 11   EMILE
    14. 01 00   DAVEY
    15. 01 01   DELORA
    16. 01 10   CHEN
    17. 01 11   SPIDER
    18. 10 00   BRUNO
    19. 10 01   DWAYNE
    20. 10 10   CHERRY
    21. 10 11   RAY
    22. 11 00   INDRA
    23. 11 01   VIOLET
    24. 11 10   EDINA
    25. 11 11   JOLINE
    26.  
    * Secondly: Last 6 bits of first byte, all of second byte: The course time, in the number of centiseconds since 0.00.00, divided by 2 (14 bytes)
    As mentioned elsewhere in the text, the times in this game only ever end in even numbers. Hence this value is the number of centiseconds, divided by 2, since the timer started counting. 14 bits is 65534 (32767 x2) centiseconds, which is 10 minutes, 55 seconds and 34 centiseconds; and as such is well over what's required. Below is a sample set of times for a 1 lap course, the raw data stripped of the name & racer ID, and the resultant conversion from the nybble & hex value into one long binary number, then a decimal, then times 2 to get the centiseconds value. If the value is 6000 or larger, we take that away, add 1 minute to the time, and keep doing it until the value is under 6000, at which point we have the part after the minutes figure.
    Code (Text):
    1.  
    2. 03 0A
    3. 000011 00001010
    4. 00001100001010
    5. 30A (hex)
    6. 778 (dec)
    7. * 2 = 1556
    8. 0:15:56
    9.  
    * Finally: Third byte, fourth byte, fifth byte, first 6 bits of sixth byte: The racer's name. This is stored as six 5-bit fields, with an alphabet running from 00001 (A) to 11010 (Z). 00000 is a space:
    Code (Text):
    1. |A    |B    |C    |D    |E    |F    |G    |H    |I    |J    |K    |L    |M    |N    |O    |P    |Q    |R    |S    |T    |U    |V    |W    |X    |Y    |Z    |
    2. |00001|00010|00011|00100|00101|00110|00111|01000|01001|01010|01011|01100|01101|01110|01111|10000|10001|10010|10011|10100|10101|10110|10111|11000|11001|11010|
    3. 00000   (space, only used to pad the name out to be 6 characters. You can't set a space in a name)
    Unused combinations: 11011, 11100, 11101, 11110, 11111

    Code (Text):
    1.  
    2. 7B 00 00 00
    3. 01111011 00000000 00000000 000000
    4. 01111 01100 00000 00000 00000 00000
    5. O     L
    6.  

    Code (Text):
    1. 0x29E: Checksum of time trial data? (2 bytes)
    Code (Text):
    1. 0x2A0: 00 (1 byte)
    Code (Text):
    1. 0x2A1: FF, repeated. Unused (351 bytes)

    Extra notes and ruminations

    * The racer order used by Micro Machines 2 is still present here, only with some characters replaced: For example Lisa (now gone) has her slot taken by Sara (new), but Violet (in both games) has the same position.
    * Like MM2: Multiple racers can have the same name without time trial records getting confused.
    * Like MM2: If a character's name is changed, their non-time trial records are ERASED from the save file (and by extension, View Stats). There is no way to retrieve this.
    * Like MM2: If a racer's name is changed, their time trial records under the old name no longer show in their number of records in View Stats, however the records themselves remain saved in Time Trial mode (under the original name). If the name is changed back, the original records will be reassigned in View Stats.
    * Like MM2: If you fail to complete a single race on any of the 1P non-single time trial modes, the stat stays as "no statistic".
    * Like MM2: If racers are under their original name when chosen, the option to rename will always be set to Yes. This applies even when either named that manually after choosing yes, or by naming them something else and then named back - as such there is no "renamed" flag stored for each character in the save file.
    * Like MM2: Time trial records always end in an even number of milliseconds. This would mean at 50Hz, 100 centiseconds pass every second: an actual second. 60Hz games would run faster - 120 centiseconds per second of gameplay - however this game was PAL only so doesn't apply.
    * Time Trial's just-before-the-race screen shows the character name in upper and lower case letters (leading letter is upper case) where most of the rest of the game is just caps-only, for some reason.
    * Like MM2: blank time trial field hex values: 3A 97 DE F7 BD EC. This is equal to Jeremy (the first racer in list order), named to a letter combination 6 characters long that doesn't exist (it'd be the next letter after Z (11011) six times), getting a time of 0.54.22.
    * Like MM2: In-game shows the time trial no record set time as being 4.59.98, on the records screen it shows "NO REC." If you reach 4:59:98 in-game, the timer stops; and when you finish the course it says it's not a new lap record (oddly the stopwatch shows 9:59:99).
    * The same pointless compression in the save for time trial records from MM2 still applies, only now there's even more wasted space. 240 bytes are used for saving time trial data. 351 bytes below it aren't used. Given this massive amount of unused space, I again question why Supersonic Software felt the need to crush the time trial store down to 6 bytes of usage per record. The total amount of space available for times is 591 bytes, as such there are 14 theoretical bytes available for each to use, with 31 bytes still left over. Given this, you could store the character name as straight ASCII (6 bytes), the character selection as an entire byte rather than two spread 2-bit bit-fields, and still have 7 bytes left per time trial entry to store the time: given all times in this game are 5 characters long (never higher than 4.59.98) and as such could be stored as 1 byte each, there's no need to have done the compression down to 6 bytes at all. Why, lads? Even with the compression they used, there's still no need to have split the racer identification nybble in half like they ended up storing it, so many weird decisions were made here.
    * On top of that, unlike Micro Machines 2, the Micro Machines Military save format has three separate checksums in it. One is understandable (like MM2's single one), but why the hell does a file that is one kilobyte in size need three separate internal checksums?!
    * If you complete a challenge/arena mode, your stat says "CHAMP" instead of how many courses you've managed.
    * Not really relevant to the game code per se - every 3rd Challenge win gets you the Bonus Life mini-game with a shooting gallery. There are 3 of these possible to get (given there's 10 races). No repeats that time, though I will say that the final snow one of the three is by far the easiest out of the three, compared to the static shooting gallery (the first one) and the static shooting gallery with a can in the way (the second one).
    * Not really relevant to the game code either - there are 10 Challenge races, and they are HARD. I was heavily abusing savestates to get first each time after the first few, and there are courses - 8 and 9 in particular - where if you do not get Blue spun out with a weapon on the first or second corner, you are not winning the race; it's as simple as that.
     
    • Informative Informative x 7
    • List
  2. Aerosol

    Aerosol

    Not here. Moderator
    11,163
    573
    93
    Not where I want to be.
    Sonic (?): Coming summer of 2055...?
    Impressive work Overlord, and happy 19K!