#include "m_field_make.h" #include "m_island.h" #include "m_name_table.h" #include "m_common_data.h" #include "m_room_type.h" #include "m_scene_table.h" #include "m_random_field.h" #include "m_soncho.h" #include "jsyswrap.h" #include "m_malloc.h" #include "libultra/libultra.h" #include "m_bg_tex.h" #include "m_house.h" #include "m_bgm.h" static mActor_name_t l_fg_outer_fill[UT_Z_NUM * UT_X_NUM] = { RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO, RSV_NO }; static mActor_name_t l_title_demo_fg[(BLOCK_Z_NUM - 2) * BLOCK_X_NUM] = { 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00DD, 0x00AB, 0x00CC, 0x00E5, 0x002E, 0x00CB, 0x00CB, 0x0174, 0x0030, 0x0069, 0x0088, 0x017C, 0x00CB, 0x00CB, 0x0055, 0x0176, 0x0046, 0x0179, 0x0045, 0x00CB, 0x00CB, 0x0175, 0x003F, 0x0029, 0x017A, 0x017D, 0x00CB, 0x00CB, 0x006A, 0x00AC, 0x0178, 0x0068, 0x017E, 0x00CB, 0x00CB, 0x0061, 0x0177, 0x0062, 0x017B, 0x0064, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB, 0x00CB }; typedef struct police_pos_s { int bx; int bz; int ut_x; int ut_z; } mFM_police_pos_c; static mFM_police_pos_c l_mfm_police_pos = { 0, 0, 0, 0 }; int l_bg_disp_num = 0; int l_bg_disp_size = 0; static u16 mFM_pal_area[11][16] ATTRIBUTE_ALIGN(32); mFM_fdinfo_c* g_fdinfo; static u8 l_block_type[BLOCK_TOTAL_NUM]; static int l_block_kind[BLOCK_TOTAL_NUM]; static void mFM_SortBGData(mFM_bg_data_c** sorted_data_p, mFM_bg_data_c* data, int count) { mFM_bg_data_c** sorted_data_p_copy = sorted_data_p; int i; for (i = 0; i < mFM_BG_ID_MAX; i++) { sorted_data_p_copy[0] = NULL; sorted_data_p_copy++; } for (i = 0; i < count; i++) { if (data->bg_id <= mFM_BG_ID_MAX) { sorted_data_p[data->bg_id] = data; } data++; } } static void mFM_SortFGData(mFM_fg_data_c** sorted_data_p, mFM_fg_data_c* data, int count, int list_size, int name_start) { mFM_fg_data_c** sorted_data_p_copy = sorted_data_p; int i; for (i = 0; i < count; i++) { sorted_data_p_copy[0] = NULL; sorted_data_p_copy++; } for (i = 0; i < list_size; i++) { int fg_idx = data->fg_id - name_start; if (fg_idx < 0) { fg_idx = 0; } sorted_data_p[fg_idx] = data; data++; } } static void mFM_BgUtDataSet(mCoBG_Collision_u* collision, u8* keep, mCoBG_Collision_u* data) { int ut_x; int ut_z; for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { collision[0] = data[0]; keep[0] = data[0].data.center; collision++; data++; keep++; } } } static void mFM_FgUtDataSet(mActor_name_t* fg, mActor_name_t* data) { int ut_x; int ut_z; for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) { for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) { fg[0] = data[0]; fg++; data++; } } } static void mFM_SetFgUtPtoSaveData(mFM_block_info_c* block_info, u8 bx_max, u8 bz_max, int* island_block_x) { int bz; int bx; for (bz = 0; bz < bz_max; bz++) { for (bx = 0; bx < bx_max; bx++) { if (bz > 0 && bz < (bz_max - 1) && bx > 0 && bx < (bx_max - 1)) { if (bx == island_block_x[0] && bz == mISL_BLOCK_Z) { block_info->fg_info.items_p = Save_Get(island.fgblock[0][0]).items[0]; } else if (bx == island_block_x[1] && bz == mISL_BLOCK_Z) { block_info->fg_info.items_p = Save_Get(island.fgblock[0][1]).items[0]; } else if (bz >= (bz_max - 3)) { block_info->fg_info.items_p = l_fg_outer_fill; } else { block_info->fg_info.items_p = Save_Get(fg[bz - 1][bx - 1]).items[0]; } } else { block_info->fg_info.items_p = l_fg_outer_fill; } block_info++; } } } static void mFM_SetFgUtPtoHomeInfo(mFM_block_info_c* block_info, u8 bx_max, u8 bz_max, mActor_name_t house_no, int floor) { int bx; int bz; for (bz = 0; bz < bz_max; bz++) { for (bx = 0; bx < bx_max; bx++) { block_info->fg_info.items_p = Save_Get(homes[house_no]).floors[floor].layer_main.items[0]; block_info++; } } } static void mFM_SetFgUtPtoCottageInfo(mFM_block_info_c* block_info, u8 bx_max, u8 bz_max) { int bx; int bz; for (bz = 0; bz < bz_max; bz++) { for (bx = 0; bx < bx_max; bx++) { block_info->fg_info.items_p = Save_Get(island).cottage.room.layer_main.items[0]; block_info++; } } } static void mFM_ChangeFGName(mActor_name_t* fg_name_p, mActor_name_t fg_name, mActor_name_t field_name, int block) { mActor_name_t house_owner_name = Common_Get(house_owner_name); if (Save_Get(scene_no) == SCENE_COTTAGE_NPC) { fg_name_p[0] = Common_Get(island_npclist[0]).house_data.main_layer_id; } else if (field_name == mFI_FIELD_NPCROOM0 && ITEM_NAME_GET_TYPE(house_owner_name) == NAME_TYPE_NPC) { int npc_idx = mNpc_SearchAnimalinfo(Save_Get(animals), house_owner_name, ANIMAL_NUM_MAX); mNpc_NpcList_c* list = Common_GetPointer(npclist[npc_idx]); fg_name_p[0] = list->house_data.main_layer_id; } else if (mFI_CheckShopFieldName(field_name)) { fg_name_p[0] = mSP_GetNowShopFgNum(); } else if (Save_Get(scene_no) == SCENE_FIELD_TOOL || Save_Get(scene_no) == SCENE_TITLE_DEMO) { fg_name_p[0] = l_title_demo_fg[block]; } else { fg_name_p[0] = fg_name; } } static void mFM_ChangeBGName(mActor_name_t* bg_name_p, mActor_name_t bg_name, mActor_name_t field_name) { if (mFI_CheckShopFieldName(field_name)) { bg_name_p[0] = mSP_GetNowShopBgNum(); } else if (mFI_GET_TYPE(field_name) == mFI_FIELD_PLAYER0_ROOM) { bg_name_p[0] = mRmTp_GetPlayerRoomCollisionIdx(field_name, bg_name); } else { bg_name_p[0] = bg_name; } } static void mFM_SetSoundSource(mFM_bg_sound_source_c* sound_source, mFM_bg_sound_source_data_c* data, int count, int bx, int bz) { int i; for (i = 0; i != count; i++) { sound_source->kind = data->kind; sound_source->pos.x = data->ut_x * mFI_UT_WORLDSIZE_X_F; sound_source->pos.x += bx * mFI_BK_WORLDSIZE_X_F + mFI_UT_WORLDSIZE_HALF_X_F; sound_source->pos.y = 0.0f; sound_source->pos.z = data->ut_z * mFI_UT_WORLDSIZE_Z_F; sound_source->pos.z += bz * mFI_BK_WORLDSIZE_Z_F + mFI_UT_WORLDSIZE_HALF_Z_F; data++; sound_source++; } } static void mFM_SetBG(mFM_bg_info_c* bg_info, mFM_bg_data_c* bg_data, u16 height, u8 type, mActor_name_t bg_name, int block_x, int block_z) { bg_info->bg_id.height = height; bg_info->bg_id.combination_type = bg_name; bg_info->opaque_gfx = bg_data->opaque_gfx; bg_info->translucent_gfx = bg_data->translucent_gfx; bg_info->animation = bg_data->animation; bg_info->animation_count = bg_data->animation_count; bg_info->rom_start_addr = bg_data->rom_start_addr; bg_info->rom_size = bg_data->rom_end_addr - bg_data->rom_start_addr; bg_info->block_type = type; bg_info->block_kind = mRF_Type2BlockInfo(type); mFM_SetSoundSource(bg_info->sound_source, bg_data->sound_source, mFM_SOUND_SOURCE_NUM, block_x, block_z); mFM_BgUtDataSet(bg_info->collision[0], bg_info->keep_h[0], bg_data->collision[0]); } static void mFM_SetFG(mFM_fg_info_c* fg_info, mFM_fg_data_c* data, mActor_name_t fg_name) { int scene; int i; fg_info->fg_id = fg_name; fg_info->move_actor_bit_data = 0; scene = Save_Get(scene_no); if ( scene != SCENE_FG && scene != SCENE_MY_ROOM_S && scene != SCENE_MY_ROOM_M && scene != SCENE_MY_ROOM_L && scene != SCENE_MY_ROOM_LL1 && scene != SCENE_MY_ROOM_LL2 && scene != SCENE_MY_ROOM_BASEMENT_S && scene != SCENE_MY_ROOM_BASEMENT_M && scene != SCENE_MY_ROOM_BASEMENT_L && scene != SCENE_MY_ROOM_BASEMENT_LL1 && scene != SCENE_COTTAGE_MY ) { if (scene == SCENE_COTTAGE_NPC) { if (mNpc_GetIslandRoomFtrNum() > 0) { mFM_FgUtDataSet(fg_info->items_p, mNpc_GetIslandRoomP(Save_Get(island).animal.id.npc_id)); mNpc_ChangeIslandRoom(fg_info->items_p); } else { mFM_FgUtDataSet(fg_info->items_p, data->items[0]); } if (fg_info != NULL && fg_info->items_p != NULL) { mActor_name_t* items_p = fg_info->items_p; items_p[(8 << 4) | 3] = EXIT_DOOR; items_p[(8 << 4) | 4] = EXIT_DOOR; } } else { mFM_FgUtDataSet(fg_info->items_p, data->items[0]); } } for (i = 0; i < mFM_HANIWA_STEP_NUM; i++) { fg_info->haniwa_step[i] = data->haniwa_step[i]; } } static void mFM_SetFG2(mActor_name_t* items_p, mFM_fg_data_c** data, mActor_name_t field_name, int name_start) { mActor_name_t house_owner_name = Common_Get(house_owner_name); if (items_p != NULL && Save_Get(scene_no) == SCENE_COTTAGE_NPC) { int idx = mFM_FG2_ID_MAX; idx -= name_start; if (idx < 0) { idx = 0; } if (data[idx] != NULL) { mFM_FgUtDataSet(items_p, data[idx]->items[0]); } } else { if (items_p != NULL && field_name == mFI_FIELD_NPCROOM0 && ITEM_NAME_GET_TYPE(house_owner_name) == NAME_TYPE_NPC) { int anm_idx = mNpc_SearchAnimalinfo(Save_Get(animals), house_owner_name, ANIMAL_NUM_MAX); mNpc_NpcList_c* npc_list = Common_GetPointer(npclist[anm_idx]); int secondary_idx = npc_list->house_data.secondary_layer_id - name_start; if (secondary_idx < 0) { secondary_idx = 0; } if (data[secondary_idx] != NULL) { mFM_FgUtDataSet(items_p, data[secondary_idx]->items[0]); } } } } static void mFM_BlockDataSet( mActor_name_t field_name, mFM_block_info_c* block_info, mFM_combination_c* save_combi_table, mFM_bg_data_c** bg_data_list, mFM_fg_data_c** fg_data_list, mFM_combo_info_c* data_combi_table, int bx_max, int bz_max, int name_start ) { mFM_combo_info_c* combi; mActor_name_t bg_name; mActor_name_t fg_name; int fg_idx; int i; int bx = 0; int bz = 0; int max = bz_max * bx_max; for (i = 0; i < max; i++) { combi = &data_combi_table[save_combi_table[0].combination_type]; mFM_ChangeFGName(&fg_name, combi->fg_id, field_name, i); mFM_ChangeBGName(&bg_name, combi->bg_id, field_name); if (bg_name > mFM_BG_ID_MAX) { bg_name = 0; } if (fg_name > mFM_FG_ID_MAX) { fg_name = 0; } fg_idx = fg_name - name_start; if (fg_idx < 0) { fg_idx = 0; } if (bg_data_list[bg_name] != NULL && fg_data_list[fg_idx]) { mFM_SetBG(&block_info->bg_info, bg_data_list[bg_name], save_combi_table[0].height, combi->type, bg_name, bx, bz); mFM_SetFG(&block_info->fg_info, fg_data_list[fg_idx], fg_name); } bx++; if (bx >= bx_max) { bx = 0; bz++; } block_info++; save_combi_table++; } } static void mFM_KeepPolicePos(int bx, int bz, int ut_x, int ut_z) { l_mfm_police_pos.bx = bx; l_mfm_police_pos.bz = bz; l_mfm_police_pos.ut_x = ut_x; l_mfm_police_pos.ut_z = ut_z; } extern void mFM_GetPolicePos(int* bx, int* bz, int* ut_x, int* ut_z) { *bx = l_mfm_police_pos.bx; *bz = l_mfm_police_pos.bz; *ut_x = l_mfm_police_pos.ut_x; *ut_z = l_mfm_police_pos.ut_z; } static void mFM_SetMoveActorInfo(mFM_block_info_c* block_info, int bx_max, int bz_max, mFM_move_actor_data_c* move_actor_data, u32 param_5, u32 param_6) { mFM_move_actor_data_c* move_ac_data_p = move_actor_data; if (block_info != NULL) { for (move_ac_data_p; move_ac_data_p != NULL && move_ac_data_p->name_id != RSV_NO; move_ac_data_p++) { int block = -1; int ut_x; int ut_z; ut_x = move_ac_data_p->ut_x; ut_z = move_ac_data_p->ut_z; if (move_ac_data_p->desired_block_kind == mRF_BLOCKKIND_NONE) { block = move_ac_data_p->block_x + move_ac_data_p->block_z * bx_max; } else { int bx; int bz; if (mFI_BlockKind2BkNum(&bx, &bz, move_ac_data_p->desired_block_kind) == TRUE) { block = bx + bz * bx_max; switch (move_ac_data_p->name_id) { case SP_NPC_POLICE: { mActor_name_t* items = block_info[block].fg_info.items_p; int i; for (i = 0; i < UT_TOTAL_NUM; i++) { if (items[0] == POLICE_STATION) { ut_x = i % UT_X_NUM; ut_z = i / UT_Z_NUM; ut_x += 2; mFM_KeepPolicePos(bx, bz, ut_x, ut_z); break; } items++; } break; } case SP_NPC_SONCHO: { if (mEv_CheckFirstJob() == FALSE || (mSC_check_ArbeitPlayer() && mSC_LightHouse_travel_check())) { block = -1; } break; } } } } if (block != -1) { mFM_move_actor_c* move_actor = block_info[block].fg_info.move_actors; int free_idx = mFI_GetMoveActorListIdx(move_actor, mFM_MOVE_ACTOR_NUM, EMPTY_NO); if (free_idx != -1) { move_actor[free_idx].name_id = move_ac_data_p->name_id; move_actor[free_idx].ut_x = ut_x; move_actor[free_idx].ut_z = ut_z; move_actor[free_idx].npc_info_idx = move_ac_data_p->npc_info_idx; move_actor[free_idx].arg = move_ac_data_p->arg; } } } } } static void mFM_SetCombiTable(mFM_combination_c* combi_table, mFM_combination_c* combi_id, u8 bx_max, u8 bz_max) { u8 bz; u8 bx; for (bz = 0; bz < bz_max; bz++) { for (bx = 0; bx < bx_max; bx++) { combi_table->combination_type = combi_id->combination_type; combi_table->height = combi_id->height; combi_table++; combi_id++; } } } static int mFM_SetBlockInfo(mFM_fdinfo_c* field_info, mFM_combination_c* combi_table) { mFM_bg_data_c** sorted_bg_data; mFM_fg_data_c** sorted_fg_data; mFM_combo_info_c* combi_info_p; mFM_bg_data_c* bg_data_p = data_bgd; mFM_fg_data_c* fg_data; size_t malloc_size; u32 aram_addr; int fg_count; int name_start; int fg_data_entries; int file_id; u32 size; u32 align_size; if (mFI_GET_TYPE(field_info->field_id) == mFI_FIELD_NPCROOM0) { malloc_size = mFM_FG_NPC_NUM * sizeof(mFM_fg_data_c*); fg_count = mFM_FG_NPC_NUM; name_start = mFM_FG_NPC_START; file_id = RESOURCE_FGNPCDATA; } else { malloc_size = mFM_FG_NUM * sizeof(mFM_fg_data_c*); fg_count = mFM_FG_NUM; name_start = mFM_FG_START; file_id = RESOURCE_FGDATA; } { size = JW_GetResSizeFileNo(file_id); align_size = ALIGN_NEXT(size, 32); fg_data = (mFM_fg_data_c*)zelda_malloc_align(align_size, 32); fg_data_entries = size / sizeof(mFM_fg_data_c); _JW_GetResourceAram(JW_GetAramAddress(file_id), (u8*)fg_data, align_size); combi_info_p = data_combi_table; sorted_bg_data = (mFM_bg_data_c**)zelda_malloc(mFM_BG_ID_MAX * sizeof(mFM_bg_data_c**)); if (sorted_bg_data == NULL) { return FALSE; } mFM_SortBGData(sorted_bg_data, bg_data_p, data_bgd_number); sorted_fg_data = (mFM_fg_data_c**)zelda_malloc(malloc_size); if (sorted_fg_data == NULL) { return FALSE; /* @BUG - possible memory leak from the sorted_bg_data malloc */ } mFM_SortFGData(sorted_fg_data, fg_data, fg_count, fg_data_entries, name_start); mFM_BlockDataSet( field_info->field_id, field_info->block_info, combi_table, sorted_bg_data, sorted_fg_data, combi_info_p, field_info->block_x_max, field_info->block_z_max, name_start ); mFM_SetFG2(field_info->fg2_p[0], sorted_fg_data, field_info->field_id, name_start); if (mFI_GET_TYPE(field_info->field_id) == mFI_FIELD_NPCROOM0) { mNpc_SetNpcFurnitureRandom(sorted_fg_data, name_start); // select a random furniture item from NPC base furniture layer } zelda_free(sorted_bg_data); zelda_free(sorted_fg_data); zelda_free(fg_data); } return 0; } static void mFM_set_pal_p(mFM_field_pal_c* pal) { if (pal != NULL) { bzero(mFM_pal_area, sizeof(mFM_pal_area)); pal->earth_pal = mFM_pal_area[0]; pal->cliff_pal = mFM_pal_area[1]; pal->bush_pal = mFM_pal_area[2]; pal->flower0_pal = mFM_pal_area[3]; pal->flower1_pal = mFM_pal_area[4]; pal->flower2_pal = mFM_pal_area[5]; pal->grass_pal = mFM_pal_area[6]; pal->tree_pal = mFM_pal_area[7]; pal->cedar_tree_pal = mFM_pal_area[8]; pal->palm_tree_pal = mFM_pal_area[9]; pal->golden_tree_pal = mFM_pal_area[10]; } } extern u16 mFM_obj_a_01_flower_pal[3 * 9][16]; extern u16 mFM_obj_01_zassou_pal[9][16]; extern u16 mFM_obj_tree_01_pal[14][16]; extern u16 mFM_obj_tree_01_pal_dol[14][16]; extern u16 mFM_obj_palm_01_pal[14][16]; extern u16 mFM_obj_gold_01_pal_dol[14][16]; static void mFM_SetFGPal(mFM_field_pal_c* pal, int term) { static int tree_pal_idx_table[mTM_TERM_NUM] = { 10, 12, 13, 0, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10 }; static int flower_pal_idx_table[mTM_TERM_NUM] = { 8, 8, 8, 0, 1, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8 }; int idx = flower_pal_idx_table[term]; bcopy(mFM_obj_a_01_flower_pal[0 * 9 + idx], pal->flower0_pal, 16 * sizeof(u16)); bcopy(mFM_obj_a_01_flower_pal[1 * 9 + idx], pal->flower1_pal, 16 * sizeof(u16)); bcopy(mFM_obj_a_01_flower_pal[2 * 9 + idx], pal->flower2_pal, 16 * sizeof(u16)); bcopy(mFM_obj_01_zassou_pal[idx], pal->grass_pal, 16 * sizeof(u16)); bcopy(mFM_obj_tree_01_pal[tree_pal_idx_table[term]], pal->tree_pal, 16 * sizeof(u16)); bcopy(mFM_obj_tree_01_pal_dol[tree_pal_idx_table[term]], pal->cedar_tree_pal, 16 * sizeof(u16)); bcopy(mFM_obj_palm_01_pal[tree_pal_idx_table[term]], pal->palm_tree_pal, 16 * sizeof(u16)); bcopy(mFM_obj_gold_01_pal_dol[tree_pal_idx_table[term]], pal->golden_tree_pal, 16 * sizeof(u16)); } extern u16 mFM_earth_pal[mFM_FIELD_PAL_NUM][16]; extern u16 mFM_cliff_pal[mFM_FIELD_PAL_NUM][16]; extern u16 mFM_bush_pal[mFM_FIELD_PAL_NUM][16]; extern u16 mFM_rail_pal[mFM_FIELD_PAL_NUM][16]; extern u16 mFM_beach_pal[mFM_FIELD_PAL_NUM][16]; static void mFM_SetFieldPal(mFM_field_pal_c* pal) { static int field_pal_idx_table[mTM_TERM_NUM] = { 9, 10, 11, 0, 1, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9 }; u32 term = Common_Get(time.term_idx); int field_pal_idx; int i; u16* pal_src; if (term >= mTM_TERM_NUM) { term = mTM_TERM_0; } if (Save_Get(scene_no) == SCENE_MUSEUM_ROOM_INSECT) { term = mTM_TERM_4; } field_pal_idx = field_pal_idx_table[term]; pal_src = mFM_earth_pal[field_pal_idx]; for (i = 0; i < 16; i++) { pal->earth_pal[i] = pal_src[i]; } pal_src = mFM_cliff_pal[field_pal_idx]; for (i = 0; i < 16; i++) { pal->cliff_pal[i] = pal_src[i]; } pal_src = mFM_bush_pal[field_pal_idx]; for (i = 0; i < 16; i++) { pal->bush_pal[i] = pal_src[i]; } mFM_SetFGPal(pal, term); } static void mFM_SetFgDepositP(mFM_block_info_c* block_info, mActor_name_t field_id, int bx_max, int bz_max, int* island_x_blocks) { mFM_block_info_c* block_info_p; int total_block; int scene; u16* deposit_p; int bz; int bx; int fg_blocks; scene = Save_Get(scene_no); total_block = bx_max * bz_max; block_info_p = block_info; for (bz = 0; bz < total_block; bz++) { block_info[bz].fg_info.deposit_p = NULL; } if ((mFI_GET_TYPE(field_id) == mFI_FIELD_FG)) { fg_blocks = 0; if (scene == SCENE_FG) { for (bz = 0; bz < bz_max; bz++) { for (bx = 0; bx < bx_max; bx++) { if (fg_blocks >= FG_BLOCK_TOTAL_NUM) { break; } if (bx > 0 && bx < bx_max - 1 && bz > 0 && bz < bz_max - 3) { block_info->fg_info.deposit_p = Save_GetPointer(deposit[fg_blocks++][0]); } block_info++; } } block_info = block_info_p + island_x_blocks[0] + bx_max * mISL_BLOCK_Z; /* @BUG - they used the island Z acre location define here on accident lol */ #ifndef BUGFIXES for (bz = 0; bz < mISL_BLOCK_Z; bz++) { #else for (bz = 0; bz < mISL_FG_BLOCK_X_NUM; bz++) { #endif block_info->fg_info.deposit_p = Save_Get(island).deposit[bz]; block_info++; } } else { for (bz = 0; bz < bz_max; bz++) { for (bx = 0; bx < bx_max; bx++) { if (fg_blocks >= FG_BLOCK_TOTAL_NUM) { break; } block_info->fg_info.deposit_p = Save_GetPointer(deposit[fg_blocks++][0]); block_info++; } } } } } extern mFM_field_data_c data_fdd[SCENE_NUM]; static mFM_fdinfo_c* mFM_MakeField(u16 scene, u16 bg_max, u8 bg_num) { mFM_field_data_c* field_data; int island_x_blocks[2]; int total_block; mFM_block_info_c* block_info; mFM_combination_c* combi; mFM_fdinfo_c* field_info = (mFM_fdinfo_c*)zelda_malloc(sizeof(mFM_fdinfo_c)); int i; int j; mActor_name_t house_owner_id; int floor_no; if (field_info == NULL) { return NULL; } bzero(field_info, sizeof(mFM_fdinfo_c)); field_data = &data_fdd[scene]; field_info->block_x_max = field_data->block_x_max; field_info->block_z_max = field_data->block_z_max; field_info->bg_num = bg_num; field_info->bg_max = bg_max; field_info->fg2_p = (mActor_name_t**)zelda_malloc((mHm_LAYER_NUM - 1) * sizeof(mActor_name_t*)); for (i = 0; i < 3; i++) { field_info->fg2_p[i] = NULL; } i = sizeof(mFM_block_info_c) * field_data->block_x_max * field_data->block_z_max; block_info = (mFM_block_info_c*)zelda_malloc(i); if (block_info == NULL) { /* @BUG - field_info was not freed */ #ifdef BUGFIXES zelda_free(field_info); #endif return NULL; } bzero(block_info, i); field_info->block_info = block_info; field_info->field_id = field_data->field_name; field_info->_04 = field_data->_94; field_info->update_fg = FALSE; field_info->born_item = FALSE; field_info->born_actor = FALSE; for (j = 0; j < mFM_VISIBLE_BLOCK_NUM; j++) { field_info->bg_draw_info[j].block_x = 0xFF; field_info->bg_draw_info[j].block_z = 0xFF; field_info->bg_draw_info[j].dma_loaded = FALSE; field_info->last_bg_idx[j] = -1; } if (Save_Get(scene_no) == SCENE_FG) { mFI_GetIslandBlockNumX(island_x_blocks); } if (Save_Get(scene_no) == SCENE_FG) { combi = Save_Get(combi_table[0]); mFM_SetFgUtPtoSaveData(field_info->block_info, field_info->block_x_max, field_info->block_z_max, island_x_blocks); } else if (mSc_IS_SCENE_PLAYER_ROOM(Save_Get(scene_no))) { house_owner_id = Common_Get(house_owner_name); floor_no = mFI_GetNowPlayerHouseFloorNo(); if (floor_no == -1) { floor_no = 0; } if (house_owner_id == RSV_NO) { house_owner_id = EMPTY_NO; Common_Set(house_owner_name, house_owner_id); } combi = field_data->combi; field_info->field_id = mFI_FIELD_PLAYER0_ROOM + house_owner_id; if (Save_Get(scene_no) == SCENE_COTTAGE_MY) { mFM_SetFgUtPtoCottageInfo(field_info->block_info, field_info->block_x_max, field_info->block_z_max); } else { mFM_SetFgUtPtoHomeInfo(field_info->block_info, field_info->block_x_max, field_info->block_z_max, house_owner_id, floor_no); } } else { mFM_block_info_c* block_info = field_info->block_info; int total_block = field_info->block_x_max * field_info->block_z_max; int k; combi = field_data->combi; for (k = total_block; k != 0; k--) { mActor_name_t* fg_p = (mActor_name_t*)zelda_malloc(UT_TOTAL_NUM * sizeof(mActor_name_t)); // There could be a memory leak here due to previous allocated blocks, perhaps investigate later if (fg_p == NULL) { break; } bzero(fg_p, UT_TOTAL_NUM * sizeof(mActor_name_t)); block_info->fg_info.items_p = fg_p; block_info++; } } if (mSc_IS_SCENE_PLAYER_ROOM(Save_Get(scene_no))) { mHm_lyr_c* layer; if (Save_Get(scene_no) == SCENE_COTTAGE_MY) { layer = &Save_Get(island).cottage.room.layer_main; } else { mActor_name_t house_owner_id = Common_Get(house_owner_name); floor_no = mFI_GetNowPlayerHouseFloorNo(); if (floor_no == -1) { floor_no = 0; } layer = &Save_Get(homes[house_owner_id]).floors[floor_no].layer_main; } for (i = 1; i < mHm_LAYER_NUM; i++) { field_info->fg2_p[i - 1] = layer[i].items[0]; } } else if (Save_Get(scene_no) == SCENE_NPC_HOUSE || Save_Get(scene_no) == SCENE_FIELD_TOOL_INSIDE) { field_info->fg2_p[0] = (mActor_name_t*)zelda_malloc(UT_TOTAL_NUM * sizeof(mActor_name_t)); if (field_info->fg2_p[0] != NULL) { bzero(field_info->fg2_p[0], UT_TOTAL_NUM * sizeof(mActor_name_t)); } } mFM_SetBlockInfo(field_info, combi); mFM_SetMoveActorInfo(field_info->block_info, field_info->block_x_max, field_info->block_z_max, field_data->move_actor_data, field_data->_94, field_data->_98); for (i = 0; i < mFM_VISIBLE_BLOCK_NUM; i++) { field_info->bg_display_list_p[i] = NULL; } for (i = 0; i < field_info->bg_num; i++) { field_info->bg_display_list_p[i] = (u8*)zelda_malloc(field_info->bg_max); field_info->bg_display_list_p[i] = (u8*)((u32)(field_info->bg_display_list_p[i]) + (16-1)); field_info->bg_display_list_p[i] = (u8*)((u32)(field_info->bg_display_list_p[i]) & (~(16-1))); } mFM_set_pal_p(&field_info->field_palette); mFM_SetFieldPal(&field_info->field_palette); mFM_SetFgDepositP(field_info->block_info, field_info->field_id, field_info->block_x_max, field_info->block_z_max, island_x_blocks); return field_info; } static mBGTex_obj_c l_bg_tex_common_dummy[27] = { { earth_tex_dummy, 0x800 }, { cliff_tex_dummy, 0x800 }, { bush_a_tex_dummy, 0x800 }, { bush_b_tex_dummy, 0x400 }, { grass_tex_dummy, 0x200 }, { rail_tex_dummy, 0x800 }, { station_tex_dummy, 0x800 }, { stone_tex_dummy, 0x800 }, { river_tex_dummy, 0x400 }, { water_1_tex_dummy, 0x200 }, { water_2_tex_dummy, 0x200 }, { bridge_1_tex_dummy, 0x800 }, { bridge_2_tex_dummy, 0x800 }, { tekkyo_tex_dummy, 0x800 }, { tunnel_tex_dummy, 0x800 }, { beach_tex_dummy, 0x800 }, { bridge_1_pal_dummy, 0x20 }, { bridge_2_pal_dummy, 0x20 }, { station_pal_dummy, 0x20 }, { beach1_tex_dummy2, 0x400 }, { beach2_tex_dummy2, 0x100 }, { sand_tex_dummy, 0x400 }, { wave1_tex_dummy, 0x400 }, { wave2_tex_dummy, 0x800 }, { wave3_tex_dummy, 0x400 }, { sprashA_tex_dummy, 0x200 }, { sprashC_tex_dummy, 0x200 }, }; static mBGTex_obj_c l_bg_pal_common_dummy[5] = { { earth_pal_dummy, 16 * sizeof(u16) }, { cliff_pal_dummy, 16 * sizeof(u16) }, { bush_pal_dummy, 16 * sizeof(u16) }, { rail_pal_dummy, 16 * sizeof(u16) }, { beach_pal_dummy2, 16 * sizeof(u16) } }; extern u8 mFM_grd_s_earth_tex[]; extern u8 mFM_grd_s_cliff_tex[]; extern u8 mFM_grd_s_bushA_tex[]; extern u8 mFM_grd_s_bushB_tex[]; extern u8 mFM_grd_s_grass_tex[]; extern u8 mFM_grd_s_rail_tex[]; extern u8 mFM_grd_s_station_tex[]; extern u8 mFM_grd_s_stone_tex[]; extern u8 mFM_grd_s_river_tex[]; extern u8 mFM_grd_water1_tex[]; extern u8 mFM_grd_water2_tex[]; extern u8 mFM_grd_s_bridge1_tex[]; extern u8 mFM_grd_s_bridge2_tex[]; extern u8 mFM_grd_s_tekkyo_tex[]; extern u8 mFM_grd_s_tunnel_tex[]; extern u8 mFM_grd_s_beach_tex[]; extern u16 mFM_grd_s_bridge1_pal[]; extern u16 mFM_grd_s_bridge2_pal[]; extern u16 mFM_grd_s_station1_pal[]; extern u8 mFM_grd_beachA_tex[]; extern u8 mFM_grd_beachB_tex[]; extern u8 mFM_grd_s_sand_tex[]; extern u8 mFM_grd_wave1_tex[]; extern u8 mFM_grd_wave2_tex[]; extern u8 mFM_grd_wave3_tex[]; extern u8 mFM_grd_sprashA_tex[]; extern u8 mFM_grd_sprashC_tex[]; static void* l_bg_tex_segment_rom_start_s_0[mFM_FIELD_TEX_NUM] = { mFM_grd_s_earth_tex, mFM_grd_s_cliff_tex, mFM_grd_s_bushA_tex, mFM_grd_s_bushB_tex, mFM_grd_s_grass_tex, mFM_grd_s_rail_tex, mFM_grd_s_station_tex, mFM_grd_s_stone_tex, mFM_grd_s_river_tex, mFM_grd_water1_tex, mFM_grd_water2_tex, mFM_grd_s_bridge1_tex, mFM_grd_s_bridge2_tex, mFM_grd_s_tekkyo_tex, mFM_grd_s_tunnel_tex, mFM_grd_s_beach_tex, mFM_grd_s_bridge1_pal, mFM_grd_s_bridge2_pal, mFM_grd_s_station1_pal, mFM_grd_beachA_tex, mFM_grd_beachB_tex, mFM_grd_s_sand_tex, mFM_grd_wave1_tex, mFM_grd_wave2_tex, mFM_grd_wave3_tex, mFM_grd_sprashA_tex, mFM_grd_sprashC_tex }; extern u8 mFM_grd_s_earth_2_tex[]; extern u8 mFM_grd_s_cliff_2_tex[]; extern u8 mFM_grd_s_bushA_2_tex[]; extern u8 mFM_grd_s_bushB_2_tex[]; extern u8 mFM_grd_s_grass_2_tex[]; extern u8 mFM_grd_s_rail_2_tex[]; extern u8 mFM_grd_s_station_2_tex[]; extern u8 mFM_grd_s_stone_2_tex[]; extern u8 mFM_grd_s_river_2_tex[]; extern u8 mFM_grd_s_bridge1_2_tex[]; extern u8 mFM_grd_s_bridge2_2_tex[]; extern u8 mFM_grd_s_tekkyo_2_tex[]; extern u8 mFM_grd_s_tunnel_2_tex[]; extern u8 mFM_grd_s_sand_2_tex[]; static void* l_bg_tex_segment_rom_start_s_1[mFM_FIELD_TEX_NUM] = { mFM_grd_s_earth_2_tex, mFM_grd_s_cliff_2_tex, mFM_grd_s_bushA_2_tex, mFM_grd_s_bushB_2_tex, mFM_grd_s_grass_2_tex, mFM_grd_s_rail_2_tex, mFM_grd_s_station_2_tex, mFM_grd_s_stone_2_tex, mFM_grd_s_river_2_tex, mFM_grd_water1_tex, mFM_grd_water2_tex, mFM_grd_s_bridge1_2_tex, mFM_grd_s_bridge2_2_tex, mFM_grd_s_tekkyo_2_tex, mFM_grd_s_tunnel_2_tex, mFM_grd_s_beach_tex, mFM_grd_s_bridge1_pal, mFM_grd_s_bridge2_pal, mFM_grd_s_station1_pal, mFM_grd_beachA_tex, mFM_grd_beachB_tex, mFM_grd_s_sand_2_tex, mFM_grd_wave1_tex, mFM_grd_wave2_tex, mFM_grd_wave3_tex, mFM_grd_sprashA_tex, mFM_grd_sprashC_tex }; extern u8 mFM_grd_s_earth_3_tex[]; extern u8 mFM_grd_s_cliff_3_tex[]; extern u8 mFM_grd_s_bushA_3_tex[]; extern u8 mFM_grd_s_bushB_3_tex[]; extern u8 mFM_grd_s_grass_3_tex[]; extern u8 mFM_grd_s_rail_3_tex[]; extern u8 mFM_grd_s_station_3_tex[]; extern u8 mFM_grd_s_stone_3_tex[]; extern u8 mFM_grd_s_river_3_tex[]; extern u8 mFM_grd_s_bridge1_3_tex[]; extern u8 mFM_grd_s_bridge2_3_tex[]; extern u8 mFM_grd_s_tekkyo_3_tex[]; extern u8 mFM_grd_s_tunnel_3_tex[]; extern u8 mFM_grd_s_sand_3_tex[]; static void* l_bg_tex_segment_rom_start_s_2[mFM_FIELD_TEX_NUM] = { mFM_grd_s_earth_3_tex, mFM_grd_s_cliff_3_tex, mFM_grd_s_bushA_3_tex, mFM_grd_s_bushB_3_tex, mFM_grd_s_grass_3_tex, mFM_grd_s_rail_3_tex, mFM_grd_s_station_3_tex, mFM_grd_s_stone_3_tex, mFM_grd_s_river_3_tex, mFM_grd_water1_tex, mFM_grd_water2_tex, mFM_grd_s_bridge1_3_tex, mFM_grd_s_bridge2_3_tex, mFM_grd_s_tekkyo_3_tex, mFM_grd_s_tunnel_3_tex, mFM_grd_s_beach_tex, mFM_grd_s_bridge1_pal, mFM_grd_s_bridge2_pal, mFM_grd_s_station1_pal, mFM_grd_beachA_tex, mFM_grd_beachB_tex, mFM_grd_s_sand_3_tex, mFM_grd_wave1_tex, mFM_grd_wave2_tex, mFM_grd_wave3_tex, mFM_grd_sprashA_tex, mFM_grd_sprashC_tex }; static void** l_bg_tex_segment_table[mFM_BG_TEX_NUM] = { l_bg_tex_segment_rom_start_s_0, l_bg_tex_segment_rom_start_s_1, l_bg_tex_segment_rom_start_s_2 }; extern u8 mFM_grd_w_earth_tex[]; extern u8 mFM_grd_w_cliff_tex[]; extern u8 mFM_grd_w_bushA_tex[]; extern u8 mFM_grd_w_bushB_tex[]; extern u8 mFM_grd_w_grass_tex[]; extern u8 mFM_grd_w_rail_tex[]; extern u8 mFM_grd_w_station_tex[]; extern u8 mFM_grd_w_stone_tex[]; extern u8 mFM_grd_w_river_tex[]; extern u8 mFM_grd_w_bridge1_tex[]; extern u8 mFM_grd_w_bridge2_tex[]; extern u8 mFM_grd_w_tekkyo_tex[]; extern u8 mFM_grd_w_sand_tex[]; static void* l_bg_tex_segment_rom_start_w_0[mFM_FIELD_TEX_NUM] = { mFM_grd_w_earth_tex, mFM_grd_w_cliff_tex, mFM_grd_w_bushA_tex, mFM_grd_w_bushB_tex, mFM_grd_w_grass_tex, mFM_grd_w_rail_tex, mFM_grd_w_station_tex, mFM_grd_w_stone_tex, mFM_grd_w_river_tex, mFM_grd_water1_tex, mFM_grd_water2_tex, mFM_grd_w_bridge1_tex, mFM_grd_w_bridge2_tex, mFM_grd_w_tekkyo_tex, mFM_grd_s_tunnel_tex, mFM_grd_s_beach_tex, mFM_grd_s_bridge1_pal, mFM_grd_s_bridge2_pal, mFM_grd_s_station1_pal, mFM_grd_beachA_tex, mFM_grd_beachB_tex, mFM_grd_w_sand_tex, mFM_grd_wave1_tex, mFM_grd_wave2_tex, mFM_grd_wave3_tex, mFM_grd_sprashA_tex, mFM_grd_sprashC_tex }; extern u8 mFM_grd_w_earth_2_tex[]; extern u8 mFM_grd_w_cliff_2_tex[]; extern u8 mFM_grd_w_bushA_2_tex[]; extern u8 mFM_grd_w_bushB_2_tex[]; extern u8 mFM_grd_w_grass_2_tex[]; extern u8 mFM_grd_w_rail_2_tex[]; extern u8 mFM_grd_w_station_2_tex[]; extern u8 mFM_grd_w_stone_2_tex[]; extern u8 mFM_grd_w_river_2_tex[]; extern u8 mFM_grd_w_bridge1_2_tex[]; extern u8 mFM_grd_w_bridge2_2_tex[]; extern u8 mFM_grd_w_tekkyo_2_tex[]; extern u8 mFM_grd_w_tunnel_2_tex[]; extern u8 mFM_grd_w_sand_2_tex[]; static void* l_bg_tex_segment_rom_start_w_1[mFM_FIELD_TEX_NUM] = { mFM_grd_w_earth_2_tex, mFM_grd_w_cliff_2_tex, mFM_grd_w_bushA_2_tex, mFM_grd_w_bushB_2_tex, mFM_grd_w_grass_2_tex, mFM_grd_w_rail_2_tex, mFM_grd_w_station_2_tex, mFM_grd_w_stone_2_tex, mFM_grd_w_river_2_tex, mFM_grd_water1_tex, mFM_grd_water2_tex, mFM_grd_w_bridge1_2_tex, mFM_grd_w_bridge2_2_tex, mFM_grd_w_tekkyo_2_tex, mFM_grd_w_tunnel_2_tex, mFM_grd_s_beach_tex, mFM_grd_s_bridge1_pal, mFM_grd_s_bridge2_pal, mFM_grd_s_station1_pal, mFM_grd_beachA_tex, mFM_grd_beachB_tex, mFM_grd_w_sand_2_tex, mFM_grd_wave1_tex, mFM_grd_wave2_tex, mFM_grd_wave3_tex, mFM_grd_sprashA_tex, mFM_grd_sprashC_tex }; extern u8 mFM_grd_w_earth_3_tex[]; extern u8 mFM_grd_w_cliff_3_tex[]; extern u8 mFM_grd_w_bushA_3_tex[]; extern u8 mFM_grd_w_bushB_3_tex[]; extern u8 mFM_grd_w_grass_3_tex[]; extern u8 mFM_grd_w_rail_3_tex[]; extern u8 mFM_grd_w_station_3_tex[]; extern u8 mFM_grd_w_stone_3_tex[]; extern u8 mFM_grd_w_river_3_tex[]; extern u8 mFM_grd_w_bridge1_3_tex[]; extern u8 mFM_grd_w_bridge2_3_tex[]; extern u8 mFM_grd_w_tekkyo_3_tex[]; extern u8 mFM_grd_w_tunnel_3_tex[]; extern u8 mFM_grd_w_sand_3_tex[]; static void* l_bg_tex_segment_rom_start_w_2[mFM_FIELD_TEX_NUM] = { mFM_grd_w_earth_3_tex, mFM_grd_w_cliff_3_tex, mFM_grd_w_bushA_3_tex, mFM_grd_w_bushB_3_tex, mFM_grd_w_grass_3_tex, mFM_grd_w_rail_3_tex, mFM_grd_w_station_3_tex, mFM_grd_w_stone_3_tex, mFM_grd_w_river_3_tex, mFM_grd_water1_tex, mFM_grd_water2_tex, mFM_grd_w_bridge1_3_tex, mFM_grd_w_bridge2_3_tex, mFM_grd_w_tekkyo_3_tex, mFM_grd_w_tunnel_3_tex, mFM_grd_s_beach_tex, mFM_grd_s_bridge1_pal, mFM_grd_s_bridge2_pal, mFM_grd_s_station1_pal, mFM_grd_beachA_tex, mFM_grd_beachB_tex, mFM_grd_w_sand_3_tex, mFM_grd_wave1_tex, mFM_grd_wave2_tex, mFM_grd_wave3_tex, mFM_grd_sprashA_tex, mFM_grd_sprashC_tex }; static void** l_bg_w_tex_segment_table[mFM_BG_TEX_NUM] = { l_bg_tex_segment_rom_start_w_0, l_bg_tex_segment_rom_start_w_1, l_bg_tex_segment_rom_start_w_2 }; static u8* l_bg_pal_segment_rom_start[5] = { (u8*)mFM_earth_pal, (u8*)mFM_cliff_pal, (u8*)mFM_bush_pal, (u8*)mFM_rail_pal, (u8*)mFM_beach_pal }; static u8 l_water_permission[mFM_FIELD_TEX_NUM] = { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE }; static void mFM_LoadBGCommonMonthlyPal() { static int field_pal_idx_table[mTM_TERM_NUM] = { 9, 10, 11, 0, 1, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9 }; u32 term = Common_Get(time.term_idx); int idx; int i; if (term >= mTM_TERM_NUM) { term = mTM_TERM_0; } if (Save_Get(scene_no) == SCENE_MUSEUM_ROOM_INSECT) { term = mTM_TERM_4; } idx = field_pal_idx_table[term]; for (i = 0; i < 5; i++) { bcopy(l_bg_pal_segment_rom_start[i] + ((l_bg_pal_common_dummy[i].size * idx) & ~1), l_bg_pal_common_dummy[i].data, l_bg_pal_common_dummy[i].size); } } extern void mFM_DecideBgTexIdx(u8* bg_tex_idx) { *bg_tex_idx = RANDOM(mFM_BG_TEX_NUM); } static void mFM_LoadBGCommonTex(int update_tex, u8 tex_idx) { void** bg_tex_tbl; u32 season = Common_Get(time.season); int i; if (season >= mTM_SEASON_NUM) { season = mTM_SEASON_SPRING; } if (Save_Get(scene_no) == SCENE_TITLE_DEMO) { mFM_DecideBgTexIdx(&tex_idx); } if (tex_idx >= mFM_BG_TEX_NUM) { tex_idx = mFM_BG_TEX_TRIANGLE; } if (Save_Get(scene_no) == SCENE_MUSEUM_ROOM_INSECT) { bg_tex_tbl = l_bg_tex_segment_table[tex_idx]; } else if (season == mTM_SEASON_WINTER) { bg_tex_tbl = l_bg_w_tex_segment_table[tex_idx]; } else { bg_tex_tbl = l_bg_tex_segment_table[tex_idx]; } for (i = 0; i < mFM_FIELD_TEX_NUM; i++) { if (update_tex == TRUE || l_water_permission[i] == TRUE) { bcopy(bg_tex_tbl[i], l_bg_tex_common_dummy[i].data, l_bg_tex_common_dummy[i].size); } } mFM_LoadBGCommonMonthlyPal(); } static void set_field_type() { int field_id = mFI_GetFieldId(); int house_owner_id; u8 field_type; if (mLd_PlayerManKindCheck() == FALSE) { house_owner_id = mFI_FIELD_PLAYER0_ROOM + mHS_get_arrange_idx(Common_Get(player_no)); } else { house_owner_id = RSV_NO; } if (field_id == mFI_FIELD_FG) { field_type = mFI_FIELDTYPE2_FG; } else if ((field_id == house_owner_id && mEv_CheckFirstIntro() == FALSE) || Save_Get(scene_no) == SCENE_COTTAGE_MY) { field_type = mFI_FIELDTYPE2_PLAYER_ROOM; } else if (field_id == mFI_FIELD_NPCROOM0) { field_type = mFI_FIELDTYPE2_NPC_ROOM; } else { field_type = mFI_FIELDTYPE2_ROOM; } Common_Set(field_type, field_type); } static void mFM_PoorTreeBlock(mFM_block_info_c* block, int ut) { mCoBG_Collision_u* col = (mCoBG_Collision_u*)block->bg_info.collision; int i; for (i = ut; i < UT_TOTAL_NUM; i += UT_X_NUM) { mCoBG_Change2PoorAttr(col + i); } } static void mFM_PoorTree() { mFM_fdinfo_c* field_info = g_fdinfo; mFM_block_info_c* first_block = field_info->block_info; mFM_block_info_c* last_block = field_info->block_info; int block_total; u8 bx_max; int i; bx_max = field_info->block_x_max; block_total = field_info->block_x_max * (field_info->block_z_max - 3); if (mFI_GET_TYPE(field_info->field_id) == mFI_FIELD_FG && Save_Get(scene_no) == SCENE_FG) { for (i = field_info->block_x_max; i < block_total; i += bx_max) { mFM_PoorTreeBlock(first_block + (i + 1), 0); mFM_PoorTreeBlock(last_block + (i + (bx_max - 2)), UT_X_NUM - 1); } } } static void mFM_PoorTreeUnderPlayerBlock() { mFM_fdinfo_c* field_info = g_fdinfo; mFM_block_info_c* block_info = field_info->block_info; int bx_max = field_info->block_x_max; if (field_info != NULL && mFI_GET_TYPE(field_info->field_id) == mFI_FIELD_FG && Save_Get(scene_no) == SCENE_FG) { mCoBG_Collision_u* col = &block_info[bx_max * 3 + 3].bg_info.collision[0][0]; if (col != NULL) { mCoBG_Change2PoorAttr(col + 7); mCoBG_Change2PoorAttr(col + 8); mCoBG_Change2PoorAttr(col + (UT_X_NUM + 7)); mCoBG_Change2PoorAttr(col + (UT_X_NUM + 8)); } } } static void mFM_SetFruit_title_demo(int scene) { if (scene == SCENE_FIELD_TOOL || scene == SCENE_TITLE_DEMO) { mFI_BlockUtNumtoFGSet(TREE_APPLE_FRUIT, 5, 5, 14, 8); } } extern void mFM_SetFieldInitData(int bg_disp_num, int bg_disp_size) { l_bg_disp_num = bg_disp_num; l_bg_disp_size = bg_disp_size; } extern void mFM_FieldInit(GAME_PLAY* play) { int bg_disp_num = l_bg_disp_num; int bg_disp_size = l_bg_disp_size; int scene = Save_Get(scene_no); mFM_LoadBGCommonTex(TRUE, Save_Get(bg_tex_idx)); if (bg_disp_num > mFM_VISIBLE_BLOCK_NUM) { bg_disp_num = mFM_VISIBLE_BLOCK_NUM; } g_fdinfo = mFM_MakeField(scene, bg_disp_size, bg_disp_num); mFI_InitMoveActorBitData(); mFI_ClearColKeep(); mFI_InitAreaInfo(); mFI_InitRegisterBgInfo(); set_field_type(); mFM_PoorTree(); if (Common_Get(field_type) == mFI_FIELDTYPE2_FG) { mRF_CheckBeastRoad(); } mFM_PoorTreeUnderPlayerBlock(); mAGrw_ChangeCedar2Tree(); mAGrw_RenewalFgItem(Common_GetPointer(time.rtc_time)); mAGrw_SetXmasTree(); mFM_SetFruit_title_demo(Save_Get(scene_no)); if (scene == SCENE_FG) { mNpc_SetNpcHomeYpos(); } mNpc_SendRegisteredGoodbyMail(); Common_Set(floor_idx, mRmTp_GetFloorIdx()); Common_Set(make_npc2_actor, FALSE); if (play->fb_wipe_type == 6) { if (scene == SCENE_MUSEUM_ENTRANCE) { mBGMPsComp_museum_status(1); } else if (scene == SCENE_MUSEUM_ROOM_PAINTING) { mBGMPsComp_museum_status(2); } else if (scene == SCENE_MUSEUM_ROOM_FISH) { mBGMPsComp_museum_status(3); } else if (scene == SCENE_MUSEUM_ROOM_INSECT) { mBGMPsComp_museum_status(4); } else if (scene == SCENE_MUSEUM_ROOM_FOSSIL) { mBGMPsComp_museum_status(5); } } else if ( mFI_GET_TYPE(g_fdinfo->field_id) == mFI_FIELD_PLAYER0_ROOM || mFI_GET_TYPE(g_fdinfo->field_id) == mFI_FIELD_ROOM0 || mFI_GET_TYPE(g_fdinfo->field_id) == mFI_FIELD_NPCROOM0 ) { if (scene == SCENE_MUSEUM_ENTRANCE) { mBGMPsComp_scene_mode(15); mBGMPsComp_museum_status(1); } else if (scene == SCENE_MUSEUM_ROOM_PAINTING) { mBGMPsComp_scene_mode(15); mBGMPsComp_museum_status(2); } else if (scene == SCENE_MUSEUM_ROOM_FISH) { mBGMPsComp_scene_mode(15); mBGMPsComp_museum_status(3); } else if (scene == SCENE_MUSEUM_ROOM_INSECT) { mBGMPsComp_scene_mode(15); mBGMPsComp_museum_status(4); } else if (scene == SCENE_MUSEUM_ROOM_FOSSIL) { mBGMPsComp_scene_mode(15); mBGMPsComp_museum_status(5); } else if (scene == SCENE_LIGHTHOUSE) { mBGMPsComp_scene_mode(16); } else { if (mEv_CheckFirstIntro() == TRUE) { mBGMPsComp_scene_mode(10); } else { mBGMPsComp_scene_mode(2); } } } else if (mFI_GET_TYPE(g_fdinfo->field_id) == mFI_FIELD_FG) { if (scene != SCENE_TITLE_DEMO) { if (mEv_CheckFirstIntro() == TRUE) { mBGMPsComp_scene_mode(9); } else if (mEv_CheckGateway() == TRUE) { mBGMPsComp_scene_mode(8); } else { mBGMPsComp_scene_mode(1); } } } else if (scene == SCENE_PLAYERSELECT || scene == SCENE_PLAYERSELECT_2 || scene == SCENE_PLAYERSELECT_3 || scene == SCENE_PLAYERSELECT_SAVE) { mBGMPsComp_scene_mode(3); } else if (scene == SCENE_START_DEMO || scene == SCENE_START_DEMO2 || scene == SCENE_START_DEMO3) { mBGMPsComp_scene_mode(4); } else { mBGMPsComp_scene_mode(0); } } extern void mFM_Field_dt() { mFM_fdinfo_c* field_info = g_fdinfo; mFM_block_info_c* block_info; int max; int i; Common_Set(last_field_id, field_info->field_id); if (mFI_GET_TYPE(field_info->field_id) == mFI_FIELD_ROOM0 && mSc_IS_SCENE_MUSEUM_ROOM(Common_Get(last_scene_no)) && !mSc_IS_SCENE_MUSEUM_ROOM(Save_Get(scene_no))) { mBGMPsComp_museum_status(0); } if (field_info->field_id != mFI_FIELD_FG && mFI_GET_TYPE(field_info->field_id) != mFI_FIELD_PLAYER0_ROOM) { if (mFI_GET_TYPE(field_info->field_id) == mFI_FIELD_NPCROOM0) { if (field_info->fg2_p[0] != NULL) { zelda_free(field_info->fg2_p[0]); } } else { block_info = field_info->block_info; max = field_info->block_x_max * field_info->block_z_max; for (i = max; i != 0; i--) { zelda_free(block_info->fg_info.items_p); block_info++; } } } zelda_free(field_info->fg2_p); zelda_free(field_info->block_info); for (i = 0; i < mFM_VISIBLE_BLOCK_NUM; i++) { zelda_free(field_info->bg_display_list_p[i]); } zelda_free(field_info); g_fdinfo = NULL; mFI_InitRegisterBgInfo(); } static void mFM_SetBlockKind(u8* type_p, int* kind_p, mFM_combination_c* combi_p, mFM_combo_info_c* combi_info_p, int count) { for (count; count != 0; count--) { int combi_type = combi_p[0].combination_type; type_p[0] = combi_info_p[combi_type].type; kind_p[0] = mRF_Type2BlockInfo(combi_info_p[combi_type].type); type_p++; kind_p++; combi_p++; } } extern void mFM_SetBlockKindLoadCombi() { mFM_SetBlockKind(g_block_type_p, g_block_kind_p, Save_Get(combi_table[0]), data_combi_table, BLOCK_TOTAL_NUM); } static void mFM_SetIslandFg(mFM_combo_info_c* combi_info_p, mFM_fg_data_c** sorted_fg_data, int* island_x_blocks) { int i; for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) { int fg_id = combi_info_p[Save_Get(combi_table[mISL_BLOCK_Z][island_x_blocks[0]]).combination_type].fg_id; if (sorted_fg_data[fg_id] == NULL) { break; } if (fg_id >= 0 && fg_id < mFM_FG_NUM) { mFM_FgUtDataSet(Save_Get(island).fgblock[0][i].items[0], sorted_fg_data[fg_id]->items[0]); } island_x_blocks++; } } static mFM_combination_c l_combiID[BLOCK_TOTAL_NUM] = { { 209, 1 }, { 201, 1 }, { 201, 1 }, { 201, 1 }, { 202, 1 }, { 201, 1 }, { 210, 1 }, { 205, 1 }, { 172, 1 }, { 222, 1 }, { 189, 1 }, { 176, 1 }, { 225, 1 }, { 208, 1 }, { 203, 1 }, { 159, 1 }, { 5, 1 }, { 215, 1 }, { 93, 1 }, { 37, 1 }, { 206, 1 }, { 203, 1 }, { 45, 0 }, { 101, 0 }, { 96, 1 }, { 152, 1 }, { 108, 0 }, { 207, 0 }, { 204, 0 }, { 42, 0 }, { 163, 0 }, { 64, 0 }, { 164, 0 }, { 213, 0 }, { 206, 0 }, { 203, 0 }, { 157, 0 }, { 217, 0 }, { 127, 0 }, { 38, 0 }, { 160, 0 }, { 206, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 }, { 196, 0 } }; u8* g_block_type_p = l_block_type; int* g_block_kind_p = l_block_kind; extern void mFM_InitFgCombiSaveData(GAME* game) { GameAlloc* game_alloc_p = NULL; void* gamealloc_data_p; mFM_fg_data_c* fg_data_p; mFM_combo_info_c* combo_info_p; mFM_combination_c* combi_table; mFM_fg_data_c** sorted_fg_data_list; size_t fg_datasize; size_t fg_datasize_align; mFM_fg_c* fg_block; int fg_id; mFM_fg_c* fg_block_p; int fg_data_num; mFM_fg_data_c* src_data; int bz; int bx; int total_fg_block; combi_table = Save_Get(combi_table[0]); fg_block = Save_Get(fg[0]); total_fg_block = 0; if (game != NULL) { game_alloc_p = &game->gamealloc; } combo_info_p = data_combi_table; mRF_MakeRandomField(l_combiID, combo_info_p, data_combi_table_number, game); mFM_SetBlockKind(g_block_type_p, g_block_kind_p, l_combiID, combo_info_p, BLOCK_TOTAL_NUM); mFM_SetCombiTable(combi_table, l_combiID, BLOCK_X_NUM, BLOCK_Z_NUM); fg_datasize = JW_GetResSizeFileNo(RESOURCE_FGDATA); fg_datasize_align = ALIGN_NEXT(fg_datasize, 32); if (game != NULL) { gamealloc_data_p = gamealloc_malloc(game_alloc_p, fg_datasize_align + 32); fg_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((u32)gamealloc_data_p, 32)); } else { fg_data_p = (mFM_fg_data_c*)zelda_malloc_align(fg_datasize_align, 32); } fg_data_num = fg_datasize / sizeof(mFM_fg_data_c); _JW_GetResourceAram(JW_GetAramAddress(RESOURCE_FGDATA), (u8*)fg_data_p, fg_datasize_align); if (game != NULL) { sorted_fg_data_list = (mFM_fg_data_c**)gamealloc_malloc(game_alloc_p, mFM_FG_NUM * sizeof(mFM_fg_data_c*)); } else { sorted_fg_data_list = (mFM_fg_data_c**)zelda_malloc(mFM_FG_NUM * sizeof(mFM_fg_data_c*)); } mFM_SortFGData(sorted_fg_data_list, fg_data_p, mFM_FG_NUM, fg_data_num, 0); fg_block_p = fg_block; for (bz = 0; bz < mISL_BLOCK_Z; bz++) { for (bx = 0; bx < BLOCK_X_NUM; bx++, combi_table++) { if (bz > 0 && bz < (BLOCK_Z_NUM - 3) && bx > 0 && bx < (BLOCK_X_NUM - 1)) { if (total_fg_block >= FG_BLOCK_TOTAL_NUM) { break; } fg_id = combo_info_p[combi_table[0].combination_type].fg_id; if (fg_block_p == NULL) { break; } src_data = sorted_fg_data_list[fg_id]; if (src_data == NULL) { break; } if (fg_id >= 0 && fg_id < mFM_FG_NUM) { mFM_FgUtDataSet(fg_block_p->items[0], src_data->items[0]); } total_fg_block++; fg_block_p++; if (total_fg_block >= FG_BLOCK_TOTAL_NUM) { break; } } } } { int island_x_blocks[2]; mFI_GetIslandBlockNumX(island_x_blocks); mFM_SetIslandFg(combo_info_p, sorted_fg_data_list, island_x_blocks); } if (game != NULL) { gamealloc_free(game_alloc_p, sorted_fg_data_list); gamealloc_free(game_alloc_p, gamealloc_data_p); } else { zelda_free(sorted_fg_data_list); zelda_free(fg_data_p); } } static int mFM_AddIdx(int* idx, int min, int max) { int res = FALSE; (*idx)++; if (*idx >= max) { *idx = min; res = TRUE; } return res; } static mActor_name_t mFM_GetNextReseve(int set, int set_idx, int river_idx, u32 block_kind, int force) { mActor_name_t reserve; if (force == FALSE && ((block_kind & mRF_BLOCKKIND_RIVER) == mRF_BLOCKKIND_RIVER)) { set = 0; set_idx = river_idx; } reserve = set * 3 + set_idx; reserve += SIGN00; return reserve; } static void mFM_RenewalReserveBlock(mActor_name_t* items, int* set, int* set_idx, int* river_idx, u32 block_kind) { int force = FALSE; int i; for (i = 0; i < UT_TOTAL_NUM; i++) { if (items[0] == SIGN00) { items[0] = mFM_GetNextReseve(*set, *set_idx, *river_idx, block_kind, force); if (force == FALSE && (block_kind & mRF_BLOCKKIND_RIVER) == mRF_BLOCKKIND_RIVER) { mFM_AddIdx(river_idx, 0, 3); force = TRUE; } else { if (mFM_AddIdx(set, 1, 7) == TRUE) { mFM_AddIdx(set_idx, 0, 3); } } } items++; } } extern void mFM_RenewalReserve() { int set = 1; int set_idx = 0; int river_idx = 0; mFM_fg_c* fg_block = Save_Get(fg[1]); int bx; int bz; for (bz = 1; bz < FG_BLOCK_Z_NUM; bz++) { for (bx = 0; bx < FG_BLOCK_X_NUM; bx++) { mFM_RenewalReserveBlock(fg_block->items[0], &set, &set_idx, &river_idx, g_block_kind_p[(bz + 1) * BLOCK_X_NUM + (bx + 1)]); fg_block++; } } } extern mActor_name_t mFM_GetReseveName(int bx, int bz) { mActor_name_t reserve_name = SIGN03; int reserve_bit_field = 0; u8 reserve_complete_sets_bit_field = 0; int free_signs; int set = 0; int reserve_noncomplete_sets = 0; int set_idx = 0; int i; if (bx > 0 && bx < (BLOCK_X_NUM - 1) && bz > 0 && bz < (BLOCK_Z_NUM - 3)) { u32 block_kind = g_block_kind_p[(bz * BLOCK_X_NUM) + bx]; mActor_name_t* items = Save_Get(fg[bz - 1][bx - 1]).items[0]; for (i = 0; i < UT_TOTAL_NUM; i++) { if (mNT_IS_RESERVE(items[0])) { reserve_bit_field |= (1 << (items[0] - SIGN00)); } items++; } for (i = 0; i < 7; i++) { u32 shift = i * 3; if (((reserve_bit_field >> shift) & 0b111) == 0b111) { reserve_complete_sets_bit_field |= (1 << i); } if (((reserve_bit_field >> (i * 3)) & 0b111) != 0b111) { reserve_noncomplete_sets++; } } /* Mark river set as unavailable */ if ( (block_kind & mRF_BLOCKKIND_RIVER) != mRF_BLOCKKIND_RIVER && ((reserve_complete_sets_bit_field & 1) == 0) ) { reserve_complete_sets_bit_field |= 1; reserve_noncomplete_sets--; } /* Select one of the 7 sets of signs */ { int selected_set = RANDOM(reserve_noncomplete_sets); for (i = 0; i < 7; i++) { if (((reserve_complete_sets_bit_field >> i) & 1) == 0) { if (selected_set <= 0) { set = i; break; } else { selected_set--; } } } } /* Count used signs in selected set */ { int subset_start = set * 3; int idx; int j; int selected_idx; free_signs = 0; for (i = subset_start; i < subset_start + 3; i++) { if (((reserve_bit_field >> i) & 1) == 0) { free_signs++; } } /* Select random free sign in set */ selected_idx = RANDOM(free_signs); idx = 0; for (j = subset_start; j < subset_start + 3; j++) { if (((reserve_bit_field >> j) & 1) == 0) { if (selected_idx <= 0) { idx = j; break; } else { selected_idx--; } } } reserve_name = SIGN00 + idx; } } return reserve_name; } extern void mFM_toSummer() { mTM_set_season_com(7); if (g_fdinfo != NULL) { mFM_LoadBGCommonTex(FALSE, Save_Get(island).grass_tex_type); mFM_SetFieldPal(&g_fdinfo->field_palette); } } extern void mFM_returnSeason() { mTM_set_season(); if (g_fdinfo != NULL) { mFM_LoadBGCommonTex(FALSE, Save_Get(bg_tex_idx)); mFM_SetFieldPal(&g_fdinfo->field_palette); } } extern void mFM_RestoreIslandBG(int* island_x_blocks, int bx_num) { mFM_combination_c* combi_p; mFM_block_info_c* block_info; mFM_bg_data_c** sorted_bg_data; mFM_bg_data_c* bg_data_p = data_bgd; mFM_combo_info_c* combo_info_p = data_combi_table; if (mFI_CheckFieldData() && Save_Get(scene_no) == SCENE_FG) { block_info = mFI_GetBlockTopP(); if (block_info != NULL) { int i; sorted_bg_data = (mFM_bg_data_c**)zelda_malloc(mFM_BG_ID_MAX * sizeof(mFM_bg_data_c*)); if (sorted_bg_data != NULL) { mFM_SortBGData(sorted_bg_data, bg_data_p, data_bgd_number); combi_p = Save_Get(combi_table[mISL_BLOCK_Z] + island_x_blocks[0]); block_info += mFI_GetBlockNum(island_x_blocks[0], mISL_BLOCK_Z); for (i = 0; i < bx_num; i++) { int bg_id = combo_info_p[combi_p[0].combination_type].bg_id; if (bg_id <= mFM_BG_ID_MAX && sorted_bg_data[bg_id] != NULL) { mFM_SetBG(&block_info->bg_info, sorted_bg_data[bg_id], combi_p->height, block_info->bg_info.block_type, bg_id, island_x_blocks[i], mISL_BLOCK_Z); } block_info++; combi_p++; } if (sorted_bg_data != NULL) { zelda_free(sorted_bg_data); } } } } } extern void mFM_SetIslandNpcRoomData(GAME* game, int malloc_flag) { GameAlloc* gamealloc = NULL; mFM_fg_data_c** sorted_fgnpc_data_list; void* gamealloc_data_p; mFM_fg_data_c* fgnpc_data_p; size_t fgnpc_size = JW_GetResSizeFileNo(RESOURCE_FGNPCDATA); size_t fgnpc_size_align = ALIGN_NEXT(fgnpc_size, 32); int fgnpc_data_num; if (game != NULL) { gamealloc = &game->gamealloc; } if (malloc_flag == TRUE) { fgnpc_data_p = (mFM_fg_data_c*)zelda_malloc_align(fgnpc_size_align, 32); } else if (game != NULL) { gamealloc_data_p = gamealloc_malloc(gamealloc, fgnpc_size_align + 32); fgnpc_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((u32)gamealloc_data_p, 32)); } else { fgnpc_data_p = (mFM_fg_data_c*)zelda_malloc_align(fgnpc_size_align, 32); } if (fgnpc_data_p != NULL) { fgnpc_data_num = fgnpc_size / sizeof(mFM_fg_data_c); _JW_GetResourceAram(JW_GetAramAddress(RESOURCE_FGNPCDATA), (u8*)fgnpc_data_p, fgnpc_size_align); if (malloc_flag == TRUE) { sorted_fgnpc_data_list = (mFM_fg_data_c**)zelda_malloc(mFM_FG_NPC_NUM * sizeof(mFM_fg_data_c*)); } else if (game != NULL) { sorted_fgnpc_data_list = (mFM_fg_data_c**)gamealloc_malloc(gamealloc, mFM_FG_NPC_NUM * sizeof(mFM_fg_data_c*)); } else { sorted_fgnpc_data_list = (mFM_fg_data_c**)zelda_malloc(mFM_FG_NPC_NUM * sizeof(mFM_fg_data_c*)); } if (sorted_fgnpc_data_list != NULL) { mFM_SortFGData(sorted_fgnpc_data_list, fgnpc_data_p, mFM_FG_NPC_NUM, fgnpc_data_num, mFM_FG_NPC_START); mNpc_IslandNpcRoomDataSet(sorted_fgnpc_data_list, mFM_FG_NPC_START); if (sorted_fgnpc_data_list != NULL) { if (malloc_flag == TRUE) { zelda_free(sorted_fgnpc_data_list); } else if (game != NULL) { gamealloc_free(gamealloc, sorted_fgnpc_data_list); } else { zelda_free(sorted_fgnpc_data_list); } } } /* @BUG - memory leak if gamealloc malloc path is not taken above */ #ifndef BUGFIXES if (gamealloc_data_p != NULL) { #else if (fgnpc_data_p != NULL) { // this is guaranteed to exist in all malloc paths #endif if (malloc_flag == TRUE) { zelda_free(fgnpc_data_p); } else if (game != NULL) { gamealloc_free(gamealloc, gamealloc_data_p); } else { zelda_free(fgnpc_data_p); } } } }