diff --git a/include/PreRender.h b/include/PreRender.h new file mode 100644 index 00000000..3be609cd --- /dev/null +++ b/include/PreRender.h @@ -0,0 +1,34 @@ +#ifndef PRERENDER_H +#define PRERENDER_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct prerender_s { + u16 width; + u16 height; + + u16 width_bak; + u16 height_bak; + + u8 _08[8]; + + void* framebuffer; + void* framebuffer_bak; + + void* _18; + + int _1C; + int _20; + + u8 _24[0x24]; +} PreRender; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index 3a3ae1ec..ba4cdcea 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -8,6 +8,15 @@ extern "C" { #endif +enum field_layer { + mCoBG_LAYER0, + mCoBG_LAYER1, + mCoBG_LAYER2, + mCoBG_LAYER3, + + mCoBG_LAYER_NUM +}; + enum background_attribute { /* TODO: finish */ mCoBG_ATTRIBUTE_GRASS0, @@ -92,6 +101,7 @@ extern int mCoBG_CheckHole_OrgAttr(u32 attribute); extern f32 mCoBG_GetBgY_OnlyCenter_FromWpos2(xyz_t wpos, f32 foot_dist); extern int mCoBG_Attribute2CheckPlant(u32 attribute, const xyz_t* wpos); extern void mCoBG_BgCheckControll(xyz_t* reverse_pos, ACTOR* actor, f32 check_range, f32 offset_y, s16 wall_attr_check, s16 no_reverse, s16 check_type); +extern int mCoBG_Height2GetLayer(f32 height); extern f32 mCoBG_GetWaterHeight_File(xyz_t wpos, char* file, int line); #define mCoBG_GetWaterHeight(wpos) mCoBG_GetWaterHeight_File(wpos, __FILE__, __LINE__) diff --git a/include/m_field_make.h b/include/m_field_make.h index 414e3b03..08e96837 100644 --- a/include/m_field_make.h +++ b/include/m_field_make.h @@ -25,6 +25,9 @@ extern "C" { #define FGIDX_2_BLOCK_X(idx) ((idx) % FG_BLOCK_X_NUM + 1) #define FGIDX_2_BLOCK_Z(idx) ((idx) / FG_BLOCK_X_NUM + 1) +#define FGBLOCKXZ_2_FGIDX(x, z) ((z) * FG_BLOCK_X_NUM + (x)) + +#define BLOCKXZ_2_BLOCKIDX(x, z) ((z) * BLOCK_X_NUM + (x)) /* sizeof(mFM_combination_c) == 2 */ typedef struct block_combination_s { @@ -44,6 +47,9 @@ typedef struct block_combo_s { /* 0x05 */ u8 type; } mFM_combo_info_c; +extern u8* g_block_type_p; +extern int* g_block_kind_p; + #ifdef __cplusplus } #endif diff --git a/include/m_map_ovl.h b/include/m_map_ovl.h new file mode 100644 index 00000000..b6181f8e --- /dev/null +++ b/include/m_map_ovl.h @@ -0,0 +1,120 @@ +#ifndef M_MAP_OVL_H +#define M_MAP_OVL_H + +#include "types.h" +#include "m_map_ovl_h.h" +#include "m_submenu_ovl.h" +#include "m_private.h" +#include "m_collision_bg.h" +#include "m_field_make.h" +#include "PreRender.h" +#include "m_npc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define mMP_RESIDENTS_PER_BLOCK_MAX 4 +#define mMP_BLOCKX_MAX 6 +#define mMP_BLOCKZ_MAX 7 + +#define mMP_CURSOR_FRAMES 18 +#define mMP_LABEL_WORD_NUM 2 + +#define mMP_BLOCK_SIZE_F 22.0f + +enum label_type { + mMP_LABEL_NPC, + mMP_LABEL_PLAYER, + mMP_LABEL_SHOP, + mMP_LABEL_POLICE, + mMP_LABEL_POST, + mMP_LABEL_SHRINE, + mMP_LABEL_STATION, + mMP_LABEL_JUNK, + mMP_LABEL_MUSEUM, + mMP_LABEL_NEEDLE, + mMP_LABEL_PORT, + + mMP_LABEL_NUM +}; + +typedef struct map_resident_info_s { + u8 name[PLAYER_NAME_LEN]; + s8 sex; + u8 house_layer; + u8 house_idx; +} mMP_ResidentInfo_c; + +typedef struct map_labelinfo_s { + mMP_ResidentInfo_c* residents[mMP_RESIDENTS_PER_BLOCK_MAX]; + s16 label_cnt; + s16 label_no; +} mMP_LabelInfo_c; + +typedef struct map_house_pos_entry_s { + u8 ut_x; + u8 ut_z; + + u8 idx; +} mMP_HousePos_Entry_c; + +typedef struct map_house_pos_s { + mActor_name_t fgblock_name; + mMP_HousePos_Entry_c entries[3]; +} mMP_HousePos_c; + +typedef struct map_label_word_s { + f32 ofs_x; + f32 ofs_y; + + u8* str; + int str_len; +} mMP_LabelWord_c; + +typedef struct map_label_s { + f32 ofs_x; + f32 ofs_y; + + Gfx* gfx; + mMP_LabelWord_c* words[mMP_LABEL_WORD_NUM]; +} mMP_Label_c; + +struct map_overlay_s { + u8 sel_bx; + u8 sel_bz; + + u8 player_bx; + u8 player_bz; + + f32 map_cursor_current_xpos; + f32 map_cursor_current_zpos; + + f32 map_cursor_target_xpos; + f32 map_cursor_target_zpos; + + int cursor_frame; + + int unk_18[2]; + + u8* map_texture[FG_BLOCK_TOTAL_NUM]; + u8 map_pal[FG_BLOCK_TOTAL_NUM]; + + mFM_combo_info_c* combination_table; + + mMP_ResidentInfo_c player_info[PLAYER_NUM]; + mMP_ResidentInfo_c animal_info[ANIMAL_NUM_MAX]; + + mMP_LabelInfo_c label_info[FG_BLOCK_Z_NUM][FG_BLOCK_X_NUM]; + + int unk_3E8[2]; + + u8 land_name_str_len; + int unk_3F4; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_map_ovl_h.h b/include/m_map_ovl_h.h new file mode 100644 index 00000000..0c70de81 --- /dev/null +++ b/include/m_map_ovl_h.h @@ -0,0 +1,16 @@ +#ifndef M_MAP_OVL_H_H +#define M_MAP_OVL_H_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct map_overlay_s mMP_Overlay_c; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_npc.h b/include/m_npc.h index b54b0078..386e1220 100644 --- a/include/m_npc.h +++ b/include/m_npc.h @@ -197,6 +197,8 @@ extern int mNpc_SearchAnimalinfo(Animal_c* animal, mActor_name_t npc_name, int c extern int mNpc_RegistEventNpc(mActor_name_t actor_name, mActor_name_t tex_name, mActor_name_t npc_name, mActor_name_t cloth_name); extern void mNpc_ClearAnimalInfo(Animal_c* animal_p); extern Animal_c* mNpc_GetInAnimalP(); +extern int mNpc_GetLooks2Sex(int looks); +extern int mNpc_CheckFreeAnimalInfo(Animal_c* animal); extern void mNpc_PrintRemoveInfo(gfxprint_t* gfxprint); extern void mNpc_PrintFriendship_fdebug(gfxprint_t* gfxprint); diff --git a/include/m_submenu.h b/include/m_submenu.h index 65cfe100..0745b0cc 100644 --- a/include/m_submenu.h +++ b/include/m_submenu.h @@ -24,6 +24,43 @@ enum { mSM_PROCESS_NUM }; +enum submenu_overlay { + mSM_OVL_NONE, + + mSM_OVL_INVENTORY, + mSM_OVL_HBOARD, + mSM_OVL_TIMEIN, + mSM_OVL_LEDIT, + mSM_OVL_MAP, + mSM_OVL_NOTICE, + mSM_OVL_REPAY, + mSM_OVL_MSCORE, + mSM_OVL_BIRTHDAY, + mSM_OVL_EDITOR, + mSM_OVL_MAILBOX, + mSM_OVL_BOARD, + mSM_OVL_ADDRESS, + mSM_OVL_HANIWA, + mSM_OVL_EDITENDCHK, + mSM_OVL_WARNING, + mSM_OVL_CPMAIL, + mSM_OVL_CPWARNING, + mSM_OVL_CPEDIT, + mSM_OVL_CATALOG, + mSM_OVL_MUSIC, + mSM_OVL_BANK, + mSM_OVL_NEEDLEWORK, + mSM_OVL_CPORIGINAL, + mSM_OVL_DESIGN, + mSM_OVL_GBA, + mSM_OVL_DIARY, + mSM_OVL_CALENDAR, + mSM_OVL_PASSWORDMAKE, + mSM_OVL_PASSWORDCHK, + + mSM_OVL_NUM +}; + typedef struct submenu_item_s { mActor_name_t item; u8 slot_no; diff --git a/include/m_submenu_ovl.h b/include/m_submenu_ovl.h index eb0bfeb1..411adaac 100644 --- a/include/m_submenu_ovl.h +++ b/include/m_submenu_ovl.h @@ -3,16 +3,99 @@ #include "types.h" #include "m_submenu_ovl_h.h" +#include "m_submenu.h" +#include "graph.h" +#include "m_mail.h" #include "PR/mbi.h" +#include "m_map_ovl_h.h" #ifdef __cplusplus extern "C" { #endif +// TODO: fill this out +typedef struct submenu_segment_s { + u8 _00[0x54]; +} mSM_Segment_c; + +typedef struct submenu_menu_info_s { + int menu_type; + int proc_status; + + int pre_menu_type; + SUBMENU_PROC pre_move_func; + SUBMENU_GAME_PROC pre_draw_func; + + int next_menu_type; + + f32 position[2]; + f32 speed[2]; + + char* _28; + int _2C; + + int next_proc_status; + s16 move_drt; + u16 _36; + + int data0; + int data1; + void* data2; + int data3; +} mSM_MenuInfo_c; + +typedef struct submenu_control_s { + SUBMENU_PROC menu_move_func; + SUBMENU_GAME_PROC menu_draw_func; + + void* hand_move_func; + void* hand_draw_func; + + void* tag_move_func; + void* tag_draw_func; + + int stick_release; + u32 trigger; + u32 last_trigger; + s16 repeat_timer; + s16 texture_movement_angle; + f32 texture_pos[2]; + int animation_flag; +} mSM_Control_c; + +typedef void (*mSM_RETURN_FUNC_PROC)(Submenu*, mSM_MenuInfo_c*); +typedef void (*mSM_MOVE_MOVE_PROC)(Submenu*, mSM_MenuInfo_c*); +typedef void (*mSM_MOVE_END_PROC)(Submenu*, mSM_MenuInfo_c*); +typedef void (*mSM_MOVE_CHG_BASE_PROC)(mSM_MenuInfo_c*, int); +typedef void (*mSM_SET_CHAR_MATRIX_PROC)(GRAPH*); +typedef void (*mSM_CBUF_COPY_PROC)(GRAPH*, PreRender*, int, int, int); +typedef void (*mSM_SET_DRAWMODE_PROC)(GRAPH*, PreRender*, f32, f32, s16); +typedef void (*mSM_DRAW_ITEM_PROC)(GRAPH*, f32, f32, f32, mActor_name_t, int, int, int); +typedef void (*mSM_DRAW_MAIL_PROC)(GRAPH*, f32, f32, f32, Mail_c*, int, int); +typedef void (*mSM_SETUP_VIEW_PROC)(Submenu*, GRAPH*, int); +typedef void (*mSM_CHANGE_VIEW_PROC)(GRAPH*, f32, f32, f32, s16, int, int); + /* sizeof(struct submenu_overlay_s) == 0xA04 */ struct submenu_overlay_s { /* TODO: finish */ - /* 0x000 */ u8 _000[0xA00 - 0x000]; + /* 0x000 */ mSM_Segment_c segment; + /* 0x054 */ mSM_MenuInfo_c menu_info[mSM_OVL_NUM]; + /* 0x90C */ mSM_Control_c menu_control; + /* 0x940 */ mSM_RETURN_FUNC_PROC return_func_proc; + /* 0x944 */ mSM_MOVE_MOVE_PROC move_Move_proc; + /* 0x948 */ mSM_MOVE_END_PROC move_End_proc; + /* 0x94C */ mSM_MOVE_CHG_BASE_PROC move_chg_base_proc; + /* 0x950 */ mSM_SET_CHAR_MATRIX_PROC set_char_matrix_proc; + /* 0x954 */ mSM_CBUF_COPY_PROC cbuf_copy_proc; + /* 0x958 */ mSM_SET_DRAWMODE_PROC set_drawMode_proc; + /* 0x95C */ mSM_DRAW_ITEM_PROC draw_item_proc; + /* 0x960 */ mSM_DRAW_MAIL_PROC draw_mail_proc; + /* 0x964 */ mSM_SETUP_VIEW_PROC setup_view_proc; + /* 0x968 */ void* unused_func_968; + /* 0x96C */ mSM_CHANGE_VIEW_PROC change_view_proc; + /* 0x970 */ u8 _940[0x9B4 - 0x970]; + /* 0x9B4 */ mMP_Overlay_c* map_ovl; + /* 0x9B8 */ u8 _9B8[0xA00 - 0x9B8]; /* 0xA00 */ Mtx* projection_matrix; }; diff --git a/rel/m_map_ovl.c b/rel/m_map_ovl.c new file mode 100644 index 00000000..1b91ede2 --- /dev/null +++ b/rel/m_map_ovl.c @@ -0,0 +1,1171 @@ +#include "m_map_ovl.h" + +#include "audio.h" +#include "m_random_field.h" +#include "m_field_info.h" +#include "m_event.h" +#include "m_font.h" +#include "m_player.h" +#include "m_player_lib.h" +#include "game.h" +#include "sys_matrix.h" +#include "m_malloc.h" +#include "m_common_data.h" + +static u8* l_map_texture[108]; +static u8 l_map_pal[108]; + +extern Gfx kan_win_model[]; +extern Gfx kan_win_model2[]; + +static Gfx* kan_win_wakuT_model_p; +static Gfx* kan_win_waku1T_model_p; +static Gfx* kan_win_waku2T_model_p; +static Gfx* kan_win_waku3T_model_p; +static Gfx* kan_win_waku4T_model_p; +static Gfx* kan_win_color0_mode_p; +static Gfx* kan_win_color1_mode_p; + +extern Gfx kan_win_wakuT_model[]; +extern Gfx kan_waku_w1T_model[]; +extern Gfx kan_waku_w2T_model[]; +extern Gfx kan_waku_w3T_model[]; +extern Gfx kan_waku_w4T_model[]; +extern Gfx kan_win_color0_mode[]; +extern Gfx kan_win_color1_mode[]; + +extern mMP_HousePos_c mMP_house_pos_list[]; + +extern Gfx kan_win_mode[]; + +static u16 kan_tizu1_pal[16] = { + +}; + +static u16 kan_tizu2_pal[16] = { + +}; + +static u16* l_kan_tizu_pal[2] = { + kan_tizu1_pal, kan_tizu2_pal +}; + +extern u8 kan_win_suuji1_tex_rgb_ia8[]; +extern u8 kan_win_suuji2_tex_rgb_ia8[]; +extern u8 kan_win_suuji3_tex_rgb_ia8[]; +extern u8 kan_win_suuji4_tex_rgb_ia8[]; +extern u8 kan_win_suuji5_tex_rgb_ia8[]; + +static u8* kan_win_evw_anime_1_tex_table[FG_BLOCK_X_NUM] = { + kan_win_suuji1_tex_rgb_ia8, + kan_win_suuji2_tex_rgb_ia8, + kan_win_suuji3_tex_rgb_ia8, + kan_win_suuji4_tex_rgb_ia8, + kan_win_suuji5_tex_rgb_ia8, +}; + +extern u8 kan_win_a_tex_rgb_ia8[]; +extern u8 kan_win_b_tex_rgb_ia8[]; +extern u8 kan_win_c_tex_rgb_ia8[]; +extern u8 kan_win_d_tex_rgb_ia8[]; +extern u8 kan_win_e_tex_rgb_ia8[]; +extern u8 kan_win_f_tex_rgb_ia8[]; + +static u8* kan_win_evw_anime_2_tex_table[FG_BLOCK_Z_NUM] = { + kan_win_a_tex_rgb_ia8, + kan_win_b_tex_rgb_ia8, + kan_win_c_tex_rgb_ia8, + kan_win_d_tex_rgb_ia8, + kan_win_e_tex_rgb_ia8, + kan_win_f_tex_rgb_ia8, +}; + +extern Gfx kan_win_npcT_1_model[]; +extern Gfx kan_win_npcT_2_model[]; +extern Gfx kan_win_npcT_3_model[]; + +extern Gfx kan_win_npc2T_1_model[]; +extern Gfx kan_win_npc2T_2_model[]; +extern Gfx kan_win_npc2T_3_model[]; + +static Gfx* kan_win_npcT_table[] = { + kan_win_npcT_1_model, + kan_win_npcT_2_model, + kan_win_npcT_3_model +}; + +static Gfx* kan_win_npc2T_table[] = { + kan_win_npc2T_1_model, + kan_win_npc2T_2_model, + kan_win_npc2T_3_model +}; + +extern Gfx kan_win_genzaiT_model[]; + +extern Gfx kan_tizu_mode[]; +extern Gfx kan_tizu_model[]; + +extern Gfx kan_win_cursorT_model[]; + +extern Gfx kan_win_playerT_model[]; +extern Gfx kan_win_omiseT_model[]; +extern Gfx kan_win_koubanT_model[]; +extern Gfx kan_win_yuuT_model[]; +extern Gfx kan_win_yashiroT_model[]; +extern Gfx kan_win_ekiT_model[]; +extern Gfx kan_win_gomiT_model[]; +extern Gfx kan_win_mu_model[]; +extern Gfx kan_win_ta_model[]; +extern Gfx kan_win_funeT_model[]; + +static mMP_LabelWord_c mMP_label_word_npc = { + -92.0f, -19.0f, + NULL, 0 +}; + +static mMP_Label_c mMP_label_npc = { + -98.0f, -24.0f, + kan_win_npcT_1_model, + { &mMP_label_word_npc, NULL } +}; + +static mMP_LabelWord_c mMP_label_word_player = { + -92.0f, -21.5f, + NULL, 0 +}; + +static mMP_Label_c mMP_label_player = { + -98.0f, -26.5f, + kan_win_playerT_model, + { &mMP_label_word_player, NULL } +}; + +static u8 mMP_label_str_shop[4] = { CHAR_S, CHAR_h, CHAR_o, CHAR_p }; + +static mMP_LabelWord_c mMP_label_word_shop = { + -83.0f, -25.0f, + mMP_label_str_shop, 4 +}; + +static mMP_Label_c mMP_label_shop = { + -93.0f, -30.0f, + kan_win_omiseT_model, + { &mMP_label_word_shop, NULL } +}; + +static u8 mMP_label_str_police[6] = { CHAR_P, CHAR_o, CHAR_l, CHAR_i, CHAR_c, CHAR_e }; + +static mMP_LabelWord_c mMP_label_word_police = { + -83.0f, -19.0f, + mMP_label_str_police, 6 +}; + +static u8 mMP_label_str_police2[7] = { CHAR_S, CHAR_t, CHAR_a, CHAR_t, CHAR_i, CHAR_o, CHAR_n }; + +static mMP_LabelWord_c mMP_label_word_police2 = { + -83.0f, -31.0f, + mMP_label_str_police2, 7 +}; + +static mMP_Label_c mMP_label_police = { + -93.0f, -30.0f, + kan_win_koubanT_model, + { &mMP_label_word_police, &mMP_label_word_police2 } +}; + +static u8 mMP_label_str_post[4] = { CHAR_P, CHAR_o, CHAR_s, CHAR_t }; + +static mMP_LabelWord_c mMP_label_word_post = { + -83.0f, -19.0f, + mMP_label_str_post, 4 +}; + +static u8 mMP_label_str_post2[6] = { CHAR_O, CHAR_f, CHAR_f, CHAR_i, CHAR_c, CHAR_e }; + +static mMP_LabelWord_c mMP_label_word_post2 = { + -83.0f, -31.0f, + mMP_label_str_post2, 6 +}; + +static mMP_Label_c mMP_label_post = { + -93.0f, -30.0f, + kan_win_yuuT_model, + { &mMP_label_word_post, &mMP_label_word_post2 } +}; + +static u8 mMP_label_str_shrine[7] = { CHAR_W, CHAR_i, CHAR_s, CHAR_h, CHAR_i, CHAR_n, CHAR_g }; + +static mMP_LabelWord_c mMP_label_word_shrine = { + -83.0f, -19.0f, + mMP_label_str_shrine, 7 +}; + +static u8 mMP_label_str_shrine2[4] = { CHAR_W, CHAR_e, CHAR_l, CHAR_l }; + +static mMP_LabelWord_c mMP_label_word_shrine2 = { + -83.0f, -31.0f, + mMP_label_str_shrine2, 4 +}; + +static mMP_Label_c mMP_label_shrine = { + -93.0f, -30.0f, + kan_win_yashiroT_model, + { &mMP_label_word_shrine, & mMP_label_word_shrine2 } +}; + +static u8 mMP_label_str_station[5] = { CHAR_T, CHAR_r, CHAR_a, CHAR_i, CHAR_n }; + +static mMP_LabelWord_c mMP_label_word_station = { + -83.0f, -19.0f, + mMP_label_str_station, 5 +}; + +static u8 mMP_label_str_station2[7] = { CHAR_S, CHAR_t, CHAR_a, CHAR_t, CHAR_i, CHAR_o, CHAR_n }; + +static mMP_LabelWord_c mMP_label_word_station2 = { + -83.0f, -31.0f, + mMP_label_str_station2, 7 +}; + +static mMP_Label_c mMP_label_station = { + -93.0f, -31.0f, + kan_win_ekiT_model, + { &mMP_label_word_station, &mMP_label_word_station2 } +}; + +static u8 mMP_label_str_junk[4] = { CHAR_D, CHAR_u, CHAR_m, CHAR_p }; + +static mMP_LabelWord_c mMP_label_word_junk = { + -83.0f, -25.0f, + mMP_label_str_junk, 4 +}; + +static mMP_Label_c mMP_label_junk = { + -93.0f, -30.0f, + kan_win_gomiT_model, + { &mMP_label_word_junk, NULL } +}; + +static u8 mMP_label_str_museum[6] = { CHAR_M, CHAR_u, CHAR_s, CHAR_e, CHAR_u, CHAR_m }; + +static mMP_LabelWord_c mMP_label_word_museum = { + -83.0f, -25.0f, + mMP_label_str_museum, 6 +}; + +static mMP_Label_c mMP_label_museum = { + -93.0f, -30.0f, + kan_win_mu_model, + { &mMP_label_word_museum, NULL } +}; + +static u8 mMP_label_str_needle[6] = { CHAR_T, CHAR_a, CHAR_i, CHAR_l, CHAR_o, CHAR_r }; + +static mMP_LabelWord_c mMP_label_word_needle = { + -83.0f, -25.0f, + mMP_label_str_needle, 6 +}; + +static mMP_Label_c mMP_label_needle = { + -93.0f, -30.0f, + kan_win_ta_model, + { &mMP_label_word_needle, NULL } +}; + +static u8 mMP_label_str_port[4] = { CHAR_D, CHAR_o, CHAR_c, CHAR_k }; + +static mMP_LabelWord_c mMP_label_word_port = { + -83.0f, -25.0f, + mMP_label_str_port, 4 +}; + +static mMP_Label_c mMP_label_port = { + -93.0f, -30.0f, + kan_win_funeT_model, + { &mMP_label_word_port, NULL } +}; + +static mMP_Label_c* mMP_label_data[mMP_LABEL_NUM] = { + &mMP_label_npc, + &mMP_label_player, + &mMP_label_shop, + &mMP_label_police, + &mMP_label_post, + &mMP_label_shrine, + &mMP_label_station, + &mMP_label_junk, + &mMP_label_museum, + &mMP_label_needle, + &mMP_label_port +}; + +static int mMP_check_layer(f32 y) { + int layer; + + switch (mCoBG_Height2GetLayer(y)) { + case mCoBG_LAYER0: + layer = 2; + break; + case mCoBG_LAYER1: + layer = 1; + break; + case mCoBG_LAYER2: + layer = 0; + break; + default: + layer = 1; + break; + } + + if (mRF_CheckFieldStep3() == FALSE) { + layer--; + } + + if (layer < 0) { + layer = 0; + } + + return layer; +} + +static int mMP_check_bg_kind(u8 kind) { + int res = TRUE; + if (kind <= 8 || kind == 0x3D || kind == 0x3E || kind == 9 || kind == 10) { + res = FALSE; + } + + return res; +} + +static u8 pluss_bridge[108] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x56, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x58, 0x59, 0xff, 0x5c, 0x5d, 0x57, 0xff, 0xff, 0x5a, 0x5b, 0x69, 0x6a, 0x6b, 0xff, 0xff, 0xff, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +static void mMP_make_max_no_table(int* max_no_table, int count) { + int bz; + int i; + int j = 0; + + for (i = 0; i < count; i++) { + max_no_table[i] = 39; + } + + //i = BLOCKXZ_2_BLOCKIDX(0, 1); + for (bz = 1; bz < mMP_BLOCKZ_MAX; bz++) { + u8 type; + int bx; + for (bx = 1; bx < mMP_BLOCKX_MAX; bx++) { + type = g_block_type_p[BLOCKXZ_2_BLOCKIDX(bx, bz)]; + if (mMP_check_bg_kind(type) == TRUE) { + max_no_table[0] = type; + + if (Save_Get(plus_bridge.exists) && + Save_Get(plus_bridge.block_x) == bx && + Save_Get(plus_bridge.block_z) == bz && + pluss_bridge[type] != 0xFF + ) { + max_no_table[0] = pluss_bridge[type]; + } + + max_no_table++; + j++; + } + + if (j >= count) { + return; + } + } + } +} + +static void mMP_dma_texture(u8** texture_pp, int type) { + *texture_pp = l_map_texture[type]; +} + +static void mMP_set_map_texture_pal(mMP_Overlay_c* map_ovl) { + int max_no_table[FG_BLOCK_TOTAL_NUM]; + int i; + + mMP_make_max_no_table(max_no_table, FG_BLOCK_TOTAL_NUM); + for (i = 0; i < FG_BLOCK_TOTAL_NUM; i++) { + map_ovl->map_pal[i] = l_map_pal[max_no_table[i]]; + mMP_dma_texture(&map_ovl->map_texture[i], max_no_table[i]); + } +} + +static mActor_name_t mMP_GetFgBlockName(mMP_Overlay_c* map_ovl, int block_x, int block_z) { + return map_ovl->combination_table[Save_Get(combi_table[block_z][block_x]).combination_type].fg_id; +} + +static void mMP_set_house_data(mMP_Overlay_c* map_ovl, mSM_MenuInfo_c* menu) { + static u8 akiya_str[PLAYER_NAME_LEN] = { CHAR_f, CHAR_r, CHAR_e, CHAR_e, CHAR_SPACE, CHAR_SPACE, CHAR_SPACE, CHAR_SPACE }; + + mMP_LabelInfo_c* player_block_label = &map_ovl->label_info[1][2]; + mMP_ResidentInfo_c* resident_p = &map_ovl->player_info[0]; + Private_c* priv = Save_Get(private); + mMP_HousePos_c* house_pos2; + Animal_c* animal = Save_Get(animals); + int residents; + int i; + + /* Process player resident info first */ + + player_block_label->label_cnt = PLAYER_NUM; + player_block_label->label_no = mMP_LABEL_PLAYER; + + residents = 0; + for (i = 0; i < PLAYER_NUM; i++) { + if (mPr_CheckPrivate(priv) == TRUE && + (Common_Get(now_private) != priv || mEv_CheckFirstIntro() == FALSE) + ) { + mPr_CopyPlayerName(resident_p->name, priv); + resident_p->sex = priv->gender; + resident_p->house_layer = 0; + resident_p->house_idx = 0; + + player_block_label->residents[residents] = resident_p; + residents++; + resident_p++; + } + + priv++; + } + + for (residents; residents < PLAYER_NUM; residents++) { + mPr_CopyPlayerName(resident_p->name, akiya_str); + resident_p->sex = -1; + resident_p->house_layer = 0; + + player_block_label->residents[residents] = resident_p; + resident_p++; + } + + house_pos2 = mMP_house_pos_list; + /* Process animal resident info next */ + resident_p = &map_ovl->animal_info[0]; + residents = 0; + + for (i = 0; i < ANIMAL_NUM_MAX; i++) { + if (mNpc_CheckFreeAnimalInfo(animal) == FALSE) { + Anmhome_c* home = &animal->home_info; + mNpc_GetNpcWorldNameAnm(resident_p->name, &animal->id); + resident_p->sex = mNpc_GetLooks2Sex(animal->id.looks); + resident_p->house_layer = mMP_check_layer(Common_Get(npclist[i].house_position.y)); + + { + mActor_name_t fgblock_name = mMP_GetFgBlockName(map_ovl, home->block_x, home->block_z); + mMP_HousePos_c* house_pos = house_pos2; + mMP_HousePos_Entry_c* pos_info = house_pos[0].entries; + + for (house_pos; house_pos->fgblock_name != 0x03B8; house_pos++) { + if (fgblock_name == house_pos->fgblock_name) { + int j; + pos_info = house_pos->entries; + + for (j = 0; j < 3; j++, pos_info++) { + if (pos_info->ut_x == home->ut_x && pos_info->ut_z == home->ut_z - 1) { + break; + } + } + + if (j == 3) { + pos_info = &house_pos->entries[0]; // default + } + + break; + } + } + + resident_p->house_idx = pos_info->idx; + } + + { + int bx = home->block_x - 1; + int bz = home->block_z - 1; + mMP_LabelInfo_c* label_info = &map_ovl->label_info[bz][bx]; + + label_info->residents[label_info->label_cnt] = resident_p; + label_info->label_cnt++; + label_info->label_no = mMP_LABEL_NPC; + } + } + + resident_p++; + animal++; + } + + /* Sort villager houses by layer, with lower layers coming first */ + { + mMP_ResidentInfo_c* resident; + mMP_ResidentInfo_c* next_resident; + mMP_LabelInfo_c* label_info = (mMP_LabelInfo_c*)map_ovl->label_info; + for (i = 0; i < FG_BLOCK_TOTAL_NUM; i++) { + if (label_info->label_no == mMP_LABEL_NPC && label_info->label_cnt > 1) { + + int j; + for (j = 0; j < label_info->label_cnt - 1; j++) { + + resident = label_info->residents[j]; + next_resident = label_info->residents[j + 1]; + + if (resident->house_layer > next_resident->house_layer) { + label_info->residents[j] = next_resident; + label_info->residents[j + 1] = resident; + j = -1; + } + } + } + + label_info++; + } + } +} + +static void mMP_set_field_data(mMP_Overlay_c* map_ovl) { + mMP_LabelInfo_c* label_info = (mMP_LabelInfo_c*)map_ovl->label_info; + int* block_kind_p = g_block_kind_p + BLOCKXZ_2_BLOCKIDX(1, 1); // start at the first non-border acre + int bx; + int bz; + + + for (bz = 0; bz < FG_BLOCK_Z_NUM; bz++) { + for (bx = 0; bx < FG_BLOCK_X_NUM; bx++) { + if (label_info->label_cnt <= 0) { + int kind = *block_kind_p; + + if (kind & mRF_BLOCKKIND_SHOP) { + label_info->label_no = mMP_LABEL_SHOP; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_POLICE) { + label_info->label_no = mMP_LABEL_POLICE; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_POSTOFFICE) { + label_info->label_no = mMP_LABEL_POST; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_SHRINE) { + label_info->label_no = mMP_LABEL_SHRINE; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_STATION) { + label_info->label_no = mMP_LABEL_STATION; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_DUMP) { + label_info->label_no = mMP_LABEL_JUNK; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_MUSEUM) { + label_info->label_no = mMP_LABEL_MUSEUM; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_TAILORS) { + label_info->label_no = mMP_LABEL_NEEDLE; + label_info->label_cnt = 2; + } + else if (kind & mRF_BLOCKKIND_DOCK) { + label_info->label_no = mMP_LABEL_PORT; + label_info->label_cnt = 2; + } + } + + label_info++; + block_kind_p++; + } + + block_kind_p += 2; // skip X border acres + } +} + +static void mMP_set_init_data(mMP_Overlay_c* map_ovl, mSM_MenuInfo_c* menu_info) { + mMP_LabelInfo_c* label_info = (mMP_LabelInfo_c*)map_ovl->label_info; + PLAYER_ACTOR* player = get_player_actor_withoutCheck((GAME_PLAY*)gamePT); + int block_x; + int block_z; + int i; + + if (Common_Get(field_type) != mFI_FIELDTYPE2_FG && Common_Get(door_data.next_scene_id) != 0) { + xyz_t pos; + + xyz_t_move_s_xyz(&pos, Common_GetPointer(structure_exit_door_data.exit_position)); + mFI_Wpos2BlockNum(&block_x, &block_z, pos); + } + else { + mFI_Wpos2BlockNum(&block_x, &block_z, player->actor_class.world_position); + } + + map_ovl->player_bx = block_x - 1; + map_ovl->player_bz = block_z - 1; + + map_ovl->sel_bx = map_ovl->player_bx; + map_ovl->sel_bz = map_ovl->player_bz; + + map_ovl->map_cursor_current_xpos = (f32)map_ovl->player_bx * mMP_BLOCK_SIZE_F; + map_ovl->map_cursor_current_zpos = -(f32)map_ovl->player_bz * mMP_BLOCK_SIZE_F; + + map_ovl->cursor_frame = 0; + + map_ovl->map_cursor_target_xpos = map_ovl->map_cursor_current_xpos; + map_ovl->map_cursor_target_zpos = map_ovl->map_cursor_current_zpos; + + mMP_set_map_texture_pal(map_ovl); + + for (i = 0; i < FG_BLOCK_TOTAL_NUM; i++) { + label_info->label_cnt = 0; + label_info++; + } + + mMP_set_house_data(map_ovl, menu_info); + mMP_set_field_data(map_ovl); + + map_ovl->land_name_str_len = mMl_strlen(Save_Get(land_info.name), LAND_NAME_SIZE, CHAR_SPACE); +} + +static void mMP_move_Move(Submenu* submenu, mSM_MenuInfo_c* menu) { + (*submenu->overlay->move_Move_proc)(submenu, menu); +} + +static void mMP_move_Play(Submenu* submenu, mSM_MenuInfo_c* menu) { + Submenu_Overlay_c* ovl = submenu->overlay; + int trigger = ovl->menu_control.trigger; + mMP_Overlay_c* map_ovl = ovl->map_ovl; + int cursor_moved = FALSE; + + if ((trigger & (BUTTON_A | BUTTON_B | BUTTON_START)) || (menu->data0 == 1 && (trigger & BUTTON_X))) { + (*ovl->move_chg_base_proc)(menu, 4); + sAdo_SysTrgStart(0x17D); + } + else if (trigger & BUTTON_CLEFT) { + if (map_ovl->sel_bx != 0) { + map_ovl->sel_bx--; + map_ovl->map_cursor_target_xpos -= mMP_BLOCK_SIZE_F; + cursor_moved = TRUE; + } + } + else if (trigger & BUTTON_CDOWN) { + if (map_ovl->sel_bz < FG_BLOCK_Z_NUM - 1) { + map_ovl->sel_bz++; + map_ovl->map_cursor_target_zpos -= mMP_BLOCK_SIZE_F; + cursor_moved = TRUE; + } + } + else if (trigger & BUTTON_CUP) { + if (map_ovl->sel_bz != 0) { + map_ovl->sel_bz--; + map_ovl->map_cursor_target_zpos += mMP_BLOCK_SIZE_F; + cursor_moved = TRUE; + } + } + else if (trigger & BUTTON_CRIGHT) { + if (map_ovl->sel_bx < FG_BLOCK_X_NUM - 1) { + map_ovl->sel_bx++; + map_ovl->map_cursor_target_xpos += mMP_BLOCK_SIZE_F; + cursor_moved = TRUE; + } + } + + if (cursor_moved == TRUE) { + menu->proc_status = 2; // TODO: enum & name + sAdo_SysTrgStart(1); + } + + map_ovl->cursor_frame++; + if (map_ovl->cursor_frame >= mMP_CURSOR_FRAMES) { + map_ovl->cursor_frame %= mMP_CURSOR_FRAMES; + } + else if (map_ovl->cursor_frame < 0) { + map_ovl->cursor_frame = 0; + } +} + +static void mMP_move_Wait(Submenu* submenu, mSM_MenuInfo_c* menu) { + mMP_Overlay_c* map_ovl = submenu->overlay->map_ovl; + f32 x_remain = add_calc(&map_ovl->map_cursor_current_xpos, map_ovl->map_cursor_target_xpos, 0.7f, 19.0f, 1.8f); + f32 z_remain = add_calc(&map_ovl->map_cursor_current_zpos, map_ovl->map_cursor_target_zpos, 0.7f, 19.0f, 1.8f); + + if (fabsf(x_remain) < 0.1f && fabsf(z_remain) < 0.1f) { + menu->proc_status = 1; + } +} + +static void mMP_move_End(Submenu* submenu, mSM_MenuInfo_c* menu) { + (*submenu->overlay->move_End_proc)(submenu, menu); +} + +typedef void (*mMP_MOVE_PROC)(Submenu*, mSM_MenuInfo_c*); +static void mMP_map_ovl_move(Submenu* submenu) { + static mMP_MOVE_PROC ovl_move_proc[5] = { + &mMP_move_Move, + &mMP_move_Play, + &mMP_move_Wait, + (mMP_MOVE_PROC)&none_proc1, + &mMP_move_End + }; + + Submenu_Overlay_c* ovl = submenu->overlay; + mSM_MenuInfo_c* menu = &ovl->menu_info[mSM_OVL_MAP]; + + (*menu->pre_move_func)(submenu); + (*ovl_move_proc[menu->proc_status])(submenu, menu); +} + +#pragma pool_data on +static void mMP_map_draw_init() { + kan_win_wakuT_model_p = kan_win_wakuT_model; + kan_win_waku1T_model_p = kan_waku_w1T_model; + kan_win_waku2T_model_p = kan_waku_w2T_model; + kan_win_waku3T_model_p = kan_waku_w3T_model; + kan_win_waku4T_model_p = kan_waku_w4T_model; + kan_win_color0_mode_p = kan_win_color0_mode; + kan_win_color1_mode_p = kan_win_color1_mode; +} +#pragma pool_data reset + +static int mMP_get_label_cnt(mMP_LabelInfo_c* label_info) { + int label_no = label_info->label_no; + if (label_no == mMP_LABEL_NPC || label_no == mMP_LABEL_PLAYER) { + return label_info->label_cnt; + } + + return 1; +} + +/* TODO: this function needs to be matched. We first need to fix pooling so that .rodata has pooling off and .data & .bss have pooling on */ +#pragma pool_data on +static void mMP_set_house_dl(GRAPH* graph, mMP_Overlay_c* map_ovl, f32 pos_x, f32 pos_y) { + static f32 offset_x[3] = { 5.0f, 13.0f, 17.0f }; + static f32 offset_y[3] = { -4.0f, -11.0f, -18.0f }; + + Gfx* gfx; + mMP_LabelInfo_c* label_info = (mMP_LabelInfo_c*)map_ovl->label_info; + f32 y = pos_y + 45.7f; + f32 base_y = y + (0.5f * mMP_BLOCK_SIZE_F); + f32 base_x = (pos_x + 11.7f) - (0.5f * mMP_BLOCK_SIZE_F); + f32 x_save; + int bx; + int bz; + + OPEN_DISP(graph); + + gfx = NOW_POLY_OPA_DISP; + gSPDisplayList(gfx++, kan_win_mode); + + /* draw all villager houses */ + + for (bz = 0; bz < FG_BLOCK_Z_NUM; bz++) { + x_save = base_x; + for (bx = 0; bx < FG_BLOCK_X_NUM; bx++) { + if (label_info->label_no == mMP_LABEL_NPC) { + mMP_ResidentInfo_c** resident_p = label_info->residents; + int i; + + for (i = 0; i < label_info->label_cnt; i++) { + Matrix_scale(16.0f, 16.0f, 1.0f, 0); + Matrix_translate(base_x + offset_x[(*resident_p)->house_idx % 3], (base_y + 11.0f) + offset_y[(*resident_p)->house_idx / 3], 140.0f, 1); + + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, kan_win_npc2T_table[(*resident_p)->house_layer]); + + resident_p++; + } + } + + base_x += mMP_BLOCK_SIZE_F; + } + + base_x = x_save; + base_y -= mMP_BLOCK_SIZE_F; + } + + /* draw "current acre" icon */ + + Matrix_scale(16.0f, 16.0f, 1.0f, 0); + Matrix_translate( + (x_save + (f32)map_ovl->player_bx * mMP_BLOCK_SIZE_F) + 3.0f + 5.0f, + (y - (0.5f * mMP_BLOCK_SIZE_F) - (f32)map_ovl->player_bz * mMP_BLOCK_SIZE_F) + 4.0f + 5.0f, + 140.0f, + 1 + ); + + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, kan_win_genzaiT_model); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); +} +#pragma pool_data reset + +static void mMP_set_map_dl(GRAPH* graph, mMP_Overlay_c* map_ovl) { + int bz; + int bx; + int block = 0; + Gfx* gfx; + + OPEN_DISP(graph); + + gfx = NOW_POLY_OPA_DISP; + + gDPSetTextureAdjustMode(gfx++, G_SPECIAL_TA_MODE, G_TA_DOLPHIN); + gSPDisplayList(gfx++, kan_tizu_mode); + + Matrix_push(); + Matrix_translate(11.7f, 45.7f, 0.0f, 1); + + for (bz = 0; bz < FG_BLOCK_Z_NUM; bz++) { + for (bx = 0; bx < FG_BLOCK_X_NUM; bx++) { + gSPSegment(gfx++, G_MWO_SEGMENT_8, map_ovl->map_texture[block]); + gSPSegment(gfx++, G_MWO_SEGMENT_9, l_kan_tizu_pal[map_ovl->map_pal[block]]); + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, kan_tizu_model); + + /* move right one acre */ + Matrix_translate(mMP_BLOCK_SIZE_F, 0.0f, 0.0f, 1); + block++; + } + + /* move left to '1' acre and down one acre */ + Matrix_translate((-mMP_BLOCK_SIZE_F) * FG_BLOCK_X_NUM, -mMP_BLOCK_SIZE_F, 0.0f, 1); + } + + Matrix_pull(); + gDPSetTextureAdjustMode(gfx++, G_SPECIAL_TA_MODE, G_TA_N64); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); +} + +static void mMP_set_cursol_dl(GRAPH* graph, mMP_Overlay_c* map_ovl, f32 base_x, f32 base_y) { + static int col_g[mMP_CURSOR_FRAMES] = { + 0, + 1, + 2, + 5, + 10, + 20, + 50, + 75, + 90, + 100, + 90, + 75, + 50, + 20, + 10, + 5, + 2, + 1 + }; + + static f32 cursol_scale[mMP_CURSOR_FRAMES] = { + 1.0f, + 1.015f, + 1.03f, + 1.04f, + 1.05f, + 1.06f, + 1.07f, + 1.08f, + 1.09f, + 1.1f, + 1.09f, + 1.08f, + 1.07f, + 1.06f, + 1.05f, + 1.04f, + 1.03f, + 1.015f + }; + + f32 x = map_ovl->map_cursor_current_xpos + base_x; + f32 y = map_ovl->map_cursor_current_zpos + base_y; + int frame = map_ovl->cursor_frame; + Gfx* gfx; + + Matrix_scale(16.0f, 16.0f, 1.0f, 0); + Matrix_translate(x + 11.7f, y + 45.7f, 140.0f, 1); + + Matrix_scale(cursol_scale[frame], cursol_scale[frame], 1.0f, 1); + + OPEN_DISP(graph); + + gfx = NOW_POLY_OPA_DISP; + + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(gfx++, 0, 255, 255, col_g[frame], 255, 255); + gSPDisplayList(gfx++, kan_win_cursorT_model); + + SET_POLY_OPA_DISP(gfx); + + CLOSE_DISP(graph); +} + +static void mMP_set_label_dl(GAME* game, mMP_LabelInfo_c* label_info, f32 xpos, f32 ypos) { + mMP_Label_c* label = mMP_label_data[label_info->label_no]; + + if (label != NULL) { + mMP_ResidentInfo_c** resident_p = label_info->residents; + mMP_LabelWord_c* word; + f32 base_x = 160.0f + xpos; + f32 base_y = 120.0f - ypos; + int i; + + for (i = 0; i < mMP_LABEL_WORD_NUM; i++) { + word = label->words[i]; + + if (word != NULL) { + if (word->str == NULL) { + /* draw resident name label (villagers, players) */ + int j; + + for (j = 0; j < label_info->label_cnt; j++) { + int width = mFont_GetStringWidth((*resident_p)->name, PLAYER_NAME_LEN, TRUE); + f32 scale_x = 54.0f / width; + + if (scale_x > 0.75f) { + scale_x = 0.75f; + } + + if (resident_p[0]->sex != -1) { + mFont_SetLineStrings( + game, + resident_p[0]->name, PLAYER_NAME_LEN, + base_x + word->ofs_x, base_y - word->ofs_y, + 255, 75, 40, 255, + FALSE, TRUE, + scale_x, 1.8125f, + mFont_MODE_POLY + ); + } + else { + mFont_SetLineStrings( + game, + resident_p[0]->name, PLAYER_NAME_LEN, + base_x + word->ofs_x, base_y - word->ofs_y, + 165, 145, 140, 255, + FALSE, TRUE, + scale_x, 1.8125f, + mFont_MODE_POLY + ); + } + + resident_p++; + base_y += 12.0f; + } + } + else { + /* draw building name */ + mFont_SetLineStrings( + game, + word->str, word->str_len, + base_x + word->ofs_x, base_y - word->ofs_y, + 120, 95, 205, 255, + FALSE, TRUE, + 1.8125f, 1.8125f, + mFont_MODE_POLY + ); + } + } + } + } +} + +static void mMP_set_base_dl(GRAPH* graph, mSM_MenuInfo_c* menu) { + Gfx* gfx; + + OPEN_DISP(graph); + gfx = NOW_POLY_OPA_DISP; + + if (menu->data0 == 0) { + gSPSegment(gfx++, G_MWO_SEGMENT_B, kan_win_color0_mode_p); + } + else { + gSPSegment(gfx++, G_MWO_SEGMENT_B, kan_win_color1_mode_p); + } + + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, kan_win_model); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); +} + +#pragma pool_data on +static void mMP_set_win_dl(GRAPH* graph, mMP_Overlay_c* map_ovl, mMP_LabelInfo_c* label_info) { + int label_count = label_info->label_cnt; + Gfx* gfx; + + OPEN_DISP(graph); + gfx = NOW_POLY_OPA_DISP; + + /* move X-acre number texture into segment 8 and Z-acre character texture int segment 9 */ + gSPSegment(gfx++, G_MWO_SEGMENT_8, kan_win_evw_anime_1_tex_table[map_ovl->sel_bx]); + gSPSegment(gfx++, G_MWO_SEGMENT_9, kan_win_evw_anime_2_tex_table[map_ovl->sel_bz]); + + /* move label area texture into segment 10 based on number of labels */ + if (label_count == 4) { + gSPSegment(gfx++, G_MWO_SEGMENT_A, kan_win_waku4T_model_p); + } + else if (label_count == 3) { + gSPSegment(gfx++, G_MWO_SEGMENT_A, kan_win_waku3T_model_p); + } + else if (label_count == 1) { + gSPSegment(gfx++, G_MWO_SEGMENT_A, kan_win_wakuT_model_p); + } + else if (label_count == 0) { + gSPSegment(gfx++, G_MWO_SEGMENT_A, kan_win_waku1T_model_p); + } + else { /* label_count == 2 */ + gSPSegment(gfx++, G_MWO_SEGMENT_A, kan_win_waku2T_model_p); + } + + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, kan_win_model2); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); +} +#pragma pool_data reset + +static void mMP_set_label_top_dl(GRAPH* graph, mMP_LabelInfo_c* label_info) { + mMP_Label_c* label = mMP_label_data[label_info->label_no]; + mMP_ResidentInfo_c** resident_p; + + if (label != NULL) { + int count = mMP_get_label_cnt(label_info); + int i; + Gfx* gfx; + + OPEN_DISP(graph); + gfx = NOW_POLY_OPA_DISP; + + Matrix_push(); + Matrix_translate(label->ofs_x, label->ofs_y, 0.0f, 1); + + if (label_info->label_no == mMP_LABEL_NPC) { + resident_p = label_info->residents; + } + else { + resident_p = NULL; + } + + for (i = 0; i < count; i++) { + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (resident_p != NULL && *resident_p != NULL && (*resident_p)->house_layer != 0) { + gSPDisplayList(gfx++, kan_win_npcT_table[(*resident_p)->house_layer]); + resident_p++; + } + else { + gSPDisplayList(gfx++, label->gfx); + + if (resident_p != NULL) { + resident_p++; + } + } + + Matrix_translate(0.0f, -12.0f, 0.0f, 1); + } + + Matrix_pull(); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); + } +} + +static void mMP_set_dl(Submenu* submenu, GAME* game, mSM_MenuInfo_c* menu) { + static u8 land_color[2][4] = { + { 255, 0, 255, 255 }, + { 60, 60, 255, 255 }, + }; + + GRAPH* graph = game->graph; + mMP_Overlay_c* map_ovl = submenu->overlay->map_ovl; + u8* col = land_color[menu->data0]; + mMP_LabelInfo_c* label_info = &map_ovl->label_info[map_ovl->sel_bz][map_ovl->sel_bx]; + u8* land_name; + f32 xpos = menu->position[0]; + f32 ypos = menu->position[1]; + f32 str_xpos; + f32 str_ypos; + + + Matrix_scale(16.0f, 16.0f, 1.0f, 0); + Matrix_translate(xpos, ypos, 140.0f, 1); + + mMP_set_base_dl(graph, menu); + mMP_set_map_dl(graph, map_ovl); + mMP_set_win_dl(graph, map_ovl, label_info); + mMP_set_label_top_dl(graph, label_info); + mMP_set_house_dl(graph, map_ovl, xpos, ypos); + mMP_set_cursol_dl(graph, map_ovl, xpos, ypos); + + (*submenu->overlay->set_char_matrix_proc)(graph); + + /* draw town name */ + land_name = Save_Get(land_info.name); + str_xpos = (xpos + -136.0f) + 24.0f; + str_ypos = (ypos + 102.0f) + -29.0f; + mFont_SetLineStrings( + game, + land_name, map_ovl->land_name_str_len, + str_xpos + 160.0f, 120.0f - str_ypos, + col[0], col[1], col[2], 255, + FALSE, TRUE, + 1.875f, 1.875f, + mFont_MODE_POLY + ); + + mMP_set_label_dl(game, label_info, xpos, ypos); +} + +static void mMP_map_ovl_draw(Submenu* submenu, GAME* game) { + Submenu_Overlay_c* overlay = submenu->overlay; + mSM_MenuInfo_c* menu = &overlay->menu_info[mSM_OVL_MAP]; + + (*menu->pre_draw_func)(submenu, game); + mMP_set_dl(submenu, game, menu); +} + +static void mMP_map_ovl_set_proc(Submenu* submenu) { + Submenu_Overlay_c* overlay = submenu->overlay; + + overlay->menu_control.menu_move_func = &mMP_map_ovl_move; + overlay->menu_control.menu_draw_func = &mMP_map_ovl_draw; +} + +static void mMP_map_ovl_init(Submenu* submenu) { + Submenu_Overlay_c* overlay = submenu->overlay; + mSM_MenuInfo_c* menu = &overlay->menu_info[mSM_OVL_MAP]; + + overlay->menu_control.animation_flag = FALSE; + (*submenu->overlay->move_chg_base_proc)(menu, 5); + + sAdo_SysTrgStart(0x17C); + mMP_set_init_data(submenu->overlay->map_ovl, menu); +} + +static void mMP_map_ovl_construct(Submenu* submenu) { + Submenu_Overlay_c* overlay = submenu->overlay; + + if (overlay->map_ovl == NULL) { + overlay->map_ovl = (mMP_Overlay_c*)zelda_malloc(sizeof(mMP_Overlay_c)); + mem_clear((u8*)overlay->map_ovl, sizeof(mMP_Overlay_c), 0); + overlay->map_ovl->combination_table = data_combi_table; + mMP_map_draw_init(); + } + + mMP_map_ovl_init(submenu); + mMP_map_ovl_set_proc(submenu); +} + +static void mMP_map_ovl_destruct(Submenu* submenu) { + mMP_Overlay_c* map_ovl = submenu->overlay->map_ovl; + + if (map_ovl != NULL) { + zelda_free(map_ovl); + } + + submenu->overlay->map_ovl = NULL; +}