summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremilybrooks <emilybrooksemilybrooks@gmail.com>2023-09-11 10:27:49 -0700
committerGitHub <noreply@github.com>2023-09-11 10:27:49 -0700
commit1b465cfe8b3f228faa08fba8d58a8d3be6e82d06 (patch)
tree52f985360d8ea448dc71ade81773f3db66c4825f
parent67934dfa87091278cad91df45e9b9577236e5742 (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.h1
-rw-r--r--include/m_common_data.h23
-rw-r--r--include/m_field_info.h4
-rw-r--r--include/m_name_table.h10
-rw-r--r--include/m_police_box.h8
-rw-r--r--include/m_snowman.h27
-rw-r--r--linker_scripts/jp/symbol_addrs_code.txt2
-rw-r--r--src/code/m_snowman.c143
-rw-r--r--yamls/jp/code.yaml4
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]