diff --git a/src/CLOUD/classes/data_test/auth_3d_test.c b/src/CLOUD/classes/data_test/auth_3d_test.c index d375dcfc..d2f23ca8 100644 --- a/src/CLOUD/classes/data_test/auth_3d_test.c +++ b/src/CLOUD/classes/data_test/auth_3d_test.c @@ -19,10 +19,17 @@ #include "../../input.h" #include "../imgui_helper.h" +typedef struct data_test_auth_3d_test_uid { + char* name; + uint32_t uid; +} data_test_auth_3d_test_uid; + +vector(data_test_auth_3d_test_uid) + typedef struct data_test_auth_3d_test_category { char* name; int32_t index; - vector_int32_t uid; + vector_data_test_auth_3d_test_uid uid; } data_test_auth_3d_test_category; vector(data_test_auth_3d_test_category) @@ -53,6 +60,7 @@ typedef struct data_test_auth_3d_test { } data_test_auth_3d_test; vector_func(data_test_auth_3d_test_category) +vector_func(data_test_auth_3d_test_uid) extern int32_t width; extern int32_t height; @@ -65,6 +73,7 @@ static const char* data_test_auth_3d_test_window_title = "Auth 3D Test##Data Tes static void data_test_auth_3d_test_category_free(data_test_auth_3d_test_category* cat); static void data_test_auth_3d_test_load_auth_file(data_test_auth_3d_test* auth_3d_test); +static int data_test_auth_3d_test_uid_quicksort_compare_func(void const* src1, void const* src2); bool data_test_auth_3d_test_init(class_data* data, render_context* rctx) { bool ret = false; @@ -86,18 +95,25 @@ bool data_test_auth_3d_test_init(class_data* data, render_context* rctx) { = vector_data_test_auth_3d_test_category_reserve_back(&auth_3d_test->category); cat->name = string_data(&i->name); cat->index = -1; - cat->uid = vector_empty(int32_t); + cat->uid = vector_empty(data_test_auth_3d_test_uid); - vector_int32_t_reserve(&cat->uid, vector_length(i->uid)); + vector_data_test_auth_3d_test_uid_reserve(&cat->uid, vector_length(i->uid)); for (int32_t* j = i->uid.begin; j != i->uid.end; j++) { if (!uids[*j].enabled) continue; - vector_int32_t_push_back(&cat->uid, &uids[*j].org_uid); + data_test_auth_3d_test_uid uid; + uid.name = string_data(&uids[*j].name); + uid.uid = uids[*j].org_uid; + vector_data_test_auth_3d_test_uid_push_back(&cat->uid, &uid); } - if (vector_length(cat->uid) > 0) + if (vector_length(cat->uid)) { + quicksort_custom(cat->uid.begin, vector_length(cat->uid), + sizeof(data_test_auth_3d_test_uid), + data_test_auth_3d_test_uid_quicksort_compare_func); cat->index = 0; + } } auth_3d_test->rctx = rctx; @@ -126,10 +142,10 @@ bool data_test_auth_3d_test_init(class_data* data, render_context* rctx) { if (vector_length(auth_3d_test->category) > 0) { data_test_auth_3d_test_category* cat = &auth_3d_test->category.begin[0]; - if (vector_length(cat->uid) > 0) { + if (vector_length(cat->uid)) { auth_3d_test->auth_3d_load = true; auth_3d_test->auth_3d_uid_load = true; - auth_3d_test->auth_3d_uid = cat->uid.begin[0]; + auth_3d_test->auth_3d_uid = cat->uid.begin[0].uid; } auth_3d_test->auth_3d_category_index = 0; @@ -171,6 +187,8 @@ bool data_test_auth_3d_test_hide(class_data* data) { auth_3d_farc_free(&auth_3d_test->farc); + auth_3d_data_unload_id(auth_3d_test->auth_3d_id, auth_3d_test->rctx); + auth_3d_test->auth_3d_category_index = -1; auth_3d_test->auth_3d_index = -1; auth_3d_test->auth_3d_uid = -1; @@ -247,7 +265,7 @@ void data_test_auth_3d_test_imgui(class_data* data) { if (vector_length(cat->uid) > 0) { auth_3d_test->auth_3d_load = true; auth_3d_test->auth_3d_uid_load = true; - auth_3d_test->auth_3d_uid = cat->uid.begin[cat->index]; + auth_3d_test->auth_3d_uid = cat->uid.begin[cat->index].uid; } else { auth_3d_test->auth_3d_load = false; @@ -269,12 +287,12 @@ void data_test_auth_3d_test_imgui(class_data* data) { continue; if (igBeginCombo("##Auth 3D Index", auth_3d_index > -1 - ? string_data(&uids[i->uid.begin[auth_3d_index]].name) : "", 0)) { - for (int32_t* j = i->uid.begin; j != i->uid.end; j++) { + ? i->uid.begin[auth_3d_index].name : "", 0)) { + for (data_test_auth_3d_test_uid* j = i->uid.begin; j != i->uid.end; j++) { int32_t auth_3d_idx = (int32_t)(j - i->uid.begin); igPushID_Ptr(j); - if (igSelectable_Bool(string_data(&uids[*j].name), + if (igSelectable_Bool(j->name, auth_3d_index == auth_3d_idx, 0, ImVec2_Empty) || imguiItemKeyPressed(GLFW_KEY_ENTER, true) || (igIsItemFocused() && auth_3d_index != auth_3d_idx)) { @@ -294,7 +312,7 @@ void data_test_auth_3d_test_imgui(class_data* data) { if (auth_3d_index != auth_3d_test->auth_3d_index) { i->index = auth_3d_index; auth_3d_test->auth_3d_uid_load = true; - auth_3d_test->auth_3d_uid = i->uid.begin[auth_3d_index]; + auth_3d_test->auth_3d_uid = i->uid.begin[auth_3d_index].uid; auth_3d_test->auth_3d_index = auth_3d_index; } auth_3d_category_found = true; @@ -524,7 +542,7 @@ void data_test_auth_3d_test_render(class_data* data) { mat4 mat; mat4_translate(auth_3d_test->trans_x, 0.0f, auth_3d_test->trans_z, &mat); mat4_rotate_y_mult(&mat, auth_3d_test->rot_y * DEG_TO_RAD_FLOAT, &mat); - auth_3d_get_value(auth, &mat, get_delta_frame()); + auth_3d_time_step(auth, &mat); auth_3d_data_set(auth, &mat, auth_3d_test->rctx); } @@ -561,7 +579,7 @@ bool data_test_auth_3d_test_dispose(class_data* data) { } static void data_test_auth_3d_test_category_free(data_test_auth_3d_test_category* cat) { - vector_int32_t_free(&cat->uid, 0); + vector_data_test_auth_3d_test_uid_free(&cat->uid, 0); } static void data_test_auth_3d_test_load_auth_file(data_test_auth_3d_test* auth_3d_test) { @@ -588,3 +606,9 @@ static void data_test_auth_3d_test_load_auth_file(data_test_auth_3d_test* auth_3 auth_3d_test->trans_z = 0.0f; auth_3d_test->rot_y = 0.0f; } + +static int data_test_auth_3d_test_uid_quicksort_compare_func(void const* src1, void const* src2) { + char* str1 = ((data_test_auth_3d_test_uid*)src1)->name; + char* str2 = ((data_test_auth_3d_test_uid*)src2)->name; + return str_utils_compare(str1, str2); +} diff --git a/src/CLOUD/classes/data_test/glitter_test.c b/src/CLOUD/classes/data_test/glitter_test.c index b5f0628d..5fe4128b 100644 --- a/src/CLOUD/classes/data_test/glitter_test.c +++ b/src/CLOUD/classes/data_test/glitter_test.c @@ -25,7 +25,6 @@ typedef struct data_test_glitter_test_struct { bool input_pause; int32_t frame_counter; double_t delta_frame; - char* path; char* file; vector_data_struct_file files; @@ -69,8 +68,6 @@ bool data_test_glitter_test_init(class_data* data, render_context* rctx) { vector_data_struct_file_erase(&glt_test->files, i - glt_test->files.begin, data_struct_file_free); - glt_test->path = vector_length(glt_test->files) > 0 - ? string_data(&glt_test->files.begin[0].path) : 0; glt_test->file = vector_length(glt_test->files) > 0 ? string_data(&glt_test->files.begin[0].name) : 0; glt_test->stage_test = false; @@ -125,7 +122,6 @@ void data_test_glitter_test_imgui(class_data* data) { vector_length(glt_test->files), &file_index, 0, false, &data->imgui_focus); if (file_index != file_index_old) { - glt_test->path = string_data(&glt_test->files.begin[file_index].path); glt_test->file = string_data(&glt_test->files.begin[file_index].name); glt_test->input_stop = true; } @@ -258,18 +254,18 @@ void data_test_glitter_test_render(class_data* data) { else goto reset; } - else if (glt_test->input_play && !glitter_particle_manager_test_load_scene(GPM_VAL, hash, true)) { + else if (glt_test->input_play && !glitter_particle_manager_load_scene(GPM_VAL, hash)) { reset: glitter_particle_manager_free_scenes(GPM_VAL); glitter_particle_manager_free_effect_groups(GPM_VAL); - glitter_file_reader* fr = glitter_file_reader_init(GLITTER_FT, - glt_test->path, glt_test->file, -1.0f); + GPM_VAL->data = &data_list[DATA_AFT]; + glitter_file_reader* fr = glitter_file_reader_init(GLITTER_FT, 0, glt_test->file, -1.0f); vector_ptr_glitter_file_reader_push_back(&GPM_VAL->file_readers, &fr); glitter_particle_manager_update_file_reader(GPM_VAL); load: glt_test->frame_counter = 0; - glitter_particle_manager_test_load_scene(GPM_VAL, hash, true); + glitter_particle_manager_load_scene(GPM_VAL, hash); } glt_test->input_play = false; glt_test->input_stop = false; @@ -307,7 +303,6 @@ bool data_test_glitter_test_dispose(class_data* data) { draw_grid_3d = false; if (glt_test) { vector_data_struct_file_free(&glt_test->files, data_struct_file_free); - glt_test->path = 0; glt_test->file = 0; glt_test->input_play = false; glt_test->input_stop = false; diff --git a/src/CLOUD/classes/data_test/stage_test.c b/src/CLOUD/classes/data_test/stage_test.c index d57416f0..9a2d5314 100644 --- a/src/CLOUD/classes/data_test/stage_test.c +++ b/src/CLOUD/classes/data_test/stage_test.c @@ -5,6 +5,7 @@ #include "stage_test.h" #include "../../../KKdLib/io/path.h" +#include "../../../KKdLib/sort.h" #include "../../../KKdLib/str_utils.h" #include "../../../KKdLib/vector.h" #include "../../../CRE/Glitter/glitter.h" @@ -52,6 +53,7 @@ extern stage stage_test_data; static const char* data_test_stage_test_window_title = "Stage Test##Data Test"; +static int data_test_stage_test_stage_pv_quicksort_compare_func(void const* src1, void const* src2); static void data_test_stage_test_stage_pv_free(data_test_stage_test_stage_pv* pv); bool data_test_stage_test_init(class_data* data, render_context* rctx) { @@ -142,15 +144,12 @@ bool data_test_stage_test_init(class_data* data, render_context* rctx) { } } - for (data_test_stage_test_stage_pv* i = stage_pv->begin; i != &stage_pv->end[-1]; i++) - for (data_test_stage_test_stage_pv* j = i + 1; j != stage_pv->end; j++) - if (i->pv_id > j->pv_id) { - data_test_stage_test_stage_pv temp = *i; - *i = *j; - *j = temp; - } + if (vector_length(*stage_pv)) + quicksort_custom(stage_pv->begin, vector_length(*stage_pv), + sizeof(data_test_stage_test_stage_pv), + data_test_stage_test_stage_pv_quicksort_compare_func); - if (vector_length(*stage_pv) > 0) + if (vector_length(*stage_pv)) stage_test->pv_id = stage_pv->begin[0].pv_id; stage* stg = rctx->stage; @@ -424,6 +423,8 @@ void data_test_stage_test_render(class_data* data) { texture_database* aft_tex_db = &aft_data->data_ft.tex_db; stage_database* aft_stage_data = &aft_data->data_ft.stage_data; + stage_set(&stage_stgtst, rctx); + stage_init(&stage_test_data); stage_load(&stage_test_data, aft_data, aft_auth_3d_db, aft_obj_db, aft_tex_db, aft_stage_data, stage_test->stage_name, rctx); @@ -466,6 +467,12 @@ bool data_test_stage_test_dispose(class_data* data) { return true; } +static int data_test_stage_test_stage_pv_quicksort_compare_func(void const* src1, void const* src2) { + int32_t pv1 = ((data_test_stage_test_stage_pv*)src1)->pv_id; + int32_t pv2 = ((data_test_stage_test_stage_pv*)src2)->pv_id; + return pv1 > pv2 ? 1 : (pv1 < pv2 ? -1 : 0); +} + static void data_test_stage_test_stage_pv_free(data_test_stage_test_stage_pv* pv) { vector_string_free(&pv->stage, string_free); } diff --git a/src/CLOUD/classes/data_view/object.c b/src/CLOUD/classes/data_view/object.c index cfdf6d6d..987ae2ce 100644 --- a/src/CLOUD/classes/data_view/object.c +++ b/src/CLOUD/classes/data_view/object.c @@ -31,7 +31,7 @@ void data_view_object_imgui(class_data* data) { ImGuiStyle* style = igGetStyle(); ImFont* font = igGetFont(); - float_t w = min((float_t)width, 360.0f); + float_t w = min((float_t)width, 420.0f); float_t h = min((float_t)height, 480.0f); igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); @@ -56,10 +56,12 @@ void data_view_object_imgui(class_data* data) { size_t count = object_storage_get_object_set_count(); for (size_t i = 0; i < count; i++) { object_set* set = object_storage_get_object_set_by_index(i); + int32_t load_count = object_storage_get_object_set_load_count_by_index(i); - igPushID_Int((int32_t)i); + igPushID_Int(set->id); char buf[0x1000]; - sprintf_s(buf, sizeof(buf), "ID: 0x%08X; Name: %s", set->id, string_data(&set->name)); + sprintf_s(buf, sizeof(buf), "ID: 0x%08X; Load Count: %3d; Name: %s", + set->id, load_count, string_data(&set->name)); igSelectable_Bool(buf, false, 0, ImVec2_Empty); igPopID(); } diff --git a/src/CLOUD/classes/data_view/texture.c b/src/CLOUD/classes/data_view/texture.c index ddad45a6..0ef2a69e 100644 --- a/src/CLOUD/classes/data_view/texture.c +++ b/src/CLOUD/classes/data_view/texture.c @@ -31,7 +31,7 @@ void data_view_texture_imgui(class_data* data) { ImGuiStyle* style = igGetStyle(); ImFont* font = igGetFont(); - float_t w = min((float_t)width, 480.0f); + float_t w = min((float_t)width, 560.0f); float_t h = min((float_t)height, 480.0f); igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); @@ -59,10 +59,10 @@ void data_view_texture_imgui(class_data* data) { if (texture_get_id(tex->id)) continue; - igPushID_Int((int32_t)i); + igPushID_Int(tex->id); char buf[0x1000]; - sprintf_s(buf, sizeof(buf), "ID: 0x%06X; Width: %5d; Height: %5d; Mipmap Count: %2d", - texture_get_index(tex->id), tex->width, tex->height, tex->max_mipmap_level + 1); + sprintf_s(buf, sizeof(buf), "ID: 0x%06X; Init Count: %3d; Width: %5d; Height: %5d; Mipmap Count: %2d", + texture_get_index(tex->id), tex->init_count, tex->width, tex->height, tex->max_mipmap_level + 1); igSelectable_Bool(buf, false, 0, ImVec2_Empty); igPopID(); } diff --git a/src/CLOUD/classes/glitter_editor.c b/src/CLOUD/classes/glitter_editor.c index 40f0f295..0ef27c8f 100644 --- a/src/CLOUD/classes/glitter_editor.c +++ b/src/CLOUD/classes/glitter_editor.c @@ -129,9 +129,8 @@ typedef struct glitter_editor_struct { glitter_type load_glt_type; glitter_type save_glt_type; data_type load_data_type; - int32_t frame_counter; - int32_t old_frame_counter; - double_t delta_frame; + float_t frame_counter; + float_t old_frame_counter; int32_t start_frame; int32_t end_frame; glitter_random random; @@ -342,6 +341,8 @@ extern bool draw_grid_3d; extern bool close; extern bool global_context_menu; +extern float_t rob_frame; + static const char* glitter_editor_window_title = "Glitter Editor"; static void glitter_editor_windows(glitter_editor_struct* glt_edt, class_data* data); @@ -1244,19 +1245,15 @@ void glitter_editor_render(class_data* data) { && glt_edt->old_frame_counter == glt_edt->frame_counter) { glt_edt->old_frame_counter = glt_edt->frame_counter; if (GPM_VAL->scenes.end != GPM_VAL->scenes.begin) - glt_edt->delta_frame += get_delta_frame(); - - int32_t delta_frame = (int32_t)glt_edt->delta_frame; - glt_edt->frame_counter += delta_frame; - glt_edt->delta_frame -= (double_t)delta_frame; + glt_edt->frame_counter += get_delta_frame(); } if (glt_edt->input_reload) { vector_ptr_glitter_scene_clear(&GPM_VAL->scenes, glitter_scene_dispose); glt_edt->effect_group->emission = GPM_VAL->emission; glitter_particle_manager_set_frame(GPM_VAL, glt_edt->effect_group, - &glt_edt->scene, (float_t)glt_edt->frame_counter, - (float_t)glt_edt->old_frame_counter, + &glt_edt->scene, glt_edt->frame_counter, + glt_edt->old_frame_counter, glt_edt->counter, &glt_edt->random, true); glt_edt->old_frame_counter = glt_edt->frame_counter; glt_edt->input_reload = false; @@ -1264,15 +1261,15 @@ void glitter_editor_render(class_data* data) { if (glt_edt->old_frame_counter != glt_edt->frame_counter) { if (glt_edt->end_frame > 0) - while (glt_edt->frame_counter >= glt_edt->end_frame) - glt_edt->frame_counter -= glt_edt->end_frame - glt_edt->start_frame; + while (glt_edt->frame_counter >= (float_t)glt_edt->end_frame) + glt_edt->frame_counter -= (float_t)(glt_edt->end_frame - glt_edt->start_frame); - if (glt_edt->frame_counter < glt_edt->start_frame) - glt_edt->frame_counter = glt_edt->start_frame; + if (glt_edt->frame_counter < (float_t)glt_edt->start_frame) + glt_edt->frame_counter = (float_t)glt_edt->start_frame; glitter_particle_manager_set_frame(GPM_VAL, glt_edt->effect_group, - &glt_edt->scene, (float_t)glt_edt->frame_counter, - (float_t)glt_edt->old_frame_counter, + &glt_edt->scene, glt_edt->frame_counter, + glt_edt->old_frame_counter, glt_edt->counter, &glt_edt->random, false); glt_edt->old_frame_counter = glt_edt->frame_counter; } @@ -1281,10 +1278,10 @@ void glitter_editor_render(class_data* data) { glt_edt->input_pause = false; else if (glt_edt->input_reset) { GPM_VAL->counter = glt_edt->counter; - glt_edt->frame_counter = glt_edt->start_frame; + glt_edt->frame_counter = (float_t)glt_edt->start_frame; glitter_particle_manager_set_frame(GPM_VAL, glt_edt->effect_group, - &glt_edt->scene, (float_t)glt_edt->frame_counter, - (float_t)glt_edt->old_frame_counter, + &glt_edt->scene, glt_edt->frame_counter, + glt_edt->old_frame_counter, glt_edt->counter, &glt_edt->random, true); glt_edt->old_frame_counter = glt_edt->frame_counter; glt_edt->input_pause = true; @@ -1292,6 +1289,8 @@ void glitter_editor_render(class_data* data) { glt_edt->input_play = false; glt_edt->input_reset = false; + rob_frame = glt_edt->frame_counter; + glitter_editor_gl_process(glt_edt); } @@ -1327,9 +1326,8 @@ bool glitter_editor_dispose(class_data* data) { glt_edt->effect_flags = 0; glt_edt->emitter_flags = 0; glt_edt->particle_flags = 0; - glt_edt->frame_counter = 0; - glt_edt->old_frame_counter = 0; - glt_edt->delta_frame = 0.0; + glt_edt->frame_counter = 0.0f; + glt_edt->old_frame_counter = 0.0f; glt_edt->start_frame = 0; glt_edt->end_frame = 0; glt_edt->random.value = 0; @@ -1731,6 +1729,7 @@ static void glitter_editor_load_file(glitter_editor_struct* glt_edt, char* path, glt_edt->effect_group = 0; glt_edt->scene = 0; + GPM_VAL->data = &data_list[glt_edt->load_data_type]; glitter_file_reader* fr = glitter_file_reader_init(glt_edt->load_glt_type, path, file, -1.0f); if (glitter_file_reader_read(GPM_VAL, fr, GPM_VAL->emission)) { @@ -2127,9 +2126,9 @@ static void glitter_editor_test_window(glitter_editor_struct* glt_edt, class_dat igSeparator(); - int32_t frame_counter = glt_edt->frame_counter; - if (imguiColumnSliderInt("Frame", &frame_counter, glt_edt->start_frame, - glt_edt->end_frame, "%d", 0, true)) { + float_t frame_counter = glt_edt->frame_counter; + if (imguiColumnSliderFloat("Frame", &frame_counter, 1.0f, + (float_t)glt_edt->start_frame, (float_t)glt_edt->end_frame, "%.0f", 0, true)) { glt_edt->old_frame_counter = glt_edt->frame_counter; glt_edt->frame_counter = frame_counter; } @@ -2192,7 +2191,7 @@ static void glitter_editor_test_window(glitter_editor_struct* glt_edt, class_dat frame = 0.0f; life_time = 0; glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); - igText("%d - %.0f/%d", max(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time); + igText("%.0f - %.0f/%d", max(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time); ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); @@ -2772,9 +2771,9 @@ static void glitter_editor_play_manager(glitter_editor_struct* glt_edt) { igSeparator(); - int32_t frame_counter = glt_edt->frame_counter; - if (imguiColumnSliderInt("Frame", &frame_counter, glt_edt->start_frame, - glt_edt->end_frame, "%d", 0, true)) { + float_t frame_counter = glt_edt->frame_counter; + if (imguiColumnSliderFloat("Frame", &frame_counter, 1.0f, + (float_t)glt_edt->start_frame, (float_t)glt_edt->end_frame, "%.0f", 0, true)) { glt_edt->old_frame_counter = glt_edt->frame_counter; glt_edt->frame_counter = frame_counter; } @@ -2784,7 +2783,6 @@ static void glitter_editor_play_manager(glitter_editor_struct* glt_edt) { igSeparator(); - size_t ctrl; size_t disp; float_t frame; @@ -2793,7 +2791,7 @@ static void glitter_editor_play_manager(glitter_editor_struct* glt_edt) { frame = 0.0f; life_time = 0; glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); - igText("%d - %.0f/%d", max(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time); + igText("%.0f - %.0f/%d", max(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time); ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); @@ -3001,8 +2999,8 @@ static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class igSeparator(); bool ext_anim_changed = false; - glitter_effect_ext_anim ext_anim = *effect.data.ext_anim; if (eg->type == GLITTER_X) { + glitter_effect_ext_anim_x ext_anim = *effect.data.ext_anim_x; if (ext_anim.flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { const int32_t max_chara = 4; if (imguiColumnComboBox("Chara Index", glitter_effect_ext_anim_index_name, @@ -3030,15 +3028,20 @@ static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class } } else { - uint32_t object_hash = (uint32_t)ext_anim.object_hash; - if (glitter_editor_hash_input(glt_edt, "Object Hash", &ext_anim.object_hash)) + uint64_t object_hash = ext_anim.object_hash; + if (glitter_editor_hash_input(glt_edt, "Object Hash", &object_hash)) { + ext_anim.object_hash = (uint32_t)object_hash; ext_anim_changed = true; + } imguiColumnInputScalar("Instance ID", ImGuiDataType_U32, &ext_anim.instance_id, 0, 0, "%d", ImGuiInputTextFlags_CharsDecimal); - if (glitter_editor_hash_input(glt_edt, "File Name Hash", &ext_anim.file_name_hash)) + uint64_t file_name_hash = ext_anim.file_name_hash; + if (glitter_editor_hash_input(glt_edt, "File Name Hash", &file_name_hash)) { + ext_anim.file_name_hash = (uint32_t)file_name_hash; ext_anim_changed = true; + } const size_t mesh_name_size = sizeof(ext_anim.mesh_name); char mesh_name[sizeof(ext_anim.mesh_name)]; @@ -3078,8 +3081,16 @@ static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class (uint32_t*)&ext_anim.flags, GLITTER_EFFECT_EXT_ANIM_GET_THEN_UPDATE)) ext_anim_changed = true; + + uint64_t hash1 = hash_fnv1a64m((void*)effect.data.ext_anim_x, sizeof(glitter_effect_ext_anim_x), false); + uint64_t hash2 = hash_fnv1a64m((void*)&ext_anim, sizeof(glitter_effect_ext_anim_x), false); + if (hash1 != hash2 && ext_anim_changed) { + *effect.data.ext_anim_x = ext_anim; + changed = true; + } } else { + glitter_effect_ext_anim ext_anim = *effect.data.ext_anim; if (ext_anim.flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { const int32_t max_chara = eg->type == GLITTER_FT ? 6 : 3; if (imguiColumnComboBox("Chara Index", glitter_effect_ext_anim_index_name, @@ -3107,8 +3118,10 @@ static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class } } else { - if (glitter_editor_hash_input(glt_edt, "Object Hash", &ext_anim.object_hash)) + if (glitter_editor_hash_input(glt_edt, "Object Hash", &ext_anim.object_hash)) { + ext_anim.object = glitter_effect_ext_anim_get_object_info(ext_anim.object_hash); ext_anim_changed = true; + } const size_t mesh_name_size = sizeof(ext_anim.mesh_name); char mesh_name[sizeof(ext_anim.mesh_name)]; @@ -3123,13 +3136,13 @@ static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class (uint32_t*)&ext_anim.flags, GLITTER_EFFECT_EXT_ANIM_TRANS_ONLY)) ext_anim_changed = true; - } - uint64_t hash1 = hash_fnv1a64m((void*)effect.data.ext_anim, sizeof(glitter_effect_ext_anim), false); - uint64_t hash2 = hash_fnv1a64m((void*)&ext_anim, sizeof(glitter_effect_ext_anim), false); - if (hash1 != hash2 && ext_anim_changed) { - *effect.data.ext_anim = ext_anim; - changed = true; + uint64_t hash1 = hash_fnv1a64m((void*)effect.data.ext_anim, sizeof(glitter_effect_ext_anim), false); + uint64_t hash2 = hash_fnv1a64m((void*)&ext_anim, sizeof(glitter_effect_ext_anim), false); + if (hash1 != hash2 && ext_anim_changed) { + *effect.data.ext_anim = ext_anim; + changed = true; + } } } diff --git a/src/CLOUD/main.c b/src/CLOUD/main.c index f100a9ed..630bfa8d 100644 --- a/src/CLOUD/main.c +++ b/src/CLOUD/main.c @@ -127,7 +127,7 @@ static void a3da_to_dft_dsc(char* a3da_path, int32_t pv_id) { auth_3d_camera_root* cr = &cam_a3da.camera_root.begin[0]; for (int32_t i = 0; i < frames; i++) { - auth_3d_get_value(&cam_a3da, (mat4*)&mat4_identity, (float_t)1.0f); + auth_3d_time_step(&cam_a3da, (mat4*)&mat4_identity); bool enable = fabs(cam_a3da.dof.model_transform.rotation_value.z) > 0.000001f; if (!enable) { dof_index[i] = 0; diff --git a/src/CLOUD/render.c b/src/CLOUD/render.c index 51ef454b..76444aae 100644 --- a/src/CLOUD/render.c +++ b/src/CLOUD/render.c @@ -11,6 +11,7 @@ #define GLFW_EXPOSE_NATIVE_WIN32 #include #include +#include "../CRE/Glitter/file_reader.h" #include "../CRE/Glitter/particle_manager.h" #include "../CRE/camera.h" #include "../CRE/data.h" @@ -31,8 +32,10 @@ #include "../CRE/timer.h" #include "../CRE/post_process.h" #include "../KKdLib/io/path.h" +#include "../KKdLib/dsc.h" #include "../KKdLib/farc.h" #include "../KKdLib/pvpp.h" +#include "../KKdLib/pvsr.h" #include"classes/imgui_helper.h" #include @@ -40,6 +43,8 @@ #define OPENGL_DEBUG 0 #endif +shader_glsl cube_line_shader; +shader_glsl cube_line_point_shader; shader_glsl grid_shader; timer render_timer; @@ -48,6 +53,8 @@ timer render_timer; #define grid_spacing 1.0f const size_t grid_vertex_count = ((size_t)(grid_size / grid_spacing) * 2 + 1) * 4; +GLuint cube_line_vao; +GLuint cube_line_vbo; GLuint grid_vbo; static GLuint common_data_ubo = 0; stage stage_stgtst; @@ -109,6 +116,11 @@ static void APIENTRY render_debug_output(GLenum source, GLenum type, uint32_t id GLenum severity, GLsizei length, const char* message, const void* userParam); #endif +static void x_pv_player_init(); +static void x_pv_player_load(int32_t pv_id, int32_t stage_id); +static void x_pv_player_update(); +static void x_pv_player_free(); + extern bool close; bool reload_render; lock render_lock; @@ -120,6 +132,7 @@ bool global_context_menu; extern size_t frame_counter; wind* wind_ptr; object_database* obj_db_ptr; +int32_t stage_index = -1; int32_t render_main(void* arg) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); @@ -192,6 +205,8 @@ int32_t render_main(void* arg) { GetClientRect(window_handle, &window_rect); width = window_rect.right; height = window_rect.bottom; + width = 1280; + height = 720; old_scale = scale = ris->scale > 0 ? ris->scale : 1.0f; @@ -334,6 +349,8 @@ void render_set_scale_index(int32_t index) { scale = (float_t)value; } +float_t rob_frame = 0.0f; + static render_context* render_load() { object_storage_init(); texture_storage_init(); @@ -353,10 +370,7 @@ static render_context* render_load() { data_struct_init(); data_struct_load("CLOUD_data.txt"); - pvpp pp; - pvpp_init(&pp); - data_struct_load_file(&data_list[DATA_X], &pp, "rom/pv/", "pv824.pvpp", pvpp_load_file); - pvpp_free(&pp); + GPM_VAL->bone_data = &data_list[DATA_AFT].data_ft.bone_data; glGenBuffers(1, &common_data_ubo); @@ -369,6 +383,69 @@ static render_context* render_load() { render_shaders_load(); + const char* cube_line_vert_shader = + "#version 430 core\n" + "layout(location = 0) in vec4 a_position;\n" + "\n" + "out VertexData {\n" + " vec4 color;\n" + "} result;\n" + "\n" + "uniform mat4 vp;\n" + "uniform vec3 trans[4];\n" + "uniform float scale;\n" + "uniform vec4 color;\n" + "\n" + "void main() {\n" + " vec4 pos;\n" + " pos.xyz = trans[gl_VertexID];\n" + " pos.w = 1.0;\n" + " gl_Position = vp * pos;\n" + " result.color = color;\n" + "}\n"; + + const char* cube_line_frag_shader = + "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "in VertexData {\n" + " vec4 color;\n" + "} frg;\n" + "\n" + "void main() {\n" + " result = frg.color;\n" + "}\n"; + + const char* cube_line_point_vert_shader = + "#version 430 core\n" + "layout(location = 0) in vec4 a_position;\n" + "\n" + "out VertexData {\n" + " vec4 color;\n" + "} result;\n" + "\n" + "uniform mat4 vp;\n" + "uniform mat4 mat;\n" + "uniform vec4 color;\n" + "\n" + "void main() {\n" + " vec4 pos = mat * a_position;\n" + " gl_Position = vp * pos;\n" + " result.color = color;\n" + "}\n"; + + const char* cube_line_point_frag_shader = + "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "in VertexData {\n" + " vec4 color;\n" + "} frg;\n" + "\n" + "void main() {\n" + " result = frg.color;\n" + "}\n"; + const char* grid_vert_shader = "#version 430 core\n" "layout(location = 0) in vec4 a_position;\n" @@ -378,7 +455,7 @@ static render_context* render_load() { " vec4 color;\n" "} result;\n" "\n" - "layout(location = 0) uniform mat4 vp;\n" + "uniform mat4 vp;\n" "\n" "vec4 colors[] = {\n" " vec4(1.0, 0.0, 0.0, 1.0),\n" @@ -403,7 +480,8 @@ static render_context* render_load() { " result = frg.color;\n" "}\n"; - const char* fbo_render_vert_shader = "#version 430 core\n" + const char* fbo_render_vert_shader = + "#version 430 core\n" "void main() {\n" " gl_Position.x = -1.0 + float(gl_VertexID / 2) * 4.0;\n" " gl_Position.y = 1.0 - float(gl_VertexID % 2) * 4.0;\n" @@ -421,7 +499,8 @@ static render_context* render_load() { " result = texelFetch(g_color, ivec2(gl_FragCoord.xy), 0);\n" "}\n"; - const char* fbo_render_depth_frag_shader = "#version 430 core\n" + const char* fbo_render_depth_frag_shader = + "#version 430 core\n" "layout(location = 0) out vec4 result;\n" "\n" "layout(binding = 0) uniform sampler2D g_color;\n" @@ -433,6 +512,16 @@ static render_context* render_load() { "}\n"; shader_glsl_param param; + memset(¶m, 0, sizeof(shader_glsl_param)); + param.name = "Cube Line"; + shader_glsl_load_string(&cube_line_shader, + (char*)cube_line_vert_shader, (char*)cube_line_frag_shader, 0, ¶m); + + memset(¶m, 0, sizeof(shader_glsl_param)); + param.name = "Cube Line Point"; + shader_glsl_load_string(&cube_line_point_shader, + (char*)cube_line_point_vert_shader, (char*)cube_line_point_frag_shader, 0, ¶m); + memset(¶m, 0, sizeof(shader_glsl_param)); param.name = "Grid"; shader_glsl_load_string(&grid_shader, @@ -446,6 +535,7 @@ static render_context* render_load() { render_resize_fb(rctx, true); rob_chara_array_init(); + rob_chara_pv_data_array_init(); data_struct* aft_data = &data_list[DATA_AFT]; auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; @@ -476,16 +566,38 @@ static render_context* render_load() { object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM681"); object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM981"); - motion_set_load_motion(2, 0, aft_mot_db); - motion_set_load_motion(946, 0, aft_mot_db); + motion_set_load_motion(motion_database_get_motion_set_id(aft_mot_db, "CMN"), 0, aft_mot_db); + motion_set_load_motion(motion_database_get_motion_set_id(aft_mot_db, "PV824"), 0, aft_mot_db); rob_chara_pv_data pv_data; rob_chara_pv_data_init(&pv_data); - rob_chara_set(&rob_chara_array[0], 0, CHARA_MIKU, 0, &pv_data); - rob_chara_reset_data(&rob_chara_array[0], &rob_chara_array[0].pv_data, aft_bone_data, aft_mot_db); - rob_chara_reset(&rob_chara_array[0], aft_bone_data, aft_data, aft_obj_db); - rob_chara_load_motion(&rob_chara_array[0], 9996, 2, aft_bone_data, aft_mot_db); - //rob_chara_set_frame(&rob_chara_array[0], 1000.0f); + pv_data.field_0 = 2; + int32_t chara_id = rob_chara_array_set_pv_data(CHARA_MIKU, &pv_data, 0, false); + if (chara_id >= 0 && chara_id < ROB_CHARA_COUNT) { + rob_chara_reset_data(&rob_chara_array[chara_id], &rob_chara_array[chara_id].pv_data, aft_bone_data, aft_mot_db); + rob_chara_reset(&rob_chara_array[chara_id], aft_bone_data, aft_data, aft_obj_db); + rob_chara_load_motion(&rob_chara_array[chara_id], + motion_database_get_motion_id(aft_mot_db, "PV824_STF_P1_00"), 2, aft_bone_data, aft_mot_db); + rob_chara_set_visibility(&rob_chara_array[chara_id], true); + //rob_chara_set_frame(&rob_chara_array[chara_id], 1000.0f); + } + + float_t cube_line_verts[] = { + -1.0, 1.0, + 1.0, 1.0, + -1.0, -1.0, + 1.0, -1.0, + }; + + glGenVertexArrays(1, &cube_line_vao); + glGenBuffers(1, &cube_line_vbo); + gl_state_bind_vertex_array(cube_line_vao); + gl_state_bind_array_buffer(cube_line_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(cube_line_verts), (void*)cube_line_verts, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float_t) * 2, 0); + gl_state_bind_array_buffer(0); + gl_state_bind_vertex_array(0); float_t* grid_verts = force_malloc(sizeof(float_t) * 3 * grid_vertex_count); @@ -527,6 +639,9 @@ static render_context* render_load() { free(grid_verts); + x_pv_player_init(); + x_pv_player_load(826, 26); + camera* cam = rctx->camera; camera_initialize(cam, aspect, internal_3d_res.x, internal_3d_res.y); @@ -534,7 +649,8 @@ static render_context* render_load() { //camera_rotate(cam, &((vec2d){ -45.0, -32.5 })); //camera_set_position(cam, &((vec3){ -6.67555f, 4.68882f, -3.67537f })); //camera_rotate(cam, &((vec2d){ 136.5, -20.5 })); - camera_set_position(cam, &((vec3) { 0.0f, 1.0f, 3.45f })); + camera_set_view_point(cam, &((vec3) { 0.0f, 1.0f, 3.45f })); + camera_set_interest(cam, &((vec3) { 0.0f, 1.0f, 0.0f })); camera_set_fov(cam, 70.0); imgui_context = igCreateContext(0); @@ -633,7 +749,8 @@ static void render_update(render_context* rctx) { //camera_rotate(cam, &((vec2d){ -45.0, -32.5 })); //camera_set_position(cam, &((vec3){ -6.67555f, 4.68882f, -3.67537f })); //camera_rotate(cam, &((vec2d){ 136.5, -20.5 })); - camera_set_position(cam, &((vec3){ 0.0f, 1.0f, 3.45f })); + camera_set_view_point(cam, &((vec3) { 0.0f, 1.0f, 3.45f })); + camera_set_interest(cam, &((vec3) { 0.0f, 1.0f, 0.0f })); camera_set_fov(cam, 70.0); } else { @@ -644,13 +761,19 @@ static void render_update(render_context* rctx) { } camera_update(cam); - float_t frame = rob_chara_get_frame(&rob_chara_array[0]); - float_t frame_count = rob_chara_get_frame_count(&rob_chara_array[0]); - frame += get_delta_frame(); - if (frame >= frame_count) - frame -= frame_count; - rob_chara_set_frame(&rob_chara_array[0], frame); - rob_chara_array[0].item_equip->shadow_type = SHADOW_CHARA; + for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) { + if (rob_chara_pv_data_array[i].field_0 == -1) + continue; + + float_t frame = rob_chara_get_frame(&rob_chara_array[i]); + float_t frame_count = rob_chara_get_frame_count(&rob_chara_array[i]); + frame += get_delta_frame(); + if (frame >= frame_count) + frame -= frame_count; + //rob_chara_set_frame(&rob_chara_array[j], frame); + rob_chara_set_frame(&rob_chara_array[i], rob_frame); + rob_chara_array[i].item_equip->shadow_type = SHADOW_CHARA; + } data_struct* aft_data = &data_list[DATA_AFT]; obj_db_ptr = &aft_data->data_ft.obj_db; @@ -659,8 +782,13 @@ static void render_update(render_context* rctx) { classes_process_render(classes, classes_count); wind_ptr = rctx->wind; - rob_chara_calc(&rob_chara_array[0]); - rob_chara_draw(&rob_chara_array[0], rctx); + for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) { + if (rob_chara_pv_data_array[i].field_0 == -1) + continue; + + rob_chara_calc(&rob_chara_array[i]); + rob_chara_draw(&rob_chara_array[i], rctx); + } stage_update(rctx->stage, rctx); @@ -688,6 +816,58 @@ static void render_update(render_context* rctx) { gl_state_bind_uniform_buffer(common_data_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, COMMON_DATA_SIZE, &common_data); gl_state_bind_uniform_buffer(0); + + shader_glsl_set_mat4(&cube_line_shader, "vp", false, cam->view_projection); + shader_glsl_set_mat4(&cube_line_point_shader, "vp", false, cam->view_projection); +} + +static void cube_line_draw(shader_glsl* shader, camera* cam, vec3* trans, float_t line_size, vec4* color) { + mat4 mat[2]; + mat4_translate(trans[0].x, trans[0].y, trans[0].z, &mat[0]); + mat4_translate(trans[1].x, trans[1].y, trans[1].z, &mat[1]); + mat4_mult(&cam->inv_view_rot, &mat[0], &mat[0]); + mat4_mult(&cam->inv_view_rot, &mat[1], &mat[1]); + mat4_get_translation(&mat[0], &trans[0]); + mat4_get_translation(&mat[1], &trans[1]); + + float_t dx = trans[1].x - trans[0].x; + float_t dy = trans[1].y - trans[0].y; + vec3 norm[2]; + norm[0] = (vec3){ -dy, dx, 0.0f }; + norm[1] = (vec3){ dy, -dx, 0.0f }; + vec3_normalize(norm[0], norm[0]); + vec3_normalize(norm[1], norm[1]); + vec3_mult_scalar(norm[0], line_size, norm[0]); + vec3_mult_scalar(norm[1], line_size, norm[1]); + mat4_mult_vec3(&cam->inv_view_rot, &norm[0], &norm[0]); + mat4_mult_vec3(&cam->inv_view_rot, &norm[1], &norm[1]); + + vec3 vert_trans[4]; + vec3_add(trans[0], norm[0], vert_trans[0]); + vec3_add(trans[0], norm[1], vert_trans[1]); + vec3_add(trans[1], norm[0], vert_trans[2]); + vec3_add(trans[1], norm[1], vert_trans[3]); + shader_glsl_set_vec3_array(shader, "trans", 4, vert_trans); + shader_glsl_set_vec4(shader, "color", *color); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +static void cube_line_point_draw(shader_glsl* shader, camera* cam, vec3* trans, + float_t size, float_t dark_size, vec4* color, vec4* dark_color) { + mat4 mat; + mat4_scale(dark_size, dark_size, dark_size, &mat); + mat4_set_translation(&mat, trans); + mat4_mult(&cam->inv_view_rot, &mat, &mat); + shader_glsl_set_mat4(&cube_line_point_shader, "mat", false, mat); + shader_glsl_set_vec4(&cube_line_point_shader, "color", *dark_color); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + mat4_scale(size, size, size, &mat); + mat4_set_translation(&mat, trans); + mat4_mult(&cam->inv_view_rot, &mat, &mat); + shader_glsl_set_mat4(&cube_line_point_shader, "mat", false, mat); + shader_glsl_set_vec4(&cube_line_point_shader, "color", *color); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } static void render_draw(render_context* rctx) { @@ -695,6 +875,8 @@ static void render_draw(render_context* rctx) { static const GLfloat depth_clear = 1.0f; static const GLint stencil_clear = 0; + camera* cam = rctx->camera; + for (int32_t i = 0; i < 32; i++) { if (!gl_state_check_texture_binding_2d(i) && !gl_state_check_texture_binding_cube_map(i)) continue; @@ -737,6 +919,207 @@ static void render_draw(render_context* rctx) { gl_state_bind_uniform_buffer_base(0, common_data_ubo); classes_process_draw(classes, classes_count); + static bool rob_draw = false; + + gl_state_disable_cull_face(); + gl_state_bind_vertex_array(cube_line_vao); + const float_t line_size = 0.0025f; + const float_t line_point_size = line_size * 1.125f; + const float_t line_point_dark_size = line_size * 1.5f; + vec4 bone_color = (vec4){ 1.0f, 0.0f, 0.0f, 1.0f }; + vec4 cns_color = (vec4){ 1.0f, 1.0f, 0.0f, 1.0f }; + vec4 exp_color = (vec4){ 0.0f, 1.0f, 0.0f, 1.0f }; + vec4 osg_color = (vec4){ 0.0f, 0.0f, 1.0f, 1.0f }; + vec4 osg_node_color = (vec4){ 1.0f, 0.0f, 1.0f, 1.0f }; + vec4 point_color = (vec4){ 1.0f, 1.0f, 1.0f, 1.0f }; + vec4 point_dark_color = (vec4){ 0.0f, 0.0f, 0.0f, 1.0f }; + for (int32_t i = 0; i < ROB_CHARA_COUNT && rob_draw; i++) { + if (rob_chara_pv_data_array[i].field_0 == -1) + continue; + + rob_chara* rob_chr = &rob_chara_array[i]; + rob_chara_bone_data* rob_bone_data = rob_chr->bone_data; + size_t object_bone_count = rob_bone_data->object_bone_count; + size_t total_bone_count = rob_bone_data->total_bone_count; + size_t ik_bone_count = rob_bone_data->ik_bone_count; + vector_bone_node* nodes = &rob_bone_data->nodes; + shader_glsl_use(&cube_line_shader); + for (bone_node* j = nodes->begin; j != nodes->end; j++) { + if (!j->parent) + continue; + + vec3 trans[2]; + mat4_get_translation(j->parent->mat, &trans[0]); + mat4_get_translation(j->mat, &trans[1]); + + if (!memcmp(&trans[0], &trans[1], sizeof(vec3))) + continue; + + cube_line_draw(&cube_line_shader, cam, trans, line_size, &bone_color); + } + + rob_chara_item_equip* rob_item_equip = rob_chr->item_equip; + for (int32_t j = rob_item_equip->first_item_equip_object; + j < rob_item_equip->max_item_equip_object; j++) { + rob_chara_item_equip_object* itm_eq_obj = &rob_item_equip->item_equip_object[j]; + + vector_ptr_ex_expression_block* expression_blocks = &itm_eq_obj->expression_blocks; + for (ex_expression_block** k = expression_blocks->begin; k != expression_blocks->end; k++) { + if (!*k) + continue; + + ex_expression_block* exp = *k; + + if (!exp->base.bone_node || !exp->base.parent_bone_node) + continue; + + vec3 trans[2]; + mat4_get_translation(exp->base.parent_bone_node->mat, &trans[0]); + mat4_get_translation(exp->base.bone_node->mat, &trans[1]); + + if (!memcmp(&trans[0], &trans[1], sizeof(vec3))) + continue; + + cube_line_draw(&cube_line_shader, cam, trans, line_size, &cns_color); + } + + vector_ptr_ex_constraint_block* constraint_blocks = &itm_eq_obj->constraint_blocks; + for (ex_constraint_block** k = constraint_blocks->begin; k != constraint_blocks->end; k++) { + if (!*k) + continue; + + ex_constraint_block* cns = *k; + + if (!cns->base.bone_node || !cns->base.parent_bone_node) + continue; + + vec3 trans[2]; + mat4_get_translation(cns->base.parent_bone_node->mat, &trans[0]); + mat4_get_translation(cns->base.bone_node->mat, &trans[1]); + + if (!memcmp(&trans[0], &trans[1], sizeof(vec3))) + continue; + + cube_line_draw(&cube_line_shader, cam, trans, line_size, &exp_color); + } + + vector_ptr_ex_osage_block* osage_blocks = &itm_eq_obj->osage_blocks; + for (ex_osage_block** k = osage_blocks->begin; k != osage_blocks->end; k++) { + if (!*k) + continue; + + ex_osage_block* osg = *k; + + if (!osg->base.bone_node || !osg->base.parent_bone_node) + continue; + + vec3 trans[2]; + mat4_get_translation(osg->base.parent_bone_node->mat, &trans[0]); + mat4_get_translation(osg->base.bone_node->mat, &trans[1]); + + if (!memcmp(&trans[0], &trans[1], sizeof(vec3))) + continue; + + cube_line_draw(&cube_line_shader, cam, trans, line_size, &osg_color); + + rob_osage* rob_osg = &osg->rob; + vector_rob_osage_node* nodes = &osg->rob.nodes; + rob_osage_node* parent_node = &osg->rob.node; + for (rob_osage_node* l = nodes->begin; l != nodes->end; parent_node = l++) { + if (!l->bone_node || !parent_node->bone_node) + continue; + + vec3 trans[2]; + mat4_get_translation(parent_node->bone_node->mat, &trans[0]); + mat4_get_translation(l->bone_node->mat, &trans[1]); + + if (!memcmp(&trans[0], &trans[1], sizeof(vec3))) + continue; + + cube_line_draw(&cube_line_shader, cam, trans, line_size, &osg_node_color); + } + } + } + + shader_glsl_use(&cube_line_point_shader); + for (bone_node* j = nodes->begin; j != nodes->end; j++) { + vec3 trans; + mat4_get_translation(j->mat, &trans); + cube_line_point_draw(&cube_line_point_shader, cam, &trans, + line_point_size, line_point_dark_size, &point_color, &point_dark_color); + } + + for (int32_t j = rob_item_equip->first_item_equip_object; + j < rob_item_equip->max_item_equip_object; j++) { + rob_chara_item_equip_object* itm_eq_obj = &rob_item_equip->item_equip_object[j]; + + vector_ptr_ex_expression_block* expression_blocks = &itm_eq_obj->expression_blocks; + for (ex_expression_block** k = expression_blocks->begin; k != expression_blocks->end; k++) { + if (!*k) + continue; + + ex_expression_block* exp = *k; + + if (!exp->base.bone_node) + continue; + + vec3 trans; + mat4_get_translation(exp->base.bone_node->mat, &trans); + cube_line_point_draw(&cube_line_point_shader, cam, &trans, + line_point_size, line_point_dark_size, &point_color, &point_dark_color); + } + + vector_ptr_ex_constraint_block* constraint_blocks = &itm_eq_obj->constraint_blocks; + for (ex_constraint_block** k = constraint_blocks->begin; k != constraint_blocks->end; k++) { + if (!*k) + continue; + + ex_constraint_block* cns = *k; + + if (!cns->base.bone_node) + continue; + + vec3 trans; + mat4_get_translation(cns->base.bone_node->mat, &trans); + cube_line_point_draw(&cube_line_point_shader, cam, &trans, + line_point_size, line_point_dark_size, &point_color, &point_dark_color); + } + + vector_ptr_ex_osage_block* osage_blocks = &itm_eq_obj->osage_blocks; + for (ex_osage_block** k = osage_blocks->begin; k != osage_blocks->end; k++) { + if (!*k) + continue; + + ex_osage_block* osg = *k; + + if (!osg->base.bone_node) + continue; + + vec3 trans; + mat4_get_translation(osg->base.bone_node->mat, &trans); + cube_line_point_draw(&cube_line_point_shader, cam, &trans, + line_point_size, line_point_dark_size, &point_color, &point_dark_color); + + rob_osage* rob_osg = &osg->rob; + vector_rob_osage_node* nodes = &osg->rob.nodes; + for (rob_osage_node* l = nodes->begin; l != nodes->end; l++) { + if (!l->bone_node) + continue; + + vec3 trans; + mat4_get_translation(l->bone_node->mat, &trans); + cube_line_point_draw(&cube_line_point_shader, cam, &trans, + line_point_size, line_point_dark_size, &point_color, &point_dark_color); + } + } + } + + //rob_chara_calc(&rob_chara_array[j]); + //rob_chara_draw(&rob_chara_array[j], rctx); + } + gl_state_bind_vertex_array(0); + gl_state_enable_cull_face(); + gl_state_bind_framebuffer(0); render_texture_shader_set_glsl(0); glViewport(0, 0, width, height); @@ -765,9 +1148,15 @@ static void render_dispose(render_context* rctx) { render_shaders_free(); shader_glsl_free(&grid_shader); + shader_glsl_free(&cube_line_point_shader); + shader_glsl_free(&cube_line_shader); + + x_pv_player_free(); glDeleteBuffers(1, &common_data_ubo); glDeleteBuffers(1, &grid_vbo); + glDeleteBuffers(1, &cube_line_vbo); + glDeleteVertexArrays(1, &cube_line_vao); rob_chara_array_free(); @@ -978,3 +1367,175 @@ static void APIENTRY render_debug_output(GLenum source, GLenum type, uint32_t id printf("########################################\n\n"); } #endif + +typedef struct x_pv_player_glitter { + string name; + uint32_t hash; + glitter_effect_group* effect_group; +} x_pv_player_glitter; + +typedef struct x_pv_player_stage_anim_speed { + int32_t frame; + int32_t bpm; +} x_pv_player_stage_anim_speed; + +vector(x_pv_player_stage_anim_speed) + +typedef struct x_pv_player { + int32_t pv_id; + int32_t stage_id; + pvpp pp; + pvsr sr; + dsc dsc; + + x_pv_player_glitter pv_glitter; + x_pv_player_glitter stage_glitter; + vector_x_pv_player_stage_anim_speed anim_speed; +} x_pv_player; + +vector_func(x_pv_player_stage_anim_speed) + +static void x_pv_player_glitter_load(x_pv_player_glitter* pv_glt, char* name); +static void x_pv_player_glitter_free(x_pv_player_glitter* pv_glt); + +static x_pv_player x_pv_player_data; + +static void x_pv_player_init() { + memset(&x_pv_player_data, 0, sizeof(x_pv_player)); +} + +static void x_pv_player_load(int32_t pv_id, int32_t stage_id) { + x_pv_player* x_pv = &x_pv_player_data; + x_pv->pv_id = pv_id; + x_pv->stage_id = stage_id; + + char path_buf[0x200]; + char file_buf[0x200]; + + data_struct* x_data = &data_list[DATA_X]; + + sprintf_s(file_buf, sizeof(file_buf), "pv%03d.pvpp", pv_id); + pvpp_init(&x_pv->pp); + data_struct_load_file(x_data, &x_pv->pp, "rom/pv/", file_buf, pvpp_load_file); + + sprintf_s(file_buf, sizeof(file_buf), "stgpv%03d_param.pvsr", stage_id); + pvsr_init(&x_pv->sr); + data_struct_load_file(x_data, &x_pv->sr, "rom/pv_stage_rsrc/", file_buf, pvsr_load_file); + + GPM_VAL->data = x_data; + sprintf_s(file_buf, sizeof(file_buf), "eff_pv%03d_main", pv_id); + x_pv_player_glitter_load(&x_pv->pv_glitter, file_buf); + + sprintf_s(file_buf, sizeof(file_buf), "eff_stgpv%03d_main", stage_id); + x_pv_player_glitter_load(&x_pv->stage_glitter, file_buf); + + dsc dsc_scene; + dsc dsc_system; + dsc dsc_easy; + dsc_init(&dsc_scene); + dsc_init(&dsc_system); + dsc_init(&dsc_easy); + + farc dsc_common_farc; + sprintf_s(path_buf, sizeof(path_buf), "rom/pv_script/pv%03d/", pv_id); + sprintf_s(file_buf, sizeof(file_buf), "pv_%03d_common.farc", pv_id); + farc_init(&dsc_common_farc); + data_struct_load_file(x_data, &dsc_common_farc, path_buf, file_buf, farc_load_file); + + sprintf_s(file_buf, sizeof(file_buf), "pv_%03d_scene.dsc", pv_id); + farc_file* dsc_scene_ff = farc_read_file(&dsc_common_farc, file_buf); + if (dsc_scene_ff) + dsc_parse(&dsc_scene, dsc_scene_ff->data, dsc_scene_ff->size, DSC_X); + + sprintf_s(file_buf, sizeof(file_buf), "pv_%03d_system.dsc", pv_id); + farc_file* dsc_system_ff = farc_read_file(&dsc_common_farc, file_buf); + if (dsc_system_ff) + dsc_parse(&dsc_system, dsc_system_ff->data, dsc_system_ff->size, DSC_X); + farc_free(&dsc_common_farc); + + sprintf_s(file_buf, sizeof(file_buf), "pv_%03d_easy.dsc", pv_id); + dsc_easy.type = DSC_X; + data_struct_load_file(x_data, &dsc_easy, path_buf, file_buf, dsc_load_file); + + dsc_merge(&x_pv->dsc, 3, &dsc_scene, &dsc_system, &dsc_easy); + + dsc_free(&dsc_scene); + dsc_free(&dsc_system); + dsc_free(&dsc_easy); + + int32_t end_func_id = dsc_x_get_func_id("END"); + int32_t time_func_id = dsc_x_get_func_id("TIME"); + int32_t bar_time_set_func_id = dsc_x_get_func_id("BAR_TIME_SET"); + int32_t pv_end_func_id = dsc_x_get_func_id("PV_END"); + int32_t bar_point_func_id = dsc_x_get_func_id("BAR_POINT"); + + dsc* d = &x_pv->dsc; + int32_t time = -1; + int32_t frame = -1; + bool bar_set = false; + int32_t prev_bar_point_time = -1; + int32_t prev_bpm = -1; + for (dsc_data* i = d->data.begin; i != d->data.end; i++) + if (i->func == end_func_id || i->func == pv_end_func_id) + break; + else if (i->func == time_func_id) { + time = (int32_t)dsc_data_get_func_data(d, i)[0]; + frame = (int32_t)roundf((float_t)time * (float_t)(60.0f / 100000.0f)); + } + else if (i->func == bar_time_set_func_id) { + if (prev_bar_point_time != -1) + continue; + + uint32_t* data = dsc_data_get_func_data(d, i); + int32_t bpm = (int32_t)data[0]; + int32_t time_signature = (int32_t)(data[1] + 1); + + if (bpm != prev_bpm) { + x_pv_player_stage_anim_speed anim_speed; + printf("Frame: %5d; BPM: %3d; Speed: %.9f\n", frame, bpm, (double_t)bpm * (1.0 / 120.0)); + vector_x_pv_player_stage_anim_speed_push_back(&x_pv->anim_speed, &anim_speed); + } + prev_bpm = bpm; + } + else if (i->func == bar_point_func_id) { + if (prev_bar_point_time != -1) { + float_t frame_speed = 200000.0f / (float_t)(time - prev_bar_point_time); + int32_t bpm = (int32_t)roundf(frame_speed * 120.0f); + if (bpm != prev_bpm) { + x_pv_player_stage_anim_speed anim_speed; + anim_speed.frame = frame; + anim_speed.bpm = bpm; + printf("Frame: %5d; BPM: %3d; Speed: %.9f\n", frame, bpm, (double_t)bpm * (1.0 / 120.0)); + vector_x_pv_player_stage_anim_speed_push_back(&x_pv->anim_speed, &anim_speed); + } + prev_bpm = bpm; + } + prev_bar_point_time = time; + } +} + +static void x_pv_player_update() { + +} + +static void x_pv_player_free() { + x_pv_player* x_pv = &x_pv_player_data; + pvpp_free(&x_pv->pp); + pvsr_free(&x_pv->sr); + dsc_free(&x_pv->dsc); + vector_x_pv_player_stage_anim_speed_free(&x_pv->anim_speed, 0); +} + +static void x_pv_player_glitter_load(x_pv_player_glitter* pv_glt, char* name) { + string_init(&pv_glt->name, name); + pv_glt->hash = hash_murmurhash(string_data(&pv_glt->name), pv_glt->name.length, 0, false, false); + glitter_file_reader* fr = glitter_file_reader_init(GLITTER_X, 0, string_data(&pv_glt->name), -1.0f); + vector_ptr_glitter_file_reader_push_back(&GPM_VAL->file_readers, &fr); + glitter_particle_manager_update_file_reader(GPM_VAL); + pv_glt->effect_group = glitter_particle_manager_get_effect_group(GPM_VAL, pv_glt->hash); +} + +static void x_pv_player_glitter_free(x_pv_player_glitter* pv_glt) { + glitter_particle_manager_free_scene(GPM_VAL, pv_glt->hash); + glitter_particle_manager_free_effect_group(GPM_VAL, pv_glt->hash); +} diff --git a/src/CRE/Glitter/effect.c b/src/CRE/Glitter/effect.c index 7d3d0d8c..f9b1a61e 100644 --- a/src/CRE/Glitter/effect.c +++ b/src/CRE/Glitter/effect.c @@ -7,7 +7,6 @@ #include "animation.h" #include "emitter.h" -static object_info glitter_effect_ext_anim_get_object_info(uint64_t hash); static bool glitter_effect_pack_file(GLT, f2_struct* st, glitter_effect* a3); static bool glitter_effect_unpack_file(GLT, void* data, glitter_effect* a3, bool use_big_endian); @@ -107,7 +106,7 @@ void glitter_effect_dispose(glitter_effect* e) { free(e); } -static object_info glitter_effect_ext_anim_get_object_info(uint64_t hash) { +object_info glitter_effect_ext_anim_get_object_info(uint64_t hash) { vector_object_set_info* object_set = &obj_db_ptr->object_set; for (object_set_info* i = object_set->begin; i != object_set->end; i++) { for (object_info_data* j = i->object.begin; j != i->object.end; j++) @@ -240,6 +239,7 @@ static bool glitter_effect_unpack_file(GLT, void* data, glitter_effect* a2, bool use_big_endian) { size_t d; glitter_effect_ext_anim* ext_anim; + glitter_effect_ext_anim_x* ext_anim_x; glitter_effect_file_flag flags; if (GLT_VAL == GLITTER_X) { @@ -317,100 +317,94 @@ static bool glitter_effect_unpack_file(GLT, if (type == 1) a2->data.flags |= GLITTER_EFFECT_LOCAL; else if (type == 2) { - ext_anim = force_malloc(sizeof(glitter_effect_ext_anim)); - a2->data.ext_anim = ext_anim; - if (ext_anim) { + ext_anim_x = force_malloc(sizeof(glitter_effect_ext_anim_x)); + a2->data.ext_anim_x = ext_anim_x; + if (ext_anim_x) { if (use_big_endian) { - ext_anim->chara_index = load_reverse_endianness_int32_t((void*)d); - ext_anim->flags = load_reverse_endianness_int32_t((void*)(d + 4)); - ext_anim->node_index = load_reverse_endianness_int32_t((void*)(d + 8)); + ext_anim_x->chara_index = load_reverse_endianness_int32_t((void*)d); + ext_anim_x->flags = load_reverse_endianness_int32_t((void*)(d + 4)); + ext_anim_x->node_index = load_reverse_endianness_int32_t((void*)(d + 8)); } else { - ext_anim->chara_index = *(int32_t*)d; - ext_anim->flags = *(int32_t*)(d + 4); - ext_anim->node_index = *(int32_t*)(d + 8); + ext_anim_x->chara_index = *(int32_t*)d; + ext_anim_x->flags = *(int32_t*)(d + 4); + ext_anim_x->node_index = *(int32_t*)(d + 8); } - ext_anim->flags |= GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM; - ext_anim->mesh_name[0] = 0; + ext_anim_x->flags |= GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM; + ext_anim_x->mesh_name[0] = 0; } } else if (type == 3) { if (a2->version == 8) { - ext_anim = force_malloc(sizeof(glitter_effect_ext_anim)); - a2->data.ext_anim = ext_anim; - if (ext_anim) { + ext_anim_x = force_malloc(sizeof(glitter_effect_ext_anim_x)); + a2->data.ext_anim_x = ext_anim_x; + if (ext_anim_x) { if (use_big_endian) { - ext_anim->object_hash = load_reverse_endianness_uint64_t((void*)d); - ext_anim->flags = load_reverse_endianness_int32_t((void*)(d + 8)); + ext_anim_x->object_hash = (uint32_t)load_reverse_endianness_uint64_t((void*)d); + ext_anim_x->flags = load_reverse_endianness_int32_t((void*)(d + 8)); } else { - ext_anim->object_hash = *(uint64_t*)d; - ext_anim->flags = *(int32_t*)(d + 8); + ext_anim_x->object_hash = (uint32_t) * (uint64_t*)d; + ext_anim_x->flags = *(int32_t*)(d + 8); } - ext_anim->instance_id = 0; - ext_anim->file_name_hash = hash_murmurhash_empty; - ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); - ext_anim->node_index = 18; + ext_anim_x->instance_id = 0; + ext_anim_x->file_name_hash = hash_murmurhash_empty; if (*(uint8_t*)(d + 12)) { - strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 20), 0x80); - ext_anim->mesh_name[0x7F] = '\0'; + strncpy_s(ext_anim_x->mesh_name, 0x80, (uint8_t*)(d + 20), 0x80); + ext_anim_x->mesh_name[0x7F] = '\0'; } else - ext_anim->mesh_name[0] = 0; + ext_anim_x->mesh_name[0] = 0; } } else if (a2->version == 10) { - ext_anim = force_malloc(sizeof(glitter_effect_ext_anim)); - a2->data.ext_anim = ext_anim; - if (ext_anim) { + ext_anim_x = force_malloc(sizeof(glitter_effect_ext_anim_x)); + a2->data.ext_anim_x = ext_anim_x; + if (ext_anim_x) { if (use_big_endian) { - ext_anim->object_hash = load_reverse_endianness_uint64_t((void*)d); - ext_anim->flags = load_reverse_endianness_int32_t((void*)(d + 8)); + ext_anim_x->object_hash = (uint32_t)load_reverse_endianness_uint64_t((void*)d); + ext_anim_x->flags = load_reverse_endianness_int32_t((void*)(d + 8)); } else { - ext_anim->object_hash = *(uint64_t*)d; - ext_anim->flags = *(int32_t*)(d + 8); + ext_anim_x->object_hash = (uint32_t) * (uint64_t*)d; + ext_anim_x->flags = *(int32_t*)(d + 8); } - ext_anim->instance_id = 0; - ext_anim->file_name_hash = hash_murmurhash_empty; - ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); - ext_anim->node_index = 18; + ext_anim_x->instance_id = 0; + ext_anim_x->file_name_hash = hash_murmurhash_empty; if (*(uint8_t*)(d + 16)) { - strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 16), 0x80); - ext_anim->mesh_name[0x7F] = '\0'; + strncpy_s(ext_anim_x->mesh_name, 0x80, (uint8_t*)(d + 16), 0x80); + ext_anim_x->mesh_name[0x7F] = '\0'; } else - ext_anim->mesh_name[0] = 0; + ext_anim_x->mesh_name[0] = 0; } } else { - ext_anim = force_malloc(sizeof(glitter_effect_ext_anim)); - a2->data.ext_anim = ext_anim; - if (ext_anim) { + ext_anim_x = force_malloc(sizeof(glitter_effect_ext_anim_x)); + a2->data.ext_anim_x = ext_anim_x; + if (ext_anim_x) { if (use_big_endian) { - ext_anim->object_hash = load_reverse_endianness_uint64_t((void*)d); - ext_anim->flags = load_reverse_endianness_int32_t((void*)(d + 8)); - ext_anim->instance_id = load_reverse_endianness_int32_t((void*)(d + 12)); - ext_anim->file_name_hash = load_reverse_endianness_uint64_t((void*)(d + 16)); + ext_anim_x->object_hash = (uint32_t)load_reverse_endianness_uint64_t((void*)d); + ext_anim_x->flags = load_reverse_endianness_int32_t((void*)(d + 8)); + ext_anim_x->instance_id = load_reverse_endianness_int32_t((void*)(d + 12)); + ext_anim_x->file_name_hash = (uint32_t)load_reverse_endianness_uint64_t((void*)(d + 16)); } else { - ext_anim->object_hash = *(uint64_t*)d; - ext_anim->flags = *(int32_t*)(d + 8); - ext_anim->instance_id = *(int32_t*)(d + 12); - ext_anim->file_name_hash = *(uint64_t*)(d + 16); + ext_anim_x->object_hash = (uint32_t) * (uint64_t*)d; + ext_anim_x->flags = *(int32_t*)(d + 8); + ext_anim_x->instance_id = *(int32_t*)(d + 12); + ext_anim_x->file_name_hash = (uint32_t) * (uint64_t*)(d + 16); } - ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); - ext_anim->node_index = 18; if (*(uint8_t*)(d + 32)) { - strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 32), 0x80); - ext_anim->mesh_name[0x7F] = '\0'; + strncpy_s(ext_anim_x->mesh_name, 0x80, (uint8_t*)(d + 32), 0x80); + ext_anim_x->mesh_name[0x7F] = '\0'; } else - ext_anim->mesh_name[0] = 0; + ext_anim_x->mesh_name[0] = 0; } } } @@ -516,7 +510,7 @@ static bool glitter_effect_unpack_file(GLT, } ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); - ext_anim->node_index = 18; + ext_anim->node_index = GLITTER_EFFECT_EXT_ANIM_CHARA_MAX; if (*(uint8_t*)(d + 12)) { strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 12), 0x80); ext_anim->mesh_name[0x7F] = 0; diff --git a/src/CRE/Glitter/effect.h b/src/CRE/Glitter/effect.h index a219a8c0..627d347e 100644 --- a/src/CRE/Glitter/effect.h +++ b/src/CRE/Glitter/effect.h @@ -14,3 +14,5 @@ extern bool glitter_effect_parse_file(glitter_effect_group* a1, extern bool glitter_effect_unparse_file(GLT, glitter_effect_group* a1, f2_struct* st, glitter_effect* a3); extern void glitter_effect_dispose(glitter_effect* e); + +extern object_info glitter_effect_ext_anim_get_object_info(uint64_t hash); diff --git a/src/CRE/Glitter/effect_inst.c b/src/CRE/Glitter/effect_inst.c index f907deec..518aa10e 100644 --- a/src/CRE/Glitter/effect_inst.c +++ b/src/CRE/Glitter/effect_inst.c @@ -9,6 +9,7 @@ #include "emitter_inst.h" #include "random.h" #include "render_scene.h" +#include "../../KKdLib/str_utils.h" #include "../auth_3d.h" #include "../rob.h" @@ -43,11 +44,13 @@ glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, if (~a1->data.flags & GLITTER_EFFECT_LOCAL && ei->data.ext_anim) { inst_ext_anim = force_malloc(sizeof(glitter_effect_inst_ext_anim)); - inst_ext_anim->a3da_id = -1; - inst_ext_anim->object_hash = GLT_VAL != GLITTER_FT - ? hash_murmurhash_empty : hash_fnv1a64m_empty; - inst_ext_anim->chara_index = -1; + inst_ext_anim->object_index = -1; inst_ext_anim->mesh_index = -1; + inst_ext_anim->a3da_id = -1; + inst_ext_anim->object_is_hrc = false; + inst_ext_anim->object = object_info_null; + inst_ext_anim->mesh_name = 0; + inst_ext_anim->mat = mat4_identity; inst_ext_anim->translation = vec3_null; @@ -59,22 +62,16 @@ glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, ei->flags |= GLITTER_EFFECT_INST_EXT_ANIM_TRANS_ONLY; if (ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { + inst_ext_anim->chara_index = ext_anim->chara_index; inst_ext_anim->bone_index = glitter_effect_inst_get_ext_anim_bone_index(ext_anim->node_index); ei->flags |= GLITTER_EFFECT_INST_CHARA_ANIM; } - else { + else inst_ext_anim->object = ext_anim->object; - inst_ext_anim->object_hash = ext_anim->object_hash; - inst_ext_anim->file_name_hash = ext_anim->file_name_hash; - inst_ext_anim->instance_id = ext_anim->instance_id; - } - size_t mesh_name_len = utf8_length(ext_anim->mesh_name); - if (mesh_name_len) { - inst_ext_anim->mesh_name = force_malloc(mesh_name_len + 1); - memcpy(inst_ext_anim->mesh_name, ext_anim->mesh_name, mesh_name_len); - } + if (ext_anim->mesh_name[0]) + inst_ext_anim->mesh_name = ext_anim->mesh_name; else inst_ext_anim->mesh_name = 0; } @@ -204,10 +201,8 @@ void glitter_effect_inst_update(GPM, GLT, } void glitter_effect_inst_dispose(glitter_effect_inst* ei) { - if (ei->ext_anim) { - free(ei->ext_anim->mesh_name); + if (ei->ext_anim) free(ei->ext_anim); - } glitter_render_scene_free(&ei->render_scene); vector_ptr_glitter_emitter_inst_free(&ei->emitters, glitter_emitter_inst_dispose); @@ -265,7 +260,7 @@ static void glitter_effect_inst_get_ext_anim(glitter_effect_inst* a1) { } if (~a1->flags & GLITTER_EFFECT_INST_FLAG_GET_EXT_ANIM_MAT) { - if (inst_ext_anim->mesh_index < 0) { + if (inst_ext_anim->mesh_index == -1) { if (!inst_ext_anim->mesh_name) return; @@ -273,9 +268,9 @@ static void glitter_effect_inst_get_ext_anim(glitter_effect_inst* a1) { inst_ext_anim->object, inst_ext_anim->mesh_name); } - int32_t v46 = inst_ext_anim->mesh_index; - if (v46 >= 0) { - object_mesh* mesh = object_storage_get_object_mesh_by_index(inst_ext_anim->object, v46); + if (inst_ext_anim->mesh_index != -1) { + object_mesh* mesh = object_storage_get_object_mesh_by_index(inst_ext_anim->object, + inst_ext_anim->mesh_index); if (mesh) { inst_ext_anim->translation = mesh->bounding_sphere.center; goto SetFlags; @@ -288,24 +283,24 @@ static void glitter_effect_inst_get_ext_anim(glitter_effect_inst* a1) { mat4 temp; if (inst_ext_anim->a3da_id != -1) obj_mat = auth_3d_data_struct_get_auth_3d_object_mat(inst_ext_anim->a3da_id, - inst_ext_anim->a3da_index, inst_ext_anim->object_is_hrc, &temp); + inst_ext_anim->object_index, inst_ext_anim->object_is_hrc, &temp); if (!obj_mat) { inst_ext_anim->a3da_id = auth_3d_data_get_auth_3d_id_by_object_info(inst_ext_anim->object, - &inst_ext_anim->a3da_index, &inst_ext_anim->object_is_hrc); + &inst_ext_anim->object_index, &inst_ext_anim->object_is_hrc, 0); if (inst_ext_anim->a3da_id == -1) return; inst_ext_anim->mesh_index = -1; obj_mat = auth_3d_data_struct_get_auth_3d_object_mat(inst_ext_anim->a3da_id, - inst_ext_anim->a3da_index, inst_ext_anim->object_is_hrc, &temp); + inst_ext_anim->object_index, inst_ext_anim->object_is_hrc, &temp); if (!obj_mat) return; } mat4 mat = mat4_identity; - int32_t chara_id = -1;// auth_3d_data_get_chara_id(inst_ext_anim->a3da_id); - if (chara_id >= 0 && chara_id <= 5) { + int32_t chara_id = auth_3d_data_get_chara_id(inst_ext_anim->a3da_id); + if (chara_id >= 0 && chara_id < ROB_CHARA_COUNT) { rob_chara* rob_chr = rob_chara_array_get(chara_id); if (rob_chr) { mat = mat4_identity/*chara root mat*/; @@ -319,11 +314,11 @@ static void glitter_effect_inst_get_ext_anim(glitter_effect_inst* a1) { } if (inst_ext_anim->mesh_name) { - if (inst_ext_anim->mesh_index < 0) + if (inst_ext_anim->mesh_index == -1) inst_ext_anim->mesh_index = object_storage_get_object_mesh_index( inst_ext_anim->object, inst_ext_anim->mesh_name); - if (inst_ext_anim->mesh_index >= 0) { + if (inst_ext_anim->mesh_index != -1) { object_mesh* mesh = object_storage_get_object_mesh_by_index( inst_ext_anim->object, inst_ext_anim->mesh_index); if (mesh) { @@ -355,10 +350,17 @@ SetFlags: static int32_t glitter_effect_inst_get_ext_anim_bone_index( glitter_effect_ext_anim_chara_node node) { - /*if (node < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) + if (node < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) return -1; - const char* bone_names[] = { + bone_database* bone_data = GPM_VAL->bone_data; + vector_string* motion_bone_names = 0; + if (!bone_data || vector_length(bone_data->skeleton) < 1 + || !bone_database_get_skeleton_motion_bones(bone_data, + bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON), &motion_bone_names)) + return -1; + + static const char* bone_names[] = { [GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD] = "face_root", [GLITTER_EFFECT_EXT_ANIM_CHARA_MOUTH] = "n_kuti_u", [GLITTER_EFFECT_EXT_ANIM_CHARA_BELLY] = "n_hara_cp", @@ -379,48 +381,11 @@ static int32_t glitter_effect_inst_get_ext_anim_bone_index( [GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE] = "kl_toe_r_wj" }; - return -1;*/ - - switch (node) { - case GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD: - return 0x0F; - case GLITTER_EFFECT_EXT_ANIM_CHARA_MOUTH: - return 0x36; - case GLITTER_EFFECT_EXT_ANIM_CHARA_BELLY: - return 0x00; - case GLITTER_EFFECT_EXT_ANIM_CHARA_CHEST: - return 0x07; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_SHOULDER: - return 0x6A; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_ELBOW: - return 0x6C; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_ELBOW_DUP: - return 0x6D; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_HAND: - return 0x7B; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_SHOULDER: - return 0x8E; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_ELBOW: - return 0x90; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_ELBOW_DUP: - return 0x91; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_HAND: - return 0x9F; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_THIGH: - return 0xC2; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_KNEE: - return 0xB8; - case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_TOE: - return 0xB7; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_THIGH: - return 0xC5; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_KNEE: - return 0xBF; - case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE: - return 0xBE; - default: - return -1; - } + char* bone_name = (char*)bone_names[node]; + for (string* i = motion_bone_names->begin; i != motion_bone_names->end; i++) + if (!str_utils_compare(bone_name, string_data(i))) + return (int32_t)(i - motion_bone_names->begin); + return -1; } static void glitter_effect_inst_get_value(GLT, glitter_effect_inst* a1) { diff --git a/src/CRE/Glitter/file_reader.c b/src/CRE/Glitter/file_reader.c index caa5dc97..137495c3 100644 --- a/src/CRE/Glitter/file_reader.c +++ b/src/CRE/Glitter/file_reader.c @@ -13,11 +13,12 @@ #include "../../KKdLib/io/path.h" #include "../../KKdLib/farc.h" #include "../../KKdLib/str_utils.h" +#include "../data.h" glitter_file_reader* glitter_file_reader_init(GLT, char* path, char* file, float_t emission) { glitter_file_reader* fr = force_malloc(sizeof(glitter_file_reader)); - fr->path = str_utils_copy(path ? path : "rom\\particle\\"); + fr->path = str_utils_copy(path ? path : "rom/particle/"); fr->file = str_utils_copy(file); fr->emission = emission; fr->type = GLT_VAL; @@ -30,7 +31,7 @@ glitter_file_reader* glitter_file_reader_init(GLT, glitter_file_reader* glitter_file_reader_winit(GLT, wchar_t* path, wchar_t* file, float_t emission) { glitter_file_reader* fr = force_malloc(sizeof(glitter_file_reader)); - fr->path = utf16_to_utf8(path ? path : L"rom\\particle\\"); + fr->path = path ? utf16_to_utf8(path) : str_utils_copy("rom/particle/"); fr->file = utf16_to_utf8(file); fr->emission = emission; fr->type = GLT_VAL; @@ -43,24 +44,22 @@ glitter_file_reader* glitter_file_reader_winit(GLT, bool glitter_file_reader_read(GPM, glitter_file_reader* fr, float_t emission) { farc f; farc_init(&f); - char* file_temp; - char* path_temp; - file_temp = str_utils_add(fr->file, ".farc"); - path_temp = str_utils_add(fr->path, file_temp); - free(file_temp); - farc_read(&f, path_temp, true, false); - free(path_temp); + char* farc_file_temp = str_utils_add(fr->file, ".farc"); + bool ret = data_struct_load_file(GPM_VAL->data, &f, fr->path, farc_file_temp, farc_load_file); + free(farc_file_temp); - farc_file* ff; - bool ret = false; - file_temp = str_utils_add(fr->file, ".dve"); - ff = farc_read_file(&f, file_temp); - free(file_temp); - if (!ff) + if (!ret) + goto End; + + ret = false; + char* dve_file_temp = str_utils_add(fr->file, ".dve"); + farc_file* dve_ff = farc_read_file(&f, dve_file_temp); + free(dve_file_temp); + if (!dve_ff) goto End; f2_struct st; - f2_struct_mread(&st, ff->data, ff->size); + f2_struct_mread(&st, dve_ff->data, dve_ff->size); if (st.header.signature == reverse_endianness_uint32_t('DVEF')) ret = glitter_diva_effect_parse_file(fr, &st, emission); else @@ -70,25 +69,25 @@ bool glitter_file_reader_read(GPM, glitter_file_reader* fr, float_t emission) { if (!ret) goto End; - file_temp = str_utils_add(fr->file, ".drs"); - ff = farc_read_file(&f, file_temp); - free(file_temp); + char* drs_file_temp = str_utils_add(fr->file, ".drs"); + farc_file* drs_ff = farc_read_file(&f, drs_file_temp); + free(drs_file_temp); - if (ff) { + if (drs_ff) { f2_struct st; - f2_struct_mread(&st, ff->data, ff->size); + f2_struct_mread(&st, drs_ff->data, drs_ff->size); if (st.header.signature == reverse_endianness_uint32_t('DVRS')) glitter_diva_resource_parse_file(GPM_VAL, fr->effect_group, &st); f2_struct_free(&st); } - file_temp = str_utils_add(fr->file, ".lst"); - ff = farc_read_file(&f, file_temp); - free(file_temp); + char* lst_file_temp = str_utils_add(fr->file, ".lst"); + farc_file* lst_ff = farc_read_file(&f, lst_file_temp); + free(lst_file_temp); - if (ff) { + if (lst_ff) { f2_struct st; - f2_struct_mread(&st, ff->data, ff->size); + f2_struct_mread(&st, lst_ff->data, lst_ff->size); if (st.header.signature == reverse_endianness_uint32_t('LIST')) glitter_diva_list_parse_file(fr->effect_group, &st); f2_struct_free(&st); diff --git a/src/CRE/Glitter/glitter.h b/src/CRE/Glitter/glitter.h index 416e79b8..244833cc 100644 --- a/src/CRE/Glitter/glitter.h +++ b/src/CRE/Glitter/glitter.h @@ -345,9 +345,11 @@ typedef struct glitter_curve_key glitter_curve_key; typedef struct glitter_curve glitter_curve; typedef struct glitter_effect_data glitter_effect_data; typedef struct glitter_effect_ext_anim glitter_effect_ext_anim; +typedef struct glitter_effect_ext_anim_x glitter_effect_ext_anim_x; typedef struct glitter_effect glitter_effect; typedef struct glitter_effect_group glitter_effect_group; typedef struct glitter_effect_inst_ext_anim glitter_effect_inst_ext_anim; +typedef struct glitter_effect_inst_ext_anim_x glitter_effect_inst_ext_anim_x; typedef struct glitter_effect_inst glitter_effect_inst; typedef struct glitter_emitter_box glitter_emitter_box; typedef struct glitter_emitter_cylinder glitter_emitter_cylinder; @@ -457,23 +459,44 @@ struct glitter_effect_data { int32_t appear_time; int32_t life_time; int32_t start_time; - glitter_effect_ext_anim* ext_anim; + union { + glitter_effect_ext_anim* ext_anim; + glitter_effect_ext_anim_x* ext_anim_x; + }; glitter_effect_flag flags; float_t emission; int32_t seed; }; struct glitter_effect_ext_anim { - uint64_t object_hash; glitter_effect_ext_anim_flag flags; - int32_t instance_id; - uint64_t file_name_hash; union { - object_info object; - int32_t chara_index; + struct { + uint64_t object_hash; + object_info object; + char mesh_name[128]; + }; + struct { + int32_t chara_index; + glitter_effect_ext_anim_chara_node node_index; + }; + }; +}; + +struct glitter_effect_ext_anim_x { + glitter_effect_ext_anim_flag flags; + union { + struct { + uint32_t file_name_hash; + uint32_t object_hash; + int32_t instance_id; + char mesh_name[128]; + }; + struct { + int32_t chara_index; + glitter_effect_ext_anim_chara_node node_index; + }; }; - int32_t node_index; - char mesh_name[128]; }; struct glitter_effect { @@ -505,23 +528,43 @@ struct glitter_effect_group { }; struct glitter_effect_inst_ext_anim { - int32_t a3da_id; - size_t a3da_index; - int32_t instance_id; - uint64_t file_name_hash; - uint64_t object_hash; union { - object_info object; - int32_t chara_index; + struct { + int32_t object_index; + int32_t mesh_index; + int32_t a3da_id; + bool object_is_hrc; + object_info object; + char* mesh_name; + }; + struct { + int32_t chara_index; + int32_t bone_index; + }; }; + mat4 mat; + vec3 translation; +}; + +struct glitter_effect_inst_ext_anim_x { union { - int32_t mesh_index; - int32_t bone_index; + struct { + int32_t object_index; + int32_t mesh_index; + int32_t a3da_id; + bool object_is_hrc; + uint32_t file_name_hash; + uint32_t object_hash; + int32_t instance_id; + char* mesh_name; + }; + struct { + int32_t chara_index; + int32_t bone_index; + }; }; mat4 mat; vec3 translation; - char* mesh_name; - bool object_is_hrc; }; struct glitter_effect_inst { @@ -544,7 +587,10 @@ struct glitter_effect_inst { }; glitter_effect_inst_flag flags; size_t id; - glitter_effect_inst_ext_anim* ext_anim; + union { + glitter_effect_inst_ext_anim* ext_anim; + glitter_effect_inst_ext_anim_x* ext_anim_x; + }; vec3 ext_anim_scale; glitter_render_scene render_scene; uint32_t random; @@ -650,6 +696,8 @@ struct glitter_particle_manager { glitter_emitter_inst* emitter; glitter_particle_inst* particle; void* rctx; + void* data; + void* bone_data; float_t emission; float_t delta_frame; uint32_t texture_counter; diff --git a/src/CRE/Glitter/particle_manager.c b/src/CRE/Glitter/particle_manager.c index b7e9f8d1..aa40afbf 100644 --- a/src/CRE/Glitter/particle_manager.c +++ b/src/CRE/Glitter/particle_manager.c @@ -198,6 +198,18 @@ size_t glitter_particle_manager_get_disp_count(GPM, glitter_particle_type ptcl_t return disp; } +glitter_effect_group* glitter_particle_manager_get_effect_group(GPM, uint64_t effect_group_hash) { + glitter_effect_group** i; + glitter_effect_group* effect_group; + + for (i = GPM_VAL->effect_groups.begin; i != GPM_VAL->effect_groups.end; i++) { + effect_group = *i; + if (effect_group && effect_group->hash == effect_group_hash) + return effect_group; + } + return 0; +} + void glitter_particle_manager_get_frame(GPM, float_t* frame, int32_t* life_time) { if (frame) *frame = 0.0f; @@ -211,6 +223,18 @@ void glitter_particle_manager_get_frame(GPM, float_t* frame, int32_t* life_time) glitter_scene_get_frame(*GPM_VAL->scenes.begin, frame, life_time); } +glitter_scene* glitter_particle_manager_get_scene(GPM, uint64_t effect_group_hash) { + glitter_scene** i; + glitter_scene* scene; + + for (i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end; i++) { + scene = *i; + if (scene && scene->hash == effect_group_hash) + return scene; + } + return 0; +} + void glitter_particle_manager_get_start_end_frame(GPM, int32_t* start_frame, int32_t* end_frame) { if (start_frame) *start_frame = 0; @@ -287,7 +311,7 @@ bool glitter_particle_manager_load_scene(GPM, uint64_t effect_group_hash) { } for (k = effect_group->effects.begin, id = 1; k != effect_group->effects.end; k++, id++) - glitter_scene_init_effect(GPM_VAL, scene, *k, id, false); + glitter_scene_init_effect(GPM_VAL, scene, *k, id, true); break; } return i != GPM_VAL->effect_groups.end; @@ -340,73 +364,6 @@ void glitter_particle_manager_set_frame(GPM, } } -bool glitter_particle_manager_test_load_effect(GPM, - uint64_t effect_group_hash, uint64_t effect_hash) { - glitter_effect_group** i; - glitter_effect_group* effect_group; - glitter_scene** j; - glitter_scene* scene; - glitter_effect** k; - glitter_effect* effect; - size_t id; - - for (i = GPM_VAL->effect_groups.begin; i != GPM_VAL->effect_groups.end; i++) { - effect_group = *i; - if (!effect_group || effect_group->hash != effect_group_hash) - continue; - - for (j = GPM_VAL->scenes.begin; j != GPM_VAL->scenes.end; j++) { - scene = *j; - if (scene && scene->hash == effect_group_hash) - break; - } - - if (j == GPM_VAL->scenes.end) { - scene = glitter_scene_init(effect_group); - vector_ptr_glitter_scene_push_back(&GPM_VAL->scenes, &scene); - } - - for (k = effect_group->effects.begin, id = 1; k != effect_group->effects.end; k++, id++) { - effect = *k; - if (effect && effect->data.name_hash == effect_hash) - glitter_scene_init_effect(GPM_VAL, scene, effect, id, true); - } - break; - } - return i != GPM_VAL->effect_groups.end; -} - -bool glitter_particle_manager_test_load_scene(GPM, uint64_t effect_group_hash, bool appear_now) { - glitter_effect_group** i; - glitter_effect_group* effect_group; - glitter_scene** j; - glitter_scene* scene; - glitter_effect** k; - size_t id; - - for (i = GPM_VAL->effect_groups.begin; i != GPM_VAL->effect_groups.end; i++) { - effect_group = *i; - if (!effect_group || effect_group->hash != effect_group_hash) - continue; - - for (j = GPM_VAL->scenes.begin; j != GPM_VAL->scenes.end; j++) { - scene = *j; - if (scene && scene->hash == effect_group_hash) - break; - } - - if (j == GPM_VAL->scenes.end) { - scene = glitter_scene_init(effect_group); - vector_ptr_glitter_scene_push_back(&GPM_VAL->scenes, &scene); - } - - for (k = effect_group->effects.begin, id = 1; k != effect_group->effects.end; k++, id++) - glitter_scene_init_effect(GPM_VAL, scene, *k, id, appear_now); - break; - } - return i != GPM_VAL->effect_groups.end; -} - void glitter_particle_manager_update_file_reader(GPM) { for (glitter_file_reader** i = GPM_VAL->file_readers.begin; i != GPM_VAL->file_readers.end;) { if (*i) { @@ -429,9 +386,39 @@ void glitter_particle_manager_update_scene(GPM, float_t delta_frame) { GPM_VAL->delta_frame = delta_frame; for (glitter_scene** i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end;) { glitter_scene* scene = *i; - if (scene && !glitter_scene_has_ended(scene, true)) { + if (!scene || glitter_scene_has_ended(scene, true)) { + vector_ptr_glitter_scene_erase(&GPM_VAL->scenes, i - GPM_VAL->scenes.begin, glitter_scene_dispose); + continue; + } + + if (scene->type == GLITTER_F2) { + scene->delta_frame_history += GPM_VAL->delta_frame; + if (!scene->skip) { + glitter_scene_update(GPM_VAL, scene, scene->delta_frame_history); + scene->delta_frame_history = 0.0f; + scene->skip = true; + } + else + scene->skip = false; + } + else + glitter_scene_update(GPM_VAL, scene, GPM_VAL->delta_frame); + i++; + } +} + +void glitter_particle_manager_update_scene_by_hash(GPM, + uint64_t effect_group_hash, float_t delta_frame) { + for (glitter_scene** i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end;) { + glitter_scene* scene = *i; + if (!scene || glitter_scene_has_ended(scene, true)) { + vector_ptr_glitter_scene_erase(&GPM_VAL->scenes, i - GPM_VAL->scenes.begin, glitter_scene_dispose); + continue; + } + + if (scene->hash == effect_group_hash) { if (scene->type == GLITTER_F2) { - scene->delta_frame_history += GPM_VAL->delta_frame; + scene->delta_frame_history += delta_frame; if (!scene->skip) { glitter_scene_update(GPM_VAL, scene, scene->delta_frame_history); scene->delta_frame_history = 0.0f; @@ -441,11 +428,10 @@ void glitter_particle_manager_update_scene(GPM, float_t delta_frame) { scene->skip = false; } else - glitter_scene_update(GPM_VAL, scene, GPM_VAL->delta_frame); - i++; + glitter_scene_update(GPM_VAL, scene, delta_frame); + break; } - else - vector_ptr_glitter_scene_erase(&GPM_VAL->scenes, i - GPM_VAL->scenes.begin, glitter_scene_dispose); + i++; } } diff --git a/src/CRE/Glitter/particle_manager.h b/src/CRE/Glitter/particle_manager.h index d5eebd36..0b0c3c15 100644 --- a/src/CRE/Glitter/particle_manager.h +++ b/src/CRE/Glitter/particle_manager.h @@ -19,7 +19,9 @@ extern bool glitter_particle_manager_free_scene(GPM, uint64_t effect_group_hash) extern void glitter_particle_manager_free_scenes(GPM); extern size_t glitter_particle_manager_get_ctrl_count(GPM, glitter_particle_type ptcl_type); extern size_t glitter_particle_manager_get_disp_count(GPM, glitter_particle_type ptcl_type); +extern glitter_effect_group* glitter_particle_manager_get_effect_group(GPM, uint64_t effect_group_hash); extern void glitter_particle_manager_get_frame(GPM, float_t* frame, int32_t* life_time); +extern glitter_scene* glitter_particle_manager_get_scene(GPM, uint64_t effect_group_hash); extern void glitter_particle_manager_get_start_end_frame(GPM, int32_t* start_frame, int32_t* end_frame); extern bool glitter_particle_manager_load_effect(GPM, uint64_t effect_group_hash, uint64_t effect_hash); extern bool glitter_particle_manager_load_scene(GPM, uint64_t effect_group_hash); @@ -28,7 +30,8 @@ extern void glitter_particle_manager_set_frame(GPM, float_t prev_frame, uint32_t counter, glitter_random* random, bool reset); extern bool glitter_particle_manager_test_load_effect(GPM, uint64_t effect_group_hash, uint64_t effect_hash); -extern bool glitter_particle_manager_test_load_scene(GPM, uint64_t effect_group_hash, bool appear_now); extern void glitter_particle_manager_update_file_reader(GPM); extern void glitter_particle_manager_update_scene(GPM, float_t delta_frame); +extern void glitter_particle_manager_update_scene_by_hash(GPM, + uint64_t effect_group_hash, float_t delta_frame); extern void glitter_particle_manager_dispose(GPM); diff --git a/src/CRE/GlitterX/effect_inst_x.c b/src/CRE/GlitterX/effect_inst_x.c index 57f0cfd1..6ee21e4a 100644 --- a/src/CRE/GlitterX/effect_inst_x.c +++ b/src/CRE/GlitterX/effect_inst_x.c @@ -9,8 +9,11 @@ #include "emitter_inst_x.h" #include "random_x.h" #include "render_scene_x.h" +#include "../../KKdLib/str_utils.h" +#include "../auth_3d.h" +#include "../rob.h" -static int32_t glitter_x_effect_inst_get_ext_anim_bone_index( +static int32_t glitter_x_effect_inst_get_ext_anim_bone_index(GPM, glitter_effect_ext_anim_chara_node node); static void glitter_x_effect_inst_get_ext_anim(glitter_effect_inst* a1); static void glitter_x_effect_inst_get_value(glitter_effect_inst* a1); @@ -18,8 +21,8 @@ static void glitter_x_effect_inst_update_init(glitter_effect_inst* a1, float_t e glitter_effect_inst* glitter_x_effect_inst_init(GPM, glitter_effect* a1, size_t id, float_t emission, bool appear_now) { - glitter_effect_inst_ext_anim* inst_ext_anim; - glitter_effect_ext_anim* ext_anim; + glitter_effect_inst_ext_anim_x* inst_ext_anim; + glitter_effect_ext_anim_x* ext_anim; glitter_emitter** i; glitter_emitter_inst* emitter_inst; @@ -40,24 +43,28 @@ glitter_effect_inst* glitter_x_effect_inst_init(GPM, glitter_effect* a1, ei->random = glitter_x_counter_get(GPM_VAL); ei->random_shared.value = ei->random; - ext_anim = ei->data.ext_anim; + ext_anim = ei->data.ext_anim_x; if (appear_now) ei->data.appear_time = 0; else ei->frame0 = (float_t)-ei->data.appear_time; - if (~a1->data.flags & GLITTER_EFFECT_LOCAL && ei->data.ext_anim) { - inst_ext_anim = force_malloc(sizeof(glitter_effect_inst_ext_anim)); - inst_ext_anim->a3da_id = -1; - inst_ext_anim->object_hash = hash_murmurhash_empty; - inst_ext_anim->chara_index = -1; + if (~a1->data.flags & GLITTER_EFFECT_LOCAL && ei->data.ext_anim_x) { + inst_ext_anim = force_malloc(sizeof(glitter_effect_inst_ext_anim_x)); + inst_ext_anim->object_index = -1; inst_ext_anim->mesh_index = -1; + inst_ext_anim->a3da_id = -1; + inst_ext_anim->object_is_hrc = false; + inst_ext_anim->file_name_hash = hash_murmurhash_empty; + inst_ext_anim->object_hash = hash_murmurhash_empty; + inst_ext_anim->instance_id = 0; + inst_ext_anim->mesh_name = 0; inst_ext_anim->mat = mat4_identity; inst_ext_anim->translation = vec3_null; - if (inst_ext_anim != (glitter_effect_inst_ext_anim*)0x0) { - ext_anim = ei->data.ext_anim; + if (inst_ext_anim) { + ext_anim = ei->data.ext_anim_x; if (ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_SET_ONCE) ei->flags |= GLITTER_EFFECT_INST_SET_EXT_ANIM_ONCE; @@ -78,26 +85,23 @@ glitter_effect_inst* glitter_x_effect_inst_init(GPM, glitter_effect* a1, if (ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { - inst_ext_anim->object = ext_anim->object; + inst_ext_anim->chara_index = ext_anim->chara_index; inst_ext_anim->bone_index = - glitter_x_effect_inst_get_ext_anim_bone_index(ext_anim->node_index); + glitter_x_effect_inst_get_ext_anim_bone_index(GPM_VAL, ext_anim->node_index); ei->flags |= GLITTER_EFFECT_INST_CHARA_ANIM; } else { - inst_ext_anim->object_hash = ext_anim->object_hash; - inst_ext_anim->file_name_hash = ext_anim->file_name_hash; + inst_ext_anim->object_hash = (uint32_t)ext_anim->object_hash; + inst_ext_anim->file_name_hash = (uint32_t)ext_anim->file_name_hash; inst_ext_anim->instance_id = ext_anim->instance_id; } - size_t mesh_name_len = utf8_length(ext_anim->mesh_name); - if (mesh_name_len) { - inst_ext_anim->mesh_name = force_malloc(mesh_name_len + 1); - memcpy(inst_ext_anim->mesh_name, ext_anim->mesh_name, mesh_name_len); - } + if (ext_anim->mesh_name[0]) + inst_ext_anim->mesh_name = ext_anim->mesh_name; else inst_ext_anim->mesh_name = 0; } - ei->ext_anim = inst_ext_anim; + ei->ext_anim_x = inst_ext_anim; ei->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM; ei->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_NON_INIT; ei->flags |= GLITTER_EFFECT_INST_FLAG_GET_EXT_ANIM_MAT; @@ -164,7 +168,7 @@ void glitter_x_effect_inst_reset(glitter_effect_inst* a1, float_t emission) { void glitter_x_effect_inst_update(GPM, glitter_effect_inst* effect, float_t delta_frame, float_t emission) { - glitter_effect_inst_ext_anim* ext_anim; + glitter_effect_inst_ext_anim_x* ext_anim; glitter_emitter_inst** i; mat4 mat; mat4 mat_rot; @@ -181,9 +185,9 @@ void glitter_x_effect_inst_update(GPM, glitter_effect_inst* effect, rot = effect->rotation; vec3_mult_scalar(effect->scale, effect->scale_all, scale); - if (effect->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS && effect->ext_anim) { + if (effect->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS && effect->ext_anim_x) { vec3 ext_trans; - ext_anim = effect->ext_anim; + ext_anim = effect->ext_anim_x; ext_trans = ext_anim->translation; mat4_translate_mult(&ext_anim->mat, ext_trans.x, ext_trans.y, ext_trans.z, &mat); mat4_normalize_rotation(&mat, &mat_rot); @@ -224,22 +228,27 @@ void glitter_x_effect_inst_update(GPM, glitter_effect_inst* effect, } void glitter_x_effect_inst_dispose(glitter_effect_inst* ei) { - if (ei->ext_anim) { - free(ei->ext_anim->mesh_name); - free(ei->ext_anim); - } + if (ei->ext_anim_x) + free(ei->ext_anim_x); glitter_x_render_scene_free(&ei->render_scene); vector_ptr_glitter_emitter_inst_free(&ei->emitters, glitter_x_emitter_inst_dispose); free(ei); } -static int32_t glitter_x_effect_inst_get_ext_anim_bone_index( +static int32_t glitter_x_effect_inst_get_ext_anim_bone_index(GPM, glitter_effect_ext_anim_chara_node node) { if (node < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) return -1; - const char* bone_names[] = { + bone_database* bone_data = GPM_VAL->bone_data; + vector_string* motion_bone_names = 0; + if (!bone_data || vector_length(bone_data->skeleton) < 1 + || !bone_database_get_skeleton_motion_bones(bone_data, + bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON), &motion_bone_names)) + return -1; + + static const char* bone_names[] = { [GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD] = "face_root", [GLITTER_EFFECT_EXT_ANIM_CHARA_MOUTH] = "n_kuti_u", [GLITTER_EFFECT_EXT_ANIM_CHARA_BELLY] = "n_hara_cp", @@ -260,20 +269,23 @@ static int32_t glitter_x_effect_inst_get_ext_anim_bone_index( [GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE] = "kl_toe_r_wj" }; - // find bone index + char* bone_name = (char*)bone_names[node]; + for (string* i = motion_bone_names->begin; i != motion_bone_names->end; i++) + if (!str_utils_compare(bone_name, string_data(i))) + return (int32_t)(i - motion_bone_names->begin); return -1; } static void glitter_x_effect_inst_get_ext_anim(glitter_effect_inst* a1) { - glitter_effect_ext_anim* ext_anim; - glitter_effect_inst_ext_anim* inst_ext_anim; + glitter_effect_ext_anim_x* ext_anim; + glitter_effect_inst_ext_anim_x* inst_ext_anim; vec3 scale; mat4 temp; mat4* mat; vec3* trans; bool set_flags; - if (!a1->ext_anim || !a1->data.ext_anim) + if (!a1->ext_anim_x || !a1->data.ext_anim_x) return; if (~a1->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM @@ -281,8 +293,8 @@ static void glitter_x_effect_inst_get_ext_anim(glitter_effect_inst* a1) { && a1->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS)) return; - ext_anim = a1->data.ext_anim; - inst_ext_anim = a1->ext_anim; + ext_anim = a1->data.ext_anim_x; + inst_ext_anim = a1->ext_anim_x; mat = 0; trans = 0; @@ -292,50 +304,48 @@ static void glitter_x_effect_inst_get_ext_anim(glitter_effect_inst* a1) { a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_NON_INIT; if (a1->flags & GLITTER_EFFECT_INST_CHARA_ANIM) { - if (inst_ext_anim->chara_index < 0 || inst_ext_anim->chara_index > 3) + rob_chara* rob_chr = rob_chara_array_get(inst_ext_anim->chara_index); + if (!rob_chr) return; temp = mat4_identity/*chara root mat*/; - mat4_get_scale((mat4*)&mat4_identity/*chara root mat*/, &scale); + mat4_get_scale(&temp, &scale); vec3_sub_scalar(scale, 1.0f, a1->ext_anim_scale); a1->ext_anim_scale.z = 0.0f; a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_SCALE; - if (false/*check chara is visible*/ - || ~ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_NO_DRAW_IF_NO_DATA) + if (rob_chr->data.field_0 & 0x01 || ~ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_NO_DRAW_IF_NO_DATA) set_flags = true; else set_flags = false; - if (inst_ext_anim->bone_index > -1) - mat4_mult(&temp, (mat4*)&mat4_identity/*chara node mat*/, &temp); + int32_t bone_index = inst_ext_anim->bone_index; + if (bone_index != -1) { + mat4* bone_mat = rob_chara_get_bone_data_mat(rob_chr, bone_index); + mat4_mult(bone_mat, &temp, &temp); + } mat = &temp; goto SetMat; } else if (a1->flags & GLITTER_EFFECT_INST_FLAG_GET_EXT_ANIM_MAT) { - if (inst_ext_anim->a3da_id == -1) { - inst_ext_anim->a3da_id = -1;/*try get a3da id*/ - //fun(inst_ext_anim->file_name_hash, inst_ext_anim->object_hash, - // &inst_ext_anim->a3da_index, &inst_ext_anim->object_is_hrc) + if (inst_ext_anim->a3da_id != -1) + mat = auth_3d_data_struct_get_auth_3d_object_mat(inst_ext_anim->a3da_id, + inst_ext_anim->object_index, inst_ext_anim->object_is_hrc, &temp); + + if (!mat) { + inst_ext_anim->a3da_id = auth_3d_data_get_auth_3d_id_by_hash( + inst_ext_anim->file_name_hash, inst_ext_anim->object_hash, + &inst_ext_anim->object_index, &inst_ext_anim->object_is_hrc, inst_ext_anim->instance_id); + if (inst_ext_anim->a3da_id == -1) + return; + inst_ext_anim->mesh_index = -1; - - if (inst_ext_anim->a3da_id > -1) - mat = (mat4*)&mat4_identity/*try get obj a3da mat*/; + mat = auth_3d_data_struct_get_auth_3d_object_mat(inst_ext_anim->a3da_id, + inst_ext_anim->object_index, inst_ext_anim->object_is_hrc, &temp); + if (!mat) + return; } - else { - mat = (mat4*)&mat4_identity/*try get obj a3da mat*/; - if (!mat) { - inst_ext_anim->a3da_id = -1;/*try get a3da id*/ - //fun(inst_ext_anim->file_name_hash, inst_ext_anim->object_hash, - // &inst_ext_anim->a3da_index, &inst_ext_anim->object_is_hrc) - if (inst_ext_anim->a3da_id != -1) - mat = (mat4*)&mat4_identity/*try get obj a3da mat*/; - } - } - - if (!mat) - return; mat4_get_scale(mat, &scale); vec3_sub_scalar(scale, 1.0f, a1->ext_anim_scale); @@ -345,27 +355,35 @@ static void glitter_x_effect_inst_get_ext_anim(glitter_effect_inst* a1) { if (!inst_ext_anim->mesh_name) goto SetMat; - if (inst_ext_anim->mesh_index < 0) - inst_ext_anim->mesh_index = -1/*try get mesh index*/; + if (inst_ext_anim->mesh_index == -1) + inst_ext_anim->mesh_index = object_storage_get_object_mesh_index_by_hash( + inst_ext_anim->object_hash, inst_ext_anim->mesh_name); - if (inst_ext_anim->mesh_index > -1) { - trans = (vec3*)&vec3_null/*try get mesh bounding sphere center*/; - if (trans) + if (inst_ext_anim->mesh_index != -1) { + object_mesh* mesh = object_storage_get_object_mesh_by_object_hash_index( + inst_ext_anim->object_hash, inst_ext_anim->mesh_index); + if (mesh) { + trans = &mesh->bounding_sphere.center; goto SetMat; + } } } else if (inst_ext_anim->object_hash != hash_murmurhash_empty) { - if (inst_ext_anim->mesh_index < 0) { + if (inst_ext_anim->mesh_index == -1) { if (!inst_ext_anim->mesh_name) return; - inst_ext_anim->mesh_index = -1/*try get mesh index*/; + inst_ext_anim->mesh_index = object_storage_get_object_mesh_index_by_hash( + inst_ext_anim->object_hash, inst_ext_anim->mesh_name); } - if (inst_ext_anim->mesh_index >= 0) { - trans = (vec3*)&vec3_null/*try get mesh bounding sphere center*/; - if (trans) + if (inst_ext_anim->mesh_index != -1) { + object_mesh* mesh = object_storage_get_object_mesh_by_object_hash_index( + inst_ext_anim->object_hash, inst_ext_anim->mesh_index); + if (mesh) { + trans = &mesh->bounding_sphere.center; goto SetMat; + } } } return; diff --git a/src/CRE/auth_3d.c b/src/CRE/auth_3d.c index cb870c08..3d66df6b 100644 --- a/src/CRE/auth_3d.c +++ b/src/CRE/auth_3d.c @@ -56,6 +56,7 @@ vector_func(ptr_auth_3d_m_object_hrc) vector_func(ptr_auth_3d_object) vector_func(ptr_auth_3d_object_hrc) +static bool auth_3d_key_detect_fast_change(auth_3d_key* data, float_t frame, float_t threshold); static kft3* auth_3d_key_find_keyframe(auth_3d_key* data, float_t frame); static float_t auth_3d_key_get_value(auth_3d_key* data, float_t frame); static float_t auth_3d_key_interpolate(auth_3d_key* data, float_t frame); @@ -70,9 +71,15 @@ static void auth_3d_model_transform_get_value(auth_3d_model_transform* mt, float static void auth_3d_model_transform_load(auth_3d* auth, auth_3d_model_transform* mt, auth_3d_model_transform_file* mtf); static void auth_3d_model_transform_set_mat(auth_3d_model_transform* mt, mat4* parent_mat); -static int32_t auth_3d_get_auth_3d_object_index_by_object_info(auth_3d* auth, object_info obj_info); +static int32_t auth_3d_get_auth_3d_object_index_by_object_info(auth_3d* auth, + object_info obj_info, int32_t instance); +static int32_t auth_3d_get_auth_3d_object_index_by_hash(auth_3d* auth, + uint32_t object_hash, int32_t instance); static mat4* auth_3d_get_auth_3d_object_hrc_bone_mats(auth_3d* auth, size_t index); -static int32_t auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth_3d* auth, object_info obj_info); +static int32_t auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth_3d* auth, + object_info obj_info, int32_t instance); +static int32_t auth_3d_get_auth_3d_object_hrc_index_by_hash(auth_3d* auth, + uint32_t object_hash, int32_t instance); static void auth_3d_ambient_data_set(auth_3d_ambient* a, render_context* rctx); static void auth_3d_ambient_get_value(auth_3d_ambient* a, float_t frame); @@ -202,7 +209,7 @@ void auth_3d_data_set(auth_3d* auth, mat4* mat, render_context* rctx) { auth_3d_post_process_data_set(&auth->post_process, rctx); } -void auth_3d_get_value(auth_3d* auth, mat4* mat, float_t delta_frame) { +void auth_3d_time_step(auth_3d* auth, mat4* mat) { if (!auth || !auth->enable) return; @@ -216,7 +223,7 @@ void auth_3d_get_value(auth_3d* auth, mat4* mat, float_t delta_frame) { auth->max_frame = -1.0f; } else if (!auth->paused) { - auth->frame += delta_frame; + auth->frame += frame_rate_control_get_delta_frame(auth->frame_rate); if (auth->max_frame >= 0.0f && auth->frame > auth->max_frame) auth->frame = auth->max_frame; } @@ -292,25 +299,12 @@ void auth_3d_get_value(auth_3d* auth, mat4* mat, float_t delta_frame) { auth->ended = ended; } -void auth_3d_unload(auth_3d* auth, render_context* rctx) { - if (!auth) - return; - - auth_3d_camera_auxiliary_restore_prev_value(&auth->camera_auxiliary, rctx); - for (auth_3d_light* i = auth->light.begin; i != auth->light.end; i++) - auth_3d_light_restore_prev_value(i, rctx); - for (auth_3d_fog* i = auth->fog.begin; i != auth->fog.end; i++) - auth_3d_fog_restore_prev_value(i, rctx); - auth_3d_dof_restore_prev_value(&auth->dof, rctx); - auth_3d_post_process_restore_prev_value(&auth->post_process, rctx); - auth_3d_free(auth); -} - void auth_3d_load(auth_3d* auth, a3da* auth_file, object_database* obj_db, texture_database* tex_db) { if (!auth || !auth_file) return; + auth->hash = auth_file->hash; auth_3d_camera_auxiliary_load(auth, &auth_file->camera_auxiliary); auth_3d_dof_load(auth, &auth_file->dof); auth_3d_play_control_load(auth, &auth_file->play_control); @@ -326,6 +320,7 @@ void auth_3d_load(auth_3d* auth, a3da* auth_file, auth->left_right_reverse = false; auth->once = false; + auth->frame_rate = &sys_frame_rate; auth->frame = 0.0f; auth->set_frame = 0.0f; auth->max_frame = auth->play_control.size; @@ -566,20 +561,111 @@ void auth_3d_load_from_farc(auth_3d* auth, farc* f, char* file, if (!ff) return; + char* l_str = string_data(&ff->name); + char* t = strrchr(l_str, '.'); + size_t l_len = ff->name.length; + if (t) + l_len = t - l_str; + + uint32_t h = hash_murmurhash(l_str, l_len, 0, false, false); + a3da a; a3da_init(&a); a3da_mread(&a, ff->data, ff->size); + a.hash = h; auth_3d_load(auth, &a, obj_db, tex_db); a3da_free(&a); } +void auth_3d_set_enable(int32_t* id, bool value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->enable = value; + } +} + +void auth_3d_set_frame_rate(int32_t* id, frame_rate_control* value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->frame_rate = value ? value : &sys_frame_rate; + } +} + +void auth_3d_set_last_frame(int32_t* id, float_t value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->last_frame = value; + } +} + +void auth_3d_set_max_frame(int32_t* id, float_t value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->max_frame = value; + } +} + +void auth_3d_set_paused(int32_t* id, bool value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->paused = value; + } +} + +void auth_3d_set_repeat(int32_t* id, bool value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->repeat = value; + } +} + +void auth_3d_set_set_frame(int32_t* id, float_t value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) { + auth->set_frame = value; + auth->frame_changed = 1; + } + } +} + +void auth_3d_set_visibility(int32_t* id, bool value) { + if (*id >= 0 && (*id & 0x7FFF) < AUTH_3D_DATA_COUNT) { + auth_3d* auth = &auth_3d_data.data[*id & 0x7FFF]; + if (auth->id == *id) + auth->visible = value; + } +} + +void auth_3d_unload(auth_3d* auth, render_context* rctx) { + if (!auth) + return; + + auth_3d_camera_auxiliary_restore_prev_value(&auth->camera_auxiliary, rctx); + for (auth_3d_light* i = auth->light.begin; i != auth->light.end; i++) + auth_3d_light_restore_prev_value(i, rctx); + for (auth_3d_fog* i = auth->fog.begin; i != auth->fog.end; i++) + auth_3d_fog_restore_prev_value(i, rctx); + auth_3d_dof_restore_prev_value(&auth->dof, rctx); + auth_3d_post_process_restore_prev_value(&auth->post_process, rctx); + auth_3d_free(auth); +} + void auth_3d_free(auth_3d* auth) { if (!auth) return; auth->uid = -1; auth->id = -1; + auth->visible = true; auth->alpha = 1.0f; + auth->chara_id = -1; auth_3d_camera_auxiliary_free(&auth->camera_auxiliary); auth_3d_dof_free(&auth->dof); @@ -729,6 +815,8 @@ void auth_3d_farc_load(auth_3d_farc* f, void* data, char* name, object_database* void auth_3d_farc_free(auth_3d_farc* f) { farc_free(&f->auth_3d_farc); + for (uint32_t* i = f->obj_set_id.begin; i != f->obj_set_id.end; i++) + object_storage_delete_object_set(*i); vector_uint32_t_free(&f->obj_set_id, 0); } @@ -979,19 +1067,18 @@ void auth_3d_post_process_free(auth_3d_post_process* pp) { auth_3d_rgba_free(&pp->scene_fade); } /* -void __fastcall sub_140248480(string *a1, list_int32_t *a2) -{ - list_int32_t_node *v4; // rcx - list_int32_t_node *v5; // rbx +void __fastcall sub_140248480(string *a1, list_int32_t *a2) { + list_int32_t_node *index; // rcx + list_int32_t_node *obj_instance; // rbx char *v6; // rcx - int32_t *i; // rbx + int32_t *next_key; // rbx char *v8; // rax size_t v9; // r8 size_t v10; // rsi char *v11; // rdi - _BYTE *v12; // rax - _BYTE *v13; // r9 - int v14; // ecx + _BYTE *key; // rax + _BYTE *next_key; // r9 + int prev_key; // ecx char *v15; // rax ssize_t v16; // r9 char *v17; // rcx @@ -999,7 +1086,7 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) list_int32_t_node *v19; // rax size_t v20; // rdx int32_t v21; // eax - pv_db_pv *v22; // rax + pv_db_pv *next_key; // rax pv_db_pv_difficulty *v23; // rcx string_union v24; // kr00_16 pv_item *__shifted(pv_item,8) v25; // rbx @@ -1033,19 +1120,17 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) vector_int32_t uids; // [rsp+70h] [rbp+7h] BYREF v49 = -2i64; - v4 = a2->head->next; + index = a2->head->next; a2->head->next = a2->head; a2->head->prev = a2->head; a2->size = 0i64; - if ( v4 != a2->head ) - { - do - { - v5 = v4->next; - j_free_2(v4); - v4 = v5; + if ( index != a2->head ) { + do { + obj_instance = index->next; + j_free_2(index); + index = obj_instance; } - while ( v5 != a2->head ); + while ( obj_instance != a2->head ); } uids.begin = 0i64; uids.end = 0i64; @@ -1055,55 +1140,47 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) else v6 = a1->data.ptr; sub_1401CBC70(v6, &uids); - for ( i = uids.begin; i != uids.end; ++i ) - { - v8 = sub_1401E7E90(*i); + for ( next_key = uids.begin; next_key != uids.end; ++next_key ) { + v8 = sub_1401E7E90(*next_key); Dst.capacity = 15i64; Dst.length = 0i64; Dst.data.data[0] = 0; - if ( *v8 ) - { + if ( *v8 ) { v9 = -1i64; do ++v9; while ( v8[v9] ); } - else - { + else { v9 = 0i64; } string_append_char_str(&Dst, v8, v9); v10 = Dst.length; - if ( Dst.length ) - { + if ( Dst.length ) { v11 = (char *)&Dst; if ( Dst.capacity >= 0x10 ) v11 = Dst.data.ptr; - while ( v10 ) - { - v12 = memchr(v11, '_', v10); - v13 = v12; - if ( !v12 ) + while ( v10 ) { + key = memchr(v11, '_', v10); + next_key = key; + if ( !key ) break; - if ( *v12 == asc_14096CDF0[0] ) - v14 = 0; + if ( *key == asc_14096CDF0[0] ) + prev_key = 0; else - v14 = *v12 < asc_14096CDF0[0] ? -1 : 1; - if ( !v14 ) - { + prev_key = *key < asc_14096CDF0[0] ? -1 : 1; + if ( !prev_key ) { v15 = (char *)&Dst; if ( Dst.capacity >= 0x10 ) v15 = Dst.data.ptr; - v16 = v13 - v15; - if ( v16 != -1 ) - { + v16 = next_key - v15; + if ( v16 != -1 ) { sub_1400215A0(&Dst, &Memory, 0i64, v16); v17 = (char *)&Memory; if ( Memory.capacity >= 0x10 ) v17 = Memory.data.ptr; a4 = obj_database_get_object_set(v17); - if ( a4 != -1 ) - { + if ( a4 != -1 ) { v18 = a2->head; v19 = list_int32_t_buy_node(a2, a2->head, a2->head->prev, &a4); v20 = a2->size; @@ -1118,38 +1195,31 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) } break; } - v10 += v11 - v12 - 1; - v11 = v12 + 1; + v10 += v11 - key - 1; + v11 = key + 1; } } if ( Dst.capacity >= 0x10 ) j_free_2(Dst.data.ptr); } - if ( !string_compare_ptr_char(a1, "ITMPV", 0i64, 5ui64) ) - { + if ( !string_compare_ptr_char(a1, "ITMPV", 0i64, 5ui64) ) { sub_1400215A0(a1, &Memory, 5i64, -1i64); v21 = sub_1400D29A0(&Memory, 0xAu); - v22 = task_pv_db_get_pv(v21); - if ( v22 ) - { - v23 = v22->difficulty[2].begin; - if ( v22->difficulty[2].end - v23 ) - { + next_key = task_pv_db_get_pv(v21); + if ( next_key ) { + v23 = next_key->difficulty[2].begin; + if ( next_key->difficulty[2].end - v23 ) { v51.data = 0ui64; v51.length = 0i64; sub_14023FDE0((vector_pv_db_pv_pv_item *)&v51, &v23->pv_item); v24 = v51.data; - if ( v51.data.ptr != *(char **)&v51.data.data[8] ) - { + if ( v51.data.ptr != *(char **)&v51.data.data[8] ) { v25 = (pv_item *__shifted(pv_item,8))(v51.data.ptr + 8); - do - { - if ( ADJ(v25)->index > 0 ) - { + do { + if ( ADJ(v25)->index > 0 ) { v26 = (char *)(ADJ(v25)->name.capacity < 0x10 ? v25 : ADJ(v25)->name.data.ptr); v27 = obj_database_get_object_info(v26); - if ( v27 != -1 ) - { + if ( v27 != -1 ) { a4 = HIWORD(*(unsigned int *)&v27); v28 = a2->head; v29 = sub_14023B3E0(&a2->head, a2->head, a2->head->prev, &a4); @@ -1165,13 +1235,10 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) } while ( ADJ(v25) != *(pv_item *__shifted(pv_item,8) *)&v24.data[8] ); } - if ( v24.ptr ) - { - if ( v24.ptr != *(char **)&v24.data[8] ) - { + if ( v24.ptr ) { + if ( v24.ptr != *(char **)&v24.data[8] ) { v31 = (pv_item *__shifted(pv_item,0x20))(v24.ptr + 32); - do - { + do { if ( ADJ(v31)->name.capacity >= 0x10 ) j_free_2(ADJ(v31)->name.data.ptr); ADJ(v31)->name.capacity = 15i64; @@ -1187,12 +1254,10 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) if ( Memory.capacity >= 0x10 ) j_free_2(Memory.data.ptr); } - if ( !string_compare_ptr_char(a1, "EFFCHRPV", 0i64, 8ui64) ) - { + if ( !string_compare_ptr_char(a1, "EFFCHRPV", 0i64, 8ui64) ) { v32 = (char *)(a1->capacity < 0x10 ? a1 : a1->data.ptr); a4 = obj_database_get_object_set(v32); - if ( a4 != -1 ) - { + if ( a4 != -1 ) { v33 = a2->head; v34 = list_int32_t_buy_node(a2, a2->head, a2->head->prev, &a4); v35 = a2->size; @@ -1210,23 +1275,19 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) v51.data.data[0] = 0; string_append_char_str(&v51, null_string, 0i64); v36 = string_compare_ptr_char(a1, "STGPV", 0i64, 5ui64); - if ( v36 != -1 ) - { + if ( v36 != -1 ) { v37 = sub_1400215A0(a1, &Memory, v36, 8i64); - if ( &v51 != v37 ) - { + if ( &v51 != v37 ) { if ( v51.capacity >= 0x10 ) j_free_2(v51.data.ptr); v51.capacity = 15i64; v51.length = 0i64; v51.data.data[0] = 0; - if ( v37->capacity >= 0x10 ) - { + if ( v37->capacity >= 0x10 ) { v51.data.ptr = v37->data.ptr; v37->data.ptr = 0i64; } - else if ( v37->length != -1i64 ) - { + else if ( v37->length != -1i64 ) { memmove(&v51, v37, v37->length + 1); } v51.length = v37->length; @@ -1239,23 +1300,19 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) j_free_2(Memory.data.ptr); } v38 = string_compare_ptr_char(a1, "STGD2PV", 0i64, 7ui64); - if ( v38 != -1 ) - { + if ( v38 != -1 ) { v39 = sub_1400215A0(a1, &Memory, v38, 10i64); - if ( &v51 != v39 ) - { + if ( &v51 != v39 ) { if ( v51.capacity >= 0x10 ) j_free_2(v51.data.ptr); v51.capacity = 15i64; v51.length = 0i64; v51.data.data[0] = 0; - if ( v39->capacity >= 0x10 ) - { + if ( v39->capacity >= 0x10 ) { v51.data.ptr = v39->data.ptr; v39->data.ptr = 0i64; } - else if ( v39->length != -1i64 ) - { + else if ( v39->length != -1i64 ) { memmove(&v51, v39, v39->length + 1); } v51.length = v39->length; @@ -1267,14 +1324,12 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) if ( Memory.capacity >= 0x10 ) j_free_2(Memory.data.ptr); } - if ( v51.length ) - { + if ( v51.length ) { v40 = (char *)&v51; if ( v51.capacity >= 0x10 ) v40 = v51.data.ptr; a4 = obj_database_get_object_set(v40); - if ( a4 != -1 ) - { + if ( a4 != -1 ) { v41 = a2->head->next; v42 = list_int32_t_buy_node(a2, v41, v41->prev, &a4); v43 = a2->size; @@ -1290,8 +1345,7 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) if ( Memory.capacity >= 0x10 ) v44 = Memory.data.ptr; a4 = obj_database_get_object_set(v44); - if ( a4 != -1 ) - { + if ( a4 != -1 ) { v45 = a2->head; v46 = list_int32_t_buy_node(a2, a2->head, a2->head->prev, &a4); v47 = a2->size; @@ -1311,14 +1365,14 @@ void __fastcall sub_140248480(string *a1, list_int32_t *a2) void sub_140248480(string* a1, vector_uint32_t* a2) { char* v6; // rcx - int32_t* i; // rbx + int32_t* next_key; // rbx char* v8; // rax size_t v9; // r8 size_t v10; // rsi char* v11; // rdi - char* v12; // rax - char* v13; // r9 - int v14; // ecx + char* key; // rax + char* next_key; // r9 + int prev_key; // ecx char* v15; // rax ssize_t v16; // r9 char* v17; // rcx @@ -1326,7 +1380,7 @@ void sub_140248480(string* a1, vector_uint32_t* a2) { list_int32_t_node* v19; // rax size_t v20; // rdx int v21; // eax - ssize_t* v22; // rax + ssize_t* next_key; // rax __int64 v23; // rcx string_union v24; // kr00_16 string* v25; // rbx @@ -1365,29 +1419,25 @@ void sub_140248480(string* a1, vector_uint32_t* a2) { uids.capacity_end = 0; v6 = string_data(a1); sub_1401CBC70(v6, &uids); - for (i = uids.begin; i != uids.end; i++) { - v8 = sub_1401E7E90(*i); + for (next_key = uids.begin; next_key != uids.end; next_key++) { + v8 = sub_1401E7E90(*next_key); string_init(&Dst, v8); v10 = Dst.length; - if (Dst.length) - { + if (Dst.length) { v11 = string_data(&Dst); - while (v10) - { - v12 = memchr(v11, '_', v10); - v13 = v12; - if (!v12) + while (v10) { + key = memchr(v11, '_', v10); + next_key = key; + if (!key) break; - if (*v12 == "_"[0]) - v14 = 0; + if (*key == "_"[0]) + prev_key = 0; else - v14 = *v12 < "_"[0] ? -1 : 1; - if (!v14) - { + prev_key = *key < "_"[0] ? -1 : 1; + if (!prev_key) { v15 = string_data(&Dst); - v16 = v13 - v15; - if (v16 != -1) - { + v16 = next_key - v15; + if (v16 != -1) { sub_1400215A0(&Dst, &Memory, 0, v16); v17 = string_data(&Memory); a4 = obj_database_get_object_set(v17); @@ -1397,8 +1447,8 @@ void sub_140248480(string* a1, vector_uint32_t* a2) { } break; } - v10 += v11 - v12 - 1; - v11 = v12 + 1; + v10 += v11 - key - 1; + v11 = key + 1; } } string_free(&Dst); @@ -1407,10 +1457,10 @@ void sub_140248480(string* a1, vector_uint32_t* a2) { if (!str_utils_get_substring_offset(string_data(a1), a1->length, 0, "ITMPV", 5)) { string_init_length(&Dst, string_data(a1), 8); sscanf_s(string_data(a1) + 5, "%03d", &v21); - v22 = sub_1404E6220(v21); - if (v22) { - v23 = v22[28]; - if ((v22[29] - v23) / 1248) { + next_key = sub_1404E6220(v21); + if (next_key) { + v23 = next_key[28]; + if ((next_key[29] - v23) / 1248) { Dst.data = 0; Dst.length = 0; sub_14023FDE0(&Dst, (_QWORD*)(v23 + 504)); @@ -1514,6 +1564,13 @@ inline auth_3d* auth_3d_data_get_auth_3d(int32_t id) { return &auth_3d_data.data[index]; } +inline int32_t auth_3d_data_get_chara_id(int32_t id) { + auth_3d* auth = auth_3d_data_get_auth_3d(id); + if (auth) + return auth->chara_id; + return -1; +} + mat4* auth_3d_data_struct_get_auth_3d_object_mat(int32_t id, size_t index, bool hrc, mat4* mat) { if (id < 0 || (id & 0x7FFF) >= AUTH_3D_DATA_COUNT) return 0; @@ -1533,7 +1590,8 @@ mat4* auth_3d_data_struct_get_auth_3d_object_mat(int32_t id, size_t index, bool } -int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, uint64_t* mesh_index, bool* hrc) { +int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, + int32_t* object_index, bool* hrc, int32_t instance) { for (int32_t* i = auth_3d_data.loaded_ids.begin; i != auth_3d_data.loaded_ids.end; i++) { if (*i < 0 || (*i & 0x7FFF) >= AUTH_3D_DATA_COUNT) @@ -1543,20 +1601,56 @@ int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, uint64_ if (auth->id != *i || !auth->enable) continue; - int32_t obj_hrc_mesh_index = auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth, obj_info); - if (obj_hrc_mesh_index >= 0) { - if (mesh_index) - *mesh_index = obj_hrc_mesh_index; + int32_t obj_hrc_index = auth_3d_get_auth_3d_object_hrc_index_by_object_info( + auth, obj_info, instance); + if (obj_hrc_index >= 0) { + if (object_index) + *object_index = obj_hrc_index; if (hrc) *hrc = true; return *i; } - int32_t obj_mesh_index = auth_3d_get_auth_3d_object_index_by_object_info(auth, obj_info); - if (obj_mesh_index >= 0) - { - if (mesh_index) - *mesh_index = obj_mesh_index; + int32_t obj_index = auth_3d_get_auth_3d_object_index_by_object_info( + auth, obj_info, instance); + if (obj_index >= 0) { + if (object_index) + *object_index = obj_index; + if (hrc) + *hrc = false; + return *i; + } + } + return -1; +} + +int32_t auth_3d_data_get_auth_3d_id_by_hash(uint32_t file_name_hash, uint32_t object_hash, + int32_t* object_index, bool* hrc, int32_t instance) { + for (int32_t* i = auth_3d_data.loaded_ids.begin; + i != auth_3d_data.loaded_ids.end; i++) { + if (*i < 0 || (*i & 0x7FFF) >= AUTH_3D_DATA_COUNT) + continue; + + auth_3d* auth = &auth_3d_data.data[*i & 0x7FFF]; + if (auth->id != *i || !auth->enable + || (file_name_hash != hash_murmurhash_empty && auth->hash != file_name_hash)) + continue; + + int32_t obj_hrc_index = auth_3d_get_auth_3d_object_hrc_index_by_hash( + auth, object_hash, instance); + if (obj_hrc_index >= 0) { + if (object_index) + *object_index = obj_hrc_index; + if (hrc) + *hrc = true; + return *i; + } + + int32_t obj_index = auth_3d_get_auth_3d_object_index_by_hash( + auth, object_hash, instance); + if (obj_index >= 0) { + if (object_index) + *object_index = obj_index; if (hrc) *hrc = false; return *i; @@ -1601,6 +1695,85 @@ void auth_3d_data_free() { vector_int32_t_free(&auth_3d_data.loaded_ids, 0); } +static bool auth_3d_key_detect_fast_change(auth_3d_key* data, float_t frame, float_t threshold) { + if (data->type < AUTH_3D_KEY_LINEAR || data->type > AUTH_3D_KEY_HOLD) + return false; + + frame = clamp(frame, 0.0f, data->max_frame); + size_t length = data->length; + if (!length) + return false; + + kft3* keys = data->keys; + kft3* key = auth_3d_key_find_keyframe(data, frame); + if (key == keys || key == &keys[1] || key == &keys[length]) + return false; + + kft3* next_key = &key[1]; + if (next_key == &keys[length]) + return false; + + kft3* prev_key = &key[-1]; + float_t v18 = key->frame - prev_key->frame; + if (v18 >= 2.0f || v18 <= 0.0f) + return 0; + + if (fabsf(key->value - prev_key->value) <= threshold) + return 0; + + kft3* v21 = &prev_key[-1]; + if (prev_key->frame <= v21->frame) { + while (v21 != keys) { + if (prev_key->frame > v21->frame) + break; + v21++; + } + if (v21 == keys) + return 0; + } + + float_t v23 = key->value - (prev_key->value / v18); + float_t v25; + float_t v30; + if (data->type != AUTH_3D_KEY_HERMITE) { + v25 = (prev_key->value - v21->value) / (prev_key->frame - v21->frame); + v30 = (next_key->value - key->value) / (next_key->frame - key->frame); + } + else { + if (prev_key->frame - v21->frame >= 2.0f) { + float_t v26; + if (v21->frame < prev_key->frame) + v26 = interpolate_chs_value(key->value, next_key->value, + key->tangent2, next_key->tangent1, prev_key->frame, v21->frame, prev_key->frame - 1.0f); + else + v26 = v21->value; + v25 = prev_key->value - v26; + } + else + v25 = (prev_key->value - v21->value) / (prev_key->frame - v21->frame); + + if (next_key->frame - key->frame >= 2.0f) { + float_t v29; + if (key->frame < next_key->frame) + v29 = interpolate_chs_value(key->value, next_key->value, + key->tangent2, next_key->tangent1, key->frame, next_key->frame, 1.0f); + else + v29 = key->value; + v30 = v29 - key->value; + } + else + v30 = (next_key->value - key->value) / (next_key->frame - key->frame); + } + + float_t v32 = fabsf(v25); + float_t v33 = v25 * v23; + float_t v34 = v30 * v23; + float_t v35 = fabsf(v23); + float_t v36 = fabsf(v30); + return (v33 <= 0.0f || (v32 < v35 && v32 <= threshold)) + && (v34 <= 0.0f || (v36 < v35 && v36 <= threshold)); +} + static kft3* auth_3d_key_find_keyframe(auth_3d_key* data, float_t frame) { kft3* key = data->keys; size_t length = data->length; @@ -1645,7 +1818,7 @@ static float_t auth_3d_key_get_value(auth_3d_key* data, float_t frame) { frame = last_frame - fmodf(delta_frame, frame_delta); break; case A3DA_EP_CYCLE_OFFSET: - offset = -(float_t)((int32_t)(delta_frame / frame_delta + 1.0)) * data->value_delta; + offset = -(float_t)((int32_t)(delta_frame / frame_delta) + 1) * data->value_delta; frame = last_frame - fmodf(delta_frame, frame_delta); break; } @@ -1666,7 +1839,7 @@ static float_t auth_3d_key_get_value(auth_3d_key* data, float_t frame) { frame = first_frame + fmodf(delta_frame, frame_delta); break; case A3DA_EP_CYCLE_OFFSET: - offset = (float_t)((int32_t)(delta_frame / frame_delta + 1.0)) * data->value_delta; + offset = (float_t)((int32_t)(delta_frame / frame_delta) + 1) * data->value_delta; frame = first_frame + fmodf(delta_frame, frame_delta); break; } @@ -1845,21 +2018,31 @@ static void auth_3d_model_transform_set_mat(auth_3d_model_transform* mt, mat4* p mat4_to_mat4u(&mat, &mt->mat); } -static int32_t auth_3d_get_auth_3d_object_index_by_object_info(auth_3d* auth, object_info obj_info) { - auth_3d_object* v2 = auth->object.begin; - auth_3d_object* v3 = auth->object.end; - int32_t v4 = 0; - if (v2 == v3) - return -1; +static int32_t auth_3d_get_auth_3d_object_index_by_object_info(auth_3d* auth, + object_info obj_info, int32_t instance) { + int32_t index = 0; + int32_t obj_instance = 0; + for (auth_3d_object* i = auth->object.begin; i != auth->object.end; i++, index++) + if (obj_info.id == i->object_info.id + && obj_info.set_id == i->object_info.set_id) { + if (obj_instance == instance) + return index; + obj_instance++; + } + return -1; +} - while (obj_info.id != v2->object_info.id - || obj_info.set_id != v2->object_info.set_id) { - v2++; - v4++; - if (v2 == v3) - return -1; - } - return v4; +static int32_t auth_3d_get_auth_3d_object_index_by_hash(auth_3d* auth, + uint32_t object_hash, int32_t instance) { + int32_t index = 0; + int32_t obj_instance = 0; + for (auth_3d_object* i = auth->object.begin; i != auth->object.end; i++, index++) + if (object_hash == i->object_hash) { + if (obj_instance == instance) + return index; + obj_instance++; + } + return -1; } static mat4* auth_3d_get_auth_3d_object_hrc_bone_mats(auth_3d* auth, size_t index) { @@ -1869,21 +2052,31 @@ static mat4* auth_3d_get_auth_3d_object_hrc_bone_mats(auth_3d* auth, size_t inde return voh->begin[index].mats.begin; } -static int32_t auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth_3d* auth, object_info obj_info) { - auth_3d_object_hrc* v2 = auth->object_hrc.begin; - auth_3d_object_hrc* v3 = auth->object_hrc.end; - int32_t v4 = 0; - if (v2 == v3) - return -1; +static int32_t auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth_3d* auth, + object_info obj_info, int32_t instance) { + int32_t index = 0; + int32_t obj_instance = 0; + for (auth_3d_object_hrc* i = auth->object_hrc.begin; i != auth->object_hrc.end; i++, index++) + if (obj_info.id == i->object_info.id + && obj_info.set_id == i->object_info.set_id) { + if (obj_instance == instance) + return index; + obj_instance++; + } + return -1; +} - while (obj_info.id != v2->object_info.id - || obj_info.set_id != v2->object_info.set_id) { - v2++; - v4++; - if (v2 == v3) - return -1; - } - return v4; +static int32_t auth_3d_get_auth_3d_object_hrc_index_by_hash(auth_3d* auth, + uint32_t object_hash, int32_t instance) { + int32_t index = 0; + int32_t obj_instance = 0; + for (auth_3d_object_hrc* i = auth->object_hrc.begin; i != auth->object_hrc.end; i++, index++) + if (object_hash == i->object_hash) { + if (obj_instance == instance) + return index; + obj_instance++; + } + return -1; } static void auth_3d_ambient_data_set(auth_3d_ambient* a, render_context* rctx) { @@ -2015,9 +2208,36 @@ static void auth_3d_camera_root_data_set(auth_3d_camera_root* cr, camera_set_view_point(cam, &view_point); camera_set_fov(cam, fov * RAD_TO_DEG); camera_set_roll(cam, roll * RAD_TO_DEG); + camera_set_fast_change(cam, cr->fast_change); + camera_set_fast_change_hist0(cam, cr->fast_change_hist0); } static void auth_3d_camera_root_get_value(auth_3d_camera_root* cr, float_t frame, mat4* mat) { + cr->fast_change = false; + cr->fast_change_hist0 = false; + if (auth_3d_key_detect_fast_change(&cr->view_point.model_transform.translation.x, frame, 0.3f) + || auth_3d_key_detect_fast_change(&cr->view_point.model_transform.translation.y, frame, 0.3f) + || auth_3d_key_detect_fast_change(&cr->view_point.model_transform.translation.z, frame, 0.3f) + || auth_3d_key_detect_fast_change(&cr->interest.translation.x, frame, 0.3f) + || auth_3d_key_detect_fast_change(&cr->interest.translation.y, frame, 0.3f) + || auth_3d_key_detect_fast_change(&cr->interest.translation.z, frame, 0.3f)) { + frame = (float_t)(int32_t)frame; + cr->fast_change = true; + } + else { + float_t frame_prev = frame - get_delta_frame(); + if (frame_prev > 0.0f && (int32_t)frame - (int32_t)frame_prev == 2) { + frame_prev = (float_t)((int32_t)frame_prev + 1); + if (auth_3d_key_detect_fast_change(&cr->view_point.model_transform.translation.x, frame_prev, 0.3f) + || auth_3d_key_detect_fast_change(&cr->view_point.model_transform.translation.y, frame_prev, 0.3f) + || auth_3d_key_detect_fast_change(&cr->view_point.model_transform.translation.z, frame_prev, 0.3f) + || auth_3d_key_detect_fast_change(&cr->interest.translation.x, frame_prev, 0.3f) + || auth_3d_key_detect_fast_change(&cr->interest.translation.y, frame_prev, 0.3f) + || auth_3d_key_detect_fast_change(&cr->interest.translation.z, frame_prev, 0.3f)) + cr->fast_change_hist0 = false; + } + } + auth_3d_model_transform_get_value(&cr->model_transform, frame); auth_3d_model_transform_set_mat(&cr->model_transform, mat); @@ -2523,7 +2743,7 @@ static void auth_3d_m_object_hrc_load(auth_3d* auth, } static void auth_3d_m_object_hrc_data_set(auth_3d_m_object_hrc* moh, auth_3d* auth, render_context* rctx) { - if (!moh->model_transform.visible) + if (!auth->visible || !moh->model_transform.visible) return; object_data* object_data = &rctx->object_data; @@ -2680,6 +2900,7 @@ static void auth_3d_object_load(auth_3d* auth, auth_3d_object_file* of, o->refract = strstr(string_data(&o->uid_name), "_REFRACT"); o->object_info = object_database_get_object_info(obj_db, string_data(&o->uid_name)); + o->object_hash = hash_murmurhash(string_data(&o->uid_name), o->uid_name.length, 0, false, false); } static void auth_3d_object_curve_get_value(auth_3d_object_curve* oc, float_t frame) { @@ -2711,7 +2932,7 @@ static void auth_3d_object_curve_load(auth_3d* auth, auth_3d_object_curve* oc, } static void auth_3d_object_data_set(auth_3d_object* o, auth_3d* auth, render_context* rctx) { - if (!o->model_transform.visible) + if (!auth->visible || !o->model_transform.visible) return; mat4 mat; @@ -2873,6 +3094,7 @@ static void auth_3d_object_hrc_load(auth_3d* auth, oh->refract = strstr(string_data(&oh->uid_name), "_REFRACT"); oh->object_info = object_database_get_object_info(obj_db, string_data(&oh->uid_name)); + oh->object_hash = hash_murmurhash(string_data(&oh->uid_name), oh->uid_name.length, 0, false, false); object* obj = object_storage_get_object(oh->object_info); if (!obj || !obj->skin_init) @@ -2899,7 +3121,7 @@ static void auth_3d_object_hrc_load(auth_3d* auth, } static void auth_3d_object_hrc_data_set(auth_3d_object_hrc* oh, auth_3d* auth, render_context* rctx) { - if (!oh->node.begin[0].model_transform.visible) + if (!auth->visible || !oh->node.begin[0].model_transform.visible) return; object_data* object_data = &rctx->object_data; @@ -3005,6 +3227,7 @@ static void auth_3d_object_instance_load(auth_3d* auth, auth_3d_m_object_hrc* mo string_copy(&oif->uid_name, &oi->uid_name); oi->object_info = object_database_get_object_info(obj_db, string_data(&oi->uid_name)); + oi->object_hash = hash_murmurhash(string_data(&oi->uid_name), oi->uid_name.length, 0, false, false); object* obj = object_storage_get_object(oi->object_info); if (!obj || !obj->skin_init) diff --git a/src/CRE/auth_3d.h b/src/CRE/auth_3d.h index 2f6b634c..eb2811ef 100644 --- a/src/CRE/auth_3d.h +++ b/src/CRE/auth_3d.h @@ -296,6 +296,8 @@ struct auth_3d_camera_root { vec3 interest_value; float_t roll_value; vec3 view_point_value; + bool fast_change; + bool fast_change_hist0; }; struct auth_3d_chara { @@ -435,6 +437,7 @@ struct auth_3d_object { auth_3d_model_transform model_transform; auth_3d_object_curve morph; object_info object_info; + uint32_t object_hash; string name; string parent_name; string parent_node; @@ -455,6 +458,7 @@ struct auth_3d_object_hrc { string name; vector_auth_3d_object_node node; object_info object_info; + uint32_t object_hash; string parent_name; string parent_node; bool reflect; @@ -469,6 +473,7 @@ struct auth_3d_object_instance { string name; vector_int32_t object_bone_indices; object_info object_info; + uint32_t object_hash; bool shadow; string uid_name; }; @@ -548,12 +553,15 @@ typedef struct auth_3d { int32_t id; bool enable; bool camera_root_update; + bool visible; bool repeat; bool ended; bool left_right_reverse; bool once; float_t alpha; + int32_t chara_id; + frame_rate_control* frame_rate; float_t frame; float_t set_frame; float_t max_frame; @@ -586,6 +594,7 @@ typedef struct auth_3d { string file_name; int32_t frame_int; + uint32_t hash; } auth_3d; #define AUTH_3D_DATA_COUNT 0x100 @@ -604,12 +613,12 @@ extern auth_3d_data_struct auth_3d_data; extern void auth_3d_init(auth_3d* auth); extern void auth_3d_data_set(auth_3d* auth, mat4* mat, render_context* rctx); -extern void auth_3d_get_value(auth_3d* auth, mat4* mat, float_t frame); -extern void auth_3d_unload(auth_3d* auth, render_context* rctx); +extern void auth_3d_time_step(auth_3d* auth, mat4* mat); extern void auth_3d_load(auth_3d* auth, a3da* auth_file, object_database* obj_db, texture_database* tex_db); extern void auth_3d_load_from_farc(auth_3d* auth, farc* f, char* file, object_database* obj_db, texture_database* tex_db); +extern void auth_3d_unload(auth_3d* auth, render_context* rctx); extern void auth_3d_free(auth_3d* auth); extern void auth_3d_farc_init(auth_3d_farc* f); @@ -647,7 +656,11 @@ extern void auth_3d_post_process_free(auth_3d_post_process* pp); extern void auth_3d_data_init(); extern int32_t auth_3d_data_load_uid(int32_t uid, auth_3d_database* auth_3d_db); extern auth_3d* auth_3d_data_get_auth_3d(int32_t id); -extern int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, uint64_t* mesh_index, bool* hrc); +extern int32_t auth_3d_data_get_chara_id(int32_t id); +extern int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, + int32_t* object_index, bool* hrc, int32_t instance); +extern int32_t auth_3d_data_get_auth_3d_id_by_hash(uint32_t file_name_hash, uint32_t object_hash, + int32_t* object_index, bool* hrc, int32_t instance); extern mat4* auth_3d_data_struct_get_auth_3d_object_mat(int32_t id, size_t index, bool hrc, mat4* mat); extern void auth_3d_data_unload_id(int32_t id, render_context* rctx); extern void auth_3d_data_free(); diff --git a/src/CRE/camera.c b/src/CRE/camera.c index a266f0ee..42818da1 100644 --- a/src/CRE/camera.c +++ b/src/CRE/camera.c @@ -163,6 +163,14 @@ void camera_set_res(camera* c, int32_t width, int32_t height) { } } +void camera_set_fast_change(camera* c, bool value) { + c->fast_change = value; +} + +void camera_set_fast_change_hist0(camera* c, bool value) { + c->fast_change_hist0 = value; +} + void camera_reset(camera* c) { camera_set_pitch(c, 0.0); camera_set_yaw(c, 0.0); @@ -256,7 +264,11 @@ void camera_update(camera* c) { mat4_inverse(&c->view_projection, &c->inv_view_projection); c->changed_proj = false; //c->changed_view = false; - } + } + + c->fast_change_hist1 = c->fast_change_hist0; + c->fast_change_hist0 = c->fast_change; + c->fast_change = false; } void camera_dispose(camera* c) { @@ -319,6 +331,8 @@ static void camera_calculate_view(camera* c) { mat4_inverse(&c->view, &c->inv_view); mat3_from_mat4(&c->view, &c->view_mat3); mat3_inverse(&c->view_mat3, &c->inv_view_mat3); + mat4_from_mat3(&c->view_mat3, &c->view_rot); + mat4_from_mat3(&c->inv_view_mat3, &c->inv_view_rot); if (fabs(c->rotation.x * RAD_TO_DEG - c->pitch) > 0.01 || fabs(-c->rotation.y * RAD_TO_DEG - c->yaw) > 0.01) { diff --git a/src/CRE/camera.h b/src/CRE/camera.h index b7b6b2eb..b8d34bf2 100644 --- a/src/CRE/camera.h +++ b/src/CRE/camera.h @@ -18,6 +18,8 @@ typedef struct camera { mat4 inv_view_projection; mat3 view_mat3; mat3 inv_view_mat3; + mat4 view_rot; + mat4 inv_view_rot; vec3 forward; vec3 rotation; vec3 view_point; @@ -38,6 +40,9 @@ typedef struct camera { double_t min_distance; bool changed_view; bool changed_proj; + bool fast_change; + bool fast_change_hist0; + bool fast_change_hist1; } camera; extern camera* camera_init(); @@ -62,6 +67,8 @@ extern void camera_get_interest(camera* c, vec3* value); extern void camera_set_interest(camera* c, vec3* value); extern void camera_get_res(camera* c, int32_t* width, int32_t* height); extern void camera_set_res(camera* c, int32_t width, int32_t height); +extern void camera_set_fast_change(camera* c, bool value); +extern void camera_set_fast_change_hist0(camera* c, bool value); extern void camera_reset(camera* c); extern void camera_move(camera* c, vec2d* move); extern void camera_rotate(camera* c, vec2d* rotate); diff --git a/src/CRE/data.c b/src/CRE/data.c index 2c233387..c2c1529f 100644 --- a/src/CRE/data.c +++ b/src/CRE/data.c @@ -128,6 +128,20 @@ void data_struct_get_directory_files(data_struct* ds, char* dir, vector_data_str bool data_struct_load_file(data_struct* ds, void* data, char* dir, char* file, bool (*load_func)(void* data, char* path, char* file, uint32_t hash)) { + if (path_check_directory_exists(dir)) { + char* t = strrchr(file, '.'); + size_t t_len; + if (t) + t_len = t - file; + else + t_len = utf8_length(file); + + uint32_t h = hash_murmurhash(file, t_len, 0, false, false); + bool ret = load_func(data, dir, file, h); + if (ret) + return true; + } + size_t dir_len = utf8_length(dir); if (dir_len >= 2 && !memcmp(dir, "./", 2)) { dir += 2; @@ -181,7 +195,7 @@ bool data_struct_load_file(data_struct* ds, void* data, char* dir, char* file, char* t = strrchr(l_str, '.'); size_t l_len = l->length; if (t) - l_len = t - l_str - 1; + l_len = t - l_str; uint32_t h = hash_murmurhash(l_str, l_len, 0, false, false); ret = load_func(data, temp, l_str, h); diff --git a/src/CRE/draw_object.c b/src/CRE/draw_object.c index 0678f9bd..38e64284 100644 --- a/src/CRE/draw_object.c +++ b/src/CRE/draw_object.c @@ -54,7 +54,7 @@ void draw_object_draw(render_context* rctx, draw_object* draw, mat4* model, mat4 mat; if (draw->mesh->flags & OBJECT_MESH_BILLBOARD) - model_mat_face_camera_view(&rctx->camera->view, model, &mat); + model_mat_face_camera_view(&rctx->camera->inv_view_rot, model, &mat); else if (draw->mesh->flags & OBJECT_MESH_BILLBOARD_Y_AXIS) model_mat_face_camera_position(&rctx->camera->view, model, &mat); else @@ -118,43 +118,41 @@ void draw_object_draw_default(render_context* rctx, draw_object* draw) { void draw_object_draw_sss(render_context* rctx, draw_object* draw) { object_material_blend_flags blend_flags = draw->material->material.blend_flags; uniform_value[U_ALPHA_TEST] = (!blend_flags.flag_28 && (draw->blend_color.w < 1.0f - || (blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through - || draw->sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT) - || blend_flags.punch_through) ? 1 : 0; + || (blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through + || draw->sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT) + || blend_flags.punch_through) ? 1 : 0; + uniform_value[U26] = 1; bool aniso = false; object_material_data* material = draw->material; switch (material->material.shader_index) { - case SHADER_FT_SKIN: - uniform_value[U26] = 1; - break; case SHADER_FT_CLOTH: - uniform_value[U26] = 1; - if (rctx->draw_pass.npr_param || material->material.ambient.w >= 1.0f - || (material->material.shader_flags.aniso_direction & 0x03) != OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL) + if (!rctx->draw_pass.npr_param && material->material.ambient.w < 1.0f + && (material->material.shader_flags.aniso_direction & 0x03) == OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL) aniso = true; break; case SHADER_FT_TIGHTS: - uniform_value[U26] = 1; - if (rctx->draw_pass.npr_param) + if (!rctx->draw_pass.npr_param) aniso = true; break; case SHADER_FT_EYEBALL: uniform_value[U26] = 0; - return; + aniso = true; + break; + case SHADER_FT_SKIN: + aniso = true; + break; } - vec3 sss_param; - if (!aniso) { + if (aniso) { + shader_env_frag_set(&shaders_ft, 25, 0.0f, 0.0f, 0.0f, 0.5f); uniform_value[U37] = 1; - sss_param = *(vec3*)&rctx->draw_pass.sss_data.param; } else { + vec4 sss_param = rctx->draw_pass.sss_data.param; + shader_env_frag_set(&shaders_ft, 25, sss_param.x, sss_param.y, sss_param.z, 0.5f); uniform_value[U37] = 0; - sss_param = vec3_null; } - - shader_env_frag_set(&shaders_ft, 25, sss_param.x, sss_param.y, sss_param.z, 0.5f); draw_object_draw_default(rctx, draw); } @@ -337,12 +335,8 @@ inline void model_mat_face_camera_position(mat4* view, mat4* src, mat4* dst) { dst->row3.w = 1.0f; } -inline void model_mat_face_camera_view(mat4* view, mat4* src, mat4* dst) { - mat3 mat; - mat3_from_mat4(view, &mat); - mat3_inverse(&mat, &mat); - mat4_from_mat3(&mat, dst); - mat4_mult(dst, src, dst); +inline void model_mat_face_camera_view(mat4* inv_view_rot, mat4* src, mat4* dst) { + mat4_mult(inv_view_rot, src, dst); } void object_sub_mesh_draw(render_context* rctx, object_primitive_type primitive_type, diff --git a/src/CRE/draw_pass.c b/src/CRE/draw_pass.c index dbdc7622..5ca36545 100644 --- a/src/CRE/draw_pass.c +++ b/src/CRE/draw_pass.c @@ -10,6 +10,7 @@ #include "light_param/light.h" #include "gl_state.h" #include "post_process.h" +#include "rob.h" #include "render_texture.h" #include "shader_ft.h" #include "shader_glsl.h" @@ -78,10 +79,13 @@ void draw_pass_main(render_context* rctx) { 9, 10, 11, 12, 13 }; + camera* cam = rctx->camera; + + post_process_update(&rctx->post_process, cam); + for (int32_t i = 0; i < 5; i++) gl_state_active_bind_texture_cube_map(ibl_texture_index[i], rctx->ibl_tex[i]); - camera* cam = rctx->camera; GPM_VAL->cam_projection = cam->projection; GPM_VAL->cam_view = cam->view; @@ -574,23 +578,58 @@ static void draw_pass_sss_contour(render_context* rctx, post_process_struct* pp) render_texture_draw_params(&shaders_ft, pp->render_width, pp->render_height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); } +static void draw_pass_sss_filter_calc_coef(double_t a1, size_t a2, double_t a3, size_t a4, + double_t* a5, double_t* a6, double_t* a7, double_t* a8) { + if (a2 > 8) + return; + + vec4 params[64]; + memset(params, 0, sizeof(vec4) * 64); + + for (size_t i = a4; i; i--) { + float_t* v20 = (float_t*)params; + double_t v56[3]; + v56[0] = *a6; + v56[1] = *a7; + v56[2] = *a8; + + for (size_t j = 0; j < 3; j++) { + double_t v22 = 0.0; + double_t v23 = 0.0; + double_t v54[8]; + double_t v24 = 1.0 / (a3 * v56[j]); + v24 *= v24; + for (size_t k = 0; k < a2; k++) { + double_t v25 = exp(-0.5 * (v23 * v23) * v24); + v54[k] = v25; + v23 += a1; + v22 += v25; + } + + double_t v27 = 1.0 / v22; + for (size_t k = 0; k < a2; k++) + v54[k] *= v27; + + float_t* v35 = v20; + for (size_t k = 0; k < a2; k++) { + double_t v37 = v54[k] * *a5; + for (size_t v36 = 0; v36 < a2; v36++) { + *v35 += (float_t)(v37 * v54[v36]); + v35 += 4; + } + } + v20++; + } + a5++; + a6++; + a7++; + a8++; + } + shader_local_frag_set_ptr_array(&shaders_ft, 4, a2 * a2, params); +} + static void draw_pass_sss_filter(render_context* rctx, sss_data_struct* a1) { - double_t a5[3]; - double_t a6[3]; - double_t a7[3]; - double_t a8[3]; - a5[0] = 0.4; - a5[1] = 0.3; - a5[2] = 0.3; - a6[0] = 1.0; - a6[1] = 2.0; - a6[2] = 5.0; - a7[0] = 0.2; - a7[1] = 0.4; - a7[2] = 1.2; - a8[0] = 0.3; - a8[1] = 0.7; - a8[2] = 2.0; + const int32_t sss_count = 6; vec3 interest = rctx->camera->interest; vec3 view_point = rctx->camera->view_point; @@ -600,17 +639,15 @@ static void draw_pass_sss_filter(render_context* rctx, sss_data_struct* a1) { float_t v14[2]; for (int32_t i = 0; i < 2; i++) { v46[i] = interest; - v14[i] = 999999.0; - /*rob_chara_data_struct_bone_data* v16 = sub_1405320F0(i); - if (chara_check_index(v13) && sub_140531F50(v13) && v16) { - mat4* v17 = rob_chara_data_struct_bone_data_get_mats_mat(v16, 0); + v14[i] = 999999.0f; + rob_chara_bone_data* v16 = rob_chara_array[i].bone_data; + if (rob_chara_pv_data_array[i].field_0 != -1 && rob_chara_array[i].data.field_0 & 1) { + mat4* v17 = rob_chara_bone_data_get_mats_mat(v16, MOTION_BONE_N_HARA_CP); if (v17) { - v46[i] = *(vec3*)&v17->row3; - vec3 dist; - vec3_sub(view_point, *(vec3*)&v17->row3, dist); - vec3_length(dist, v14[i]); + mat4_get_translation(v17, &v46[i]); + vec3_distance(view_point, v46[i], v14[i]); } - }*/ + } } vec3 v24; @@ -623,7 +660,7 @@ static void draw_pass_sss_filter(render_context* rctx, sss_data_struct* a1) { float_t length; vec3_distance(interest, v24, length); - if (length > 1.25) + if (length > 1.25f) interest = v46[0]; float_t v29; @@ -670,44 +707,26 @@ static void draw_pass_sss_filter(render_context* rctx, sss_data_struct* a1) { uniform_value[U_SSS_FILTER] = 3; shader_set(&shaders_ft, SHADER_FT_SSS_FILT); shader_local_frag_set(&shaders_ft, 1, 5.0f, 0.0f, 0.0f, 0.0f); - float_t params[144]; - for (int32_t i = 0; i < 144; i += 4) - *(vec4u*)¶ms[i] = vec4u_null; - for (int32_t i = 0; i < 3; i++) { - float_t* v20 = params; - double_t v56[3]; - v56[0] = *a6; - v56[1] = a7[i]; - v56[2] = *a8; - double_t v38 = *a5; - for (int32_t j = 0; j < 3; j++, v20++) { - double_t v54[6]; - double_t v22 = 0.0; - double_t v23 = 0.0; - double_t v24 = 1.0 / (v34 * v56[j]); - for (int32_t k = 0; k < 6; k++) { - v54[k] = exp((v24 * v24) * (v23 * v23) * -0.5); - v22 += v54[k]; - v23 += 1.0; - } + double_t a5[3]; + double_t a6[3]; + double_t a7[3]; + double_t a8[3]; + a5[0] = 0.4; + a5[1] = 0.3; + a5[2] = 0.3; + a6[0] = 1.0; + a6[1] = 2.0; + a6[2] = 5.0; + a7[0] = 0.2; + a7[1] = 0.4; + a7[2] = 1.2; + a8[0] = 0.3; + a8[1] = 0.7; + a8[2] = 2.0; + draw_pass_sss_filter_calc_coef(1.0, sss_count, v34, 3, a5, a6, a7, a8); - size_t v26 = 0; - double_t v27 = 1.0 / v22; - for (int32_t k = 0; k < 6; k++) - v54[k] *= v27; - - float_t* v35 = v20; - for (int32_t v33 = 0, v34 = 0; v33 < 6; v33++, v34 += 6, v35 += 24) { - double_t v37 = v54[v33] * v38; - float_t* v39 = v35; - float_t* v50 = ¶ms[4 * v34 + j]; - for (int32_t v36 = 0; v36 < 6; v36++) - v50[v36 * 4] += (float_t)(v37 * v54[v36]); - } - } - } - shader_local_frag_set_ptr_array(&shaders_ft, 4, 36, (vec4*)params); + shader_local_frag_set(&shaders_ft, 1, (float_t)(sss_count - 1), 0.0f, 1.0f, 1.0f); glViewport(0, 0, 320, 180); gl_state_bind_texture_2d(a1->textures[2].color_texture->texture); render_texture_draw_params(&shaders_ft, 320, 180, 1.0f, 1.0f, 0.96f, 1.0f, 0.0f); diff --git a/src/CRE/draw_task.c b/src/CRE/draw_task.c index de3e8bef..15ab1a85 100644 --- a/src/CRE/draw_task.c +++ b/src/CRE/draw_task.c @@ -4,6 +4,7 @@ */ #include "draw_task.h" +#include "../KKdLib/sort.h" #include "camera.h" #include "fbo.h" #include "post_process.h" @@ -17,6 +18,9 @@ static void draw_task_object_init(draw_task* task, object_data* object_data, mat int32_t instances_count, mat4* instances_mat, void(*draw_object_func)(draw_object*)); static void draw_task_object_translucent_init(draw_task* task, mat4* mat, draw_task_object_translucent* object); +static int draw_task_sort_quicksort_compare0(void const* src1, void const* src2); +static int draw_task_sort_quicksort_compare1(void const* src1, void const* src2); +static int draw_task_sort_quicksort_compare2(void const* src1, void const* src2); static int32_t draw_task_translucent_sort_count_layers(render_context* rctx, int32_t* alpha_array, draw_object_type opaque, draw_object_type transparent, draw_object_type translucent); @@ -742,38 +746,22 @@ void draw_task_sort(render_context* rctx, draw_object_type type, int32_t compare task->bounding_radius = task->data.object.mesh->bounding_sphere.radius; } - //mat4_mult_vec3_trans(&rctx->camera->view, ¢er, ¢er); - //task->depth = center.z; - task->depth = rctx->camera->view_point.z - center.z; + mat4_mult_vec3_trans(&rctx->camera->view, ¢er, ¢er); + task->depth = center.z; } switch (compare_func) { case 0: - for (draw_task** i = vec->begin; i != &vec->end[-1]; i++) - for (draw_task** j = i + 1; j != vec->end; j++) - if ((*i)->depth > (*j)->depth) { - draw_task* temp = *i; - *i = *j; - *j = temp; - } + quicksort_custom(vec->begin, vector_length(*vec), + sizeof(draw_task*), draw_task_sort_quicksort_compare0); break; case 1: - for (draw_task** i = vec->begin; i != &vec->end[-1]; i++) - for (draw_task** j = i + 1; j != vec->end; j++) - if ((*i)->depth < (*j)->depth) { - draw_task* temp = *i; - *i = *j; - *j = temp; - } + quicksort_custom(vec->begin, vector_length(*vec), + sizeof(draw_task*), draw_task_sort_quicksort_compare1); break; case 2: - for (draw_task** i = vec->begin; i != &vec->end[-1]; i++) - for (draw_task** j = i + 1; j != vec->end; j++) - if ((*i)->bounding_radius < (*j)->bounding_radius) { - draw_task* temp = *i; - *i = *j; - *j = temp; - } + quicksort_custom(vec->begin, vector_length(*vec), + sizeof(draw_task*), draw_task_sort_quicksort_compare2); break; } } @@ -934,6 +922,24 @@ inline static void draw_task_object_translucent_init(draw_task* task, mat4* mat, task->data.object_translucent = *object; } +static int draw_task_sort_quicksort_compare0(void const* src1, void const* src2) { + float_t d1 = (*(draw_task**)src1)->depth; + float_t d2 = (*(draw_task**)src2)->depth; + return d1 > d2 ? -1 : (d1 < d2 ? 1 : 0); +} + +static int draw_task_sort_quicksort_compare1(void const* src1, void const* src2) { + float_t d1 = (*(draw_task**)src1)->depth; + float_t d2 = (*(draw_task**)src2)->depth; + return d1 < d2 ? -1 : (d1 > d2 ? 1 : 0); +} + +static int draw_task_sort_quicksort_compare2(void const* src1, void const* src2) { + float_t r1 = (*(draw_task**)src1)->bounding_radius; + float_t r2 = (*(draw_task**)src2)->bounding_radius; + return r1 < r2 ? 1 : (r1 > r2 ? -1 : 0); +} + inline static int32_t draw_task_translucent_sort_count_layers(render_context* rctx, int32_t* alpha_array, draw_object_type opaque, draw_object_type transparent, draw_object_type translucent) { diff --git a/src/CRE/object.c b/src/CRE/object.c index 9d77b1b2..d77ff32a 100644 --- a/src/CRE/object.c +++ b/src/CRE/object.c @@ -123,6 +123,7 @@ void object_set_load(object_set* set, obj_set* obj_set_file, txp_set* txp_set_fi string_copy(name, &set->name); set->id = id; + set->hash = hash_murmurhash(string_data(&set->name), set->name.length, 0, false, false); int32_t objects_count = obj_set_file->objects_count; set->objects_count = objects_count; @@ -466,6 +467,7 @@ void object_set_load(object_set* set, obj_set* obj_set_file, txp_set* txp_set_fi obj->flags = obj_file->flags; string_copy(&obj_file->name, &obj->name); obj->id = obj_file->id; + obj->hash = hash_murmurhash(string_data(&obj->name), obj->name.length, 0, false, false); if (!obj_file->skin_init) { memset(&obj->skin, 0, sizeof(object_skin)); @@ -716,6 +718,10 @@ bool object_set_load_db_entry(object_set_info** set_info, void* data, object_database* obj_db, char* name) { if (!object_database_get_object_set_info(obj_db, name, set_info)) return false; + else if (object_storage_get_object_set((*set_info)->id)) { + object_storage_append_object_set((*set_info)->id); + return true; + } size_t temp[2]; temp[0] = (size_t)data; @@ -726,6 +732,11 @@ bool object_set_load_db_entry(object_set_info** set_info, bool object_set_load_by_db_entry(object_set_info* set_info, void* data, object_database* obj_db) { + if (object_storage_get_object_set(set_info->id)) { + object_storage_append_object_set(set_info->id); + return true; + } + size_t temp[2]; temp[0] = (size_t)data; temp[1] = (size_t)set_info; @@ -737,6 +748,10 @@ bool object_set_load_by_db_index(object_set_info** set_info, void* data, object_database* obj_db, uint32_t set_id) { if (!object_database_get_object_set_info_by_set_id(obj_db, set_id, set_info)) return false; + else if (object_storage_get_object_set(set_id)) { + object_storage_append_object_set(set_id); + return true; + } size_t temp[2]; temp[0] = (size_t)data; @@ -1064,6 +1079,36 @@ inline object_mesh* object_storage_get_object_mesh_by_index(object_info obj_info return 0; } +inline object_mesh* object_storage_get_object_mesh_by_object_hash(uint32_t hash, char* mesh_name) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].hash == hash) { + object* obj = &set->objects[j]; + for (int32_t k = 0; k < obj->meshes_count; k++) + if (!str_utils_compare(obj->meshes[k].name, mesh_name)) + return &obj->meshes[k]; + return 0; + } + return 0; + } + return 0; +} + +inline object_mesh* object_storage_get_object_mesh_by_object_hash_index(uint32_t hash, int32_t index) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].hash == hash) { + object* obj = &set->objects[j]; + if (index > -1 && index < obj->meshes_count) + return &obj->meshes[index]; + return 0; + } + } + return 0; +} + inline int32_t object_storage_get_object_mesh_index(object_info obj_info, char* mesh_name) { for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) if (i->set_id == obj_info.set_id) { @@ -1081,6 +1126,21 @@ inline int32_t object_storage_get_object_mesh_index(object_info obj_info, char* return -1; } +inline int32_t object_storage_get_object_mesh_index_by_hash(uint32_t hash, char* mesh_name) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].hash == hash) { + object* obj = &set->objects[j]; + for (int32_t k = 0; k < obj->meshes_count; k++) + if (!str_utils_compare(obj->meshes[k].name, mesh_name)) + return k; + return -1; + } + } + return -1; +} + inline object_set* object_storage_get_object_set(uint32_t set_id) { for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) if (i->set_id == set_id) @@ -1092,12 +1152,25 @@ inline ssize_t object_storage_get_object_set_count() { return vector_length(object_storage_data); } +inline int32_t object_storage_get_object_set_load_count(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) + return i->count; + return 0; +} + inline object_set* object_storage_get_object_set_by_index(ssize_t index) { if (index >= 0 && index < vector_length(object_storage_data)) return &object_storage_data.begin[index].set; return 0; } +inline int32_t object_storage_get_object_set_load_count_by_index(ssize_t index) { + if (index >= 0 && index < vector_length(object_storage_data)) + return object_storage_data.begin[index].count; + return 0; +} + inline ssize_t object_storage_get_object_set_index(uint32_t set_id) { for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) if (i->set_id == set_id) @@ -1493,12 +1566,15 @@ static bool object_set_load_file_modern(void* data, char* path, char* file, uint break; } - if (name && obj_set.ready) { - object_set object_set; - object_set_init(&object_set); - object_set_load(&object_set, &obj_set, &txp_set, tex_db, name, hash, true); - object_storage_insert_object_set(&object_set, hash); - } + if (name && obj_set.ready) + if (!object_storage_get_object_set(hash)) { + object_set object_set; + object_set_init(&object_set); + object_set_load(&object_set, &obj_set, &txp_set, tex_db, name, hash, true); + object_storage_insert_object_set(&object_set, hash); + } + else + object_storage_append_object_set(hash); obj_free(&obj_set); txp_set_free(&txp_set); diff --git a/src/CRE/object.h b/src/CRE/object.h index 0cbbd4ec..0546c9e9 100644 --- a/src/CRE/object.h +++ b/src/CRE/object.h @@ -539,6 +539,7 @@ typedef struct object { bool skin_init; string name; uint32_t id; + uint32_t hash; } object; typedef GLint object_mesh_index_buffer; @@ -562,6 +563,7 @@ typedef struct object_vertex_buffer { typedef struct object_set { string name; uint32_t id; + uint32_t hash; object* objects; int32_t objects_count; uint32_t* texture_ids; @@ -609,11 +611,16 @@ extern void object_storage_insert_object_set(object_set* set, uint32_t set_id); extern object* object_storage_get_object(object_info obj_info); extern object_mesh* object_storage_get_object_mesh(object_info obj_info, char* mesh_name); extern object_mesh* object_storage_get_object_mesh_by_index(object_info obj_info, int32_t index); +extern object_mesh* object_storage_get_object_mesh_by_object_hash(uint32_t hash, char* mesh_name); +extern object_mesh* object_storage_get_object_mesh_by_object_hash_index(uint32_t hash, int32_t index); extern int32_t object_storage_get_object_mesh_index(object_info obj_info, char* mesh_name); +extern int32_t object_storage_get_object_mesh_index_by_hash(uint32_t hash, char* mesh_name); extern object_set* object_storage_get_object_set(uint32_t set_id); extern ssize_t object_storage_get_object_set_count(); +extern int32_t object_storage_get_object_set_load_count(uint32_t set_id); extern object_set* object_storage_get_object_set_by_index(ssize_t index); extern ssize_t object_storage_get_object_set_index(uint32_t set_id); +extern int32_t object_storage_get_object_set_load_count_by_index(ssize_t index); extern object_skin* object_storage_get_object_skin(object_info obj_info); extern object_index_buffer* object_storage_get_object_index_buffers(uint32_t set_id); extern object_mesh_index_buffer* object_storage_get_object_mesh_index_buffer(object_info obj_info); diff --git a/src/CRE/post_process.c b/src/CRE/post_process.c index a9a79073..659c1cb6 100644 --- a/src/CRE/post_process.c +++ b/src/CRE/post_process.c @@ -11,6 +11,8 @@ #include "static_var.h" #include "texture.h" +extern int32_t stage_index; + void post_process_init(post_process_struct* pp) { static const char* alpha_layer_vert_shader = "#version 430 core\n" @@ -51,6 +53,8 @@ void post_process_init(post_process_struct* pp) { pp->dof = post_process_dof_init(); pp->exposure = post_process_exposure_init(); pp->tone_map = post_process_tone_map_init(); + pp->stage_index = -1; + pp->stage_index_prev = -1; glGenSamplers(2, pp->samplers); glSamplerParameteri(pp->samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -85,7 +89,7 @@ void post_process_apply(post_process_struct* pp, camera* cam, texture* light_pro (mat4*)&mat4_identity, (mat4*)&mat4_identity, (mat4*)&mat4_identity); post_process_get_blur(pp->blur, &pp->render_texture); - post_process_get_exposure(pp->exposure, + post_process_get_exposure(pp->exposure, pp->reset_exposure, pp->blur->tex[4].color_texture->texture, pp->blur->tex[2].color_texture->texture); post_process_apply_tone_map(pp->tone_map, &pp->render_texture, light_proj_tex, 0, &pp->render_texture, &pp->buf_texture, &pp->sss_contour_texture, @@ -287,6 +291,40 @@ void post_process_reset(post_process_struct* pp) { TONE_MAP_YCC_EXPONENT); } +void post_process_update(post_process_struct* pp, camera* cam) { + pp->view_point_prev = pp->view_point; + pp->interest_prev = pp->interest; + camera_get_view_point(cam, &pp->view_point); + camera_get_interest(cam, &pp->interest); + + pp->stage_index_prev = pp->stage_index; + pp->stage_index = stage_index; + + bool reset_exposure = cam->fast_change_hist1 && !cam->fast_change_hist0; + pp->reset_exposure = reset_exposure; + if (reset_exposure) { + float_t view_point_dist; + vec3_distance(pp->view_point, pp->view_point_prev, view_point_dist); + + vec3 dir; + vec3_sub(pp->interest, pp->view_point, dir); + vec3_normalize(dir, dir); + + vec3 dir_prev; + vec3_sub(pp->interest_prev, pp->view_point_prev, dir_prev); + vec3_normalize(dir_prev, dir_prev); + + float_t dir_diff_angle; + vec3_dot(dir, dir_prev, dir_diff_angle); + if (dir_diff_angle < 0.5f) + dir_diff_angle = 0.0f; + if (view_point_dist < dir_diff_angle * 0.4f) + pp->reset_exposure = false; + } + else if (pp->stage_index != pp->stage_index_prev) + pp->reset_exposure = true; +} + void post_process_free(post_process_struct* pp) { post_process_aa_dispose(pp->aa); post_process_blur_dispose(pp->blur); diff --git a/src/CRE/post_process.h b/src/CRE/post_process.h index 16d52b34..e8e676d2 100644 --- a/src/CRE/post_process.h +++ b/src/CRE/post_process.h @@ -49,6 +49,13 @@ typedef struct post_process_struct { shader_glsl alpha_layer_shader; int32_t render_width; int32_t render_height; + vec3 view_point; + vec3 interest; + vec3 view_point_prev; + vec3 interest_prev; + int32_t stage_index; + int32_t stage_index_prev; + bool reset_exposure; int32_t sprite_width; int32_t sprite_height; int32_t screen_x_offset; @@ -67,4 +74,5 @@ extern int32_t post_process_movie_texture_set(post_process_struct* pp, texture* extern void post_process_movie_texture_free(post_process_struct* pp, texture* movie_texture); extern int32_t post_process_render_texture_set(post_process_struct* pp, texture* render_texture, bool task_photo); extern void post_process_render_texture_free(post_process_struct* pp, texture* render_texture, bool task_photo); +extern void post_process_update(post_process_struct* pp, camera* cam); extern void post_process_free(post_process_struct* pp); diff --git a/src/CRE/post_process/exposure.c b/src/CRE/post_process/exposure.c index 4f3c48b2..ce0fab99 100644 --- a/src/CRE/post_process/exposure.c +++ b/src/CRE/post_process/exposure.c @@ -16,14 +16,18 @@ post_process_exposure* post_process_exposure_init() { return exp; } -void post_process_get_exposure(post_process_exposure* exp, GLuint in_tex_0, GLuint in_tex_1) { +void post_process_get_exposure(post_process_exposure* exp, + bool reset_exposure, GLuint in_tex_0, GLuint in_tex_1) { if (!exp) return; uniform_value[U_EXPOSURE] = 1; render_texture_shader_set(&shaders_ft, SHADER_FT_EXPOSURE); - glViewport(exp->exposure_history_counter, 0, 1, 1); // 14 + if (reset_exposure) + glViewport(0, 0, 32, 1); + else + glViewport(exp->exposure_history_counter, 0, 1, 1); render_texture_bind(&exp->exposure_history, 0); gl_state_active_bind_texture_2d(0, in_tex_0); gl_state_active_bind_texture_2d(1, in_tex_1); diff --git a/src/CRE/post_process/exposure.h b/src/CRE/post_process/exposure.h index 1fec9943..b6184d19 100644 --- a/src/CRE/post_process/exposure.h +++ b/src/CRE/post_process/exposure.h @@ -17,6 +17,7 @@ typedef struct post_process_exposure { } post_process_exposure; extern post_process_exposure* post_process_exposure_init(); -extern void post_process_get_exposure(post_process_exposure* exp, GLuint in_tex_0, GLuint in_tex_1); +extern void post_process_get_exposure(post_process_exposure* exp, + bool reset_exposure, GLuint in_tex_0, GLuint in_tex_1); extern void post_process_exposure_init_fbo(post_process_exposure* exp); extern void post_process_exposure_dispose(post_process_exposure* exp); diff --git a/src/CRE/render_context.c b/src/CRE/render_context.c index 5b99791f..49ee12b6 100644 --- a/src/CRE/render_context.c +++ b/src/CRE/render_context.c @@ -33,8 +33,20 @@ static void sss_data_free(sss_data_struct* sss); const texture_pattern_struct texture_pattern_struct_null = { -1, -1 }; +frame_rate_control sys_frame_rate = { 1.0f }; +frame_rate_control diva_pv_frame_rate = { 1.0f }; +frame_rate_control diva_stage_frame_rate = { 1.0f }; + static const GLfloat depth_clear = 1.0f; +inline float_t frame_rate_control_get_delta_frame(frame_rate_control* control) { + return get_delta_frame() * control->frame_speed; +} + +inline void frame_rate_control_set_frame_speed(frame_rate_control* control, float_t value) { + control->frame_speed = value; +} + light_proj* light_proj_init(int32_t width, int32_t height) { light_proj* litproj = force_malloc(sizeof(light_proj)); render_texture_init(&litproj->shadow_texture[0], @@ -570,6 +582,20 @@ void render_context_set_light_param(render_context* rctx, light_param_data* ligh render_context_light_param_data_face_set(rctx, &light_param->face); } +void render_context_unset_light_param(render_context* rctx, light_param_data* light_param) { + if (light_param->light.ready) + render_context_light_param_data_light_set(rctx, &light_param->light); + if (light_param->fog.ready) + render_context_light_param_data_fog_set(rctx, &light_param->fog); + if (light_param->glow.ready) + render_context_light_param_data_glow_set(rctx, &light_param->glow); + if (light_param->ibl.ready) + render_context_light_param_data_ibl_set(rctx, &light_param->ibl); + render_context_light_param_data_wind_set(rctx, &light_param->wind); + if (light_param->face.ready) + render_context_light_param_data_face_set(rctx, &light_param->face); +} + inline void render_context_update(render_context* rctx) { wind_update(rctx->wind); draw_state_stats_update(&rctx->draw_state); diff --git a/src/CRE/render_context.h b/src/CRE/render_context.h index 9c3aeba9..da21d512 100644 --- a/src/CRE/render_context.h +++ b/src/CRE/render_context.h @@ -357,6 +357,10 @@ typedef struct draw_task { draw_task_union data; } draw_task; +typedef struct frame_rate_control { + float_t frame_speed; +} frame_rate_control; + typedef struct light_proj { bool enable; render_texture shadow_texture[2]; @@ -477,14 +481,21 @@ struct shadow { bool field_2F5; }; +extern frame_rate_control sys_frame_rate; +extern frame_rate_control diva_pv_frame_rate; +extern frame_rate_control diva_stage_frame_rate; extern const texture_pattern_struct texture_pattern_struct_null; +extern float_t frame_rate_control_get_delta_frame(frame_rate_control* control); +extern void frame_rate_control_set_frame_speed(frame_rate_control* control, float_t value); + extern light_proj* light_proj_init(int32_t width, int32_t height); extern void light_proj_get_proj_mat(vec3* view_point, vec3* interest, float_t fov, mat4* mat); extern void light_proj_resize(light_proj* litproj, int32_t width, int32_t height); extern bool light_proj_set(light_proj* litproj, render_context* rctx); extern bool light_proj_set_mat(render_context* rctx, bool set_mat); extern void light_proj_free(light_proj* litproj); + extern draw_task* object_data_buffer_add_draw_task(object_data_buffer* buffer, draw_task_type type); extern mat4u* object_data_buffer_add_mat4(object_data_buffer* buffer, int32_t count); extern void object_data_buffer_reset(object_data_buffer* buffer); @@ -514,6 +525,7 @@ extern void object_data_set_texture_specular_offset(object_data* object_data, ve extern void object_data_set_texture_transform(object_data* object_data, int32_t count, texture_transform_struct* value); extern void object_data_set_wet_param(object_data* object_data, float_t value); + extern render_context* render_context_init(); extern void render_context_light_param_data_light_set(render_context* rctx, light_param_light* light); extern void render_context_light_param_data_fog_set(render_context* rctx, light_param_fog* f); @@ -522,6 +534,8 @@ extern void render_context_light_param_data_ibl_set(render_context* rctx, light_ extern void render_context_light_param_data_wind_set(render_context* rctx, light_param_wind* w); extern void render_context_light_param_data_face_set(render_context* rctx, light_param_face* face); extern void render_context_set_light_param(render_context* rctx, light_param_data* light_param); +extern void render_context_unset_light_param(render_context* rctx, light_param_data* light_param); extern void render_context_update(render_context* rctx); extern void render_context_free(render_context* rctx); + extern void shadow_update(shadow* shad, render_context* rctx); \ No newline at end of file diff --git a/src/CRE/rob.c b/src/CRE/rob.c index 25e0f490..d2a5c2e8 100644 --- a/src/CRE/rob.c +++ b/src/CRE/rob.c @@ -389,7 +389,8 @@ static void skin_param_osage_root_free(skin_param_osage_root* root); vector_func(motion_storage) vector_motion_storage motion_storage_data; -rob_chara rob_chara_array[6]; +rob_chara rob_chara_array[ROB_CHARA_COUNT]; +rob_chara_pv_data rob_chara_pv_data_array[ROB_CHARA_COUNT]; extern wind* wind_ptr; static const exp_func_op1 exp_func_op1_array[] = { @@ -1314,7 +1315,7 @@ static void sub_1405F9640(rob_chara_item_equip_object* itm_eq_obj) { i != rob_itm_equip->field_940.end; i++, index++) { /*size_t rob_chr = 0; int32_t child_osg_node = 0; - sub_140489480(itm_eq_obj->obj_info, v3->motion_id, &rob_chr, &child_osg_node); + sub_140489480(itm_eq_obj->obj_info, chr_data->motion_id, &rob_chr, &child_osg_node); if (!rob_chr) break; @@ -1362,6 +1363,76 @@ static void rob_chara_item_equip_calc(rob_chara_item_equip* rob_item_equip) { rob_chara_item_equip_object_calc(&rob_item_equip->item_equip_object[i]); } +static float_t rob_chara_get_trans_scale(rob_chara* rob_chr, int32_t bone, vec3* trans) { + if (bone > 26) + return 0.0f; + *trans = rob_chr->data.field_1E68.field_DF8[bone].trans; + return rob_chr->data.field_1E68.field_DF8[bone].scale; +} + +mat4* rob_chara_bone_data_get_mats_mat(rob_chara_bone_data* rob_bone_data, ssize_t index) { + if (index < vector_length(rob_bone_data->mats)) + return &rob_bone_data->mats.begin[index]; + return 0; +} + +static void sub_140509D30(rob_chara* rob_chr) { + struc_195* v39 = rob_chr->data.field_1E68.field_DF8; + struc_195* v40 = rob_chr->data.field_1E68.field_1230; + struc_195* v41 = rob_chr->data.field_1E68.field_1668; + mat4u* v42 = rob_chr->data.field_1E68.field_78; + mat4u* v43 = rob_chr->data.field_1E68.field_738; + + const struc_218* v3 = rob_chr->chara_init_data->field_828; + const struc_218* v6 = rob_chr->chara_init_data->field_830; + mat4 mat; + for (int32_t i = 0; i < 27; i++) { + mat = *rob_chara_bone_data_get_mats_mat(rob_chr->bone_data, v3->bone_index); + mat4_translate_mult(&mat, v3->bone_offset.x, v3->bone_offset.y, v3->bone_offset.z, &mat); + mat4_to_mat4u(&mat, v42); + + mat = *rob_chara_bone_data_get_mats_mat(rob_chr->bone_data, v6->bone_index); + mat4_translate_mult(&mat, v3->bone_offset.x, v3->bone_offset.y, v3->bone_offset.z, &mat); + mat4_to_mat4u(&mat, v43); + float_t v14 = rob_chr->data.adjust_data.scale; + + vec3 v23; + vec3_mult_scalar(*(vec3*)&v42->row3, v14, v23); + vec3_add(v23, rob_chr->data.adjust_data.trans, v23); + *(vec3*)&v42->row3 = v23; + + vec3 v29; + vec3_mult_scalar(*(vec3*)&v43->row3, v14, v23); + vec3_add(v23, rob_chr->data.adjust_data.trans, v29); + *(vec3*)&v43->row3 = v29; + + float_t v20 = v3->scale * v14; + v39->scale = v20; + v39->field_24 = v20; + v39->prev_trans = v39->trans; + v39->trans = v23; + + float_t v19 = v6->scale * v14; + v40->scale = v19; + v40->field_24 = v19; + v40->prev_trans = v40->trans; + v40->trans = v29; + + v41->scale = v19; + v41->field_24 = v19; + v41->prev_trans = v41->trans; + v41->trans = v29; + + v39++; + v40++; + v41++; + v42++; + v43++; + v3++; + v6++; + } +} + void rob_chara_calc(rob_chara* rob_chr) { if (rob_chara_bone_data_get_frame(rob_chr->bone_data) < 0.0) rob_chara_bone_data_set_frame(rob_chr->bone_data, 0.0); @@ -1371,9 +1442,7 @@ void rob_chara_calc(rob_chara* rob_chr) { if (frame > frame_count) rob_chara_bone_data_set_frame(rob_chr->bone_data, frame_count); - mat4_get_translation(&rob_chr->bone_data->mats.begin[MOTION_BONE_KL_KOSI_ETC_WJ], - &rob_chr->item_equip->position); - //rob_chara_get_trans_scale(rob_chr, 0, &rob_chr->item_equip->position); + rob_chara_get_trans_scale(rob_chr, 0, &rob_chr->item_equip->position); rob_chara_item_equip_calc(rob_chr->item_equip); @@ -1561,6 +1630,28 @@ void rob_chara_reset(rob_chara* rob_chr, bone_database* bone_data, void* data, o }*/ } +static float_t chara_size_table_get_value(uint32_t a1) { + static const float_t chara_size_table[] = { + 1.07f, 1.0f, 0.96f, 0.987f, 1.025f + }; + + if (a1 > 4) + return 1.0f; + else + return chara_size_table[a1]; +} + +static float_t chara_pos_adjust_y_table_get_value(uint32_t a1) { + static const float_t chara_pos_adjust_y_table[] = { + 0.071732f, 0.0f, -0.03859f, 0.0f, 0.0f + }; + + if (a1 > 4) + return 0.0f; + else + return chara_pos_adjust_y_table[a1]; +} + void rob_chara_reset_data(rob_chara* rob_chr, rob_chara_pv_data* pv_data, bone_database* bone_data, motion_database* mot_db) { rob_chara_bone_data_reset(rob_chr->bone_data); @@ -1568,6 +1659,12 @@ void rob_chara_reset_data(rob_chara* rob_chr, rob_chara_pv_data* pv_data, BONE_DATABASE_SKELETON_COMMON, rob_chr->chara_init_data->skeleton_type, bone_data); rob_chara_item_equip_get_parent_bone_nodes(rob_chr->item_equip, rob_chara_bone_data_get_node(rob_chr->bone_data, 0), bone_data); + rob_chara_data* chr_data = &rob_chr->data; + chr_data->field_1D38.field_0 = pv_data->field_14; + chr_data->field_1D38.field_6 = pv_data->field_14; + chr_data->adjust_data.scale = chara_size_table_get_value(rob_chr->pv_data.chara_size_index); + chr_data->adjust_data.height_adjust = rob_chr->pv_data.height_adjust; + chr_data->adjust_data.pos_adjust_y = chara_pos_adjust_y_table_get_value(rob_chr->pv_data.chara_size_index); rob_chara_bone_data_eyes_xrot_adjust(rob_chr->bone_data, chara_some_data_array, &pv_data->eyes_adjust); rob_chara_bone_data_get_ik_scale(rob_chr->bone_data, bone_data); rob_chara_load_default_motion(rob_chr, bone_data, mot_db); @@ -1576,7 +1673,14 @@ void rob_chara_reset_data(rob_chara* rob_chr, rob_chara_pv_data* pv_data, rob_chara_set_draw(rob_chr, ITEM_MAX, true); } -void rob_chara_set(rob_chara* rob_chr, int8_t chara_id, +void rob_chara_set_frame(rob_chara* rob_chr, float_t frame) { + rob_chara_bone_data_set_frame(rob_chr->bone_data, frame); + rob_chara_bone_data_interpolate(rob_chr->bone_data); + rob_chara_bone_data_update(rob_chr->bone_data, 0); + sub_140509D30(rob_chr); +} + +void rob_chara_set_pv_data(rob_chara* rob_chr, int8_t chara_id, chara_index chara_index, uint32_t module_index, rob_chara_pv_data* pv_data) { rob_chr->chara_id = chara_id; rob_chr->chara_index = chara_index; @@ -1585,10 +1689,15 @@ void rob_chara_set(rob_chara* rob_chr, int8_t chara_id, rob_chr->chara_init_data = chara_init_data_get(chara_index); } -void rob_chara_set_frame(rob_chara* rob_chr, float_t frame) { - rob_chara_bone_data_set_frame(rob_chr->bone_data, frame); - rob_chara_bone_data_interpolate(rob_chr->bone_data); - rob_chara_bone_data_update(rob_chr->bone_data, 0); +void rob_chara_set_visibility(rob_chara* rob_chr, bool value) { + rob_chr->data.field_0 &= ~0x01; + rob_chr->data.field_3 &= ~0x01; + rob_chr->data.field_0 |= value & 0x01; + rob_chr->data.field_3 |= value & 0x01; + /*if (rob_chara_check_for_ageageagain_module(rob_chr->chara_index, rob_chr->module_index)) { + sub_140543780(rob_chr->chara_id, 1, value); + sub_140543780(rob_chr->chara_id, 2, value); + }*/ } void rob_chara_free(rob_chara* rob_chr) { @@ -2111,11 +2220,6 @@ static void bone_data_mult_ik(bone_data* a1, int32_t skeleton_select) { rot_sin = -rot_sin; else rot_2nd_sin = -rot_2nd_sin; - - float_t arot_sin = asinf(rot_sin) * RAD_TO_DEG_FLOAT; - float_t arot_cos = acosf(rot_cos) * RAD_TO_DEG_FLOAT; - float_t arot_2nd_sin = asinf(rot_2nd_sin) * RAD_TO_DEG_FLOAT; - float_t arot_2nd_cos = acosf(rot_2nd_cos) * RAD_TO_DEG_FLOAT; } else { rot_sin = 0.0f; @@ -2206,27 +2310,27 @@ static void bone_data_parent_load_bone_database(bone_data_parent* bone, size_t total_bone_count = 0; size_t ik_bone_count = 0; - bone_data* v16 = bone->bones.begin; - for (bone_database_bone* i = bones->begin; i != bones->end; i++, v16++) { - v16->motion_bone_index = (motion_bone_index)(i - bones->begin); - v16->type = i->type; - v16->mirror = i->mirror; - v16->parent = i->parent; - v16->flags = i->flags; + bone_data* bone_node = bone->bones.begin; + for (bone_database_bone* i = bones->begin; i != bones->end; i++, bone_node++) { + bone_node->motion_bone_index = (motion_bone_index)(i - bones->begin); + bone_node->type = i->type; + bone_node->mirror = i->mirror; + bone_node->parent = i->parent; + bone_node->flags = i->flags; if (i->type >= BONE_DATABASE_BONE_POSITION_ROTATION) - v16->key_set_count = 6; + bone_node->key_set_count = 6; else - v16->key_set_count = 3; - v16->base_translation[0] = *common_translation++; - v16->base_translation[1] = *translation++; - v16->node = &rob_bone_data->nodes.begin[total_bone_count]; - v16->has_parent = i->has_parent; + bone_node->key_set_count = 3; + bone_node->base_translation[0] = *common_translation++; + bone_node->base_translation[1] = *translation++; + bone_node->node = &rob_bone_data->nodes.begin[total_bone_count]; + bone_node->has_parent = i->has_parent; if (i->has_parent) - v16->parent_mat = &rob_bone_data->mats.begin[i->parent]; + bone_node->parent_mat = &rob_bone_data->mats.begin[i->parent]; else - v16->parent_mat = 0; + bone_node->parent_mat = 0; - v16->pole_target_mat = 0; + bone_node->pole_target_mat = 0; switch (i->type) { case BONE_DATABASE_BONE_ROTATION: case BONE_DATABASE_BONE_TYPE_1: @@ -2240,8 +2344,8 @@ static void bone_data_parent_load_bone_database(bone_data_parent* bone, total_bone_count++; break; case BONE_DATABASE_BONE_HEAD_IK_ROTATION: - v16->ik_segment_length[0] = (common_translation++)->x; - v16->ik_segment_length[1] = (translation++)->x; + bone_node->ik_segment_length[0] = (common_translation++)->x; + bone_node->ik_segment_length[1] = (translation++)->x; chain_pos += 2; ik_bone_count++; @@ -2249,15 +2353,15 @@ static void bone_data_parent_load_bone_database(bone_data_parent* bone, break; case BONE_DATABASE_BONE_ARM_IK_ROTATION: case BONE_DATABASE_BONE_LEGS_IK_ROTATION: - v16->ik_segment_length[0] = (common_translation++)->x; - v16->ik_segment_length[1] = (translation++)->x; - v16->ik_2nd_segment_length[0] = (common_translation++)->x; - v16->ik_2nd_segment_length[1] = (translation++)->x; + bone_node->ik_segment_length[0] = (common_translation++)->x; + bone_node->ik_segment_length[1] = (translation++)->x; + bone_node->ik_2nd_segment_length[0] = (common_translation++)->x; + bone_node->ik_2nd_segment_length[1] = (translation++)->x; mat4* pole_target = 0; if (i->pole_target) pole_target = &rob_bone_data->mats.begin[i->pole_target]; - v16->pole_target_mat = pole_target; + bone_node->pole_target_mat = pole_target; chain_pos += 3; ik_bone_count++; @@ -2295,10 +2399,10 @@ static void bone_data_parent_load_bone_indices_from_mot(bone_data_parent* a1, } *vector_uint16_t_reserve_back(bone_indices) = (uint16_t)bone_index; - bone_data* v15 = &a1->bones.begin[bone_index]; - v15->key_set_offset = (int32_t)key_set_offset; - v15->frame = -1.0f; - if (v15->type >= BONE_DATABASE_BONE_POSITION_ROTATION) + bone_data* bone_node = &a1->bones.begin[bone_index]; + bone_node->key_set_offset = (int32_t)key_set_offset; + bone_node->frame = -1.0f; + if (bone_node->type >= BONE_DATABASE_BONE_POSITION_ROTATION) key_set_offset+= 6; else key_set_offset+= 3; @@ -4242,11 +4346,11 @@ static void sub_14053CE30(rob_osage_node_data_normal_ref* normal_ref, mat4* a2) } } -static void sub_14047E1C0(rob_osage* a1, vec3* a2) { - for (rob_osage_node* i = a1->nodes.begin + 1; i != a1->nodes.end; i++) +static void sub_14047E1C0(rob_osage* rob_osg, vec3* scale) { + for (rob_osage_node* i = rob_osg->nodes.begin + 1; i != rob_osg->nodes.end; i++) if (i->data_ptr->normal_ref.field_0) { sub_14053CE30(&i->data_ptr->normal_ref, i->bone_node_mat); - mat4_scale_rot(i->bone_node_mat, a2->x, a2->y, a2->z, i->bone_node_mat); + mat4_scale_rot(i->bone_node_mat, scale->x, scale->y, scale->z, i->bone_node_mat); } } @@ -4445,10 +4549,10 @@ static void ex_osage_block_field_18(ex_osage_block* osg, int32_t a2, bool a3) { } static void ex_osage_block_field_28(ex_osage_block* osg) { - rob_chara_item_equip* rob_itm_equip = osg->base.item_equip_object->item_equip; + /*rob_chara_item_equip* rob_itm_equip = osg->base.item_equip_object->item_equip; bone_node* parent_node = osg->base.parent_bone_node; vec3 parent_scale = parent_node->exp_data.parent_scale; - //sub_14047E240(&osg->rob, parent_node->ex_data_mat, &parent_scale, &rob_itm_equip->field_940); + //sub_14047E240(&osg->rob, parent_node->ex_data_mat, &parent_scale, &rob_itm_equip->field_940);*/ } static void ex_osage_block_field_40(ex_osage_block* osg) { @@ -4588,7 +4692,7 @@ static float_t exp_abs(float_t v1) { } static float_t exp_acos(float_t v1) { - return acosf(v1); + return acosf(v1) * RAD_TO_DEG_FLOAT; } static float_t exp_add(float_t v1, float_t v2) { @@ -4600,11 +4704,11 @@ static float_t exp_and(float_t v1, float_t v2) { } static float_t exp_asin(float_t v1) { - return asinf(v1); + return asinf(v1) * RAD_TO_DEG_FLOAT; } static float_t exp_atan(float_t v1) { - return atanf(v1); + return atanf(v1) * RAD_TO_DEG_FLOAT; } static float_t exp_av(float_t v1) { @@ -4620,7 +4724,7 @@ static float_t exp_cond(float_t v1, float_t v2, float_t v3) { } static float_t exp_cos(float_t v1) { - return cosf(v1); + return cosf(fmodf(v1, 360.0f) * DEG_TO_RAD_FLOAT); } static float_t exp_div(float_t v1, float_t v2) { @@ -4734,7 +4838,7 @@ static float_t exp_round(float_t v1) { } static float_t exp_sin(float_t v1) { - return sinf(v1); + return sinf(fmodf(v1, 360.0f) * DEG_TO_RAD_FLOAT); } static float_t exp_sqrt(float_t v1) { @@ -4746,7 +4850,7 @@ static float_t exp_sub(float_t v1, float_t v2) { } static float_t exp_tan(float_t v1) { - return tanf(v1); + return tanf(fmodf(v1, 360.0f) * DEG_TO_RAD_FLOAT); } static const float_t get_osage_gravity_const() { @@ -6474,7 +6578,7 @@ static void rob_chara_item_sub_data_reload_items(rob_chara_item_sub_data* itm_su //sub_data.outer = 181; //sub_data.kata = 481; //sub_data.head = 981; - rob_chara_reload_items(&rob_chara_array[0], + rob_chara_reload_items(&rob_chara_array[chara_id], &sub_data, bone_data, data, obj_db); /*rob_chara_item_equip* rob_item_equip = rob_chara_array[chara_id].item_equip; @@ -6643,6 +6747,7 @@ static void rob_chara_load_default_motion_sub(rob_chara* rob_chr, int32_t skelet //sub_14041D310(rob_chr->bone_data); rob_chara_bone_data_interpolate(rob_chr->bone_data); rob_chara_bone_data_update(rob_chr->bone_data, 0); + sub_140509D30(rob_chr); //sub_140419820(rob_chr->bone_data, skeleton_select); } @@ -7315,7 +7420,7 @@ static void skin_param_osage_root_free(skin_param_osage_root* root) { } void rob_chara_array_init() { - for (int32_t i = 0; i < 6; i++) + for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) rob_chara_init(&rob_chara_array[i]); } @@ -7325,38 +7430,66 @@ rob_chara* rob_chara_array_get(int32_t chara_id) { return 0; } +int32_t rob_chara_array_set_pv_data(chara_index chara_index, + rob_chara_pv_data* pv_data, uint32_t module_index, bool a4) { + if (pv_data->field_0 > 3) + return -1; + + rob_chara_pv_data* v9 = rob_chara_pv_data_array; + int32_t chara_id = 0; + while (v9->field_0 != -1) { + chara_id++; + v9++; + if (chara_id >= ROB_CHARA_COUNT) + return -1; + } + + if (a4 && module_index > 498) + module_index = 0; + rob_chara_pv_data_array[chara_id] = *pv_data; + rob_chara_set_pv_data(&rob_chara_array[chara_id], chara_id, chara_index, module_index, pv_data); + return chara_id; +} + void rob_chara_array_free() { - for (int32_t i = 0; i < 6; i++) + for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) rob_chara_free(&rob_chara_array[i]); } void rob_chara_pv_data_init(rob_chara_pv_data* pv_data) { memset(pv_data, 0, sizeof(rob_chara_pv_data)); - pv_data->index = 2; + pv_data->field_0 = 2; pv_data->field_4 = 1; pv_data->field_5 = 0; pv_data->field_6 = 0; pv_data->field_14 = 0x00; pv_data->field_16 = 0xC9; - pv_data->field_74 = -1; - pv_data->field_78 = -1; - pv_data->field_7C = -1; - pv_data->field_80 = -1; - pv_data->field_84 = -1; - pv_data->field_88 = -1; - pv_data->field_8C = -1; - pv_data->field_90 = -1; - pv_data->field_94 = -1; - pv_data->field_98 = -1; - pv_data->field_9C = 1; + pv_data->field_74[0] = -1; + pv_data->field_74[1] = -1; + pv_data->field_74[2] = -1; + pv_data->field_74[3] = -1; + pv_data->field_74[4] = -1; + pv_data->field_74[5] = -1; + pv_data->field_74[6] = -1; + pv_data->field_74[7] = -1; + pv_data->field_74[8] = -1; + pv_data->field_74[9] = -1; + pv_data->chara_size_index = 1; + pv_data->height_adjust = false; pv_data->eyes_adjust.base_adjust = EYES_BASE_ADJUST_DIRECTION; pv_data->eyes_adjust.neg = -1.0f; pv_data->eyes_adjust.pos = -1.0f; } inline bool rob_chara_pv_data_array_check_chara_id(int32_t chara_id) { - //return rob_chara_pv_data_array[chara_id].index != -1; - return rob_chara_array[chara_id].chara_id != -1; + return rob_chara_pv_data_array[chara_id].field_0 != -1; +} + +void rob_chara_pv_data_array_init() { + for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) + rob_chara_pv_data_init(&rob_chara_pv_data_array[i]); + for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) + rob_chara_pv_data_array[i].field_0 = -1; } inline void motion_storage_init() { diff --git a/src/CRE/rob.h b/src/CRE/rob.h index 8b5f1f2f..192e9560 100644 --- a/src/CRE/rob.h +++ b/src/CRE/rob.h @@ -563,21 +563,21 @@ struct rob_chara_bone_data { }; typedef struct struc_242 { - int32_t field_0; - int32_t field_4; - int32_t field_8; - int32_t field_C; - int32_t field_10; - int32_t field_14; - int32_t field_18; + float_t field_0; + float_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; int32_t field_1C; - int32_t field_20; - int32_t field_24; - int32_t field_28; + float_t field_20; + float_t field_24; + float_t field_28; } struc_242; typedef struct rob_chara_pv_data { - int32_t index; + int32_t field_0; bool field_4; bool field_5; bool field_6; @@ -587,19 +587,10 @@ typedef struct rob_chara_pv_data { struc_242 field_18; struc_242 field_44; int32_t field_70; - int32_t field_74; - int32_t field_78; - int32_t field_7C; - int32_t field_80; - int32_t field_84; - int32_t field_88; - int32_t field_8C; - int32_t field_90; - int32_t field_94; - int32_t field_98; - int32_t field_9C; - bool field_A0; - int32_t shadow_type[4]; + int32_t field_74[10]; + int32_t chara_size_index; + bool height_adjust; + int32_t item_no[4]; eyes_adjust eyes_adjust; } rob_chara_pv_data; @@ -1794,25 +1785,26 @@ typedef struct struc_399 { mat4u field_6C; } struc_399; -typedef struct struc_220 { - float_t size; +typedef struct rob_chara_adjust_data { + float_t scale; bool height_adjust; - float_t field_8; + float_t pos_adjust_y; vec3 pos_adjust; - float_t field_18; - float_t field_1C; - float_t field_20; - int8_t field_24; - int8_t field_25; - int8_t field_26; - int8_t field_27; + vec3 offset; + bool offset_x; + bool offset_y; + bool offset_z; + bool get_global_trans; vec3 trans; mat4u mat; - vec4u field_74; -} struc_220; + float_t left_hand_scale; + float_t right_hand_scale; + float_t left_hand_scale_default; + float_t right_hand_scale_default; +} rob_chara_adjust_data; typedef struct struc_195 { - vec3 rotation; + vec3 prev_trans; vec3 trans; float_t scale; float_t field_1C; @@ -1966,7 +1958,7 @@ typedef struct struc_209 { } struc_209; typedef struct rob_chara_data { - bool field_0; + uint8_t field_0; uint8_t field_1; uint8_t field_2; uint8_t field_3; @@ -1976,7 +1968,7 @@ typedef struct rob_chara_data { struc_268 field_290; struc_223 field_1588; struc_399 field_1D38; - struc_220 field_1DE4; + rob_chara_adjust_data adjust_data; struc_209 field_1E68; float_t field_3D90; int32_t field_3D94; @@ -2021,7 +2013,10 @@ typedef struct skeleton_rotation_offset { vec3 rotation; } skeleton_rotation_offset; +#define ROB_CHARA_COUNT 6 + extern rob_chara rob_chara_array[]; +extern rob_chara_pv_data rob_chara_pv_data_array[]; extern chara_init_data* chara_init_data_get(chara_index chara_index); @@ -2029,6 +2024,7 @@ extern void motion_set_load_motion(uint32_t set, string* motion_name, motion_dat extern void motion_set_unload(uint32_t set); extern void rob_chara_init(rob_chara* rob_chr); +extern mat4* rob_chara_bone_data_get_mats_mat(rob_chara_bone_data* rob_bone_data, ssize_t index); extern void rob_chara_calc(rob_chara* rob_chr); extern void rob_chara_draw(rob_chara* rob_chr, render_context* rctx); extern mat4* rob_chara_get_bone_data_mat(rob_chara* chara, size_t index); @@ -2042,19 +2038,23 @@ extern void rob_chara_reset(rob_chara* rob_chr, bone_database* bone_data, void* data, object_database* obj_db); extern void rob_chara_reset_data(rob_chara* rob_chr, rob_chara_pv_data* pv_data, bone_database* bone_data, motion_database* mot_db); -extern void rob_chara_set(rob_chara* rob_chr, int8_t chara_id, - chara_index chara_index, uint32_t module_index, rob_chara_pv_data* pv_data); extern void rob_chara_set_frame(rob_chara* rob_chr, float_t frame); +extern void rob_chara_set_pv_data(rob_chara* rob_chr, int8_t chara_id, + chara_index chara_index, uint32_t module_index, rob_chara_pv_data* pv_data); +extern void rob_chara_set_visibility(rob_chara* rob_chr, bool value); extern void rob_chara_free(rob_chara* rob_chr); extern void rob_chara_array_init(); extern rob_chara* rob_chara_array_get(int32_t chara_id); +extern int32_t rob_chara_array_set_pv_data(chara_index chara_index, + rob_chara_pv_data* pv_data, uint32_t module_index, bool a4); extern void rob_chara_array_free(); extern void rob_chara_pv_data_init(rob_chara_pv_data* pv_data); - extern bool rob_chara_pv_data_array_check_chara_id(int32_t chara_id); +extern void rob_chara_pv_data_array_init(); + extern void motion_storage_init(); extern void motion_storage_append_mot_set(uint32_t set_id); extern void motion_storage_insert_motion_set(mot_set* set, uint32_t set_id); diff --git a/src/CRE/stage.c b/src/CRE/stage.c index 41c3e7b5..76041f46 100644 --- a/src/CRE/stage.c +++ b/src/CRE/stage.c @@ -111,7 +111,15 @@ void stage_load(stage* s, data_struct* data, auth_3d_database* auth_3d_db, objec string_free(&auth_3d_file); continue; } - + + char* l_str = string_data(&ff->name); + char* t = strrchr(l_str, '.'); + size_t l_len = ff->name.length; + if (t) + l_len = t - l_str; + + uint32_t h = hash_murmurhash(l_str, l_len, 0, false, false); + a3da a3da_file; a3da_init(&a3da_file); a3da_mread(&a3da_file, ff->data, ff->size); @@ -120,6 +128,7 @@ void stage_load(stage* s, data_struct* data, auth_3d_database* auth_3d_db, objec string_free(&auth_3d_file); continue; } + a3da_file.hash = h; int32_t id = auth_3d_data_load_uid(uids[*j].org_uid, auth_3d_db); auth_3d* auth = auth_3d_data_get_auth_3d(id); @@ -172,11 +181,14 @@ void stage_load(stage* s, data_struct* data, auth_3d_database* auth_3d_db, objec texture_storage_get_texture(movie_texture)); } +extern int32_t stage_index; + void stage_set(stage* s, render_context* rctx) { if (!s || !rctx || s == rctx->stage) return; rctx->stage = s; + stage_index = (uint32_t)(s->modern ? s->stage_modern->id : s->stage->id); render_context_set_light_param(rctx, light_param_storage_get_light_param_data(s->light_param_name)); } @@ -191,7 +203,7 @@ void stage_update(stage* s, render_context* rctx) { for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) { auth_3d* auth = auth_3d_data_get_auth_3d(*i); if (auth) - auth_3d_get_value(auth, (mat4*)&mat4_identity, get_delta_frame()); + auth_3d_time_step(auth, (mat4*)&mat4_identity); } } @@ -225,7 +237,7 @@ void stage_update_modern(stage* s, render_context* rctx) { for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) { auth_3d* auth = auth_3d_data_get_auth_3d(*i); if (auth) - auth_3d_get_value(auth, (mat4*)&mat4_identity, get_delta_frame()); + auth_3d_time_step(auth, (mat4*)&mat4_identity); } } diff --git a/src/CRE/static_var.c b/src/CRE/static_var.c index fe059d0a..82341c45 100644 --- a/src/CRE/static_var.c +++ b/src/CRE/static_var.c @@ -18,7 +18,7 @@ int32_t sv_anisotropy = 1; size_t frame_counter = 0; -bool select_frame_speed = true; +bool select_frame_speed = false; float_t frame_speed = 1.0f; float_t target_fps = 60.0f; float_t current_fps = 60.0f; diff --git a/src/DivaGL/bone_data.c b/src/DivaGL/bone_data.c index f5d6c1bd..d98c14a4 100644 --- a/src/DivaGL/bone_data.c +++ b/src/DivaGL/bone_data.c @@ -2080,7 +2080,7 @@ static void sub_140539750(struc_223* a1) { static void sub_140505EA0(rob_chara_data* a1) { void(*sub_140506A20)(struc_399 * a1) = (void*)0x0000000140506A20; - void(*sub_140506AE0)(struc_220 * a1) = (void*)0x0000000140506AE0; + void(*sub_140506AE0)(rob_chara_adjust_data * a1) = (void*)0x0000000140506AE0; void(*sub_140505FB0)(struc_209 * a1) = (void*)0x0000000140505FB0; a1->field_0 = 0; @@ -2089,7 +2089,7 @@ static void sub_140505EA0(rob_chara_data* a1) { sub_140506440(&a1->field_290); sub_140539750(&a1->field_1588); sub_140506A20(&a1->field_1D38); - sub_140506AE0(&a1->field_1DE4); + sub_140506AE0(&a1->adjust_data); sub_140505FB0(&a1->field_1E68); a1->field_3D90 = 0.0f; a1->field_3D94 = 0; @@ -3470,14 +3470,14 @@ static float_t chara_size_table_get_value(uint32_t a1) { } static float_t chara_pos_adjust_y_table_get_value(uint32_t a1) { - static const float_t flt_1411ADAD0[] = { + static const float_t chara_pos_adjust_y_table[] = { 0.071732f, 0.0f, -0.03859f, 0.0f, 0.0f }; if (a1 > 4) return 0.0f; else - return flt_1411ADAD0[a1]; + return chara_pos_adjust_y_table[a1]; } static void sub_14041C5C0(rob_chara_bone_data* a1, struc_243* a2) { @@ -3637,9 +3637,9 @@ void rob_chara_reset_data(rob_chara* a1, rob_chara_pv_data* a2) { v3->field_1D38.field_18 = v8; v3->field_1D38.field_24 = v8; v3->field_1D38.field_48 = v8; - v3->field_1DE4.size = chara_size_table_get_value(a1->pv_data.field_9C); - v3->field_1DE4.height_adjust = a1->pv_data.height_adjust; - v3->field_1DE4.field_8 = chara_pos_adjust_y_table_get_value(a1->pv_data.field_9C); + v3->adjust_data.scale = chara_size_table_get_value(a1->pv_data.chara_size_index); + v3->adjust_data.height_adjust = a1->pv_data.height_adjust; + v3->adjust_data.pos_adjust_y = chara_pos_adjust_y_table_get_value(a1->pv_data.chara_size_index); v3->field_8.field_1A8 = a1->chara_init_data->field_838[v3->field_8.field_1A4]; sub_14041C5C0(a1->bone_data, sub_140510550(a1->chara_index)); rob_chara_bone_data_eyes_xrot_adjust(a1->bone_data, diff --git a/src/DivaGL/bone_data.h b/src/DivaGL/bone_data.h index 4a55f82c..d84353e6 100644 --- a/src/DivaGL/bone_data.h +++ b/src/DivaGL/bone_data.h @@ -1429,22 +1429,23 @@ typedef struct struc_399 { mat4u field_6C; } struc_399; -typedef struct struc_220 { - float_t size; +typedef struct rob_chara_adjust_data { + float_t scale; bool height_adjust; - float_t field_8; + float_t pos_adjust_y; vec3 pos_adjust; - float_t field_18; - float_t field_1C; - float_t field_20; - uint8_t field_24; - uint8_t field_25; - uint8_t field_26; - uint8_t field_27; + vec3 offset; + bool offset_x; + bool offset_y; + bool offset_z; + bool get_global_trans; vec3 trans; mat4u mat; - vec4u field_74; -} struc_220; + float_t left_hand_scale; + float_t right_hand_scale; + float_t left_hand_scale_default; + float_t right_hand_scale_default; +} rob_chara_adjust_data; typedef struct struc_195 { vec3 rotation; @@ -1597,7 +1598,7 @@ typedef struct struc_209 { } struc_209; typedef struct rob_chara_data { - bool field_0; + uint8_t field_0; uint8_t field_1; uint8_t field_2; uint8_t field_3; @@ -1607,7 +1608,7 @@ typedef struct rob_chara_data { struc_268 field_290; struc_223 field_1588; struc_399 field_1D38; - struc_220 field_1DE4; + rob_chara_adjust_data adjust_data; struc_209 field_1E68; float_t field_3D90; int32_t field_3D94; @@ -1674,9 +1675,9 @@ typedef struct rob_chara_pv_data { int32_t field_90; int32_t field_94; int32_t field_98; - int32_t field_9C; + int32_t chara_size_index; bool height_adjust; - int32_t field_A4[4]; + int32_t item_no[4]; eyes_adjust eyes_adjust; } rob_chara_pv_data; @@ -3729,7 +3730,7 @@ extern void bone_data_mult_2(rob_chara_bone_data* a1, mat4* a2); extern void rob_chara_bone_data_motion_load(rob_chara_bone_data* a1, int32_t motion_id, int32_t a3); extern void rob_chara_bone_data_interpolate(rob_chara_bone_data* a1); extern void rob_chara_bone_data_update(rob_chara_bone_data* a1, mat4* a2); -extern void rob_chara_reset(rob_chara* a1, rob_chara_pv_data* a2); +extern void rob_chara_reset_data(rob_chara* a1, rob_chara_pv_data* a2); extern void ex_node_block_field_10(ex_node_block* node); diff --git a/src/DivaGL/inject.c b/src/DivaGL/inject.c index bacdae36..49d422ee 100644 --- a/src/DivaGL/inject.c +++ b/src/DivaGL/inject.c @@ -67,7 +67,7 @@ static patch_struct patch_data[] = { { (void*)0x00000001405E4FC0, (uint64_t)&aft_shader_load_all_shaders, }, { (void*)0x00000001405E4B50, (uint64_t)&aft_shader_bind, }, { (void*)0x00000001401D3860, (uint64_t)&printf_proxy, }, - //{ (void*)0x0000000140507210, (uint64_t)&rob_chara_data_reset, }, + //{ (void*)0x0000000140507210, (uint64_t)&rob_chara_reset_data, }, //{ (void*)0x00000001401EBD30, (uint64_t)&bone_data_mult_ik, }, //{ (void*)0x00000001401EB6D0, (uint64_t)&bone_data_mult_1, }, //{ (void*)0x000000014041DA50, (uint64_t)&bone_data_mult_2, }, diff --git a/src/KKdLib/a3da.c b/src/KKdLib/a3da.c index ce7adb72..4296f4f1 100644 --- a/src/KKdLib/a3da.c +++ b/src/KKdLib/a3da.c @@ -203,6 +203,7 @@ bool a3da_load_file(void* data, char* path, char* file, uint32_t hash) { a3da* a = data; a3da_read(a, string_data(&s)); + a->hash = hash; string_free(&s); return a->ready; diff --git a/src/KKdLib/a3da.h b/src/KKdLib/a3da.h index b6b66730..5b0a630c 100644 --- a/src/KKdLib/a3da.h +++ b/src/KKdLib/a3da.h @@ -423,6 +423,8 @@ typedef struct a3da { bool compressed; a3da_format format; + uint32_t hash; + a3da_compress_f16 _compress_f16; string _file_name; string _property_version; diff --git a/src/KKdLib/database/object.c b/src/KKdLib/database/object.c index 00158266..8daa4f69 100644 --- a/src/KKdLib/database/object.c +++ b/src/KKdLib/database/object.c @@ -8,6 +8,7 @@ #include "../io/path.h" #include "../io/stream.h" #include "../hash.h" +#include "../sort.h" #include "../str_utils.h" vector_func(object_info) @@ -797,19 +798,8 @@ static void object_database_modern_write_inner(object_database* obj_db, stream* object_database_strings_push_back_check(&strings, string_data(&j->name)); } - for (string* i = strings.begin; i != &strings.end[-1]; i++) { - char* i_str = string_data(i); - for (string* j = i + 1; j != strings.end; j++) - if (str_utils_compare(i_str, string_data(j)) > 0) { - string temp = *i; - *i = *j; - *j = temp; - i_str = string_data(i); - } - } - + quicksort_string(strings.begin, vector_length(strings)); vector_ssize_t_reserve(&string_offsets, vector_length(strings)); - for (string* i = strings.begin; i != strings.end; i++) { ssize_t off = io_get_position(&s_mosi); io_write_string_null_terminated(&s_mosi, i); diff --git a/src/KKdLib/database/stage.c b/src/KKdLib/database/stage.c index e944336c..3c61ee8d 100644 --- a/src/KKdLib/database/stage.c +++ b/src/KKdLib/database/stage.c @@ -328,6 +328,7 @@ static void stage_database_classic_read_inner(stage_database* stage_data, stream for (int32_t i = 0; i < count; i++) { stage_info* stage = &stage_data->stage.begin[i]; + stage->id = i; io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &stage->name); io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &stage->auth_3d_name); stage->object_set_id = io_read_uint32_t(s); diff --git a/src/KKdLib/database/stage.h b/src/KKdLib/database/stage.h index 4578c2d9..080f24e1 100644 --- a/src/KKdLib/database/stage.h +++ b/src/KKdLib/database/stage.h @@ -53,6 +53,7 @@ typedef struct stage_effects { } stage_effects; typedef struct stage_info { + int32_t id; string name; string auth_3d_name; uint32_t object_set_id; diff --git a/src/KKdLib/database/texture.c b/src/KKdLib/database/texture.c index ace87a1d..3ea7de73 100644 --- a/src/KKdLib/database/texture.c +++ b/src/KKdLib/database/texture.c @@ -8,6 +8,7 @@ #include "../io/path.h" #include "../io/stream.h" #include "../hash.h" +#include "../sort.h" #include "../str_utils.h" vector_func(texture_info) @@ -435,19 +436,8 @@ static void texture_database_modern_write_inner(texture_database* tex_db, stream for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) texture_database_strings_push_back_check(&strings, string_data(&i->name)); - for (string* i = strings.begin; i != &strings.end[-1]; i++) { - char* i_str = string_data(i); - for (string* j = i + 1; j != strings.end; j++) - if (str_utils_compare(i_str, string_data(j)) > 0) { - string temp = *i; - *i = *j; - *j = temp; - i_str = string_data(i); - } - } - + quicksort_string(strings.begin, vector_length(strings)); vector_ssize_t_reserve(&string_offsets, vector_length(strings)); - for (string* i = strings.begin; i != strings.end; i++) { *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_mtxi); io_write_string_null_terminated(&s_mtxi, i); diff --git a/src/KKdLib/dsc.c b/src/KKdLib/dsc.c index dbc773ec..96aa46cd 100644 --- a/src/KKdLib/dsc.c +++ b/src/KKdLib/dsc.c @@ -5,6 +5,7 @@ #include "dsc.h" #include "f2/struct.h" +#include "sort.h" #include "str_utils.h" vector_func(dsc_data) @@ -857,6 +858,167 @@ const int32_t dsc_mgf_func_count = DSC_MGF_FUNC_COUNT; const int32_t dsc_x_func_count = DSC_X_FUNC_COUNT; const int32_t dsc_vrfl_func_count = DSC_VRFL_FUNC_COUNT; +inline int32_t dsc_ac101_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC101_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac101_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ac110_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC110_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac110_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ac120_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC120_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac120_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ac200_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC200_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac200_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ac210_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC210_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac210_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ac500_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC500_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac500_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ac510_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AC510_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ac510_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_aft101_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AFT101_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_aft101_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_aft200_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AFT200_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_aft200_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_aft300_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AFT300_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_aft300_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_aft310_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AFT310_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_aft310_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_aft410_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AFT410_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_aft410_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_aft701_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_AFT701_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_aft701_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_ft_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_FT_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_ft_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_psp_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_PSP_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_psp_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_2nd_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_2ND_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_2nd_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_dt_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_DT_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_dt_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_dt2_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_DT2_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_dt2_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_f_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_F_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_f_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_f2_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_F2_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_f2_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_mgf_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_MGF_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_mgf_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_x_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_X_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_x_get_func_name(i))) + return i; + return -1; +} + +inline int32_t dsc_vrfl_get_func_id(const char* name) { + for (int32_t i = 0; i < DSC_VRFL_FUNC_COUNT; i++) + if (!str_utils_compare((char*)name, (char*)dsc_vrfl_get_func_name(i))) + return i; + return -1; +} + inline int32_t dsc_ac101_get_func_length(int32_t id) { return id > -1 && id < DSC_AC101_FUNC_COUNT ? dsc_ac101_func[id].length : -1; } @@ -946,7 +1108,7 @@ inline int32_t dsc_x_get_func_length(int32_t id) { } inline int32_t dsc_vrfl_get_func_length(int32_t id) { - return id > -1 && id < DSC_VRFL_FUNC_COUNT ? dsc_x_func[id].length : -1; + return id > -1 && id < DSC_VRFL_FUNC_COUNT ? dsc_vrfl_func[id].length : -1; } inline int32_t dsc_ac200_get_func_length_old(int32_t id) { @@ -1090,7 +1252,7 @@ inline const char* dsc_x_get_func_name(int32_t id) { } inline const char* dsc_vrfl_get_func_name(int32_t id) { - return id > -1 && id < DSC_VRFL_FUNC_COUNT ? dsc_x_func[id].name : 0; + return id > -1 && id < DSC_VRFL_FUNC_COUNT ? dsc_vrfl_func[id].name : 0; } const int32_t dsc_func_count_array[] = { @@ -1119,6 +1281,32 @@ const int32_t dsc_func_count_array[] = { [DSC_VRFL] = DSC_VRFL_FUNC_COUNT, }; +const dsc_get_func_id dsc_get_func_id_array[] = { + [DSC_AC101] = dsc_ac101_get_func_id, + [DSC_AC110] = dsc_ac110_get_func_id, + [DSC_AC120] = dsc_ac120_get_func_id, + [DSC_AC200] = dsc_ac200_get_func_id, + [DSC_AC210] = dsc_ac210_get_func_id, + [DSC_AC500] = dsc_ac500_get_func_id, + [DSC_AC510] = dsc_ac510_get_func_id, + [DSC_AFT101] = dsc_aft101_get_func_id, + [DSC_AFT200] = dsc_aft200_get_func_id, + [DSC_AFT300] = dsc_aft300_get_func_id, + [DSC_AFT310] = dsc_aft310_get_func_id, + [DSC_AFT410] = dsc_aft410_get_func_id, + [DSC_AFT701] = dsc_aft701_get_func_id, + [DSC_FT] = dsc_ft_get_func_id, + [DSC_PSP] = dsc_psp_get_func_id, + [DSC_2ND] = dsc_2nd_get_func_id, + [DSC_DT] = dsc_dt_get_func_id, + [DSC_DT2] = dsc_dt2_get_func_id, + [DSC_F] = dsc_f_get_func_id, + [DSC_F2] = dsc_f2_get_func_id, + [DSC_MGF] = dsc_mgf_get_func_id, + [DSC_X] = dsc_x_get_func_id, + [DSC_VRFL] = dsc_vrfl_get_func_id, +}; + const dsc_get_func_length dsc_get_func_length_array[] = { [DSC_AC101] = dsc_ac101_get_func_length, [DSC_AC110] = dsc_ac110_get_func_length, @@ -1197,6 +1385,17 @@ const dsc_get_func_name dsc_get_func_name_array[] = { [DSC_VRFL] = dsc_vrfl_get_func_name, }; +typedef struct dsc_data_time { + int32_t time; + int32_t pv_branch_mode; + const char* name; + int32_t func; + uint32_t data_offset; +} dsc_data_time; + +vector(dsc_data_time) +vector_func(dsc_data_time) + static void dsc_convert_from_ac100_cloth_wet(dsc_replace* dr, dsc_replace_data* drd, uint32_t* data); static void dsc_convert_from_ac100_edit_face(dsc_replace* dr, dsc_replace_data* drd, uint32_t* data); static void dsc_convert_from_ac100_edit_motion(dsc_replace* dr, dsc_replace_data* drd, uint32_t* data); @@ -1596,15 +1795,208 @@ void dsc_data_buffer_rebuild(dsc* d) { uint32_t* func_data = dsc_data_get_func_data(d, i); i->data_offset = (uint32_t)vector_length(data_buffer); - for (int32_t j = get_func_length(i->func); j; j--) - vector_uint32_t_push_back(&data_buffer, func_data++); + int32_t func_length = get_func_length(i->func); + memmove(vector_uint32_t_reserve_back_range(&data_buffer, func_length), + func_data, sizeof(uint32_t) * func_length); + func_data += func_length; } vector_uint32_t_free(&d->data_buffer, 0); d->data_buffer = data_buffer; } -inline void* dsc_data_get_func_data(dsc* d, dsc_data* data) { - return d->data_buffer.begin + data->data_offset; +inline uint32_t* dsc_data_get_func_data(dsc* d, dsc_data* data) { + return (uint32_t*)(d->data_buffer.begin + data->data_offset); +} + +static size_t dsc_data_time_radix_index_func_pv_branch_mode(dsc_data_time* data, size_t index); +static size_t dsc_data_time_radix_index_func_time(dsc_data_time* data, size_t index); + +static size_t dsc_data_time_radix_index_func_pv_branch_mode(dsc_data_time* data, size_t index) { + return (size_t)(ssize_t)data[index].pv_branch_mode; +} + +static size_t dsc_data_time_radix_index_func_time(dsc_data_time* data, size_t index) { + return (size_t)(ssize_t)data[index].time; +} + +void dsc_merge(dsc* d, int32_t count, ...) { + if (!d) + return; + + dsc_init(d); + + va_list args; + va_start(args, count); + dsc* s0 = va_arg(args, dsc*); + if (!s0) { + va_end(args); + return; + } + + for (int32_t i = 1; i < count; i++) { + dsc* d1 = va_arg(args, dsc*); + if (!d1 || s0->type != d1->type || s0->signature != d1->signature) { + va_end(args); + return; + } + } + va_end(args); + + d->type = s0->type; + d->signature = s0->signature; + d->id = s0->id; + + dsc_get_func_id get_func_id = dsc_get_func_id_array[s0->type]; + dsc_get_func_length get_func_length = dsc_get_dsc_get_func_length(s0); + dsc_get_func_name get_func_name = dsc_get_func_name_array[s0->type]; + + int32_t time_func_id = get_func_id("TIME"); + int32_t pv_branch_mode_func_id = get_func_id("PV_BRANCH_MODE"); + + size_t func_count = 0; + size_t size = 0; + va_start(args, count); + for (int32_t i = 0; i < count; i++) { + dsc* s = va_arg(args, dsc*); + func_count += vector_length(s->data); + for (dsc_data* j = s->data.begin; j != s->data.end; j++) + if (j->func == time_func_id || j->func == pv_branch_mode_func_id) + func_count--; + else + size += get_func_length(j->func); + } + va_end(args); + + vector_dsc_data_time data_time = vector_empty(dsc_data_time); + vector_uint32_t data_time_buffer = vector_empty(uint32_t); + vector_dsc_data_time_reserve(&data_time, func_count); + vector_uint32_t_reserve(&data_time_buffer, size); + va_start(args, count); + for (int32_t i = 0; i < count; i++) { + dsc* s = va_arg(args, dsc*); + func_count += vector_length(s->data); + + int32_t time = -1; + int32_t pv_branch_mode = 0; + for (dsc_data* j = s->data.begin; j != s->data.end; j++) { + if (j->func == time_func_id) { + time = (int32_t)dsc_data_get_func_data(s, j)[0]; + continue; + } + else if (j->func == pv_branch_mode_func_id) { + pv_branch_mode = (int32_t)dsc_data_get_func_data(s, j)[0]; + continue; + } + + dsc_data_time* dsc_d = vector_dsc_data_time_reserve_back(&data_time); + dsc_d->time = time; + dsc_d->pv_branch_mode = pv_branch_mode; + dsc_d->name = j->name; + dsc_d->func = j->func; + dsc_d->data_offset = (uint32_t)vector_length(data_time_buffer); + + uint32_t* func_data = dsc_data_get_func_data(s, j); + int32_t func_length = get_func_length(j->func); + memmove(vector_uint32_t_reserve_back_range(&data_time_buffer, func_length), + func_data, sizeof(uint32_t) * func_length); + func_data += func_length; + } + } + va_end(args); + + if (vector_length(data_time)) { + for (dsc_data_time* i = data_time.begin; i != data_time.end; i++) + i->time = radix_preprocess_int32_t(i->time); + radix_sort_custom(data_time.begin, vector_length(data_time), sizeof(dsc_data_time), + sizeof(int32_t), dsc_data_time_radix_index_func_time); + for (dsc_data_time* i = data_time.begin; i != data_time.end; i++) + i->time = radix_postprocess_int32_t(i->time); + } + + func_count = vector_length(data_time); + size = 0; + + int32_t time = -1; + int32_t time_count = 0; + for (dsc_data_time* i = data_time.begin; i != data_time.end; i++) + if (time != i->time) { + if (time_count > 1) + radix_sort_custom(i - time_count, time_count, sizeof(dsc_data_time), + sizeof(int32_t), dsc_data_time_radix_index_func_pv_branch_mode); + time = i->time; + time_count = 1; + func_count++; + size++; + } + else + time_count++; + + if (time_count > 1) + radix_sort_custom(data_time.end - time_count, time_count, sizeof(dsc_data_time), + sizeof(int32_t), dsc_data_time_radix_index_func_pv_branch_mode); + + int32_t pv_branch_mode = -1; + int32_t pv_branch_mode_count = 0; + for (dsc_data_time* i = data_time.begin; i != data_time.end; i++) + if (pv_branch_mode != i->pv_branch_mode) { + pv_branch_mode = i->pv_branch_mode; + pv_branch_mode_count = 1; + func_count++; + size++; + } + else + pv_branch_mode_count++; + + for (dsc_data_time* i = data_time.begin; i != data_time.end; i++) + size += get_func_length(i->func); + + vector_dsc_data data = vector_empty(dsc_data); + vector_uint32_t data_buffer = vector_empty(uint32_t); + vector_dsc_data_reserve(&data, func_count); + vector_uint32_t_reserve(&data_buffer, size); + + time = -1; + pv_branch_mode = -1; + for (dsc_data_time* i = data_time.begin; i != data_time.end; i++) { + if (time_func_id != -1 && time != i->time) { + time = i->time; + + dsc_data* dsc_d = vector_dsc_data_reserve_back(&data); + dsc_d->name = get_func_name(time_func_id); + dsc_d->func = time_func_id; + dsc_d->data_offset = (uint32_t)vector_length(data_buffer); + + *(int32_t*)vector_uint32_t_reserve_back(&data_buffer) = time; + } + + if (pv_branch_mode_func_id != -1 && pv_branch_mode != i->pv_branch_mode) { + pv_branch_mode = i->pv_branch_mode; + + dsc_data* dsc_d = vector_dsc_data_reserve_back(&data); + dsc_d->name = get_func_name(pv_branch_mode_func_id); + dsc_d->func = pv_branch_mode_func_id; + dsc_d->data_offset = (uint32_t)vector_length(data_buffer); + + *(int32_t*)vector_uint32_t_reserve_back(&data_buffer) = pv_branch_mode; + } + + uint32_t* func_data = (uint32_t*)(data_time_buffer.begin + i->data_offset); + dsc_data* dsc_d = vector_dsc_data_reserve_back(&data); + dsc_d->name = get_func_name(i->func); + dsc_d->func = i->func; + dsc_d->data_offset = (uint32_t)vector_length(data_buffer); + + int32_t func_length = get_func_length(i->func); + memmove(vector_uint32_t_reserve_back_range(&data_buffer, func_length), + func_data, sizeof(uint32_t) * func_length); + func_data += func_length; + } + + vector_dsc_data_time_free(&data_time, 0); + vector_uint32_t_free(&data_time_buffer, 0); + + d->data = data; + d->data_buffer = data_buffer; } bool dsc_parse(dsc* d, void* data, size_t length, dsc_type type) { @@ -1795,11 +2187,11 @@ bool dsc_load_file(void* data, char* path, char* file, uint32_t hash) { stream dsc_s; io_open(&dsc_s, string_data(&s), "rb"); void* dsc_data = force_malloc(dsc_s.length); - size_t dsc_replace_data = dsc_s.length; - io_read(&dsc_s, dsc_data, dsc_replace_data); + size_t dsc_length = dsc_s.length; + io_read(&dsc_s, dsc_data, dsc_length); dsc* d = data; - bool ret = dsc_parse(d, dsc_data, dsc_replace_data, d->type); + bool ret = dsc_parse(d, dsc_data, dsc_length, d->type); io_free(&dsc_s); string_free(&s); diff --git a/src/KKdLib/dsc.h b/src/KKdLib/dsc.h index 05a15f39..c4a711c6 100644 --- a/src/KKdLib/dsc.h +++ b/src/KKdLib/dsc.h @@ -282,6 +282,7 @@ typedef struct dsc { typedef struct dsc_replace dsc_replace; typedef struct dsc_replace_data dsc_replace_data; +typedef int32_t(*dsc_get_func_id)(const char* name); typedef int32_t(*dsc_get_func_length)(int32_t id); typedef const char*(*dsc_get_func_name)(int32_t id); typedef const void(*dsc_func_convert)(dsc_replace* dr, dsc_replace_data* drd, uint32_t* data); @@ -332,6 +333,30 @@ extern const int32_t dsc_mgf_func_count; extern const int32_t dsc_x_func_count; extern const int32_t dsc_vrfl_func_count; +extern int32_t dsc_ac101_get_func_id(const char* name); +extern int32_t dsc_ac110_get_func_id(const char* name); +extern int32_t dsc_ac120_get_func_id(const char* name); +extern int32_t dsc_ac200_get_func_id(const char* name); +extern int32_t dsc_ac210_get_func_id(const char* name); +extern int32_t dsc_ac500_get_func_id(const char* name); +extern int32_t dsc_ac510_get_func_id(const char* name); +extern int32_t dsc_aft101_get_func_id(const char* name); +extern int32_t dsc_aft200_get_func_id(const char* name); +extern int32_t dsc_aft300_get_func_id(const char* name); +extern int32_t dsc_aft310_get_func_id(const char* name); +extern int32_t dsc_aft410_get_func_id(const char* name); +extern int32_t dsc_aft701_get_func_id(const char* name); +extern int32_t dsc_ft_get_func_id(const char* name); +extern int32_t dsc_psp_get_func_id(const char* name); +extern int32_t dsc_2nd_get_func_id(const char* name); +extern int32_t dsc_dt_get_func_id(const char* name); +extern int32_t dsc_dt2_get_func_id(const char* name); +extern int32_t dsc_f_get_func_id(const char* name); +extern int32_t dsc_f2_get_func_id(const char* name); +extern int32_t dsc_mgf_get_func_id(const char* name); +extern int32_t dsc_x_get_func_id(const char* name); +extern int32_t dsc_vrfl_get_func_id(const char* name); + extern int32_t dsc_ac101_get_func_length(int32_t id); extern int32_t dsc_ac110_get_func_length(int32_t id); extern int32_t dsc_ac120_get_func_length(int32_t id); @@ -402,7 +427,8 @@ extern const dsc_get_func_name dsc_get_func_name_array[]; extern void dsc_init(dsc* d); extern void dsc_convert(dsc* d, dsc_type dst_type); extern void dsc_data_buffer_rebuild(dsc* d); -extern void* dsc_data_get_func_data(dsc* d, dsc_data* data); +extern uint32_t* dsc_data_get_func_data(dsc* d, dsc_data* data); +extern void dsc_merge(dsc* d, int32_t count, ...); extern bool dsc_parse(dsc* d, void* data, size_t length, dsc_type type); extern void dsc_unparse(dsc* d, void** data, size_t* length); extern bool dsc_load_file(void* data, char* path, char* file, uint32_t hash); diff --git a/src/KKdLib/obj.c b/src/KKdLib/obj.c index 2b22b14e..8ec382a1 100644 --- a/src/KKdLib/obj.c +++ b/src/KKdLib/obj.c @@ -9,6 +9,7 @@ #include "io/stream.h" #include "half_t.h" #include "hash.h" +#include "sort.h" #include "str_utils.h" #include "vector.h" @@ -1716,19 +1717,8 @@ static void obj_classic_write_skin(obj* obj, stream* s, ssize_t base_offset) { } if (sk->bones || sk->ex_data_init) { - for (string* i = strings.begin; i != &strings.end[-1]; i++) { - char* i_str = string_data(i); - for (string* j = i + 1; j != strings.end; j++) - if (str_utils_compare(i_str, string_data(j)) > 0) { - string temp = *i; - *i = *j; - *j = temp; - i_str = string_data(i); - } - } - + quicksort_string(strings.begin, vector_length(strings)); vector_ssize_t_reserve(&string_offsets, vector_length(strings)); - for (string* i = strings.begin; i != strings.end; i++) { *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); io_write_string_null_terminated(s, i); @@ -5426,19 +5416,8 @@ static void obj_modern_write_skin(obj* obj, stream* s, } if (sk->bones || sk->ex_data_init) { - for (string* i = strings.begin; i != &strings.end[-1]; i++) { - char* i_str = string_data(i); - for (string* j = i + 1; j != strings.end; j++) - if (str_utils_compare(i_str, string_data(j)) > 0) { - string temp = *i; - *i = *j; - *j = temp; - i_str = string_data(i); - } - } - + quicksort_string(strings.begin, vector_length(strings)); vector_ssize_t_reserve(&string_offsets, vector_length(strings)); - for (string* i = strings.begin; i != strings.end; i++) { ssize_t off = io_get_position(s); io_write_string_null_terminated(s, i); @@ -6748,7 +6727,7 @@ inline static ssize_t obj_skin_strings_get_string_offset_by_index(vector_string* if (!(index & 0x8000)) return 0; - char* str = strings[index]; + char* str = strings[index & 0x7FFF]; size_t len = utf8_length(str); for (string* i = vec->begin; i != vec->end; i++) if (!memcmp(str, string_data(i), min(len, i->length) + 1)) diff --git a/src/KKdLib/pvpp.c b/src/KKdLib/pvpp.c index b227f534..15763a50 100644 --- a/src/KKdLib/pvpp.c +++ b/src/KKdLib/pvpp.c @@ -18,30 +18,14 @@ vector_func(pvpp_effect) vector_func(pvpp_glitter) vector_func(pvpp_motion) -static void pvpp_a3da_init(pvpp_a3da* a3d); static void pvpp_a3da_read(pvpp_a3da* a3d, stream* s); -static void pvpp_a3da_free(pvpp_a3da* a3d); -static void pvpp_chara_init(pvpp_chara* chr); static void pvpp_chara_read(pvpp_chara* chr, stream* s); -static void pvpp_chara_free(pvpp_chara* chr); -static void pvpp_chara_effect_init(pvpp_chara_effect* chr_eff); static void pvpp_chara_effect_read(pvpp_chara_effect* chr_eff, stream* s); -static void pvpp_chara_effect_free(pvpp_chara_effect* chr_eff); -static void pvpp_chara_effect_a3da_init(pvpp_chara_effect_a3da* chr_pv_eff); static void pvpp_chara_effect_a3da_read(pvpp_chara_effect_a3da* chr_pv_eff, stream* s); -static void pvpp_chara_effect_a3da_free(pvpp_chara_effect_a3da* chr_pv_eff); -static void pvpp_chara_item_init(pvpp_chara_item* chr_itm); static void pvpp_chara_item_read(pvpp_chara_item* chr_itm, stream* s); -static void pvpp_chara_item_free(pvpp_chara_item* chr_itm); -static void pvpp_effect_init(pvpp_effect* eff); static void pvpp_effect_read(pvpp_effect* eff, stream* s); -static void pvpp_effect_free(pvpp_effect* eff); -static void pvpp_glitter_init(pvpp_glitter* glt); static void pvpp_glitter_read(pvpp_glitter* glt, stream* s); -static void pvpp_glitter_free(pvpp_glitter* glt); -static void pvpp_motion_init(pvpp_motion* mot); static void pvpp_motion_read(pvpp_motion* mot, stream* s); -static void pvpp_motion_free(pvpp_motion* mot); static void pvpp_read_inner(pvpp* pp, stream* s); void pvpp_init(pvpp* pp) { @@ -101,24 +85,83 @@ void pvpp_free(pvpp* pp) { vector_pvpp_effect_free(&pp->effect, pvpp_effect_free); } -static void pvpp_a3da_init(pvpp_a3da* a3d) { +void pvpp_a3da_init(pvpp_a3da* a3d) { memset(a3d, 0, sizeof(pvpp_a3da)); } +void pvpp_a3da_free(pvpp_a3da* a3d) { + string_free(&a3d->name); +} + +void pvpp_chara_init(pvpp_chara* chr) { + memset(chr, 0, sizeof(pvpp_chara)); +} + +void pvpp_chara_free(pvpp_chara* chr) { + vector_pvpp_a3da_free(&chr->a3da, pvpp_a3da_free); + vector_pvpp_chara_effect_free(&chr->chara_effect, pvpp_chara_effect_free); + vector_pvpp_chara_item_free(&chr->item, pvpp_chara_item_free); + vector_pvpp_glitter_free(&chr->glitter, pvpp_glitter_free); + vector_pvpp_motion_free(&chr->motion, pvpp_motion_free); +} + +void pvpp_chara_effect_init(pvpp_chara_effect* chr_eff) { + memset(chr_eff, 0, sizeof(pvpp_chara_effect)); +} + +void pvpp_chara_effect_free(pvpp_chara_effect* chr_eff) { + vector_pvpp_chara_effect_a3da_free(&chr_eff->effect_a3da, pvpp_chara_effect_a3da_free); +} + +void pvpp_chara_effect_a3da_init(pvpp_chara_effect_a3da* chr_eff_a3da) { + memset(chr_eff_a3da, 0, sizeof(pvpp_chara_effect_a3da)); +} + +void pvpp_chara_effect_a3da_free(pvpp_chara_effect_a3da* chr_eff_a3da) { + pvpp_a3da_free(&chr_eff_a3da->a3da); +} + +void pvpp_chara_item_init(pvpp_chara_item* chr_itm) { + memset(chr_itm, 0, sizeof(pvpp_chara_item)); +} + +void pvpp_chara_item_free(pvpp_chara_item* chr_itm) { + vector_pvpp_a3da_free(&chr_itm->a3da, pvpp_a3da_free); + string_free(&chr_itm->bone); +} + +void pvpp_effect_init(pvpp_effect* eff) { + memset(eff, 0, sizeof(pvpp_effect)); +} + +void pvpp_effect_free(pvpp_effect* eff) { + vector_pvpp_a3da_free(&eff->a3da, pvpp_a3da_free); + vector_pvpp_glitter_free(&eff->glitter, pvpp_glitter_free); +} + +void pvpp_glitter_init(pvpp_glitter* glt) { + memset(glt, 0, sizeof(pvpp_glitter)); +} + +void pvpp_glitter_free(pvpp_glitter* glt) { + string_free(&glt->name); + string_free(&glt->unk1); +} + +void pvpp_motion_init(pvpp_motion* mot) { + memset(mot, 0, sizeof(pvpp_motion)); +} + +void pvpp_motion_free(pvpp_motion* mot) { + string_free(&mot->name); +} + static void pvpp_a3da_read(pvpp_a3da* a3d, stream* s) { io_read_string_null_terminated_offset(s, io_read_offset_x(s), &a3d->name); a3d->hash = io_read_uint32_t_stream_reverse_endianness(s); io_align_read(s, 0x08); } -static void pvpp_a3da_free(pvpp_a3da* a3d) { - memset(a3d, 0, sizeof(pvpp_a3da)); -} - -static void pvpp_chara_init(pvpp_chara* chr) { - memset(chr, 0, sizeof(pvpp_chara)); -} - static void pvpp_chara_read(pvpp_chara* chr, stream* s) { uint8_t u00 = io_read_uint8_t(s); uint8_t chr_eff_count = io_read_uint8_t(s); @@ -139,17 +182,17 @@ static void pvpp_chara_read(pvpp_chara* chr, stream* s) { chr->chara_effect.end += chr_eff_count; io_position_push(s, chr_eff_offset, SEEK_SET); - for (int32_t j = 0; j < chr_eff_count; j++) - pvpp_chara_effect_read(&chr->chara_effect.begin[j], s); + for (int32_t i = 0; i < chr_eff_count; i++) + pvpp_chara_effect_read(&chr->chara_effect.begin[i], s); io_position_pop(s); vector_pvpp_motion_reserve(&chr->motion, motion_count); chr->motion.end += motion_count; io_position_push(s, motion_offset, SEEK_SET); - for (int32_t j = 0; j < motion_count; j++) { + for (int32_t i = 0; i < motion_count; i++) { io_position_push(s, io_read_offset_x(s), SEEK_SET); - pvpp_motion_read(&chr->motion.begin[j], s); + pvpp_motion_read(&chr->motion.begin[i], s); io_position_pop(s); } io_position_pop(s); @@ -158,39 +201,27 @@ static void pvpp_chara_read(pvpp_chara* chr, stream* s) { chr->a3da.end += a3da_count; io_position_push(s, a3da_offset, SEEK_SET); - for (int32_t j = 0; j < a3da_count; j++) - pvpp_a3da_read(&chr->a3da.begin[j], s); + for (int32_t i = 0; i < a3da_count; i++) + pvpp_a3da_read(&chr->a3da.begin[i], s); io_position_pop(s); vector_pvpp_chara_item_reserve(&chr->item, item_count); chr->item.end += item_count; io_position_push(s, item_offset, SEEK_SET); - for (int32_t j = 0; j < item_count; j++) - pvpp_chara_item_read(&chr->item.begin[j], s); + for (int32_t i = 0; i < item_count; i++) + pvpp_chara_item_read(&chr->item.begin[i], s); io_position_pop(s); vector_pvpp_glitter_reserve(&chr->glitter, glitter_count); chr->glitter.end += glitter_count; io_position_push(s, glitter_offset, SEEK_SET); - for (int32_t j = 0; j < glitter_count; j++) - pvpp_glitter_read(&chr->glitter.begin[j], s); + for (int32_t i = 0; i < glitter_count; i++) + pvpp_glitter_read(&chr->glitter.begin[i], s); io_position_pop(s); } -static void pvpp_chara_free(pvpp_chara* chr) { - vector_pvpp_a3da_free(&chr->a3da, pvpp_a3da_free); - vector_pvpp_chara_effect_free(&chr->chara_effect, pvpp_chara_effect_free); - vector_pvpp_chara_item_free(&chr->item, pvpp_chara_item_free); - vector_pvpp_glitter_free(&chr->glitter, pvpp_glitter_free); - vector_pvpp_motion_free(&chr->motion, pvpp_motion_free); -} - -static void pvpp_chara_effect_init(pvpp_chara_effect* chr_eff) { - memset(chr_eff, 0, sizeof(pvpp_chara_effect)); -} - static void pvpp_chara_effect_read(pvpp_chara_effect* chr_eff, stream* s) { chr_eff->base_chara = io_read_uint8_t(s); uint8_t pv_effects_count = io_read_uint8_t(s); @@ -200,19 +231,11 @@ static void pvpp_chara_effect_read(pvpp_chara_effect* chr_eff, stream* s) { chr_eff->effect_a3da.end += pv_effects_count; io_position_push(s, pv_effects_offstet, SEEK_SET); - for (int32_t k = 0; k < pv_effects_count; k++) - pvpp_chara_effect_a3da_read(&chr_eff->effect_a3da.begin[k], s); + for (int32_t i = 0; i < pv_effects_count; i++) + pvpp_chara_effect_a3da_read(&chr_eff->effect_a3da.begin[i], s); io_position_pop(s); } -static void pvpp_chara_effect_free(pvpp_chara_effect* chr_eff) { - vector_pvpp_chara_effect_a3da_free(&chr_eff->effect_a3da, pvpp_chara_effect_a3da_free); -} - -static void pvpp_chara_effect_a3da_init(pvpp_chara_effect_a3da* chr_eff_a3da) { - memset(chr_eff_a3da, 0, sizeof(pvpp_chara_effect_a3da)); -} - static void pvpp_chara_effect_a3da_read(pvpp_chara_effect_a3da* chr_eff_a3da, stream* s) { chr_eff_a3da->u00 = io_read_uint8_t(s); chr_eff_a3da->u01 = io_read_uint8_t(s); @@ -230,14 +253,6 @@ static void pvpp_chara_effect_a3da_read(pvpp_chara_effect_a3da* chr_eff_a3da, st io_position_pop(s); } -static void pvpp_chara_effect_a3da_free(pvpp_chara_effect_a3da* chr_eff_a3da) { - pvpp_a3da_free(&chr_eff_a3da->a3da); -} - -static void pvpp_chara_item_init(pvpp_chara_item* chr_itm) { - memset(chr_itm, 0, sizeof(pvpp_chara_item)); -} - static void pvpp_chara_item_read(pvpp_chara_item* chr_itm, stream* s) { uint8_t a3das_count = io_read_uint8_t(s); size_t a3das_offset = io_read_offset_x(s); @@ -258,15 +273,6 @@ static void pvpp_chara_item_read(pvpp_chara_item* chr_itm, stream* s) { io_read_string_null_terminated_offset(s, bone_offset, &chr_itm->bone); } -static void pvpp_chara_item_free(pvpp_chara_item* chr_itm) { - vector_pvpp_a3da_free(&chr_itm->a3da, pvpp_a3da_free); - string_free(&chr_itm->bone); -} - -static void pvpp_effect_init(pvpp_effect* eff) { - memset(eff, 0, sizeof(pvpp_effect)); -} - static void pvpp_effect_read(pvpp_effect* eff, stream* s) { uint8_t a3da_count = io_read_uint8_t(s); uint8_t effect_count = io_read_uint8_t(s); @@ -278,28 +284,19 @@ static void pvpp_effect_read(pvpp_effect* eff, stream* s) { eff->a3da.end += a3da_count; io_position_push(s, a3da_offset, SEEK_SET); - for (int32_t j = 0; j < a3da_count; j++) - pvpp_a3da_read(&eff->a3da.begin[j], s); + for (int32_t i = 0; i < a3da_count; i++) + pvpp_a3da_read(&eff->a3da.begin[i], s); io_position_pop(s); vector_pvpp_glitter_reserve(&eff->glitter, effect_count); eff->glitter.end += effect_count; io_position_push(s, effect_offset, SEEK_SET); - for (int32_t j = 0; j < effect_count; j++) - pvpp_glitter_read(&eff->glitter.begin[j], s); + for (int32_t i = 0; i < effect_count; i++) + pvpp_glitter_read(&eff->glitter.begin[i], s); io_position_pop(s); } -static void pvpp_effect_free(pvpp_effect* eff) { - vector_pvpp_a3da_free(&eff->a3da, pvpp_a3da_free); - vector_pvpp_glitter_free(&eff->glitter, pvpp_glitter_free); -} - -static void pvpp_glitter_init(pvpp_glitter* glt) { - memset(glt, 0, sizeof(pvpp_glitter)); -} - static void pvpp_glitter_read(pvpp_glitter* glt, stream* s) { io_read_string_null_terminated_offset(s, io_read_offset_x(s), &glt->name); io_read_string_null_terminated_offset(s, io_read_offset_x(s), &glt->unk1); @@ -307,25 +304,12 @@ static void pvpp_glitter_read(pvpp_glitter* glt, stream* s) { io_align_read(s, 0x08); } -static void pvpp_glitter_free(pvpp_glitter* glt) { - string_free(&glt->name); - string_free(&glt->unk1); -} - -static void pvpp_motion_init(pvpp_motion* mot) { - memset(mot, 0, sizeof(pvpp_motion)); -} - static void pvpp_motion_read(pvpp_motion* mot, stream* s) { io_read_string_null_terminated_offset(s, io_read_offset_x(s), &mot->name); mot->hash = io_read_uint32_t_stream_reverse_endianness(s); io_align_read(s, 0x08); } -static void pvpp_motion_free(pvpp_motion* mot) { - string_free(&mot->name); -} - static void pvpp_read_inner(pvpp* pp, stream* s) { f2_struct st; f2_struct_sread(&st, s); diff --git a/src/KKdLib/pvpp.h b/src/KKdLib/pvpp.h index 1e369e40..8dfabf9c 100644 --- a/src/KKdLib/pvpp.h +++ b/src/KKdLib/pvpp.h @@ -77,8 +77,8 @@ typedef struct pvpp_effect { } pvpp_effect; vector(pvpp_chara_effect) -vector(pvpp_motion) vector(pvpp_chara_item) +vector(pvpp_motion) typedef struct pvpp_chara { vector_pvpp_a3da a3da; @@ -103,3 +103,20 @@ extern void pvpp_read(pvpp* pp, char* path); extern void pvpp_wread(pvpp* pp, wchar_t* path); extern bool pvpp_load_file(void* data, char* path, char* file, uint32_t hash); extern void pvpp_free(pvpp* pp); + +extern void pvpp_a3da_init(pvpp_a3da* a3d); +extern void pvpp_a3da_free(pvpp_a3da* a3d); +extern void pvpp_chara_init(pvpp_chara* chr); +extern void pvpp_chara_free(pvpp_chara* chr); +extern void pvpp_chara_effect_init(pvpp_chara_effect* chr_eff); +extern void pvpp_chara_effect_free(pvpp_chara_effect* chr_eff); +extern void pvpp_chara_effect_a3da_init(pvpp_chara_effect_a3da* chr_pv_eff); +extern void pvpp_chara_effect_a3da_free(pvpp_chara_effect_a3da* chr_pv_eff); +extern void pvpp_chara_item_init(pvpp_chara_item* chr_itm); +extern void pvpp_chara_item_free(pvpp_chara_item* chr_itm); +extern void pvpp_effect_init(pvpp_effect* eff); +extern void pvpp_effect_free(pvpp_effect* eff); +extern void pvpp_glitter_init(pvpp_glitter* glt); +extern void pvpp_glitter_free(pvpp_glitter* glt); +extern void pvpp_motion_init(pvpp_motion* mot); +extern void pvpp_motion_free(pvpp_motion* mot); diff --git a/src/KKdLib/pvsr.c b/src/KKdLib/pvsr.c index 483b6b19..86e0fa6a 100644 --- a/src/KKdLib/pvsr.c +++ b/src/KKdLib/pvsr.c @@ -4,555 +4,439 @@ */ #include "pvsr.h" +#include "f2/struct.h" +#include "io/path.h" +#include "io/stream.h" +#include "str_utils.h" -/* -private struct PVSR -{ - public StageEffect[] StageEffects; - public Effect[] EffectList; - public string[] EMCSList; - public StageEffect?[] StageChangeEffects; - public AET[] AETs; +vector_func(pvsr_a3da) +vector_func(pvsr_aet) +vector_func(pvsr_aet_entry) +vector_func(pvsr_effect) +vector_func(pvsr_glitter) +vector_func(pvsr_stage_effect) - public struct AET - { - public ushort U48; - public ushort U4A; - public ushort U4C; - public ushort U4E; - public ushort U50; - public ushort U52; - public ushort U54; - public ushort U56; - public ushort U58; - public ushort U5A; - public ushort U5C; - public ushort U5E; - public ushort U60; +static void pvsr_a3da_read(pvsr_a3da* a3d, stream* s); +static void pvsr_aet_read(pvsr_aet* aet, stream* s, int32_t x00); +static void pvsr_aet_entry_read(pvsr_aet_entry* aet_entry, stream* s); +static bool pvsr_aet_sub1_read(pvsr_aet_sub1* aet_sub1, stream* s, ssize_t offset); +static bool pvsr_aet_sub2_read(pvsr_aet_sub2* aet_sub2, stream* s, ssize_t offset); +static void pvsr_effect_read(pvsr_effect* eff, stream* s); +static void pvsr_glitter_read(pvsr_glitter* glt, stream* s); +static void pvsr_read_inner(pvsr* sr, stream* s); +static void pvsr_stage_effect_read(pvsr_stage_effect* stg_eff, stream* s); - public string SetName; - public AETEntry[] FrontList; - public AETEntry[] FrontLowList; - public AETEntry[] BackList; - public Sub1? Sub1Data; - public Sub2? Sub2AData; - public Sub2? Sub2BData; - public Sub2? Sub2CData; - public Sub2? Sub2DData; - public AETEntry[] Unk03List; - public AETEntry[] Unk04List; +void pvsr_init(pvsr* sr) { + memset(sr, 0, sizeof(pvsr)); +} - public override string ToString() => - $"(Set Name: {SetName}; Front List Count: {(FrontList != null ? FrontList.Length : 0)}" - + $"; Front Low List Count: {(FrontLowList != null ? FrontLowList.Length : 0)}" - + $"; Back List Count: {(BackList != null ? BackList.Length : 0)}" - + $"; U48: {U48}; U4A: {U4A}; U4C: {U4C}; U4E: {U4E}; U4C: {U4C}; U50: {U50}; U52: {U52}" - + $"; U54: {U54}; U56: {U56}; U58: {U58}; U5A: {U5A}; U5E: {U5E}; U60: {U60}" - + $"; Unk 3 List Count: {(Unk03List != null ? Unk03List.Length : 0)}" - + $"; Unk 4 List Count: {(Unk04List != null ? Unk04List.Length : 0)}"; +void pvsr_read(pvsr* sr, char* path) { + if (!sr || !path) + return; - public struct Sub1 - { - public string Name; - public uint Hash; - public ushort Unk2; + char* path_pvsr = str_utils_add(path, ".pvsr"); + if (path_check_file_exists(path_pvsr)) { + stream s; + io_open(&s, path_pvsr, "rb"); + if (s.io.stream) + pvsr_read_inner(sr, &s); + io_free(&s); + } + free(path_pvsr); +} - public override string ToString() => - $"(Name: {Name}; Hash: {Hash:X08}; Unk 2: {Unk2})"; - } +void pvsr_wread(pvsr* sr, wchar_t* path) { + if (!sr || !path) + return; - public struct Sub2 - { - public ushort U00; - public ushort U02; - public ushort U04; - public ushort U06; - public ushort U08; - public ushort U0A; - public ushort U0C; + wchar_t* path_pvsr = str_utils_wadd(path, L".pvsr"); + if (path_wcheck_file_exists(path_pvsr)) { + stream s; + io_wopen(&s, path_pvsr, L"rb"); + if (s.io.stream) + pvsr_read_inner(sr, &s); + io_free(&s); + } + free(path_pvsr); +} - public override string ToString() => - $"(U00: {U00}; U02: {U02}; U04: {U04}; U06: {U06}; U08: {U08}; U0A: {U0A})"; - } +bool pvsr_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + pvsr* sr = data; + pvsr_read(sr, string_data(&s)); + + string_free(&s); + return sr->ready; +} + +void pvsr_free(pvsr* sr) { + vector_pvsr_aet_free(&sr->aet, pvsr_aet_free); + vector_pvsr_effect_free(&sr->effect, pvsr_effect_free); + vector_string_free(&sr->emcs, string_free); + for (int32_t i = 0; i < PVSR_STAGE_CHANGE_EFFECT_COUNT; i++) + for (int32_t j = 0; j < PVSR_STAGE_CHANGE_EFFECT_COUNT; j++) + if (sr->stage_change_effect_init[i][j]) + pvsr_stage_effect_free(&sr->stage_change_effect[i][j]); + vector_pvsr_stage_effect_free(&sr->stage_effect, pvsr_stage_effect_free); +} + +void pvsr_a3da_init(pvsr_a3da* a3d) { + memset(a3d, 0, sizeof(pvsr_a3da)); +} + +void pvsr_a3da_free(pvsr_a3da* a3d) { + string_free(&a3d->name); +} + +void pvsr_aet_init(pvsr_aet* aet) { + memset(aet, 0, sizeof(pvsr_aet)); +} + +void pvsr_aet_free(pvsr_aet* aet) { + string_free(&aet->set_name); + vector_pvsr_aet_entry_free(&aet->front, pvsr_aet_entry_free); + vector_pvsr_aet_entry_free(&aet->front_low, pvsr_aet_entry_free); + vector_pvsr_aet_entry_free(&aet->back, pvsr_aet_entry_free); + pvsr_aet_sub1_free(&aet->sub1_data); + pvsr_aet_sub2_free(&aet->sub2a_data); + pvsr_aet_sub2_free(&aet->sub2b_data); + pvsr_aet_sub2_free(&aet->sub2c_data); + pvsr_aet_sub2_free(&aet->sub2d_data); + vector_pvsr_aet_entry_free(&aet->unk03, pvsr_aet_entry_free); + vector_pvsr_aet_entry_free(&aet->unk04, pvsr_aet_entry_free); +} + +void pvsr_aet_entry_init(pvsr_aet_entry* aet_entry) { + memset(aet_entry, 0, sizeof(pvsr_aet_entry)); +} + +void pvsr_aet_entry_free(pvsr_aet_entry* aet_entry) { + string_free(&aet_entry->name); +} + +void pvsr_aet_sub1_init(pvsr_aet_sub1* aet_sub1) { + memset(aet_sub1, 0, sizeof(pvsr_aet_sub1)); +} + +void pvsr_aet_sub1_free(pvsr_aet_sub1* aet_sub1) { + string_free(&aet_sub1->name); +} + +void pvsr_aet_sub2_init(pvsr_aet_sub2* aet_sub2) { + memset(aet_sub2, 0, sizeof(pvsr_aet_sub2)); +} + +void pvsr_aet_sub2_free(pvsr_aet_sub2* aet_sub2) { + +} + +void pvsr_effect_init(pvsr_effect* eff) { + memset(eff, 0, sizeof(pvsr_effect)); +} + +void pvsr_effect_free(pvsr_effect* eff) { + string_free(&eff->name); +} + +void pvsr_glitter_init(pvsr_glitter* glt) { + memset(glt, 0, sizeof(pvsr_glitter)); +} + +void pvsr_glitter_free(pvsr_glitter* glt) { + string_free(&glt->name); +} + +void pvsr_stage_effect_init(pvsr_stage_effect* stg_eff) { + memset(stg_eff, 0, sizeof(pvsr_stage_effect)); +} + +void pvsr_stage_effect_free(pvsr_stage_effect* stg_eff) { + vector_pvsr_a3da_free(&stg_eff->a3da, pvsr_a3da_free); + vector_pvsr_glitter_free(&stg_eff->glitter, pvsr_glitter_free); +} + +static void pvsr_a3da_read(pvsr_a3da* a3d, stream* s) { + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &a3d->name); + a3d->hash = io_read_uint32_t_stream_reverse_endianness(s); + io_align_read(s, 0x08); +} + +static void pvsr_aet_read(pvsr_aet* aet, stream* s, int32_t x00) { + ssize_t set_name_offset = io_read_offset_x(s); + ssize_t front_offset = io_read_offset_x(s); + ssize_t front_low_offset = io_read_offset_x(s); + ssize_t back_offset = io_read_offset_x(s); + ssize_t sub1_offset = io_read_offset_x(s); + ssize_t sub2a_offset = io_read_offset_x(s); + ssize_t sub2b_offset = io_read_offset_x(s); + ssize_t sub2c_offset = io_read_offset_x(s); + ssize_t sub2d_offset = io_read_offset_x(s); + aet->u48 = io_read_uint16_t_stream_reverse_endianness(s); + aet->u4a = io_read_uint16_t_stream_reverse_endianness(s); + aet->u4c = io_read_uint16_t_stream_reverse_endianness(s); + aet->u4e = io_read_uint16_t_stream_reverse_endianness(s); + aet->u50 = io_read_uint16_t_stream_reverse_endianness(s); + aet->u52 = io_read_uint16_t_stream_reverse_endianness(s); + aet->u54 = io_read_uint16_t_stream_reverse_endianness(s); + aet->u56 = io_read_uint16_t_stream_reverse_endianness(s); + aet->u58 = io_read_uint16_t_stream_reverse_endianness(s); + aet->u5a = io_read_uint16_t_stream_reverse_endianness(s); + aet->u5c = io_read_uint16_t_stream_reverse_endianness(s); + aet->u5e = io_read_uint16_t_stream_reverse_endianness(s); + aet->u60 = io_read_uint16_t_stream_reverse_endianness(s); + uint8_t front_count = io_read_uint8_t(s); + uint8_t front_low_count = io_read_uint8_t(s); + uint8_t back_count = io_read_uint8_t(s); + io_align_read(s, 0x08); + ssize_t o68 = 0; + ssize_t o70 = 0; + uint8_t u78 = 0; + uint8_t u79 = 0; + if (x00 & 0x100) { + o68 = io_read_offset_x(s); + o70 = io_read_offset_x(s); + u78 = io_read_uint8_t(s); + u79 = io_read_uint8_t(s); + io_align_read(s, 0x08); } - public struct AETEntry - { - public string Name; - public uint Hash; - public float BrightScale; + io_read_string_null_terminated_offset(s, set_name_offset, &aet->set_name); - public override string ToString() => - $"(Name: {Name}; Hash: {Hash:X08}; Bright Scale: {BrightScale})"; - } + vector_pvsr_aet_entry_reserve(&aet->front, front_count); + aet->front.end += front_count; - public struct A3DAEntry - { - public string Name; - public uint Hash; + io_position_push(s, front_offset, SEEK_SET); + for (int32_t i = 0; i < front_count; i++) + pvsr_aet_entry_read(&aet->front.begin[i], s); + io_position_pop(s); - public override string ToString() => - $"(Name: {Name}; Hash: {Hash:X08})"; - } + vector_pvsr_aet_entry_reserve(&aet->front_low, front_low_count); + aet->front_low.end += front_low_count; - public struct Effect - { - public string Name; - public float Emission; + io_position_push(s, front_low_offset, SEEK_SET); + for (int32_t i = 0; i < front_low_count; i++) + pvsr_aet_entry_read(&aet->front_low.begin[i], s); + io_position_pop(s); - public override string ToString() => - $"(Name: {Name}; Emission: {Emission})"; - } + vector_pvsr_aet_entry_reserve(&aet->back, back_count); + aet->back.end += back_count; - public struct Glitter - { - public string Name; - public byte Unk1; + io_position_push(s, back_offset, SEEK_SET); + for (int32_t i = 0; i < back_count; i++) + pvsr_aet_entry_read(&aet->back.begin[i], s); + io_position_pop(s); - public override string ToString() => - $"(Name: {Name}; Unk 1: {Unk1})"; - } + aet->sub1_data_init = pvsr_aet_sub1_read(&aet->sub1_data, s, sub1_offset); + aet->sub2a_data_init = pvsr_aet_sub2_read(&aet->sub2a_data, s, sub2a_offset); + aet->sub2b_data_init = pvsr_aet_sub2_read(&aet->sub2b_data, s, sub2b_offset); + aet->sub2c_data_init = pvsr_aet_sub2_read(&aet->sub2c_data, s, sub2c_offset); + aet->sub2d_data_init = pvsr_aet_sub2_read(&aet->sub2d_data, s, sub2d_offset); - public struct StageEffect - { - public A3DAEntry[] A3DAs; - public Glitter[] Glitters; + if (x00 & 0x100) { + vector_pvsr_aet_entry_reserve(&aet->unk03, u78); + aet->unk03.end += u78; - public override string ToString() => - $"A3DAs Count: {(A3DAs != null ? A3DAs.Length : 0)}" - + $"; Effects Count: {(Glitters != null ? Glitters.Length : 0)})"; + io_position_push(s, o68, SEEK_SET); + for (int32_t i = 0; i < u78; i++) + pvsr_aet_entry_read(&aet->unk03.begin[i], s); + io_position_pop(s); + + vector_pvsr_aet_entry_reserve(&aet->unk04, u79); + aet->unk04.end += u79; + + io_position_push(s, o70, SEEK_SET); + for (int32_t i = 0; i < u79; i++) + pvsr_aet_entry_read(&aet->unk04.begin[i], s); + io_position_pop(s); } } -private static PVSR PVSRReader(string file) -{ - int i, j; - KKdBaseLib.F2.Struct st = File.ReadAllBytes(file + ".pvsr").RSt(); +static void pvsr_aet_entry_read(pvsr_aet_entry* aet_entry, stream* s) { + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &aet_entry->name); + aet_entry->hash = io_read_uint32_t_stream_reverse_endianness(s); + aet_entry->bright_scale = io_read_float_t_stream_reverse_endianness(s); +} - PVSR pvsr = default; - Stream s = File.OpenReader(st.Data); - s.IsBE = st.Header.UseBigEndian; - s.IsX = true; +static bool pvsr_aet_sub1_read(pvsr_aet_sub1* aet_sub1, stream* s, ssize_t offset) { + if (offset <= 0) + return false; - int x00 = s.RI32E(); - byte x04 = s.RU8(); - byte x05 = s.RU8(); - byte x06 = s.RU8(); - byte x07 = s.RU8(); - byte stageEffectsCount = s.RU8(); - byte aetsCount = s.RU8(); - byte x0A = s.RU8(); - byte x0B = s.RU8(); - byte x0C = s.RU8(); - byte x0D = s.RU8(); - byte x0E = s.RU8(); - byte x0F = s.RU8(); - long x10 = s.RI64E(); - long stageEffectsOffset = s.RI64E(); - long stageEffectsListOffset = s.RI64E(); - long aetsOffset = s.RI64E(); + io_position_push(s, offset, SEEK_SET); + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &aet_sub1->name); + aet_sub1->hash = io_read_uint32_t_stream_reverse_endianness(s); + aet_sub1->unk2 = io_read_uint16_t_stream_reverse_endianness(s); + io_align_read(s, 0x08); + io_position_pop(s); + return true; +} - s.PI64 = x10; - byte UnknownsCount = s.RU8(); - byte EffectsCount = s.RU8(); - byte EMCSsCount = s.RU8(); - s.A(0x08); - long UnknownOffset = s.RI64E(); - long EffectsOffset = s.RI64E(); - long EMCSsOffset = s.RI64E(); +static bool pvsr_aet_sub2_read(pvsr_aet_sub2* aet_sub2, stream* s, ssize_t offset) { + if (offset <= 0) + return false; - s.PI64 = EffectsOffset; - pvsr.EffectList = new PVSR.Effect[EffectsCount]; - for (i = 0; i < EffectsCount; i++) - { - ref PVSR.Effect effect = ref pvsr.EffectList[i]; - effect.Name = s.RSaO(); - effect.Emission = s.RF32E(); - s.A(0x08); - } + io_position_push(s, offset, SEEK_SET); + aet_sub2->u00 = io_read_uint16_t_stream_reverse_endianness(s); + aet_sub2->u02 = io_read_uint16_t_stream_reverse_endianness(s); + aet_sub2->u04 = io_read_uint16_t_stream_reverse_endianness(s); + aet_sub2->u06 = io_read_uint16_t_stream_reverse_endianness(s); + aet_sub2->u08 = io_read_uint16_t_stream_reverse_endianness(s); + aet_sub2->u0a = io_read_uint16_t_stream_reverse_endianness(s); + aet_sub2->u0c = io_read_uint16_t_stream_reverse_endianness(s); + io_align_read(s, 0x08); + io_position_pop(s); + return true; +} - s.PI64 = EMCSsOffset; - pvsr.EMCSList = new string[EMCSsCount]; - for (i = 0; i < EMCSsCount; i++) - pvsr.EMCSList[i] = s.RSaO(); +static void pvsr_effect_read(pvsr_effect* eff, stream* s) { + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &eff->name); + eff->emission = io_read_float_t_stream_reverse_endianness(s); + io_align_read(s, 0x08); +} - s.PI64 = stageEffectsOffset; - pvsr.StageEffects = new PVSR.StageEffect[stageEffectsCount]; - for (i = 0; i < stageEffectsCount; i++) - pvsr.StageEffects[i] = readStageEffect(); +static void pvsr_glitter_read(pvsr_glitter* glt, stream* s) { + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &glt->name); + glt->unk1 = io_read_uint8_t(s); + io_align_read(s, 0x08); +} - s.PI64 = stageEffectsListOffset; - pvsr.StageChangeEffects = new PVSR.StageEffect?[0x100]; - for (i = 0; i < 0x100; i++) - { - long o = s.RI64E(); - if (o > 0) - pvsr.StageChangeEffects[i] = readStageEffect(o); +static void pvsr_read_inner(pvsr* sr, stream* s) { + f2_struct st; + f2_struct_sread(&st, s); + if (st.header.signature == reverse_endianness_uint32_t('PVSR') && st.data) { + stream s_pvsr; + io_mopen(&s_pvsr, st.data, st.length); + s_pvsr.is_big_endian = st.header.use_big_endian; - } + int32_t x00 = io_read_int32_t_stream_reverse_endianness(&s_pvsr); + uint8_t x04 = io_read_uint8_t(&s_pvsr); + uint8_t x05 = io_read_uint8_t(&s_pvsr); + uint8_t x06 = io_read_uint8_t(&s_pvsr); + uint8_t x07 = io_read_uint8_t(&s_pvsr); + uint8_t stage_effect_count = io_read_uint8_t(&s_pvsr); + uint8_t aets_count = io_read_uint8_t(&s_pvsr); + uint8_t x0a = io_read_uint8_t(&s_pvsr); + uint8_t x0b = io_read_uint8_t(&s_pvsr); + uint8_t x0c = io_read_uint8_t(&s_pvsr); + uint8_t x0d = io_read_uint8_t(&s_pvsr); + uint8_t x0e = io_read_uint8_t(&s_pvsr); + uint8_t x0f = io_read_uint8_t(&s_pvsr); + ssize_t x10 = io_read_offset_x(&s_pvsr); + ssize_t stage_effect_offset = io_read_offset_x(&s_pvsr); + ssize_t stage_change_effect_offset = io_read_offset_x(&s_pvsr); + ssize_t aet_offset = io_read_offset_x(&s_pvsr); - s.PI64 = aetsOffset; - pvsr.AETs = new PVSR.AET[aetsCount]; - for (i = 0; i < aetsCount; i++) - { - long offset = s.PI64; - ref PVSR.AET aet = ref pvsr.AETs[i]; + io_position_push(&s_pvsr, x10, SEEK_SET); + uint8_t unknown_count = io_read_uint8_t(&s_pvsr); + uint8_t effect_count = io_read_uint8_t(&s_pvsr); + uint8_t emcs_count = io_read_uint8_t(&s_pvsr); + ssize_t unknown_offset = io_read_offset_x(&s_pvsr); + ssize_t effect_offset = io_read_offset_x(&s_pvsr); + ssize_t emcs_offset = io_read_offset_x(&s_pvsr); + io_position_pop(&s_pvsr); - long setNameOffset = s.RI64E(); - long frontOffset = s.RI64E(); - long frontLowOffset = s.RI64E(); - long backOffset = s.RI64E(); - long sub1Offset = s.RI64E(); - long sub2AOffset = s.RI64E(); - long sub2BOffset = s.RI64E(); - long sub2COffset = s.RI64E(); - long sub2DOffset = s.RI64E(); - aet.U48 = s.RU16E(); - aet.U4A = s.RU16E(); - aet.U4C = s.RU16E(); - aet.U4E = s.RU16E(); - aet.U50 = s.RU16E(); - aet.U52 = s.RU16E(); - aet.U54 = s.RU16E(); - aet.U56 = s.RU16E(); - aet.U58 = s.RU16E(); - aet.U5A = s.RU16E(); - aet.U5C = s.RU16E(); - aet.U5E = s.RU16E(); - aet.U60 = s.RU16E(); - byte frontCount = s.RU8(); - byte frontLowCount = s.RU8(); - byte backCount = s.RU8(); - s.A(0x08); - long O68 = 0; - long O70 = 0; - byte U78 = 0; - byte U79 = 0; - if ((x00 & 0x100) != 0) - { - O68 = s.RI64E(); - O70 = s.RI64E(); - U78 = s.RU8(); - U79 = s.RU8(); - s.A(0x08); - } + vector_pvsr_effect_reserve(&sr->effect, effect_count); + sr->effect.end += effect_count; - aet.SetName = s.RSaO(setNameOffset); + io_position_push(&s_pvsr, effect_offset, SEEK_SET); + for (int32_t i = 0; i < effect_count; i++) + pvsr_effect_read(&sr->effect.begin[i], &s_pvsr); + io_position_pop(&s_pvsr); - s.PI64 = frontOffset; - aet.FrontList = new PVSR.AETEntry[frontCount]; - for (j = 0; j < frontCount; j++) - aet.FrontList[j] = readAETEntry(); + vector_string_reserve(&sr->emcs, emcs_count); + sr->emcs.end += emcs_count; - s.PI64 = frontLowOffset; - aet.FrontLowList = new PVSR.AETEntry[frontLowCount]; - for (j = 0; j < frontLowCount; j++) - aet.FrontLowList[j] = readAETEntry(); + io_position_push(&s_pvsr, emcs_offset, SEEK_SET); + for (int32_t i = 0; i < emcs_count; i++) + io_read_string_null_terminated_offset(&s_pvsr, + io_read_offset_x(&s_pvsr), &sr->emcs.begin[i]); + io_position_pop(&s_pvsr); - s.PI64 = backOffset; - aet.BackList = new PVSR.AETEntry[backCount]; - for (j = 0; j < backCount; j++) - aet.BackList[j] = readAETEntry(); + vector_pvsr_stage_effect_reserve(&sr->stage_effect, stage_effect_count); + sr->stage_effect.end += stage_effect_count; - aet.Sub1Data = readAETSub1(sub1Offset); - aet.Sub2AData = readAETSub2(sub2AOffset); - aet.Sub2BData = readAETSub2(sub2BOffset); - aet.Sub2CData = readAETSub2(sub2COffset); - aet.Sub2DData = readAETSub2(sub2DOffset); + io_position_push(&s_pvsr, stage_effect_offset, SEEK_SET); + for (int32_t i = 0; i < stage_effect_count; i++) + pvsr_stage_effect_read(&sr->stage_effect.begin[i], &s_pvsr); + io_position_pop(&s_pvsr); - if (O68 > 0) - { - s.PI64 = O68; - aet.Unk03List = new PVSR.AETEntry[U78]; - for (j = 0; j < U78; j++) - aet.Unk03List[j] = readAETEntry(); - } - - if (O70 > 0) - { - s.PI64 = O70; - aet.Unk04List = new PVSR.AETEntry[U79]; - for (j = 0; j < U79; j++) - aet.Unk04List[j] = readAETEntry(); - } - s.PI64 = offset + ((x00 & 0x100) != 0 ? 0x80 : 0x68); - } - s.C(); - return pvsr; - - PVSR.StageEffect readStageEffect(long o = 0) - { - long offset = s.PI64; - if (o > 0) - s.PI64 = o; - PVSR.StageEffect eff = default; - byte U00 = s.RU8(); - byte U01 = s.RU8(); - byte U02 = s.RU8(); - byte U03 = s.RU8(); - byte U04 = s.RU8(); - s.A(0x08); - long A3DAsOffset = s.RI64E(); - long GlittersOffset = s.RI64E(); - - int a3dasCount; - int glittersCount; - if (U04 != 0xFF) - { - a3dasCount = U00; - glittersCount = U01; - } - else - { - a3dasCount = U01; - glittersCount = U02; - } - - if (A3DAsOffset > 0) - { - s.PI64 = A3DAsOffset; - eff.A3DAs = new PVSR.A3DAEntry[a3dasCount]; - for (int i = 0; i < a3dasCount; i++) - { - PVSR.A3DAEntry entry = default; - entry.Name = s.RSaO(); - entry.Hash = s.RU32E(); - s.A(0x08); - eff.A3DAs[i] = entry; + for (int32_t i = 0; i < PVSR_STAGE_CHANGE_EFFECT_COUNT; i++) + for (int32_t j = 0; j < PVSR_STAGE_CHANGE_EFFECT_COUNT; j++) { + pvsr_stage_effect_init(&sr->stage_change_effect[i][j]); + sr->stage_change_effect_init[i][j] = false; } - } - if (GlittersOffset > 0) - { - s.PI64 = GlittersOffset; - eff.Glitters = new PVSR.Glitter[glittersCount]; - for (int i = 0; i < glittersCount; i++) - eff.Glitters[i] = readGlitter(); - } + io_position_push(&s_pvsr, stage_change_effect_offset, SEEK_SET); + for (int32_t i = 0; i < PVSR_STAGE_CHANGE_EFFECT_COUNT; i++) + for (int32_t j = 0; j < PVSR_STAGE_CHANGE_EFFECT_COUNT; j++) { + ssize_t offset = io_read_offset_x(&s_pvsr); + if (offset <= 0) + continue; - if (o > 0) - s.PI64 = offset; - else - s.PI64 = offset + 0x20; - return eff; - } + io_position_push(&s_pvsr, offset, SEEK_SET); + pvsr_stage_effect_read(&sr->stage_change_effect[i][j], &s_pvsr); + sr->stage_change_effect_init[i][j] = true; + io_position_pop(&s_pvsr); + } + io_position_pop(&s_pvsr); - PVSR.AETEntry readAETEntry() - { - PVSR.AETEntry entry = default; - entry.Name = s.RSaO(); - entry.Hash = s.RU32E(); - entry.BrightScale = s.RF32E(); - return entry; - } + vector_pvsr_aet_reserve(&sr->aet, aets_count); + sr->aet.end += aets_count; - PVSR.AET.Sub1? readAETSub1(long offset) - { - if (offset <= 0) - return default; + io_position_push(&s_pvsr, aet_offset, SEEK_SET); + for (int32_t i = 0; i < aets_count; i++) + pvsr_aet_read(&sr->aet.begin[i], &s_pvsr, x00); + io_position_pop(&s_pvsr); - s.PI64 = offset; - PVSR.AET.Sub1 sub = default; - sub.Name = s.RSaO(); - sub.Hash = s.RU32E(); - sub.Unk2 = s.RU16E(); - s.A(0x08); - return sub; - } + io_free(&s_pvsr); - PVSR.AET.Sub2? readAETSub2(long offset) - { - if (offset <= 0) - return default; - - s.PI64 = offset; - PVSR.AET.Sub2 sub = default; - sub.U00 = s.RU16E(); - sub.U02 = s.RU16E(); - sub.U04 = s.RU16E(); - sub.U06 = s.RU16E(); - sub.U08 = s.RU16E(); - sub.U0A = s.RU16E(); - sub.U0C = s.RU16E(); - s.A(0x08); - return sub; - } - - PVSR.Glitter readGlitter() - { - PVSR.Glitter eff = default; - eff.Name = s.RSaO(); - eff.Unk1 = s.RU8(); - s.A(0x08); - return eff; + sr->ready = true; } + f2_struct_free(&st); } -private static void PVSRMsgPackWriter(string file, PVSR pvsr) -{ - int i, j; - MsgPack _PVSR = new MsgPack("PVSR"); +static void pvsr_stage_effect_read(pvsr_stage_effect* stg_eff, stream* s) { + uint8_t u00 = io_read_uint8_t(s); + uint8_t u01 = io_read_uint8_t(s); + uint8_t u02 = io_read_uint8_t(s); + uint8_t u03 = io_read_uint8_t(s); + uint8_t u04 = io_read_uint8_t(s); + ssize_t a3da_offset = io_read_offset_x(s); + ssize_t glitter_offset = io_read_offset_x(s); + io_read_offset_x(s); - int stageEffectsCount = pvsr.StageEffects != null ? pvsr.StageEffects.Length : 0; - MsgPack stgEffs = new MsgPack(stageEffectsCount, "StageEffects"); - for (i = 0; i < stageEffectsCount; i++) - stgEffs[i] = writeStageEffect(pvsr.StageEffects[i]); - if (stageEffectsCount > 0) - _PVSR.Add(stgEffs); - - int effectsCount = pvsr.EffectList != null ? pvsr.EffectList.Length : 0; - MsgPack effectList = new MsgPack(effectsCount, "EffectList"); - for (i = 0; i < effectsCount; i++) - { - ref PVSR.Effect effect = ref pvsr.EffectList[i]; - effectList[i] = MsgPack.New.Add("Name", effect.Name).Add("Emission", effect.Emission); + uint8_t a3da_count; + uint8_t glitter_count; + if (u04 != 0xFF) { + a3da_count = u00; + glitter_count = u01; } - if (effectsCount > 0) - _PVSR.Add(effectList); - - int emcssCount = pvsr.EMCSList != null ? pvsr.EMCSList.Length : 0; - MsgPack emcsList = new MsgPack(emcssCount, "EMCSList"); - for (i = 0; i < emcssCount; i++) - emcsList[i] = pvsr.EMCSList[i]; - if (emcssCount > 0) - _PVSR.Add(emcsList); - - MsgPack stgChgEffs = new MsgPack(0x10, "StageChangeEffects"); - for (i = 0; i < 0x10; i++) - { - MsgPack stgChgEff = new MsgPack(0x10); - for (j = 0; j < 0x10; j++) - { - if (pvsr.StageChangeEffects[i * 0x10 + j].HasValue) - stgChgEff[j] = writeStageEffect(pvsr.StageChangeEffects[i * 0x10 + j].Value); - else - stgChgEff[j] = default; - } - stgChgEffs[i] = stgChgEff; - } - _PVSR.Add(stgChgEffs); - - int aetsCount = pvsr.AETs != null ? pvsr.AETs.Length : 0; - MsgPack aets = new MsgPack(aetsCount, "AETs"); - for (i = 0; i < aetsCount; i++) - { - ref PVSR.AET aet = ref pvsr.AETs[i]; - - MsgPack a = MsgPack.New.Add("SetName", aet.SetName); - int frontCount = aet.FrontList != null ? aet.FrontList.Length : 0; - MsgPack frontList = new MsgPack(frontCount, "FrontList"); - for (j = 0; j < frontCount; j++) - frontList[j] = writeAETEntry(aet.FrontList[j]); - if (frontCount > 0) - a.Add(frontList); - - int frontLowCount = aet.FrontLowList != null ? aet.FrontLowList.Length : 0; - MsgPack frontLowList = new MsgPack(frontLowCount, "FrontLowList"); - for (j = 0; j < frontLowCount; j++) - frontLowList[j] = writeAETEntry(aet.FrontLowList[j]); - if (frontLowCount > 0) - a.Add(frontLowList); - - int backCount = aet.BackList != null ? aet.BackList.Length : 0; - MsgPack backList = new MsgPack(backCount, "BackList"); - for (j = 0; j < backCount; j++) - backList[j] = writeAETEntry(aet.BackList[j]); - if (backCount > 0) - a.Add(backList); - - a.Add("U48", aet.U48); - a.Add("U4A", aet.U4A); - a.Add("U4C", aet.U4C); - a.Add("U4E", aet.U4E); - a.Add("U50", aet.U50); - a.Add("U52", aet.U52); - a.Add("U54", aet.U54); - a.Add("U56", aet.U56); - a.Add("U58", aet.U58); - a.Add("U5A", aet.U5A); - a.Add("U5C", aet.U5C); - a.Add("U5E", aet.U5E); - a.Add("U60", aet.U60); - - MsgPack temp; - if ((temp = writeAETSub1(aet.Sub1Data, "Sub1")).NotNull) - a.Add(temp); - if ((temp = writeAETSub2(aet.Sub2AData, "Sub2A")).NotNull) - a.Add(temp); - if ((temp = writeAETSub2(aet.Sub2BData, "Sub2B")).NotNull) - a.Add(temp); - if ((temp = writeAETSub2(aet.Sub2CData, "Sub2C")).NotNull) - a.Add(temp); - if ((temp = writeAETSub2(aet.Sub2DData, "Sub2D")).NotNull) - a.Add(temp); - - int unk03Count = aet.FrontList != null ? aet.FrontList.Length : 0; - MsgPack unk03List = new MsgPack(unk03Count, "Unk04List"); - for (j = 0; j < unk03Count; j++) - unk03List[j] = writeAETEntry(aet.Unk03List[j]); - if (unk03Count > 0) - _PVSR.Add(unk03List); - - int unk04Count = aet.Unk04List != null ? aet.Unk04List.Length : 0; - MsgPack unk04List = new MsgPack(unk04Count, "Unk04List"); - for (j = 0; j < unk04Count; j++) - unk04List[j] = writeAETEntry(aet.Unk04List[j]); - if (unk04Count > 0) - a.Add(unk04List); - aets[i] = a; - } - if (aetsCount > 0) - _PVSR.Add(aets); - - _PVSR.Write(false, true, file, json); - - MsgPack writeStageEffect(PVSR.StageEffect eff, string name = null) - { - MsgPack effect = new MsgPack(name); - int a3dasCount = eff.A3DAs != null ? eff.A3DAs.Length : 0; - MsgPack a3das = new MsgPack(a3dasCount, "A3DAs"); - for (int i = 0; i < a3dasCount; i++) - a3das[i] = eff.A3DAs[i].Name; - if (a3dasCount > 0) - effect.Add(a3das); - - int glittersCount = eff.Glitters != null ? eff.Glitters.Length : 0; - MsgPack glitters = new MsgPack(glittersCount, "Glitters"); - for (int i = 0; i < glittersCount; i++) - glitters[i] = writeGlitter(eff.Glitters[i]); - if (glittersCount > 0) - effect.Add(glitters); - - if (a3dasCount > 0 || glittersCount > 0) - return effect; - else - return default; + else { + a3da_count = u01; + glitter_count = u02; } - MsgPack writeAETEntry(PVSR.AETEntry entry, string name = null) => - new MsgPack(name).Add("Name", entry.Name).Add("BrightScale", entry.BrightScale); + vector_pvsr_a3da_reserve(&stg_eff->a3da, a3da_count); + stg_eff->a3da.end += a3da_count; - MsgPack writeAETSub1(PVSR.AET.Sub1? sub, string name = null) - { - if (!sub.HasValue) - return default; + io_position_push(s, a3da_offset, SEEK_SET); + for (int32_t i = 0; i < a3da_count; i++) + pvsr_a3da_read(&stg_eff->a3da.begin[i], s); + io_position_pop(s); - PVSR.AET.Sub1 s = sub.Value; - return new MsgPack(name).Add("Name", s.Name).Add("Unk2", s.Unk2); - } + vector_pvsr_glitter_reserve(&stg_eff->glitter, glitter_count); + stg_eff->glitter.end += glitter_count; - MsgPack writeAETSub2(PVSR.AET.Sub2? sub, string name = null) - { - if (!sub.HasValue) - return default; - - PVSR.AET.Sub2 s = sub.Value; - return new MsgPack(name) - .Add("U00", s.U00).Add("U02", s.U02).Add("U04", s.U04).Add("U06", s.U06) - .Add("U08", s.U08).Add("U0A", s.U0A).Add("U0C", s.U0C); - } - - MsgPack writeGlitter(PVSR.Glitter eff, string name = null) => - new MsgPack(name).Add("Name", eff.Name).Add("Unk1", eff.Unk1); + io_position_push(s, glitter_offset, SEEK_SET); + for (int32_t i = 0; i < glitter_count; i++) + pvsr_glitter_read(&stg_eff->glitter.begin[i], s); + io_position_pop(s); } -*/ diff --git a/src/KKdLib/pvsr.h b/src/KKdLib/pvsr.h index 5aa1c6e9..2220a040 100644 --- a/src/KKdLib/pvsr.h +++ b/src/KKdLib/pvsr.h @@ -8,3 +8,123 @@ #include "default.h" #include "string.h" #include "vector.h" + +typedef struct pvsr_aet_sub1 { + string name; + uint32_t hash; + uint16_t unk2; +} pvsr_aet_sub1; + +typedef struct pvsr_aet_sub2 { + uint16_t u00; + uint16_t u02; + uint16_t u04; + uint16_t u06; + uint16_t u08; + uint16_t u0a; + uint16_t u0c; +} pvsr_aet_sub2; + +typedef struct pvsr_aet_entry { + string name; + uint32_t hash; + float_t bright_scale; +} pvsr_aet_entry; + +vector(pvsr_aet_entry) + +typedef struct pvsr_aet { + uint16_t u48; + uint16_t u4a; + uint16_t u4c; + uint16_t u4e; + uint16_t u50; + uint16_t u52; + uint16_t u54; + uint16_t u56; + uint16_t u58; + uint16_t u5a; + uint16_t u5c; + uint16_t u5e; + uint16_t u60; + + string set_name; + vector_pvsr_aet_entry front; + vector_pvsr_aet_entry front_low; + vector_pvsr_aet_entry back; + pvsr_aet_sub1 sub1_data; + bool sub1_data_init; + pvsr_aet_sub2 sub2a_data; + bool sub2a_data_init; + pvsr_aet_sub2 sub2b_data; + bool sub2b_data_init; + pvsr_aet_sub2 sub2c_data; + bool sub2c_data_init; + pvsr_aet_sub2 sub2d_data; + bool sub2d_data_init; + vector_pvsr_aet_entry unk03; + vector_pvsr_aet_entry unk04; +} pvsr_aet; + +typedef struct pvsr_a3da { + string name; + uint32_t hash; +} pvsr_a3da; + +typedef struct pvsr_effect { + string name; + float_t emission; +} pvsr_effect; + +typedef struct pvsr_glitter { + string name; + uint8_t unk1; +} pvsr_glitter; + +vector(pvsr_a3da) +vector(pvsr_glitter) + +typedef struct pvsr_stage_effect { + vector_pvsr_a3da a3da; + vector_pvsr_glitter glitter; +} pvsr_stage_effect; + +vector(pvsr_aet) +vector(pvsr_effect) +vector(pvsr_stage_effect) + +#define PVSR_STAGE_CHANGE_EFFECT_COUNT 0x10 + +typedef struct pvsr { + bool ready; + + vector_pvsr_aet aet; + vector_pvsr_effect effect; + vector_string emcs; + pvsr_stage_effect stage_change_effect[PVSR_STAGE_CHANGE_EFFECT_COUNT][PVSR_STAGE_CHANGE_EFFECT_COUNT]; + bool stage_change_effect_init[PVSR_STAGE_CHANGE_EFFECT_COUNT][PVSR_STAGE_CHANGE_EFFECT_COUNT]; + vector_pvsr_stage_effect stage_effect; +} pvsr; + +extern void pvsr_init(pvsr* sr); +extern void pvsr_read(pvsr* sr, char* path); +extern void pvsr_wread(pvsr* sr, wchar_t* path); +extern bool pvsr_load_file(void* data, char* path, char* file, uint32_t hash); +extern void pvsr_free(pvsr* sr); + +extern void pvsr_a3da_init(pvsr_a3da* a3d); +extern void pvsr_a3da_free(pvsr_a3da* a3d); +extern void pvsr_aet_init(pvsr_aet* aet); +extern void pvsr_aet_free(pvsr_aet* aet); +extern void pvsr_aet_entry_init(pvsr_aet_entry* aet_entry); +extern void pvsr_aet_entry_free(pvsr_aet_entry* aet_entry); +extern void pvsr_aet_sub1_init(pvsr_aet_sub1* aet_sub1); +extern void pvsr_aet_sub1_free(pvsr_aet_sub1* aet_sub1); +extern void pvsr_aet_sub2_init(pvsr_aet_sub2* aet_sub2); +extern void pvsr_aet_sub2_free(pvsr_aet_sub2* aet_sub2); +extern void pvsr_effect_init(pvsr_effect* eff); +extern void pvsr_effect_free(pvsr_effect* eff); +extern void pvsr_glitter_init(pvsr_glitter* glt); +extern void pvsr_glitter_free(pvsr_glitter* glt); +extern void pvsr_stage_effect_init(pvsr_stage_effect* stg_eff); +extern void pvsr_stage_effect_free(pvsr_stage_effect* stg_eff); diff --git a/src/KKdLib/sort.c b/src/KKdLib/sort.c index 3b802748..c6d8ba61 100644 --- a/src/KKdLib/sort.c +++ b/src/KKdLib/sort.c @@ -6,26 +6,36 @@ */ #include "sort.h" +#include +#include "str_utils.h" #define RADIX_BASE 8 #define RADIX (1 << RADIX_BASE) -void radix_sort_int8_t(int8_t* arr, size_t n) { +static int quicksort_int8_t_compare(void const* src1, void const* src2); +static int quicksort_uint8_t_compare(void const* src1, void const* src2); +static int quicksort_int16_t_compare(void const* src1, void const* src2); +static int quicksort_uint16_t_compare(void const* src1, void const* src2); +static int quicksort_int32_t_compare(void const* src1, void const* src2); +static int quicksort_uint32_t_compare(void const* src1, void const* src2); +static int quicksort_int64_t_compare(void const* src1, void const* src2); +static int quicksort_uint64_t_compare(void const* src1, void const* src2); +static int quicksort_ssize_t_compare(void const* src1, void const* src2); +static int quicksort_size_t_compare(void const* src1, void const* src2); +static int quicksort_char_ptr_compare(void const* src1, void const* src2); +static int quicksort_wchar_t_ptr_compare(void const* src1, void const* src2); +static int quicksort_string_compare(void const* src1, void const* src2); +static int quicksort_wstring_compare(void const* src1, void const* src2); + +inline void radix_sort_int8_t(int8_t* arr, size_t n) { if (n <= 1) return; - uint8_t* a = (uint8_t*)arr; for (size_t i = 0; i < n; i++) - if (a[i] & 0x80) - a[i] |= 0x80; - else - a[i] = (uint8_t)(-(int8_t)a[i]); - radix_sort_uint8_t(a, n); + arr[i] = radix_preprocess_int8_t(arr[i]); + radix_sort_uint8_t((uint8_t*)arr, n); for (size_t i = 0; i < n; i++) - if (a[i] & 0x80) - a[i] &= ~0x80; - else - a[i] = (uint8_t)(-(int8_t)a[i]); + arr[i] = radix_postprocess_int8_t(arr[i]); } void radix_sort_uint8_t(uint8_t* arr, size_t n) { @@ -65,22 +75,15 @@ void radix_sort_uint8_t(uint8_t* arr, size_t n) { free(c); } -void radix_sort_int16_t(int16_t* arr, size_t n) { +inline void radix_sort_int16_t(int16_t* arr, size_t n) { if (n <= 1) return; - uint16_t* a = (uint16_t*)arr; for (size_t i = 0; i < n; i++) - if (a[i] & 0x8000) - a[i] |= 0x8000; - else - a[i] = (uint16_t)(-(int16_t)a[i]); - radix_sort_uint16_t(a, n); + arr[i] = radix_preprocess_int16_t(arr[i]); + radix_sort_uint16_t((uint16_t*)arr, n); for (size_t i = 0; i < n; i++) - if (a[i] & 0x8000) - a[i] &= ~0x8000; - else - a[i] = (uint16_t)(-(int16_t)a[i]); + arr[i] = radix_postprocess_int16_t(arr[i]); } void radix_sort_uint16_t(uint16_t* arr, size_t n) { @@ -120,22 +123,15 @@ void radix_sort_uint16_t(uint16_t* arr, size_t n) { free(c); } -void radix_sort_int32_t(int32_t* arr, size_t n) { +inline void radix_sort_int32_t(int32_t* arr, size_t n) { if (n <= 1) return; - uint32_t* a = (uint32_t*)arr; for (size_t i = 0; i < n; i++) - if (a[i] & 0x80000000) - a[i] |= 0x80000000; - else - a[i] = (uint32_t)(-(int32_t)a[i]); - radix_sort_uint32_t(a, n); + arr[i] = radix_preprocess_int32_t(arr[i]); + radix_sort_uint32_t((uint32_t*)arr, n); for (size_t i = 0; i < n; i++) - if (a[i] & 0x80000000) - a[i] &= ~0x80000000; - else - a[i] = (uint32_t)(-(int32_t)a[i]); + arr[i] = radix_postprocess_int32_t(arr[i]); } void radix_sort_uint32_t(uint32_t* arr, size_t n) { @@ -175,22 +171,15 @@ void radix_sort_uint32_t(uint32_t* arr, size_t n) { free(c); } -void radix_sort_int64_t(int64_t* arr, size_t n) { +inline void radix_sort_int64_t(int64_t* arr, size_t n) { if (n <= 1) return; - uint64_t* a = (uint64_t*)arr; for (size_t i = 0; i < n; i++) - if (a[i] & 0x8000000000000000) - a[i] |= 0x8000000000000000; - else - a[i] = (uint64_t)(-(int64_t)a[i]); - radix_sort_uint64_t(a, n); + arr[i] = radix_preprocess_int64_t(arr[i]); + radix_sort_uint64_t((uint64_t*)arr, n); for (size_t i = 0; i < n; i++) - if (a[i] & 0x8000000000000000) - a[i] &= ~0x8000000000000000; - else - a[i] = (uint64_t)(-(int64_t)a[i]); + arr[i] = radix_postprocess_int64_t(arr[i]); } void radix_sort_uint64_t(uint64_t* arr, size_t n) { @@ -230,22 +219,15 @@ void radix_sort_uint64_t(uint64_t* arr, size_t n) { free(c); } -void radix_sort_ssize_t(ssize_t* arr, size_t n) { +inline void radix_sort_ssize_t(ssize_t* arr, size_t n) { if (n <= 1) return; - size_t* a = (size_t*)arr; for (size_t i = 0; i < n; i++) - if (a[i] & 0x8000000000000000) - a[i] |= 0x8000000000000000; - else - a[i] = (size_t)(-(ssize_t)a[i]); - radix_sort_size_t(a, n); + arr[i] = radix_preprocess_ssize_t(arr[i]); + radix_sort_size_t((size_t*)arr, n); for (size_t i = 0; i < n; i++) - if (a[i] & 0x8000000000000000) - a[i] &= ~0x8000000000000000; - else - a[i] = (size_t)(-(ssize_t)a[i]); + arr[i] = radix_postprocess_ssize_t(arr[i]); } void radix_sort_size_t(size_t* arr, size_t n) { @@ -284,3 +266,189 @@ void radix_sort_size_t(size_t* arr, size_t n) { free(o); free(c); } + +void radix_sort_custom(void* arr, size_t n, size_t size, size_t idx_len, radix_index_func idx_func) { + if (n <= 1) + return; + + uint8_t* o = force_malloc(size * n); + size_t* c = force_malloc_s(size_t, RADIX); + uint8_t* a = arr; + void* org_arr = arr; + + for (size_t shift = 0, s = 0; shift < idx_len * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); + + for (size_t i = 0; i < n; i++) + c[(idx_func(a, i) >> s) & (RADIX - 1)]++; + + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = n - 1; i >= 0; i--) { + size_t index = --c[(idx_func(a, i) >> s) & (RADIX - 1)]; + memmove(o + size * index, a + size * i, size); + } + + uint8_t* t = a; + a = o; + o = t; + } + + if (org_arr == o) { + uint8_t* t = a; + a = o; + o = t; + + memmove(a, o, size * n); + } + + free(o); + free(c); +} + +inline void quicksort_int8_t(int8_t* arr, size_t n) { + qsort(arr, n, sizeof(int8_t), quicksort_int8_t_compare); +} + +inline void quicksort_uint8_t(uint8_t* arr, size_t n) { + qsort(arr, n, sizeof(uint8_t), quicksort_uint8_t_compare); +} + +inline void quicksort_int16_t(int16_t* arr, size_t n) { + qsort(arr, n, sizeof(int16_t), quicksort_int16_t_compare); +} + +inline void quicksort_uint16_t(uint16_t* arr, size_t n) { + qsort(arr, n, sizeof(uint16_t), quicksort_uint16_t_compare); +} + +inline void quicksort_int32_t(int32_t* arr, size_t n) { + qsort(arr, n, sizeof(int32_t), quicksort_int32_t_compare); +} + +inline void quicksort_uint32_t(uint32_t* arr, size_t n) { + qsort(arr, n, sizeof(uint32_t), quicksort_uint32_t_compare); +} + +inline void quicksort_int64_t(int64_t* arr, size_t n) { + qsort(arr, n, sizeof(int64_t), quicksort_int64_t_compare); +} + +inline void quicksort_uint64_t(uint64_t* arr, size_t n) { + qsort(arr, n, sizeof(uint64_t), quicksort_uint64_t_compare); +} + +inline void quicksort_ssize_t(ssize_t* arr, size_t n) { + qsort(arr, n, sizeof(ssize_t), quicksort_ssize_t_compare); +} + +inline void quicksort_size_t(size_t* arr, size_t n) { + qsort(arr, n, sizeof(size_t), quicksort_size_t_compare); +} + +void quicksort_char_ptr(char** arr, size_t n) { + qsort(arr, n, sizeof(char*), quicksort_char_ptr_compare); +} + +void quicksort_wchar_t_ptr(wchar_t** arr, size_t n) { + qsort(arr, n, sizeof(wchar_t*), quicksort_wchar_t_ptr_compare); +} + +inline void quicksort_string(string* arr, size_t n) { + qsort(arr, n, sizeof(string), quicksort_string_compare); +} + +inline void quicksort_wstring(wstring* arr, size_t n) { + qsort(arr, n, sizeof(wstring), quicksort_wstring_compare); +} + +inline void quicksort_custom(void* arr, size_t n, size_t s, quicksort_compare_func comp_finc) { + qsort(arr, n, s, comp_finc); +} + +static int quicksort_int8_t_compare(void const* src1, void const* src2) { + int8_t s1 = *(int8_t*)src1; + int8_t s2 = *(int8_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_uint8_t_compare(void const* src1, void const* src2) { + uint8_t s1 = *(uint8_t*)src1; + uint8_t s2 = *(uint8_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_int16_t_compare(void const* src1, void const* src2) { + int16_t s1 = *(int16_t*)src1; + int16_t s2 = *(int16_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_uint16_t_compare(void const* src1, void const* src2) { + uint16_t s1 = *(uint16_t*)src1; + uint16_t s2 = *(uint16_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_int32_t_compare(void const* src1, void const* src2) { + int32_t s1 = *(int32_t*)src1; + int32_t s2 = *(int32_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_uint32_t_compare(void const* src1, void const* src2) { + uint32_t s1 = *(uint32_t*)src1; + uint32_t s2 = *(uint32_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_int64_t_compare(void const* src1, void const* src2) { + int64_t s1 = *(int64_t*)src1; + int64_t s2 = *(int64_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_uint64_t_compare(void const* src1, void const* src2) { + uint64_t s1 = *(uint64_t*)src1; + uint64_t s2 = *(uint64_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_ssize_t_compare(void const* src1, void const* src2) { + ssize_t s1 = *(ssize_t*)src1; + ssize_t s2 = *(ssize_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_size_t_compare(void const* src1, void const* src2) { + size_t s1 = *(ssize_t*)src1; + size_t s2 = *(ssize_t*)src2; + return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0); +} + +static int quicksort_char_ptr_compare(void const* src1, void const* src2) { + char* str1 = *(char**)src1; + char* str2 = *(char**)src2; + return str_utils_compare(str1, str2); +} + +static int quicksort_wchar_t_ptr_compare(void const* src1, void const* src2) { + wchar_t* str1 = *(wchar_t**)src1; + wchar_t* str2 = *(wchar_t**)src2; + return str_utils_wcompare(str1, str2); +} + +static int quicksort_string_compare(void const* src1, void const* src2) { + string* str1 = (string*)src1; + string* str2 = (string*)src2; + return str_utils_compare_length(string_data(str1), str1->length, + string_data(str2), str2->length); +} + +static int quicksort_wstring_compare(void const* src1, void const* src2) { + wstring* str1 = (wstring*)src1; + wstring* str2 = (wstring*)src2; + return str_utils_wcompare_length(wstring_data(str1), str1->length, + wstring_data(str2), str2->length); +} diff --git a/src/KKdLib/sort.h b/src/KKdLib/sort.h index a2111101..8f94ba7b 100644 --- a/src/KKdLib/sort.h +++ b/src/KKdLib/sort.h @@ -10,6 +10,47 @@ #include "default.h" #include "string.h" +typedef size_t(*radix_index_func)(void* data, size_t index); +typedef int(*quicksort_compare_func)(void const* src1, void const* src2); + +#define radix_preprocess_int8_t(v) \ +((int8_t)((uint8_t)(v) ^ 0x80u)) + +#define radix_postprocess_int8_t(v) \ +((int8_t)((uint8_t)(v) ^ 0x80u)) + +#define radix_preprocess_int16_t(v) \ +((int16_t)((uint16_t)(v) ^ 0x8000u)) + +#define radix_postprocess_int16_t(v) \ +((int16_t)((uint16_t)(v) ^ 0x8000u)) + +#define radix_preprocess_int32_t(v) \ +((int32_t)((uint32_t)(v) ^ 0x80000000u)) + +#define radix_postprocess_int32_t(v) \ +((int32_t)((uint32_t)(v) ^ 0x80000000u)) + +#define radix_preprocess_int64_t(v) \ +((int64_t)((uint64_t)(v) ^ 0x8000000000000000u)) + +#define radix_postprocess_int64_t(v) \ +((int64_t)((uint64_t)(v) ^ 0x8000000000000000u)) + +#ifdef _WIN64 +#define radix_preprocess_ssize_t(v) \ +((ssize_t)((size_t)(v) ^ 0x8000000000000000u)) + +#define radix_postprocess_ssize_t(v) \ +((ssize_t)((size_t)(v) ^ 0x8000000000000000u)) +#else +#define radix_preprocess_ssize_t(v) \ +((ssize_t)((size_t)(v) ^ 0x80000000u)) + +#define radix_postprocess_ssize_t(v) \ +((ssize_t)((size_t)(v) ^ 0x80000000u)) +#endif + extern void radix_sort_int8_t(int8_t* arr, size_t n); extern void radix_sort_uint8_t(uint8_t* arr, size_t n); extern void radix_sort_int16_t(int16_t* arr, size_t n); @@ -20,3 +61,20 @@ extern void radix_sort_int64_t(int64_t* arr, size_t n); extern void radix_sort_uint64_t(uint64_t* arr, size_t n); extern void radix_sort_ssize_t(ssize_t* arr, size_t n); extern void radix_sort_size_t(size_t* arr, size_t n); +extern void radix_sort_custom(void* arr, size_t n, size_t s, size_t idx_len, radix_index_func idx_func); + +extern void quicksort_int8_t(int8_t* arr, size_t n); +extern void quicksort_uint8_t(uint8_t* arr, size_t n); +extern void quicksort_int16_t(int16_t* arr, size_t n); +extern void quicksort_uint16_t(uint16_t* arr, size_t n); +extern void quicksort_int32_t(int32_t* arr, size_t n); +extern void quicksort_uint32_t(uint32_t* arr, size_t n); +extern void quicksort_int64_t(int64_t* arr, size_t n); +extern void quicksort_uint64_t(uint64_t* arr, size_t n); +extern void quicksort_ssize_t(ssize_t* arr, size_t n); +extern void quicksort_size_t(size_t* arr, size_t n); +extern void quicksort_char_ptr(char** arr, size_t n); +extern void quicksort_wchar_t_ptr(wchar_t** arr, size_t n); +extern void quicksort_string(string* arr, size_t n); +extern void quicksort_wstring(wstring* arr, size_t n); +extern void quicksort_custom(void* arr, size_t n, size_t s, quicksort_compare_func comp_finc); diff --git a/src/KKdLib/types.h b/src/KKdLib/types.h index 95e1429a..b411c5bc 100644 --- a/src/KKdLib/types.h +++ b/src/KKdLib/types.h @@ -16,7 +16,11 @@ #ifdef ssize_t #undef ssize_t #endif +#ifdef _WIN64 typedef __int64 ssize_t; +#else +typedef int size_t; +#endif #ifdef float_t #undef float_t