diff options
| author | emilybrooks <emilybrooksemilybrooks@gmail.com> | 2023-09-11 10:27:49 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-11 10:27:49 -0700 |
| commit | 1b465cfe8b3f228faa08fba8d58a8d3be6e82d06 (patch) | |
| tree | 52f985360d8ea448dc71ade81773f3db66c4825f | |
| parent | 67934dfa87091278cad91df45e9b9577236e5742 (diff) | |
m_snowman OK (#94)
* moved everything from private fork
* trying to figure out name stuff
* matched mSN_check_life
* fully matching
* add season enum
* forgot
* fixed structs
| -rw-r--r-- | include/libc64/qrand.h | 1 | ||||
| -rw-r--r-- | include/m_common_data.h | 23 | ||||
| -rw-r--r-- | include/m_field_info.h | 4 | ||||
| -rw-r--r-- | include/m_name_table.h | 10 | ||||
| -rw-r--r-- | include/m_police_box.h | 8 | ||||
| -rw-r--r-- | include/m_snowman.h | 27 | ||||
| -rw-r--r-- | linker_scripts/jp/symbol_addrs_code.txt | 2 | ||||
| -rw-r--r-- | src/code/m_snowman.c | 143 | ||||
| -rw-r--r-- | yamls/jp/code.yaml | 4 |
9 files changed, 207 insertions, 15 deletions
diff --git a/include/libc64/qrand.h b/include/libc64/qrand.h index b50dbdb..b22bf17 100644 --- a/include/libc64/qrand.h +++ b/include/libc64/qrand.h @@ -3,7 +3,6 @@ #include "ultra64.h" - u32 qrand(void); void sqrand(u32 seed); f32 fqrand(void); diff --git a/include/m_common_data.h b/include/m_common_data.h index bd3d432..c3ef8d1 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -13,6 +13,7 @@ #include "m_private.h" #include "m_quest.h" #include "unk.h" +#include "m_snowman.h" struct Actor; struct ActorOverlay; @@ -101,6 +102,13 @@ typedef struct mPr_mother_mail_info_c { /* 0x00 */ UNK_TYPE1 unk_00[0xE]; } mPr_mother_mail_info_c; // size = 0xE +typedef enum Season { + /* 0 */ SPRING, + /* 1 */ SUMMER, + /* 2 */ FALL, + /* 3 */ WINTER, +} Season; + typedef struct Time_c { /* 0x00 */ u32 season; /* 0x04 */ u32 term_idx; @@ -160,7 +168,9 @@ typedef struct CommonData { /* 0x0EF58 */ u16 fruit; /* 0x0EF5A */ UNK_TYPE1 unk_0EF5A[0x12]; /* 0x0EF6C */ Mail unk_0EF6C[5]; - /* 0x0F2A0 */ UNK_TYPE1 unk_0F2A0[0x198]; + /* 0x0F2A0 */ UNK_TYPE1 unk_0F2A0[0x17C]; + /* 0x0F41C */ SnowmanData snowmanData[SNOWMAN_SAVE_COUNT]; + /* 0x0F428 */ UNK_TYPE1 unk_F428[0x10]; /* 0x0F438 */ u8 station_type; /* train station type */ /* 0x0F439 */ u8 unk0F439[0x3]; /* 0x0F43C */ u16 deposit[FG_BLOCK_X_NUM * FG_BLOCK_Z_NUM][UT_Z_NUM]; /* flags for which items are buried around town */ @@ -171,7 +181,12 @@ typedef struct CommonData { /* 0x0F86A */ u8 unk0F86A[0x32]; /* 0x0F89C */ lbRTC_time_c unk_0F89C; /* 0x0F8A4 */ lbRTC_time_c unk_0F8A4; - /* 0x0F8AC */ u8 unk0F8AC[0x754]; + /* 0x0F8AC */ UNK_TYPE1 unk0F8AC; + /* 0x0F8AD */ u8 snowmanYear; // Year last snowman was built. + /* 0x0F8AE */ u8 snowmanMonth; // Month last snowman was built. + /* 0x0F8AF */ u8 snowmanDay; // Day last snowman was built. + /* 0x0F8B0 */ u8 snowmanHour; // Hour last snowman was built. + /* 0x0F8B1 */ UNK_TYPE1 unk0F8B1[0x74F]; /* 0x10000 */ u8 unk_10000; // named "game_started" in AC GCN decomp /* 0x10001 */ u8 unk_10001; /* 0x10002 */ u8 unk10002[0x1]; @@ -209,7 +224,9 @@ typedef struct CommonData { /* 0x105A0 */ u32 scene_from_title_demo; /* 0x105A4 */ UNK_TYPE1 unk_105A4[0xF0]; /* 0x10694 */ mNpc_walk_c npc_walk; - /* 0x10710 */ UNK_TYPE1 unk_10710[0xA6]; + /* 0x10710 */ UNK_TYPE1 unk_10710[0x3C]; + /* 0x1074C */ UNK_TYPE unk_1074C; + /* 0x10750 */ UNK_TYPE1 unk_10750[0x66]; /* 0x107B6 */ s16 unk_107B6; // named "demo_profile" in AC GCN decomp (though it's an array of two s16s in that game) /* 0x107B8 */ u8 unk107B8[0x28]; /* 0x107E0 */ s8 player_decoy_flag; diff --git a/include/m_field_info.h b/include/m_field_info.h index 7451f66..913190e 100644 --- a/include/m_field_info.h +++ b/include/m_field_info.h @@ -88,7 +88,7 @@ struct Game_Play; // void func_8008A3BC_jp(); // void func_8008A410_jp(); // void func_8008A4F8_jp(); -// void mFI_GetUnitFG(); +u16* mFI_GetUnitFG(Vec3f); // void func_8008A608_jp(); // void func_8008A670_jp(); // void func_8008A74C_jp(); @@ -154,7 +154,7 @@ void func_8008C478_jp(u16* deposit, int ut_x, int ut_z); // void func_8008C610_jp(); // void func_8008C630_jp(); // void func_8008C650_jp(); -// void mFI_Wpos2DepositOFF(); +void mFI_Wpos2DepositOFF(Vec3f); // void func_8008C708_jp(); // void func_8008C764_jp(); // void func_8008C798_jp(); diff --git a/include/m_name_table.h b/include/m_name_table.h index 795c642..f0656d2 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -149,4 +149,14 @@ #define DEAD_GOLD_SAPLING (GOLD_TREE + 1) /* end of environmental objects */ +#define SNOWMAN0 0xA008 +#define SNOWMAN1 (SNOWMAN0 + 1) +#define SNOWMAN2 (SNOWMAN1 + 1) +#define SNOWMAN3 (SNOWMAN2 + 1) +#define SNOWMAN4 (SNOWMAN3 + 1) +#define SNOWMAN5 (SNOWMAN4 + 1) +#define SNOWMAN6 (SNOWMAN5 + 1) +#define SNOWMAN7 (SNOWMAN6 + 1) +#define SNOWMAN8 (SNOWMAN7 + 1) + #endif diff --git a/include/m_police_box.h b/include/m_police_box.h new file mode 100644 index 0000000..639815d --- /dev/null +++ b/include/m_police_box.h @@ -0,0 +1,8 @@ +#ifndef M_POLICE_BOX_H +#define M_POLICE_BOX_H + +#include "ultra64.h" + +void mPB_keep_item(u16); + +#endif diff --git a/include/m_snowman.h b/include/m_snowman.h index caca944..b2c9a15 100644 --- a/include/m_snowman.h +++ b/include/m_snowman.h @@ -2,13 +2,28 @@ #define M_SNOWMAN_H #include "ultra64.h" +#include "z64math.h" -// void mSN_check_life(); -// void mSN_ClearSnowmanData(); -// void mSN_ClearSnowman(); -// void mSN_MeltSnowman(); -// void mSN_get_free_space(); -// void func_800C8BC4_jp(); +#define SNOWMAN_SAVE_COUNT 3 + +typedef struct SnowmanData { + /* 0x00 */ u8 exists; + /* 0x01 */ u8 headSize; + /* 0x02 */ u8 bodySize; + /* 0x03 */ u8 unk3; //score +} SnowmanData; // size = 0x4 + +typedef struct SnowmanInfo { + /* 0x00 */ s32 unk0; //scale + /* 0x04 */ Vec3f position; +} SnowmanInfo; // size = 0x10 + +s32 mSN_check_life(u16* name, s32 daysElapsed); +void mSN_ClearSnowmanData(u16* name, s32 snowmanIndex); +s32 mSN_ClearSnowman(u16* name); +s32 mSN_MeltSnowman(u16* name, s32 daysElapsed); +s32 mSN_get_free_space(void); +void mSN_regist_snowman_society(SnowmanInfo* snowmanInfo); void mSN_decide_msg(void); void mSN_snowman_init(void); diff --git a/linker_scripts/jp/symbol_addrs_code.txt b/linker_scripts/jp/symbol_addrs_code.txt index 869759a..749f301 100644 --- a/linker_scripts/jp/symbol_addrs_code.txt +++ b/linker_scripts/jp/symbol_addrs_code.txt @@ -3144,7 +3144,7 @@ mSN_ClearSnowmanData = 0x800C87E4; // type:func mSN_ClearSnowman = 0x800C8828; // type:func mSN_MeltSnowman = 0x800C8888; // type:func mSN_get_free_space = 0x800C8B88; // type:func -func_800C8BC4_jp = 0x800C8BC4; // type:func +mSN_regist_snowman_society = 0x800C8BC4; // type:func mSN_decide_msg = 0x800C8CC8; // type:func mSN_snowman_init = 0x800C8D04; // type:func func_800C8D40_jp = 0x800C8D40; // type:func diff --git a/src/code/m_snowman.c b/src/code/m_snowman.c new file mode 100644 index 0000000..a60ac1f --- /dev/null +++ b/src/code/m_snowman.c @@ -0,0 +1,143 @@ +/** + * @file m_snowman.c + * + * Manages data associated with snowmen. + * + * This data is stored in the SnowmanData struct in the save file. + * There can be three snowmen built at a single time. Each snowman has 3 variations depending on how melted they are. + * The first snowman uses the names SNOWMAN0, SNOWMAN1, and SNOWMAN2, the second snowman uses SNOWMAN3, SNOWMAN4, and + * SNOWMAN5, etc. + * + */ + +#include "global.h" +#include "m_snowman.h" +#include "m_common_data.h" +#include "m_field_info.h" +#include "m_police_box.h" +#include "m_lib.h" +#include "libc64/qrand.h" +#include "m_name_table.h" + +/** + * After advancing daysElapsed days, is the snowman completely melted? + * + * @return True if the snowman is alive, False if the snowman is dead. + */ +s32 mSN_check_life(u16* name, s32 daysElapsed) { + s32 ret = false; + + // Snowmen outside of winter die regardless of daysElapsed. + if (common_data.time.season == WINTER) { + s32 snowmanAge = ((*name - SNOWMAN0) % SNOWMAN_SAVE_COUNT); + + if (snowmanAge + daysElapsed < 3) { + ret = true; + } + } + + return ret; +} + +void mSN_ClearSnowmanData(u16* name, s32 snowmanIndex) { + bzero(&common_data.snowmanData[snowmanIndex], sizeof(SnowmanData)); + *name = 0; +} + +s32 mSN_ClearSnowman(u16* name) { + s32 ret = 0; + + if ((*name >= SNOWMAN0) && (*name <= SNOWMAN8)) { + s32 snowmanIndex = (*name - SNOWMAN0) / SNOWMAN_SAVE_COUNT; + + mSN_ClearSnowmanData(name, snowmanIndex); + ret = 1; + } + + return ret; +} + +/** + * Modify a snowman according to how many days have passed. + * + * @return 0 if the actor isn't a snowman. 1 if the actor is a snowman. + */ +s32 mSN_MeltSnowman(u16* name, s32 daysElapsed) { + s32 ret = 0; + + if ((*name >= SNOWMAN0) && (*name <= SNOWMAN8)) { + s32 snowmanIndex = (*name - SNOWMAN0) / SNOWMAN_SAVE_COUNT; + + if (daysElapsed < 0) { + daysElapsed = 1; + common_data.snowmanYear = 0; + common_data.snowmanMonth = 0; + common_data.snowmanDay = 0; + common_data.snowmanHour = 0; + } + + if (!mSN_check_life(name, daysElapsed)) { + mSN_ClearSnowmanData(name, snowmanIndex); + + } else { + SnowmanData* snowmanData = &common_data.snowmanData[snowmanIndex]; + + *name += daysElapsed; + + while (daysElapsed) { + snowmanData->headSize = (u8)(s32)(snowmanData->headSize * 0.8f); + snowmanData->bodySize = (u8)(s32)(snowmanData->bodySize * 0.8f); + daysElapsed--; + } + } + + ret = 1; + } + + return ret; +} + +/** + * Find a slot in SnowmanData that isn't occupied by a snowman. + * + * @return the index of the first empty slot. If there are no empty slots, return -1. + */ +s32 mSN_get_free_space(void) { + SnowmanData* snowmanData = common_data.snowmanData; + s32 snowmanIndex; + + for (snowmanIndex = 0; snowmanIndex < SNOWMAN_SAVE_COUNT; snowmanIndex++) { + if (!snowmanData[snowmanIndex].exists) { + return snowmanIndex; + } + } + + return -1; +} + +void mSN_regist_snowman_society(SnowmanInfo* snowmanInfo) { + u16 sp2E = *mFI_GetUnitFG(snowmanInfo->position); + s32 snowmanIndex = mSN_get_free_space(); + u16 name; + + if (snowmanIndex != -1) { + mem_copy(&common_data.snowmanData[snowmanIndex], snowmanInfo, sizeof(SnowmanData)); + + if (sp2E) { + mPB_keep_item(sp2E); + mFI_Wpos2DepositOFF(snowmanInfo->position); + } + + name = snowmanIndex * SNOWMAN_SAVE_COUNT + SNOWMAN0; + mFI_SetFG_common(name, snowmanInfo->position, 1); + } +} + +void mSN_decide_msg(void) { + common_data.unk_1074C = fqrand() * 3.0f; +} + +void mSN_snowman_init(void) { + bzero(common_data.snowmanData, sizeof(SnowmanData[SNOWMAN_SAVE_COUNT])); + mSN_decide_msg(); +} diff --git a/yamls/jp/code.yaml b/yamls/jp/code.yaml index 0eeecea..e62b31d 100644 --- a/yamls/jp/code.yaml +++ b/yamls/jp/code.yaml @@ -73,7 +73,7 @@ - [0x6E80C0, c, code/m_submenu] - [0x6E9650, asm, code/6E9650] - [0x6EAB20, asm, code/m_skin_matrix] - - [0x6EC430, asm, code/m_snowman] + - [0x6EC430, c, code/m_snowman] - [0x6EC9E0, asm, code/6EC9E0] - [0x6ECD90, asm, code/6ECD90] - [0x6EDD10, asm, code/m_time] @@ -212,7 +212,7 @@ - [0x73B5C0, .rodata, code/m_submenu] - [0x73B6D0, rodata, code/m_scene] - [0x73B700, rodata, code/73B700] - - [0x73B710, rodata, code/73B710] + - [0x73B710, .rodata, code/m_snowman] - [0x73B720, rodata, code/m_titledemo] - [0x73B740, rodata, code/73B740] - [0x73B780, rodata, code/m_time] |
