diff --git a/src/CRE/data.cpp b/src/CRE/data.cpp index cd8138a8..25dc5e50 100644 --- a/src/CRE/data.cpp +++ b/src/CRE/data.cpp @@ -298,12 +298,9 @@ bool data_struct::check_directory_exists(const char* dir) { bool data_struct::check_file_exists(const char* path) { const char* t = strrchr(path, '/'); - if (t) { - std::string dir(path, t - path + 1); - return check_file_exists(dir.c_str(), t + 1); - } + if (!t) + t = strrchr(path, '\\'); - t = strrchr(path, '\\'); if (t) { std::string dir(path, t - path + 1); return check_file_exists(dir.c_str(), t + 1); @@ -658,12 +655,9 @@ bool data_struct::get_file_path(const char* dir, const char* file, std::string& bool data_struct::load_file(void* data, const char* path, bool (*load_func)(void* data, const char* dir, const char* file, uint32_t hash)) { const char* t = strrchr(path, '/'); - if (t) { - std::string dir(path, t - path + 1); - return load_file(data, dir.c_str(), t + 1, load_func); - } + if (!t) + t = strrchr(path, '\\'); - t = strrchr(path, '\\'); if (t) { std::string dir(path, t - path + 1); return load_file(data, dir.c_str(), t + 1, load_func); diff --git a/src/CRE/file_handler.cpp b/src/CRE/file_handler.cpp index 8772720e..67446998 100644 --- a/src/CRE/file_handler.cpp +++ b/src/CRE/file_handler.cpp @@ -5,6 +5,7 @@ #include #include "../KKdLib/io/file_stream.hpp" +#include "../KKdLib/io/path.hpp" #include "../KKdLib/hash.hpp" #include "file_handler.hpp" #include "data.hpp" @@ -380,15 +381,24 @@ size_t p_file_handler::get_size() { bool p_file_handler::read_file(void* data, const char* path) { const char* t = strrchr(path, '/'); + if (!t) + t = strrchr(path, '\\'); + if (t) { std::string dir(path, t - path + 1); return read_file(data, dir.c_str(), 0, t + 1, false); } + return false; +} + +bool p_file_handler::read_file(void* data, const char* farc_path, const char* file, bool cache) { + const char* t = strrchr(farc_path, '/'); + if (!t) + t = strrchr(farc_path, '\\'); - t = strrchr(path, '\\'); if (t) { - std::string dir(path, t - path + 1); - return read_file(data, dir.c_str(), 0, t + 1, false); + std::string dir(farc_path, t - farc_path + 1); + return read_file(data, dir.c_str(), t + 1, file, cache); } return false; } @@ -404,7 +414,8 @@ bool p_file_handler::read_file(void* data, const char* dir, reset(); } - if (!((data_struct*)data)->check_file_exists(dir, farc_file ? farc_file : file)) + if (data && !((data_struct*)data)->check_file_exists(dir, farc_file ? farc_file : file) + || !data && !path_check_file_exists(std::string(dir).append(farc_file ? farc_file : file).c_str())) return false; ptr = new file_handler; @@ -437,7 +448,7 @@ bool p_file_handler::read_file(void* data, const char* dir, const char* file) { } bool p_file_handler::read_file(void* data, const char* dir, uint32_t hash, const char* ext) { - if (!dir || !hash || hash == hash_murmurhash_empty) + if (!data || !dir || !hash || hash == hash_murmurhash_empty) return false; if (ptr) { @@ -483,12 +494,22 @@ void p_file_handler::read_now() { ptr->reading = true; if (ptr->not_ready) { bool ret; - if (ptr->farc_file.size()) - ret = ((data_struct*)ptr->ds)->load_file( - ptr, ptr->dir.c_str(), ptr->farc_file.c_str(), file_handler_load_farc_file); - else - ret = ((data_struct*)ptr->ds)->load_file( - ptr, ptr->dir.c_str(), ptr->file.c_str(), file_handler_load_file); + if (ptr->ds) { + if (ptr->farc_file.size()) + ret = ((data_struct*)ptr->ds)->load_file( + ptr, ptr->dir.c_str(), ptr->farc_file.c_str(), file_handler_load_farc_file); + else + ret = ((data_struct*)ptr->ds)->load_file( + ptr, ptr->dir.c_str(), ptr->file.c_str(), file_handler_load_file); + } + else { + if (ptr->farc_file.size()) + ret = file_handler_load_farc_file( + ptr, ptr->dir.c_str(), ptr->farc_file.c_str(), hash_murmurhash_empty); + else + ret = file_handler_load_file( + ptr, ptr->dir.c_str(), ptr->file.c_str(), hash_murmurhash_empty); + } if (ret) ptr->not_ready = false; diff --git a/src/CRE/file_handler.hpp b/src/CRE/file_handler.hpp index a09e1ce7..28fb8414 100644 --- a/src/CRE/file_handler.hpp +++ b/src/CRE/file_handler.hpp @@ -57,6 +57,7 @@ struct p_file_handler { const void* get_data(); size_t get_size(); bool read_file(void* data, const char* path); + bool read_file(void* data, const char* farc_path, const char* file, bool cache); bool read_file(void* data, const char* dir, const char* farc_file, const char* file, bool cache); bool read_file(void* data, const char* dir, const char* file); bool read_file(void* data, const char* dir, uint32_t hash, const char* ext); diff --git a/src/CRE/mdata_manager.cpp b/src/CRE/mdata_manager.cpp index da10c3a1..5ab2b446 100644 --- a/src/CRE/mdata_manager.cpp +++ b/src/CRE/mdata_manager.cpp @@ -8,7 +8,7 @@ MdataMgr mdata_manager; -MdataMgr::MdataMgr() : state() { +MdataMgr::MdataMgr() : state(), inner_state(), pv_db_paths_count(), pv_db_total_paths_count() { prefixes.push_back(""); prefixes.push_back("mdata_"); } @@ -30,9 +30,14 @@ bool MdataMgr::ctrl() { case 1: if (!task_pv_db_get()->field_99) task_pv_db_add_paths(); + + inner_state = 3; + pv_db_paths_count = 0; + pv_db_total_paths_count = task_pv_db_get_paths_count(); state = 2; break; case 2: + pv_db_paths_count = pv_db_total_paths_count - task_pv_db_get_paths_count(); if (task_pv_db_is_paths_empty()) state = 3; break; @@ -44,6 +49,10 @@ bool MdataMgr::ctrl() { Log("--->LOAD ROM PVDB!\n"); if (!task_pv_db_get()->field_99) task_pv_db_add_paths(); + + inner_state = 5; + pv_db_paths_count = 0; + pv_db_total_paths_count = task_pv_db_get_paths_count(); state = 5; break; case 5: @@ -51,9 +60,13 @@ bool MdataMgr::ctrl() { return true; break; case 6: + inner_state = 7; + pv_db_paths_count = 0; + pv_db_total_paths_count = 0; state = 15; break; case 15: + inner_state = 9; return true; } return false; @@ -84,6 +97,71 @@ const std::list& MdataMgr::GetPrefixes() { return prefixes; } +std::string MdataMgr::GetStateString() { + char buf[0x40]; + std::string str; + switch (inner_state) { + case 1: + str.assign("WAIT 1"); + if (pv_db_total_paths_count <= 0) + break; + + sprintf_s(buf, sizeof(buf), " (%d/%d)", pv_db_paths_count, pv_db_total_paths_count); + str.append(buf); + break; + case 2: + str.assign("WAIT 2"); + break; + case 3: + str.assign("WAIT 7"); + if (pv_db_total_paths_count <= 0) + break; + + sprintf_s(buf, sizeof(buf), " (%d/%d)", pv_db_paths_count, pv_db_total_paths_count); + str.append(buf); + break; + case 4: + str.assign("WAIT 8"); + if (pv_db_total_paths_count <= 0) + break; + + sprintf_s(buf, sizeof(buf), " (%d/%d)", pv_db_paths_count, pv_db_total_paths_count); + str.append(buf); + break; + case 5: + str.assign("WAIT 9"); + if (pv_db_total_paths_count <= 0) + break; + + sprintf_s(buf, sizeof(buf), " (%d/%d)", pv_db_paths_count, pv_db_total_paths_count); + str.append(buf); + break; + case 6: + str.assign("WAIT 10", 7ui64); + if (pv_db_total_paths_count <= 0) + break; + + sprintf_s(buf, sizeof(buf), " (%d/%d)", pv_db_paths_count, pv_db_total_paths_count); + str.append(buf); + break; + case 7: + str.assign("WAIT 15"); + break; + case 8: + str.assign("WAIT 16"); + if (pv_db_total_paths_count <= 0) + break; + + sprintf_s(buf, sizeof(buf), " (%d/%d)", pv_db_paths_count, pv_db_total_paths_count); + str.append(buf); + break; + case 9: + str.assign("OK"); + break; + } + return str; +} + bool mdata_manager_add_task() { return app::TaskWork::add_task(mdata_manager_get(), 0, "M_DATA_MANAGER"); } diff --git a/src/CRE/mdata_manager.hpp b/src/CRE/mdata_manager.hpp index 10b3b5d7..375536a0 100644 --- a/src/CRE/mdata_manager.hpp +++ b/src/CRE/mdata_manager.hpp @@ -13,6 +13,9 @@ class MdataMgr : public app::Task { public: int32_t state; + int32_t inner_state; + int32_t pv_db_paths_count; + int32_t pv_db_total_paths_count; std::string log; std::list prefixes; @@ -27,6 +30,7 @@ public: void Log(const char* fmt, ...); const std::list& GetPrefixes(); + std::string GetStateString(); }; extern bool mdata_manager_add_task(); diff --git a/src/CRE/object.cpp b/src/CRE/object.cpp index e78f14dc..9687fa10 100644 --- a/src/CRE/object.cpp +++ b/src/CRE/object.cpp @@ -1818,6 +1818,13 @@ inline uint32_t object_storage_get_obj_mesh_index_by_hash(uint32_t hash, const c return -1; } +inline const char* object_storage_get_obj_name(object_info obj_info) { + obj* obj = object_storage_get_obj(obj_info); + if (obj) + return obj->name; + return 0; +} + inline obj_set* object_storage_get_obj_set(uint32_t set_id) { auto elem = object_storage_data.find(set_id); if (elem != object_storage_data.end()) diff --git a/src/CRE/object.hpp b/src/CRE/object.hpp index 45fe69a6..40355199 100644 --- a/src/CRE/object.hpp +++ b/src/CRE/object.hpp @@ -129,6 +129,7 @@ extern obj_mesh* object_storage_get_obj_mesh_by_object_hash(uint32_t hash, const extern obj_mesh* object_storage_get_obj_mesh_by_object_hash_index(uint32_t hash, uint32_t index); extern uint32_t object_storage_get_obj_mesh_index(object_info obj_info, const char* mesh_name); extern uint32_t object_storage_get_obj_mesh_index_by_hash(uint32_t hash, const char* mesh_name); +extern const char* object_storage_get_obj_name(object_info obj_info); extern obj_set* object_storage_get_obj_set(uint32_t set_id); extern size_t object_storage_get_obj_set_count(); extern int32_t object_storage_get_obj_storage_load_count(uint32_t set_id); diff --git a/src/CRE/rob/rob.cpp b/src/CRE/rob/rob.cpp index 8d3cb2f7..010a3ec8 100644 --- a/src/CRE/rob/rob.cpp +++ b/src/CRE/rob/rob.cpp @@ -12,6 +12,8 @@ #include "../../KKdLib/sort.hpp" #include "../../KKdLib/str_utils.hpp" #include "../../KKdLib/waitable_timer.hpp" +#include "../customize_item_table.hpp" +#include "../module_table.hpp" #include "../data.hpp" #include "../effect.hpp" #include "../hand_item.hpp" @@ -63,8 +65,7 @@ struct OpdMaker { bool CheckOpdiFilesNotReady(); const void* GetOpdiFileData(object_info obj_info, uint32_t motion_id); bool IsValidOpdiFile(rob_chara* rob_chr, uint32_t motion_id); - void ReadOpdiFiles(rob_chara* rob_chr, std::vector& motions, - void* data, const object_database* obj_db, const motion_database* mot_db); + void ReadOpdiFiles(rob_chara* rob_chr, std::vector& motions); void Reset(); }; @@ -102,7 +103,7 @@ struct OpdMakeWorker : public app::Task { bool field_D4; OpdMaker::Data data; - OpdMakeWorker(); + OpdMakeWorker(int32_t chara_id); virtual ~OpdMakeWorker() override; virtual bool init() override; @@ -167,9 +168,20 @@ struct opd_farc_params { opd_farc_params(); }; +struct opd_farc_file { + std::string name; + size_t offset; + size_t size; + + opd_farc_file(); + opd_farc_file(const std::string& name, size_t offset, size_t size); + ~opd_farc_file(); +}; + struct opd_farc { std::string path; opd_farc_params params; + std::vector files; std::string data_path; file_stream* stream; size_t farc_size; @@ -178,7 +190,7 @@ struct opd_farc { ~opd_farc(); bool add_file(const void* data, size_t size, const std::string& name); - bool open(const std::string& path, const opd_farc_params& data); + bool open(const std::string& path, const opd_farc_params& params); void reset(); bool write_file(); }; @@ -190,7 +202,7 @@ struct p_opd_farc { ~p_opd_farc(); bool add_file(const void* data, size_t size, const std::string& file); - bool open(const std::string& path, const opd_farc_params& data); + bool open(const std::string& path, const opd_farc_params& params); bool open(const std::string& path, bool compress, size_t align); bool write_file(); }; @@ -245,6 +257,18 @@ public: void Reset(); }; +struct osage_play_data_database_struct { + std::map map; + + osage_play_data_database_struct(); + ~osage_play_data_database_struct(); + + size_t& find(const std::string& key); + size_t& get_ver_by_name(size_t& ver, const std::string& name); + void load(const std::string& file_path); + void reset(); +}; + struct rob_osage_mothead_data { bool init; mothead_data_type type; @@ -290,65 +314,37 @@ struct rob_osage_mothead { void set_sleeve_adjust(const mothead_data* mhd_data); }; -struct struc_567 { - uint16_t year; - uint16_t month; - uint16_t day; -}; - -struct struc_568 { - struc_567 field_0; - int64_t field_10; -}; - struct OpdMakeManager : app::Task { - struct Chara { - uint32_t mode; - uint32_t progress; - chara_index chara; - std::vector items; - - Chara(); - ~Chara(); - }; - - struct Data { - uint32_t mode; - uint32_t count; - uint32_t index; - std::vector charas; - - Data(); - ~Data(); - }; - - struct CharaConstume { + struct CharaCostume { std::vector items[ITEM_SUB_MAX]; - CharaConstume(); - ~CharaConstume(); + CharaCostume(); + ~CharaCostume(); }; - struct CharaConstumes { + struct CharaData { + size_t left; size_t count; - uint32_t index; - CharaConstume chara[CHARA_MAX]; + CharaCostume chara_costumes[CHARA_MAX]; - CharaConstumes(); - ~CharaConstumes(); + CharaData(); + ~CharaData(); + void AddCostumes(const std::list>& costumes); + void AddObjects(const std::vector& customize_items); bool CheckNoItems(chara_index chara_index); void PopItems(chara_index chara_index, int32_t items[ITEM_SUB_MAX]); + void Reset(); + void SortUnique(); }; int32_t mode; - struc_568 field_70; - CharaConstumes chara_costumes; + CharaData chara_data; chara_index chara; std::vector motion_ids; std::vector motion_set_ids; OpdMakeWorker* workers[4]; - Data data; + OpdMakeManagerData data; bool field_1888; bool use_opdi; @@ -361,6 +357,9 @@ struct OpdMakeManager : app::Task { void disp() override; bool del(); + + void AddTask(const OpdMakeManagerArgs& args); + OpdMakeManagerData* GetData(); }; struct struc_380 { @@ -1095,8 +1094,6 @@ static void motion_blend_mot_set_duration(motion_blend_mot* mot, static PvOsageManager* pv_osage_manager_array_get(int32_t chara_id); -static int pv_data_set_motion_quicksort_compare_func(void const* src1, void const* src2); - static void rob_base_rob_chara_init(rob_chara* rob_chr); static void rob_base_rob_chara_ctrl(rob_chara* rob_chr); static void rob_base_rob_chara_ctrl_thread_main(rob_chara* rob_chr); @@ -1210,10 +1207,6 @@ static void rob_chara_set_pv_data(rob_chara* rob_chr, int8_t chara_id, static void rob_cmn_mottbl_read(void* a1, const void* data, size_t size); -static const char* get_ram_osage_play_data_dir(); -static const char* get_ram_osage_play_data_tmp_dir(); -static const char* get_rom_osage_play_data_dir(); - static void opd_chara_data_array_add_frame_data(int32_t chara_id); static void opd_chara_data_array_encode_data(int32_t chara_id); static void opd_chara_data_array_encode_init_data(int32_t chara_id, int32_t motion_id); @@ -1238,8 +1231,10 @@ rob_manager_rob_impl rob_manager_rob_impls2[7]; bool rob_manager_rob_impls2_init = false; opd_chara_data* opd_chara_data_array; +OpdChecker* opd_checker; OpdMakeManager* opd_make_manager; OpdMaker* opd_maker_array; +osage_play_data_database_struct* osage_play_data_database; OsagePlayDataManager* osage_play_data_manager; PvOsageManager* pv_osage_manager_array; rob_cmn_mottbl_header* rob_cmn_mottbl_data; @@ -1249,6 +1244,7 @@ RobThreadHandler* rob_thread_handler; TaskRobLoad* task_rob_load; TaskRobManager* task_rob_manager; +static int32_t opd_chara_data_counter = 0; static int32_t opd_maker_counter = 0; static int32_t pv_osage_manager_counter = 0; static int32_t rob_thread_parent_counter = 0; @@ -2300,7 +2296,7 @@ bool check_cos_id_is_501(int32_t cos_id) { const uint32_t* get_opd_motion_set_ids() { static const uint32_t opd_motion_set_ids[] = { - 51, 194, 797, (uint32_t)-1, + 51, 194, 797, (uint32_t)-1, // EDT, EDT2, EDTF1 }; return opd_motion_set_ids; @@ -2338,10 +2334,100 @@ void motion_set_unload_mothead(uint32_t set) { mothead_storage_data.erase(elem); } +const char* get_ram_osage_play_data_dir() { + return "ram/osage_play_data"; +} + +const char* get_ram_osage_play_data_tmp_dir() { + return "ram/osage_play_data_tmp"; +} + +const char* get_rom_osage_play_data_dir() { + return "rom/osage_play_data"; +} + +const char* get_rom_osage_play_data_opdi_dir() { + return "rom/osage_play_data/opdi"; +} + +OpdChecker* opd_checker_get() { + return opd_checker; +} + +bool opd_checker_check_state_not_3() { + return opd_checker_get()->CheckStateNot3(); +} + +bool opd_checker_has_objects() { + return !!opd_checker_get()->GetObjects().size(); +} + +void opd_checker_launch_thread() { + opd_checker_get()->LaunchThread(); +} + +void opd_checker_terminate_thread() { + opd_checker_get()->TerminateThread(); +} + +void opd_make_manager_add_task(const OpdMakeManagerArgs& args) { + opd_make_manager->AddTask(args); +} + +bool opd_make_manager_check_task_ready() { + return app::TaskWork::check_task_ready(opd_make_manager); +} + bool opd_make_manager_del_task() { return opd_make_manager->del(); } +OpdMakeManagerData* opd_make_manager_get_data() { + return opd_make_manager->GetData(); +} + +static std::vector opd_make_start_get_motion_ids() { + data_struct* aft_data = &data_list[DATA_AFT]; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + + const uint32_t* opd_motion_set_ids = get_opd_motion_set_ids(); + std::vector motion_ids; + while (*opd_motion_set_ids != -1) { + const motion_set_info* set_info = aft_mot_db->get_motion_set_by_id(*opd_motion_set_ids); + if (!set_info) { + opd_motion_set_ids++; + continue; + } + + motion_ids.reserve(set_info->motion.size()); + for (const motion_info& i : set_info->motion) + motion_ids.push_back(i.id); + opd_motion_set_ids++; + } + + motion_ids.push_back(195); // CMN_MRA00_13_01 + prj::sort_unique(motion_ids); + return motion_ids; +} + +void opd_make_start() { + std::vector& objects = opd_checker_get()->GetObjects(); + std::vector motion_ids = opd_make_start_get_motion_ids(); + + OpdMakeManagerArgs args; + args.modules = 0; + args.field_18 = false; + args.use_opdi = true; + args.motion_ids = &motion_ids; + args.objects = &objects; + opd_make_manager->AddTask(args); +} + +void opd_make_stop() { + opd_checker_terminate_thread(); + opd_make_manager_del_task(); +} + bool osage_play_data_manager_add_task() { return osage_play_data_manager->add(); } @@ -2370,6 +2456,20 @@ void osage_play_data_manager_reset() { osage_play_data_manager->Reset(); } +void osage_play_database_load() { + data_struct* aft_data = &data_list[DATA_AFT]; + + for (const std::string& i : mdata_manager_get()->GetPrefixes()) { + std::string path(get_rom_osage_play_data_dir()); + path.append(i); + path.append("/"); + path.append("opd_db.txt"); + + if (aft_data->check_file_exists(path.c_str())) + osage_play_data_database->load(path.c_str()); + } +} + void pv_osage_manager_array_reset(int32_t chara_id) { pv_osage_manager_array_get(chara_id)->Reset(); } @@ -2378,12 +2478,18 @@ void rob_init() { if (!opd_chara_data_array) opd_chara_data_array = new opd_chara_data[ROB_CHARA_COUNT]; + if (!opd_checker) + opd_checker = new OpdChecker; + if (!opd_make_manager) opd_make_manager = new OpdMakeManager; if (!opd_maker_array) opd_maker_array = new OpdMaker[4]; + if (!osage_play_data_database) + osage_play_data_database = new osage_play_data_database_struct; + if (!osage_play_data_manager) osage_play_data_manager = new OsagePlayDataManager; @@ -2468,6 +2574,11 @@ void rob_free() { osage_play_data_manager = 0; } + if (osage_play_data_database) { + delete osage_play_data_database; + osage_play_data_database = 0; + } + if (opd_maker_array) { delete[] opd_maker_array; opd_maker_array = 0; @@ -5017,6 +5128,201 @@ osage_init_data::~osage_init_data() { } +OpdMakeManagerData::Chara::Chara() : mode(), progress() { + chara = CHARA_MAX; +} + +OpdMakeManagerData::Chara::~Chara() { + +} + +OpdMakeManagerData::OpdMakeManagerData() : left(), count() { + mode = -1; +} + +OpdMakeManagerData::~OpdMakeManagerData() { + +} +OpdChecker::OpdChecker() : state(), field_8(), field_10(), +field_18(), index(), size(), terminated(), thread() { + SetState(0); + field_40 = -1; +} + +OpdChecker::~OpdChecker() { + +} + +bool OpdChecker::CheckFileAdler32Checksum(const std::string& path) { + bool ret = false; + file_stream fs; + fs.open(path.c_str(), "rb"); + if (fs.check_not_null()) { + size_t length = fs.get_length(); + if (length) { + uint8_t* data = force_malloc(length); + if (fs.read(data, length)) { + adler_buf adler; + adler.get_adler(data, length - 8); + ret = *(uint32_t*)&data[length - 4] == adler.adler; + free_def(data); + } + } + } + fs.close(); + return ret; +} + +bool OpdChecker::CheckFileVersion(const std::string& path, uint32_t version) { + bool ret = false; + file_stream fs; + fs.open(path.c_str(), "rb"); + if (fs.check_not_null()) { + size_t length = fs.get_length(); + if (length) { + uint32_t footer[2] = {}; + if (!fs.set_position(length - 8, SEEK_SET) + && fs.read(footer, sizeof(footer))) + ret = footer[0] == version; + } + } + fs.close(); + return ret; +} + +bool OpdChecker::CheckStateNot3() { + if (GetState()) + return GetState() != 3; + return false; +} + +std::vector& OpdChecker::GetObjects() { + GetState(); + return objects; +} + +void OpdChecker::GetIndexSize(int32_t& index, int32_t& size) { + std::unique_lock u_lock(index_mtx); + index = this->index; + size = this->size; +} + +int32_t OpdChecker::GetState() { + std::unique_lock u_lock(state_mtx); + return state; +} + +bool OpdChecker::GetTerminated() { + std::unique_lock u_lock(terminated_mtx); + return terminated; +} + +void OpdChecker::LaunchThread() { + SetState(1); + + thread = new std::thread(OpdChecker::ThreadMain, this); + if (thread) { + std::wstring buf = swprintf_s_string(L"OPD Checker"); + SetThreadDescription((HANDLE)thread->native_handle(), buf.c_str()); + } +} + +void OpdChecker::SetIndexSize(int32_t index, int32_t size) { + std::unique_lock u_lock(index_mtx); + this->index = index; + this->size = size; +} + +void OpdChecker::SetState(int32_t value) { + std::unique_lock u_lock(state_mtx); + state = value; +} + +void OpdChecker::SetTerminated() { + std::unique_lock u_lock(terminated_mtx); + terminated = true; +} + +void OpdChecker::TerminateThread() { + SetTerminated(); + + if (thread) { + thread->join(); + delete thread; + } + + thread = 0; +} + +void OpdChecker::ThreadMain(OpdChecker* opd_checker) { + opd_checker->terminated = 0; + opd_checker->SetIndexSize(0, (int32_t)osage_play_data_database->map.size()); + opd_checker->sub_140471020(); +} + +void OpdChecker::sub_140471020() { + data_struct* aft_data = &data_list[DATA_AFT]; + + //bool v63 = sub_14066CC20(1); + while (GetState() == 1) { + std::vector files = path_get_files(get_ram_osage_play_data_dir()); + for (std::string& i : files) { + if (!i.size()) + continue; + + size_t pos = i.find(".farc"); + if (pos != -1) + continue; + + std::string temp = string_to_upper(i.substr(0, pos)); + auto elem = osage_play_data_database->map.find(temp); + if (elem != osage_play_data_database->map.end() && !temp.compare(elem->first)) + path_delete_file(sprintf_s_string("%s/%s", get_ram_osage_play_data_dir() + i).c_str()); + } + + SetState(2); + } + + int32_t index = 0; + for (auto& i : osage_play_data_database->map) { + if (GetTerminated()) + break; + + std::string file = string_to_lower(sprintf_s_string("/%s.farc", i.first.c_str())); + + std::string rom_path(get_rom_osage_play_data_dir()); + rom_path.append(file); + + std::string ram_path(get_ram_osage_play_data_dir()); + ram_path.append(file); + + bool v54 = false; + if (aft_data->get_file_path(rom_path)) + v54 = CheckFileVersion(rom_path.c_str(), (uint32_t)i.second); + + if (v54) { + if (path_check_file_exists(ram_path.c_str())) + path_delete_file(ram_path.c_str()); + } + else { + if (!path_check_file_exists(ram_path.c_str()) + || /*!v63 && */!CheckFileAdler32Checksum(ram_path) + || !CheckFileVersion(ram_path, (uint32_t)i.second)) { + path_delete_file(ram_path.c_str()); + objects.push_back(i.first); + } + } + + SetIndexSize(++index, (int32_t)osage_play_data_database->map.size()); + } + + prj::sort_unique(objects); + SetState(3); + + //if (!v63) + // sub_14066FE10(1); +} + static float_t bone_data_limit_angle(float_t angle) { bool neg; if (angle < 0.0f) { @@ -11262,18 +11568,6 @@ static void rob_cmn_mottbl_read(void* a1, const void* data, size_t size) { } } -static const char* get_ram_osage_play_data_dir() { - return "ram/osage_play_data"; -} - -static const char* get_ram_osage_play_data_tmp_dir() { - return "ram/osage_play_data_tmp"; -} - -static const char* get_rom_osage_play_data_dir() { - return "rom/osage_play_data"; -} - static void opd_chara_data_array_add_frame_data(int32_t chara_id) { opd_chara_data_array_get(chara_id)->add_frame_data(); } @@ -15792,11 +16086,13 @@ bool OpdMaker::Data::IsValidOpdiFile(rob_chara* rob_chr, uint32_t motion_id) { return true; } -void OpdMaker::Data::ReadOpdiFiles(rob_chara* rob_chr, std::vector& motions, - void* data, const object_database* obj_db, const motion_database* mot_db) { +void OpdMaker::Data::ReadOpdiFiles(rob_chara* rob_chr, std::vector& motions) { if (!empty || !rob_chr) return; + data_struct* aft_data = &data_list[DATA_AFT]; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + rob_chara_item_equip* rob_itm_equip = rob_chr->item_equip; for (int32_t i = ITEM_KAMI; i < ITEM_MAX; i++) { rob_chara_item_equip_object* itm_eq_obj = rob_itm_equip->get_item_equip_object((item_id)i); @@ -15804,19 +16100,25 @@ void OpdMaker::Data::ReadOpdiFiles(rob_chara* rob_chr, std::vector& mo continue; object_info obj_info = itm_eq_obj->obj_info; + const char* object_name = object_storage_get_obj_name(obj_info); + if (!object_name) + continue; + for (uint32_t& i : motions) { auto elem = opdi_files.insert({ { obj_info, i }, 0 }).first; - const char* object_name = obj_db->get_object_name(obj_info); - const char* motion_name = mot_db->get_motion_name(i); - if (object_name && motion_name) { - std::string farc_file = string_to_lower(sprintf_s_string("%s.opdi", object_name)); - std::string file = string_to_lower(sprintf_s_string("%s_%s.opdi", object_name, motion_name)); + const char* motion_name = aft_mot_db->get_motion_name(i); + if (!motion_name) + continue; - p_file_handler* file_handler = new p_file_handler; - file_handler->read_file(data, "rom/osage_play_data/opdi", farc_file.c_str(), file.c_str(), true); - elem->second = file_handler; - } + std::string farc_path = string_to_lower(sprintf_s_string( + "%s_%s.opdi", get_rom_osage_play_data_opdi_dir(), object_name)); + std::string file = string_to_lower(sprintf_s_string( + "%s_%s.opdi", object_name, motion_name)); + + p_file_handler* file_handler = new p_file_handler; + file_handler->read_file(aft_data, farc_path.c_str(), file.c_str(), true); + elem->second = file_handler; } } empty = false; @@ -15941,13 +16243,13 @@ void OpdMaker::Ctrl() { std::string chara_dir = sprintf_s_string("%s/%d", ram_osage_play_data_tmp_path, chara_id); - std::vector files = aft_data->get_directory_files(chara_dir.c_str()); - for (data_struct_file& i : files) { - if (!i.path.size() || !i.name.size()) + std::vector files = path_get_files(chara_dir.c_str()); + for (std::string& i : files) { + if (!i.size()) continue; - std::string tmp_path = sprintf_s_string("%s/%s", chara_dir.c_str(), i.name.c_str()); - std::string ram_path = sprintf_s_string("%s/%s", ram_osage_play_data_tmp_path, i.name.c_str()); + std::string tmp_path = sprintf_s_string("%s/%s", chara_dir.c_str(), i.c_str()); + std::string ram_path = sprintf_s_string("%s/%s", ram_osage_play_data_tmp_path, i.c_str()); if (path_check_file_exists(ram_path.c_str())) path_delete_file(ram_path.c_str()); @@ -15955,11 +16257,11 @@ void OpdMaker::Ctrl() { if (!path_check_file_exists(tmp_path.c_str())) continue; - size_t pos = i.name.find(".farc"); + size_t pos = i.find(".farc"); if (pos == -1) continue; - std::string name(i.name.substr(0, pos)); + std::string name(i.substr(0, pos)); for (char& c : name) if (c >= 'a' && c <= 'z') c -= 0x20; @@ -15979,28 +16281,27 @@ void OpdMaker::Ctrl() { fs.close(); void* file_data = force_malloc(file_length); - if (!file_data) { - file_stream fs; - fs.open(tmp_path.c_str(), "rb"); - if (fs.check_not_null()) { - size_t read_length = fs.read(file_data, file_length); - fs.close(); + if (!file_data) + continue; - if (read_length) { - adler_buf adler; - adler.get_adler(file_data, file_length); - footer[1] = adler.adler; - free_def(file_data); + fs.open(tmp_path.c_str(), "rb"); + size_t read_length = fs.read(file_data, file_length); + fs.close(); - file_stream fs; - fs.open(tmp_path.c_str(), "ab"); - if (fs.check_not_null()) { - fs.write(footer, sizeof(footer)); - fs.close(); - } - } - } + if (!read_length) { + free_def(file_data); + continue; } + + adler_buf adler; + adler.get_adler(file_data, file_length); + footer[1] = adler.adler; + + fs.open(tmp_path.c_str(), "ab"); + if (fs.check_not_null()) + fs.write(footer, sizeof(footer)); + fs.close(); + free_def(file_data); } rob_chr = 0; @@ -16015,7 +16316,7 @@ bool OpdMaker::GetEnd() { bool OpdMaker::InitThread(rob_chara* rob_chr, const std::vector* motion_ids, OpdMaker::Data* data) { bool waiting = IsWaiting(); - if (waiting || rob_chr) + if (waiting || this->rob_chr) return waiting; if (thread) { @@ -16082,8 +16383,8 @@ void OpdMaker::ThreadMain(OpdMaker* opd_maker) { opd_maker->Ctrl(); } -OpdMakeWorker::OpdMakeWorker() : state(), chara_id(), items(), field_D4() { - +OpdMakeWorker::OpdMakeWorker(int32_t chara_id) : state(), items(), field_D4() { + this->chara_id = chara_id; } OpdMakeWorker::~OpdMakeWorker() { @@ -16099,7 +16400,6 @@ bool OpdMakeWorker::init() { bool OpdMakeWorker::ctrl() { data_struct* aft_data = &data_list[DATA_AFT]; bone_database* aft_bone_data = &aft_data->data_ft.bone_data; - motion_database* aft_mot_db = &aft_data->data_ft.mot_db; object_database* aft_obj_db = &aft_data->data_ft.obj_db; rob_chara* rob_chr = rob_chara_array_get(chara_id); @@ -16107,7 +16407,7 @@ bool OpdMakeWorker::ctrl() { const chara_init_data* chr_init_data = chara_init_data_get(chara_index); switch (state) { case 1: { - opd_make_manager->chara_costumes.PopItems(chara_index, items); + opd_make_manager->chara_data.PopItems(chara_index, items); for (int32_t i = 0; i < ITEM_SUB_MAX; i++) { rob_chr->item_cos_data.set_chara_index(chara_index); @@ -16125,40 +16425,41 @@ bool OpdMakeWorker::ctrl() { task_rob_load_append_load_req_data_obj(chara_index, rob_chr->item_cos_data.get_cos()); state = 3; } - } return false; + } break; case 3: { if (task_rob_load_check_load_req_data()) - return false; + break; rob_chr->item_cos_data.reload_items(chara_id, aft_bone_data, aft_data, aft_obj_db); for (int32_t i = ITEM_KAMI; i < ITEM_MAX; i++) { rob_chara_item_equip_object* itm_eq_obj = rob_chr->item_equip->get_item_equip_object((item_id)i); - if (aft_obj_db->get_object_name(itm_eq_obj->obj_info) && itm_eq_obj->osage_nodes_count) { - int32_t j = ITEM_ATAMA; - const object_info* k = chr_init_data->field_7E4; - object_info v14 = itm_eq_obj->obj_info; - for (; *k != v14; j++, k++) { - if (j < ITEM_KAMI) - continue; + if (!object_storage_get_obj_name(itm_eq_obj->obj_info) && itm_eq_obj->osage_nodes_count) + continue; - if (opd_make_manager->use_opdi) - state = 4; - else - state = 6; - return false; - } + int32_t j = ITEM_ATAMA; + const object_info* k = chr_init_data->field_7E4; + object_info v14 = itm_eq_obj->obj_info; + for (; *k != v14; j++, k++) { + if (j < ITEM_KAMI) + continue; + + if (opd_make_manager->use_opdi) + state = 4; + else + state = 6; + return false; } } state = 10; } break; case 4: { - data.ReadOpdiFiles(rob_chr, opd_make_manager->motion_ids, aft_data, aft_obj_db, aft_mot_db); + data.ReadOpdiFiles(rob_chr, opd_make_manager->motion_ids); state = 5; } break; case 5: { if (data.CheckOpdiFilesNotReady()) - return false; + break; state = 6; } case 6: { @@ -16171,47 +16472,49 @@ bool OpdMakeWorker::ctrl() { } break; case 7: { if (skin_param_manager_check_task_ready(chara_id)) - return false; + break; state = 8; } case 8: { + path_create_directory(get_ram_osage_play_data_tmp_dir()); opd_maker_array[chara_id].InitThread(rob_chr, &opd_make_manager->motion_ids, opd_make_manager->use_opdi ? &data : 0); state = 9; } break; case 9: { if (opd_maker_array[chara_id].IsWaiting()) - return false; + break; data.Reset(); + const char* ram_osage_play_data_path = get_ram_osage_play_data_dir(); const char* ram_osage_play_data_tmp_path = get_ram_osage_play_data_tmp_dir(); std::string chara_dir = sprintf_s_string("%s/%d", ram_osage_play_data_tmp_path, chara_id); - std::vector files = aft_data->get_directory_files(chara_dir.c_str()); - for (data_struct_file& i : files) { - if (!i.path.size() || !i.name.size()) + std::vector files = path_get_files(chara_dir.c_str()); + for (std::string& i : files) { + if (!i.size()) continue; - std::string tmp_path = sprintf_s_string("%s/%s", chara_dir.c_str(), i.name.c_str()); - std::string fs_copy_file_tmp_path = sprintf_s_string("%s/%s.fs_copy_file.tmp", ram_osage_play_data_tmp_path, i.name.c_str()); - std::string ram_path = sprintf_s_string("%s/%s", ram_osage_play_data_tmp_path, i.name.c_str()); + std::string tmp_path = sprintf_s_string("%s/%s", chara_dir.c_str(), i.c_str()); + std::string fs_copy_file_tmp_path = sprintf_s_string( + "%s/%s.fs_copy_file.tmp", ram_osage_play_data_tmp_path, i.c_str()); + std::string ram_path = sprintf_s_string("%s/%s", ram_osage_play_data_path, i.c_str()); if (!path_check_file_exists(tmp_path.c_str())) continue; - if (path_check_directory_exists(ram_osage_play_data_tmp_path) - && path_check_file_exists(fs_copy_file_tmp_path.c_str())) { - if (path_check_file_exists(ram_path.c_str())) - path_delete_file(ram_path.c_str()); - - if (!path_rename_file(fs_copy_file_tmp_path.c_str(), ram_path.c_str()) - && path_check_file_exists(fs_copy_file_tmp_path.c_str())) - path_delete_file(fs_copy_file_tmp_path.c_str()); + if (!path_check_directory_exists(ram_osage_play_data_tmp_path) + || !path_rename_file(tmp_path.c_str(), fs_copy_file_tmp_path.c_str())) { + path_delete_file(tmp_path.c_str()); + continue; } path_delete_file(tmp_path.c_str()); + + path_rename_file(fs_copy_file_tmp_path.c_str(), ram_path.c_str()); + path_delete_file(fs_copy_file_tmp_path.c_str()); } if (field_D4) @@ -16228,7 +16531,7 @@ bool OpdMakeWorker::ctrl() { rob_chr->item_cos_data.reload_items(chara_id, aft_bone_data, aft_data, aft_obj_db); skin_param_manager_reset(chara_id); - if (opd_make_manager->chara_costumes.CheckNoItems(chara_index)) + if (opd_make_manager->chara_data.CheckNoItems(chara_index)) return true; state = 1; } break; @@ -16251,6 +16554,14 @@ void OpdMakeWorker::disp() { } +bool OpdMakeWorker::add(bool a2) { + if (!task_rob_manager_check_chara_loaded(chara_id)) + return false; + + field_D4 = a2; + return app::TaskWork::add_task(this, "OPD_MAKE_WORKER"); +} + osage_play_data_header::osage_play_data_header() : frame_count(), nodes_count() { signature = 0x11033115; obj_info = { -1, -1 }; @@ -16277,6 +16588,20 @@ opd_farc_params::opd_farc_params() : compress(), encrypt() { align = 1; } +opd_farc_file::opd_farc_file() : offset(), size() { + +} + +opd_farc_file::opd_farc_file(const std::string& name, size_t offset, size_t size) { + this->name.assign(name); + this->offset = offset; + this->size = size; +} + +opd_farc_file::~opd_farc_file() { + +} + opd_farc::opd_farc() : stream(), farc_size() { } @@ -16289,15 +16614,18 @@ bool opd_farc::add_file(const void* data, size_t size, const std::string& name) if (!data || !size || !name.size() || !stream) return false; + size_t offset = stream->get_position(); stream->write(data, size); + files.push_back({ name, offset, size }); return true; } -bool opd_farc::open(const std::string& path, const opd_farc_params& data) { +bool opd_farc::open(const std::string& path, const opd_farc_params& params) { reset(); - if (!path.size() || !data.align || ((data.align - 1) & data.align)) + if (!path.size() || !params.align || ((params.align - 1) & params.align)) return 0; + this->params = params; this->path.assign(path); data_path.assign(path); data_path.append(".data"); @@ -16309,6 +16637,7 @@ bool opd_farc::open(const std::string& path, const opd_farc_params& data) { void opd_farc::reset() { path.clear(); params = {}; + files.clear(); data_path.clear(); if (stream) { delete stream; @@ -16321,63 +16650,69 @@ bool opd_farc::write_file() { std::string path_tmp(path); path_tmp.append(".tmp"); + file_stream fs; bool ret = false; - if (stream) { - stream->close(); - delete stream; + if (!stream) + goto End; - if (!path_delete_file(path.c_str())) { - file_stream data_fs; - data_fs.open(data_path.c_str(), "rb"); - if (data_fs.check_not_null() && data_fs.get_length()) { - size_t length = data_fs.length; - uint8_t* data = force_malloc(length); + stream->close(); - size_t len = data_fs.read(data, length); - if (len) { - bool compress = params.compress; - bool encrypt = params.encrypt; + delete stream; + stream = 0; - farc f; - farc_file* ff = f.add_file(data_path.c_str()); - ff->data = data; - ff->size = length; - ff->compressed = compress; - ff->encrypted = encrypt; - ff->data_changed = true; + if (!path_delete_file(path.c_str())) + goto End; - farc_signature signature; - farc_flags flags; - if (encrypt) { - signature = FARC_FARC; - flags = FARC_AES; + fs.open(data_path.c_str(), "rb"); + if (fs.check_not_null() && fs.get_length()) { + bool compress = params.compress; + bool encrypt = params.encrypt; + farc f; - if (compress) - enum_or(flags, FARC_GZIP); - } - else if (compress) { - signature = FARC_FArC; - flags = FARC_NONE; - } - else { - signature = FARC_FArc; - flags = FARC_NONE; - } - f.write(path_tmp.c_str(), signature, flags, false, false); - ret = true; - } - else - free_def(data); - } - - if (ret) { - path_delete_file(path.c_str()); - if (path_rename_file(path_tmp.c_str(), path.c_str())) - ret = false; + for (opd_farc_file& i : files) { + fs.set_position(i.offset, SEEK_SET); + uint8_t* data = force_malloc(i.size); + size_t len = fs.read(data, i.size); + if (len) { + farc_file* ff = f.add_file(i.name.c_str()); + ff->data = data; + ff->size = i.size; + ff->compressed = compress; + ff->encrypted = encrypt; + ff->data_changed = true; } } + + farc_signature signature; + farc_flags flags; + if (encrypt) { + signature = FARC_FARC; + flags = FARC_AES; + + if (compress) + enum_or(flags, FARC_GZIP); + } + else if (compress) { + signature = FARC_FArC; + flags = FARC_NONE; + } + else { + signature = FARC_FArc; + flags = FARC_NONE; + } + f.alignment = (uint32_t)params.align; + f.write(path_tmp.c_str(), signature, flags, false, false); + ret = true; + } + fs.close(); + + if (ret) { + path_delete_file(path.c_str()); + if (!path_rename_file(path_tmp.c_str(), path.c_str())) + ret = false; } +End: path_delete_file(data_path.c_str()); path_delete_file(path_tmp.c_str()); reset(); @@ -16385,7 +16720,7 @@ bool opd_farc::write_file() { } p_opd_farc::p_opd_farc() : ptr() { - + ptr = new opd_farc; } p_opd_farc::~p_opd_farc() { @@ -16399,8 +16734,8 @@ bool p_opd_farc::add_file(const void* data, size_t size, const std::string& file return ptr->add_file(data, size, file); } -bool p_opd_farc::open(const std::string& path, const opd_farc_params& data) { - return ptr->open(path, data); +bool p_opd_farc::open(const std::string& path, const opd_farc_params& params) { + return ptr->open(path, params); } bool p_opd_farc::open(const std::string& path, bool compress, size_t align) { @@ -16415,6 +16750,7 @@ bool p_opd_farc::write_file() { } opd_chara_data::opd_chara_data() : chara_id(), init(), frame_index(), frame_count(), motion_id(), field_18() { + chara_id = opd_chara_data_counter++; reset(); } @@ -16428,13 +16764,13 @@ void opd_chara_data::add_frame_data() { rob_chara_item_equip* rob_itm_equip = rob_chara_array_get(chara_id)->item_equip; for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++) { - rob_chara_item_equip_object* itm_eq_obj = rob_itm_equip->get_item_equip_object((item_id)(ITEM_KAMI + i)); + rob_chara_item_equip_object* itm_eq_obj + = rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i)); if (!itm_eq_obj->osage_nodes_count) continue; std::vector>& opd_data = this->opd_data[i]; - size_t node_index = 0; for (ExOsageBlock*& j : itm_eq_obj->osage_blocks) { std::vector& opd_node_data = opd_data.data()[node_index++]; @@ -16471,7 +16807,6 @@ void opd_chara_data::encode_data() { data_struct* aft_data = &data_list[DATA_AFT]; motion_database* aft_mot_db = &aft_data->data_ft.mot_db; - object_database* aft_obj_db = &aft_data->data_ft.obj_db; const char* motion_name = aft_mot_db->get_motion_name(this->motion_id); if (!motion_name) @@ -16487,26 +16822,30 @@ void opd_chara_data::encode_data() { p_opd_farc* opd = this->opd; for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++, opd++) { - rob_chara_item_equip_object* itm_eq_obj = rob_itm_equip->get_item_equip_object((item_id)(ITEM_KAMI + i)); + rob_chara_item_equip_object* itm_eq_obj + = rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i)); if (!itm_eq_obj->osage_nodes_count) continue; object_info obj_info = itm_eq_obj->obj_info; - const char* object_name = aft_obj_db->get_object_name(obj_info); + const char* object_name = object_storage_get_obj_name(obj_info); if (!object_name) continue; - std::vector>& opd_data = this->opd_data[i]; + const std::vector>& opd_data = this->opd_data[i]; size_t total_frame_count = 0; - for (std::vector& j : opd_data) - for (opd_vec3_data_vec& k : j) + for (const std::vector& j : opd_data) + for (const opd_vec3_data_vec& k : j) total_frame_count += k.x.size(); size_t max_size = sizeof(osage_play_data_header) + (6ULL * (frame_count + 2ULL) * total_frame_count); - uint8_t* data = force_malloc(max_size); + uint8_t* data = (uint8_t*)malloc(max_size); + if (!data) + continue; osage_play_data_header* opd_head = (osage_play_data_header*)data; + opd_head->signature = 0; opd_head->frame_count = frame_count; opd_head->motion_id = motion_id; opd_head->obj_info = { (uint16_t)obj_info.id, (uint16_t)obj_info.set_id }; @@ -16517,11 +16856,11 @@ void opd_chara_data::encode_data() { size_t osage_node_index = 0; bool higher_accuracy = false; - for (std::vector& j : opd_data) { + for (const std::vector& j : opd_data) { if (osage_node_index < itm_eq_obj->osage_blocks.size()) higher_accuracy = itm_eq_obj->osage_blocks.data()[osage_node_index]->has_children_node; - for (opd_vec3_data_vec& k : j) { + for (const opd_vec3_data_vec& k : j) { size_t size_x = 0; opd_encode_data(k.x, d, size_x, higher_accuracy); d += size_x; @@ -16554,7 +16893,6 @@ void opd_chara_data::encode_init_data(uint32_t motion_id) { data_struct* aft_data = &data_list[DATA_AFT]; motion_database* aft_mot_db = &aft_data->data_ft.mot_db; - object_database* aft_obj_db = &aft_data->data_ft.obj_db; const char* motion_name = aft_mot_db->get_motion_name(this->motion_id); if (!motion_name) @@ -16568,12 +16906,13 @@ void opd_chara_data::encode_init_data(uint32_t motion_id) { p_opd_farc* opdi = this->opdi; for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++, opdi++) { - rob_chara_item_equip_object* itm_eq_obj = rob_itm_equip->get_item_equip_object((item_id)(ITEM_KAMI + i)); + rob_chara_item_equip_object* itm_eq_obj + = rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i)); if (!itm_eq_obj->osage_nodes_count) continue; object_info obj_info = itm_eq_obj->obj_info; - const char* object_name = aft_obj_db->get_object_name(obj_info); + const char* object_name = object_storage_get_obj_name(obj_info); if (!object_name) continue; @@ -16632,7 +16971,8 @@ void opd_chara_data::init_data(uint32_t motion_id) { rob_chara_item_equip* rob_itm_equip = rob_chr->item_equip; int32_t frame_count = (int32_t)rob_chr->data.field_1588.field_0.frame; for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++) { - rob_chara_item_equip_object* itm_eq_obj = rob_itm_equip->get_item_equip_object((item_id)(ITEM_KAMI + i)); + rob_chara_item_equip_object* itm_eq_obj + = rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i)); if (!itm_eq_obj->osage_nodes_count) continue; @@ -16677,11 +17017,63 @@ void opd_chara_data::init_data(uint32_t motion_id) { } void opd_chara_data::open_opd_file() { + rob_chara* rob_chr = rob_chara_array_get(chara_id); + if (!rob_chr) + return; + rob_chara_item_equip* rob_itm_equip = rob_chr->item_equip; + + p_opd_farc* opd = this->opd; + for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++, opd++) { + rob_chara_item_equip_object* itm_eq_obj + = rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i)); + if (!itm_eq_obj->osage_nodes_count) + continue; + + const char* ram_osage_play_data_tmp_path = get_ram_osage_play_data_tmp_dir(); + path_create_directory(ram_osage_play_data_tmp_path); + + std::string chara_dir = sprintf_s_string("%s/%d", ram_osage_play_data_tmp_path, chara_id); + if (!path_check_directory_exists(chara_dir.c_str())) + path_create_directory(chara_dir.c_str()); + + const char* object_name = object_storage_get_obj_name(itm_eq_obj->obj_info); + if (!object_name) + continue; + + std::string tmp_path = sprintf_s_string("%s/%s.farc", chara_dir.c_str(), object_name); + opd->open(tmp_path.c_str(), true, 1); + } } void opd_chara_data::open_opdi_file() { + rob_chara* rob_chr = rob_chara_array_get(chara_id); + if (!rob_chr) + return; + rob_chara_item_equip* rob_itm_equip = rob_chr->item_equip; + + p_opd_farc* opdi = this->opdi; + for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++, opdi++) { + rob_chara_item_equip_object* itm_eq_obj + = rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i)); + if (!itm_eq_obj->osage_nodes_count) + continue; + + const char* ram_osage_play_data_tmp_path = get_ram_osage_play_data_tmp_dir(); + path_create_directory(ram_osage_play_data_tmp_path); + + std::string chara_dir = sprintf_s_string("%s/%d", ram_osage_play_data_tmp_path, rob_chr->chara_id); + if (!path_check_directory_exists(chara_dir.c_str())) + path_create_directory(chara_dir.c_str()); + + const char* object_name = object_storage_get_obj_name(itm_eq_obj->obj_info); + if (!object_name) + continue; + + std::string tmp_path = sprintf_s_string("%s/%s.opdi", chara_dir.c_str(), object_name); + opdi->open(tmp_path.c_str(), true, 1); + } } void opd_chara_data::reset() { @@ -16700,10 +17092,9 @@ void opd_chara_data::write_file() { return; rob_chara_item_equip* rob_itm_equip = rob_chr->item_equip; - for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++) { - if (rob_itm_equip->get_item_equip_object((item_id)(ITEM_KAMI + i))->osage_nodes_count) + for (int32_t i = 0; i < ITEM_OSAGE_COUNT; i++) + if (rob_itm_equip->get_item_equip_object((item_id)(ITEM_OSAGE_FIRST + i))->osage_nodes_count) opd[i].write_file(); - } } OsagePlayDataManager::OsagePlayDataManager() : state() { @@ -16745,14 +17136,6 @@ void OsagePlayDataManager::disp() { } -bool OpdMakeWorker::add(bool a2) { - if (!task_rob_manager_check_chara_loaded(chara_id)) - return false; - - field_D4 = a2; - return app::TaskWork::add_task(this, "OPD_MAKE_WORKER"); -} - bool OsagePlayDataManager::add() { return app::TaskWork::add_task(this, "OSAGE_PLAY_DATA_MANAGER"); } @@ -16799,7 +17182,6 @@ void OsagePlayDataManager::LoadOpdFile(p_file_handler* pfhndl) { void OsagePlayDataManager::LoadOpdFileList() { data_struct* aft_data = &data_list[DATA_AFT]; motion_database* aft_mot_db = &aft_data->data_ft.mot_db; - object_database* aft_obj_db = &aft_data->data_ft.obj_db; prj::sort_unique(opd_req_data); for (const std::pair& i : opd_req_data) { @@ -16807,7 +17189,7 @@ void OsagePlayDataManager::LoadOpdFileList() { if (elem != opd_file_data.end()) continue; - const char* object_name = aft_obj_db->get_object_name(i.first); + const char* object_name = object_storage_get_obj_name(i.first); if (!object_name) continue; @@ -16818,13 +17200,23 @@ void OsagePlayDataManager::LoadOpdFileList() { std::string obj_name_buf = string_to_lower(object_name); std::string mot_name_buf = string_to_lower(motion_name); - std::string file_buf = sprintf_s_string("%s_%s.%s", obj_name_buf.c_str(), mot_name_buf.c_str(), "opd"); - std::string farc_buf = sprintf_s_string("%s.farc", obj_name_buf.c_str()); + std::string file_buf = sprintf_s_string("%s_%s.%s", + obj_name_buf.c_str(), mot_name_buf.c_str(), "opd"); - if (aft_data->check_file_exists("rom/osage_play_data/", farc_buf.c_str())) { + std::string rom_farc_buf = sprintf_s_string("%s/%s.farc", + get_rom_osage_play_data_dir(), obj_name_buf.c_str()); + if (aft_data->check_file_exists(rom_farc_buf.c_str())) { file_handlers.push_back(new p_file_handler); - file_handlers.back()->read_file(aft_data, - "rom/osage_play_data/", farc_buf.c_str(), file_buf.c_str(), true); + file_handlers.back()->read_file(aft_data, rom_farc_buf.c_str(), file_buf.c_str(), true); + continue; + } + + std::string ram_farc_buf = sprintf_s_string("%s/%s.farc", + get_ram_osage_play_data_dir(), obj_name_buf.c_str()); + if (path_check_file_exists(ram_farc_buf.c_str())) { + file_handlers.push_back(new p_file_handler); + file_handlers.back()->read_file(0, ram_farc_buf.c_str(), file_buf.c_str(), true); + continue; } } opd_req_data.clear(); @@ -16836,6 +17228,65 @@ void OsagePlayDataManager::Reset() { opd_file_data.clear(); } +osage_play_data_database_struct::osage_play_data_database_struct() { + reset(); +} + +osage_play_data_database_struct::~osage_play_data_database_struct() { + reset(); +} + +size_t& osage_play_data_database_struct::find(const std::string& key) { + auto elem = map.find(key); + if (elem == map.end() || key.compare(elem->first) < 0) + elem = map.insert({ key, 0 }).first; + return elem->second; +} + +size_t& osage_play_data_database_struct::get_ver_by_name(size_t& ver, const std::string& name) { + ver = 0; + + auto elem = map.find(name); + if (elem == map.end()) + ver = elem->second; + return ver; +} + +void osage_play_data_database_struct::load(const std::string& path) { + data_struct* aft_data = &data_list[DATA_AFT]; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + + key_val kv; + aft_data->load_file(&kv, path.c_str(), key_val::load_file); + + if (!kv.open_scope("file")) { + kv.close_scope(); + return; + } + + uint32_t count = 0; + if (!kv.read("length", count) || !count) + return; + + for (uint32_t j = 0; j < count; j++) { + if (!kv.open_scope_fmt(j)) + continue; + + std::string name; + if (kv.read("name", name) && aft_obj_db->get_object_info(name.c_str()).not_null()) { + int32_t ver; + if (kv.read("ver", ver)) + find(name) = ver; + } + kv.close_scope(); + } + kv.close_scope(); +} + +void osage_play_data_database_struct::reset() { + map.clear(); +} + inline rob_osage_mothead_data::rob_osage_mothead_data(mothead_data_type type, uint32_t motion_id, const motion_database* mot_db) { data = 0; @@ -17132,61 +17583,108 @@ void rob_osage_mothead::set_sleeve_adjust(const mothead_data* mhd_data) { rob_bone_data->sleeve_adjust.radius = ((float_t*)data)[1]; } -OpdMakeManager::CharaConstume::CharaConstume() { +OpdMakeManager::CharaCostume::CharaCostume() { } -OpdMakeManager::CharaConstume::~CharaConstume() { +OpdMakeManager::CharaCostume::~CharaCostume() { } -OpdMakeManager::CharaConstumes::CharaConstumes() : count(), index() { +OpdMakeManager::CharaData::CharaData() : left(), count() { + Reset(); +} + +OpdMakeManager::CharaData::~CharaData() { } -OpdMakeManager::CharaConstumes::~CharaConstumes() { +void OpdMakeManager::CharaData::AddCostumes(const std::list>& costumes) { + for (const std::pair& i : costumes) { + const item_cos_data* cos = item_table_handler_array_get_item_cos_data(i.first, i.second); + for (int32_t j = 0; j < ITEM_SUB_MAX; j++) { + int32_t item_no = cos->arr[j]; + if (!item_no) + continue; + const item_table_item* item = item_table_handler_array_get_item(i.first, item_no); + if (!item) + continue; + + if (!(item->attr & 0x0C)) + chara_costumes[i.first].items[j].push_back(item_no); + else if (item->org_itm) + chara_costumes[i.first].items[j].push_back(item->org_itm); + } + } } -bool OpdMakeManager::CharaConstumes::CheckNoItems(chara_index chara_index) { - std::vector* _items = chara[chara_index].items; - for (int32_t i = 0; i < ITEM_SUB_MAX; i++, _items++) - if (_items->size()) +void OpdMakeManager::CharaData::AddObjects(const std::vector& customize_items) { + for (const std::string& i : customize_items) { + chara_index chara_index = CHARA_MAX; + int32_t item_no = 0; + customize_item_table_handler_data_get_chara_item(i, chara_index, item_no); + if (chara_index < CHARA_MIKU || chara_index >= CHARA_MAX || !item_no) + continue; + + const item_table_item* item = item_table_handler_array_get_item(chara_index, item_no); + if (!item) + continue; + + if (!(item->attr & 0x0C)) + chara_costumes[chara_index].items[item->sub_id].push_back(item_no); + else if (item->org_itm) + chara_costumes[chara_index].items[item->sub_id].push_back(item->org_itm); + } +} + +bool OpdMakeManager::CharaData::CheckNoItems(chara_index chara_index) { + std::vector* chara_items = chara_costumes[chara_index].items; + for (int32_t i = 0; i < ITEM_SUB_MAX; i++, chara_items++) + if (chara_items->size()) return false; return true; } -void OpdMakeManager::CharaConstumes::PopItems(chara_index chara_index, int32_t items[ITEM_SUB_MAX]) { - std::vector* _items = chara[chara_index].items; - for (int32_t i = 0; i < ITEM_SUB_MAX; i++, _items++) { +void OpdMakeManager::CharaData::PopItems(chara_index chara_index, int32_t items[ITEM_SUB_MAX]) { + std::vector* chara_items = chara_costumes[chara_index].items; + for (int32_t i = 0; i < ITEM_SUB_MAX; i++, chara_items++) { items[i] = 0; - if (!_items->size()) + if (!chara_items->size()) continue; - items[i] = _items->back(); - _items->pop_back(); - count--; + items[i] = chara_items->back(); + chara_items->pop_back(); + left--; } } -OpdMakeManager::Chara::Chara() : mode(), progress() { - chara = CHARA_MAX; +void OpdMakeManager::CharaData::Reset() { + for (CharaCostume& i : chara_costumes) + for (std::vector& j : i.items) + j.clear(); + + left = 0; + count = 0; } -OpdMakeManager::Chara::~Chara() { +void OpdMakeManager::CharaData::SortUnique() { + for (CharaCostume& i : chara_costumes) + for (std::vector& j : i.items) { + prj::sort_unique(j); + count += (uint32_t)j.size(); + } + left = count; } -OpdMakeManager::Data::Data() : mode(), count(), index() { +OpdMakeManager::OpdMakeManager() : mode(), workers(), field_1888(), use_opdi() { + mode = 0; + chara = CHARA_MIKU; -} - -OpdMakeManager::Data::~Data() { - -} - -OpdMakeManager::OpdMakeManager() : field_70(), mode(), workers(), field_1888(), use_opdi() { - chara = CHARA_MAX; + int32_t chara_id = 0; + for (OpdMakeWorker*& i : workers) + i = new OpdMakeWorker(chara_id++); } OpdMakeManager::~OpdMakeManager() { @@ -17198,10 +17696,10 @@ bool OpdMakeManager::init() { rctx_ptr->render_manager->set_pass_sw(rndr::RND_PASSID_3D, false); - if (path_check_directory_exists("ram/osage_play_data")) - RemoveDirectoryA("ram/osage_play_data"); + if (path_check_directory_exists(get_ram_osage_play_data_dir())) + path_delete_directory(get_ram_osage_play_data_dir()); - CreateDirectoryA("ram/osage_play_data", 0); + path_create_directory(get_ram_osage_play_data_dir()); if (field_1888 || !app::TaskWork::check_task_ready(task_rob_manager)) { task_rob_manager_add_task(); @@ -17252,15 +17750,15 @@ bool OpdMakeManager::ctrl() { break; } break; case 5: { - bool v8 = false; + bool has_items = false; for (int32_t i = 0; i < CHARA_MAX; i++) - if (!chara_costumes.CheckNoItems((chara_index)i)) { + if (!chara_data.CheckNoItems((chara_index)i)) { chara = (chara_index)i; - v8 = true; + has_items = true; break; } - if (v8) { + if (has_items) { for (int32_t i = 0; i < 4; i++) { rob_chara_pv_data pv_data; pv_data.type = ROB_CHARA_TYPE_3; @@ -17272,12 +17770,12 @@ bool OpdMakeManager::ctrl() { mode = 11; } break; case 6: { - bool v11 = false; + bool wait = false; for (int32_t i = 0; i < 4; i++) if (!task_rob_manager_check_chara_loaded(i)) - v11 = true; + wait = true; - if (!v11) { + if (!wait) { task_rob_manager->hide(); mode = 7; } @@ -17290,12 +17788,12 @@ bool OpdMakeManager::ctrl() { mode = 8; } break; case 8: { - bool v18 = false; + bool wait = false; for (OpdMakeWorker*& i : workers) if (app::TaskWork::check_task_ready(i)) - v18 = true; + wait = true; - if (!v18) + if (!wait) mode = field_1888 ? 12 : 9; } break; case 9: @@ -17322,8 +17820,8 @@ bool OpdMakeManager::ctrl() { break; } data.mode = mode; - data.count = (uint32_t)chara_costumes.count; - data.index = chara_costumes.index; + data.left = (uint32_t)chara_data.left; + data.count = (uint32_t)chara_data.count; return ret; } @@ -17349,9 +17847,8 @@ bool OpdMakeManager::dest() { rctx_ptr->render_manager->set_pass_sw(rndr::RND_PASSID_3D, true); - if (path_check_directory_exists("ram/osage_play_data")) - RemoveDirectoryA("ram/osage_play_data"); - + if (path_check_directory_exists(get_ram_osage_play_data_tmp_dir())) + path_delete_directory(get_ram_osage_play_data_tmp_dir()); return true; } @@ -17365,6 +17862,36 @@ bool OpdMakeManager::del() { return app::Task::del(); } +OpdMakeManagerData* OpdMakeManager::GetData() { + return &data; +} + +void OpdMakeManager::AddTask(const OpdMakeManagerArgs& args) { + if (app::TaskWork::check_task_ready(this) || !args.motion_ids) + return; + + chara_data.Reset(); + + if (args.modules) { + const std::vector& modules = module_data_handler_data_get_modules(); + std::list> costumes; + for (const uint32_t& i : *args.modules) + costumes.push_back({ modules[i].chara_index, modules[i].cos }); + chara_data.AddCostumes(costumes); + } + + if (args.objects) + chara_data.AddObjects(*args.objects); + + chara_data.SortUnique(); + + motion_ids.assign(args.motion_ids->begin(), args.motion_ids->end()); + this->field_1888 = args.field_18; + this->use_opdi = args.use_opdi; + + app::TaskWork::add_task(this, "OPD_MAKE_MANAGER"); +} + ReqData::ReqData() : chara_index(), count() { } diff --git a/src/CRE/rob/rob.hpp b/src/CRE/rob/rob.hpp index 570bbd2b..438fa02c 100644 --- a/src/CRE/rob/rob.hpp +++ b/src/CRE/rob/rob.hpp @@ -3576,6 +3576,70 @@ struct osage_init_data { ~osage_init_data(); }; +struct OpdMakeManagerArgs { + const std::vector* motion_ids; + const std::vector* modules; + const std::vector* objects; + bool field_18; + bool use_opdi; +}; + +struct OpdMakeManagerData { + struct Chara { + uint32_t mode; + uint32_t progress; + chara_index chara; + std::vector items; + + Chara(); + ~Chara(); + }; + + uint32_t mode; + uint32_t left; + uint32_t count; + std::vector charas; + + OpdMakeManagerData(); + ~OpdMakeManagerData(); +}; + +struct OpdChecker { + int32_t state; + int64_t field_8; + int64_t field_10; + int64_t field_18; + std::vector objects; + int32_t index; + int32_t size; + int32_t field_40; + bool terminated; + std::thread* thread; + std::mutex state_mtx; + std::mutex terminated_mtx; + std::mutex index_mtx; + + OpdChecker(); + ~OpdChecker(); + + bool CheckFileAdler32Checksum(const std::string& path); + bool CheckFileVersion(const std::string& path, uint32_t version); + bool CheckStateNot3(); + std::vector& GetObjects(); + void GetIndexSize(int32_t& index, int32_t& size); + int32_t GetState(); + bool GetTerminated(); + void LaunchThread(); + void SetIndexSize(int32_t index, int32_t size); + void SetState(int32_t value); + void SetTerminated(); + void TerminateThread(); + + static void ThreadMain(OpdChecker* opd_checker); + + void sub_140471020(); +}; + #define ROB_CHARA_COUNT 6 extern const chara_init_data* chara_init_data_get(chara_index chara_index); @@ -3595,7 +3659,24 @@ extern const float_t get_osage_gravity_const(); extern void motion_set_load_mothead(uint32_t set, std::string&& mdata_dir, const motion_database* mot_db); extern void motion_set_unload_mothead(uint32_t set); +extern const char* get_ram_osage_play_data_dir(); +extern const char* get_ram_osage_play_data_tmp_dir(); +extern const char* get_rom_osage_play_data_dir(); +extern const char* get_rom_osage_play_data_opdi_dir(); + +extern OpdChecker* opd_checker_get(); +extern bool opd_checker_check_state_not_3(); +extern bool opd_checker_has_objects(); +extern void opd_checker_launch_thread(); +extern void opd_checker_terminate_thread(); + +extern void opd_make_manager_add_task(const OpdMakeManagerArgs& args); +extern bool opd_make_manager_check_task_ready(); extern bool opd_make_manager_del_task(); +extern OpdMakeManagerData* opd_make_manager_get_data(); + +extern void opd_make_start(); +extern void opd_make_stop(); extern bool osage_play_data_manager_add_task(); extern void osage_play_data_manager_append_chara_motion_id(rob_chara* rob_chr, uint32_t motion_id); @@ -3606,6 +3687,8 @@ extern void osage_play_data_manager_get_opd_file_data(object_info obj_info, uint32_t motion_id, const float_t*& data, uint32_t& count); extern void osage_play_data_manager_reset(); +extern void osage_play_database_load(); + extern void pv_osage_manager_array_reset(int32_t chara_id); extern void rob_init(); diff --git a/src/CRE/rob/skin_param.cpp b/src/CRE/rob/skin_param.cpp index a5ef2b9c..ea9a2863 100644 --- a/src/CRE/rob/skin_param.cpp +++ b/src/CRE/rob/skin_param.cpp @@ -59,8 +59,8 @@ struct SkinParamManager : public app::Task { void AddFiles(); bool AddTask(std::vector& vec); bool CtrlFiles(); - int32_t GetExtSkpFile(const osage_init_data& osage_init, const std::string& dir, - std::string& file, void* data, motion_database* mot_db, object_database* obj_db); + int32_t GetExtSkpFile(const osage_init_data& osage_init, + const std::string& dir, std::string& file, void* data, motion_database* mot_db); std::vector* GetSkinParamFileData( object_info obj_info, uint32_t motion_id, int32_t frame); void Reset(); @@ -81,7 +81,7 @@ struct sp_skp_db { int32_t get_ext_skp_file(const osage_init_data& osage_init, const object_info obj_info, std::string& file, std::string& farc, - void* data, motion_database* mot_db, object_database* obj_db); + void* data, motion_database* mot_db); }; static bool osage_setting_data_load_file(void* data, const char* dir, const char* file, uint32_t hash); @@ -716,7 +716,6 @@ void SkinParamManager::AddFiles() { data_struct* aft_data = &data_list[DATA_AFT]; motion_database* aft_mot_db = &aft_data->data_ft.mot_db; - object_database* aft_obj_db = &aft_data->data_ft.obj_db; files.clear(); for (osage_init_data& i : osage_init) { @@ -726,7 +725,7 @@ void SkinParamManager::AddFiles() { if (obj_info.is_null()) continue; - const char* obj_name = aft_obj_db->get_object_name(obj_info); + const char* obj_name = object_storage_get_obj_name(obj_info); if (!obj_name) continue; @@ -769,8 +768,7 @@ void SkinParamManager::AddFiles() { skp_file->type = -1; if (i.dir.size()) { - skp_file->type = GetExtSkpFile(i, i.dir, - file, aft_data, aft_mot_db, aft_obj_db); + skp_file->type = GetExtSkpFile(i, i.dir, file, aft_data, aft_mot_db); if (skp_file->type != -1) dir.assign(i.dir); } @@ -778,7 +776,7 @@ void SkinParamManager::AddFiles() { bool read_farc = false; if (skp_file->type == -1) { skp_file->type = sp_skp_db_data->get_ext_skp_file(i, - obj_info, file, farc_file, aft_data, aft_mot_db, aft_obj_db); + obj_info, file, farc_file, aft_data, aft_mot_db); if (skp_file->type == -1) { delete skp_file; continue; @@ -907,8 +905,8 @@ bool SkinParamManager::CtrlFiles() { return !!files.size(); } -int32_t SkinParamManager::GetExtSkpFile(const osage_init_data& osage_init, const std::string& dir, - std::string& file, void* data, motion_database* mot_db, object_database* obj_db) { +int32_t SkinParamManager::GetExtSkpFile(const osage_init_data& osage_init, + const std::string& dir, std::string& file, void* data, motion_database* mot_db) { if (!dir.size()) return -1; @@ -1162,7 +1160,7 @@ void sp_skp_db::parse(key_val* kv) { int32_t sp_skp_db::get_ext_skp_file(const osage_init_data& osage_init, const object_info obj_info, std::string& file, std::string& farc, - void* data, motion_database* mot_db, object_database* obj_db) { + void* data, motion_database* mot_db) { if (obj_info.is_null()) return 2; @@ -1207,7 +1205,7 @@ int32_t sp_skp_db::get_ext_skp_file(const osage_init_data& osage_init, } } - const char* obj_name = obj_db->get_object_name(obj_info); + const char* obj_name = object_storage_get_obj_name(obj_info); sprintf_s(buf0, buf0_size, "ext_skp_%s.txt", obj_name); if (type == 1) { diff --git a/src/KKdLib/database/item_table.hpp b/src/KKdLib/database/item_table.hpp index 2eea46bb..2ff1eca2 100644 --- a/src/KKdLib/database/item_table.hpp +++ b/src/KKdLib/database/item_table.hpp @@ -63,6 +63,7 @@ enum item_id { ITEM_ITEM16 = 0x1E, ITEM_MAX = 0x1F, + ITEM_OSAGE_FIRST = ITEM_KAMI, ITEM_OSAGE_COUNT = (ITEM_MAX - ITEM_KAMI), }; diff --git a/src/ReDIVA/print_work.cpp b/src/ReDIVA/print_work.cpp index d181f1ee..44c4b093 100644 --- a/src/ReDIVA/print_work.cpp +++ b/src/ReDIVA/print_work.cpp @@ -422,6 +422,12 @@ void PrintWork::SetResolutionMode(::resolution_mode value) { resolution_mode = value; } +void PrintWork::set_text_position(float_t column, float_t line) { + line_origin_loc.x = (font->spacing.x + font->glyph.x * font->font_ptr->column_scale) * column; + line_origin_loc.y = (font->spacing.y + font->glyph.y) * line; + text_current_loc = line_origin_loc; +} + void PrintWork::printf(app::text_flags flags, const char* fmt, ...) { va_list args; va_start(args, fmt); diff --git a/src/ReDIVA/print_work.hpp b/src/ReDIVA/print_work.hpp index ddfc6427..2e7740ae 100644 --- a/src/ReDIVA/print_work.hpp +++ b/src/ReDIVA/print_work.hpp @@ -86,6 +86,7 @@ struct PrintWork { void PutText(app::text_flags flags, const wchar_t* str_begin, const wchar_t* str_end); void SetFont(const font_info* value); void SetResolutionMode(::resolution_mode value); + void set_text_position(float_t column, float_t line); void printf(app::text_flags flags, const char* fmt, ...); void printf_align_left(const char* fmt, ...); diff --git a/src/ReDIVA/render.cpp b/src/ReDIVA/render.cpp index 4b4c79e8..ccd69734 100644 --- a/src/ReDIVA/render.cpp +++ b/src/ReDIVA/render.cpp @@ -173,7 +173,7 @@ int32_t height; static const double_t aspect = 16.0 / 9.0; -static const int32_t fast_loader_speed = 60; +static const int32_t fast_loader_speed = 1; bool light_chara_ambient; vec4 npr_cloth_spec_color = 1.0f; @@ -639,6 +639,8 @@ static render_context* render_context_load() { task_data_test_glitter_particle_init(); x_pv_game_data_init(); + osage_play_database_load(); + Glitter::glt_particle_manager->bone_data = aft_bone_data; #if defined(CRE_DEV) diff --git a/src/ReDIVA/system_startup.cpp b/src/ReDIVA/system_startup.cpp index 1e017e4e..cb6c9a89 100644 --- a/src/ReDIVA/system_startup.cpp +++ b/src/ReDIVA/system_startup.cpp @@ -1,4 +1,4 @@ -/* +/* by korenkonder GitHub/GitLab: korenkonder */ @@ -7,25 +7,96 @@ #include "../CRE/auth_2d.hpp" #include "../CRE/mdata_manager.hpp" #include "../CRE/sprite.hpp" +#include "../KKdLib/io/path.hpp" #include "pv_game/pv_game.hpp" +#include "input_state.hpp" #include "game_state.hpp" - -system_startup_detail::TaskSystemStartup* task_system_startup; +#include "print_work.hpp" struct system_startup_struct { int32_t state; int32_t wait; + int32_t time; + int32_t dhcp_wait_time; + int32_t field_10; + int32_t touch_panel_state; + int32_t field_18; + bool field_1C; bool ready; + int64_t field_20; + int32_t location_server_state; + int32_t net_param_state; + int32_t field_30; + int32_t field_34; + int32_t field_38; + int32_t frame; + int32_t field_44; + int32_t field_48; + int32_t field_4C; + color4u8 field_50; + int32_t card_system_state; + int32_t touch_slider_state; + int32_t all_net_state; + int32_t pv_information_state; + int32_t field_64; + int32_t extended_data_state; + int32_t printer_state; + bool field_70; + font_info font; + PrintWork print_work; + + system_startup_struct(); +}; + +class SSOpdMakeTask : public app::Task { +public: + int32_t frame; + PrintWork print_work; + font_info font_info; + int32_t state; + bool skip_check; + bool skip_make; + + SSOpdMakeTask(); + virtual ~SSOpdMakeTask() override; + + virtual bool init() override; + virtual bool ctrl() override; + virtual bool dest() override; + virtual void disp() override; + + bool add(); + std::string GetStateString(); + void SetSkipCheck(bool value); + void SetSkipMake(bool value); }; extern render_context* rctx_ptr; -system_startup_struct system_startup; +SSOpdMakeTask* ss_opd_make_task; +system_startup_struct* system_startup; +system_startup_detail::TaskSystemStartup* task_system_startup; -int32_t system_startup_ready; +int32_t system_startup_ready = 0; + +int32_t ss_opd_make_task_percentage_line_width = 85; + +static void ss_opd_make_start(); +static SSOpdMakeTask* ss_opd_make_task_get(); static bool system_startup_check_ready(); +std::string system_startup_get_wait(size_t size, size_t frame); + +static void system_startup_extended_data_ctrl(); +static void system_startup_extended_data_disp(); + +static void system_startup_pv_information_ctrl(); +static void system_startup_pv_information_dest(); +static void system_startup_pv_information_disp(); + +static void task_pv_db_reset(); + namespace system_startup_detail { TaskSystemStartup::TaskSystemStartup() { @@ -36,44 +107,110 @@ namespace system_startup_detail { } bool TaskSystemStartup::init() { - system_startup.state = 0; - system_startup.wait = 0; - system_startup.ready = false; + system_startup->state = 0; + system_startup->wait = 0; + if (test_mode_get()) + system_startup->time = 3600; + else + system_startup->time = 7200; + system_startup->dhcp_wait_time = 36000; + system_startup->field_10 = 0; + system_startup->touch_panel_state = 0; + system_startup->field_18 = 0; + system_startup->field_1C = false; + system_startup->ready = false; + system_startup->field_20 = 0; + system_startup->location_server_state = 0; + system_startup->net_param_state = 0; + system_startup->field_30 = 0; + system_startup->field_34 = 0; + system_startup->field_38 = 36000; + system_startup->frame = 0; + system_startup->field_44 = 1; + system_startup->field_48 = 0; + system_startup->field_4C = 0; + system_startup->field_50 = 0xFF4EA8C0; + system_startup->card_system_state = 0; + system_startup->touch_slider_state = 0; + system_startup->all_net_state = 0; + system_startup->pv_information_state = 0; + system_startup->field_64 = 0; + system_startup->extended_data_state = 0; + system_startup->printer_state = 0; + system_startup->field_70 = false; + + system_startup->field_10++; + + system_startup->font.init_font_data(16); + system_startup->print_work.SetFont(&system_startup->font); + system_startup->print_work.color = color_white; return true; } bool TaskSystemStartup::ctrl() { + system_startup->frame++; system_startup_ready = 0; - switch (system_startup.state) { + switch (system_startup->state) { case 0: - system_startup.state = 1; + system_startup->state = 1; case 1: - system_startup.state = 2; + system_startup->state = 2; break; case 2: - mdata_manager_add_task(); - system_startup.state = 3; + system_startup->state = 3; break; - case 3: + case 3: { + system_startup_pv_information_ctrl(); + system_startup_extended_data_ctrl(); + + //if (system_startup->location_server_state < 0 && system_startup->net_param_state < 0 + // && system_startup->field_1C && system_startup->pv_information_state < 0 + // && system_startup->extended_data_state < 0 && (test_mode_get() || system_startup->all_net_state < 0)) + if (system_startup->pv_information_state < 0 && system_startup->extended_data_state < 0) + if (test_mode_get()) + system_startup->state = 6; + else { + system_startup->state = 4; + system_startup->field_10++; + } + + if (!system_startup->field_10) + system_startup->time--; + + bool v1 = false; + if (test_mode_get() && input_state_get(0)->CheckTapped(1)) + v1 = true; + + if (system_startup->time >= 0 && !v1) + break; + + system_startup_pv_information_dest(); + + if (test_mode_get()) + system_startup->state = 6; + else { + system_startup->state = 4; + system_startup->field_10++; + } if (!app::TaskWork::check_task_ready(mdata_manager_get())) - system_startup.state = 4; - break; + system_startup->state = 4; + } break; case 4: rctx_ptr->render_manager->set_pass_sw(rndr::RND_PASSID_3D, false); task_pv_game_init_test_pv(); - system_startup.state = 5; + system_startup->state = 5; break; case 5: if (!task_pv_game_check_task_ready() && system_startup_check_ready()) - system_startup.state = 6; + system_startup->state = 6; break; case 6: - system_startup.wait = 0;//120; - system_startup.state = 7; + system_startup->wait = 0;//120; + system_startup->state = 7; break; case 7: - if (system_startup.wait-- < 0) - system_startup.state = 8; + if (system_startup->wait-- < 0) + system_startup->state = 8; break; case 8: rctx_ptr->render_manager->set_pass_sw(rndr::RND_PASSID_3D, true); @@ -87,7 +224,7 @@ namespace system_startup_detail { if (task_pv_game_check_task_ready() && !system_startup_check_ready()) return false; - opd_make_manager_del_task(); + opd_make_stop(); mdata_manager_del_task(); return true; } @@ -96,10 +233,115 @@ namespace system_startup_detail { resolution_struct* res_wind = res_window_get(); spr::put_sprite_rect({ 0.0f, 0.0f, (float_t)res_wind->width, (float_t)res_wind->height }, res_wind->resolution_mode, spr::SPR_PRIO_25, color_black, 0); + + system_startup->print_work.prio = spr::SPR_PRIO_25; + system_startup->print_work.color = color_white; + system_startup->print_work.SetResolutionMode(RESOLUTION_MODE_HD); + system_startup->print_work.set_text_position(7.0f, 3.0f); + + switch (system_startup->state) { + case 0: + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + "SYSTEM INITIALIZE..."); + break; + case 1: { + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "DHCP WAIT "); + std::string buf = system_startup_get_wait(8, get_frame_counter() / 15); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + + if (36000 - system_startup->dhcp_wait_time >= 900) { + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + u8"ALL.Net用ルーターなどの\n"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + u8"ネットワーク機器の接続や\n"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + u8"起動順序を確認して下さい。\n"); + + std::string buf = sprintf_s_string("%d\n", system_startup->dhcp_wait_time); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + } + + if (test_mode_get()) { + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + "PRESS SERVICE BUTTON TO CANCEL\n"); + } + } break; + default: + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "SYSTEM STARTUP "); + + switch (0 /*sub_14066D190()*/) { + case 0: { + std::string buf = sprintf_s_string("(SATELLITE:%s)", false /*sub_14066E890()*/ ? "MAIN" : "SUB"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + } break; + case 1: + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "(SERVER)"); + break; + default: + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "(UNKNOWN)"); + break; + } + + system_startup->print_work.set_text_position(7.0, 4.0); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n\n"); + + //system_startup_touch_panel_disp(); + //system_startup_card_system_disp(); + //system_startup_touch_slider_bd_disp(); + //system_startup_all_net_disp(); + //system_startup_location_server_disp(); + system_startup_pv_information_disp(); + //system_startup_net_param_disp(); + system_startup_extended_data_disp(); + //system_startup_printer_disp(); + + switch (system_startup->state) { + case 2: + if (36000 - system_startup->dhcp_wait_time >= 900) { + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + u8"メイン機までの接続は正常です。ALL.Net用ルーターなどの\n"); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + u8"ネットワーク機器の接続や起動順序を確認して下さい。\n"); + + std::string buf = sprintf_s_string("%d\n", system_startup->dhcp_wait_time); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + } + break; + } + + if ((unsigned int)(system_startup->state - 3) <= 2) { + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + if (system_startup->field_10) { + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "TIME STOP "); + std::string buf = system_startup_get_wait(8, system_startup->frame / 15); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + } + else { + std::string buf = sprintf_s_string("TIME %d\n", system_startup->time); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + } + + if (test_mode_get()) + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + "PRESS SERVICE BUTTON TO CANCEL\n"); + } + break; + } } } bool task_system_startup_add_task() { + if (!ss_opd_make_task) + ss_opd_make_task = new SSOpdMakeTask; + + if (!system_startup) + system_startup = new system_startup_struct; + if (!task_system_startup) task_system_startup = new system_startup_detail::TaskSystemStartup; @@ -110,6 +352,12 @@ bool task_system_startup_del_task() { if (!app::TaskWork::check_task_ready(task_system_startup)) { delete task_system_startup; task_system_startup = 0; + + delete system_startup; + system_startup = 0; + + delete ss_opd_make_task; + ss_opd_make_task = 0; return true; } @@ -124,8 +372,197 @@ void task_system_startup_free() { } } +system_startup_struct::system_startup_struct() : state(), wait(), time(), dhcp_wait_time(), +field_10(), touch_panel_state(), field_18(), field_1C(), ready(), field_20(), +location_server_state(), net_param_state(), field_30(), field_34(), field_38(), frame(), +field_44(), field_48(), field_4C(), card_system_state(), touch_slider_state(), all_net_state(), +pv_information_state(), field_64(), extended_data_state(), printer_state(), field_70() { + +} + +SSOpdMakeTask::SSOpdMakeTask() : frame() { + state = 1; + skip_check = true; + skip_make = true; +} + +SSOpdMakeTask:: ~SSOpdMakeTask() { + +} + +bool SSOpdMakeTask::init() { + frame = 0; + font_info.init_font_data(16); + print_work.SetFont(&font_info); + print_work.color = color_white; + print_work.prio = spr::SPR_PRIO_25; + + skip_check = true; + skip_make = true; + + if (path_check_directory_exists(get_ram_osage_play_data_tmp_dir())) + path_delete_directory(get_ram_osage_play_data_tmp_dir()); + return true; +} + +bool SSOpdMakeTask::ctrl() { + switch (state) { + case 1: + frame++; + state = 3; + break; + case 2: + if (++frame < 300) { + frame++; + break; + } + + frame++; + state = 3; + break; + case 3: + if (skip_check) { + frame++; + break; + } + + opd_checker_launch_thread(); + frame++; + state = 4; + break; + case 4: + if (opd_checker_check_state_not_3()) { + frame++; + break; + } + + frame++; + state = opd_checker_has_objects() ? 5 : 8; + break; + case 5: + if (skip_make) { + frame++; + break; + } + + ss_opd_make_start(); + frame++; + state = 6; + break; + case 6: + if (opd_make_manager_check_task_ready()) { + frame++; + break; + } + + frame = 0; + frame++; + state = 7; + break; + case 7: + if (frame < 60) { + frame++; + break; + } + + frame++; + state = 8; + break; + case 8: + frame++; + return true; + } + return false; +} + +bool SSOpdMakeTask::dest() { + return true; +} + +void SSOpdMakeTask::disp() { + OpdMakeManagerData* opd_make_manager_data = opd_make_manager_get_data(); + print_work.set_text_position(7.0f, 19.0f); + print_work.SetResolutionMode(RESOLUTION_MODE_HD); + + if (state != 6 && state != 7) + return; + + print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + u8"拡張データをインストール中です。電源を切らないで下さい。\n"); + print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, + "Installing the extended data. Please do not turn off the power.\n"); + print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); + uint32_t count = opd_make_manager_data->count; + if (!count) + return; + + static const char rotating_cursor_array[] = { + '-', '\\', '|', '/', '-', '\\', '|', '/' + }; + + int32_t percentage = 100 * (count - opd_make_manager_data->left) / count; + if (state == 6 && percentage >= 100) + percentage = 99; + + int32_t disp = max_def(percentage * ss_opd_make_task_percentage_line_width / 100, 0); + + std::string buf("|"); + for (int32_t i = 0; i < disp; i++) + buf.append("*"); + + if (state == 6) + buf.append(1, rotating_cursor_array[(frame / 4) % 8]); + + for (int32_t i = 0; i < ss_opd_make_task_percentage_line_width - disp - 1; i++) + buf.append("."); + buf.append("|"); + buf.append(sprintf_s_string(" (%3d%%)", percentage)); + print_work.printf_align_left("%s\n", buf.c_str()); +} + +bool SSOpdMakeTask::add() { + return app::TaskWork::add_task(this, "SSOpdMakeTask"); +} + +std::string SSOpdMakeTask::GetStateString() { + std::string str = sprintf_s_string("WAIT %d ", state); + switch (state) { + case 4: { + int32_t index = 0; + int32_t size = 0; + opd_checker_get()->GetIndexSize(index, size); + if (size) + str.append(sprintf_s_string("(%d/%d) ", index, size)); + } break; + case 6: { + OpdMakeManagerData* opd_make_manager_data = opd_make_manager_get_data(); + uint32_t count = opd_make_manager_data->count; + if (count) + str.append(sprintf_s_string("(%d/%d) ", count - opd_make_manager_data->left, count)); + } break; + } + return str; +} + +void SSOpdMakeTask::SetSkipCheck(bool value) { + skip_check = value; +} + +void SSOpdMakeTask::SetSkipMake(bool value) { + skip_make = value; +} + +static void ss_opd_make_start() { + opd_make_start(); + ss_opd_make_task_get()->add(); +} + +static SSOpdMakeTask* ss_opd_make_task_get() { + return ss_opd_make_task; +} + static bool system_startup_check_ready() { - if (test_mode_get() || system_startup.ready) + if (test_mode_get() || system_startup->ready) return true; task_pv_game_del_task(); @@ -133,9 +570,134 @@ static bool system_startup_check_ready() { //task_mask_screen_fade_in(0.0f, 0); rctx_ptr->render_manager->set_multisample(true); if (task_rob_manager_del_task()) { - system_startup.ready = true; + system_startup->ready = true; return true; } } - return system_startup.ready; + return system_startup->ready; +} + +static void system_startup_extended_data_ctrl() { + if (test_mode_get()) { + system_startup->extended_data_state = -1; + return; + } + + switch (system_startup->extended_data_state) { + case 0: + system_startup->field_10++; + ss_opd_make_task_get()->add(); + system_startup->extended_data_state = 1; + break; + case 1: + //if (system_startup->aime_state < 0) + ss_opd_make_task_get()->SetSkipCheck(false); + + //if (system_startup->location_server_state < 0 && system_startup->net_param_state < 0 + // && system_startup->field_1C && system_startup->net_param_state < 0 + // && system_startup->pv_information_state < 0 && system_startup->all_net_state < 0) + if (system_startup->pv_information_state < 0) + ss_opd_make_task_get()->SetSkipMake(false); + + if (!app::TaskWork::check_task_ready(ss_opd_make_task_get())) { + system_startup->extended_data_state = -1; + system_startup->field_10--; + } + break; + } +} + +static void system_startup_extended_data_disp() { + if (test_mode_get()) + return; + + std::string buf("EXTENDED DATA : "); + + switch (system_startup->extended_data_state) { + case -2: + buf.append("NG"); + break; + case -1: + buf.append("OK"); + break; + default: + buf.append(ss_opd_make_task_get()->GetStateString()); + break; + } + + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); +} + +std::string system_startup_get_wait(size_t size, size_t frame) { + std::string str; + str.resize(size / 2 + 1, '.'); + size_t pos = frame % ((size / 2) * 2); + if (pos >= size / 2) + str[size / 2 * 2 - pos] = 'o'; + else + str[pos] = 'o'; + return str; +} + +static void system_startup_pv_information_ctrl() { + switch (system_startup->pv_information_state) { + case -1: + break; + case 0: + /*if (system_startup->aime_state < 0)*/ { + mdata_manager_get(); + mdata_manager_add_task(); + system_startup->pv_information_state = 1; + } + break; + case 1: + /*if (system_startup->field_28 < 0) + mdata_manager_get()->field_179 = true;*/ + + if (!app::TaskWork::check_task_ready(mdata_manager_get())) { + system_startup->field_10--; + system_startup->pv_information_state = -1; + } + break; + default: + system_startup->pv_information_state = -2; + break; + } +} + +static void system_startup_pv_information_dest() { + if ((unsigned int)(system_startup->pv_information_state + 2) > 1) { + //mdata_manager_get()->field_179 = true; + task_pv_db_reset(); + system_startup->field_10--; + system_startup->pv_information_state = -2; + } +} + +static void system_startup_pv_information_disp() { + std::string buf( "PV INFORMATION : "); + switch (system_startup->pv_information_state) { + case -2: + buf.append("NG"); + break; + case -1: + buf.append("OK"); + break; + default: + if (!app::TaskWork::check_task_ready(mdata_manager_get())) + buf.append("WAIT"); + else + buf.append(mdata_manager_get()->GetStateString()); + break; + } + + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, buf.data(), buf.size()); + system_startup->print_work.PrintText(app::TEXT_FLAG_ALIGN_FLAG_LEFT, "\n"); +} + +static void task_pv_db_reset() { + pv_db::TaskPvDB* task_pv_db = task_pv_db_get(); + task_pv_db->reset = true; + task_pv_db->field_99 = true; }