diff --git a/asm/include/overlay_29_022EAA20.inc b/asm/include/overlay_29_022EAA20.inc deleted file mode 100644 index b8c60004..00000000 --- a/asm/include/overlay_29_022EAA20.inc +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -.public DUNGEON_PRNG_STATE -.public DUNGEON_PRNG_STATE_SECONDARY_VALUES diff --git a/asm/overlay_29_022EAA20.s b/asm/overlay_29_022EAA20.s deleted file mode 100644 index 10a98a1d..00000000 --- a/asm/overlay_29_022EAA20.s +++ /dev/null @@ -1,42 +0,0 @@ - .include "asm/macros.inc" - .include "overlay_29_022EAA20.inc" - - .text - -; https://decomp.me/scratch/UiD3J - arm_func_start DungeonRand16Bit -DungeonRand16Bit: ; 0x022EAA20 - stmdb sp!, {r3, lr} - ldr r1, _022EAA88 ; =DUNGEON_PRNG_STATE - ldrb r0, [r1] - cmp r0, #0 - ldr r0, _022EAA8C ; =0x5D588B65 - beq _022EAA5C - ldr lr, [r1, #0x10] - ldr r3, _022EAA90 ; =DUNGEON_PRNG_STATE_SECONDARY_VALUES - ldr r1, _022EAA94 ; =0x00269EC3 - ldr r2, [r3, lr, lsl #2] - umull ip, r0, r2, r0 - adds r1, ip, r1 - mov r0, r1, lsl #0x10 - str r1, [r3, lr, lsl #2] - b _022EAA80 -_022EAA5C: - ldr r2, [r1, #4] - add r2, r2, #1 - str r2, [r1, #4] - ldr r2, [r1, #0xc] - mul r0, r2, r0 - add r2, r0, #1 - mov r0, r2, lsr #0x10 - mov r0, r0, lsl #0x10 - str r2, [r1, #0xc] -_022EAA80: - mov r0, r0, lsr #0x10 - ldmia sp!, {r3, pc} - .align 2, 0 -_022EAA88: .word DUNGEON_PRNG_STATE -_022EAA8C: .word 0x5D588B65 -_022EAA90: .word DUNGEON_PRNG_STATE_SECONDARY_VALUES -_022EAA94: .word 0x00269EC3 - arm_func_end DungeonRand16Bit diff --git a/include/dg_random.h b/include/dg_random.h index d11d62e6..ac3acb46 100644 --- a/include/dg_random.h +++ b/include/dg_random.h @@ -3,6 +3,16 @@ #include "util.h" +typedef struct prng_state { + bool8 use_secondary; + u32 seq_num_primary; + u32 preseed; + u32 last_value_primary; + s32 idx_secondary; +} prng_state; + +void InitDungeonRng(u32 seed); +u16 DungeonRand16Bit(void); // Compute a pseudorandom integer under a given maximum value using the dungeon PRNG. // pseudorandom integer on the interval [0, end - 1] s32 DungeonRandInt(s32 end); diff --git a/include/overlay_29_022EA9EC.h b/include/overlay_29_022EA9EC.h deleted file mode 100644 index adb012b5..00000000 --- a/include/overlay_29_022EA9EC.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef PMDSKY_OVERLAY_29_022EA9EC_H -#define PMDSKY_OVERLAY_29_022EA9EC_H - -void InitDungeonRng(u32 seed); - -#endif //PMDSKY_OVERLAY_29_022EA9EC_H diff --git a/main.lsf b/main.lsf index 539db911..f777412b 100644 --- a/main.lsf +++ b/main.lsf @@ -481,8 +481,6 @@ Overlay OVY_29 Object asm/overlay_29_022E9488.o Object src/dg_uty.o Object asm/overlay_29_022E9618.o - Object src/overlay_29_022EA9EC.o - Object asm/overlay_29_022EAA20.o Object src/dg_random.o Object asm/overlay_29_022EAB50.o Object src/dungeon_action.o diff --git a/src/dg_random.c b/src/dg_random.c index 45ac4769..1cebc260 100644 --- a/src/dg_random.c +++ b/src/dg_random.c @@ -1,8 +1,45 @@ #include "dg_random.h" -// file starts at 0x022ea968 +extern prng_state DUNGEON_PRNG_STATE; +extern u32 DUNGEON_PRNG_STATE_SECONDARY_VALUES[]; +#define DUNGEON_PRNG_LCG_MULTIPLIER 0x5d588b65 +#define DUNGEON_PRNG_LCG_INCREMENT_SECONDARY 0x00269ec3 -extern s16 DungeonRand16Bit(void); +void InitDungeonRng(u32 seed) { + DUNGEON_PRNG_STATE.last_value_primary = seed|1; + s32 scratch_0 = 0; + DUNGEON_PRNG_STATE.seq_num_primary = scratch_0; + do { + DUNGEON_PRNG_STATE_SECONDARY_VALUES[scratch_0]=seed; + scratch_0++; + } while (scratch_0<5); +} + +u16 DungeonRand16Bit(void) { + u32 mult = DUNGEON_PRNG_LCG_MULTIPLIER; + + if (DUNGEON_PRNG_STATE.use_secondary) { + u32 increment = DUNGEON_PRNG_LCG_INCREMENT_SECONDARY; + s32 idx = DUNGEON_PRNG_STATE.idx_secondary; + u32 val = DUNGEON_PRNG_STATE_SECONDARY_VALUES[idx]; + + u64 temp = (u64)val * mult; + temp += increment; + + u32 result = (u32)temp; + DUNGEON_PRNG_STATE_SECONDARY_VALUES[idx] = result; + + return (u16)result; + } else { + // Accessing the global directly often changes register allocation + DUNGEON_PRNG_STATE.seq_num_primary++; + + u32 result = (DUNGEON_PRNG_STATE.last_value_primary * mult) + 1; + DUNGEON_PRNG_STATE.last_value_primary = result; + + return (u16)(result >> 16); + } +} s32 DungeonRandInt(s32 end) { diff --git a/src/overlay_29_022EA9EC.c b/src/overlay_29_022EA9EC.c deleted file mode 100644 index b8d0c1c3..00000000 --- a/src/overlay_29_022EA9EC.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "overlay_29_022EA9EC.h" - -extern u32 DUNGEON_PRNG_STATE[]; -extern u32 DUNGEON_PRNG_STATE_SECONDARY_VALUES[]; - -void InitDungeonRng(u32 seed) { - DUNGEON_PRNG_STATE[3] = seed|1; - s32 scratch_0 = 0; - DUNGEON_PRNG_STATE[1] = scratch_0; - do { - DUNGEON_PRNG_STATE_SECONDARY_VALUES[scratch_0]=seed; - scratch_0++; - } while (scratch_0<5); -}