diff --git a/config/rel_slices.yml b/config/rel_slices.yml index a8a72c4b..3a6ac8cc 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -426,6 +426,10 @@ ac_haniwa.c: .text: [0x80427624, 0x80428F64] .rodata: [0x806440B8, 0x806440F8] .data: [0x80683D08, 0x80683E98] +ac_my_indoor.c: + .text: [0x8046EE38, 0x80470288] + .rodata: [0x80644A88, 0x80644A98] + .data: [0x806870F0, 0x806873E8] ac_psnowman.c: .text: [0x80484098, 0x80484694] .rodata: [0x80644C30, 0x80644C60] @@ -892,6 +896,8 @@ ac_weather_fine.c: # dataobject.obj files data/combi/data_combi.c: .data: [0x8080DD80, 0x8080E628] +data/item/item_name.c: + .data: [0x808BF660, 0x808C8830] data/npc/default_list.c: .data: [0x8096CD90, 0x8096D328] data/npc/grow_list.c: @@ -918,8 +924,6 @@ data/field/bg/earth_pal.c: .data: [0x80C90100, 0x80C90280] data/field/bg/rail_pal.c: .data: [0x80F8C2C8, 0x80F8C460] -data/item/item_name.c: - .data: [0x808BF660, 0x808C8830] m_bg_tex.c: .bss: [0x8125AC80, 0x81263080] sys_stacks.c: diff --git a/include/ac_my_indoor.h b/include/ac_my_indoor.h index 035d2973..14f918fb 100644 --- a/include/ac_my_indoor.h +++ b/include/ac_my_indoor.h @@ -8,53 +8,77 @@ extern "C" { #endif +#define aMI_PAL_SIZE (16 * sizeof(u16)) +#define aMI_TEX_SIZE ((64 * 64) / 2) + +#define aMI_WALL_TEX_NUM 2 +#define aMI_FLOOR_TEX_NUM 4 + +#define aMI_WALL_BANK_SIZE (aMI_PAL_SIZE + aMI_WALL_TEX_NUM * aMI_TEX_SIZE) +#define aMI_FLOOR_BANK_SIZE (aMI_PAL_SIZE + aMI_FLOOR_TEX_NUM * aMI_TEX_SIZE) + +#define aMI_STEP_TYPE_NUM 4 + +enum { + aMI_BANK0, + aMI_BANK1, + + aMI_BANK_NUM +}; + 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 mActor_name_t (*aMI_WALL_IDX_2_CHANGE_WALL_PROC)(int wall_idx, int is_original_design); +typedef mActor_name_t (*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; + 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 void (*aMI_DRAW_PROC)(ACTOR*, GAME*); + typedef struct my_indoor_data_bank_s { - u8 _00[0x0C - 0x00]; - u8* floor_data_p; - u8* wall_data_p; - int _14; + int _00; + aMI_DRAW_PROC floor_draw_proc; + aMI_DRAW_PROC wall_draw_proc; + u8* floor_data_p; + u8* wall_data_p; + int _14; } aMI_bank_c; +typedef struct my_indoor_reserve_s { + int reserve_flag; + int idx; + int is_original_flag; +} aMI_reserve_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; + 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[aMI_BANK_NUM]; + int _1B4; + aMI_Clip_c clip; + s16 room_kind; + aMI_reserve_c wall_reserve; + aMI_reserve_c floor_reserve; + int room_step[aMI_STEP_TYPE_NUM]; + int _200; // very small chance this is part of room_step + int house_floor_no; }; extern ACTOR_PROFILE My_Indoor_Profile; @@ -64,4 +88,3 @@ extern ACTOR_PROFILE My_Indoor_Profile; #endif #endif - diff --git a/src/ac_my_indoor.c b/src/ac_my_indoor.c new file mode 100644 index 00000000..a438ed1f --- /dev/null +++ b/src/ac_my_indoor.c @@ -0,0 +1,902 @@ +#include "ac_my_indoor.h" + +#include "m_field_info.h" +#include "m_malloc.h" +#include "m_room_type.h" +#include "m_name_table.h" +#include "m_common_data.h" +#include "m_rcp.h" +#include "m_mark_room.h" +#include "sys_matrix.h" + +enum { + aMI_ROOM_KIND_S, + aMI_ROOM_KIND_M, + aMI_ROOM_KIND_L, + aMI_ROOM_KIND_LL1, + aMI_ROOM_KIND_LL2, + aMI_ROOM_KIND_BASEMENT, + + aMI_ROOM_KIND_NUM +}; + +enum { + aMI_ROOM_SIZE_S, + aMI_ROOM_SIZE_M, + aMI_ROOM_SIZE_L, + + aMI_ROOM_SIZE_NUM +}; + +typedef struct { + Gfx* floor_model; + Gfx* wall_model; +} aMI_disp_wall_floor_c; + +typedef struct { + aMI_disp_wall_floor_c main; + aMI_disp_wall_floor_c new1; + aMI_disp_wall_floor_c new2; + int size; +} aMI_size_disp_data_c; + +typedef struct { + Gfx* disp; + int _04; +} aMI_room_step_data_c; + +typedef struct { + int scene; + s16 room_kind; +} aMI_room_kind_data_c; + +extern Gfx rom_myhome1_floor_model[]; +extern Gfx rom_myhome1_wall_model[]; +extern Gfx rom_myhome1_floor_new_model[]; +extern Gfx rom_myhome1_wall_new_model[]; +extern Gfx rom_myhome1_floor_new2_model[]; +extern Gfx rom_myhome1_wall_new2_model[]; + +extern Gfx rom_myhome2B_floor_model[]; +extern Gfx rom_myhome2B_wall_model[]; +extern Gfx rom_myhome2B_floor_new_model[]; +extern Gfx rom_myhome2B_wall_new_model[]; +extern Gfx rom_myhome2B_floor_new2_model[]; +extern Gfx rom_myhome2B_wall_new2_model[]; + +extern Gfx rom_myhome3_floor_model[]; +extern Gfx rom_myhome3_wall_model[]; +extern Gfx rom_myhome3_floor_new_model[]; +extern Gfx rom_myhome3_wall_new_model[]; +extern Gfx rom_myhome3_floor_new2_model[]; +extern Gfx rom_myhome3_wall_new2_model[]; + +extern Gfx rom_myhome4_1_floor_model[]; +extern Gfx rom_myhome4_1_wall_model[]; +extern Gfx rom_myhome4_1_floor_new_model[]; +extern Gfx rom_myhome4_1_wall_new_model[]; +extern Gfx rom_myhome4_1_floor_new2_model[]; +extern Gfx rom_myhome4_1_wall_new2_model[]; + +extern Gfx rom_myhome4_2_floor_model[]; +extern Gfx rom_myhome4_2_wall_model[]; +extern Gfx rom_myhome4_2_floor_new_model[]; +extern Gfx rom_myhome4_2_wall_new_model[]; +extern Gfx rom_myhome4_2_floor_new2_model[]; +extern Gfx rom_myhome4_2_wall_new2_model[]; + +extern Gfx rom_myhome_ug_model[]; + +// clang-format off +static aMI_size_disp_data_c aMI_size_dsp_table[aMI_ROOM_KIND_NUM] = { + { + rom_myhome1_floor_model, rom_myhome1_wall_model, + rom_myhome1_floor_new_model, rom_myhome1_wall_new_model, + rom_myhome1_floor_new2_model, rom_myhome1_wall_new2_model, + aMI_ROOM_SIZE_S + }, + { + rom_myhome2B_floor_model, rom_myhome2B_wall_model, + rom_myhome2B_floor_new_model, rom_myhome2B_wall_new_model, + rom_myhome2B_floor_new2_model, rom_myhome2B_wall_new2_model, + aMI_ROOM_SIZE_M + }, + { + rom_myhome3_floor_model, rom_myhome3_wall_model, + rom_myhome3_floor_new_model, rom_myhome3_wall_new_model, + rom_myhome3_floor_new2_model, rom_myhome3_wall_new2_model, + aMI_ROOM_SIZE_L + }, + { + rom_myhome4_1_floor_model, rom_myhome4_1_wall_model, + rom_myhome4_1_floor_new_model, rom_myhome4_1_wall_new_model, + rom_myhome4_1_floor_new2_model, rom_myhome4_1_wall_new2_model, + aMI_ROOM_SIZE_L + }, + { + rom_myhome4_2_floor_model, rom_myhome4_2_wall_model, + rom_myhome4_2_floor_new_model, rom_myhome4_2_wall_new_model, + rom_myhome4_2_floor_new2_model, rom_myhome4_2_wall_new2_model, + aMI_ROOM_SIZE_M + }, + { + rom_myhome_ug_model, NULL, + rom_myhome_ug_model, NULL, + rom_myhome_ug_model, NULL, + aMI_ROOM_SIZE_L + }, +}; +// clang-format on + +extern Gfx obj_myhome_step_down_model[]; +extern Gfx obj_myhome_step_up_model[]; + +static aMI_room_step_data_c aMI_step_data[aMI_STEP_TYPE_NUM] = { + { obj_myhome_step_down_model, 0 }, + { obj_myhome_step_up_model, 0 }, + { obj_myhome_step_down_model, 0 }, + { obj_myhome_step_up_model, 0 }, +}; + +static f32 aMI_scale_x_table[aMI_STEP_TYPE_NUM] = { 1.0f, 1.0f, -1.0f, -1.0f }; + +static void My_Indoor_Actor_ct(ACTOR*, GAME*); +static void My_Indoor_Actor_dt(ACTOR*, GAME*); +static void My_Indoor_Actor_move(ACTOR*, GAME*); +static void My_Indoor_Actor_draw(ACTOR*, GAME*); + +ACTOR_PROFILE My_Indoor_Profile = { + mAc_PROFILE_MY_INDOOR, + ACTOR_PART_FG, + ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(MY_INDOOR_ACTOR), + &My_Indoor_Actor_ct, + &My_Indoor_Actor_dt, + &My_Indoor_Actor_move, + &My_Indoor_Actor_draw, + NULL, +}; + +static void aMI_DrawMyFloor(ACTOR*, GAME*); +static void aMI_DrawMyOriginalFloor(ACTOR*, GAME*); + +static void aMI_DrawMyWall(ACTOR*, GAME*); +static void aMI_DrawMyOriginalWall(ACTOR*, GAME*); + +static int aMI_GetPlayerRoomIdx(void) { + mActor_name_t field_id = mFI_GetFieldId(); + + if (mFI_GET_TYPE(field_id) == mFI_FIELD_PLAYER0_ROOM) { + return (field_id - mFI_FIELD_PLAYER0_ROOM) & 3; + } + + return 0; +} + +static void* aMI_SucureBank(u32 size, GAME_PLAY* play) { + return zelda_malloc_align(size, 32); +} + +static void aMI_GetMyIndoorBank(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int i; + + for (i = 0; i < aMI_BANK_NUM; i++) { + my_indoor->banks[i].wall_data_p = (u8*)aMI_SucureBank(aMI_WALL_BANK_SIZE, play); + } + + for (i = 0; i < aMI_BANK_NUM; i++) { + my_indoor->banks[i].floor_data_p = (u8*)aMI_SucureBank(aMI_FLOOR_BANK_SIZE, play); + } +} + +static void aMI_CopyFloorTexture(ACTOR* actorx, s16 floor_idx, s16 bank_no) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + int bank; + + if (bank_no == aMI_BANK_NUM) { + int i; + + for (i = 0; i < aMI_BANK_NUM; i++) { + mRmTp_CopyFloorData(my_indoor->banks[i].floor_data_p, floor_idx); + my_indoor->banks[i].floor_draw_proc = + FLOOR_IS_MY_ORIG(floor_idx) ? &aMI_DrawMyOriginalFloor : &aMI_DrawMyFloor; + } + } else { + bank = bank_no & 1; + mRmTp_CopyFloorData(my_indoor->banks[bank_no & 1].floor_data_p, floor_idx); + my_indoor->banks[bank].floor_draw_proc = + FLOOR_IS_MY_ORIG(floor_idx) ? &aMI_DrawMyOriginalFloor : &aMI_DrawMyFloor; + } +} + +static void aMI_CopyWallTexture(ACTOR* actorx, s16 wall_idx, s16 bank_no) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + int bank; + + if (bank_no == aMI_BANK_NUM) { + int i; + + for (i = 0; i < aMI_BANK_NUM; i++) { + mRmTp_CopyWallData(my_indoor->banks[i].wall_data_p, wall_idx); + my_indoor->banks[i].wall_draw_proc = WALL_IS_MY_ORIG(wall_idx) ? &aMI_DrawMyOriginalWall : &aMI_DrawMyWall; + } + } else { + mRmTp_CopyWallData(my_indoor->banks[bank_no & 1].wall_data_p, wall_idx); + my_indoor->banks[bank_no & 1].wall_draw_proc = + WALL_IS_MY_ORIG(wall_idx) ? &aMI_DrawMyOriginalWall : &aMI_DrawMyWall; + } +} + +static void aNI_SetFloorSE(s16 floor_idx) { + if (!(floor_idx >= 0 && floor_idx < FLOOR_PLAYER_ROOM_END) == FALSE) { + Common_Set(floor_idx, floor_idx); + } else { + Common_Set(floor_idx, FLOOR_ORIGINAL_SE); + } +} + +static void aMI_MyIndoorDma(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + + aMI_CopyWallTexture(actorx, my_indoor->wall_num, aMI_BANK_NUM); + aMI_CopyFloorTexture(actorx, my_indoor->floor_num, aMI_BANK_NUM); + + if (mSc_IS_SCENE_BASEMENT(Save_Get(scene_no))) { + Common_Set(floor_idx, FLOOR_BASEMENT); + } else { + aNI_SetFloorSE(my_indoor->floor_num); + } +} + +static mActor_name_t aMI_ChangeWall(mActor_name_t item); +static mActor_name_t aMI_ChangeCarpet(mActor_name_t item); +static void aMI_IndoorDmaAgain(void); +static void aMI_Change2Default(void); +static mActor_name_t aMI_WallIdx2ChangeWall(int idx, int is_original_flag); +static mActor_name_t aMI_FloorIdx2ChangeFloor(int idx, int is_original_flag); + +static void aMI_SetClipProc(ACTOR* actorx, int set_flag) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + + if (set_flag == FALSE) { + Common_Get(clip).my_indoor_clip = NULL; + } else { + aMI_Clip_c* clip = &my_indoor->clip; + + Common_Get(clip).my_indoor_clip = clip; + + clip->my_indoor_actor_p = my_indoor; + clip->change_wall_proc = &aMI_ChangeWall; + clip->change_carpet_proc = &aMI_ChangeCarpet; + clip->indoor_dma_again_proc = &aMI_IndoorDmaAgain; + clip->change_2_default_proc = &aMI_Change2Default; + clip->wall_idx_2_change_wall_proc = &aMI_WallIdx2ChangeWall; + clip->floor_idx_2_change_floor_proc = &aMI_FloorIdx2ChangeFloor; + } +} + +static s16 aMR_GetSceneRoomKind(void) { + static aMI_room_kind_data_c room_kind_data[] = { + { SCENE_MY_ROOM_S, aMI_ROOM_KIND_S }, + { SCENE_MY_ROOM_M, aMI_ROOM_KIND_M }, + { SCENE_MY_ROOM_L, aMI_ROOM_KIND_L }, + { SCENE_MY_ROOM_LL1, aMI_ROOM_KIND_LL1 }, + { SCENE_MY_ROOM_LL2, aMI_ROOM_KIND_LL2 }, + { SCENE_MY_ROOM_BASEMENT_S, aMI_ROOM_KIND_BASEMENT }, + { SCENE_MY_ROOM_BASEMENT_M, aMI_ROOM_KIND_BASEMENT }, + { SCENE_MY_ROOM_BASEMENT_L, aMI_ROOM_KIND_BASEMENT }, + { SCENE_COTTAGE_MY, aMI_ROOM_KIND_L }, + { SCENE_MY_ROOM_BASEMENT_LL1, aMI_ROOM_KIND_BASEMENT }, + { -1, 0 }, + }; + + aMI_room_kind_data_c* room_kind_p = room_kind_data; + int scene = Save_Get(scene_no); + + while (room_kind_p->scene != -1) { + if (scene == room_kind_p->scene) { + return room_kind_p->room_kind; + } + + room_kind_p++; + } + + return aMI_ROOM_KIND_S; +} + +static void aMI_CheckFloorWallIndex(s16* wall_idx, s16* floor_idx) { + if (!(*floor_idx >= 0 && *floor_idx < FLOOR_ETC_START) && !FLOOR_IS_MY_ORIG(*floor_idx)) { + *floor_idx = 0; + } + + if (!(*wall_idx >= 0 && *wall_idx < WALL_ETC_START) && !WALL_IS_MY_ORIG(*wall_idx)) { + *wall_idx = 0; + } +} + +static void aMI_MakeStepData(MY_INDOOR_ACTOR* my_indoor, int house_idx) { + if (Save_Get(scene_no) == SCENE_MY_ROOM_M || Save_Get(scene_no) == SCENE_MY_ROOM_L || + Save_Get(scene_no) == SCENE_MY_ROOM_LL1) { + if (Save_Get(homes[house_idx]).flags.has_basement) { + my_indoor->room_step[0] = TRUE; + } + } + + if (Save_Get(scene_no) == SCENE_MY_ROOM_LL1) { + my_indoor->room_step[1] = TRUE; + } + + if (Save_Get(scene_no) == SCENE_MY_ROOM_LL2) { + my_indoor->room_step[2] = TRUE; + } + + if (mFI_GetPlayerHouseFloorNo(Save_Get(scene_no)) == 2) { + my_indoor->room_step[3] = TRUE; + } +} + +static void aMI_InitActorMember(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + int floor_no = mFI_GetPlayerHouseFloorNo(Save_Get(scene_no)); + int player_room_idx = aMI_GetPlayerRoomIdx(); + int now_floor_no; + + my_indoor->room_kind = aMR_GetSceneRoomKind(); + now_floor_no = mFI_GetNowPlayerHouseFloorNo(); + my_indoor->house_floor_no = now_floor_no; + + if (now_floor_no == -1) { + my_indoor->house_floor_no = 0; + } + + if (Save_Get(scene_no) == SCENE_COTTAGE_MY) { + my_indoor->floor_num = Save_Get(island).cottage.room.wall_floor.flooring_idx; + my_indoor->wall_num = Save_Get(island).cottage.room.wall_floor.wallpaper_idx; + my_indoor->wall_is_original_design = FALSE; + my_indoor->floor_is_original_design = FALSE; + } else { + my_indoor->floor_num = + Save_Get(homes[player_room_idx]).floors[my_indoor->house_floor_no].wall_floor.flooring_idx; + my_indoor->wall_num = + Save_Get(homes[player_room_idx]).floors[my_indoor->house_floor_no].wall_floor.wallpaper_idx; + my_indoor->floor_is_original_design = mRmTp_GetNowSceneOriginalFloorStatus(); + my_indoor->wall_is_original_design = mRmTp_GetNowSceneOriginalWallStatus(); + } + + aMI_CheckFloorWallIndex(&my_indoor->wall_num, &my_indoor->floor_num); + aMI_MakeStepData(my_indoor, player_room_idx); +} + +static void My_Indoor_Actor_ct(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + + aMI_InitActorMember(actorx, game); + aMI_GetMyIndoorBank(actorx, game); + aMI_MyIndoorDma(actorx, game); + aMI_SetClipProc(actorx, TRUE); +} + +static void My_Indoor_Actor_dt(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + int i; + + aMI_SetClipProc(actorx, FALSE); + + for (i = 0; i < aMI_BANK_NUM; i++) { + if (my_indoor->banks[i].wall_data_p != NULL) { + zelda_free(my_indoor->banks[i].wall_data_p); + } + + if (my_indoor->banks[i].floor_data_p != NULL) { + zelda_free(my_indoor->banks[i].floor_data_p); + } + } +} + +static void aMI_DrawMyStep(ACTOR* actorx, GAME* game) { + static xyz_t step_draw_pos[aMI_ROOM_SIZE_NUM] = { + { 120.0f, 40.0f, 220.0f }, + { 160.0f, 40.0f, 300.0f }, + { 200.0f, 40.0f, 380.0f }, + }; + + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int i; + + Global_kankyo_set_room_prim(play); + _texture_z_light_fog_prim(game->graph); + + for (i = 0; i < aMI_STEP_TYPE_NUM; i++) { + if (my_indoor->room_step[i] != FALSE) { + int size = aMI_size_dsp_table[my_indoor->room_kind].size; + + if (size >= 0 && size < aMI_ROOM_SIZE_NUM) { + GRAPH* graph = game->graph; + xyz_t* pos = &step_draw_pos[size]; + + OPEN_DISP(graph); + + Matrix_translate(pos->x, pos->y, pos->z, 0); + Matrix_scale(aMI_scale_x_table[i] * 0.01f, 0.01f, 0.01f, 1); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(NEXT_POLY_OPA_DISP, aMI_step_data[i].disp); + + CLOSE_DISP(graph); + } + } + } +} + +static void aMI_DrawMyFloor(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + GRAPH* graph; + aMI_bank_c* bank = &my_indoor->banks[my_indoor->floor_bank_idx]; + u8* data_p = bank->floor_data_p; + u8* tex0 = data_p + aMI_PAL_SIZE + 0 * aMI_TEX_SIZE; + u8* tex1 = data_p + aMI_PAL_SIZE + 1 * aMI_TEX_SIZE; + u8* tex2 = data_p + aMI_PAL_SIZE + 2 * aMI_TEX_SIZE; + u8* tex3 = data_p + aMI_PAL_SIZE + 3 * aMI_TEX_SIZE; + aMI_disp_wall_floor_c* disp_info = &aMI_size_dsp_table[my_indoor->room_kind].main; + + Global_kankyo_set_room_prim(play); + + if (disp_info->floor_model != NULL) { + graph = game->graph; + + _texture_z_light_fog_prim(graph); + Matrix_translate(0.0f, 0.0f, 0.0f, 0); + Matrix_scale(0.0625f, 0.0625f, 0.0625f, 1); + + OPEN_DISP(graph); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + // Set segment 8-B to the four floor textures + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_8, tex0); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, tex1); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_A, tex2); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_B, tex3); + + // Set segment C to the palette + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_C, data_p); + + // Draw model + gSPDisplayList(NEXT_POLY_OPA_DISP, disp_info->floor_model); + + CLOSE_DISP(graph); + } +} + +typedef struct { + int shift_s; + int shift_t; +} aMI_wrapmirror_shift_c; + +static aMI_wrapmirror_shift_c wrapmirror_floor_shift_s[4] = { + { 0, 32 }, + { -32, 32 }, + { 0, 0 }, + { -32, 0 }, +}; + +static aMI_wrapmirror_shift_c wrapmirror_floor_shift_m[4] = { + { 0, 33 }, + { 16, 33 }, + { 0, 49 }, + { 16, 49 }, +}; + +static aMI_wrapmirror_shift_c wrapmirror_floor_shift_l[4] = { + { 0, 32 }, + { 0, 32 }, + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_shift_c* wrapmirror_floor_shift_table[] = { + wrapmirror_floor_shift_s, wrapmirror_floor_shift_m, wrapmirror_floor_shift_l, + wrapmirror_floor_shift_l, wrapmirror_floor_shift_m, wrapmirror_floor_shift_s, +}; + +typedef struct { + int scale_s; + int scale_t; +} aMI_wrapmirror_scale_c; + +static aMI_wrapmirror_scale_c scale_floor_shift_s[4] = { + { 0, 32 }, + { -32, 32 }, + { 0, 0 }, + { -32, 0 }, +}; + +static aMI_wrapmirror_scale_c scale_floor_shift_m[4] = { + { 0, 33 }, + { 16, 33 }, + { 0, 17 }, + { 16, 17 }, +}; + +static aMI_wrapmirror_scale_c scale_floor_shift_l[4] = { + { 0, 32 }, + { 0, 32 }, + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_scale_c* scale_floor_shift_table[] = { + scale_floor_shift_s, scale_floor_shift_m, scale_floor_shift_l, + scale_floor_shift_l, scale_floor_shift_m, scale_floor_shift_s, +}; + +static aMI_wrapmirror_shift_c wrapmirror_wall_shift_s[2] = { + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_shift_c wrapmirror_wall_shift_m[2] = { + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_shift_c wrapmirror_wall_shift_l[2] = { + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_shift_c* wrapmirror_wall_shift_table[] = { + wrapmirror_wall_shift_s, wrapmirror_wall_shift_m, wrapmirror_wall_shift_l, + wrapmirror_wall_shift_l, wrapmirror_wall_shift_m, wrapmirror_wall_shift_s, +}; + +static aMI_wrapmirror_scale_c scale_wall_shift_s[2] = { + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_scale_c scale_wall_shift_m[2] = { + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_scale_c scale_wall_shift_l[2] = { + { 0, 32 }, + { 0, 32 }, +}; + +static aMI_wrapmirror_scale_c* scale_wall_shift_table[] = { + scale_wall_shift_s, scale_wall_shift_m, scale_wall_shift_l, + scale_wall_shift_l, scale_wall_shift_m, scale_wall_shift_s, +}; + +/* @unused int aMI_GetTextureMode(...?) */ + +static void aMI_DrawMyOriginalFloor(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + aMI_disp_wall_floor_c* disp; + GRAPH* graph; + aMI_bank_c* bank = &my_indoor->banks[my_indoor->floor_bank_idx]; + u8* data_p = bank->floor_data_p; + u8* tex0 = data_p + aMI_PAL_SIZE + 0 * aMI_TEX_SIZE; + u8* tex1 = data_p + aMI_PAL_SIZE + 1 * aMI_TEX_SIZE; + u8* tex2 = data_p + aMI_PAL_SIZE + 2 * aMI_TEX_SIZE; + u8* tex3 = data_p + aMI_PAL_SIZE + 3 * aMI_TEX_SIZE; + + if (my_indoor->floor_is_original_design == FALSE) { + disp = &aMI_size_dsp_table[my_indoor->room_kind].new1; + } else { + disp = &aMI_size_dsp_table[my_indoor->room_kind].new2; + } + + Global_kankyo_set_room_prim((GAME_PLAY*)game); + + if (disp->floor_model != NULL) { + graph = game->graph; + + _texture_z_light_fog_prim(graph); + Matrix_translate(0.0f, 0.0f, 0.0f, 0); + Matrix_scale(0.0625f, 0.0625f, 0.0625f, 1); + + OPEN_DISP(graph); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + // Set segment 8-B to the four floor textures + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_8, tex0); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, tex1); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_A, tex2); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_B, tex3); + + // Set segment C to the palette + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_C, data_p); + + // Draw model + gSPDisplayList(NEXT_POLY_OPA_DISP, disp->floor_model); + + CLOSE_DISP(graph); + } +} + +static void aMI_DrawMyWall(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + GRAPH* graph; + aMI_bank_c* bank = &my_indoor->banks[my_indoor->wall_bank_idx]; + u8* data_p = bank->wall_data_p; + int room_kind = my_indoor->room_kind; + u8* tex0 = data_p + aMI_PAL_SIZE + 0 * aMI_TEX_SIZE; + u8* tex1 = data_p + aMI_PAL_SIZE + 1 * aMI_TEX_SIZE; + aMI_disp_wall_floor_c* disp_info = &aMI_size_dsp_table[my_indoor->room_kind].main; + + Global_kankyo_set_room_prim(play); + + if (disp_info->wall_model != NULL) { + graph = game->graph; + + _texture_z_light_fog_prim(graph); + Matrix_translate(0.0f, 0.0f, 0.0f, 0); + Matrix_scale(0.0625f, 0.0625f, 0.0625f, 1); + + OPEN_DISP(graph); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + // Set segment 8-9 to the two wall textures + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_8, tex0); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, tex1); + + // Set segment A to the palette + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_A, data_p); + + // Draw model + gSPDisplayList(NEXT_POLY_OPA_DISP, disp_info->wall_model); + + CLOSE_DISP(graph); + } +} + +static void aMI_DrawMyOriginalWall(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + aMI_disp_wall_floor_c* disp; + GRAPH* graph; + aMI_bank_c* bank = &my_indoor->banks[my_indoor->wall_bank_idx]; + u8* data_p = bank->wall_data_p; + u8* tex0 = data_p + aMI_PAL_SIZE + 0 * aMI_TEX_SIZE; + u8* tex1 = data_p + aMI_PAL_SIZE + 1 * aMI_TEX_SIZE; + + if (my_indoor->wall_is_original_design == FALSE) { + disp = &aMI_size_dsp_table[my_indoor->room_kind].new1; + } else { + disp = &aMI_size_dsp_table[my_indoor->room_kind].new2; + } + + Global_kankyo_set_room_prim((GAME_PLAY*)game); + + if (disp->wall_model != NULL) { + graph = game->graph; + + _texture_z_light_fog_prim(graph); + Matrix_translate(0.0f, 0.0f, 0.0f, 0); + Matrix_scale(0.0625f, 0.0625f, 0.0625f, 1); + + OPEN_DISP(graph); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + // Set segment 8-9 to the two wall textures + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_8, tex0); + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, tex1); + + // Set segment A to the palette + gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_A, data_p); + + // Draw model + gSPDisplayList(NEXT_POLY_OPA_DISP, disp->wall_model); + + CLOSE_DISP(graph); + } +} + +static void My_Indoor_Actor_draw(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + + // Draw the wall + (*my_indoor->banks[my_indoor->wall_bank_idx & 1].wall_draw_proc)(actorx, game); + + // Draw the floor + (*my_indoor->banks[my_indoor->floor_bank_idx & 1].floor_draw_proc)(actorx, game); + + // Draw stairs + aMI_DrawMyStep(actorx, game); +} + +static void aMI_Change2ReservedWall(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + if (my_indoor->wall_reserve.reserve_flag && play->submenu.process_status == mSM_PROCESS_WAIT) { + my_indoor->wall_reserve.reserve_flag = FALSE; + + if (Common_Get(field_type) == mFI_FIELDTYPE2_PLAYER_ROOM) { + int player_room_idx = aMI_GetPlayerRoomIdx(); + int bank_idx = my_indoor->wall_bank_idx; + + my_indoor->wall_num = my_indoor->wall_reserve.idx; + my_indoor->wall_bank_idx = (bank_idx ^ 1) & 1; + my_indoor->wall_is_original_design = my_indoor->wall_reserve.is_original_flag; + + aMI_CopyWallTexture(actorx, my_indoor->wall_num, my_indoor->wall_bank_idx); + + if (Save_Get(scene_no) == SCENE_COTTAGE_MY) { + Save_Get(island).cottage.room.wall_floor.wallpaper_idx = my_indoor->wall_num; + } else { + Save_Get(homes[player_room_idx]).floors[my_indoor->house_floor_no].wall_floor.wallpaper_idx = + my_indoor->wall_num; + mRmTp_SetNowSceneOriginalWallStatus((u8)my_indoor->wall_is_original_design); + } + + mMkRm_ReportChangePlayerRoom(); + sAdo_SysTrgStart(0x11B); + } + } +} + +static void aMI_Change2ReservedFloor(ACTOR* actorx, GAME* game) { + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + if (my_indoor->floor_reserve.reserve_flag && play->submenu.process_status == mSM_PROCESS_WAIT) { + my_indoor->floor_reserve.reserve_flag = FALSE; + + if (Common_Get(field_type) == mFI_FIELDTYPE2_PLAYER_ROOM) { + int player_room_idx = aMI_GetPlayerRoomIdx(); + int bank_idx = my_indoor->floor_bank_idx; + + my_indoor->floor_num = my_indoor->floor_reserve.idx; + my_indoor->floor_bank_idx = (bank_idx ^ 1) & 1; + my_indoor->floor_is_original_design = my_indoor->floor_reserve.is_original_flag; + + aMI_CopyFloorTexture(actorx, my_indoor->floor_num, my_indoor->floor_bank_idx); + + if (Save_Get(scene_no) == SCENE_COTTAGE_MY) { + Save_Get(island).cottage.room.wall_floor.flooring_idx = my_indoor->floor_num; + } else { + Save_Get(homes[player_room_idx]).floors[my_indoor->house_floor_no].wall_floor.flooring_idx = + my_indoor->floor_num; + mRmTp_SetNowSceneOriginalFloorStatus(my_indoor->floor_is_original_design); + } + + aNI_SetFloorSE(my_indoor->floor_num); + sAdo_SysTrgStart(0x11B); + mMkRm_ReportChangePlayerRoom(); + } + } +} + +static void My_Indoor_Actor_move(ACTOR* actorx, GAME* game) { + aMI_Change2ReservedWall(actorx, game); + aMI_Change2ReservedFloor(actorx, game); +} + +static mActor_name_t aMI_ChangeCarpet(mActor_name_t item) { + mActor_name_t old_floor; + + // Do not allow changing the floor in the basement + if (mFI_GetNowPlayerHouseFloorNo() == 2) { + return EMPTY_NO; + } + + if (Common_Get(clip).my_indoor_clip != NULL && + (item >= ITM_CARPET00 && item < (ITM_CARPET00 + FLOOR_PLAYER_ROOM_END))) { + MY_INDOOR_ACTOR* my_indoor = Common_Get(clip).my_indoor_clip->my_indoor_actor_p; + + if (my_indoor != NULL && my_indoor->floor_reserve.reserve_flag == FALSE) { + old_floor = ITM_CARPET00 + my_indoor->floor_num; + my_indoor->floor_reserve.reserve_flag = TRUE; + my_indoor->floor_reserve.idx = item - ITM_CARPET00; + my_indoor->floor_reserve.is_original_flag = FALSE; + + return old_floor; + } + } + + return EMPTY_NO; +} + +static mActor_name_t aMI_FloorIdx2ChangeFloor(int idx, int is_original_flag) { + MY_INDOOR_ACTOR* my_indoor = Common_Get(clip).my_indoor_clip->my_indoor_actor_p; + mActor_name_t old_floor; + + if (my_indoor != NULL) { + old_floor = ITM_CARPET00 + my_indoor->floor_num; + + if (mFI_GetNowPlayerHouseFloorNo() != 2 && my_indoor->floor_reserve.reserve_flag == FALSE) { + my_indoor->floor_reserve.reserve_flag = TRUE; + my_indoor->floor_reserve.idx = idx; + my_indoor->floor_reserve.is_original_flag = is_original_flag; + + // Don't give 'original design' items back + if (FLOOR_IS_MY_ORIG(my_indoor->floor_num)) { + return EMPTY_NO; + } + + return old_floor; + } + } + + return EMPTY_NO; +} + +static mActor_name_t aMI_ChangeWall(mActor_name_t item) { + mActor_name_t old_wall; + + // Do not allow changing the wall in the basement + if (mFI_GetNowPlayerHouseFloorNo() == 2) { + return EMPTY_NO; + } + + if (Common_Get(clip).my_indoor_clip != NULL) { + MY_INDOOR_ACTOR* my_indoor = Common_Get(clip).my_indoor_clip->my_indoor_actor_p; + + if (my_indoor != NULL && (item >= ITM_WALL00 && item < (ITM_WALL00 + WALL_ETC_END)) && + my_indoor->wall_reserve.reserve_flag == FALSE) { + old_wall = ITM_WALL00 + my_indoor->wall_num; + my_indoor->wall_reserve.reserve_flag = TRUE; + my_indoor->wall_reserve.idx = item - ITM_WALL00; + my_indoor->wall_reserve.is_original_flag = FALSE; + + return old_wall; + } + } + + return EMPTY_NO; +} + +static mActor_name_t aMI_WallIdx2ChangeWall(int idx, int is_original_flag) { + MY_INDOOR_ACTOR* my_indoor = Common_Get(clip).my_indoor_clip->my_indoor_actor_p; + mActor_name_t wall_floor; + + if (my_indoor != NULL) { + wall_floor = ITM_WALL00 + my_indoor->wall_num; + + if (mFI_GetNowPlayerHouseFloorNo() != 2 && my_indoor->wall_reserve.reserve_flag == FALSE) { + my_indoor->wall_reserve.reserve_flag = TRUE; + my_indoor->wall_reserve.idx = idx; + my_indoor->wall_reserve.is_original_flag = is_original_flag; + + // Don't give 'original design' items back + if (WALL_IS_MY_ORIG(my_indoor->wall_num)) { + return EMPTY_NO; + } + + return wall_floor; + } + } + + return EMPTY_NO; +} + +static void aMI_Change2Default(void) { + aMI_ChangeWall(ITM_WALL00); + aMI_ChangeCarpet(ITM_CARPET00); +} + +static void aMI_IndoorDmaAgain(void) { + if (Common_Get(clip).my_indoor_clip != NULL) { + ACTOR* actorx = (ACTOR*)Common_Get(clip).my_indoor_clip->my_indoor_actor_p; + MY_INDOOR_ACTOR* my_indoor = (MY_INDOOR_ACTOR*)actorx; + + if (my_indoor != NULL) { + aMI_CopyWallTexture(actorx, my_indoor->wall_num, aMI_BANK_NUM); + aMI_CopyFloorTexture(actorx, my_indoor->floor_num, aMI_BANK_NUM); + } + } +}