From a45d97d09e7abfad7a8e8ccbf88cc0be0ea46a28 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Tue, 7 Nov 2023 22:30:33 -0500 Subject: [PATCH] Implement & link m_island.c, link m_land.c --- config/rel_disasm_overrides.yml | 3 +- config/rel_slices.yml | 8 + include/libjsys/jsyswrapper.h | 111 +++-- include/m_common_data.h | 4 +- include/m_island.h | 136 +++++ include/m_name_table.h | 21 + rel/m_island.c | 844 ++++++++++++++++++++++++++++++++ rel/m_land.c | 7 +- rel/m_npc.c | 5 + rel/m_random_field.c | 4 +- 10 files changed, 1103 insertions(+), 40 deletions(-) create mode 100644 rel/m_island.c diff --git a/config/rel_disasm_overrides.yml b/config/rel_disasm_overrides.yml index bc416a6c..e376c805 100644 --- a/config/rel_disasm_overrides.yml +++ b/config/rel_disasm_overrides.yml @@ -10,4 +10,5 @@ symbol_aligns: 0x80C78B20: 32 # mFM_grd_s_cliff_tex 0x80F8C460: 32 # mFM_grd_s_rail_tex 0x80657200: 32 # .data msg.o - 0x81297E80: 32 # .bss msg.o \ No newline at end of file + 0x81297E80: 32 # .bss msg.o + 0x81296140: 32 # .bss m_island.o \ No newline at end of file diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 885a58f9..b01987f3 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -127,6 +127,14 @@ m_home.c: .data: [0x806546C8, 0x80655340] m_house.c: .text: [0x803B3688, 0x803B3880] +m_land.c: + .text: [0x803B3880, 0x803B3CB8] + .rodata: [0x80642478, 0x80642480] + .bss: [0x81296128, 0x81296140] +m_island.c: + .text: [0x803B3CB8, 0x803B5A68] + .data: [0x80655340, 0x80655388] + .bss: [0x81296140, 0x81297A68] m_item_name.c: .text: [0x803B5A68, 0x803B5CC4] .data: [0x80655388, 0x80655D48] diff --git a/include/libjsys/jsyswrapper.h b/include/libjsys/jsyswrapper.h index be1ab21e..24d6e313 100644 --- a/include/libjsys/jsyswrapper.h +++ b/include/libjsys/jsyswrapper.h @@ -10,39 +10,84 @@ extern "C" { #endif enum resource_index { - /* TODO: finish */ - RESOURCE_FGDATA = 0, - RESOURCE_MAIL = 1, - RESOURCE_MAIL_TABLE = 2, - RESOURCE_MAILA = 3, - RESOURCE_MAILA_TABLE = 4, - RESOURCE_MAILB = 5, - RESOURCE_MAILB_TABLE = 6, - RESOURCE_MAILC = 7, - RESOURCE_MAILC_TABLE = 8, - RESOURCE_PALLET_BOY = 9, - RESOURCE_PS = 10, - RESOURCE_PS_TABLE = 11, - RESOURCE_PSZ = 12, - RESOURCE_PSZ_TABLE = 13, - RESOURCE_SELECT = 14, - RESOURCE_SELECT_TABLE = 15, - RESOURCE_STRING = 16, - RESOURCE_STRING_TABLE = 17, - RESOURCE_SUPERZ = 18, - RESOURCE_SUPERZ_TABLE = 19, - RESOURCE_SUPER = 20, - RESOURCE_SUPER_TABLE = 21, - RESOURCE_TEX_BOY = 22, - RESOURCE_FACE_BOY = 23, - RESOURCE_FGNPCDATA = 24, - RESOURCE_MESSAGE = 25, - RESOURCE_MESSAGE_TABLE = 26, - RESOURCE_MY_ORIGINAL = 27, - RESOURCE_NEEDLEWORK_JOYBOOT = 28, - RESOURCE_PLAYER_ROOM_FLOOR = 29, - RESOURCE_PLAYER_ROOM_WALL = 30, - RESOURCE_NPC_NAME_STR_TABLE = 31, + RESOURCE_FGDATA, + RESOURCE_MAIL, + RESOURCE_MAIL_TABLE, + RESOURCE_MAILA, + RESOURCE_MAILA_TABLE, + RESOURCE_MAILB, + RESOURCE_MAILB_TABLE, + RESOURCE_MAILC, + RESOURCE_MAILC_TABLE, + RESOURCE_PALLET_BOY, + RESOURCE_PS, + RESOURCE_PS_TABLE, + RESOURCE_PSZ, + RESOURCE_PSZ_TABLE, + RESOURCE_SELECT, + RESOURCE_SELECT_TABLE, + RESOURCE_STRING, + RESOURCE_STRING_TABLE, + RESOURCE_SUPERZ, + RESOURCE_SUPERZ_TABLE, + RESOURCE_SUPER, + RESOURCE_SUPER_TABLE, + RESOURCE_TEX_BOY, + RESOURCE_FACE_BOY, + RESOURCE_FGNPCDATA, + RESOURCE_MESSAGE, + RESOURCE_MESSAGE_TABLE, + RESOURCE_MY_ORIGINAL, + RESOURCE_NEEDLEWORK_JOYBOOT, + RESOURCE_PLAYER_ROOM_FLOOR, + RESOURCE_PLAYER_ROOM_WALL, + RESOURCE_NPC_NAME_STR_TABLE, + RESOURCE_D_OBJ_NPC_STOCK_SCH, + RESOURCE_D_OBJ_NPC_STOCK_SCL, + RESOURCE_TITLE, + RESOURCE_MURA_SPRING, + RESOURCE_MURA_SUMMER, + RESOURCE_MURA_FALL, + RESOURCE_MURA_WINTER, + RESOURCE_ODEKAKE, + RESOURCE_OMAKE, + RESOURCE_EKI1, + RESOURCE_EKI1_2, + RESOURCE_EKI1_3, + RESOURCE_EKI1_4, + RESOURCE_EKI1_5, + RESOURCE_EKI2, + RESOURCE_EKI2_2, + RESOURCE_EKI2_3, + RESOURCE_EKI2_4, + RESOURCE_EKI2_5, + RESOURCE_EKI3, + RESOURCE_EKI3_2, + RESOURCE_EKI3_3, + RESOURCE_EKI3_4, + RESOURCE_EKI3_5, + RESOURCE_TEGAMI, + RESOURCE_TEGAMI2, + RESOURCE_FAMIKON, + RESOURCE_BOY1, + RESOURCE_BOY2, + RESOURCE_BOY3, + RESOURCE_BOY4, + RESOURCE_BOY5, + RESOURCE_BOY6, + RESOURCE_BOY7, + RESOURCE_BOY8, + RESOURCE_GIRL11, + RESOURCE_GIRL12, + RESOURCE_GIRL13, + RESOURCE_GIRL14, + RESOURCE_GIRL15, + RESOURCE_GIRL16, + RESOURCE_GIRL17, + RESOURCE_GIRL18, + RESOURCE_D_BG_ISLAND_SCH, + + RESOURCE_NUM }; extern void JW_Init(); diff --git a/include/m_common_data.h b/include/m_common_data.h index d612fdf1..93d7505e 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -285,7 +285,9 @@ typedef struct common_data_s { /* 0x0288A0 */ u8 pad_connected; /* is gamepad 0 connected? */ /* 0x0288A1 */ u8 unk288A1; /* 0x0288A2 */ s16 current_sound_effect; - /* 0x0288A4 */ u8 _288a4[0x02DB40 - 0x0288A4]; + /* 0x0288A4 */ u8 _288a4[0x0288C0 - 0x0288A4]; + /* 0x0288C0 */ Island_c transfer_island; /* used when transferring islands with the GBA */ + /* 0x02A1C0 */ Island_agb_c agb_island; /* converted island data sent over to the GBA */ /* 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. */ /* 0x02DB42 */ u16 select_last_select_no; /* 0x02DB44 */ u16 select_last_top_no; diff --git a/include/m_island.h b/include/m_island.h index 54cc5a75..3eddea0a 100644 --- a/include/m_island.h +++ b/include/m_island.h @@ -50,7 +50,143 @@ typedef struct island_s { } Island_c; extern void mISL_ClearKeepIsland(); +extern void mISL_KeepIsland(Island_c* island); +extern void mISL_ChangeBG(); +extern void mISL_RestoreIsland(); extern void mISL_init(Island_c* island); +extern void mISL_ClearNowPlayerAction(); +extern void mISL_SetPlayerAction(PersonalID_c* pid, u32 action); +extern void mISL_SetNowPlayerAction(u32 action); +extern int mISL_CheckPlayerAction(PersonalID_c* pid, u32 action); +extern int mISL_CheckNowPlayerAction(u32 action); + +/* NOTE: a lot of these seem to be padded to 4-bytes and should be redone in the future */ + +typedef struct agb_landinfo_s { + u8 name[LAND_NAME_SIZE]; + s8 exists; + u16 id; +} mISL_landinfo_agb_c; + +typedef struct agb_floor_s { + /* 0x000 */ mHm_lyr_c layers[mHm_LAYER_NUM]; + /* 0x8A0 */ mHm_wf_c wall_floor; + /* 0x8A2 */ u16 pad_8A2; + /* 0x8A4 */ TempoBeat_c tempo_beat; + /* 0x8A8 */ u32 floor_bit_info; +} mISL_flr_agb_c; + +typedef struct agb_cottage_s { + /* 0x000 */ mHm_wf_c unused_wall_floor; /* Has wallpaper & flooring bounds checks in sChk_CheckSaveData_Cattage */ + /* 0x002 */ u8 pad_2[2]; + /* 0x004 */ u8 unk_2[2]; /* struct/array that is two bytes long, maybe another wall floor? */ + /* 0x008 */ mISL_flr_agb_c room; /* Cottage room */ + /* 0x8B8 */ u8 unk_8B8; // unk_4 + /* 0x8B9 */ u8 unk_8B9; // unk_5 + /* 0x8BA */ u8 pad_8BA; + /* 0x8BB */ u8 pad_8BB; + /* 0x8BC */ mHm_goki_c goki; /* Cottage cockroaches */ + /* 0x8C8 */ u32 pad_8C8; + /* 0x8CC */ u32 music_box[2]; /* Cottage music storage... separate from main home? */ +} mISL_cottage_agb_c; + +typedef struct agb_anmplayermail_s { + /* 0x000 */ u8 font; /* 'font' to use for letter info */ + /* 0x001 */ u8 paper_type; + /* 0x002 */ mActor_name_t present; + /* 0x004 */ u8 header_back_start; /* position for name insertion in header */ + /* 0x005 */ u8 pad_5[3]; /* likely pad */ + /* 0x008 */ u8 header[MAIL_HEADER_LEN]; + /* 0x020 */ u8 body[MAIL_BODY_LEN]; + /* 0x0E0 */ u8 footer[MAIL_FOOTER_LEN]; + /* 0x100 */ lbRTC_ymd_c date; /* sent date */ +} mISL_Anmplmail_agb_c; + +typedef struct agb_anmmem_s { + PersonalID_c player_id; + lbRTC_time_c last_speak_time; + memuni_u memuni; + u64 saved_town_tune; + s8 friendship; + u32 letter_info; + mISL_Anmplmail_agb_c letter; +} mISL_Anmmem_agb_c; + +typedef struct agb_quest_base_s { + /* 0x00 */ u32 info; + /* 0x04 */ lbRTC_time_c time_limit; +} mISL_quest_base_c; + +typedef struct agb_quest_contest_s { + /* 0x00 */ mISL_quest_base_c base; /* quest base struct */ + /* 0x0C */ mActor_name_t requested_item; /* item (if any) requested by the villager */ + /* 0x0E */ u8 pad_0E[2]; + /* 0x10 */ PersonalID_c player_id; /* personal id of the player */ + /* 0x24 */ s8 type; /* type of quest, seems to be repeat of data in quest base */ + /* 0x25 */ u8 pad_25[3]; + /* 0x28 */ mQst_contest_info_u info; /* contest info for flower & letter quests */ +} mISL_quest_contest_c; + +typedef struct agb_animal_s { + /* 0x000 */ AnmPersonalID_c id; /* this villager's ID */ + /* 0x010 */ mISL_Anmmem_agb_c memories[ANIMAL_MEMORY_NUM]; /* memories of players who've spoken to this villager */ + /* 0x8D0 */ Anmhome_c home_info; /* home position info */ + /* 0x8D5 */ u8 pad_8D5[3]; + /* 0x8D8 */ u8 catchphrase[ANIMAL_CATCHPHRASE_LEN]; /* may be called 'word_ending' */ + /* 0x8E2 */ u8 pad_8E2[2]; + /* 0x8E4 */ mISL_quest_contest_c contest_quest; /* current contest quest information */ + /* 0x910 */ u8 parent_name[PLAYER_NAME_LEN]; /* name of the player who 'spawned' the villager in, unsure why this is tracked */ + /* 0x918 */ u8 pad_918[4]; + /* 0x91C */ anmuni_u anmuni; /* name of the last town the villager lived in or saved island ftr */ + /* 0x924 */ u8 pad_924[4]; /* may include last_land_id */ + /* 0x928 */ u8 mood; /* probably called 'feel' based on code */ + /* 0x929 */ u8 mood_time; /* probably called 'feel_tim' based on code */ + /* 0x92A */ mActor_name_t cloth; /* shirt the villager is wearing */ + /* 0x92C */ u16 remove_info; /* info about villager moving between towns? kinda stubbed */ + /* 0x92D */ u8 is_home; /* TRUE when the villager is home, otherwise FALSE */ + /* 0x92E */ u8 moved_in; /* TRUE when the villager moved in after town creation, FALSE if they started out in town */ + /* 0x92F */ u8 removing; /* TRUE when the villager is leaving town, FALSE otherwise */ + /* 0x930 */ u8 cloth_original_id; /* 0xFF when not wearing an Able Sister's pattern, otherwise 0-3 indicating which pattern */ + /* 0x931 */ s8 umbrella_id; /* 0xFF when no umbrella, 0-31 when a standard umbrella, 32-35 when using an Able Sister's pattern + /* 0x932 */ u8 unk_932; /* Exists according to mISL_gc_to_agb_animal, but seems unused in practice */ + /* 0x934 */ mActor_name_t present_cloth; /* The most recently received shirt from a letter which the villager may change into */ + /* 0x936 */ u8 pad_936[6]; + /* 0x93C */ u8 animal_relations[ANIMAL_NUM_MAX]; /* relationships between all villagers in town, starts at 128 which is neutral */ + /* 0x94B */ u8 pad_94B[5]; + /* 0x950 */ AnmHPMail_c hp_mail[ANIMAL_HP_MAIL_NUM]; /* mail password info storage */ + /* 0x9C0 */ u8 _9C0[24]; /* unknown usage/unused */ +} mISL_Animal_agb_c; + +typedef struct island_agb_s { + /* 0x0000 */ u8 _0000[8]; + /* 0x0008 */ u8 name[mISL_ISLAND_NAME_LEN]; /* island name */ + /* 0x0010 */ u8 grass_tex_type; /* grass type */ + /* 0x0011 */ u8 _0011[2]; + /* 0x0013 */ u8 _0013; + /* 0x0014 */ mISL_landinfo_agb_c landinfo; /* land info for town */ + /* 0x0020 */ u8 _0020[4]; + /* 0x0024 */ mFM_fg_c fgblock[mISL_FG_BLOCK_Z_NUM][mISL_FG_BLOCK_X_NUM]; /* island item actor data */ + /* 0x0424 */ u8 _0424[4]; + /* 0x0428 */ mISL_cottage_agb_c cottage; /* player shared cottage data */ + /* 0x0D00 */ mNW_original_design_c flag_design; /* island flag design */ + /* 0x0F20 */ mISL_Animal_agb_c animal; /* islander info */ + /* 0x18F8 */ u16 deposit[mISL_FG_BLOCK_X_NUM * mISL_FG_BLOCK_Z_NUM][UT_Z_NUM]; /* buried item bitfield */ + /* 0x1938 */ u8 bg_data[mISL_ISLAND_BLOCK_NUM]; /* island acre ids */ + /* 0x193A */ u8 weather; + /* 0x193C */ lbRTC_time_c renew_time; /* last time island was visited? */ + /* 0x1944 */ int npc_idx; + /* 0x1948 */ u32 earth_tex[1024]; + /* 0x2948 */ u32 npc_tex[1024]; + /* 0x3948 */ u16 npc_pal[16]; + /* 0x3968 */ u8 _3968[20]; + /* 0x397C */ u8 _397C; + /* 0x397D */ u8 last_song_male; /* last song kapp'n sang for a male character */ + /* 0x397E */ u8 last_song_female; /* last song kapp'n sang for a female character */ + /* 0x397F */ u8 checksum; +} Island_agb_c; + +extern void mISL_gc_to_agb(Island_agb_c* agb, Island_c* gc); +extern void mISL_agb_to_gc(Island_c* gc, Island_agb_c* agb); #ifdef __cplusplus } diff --git a/include/m_name_table.h b/include/m_name_table.h index ab6f5434..78be918a 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -1648,6 +1648,27 @@ extern mActor_name_t mNT_FishIdx2FishItemNo(int idx); #define NPC_TYBALT 0xE0B6 #define NPC_LOBO 0xE0B9 #define NPC_BIFF 0xE0C2 +#define NPC_MAELLE (NPC_START + 216) +#define NPC_OHARE (NPC_START + 217) +#define NPC_BLISS (NPC_START + 218) +#define NPC_DRIFT (NPC_START + 219) +#define NPC_BUD (NPC_START + 220) +#define NPC_BOOMER (NPC_START + 221) +#define NPC_ELINA (NPC_START + 222) +#define NPC_FLASH (NPC_START + 223) +#define NPC_DOBIE (NPC_START + 224) +#define NPC_FLOSSIE (NPC_START + 225) +#define NPC_ANNALISE (NPC_START + 226) +#define NPC_PLUCKY (NPC_START + 227) +#define NPC_FAITH (NPC_START + 228) +#define NPC_YODEL (NPC_START + 229) +#define NPC_ROWAN (NPC_START + 230) +#define NPC_JUNE (NPC_START + 231) +#define NPC_CHERI (NPC_START + 232) +#define NPC_PIGLEG (NPC_START + 233) +#define NPC_ANKHA (NPC_START + 234) +#define NPC_PUNCHY (NPC_START + 235) +#define NPC_END (NPC_START + 236) #define DUMMY_START 0xF000 #define DUMMY_RESERVE 0xF0EE // unsure about this, only true in DnM diff --git a/rel/m_island.c b/rel/m_island.c new file mode 100644 index 00000000..69b05844 --- /dev/null +++ b/rel/m_island.c @@ -0,0 +1,844 @@ +#include "m_island.h" + +#include "m_field_info.h" +#include "m_common_data.h" +#include "m_random_field.h" +#include "m_malloc.h" +#include "libultra/libultra.h" +#include "libjsys/jsyswrapper.h" + +static Island_c l_keepIsland; +static u16 l_keepIslandComb[mISL_FG_BLOCK_X_NUM * mISL_FG_BLOCK_Z_NUM]; + +static u8 l_misl_count_max_table[32] = { + 10, + 4, + 1, + 10, + 1, + 5, + 3, + 10, + 5, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 +}; + +static u8 l_misl_count_table[32]; + +extern void mISL_ClearKeepIsland() { + bzero(&l_keepIsland, sizeof(l_keepIsland)); +} + +extern void mISL_KeepIsland(Island_c* island) { + if (mLd_CheckThisLand(island->landinfo.name, island->landinfo.id) == TRUE) { + bcopy(island, &l_keepIsland, sizeof(l_keepIsland)); + } +} + +static void mISL_KeepIslandComb(u16* dst, mFM_combination_c* combi, int count) { + while (count != 0 && dst != NULL && combi != NULL) { + count--; + dst[0] = combi[0].combination_type; + dst++; + combi++; + } +} + +static void mISL_RestoreIslandComb_com(mFM_combination_c* combi, u16* src, int count) { + while (count != 0 && src != NULL && combi != NULL) { + count--; + combi[0].combination_type = *src; + combi++; + src++; + } +} + +static void mISL_RestoreIslandComb() { + int island_x_blocks[mISL_FG_BLOCK_X_NUM]; + + mFI_GetIslandBlockNumX(island_x_blocks); + + if (island_x_blocks[0] > 0 && island_x_blocks[1] < (BLOCK_X_NUM - 1)) { + mISL_RestoreIslandComb_com(Save_GetPointer(combi_table[mISL_BLOCK_Z][island_x_blocks[0]]), l_keepIslandComb, mISL_FG_BLOCK_X_NUM); + } +} + +extern void mISL_ChangeBG() { + int island_x_blocks[mISL_FG_BLOCK_X_NUM]; + + mFI_GetIslandBlockNumX(island_x_blocks); + + if (island_x_blocks[0] > 0 && island_x_blocks[1] < (BLOCK_X_NUM - 1)) { + mISL_KeepIslandComb(l_keepIslandComb, Save_GetPointer(combi_table[mISL_BLOCK_Z][island_x_blocks[0]]), mISL_FG_BLOCK_X_NUM); + mRF_IslandBgData_To_VillageData(); + mFM_RestoreIslandBG(island_x_blocks, mISL_FG_BLOCK_X_NUM); + } +} + +extern void mISL_RestoreIsland() { + Island_c* island = Save_GetPointer(island); + Island_c* keep_island = &l_keepIsland; + + if (mLd_CheckThisLand(island->landinfo.name, island->landinfo.id) == FALSE) { + bcopy(keep_island, island, sizeof(l_keepIsland)); + mISL_RestoreIslandComb(); + } + else { + bcopy(island, keep_island, sizeof(l_keepIsland)); + } +} + +extern void mISL_init(Island_c* island) { + mLd_ClearLandName(island->name); + bcopy(Save_GetPointer(land_info), &island->landinfo, sizeof(mLd_land_info_c)); + mHm_InitCottage(&island->cottage); + mNpc_DecideIslandNpc(&island->animal); + Save_Get(island).grass_tex_type = Save_Get(bg_tex_idx); +} + +static u32* mISL_GetCheckP(PersonalID_c* pid) { + Anmmem_c* memory = Save_Get(island).animal.memories; + u32* check_p = NULL; + + if (pid != NULL && mPr_NullCheckPersonalID(pid) == FALSE) { + int idx = mNpc_GetAnimalMemoryIdx(pid, memory, ANIMAL_MEMORY_NUM); + + if (idx != -1) { + check_p = &memory[idx].memuni.island.check; + } + } + + return check_p; +} + +extern void mISL_ClearNowPlayerAction() { + Private_c* priv = Common_Get(now_private); + + if (priv != NULL) { + u32* check_p = mISL_GetCheckP(&priv->player_ID); + + if (check_p != NULL) { + check_p[0] = 0; + } + + bzero(l_misl_count_table, sizeof(l_misl_count_table)); + } +} + +extern void mISL_SetPlayerAction(PersonalID_c* pid, u32 action) { + if (pid != NULL && mFI_CheckInIsland() == TRUE) { + u32* check_p = mISL_GetCheckP(pid); + + if (check_p != NULL) { + int i; + + for (i = 0; i < ARRAY_COUNT(l_misl_count_table); i++) { + if (((action >> i) & 1) != 0) { + l_misl_count_table[i]++; + } + + if (l_misl_count_max_table[i] <= l_misl_count_table[i]) { + check_p[0] |= (1 << i); + l_misl_count_table[i] = l_misl_count_max_table[i]; + } + } + } + } +} + +extern void mISL_SetNowPlayerAction(u32 action) { + Private_c* priv = Common_Get(now_private); + + if (priv != NULL) { + mISL_SetPlayerAction(&priv->player_ID, action); + } +} + +extern int mISL_CheckPlayerAction(PersonalID_c* pid, u32 action) { + int res = FALSE; + + if (pid != NULL) { + u32* check_p = mISL_GetCheckP(pid); + + if (check_p != NULL && (check_p[0] & action) != 0) { + res = TRUE; + } + } + + return res; +} + +extern int mISL_CheckNowPlayerAction(u32 action) { + Private_c* priv = Common_Get(now_private); + int res = FALSE; + + if (priv != NULL) { + res = mISL_CheckPlayerAction(&priv->player_ID, action); + } + + return res; +} + +static void mISL_int(u32* dst, u32* src, int n) { + int i; + + for (i = n; i != 0; i--) { + u32 v = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00) << 8) | ((src[0] >> 8) & 0xFF00) | ((src[0] >> 24) & 0xFF); + src++; + *dst++ = v; + } +} + +static void mISL_short(register u16* dst, register u16* src, register int n) { + int i; + + for (i = n; i != 0; i--) { + u16 v = ((src[0] & 0xFF) << 8 ) | ((src[0] & 0xFF00) >> 8); + src++; + *dst++ = v; + } +} + +static void mISL_u64(u64* dst, u64* src, int n) { + int i; + + for (i = n; i != 0; i--) { + u32 src_hi; + u32 src_lo; + u32 dst_lo; + u32 dst_hi; + + src_hi = (u32)((src[0] >> 32) & 0xFFFFFFFF); + src_lo = (u32)(src[0] & 0xFFFFFFFF); + + mISL_int(&dst_lo, &src_hi, 1); + mISL_int(&dst_hi, &src_lo, 1); + + *dst = (((u64)dst_hi) << 32) | (u64)dst_lo; + + src++; + dst++; + } +} + +static mActor_name_t l_misl_agb_npc_table[NPC_ISLANDER_NUM] = { + NPC_BLISS, + NPC_DOBIE, + NPC_OHARE, + NPC_DRIFT, + NPC_JUNE, + NPC_FAITH, + NPC_FLOSSIE, + NPC_FLASH, + NPC_MAELLE, + NPC_ANNALISE, + NPC_BUD, + NPC_ELINA, + NPC_BOOMER, + NPC_PIGLEG, + NPC_YODEL, + NPC_PLUCKY, + NPC_ROWAN, + NPC_ANKHA +}; + +static int mISL_get_npc_idx(mActor_name_t npc_id) { + mActor_name_t* agb_npc_table_p = l_misl_agb_npc_table; + int res = 0; + int i; + + if (ITEM_NAME_GET_TYPE(npc_id) == NAME_TYPE_NPC) { + for (i = 0; i < NPC_ISLANDER_NUM; i++) { + if (*agb_npc_table_p == npc_id) { + res = i; + break; + } + + agb_npc_table_p++; + } + } + + return res; +} + +static void mISL_get_npc_tex(u32* dst, u32* src, int idx) { + if (idx != -1 && dst != NULL && src != NULL) { + u32 base_addr = JW_GetAramAddress(RESOURCE_D_OBJ_NPC_STOCK_SCH); + + _JW_GetResourceAram(base_addr + idx * (1024 * sizeof(u32)), (u8*)src, 1024 * sizeof(u32)); + mISL_int(dst, src, 1024); + } +} + +static void mISL_get_npc_pal(u16* dst, u16* src, int idx) { + if (idx != -1 && dst != NULL && src != NULL) { + u32 base_addr = JW_GetAramAddress(RESOURCE_D_OBJ_NPC_STOCK_SCL); + + _JW_GetResourceAram(base_addr + idx * (16 * sizeof(u16)), (u8*)src, 16 * sizeof(u16)); + mISL_short(dst, src, 16); + } +} + +static void mISL_get_earth_tex(u32* dst, u32* src, int idx) { + if (idx < mFM_BG_TEX_NUM && dst != NULL && src != NULL) { + u32 base_addr = JW_GetAramAddress(RESOURCE_D_BG_ISLAND_SCH); + + _JW_GetResourceAram(base_addr + idx * (1024 * sizeof(u32)), (u8*)src, 1024 * sizeof(u32)); + mISL_int(dst, src, 1024); + } +} + +static void mISL_gc_to_agb_iandinfo(mISL_landinfo_agb_c* agb, mLd_land_info_c* gc) { + bcopy(gc->name, agb->name, LAND_NAME_SIZE); + agb->exists = gc->exists; + mISL_short(&agb->id, &gc->id, 1); +} + +static void mISL_agb_to_gc_iandinfo(mLd_land_info_c* gc, mISL_landinfo_agb_c* agb) { + bcopy(agb->name, gc->name, LAND_NAME_SIZE); + gc->exists = agb->exists; + mISL_short(&gc->id, &agb->id, 1); +} + +static void mISL_gc_to_agb_fg(mActor_name_t* agb, mActor_name_t* gc) { + mISL_short(agb, gc, UT_TOTAL_NUM); +} + +static void mISL_gc_to_agb_fg2(mActor_name_t* agb, mActor_name_t* gc) { + int i; + + for (i = 0; i < UT_TOTAL_NUM; i++) { + mActor_name_t item; + + if (*gc == 0xF123) { + item = COTTAGE_MY; + } + else if (*gc == 0xF124) { + item = COTTAGE_NPC; + } + else if (*gc == 0xF122) { + item = FLAG; + } + else if (*gc == 0xF128) { + item = BOAT; + } + else if (*gc >= HOLE_START && *gc <= HOLE_END) { + item = EMPTY_NO; + } + else if (*gc == 0xF11F) { + item = ACTOR_PROP_VILLAGER_SIGNBOARD; + } + else { + item = *gc; + } + + + mISL_short(agb, &item, 1); + agb++; + gc++; + } +} + +static void mISL_agb_to_gc_fg(mActor_name_t* gc, mActor_name_t* agb) { + mISL_short(gc, agb, UT_TOTAL_NUM); +} + +static void mISL_gc_to_agb_fgblock(mFM_fg_c* agb, mFM_fg_c* gc) { + int i; + + for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { + mISL_gc_to_agb_fg2(agb->items[0], gc->items[0]); + agb++; + gc++; + } +} + +static void mISL_agb_to_gc_fgblock(mFM_fg_c* gc, mFM_fg_c* agb) { + int i; + + for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { + mISL_agb_to_gc_fg(gc->items[0], agb->items[0]); + agb++; + gc++; + } +} + +static void mISL_gc_to_agb_layer(mHm_lyr_c* agb, mHm_lyr_c* gc) { + int i; + + for (i = 0; i < mHm_LAYER_NUM; i++) { + mISL_gc_to_agb_fg(agb->items[0], gc->items[0]); + mISL_u64(&agb->ftr_switch, &gc->ftr_switch, 1); + mISL_int(agb->unk_208, gc->unk_208, ARRAY_COUNT(agb->unk_208)); + + agb++; + gc++; + } +} + +static void mISL_gc_to_agb_fllot_bit(u32* agb, mHm_fllot_bit_c* gc) { + mHm_fllot_bit_c tmp[4]; + + bzero(tmp, sizeof(tmp)); + tmp[0].wall_original = gc->wall_original; + tmp[0].floor_original = gc->floor_original; + mISL_int(agb, (u32*)tmp, 1); +} + +static void mISL_agb_to_gc_fllot_bit(mHm_fllot_bit_c* gc, u32* agb) { + mHm_fllot_bit_c tmp[4]; + + bzero(tmp, sizeof(tmp)); + mISL_int((u32*)tmp, agb, 1); + + /* @BUG - devs made an oopsie and reused GC here */ + #ifndef BUGFIXES + gc->wall_original = (u32)gc->wall_original; + gc->floor_original = (u32)gc->floor_original; + #else + gc->wall_original = agb->wall_original; + gc->floor_original = agb->floor_original; + #endif +} + +static void mISL_gc_to_agb_cottage_floor(mISL_flr_agb_c* agb, mHm_flr_c* gc) { + mISL_gc_to_agb_layer(agb->layers, &gc->layer_main); + bcopy(&gc->wall_floor, &agb->wall_floor, sizeof(gc->wall_floor)); + bcopy(&gc->tempo_beat, &agb->tempo_beat, sizeof(gc->tempo_beat)); + mISL_gc_to_agb_fllot_bit(&agb->floor_bit_info, &gc->floor_bit_info); +} + +static void mISL_agb_to_gc_cottage_floor(mHm_flr_c* gc, mISL_flr_agb_c* agb) { + mISL_gc_to_agb_layer(&gc->layer_main, agb->layers); + bcopy(&agb->wall_floor, &gc->wall_floor, sizeof(gc->wall_floor)); + bcopy(&agb->tempo_beat, &gc->tempo_beat, sizeof(gc->tempo_beat)); + mISL_agb_to_gc_fllot_bit(&gc->floor_bit_info, &agb->floor_bit_info); +} + +static void mISL_gc_to_agb_ymd(lbRTC_ymd_c* agb, lbRTC_ymd_c* gc) { + mISL_short(&agb->year, &gc->year, 1); + agb->month = gc->month; + agb->day = gc->day; +} + +static void mISL_gc_to_agb_time(lbRTC_time_c* agb, lbRTC_time_c* gc) { + agb->sec = gc->sec; + agb->min = gc->min; + agb->hour = gc->hour; + agb->day = gc->day; + agb->weekday = gc->weekday; + agb->month = gc->month; + mISL_short(&agb->year, &gc->year, 1); +} + +static void mISL_gc_to_agb_goki(mHm_goki_c* agb, mHm_goki_c* gc) { + mISL_gc_to_agb_time(&agb->time, &gc->time); + agb->num = gc->num; +} + +static void mISL_agb_to_gc_goki(mHm_goki_c* gc, mHm_goki_c* agb) { + mISL_gc_to_agb_time(&gc->time, &agb->time); + gc->num = agb->num; +} + +static void mISL_gc_to_agb_cottage(mISL_cottage_agb_c* agb, mHm_cottage_c* gc) { + bcopy(&gc->unused_wall_floor, &agb->unused_wall_floor, sizeof(gc->unused_wall_floor)); + bcopy(gc->unk_2, agb->unk_2, sizeof(gc->unk_2)); + mISL_gc_to_agb_cottage_floor(&agb->room, &gc->room); + agb->unk_8B8 = gc->unk_4; + agb->unk_8B9 = gc->unk_5; + mISL_gc_to_agb_goki(&agb->goki, &gc->goki); + mISL_int(agb->music_box, gc->music_box, 2); +} + +static void mISL_agb_to_gc_cottage(mHm_cottage_c* gc, mISL_cottage_agb_c* agb) { + bcopy(&agb->unused_wall_floor, &gc->unused_wall_floor, sizeof(gc->unused_wall_floor)); + bcopy(agb->unk_2, gc->unk_2, sizeof(gc->unk_2)); + gc->unk_4 = agb->unk_8B8; + gc->unk_5 = agb->unk_8B9; + mISL_agb_to_gc_cottage_floor(&gc->room, &agb->room); + mISL_agb_to_gc_goki(&gc->goki, &agb->goki); + mISL_int(gc->music_box, agb->music_box, 2); +} + +static void mISL_gc_to_agb_mail(mISL_Anmplmail_agb_c* agb, Anmplmail_c* gc) { + agb->font = gc->font; + agb->paper_type = gc->paper_type; + agb->present = gc->present; + agb->header_back_start = gc->header_back_start; + bcopy(gc->header, agb->header, MAIL_HEADER_LEN); + bcopy(gc->body, agb->body, MAIL_BODY_LEN); + bcopy(gc->footer, agb->footer, MAIL_FOOTER_LEN); + mISL_gc_to_agb_ymd(&agb->date, &gc->date); +} + +static void mISL_agb_to_gc_mail(Anmplmail_c* gc, mISL_Anmplmail_agb_c* agb) { + gc->font = agb->font; + gc->paper_type = agb->paper_type; + gc->present = agb->present; + gc->header_back_start = agb->header_back_start; + bcopy(agb->header, gc->header, MAIL_HEADER_LEN); + bcopy(agb->body, gc->body, MAIL_BODY_LEN); + bcopy(agb->footer, gc->footer, MAIL_FOOTER_LEN); + mISL_gc_to_agb_ymd(&gc->date, &agb->date); +} + +static void mIS_gc_to_agb_anmpersonal(AnmPersonalID_c* agb, AnmPersonalID_c* gc) { + mISL_short(&agb->npc_id, &gc->npc_id, 1); + mISL_short(&agb->land_id, &gc->land_id, 1); + bcopy(gc->land_name, agb->land_name, LAND_NAME_SIZE); + agb->name_id = gc->name_id; + agb->looks = gc->looks; +} + +static void mIS_agb_to_gc_anmpersonal(AnmPersonalID_c* gc, AnmPersonalID_c* agb) { + mISL_short(&gc->npc_id, &agb->npc_id, 1); + mISL_short(&gc->land_id, &agb->land_id, 1); + bcopy(agb->land_name, gc->land_name, LAND_NAME_SIZE); + gc->name_id = agb->name_id; + gc->looks = agb->looks; +} + +static void mISL_gc_to_agb_personal(PersonalID_c* agb, PersonalID_c* gc) { + bcopy(gc->player_name, agb->player_name, PLAYER_NAME_LEN); + bcopy(gc->land_name, agb->land_name, LAND_NAME_SIZE); + mISL_short(&agb->player_id, &gc->player_id, 1); + mISL_short(&agb->land_id, &gc->land_id, 1); +} + +static void mISL_gc_to_agb_memuni(memuni_u* agb, memuni_u* gc) { + mISL_int((u32*)agb, (u32*)gc, sizeof(memuni_u) / sizeof(u32)); +} + +static void mISL_agb_to_gc_memuni(memuni_u* gc, memuni_u* agb) { + mISL_int((u32*)gc, (u32*)agb, sizeof(memuni_u) / sizeof(u32)); +} + +static void mISL_gc_to_agb_memletter(u32* agb, Anmlet_c* gc) { + Anmlet_c t[4]; + + bzero(t, sizeof(t)); + t[0].exists = gc->exists; + t[0].cond = gc->cond; + t[0].send_reply = gc->send_reply; + t[0].has_present_cloth = gc->has_present_cloth; + t[0].wearing_present_cloth = gc->wearing_present_cloth; + mISL_int(agb, (u32*)t, 1); +} + +static void mISL_agb_to_gc_memletter(Anmlet_c* gc, u32* agb) { + Anmlet_c t[4]; + + bzero(t, sizeof(t)); + mISL_int((u32*)t, agb, 1); + gc->exists = t[0].exists; + gc->cond = t[0].cond; + gc->send_reply = t[0].send_reply; + gc->has_present_cloth = t[0].has_present_cloth; + gc->wearing_present_cloth = t[0].wearing_present_cloth; +} + +static void mISL_gc_to_agb_memory(mISL_Anmmem_agb_c* agb, Anmmem_c* gc) { + mISL_gc_to_agb_personal(&agb->player_id, &gc->memory_player_id); + mISL_gc_to_agb_time(&agb->last_speak_time, &gc->last_speak_time); + mISL_gc_to_agb_memuni(&agb->memuni, &gc->memuni); + /* @BUG - devs forgot to save this, but remembered to restore it */ + #ifdef BUGFIXES + mISL_u64(&agb->saved_town_tune, &gc->saved_town_tune, 1); + #endif + agb->friendship = gc->friendship; + mISL_gc_to_agb_memletter(&agb->letter_info, &gc->letter_info); + mISL_gc_to_agb_mail(&agb->letter, &gc->letter); +} + +static void mISL_agb_to_gc_memory(Anmmem_c* gc, mISL_Anmmem_agb_c* agb) { + mISL_gc_to_agb_personal(&gc->memory_player_id, &agb->player_id); + mISL_gc_to_agb_time(&gc->last_speak_time, &agb->last_speak_time); + mISL_agb_to_gc_memuni(&gc->memuni, &agb->memuni); + mISL_u64(&gc->saved_town_tune, &agb->saved_town_tune, 1); + gc->friendship = agb->friendship; + mISL_agb_to_gc_memletter(&gc->letter_info, &agb->letter_info); + mISL_agb_to_gc_mail(&gc->letter, &agb->letter); +} + + +static void mISL_gc_to_agb_qclass(mISL_quest_base_c* agb, mQst_base_c* gc) { + mQst_base_c t; + + bzero(&t, sizeof(t)); + t.quest_type = gc->quest_type; + t.quest_kind = gc->quest_kind; + t.time_limit_enabled = gc->time_limit_enabled; + t.progress = gc->progress; + t.give_reward = gc->give_reward; + mISL_int(&agb->info, (u32*)&t, 1); + mISL_gc_to_agb_time(&agb->time_limit, &gc->time_limit); +} + +static void mISL_agb_to_gc_qclass(mQst_base_c* gc, mISL_quest_base_c* agb) { + mQst_base_c t; + + bzero(&t, sizeof(t)); + mISL_int((u32*)&t, &agb->info, 1); + gc->quest_type = t.quest_type; + gc->quest_kind = t.quest_kind; + gc->time_limit_enabled = t.time_limit_enabled; + gc->progress = t.progress; + gc->give_reward = t.give_reward; + mISL_gc_to_agb_time(&gc->time_limit, &agb->time_limit); +} + +static void mISL_gc_to_agb_qdata(mQst_contest_info_u* agb, mQst_contest_info_u* gc) { + mISL_int((u32*)agb, (u32*)gc, sizeof(mQst_contest_info_u) / sizeof(u32)); +} + +static void mISL_agb_to_gc_qdata(mQst_contest_info_u* gc, mQst_contest_info_u* agb) { + mISL_int((u32*)gc, (u32*)agb, sizeof(mQst_contest_info_u) / sizeof(u32)); +} + +static void mISL_gc_to_agb_quest(mISL_quest_contest_c* agb, mQst_contest_c* gc) { + mISL_gc_to_agb_qclass(&agb->base, &gc->base); + mISL_short(&agb->requested_item, &gc->requested_item, 1); + mISL_gc_to_agb_personal(&agb->player_id, &gc->player_id); + agb->type = gc->type; + mISL_gc_to_agb_qdata(&agb->info, &gc->info); +} + +static void mISL_agb_to_gc_quest(mQst_contest_c* gc, mISL_quest_contest_c* agb) { + mISL_agb_to_gc_qclass(&gc->base, &agb->base); + mISL_short(&gc->requested_item, &agb->requested_item, 1); + mISL_gc_to_agb_personal(&agb->player_id, &gc->player_id); + gc->type = agb->type; + mISL_agb_to_gc_qdata(&gc->info, &agb->info); +} + +static void mISL_gc_to_agb_anmuni(anmuni_u* agb, anmuni_u* gc) { + mISL_int((u32*)agb, (u32*)gc, sizeof(anmuni_u) / sizeof(u32)); +} + +static void mISL_agb_to_gc_anmuni(anmuni_u* gc, anmuni_u* agb) { + mISL_int((u32*)gc, (u32*)agb, sizeof(anmuni_u) / sizeof(u32)); +} + +static void mISL_gc_to_agb_hp_mail(AnmHPMail_c* agb, AnmHPMail_c* gc) { + mISL_gc_to_agb_time(&agb->receive_time, &gc->receive_time); + bcopy(gc->password, agb->password, sizeof(gc->password)); +} + +static void mISL_agb_to_gc_hp_mail(AnmHPMail_c* gc, AnmHPMail_c* agb) { + mISL_gc_to_agb_time(&gc->receive_time, &agb->receive_time); + bcopy(agb->password, gc->password, sizeof(gc->password)); +} + +static void mISL_gc_to_agb_animal(mISL_Animal_agb_c* agb, Animal_c* gc) { + int i; + + mIS_gc_to_agb_anmpersonal(&agb->id, &gc->id); + for (i = 0; i < ANIMAL_MEMORY_NUM; i++) { + mISL_gc_to_agb_memory(&agb->memories[i], &gc->memories[i]); + } + + bcopy(&gc->home_info, &agb->home_info, sizeof(Anmhome_c)); + bcopy(gc->catchphrase, agb->catchphrase, ANIMAL_CATCHPHRASE_LEN); + mISL_gc_to_agb_quest(&agb->contest_quest, &gc->contest_quest); + bcopy(gc->parent_name, agb->parent_name, PLAYER_NAME_LEN); + mISL_gc_to_agb_anmuni(&agb->anmuni, &gc->anmuni); + agb->mood = gc->mood; + agb->mood_time = gc->mood_time; + mISL_short(&agb->cloth, &gc->cloth, 1); + mISL_short(&agb->remove_info, &gc->remove_info, 1); + agb->is_home = gc->is_home; + agb->moved_in = gc->moved_in; + agb->removing = gc->removing; + agb->cloth_original_id = gc->cloth_original_id; + agb->umbrella_id = gc->umbrella_id; + agb->unk_932 = gc->unk_8ED; + mISL_short(&agb->present_cloth, &gc->present_cloth, 1); + bcopy(gc->animal_relations, agb->animal_relations, ANIMAL_NUM_MAX); + + for (i = 0; i < ANIMAL_HP_MAIL_NUM; i++) { + mISL_gc_to_agb_hp_mail(&agb->hp_mail[i], &gc->hp_mail[i]); + } +} + +static void mISL_agb_to_gc_animal(Animal_c* gc, mISL_Animal_agb_c* agb) { + int i; + + mIS_agb_to_gc_anmpersonal(&gc->id, &agb->id); + for (i = 0; i < ANIMAL_MEMORY_NUM; i++) { + mISL_agb_to_gc_memory(&gc->memories[i], &agb->memories[i]); + } + + bcopy(&agb->home_info, &gc->home_info, sizeof(Anmhome_c)); + bcopy(agb->catchphrase, gc->catchphrase, ANIMAL_CATCHPHRASE_LEN); + mISL_agb_to_gc_quest(&gc->contest_quest, &agb->contest_quest); + bcopy(agb->parent_name, gc->parent_name, PLAYER_NAME_LEN); + mISL_agb_to_gc_anmuni(&gc->anmuni, &agb->anmuni); + gc->mood = agb->mood; + gc->mood_time = agb->mood_time; + mISL_short(&gc->cloth, &agb->cloth, 1); + mISL_short(&gc->remove_info, &agb->remove_info, 1); + gc->is_home = agb->is_home; + gc->moved_in = agb->moved_in; + gc->removing = agb->removing; + gc->cloth_original_id = agb->cloth_original_id; + gc->umbrella_id = agb->umbrella_id; + gc->unk_8ED = agb->unk_932; + mISL_short(&gc->present_cloth, &agb->present_cloth, 1); + bcopy(agb->animal_relations, gc->animal_relations, ANIMAL_NUM_MAX); + + for (i = 0; i < ANIMAL_HP_MAIL_NUM; i++) { + mISL_agb_to_gc_hp_mail(&gc->hp_mail[i], &agb->hp_mail[i]); + } +} + +static int mISL_ReturnCheckSum(u8* data, int size) { + int checksum = 0; + int i; + + for (i = size; i != 0; i--) { + checksum += *data++; + } + + return checksum; +} + +static u8 mISL_GetFlatCheckSum(u8* data, int size, u8 now_checksum, int ignored_section_checksum) { + int checksum = mISL_ReturnCheckSum(data, size); + u8 diff = (u8)(checksum - now_checksum) - ignored_section_checksum; + + diff = ~diff; + diff = diff + 1; + + return diff; +} + +extern void mISL_gc_to_agb(Island_agb_c* agb, Island_c* gc) { + int npc_idx; + u32* temp; + + if (agb != NULL) { + bcopy(gc->name, agb->name, mISL_ISLAND_NAME_LEN); + agb->_0013 = 0; + mISL_gc_to_agb_iandinfo(&agb->landinfo, &gc->landinfo); + mISL_gc_to_agb_fgblock(agb->fgblock[0], gc->fgblock[0]); + mISL_gc_to_agb_cottage(&agb->cottage, &gc->cottage); + bcopy(&gc->flag_design, &agb->flag_design, sizeof(mNW_original_design_c)); + mISL_gc_to_agb_animal(&agb->animal, &gc->animal); + mISL_short(agb->deposit[0], gc->deposit[0], sizeof(gc->deposit) / sizeof(u16)); + bcopy(gc->bg_data, agb->bg_data, sizeof(gc->bg_data)); + mISL_gc_to_agb_time(&agb->renew_time, &gc->renew_time); + + if (Common_Get(island_weather) == mEnv_WEATHER_RAIN) { + agb->weather = mEnv_WEATHER_RAIN; + } + else { + agb->weather = mEnv_WEATHER_CLEAR; + } + + npc_idx = mISL_get_npc_idx(Save_Get(island).animal.id.npc_id); + mISL_int((u32*)&agb->npc_idx, (u32*)&npc_idx, 1); + temp = (u32*)zelda_malloc_align(0x1000, 32); + agb->grass_tex_type = gc->grass_tex_type; + + if (temp != NULL) { + bzero(temp, 0x1000); + mISL_get_npc_tex(agb->npc_tex, temp, npc_idx); + bzero(temp, 0x1000); + mISL_get_npc_pal(agb->npc_pal, (u16*)temp, npc_idx); + bzero(temp, 0x1000); + mISL_get_earth_tex(agb->earth_tex, temp, agb->grass_tex_type); + zelda_free(temp); + } + + agb->last_song_male = gc->last_song_male; + agb->last_song_female = gc->last_song_female; + // remove the land info portion from the checksum as it can change + agb->checksum = mISL_GetFlatCheckSum((u8*)agb, sizeof(Island_agb_c), agb->checksum, mISL_ReturnCheckSum((u8*)&agb->landinfo, 16)); + } +} + +static void mISL_toHole(mActor_name_t* fg, u16* deposit, int bx, int bz) { + int ut_x; + int ut_z; + + for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { + for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { + if (*fg == ITM_PITFALL && (((*deposit) >> ut_x) & 1) != 0) { + int hole_no = mCoBG_BnumUnum2HoleNumber(bx, bz, ut_x, ut_z); + + if (hole_no < 0 || hole_no >= 25) { + hole_no = 0; + } + + fg[0] = BURIED_PITFALL_START + hole_no; + deposit[0] &= ~(1 << ut_x); + } + + fg++; + } + + deposit++; + } +} + +/* @nonmatching */ +#ifndef MUST_MATCH +extern void mISL_agb_to_gc(Island_c* gc, Island_agb_c* agb) { + int island_x_blocks[mISL_FG_BLOCK_X_NUM]; + int i; + + if (agb != NULL) { + bcopy(agb->name, gc->name, mISL_ISLAND_NAME_LEN); + mISL_agb_to_gc_iandinfo(&gc->landinfo, &agb->landinfo); + mISL_agb_to_gc_fgblock(gc->fgblock[0], agb->fgblock[0]); + mISL_agb_to_gc_cottage(&gc->cottage, &agb->cottage); + bcopy(&agb->flag_design, &gc->flag_design, sizeof(mNW_original_design_c)); + mISL_agb_to_gc_animal(&gc->animal, &agb->animal); + mISL_short((u16*)gc->deposit, (u16*)agb->deposit, sizeof(gc->deposit) / sizeof(u16)); + bcopy(agb->bg_data, gc->bg_data, sizeof(gc->bg_data)); + mISL_gc_to_agb_time(&gc->renew_time, &agb->renew_time); + gc->last_song_male = agb->last_song_male; + gc->last_song_female = agb->last_song_female; + + if (mFI_CheckFieldData() == TRUE) { + bzero(island_x_blocks, sizeof(island_x_blocks)); + mFI_GetIslandBlockNumX(island_x_blocks); + + for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { + int idx = i + island_x_blocks[0]; + mActor_name_t* fg_p = &gc->fgblock[0][i].items[0][0]; + u16* deposit_p = (u16*)&gc->deposit[(u16)i]; // the access to deposit is strange, casting to u16 is incorrect but it makes all other instructions correct + + mISL_toHole(fg_p, deposit_p, idx, mISL_BLOCK_Z); + } + } + } +} +#else +extern asm void mISL_agb_to_gc(Island_c* gc, Island_agb_c* agb) { + #include "asm/803b5948.s" +} +#endif diff --git a/rel/m_land.c b/rel/m_land.c index 4716bbe1..e846c2bc 100644 --- a/rel/m_land.c +++ b/rel/m_land.c @@ -43,7 +43,7 @@ #include "m_string.h" #include "types.h" -static int l_mld_start_flag; +static int l_mld_start_flag = FALSE; /** * @brief Turns on the start flag. @@ -170,14 +170,15 @@ extern int mLd_AddMuraString(u8* name, int name_len) { */ extern int mLd_GetLandNameStringAddMura(u8* buf) { int mura_size; + int i; u8* name = mLd_GetLandName(); int size = mMsg_Get_Length_String(name, LAND_NAME_SIZE); mem_copy(buf, name, size); mura_size = mLd_AddMuraString(buf, size); - for (mura_size; mura_size < LAND_NAME_MURA_SIZE; mura_size++) { - buf[mura_size] = CHAR_SPACE; + for (i = mura_size; i < LAND_NAME_MURA_SIZE; i++) { + buf[i] = CHAR_SPACE; } return mura_size; diff --git a/rel/m_npc.c b/rel/m_npc.c index 6640378d..a828e6c0 100644 --- a/rel/m_npc.c +++ b/rel/m_npc.c @@ -6806,7 +6806,12 @@ extern int mNpc_ReceiveHPMail(Mail_c* mail) { animal = &animal[npc_idx]; if (animal != NULL) { + /* @BUG - the final byte of the password should not be stored. */ + #ifndef BUGFIXES bcopy(password, animal->hp_mail[private_idx].password, mMpswd_PASSWORD_DATA_LEN); + #else + bcopy(password, animal->hp_mail[private_idx].password, sizeof(animal->hp_mail[private_idx].password)); + #endif lbRTC_TimeCopy(&animal->hp_mail[private_idx].receive_time, Common_GetPointer(time.rtc_time)); res = TRUE; } diff --git a/rel/m_random_field.c b/rel/m_random_field.c index 59e84905..b92c892c 100644 --- a/rel/m_random_field.c +++ b/rel/m_random_field.c @@ -1015,8 +1015,8 @@ extern void mRF_IslandBgData_To_VillageData() { mActor_name_t right_t = right_bg_idx + 0x70; if (mFI_BlockKind2BkNum(&island_left_bx, &island_left_bz, mRF_BLOCKKIND_ISLAND_LEFT)) { - mActor_name_t left_bg_name = mRF_FindBgNameTypeCombiNum(left_t, 0x62); - mActor_name_t right_bg_name = mRF_FindBgNameTypeCombiNum(right_t, 0x63); + mActor_name_t left_bg_name = mRF_FindBgNameTypeCombiNum(left_t, mFM_BLOCK_TYPE_ISLAND_LEFT); + mActor_name_t right_bg_name = mRF_FindBgNameTypeCombiNum(right_t, mFM_BLOCK_TYPE_ISLAND_RIGHT); Save_Set(combi_table[island_left_bz][island_left_bx].combination_type, left_bg_name); Save_Set(combi_table[island_left_bz][island_left_bx + 1].combination_type, right_bg_name);