diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 8c87646b..a593d9b3 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -218,6 +218,10 @@ m_time.c: .rodata: [0x806433B0, 0x806433D8] .data: [0x8065E378, 0x8065E438] .bss: [0x8129F410, 0x8129F420] +m_scene.c: + .text: [0x803F0610, 0x803F1528] + .rodata: [0x806432F8, 0x80643310] + .data: [0x8065DE80, 0x8065DEC8] m_skin_matrix.c: .text: [0x803f1528, 0x803f1bb4] .rodata: [0x80643310, 0x80643318] diff --git a/include/ac_arrange_room.h b/include/ac_arrange_room.h index 48dd54c8..0da63b0a 100644 --- a/include/ac_arrange_room.h +++ b/include/ac_arrange_room.h @@ -8,6 +8,25 @@ extern "C" { #endif +typedef struct arrange_room_actor_s ARRANGE_ROOM_ACTOR; + +typedef void (*aAR_REDMA_PROC)(); + +typedef struct arrange_room_actor_clip_s { + ARRANGE_ROOM_ACTOR* arrange_room_actor_p; + aAR_REDMA_PROC redma_proc; +} aAR_Clip_c; + +struct arrange_room_actor_s { + ACTOR actor_class; + int _174; + u8* wall_data_p; + int wall_num; + u8* floor_data_p; + int floor_num; + aAR_Clip_c clip; +}; + extern ACTOR_PROFILE Arrange_Room_Profile; #ifdef __cplusplus diff --git a/include/ac_furniture.h b/include/ac_furniture.h index fd4b4c29..dfa8fc44 100644 --- a/include/ac_furniture.h +++ b/include/ac_furniture.h @@ -100,7 +100,7 @@ typedef struct ftr_profile_s { typedef struct furniture_collision_s { f32 start[2]; /* starting xz pos */ f32 end[2]; /* ending xz pos */ - f32 normal[2] /* xz normal */ + f32 normal[2]; /* xz normal */ f32 height; /* collision y */ f32 edge_contact_ratio; /* percentage of the xz collision in contact with edge to count as collision */ } aFTR_collision_c; diff --git a/include/ac_my_indoor.h b/include/ac_my_indoor.h index 8d0e7f60..035d2973 100644 --- a/include/ac_my_indoor.h +++ b/include/ac_my_indoor.h @@ -8,6 +8,55 @@ extern "C" { #endif +typedef struct my_indoor_actor_s MY_INDOOR_ACTOR; + +typedef mActor_name_t (*aMI_CHANGE_WALL_PROC)(mActor_name_t item); +typedef mActor_name_t (*aMI_CHANGE_CARPET_PROC)(mActor_name_t item); +typedef void (*aMI_INDOOR_DMA_AGAIN_PROC)(); +typedef void (*aMI_CHANGE_2_DEFAULT_PROC)(); +typedef void (*aMI_WALL_IDX_2_CHANGE_WALL_PROC)(int wall_idx, int is_original_design); +typedef void (*aMI_FLOOR_IDX_2_CHANGE_FLOOR_PROC)(int floor_idx, int is_original_design); + +typedef struct my_room_actor_clip_s { + MY_INDOOR_ACTOR* my_indoor_actor_p; + aMI_CHANGE_WALL_PROC change_wall_proc; + aMI_CHANGE_CARPET_PROC change_carpet_proc; + aMI_INDOOR_DMA_AGAIN_PROC indoor_dma_again_proc; + aMI_CHANGE_2_DEFAULT_PROC change_2_default_proc; + aMI_WALL_IDX_2_CHANGE_WALL_PROC wall_idx_2_change_wall_proc; + aMI_FLOOR_IDX_2_CHANGE_FLOOR_PROC floor_idx_2_change_floor_proc; +} aMI_Clip_c; + +typedef struct my_indoor_data_bank_s { + u8 _00[0x0C - 0x00]; + u8* floor_data_p; + u8* wall_data_p; + int _14; +} aMI_bank_c; + +struct my_indoor_actor_s { + ACTOR actor_class; + s16 floor_num; + s16 wall_num; + int floor_is_original_design; + int wall_is_original_design; + s16 floor_bank_idx; + s16 wall_bank_idx; + aMI_bank_c banks[2]; + int _1B4; + aMI_Clip_c clip; + s16 room_kind; + int change_wall_flag; + int reserved_wall_num; + int reserved_wall_is_original_design; + int change_floor_flag; + int reserved_floor_num; + int reserved_floor_is_original_design; + int room_step[4]; + int _200; // very small chance this is part of room_step + int house_floor_no; +}; + extern ACTOR_PROFILE My_Indoor_Profile; #ifdef __cplusplus diff --git a/include/ac_my_room.h b/include/ac_my_room.h index 26de9c15..b6e499db 100644 --- a/include/ac_my_room.h +++ b/include/ac_my_room.h @@ -3,11 +3,68 @@ #include "types.h" #include "m_actor.h" +#include "ac_furniture.h" #ifdef __cplusplus extern "C" { #endif +typedef struct my_room_actor_s MY_ROOM_ACTOR; + +typedef struct my_room_clock_info_s { + int tick0; /* set on frame 15 */ + int tick1; /* set on frame 45 */ + int tick_stop; /* set on frame 0 */ + int frame; /* 0-119 */ +} aMR_clock_info_c; + +typedef int (*aMR_JUDGE_BREED_NEW_FTR_PROC)(GAME_PLAY* play, u16 ftr_no, int* ut_x, int* ut_z, u16* rotation, int* square_offset, int* layer); +typedef mActor_name_t (*aMR_SEARCH_PICKUP_FURNITURE_PROC)(GAME_PLAY* play); +typedef void (*aMR_FURNITURE2ITEMBAG_PROC)(GAME_PLAY* play); +typedef int (*aMR_JUDGE_PLAYER_ACTION_PROC)(xyz_t* wpos0, xyz_t* wpos1, int ftr_actor_idx); +typedef void (*aMR_PLAYER_MOVE_FURNITURE_PROC)(int ftr_actor_idx, xyz_t* wpos); +typedef int (*aMR_FTR_ID_2_WPOS_PROC)(xyz_t* wpos, int ftr_id); +typedef int (*aMR_UNIT_NUM_2_FTR_ITEMNO_FTRID_PROC)(mActor_name_t* ftr_item_no, int* ftr_id, int ut_x, int ut_z, s16 layer); +typedef void (*aMR_FTR_ID_2_EXTINGUISH_FURNITURE_PROC)(int ftr_id); +typedef void (*aMR_REDMA_FTR_BANK_PROC)(); +typedef int (*aMR_RESERVE_FURNITURE_PROC)(GAME_PLAY* play, u16 ftr_no, int judge_res, int ut_x, int ut_z, u16 rotation, int square_offset, int layer); +typedef int (*aMR_COUNT_FRIEND_FURNITURE_PROC)(FTR_ACTOR* ftr_actor, u8 switch_on); +typedef int (*aMR_JUDGE_PLACE_2ND_LAYER_PROC)(int ut_x, int ut_z); +typedef void (*aMR_OPEN_CLOSE_COMMON_MOVE_PROC)(FTR_ACTOR* ftr_actor, ACTOR* actor, GAME* game, f32 start_frame, f32 end_frame); + +typedef struct my_room_clip_s { + MY_ROOM_ACTOR* my_room_actor_p; + aMR_JUDGE_BREED_NEW_FTR_PROC judge_breed_new_ftr_proc; + aMR_SEARCH_PICKUP_FURNITURE_PROC search_pickup_ftr_proc; + aMR_FURNITURE2ITEMBAG_PROC ftr2itemBag_proc; + aMR_JUDGE_PLAYER_ACTION_PROC judge_player_action_proc; + aMR_PLAYER_MOVE_FURNITURE_PROC player_move_ftr_proc; + aMR_FTR_ID_2_WPOS_PROC ftrId2wpos_proc; + aMR_UNIT_NUM_2_FTR_ITEMNO_FTRID_PROC unitNum2ftrItemNoftrId_proc; + aMR_FTR_ID_2_EXTINGUISH_FURNITURE_PROC ftrId2extinguishFtr_proc; + aMR_REDMA_FTR_BANK_PROC redma_ftr_bank_proc; + aMR_RESERVE_FURNITURE_PROC reserve_ftr_proc; + aMR_COUNT_FRIEND_FURNITURE_PROC count_friend_ftr_proc; + aMR_JUDGE_PLACE_2ND_LAYER_PROC judge_place_2nd_layer_proc; + aMR_OPEN_CLOSE_COMMON_MOVE_PROC open_close_common_move_proc; + /* TODO: function definitions */ + void* get_bed_action_proc; + void* mini_disk_common_move_proc; + void* famicom_emum_common_move_proc; + void* set_leaf_proc; + void* ftr2leaf_proc; + void* leaf_start_pos_proc; + void* pickup_ftr_layer_proc; + void* leaf_pickuped_proc; + void* ftrNo2bankAddress_proc; + void* call_sit_down_ongen_pos_se_proc; + aMR_clock_info_c* clock_info_p; /* used for playing the clock tick? sfx */ + void* sound_melody_proc; + void* check_danna_kill_proc; +} aMR_Clip_c; + +/* TODO: my room actor */ + extern ACTOR_PROFILE My_Room_Profile; #ifdef __cplusplus diff --git a/include/ac_npc.h b/include/ac_npc.h index 028e9f01..23b0fda5 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -35,6 +35,8 @@ typedef ACTOR* (*aNPC_GET_ACTOR_AREA_PROC)(size_t, const char*, int); typedef void (*aNPC_FREE_ACTOR_AREA_PROC)(ACTOR*); typedef void (*aNPC_SET_ATTENTION_REQUEST_PROC)(u8, ACTOR*, xyz_t*); +typedef void (*aNPC_REBUILD_DMA_PROC)(); + typedef int (*aNPC_FORCE_CALL_REQ_PROC)(NPC_ACTOR*, int); struct ac_npc_clip_s { @@ -45,7 +47,9 @@ struct ac_npc_clip_s { aNPC_FREE_ACTOR_AREA_PROC free_actor_area_proc; aNPC_DMA_DRAW_DATA_PROC dma_draw_data_proc; aNPC_SET_ATTENTION_REQUEST_PROC set_attention_request_proc; - void* _01C[(0x124 - 0x01C) / sizeof(void*)]; + void* _01C[(0x0F8 - 0x01C) / sizeof(void*)]; + aNPC_REBUILD_DMA_PROC rebuild_dma_proc; + void* _0FC[(0x124 - 0x0FC) / sizeof(void*)]; aNPC_FORCE_CALL_REQ_PROC force_call_req_proc; void* _128; }; diff --git a/include/ac_shop_indoor.h b/include/ac_shop_indoor.h index 9a88a556..6bcb23c7 100644 --- a/include/ac_shop_indoor.h +++ b/include/ac_shop_indoor.h @@ -8,6 +8,35 @@ extern "C" { #endif +typedef struct shop_indoor_actor_s SHOP_INDOOR_ACTOR; + +typedef int (*aSI_CHANGE_WALL_PROC)(mActor_name_t item); +typedef int (*aSI_CHANGE_CARPET_PROC)(mActor_name_t item); +typedef void (*aSI_INDOOR_DMA_AGAIN_PROC)(); +typedef void (*aSI_CHANGE2DEFAULT_PROC)(); + +typedef struct shop_indoor_clip_s { + SHOP_INDOOR_ACTOR* shop_indoor_actor; + aSI_CHANGE_WALL_PROC change_wall_proc; + aSI_CHANGE_CARPET_PROC change_carpet_proc; + aSI_INDOOR_DMA_AGAIN_PROC indoor_dma_again_proc; + aSI_CHANGE2DEFAULT_PROC change2default_proc; +} aSI_Clip_c; + +struct shop_indoor_actor_s { + ACTOR actor_class; + s16 floor_default_tex_no; + s16 wall_default_tex_no; + s16 floor_data_idx; + s16 wall_data_idx; + int _17C; + u8* floor_data_p[2]; + u8* wall_data_p[2]; + s16 shop_idx; + aSI_Clip_c clip; + int fukubiki_active; +}; + extern ACTOR_PROFILE Shop_Indoor_Profile; #ifdef __cplusplus diff --git a/include/ac_shop_manekin.h b/include/ac_shop_manekin.h index 951990b3..0e7ed639 100644 --- a/include/ac_shop_manekin.h +++ b/include/ac_shop_manekin.h @@ -8,6 +8,44 @@ extern "C" { #endif +typedef struct manekin_actor_s { + xyz_t wpos; + int ut_x; + int ut_z; + mActor_name_t item; + u8* tex_p; + u8* palette_p; + mCoBG_bg_regist_c bg_regist; + int move_bg_num; + int _4C; + int naked; +} MANEKIN_ACTOR; + +typedef struct shop_manekin_actor_s SHOP_MANEKIN_ACTOR; + +typedef void (*aSM_MANEKIN_DMA_AGAIN_PROC)(); +typedef void (*aSM_CHANGE2NAKEDMANEKIN_PROC)(int ut_x, int ut_z); +typedef void (*aSM_NAKED2CLOTH_PROC)(int ut_x, int ut_z); + +typedef struct shop_manekin_clip_s { + SHOP_MANEKIN_ACTOR* shop_manekin_actor_p; + aSM_MANEKIN_DMA_AGAIN_PROC manekin_dma_again_proc; + aSM_CHANGE2NAKEDMANEKIN_PROC change2naked_manekin_proc; + aSM_NAKED2CLOTH_PROC naked2cloth_proc; +} aSM_Clip_c; + +struct shop_manekin_actor_s { + ACTOR actor_class; + int current_block_manekin_num; + MANEKIN_ACTOR* manekin_actors; + int now_block_x; + int now_block_z; + aSM_Clip_c clip; + u8* naked_tex_p; + u8* naked_pal_p; + int _19C; +}; + extern ACTOR_PROFILE Shop_Manekin_Profile; #ifdef __cplusplus diff --git a/include/ac_shop_umbrella.h b/include/ac_shop_umbrella.h index 106ddb1b..d35893f3 100644 --- a/include/ac_shop_umbrella.h +++ b/include/ac_shop_umbrella.h @@ -8,6 +8,40 @@ extern "C" { #endif +typedef struct shop_umbrella_actor_s SHOP_UMBRELLA_ACTOR; + +typedef void (*aShopUmbrella_UMBRELLA_DMA_AGAIN_PROC)(); +typedef void (*aShopUmbrella_DELETE_UMBRELLA_PROC)(int ut_x, int ut_z); + +typedef struct shop_umbrella_actor_clip_s { + SHOP_UMBRELLA_ACTOR* shop_umbrella_actor_p; + aShopUmbrella_UMBRELLA_DMA_AGAIN_PROC umbrella_dma_again_proc; + aShopUmbrella_DELETE_UMBRELLA_PROC delete_umbrella_proc; +} aShopUmbrella_Clip_c; + +typedef struct umbrella_actor_s { + xyz_t wpos; + int ut_x; + int ut_z; + mActor_name_t item; + int umbrella_idx; + int _1C; + mCoBG_bg_regist_c bg_regist; + int move_bg_idx; + int _4C; + s16 state; + f32 scale; +} aShopUmbrella_umbrella_c; + +struct shop_umbrella_actor_s { + ACTOR actor_class; + int umbrella_num; + aShopUmbrella_umbrella_c* umbrellas; + int bx; + int bz; + aShopUmbrella_Clip_c clip; +}; + extern ACTOR_PROFILE Shop_Umbrella_Profile; #ifdef __cplusplus diff --git a/include/m_card.h b/include/m_card.h index de2e91ac..21860def 100644 --- a/include/m_card.h +++ b/include/m_card.h @@ -3,11 +3,19 @@ #include "types.h" #include "libu64/gfxprint.h" +#include "m_personal_id.h" +#include "m_land_h.h" +#include "m_private.h" #ifdef __cplusplus extern "C" { #endif +typedef struct { + mLd_land_info_c land; + PersonalID_c pid[PLAYER_NUM]; +} mCD_persistent_data_c; + extern u8 mCD_GetThisLandSlotNo_code(int* player_no, int* slot_card_results); extern void mCD_save_data_aram_malloc(); extern void mCD_set_aram_save_data(); diff --git a/include/m_clip.h b/include/m_clip.h index 12ac24dd..9b5bd1b5 100644 --- a/include/m_clip.h +++ b/include/m_clip.h @@ -14,31 +14,61 @@ #include "ac_aprilfool_control.h" #include "ac_groundhog_control.h" #include "ac_event_manager.h" +#include "ac_shop_manekin.h" +#include "ac_shop_indoor.h" +#include "ac_my_room.h" +#include "ac_my_indoor.h" +#include "ac_arrange_room.h" +#include "ac_shop_umbrella.h" #ifdef __cplusplus extern "C" { #endif +typedef void (*CLIP_NONE_PROC)(); + /* sizeof(Clip_c) == 0x104 */ typedef struct clip_s { - /* 0x000 */ void* _000[(0x040 - 0x000) / sizeof(void*)]; + /* 0x000 */ void* _000[(0x020 - 0x000) / sizeof(void*)]; + /* 0x020 */ int arrange_ftr_num; + /* 0x024 */ void* _024[(0x040 - 0x024) / sizeof(void*)]; /* 0x040 */ aNPC_Clip_c* npc_clip; - /* 0x044 */ void* _044[(0x074 - 0x044) / sizeof(void*)]; + /* 0x044 */ void* _044[(0x060 - 0x044) / sizeof(void*)]; + /* 0x060 */ aSM_Clip_c* shop_manekin_clip; + /* 0x064 */ void* _064; + /* 0x068 */ CLIP_NONE_PROC _068; + /* 0x06C */ void* _06C; + /* 0x070 */ aSI_Clip_c* shop_indoor_clip; /* 0x074 */ bIT_Clip_c* bg_item_clip; /* 0x078 */ void* _078; /* 0x07C */ aINS_Clip_c* insect_clip; - /* 0x080 */ void* _080[(0x08C - 0x080) / sizeof(void*)]; + /* 0x080 */ aMR_Clip_c* my_room_clip; + /* 0x084 */ void* _084; + /* 0x088 */ void* _088; /* 0x08C */ aSTR_Clip_c* structure_clip; /* 0x090 */ eEC_EffectControl_Clip_c* effect_clip; /* 0x094 */ aTOL_Clip_c* tools_clip; - /* 0x098 */ void* _094[(0x0A0 - 0x098) / sizeof(void*)]; + /* 0x098 */ void* _098; + /* 0x09C */ aMI_Clip_c* my_indoor_clip; /* 0x0A0 */ mDemo_Clip_c* demo_clip; /* can be multiple clip classes */ /* 0x0A4 */ void* demo_clip2; /* can be multiple clip classes */ /* 0x0A8 */ void* _0A8; /* 0x0AC */ aGYO_Clip_c* gyo_clip; - /* 0x0B0 */ void* _0B0[(0x0DC - 0x0B0) / sizeof(void*)]; + /* 0x0B0 */ void* _0B0; + /* 0x0B4 */ void* _0B4; + /* 0x0B8 */ aShopUmbrella_Clip_c* shop_umbrella_clip; + /* 0x0BC */ aAR_Clip_c* arrange_room_clip; + /* 0x0C0 */ void* _0C0; + /* 0x0C4 */ void* _0C4; + /* 0x0C8 */ void* _0C8; + /* 0x0CC */ void* _0CC; + /* 0x0D0 */ void* _0D0; + /* 0x0D4 */ CLIP_NONE_PROC ball_redma_proc; /* removed in DnM+ */ + /* 0x0D8 */ void* _0D8; /* 0x0DC */ aAL_Clip_c* animal_logo_clip; - /* 0x0E0 */ void* _0E0[(0x0EC - 0x0E0) / sizeof(void*)]; + /* 0x0E0 */ void* _0E0; + /* 0x0E4 */ void* _0E4; + /* 0x0E8 */ void* _0E8; /* 0x0EC */ aAPC_Clip_c* aprilfool_control_clip; /* 0x0F0 */ aEvMgr_Clip_c* event_manager_clip; /* 0x0F4 */ aGHC_Clip_c* groundhog_control_clip; diff --git a/include/m_common_data.h b/include/m_common_data.h index b971b93c..5ec23c46 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -31,6 +31,7 @@ #include "m_npc_schedule_h.h" #include "m_all_grow.h" #include "m_fishrecord.h" +#include "m_card.h" #ifdef __cplusplus extern "C" { @@ -221,7 +222,8 @@ typedef struct common_data_s { /* 0x02852E */ s16 goods_power; /* 0x028530 */ Door_data_c door_data; /* misc door data */ /* 0x028544 */ Door_data_c structure_exit_door_data; /* door data for when exiting a building */ - /* 0x028558 */ u8 tmp1[0x028590 - 0x028558]; + /* 0x028558 */ u8 _28558[0x02857C - 0x028558]; + /* 0x02857C */ Door_data_c famicom_emu_exit_door_data; /* 0x028590 */ u8 remove_cut_tree_info_bitfield; /* resets the cut tree states for trees in a visible acre */ /* 0x028591 */ u8 floor_idx; /* 0x028592 */ s16 demo_profiles[mDemo_CLIP_TYPE_NUM - 1]; @@ -284,7 +286,7 @@ typedef struct common_data_s { /* 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; - /* 0x02DB46 */ u8 _2DB46[0x2DBA2 - 0x2DB46]; + /* 0x02DB46 */ mCD_persistent_data_c travel_persistent_data; /* used for checking if travelling back to town */ /* 0x02DBA2 */ s16 island_weather; /* 0x02DBA4 */ s16 island_weather_intensity; /* 0x02DBA6 */ u8 _2DBA6[0x2DBAC - 0x2DBA6]; diff --git a/include/m_home_h.h b/include/m_home_h.h index 3127133a..a200b7e1 100644 --- a/include/m_home_h.h +++ b/include/m_home_h.h @@ -134,7 +134,7 @@ typedef struct home_floor_s { u8 wall_original:1; /* is wallpaper a pattern (original)? */ u8 floor_original:1; /* is flooring a pattern (original)? */ u8 bit_2_7:6; /* unused? */ - } fllot_bit; /* Name exposed? by mISL_gc_to_agb_fllot_bit */ + } fllot_bit; /* Name exposed? by mISL_gc_to_agb_fllot_bit, may also be floor_bit_info as 'mRmTp_GetNowSceneFloorBitInfoP' */ } mHm_flr_c; /* sizeof(mHm_flg_c) == 1 */ diff --git a/include/m_npc.h b/include/m_npc.h index ec6f9c87..2ae1854e 100644 --- a/include/m_npc.h +++ b/include/m_npc.h @@ -241,6 +241,7 @@ extern void mNpc_SetNpcHomeYpos(); extern void mNpc_SendRegisteredGoodbyMail(); extern void mNpc_IslandNpcRoomDataSet(mFM_fg_data_c** sorted_fg_data_list, int fg_name_start); extern Animal_c* mNpc_GetAnimalInfoP(mActor_name_t npc_name); +extern int mNpc_RegistMaskNpc(mActor_name_t mask_id, mActor_name_t npc_id, mActor_name_t cloth); extern void mNpc_PrintRemoveInfo(gfxprint_t* gfxprint); extern void mNpc_PrintFriendship_fdebug(gfxprint_t* gfxprint); diff --git a/include/m_play.h b/include/m_play.h index b28e8969..f8665aea 100644 --- a/include/m_play.h +++ b/include/m_play.h @@ -33,7 +33,7 @@ struct game_play_s { /* 0x00E4 */ mFI_block_tbl_c block_table; /* 0x00F4 */ mFI_block_tbl_c last_block_table; /* 0x0104 */ u8 _0104[0x010C - 0x0104]; - /* 0x010C */ Scene_status_c* current_scene_data; + /* 0x010C */ Scene_Word_u* current_scene_data; /* 0x0110 */ Object_Exchange_c object_exchange; /* 0x1A68 */ View view; /* 0x1B88 */ Camera2 camera; @@ -45,8 +45,7 @@ struct game_play_s { /* 0x1FA4 */ s8 unk1FA4; /* 0x1FA8 */ u8 _1FA4[0x1FB8 - 0x1FA8]; /* 0x1FB8 */ PreRender prerender; - /* 0x2000 */ Door_data_c* door_data; - /* 0x2004 */ int _2004; + /* 0x2000 */ Door_info_c door_info; /* 0x2008 */ int next_scene_no; /* 0x200C */ MtxF projection_matrix; /* 0x204C */ MtxF billboard_matrix; @@ -71,7 +70,7 @@ struct game_play_s { /* 0x2328 */ CollisionCheck_c collision_check; /* 0x23F8 */ DRAW_CHK_PROC draw_chk_proc; // only used by mikanbox actor /* 0x23FC */ u32 fade_color_value; - /* 0x2400 */ Scene_status_c* scene_data_2400; + /* 0x2400 */ Scene_data_status_c* scene_data_status; /* 0x2404 */ u8 _2400[0x2600 - 0x2404]; }; diff --git a/include/m_player_lib.h b/include/m_player_lib.h index 24fa5a36..cb26a2f1 100644 --- a/include/m_player_lib.h +++ b/include/m_player_lib.h @@ -28,6 +28,11 @@ extern int mPlib_Get_address_able_display(); extern int mPlib_get_player_actor_main_index(GAME_PLAY* play); extern int mPlib_check_player_actor_main_index_AllWade(GAME_PLAY* play); +extern void mPlib_Object_Exchange_keep_new_PlayerMdl(GAME_PLAY* play); +extern void mPlib_Object_Exchange_keep_new_PlayerTex(GAME_PLAY* play, int bank_id, int base_idx); +extern void mPlib_Object_Exchange_keep_new_PlayerFaceTex(GAME_PLAY* play); +extern void mPlib_Object_Exchange_keep_new_PlayerFacePallet(GAME_PLAY* play, int bank_id, int base_idx); + #define GET_PLAYER_ACTOR(play) get_player_actor_withoutCheck(play) #define GET_PLAYER_ACTOR_NOW() get_player_actor_withoutCheck((GAME_PLAY*)gamePT) diff --git a/include/m_private.h b/include/m_private.h index 19cf8c7c..e9bf6054 100644 --- a/include/m_private.h +++ b/include/m_private.h @@ -22,6 +22,7 @@ extern "C" { #define mPr_WALLET_MAX 99999 #define mPr_DEPOSIT_MAX 999999999 +#define mPr_FLAG_MASK_CAT_SCHEDULED (1 << 0) // Blanca appears when travelling #define mPr_FLAG_POSTOFFICE_GIFT0 (1 << 2) // 1,000,000 Bells #define mPr_FLAG_POSTOFFICE_GIFT1 (1 << 3) // 10,000,000 Bells #define mPr_FLAG_POSTOFFICE_GIFT2 (1 << 4) // 100,000,000 Bells diff --git a/include/m_scene.h b/include/m_scene.h index 25f9449e..6e8bc216 100644 --- a/include/m_scene.h +++ b/include/m_scene.h @@ -2,13 +2,17 @@ #define M_SCENE_H #include "types.h" +#include "m_actor.h" #include "m_lib.h" #include "famicom_emu.h" +#include "m_scene_table.h" #ifdef __cplusplus extern "C" { #endif +#define mSc_ARENA_SIZE 0xA000 + typedef struct door_data_s { int next_scene_id; u8 exit_orientation; @@ -25,87 +29,178 @@ typedef struct door_data_s { typedef struct object_bank_s { s16 bank_id; char* ram_start; - // TODO: others - u8 _08[0x58 - 0x08]; + char* dma_start; + u32 rom_addr; + size_t size; + u32 _14; + int _18; + int _1C; + int _20; + int _24; + int _28; + OSMessageQueue* msg_queue_p; + OSMessage _30_msg; + OSMessageQueue dma_controller_msg_queue; + OSMessage dma_controller_msg; s16 num_exist; - u8 _0x5A[0x5C - 0x5A]; + u8 part_id; + u8 state; } Object_Bank_c; typedef struct object_exchange_s { Object_Bank_c banks[mSc_OBJECT_BANK_NUM]; - int bank_id; - int _192C; + int bank_idx; + int keep_id; int exchange_id; - u8 _1934[0x1958-0x1934]; + char* next_bank_ram_address; + char* max_ram_address; + char* start_address_save[2]; + char* end_address_save[2]; + char* _194C; + int selected_partition; + int _1954; } Object_Exchange_c; -typedef struct scene_status_s{ - u8 unk0[0x13]; - u8 unk13; -}Scene_status_c; +enum { + mSc_SCENE_DATA_TYPE_PLAYER_PTR, + mSc_SCENE_DATA_TYPE_CTRL_ACTOR_PTR, + mSc_SCENE_DATA_TYPE_ACTOR_PTR, + mSc_SCENE_DATA_TYPE_OBJECT_EXCHANGE_BANK_PTR, + mSc_SCENE_DATA_TYPE_DOOR_DATA_PTR, + mSc_SCENE_DATA_TYPE_FIELD_CT, + mSc_SCENE_DATA_TYPE_MY_ROOM_CT, + mSc_SCENE_DATA_TYPE_ARRANGE_ROOM_CT, + mSc_SCENE_DATA_TYPE_ARRANGE_FURNITURE_CT, + mSc_SCENE_DATA_TYPE_SOUND, + mSc_SCENE_DATA_TYPE_END, -extern Scene_status_c test01_info; -extern Scene_status_c test02_info; -extern Scene_status_c test03_info; -extern Scene_status_c water_test_info; -extern Scene_status_c test_step01_info; -extern Scene_status_c test04_info; -extern Scene_status_c npc_room01_info; -extern Scene_status_c test_fd_npc_land_info; -extern Scene_status_c field_tool_field_info; -extern Scene_status_c shop01_info; -extern Scene_status_c BG_TEST01_info; -extern Scene_status_c BG_TEST01_XLU_info; -extern Scene_status_c broker_shop_info; -extern Scene_status_c fg_tool_in_info; -extern Scene_status_c post_office_info; -extern Scene_status_c start_demo1_info; -extern Scene_status_c start_demo2_info; -extern Scene_status_c police_box_info; -extern Scene_status_c buggy_info; -extern Scene_status_c player_select_info; -extern Scene_status_c player_room_s_info; -extern Scene_status_c player_room_m_info; -extern Scene_status_c player_room_l_info; -extern Scene_status_c shop02_info; -extern Scene_status_c shop03_info; -extern Scene_status_c shop04_1f_info; -extern Scene_status_c test05_info; -extern Scene_status_c PLAYER_SELECT2_info; -extern Scene_status_c PLAYER_SELECT3_info; -extern Scene_status_c shop04_2f_info; -extern Scene_status_c event_notification_info; -extern Scene_status_c kamakura_info; -extern Scene_status_c field_tool_field_info; -extern Scene_status_c title_demo_info; -extern Scene_status_c PLAYER_SELECT4_info; -extern Scene_status_c museum_entrance_info; -extern Scene_status_c museum_picture_info; -extern Scene_status_c museum_fossil_info; -extern Scene_status_c museum_insect_info; -extern Scene_status_c museum_fish_info; -extern Scene_status_c player_room_ll1_info; -extern Scene_status_c player_room_ll2_info; -extern Scene_status_c p_room_bm_s_info; -extern Scene_status_c p_room_bm_m_info; -extern Scene_status_c p_room_bm_l_info; -extern Scene_status_c p_room_bm_ll1_info; -extern Scene_status_c NEEDLEWORK_info; -extern Scene_status_c player_room_island_info; -extern Scene_status_c npc_room_island_info; -extern Scene_status_c start_demo3_info; -extern Scene_status_c lighthouse_info; -extern Scene_status_c tent_info; + mSc_SCENE_DATA_TYPE_NUM +}; -extern int mSc_secure_exchange_keep_bank(Object_Exchange_c*, Object_Bank_c*, int); +typedef struct { + u8 type; + u8 num_actors; + Actor_data* data_p; +} Scene_Word_Data_Actor_c; + +typedef struct { + u8 type; + u8 num_ctrl_actors; + s16* ctrl_actor_profile_p; +} Scene_Word_Data_Ctrl_Actor_c; + +typedef struct { + u8 type; + u8 num_banks; + s16* banks_p; +} Scene_Word_Data_Object_Bank_c; + +typedef struct { + u8 type; + u8 num_doors; + Door_data_c* door_data_p; +} Scene_Word_Data_Door_Data_c; + +typedef struct { + u8 type; + u8 item_type; + u8 bg_num; + u16 bg_disp_size; + u8 room_type; + u8 draw_type; +} Scene_Word_Data_FieldCt_c; + +typedef struct { + u8 type; + u8 arrange_ftr_num; +} Scene_Word_Data_ArrangeFurniture_ct_c; + +typedef struct { + u8 type; +} Scene_Word_Data_Misc_c; + +typedef union scene_word_u { + Scene_Word_Data_Misc_c misc; /* MY_ROOM_CT, ARRANGE_ROOM_CT, ARRANGE_FURNITURE_CT, SOUND */ + Scene_Word_Data_Actor_c actor; /* PLAYER_PTR, ACTOR_PTR */ + Scene_Word_Data_Ctrl_Actor_c control_actor; + Scene_Word_Data_Object_Bank_c object_bank; + Scene_Word_Data_Door_Data_c door_data; + Scene_Word_Data_FieldCt_c field_ct; + Scene_Word_Data_ArrangeFurniture_ct_c arrange_ftr_ct; +} Scene_Word_u; + +typedef struct door_info_s { + u8 num_doors; + Door_data_c* door_data_p; +} Door_info_c; + +extern Scene_Word_u test01_info[]; +extern Scene_Word_u test02_info[]; +extern Scene_Word_u test03_info[]; +extern Scene_Word_u water_test_info[]; +extern Scene_Word_u test_step01_info[]; +extern Scene_Word_u test04_info[]; +extern Scene_Word_u npc_room01_info[]; +extern Scene_Word_u test_fd_npc_land_info[]; +extern Scene_Word_u field_tool_field_info[]; +extern Scene_Word_u shop01_info[]; +extern Scene_Word_u BG_TEST01_info[]; +extern Scene_Word_u BG_TEST01_XLU_info[]; +extern Scene_Word_u broker_shop_info[]; +extern Scene_Word_u fg_tool_in_info[]; +extern Scene_Word_u post_office_info[]; +extern Scene_Word_u start_demo1_info[]; +extern Scene_Word_u start_demo2_info[]; +extern Scene_Word_u police_box_info[]; +extern Scene_Word_u buggy_info[]; +extern Scene_Word_u player_select_info[]; +extern Scene_Word_u player_room_s_info[]; +extern Scene_Word_u player_room_m_info[]; +extern Scene_Word_u player_room_l_info[]; +extern Scene_Word_u shop02_info[]; +extern Scene_Word_u shop03_info[]; +extern Scene_Word_u shop04_1f_info[]; +extern Scene_Word_u test05_info[]; +extern Scene_Word_u PLAYER_SELECT2_info[]; +extern Scene_Word_u PLAYER_SELECT3_info[]; +extern Scene_Word_u shop04_2f_info[]; +extern Scene_Word_u event_notification_info[]; +extern Scene_Word_u kamakura_info[]; +extern Scene_Word_u field_tool_field_info[]; +extern Scene_Word_u title_demo_info[]; +extern Scene_Word_u PLAYER_SELECT4_info[]; +extern Scene_Word_u museum_entrance_info[]; +extern Scene_Word_u museum_picture_info[]; +extern Scene_Word_u museum_fossil_info[]; +extern Scene_Word_u museum_insect_info[]; +extern Scene_Word_u museum_fish_info[]; +extern Scene_Word_u player_room_ll1_info[]; +extern Scene_Word_u player_room_ll2_info[]; +extern Scene_Word_u p_room_bm_s_info[]; +extern Scene_Word_u p_room_bm_m_info[]; +extern Scene_Word_u p_room_bm_l_info[]; +extern Scene_Word_u p_room_bm_ll1_info[]; +extern Scene_Word_u NEEDLEWORK_info[]; +extern Scene_Word_u player_room_island_info[]; +extern Scene_Word_u npc_room_island_info[]; +extern Scene_Word_u start_demo3_info[]; +extern Scene_Word_u lighthouse_info[]; +extern Scene_Word_u tent_info[]; + +extern char* mSc_secure_exchange_keep_bank(Object_Exchange_c* exchange, s16 bank_id, size_t size); +extern void mSc_background_dmacopy_controller(Object_Bank_c* bank); +extern void mSc_dmacopy_data_bank(Object_Exchange_c* exchange); extern int mSc_bank_regist_check(Object_Exchange_c* exchange, s16 bank_id); extern void mSc_regist_initial_exchange_bank(GAME_PLAY* play); -extern void mSc_dmacopy_data_bank(Object_Exchange_c*); -extern void mSc_data_bank_ct(GAME_PLAY*, Object_Exchange_c*); -extern void Door_info_ct(Door_data_c**); -extern void Scene_ct(GAME_PLAY*, void*); -extern void mSc_decide_exchange_bank(Object_Exchange_c*); -extern void return_emu_game(GAME*); +extern void mSc_dmacopy_all_exchange_bank(Object_Exchange_c* exchange); +extern void mSc_data_bank_ct(GAME_PLAY* play, Object_Exchange_c* exchange); +extern void mSc_decide_exchange_bank(Object_Exchange_c* exchange); +extern void Scene_ct(GAME_PLAY* play, Scene_Word_u* scene_data); +extern void Door_info_ct(Door_info_c* door_info); +extern int goto_other_scene(GAME_PLAY* play, Door_data_c* door_data, int update_player_mode); +extern int goto_next_scene(GAME_PLAY* play, int next_idx, int update_player_mode); +extern int goto_emu_game(GAME_PLAY* play, u8 famicom_rom_id); +extern void return_emu_game(GAME* game); #ifdef __cplusplus diff --git a/include/m_scene_ftr.h b/include/m_scene_ftr.h new file mode 100644 index 00000000..d4829e8d --- /dev/null +++ b/include/m_scene_ftr.h @@ -0,0 +1,18 @@ +#ifndef M_SCENE_FTR_H +#define M_SCENE_FTR_H + +#include "types.h" +#include "m_play_h.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void mScn_ObtainMyRoomBank(GAME_PLAY* play); +extern void mScn_ObtainCarpetBank(GAME_PLAY* play); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_scene_table.h b/include/m_scene_table.h index 46177b80..07091587 100644 --- a/include/m_scene_table.h +++ b/include/m_scene_table.h @@ -2,7 +2,7 @@ #define M_SCENE_TABLE_H #include "types.h" -#include "m_scene.h" +//#include "m_scene.h" #ifdef __cplusplus extern "C" { @@ -17,6 +17,11 @@ enum field_draw_type { FIELD_DRAW_TYPE_NUM }; +typedef struct scene_status_s { + u8 unk0[0x13]; + u8 unk13; +} Scene_data_status_c; + /* TODO: is this right? I assume so based on file names but there may be a better place for this @@ -94,7 +99,7 @@ enum scene_table { #define mSc_IS_SCENE_MUSEUM_ROOM(scene) \ ((scene) >= SCENE_MUSEUM_ENTRANCE && (scene) <= SCENE_MUSEUM_ROOM_FISH) -extern Scene_status_c scene_data_status[SCENE_NUM]; +extern Scene_data_status_c scene_data_status[SCENE_NUM]; #ifdef __cplusplus } diff --git a/include/m_submenu.h b/include/m_submenu.h index 4c81aea4..8ed7c7d4 100644 --- a/include/m_submenu.h +++ b/include/m_submenu.h @@ -113,6 +113,7 @@ extern void mSM_submenu_move(Submenu*); extern void mSM_submenu_draw(Submenu*, GAME_PLAY*); extern int mSM_CHECK_ALL_FISH_GET(); extern int mSM_CHECK_ALL_INSECT_GET(); +extern void mSM_Object_Exchange_keep_new_Menu(GAME_PLAY* play); #ifdef __cplusplus } diff --git a/rel/ac_tools.c b/rel/ac_tools.c index 2eb63739..fad5fe61 100644 --- a/rel/ac_tools.c +++ b/rel/ac_tools.c @@ -114,9 +114,9 @@ static void aTOL_secure_pl_umbrella_bank_area(GAME* game){ int id; exchange = &play->object_exchange; - id = exchange->bank_id; + id = exchange->bank_idx; - if(mSc_secure_exchange_keep_bank(exchange, NULL, 0xC00) != 0U){ + if(mSc_secure_exchange_keep_bank(exchange, 0, 0xC00) != NULL){ Common_Set(clip.tools_clip->bank_id, id); } else{ diff --git a/rel/m_play.c b/rel/m_play.c index 61a4fff1..59fb1faf 100644 --- a/rel/m_play.c +++ b/rel/m_play.c @@ -911,7 +911,7 @@ void Gameplay_Scene_Init(GAME_PLAY* play){ mSc_data_bank_ct(play, &play->object_exchange); Global_light_ct(&play->global_light); - Door_info_ct(&play->door_data); + Door_info_ct(&play->door_info); common_data_clear(); Scene_ct(play, play->current_scene_data); mSc_decide_exchange_bank(&play->object_exchange); @@ -920,95 +920,95 @@ void Gameplay_Scene_Init(GAME_PLAY* play){ u8 mPl_SceneNo2SoundRoomType(int scene) { switch (scene) { - case 20: - return 1; + case SCENE_MY_ROOM_S: + return 1; - case 6: - case 9: - case 12: - case 14: - case 18: - case 21: - case 31: - case 41: - case 51: - return 2; + case SCENE_NPC_HOUSE: + case SCENE_SHOP0: + case SCENE_BROKER_SHOP: + case SCENE_POST_OFFICE: + case SCENE_BUGGY: + case SCENE_MY_ROOM_M: + case SCENE_KAMAKURA: + case SCENE_MY_ROOM_LL2: + case SCENE_TENT: + return 2; - case 22: - case 23: - case 24: - case 25: - case 29: - case 40: - case 47: - case 17: - return 3; + case SCENE_MY_ROOM_L: + case SCENE_CONVENI: + case SCENE_SUPER: + case SCENE_DEPART: + case SCENE_DEPART_2: + case SCENE_MY_ROOM_LL1: + case SCENE_COTTAGE_MY: + case SCENE_POLICE_BOX: + return 3; default: - return 0; + return 0; } } void Gameplay_Scene_Read(GAME_PLAY* play, s16 idx){ - static Scene_status_c* scene_word_data[SCENE_NUM] = { - &test01_info, - &test02_info, - &test03_info, - &water_test_info, - &test_step01_info, - &test04_info, - &npc_room01_info, - &test_fd_npc_land_info, - &field_tool_field_info, - &shop01_info, - &BG_TEST01_info, - &BG_TEST01_XLU_info, - &broker_shop_info, - &fg_tool_in_info, - &post_office_info, - &start_demo1_info, - &start_demo2_info, - &police_box_info, - &buggy_info, - &player_select_info, - &player_room_s_info, - &player_room_m_info, - &player_room_l_info, - &shop02_info, - &shop03_info, - &shop04_1f_info, - &test05_info, - &PLAYER_SELECT2_info, - &PLAYER_SELECT3_info, - &shop04_2f_info, - &event_notification_info, - &kamakura_info, - &field_tool_field_info, - &title_demo_info, - &PLAYER_SELECT4_info, - &museum_entrance_info, - &museum_picture_info, - &museum_fossil_info, - &museum_insect_info, - &museum_fish_info, - &player_room_ll1_info, - &player_room_ll2_info, - &p_room_bm_s_info, - &p_room_bm_m_info, - &p_room_bm_l_info, - &p_room_bm_ll1_info, - &NEEDLEWORK_info, - &player_room_island_info, - &npc_room_island_info, - &start_demo3_info, - &lighthouse_info, - &tent_info, + static Scene_Word_u* scene_word_data[SCENE_NUM] = { + test01_info, + test02_info, + test03_info, + water_test_info, + test_step01_info, + test04_info, + npc_room01_info, + test_fd_npc_land_info, + field_tool_field_info, + shop01_info, + BG_TEST01_info, + BG_TEST01_XLU_info, + broker_shop_info, + fg_tool_in_info, + post_office_info, + start_demo1_info, + start_demo2_info, + police_box_info, + buggy_info, + player_select_info, + player_room_s_info, + player_room_m_info, + player_room_l_info, + shop02_info, + shop03_info, + shop04_1f_info, + test05_info, + PLAYER_SELECT2_info, + PLAYER_SELECT3_info, + shop04_2f_info, + event_notification_info, + kamakura_info, + field_tool_field_info, + title_demo_info, + PLAYER_SELECT4_info, + museum_entrance_info, + museum_picture_info, + museum_fossil_info, + museum_insect_info, + museum_fish_info, + player_room_ll1_info, + player_room_ll2_info, + p_room_bm_s_info, + p_room_bm_m_info, + p_room_bm_l_info, + p_room_bm_ll1_info, + NEEDLEWORK_info, + player_room_island_info, + npc_room_island_info, + start_demo3_info, + lighthouse_info, + tent_info, }; - Scene_status_c* current = &scene_data_status[idx]; + Scene_data_status_c* current = &scene_data_status[idx]; current->unk13 = 0; - play->scene_data_2400 = current; + play->scene_data_status = current; play->scene_id = idx; play->current_scene_data = scene_word_data[idx]; current->unk13 = 0; diff --git a/rel/m_scene.c b/rel/m_scene.c new file mode 100644 index 00000000..0433a5b8 --- /dev/null +++ b/rel/m_scene.c @@ -0,0 +1,588 @@ +#include "m_scene.h" + +#include "m_player_lib.h" +#include "libultra/libultra.h" +#include "libjsys/jsyswrapper.h" +#include "m_play.h" +#include "m_common_data.h" +#include "m_npc.h" +#include "m_name_table.h" +#include "m_card.h" +#include "m_submenu.h" +#include "m_scene_ftr.h" + +static void mSc_set_bank_status_after(Object_Bank_c* bank) { + bank->bank_id = ABS(bank->bank_id); + bank->ram_start = bank->dma_start; + bank->state = 0; +} + +static void mSc_clear_bank_status(Object_Bank_c* bank) { + bank->bank_id = 0; + bank->size = 0; + bank->dma_start = NULL; + bank->ram_start = NULL; +} + +static void Object_Exchange_keep_new_Player(GAME_PLAY* play) { + mPlib_Object_Exchange_keep_new_PlayerMdl(play); + mPlib_Object_Exchange_keep_new_PlayerTex(play, 0, 0); + mPlib_Object_Exchange_keep_new_PlayerPallet(play, 0, 0); + mPlib_Object_Exchange_keep_new_PlayerTex(play, 1, 2); + mPlib_Object_Exchange_keep_new_PlayerPallet(play, 1, 2); + mPlib_Object_Exchange_keep_new_PlayerFaceTex(play); + mPlib_Object_Exchange_keep_new_PlayerFacePallet(play, 1, 0); + mPlib_Object_Exchange_keep_new_PlayerFacePallet(play, 2, 1); +} + +extern char* mSc_secure_exchange_keep_bank(Object_Exchange_c* exchange, s16 bank_id, size_t size) { + char* area = NULL; + Object_Bank_c* bank = exchange->banks + exchange->bank_idx; + + if (exchange->bank_idx < mSc_OBJECT_BANK_NUM) { + area = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + size, 32); + + if (area >= exchange->max_ram_address) { + area = NULL; + } + else { + bank->bank_id = bank_id; + bank->ram_start = exchange->next_bank_ram_address; + bank->dma_start = exchange->next_bank_ram_address; + bank->rom_addr = 0; + bank->size = size; + bank->num_exist = 0; + bank->state = 3; + + exchange->next_bank_ram_address = area; + exchange->bank_idx++; + } + } + + return area; +} + +extern void mSc_background_dmacopy_controller(Object_Bank_c* bank) { + switch (bank->state) { + case 1: + { + if (bank->_14 == 0) { + osCreateMesgQueue(&bank->dma_controller_msg_queue, &bank->dma_controller_msg, 1); + _JW_GetResourceAram(bank->rom_addr, (u8*)bank->dma_start, bank->size); + DCStoreRangeNoSync(bank->dma_start, bank->size); + bank->state = 0; + } + + break; + } + + case 2: + { + if (osRecvMesg(&bank->dma_controller_msg_queue, NULL, OS_MESSAGE_NOBLOCK) == FALSE) { + mSc_set_bank_status_after(bank); + } + + break; + } + } +} + +extern void mSc_dmacopy_data_bank(Object_Exchange_c* exchange) { + /* stubbed */ +} + +extern int mSc_bank_regist_check(Object_Exchange_c* exchange, s16 bank_id) { + int res = -1; + int i; + + for (i = 0; i < mSc_OBJECT_BANK_NUM; i++) { + if (ABS(exchange->banks[i].bank_id) == bank_id) { + res = i; + + break; + } + } + + return res; +} + +extern void mSc_regist_initial_exchange_bank(GAME_PLAY* play) { + play->object_exchange.selected_partition = 0; + play->object_exchange.exchange_id = play->object_exchange.bank_idx; + + if (Common_Get(field_type) == mFI_FIELDTYPE2_FG) { + u32 size; + + /* Split the remaining object exchange space into two equal portions */ + size = (u32)(play->object_exchange.max_ram_address - play->object_exchange.next_bank_ram_address) / 2; + play->object_exchange.start_address_save[0] = play->object_exchange.next_bank_ram_address; + play->object_exchange.end_address_save[0] = (char*)ALIGN_NEXT((u32)play->object_exchange.next_bank_ram_address + size, 32); + + play->object_exchange.start_address_save[1] = play->object_exchange.end_address_save[0]; + play->object_exchange.end_address_save[1] = play->object_exchange.max_ram_address; + + /* Temporarily limit the maximum address to half the remaining free space */ + play->object_exchange.max_ram_address = play->object_exchange.end_address_save[0]; + } + else { + play->object_exchange.start_address_save[0] = play->object_exchange.next_bank_ram_address; + play->object_exchange.end_address_save[0] = play->object_exchange.max_ram_address; + + play->object_exchange.start_address_save[1] = play->object_exchange.next_bank_ram_address; + play->object_exchange.end_address_save[1] = play->object_exchange.max_ram_address; + } + + play->object_exchange.exchange_id = play->object_exchange.bank_idx; /* leftover from DnM? */ +} + +static void mSc_dmacopy_all_exchange_bank_sub(Object_Bank_c* bank, Object_Exchange_c* exchange, int idx) { + if (idx >= exchange->exchange_id) { + char* area = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + bank->size, 32); + + if (area >= exchange->max_ram_address) { + exchange->selected_partition = (exchange->selected_partition + 1) % 2; + exchange->next_bank_ram_address = exchange->start_address_save[exchange->selected_partition]; + exchange->max_ram_address = exchange->end_address_save[exchange->selected_partition]; + + area = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + bank->size, 32); + } + + bank->dma_start = exchange->next_bank_ram_address; + bank->part_id = exchange->selected_partition; + exchange->next_bank_ram_address = area; + } + + _JW_GetResourceAram(bank->rom_addr, (u8*)bank->dma_start, bank->size); + DCStoreRangeNoSync(bank->dma_start, bank->size); + mSc_set_bank_status_after(bank); +} + +extern void mSc_dmacopy_all_exchange_bank(Object_Exchange_c* exchange) { + Object_Bank_c* bank; + int i; + + bank = exchange->banks + exchange->keep_id; + exchange->next_bank_ram_address = exchange->start_address_save[exchange->selected_partition]; + + for (i = exchange->keep_id; i < mSc_OBJECT_BANK_NUM; i++) { + if (bank->bank_id != 0 && bank->state != 3) { + if (bank->bank_id < 0) { + mSc_dmacopy_all_exchange_bank_sub(bank, exchange, i); + } + else if (bank->num_exist != 0) { + mSc_dmacopy_all_exchange_bank_sub(bank, exchange, i); + } + else if (i >= exchange->exchange_id) { + mSc_clear_bank_status(bank); + } + else { + bank->bank_id = 0; + } + } + + bank++; + } + + if (Common_Get(clip).npc_clip != NULL) { + Common_Get(clip).npc_clip->rebuild_dma_proc(); + } + + if (Common_Get(clip)._068 != NULL) { + (*Common_Get(clip)._068)(); + } + + if (Common_Get(clip).shop_manekin_clip != NULL) { + Common_Get(clip).shop_manekin_clip->manekin_dma_again_proc(); + } + + if (Common_Get(clip).shop_indoor_clip != NULL) { + Common_Get(clip).shop_indoor_clip->indoor_dma_again_proc(); + } + + if (Common_Get(clip).my_room_clip != NULL) { + Common_Get(clip).my_room_clip->redma_ftr_bank_proc(); + } + + if (Common_Get(clip).my_indoor_clip != NULL) { + Common_Get(clip).my_indoor_clip->indoor_dma_again_proc(); + } + + if (Common_Get(clip).arrange_room_clip != NULL) { + Common_Get(clip).arrange_room_clip->redma_proc(); + } + + if (Common_Get(clip).shop_umbrella_clip != NULL) { + Common_Get(clip).shop_umbrella_clip->umbrella_dma_again_proc(); + } + + if (Common_Get(clip).ball_redma_proc != NULL) { + (*Common_Get(clip).ball_redma_proc)(); + } +} + +extern void mSc_data_bank_ct(GAME_PLAY* play, Object_Exchange_c* exchange) { + char* exchange_arena; + + bzero(exchange, sizeof(Object_Exchange_c)); + + exchange->keep_id = -1; + exchange->exchange_id = -1; + + exchange_arena = (char*)THA_allocAlign(&play->game.tha, mSc_ARENA_SIZE, ~0x1F); + exchange->next_bank_ram_address = exchange_arena; + exchange->start_address_save[0] = exchange_arena; + exchange->start_address_save[1] = exchange_arena; + + exchange_arena += mSc_ARENA_SIZE; + exchange->max_ram_address = exchange_arena; + exchange->end_address_save[0] = exchange_arena; + exchange->end_address_save[1] = exchange_arena; +} + +extern void mSc_decide_exchange_bank(Object_Exchange_c* exchange) { + exchange->keep_id = exchange->bank_idx; + exchange->_194C = exchange->next_bank_ram_address; +} + +static void Scene_player_select(int scene_no, int npc_actor) { + if (Save_Get(scene_no) == scene_no) { + int met_villagers_bitfield = 0; + int met_villagers_num = 0; + mActor_name_t npc_id; + Animal_c* animal = Save_Get(animals); + Anmmem_c* memory; + int i; + int j; + int selected; + + /* Track all villagers who have met a player from town before */ + for (i = 0; i < ANIMAL_NUM_MAX; i++) { + if (mNpc_CheckFreeAnimalPersonalID(&animal->id) == FALSE) { + memory = animal->memories; + + for (j = 0; j < ANIMAL_MEMORY_NUM; j++) { + if ( + memory->memory_player_id.land_id == Save_Get(land_info).id && + mLd_CheckCmpLandName(memory->memory_player_id.land_name, Save_Get(land_info).name) == TRUE + ) { + met_villagers_bitfield |= (1 << i); + met_villagers_num++; + + break; + } + + memory++; + } + } + + animal++; + } + + /* Roll a random villager if none have met a player in town before */ + if (met_villagers_num == 0) { + do { + selected = RANDOM(ANIMAL_NUM_MAX); + } while (mNpc_CheckFreeAnimalPersonalID(&Save_Get(animals[selected]).id)); + + npc_id = Save_Get(animals[selected]).id.npc_id; + i = mNpc_SearchAnimalinfo(Save_Get(animals), npc_id, ANIMAL_NUM_MAX); + } + else { + /* Pick a random villager which has met a player in town */ + + selected = RANDOM(met_villagers_num); + + for (i = 0; i < ANIMAL_NUM_MAX; i++) { + if ((met_villagers_bitfield & 1) != 0) { + if (selected == 0) { + break; + } + else { + selected--; + } + } + + met_villagers_bitfield >>= 1; + } + + npc_id = Save_Get(animals[i]).id.npc_id; + } + + if (scene_no == SCENE_PLAYERSELECT_2) { + Common_Set(player_select_animal_no, i); + } + + mNpc_RegistEventNpc(npc_actor, npc_id, npc_id, Save_Get(animals[i]).cloth); + } +} + +static void Scene_Proc_Player_Ptr(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_Ctrl_Actor_Ptr(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_Actor_Ptr(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_Object_Exchange_Bank_Ptr(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_Door_Data_Ptr(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_Field_ct(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_MyRoom_ct(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_ArrangeRoom_ct(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_ArrangeFurniture_ct(GAME_PLAY* play, Scene_Word_u* data); +static void Scene_Proc_Sound(GAME_PLAY* play, Scene_Word_u* data); + +typedef void (*mSc_SCENE_WORD_PROC)(GAME_PLAY*, Scene_Word_u*); + +extern void Scene_ct(GAME_PLAY* play, Scene_Word_u* scene_data) { + static mSc_SCENE_WORD_PROC Scene_Proc[mSc_SCENE_DATA_TYPE_NUM] = { + &Scene_Proc_Player_Ptr, + &Scene_Proc_Ctrl_Actor_Ptr, + &Scene_Proc_Actor_Ptr, + &Scene_Proc_Object_Exchange_Bank_Ptr, + &Scene_Proc_Door_Data_Ptr, + &Scene_Proc_Field_ct, + &Scene_Proc_MyRoom_ct, + &Scene_Proc_ArrangeRoom_ct, + &Scene_Proc_ArrangeFurniture_ct, + &Scene_Proc_Sound, + NULL + }; + + /* Initialize all scene data */ + while (TRUE) { + u32 type = scene_data->misc.type; + + if (type == mSc_SCENE_DATA_TYPE_END) { + break; + } + + if (type < mSc_SCENE_DATA_TYPE_NUM) { + (*Scene_Proc[type])(play, scene_data); + } + + scene_data++; + } + + /* Setup player select actors */ + Scene_player_select(SCENE_PLAYERSELECT_2, SP_NPC_P_SEL2); // load + Scene_player_select(SCENE_PLAYERSELECT_SAVE, SP_NPC_RESTART); // save + + /* Select Rover or Blanca for visiting town scene */ + if (Save_Get(scene_no) == SCENE_START_DEMO3) { + int rover_shown = FALSE; + + if ( + mLd_CheckCmpLand( + Common_Get(now_private)->player_ID.land_name, Common_Get(now_private)->player_ID.land_id, + Common_Get(travel_persistent_data).land.name, Common_Get(travel_persistent_data).land.id + ) == TRUE + ) { + if (Common_Get(now_private)->state_flags & mPr_FLAG_MASK_CAT_SCHEDULED) { + Common_Get(now_private)->state_flags &= ~mPr_FLAG_MASK_CAT_SCHEDULED; + rover_shown = TRUE; + } + else if (fqrand() < 0.5f) { + Common_Get(now_private)->state_flags |= mPr_FLAG_MASK_CAT_SCHEDULED; // Blanca is scheduled + } + else { + Common_Get(now_private)->state_flags &= ~mPr_FLAG_MASK_CAT_SCHEDULED; + rover_shown = TRUE; + } + } + else { + rover_shown = TRUE; + } + + if (rover_shown == FALSE) { + mActor_name_t blanca_cloth; + + mSP_SelectRandomItem_New(NULL, &blanca_cloth, 1, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_ABC, FALSE); + mNpc_RegistMaskNpc(SP_NPC_MASK_CAT2, SP_NPC_MASK_CAT2, blanca_cloth); + Save_Get(mask_cat).cloth_no = (blanca_cloth >= ITM_CLOTH_START && blanca_cloth < ITM_CLOTH_END) ? (blanca_cloth - ITM_CLOTH_START) : EMPTY_NO; + } + else { + mNpc_RegistMaskNpc(SP_NPC_MASK_CAT2, SP_NPC_GUIDE, EMPTY_NO); // Rover + } + } +} + +static void Scene_Proc_Player_Ptr(GAME_PLAY* play, Scene_Word_u* scene_data) { + static s16 angle_table[8] = { + DEG2SHORT_ANGLE( 0.0f), /* 0x0000 */ + DEG2SHORT_ANGLE( 45.0f), /* 0x2000 */ + DEG2SHORT_ANGLE( 90.0f), /* 0x4000 */ + DEG2SHORT_ANGLE( 135.0f), /* 0x6000 */ + DEG2SHORT_ANGLE(-180.0f), /* 0x8000 */ + DEG2SHORT_ANGLE(-135.0f), /* 0xA000 */ + DEG2SHORT_ANGLE( -90.0f), /* 0xC000 */ + DEG2SHORT_ANGLE( -45.0f) /* 0xE000 */ + }; + + Actor_data* data = scene_data->actor.data_p; + + play->player_data = data; + + /* Update player position & orientation based on the current door exit data */ + if (Common_Get(door_data).next_scene_id != 0) { + mem_copy((u8*)&data->position, (u8*)&Common_Get(door_data).exit_position, sizeof(s_xyz)); + data->rotation.y = angle_table[Common_Get(door_data).exit_orientation]; + } + + data->arg = Common_Get(door_data).extra_data; + Object_Exchange_keep_new_Player(play); + mSM_Object_Exchange_keep_new_Menu(play); +} + +static void Scene_Proc_Ctrl_Actor_Ptr(GAME_PLAY* play, Scene_Word_u* scene_data) { + s16* data = scene_data->control_actor.ctrl_actor_profile_p; + + play->ctrl_actor_data_num = scene_data->control_actor.num_ctrl_actors; + play->ctrl_actor_data = data; +} + +static void Scene_Proc_Actor_Ptr(GAME_PLAY* play, Scene_Word_u* scene_data) { + Actor_data* data_p = scene_data->actor.data_p; + + play->actor_data_num = scene_data->actor.num_actors; + play->actor_data = data_p; +} + +static void Scene_Proc_Object_Exchange_Bank_Ptr(GAME_PLAY* play, Scene_Word_u* scene_data) { + play->obj_bank_data_num = scene_data->object_bank.num_banks; + play->obj_bank_data = scene_data->object_bank.banks_p; +} + +static void Scene_Proc_Door_Data_Ptr(GAME_PLAY* play, Scene_Word_u* scene_data) { + Door_data_c* data_p = scene_data->door_data.door_data_p; + + play->door_info.num_doors = scene_data->door_data.num_doors; + play->door_info.door_data_p = data_p; +} + +extern void Door_info_ct(Door_info_c* door_info) { + door_info->num_doors = 0; +} + +static void Scene_Proc_Sound(GAME_PLAY* play, Scene_Word_u* scene_data) { + // stubbed +} + +static void set_item_info(GAME_PLAY* play, Scene_Word_Data_FieldCt_c* field_ct) { + static s16 profile_table[4] = { + mAc_PROFILE_BGITEM, + mAc_PROFILE_DUMMY, + mAc_PROFILE_BGPOLICEITEM, + mAc_PROFILE_BGPOSTITEM + }; + + int item_type = field_ct->item_type; + + if (item_type == 0) { + Common_Set(bg_item_profile, Common_Get(time).bgitem_profile); + } + else { + Common_Set(bg_item_profile, profile_table[item_type]); + } + + Common_Set(bg_item_type, item_type); +} + +static void Scene_Proc_Field_ct(GAME_PLAY* play, Scene_Word_u* scene_data) { + mFM_SetFieldInitData(scene_data->field_ct.bg_num, scene_data->field_ct.bg_disp_size); + set_item_info(play, &scene_data->field_ct); + Common_Set(field_draw_type, scene_data->field_ct.draw_type); + Common_Set(game_started, FALSE); + Common_Set(in_initial_block, TRUE); + Common_Set(sunlight_flag, TRUE); +} + +static void Scene_Proc_MyRoom_ct(GAME_PLAY* play, Scene_Word_u* scene_data) { + mScn_ObtainMyRoomBank(play); +} + +static void Scene_Proc_ArrangeRoom_ct(GAME_PLAY* play, Scene_Word_u* scene_data) { + mScn_ObtainCarpetBank(play); +} + +static void Scene_Proc_ArrangeFurniture_ct(GAME_PLAY* play, Scene_Word_u* scene_data) { + Common_Get(clip).arrange_ftr_num = scene_data->arrange_ftr_ct.arrange_ftr_num; +} + +extern int goto_other_scene(GAME_PLAY* play, Door_data_c* door_data, int update_player_mode) { + PLAYER_ACTOR* player = get_player_actor_withoutCheck(play); + int res = 0; // failed + + if (player != NULL) { + if (play->fb_wipe_mode == 0) { + play->fb_fade_type = 2; + + if (door_data->wipe_type == 0) { + play->fb_wipe_type = 3; + } + else { + play->fb_wipe_type = door_data->wipe_type; + } + + if (Common_Get(transition).wipe_type == 0xFF) { + Common_Get(transition).wipe_type = play->fb_wipe_type; + } + + Common_Set(door_data, *door_data); + Common_Get(door_data).next_scene_id = door_data->next_scene_id + 1; + play->next_scene_no = door_data->next_scene_id; + + if (update_player_mode) { + mPlib_request_main_invade_type1(play); + } + + restore_fgdata_all(play); + play->game.pad_initialized = FALSE; + res = 1; // success + } + else { + res = 2; // already changing scenes + } + } + + return res; +} + +extern int goto_next_scene(GAME_PLAY* play, int next_idx, int update_player_mode) { + int res = FALSE; + + if (play->door_info.num_doors != 0) { + res = goto_other_scene(play, play->door_info.door_data_p + next_idx, update_player_mode); + } + + return res; +} + +extern int goto_emu_game(GAME_PLAY* play, u8 famicom_rom_id) { + PLAYER_ACTOR* player = get_player_actor_withoutCheck(play); + int res = FALSE; + + if (player != NULL) { + Door_data_c* door_data; + + play->fb_fade_type = 3; + play->fb_wipe_type = 3; + res = TRUE; + + door_data = Common_GetPointer(famicom_emu_exit_door_data); + door_data->next_scene_id = Save_Get(scene_no); + door_data->exit_orientation = 0; + door_data->exit_type = 0; + door_data->extra_data = 0; + door_data->exit_position.x = player->actor_class.world.position.x; + door_data->exit_position.y = player->actor_class.world.position.y; + door_data->exit_position.z = player->actor_class.world.position.z; + door_data->door_actor_name = EMPTY_NO; + Common_Set(current_famicom_rom, famicom_rom_id); + } + + return res; +} + +extern void return_emu_game(GAME* game) { + mem_copy((u8*)Common_GetPointer(door_data), (u8*)Common_GetPointer(famicom_emu_exit_door_data), sizeof(Door_data_c)); // copy exit door data + Common_Get(door_data).next_scene_id = Common_Get(famicom_emu_exit_door_data).next_scene_id + 1; + game->pad_initialized = FALSE; + game_goto_next_game_play(game); + Save_Set(scene_no, Common_Get(famicom_emu_exit_door_data).next_scene_id); +}