2017-04-25 11:44:45 -07:00
|
|
|
# info dump on the RNG in OoT and MM
|
|
|
|
|
2017-04-25 11:52:21 -07:00
|
|
|
if you find any discrepancies, please
|
|
|
|
leave a comment or tweet at [@antiformant][twitter].
|
|
|
|
|
|
|
|
[twitter]: https://twitter.com/antiformant
|
|
|
|
|
2017-04-25 11:44:45 -07:00
|
|
|
## 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
|
2017-04-25 11:52:21 -07:00
|
|
|
that are not commonly invoked; you can find these the same way.
|
2017-04-25 11:44:45 -07:00
|
|
|
|
|
|
|
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.
|
2017-04-25 11:52:21 -07:00
|
|
|
obviously, this does not apply to OoT.
|
2017-04-25 11:44:45 -07:00
|
|
|
|
|
|
|
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
|
2017-04-25 11:57:05 -07:00
|
|
|
the reset that occurs when loading scenes, as described earlier.
|
2017-04-25 11:44:45 -07:00
|
|
|
|
|
|
|
### 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.
|