Okay, as promised, here is a blog-style post on how I made the settings definition file for Monkey Ball (
https://github.com/DragonMinded/netboot/blob/trunk/naomi/settings/definitions/BDF0.settings). Note that a prerequisite for following along on this post is that you have all of the utilities set up! See
https://www.arcade-projects.com/threads/netboot-naomi-with-eeprom-presets.18977/#post-295167 if you
have not set things up yet.
Okay, so lets get started figuring out the settings for
Monkey Ball!
First, I make sure my BIOS and region and controls are correct in demul. I also delete the "dummy.sram" and "dummy.eeprom" files in the nvram folder just in case. This means I'll be starting off completely fresh. Now I load up the netboot ROM for Monkey Ball using the "Naomi/Naomi2 Boot" option and wait for the game to finish loading completely. Once it shows the attract screen, I completely close demul (it doesn't seem to write the eeprom files until its closed) and then I take the "dummy.eeprom" file and I run it through eeprominfo and I get this output:
Code:
$ ./eeprominfo dummy.eeprom
Serial: BDF0
Game Settings Hex: 00 03 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 80 00 00 00 00 00 00 00 ff 00 00 00 80 00 00
Okay, so the game serial is
BDF0 and the length of the game settings is
32 bytes. That's enough to start a settings file. I create a new file named "BDF0.settings" and I put the following in it:
Code:
Setting00: byte, read-only, default is 00
Setting01: byte, read-only, default is 03
Setting02: byte, read-only, default is 00
Setting03: byte, read-only, default is 00
Setting04: byte, read-only, default is 00
Setting05: byte, read-only, default is 00
Setting06: byte, read-only, default is 00
Setting07: byte, read-only, default is 00
Setting08: byte, read-only, default is 00
Setting09: byte, read-only, default is 00
Setting10: byte, read-only, default is 00
Setting11: byte, read-only, default is 00
Setting12: byte, read-only, default is 00
Setting13: byte, read-only, default is ff
Setting14: byte, read-only, default is 00
Setting15: byte, read-only, default is 00
Setting16: byte, read-only, default is 00
Setting17: byte, read-only, default is 80
Setting18: byte, read-only, default is 00
Setting19: byte, read-only, default is 00
Setting20: byte, read-only, default is 00
Setting21: byte, read-only, default is 00
Setting22: byte, read-only, default is 00
Setting23: byte, read-only, default is 00
Setting24: byte, read-only, default is 00
Setting25: byte, read-only, default is ff
Setting26: byte, read-only, default is 00
Setting27: byte, read-only, default is 00
Setting28: byte, read-only, default is 00
Setting29: byte, read-only, default is 80
Setting30: byte, read-only, default is 00
Setting31: byte, read-only, default is 00
If you compare the bytes, you can see that all I did was make a single-byte setting for each byte in the eeprom and write down the default for each. I set them all to read-only for now since I don't know what any of them do. To test that I got the defaults right, I run the following:
Code:
./edit_settings mbdefault.eeprom --serial BDF0
Its important to note that the "mbdefault.eeprom" file
does not exist when I run this command, which is why I give it the "--serial BDF0" argument. I make no changes and exit, saying yes to write the EEPROM file out and then I compare the newly written "mbdefault.eeprom" against "dummy.eeprom". They're the exact same so I know I got the defaults right!
Now its time to start changing settings and seeing what happens to the file. I could try to reverse-engineer the test code for Monkey Ball, but that would take a long time and its not something that very many people can do. I boot up demul again, immediately go into the test menu right when I see the Naomi splash screen and head to game test mode. There's three sections that look like they are persistent: game assignments which is probably stored in the eeprom, joystick calibration which is also probably stored in the eeprom, and bookkeeping which might be stored in the eeprom or sram. I don't really care about how the bookkeeping is stored, so I make a note to myself to just ignore it. I head to game assignments first and look at what's available:
Let's start messing with one of these settings. Just looking at the eeprom data, I'm already betting that the second byte "03" is number of monkeys since it matches the number on the screen. So let's change that one. Cycling through it, I see that it can be set to 2 through 5. So lets set the number of monkeys to 5, exit back to system test, exit demul and run eeprominfo again:
Code:
$ ./eeprominfo dummy.eeprom
Serial: BDF0
Game Settings Hex: 00 05 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 80 00 00 00 00 00 00 00 ff 00 00 00 80 00 00
Look at that, the second byte changed to 05 and the rest are the same. So that's for sure the "Number of Monkeys" setting. I'll update "Setting1" to this instead:
Code:
Number of Monkeys: byte, default is 03, values are 2 to 5
Now, I can test that it was right by doing the following:
Code:
$ ./eeprominfo dummy.eeprom --display-parsed-settings
Serial: BDF0
Game Settings Hex: 00 05 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 80 00 00 00 00 00 00 00 ff 00 00 00 80 00 00
Parsed Game Settings:
Number of Monkeys: 5
Cool, looks good to me! Now I'll tackle the other two settings by doing the exact same thing. I'll change one setting at a time, see how the setting hex changes and updating the settings file accordingly. Here's what I came up with:
Code:
Game Difficulty: byte, default is 00, 0 - Normal, 1 - Hard
Number of Monkeys: byte, default is 03, values are 2 to 5
Ball Velocity Boost: byte, default is 00, 0 - Off, 1 - On
Setting03: byte, read-only, default is 00
Setting04: byte, read-only, default is 00
Setting05: byte, read-only, default is 00
Setting06: byte, read-only, default is 00
Setting07: byte, read-only, default is 00
Setting08: byte, read-only, default is 00
Setting09: byte, read-only, default is 00
Setting10: byte, read-only, default is 00
Setting11: byte, read-only, default is 00
Setting12: byte, read-only, default is 00
Setting13: byte, read-only, default is ff
Setting14: byte, read-only, default is 00
Setting15: byte, read-only, default is 00
Setting16: byte, read-only, default is 00
Setting17: byte, read-only, default is 80
Setting18: byte, read-only, default is 00
Setting19: byte, read-only, default is 00
Setting20: byte, read-only, default is 00
Setting21: byte, read-only, default is 00
Setting22: byte, read-only, default is 00
Setting23: byte, read-only, default is 00
Setting24: byte, read-only, default is 00
Setting25: byte, read-only, default is ff
Setting26: byte, read-only, default is 00
Setting27: byte, read-only, default is 00
Setting28: byte, read-only, default is 00
Setting29: byte, read-only, default is 80
Setting30: byte, read-only, default is 00
Setting31: byte, read-only, default is 00
Now, its on to the calibration screen. I'll do the same thing on that screen as I did for game assignments and take a screenshot of the defaults and then save them. This is what I get when I run the eeprominfo utility:
Code:
$ ./eeprominfo dummy.eeprom
Serial: BDF0
Game Settings Hex: 01 05 01 00 00 00 00 00 00 60 00 00 00 a0 00 00 80 7f 00 00 00 60 00 00 00 a0 00 00 80 7f 00 00
And here's what the settings looked like before I saved:
I can see the 60 and a0 values that were displayed on the screen in a few places of the eeprom, so I'm willing to bet those are the calibration options. I'm going to try something a little bit different from the first section to see if I can't narrow it down faster. I'll add the settings to the settings definition file "BDF0.settings", set them to four different unique values using "edit_settings" and then copy "dummy.eeprom" back into the demul nvram folder. When I boot the game and go to game test mode, I'll see what the settings page says when I look.
Here's how I set the settings file to do this:
Code:
Game Difficulty: byte, default is 00, 0 - Normal, 1 - Hard
Number of Monkeys: byte, default is 03, values are 2 to 5
Ball Velocity Boost: byte, default is 00, 0 - Off, 1 - On
Setting03: byte, read-only, default is 00
Setting04: byte, read-only, default is 00
Setting05: byte, read-only, default is 00
Setting06: byte, read-only, default is 00
Setting07: byte, read-only, default is 00
Setting08: byte, read-only, default is 00
Setting09: byte, default is 60, values are 00 to ff in hex
Setting10: byte, read-only, default is 00
Setting11: byte, read-only, default is 00
Setting12: byte, read-only, default is 00
Setting13: byte, default is a0, values are 00 to ff in hex
Setting14: byte, read-only, default is 00
Setting15: byte, read-only, default is 00
Setting16: byte, read-only, default is 00
Setting17: byte, read-only, default is 80
Setting18: byte, read-only, default is 00
Setting19: byte, read-only, default is 00
Setting20: byte, read-only, default is 00
Setting21: byte, default is 60, values are 00 to ff in hex
Setting22: byte, read-only, default is 00
Setting23: byte, read-only, default is 00
Setting24: byte, read-only, default is 00
Setting25: byte, default is a0, values are 00 to ff in hex
Setting26: byte, read-only, default is 00
Setting27: byte, read-only, default is 00
Setting28: byte, read-only, default is 00
Setting29: byte, read-only, default is 80
Setting30: byte, read-only, default is 00
Setting31: byte, read-only, default is 00
Then I run:
Code:
./edit_settings dummy.eeprom
And after setting the values I copy the eeprom back to demul and re-start it. When I load game settings, nothing is changed though... Hmmmm. Maybe I'm missing something? But wait, when I went into calibration, changed nothing and chose the "exit with save" option, it didn't just change the 4 bytes that I messed with. It also messed with several other bytes as well. And when the game wrote defaults way back at the top, it didn't write 60 and a0 for the spots I think are calibration, it wrote 00 and ff. I bet you those other bytes that changed are related as well. So let's make those other settings default to their new values. I changed the definition file to this:
Code:
Game Difficulty: byte, default is 00, 0 - Normal, 1 - Hard
Number of Monkeys: byte, default is 03, values are 2 to 5
Ball Velocity Boost: byte, default is 00, 0 - Off, 1 - On
Setting03: byte, read-only, default is 00
Setting04: byte, read-only, default is 00
Setting05: byte, read-only, default is 00
Setting06: byte, read-only, default is 00
Setting07: byte, read-only, default is 00
Setting08: byte, read-only, default is 00
Setting09: byte, default is 60, values are 00 to ff in hex
Setting10: byte, read-only, default is 00
Setting11: byte, read-only, default is 00
Setting12: byte, read-only, default is 00
Setting13: byte, default is a0, values are 00 to ff in hex
Setting14: byte, read-only, default is 00
Setting15: byte, read-only, default is 00
Setting16: byte, read-only, default is 80
Setting17: byte, read-only, default is 7f
Setting18: byte, read-only, default is 00
Setting19: byte, read-only, default is 00
Setting20: byte, read-only, default is 00
Setting21: byte, default is 60, values are 00 to ff in hex
Setting22: byte, read-only, default is 00
Setting23: byte, read-only, default is 00
Setting24: byte, read-only, default is 00
Setting25: byte, default is a0, values are 00 to ff in hex
Setting26: byte, read-only, default is 00
Setting27: byte, read-only, default is 00
Setting28: byte, read-only, default is 80
Setting29: byte, read-only, default is 7f
Setting30: byte, read-only, default is 00
Setting31: byte, read-only, default is 00
Still no dice. The calibration screen only shows the defaults. That's a bummer. Okay, let's just configure some values on the configuration screen in demul and then print out what the eeprom looks like after calibrating:
Code:
$ ./eeprominfo dummy.eeprom --display
Serial: BDF0
Game Settings Hex: 00 03 00 00 00 00 00 00 39 39 00 00 ff fe 00 00 80 7f 00 00 00 60 00 00 ff fe 00 00 80 7f 00 00
Parsed Game Settings:
Game Difficulty: Normal
Number of Monkeys: 3
Ball Velocity Boost: Off
Setting09: 39
Setting13: fe
Setting21: 60
Setting25: fe
Okay, so our guesses are sorta right. Let's go back in with a fresh eeprom, run the calibration one more time and see if we can't set some unique values for each setting.
After saving that exact calibration, let's print out the eeprom and see what values are there. It looks like we are actually right about the calibration values, but there's more going on:
Code:
$ ./eeprominfo dummy.eeprom --display
Serial: BDF0
Game Settings Hex: 00 03 00 00 00 00 00 00 26 26 00 00 e6 e5 00 00 80 7f 00 00 59 59 00 00 b9 b8 00 00 80 7f 00 00
Parsed Game Settings:
Game Difficulty: Normal
Number of Monkeys: 3
Ball Velocity Boost: Off
Setting09: 26
Setting13: e5
Setting21: 59
Setting25: b8
Wait a minute, the 7f values that are defaulted are pretty suspicious. That's the Now H/Now V values. I bet those are the centering values. For some reason, the game is storing the low values twice, the center values twice (with the first value equal to the second value plus 1), and the high values twice (with the first value equal to the second value plus 1). We can work with that.
Let's start with the following settings modifications:
Code:
Game Difficulty: byte, default is 00, 0 - Normal, 1 - Hard
Number of Monkeys: byte, default is 03, values are 2 to 5
Ball Velocity Boost: byte, default is 00, 0 - Off, 1 - On
Setting03: byte, read-only, default is 00
Setting04: byte, read-only, default is 00
Setting05: byte, read-only, default is 00
Setting06: byte, read-only, default is 00
Setting07: byte, read-only, default is 00
Setting08: byte, read-only, default is 00
Left: byte, default is 60, values are 00 to ff in hex
Setting10: byte, read-only, default is 00
Setting11: byte, read-only, default is 00
Setting12: byte, read-only, default is 00
Right: byte, default is a0, values are 00 to ff in hex
Setting14: byte, read-only, default is 00
Setting15: byte, read-only, default is 00
Setting16: byte, read-only, default is 80
Horizontal Center (Now H): byte, default is 7f, values are 00 to ff in hex
Setting18: byte, read-only, default is 00
Setting19: byte, read-only, default is 00
Setting20: byte, read-only, default is 00
Push: byte, default is 60, values are 00 to ff in hex
Setting22: byte, read-only, default is 00
Setting23: byte, read-only, default is 00
Setting24: byte, read-only, default is 00
Pull: byte, default is a0, values are 00 to ff in hex
Setting26: byte, read-only, default is 00
Setting27: byte, read-only, default is 00
Setting28: byte, read-only, default is 80
Vertical Center (Now V): byte, default is 7f, values are 00 to ff in hex
Setting30: byte, read-only, default is 00
Setting31: byte, read-only, default is 00
Printing out the eeprom we have gives us this:
Code:
$ ./eeprominfo dummy.eeprom --display
Serial: BDF0
Game Settings Hex: 00 03 00 00 00 00 00 00 26 26 00 00 e6 e5 00 00 80 7f 00 00 59 59 00 00 b9 b8 00 00 80 7f 00 00
Parsed Game Settings:
Game Difficulty: Normal
Number of Monkeys: 3
Ball Velocity Boost: Off
Left: 26
Right: e5
Horizontal Center (Now H): 7f
Push: 59
Pull: b8
Vertical Center (Now V): 7f
Okay, so we know that these are the right settings but we still have to handle the other bytes. We can do a fancy trick in "BDF0.settings" where we state that a setting default is dependent on another setting's value. Here's what my settings definition looks like now:
Code:
Game Difficulty: byte, default is 00, 0 - Normal, 1 - Hard
Number of Monkeys: byte, default is 03, values are 2 to 5
Ball Velocity Boost: byte, default is 00, 0 - Off, 1 - On
Setting03: byte, read-only, default is 00
Setting04: byte, read-only, default is 00
Setting05: byte, read-only, default is 00
Setting06: byte, read-only, default is 00
Setting07: byte, read-only, default is 00
LeftUnknown: byte, read-only, default is value of Left
Left: byte, default is 60, values are 00 to ff in hex
Setting10: byte, read-only, default is 00
Setting11: byte, read-only, default is 00
RightUnknown: byte, read-only, default is value of Right + 1
Right: byte, default is a0, values are 00 to ff in hex
Setting14: byte, read-only, default is 00
Setting15: byte, read-only, default is 00
HCenterUnknown: byte, read-only, default is value of Horizontal Center (Now H) + 1
Horizontal Center (Now H): byte, default is 7f, values are 00 to ff in hex
Setting18: byte, read-only, default is 00
Setting19: byte, read-only, default is 00
PushUnknown: byte, read-only, default is value of Push
Push: byte, default is 60, values are 00 to ff in hex
Setting22: byte, read-only, default is 00
Setting23: byte, read-only, default is 00
PullUnknown: byte, read-only, default is value of Pull + 1
Pull: byte, default is a0, values are 00 to ff in hex
Setting26: byte, read-only, default is 00
Setting27: byte, read-only, default is 00
VCenterUnknown: byte, read-only, default is value of Vertical Center (Now V) + 1
Vertical Center (Now V): byte, default is 7f, values are 00 to ff in hex
Setting30: byte, read-only, default is 00
Setting31: byte, read-only, default is 00
So it turns out that the game does not display the current calibration on the screen. It always resets back to 60-a0 for both left/right and push/pull. So my strategy of setting values and seeing what happens would never have worked. I figured that out by running the calibration, saving and exiting and immediately re-entering the screen at which point the calibration values were back to their defaults again. However, it lead me down the path of figuring out that there are other settings bytes that matter. Now that I have this all figured out, I tested it by going into demul, setting the values for the calibration to some random values, then making a copy of the eeprom. I edited the copy and changed some of the calibrations, and then looked at the output of eeprominfo:
Code:
$ ./eeprominfo dummy.eeprom --display
Serial: BDF0
Game Settings Hex: 00 03 00 00 00 00 00 00 39 39 00 00 ff fe 00 00 80 7f 00 00 00 00 00 00 ff fe 00 00 80 7f 00 00
Parsed Game Settings:
Game Difficulty: Normal
Number of Monkeys: 3
Ball Velocity Boost: Off
Left: 39
Right: fe
Horizontal Center (Now H): 7f
Push: 00
Pull: fe
Vertical Center (Now V): 7f
Cool, its adjusting those other bytes the way it should! Finally, I set the values back to what they were before using "edit_settings" and then compared it to the copy of the eeprom that I made above. Everything matched byte-for-byte which means the settings definition is adjusting the correct bytes in the correct manner!
And that's it! Now I have a settings editor for Monkey Ball:
Keep in mind that Monkey Ball ended up being a bit difficult to figure out due to the way the calibration screen works. When I did Marvel Vs. Capcom 2 it was much more straightforward. It should be pretty easy to figure out settings for other games. If you want to give it a try, you can post your results here!