diff --git a/rng.md b/rng.md new file mode 100644 index 0000000..dc352be --- /dev/null +++ b/rng.md @@ -0,0 +1,121 @@ +# info dump on the RNG in OoT and MM + +if you find any discrepancies, please +leave a comment or tweet at [@antiformant][twitter]. + +[twitter]: https://twitter.com/antiformant + +## the function itself + +the random number generator in both games is an LCG: +https://en.wikipedia.org/wiki/Linear_congruential_generator +specifically, it uses the constants from Numerical Recipes in C. + +```c +/* the C code looks something like this: */ +static uint32_t rng_value = 1; +uint32_t prng() { + /* note: intentional unsigned overflow. */ + rng_value = rng_value * 1664525 + 1013904223; + return rng_value; + /* note: in the game, there's some code to reinterpret the value + as a floating point number, which I've omitted here. */ +} +``` + +if you're interested, you can find the function(s) in any version by searching +for F35F in RAM. you should see a 660D nearby, usually a bit before. +you can find the rng_value variable +by looking at the disassembly of the RNG function. +note that there are a few different variations of the function +that are not commonly invoked; you can find these the same way. + +here are some known addresses: + +game, version | RNG value | RNG function | variants +------------- | --------- | ------------ | -------- +OoT 1.0 | 80105440 | 800CDC90 | ? +OoT 1.2 | 80105A80 | 800CE4D0 | ? +MM (J) 1.1 | 8009E890 | 8008797C | 80087940 +MM (U): | 80097530 | 80086FDC | ? + +## the quirks + +when a new scene is loaded, +the RNG value is set directly to the CPU's cycle count. +that means, depending on all the code that has been run +up to that point, the RNG value is set to a +pseudo-unpredictable value when you enter a new area. + +to clarify what a "new scene" being loaded is: + +* loading the title screen +* loading a save file +* entering a new area (TODO: do rooms within a scene count?) +* **not** the N64 logo being shown +* **not** the file select screen + +### other invocations + +creating a new file will invoke the RNG +to determine the Bomber's Code, etc. +obviously, this does not apply to OoT. + +although the GameCube versions don't have an N64 logo, +they still do similar initializations before the title screen is shown. + +### emulators + +as far as i know, the cycle counter in emulators +(including Virtual Console, excluding CEN64) +is very roughly approximated. +it's not a critical component to emulating most games, +so emulators can skimp on it to achieve better performance. + +this means RNG should be fairly consistent, given identical inputs. +*this does not mean RNG will be consistent across emulators.* +the plugins you use might affect this as well. + +## exploiting the RNG + +### in Ocarina of Time + +because the title screen sequence starts on Hyrule Field +with a ton of actors loaded, +the RNG value is updated many times each frame. + +as far as i know, you'd have to be frame perfect to reach the file select screen +with a consistent RNG, but i haven't done a lot of testing. +maybe there's a part of the title sequence +with wider gaps between RNG invocations, +giving you a wider window to enter the inputs to reach the file select screen. + +this might not be exploitable anyway due to +the reset that occurs when loading scenes, as described earlier. + +### in Majora's Mask + +the first title screen in this game is very simple. +only a handful of actors are loaded and executing. +as a result, the RNG is only invoked +something like every 75 frames *on average.* + +this is a big window to reach the file select screen. +*in theory,* you should be able mash A and Start to reach the +file select to create a file, and that file will have the same +Bomber's code, lottery codes, and Spider House mask order. + +remember that "the same" is specific to each emulator, +as described earlier. + +### in practice + +this needs testing. + +i can somewhat consistently reach the file select screen +with the same RNG value in Project64 2.2 and Bizhawk 1.12.1. + +Virtual Console and N64 have not been tested. + +this might be useful for the new MM 100% ruleset +if it's found to be consistent, but don't hold your breath.