From 6b29ad6affdcdddf2fc1755e2e595d3fdc085cbb Mon Sep 17 00:00:00 2001 From: slaw-22 <> Date: Tue, 19 May 2026 20:03:27 +0000 Subject: [PATCH 1/4] Decomp CopySpawnEntriesOnce. Ensure 100% matches by localising DUNGEON_PTR externs with slightly different definitions. --- asm/overlay_29_022DEBA4.s | 2 +- asm/overlay_29_022E37DC.s | 35 +----------------------------- include/dungeon.h | 7 ++---- include/spawn_1.h | 6 +++++ include/{spawn.h => spawn_2.h} | 6 ++--- main.lsf | 3 ++- src/dg_camera.c | 2 ++ src/dg_uty.c | 1 + src/dungeon_ai.c | 2 ++ src/dungeon_ai_attack.c | 1 + src/dungeon_ai_itcm.c | 2 ++ src/dungeon_ai_items_1.c | 1 + src/dungeon_ai_movement.c | 2 ++ src/dungeon_capabilities_4.c | 2 ++ src/dungeon_damage.c | 2 ++ src/dungeon_logic_5.c | 2 ++ src/dungeon_logic_7.c | 2 ++ src/dungeon_map_access.c | 1 + src/dungeon_map_access_1.c | 2 ++ src/dungeon_pokemon_attributes_1.c | 2 ++ src/dungeon_projectile_throw.c | 2 ++ src/dungeon_range.c | 2 ++ src/dungeon_recruitment.c | 1 + src/fixed_room_data_1.c | 2 ++ src/move_checks.c | 2 ++ src/overlay_29_022DEAB0.c | 2 ++ src/overlay_29_022F7364.c | 2 ++ src/overlay_29_022F73B4.c | 2 ++ src/overlay_29_022F7654.c | 1 + src/overlay_29_022FA430.c | 2 ++ src/overlay_29_022FB538.c | 2 ++ src/overlay_29_022FBBEC.c | 2 ++ src/overlay_29_023000E4.c | 2 ++ src/overlay_29_0230AB58.c | 2 ++ src/overlay_29_02336428.c | 2 ++ src/overlay_29_0233836C.c | 2 ++ src/overlay_29_023383a8_0.c | 2 ++ src/overlay_29_02338548.c | 2 ++ src/overlay_29_02338560.c | 1 + src/overlay_29_02338604.c | 2 ++ src/overlay_31_02382820.c | 2 ++ src/overlay_31_02383478.c | 1 + src/overlay_31_02383880.c | 1 + src/run_dungeon.c | 2 ++ src/run_dungeon_1.c | 2 ++ src/spawn_1.c | 15 +++++++++++++ src/{spawn.c => spawn_2.c} | 4 +++- src/weather.c | 2 ++ 48 files changed, 104 insertions(+), 45 deletions(-) create mode 100644 include/spawn_1.h rename include/{spawn.h => spawn_2.h} (75%) create mode 100644 src/spawn_1.c rename src/{spawn.c => spawn_2.c} (96%) diff --git a/asm/overlay_29_022DEBA4.s b/asm/overlay_29_022DEBA4.s index aea6f2cb..2e4405f4 100644 --- a/asm/overlay_29_022DEBA4.s +++ b/asm/overlay_29_022DEBA4.s @@ -710,7 +710,7 @@ _022DF574: bl ov29_022E8708 bl ov29_022DD5B4 bl ov29_023369F8 - bl ov29_022E7CFC + bl CopySpawnEntriesOnce bl ov29_022F7130 cmp r5, #0 bne _022DF5C4 diff --git a/asm/overlay_29_022E37DC.s b/asm/overlay_29_022E37DC.s index 7c117624..bed9eaf2 100644 --- a/asm/overlay_29_022E37DC.s +++ b/asm/overlay_29_022E37DC.s @@ -5618,37 +5618,4 @@ _022E7CF4: .word DUNGEON_PTR _022E7CF8: .word 0x0002C966 #endif arm_func_end MonsterSpawnListPartialCopy - - arm_func_start ov29_022E7CFC -ov29_022E7CFC: ; 0x022E7CFC -#ifdef JAPAN -#define OV29_022E7CFC_OFFSET -0xA4 -#else -#define OV29_022E7CFC_OFFSET 0 -#endif - stmdb sp!, {r3, lr} - ldr r1, _022E7D48 ; =DUNGEON_PTR - ldr r0, [r1] - add r0, r0, #0x3000 - ldrb r2, [r0, #0xe28 + OV29_022E7CFC_OFFSET] - cmp r2, #0 - ldmneia sp!, {r3, pc} - mov r2, #1 - strb r2, [r0, #0xe28 + OV29_022E7CFC_OFFSET] - ldr r0, [r1] - mov r1, #0 -#ifdef JAPAN - add r0, r0, #0x124 -#else - add r0, r0, #0x174 -#endif - add r0, r0, #0x3800 - bl CopySpawnEntriesMaster - ldr r1, _022E7D48 ; =DUNGEON_PTR - ldr r1, [r1] - add r1, r1, #0x3000 - str r0, [r1, #0xe20 + OV29_022E7CFC_OFFSET] - ldmia sp!, {r3, pc} - .align 2, 0 -_022E7D48: .word DUNGEON_PTR - arm_func_end ov29_022E7CFC + diff --git a/include/dungeon.h b/include/dungeon.h index 003e230d..ca7fe221 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -12,8 +12,6 @@ #define DUNGEON_MAX_SIZE_Y 32 #define CORRIDOR_ROOM 0xFF -extern struct dungeon *DUNGEON_PTR[]; - enum terrain_type { // These 3 seem to indicate the 'main' type of the terrain. See helper functions for how they're set. @@ -1217,9 +1215,8 @@ struct dungeon { u8 field_0x3e25; u8 field_0x3e26; u8 field_0x3e27; - // 0x3E28: Related in some way to the spawn entries on the floor. Does something about them - // if false, then set to true. - bool8 unk_spawn_entry_id_check; + // 0x3E28: Set to true after spawn entries are copied. Prevents copying spawn entries more than once. + bool8 spawn_entries_copied; u8 field_0x3e29; u8 field_0x3e2a; u8 field_0x3e2b; diff --git a/include/spawn_1.h b/include/spawn_1.h new file mode 100644 index 00000000..f6b70ad7 --- /dev/null +++ b/include/spawn_1.h @@ -0,0 +1,6 @@ +#ifndef PMDSKY_SPAWN_1_H +#define PMDSKY_SPAWN_1_H + +void CopySpawnEntriesOnce(); + +#endif //PMDSKY_SPAWN_1_H diff --git a/include/spawn.h b/include/spawn_2.h similarity index 75% rename from include/spawn.h rename to include/spawn_2.h index bcf3ee28..8868b47e 100644 --- a/include/spawn.h +++ b/include/spawn_2.h @@ -1,5 +1,5 @@ -#ifndef PMDSKY_SPAWN_H -#define PMDSKY_SPAWN_H +#ifndef PMDSKY_SPAWN_2_H +#define PMDSKY_SPAWN_2_H // Weight type index is 0 for normal spawns and 1 for monster house spawns. // Returns a monster ID. @@ -7,4 +7,4 @@ s32 GetMonsterIdToSpawn(s32 weight_type_idx); s32 GetMonsterLevelToSpawn(s32 monster_id); s32 IsOnMonsterSpawnList(s32 monster_id); -#endif //PMDSKY_SPAWN_H +#endif //PMDSKY_SPAWN_2_H diff --git a/main.lsf b/main.lsf index 6862a146..c8602b4d 100644 --- a/main.lsf +++ b/main.lsf @@ -506,7 +506,8 @@ Overlay OVY_29 Object asm/overlay_29_022E335C.o Object src/dg_effect.o Object asm/overlay_29_022E37DC.o - Object src/spawn.o + Object src/spawn_1.o + Object src/spawn_2.o Object asm/overlay_29_022E7EC4.o Object src/position_util.o Object asm/overlay_29_rodata_02351628.o diff --git a/src/dg_camera.c b/src/dg_camera.c index d6c6ab3e..f5ca9ee8 100644 --- a/src/dg_camera.c +++ b/src/dg_camera.c @@ -6,6 +6,8 @@ // file starts at 0x022e26b68 +extern struct dungeon *DUNGEON_PTR[]; + bool8 EntityIsValid__022E32E8(struct entity *entity) { if (entity == NULL) diff --git a/src/dg_uty.c b/src/dg_uty.c index a0a5aa8a..dd689045 100644 --- a/src/dg_uty.c +++ b/src/dg_uty.c @@ -4,6 +4,7 @@ // file starts at 0x022e9020 +extern struct dungeon *DUNGEON_PTR[]; extern struct entity *LEADER_PTR; struct entity* GetLeader() diff --git a/src/dungeon_ai.c b/src/dungeon_ai.c index e2edaa92..ecc8ff16 100644 --- a/src/dungeon_ai.c +++ b/src/dungeon_ai.c @@ -24,6 +24,8 @@ #define WATCHING_CAREFULLY_MESSAGE 0xDEE #endif +extern struct dungeon *DUNGEON_PTR[]; + extern void EndFrozenClassStatus(struct entity *user, struct entity *target, bool8 log); extern void SubstitutePlaceholderStringTags(u8 *string_id, struct entity *entity, u32 param_3); extern void LogMessageByIdWithPopupCheckUser(struct entity *user, u32 message_id); diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 66c67a1b..8763c23a 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -27,6 +27,7 @@ bool8 AI_CAN_ATTACK_IN_DIRECTION[NUM_DIRECTIONS] = {0}; u8 AI_POTENTIAL_ATTACK_TARGET_DIRECTIONS[NUM_DIRECTIONS] = {0}; +extern struct dungeon *DUNGEON_PTR[]; // AI_POTENTIAL_ATTACK_TARGET_WEIGHTS is defined twice within AiConsiderMove, so it needs two separate symbols in ASM until the function is matched. #ifdef NONMATCHING diff --git a/src/dungeon_ai_itcm.c b/src/dungeon_ai_itcm.c index 98883382..67d4a0cb 100644 --- a/src/dungeon_ai_itcm.c +++ b/src/dungeon_ai_itcm.c @@ -29,6 +29,8 @@ #define REGULAR_ATTACK_INDEX 4 +extern struct dungeon *DUNGEON_PTR[]; + // https://decomp.me/scratch/zg7V6 #ifdef NONMATCHING void ChooseAiMove(struct entity *monster) diff --git a/src/dungeon_ai_items_1.c b/src/dungeon_ai_items_1.c index a34190b8..9f156d59 100644 --- a/src/dungeon_ai_items_1.c +++ b/src/dungeon_ai_items_1.c @@ -16,6 +16,7 @@ // This needs to be marked as non-volatile here to match GetPossibleAiThrownItemDirections, // but AiDecideUseItem needs it to be volatile to match. extern s32 AI_THROWN_ITEM_ACTION_CHOICE_COUNT; +extern struct dungeon *DUNGEON_PTR[]; void GetPossibleAiThrownItemDirections(struct entity *entity, s32 ally_or_enemy, struct item *item, bool8 always_add) { diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index c7a4d5da..cdbdf7bd 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -40,6 +40,8 @@ #define TURN_RIGHT_90 4 #define TURN_LEFT_135 5 +extern struct dungeon *DUNGEON_PTR[]; + struct can_move_in_direction_info { bool8 try_turn; diff --git a/src/dungeon_capabilities_4.c b/src/dungeon_capabilities_4.c index 1ad90b87..7ec740c0 100644 --- a/src/dungeon_capabilities_4.c +++ b/src/dungeon_capabilities_4.c @@ -16,6 +16,8 @@ #include "secondary_terrain_types.h" #include "targeting.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 CanMonsterMoveOrSwapWithAllyInAnyDirection(struct entity *monster) { for (u8 i = 0; i < NUM_DIRECTIONS; i++) diff --git a/src/dungeon_damage.c b/src/dungeon_damage.c index 0bbdb705..90669778 100644 --- a/src/dungeon_damage.c +++ b/src/dungeon_damage.c @@ -12,6 +12,8 @@ #define NUM_EFFECTIVENESS 4 +extern struct dungeon *DUNGEON_PTR[]; + s32 WeightWeakTypePicker(struct entity *user, struct entity *target, enum type_id move_type) { s32 weight = 1; diff --git a/src/dungeon_logic_5.c b/src/dungeon_logic_5.c index 5c42e62a..7a36e2c9 100644 --- a/src/dungeon_logic_5.c +++ b/src/dungeon_logic_5.c @@ -9,6 +9,8 @@ #include "overlay_29_023000E4.h" #include "special_move_types.h" +extern struct dungeon *DUNGEON_PTR[]; + extern s32 GetMoveBasePower(struct move*); bool8 CanSeeTeammate(struct entity *monster) diff --git a/src/dungeon_logic_7.c b/src/dungeon_logic_7.c index 036f3cf4..a08b0767 100644 --- a/src/dungeon_logic_7.c +++ b/src/dungeon_logic_7.c @@ -6,6 +6,8 @@ #include "fixed_room_data_1.h" #include "util.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsMonsterLoneOutlaw(struct monster* monster_info) { return IsBehaviorLoneOutlaw(monster_info->monster_behavior); diff --git a/src/dungeon_map_access.c b/src/dungeon_map_access.c index 9b851f69..de5b89e2 100644 --- a/src/dungeon_map_access.c +++ b/src/dungeon_map_access.c @@ -1,6 +1,7 @@ #include "dungeon_map_access.h" #include "dungeon.h" +extern struct dungeon *DUNGEON_PTR[]; extern struct tile DEFAULT_TILE_COPY; extern struct tile* DEFAULT_TILE; diff --git a/src/dungeon_map_access_1.c b/src/dungeon_map_access_1.c index a596cdc3..dfbb7969 100644 --- a/src/dungeon_map_access_1.c +++ b/src/dungeon_map_access_1.c @@ -4,6 +4,8 @@ #include "secondary_terrain_types.h" #include "tileset.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsTileGround(struct tile *tile) { bool8 is_ground = FALSE; diff --git a/src/dungeon_pokemon_attributes_1.c b/src/dungeon_pokemon_attributes_1.c index 5942a625..eea90f87 100644 --- a/src/dungeon_pokemon_attributes_1.c +++ b/src/dungeon_pokemon_attributes_1.c @@ -11,6 +11,8 @@ #include "progression.h" #include "pokemon.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 CanSeeInvisibleMonsters(struct entity *entity) { if (GetEntInfo(entity)->blinker_class_status.blinded == STATUS_BLINKER_EYEDROPS) diff --git a/src/dungeon_projectile_throw.c b/src/dungeon_projectile_throw.c index 2cfb254a..fd0fe6c9 100644 --- a/src/dungeon_projectile_throw.c +++ b/src/dungeon_projectile_throw.c @@ -20,6 +20,8 @@ #define CURVED_PROJECTILE_LOG_MESSAGE_3 0xbe3 #endif +extern struct dungeon *DUNGEON_PTR[]; + extern bool8 ov29_022E2CA0(struct position *pos); extern void ov29_0234B4CC(bool8 val); extern s32 SinAbs4096(s32 x); diff --git a/src/dungeon_range.c b/src/dungeon_range.c index de6aa98d..fefbcd05 100644 --- a/src/dungeon_range.c +++ b/src/dungeon_range.c @@ -5,6 +5,8 @@ #include "dungeon_range_2.h" #include "main_0208655C.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsPositionActuallyInSight(struct position *origin, struct position *target, bool8 user_has_dropeye) { s16 visibility = GetVisibilityRange(); diff --git a/src/dungeon_recruitment.c b/src/dungeon_recruitment.c index 38f081d4..2694ef0e 100644 --- a/src/dungeon_recruitment.c +++ b/src/dungeon_recruitment.c @@ -33,6 +33,7 @@ extern const s16 ROCK_HORN_RECRUIT_BOOST; extern const s16 GRASS_CORNET_RECRUIT_BOOST; extern const s16 SKY_MELODICA_RECRUIT_BOOST; +extern struct dungeon *DUNGEON_PTR[]; extern s16 RECRUITMENT_LEVEL_BOOST_TABLE[]; bool8 SpecificRecruitCheck(u32 monster_id) diff --git a/src/fixed_room_data_1.c b/src/fixed_room_data_1.c index 719929e9..73419034 100644 --- a/src/fixed_room_data_1.c +++ b/src/fixed_room_data_1.c @@ -2,6 +2,8 @@ #include "dungeon.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsFullFloorFixedRoom() { u8 fixed_room_id = DUNGEON_PTR[0]->gen_info.fixed_room_id; diff --git a/src/move_checks.c b/src/move_checks.c index b8d15c28..3e430f1e 100644 --- a/src/move_checks.c +++ b/src/move_checks.c @@ -17,6 +17,8 @@ #include "trap.h" #include "weather.h" +extern struct dungeon *DUNGEON_PTR[]; + extern bool8 GendersEqualNotGenderless(s16 monster1, s16 monster2); // https://decomp.me/scratch/TnODN diff --git a/src/overlay_29_022DEAB0.c b/src/overlay_29_022DEAB0.c index 089bdb63..2e9472e5 100644 --- a/src/overlay_29_022DEAB0.c +++ b/src/overlay_29_022DEAB0.c @@ -11,6 +11,8 @@ void sub_020091B0(s32, s32); void StartFadeDungeonWrapper(s32, s32, s32); void ov29_0234C738(s32); +extern struct dungeon *DUNGEON_PTR[]; + struct dungeon* DungeonAlloc(void) { #ifdef JAPAN diff --git a/src/overlay_29_022F7364.c b/src/overlay_29_022F7364.c index af4d7bf5..0b6d78be 100644 --- a/src/overlay_29_022F7364.c +++ b/src/overlay_29_022F7364.c @@ -4,6 +4,8 @@ #include "util.h" #include "main_02051760.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 EntityIsValid__022F7364(struct entity *entity) { if (entity == NULL) diff --git a/src/overlay_29_022F73B4.c b/src/overlay_29_022F73B4.c index 7f62619d..d2e69af2 100644 --- a/src/overlay_29_022F73B4.c +++ b/src/overlay_29_022F73B4.c @@ -3,6 +3,8 @@ #include "util.h" #include "enums.h" +extern struct dungeon *DUNGEON_PTR[]; + bool32 FloorNumberIsEven() { struct dungeon *dungeon = DUNGEON_PTR[0]; if (dungeon->id == DUNGEON_LABYRINTH_CAVE && dungeon->floor == 10) return 0; diff --git a/src/overlay_29_022F7654.c b/src/overlay_29_022F7654.c index 5938a57a..3fd337f6 100644 --- a/src/overlay_29_022F7654.c +++ b/src/overlay_29_022F7654.c @@ -3,6 +3,7 @@ #include "enums.h" #include "wan.h" +extern struct dungeon *DUNGEON_PTR[]; extern struct wan_table *WAN_TABLE; extern s16 GetSpriteIndex__020526EC(s16 monster_id); extern s16 ReplaceWanFromBinFile(struct wan_table *wan_table, s16 wan_id, s16 pack_id, s16 file_index, bool8 compressed); diff --git a/src/overlay_29_022FA430.c b/src/overlay_29_022FA430.c index 210a9516..c1317943 100644 --- a/src/overlay_29_022FA430.c +++ b/src/overlay_29_022FA430.c @@ -7,6 +7,8 @@ #include "overlay_29_02336428.h" #include "position_util.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 ShouldMonsterHeadToStairs(struct entity *entity) { u8 stairs_room = GetStairsRoom(); diff --git a/src/overlay_29_022FB538.c b/src/overlay_29_022FB538.c index 5d10936a..4c8aec6d 100644 --- a/src/overlay_29_022FB538.c +++ b/src/overlay_29_022FB538.c @@ -5,6 +5,8 @@ #include "overlay_29_022F7364.h" #include "targeting.h" +extern struct dungeon *DUNGEON_PTR[]; + extern u8 GetScenarioBalanceVeneer(); extern u32 GetSpawnThreshold(); diff --git a/src/overlay_29_022FBBEC.c b/src/overlay_29_022FBBEC.c index c904f793..bbc00357 100644 --- a/src/overlay_29_022FBBEC.c +++ b/src/overlay_29_022FBBEC.c @@ -3,6 +3,8 @@ #include "dungeon_util_static.h" #include "overlay_29_022F7364.h" +extern struct dungeon *DUNGEON_PTR[]; + struct entity* FindMonsterWithBehavior(enum monster_behavior monster_behavior) { for (s32 i = 0; i < DUNGEON_MAX_POKEMON; i++) diff --git a/src/overlay_29_023000E4.c b/src/overlay_29_023000E4.c index b163d6ec..8e91ddf2 100644 --- a/src/overlay_29_023000E4.c +++ b/src/overlay_29_023000E4.c @@ -1,6 +1,8 @@ #include "overlay_29_023000E4.h" #include "dungeon_util_static.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 EntityIsValid__023000E4(struct entity *entity) { if (entity == NULL) diff --git a/src/overlay_29_0230AB58.c b/src/overlay_29_0230AB58.c index ae04ebfc..b6237b38 100644 --- a/src/overlay_29_0230AB58.c +++ b/src/overlay_29_0230AB58.c @@ -3,6 +3,8 @@ #include "dungeon_pokemon_attributes.h" #include "dungeon_util_static.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 ScrappyShouldActivate(struct entity *attacker, struct entity *defender, enum type_id attack_type) { for (s16 i = 0; i < 2; i++) diff --git a/src/overlay_29_02336428.c b/src/overlay_29_02336428.c index 71401239..5361d0d3 100644 --- a/src/overlay_29_02336428.c +++ b/src/overlay_29_02336428.c @@ -2,6 +2,8 @@ #include "dungeon.h" #include "dungeon_map_access.h" +extern struct dungeon *DUNGEON_PTR[]; + u8 GetStairsRoom() { return GetTile(DUNGEON_PTR[0]->gen_info.stairs_pos.x, DUNGEON_PTR[0]->gen_info.stairs_pos.y)->room; diff --git a/src/overlay_29_0233836C.c b/src/overlay_29_0233836C.c index 3c99d670..ace89675 100644 --- a/src/overlay_29_0233836C.c +++ b/src/overlay_29_0233836C.c @@ -3,6 +3,8 @@ #include "main_0200330C.h" #include "overlay_29_02337CA8.h" +extern struct dungeon *DUNGEON_PTR[]; + extern void LogMessageByIdWithPopupCheckUser(struct entity *user, u32 message_id); extern void ov29_02306D54(struct entity *); diff --git a/src/overlay_29_023383a8_0.c b/src/overlay_29_023383a8_0.c index 88fce053..551a48f3 100644 --- a/src/overlay_29_023383a8_0.c +++ b/src/overlay_29_023383a8_0.c @@ -3,6 +3,8 @@ #include "dungeon.h" #include "dungeon_mode.h" +extern struct dungeon *DUNGEON_PTR[]; + extern void TryRevealAttackedTrap(struct position* pos, int param1); extern bool32 PositionIsOnHiddenStairs(struct position* pos); extern void HiddenStairsTrigger(bool32 param0); diff --git a/src/overlay_29_02338548.c b/src/overlay_29_02338548.c index 2a9efa14..bd0cb075 100644 --- a/src/overlay_29_02338548.c +++ b/src/overlay_29_02338548.c @@ -2,6 +2,8 @@ #include "dungeon.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 TeamMemberHasExclusiveItemEffectActive(u8); bool8 ShouldBoostKecleonShopSpawnChance(void) diff --git a/src/overlay_29_02338560.c b/src/overlay_29_02338560.c index a5f5bdde..fb5a3ce3 100644 --- a/src/overlay_29_02338560.c +++ b/src/overlay_29_02338560.c @@ -2,6 +2,7 @@ #include "dungeon.h" #include "fixed_room_data_1.h" +extern struct dungeon *DUNGEON_PTR[]; extern u16 ov29_02352B5C[2]; void ov29_02344E88(s16 *param_1); diff --git a/src/overlay_29_02338604.c b/src/overlay_29_02338604.c index 7039b96c..c411d597 100644 --- a/src/overlay_29_02338604.c +++ b/src/overlay_29_02338604.c @@ -2,6 +2,8 @@ #include "dungeon.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsSecretBazaar() { return DUNGEON_PTR[0]->gen_info.fixed_room_id==FIXED_SECRET_BAZAAR; diff --git a/src/overlay_31_02382820.c b/src/overlay_31_02382820.c index 02cb6da3..f5d84bb2 100644 --- a/src/overlay_31_02382820.c +++ b/src/overlay_31_02382820.c @@ -6,6 +6,8 @@ #include "weather.h" #include "main_02001188.h" +extern struct dungeon *DUNGEON_PTR[]; + extern const u8 DUNGEON_MENU_SWITCH_STR1[];// = "[dungeon:0]"; extern struct struct_1* OVERLAY31_UNKNOWN_POINTER__NA_238A260[2]; diff --git a/src/overlay_31_02383478.c b/src/overlay_31_02383478.c index d1b7e5c7..0e7b7616 100644 --- a/src/overlay_31_02383478.c +++ b/src/overlay_31_02383478.c @@ -3,6 +3,7 @@ #include "dungeon_map_access.h" #include "overlay_29_022E1610.h" +extern struct dungeon *DUNGEON_PTR[]; extern struct loc_struct* OVERLAY31_UNKNOWN_POINTER__NA_238A26C; extern struct bag_items* BAG_ITEMS_PTR_MIRROR; extern u32 OVERLAY31_UNKNOWN_STRUCT__NA_2389EF0; diff --git a/src/overlay_31_02383880.c b/src/overlay_31_02383880.c index caacf7a0..562e6640 100644 --- a/src/overlay_31_02383880.c +++ b/src/overlay_31_02383880.c @@ -4,6 +4,7 @@ #include "overlay_31_02383478.h" #include "main_02001188.h" +extern struct dungeon *DUNGEON_PTR[]; extern struct loc_struct* OVERLAY31_UNKNOWN_POINTER__NA_238A26C; extern u8 PositionHasItem(struct position* pos); diff --git a/src/run_dungeon.c b/src/run_dungeon.c index a794ce10..068ddbd2 100644 --- a/src/run_dungeon.c +++ b/src/run_dungeon.c @@ -2,6 +2,8 @@ #include "dungeon.h" #include "overlay_10_022C2574.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsCurrentTilesetBackground() { return IsBackgroundTileset(DUNGEON_PTR[0]->gen_info.tileset_id); diff --git a/src/run_dungeon_1.c b/src/run_dungeon_1.c index 2514eb0d..213b6d70 100644 --- a/src/run_dungeon_1.c +++ b/src/run_dungeon_1.c @@ -2,6 +2,8 @@ #include "dungeon.h" #include "enums.h" +extern struct dungeon *DUNGEON_PTR[]; + bool8 IsBossFight(enum fixed_room_id fixed_room_id) { if (fixed_room_id != FIXED_NONE && fixed_room_id < FIXED_ZERO_ISLE_NORTH) diff --git a/src/spawn_1.c b/src/spawn_1.c new file mode 100644 index 00000000..5184eb96 --- /dev/null +++ b/src/spawn_1.c @@ -0,0 +1,15 @@ +#include "dungeon.h" +#include "spawn_1.h" + +extern s32 CopySpawnEntriesMaster(struct monster_spawn_entry[], s32); +extern struct dungeon *DUNGEON_PTR; + +void CopySpawnEntriesOnce() { + if (DUNGEON_PTR->spawn_entries_copied != FALSE) { + return; + } + + DUNGEON_PTR->spawn_entries_copied = 1; + DUNGEON_PTR->monster_spawn_entries_length = + CopySpawnEntriesMaster(DUNGEON_PTR->spawn_entries, 0); +} diff --git a/src/spawn.c b/src/spawn_2.c similarity index 96% rename from src/spawn.c rename to src/spawn_2.c index fa293a17..ee31445f 100644 --- a/src/spawn.c +++ b/src/spawn_2.c @@ -1,7 +1,9 @@ #include "dg_random.h" #include "dungeon.h" #include "overlay_29_022F73B4.h" -#include "spawn.h" +#include "spawn_2.h" + +extern struct dungeon *DUNGEON_PTR[]; extern s32 GetMonsterIdFromSpawnEntry(struct monster_spawn_entry *); extern s32 GetMonsterLevelFromSpawnEntry(struct monster_spawn_entry *); diff --git a/src/weather.c b/src/weather.c index 481748ae..83de076c 100644 --- a/src/weather.c +++ b/src/weather.c @@ -3,6 +3,8 @@ #include "dungeon_items.h" #include "dungeon_pokemon_attributes.h" +extern struct dungeon *DUNGEON_PTR[]; + enum weather_id GetApparentWeather(struct entity *entity) { if (entity != NULL) From c2cf2f2e4a50c4f61a0acbf8ab9c17343f1f3d88 Mon Sep 17 00:00:00 2001 From: slaw-22 <> Date: Tue, 19 May 2026 20:23:58 +0000 Subject: [PATCH 2/4] Decomp MonsterSpawnListPartialCopy --- asm/include/overlay_29_022DEBA4.inc | 1 + asm/include/overlay_29_022E37DC.inc | 47 ++++++++++---------- asm/overlay_29_022E37DC.s | 69 ----------------------------- include/dungeon_mode.h | 2 +- include/spawn_1.h | 1 + src/spawn_1.c | 23 ++++++++++ 6 files changed, 49 insertions(+), 94 deletions(-) diff --git a/asm/include/overlay_29_022DEBA4.inc b/asm/include/overlay_29_022DEBA4.inc index 7a6940e3..d8a3fc21 100644 --- a/asm/include/overlay_29_022DEBA4.inc +++ b/asm/include/overlay_29_022DEBA4.inc @@ -3,6 +3,7 @@ .public ChangeGiratinaFormIfSkyDungeon .public ClearHiddenStairs .public CloseFixedBin +.public CopySpawnEntriesOnce .public CountItemsOnFloorForAcuteSniffer .public Debug_Print0 .public DeleteAllMonsterSpriteFiles diff --git a/asm/include/overlay_29_022E37DC.inc b/asm/include/overlay_29_022E37DC.inc index 5f04d737..0b7937c4 100644 --- a/asm/include/overlay_29_022E37DC.inc +++ b/asm/include/overlay_29_022E37DC.inc @@ -7,8 +7,8 @@ .public CheckActiveChallengeRequest .public CheckSpawnThreshold .public DIRECTIONS_XY -.public DisplayAnimatedNumbers .public DUNGEON_PTR +.public DisplayAnimatedNumbers .public DungeonFloorToGroupFloor .public DungeonGetTotalSpriteFileSize .public DungeonGoesUp @@ -29,7 +29,6 @@ .public GetNbRecruited .public GetSecondFormIfValid .public GetSpriteFileSize -.public GetSpriteSize .public HandleSir0Translation .public IsBossFight .public IsCurrentFixedRoomBossFight @@ -47,6 +46,28 @@ .public MemFree .public MonsterIsType .public NeedsItemToSpawn +.public PlayEffectAnimationEntity +.public PlaySeByIdIfNotSilence +.public RandIntSafe +.public STATUS_ICON_ARRAY_BIDE +.public STATUS_ICON_ARRAY_BLINDED +.public STATUS_ICON_ARRAY_BURN +.public STATUS_ICON_ARRAY_CRINGE +.public STATUS_ICON_ARRAY_CURSE +.public STATUS_ICON_ARRAY_FREEZE +.public STATUS_ICON_ARRAY_INVISIBLE +.public STATUS_ICON_ARRAY_LEECH_SEED +.public STATUS_ICON_ARRAY_LONG_TOSS +.public STATUS_ICON_ARRAY_MAGNET_RISE +.public STATUS_ICON_ARRAY_MIRACLE_EYE +.public STATUS_ICON_ARRAY_MUZZLED +.public STATUS_ICON_ARRAY_REFLECT +.public STATUS_ICON_ARRAY_SLEEP +.public STATUS_ICON_ARRAY_SURE_SHOT +.public SetMonsterId +.public ShouldDisplayEntityWrapper +.public SubstitutePlaceholderStringTags +.public UnloadFile .public ov10_022BDC68 .public ov10_022BDE50 .public ov10_022BEC08 @@ -81,28 +102,6 @@ .public ov29_023515B0 .public ov29_023515CC .public ov29_0235354C -.public PlayEffectAnimationEntity -.public PlaySeByIdIfNotSilence -.public RandIntSafe -.public SetMonsterId -.public ShouldDisplayEntityWrapper -.public STATUS_ICON_ARRAY_BIDE -.public STATUS_ICON_ARRAY_BLINDED -.public STATUS_ICON_ARRAY_BURN -.public STATUS_ICON_ARRAY_CRINGE -.public STATUS_ICON_ARRAY_CURSE -.public STATUS_ICON_ARRAY_FREEZE -.public STATUS_ICON_ARRAY_INVISIBLE -.public STATUS_ICON_ARRAY_LEECH_SEED -.public STATUS_ICON_ARRAY_LONG_TOSS -.public STATUS_ICON_ARRAY_MAGNET_RISE -.public STATUS_ICON_ARRAY_MIRACLE_EYE -.public STATUS_ICON_ARRAY_MUZZLED -.public STATUS_ICON_ARRAY_REFLECT -.public STATUS_ICON_ARRAY_SLEEP -.public STATUS_ICON_ARRAY_SURE_SHOT .public sub_0201C000 .public sub_0201CF90 .public sub_0201D034 -.public SubstitutePlaceholderStringTags -.public UnloadFile diff --git a/asm/overlay_29_022E37DC.s b/asm/overlay_29_022E37DC.s index bed9eaf2..2e042a94 100644 --- a/asm/overlay_29_022E37DC.s +++ b/asm/overlay_29_022E37DC.s @@ -5550,72 +5550,3 @@ _022E7C54: .align 2, 0 _022E7C5C: .word DUNGEON_PTR arm_func_end CopySpawnEntriesMaster - - arm_func_start MonsterSpawnListPartialCopy -MonsterSpawnListPartialCopy: ; 0x022E7C60 - stmdb sp!, {r4, r5, r6, lr} - mov r6, r0 - mov r5, r1 - mov r4, #0 - b _022E7CE4 -_022E7C74: - ldr r0, _022E7CF4 ; =DUNGEON_PTR - ldr r0, [r0] -#ifdef JAPAN - add r0, r0, #0x8c0 - add r0, r0, #0x2c000 -#else - add r0, r0, #0x164 - add r0, r0, #0x2c800 -#endif - add r0, r0, r4, lsl #3 - bl GetMonsterIdFromSpawnEntry - cmp r0, #0 - beq _022E7CEC - bl GetSpriteSize - cmp r0, #6 - bhi _022E7CE0 -#ifdef JAPAN - ldr r0, _022E7CF4 ; =DUNGEON_PTR - ldr r0, [r0] - add r1, r0, r4, lsl #3 - add r0, r1, #0x2c800 - ldrsh r0, [r0, #0xc2] - cmp r0, #0 - beq _022E7CE0 - add r0, r1, #0x8c0 - add r3, r0, #0x2c000 -#else - ldr r1, _022E7CF4 ; =DUNGEON_PTR - ldr r0, _022E7CF8 ; =0x0002C966 - ldr r1, [r1] - add r1, r1, r4, lsl #3 - ldrsh r0, [r1, r0] - cmp r0, #0 - beq _022E7CE0 - add r0, r1, #0x164 - add r3, r0, #0x2c800 -#endif - add r2, r6, r5, lsl #3 - mov r1, #4 -_022E7CCC: - ldrh r0, [r3], #2 - subs r1, r1, #1 - strh r0, [r2], #2 - bne _022E7CCC - add r5, r5, #1 -_022E7CE0: - add r4, r4, #1 -_022E7CE4: - cmp r4, #0x10 - blt _022E7C74 -_022E7CEC: - mov r0, r5 - ldmia sp!, {r4, r5, r6, pc} - .align 2, 0 -_022E7CF4: .word DUNGEON_PTR -#ifndef JAPAN -_022E7CF8: .word 0x0002C966 -#endif - arm_func_end MonsterSpawnListPartialCopy - diff --git a/include/dungeon_mode.h b/include/dungeon_mode.h index 2dd65c2f..4563d57e 100644 --- a/include/dungeon_mode.h +++ b/include/dungeon_mode.h @@ -837,7 +837,7 @@ struct monster_spawn_entry { u16 level_mult_512; // 0x0: Spawn level << 9 // 0x2: Incremental spawn weights for this entry. // [0] = normal spawn weight, [1] = monster house spawn weight - u16 incremental_spawn_weight[2]; + s16 incremental_spawn_weight[2]; // 0x6: Monster id. Depending on where this struct is used, it can have values above 600 // to list secondary gender entries. enum monster_id id; diff --git a/include/spawn_1.h b/include/spawn_1.h index f6b70ad7..9cb5d3b3 100644 --- a/include/spawn_1.h +++ b/include/spawn_1.h @@ -1,6 +1,7 @@ #ifndef PMDSKY_SPAWN_1_H #define PMDSKY_SPAWN_1_H +s32 MonsterSpawnListPartialCopy(struct monster_spawn_entry entry_out[], s32 idx_out); void CopySpawnEntriesOnce(); #endif //PMDSKY_SPAWN_1_H diff --git a/src/spawn_1.c b/src/spawn_1.c index 5184eb96..14eae936 100644 --- a/src/spawn_1.c +++ b/src/spawn_1.c @@ -2,8 +2,31 @@ #include "spawn_1.h" extern s32 CopySpawnEntriesMaster(struct monster_spawn_entry[], s32); +extern s32 GetMonsterIdFromSpawnEntry(struct monster_spawn_entry*); +extern u32 GetSpriteSize(s32); extern struct dungeon *DUNGEON_PTR; +s32 MonsterSpawnListPartialCopy(struct monster_spawn_entry entry_out[], s32 idx_out) { + for(s32 i = 0; i < 16; i++) { + s32 monster_id = GetMonsterIdFromSpawnEntry(&(DUNGEON_PTR->spawn_entries_master[i])); + if(monster_id == 0) { + break; + } + + if(GetSpriteSize(monster_id) > 6) { + continue; + } + + if(DUNGEON_PTR->spawn_entries_master[i].incremental_spawn_weight[0] == 0) { + continue; + } + + entry_out[idx_out] = DUNGEON_PTR->spawn_entries_master[i]; + idx_out++; + } + return idx_out; +} + void CopySpawnEntriesOnce() { if (DUNGEON_PTR->spawn_entries_copied != FALSE) { return; From fb923dae6fb9e2355a71cfd621cb68c093c4da9f Mon Sep 17 00:00:00 2001 From: slaw-22 <> Date: Tue, 19 May 2026 20:29:51 +0000 Subject: [PATCH 3/4] Decomp CopySpawnEntriesMaster --- asm/overlay_29_022E37DC.s | 49 --------------------------------------- include/spawn_1.h | 1 + src/spawn_1.c | 14 +++++++++++ 3 files changed, 15 insertions(+), 49 deletions(-) diff --git a/asm/overlay_29_022E37DC.s b/asm/overlay_29_022E37DC.s index 2e042a94..98b7d0aa 100644 --- a/asm/overlay_29_022E37DC.s +++ b/asm/overlay_29_022E37DC.s @@ -5501,52 +5501,3 @@ ov29_022E7BD0: ; 0x022E7BD0 moveq r0, #0x46 ldmia sp!, {r3, pc} arm_func_end ov29_022E7BD0 - - arm_func_start CopySpawnEntriesMaster -CopySpawnEntriesMaster: ; 0x022E7BE8 - stmdb sp!, {r3, r4, r5, r6, r7, lr} - mov r6, r0 - mov r5, r1 - mov r4, #0 - ldr r7, _022E7C5C ; =DUNGEON_PTR - b _022E7C4C -_022E7C00: - ldr r0, [r7] -#ifdef JAPAN - add r0, r0, #0x8c0 - add r0, r0, #0x2c000 -#else - add r0, r0, #0x164 - add r0, r0, #0x2c800 -#endif - add r0, r0, r4, lsl #3 - bl GetMonsterIdFromSpawnEntry - cmp r0, #0 - beq _022E7C54 - ldr r0, [r7] - add r2, r6, r5, lsl #3 - add r0, r0, r4, lsl #3 -#ifdef JAPAN - add r0, r0, #0x8c0 - add r3, r0, #0x2c000 -#else - add r0, r0, #0x164 - add r3, r0, #0x2c800 -#endif - mov r1, #4 -_022E7C34: - ldrh r0, [r3], #2 - subs r1, r1, #1 - strh r0, [r2], #2 - bne _022E7C34 - add r5, r5, #1 - add r4, r4, #1 -_022E7C4C: - cmp r4, #0x10 - blt _022E7C00 -_022E7C54: - mov r0, r5 - ldmia sp!, {r3, r4, r5, r6, r7, pc} - .align 2, 0 -_022E7C5C: .word DUNGEON_PTR - arm_func_end CopySpawnEntriesMaster diff --git a/include/spawn_1.h b/include/spawn_1.h index 9cb5d3b3..2f4a1634 100644 --- a/include/spawn_1.h +++ b/include/spawn_1.h @@ -1,6 +1,7 @@ #ifndef PMDSKY_SPAWN_1_H #define PMDSKY_SPAWN_1_H +s32 CopySpawnEntriesMaster(struct monster_spawn_entry out[], s32 idx_out); s32 MonsterSpawnListPartialCopy(struct monster_spawn_entry entry_out[], s32 idx_out); void CopySpawnEntriesOnce(); diff --git a/src/spawn_1.c b/src/spawn_1.c index 14eae936..976c3be1 100644 --- a/src/spawn_1.c +++ b/src/spawn_1.c @@ -6,6 +6,20 @@ extern s32 GetMonsterIdFromSpawnEntry(struct monster_spawn_entry*); extern u32 GetSpriteSize(s32); extern struct dungeon *DUNGEON_PTR; +s32 CopySpawnEntriesMaster(struct monster_spawn_entry out[], s32 idx_out) { + for(s32 i = 0; i < 16; i++) { + s32 monster_id = GetMonsterIdFromSpawnEntry(&(DUNGEON_PTR->spawn_entries_master[i])); + if(monster_id == 0) { + break; + } + + out[idx_out] = DUNGEON_PTR->spawn_entries_master[i]; + idx_out++; + } + + return idx_out; +} + s32 MonsterSpawnListPartialCopy(struct monster_spawn_entry entry_out[], s32 idx_out) { for(s32 i = 0; i < 16; i++) { s32 monster_id = GetMonsterIdFromSpawnEntry(&(DUNGEON_PTR->spawn_entries_master[i])); From 415b47f3090b753ac23caf3eeeae28c54ae912cc Mon Sep 17 00:00:00 2001 From: slaw-22 <> Date: Tue, 19 May 2026 20:59:36 +0000 Subject: [PATCH 4/4] Decomp GetRandomSecretRoomItem, GetRandomBazaarItem and GetItemIdToSpawn --- asm/include/overlay_29_022E37DC.inc | 1 - asm/include/overlay_29_02341E6C.inc | 1 + asm/include/overlay_29_02344178.inc | 1 + asm/overlay_29_022E37DC.s | 98 ----------------------------- asm/overlay_29_02341E6C.s | 2 +- asm/overlay_29_02344178.s | 2 +- include/dungeon.h | 47 ++++---------- include/enums.h | 9 +++ include/item.h | 1 + include/spawn_1.h | 3 + src/spawn_1.c | 60 ++++++++++++++++++ 11 files changed, 89 insertions(+), 136 deletions(-) diff --git a/asm/include/overlay_29_022E37DC.inc b/asm/include/overlay_29_022E37DC.inc index 0b7937c4..63127ed5 100644 --- a/asm/include/overlay_29_022E37DC.inc +++ b/asm/include/overlay_29_022E37DC.inc @@ -19,7 +19,6 @@ .public FloorNumberIsEven .public GetEffectAnimationField0x19 .public GetFloorType -.public GetItemCategoryVeneer .public GetLeader .public GetMonsterGenderVeneer .public GetMonsterIdFromSpawnEntry diff --git a/asm/include/overlay_29_02341E6C.inc b/asm/include/overlay_29_02341E6C.inc index 2bc3a543..f7703e1b 100644 --- a/asm/include/overlay_29_02341E6C.inc +++ b/asm/include/overlay_29_02341E6C.inc @@ -20,6 +20,7 @@ .public GetOutlawLeaderLevel .public GetOutlawLevel .public GetOutlawMinionLevel +.public GetRandomSecretRoomItem .public GetResolvedPerformanceProgressFlag .public GetSpecialTargetItem .public GetTileSafe diff --git a/asm/include/overlay_29_02344178.inc b/asm/include/overlay_29_02344178.inc index 882987a1..a3be25df 100644 --- a/asm/include/overlay_29_02344178.inc +++ b/asm/include/overlay_29_02344178.inc @@ -12,6 +12,7 @@ .public GetMissionEnemyMinionGroup .public GetMissionTargetEnemy .public GetMoneyCarried +.public GetRandomBazaarItem .public InitStandardItem .public IsBagFull .public IsItemInBag diff --git a/asm/overlay_29_022E37DC.s b/asm/overlay_29_022E37DC.s index 98b7d0aa..d3545498 100644 --- a/asm/overlay_29_022E37DC.s +++ b/asm/overlay_29_022E37DC.s @@ -5403,101 +5403,3 @@ _022E7AB8: moveq r0, #0x10 ldmia sp!, {r4, pc} arm_func_end GetRandomTrapId - - arm_func_start GetItemIdToSpawn -GetItemIdToSpawn: ; 0x022E7AC4 - stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - mov r4, r0 - ldr r0, _022E7BA8 ; =0x00002710 - bl DungeonRandInt - mov r1, #0xb10 - mul r5, r4, r1 - ldr r2, _022E7BAC ; =DUNGEON_PTR - mov r4, #0x10 - ldr r1, [r2] - mov r3, #0 - add r6, r1, r5 - ldr r1, _022E7BB0 ; =0x000286D2 - b _022E7B18 -_022E7AF8: - add r2, r6, r3, lsl #1 - ldrsh r2, [r2, r1] - cmp r2, #0 - beq _022E7B14 - cmp r2, r0 - andge r4, r3, #0xff - bge _022E7B20 -_022E7B14: - add r3, r3, #1 -_022E7B18: - cmp r3, #0x10 - blt _022E7AF8 -_022E7B20: - cmp r4, #0x10 - moveq r0, #0xb7 - ldmeqia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - ldr r0, _022E7BA8 ; =0x00002710 - bl DungeonRandInt - mov r6, r0 - mov r7, #0 - ldr sb, _022E7BAC ; =DUNGEON_PTR - ldr r8, _022E7BB4 ; =0x000286F2 - b _022E7B98 -_022E7B48: - ldr r0, [sb] - add r0, r5, r0 - add r0, r0, r7, lsl #1 - ldrsh r0, [r0, r8] - cmp r0, #0 - beq _022E7B94 - mov r0, r7, lsl #0x10 - mov r0, r0, asr #0x10 - bl GetItemCategoryVeneer - cmp r4, r0 - bne _022E7B94 - ldr r0, [sb] - add r0, r5, r0 - add r0, r0, r7, lsl #1 - ldrsh r0, [r0, r8] - cmp r0, r6 - movge r0, r7, lsl #0x10 - movge r0, r0, asr #0x10 - ldmgeia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} -_022E7B94: - add r7, r7, #1 -_022E7B98: - cmp r7, #0x16c - blt _022E7B48 - mov r0, #0xb7 - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, pc} - .align 2, 0 -_022E7BA8: .word 0x00002710 -_022E7BAC: .word DUNGEON_PTR -#ifdef JAPAN -_022E7BB0: .word 0x0002862E -_022E7BB4: .word 0x0002864E -#else -_022E7BB0: .word 0x000286D2 -_022E7BB4: .word 0x000286F2 -#endif - arm_func_end GetItemIdToSpawn - - arm_func_start ov29_022E7BB8 -ov29_022E7BB8: ; 0x022E7BB8 - stmdb sp!, {r3, lr} - mov r0, #4 - bl GetItemIdToSpawn - cmp r0, #0xb7 - moveq r0, #0x46 - ldmia sp!, {r3, pc} - arm_func_end ov29_022E7BB8 - - arm_func_start ov29_022E7BD0 -ov29_022E7BD0: ; 0x022E7BD0 - stmdb sp!, {r3, lr} - mov r0, #5 - bl GetItemIdToSpawn - cmp r0, #0xb7 - moveq r0, #0x46 - ldmia sp!, {r3, pc} - arm_func_end ov29_022E7BD0 diff --git a/asm/overlay_29_02341E6C.s b/asm/overlay_29_02341E6C.s index 82481bc5..6f808d09 100644 --- a/asm/overlay_29_02341E6C.s +++ b/asm/overlay_29_02341E6C.s @@ -1672,7 +1672,7 @@ _023434D8: bl IsSecretRoom cmp r0, #0 beq _023434F0 - bl ov29_022E7BD0 + bl GetRandomSecretRoomItem mov r3, r0 b _02343528 _023434F0: diff --git a/asm/overlay_29_02344178.s b/asm/overlay_29_02344178.s index 42aad0c4..3a8506ce 100644 --- a/asm/overlay_29_02344178.s +++ b/asm/overlay_29_02344178.s @@ -501,7 +501,7 @@ _023447C4: cmp r0, #0x32 movlt r6, #0x46 blt _023447FC - bl ov29_022E7BB8 + bl GetRandomBazaarItem mov r6, r0 _023447FC: mov r1, r5 diff --git a/include/dungeon.h b/include/dungeon.h index ca7fe221..bb2ded90 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -99,6 +99,14 @@ struct dungeon_generation_info { // There's another 6 words that look like spawn positions right after these 4 }; +// Thresholds are ascending cumulative weights (0-10000) +struct item_spawn_weights { + s16 category_threshold[0x8]; + s16 unknown_1[0x8]; + s16 item_threshold[0x16c]; + s16 unknown_2[0x40c]; +}; + // Dungeon state struct dungeon { u8 field_0x0; // 0x0: Initialized to 0x0. @@ -1640,41 +1648,10 @@ struct dungeon { // 0x286B1: Initialized to 0xFF, then set to a copy of dungeon::0x74B u8 field_0x286b1; struct floor_properties floor_properties; // 0x286B2: Properties about the current floor - // 0x286D2: Maybe a 0x10 long array? - u16 field_0x286d2; - u16 field_0x286d4; - u16 field_0x286d6; - u16 field_0x286d8; - u16 field_0x286da; - u16 field_0x286dc; - u16 field_0x286de; - u16 field_0x286e0; - u16 field_0x286e2; - u16 field_0x286e4; - u16 field_0x286e6; - u16 field_0x286e8; - u16 field_0x286ea; - u16 field_0x286ec; - u16 field_0x286ee; - u16 field_0x286f0; - // 0x286F2: Spawn weights for regular items. It's the unrolled form of this floor's regular - // item spawn list. - // It has enough space to hold 1416 entries (1400 items + 16 categories), but only the - // first 0x16C slots are used since spawn lists can't encode item IDs larger than that. - u16 regular_item_weights[1416]; - // 0x29202: Spawn weights for Kecleon shop items. Same format as regular_item_weights. - u16 kecleon_item_weights[1416]; - // 0x29D12: Spawn weights for monster house items. Same format as regular_item_weights. - u16 monster_house_item_weights[1416]; - // 0x2A822: Spawn weights for buried items. Same format as regular_item_weights. - u16 buried_item_weights[1416]; - // 0x2B332: Spawn weights for bazaar grab bag items. Same format as regular_item_weights. - u16 grab_bag_item_weights[1416]; - // 0x2BE42: Spawn weights for secret room items in treasure boxes. - // Same format as regular_item_weights? For some reason the weights for the secret rooms - // are of a different length than the other item weight lists before it. The trap weights - // appear to overlap what would be entries 1400-1415. - u16 secret_room_item_weights[1400]; + // Spawn weights for items in different contexts. + // 0 = regular, 1 = Kecleon shop, 2 = monster house, 3 buried, + // 4 = bazaar, 5 = secret room + struct item_spawn_weights item_spawn_weights[6]; // 0x2C932: Spawn weights for traps. u16 trap_weights[25]; // 0x2C964: List of spawn entries on this floor diff --git a/include/enums.h b/include/enums.h index f0c00df8..509b259b 100644 --- a/include/enums.h +++ b/include/enums.h @@ -3716,4 +3716,13 @@ enum dungeon_mode { DMODE_OPEN_AND_REQUEST = 3, // Dunegon is unlocked and cleared }; +enum spawn_weight_type { + SPAWN_REGULAR = 0, + SPAWN_KECLEON_SHOP = 1, + SPAWN_MONSTER_HOUSE = 2, + SPAWN_BURIED = 3, + SPAWN_BAZAAR = 4, + SPAWN_SECRET_ROOM = 5, +}; + #endif //PMDSKY_ENUMS_H diff --git a/include/item.h b/include/item.h index ff6d0fb5..0173693a 100644 --- a/include/item.h +++ b/include/item.h @@ -1426,6 +1426,7 @@ enum item_category { CATEGORY_TREASURE_BOXES_2 = 13, CATEGORY_TREASURE_BOXES_3 = 14, CATEGORY_EXCLUSIVE_ITEMS = 15, + CATEGORY_DUMMY = 16, }; enum item_flag { diff --git a/include/spawn_1.h b/include/spawn_1.h index 2f4a1634..0a80a606 100644 --- a/include/spawn_1.h +++ b/include/spawn_1.h @@ -1,6 +1,9 @@ #ifndef PMDSKY_SPAWN_1_H #define PMDSKY_SPAWN_1_H +s16 GetItemIdToSpawn(enum spawn_weight_type spawn_type); +s32 GetRandomBazaarItem(); +s32 GetRandomSecretRoomItem(); s32 CopySpawnEntriesMaster(struct monster_spawn_entry out[], s32 idx_out); s32 MonsterSpawnListPartialCopy(struct monster_spawn_entry entry_out[], s32 idx_out); void CopySpawnEntriesOnce(); diff --git a/src/spawn_1.c b/src/spawn_1.c index 976c3be1..5c4928c9 100644 --- a/src/spawn_1.c +++ b/src/spawn_1.c @@ -1,4 +1,8 @@ +#include "dg_random.h" #include "dungeon.h" +#include "enums.h" +#include "item.h" +#include "item_util.h" #include "spawn_1.h" extern s32 CopySpawnEntriesMaster(struct monster_spawn_entry[], s32); @@ -6,6 +10,62 @@ extern s32 GetMonsterIdFromSpawnEntry(struct monster_spawn_entry*); extern u32 GetSpriteSize(s32); extern struct dungeon *DUNGEON_PTR; +s16 GetItemIdToSpawn(enum spawn_weight_type spawn_type) { + s32 idx; + s32 rnd = DungeonRandInt(10000); + enum item_category category = CATEGORY_DUMMY; + for(idx = 0; idx < 16; idx++) { + s16 threshold = DUNGEON_PTR->item_spawn_weights[spawn_type].category_threshold[idx]; + if(threshold == 0) { + continue; + } + + if(threshold >= rnd) { + category = (enum item_category)idx; + break; + } + } + + if(category == CATEGORY_DUMMY) { + return ITEM_POKE; + } + + rnd = DungeonRandInt(10000); + for(idx = 0; idx < 0x16c; idx++) { + s16 threshold = DUNGEON_PTR->item_spawn_weights[spawn_type].item_threshold[idx]; + if(threshold == 0) { + continue; + } + + if(category != GetItemCategoryVeneer(idx)) { + continue; + } + + threshold = DUNGEON_PTR->item_spawn_weights[spawn_type].item_threshold[idx]; + if(threshold >= rnd) { + return idx; + } + } + + return ITEM_POKE; +} + +s32 GetRandomBazaarItem() { + s32 item_id = GetItemIdToSpawn(SPAWN_BAZAAR); + if(item_id == ITEM_POKE) { + return ITEM_ORAN_BERRY; + } + return item_id; +} + +s32 GetRandomSecretRoomItem() { + s32 item_id = GetItemIdToSpawn(SPAWN_SECRET_ROOM); + if(item_id == ITEM_POKE) { + return ITEM_ORAN_BERRY; + } + return item_id; +} + s32 CopySpawnEntriesMaster(struct monster_spawn_entry out[], s32 idx_out) { for(s32 i = 0; i < 16; i++) { s32 monster_id = GetMonsterIdFromSpawnEntry(&(DUNGEON_PTR->spawn_entries_master[i]));