Merge remote-tracking branch 'rng64/master'
This commit is contained in:
commit
f94f5382de
1 changed files with 121 additions and 0 deletions
121
rng.md
Normal file
121
rng.md
Normal file
|
@ -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.
|
Loading…
Reference in a new issue