From 42b79c03f587b9796fe3113c87dae51856278164 Mon Sep 17 00:00:00 2001 From: Chesyon <55322011+Chesyon@users.noreply.github.com> Date: Wed, 6 May 2026 08:18:22 -0400 Subject: [PATCH 1/4] Define prng_state struct --- include/overlay_29_022EA9EC.h | 10 ++++++++++ src/overlay_29_022EA9EC.c | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/overlay_29_022EA9EC.h b/include/overlay_29_022EA9EC.h index adb012b5..66cdf6f4 100644 --- a/include/overlay_29_022EA9EC.h +++ b/include/overlay_29_022EA9EC.h @@ -1,6 +1,16 @@ #ifndef PMDSKY_OVERLAY_29_022EA9EC_H #define PMDSKY_OVERLAY_29_022EA9EC_H +#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); #endif //PMDSKY_OVERLAY_29_022EA9EC_H diff --git a/src/overlay_29_022EA9EC.c b/src/overlay_29_022EA9EC.c index b8d0c1c3..150f3b75 100644 --- a/src/overlay_29_022EA9EC.c +++ b/src/overlay_29_022EA9EC.c @@ -1,12 +1,12 @@ #include "overlay_29_022EA9EC.h" -extern u32 DUNGEON_PRNG_STATE[]; +extern prng_state DUNGEON_PRNG_STATE; extern u32 DUNGEON_PRNG_STATE_SECONDARY_VALUES[]; void InitDungeonRng(u32 seed) { - DUNGEON_PRNG_STATE[3] = seed|1; + DUNGEON_PRNG_STATE.last_value_primary = seed|1; s32 scratch_0 = 0; - DUNGEON_PRNG_STATE[1] = scratch_0; + DUNGEON_PRNG_STATE.seq_num_primary = scratch_0; do { DUNGEON_PRNG_STATE_SECONDARY_VALUES[scratch_0]=seed; scratch_0++; From bf88ff37fc44c22a2536df097a10b81e5c1fa361 Mon Sep 17 00:00:00 2001 From: Chesyon <55322011+Chesyon@users.noreply.github.com> Date: Wed, 6 May 2026 08:20:11 -0400 Subject: [PATCH 2/4] Decomp DungeonRand16Bit --- asm/include/overlay_29_022EAA20.inc | 3 --- asm/overlay_29_022EAA20.s | 42 ----------------------------- include/overlay_29_022EA9EC.h | 1 + main.lsf | 1 - src/overlay_29_022EA9EC.c | 28 +++++++++++++++++++ 5 files changed, 29 insertions(+), 46 deletions(-) delete mode 100644 asm/include/overlay_29_022EAA20.inc delete mode 100644 asm/overlay_29_022EAA20.s 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/overlay_29_022EA9EC.h b/include/overlay_29_022EA9EC.h index 66cdf6f4..e2a28edc 100644 --- a/include/overlay_29_022EA9EC.h +++ b/include/overlay_29_022EA9EC.h @@ -12,5 +12,6 @@ typedef struct prng_state { } prng_state; void InitDungeonRng(u32 seed); +u32 DungeonRand16Bit(void); #endif //PMDSKY_OVERLAY_29_022EA9EC_H diff --git a/main.lsf b/main.lsf index e4ab923a..d853f309 100644 --- a/main.lsf +++ b/main.lsf @@ -480,7 +480,6 @@ Overlay OVY_29 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/overlay_29_022EA9EC.c b/src/overlay_29_022EA9EC.c index 150f3b75..a0dcf85e 100644 --- a/src/overlay_29_022EA9EC.c +++ b/src/overlay_29_022EA9EC.c @@ -2,6 +2,8 @@ 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 void InitDungeonRng(u32 seed) { DUNGEON_PRNG_STATE.last_value_primary = seed|1; @@ -12,3 +14,29 @@ void InitDungeonRng(u32 seed) { scratch_0++; } while (scratch_0<5); } + +u32 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); + } +} From fcf64194a0074239e4f0e3fb238ae71975a2b97b Mon Sep 17 00:00:00 2001 From: Chesyon <55322011+Chesyon@users.noreply.github.com> Date: Wed, 6 May 2026 08:27:02 -0400 Subject: [PATCH 3/4] Use decompiled DungeonRand16Bit in dg_random --- include/overlay_29_022EA9EC.h | 2 +- src/dg_random.c | 3 +-- src/overlay_29_022EA9EC.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/overlay_29_022EA9EC.h b/include/overlay_29_022EA9EC.h index e2a28edc..8c4aa5dc 100644 --- a/include/overlay_29_022EA9EC.h +++ b/include/overlay_29_022EA9EC.h @@ -12,6 +12,6 @@ typedef struct prng_state { } prng_state; void InitDungeonRng(u32 seed); -u32 DungeonRand16Bit(void); +u16 DungeonRand16Bit(void); #endif //PMDSKY_OVERLAY_29_022EA9EC_H diff --git a/src/dg_random.c b/src/dg_random.c index 45ac4769..735937ad 100644 --- a/src/dg_random.c +++ b/src/dg_random.c @@ -1,9 +1,8 @@ #include "dg_random.h" +#include "overlay_29_022EA9EC.h" // file starts at 0x022ea968 -extern s16 DungeonRand16Bit(void); - s32 DungeonRandInt(s32 end) { s32 entropy = DungeonRand16Bit(); diff --git a/src/overlay_29_022EA9EC.c b/src/overlay_29_022EA9EC.c index a0dcf85e..4c9f51c8 100644 --- a/src/overlay_29_022EA9EC.c +++ b/src/overlay_29_022EA9EC.c @@ -15,7 +15,7 @@ void InitDungeonRng(u32 seed) { } while (scratch_0<5); } -u32 DungeonRand16Bit(void) { +u16 DungeonRand16Bit(void) { u32 mult = DUNGEON_PRNG_LCG_MULTIPLIER; if (DUNGEON_PRNG_STATE.use_secondary) { From 4479e539313fa79b3981b741780ca91d25da925d Mon Sep 17 00:00:00 2001 From: Chesyon <55322011+Chesyon@users.noreply.github.com> Date: Wed, 6 May 2026 08:40:40 -0400 Subject: [PATCH 4/4] merge overlay_29_022EA9EC with dg_random.c --- include/dg_random.h | 10 +++++++++ include/overlay_29_022EA9EC.h | 17 -------------- main.lsf | 1 - src/dg_random.c | 42 +++++++++++++++++++++++++++++++++-- src/overlay_29_022EA9EC.c | 42 ----------------------------------- 5 files changed, 50 insertions(+), 62 deletions(-) delete mode 100644 include/overlay_29_022EA9EC.h delete mode 100644 src/overlay_29_022EA9EC.c 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 8c4aa5dc..00000000 --- a/include/overlay_29_022EA9EC.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef PMDSKY_OVERLAY_29_022EA9EC_H -#define PMDSKY_OVERLAY_29_022EA9EC_H - -#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); - -#endif //PMDSKY_OVERLAY_29_022EA9EC_H diff --git a/main.lsf b/main.lsf index d853f309..dcd4e58c 100644 --- a/main.lsf +++ b/main.lsf @@ -479,7 +479,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 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 735937ad..1cebc260 100644 --- a/src/dg_random.c +++ b/src/dg_random.c @@ -1,7 +1,45 @@ #include "dg_random.h" -#include "overlay_29_022EA9EC.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 + +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 4c9f51c8..00000000 --- a/src/overlay_29_022EA9EC.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "overlay_29_022EA9EC.h" - -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 - -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); - } -}