Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * This is a refactored version of Mario64's RNG method (as seen
- * in pannenkoek's video*), designed as a module to be put in its own file.
- *
- * Pannenkoek's RNG video: https://www.youtube.com/watch?v=MiuLeTE2MeQ
- *
- * Uses more descriptive type names and avoids casting in favor of bit masking.
- * Runs exactly as fast as the original code according to my benchmarks.
- * But that's not surprising as modern compilers do an excellent job optimizing.
- *
- * The functions shigeru() and miyamoto() were named as such because they
- * are completely random operations that add unnecessary cyclomatic complexity
- * to the algorithm. Thus the function names are also completely random.
- *
- * There aren't that many ways to break it down. In my opinion, the original algorithm
- * is very poorly written. It's not so simple to "fix" it without altering its functionality,
- * as no matter how it is altered, you'll always end up with a dense mess of bitwise operation and
- * hand-optimized (not to mention, inconsistent) code--a telling sign of unmaintainable code
- * that was written once and never touched again.
- */
- typedef unsigned char uint8;
- typedef unsigned short uint16;
- typedef signed short sint16;
- static const uint16 MAGIC[] = { 0x560A, 0xFF80, 0xAA55, 0x1FF4, 0x8180 };
- static uint16
- high_byte(uint16 n)
- {
- return n & 0xFF00;
- }
- static uint16
- low_byte(uint16 n)
- {
- return n & 0x00FF;
- }
- static uint16
- low_to_high(uint16 n)
- {
- return low_byte(n) << 8;
- }
- static uint16
- high_to_low(uint16 n)
- {
- return high_byte(n) >> 8;
- }
- static uint16
- swap_bytes(uint16 n)
- {
- return low_to_high(n) | high_to_low(n);
- }
- static uint8
- is_odd(uint16 n)
- {
- return n % 2 == 1;
- }
- static sint16
- shigeru(sint16 n)
- {
- return n ^ MAGIC[4];
- }
- static uint16
- miyamoto(sint16 n)
- {
- return (n == MAGIC[2]) ? 0 : (n ^ MAGIC[3]);
- }
- uint16
- get_random_number(uint16 input)
- {
- uint16 s0, s1;
- input = input == MAGIC[0] ? 0 : input;
- s0 = low_to_high(input) ^ input;
- input = swap_bytes(s0);
- s0 = (low_byte(s0) << 1) ^ input;
- s1 = (s0 >> 1) ^ MAGIC[1];
- input = is_odd(s0) ? shigeru(s1) : miyamoto(s1);
- return input;
- }
- // Works as expected: get_random_number(17711) -> 63470
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement