diff --git a/asm/include/overlay_29_02300108.inc b/asm/include/overlay_29_0230027C.inc similarity index 87% rename from asm/include/overlay_29_02300108.inc rename to asm/include/overlay_29_0230027C.inc index 7cbd4f92..08e85c62 100644 --- a/asm/include/overlay_29_02300108.inc +++ b/asm/include/overlay_29_0230027C.inc @@ -3,6 +3,8 @@ .public DUNGEON_PTR .public GetActiveTeamMember .public GetExplorerMazeMonster +.public GetMonsterDisplayNameType +.public GetMonsterName .public GetName .public GetNameRaw .public GetNameWithGender diff --git a/asm/overlay_29_02300108.s b/asm/overlay_29_0230027C.s similarity index 51% rename from asm/overlay_29_02300108.s rename to asm/overlay_29_0230027C.s index f7e70270..506bfe09 100644 --- a/asm/overlay_29_02300108.s +++ b/asm/overlay_29_0230027C.s @@ -1,206 +1,8 @@ .include "asm/macros.inc" - .include "overlay_29_02300108.inc" + .include "overlay_29_0230027C.inc" .text -#ifndef JAPAN - arm_func_start GetMonsterDisplayNameType -GetMonsterDisplayNameType: ; 0x02300108 - ldr r1, _02300160 ; =DUNGEON_PTR - ldr r1, [r1] - add r1, r1, #0x1a000 - ldrb r2, [r1, #0x23e] - cmp r2, #0 - ldreqb r2, [r1, #0x245] - cmpeq r2, #0 - bne _0230013C - ldrb r1, [r1, #0x244] - cmp r1, #0 - ldreqb r1, [r0, #0xef] - cmpeq r1, #1 - bne _0230014C -_0230013C: - ldrb r1, [r0, #6] - cmp r1, #0 - movne r0, #1 - bxne lr -_0230014C: - ldrb r0, [r0, #0xd8] - cmp r0, #2 - moveq r0, #2 - movne r0, #0 - bx lr - .align 2, 0 -_02300160: .word DUNGEON_PTR - arm_func_end GetMonsterDisplayNameType -#endif - - arm_func_start GetMonsterName -GetMonsterName: ; 0x02300164 -#ifdef JAPAN - stmdb sp!, {r4, lr} - ldr r2, _02301678 ; =DUNGEON_PTR - mov r4, r0 - ldr r0, [r2] - add r0, r0, #0x1a000 - ldrb r2, [r0, #0x19a] - cmp r2, #0 - ldreqb r2, [r0, #0x1a1] - cmpeq r2, #0 - bne _02301574 - ldrb r0, [r0, #0x1a0] - cmp r0, #0 - ldreqb r0, [r1, #0xef] - cmpeq r0, #1 - bne _02300190 -_02301574: - ldrb r0, [r1, #6] - cmp r0, #0 - beq _02300190 - ldr r1, _02300274 ; =0x00000C34 - mov r0, r4 - bl CopyStringFromId - ldmia sp!, {r4, pc} -_02300190: - ldrb r0, [r1, #0xd8] -#else - stmdb sp!, {r3, r4, r5, lr} - mov r4, r1 - mov r5, r0 - mov r0, r4 - bl GetMonsterDisplayNameType - cmp r0, #1 - bne _02300190 - ldr r1, _02300274 ; =0x00000C34 - mov r0, r5 - bl CopyStringFromId - ldmia sp!, {r3, r4, r5, pc} -_02300190: -#endif - cmp r0, #2 - bne _023001A8 - ldr r1, _02300278 ; =0x00000C32 -#ifdef JAPAN - mov r0, r4 - bl CopyStringFromId - ldmia sp!, {r4, pc} -_023001A8: - ldrb r0, [r1, #6] - cmp r0, #0 - beq _0230025C - ldrb r0, [r1, #0xbc] -#else - mov r0, r5 - bl CopyStringFromId - ldmia sp!, {r3, r4, r5, pc} -_023001A8: - ldrb r0, [r4, #6] - cmp r0, #0 - beq _0230025C - ldrb r0, [r4, #0xbc] -#endif - cmp r0, #0xb - bne _023001DC - mov r0, #0 - bl GetExplorerMazeMonster - mov r1, r0 -#ifdef JAPAN - mov r0, r4 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r4, pc} -#else - mov r0, r5 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r3, r4, r5, pc} -#endif -_023001DC: - cmp r0, #0xc - bne _02300200 - mov r0, #1 - bl GetExplorerMazeMonster - mov r1, r0 -#ifdef JAPAN - mov r0, r4 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r4, pc} -#else - mov r0, r5 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r3, r4, r5, pc} -#endif -_02300200: - cmp r0, #0xd - bne _02300224 - mov r0, #2 - bl GetExplorerMazeMonster - mov r1, r0 -#ifdef JAPAN - mov r0, r4 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r4, pc} -#else - mov r0, r5 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r3, r4, r5, pc} -#endif -_02300224: - cmp r0, #0xe - bne _02300248 - mov r0, #3 - bl GetExplorerMazeMonster - mov r1, r0 -#ifdef JAPAN - mov r0, r4 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r4, pc} -_02300248: - ldrsh r1, [r1, #4] - mov r0, r4 - mov r2, #0x4e - bl GetNameWithGender - ldmia sp!, {r4, pc} -_0230025C: - ldrsh r0, [r1, #0xc] - bl GetActiveTeamMember - mov r1, r0 - mov r0, r4 - bl sub_020585B4 - ldmia sp!, {r4, pc} - .align 2, 0 -_02301678: .word DUNGEON_PTR -_02300274: .word 0x00000973 -_02300278: .word 0x00000971 -#else - mov r0, r5 - mov r2, #0x4e - bl sub_02056084 - ldmia sp!, {r3, r4, r5, pc} -_02300248: - ldrsh r1, [r4, #4] - mov r0, r5 - mov r2, #0x4e - bl GetNameWithGender - ldmia sp!, {r3, r4, r5, pc} -_0230025C: - ldrsh r0, [r4, #0xc] - bl GetActiveTeamMember - mov r1, r0 - mov r0, r5 - bl sub_020585B4 - ldmia sp!, {r3, r4, r5, pc} - .align 2, 0 -_02300274: .word 0x00000C34 -_02300278: .word 0x00000C32 -#endif - arm_func_end GetMonsterName - arm_func_start ov29_0230027C ov29_0230027C: ; 0x0230027C stmdb sp!, {r4, lr} diff --git a/include/common.h b/include/common.h new file mode 100644 index 00000000..9b1fb887 --- /dev/null +++ b/include/common.h @@ -0,0 +1,88 @@ +#ifndef PMDSKY_COMMON_H +#define PMDSKY_COMMON_H + +#include "item.h" +#include "move.h" + +struct ground_move { + // 0x0: flags: 1-byte bitfield + // See move::flags0 for details + u8 f_exists : 1; + u8 f_subsequent_in_link_chain : 1; + u8 f_enabled_for_ai : 1; + u8 f_set : 1; + u8 f_last_used : 1; // unconfirmed, but probably the same as struct move + u8 f_disabled : 1; + u8 flags_unk6 : 2; + + u8 field_0x1; // Probably padding since it doesn't get initialized + u16 id; // 0x2 + u8 ginseng; // 0x4: Ginseng boost + u16 field_0x5; // Probably padding since it doesn't get initialized +}; + +struct ground_monster { + u8 is_valid; // 0x0: True if the entry is valid + s8 level; // 0x1: Monster level + u8 joined_at; // 0x2 + u8 joined_at_floor; // 0x3: See struct monster::joined_at_floor + u16 id; // 0x4: Monster ID + s8 level_at_first_evo; // 0x6: Level upon first evolution, or 0 if not applicable + s8 level_at_second_evo; // 0x7: Level upon second evolution, or 0 if not applicable + u16 iq; // 0x8 + u16 max_hp; // 0xA + u8 offensive_stats[2]; // 0xC: {atk, sp_atk} + u8 defensive_stats[2]; // 0xE: {def, sp_def} + s32 exp; // 0x10 + // 0x14: Bitvector that keeps track of which IQ skills the monster has enabled. + // See enum iq_skill_id for the meaning of each bit. + u32 iq_skill_flags[3]; + u8 tactic; // 0x20 + u8 field_0x21; + struct ground_move moves[4]; // 0x22 + char name[10]; // 0x3A: Display name of the monster +}; + +// Stores information about active team members, including those from special episodes. +// A lot of the fields seem to be analogous to fields on struct monster. +struct team_member { + // 0x0: flags: 1-byte bitfield + u8 f_is_valid : 1; + u8 flags_unk1 : 7; + + u8 is_leader; // 0x1 + u8 level; // 0x2 + u8 joined_at; // 0x3 + u8 joined_at_floor; // 0x4 + u8 field_0x5; + u16 iq; // 0x6 + s16 member_index; // 0x8: Index in the list of all team members (not just the active ones) + s16 team_index; // 0xA: In order by team lineup + u16 id; // 0xC + u16 current_hp; // 0xE + u16 max_hp; // 0x10 + u8 offensive_stats[2]; // 0x12: {atk, sp_atk} + u8 defensive_stats[2]; // 0x14: {def, sp_def} + u8 field_0x16; + u8 field_0x17; + s32 exp; // 0x18 + struct move moves[4]; // 0x1C + u8 field_0x3C; + u8 field_0x3D; + struct item held_item; // 0x3E + s16 belly; // 0x44: Integer part + s16 belly_thousandths; // 0x46 + s16 max_belly; // 0x48: Integer part + s16 max_belly_thousandths; // 0x4A + // 0x4C: Bitvector that keeps track of which IQ skills the monster has enabled. + // See enum iq_skill_id for the meaning of each bit. + u32 iq_skill_flags[3]; + u8 tactic; // 0x58 + u8 field_0x59; + s16 hidden_power_base_power; // 0x5A + u8 hidden_power_type; // 0x5C + u8 field_0x5D; // Gets copied to monster->field_0x47. + char name[10]; // 0x5E: Display name of the monster +}; + +#endif diff --git a/include/overlay_29_023000E4.h b/include/overlay_29_023000E4.h index 75e3e38c..af9b55b2 100644 --- a/include/overlay_29_023000E4.h +++ b/include/overlay_29_023000E4.h @@ -2,8 +2,21 @@ #define PMDSKY_OVERLAY_29_023000E4_H #include "dungeon_mode.h" +#include "dungeon.h" +#include "common.h" +#include "main_0202593C.h" // Checks if an entity pointer points to a valid entity (not entity type 0, which represents no entity). bool8 EntityIsValid__023000E4(struct entity *entity); +#ifndef JAPAN +// Used when determining how a monster's name should be displayed. +enum display_name_type { + DISPLAY_NAME_NORMAL = 0, // Display the name as usual + DISPLAY_NAME_UNKNOWN = 1, // Display "(?)" + DISPLAY_NAME_DECOY = 2, // Display "Decoy" +}; +enum display_name_type GetMonsterDisplayNameType(struct monster *monster); +#endif +void GetMonsterName(char *buffer, struct monster *target_info); #endif //PMDSKY_OVERLAY_29_023000E4_H diff --git a/main.lsf b/main.lsf index 80f8ab6f..b372da7a 100644 --- a/main.lsf +++ b/main.lsf @@ -352,7 +352,7 @@ Overlay OVY_29 Object src/overlay_29_022FFF28.o Object asm/overlay_29_022FFF4C.o Object src/overlay_29_023000E4.o - Object asm/overlay_29_02300108.o + Object asm/overlay_29_0230027C.o Object src/dungeon_logic.o Object src/dungeon_logic_1.o Object asm/overlay_29_023007A8.o diff --git a/src/overlay_29_023000E4.c b/src/overlay_29_023000E4.c index 4eda217d..b68b36c1 100644 --- a/src/overlay_29_023000E4.c +++ b/src/overlay_29_023000E4.c @@ -7,3 +7,47 @@ bool8 EntityIsValid__023000E4(struct entity *entity) return entity->type != ENTITY_NOTHING; } + +extern struct dungeon *DUNGEON_PTR[]; +#ifndef JAPAN +enum display_name_type GetMonsterDisplayNameType(struct monster *monster) { + struct dungeon *dungeon = DUNGEON_PTR[0]; + if ( dungeon->display_data.blinded || dungeon->display_data.hallucinating || (!dungeon->display_data.can_see_traps && (monster->invisible_class_status.status == 1))) { + if (monster->is_not_team_member) return DISPLAY_NAME_UNKNOWN; + } + if (monster->curse_class_status.curse == STATUS_CURSE_DECOY) return DISPLAY_NAME_DECOY; + return DISPLAY_NAME_NORMAL; +} +#endif + +extern void GetNameWithGender(char *dst, s16 monster_id, char color_id); +extern struct ground_monster *GetExplorerMazeMonster(u8 entry_number); +extern void sub_02056084(char *dst, struct ground_monster *ground_monster, u8 unk); +extern void sub_020585B4(char *dst, struct team_member *team_member); +extern struct team_member *GetActiveTeamMember(int roster_idx); + +void GetMonsterName(char *buffer, struct monster *target_info) { +#ifndef JAPAN + int display_name_type = GetMonsterDisplayNameType(target_info); + if (display_name_type == DISPLAY_NAME_UNKNOWN) CopyStringFromId(buffer, 3124); + else if (display_name_type == DISPLAY_NAME_DECOY) CopyStringFromId(buffer, 3122); +#else + struct dungeon *dungeon = DUNGEON_PTR[0]; + if ( dungeon->display_data.blinded || dungeon->display_data.hallucinating || (!dungeon->display_data.can_see_traps && (target_info->invisible_class_status.status == 1))) { + if (target_info->is_not_team_member) { + CopyStringFromId(buffer, 2419); + return; + } + } + if (target_info->curse_class_status.curse == STATUS_CURSE_DECOY) CopyStringFromId(buffer, 2417); +#endif + else if (target_info->is_not_team_member) { + enum monster_behavior behavior = target_info->monster_behavior; + if (behavior == BEHAVIOR_EXPLORER_MAZE_1) sub_02056084(buffer, GetExplorerMazeMonster(0), 0x4e); + else if (behavior == BEHAVIOR_EXPLORER_MAZE_2) sub_02056084(buffer, GetExplorerMazeMonster(1), 0x4e); + else if (behavior == BEHAVIOR_EXPLORER_MAZE_3) sub_02056084(buffer, GetExplorerMazeMonster(2), 0x4e); + else if (behavior == BEHAVIOR_EXPLORER_MAZE_4) sub_02056084(buffer, GetExplorerMazeMonster(3), 0x4e); + else GetNameWithGender(buffer, target_info->apparent_id, 'N'); + } + else sub_020585B4(buffer, GetActiveTeamMember(target_info->team_index)); +}