From e8bb03784dd1907fb10c3d284bcb401ef4777a0a Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Tue, 9 May 2023 20:28:40 -0400 Subject: [PATCH] m_notice work --- include/dolphin/os/OSThread.h | 3 - include/irqmgr.h | 13 +- include/m_common_data.h | 62 ++- include/m_event.h | 14 + include/m_field_info.h | 9 +- include/m_fishrecord.h | 20 + include/m_flashrom.h | 15 + include/m_handbill.h | 23 ++ include/m_item_name.h | 20 + include/m_land.h | 17 + include/m_museum_display.h | 38 ++ include/m_name_table.h | 2 + include/m_needlework.h | 3 +- include/m_npc.h | 4 + include/m_private.h | 1 - include/m_shop.h | 1 + include/m_string.h | 3 + include/m_time.h | 6 + include/padmgr.h | 2 +- rel/m_font.c | 2 +- rel/m_land.c | 4 +- rel/m_notice.c | 731 ++++++++++++++++++++++++++++++++++ 22 files changed, 963 insertions(+), 30 deletions(-) create mode 100644 include/m_fishrecord.h create mode 100644 include/m_handbill.h create mode 100644 include/m_item_name.h create mode 100644 include/m_museum_display.h create mode 100644 rel/m_notice.c diff --git a/include/dolphin/os/OSThread.h b/include/dolphin/os/OSThread.h index 0d0e6dde..6a5a7869 100644 --- a/include/dolphin/os/OSThread.h +++ b/include/dolphin/os/OSThread.h @@ -67,9 +67,6 @@ struct OSThread u8 *stackBase; // the thread's designated stack (high address) u32 *stackEnd; // last word of stack (low address) - - s32 error; // error state of thread - void* specific[2]; // data specific to this thread (set by programmer) }; // Thread states diff --git a/include/irqmgr.h b/include/irqmgr.h index d4ca499e..245fee1c 100644 --- a/include/irqmgr.h +++ b/include/irqmgr.h @@ -32,16 +32,9 @@ typedef struct { irqmgr_mesg_t msgDelayPreNMI; OSMessageQueue _msgQueue; OSMessage _msgBuf[IRQMGR_MESSAGES_MAX]; - - union { - OSThread thread; - struct { - u8 unused[sizeof(OSThread) - 2 * sizeof(void*)]; - irqmgr_client_t* clients; - u8 prenmi; - }; - }; - + OSThread thread; + irqmgr_client_t* clients; + u8 prenmi; OSTime prenmi_time; OSTimer timer; OSTime retraceTime; diff --git a/include/m_common_data.h b/include/m_common_data.h index 537efb3e..9898dc44 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -19,6 +19,8 @@ #include "m_config.h" #include "m_island.h" #include "m_needlework.h" +#include "m_museum_display.h" +#include "m_lib.h" #ifdef __cplusplus extern "C" { @@ -42,6 +44,18 @@ typedef struct time_s { int add_idx; } Time_c; +/* sizeof(PlusBridge_c) == 8 */ +typedef struct plus_bridge_s { + /* 0x00 */ u8 block_x; + /* 0x01 */ u8 block_z; + /* 0x02 */ struct { + u8 exists:1; + u8 pending:1; + u8 pad:6; + }; + /* 0x04 */ lbRTC_ymd_t build_date; +} PlusBridge_c; + typedef struct Save_s { /* 0x000000 */ mFRm_chk_t save_check; /* save information */ /* 0x000014 */ int scene_no; /* current 'scene' id */ @@ -77,24 +91,38 @@ typedef struct Save_s { /* 0x020F1B */ u8 npc_force_go_home; /* when set to 1, forces the 'm_go_home' code to activate */ /* 0x020F1C */ u16 deposit[FG_BLOCK_X_NUM * FG_BLOCK_Z_NUM][UT_Z_NUM]; /* flags for which items are buried around town */ /* 0x0212DC */ lbRTC_time_c last_grow_time; /* last time that a new villager moved into town */ - /* 0x0212E4 */ u8 _tmp4[0xAA]; + /* 0x0212E4 */ u8 _tmp4[0x02137E - 0x0212E4]; + /* 0x02137E */ lbRTC_time_c treasure_buried_time; /* last time treasure was actually buried */ + /* 0x021386 */ lbRTC_time_c treasure_checked_time; /* last time check to bury treasure was executed */ /* 0x02138E */ u8 saved_rom_debug; /* flag to set save to 'debug rom' mode */ - /* 0x02138F */ u8 _tmp5[0x11]; + /* 0x02138F */ u8 snowman_year; /* year last snowman was built */ + /* 0x021390 */ u8 snowman_month; /* month last snowman was built */ + /* 0x021391 */ u8 snowman_day; /* day last snowman was built */ + /* 0x021392 */ u8 snowman_hour; /* hour last snowman was built */ + /* 0x021393 */ u8 haniwa_scheduled; /* when set, gyroids will be spwaned */ + /* 0x021394 */ u8 dust_flag; /* set by field assessment for too much 'dust' (garbage) around town, causes immediate fail of town ranking */ + /* 0x021395 */ u8 clear_grass; /* set by Wisp, removes all weeds */ + /* 0x021396 */ lbRTC_ymd_t event_year_ymd; /* might not exist and just be lbRTC_year_t */ + /* 0x02139A */ u8 unused_2139A[6]; /* 0x0213A0 */ u8 keep_house_size[PLAYER_NUM]; /* saved flags for house sizes */ - /* 0x0213A4 */ u8 _tmp6[0x21400 - 0x213A4]; + /* 0x0213A4 */ lbRTC_ymd_t force_remove_date; /* last time the NPC force remove timer was updated */ + /* 0x0213A8 */ mMmd_info_c museum_display; /* museum display bits */ + /* 0x0213E7 */ u8 _tmp6[0x213F0 - 0x213E7]; + /* 0x0213F0 */ PlusBridge_c plus_bridge; /* additional bridge info */ /* 0x021400 */ mNW_needlework_c needlework; /* Able Sisters' designs */ /* 0x022500 */ u8 _tmp7[0x22528 - 0x22500]; /* 0x022528 */ OSTime time_delta; /* time delta against GC RTC */ - /* 0x022530 */ u8 _tmp8[0x10]; /* 0x022540 */ Island_c island; /* island data */ /* 0x023E40 */ u8 _tmp9[0x320]; /* 0x024160 */ Anmret_c return_animal; /* information about villager which moved back in to your town after moving to someone else's town */ - /* 0x02416C */ u8 _tmp10[0x1E94]; + /* 0x02416C */ u8 _tmp10[0x241A0 - 0x2416C]; + /* 0x0241A0 */ lbRTC_time_c saved_auto_nwrite_time; /* save data notice time used for fishing tourney results? */ + /* 0x0241A8 */ u8 _tmp11[0x26000 - 0x241A8]; } Save_t; typedef union save_u { Save_t save; - u8 raw[0x26000]; /* Temp to force length */ + //u8 raw[0x26000]; /* Temp to force length */ } Save; /* sizeof(common_data_t) == 0x2DC00 */ @@ -113,9 +141,27 @@ typedef struct common_data_s { /* 0x026144 */ u8 tmp0[0x23E8]; /* 0x02852C */ s16 money_power; /* 0x02852E */ s16 goods_power; - /* 0x028530 */ u8 tmp1[0x5680]; + /* 0x028530 */ u8 tmp1[0x28879 - 0x28530]; + /* 0x028879 */ u8 auto_nwrite_count; + /* 0x02887A */ lbRTC_year_t auto_nwrite_year; + /* 0x02887C */ u8 save_error_type; /* set to one of the mFRm_ERROR_* states when save is invalid */ + /* 0x02887D */ u8 train_coming_flag; /* set when the train is coming */ + /* 0x02887E */ u8 buried_treasure_flag; /* when set, treasure cannot be buried */ + /* 0x02887F */ u8 tmp2[0x2DB40 - 0x2887F]; + /* 0x02DB40 */ u8 auto_nwrite_set; /* when true, saved nwrite time will be utilized. Seems to be used to keep same date for fishing tourney stuff. */ + /* 0x02DB41 */ u8 tmp3[0x2DBB0 - 0x2DB41]; /* 0x02DBB0 */ s16 can_look_goki_count; - /* 0x02DBB2 */ u8 tmp2[0x4E]; + /* 0x02DBB4 */ f32 rainbow_opacity; /* current opacity of rainbow (0.0f - 1.0f) */ + /* 0x02DBB8 */ u32 event_flags[7]; /* TODO: make array size a definition/enum */ + /* 0x02DBD4 */ xyz_t* pluss_bridge_pos; /* position of extra bridge */ + /* 0x02DBD8 */ lbRTC_time_c auto_nwrite_time; /* cached notice time used for fishing tourney results? */ + /* 0x02DBE0 */ u8 rhythym_updated; + /* 0x02DBE1 */ u8 _2dbe1; + /* 0x02DBE2 */ u8 hem_visible; /* controls farley's visiblilty during cutscene? */ + /* 0x02DBE4 */ u8* carde_program_p; /* pointer to current e-Reader program data */ + /* 0x02DBE8 */ size_t carde_program_size; /* size of current e-Reader program data */ + /* 0x02DBEC */ int unk_nook_present_count; /* something possibly to do withhanding over password present? */ + /* 0x02DBF0 */ u8 pad[16]; } common_data_t; extern common_data_t common_data; diff --git a/include/m_event.h b/include/m_event.h index 67d0f90a..380607ee 100644 --- a/include/m_event.h +++ b/include/m_event.h @@ -96,8 +96,22 @@ enum events { mEv_SPECL_DESIGNER_COMPLETE = (int)mEv_SET(mEv_SPECL_EVENT, 0) }; +enum week_type { + mEv_WEEKTYPE_NONE, + mEv_WEEKTYPE_1ST, + mEv_WEEKTYPE_2ND, + mEv_WEEKTYPE_3RD, + mEv_WEEKTYPE_4TH, + mEv_WEEKTYPE_5TH, + mEv_WEEKTYPE_LAST, + mEv_WEEKTYPE_SPECIAL +}; + extern int mEv_CheckFirstJob(); extern int mEv_CheckArbeit(); +extern int mEv_CheckTitleDemo(); + +extern int mEv_weekday2day(lbRTC_month_t month, int week_type, lbRTC_weekday_t weekday); extern void mEv_debug_print4f(gfxprint_t* gfxprint); extern void mEv_sp_debug_print4f(gfxprint_t* gfxprint); diff --git a/include/m_field_info.h b/include/m_field_info.h index 3a99c081..a0795e50 100644 --- a/include/m_field_info.h +++ b/include/m_field_info.h @@ -9,6 +9,9 @@ extern "C" { #endif +#define mFI_ROW_TO_CHARSTR(row) ((row) + 'A') +#define mFI_COL_TO_CHARSTR(col) ((col) + '0') + enum field_type { mFI_FIELDTYPE_FG, mFI_FIELDTYPE_1, @@ -21,8 +24,9 @@ enum field_type { mFI_FIELDTYPE_NUM }; -#define mFI_TO_FIELD_ID(type, index) ((type << 12) | index) -#define mFI_GET_TYPE (field_id) (field_id & 0xF000) +#define mFI_TO_FIELD_ID(type, index) (((type) << 12) | (index)) +#define mFI_GET_TYPE(field_id) ((field_id) & 0xF000) +#define mFI_TYPE(type) ((type) << 12) enum field_room { /* TODO: others */ @@ -55,6 +59,7 @@ extern mActor_name_t mFI_GetFieldId(); extern int mFI_GetClimate(); extern mActor_name_t* mFI_BkNumtoUtFGTop(int block_x, int block_z); extern void mFI_ClearDeposit(int block_x, int block_z); +extern int mFI_SetTreasure(int* block_x, int* block_z, mActor_name_t item_no); extern void mFI_PrintNowBGNum(gfxprint_t* gfxprint); extern void mFI_PrintFgAttr(gfxprint_t* gfxprint); diff --git a/include/m_fishrecord.h b/include/m_fishrecord.h new file mode 100644 index 00000000..4a6749c2 --- /dev/null +++ b/include/m_fishrecord.h @@ -0,0 +1,20 @@ +#ifndef M_FISHRECORD_H +#define M_FISHRECORD_H + +#include "types.h" +#include "m_personal_id.h" +#include "lb_rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void mEv_fishRecord_holder(PersonalID_c* winner_pid, u32* winning_size, lbRTC_ymd_t* contest_date); +extern int mEv_fishday(lbRTC_ymd_t* dates, lbRTC_time_c* now_time); +extern void mFR_fishmail(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_flashrom.h b/include/m_flashrom.h index 80ba2ee4..6f3b3688 100644 --- a/include/m_flashrom.h +++ b/include/m_flashrom.h @@ -13,6 +13,21 @@ extern "C" { #define mFRm_ERROR_INFO_NUM 10 #define mFRm_NO_ERROR_NO 7 +enum save_error_type { + mFRm_ERROR_BAD_RTC, /* RTC returned abnormal value */ + mFRm_ERROR_MEMCARD_TRAVELDATA_CONFLICT, /* travel data is on the same memory card as requesting to save town data */ + mFRm_ERROR_DATA_CORRUPTED, /* save data is corrupt */ + mFRm_ERROR_MEMCARD_NO_FILES, /* memory card is out of "files" */ + mFRm_ERROR_MEMCARD_DAMAGED, /* memory card is damaged */ + mFRm_ERROR_MEMCARD_FORMAT, /* memory card requires formatting (corrupt or different region?) */ + mFRm_ERROR_MEMCARD_INVALID, /* memory card type "cannot be used with Animal Crossing" */ + mFRm_ERROR_MEMCARD_NO_SPACE, /* memory card has free files, but not enough free space for save */ + mFRm_ERROR_NOT_MEMCARD, /* device in card slot is not a memory card */ + mFRm_ERROR_NO_MEMCARD, /* nothing inserted in either Slot A or Slot B */ + + mFRm_ERROR_NUM +}; + typedef struct mFRm_chk_s { /* 0x00 */ int version; /* 0x04 */ u32 code; diff --git a/include/m_handbill.h b/include/m_handbill.h new file mode 100644 index 00000000..e56438ea --- /dev/null +++ b/include/m_handbill.h @@ -0,0 +1,23 @@ +#ifndef M_HANDBILL_H +#define M_HANDBILL_H + +#include "types.h" +#include "m_mail.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define mHandbill_HEADER_LEN MAIL_HEADER_LEN +#define mHandbill_FOOTER_LEN MAIL_FOOTER_LEN +#define mHandbill_BODY_LEN MAIL_BODY_LEN + +extern void mHandbill_Load_HandbillFromRom(u8* header, int* header_back_pos, u8* footer, u8* body, int handbill_no); +extern void mHandbill_Set_free_str(int free_str_no, u8* str, int str_len); +extern void mHandbill_Set_free_str_art(int free_str_no, u8* str, int str_len, int article_no); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_item_name.h b/include/m_item_name.h new file mode 100644 index 00000000..3c8be34a --- /dev/null +++ b/include/m_item_name.h @@ -0,0 +1,20 @@ +#ifndef M_ITEM_NAME_H +#define M_ITEM_NAME_H + +#include "types.h" +#include "m_actor_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define mIN_ITEM_NAME_LEN 16 + +extern void mIN_copy_name_str(u8* str, mActor_name_t item_no); +extern int mIN_get_item_article(mActor_name_t item_no); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_land.h b/include/m_land.h index 104b0b56..31dbdaa2 100644 --- a/include/m_land.h +++ b/include/m_land.h @@ -15,7 +15,24 @@ extern "C" { #define NATIVE 0 #define FOREIGN 1 +extern void mLd_StartFlagOn(); +extern int mLd_CheckStartFlag(); +extern int mLd_NullCheckLandName(const u8* land_name); +extern int mLd_CheckId(u16 land_id); +extern int mLd_CheckCmpLandName(u8* name_a, u8* name_b); +extern int mLd_CheckCmpLand(u8* name_a, u16 id_a, u8* name_b, u16 id_b); +extern void mLd_ClearLandName(u8* name); +extern void mLd_CopyLandName(u8* dst, u8* src); +extern int mLd_AddMuraString(u8* name, int name_len); +extern void mLd_GetLandNameStringAddMura(u8* buf); +extern void mLd_SetFreeStrLandMuraName(u8* name, int free_str_no); extern u8* mLd_GetLandName(); +extern u16 mLd_MakeLandId(); +extern int mLd_PlayerManKindCheckNo(u8 player_no); +extern int mLd_PlayerManKindCheck(); +extern int mLd_CheckThisLand(u8* other_name, u16 other_id); +extern void mLd_LandInfoInit(); +extern void mLd_LandDataInit(); #ifdef __cplusplus } diff --git a/include/m_museum_display.h b/include/m_museum_display.h new file mode 100644 index 00000000..2c070ef8 --- /dev/null +++ b/include/m_museum_display.h @@ -0,0 +1,38 @@ +#ifndef M_MUSEUM_DISPLAY_H +#define M_MUSEUM_DISPLAY_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* TODO: these should be determined from item name indices */ + +#define mMmd_FOSSIL_BIT_NUM 13 +#define mMmd_ART_BIT_NUM 8 +#define mMmd_FISH_BIT_NUM 21 +#define mMmd_INSECT_BIT_NUM 21 + +/* 4 bits per donatable item */ +#define mMmd_BIT_INFO(info, category, index) \ + (((info).category[(index) / 2] >> (((index) & 1) << 2)) & 0x0F) + +#define mMmd_ART_BIT(info, index) mMmd_BIT_INFO(info, art, index) +#define mMmd_INSECT_BIT(info, index) mMmd_BIT_INFO(info, insect, index) +#define mMmd_FISH_BIT(info, index) mMmd_BIT_INFO(info, fish, index) +#define mMmd_FOSSIL_BIT(info, index) mMmd_BIT_INFO(info, fossil, index) + +/* sizeof(mMmd_info_c) == 0x3F */ +typedef struct museum_display_info_s { + /* 0x00 */ u8 fossil_bit[mMmd_FOSSIL_BIT_NUM]; + /* 0x0D */ u8 art_bit[mMmd_ART_BIT_NUM]; + /* 0x15 */ u8 fish_bit[mMmd_FISH_BIT_NUM]; + /* 0x2A */ u8 insect_bit[mMmd_INSECT_BIT_NUM]; +} mMmd_info_c; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_name_table.h b/include/m_name_table.h index b55d7382..95135397 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -55,6 +55,8 @@ enum { #define ITM_SHOVEL 0x2202 #define ITM_ROD 0x2203 +#define ITM_PITFALL 0x2512 + #define ITM_ENV_START 0x2900 #define ITM_SAPLING ITM_ENV_START #define ITM_CEDAR_SAPLING 0x2901 diff --git a/include/m_needlework.h b/include/m_needlework.h index 0da6d6ef..4c8350c6 100644 --- a/include/m_needlework.h +++ b/include/m_needlework.h @@ -24,9 +24,8 @@ extern "C" { typedef struct original_data_s { /* 0x000 */ u8 name[mNW_ORIGINAL_DESIGN_NAME_LEN]; /* 0x010 */ u8 palette; - /* 0x011 */ u8 pad[15]; - /* 0x020 */ u8 design[mNW_DESIGN_TEX_SIZE]; + /* 0x020 */ u8 design[mNW_DESIGN_TEX_SIZE] ATTRIBUTE_ALIGN(32); /* this is aligned to 32 bytes for ARAM transfer */ } mNW_original_design_c; /* sizeof(mNW_needlework_c) == 0x1100 */ diff --git a/include/m_npc.h b/include/m_npc.h index bfcdea41..cd9c28d9 100644 --- a/include/m_npc.h +++ b/include/m_npc.h @@ -145,6 +145,10 @@ typedef struct animal_return_s { /* 0x04 */ lbRTC_time_c renew_time; /* time that this struct was updated */ } Anmret_c; +/* anm_id could also just be a Animal_c pointer */ +extern void mNpc_GetNpcWorldNameAnm(u8* name, AnmPersonalID_c* anm_id); +extern int mNpc_CheckFreeAnimalPersonalID(AnmPersonalID_c* anm_id); + extern void mNpc_PrintRemoveInfo(gfxprint_t* gfxprint); extern void mNpc_PrintFriendship_fdebug(gfxprint_t* gfxprint); diff --git a/include/m_private.h b/include/m_private.h index ade41a7b..e32c35cf 100644 --- a/include/m_private.h +++ b/include/m_private.h @@ -152,7 +152,6 @@ typedef struct private_s { /* 0x11DC */ mPr_map_info_c maps[mPr_FOREIGN_MAP_COUNT]; /* maps 'collected' for foreign towns */ /* 0x122C */ u32 bank_account; /* probably 'deposit' interally */ - /* 0x1230 */ u8 unused_1230[16]; /* 0x1240 */ mNW_original_design_c my_org[mPr_ORIGINAL_DESIGN_COUNT]; /* Able Sisters' designs */ /* 0x2340 */ u8 my_org_no_table[mPr_ORIGINAL_DESIGN_COUNT]; /* order of designs */ /* 0x2348 */ u32 state_flags; /* TODO: this might be a bitfield/struct, also document bits */ diff --git a/include/m_shop.h b/include/m_shop.h index 2260e201..9d10a558 100644 --- a/include/m_shop.h +++ b/include/m_shop.h @@ -126,6 +126,7 @@ typedef struct shop_s { extern void mSP_PrintNowShopSalesSum(gfxprint_t* gfxprint); extern void mSP_SelectRandomItem_New(GAME* unused, mActor_name_t* item_tbl, int item_tbl_count, mActor_name_t* goods_exist_tbl, int goods_exist_tbl_count, int category, int list_type, int get_uncollected_item); extern void mSP_RandomUmbSelect(mActor_name_t* item_buf, int item_buf_count); +extern int mSP_GetShopLevel(); extern void mItemDebug_ItemDebugMain(); extern void mItemDebug_ItemDebugDraw(gfxprint_t* gfxprint); diff --git a/include/m_string.h b/include/m_string.h index 26b3ae2a..299329c3 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -2,12 +2,15 @@ #define M_STRING_H #include "types.h" +#include "lb_rtc.h" #ifdef __cplusplus extern "C" { #endif extern void mString_Load_StringFromRom(u8* buf, size_t buf_size, u32 str_no); +extern int mString_Load_MonthStringFromRom(u8* buf, lbRTC_month_t month); +extern int mString_Load_DayStringFromRom(u8* buf, lbRTC_day_t day); #ifdef __cplusplus } diff --git a/include/m_time.h b/include/m_time.h index 3a680933..48bebdc2 100644 --- a/include/m_time.h +++ b/include/m_time.h @@ -8,6 +8,10 @@ extern "C" { #endif + +/* TODO: this might have a better header to live in */ +#define mTM_FIELD_RENEW_HOUR 6 /* hour which daily things 'reset' */ + #define mTM_MIN_YEAR 2001 #define mTM_MAX_YEAR 2030 @@ -69,6 +73,8 @@ extern const lbRTC_time_c mTM_rtcTime_clear_code; extern const lbRTC_ymd_t mTM_rtcTime_ymd_clear_code; extern const lbRTC_time_c mTM_rtcTime_default_code; +#define mTM_IsTimeCleared(time) (lbRTC_IsEqualTime((time), &mTM_rtcTime_clear_code, lbRTC_CHECK_ALL) == TRUE) + #ifdef __cplusplus } #endif diff --git a/include/padmgr.h b/include/padmgr.h index 1ecd87fa..7270e3fb 100644 --- a/include/padmgr.h +++ b/include/padmgr.h @@ -44,7 +44,7 @@ typedef struct { /* 0x00AC */ irqmgr_client_t irqclient; /* 0x00B4 */ u32 _unk0; /* maybe additional value in irqmgr_client_t? */ /* 0x00B8 */ OSThread thread; - /* 0x03D0 */ u8 _tmp[0x58]; //pad_t pads[MAXCONTROLLERS]; // TODO: figure out what's going on here. + /* 0x03C8 */ u8 _tmp[0x60]; //pad_t pads[MAXCONTROLLERS]; // TODO: figure out what's going on here. /* 0x0428 */ OSContPad n64_pads[MAXCONTROLLERS]; /* Converted from PADStatus via JUTGamePad */ /* 0x0440 */ u8 num_controllers; /* 0x0441 */ u8 device_type[4]; diff --git a/rel/m_font.c b/rel/m_font.c index 0ba7b71e..a0f705f7 100644 --- a/rel/m_font.c +++ b/rel/m_font.c @@ -88,7 +88,7 @@ extern int mFont_UnintToString( int last_figure; int l = figure - figure_start; - u8 fill_char = fill_zero ? CHAR_ZERO : CHAR_SPACE ; + u8 fill_char = fill_zero ? CHAR_ZERO : CHAR_SPACE; u8 left_fill_char = fill_zero && !left_cut ? CHAR_ZERO : CHAR_SPACE; cur_num = num; diff --git a/rel/m_land.c b/rel/m_land.c index d30c458f..1cf1cb47 100644 --- a/rel/m_land.c +++ b/rel/m_land.c @@ -221,7 +221,7 @@ extern u16 mLd_MakeLandId() { /** * @brief Checks if a player is a foreigner based on their player number. * @param player_no The player number. - * @return FOREIGN if the player is a foreigner, NATIVE otherwise. + * @return TRUE if the player is a foreigner, FALSE otherwise. */ extern int mLd_PlayerManKindCheckNo(u8 player_no) { int foreigner = TRUE; @@ -234,7 +234,7 @@ extern int mLd_PlayerManKindCheckNo(u8 player_no) { /** * @brief Checks if the current player is a foreigner. - * @return FOREIGN if the current player is a foreigner, NATIVE otherwise. + * @return TRYE if the current player is a foreigner, FALSE otherwise. */ extern int mLd_PlayerManKindCheck() { return mLd_PlayerManKindCheckNo(Common_Get(player_no)); diff --git a/rel/m_notice.c b/rel/m_notice.c new file mode 100644 index 00000000..dbe101c7 --- /dev/null +++ b/rel/m_notice.c @@ -0,0 +1,731 @@ +#include "m_notice.h" + +#include "lb_rtc.h" +#include "lb_reki.h" +#include "m_time.h" +#include "m_event.h" +#include "m_mail.h" +#include "m_font.h" +#include "m_string.h" +#include "m_handbill.h" +#include "m_field_info.h" +#include "m_lib.h" +#include "m_land.h" +#include "m_item_name.h" +#include "m_npc.h" +#include "m_name_table.h" +#include "m_shop.h" +#include "m_fishrecord.h" +#include "m_event.h" +#include "m_common_data.h" + +#define lbRTC_TIME_TO_U32(t) ((u32)(((t)->year << 16) + ((t)->month << 8) + (t)->day)) + +#define mNtc_TO_MONTHDAY(mo, day) ((u16)((((mo) & 0xFF) << 8) | ((day) & 0xFF))) +#define mNtc_GET_MONTH(monthday) (((monthday) >> 8) & 0xFF) +#define mNtc_GET_DAY(monthday) ((monthday) & 0xFF) + +#define mNTC_UNUSED_DATE mNtc_TO_MONTHDAY(0xFF, 0xFF) + +#define mNtc_FISHING_DAY_YEAR 0xFFFF +#define mNtc_FISHING_DAY_NUM 0xFF + +#define mNtc_MIN_DAYS_BETWEEN_TREASURE 3 +#define mNtc_TREASURE_CHANCE 0.4f /* 40% chance when possible */ + +#define mNtc_NWRITE_NUM 5 + +#define mNtc_DATA_LIST_NUM 43 + +#define mNtc_UNUSED_MONTH 0xFF +#define mNtc_UNUSED_DAY 0xFF + +/* sizeof(mNtc_date_c) == 2 */ +typedef struct notice_date_s { + /* 0x00 */ lbRTC_month_t month; + /* 0x01 */ lbRTC_day_t day; +} mNtc_date_c; + +/* sizeof(mNtc_date_data_c) == 4 */ +typedef struct notice_date_data_s { + /* 0x00 */ u16 id; + /* 0x02 */ u16 date; +} mNtc_date_data_c; + +static mNtc_date_data_c mNtc_auto_nwrite_data[48]; + +static void mNtc_copy_data_list() { + static mNtc_date_data_c auto_nwrite_date_data[mNtc_DATA_LIST_NUM] = { + { 0x00, mNtc_TO_MONTHDAY(lbRTC_JANUARY, 1) }, /* Nook's New Year's post */ + { 0x01, mNtc_TO_MONTHDAY(lbRTC_JANUARY, 15) }, /* Snow weather report */ + { 0x02, mNtc_TO_MONTHDAY(lbRTC_JANUARY, 25) }, /* Groundhog day notice */ + { 0x03, mNtc_TO_MONTHDAY(lbRTC_FEBRUARY, 1) }, /* Valentine's Day notice */ + { 0x04, mNtc_TO_MONTHDAY(lbRTC_FEBRUARY, 15) }, /* Pete's Valentine's Day complaint */ + { 0x05, mNtc_TO_MONTHDAY(lbRTC_MARCH, 15) }, /* Cherry Blossom Festival notice */ + { 0x06, mNtc_TO_MONTHDAY(lbRTC_MARCH, 11) }, /* Spring Sports Fair notice */ + { 0x07, mNtc_TO_MONTHDAY(lbRTC_MARCH, 16) }, /* Spring Sports Fair vernal equinox notice */ + { 0x08, mNtc_TO_MONTHDAY(lbRTC_MARCH, 20) }, /* Spring Sports Fair schedule */ + { 0x09, mNtc_TO_MONTHDAY(lbRTC_APRIL, 3) }, /* Cherry Blossom Festival reminder notice */ + { 0x0A, mNtc_TO_MONTHDAY(lbRTC_APRIL, 21) }, /* Spring weather notice */ + { 0x0B, mNtc_TO_MONTHDAY(lbRTC_MAY, 6) }, /* June weather notice */ + { 0x0C, mNtc_TO_MONTHDAY(lbRTC_MAY, 20) }, /* Summer fishing tourney notice */ + { 0x0D, mNtc_TO_MONTHDAY(lbRTC_JUNE, 8) }, /* Chip's 1st summer fishing tourney post */ + { 0x0E, mNtc_TO_MONTHDAY(lbRTC_JUNE, 23) }, /* Chip's final summer fishing tourney post */ + { 0x0F, mNtc_TO_MONTHDAY(lbRTC_JUNE, 25) }, /* Fireworks Festival notice */ + { 0x10, mNtc_TO_MONTHDAY(lbRTC_JULY, 1) }, /* July weather notice */ + { 0x11, mNtc_TO_MONTHDAY(lbRTC_JULY, 5) }, /* Phyllis? Fireworks Festival complaint */ + { 0x12, mNtc_TO_MONTHDAY(lbRTC_JULY, 15) }, /* Morning aerobics notice */ + { 0x13, mNtc_TO_MONTHDAY(lbRTC_JULY, 25) }, /* Copper morning aerobics post */ + { 0x14, mNtc_TO_MONTHDAY(lbRTC_AUGUST, 1) }, /* Meteor Shower notice */ + { 0x15, mNtc_TO_MONTHDAY(lbRTC_AUGUST, 30) }, /* Copper morning aerobics final day notice */ + { 0x16, mNtc_TO_MONTHDAY(lbRTC_SEPTEMBER, 1) }, /* Moon Viewing notice */ + { 0x17, mNtc_TO_MONTHDAY(lbRTC_SEPTEMBER, 15) }, /* September weather report */ + { 0x18, mNtc_TO_MONTHDAY(lbRTC_SEPTEMBER, 13) }, /* Pete's Fall Sports Fair post */ + { 0x19, mNtc_TO_MONTHDAY(lbRTC_SEPTEMBER, 18) }, /* Fall Sports Fair notice */ + { 0x1A, mNtc_TO_MONTHDAY(lbRTC_SEPTEMBER, 22) }, /* Fall Sports Fair schedule */ + { 0x1B, mNtc_TO_MONTHDAY(lbRTC_OCTOBER, 10) }, /* Mushrooming season notice */ + { 0x1C, mNtc_TO_MONTHDAY(lbRTC_OCTOBER, 16) }, /* Nook's Halloween candy post */ + { 0x1D, mNtc_TO_MONTHDAY(lbRTC_OCTOBER, 20) }, /* Halloween notice */ + { 0x1E, mNtc_TO_MONTHDAY(lbRTC_OCTOBER, 25) }, /* Fall fishing tourney notice */ + { 0x1F, mNtc_TO_MONTHDAY(lbRTC_NOVEMBER, 8) }, /* Chip's 1st fall fishing tourney post */ + { 0x20, mNtc_TO_MONTHDAY(lbRTC_NOVEMBER, 10) }, /* Harvest Festival notice */ + { 0x21, mNtc_TO_MONTHDAY(lbRTC_NOVEMBER, 12) }, /* November weather report */ + { 0x22, mNtc_TO_MONTHDAY(lbRTC_NOVEMBER, 23) }, /* Chip's final fall fishing tourney post */ + { 0x23, mNtc_TO_MONTHDAY(lbRTC_DECEMBER, 9) }, /* Winter storm warning */ + { 0x24, mNtc_TO_MONTHDAY(lbRTC_DECEMBER, 20) }, /* Jingle's holiday notice */ + { 0x25, mNtc_TO_MONTHDAY(lbRTC_DECEMBER, 25) }, /* New Year's Eve countdown notice */ + { 0x26, mNtc_TO_MONTHDAY(lbRTC_DECEMBER, 28) }, /* New Year's Day event notice */ + { 0x27, mNTC_UNUSED_DATE }, /* Pete check mailbox info? */ + { 0x28, mNTC_UNUSED_DATE }, /* Anti-litter notice? */ + { 0x29, mNtc_TO_MONTHDAY(lbRTC_MARCH, 31) }, /* Day light savings begin notice */ + { 0x2A, mNtc_TO_MONTHDAY(lbRTC_OCTOBER, 31) } /* Day light savings end notice */ + }; + + mem_copy((u8*)mNtc_auto_nwrite_data, (u8*)auto_nwrite_date_data, mNtc_DATA_LIST_NUM * sizeof(mNtc_date_data_c)); +} + +static void mNtc_operate_data_list() { + mNtc_date_data_c* data_p; + int day; + + /* update Spring Sports Fair dates */ + day = lbRk_VernalEquinoxDay(Common_Get(time.rtc_time.year)); + /* month = march, day = vernal equinox day - 10 */ + data_p = mNtc_auto_nwrite_data + 6; + data_p->date = day + 0x2F6; + /* month = march, day = vernal equinox day - 5 */ + data_p = mNtc_auto_nwrite_data + 7; + data_p->date = day + 0x2FB; + /* month = march, day = vernal equinox day - 1 */ + data_p = mNtc_auto_nwrite_data + 8; + data_p->date = day + 0x2FF; + + /* update Fall Sports Fair dates */ + day = lbRk_AutumnalEquinoxDay(Common_Get(time.rtc_time.year)); + /* month = september, day = autumnal equinox day - 10 */ + data_p = mNtc_auto_nwrite_data + 0x18; + data_p->date = day + 0x8F6; + /* month = september, day = autumnal equinox day - 5 */ + data_p = mNtc_auto_nwrite_data + 0x19; + data_p->date = day + 0x8FB; + /* month = september, day = autumnal equinox day - 1 */ + data_p = mNtc_auto_nwrite_data + 0x1A; + data_p->date = day + 0x8FF; + + /* update daylight savings time dates */ + mNtc_auto_nwrite_data[0x29].date = mEv_weekday2day(lbRTC_MARCH, mEv_WEEKTYPE_LAST, lbRTC_SUNDAY) + 0x300; /* month = march, day = last sunday */ + mNtc_auto_nwrite_data[0x2A].date = mEv_weekday2day(lbRTC_OCTOBER, mEv_WEEKTYPE_LAST, lbRTC_SUNDAY) + 0x9F9; /* month = october, day = second to last sunday */ +} + +static void mNtc_sort_data_list() { + mNtc_date_data_c replace_data; + mNtc_date_data_c now_data; + int replace_idx; + int i, j; + + /* sort from earliest to latest dates */ + for (i = 0; i < mNtc_DATA_LIST_NUM; i++) { + now_data = mNtc_auto_nwrite_data[i]; + replace_data = now_data; + replace_idx = i; + + /* search through all entries ahead and find the next closest date */ + for (j = i + 1; j < mNtc_DATA_LIST_NUM; j++) { + if (mNtc_auto_nwrite_data[j].date < replace_data.date) { + replace_data = mNtc_auto_nwrite_data[j]; + replace_idx = j; + } + } + + /* swap the entries */ + mNtc_auto_nwrite_data[replace_idx] = now_data; + mNtc_auto_nwrite_data[i] = replace_data; + } +} + +static void mNtc_make_auto_nwrite_data_list() { + mNtc_copy_data_list(); /* copy the base list */ + mNtc_operate_data_list(); /* update dynamic dates */ + mNtc_sort_data_list(); /* sort entries by date */ +} + +static int mNtc_get_auto_nwrite_data_last_idx() { + int i; + int res = mNtc_DATA_LIST_NUM - 1; + + for (i = mNtc_DATA_LIST_NUM - 1; i >= 0; i--) { + if (mNtc_auto_nwrite_data[i].date != 0xFFFF) { + res = i; + break; + } + } + + return res; +} + +static void mNtc_ClearPage(mNtc_board_post_c* page, int count) { + for (count; count != 0; count--) { + page->post_time = mTM_rtcTime_clear_code; + mem_clear(page->message, MAIL_BODY_LEN, CHAR_SPACE); + page++; + } +} + +extern void mNtc_SetInitData() { + mNtc_board_post_c* post; + lbRTC_time_c rtc_time; + int header_back_pos; + int handbill_no_tbl[4] = { 0x1E, 0x1F, 0x20, 0x21 }; + u8 header[mHandbill_HEADER_LEN]; + u8 footer[mHandbill_FOOTER_LEN]; + int i; + + post = Save_Get(noticeboard); + //handbill_no_tbl[0] = 0x1E; /* noticeboard free to use post */ + //handbill_no_tbl[1] = 0x1F; /* Nook's HRA recruitment post */ + //handbill_no_tbl[2] = 0x20; /* HRA points guide post */ + //handbill_no_tbl[3] = 0x21; /* noticeboard usage post */ + + rtc_time = Common_Get(time.rtc_time); + + for (i = 0; i < 4; i++) { + post->post_time = rtc_time; + mHandbill_Load_HandbillFromRom(header, &header_back_pos, footer, post->message, handbill_no_tbl[i]); + post++; + } + + mNtc_ClearPage(post, mNtc_BOARD_POST_COUNT - 4); +} + +extern int mNtc_notice_write_num() { + mNtc_board_post_c* post; + int i; + + post = Save_Get(noticeboard); + for (i = 0; i < mNtc_BOARD_POST_COUNT; i++) { + if (lbRTC_IsEqualTime(&post->post_time, &mTM_rtcTime_clear_code, lbRTC_CHECK_ALL) == TRUE) { + break; + } + post++; + } + + return i; +} + +extern void mNtc_notice_write(mNtc_board_post_c* new_post) { + int write_num = mNtc_notice_write_num(); + if (write_num == mNtc_BOARD_POST_COUNT) { + mNtc_board_post_c* post = Save_Get(noticeboard); + int i; + + /* delete first post and move all others down one */ + for (i = 0; i < mNtc_BOARD_POST_COUNT - 1; i++) { + mem_copy(post, post + 1, sizeof(mNtc_board_post_c)); + post++; + } + + /* copy new post */ + mem_copy((u8*)post, (u8*)new_post, sizeof(mNtc_board_post_c)); + } + else { + /* space available, write to lowest unused slot */ + mem_copy((u8*)(Save_Get(noticeboard) + write_num), (u8*)new_post, sizeof(mNtc_board_post_c)); + } +} + +static int mNtc_set_landname_string(u8* buf) { + mem_copy(buf, Save_Get(land_info.name), LAND_NAME_SIZE); + return mMl_strlen(Save_Get(land_info.name), LAND_NAME_SIZE, CHAR_SPACE); +} + +static void mNtc_set_treasure_string(AnmPersonalID_c* sender_id, mActor_name_t item_no, int block_x, int block_z) { + static u8 choume_str[BLOCK_X_NUM] = "QABCDEF"; + + int land_name_len; + u8 b_str; + u8 land_name[LAND_NAME_SIZE]; + u8 anm_name[ANIMAL_NAME_LEN]; + u8 item_name[mIN_ITEM_NAME_LEN]; + + mNpc_GetNpcWorldNameAnm(anm_name, sender_id); + mHandbill_Set_free_str(1, anm_name, ANIMAL_NAME_LEN); + mIN_copy_name_str(item_name, item_no); + mHandbill_Set_free_str_art(2, item_name, mIN_ITEM_NAME_LEN, mIN_get_item_article(item_no)); + + b_str = choume_str[block_z]; + mHandbill_Set_free_str(3, &b_str, 1); /* z-acre friendly name (A-F) */ + + b_str = mFI_COL_TO_CHARSTR(block_x); + mHandbill_Set_free_str(4, &b_str, 1); /* x-acre friendly name (1-5) */ + + land_name_len = mNtc_set_landname_string(land_name); + mHandbill_Set_free_str(5, land_name, land_name_len); +} + +// @nonmatching +/* TODO: match */ +static void mNtc_check_treasure() { + int valid_animal_ids[ANIMAL_NUM_MAX]; + lbRTC_time_c rtc_time; + lbRTC_time_c* treasure_checked_time; + lbRTC_time_c* treasure_buried_time; + Animal_c* animal; + mLd_land_info_c* land_info; + u32 comp_time_rtc; + u32 comp_time_buried; + int valid_animal_num; + int interval_days; + + valid_animal_num = 0; + rtc_time = Common_Get(time.rtc_time); + animal = Save_Get(animals); + land_info = Save_GetPointer(land_info); + treasure_buried_time = Save_GetPointer(treasure_buried_time); + treasure_checked_time = Save_GetPointer(treasure_checked_time); + + if (rtc_time.hour >= mTM_FIELD_RENEW_HOUR) { + comp_time_rtc = lbRTC_TIME_TO_U32(&rtc_time); + comp_time_buried = lbRTC_TIME_TO_U32(treasure_buried_time); + if (comp_time_rtc > comp_time_buried) { + interval_days = lbRTC_GetIntervalDays(treasure_buried_time, &rtc_time); + } + else if (comp_time_rtc < comp_time_buried) { + interval_days = lbRTC_GetIntervalDays(&rtc_time, treasure_buried_time); + } + else { + interval_days = 0; + } + + if (lbRTC_IsEqualTime(treasure_buried_time, &mTM_rtcTime_clear_code, lbRTC_CHECK_ALL) || + interval_days >= mNtc_MIN_DAYS_BETWEEN_TREASURE + ) { + if (lbRTC_IsEqualTime(treasure_checked_time, &mTM_rtcTime_clear_code, lbRTC_CHECK_ALL) || + treasure_checked_time->year != rtc_time.year || + treasure_checked_time->month != rtc_time.month || + treasure_checked_time->day != rtc_time.day + ) { + int i; + + for (i = 0; i < ANIMAL_NUM_MAX; i++, animal++) { + if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) { + int mem; + + for (mem = 0; mem < ANIMAL_MEMORY_NUM; mem++) { + if (animal->memories[mem].memory_player_id.land_id == land_info->id && + mLd_CheckCmpLandName(animal->memories[mem].memory_player_id.land_name, land_info->name) + ) { + if (valid_animal_num == ANIMAL_NUM_MAX) { + return; + } + + valid_animal_ids[valid_animal_num++] = i; + break; + } + //memory++; + } + } + } + + if (valid_animal_num != 0 && fqrand() < mNtc_TREASURE_CHANCE) { + f32 rng; + mActor_name_t item; + int b_x = 0; + int b_z = 0; + + + /* 1/3rd chance of pitfall, 2/3rds chance of rare furniture */ + rng = fqrand(); + if (rng < (1.0f / 3.0f)) { + item = ITM_PITFALL; + } + else { + int list_type = rng < (2.0f / 3.0f) ? mSP_LISTTYPE_LOTTERY : mSP_LISTTYPE_EVENT; /* 50/50 to roll redd or lottery furniture*/ + mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, mSP_KIND_FURNITURE, list_type, FALSE); + } + + if (mFI_SetTreasure(&b_x, &b_z, item)) { + u8 header[mHandbill_HEADER_LEN]; + u8 footer[mHandbill_FOOTER_LEN]; + int header_back_pos; + mNtc_board_post_c post; + int selected_animal = (int)(fqrand() * (f32)valid_animal_num); + int selected_animal_idx = valid_animal_ids[selected_animal % valid_animal_num]; + animal = Save_GetPointer(animals[selected_animal_idx]); + + mNtc_set_treasure_string(&animal->id, item, b_x, b_z); + lbRTC_TimeCopy(&post.post_time, &rtc_time); + mHandbill_Load_HandbillFromRom(header, &header_back_pos, footer, post.message, 0x1F0 + animal->id.looks * 3 + (((int)(fqrand() * 3.0f)) % 3)); + mNtc_notice_write(&post); + lbRTC_TimeCopy(Save_GetPointer(treasure_buried_time), &rtc_time); + } + } + } + } + } +} + +static void mNtc_set_near_old_nwrite_data(lbRTC_time_c* nwrite_time, lbRTC_year_t* nwrite_year, u8* nwrite_num) { + mNtc_date_data_c* auto_nwrite_p; + s16 date; + int last_idx; + int i; + + date = (nwrite_time->month << 8) + nwrite_time->day; + last_idx = mNtc_DATA_LIST_NUM - 1; + auto_nwrite_p = mNtc_auto_nwrite_data + (mNtc_DATA_LIST_NUM - 1); + + for (i = mNtc_DATA_LIST_NUM; i != 0; i--) { + if (date > auto_nwrite_p->date || (date == auto_nwrite_p->date && nwrite_time->hour >= mTM_FIELD_RENEW_HOUR)) { + break; + } + + auto_nwrite_p--; + last_idx--; + } + + if (last_idx != -1) { + *nwrite_year = nwrite_time->year; + *nwrite_num = last_idx; + } + else { + *nwrite_year = nwrite_time->year - 1; + *nwrite_num = mNtc_get_auto_nwrite_data_last_idx(); + } +} + +static int mNtc_make_auto_nwrite_day_string(u8* str, int month, int day) { + int month_len; + int day_len; + u8 buf[24]; + + month_len = mString_Load_MonthStringFromRom(buf, month); + mem_copy(str, buf, month_len); + str[month_len] = CHAR_SPACE; + day_len = mString_Load_DayStringFromRom(buf, day); + mem_copy(str + month_len + 1, buf, day_len); + return month_len + day_len + 1; +} + +static void mNtc_set_auto_nwrite_common_string() { + int land_name_len; + u8 land_name[LAND_NAME_SIZE]; + u8 shop_name[16]; + + land_name_len = mNtc_set_landname_string(land_name); + mHandbill_Set_free_str(0, land_name, land_name_len); + + mString_Load_StringFromRom(shop_name, 16, 0x558 + mSP_GetShopLevel()); + mHandbill_Set_free_str(1, shop_name, 16); +} + +static void mNtc_set_auto_nwrite_fishing_string(const lbRTC_ymd_t* date) { + u8 month_str[] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; + u8 day_str[] = { ' ', ' ', ' ', ' ' }; + u8 size_str[] = { ' ', ' ' }; + PersonalID_c winner_pid; + u32 size; + lbRTC_ymd_t win_date = *date; + + mEv_fishRecord_holder(&winner_pid, &size, &win_date); + mFont_UnintToString(size_str, 2, size, 2, 0, 0, TRUE); + mString_Load_MonthStringFromRom(month_str, date->month); + mHandbill_Set_free_str(0, month_str, 9); + mString_Load_DayStringFromRom(day_str, date->day); + mHandbill_Set_free_str(1, day_str, 4); + mHandbill_Set_free_str(2, winner_pid.player_name, PLAYER_NAME_LEN); + mHandbill_Set_free_str(3, size_str, 2); +} + +static void mNtc_set_auto_nwrite_string(lbRTC_year_t year) { + lbRTC_ymd_t harvest_moon_date; + int autumnal_equi_day; + int len; + u8 buf[28]; + + lbRk_HarvestMoonDay(&harvest_moon_date, year); + len = mNtc_make_auto_nwrite_day_string(buf, harvest_moon_date.month, harvest_moon_date.day); + mHandbill_Set_free_str(2, buf, len); + autumnal_equi_day = lbRk_AutumnalEquinoxDay(year); + len = mNtc_make_auto_nwrite_day_string(buf, lbRTC_SEPTEMBER, autumnal_equi_day); + mHandbill_Set_free_str(4, buf, len); +} + +extern void mNtc_auto_nwrite_time_ct() { + mNtc_make_auto_nwrite_data_list(); + + if (lbRTC_IsEqualTime(Save_GetPointer(saved_auto_nwrite_time), &mTM_rtcTime_clear_code, lbRTC_CHECK_ALL) == TRUE) { + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + mNtc_set_near_old_nwrite_data(&rtc_time, Common_GetPointer(auto_nwrite_year), Common_GetPointer(auto_nwrite_count)); + } + else { + mNtc_set_near_old_nwrite_data(Save_GetPointer(save_check.time), Common_GetPointer(auto_nwrite_year), Common_GetPointer(auto_nwrite_count)); + } +} + +/* TODO: better understand this function & refactor */ +static int mNtc_get_fishing_day(lbRTC_ymd_t* ymds, u16* dates, lbRTC_time_c* time, u16* fishing_term_date) { + int notice_year; + int notice_hour; + lbRTC_time_c time_temp; + lbRTC_ymd_t ymd_buf[5]; + int valid_count = 0; + int i; + + if (Common_Get(auto_nwrite_set) == FALSE) { + if (mTM_IsTimeCleared(Save_GetPointer(saved_auto_nwrite_time))) { + notice_year = time->year; + notice_hour = time->hour; + } + else { + notice_year = Save_Get(saved_auto_nwrite_time.year); + notice_hour = Save_Get(saved_auto_nwrite_time.hour); + } + } + else { + notice_year = Common_Get(auto_nwrite_time.year); + notice_hour = Common_Get(auto_nwrite_time.hour); + } + + time_temp = *time; + mEv_fishday(ymd_buf, &time_temp); + + for (i = 0; i < 5; i++) { + dates[i] = 0; + ymds[i].year = 0; + ymds[i].month = 0; + ymds[i].day = 0; + } + + for (i = 0; i < 5; i++) { + lbRTC_ymd_t* ymd = ymd_buf + i; + u16 month_day = (ymd_buf[i].month << 8) + ymd_buf[i].day; + + if (ymd->year > notice_year || + (notice_year == ymd->year && (month_day > *fishing_term_date || + (month_day == *fishing_term_date && notice_hour < 18))) + ) { + dates[valid_count] = month_day; + ymds[valid_count] = *ymd; + valid_count++; + } + } + + return valid_count; +} + +static void mNtc_set_fishing_term(u16* date, lbRTC_year_t* year) { + if (Common_Get(auto_nwrite_set) == FALSE) { + if (mTM_IsTimeCleared(Save_GetPointer(saved_auto_nwrite_time))) { + *date = (Common_Get(time.rtc_time.month) << 8) + Common_Get(time.rtc_time.day); + *year = Common_Get(time.rtc_time.year); + } + else { + *date = (Save_Get(saved_auto_nwrite_time.month) << 8) + Save_Get(saved_auto_nwrite_time.day); + *year = Save_Get(saved_auto_nwrite_time.year); + } + } + else { + *date = (Common_Get(auto_nwrite_time.month) << 8) + Common_Get(auto_nwrite_time.day); + *year = Common_Get(auto_nwrite_time.year); + } +} + +// @nonmatching +/* TODO: match */ +static void mNtc_decide_nwrite_data( + int* write_count, + lbRTC_year_t* nwrite_year, + u8* nwrite_num, + lbRTC_year_t now_nwrite_year, + u8 now_nwrite_num, + lbRTC_year_t* out_nwrite_years, + u8* out_nwrite_nums, + int* fishing_day, + u16 fishing_term_date, + lbRTC_year_t fishing_term_year, + lbRTC_ymd_t* ymds, + u16* month_days +) { + + while (*write_count != 0) { + while (TRUE) { + //fish_day = *fishing_day; + if ((*fishing_day <= 0 || (ymds[*fishing_day - 1].year <= fishing_term_year && (fishing_term_year != ymds[*fishing_day - 1].year || (month_days[*fishing_day - 1] < fishing_term_date)))) || + (ymds[*fishing_day - 1].year <= *nwrite_year && (*nwrite_year != ymds[*fishing_day - 1].year || month_days[*fishing_day - 1] < mNtc_auto_nwrite_data[*nwrite_num].date)) + ) { + break; + } + + (*write_count)--; + (*fishing_day)--; + + out_nwrite_years[*write_count] = -1; + out_nwrite_nums[*write_count] = -1; + } + + if (*nwrite_year <= now_nwrite_year) { + if (*nwrite_year != now_nwrite_year) { + return; + } + if (*nwrite_num <= now_nwrite_num) { + return; + } + } + + (*write_count)--; + + out_nwrite_years[*write_count] = *nwrite_year; + out_nwrite_nums[*write_count] = *nwrite_num; + + if (*nwrite_num == 0) { + *nwrite_num = mNtc_get_auto_nwrite_data_last_idx(); + (*nwrite_year)--; + } + else { + (*nwrite_num)--; + } + } +} + +// @nonmatching +/* TODO: match */ +static void mNtc_set_auto_nwrite(int write_count, u8* nwrite_nums, lbRTC_year_t* nwrite_years, int fishing_day, lbRTC_ymd_t* ymds, u16* month_days) { + mNtc_board_post_c post; + lbRTC_year_t now_year; + int header_back_pos; + u8 footer[MAIL_FOOTER_LEN]; + u8 header[MAIL_HEADER_LEN]; + int year; + int month; + int day; + + post.post_time.sec = 0; + post.post_time.min = 0; + post.post_time.hour = 0; + + now_year = 0; + + for (write_count; write_count < 5; write_count++) { + /* write 'fishing day' info */ + if (nwrite_nums[write_count] == mNtc_FISHING_DAY_NUM && nwrite_years[write_count] == mNtc_FISHING_DAY_YEAR) { + lbRTC_ymd_t* post_date = ymds + fishing_day; + lbRTC_ymd_t temp; + int id; + post.post_time.year = post_date->year; + post.post_time.month = mNtc_GET_MONTH(month_days[fishing_day]); + post.post_time.day = mNtc_GET_DAY(month_days[fishing_day]); + post.post_time.weekday = lbRTC_Week(post.post_time.year, post.post_time.month, post.post_time.day); + + temp = *post_date; + mNtc_set_auto_nwrite_fishing_string(&temp); + now_year = 0; + mHandbill_Load_HandbillFromRom(header, &header_back_pos, footer, post.message, 0x242 + ((post_date->day / 7u) & 3)); + mNtc_notice_write(&post); + } + else { /* write standard post */ + mNtc_set_auto_nwrite_common_string(); + /* check if we need to change the year string to a different year */ + if (now_year != nwrite_years[write_count]) { + mNtc_set_auto_nwrite_string(nwrite_years[write_count]); + now_year = nwrite_years[write_count]; + } + + year = nwrite_years[write_count]; + month = mNtc_GET_MONTH(mNtc_auto_nwrite_data[nwrite_nums[write_count]].date); + day = mNtc_GET_DAY(mNtc_auto_nwrite_data[nwrite_nums[write_count]].date); + + post.post_time.year = year; + post.post_time.month = month; + post.post_time.day = day; + post.post_time.weekday = lbRTC_Week(year, month, day); + + mHandbill_Load_HandbillFromRom(header, &header_back_pos, footer, post.message, 0x1A4 + mNtc_auto_nwrite_data[nwrite_nums[write_count]].id); + mNtc_notice_write(&post); + } + } +} + +extern void mNtc_set_auto_nwrite_data() { + u8 nwrite_num; + u16 fishing_term_date; + lbRTC_year_t fishing_term_year; + lbRTC_year_t nwrite_year; + lbRTC_year_t now_nwrite_year; + u8 now_nwrite_num; + lbRTC_time_c rtc_time; + u8 set_nwrite_nums[5]; + lbRTC_ymd_t nwrite_ymds[mNtc_NWRITE_NUM]; + u16 nwrite_dates[mNtc_NWRITE_NUM]; + lbRTC_year_t set_nwrite_years[mNtc_NWRITE_NUM]; + int write_count; + + if (mEv_CheckTitleDemo() == FALSE && mFI_GET_TYPE(mFI_GetFieldId()) == mFI_TYPE(mFI_FIELDTYPE_FG)) { + int fishing_day; + now_nwrite_year = Common_Get(auto_nwrite_year); + if (now_nwrite_year != 0) { + write_count = mNtc_NWRITE_NUM; + fishing_day = 0; + rtc_time = Common_Get(time.rtc_time); + now_nwrite_num = Common_Get(auto_nwrite_count); + mNtc_make_auto_nwrite_data_list(); + mNtc_set_fishing_term(&fishing_term_date, &fishing_term_year); + fishing_day = mNtc_get_fishing_day(nwrite_ymds, nwrite_dates, &rtc_time, &fishing_term_date); + mNtc_set_near_old_nwrite_data(&rtc_time, &nwrite_year, &nwrite_num); + + mNtc_decide_nwrite_data( + &write_count, + &nwrite_year, + &nwrite_num, + now_nwrite_year, + now_nwrite_num, + set_nwrite_years, + set_nwrite_nums, + &fishing_day, + fishing_term_date, + fishing_term_year, + nwrite_ymds, + nwrite_dates + ); + + if (write_count != mNtc_NWRITE_NUM) { + mNtc_set_auto_nwrite(write_count, set_nwrite_nums, set_nwrite_years, fishing_day, nwrite_ymds, nwrite_dates); + } + else { + if (Common_Get(buried_treasure_flag) == FALSE) { + mNtc_check_treasure(); + } + } + + mNtc_set_near_old_nwrite_data(&rtc_time, &nwrite_year, &nwrite_num); + + Common_Set(auto_nwrite_year, nwrite_year); + Common_Set(auto_nwrite_count, nwrite_num); + Common_Set(auto_nwrite_set, TRUE); + Common_Set(auto_nwrite_time, Common_Get(time.rtc_time)); + Save_Set(saved_auto_nwrite_time, Common_Get(time.rtc_time)); + mFR_fishmail(); /* send fishing tourney result mail */ + Common_Set(buried_treasure_flag, TRUE); + lbRTC_TimeCopy(Save_GetPointer(treasure_checked_time), &rtc_time); + } + } +}