/** * @file RSEModel.c * @date 19/08/2022 * @author JackCarterSmith * @copyright GPL-v3.0 * @brief HOB model parser and export to Waveform OBJ format. * */ #include #include #include #if defined(_WIN32) #include #include #define F_OK 0 #define access _access #else #include #include #include #endif #include "options.h" #include #include #include "model_export.h" #include "lib_interface.h" #define MAX_STR_VAR 1024 /* * Internal functions declarations */ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* opt_ptr); static void createSubDir(char *dirName); static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]); static void dispHelp(); /* * - MAIN - */ int main(int argc, char *argv[]) { T_PROG_OPTIONS _opts = {0}; unsigned char p; unsigned int status = RSPLIB_SUCCESS; // Hello world! printf("\n*~[ Rogue Squadron Extractor (RSE) - RSPModelLib v%s ]~*\n\n", RSPModel_getVersion()); // Try linking to externals modules linkTextureLib(&_opts); // Check for arguments if (argc < 2) { printf("[ERR] No input file/commands specified!\n"); dispHelp(); return RSPLIB_ERROR_ARGS_NULL; } // Create options for programs according to user's arguments. p = checkInputArgs(&_opts, argc, argv); if ( p == RSPLIB_ERROR_GENERIC ) return RSPLIB_SUCCESS; else if ( p != RSPLIB_SUCCESS ) return p; status = mainProcess(argc, argv, &_opts); unlinkTextureLib(); return status; } /* * Private functions definition */ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* p_opts) { unsigned short file_index; RSPMODEL_PARAMETERS libParams; T_RSPMODEL_HOB* hobStruct = NULL; char hmt_filename[MAX_STR_VAR] = {0}; void* hmtStruct = NULL; unsigned int i; libParams.raw = p_opts->raw & 0x7; // Manage multiple inputs files for ( file_index = p_opts->input_files_cnt; file_index < args_cnt; file_index++) { printf("\n=============================================\n[INFO] - Parsing file: %s ...\n", args_value[file_index]); // Allocate T_RSPMODEL_HOB structure to store extracted datas. hobStruct = calloc(1, sizeof(T_RSPMODEL_HOB)); if (hobStruct) { // Parse data from HOB file and put in T_RSPMODEL_HOB structure. if (RSPModel_processHOBFile(hobStruct, args_value[file_index], libParams) != RSPLIB_SUCCESS) { printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]); RSPModel_freeHOB(hobStruct); return RSPLIB_ERROR_PROCESS; } // If Texture module loaded, process HMT file for mtl naming (doesn't extract texture!) if (p_opts->texture_module) { if (strlen(args_value[file_index]) >= MAX_STR_VAR) return RSPLIB_ERROR_GENERIC; strncpy(hmt_filename, args_value[file_index], strlen(args_value[file_index]) - 3); hmt_filename[strlen(args_value[file_index]) - 1] = 0; //C6053 fix strncat(hmt_filename, "HMT", strlen(args_value[file_index])); if (access(hmt_filename, F_OK) == 0) { hmtStruct = RSPTexture_createHMT(); RSPTexture_processHMTFile(hmtStruct, hmt_filename, 0); } else { printf("[ERR] HMT file '%s' not found for mtl processing!\n", hmt_filename); return RSPLIB_ERROR_GENERIC; } } } else return RSPLIB_ERROR_MEMORY; if (hobStruct->obj_count > 0) { // Create output folders structure. if (p_opts->output_dir) createSubDir(args_value[file_index]); for ( i = 0; i < hobStruct->obj_count; i++ ) { if (exportOBJModel(&(hobStruct->objects[i]), args_value[file_index], hmtStruct, p_opts) == RSPLIB_SUCCESS) printf("[INFO] Successfully exported %s object in OBJ format.\n", hobStruct->objects[i].name); else printf("[ERR] Failed to export %s object in OBJ format!\n", hobStruct->objects[i].name); } } if (p_opts->texture_module) RSPTexture_freeHMT(hmtStruct); } RSPModel_freeHOB(hobStruct); return RSPLIB_SUCCESS; } static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]) { char test[256]; int i; // Set default options opt_ptr->output_dir = 1; if (p_arg_nbr > 1) { for ( i = 1; i < p_arg_nbr; i++) { strcpy(test, p_args[i]); if (p_args[i][0] != '-') break; if (strcmp(p_args[i], "-h") == 0) { dispHelp(); return RSPLIB_ERROR_GENERIC; } else if (strcmp(p_args[i], "-v") == 0) { opt_ptr->verbose_mode = 1; printf("[OPTN] Verbose enabled.\n"); } else if (strcmp(p_args[i], "-vv") == 0) { opt_ptr->verbose_mode = 1; opt_ptr->debug_mode = 1; printf("[OPTN] Debug enabled.\n"); } else if (strcmp(p_args[i], "-vvv") == 0) { opt_ptr->verbose_mode = 1; opt_ptr->debug_mode = 1; opt_ptr->god_mode = 1; printf("[OPTN] God damn it!\n"); } else if (strcmp(p_args[i], "-no-subdir") == 0) { opt_ptr->output_dir = 0; printf("[OPTN] Export to current directory.\n"); } else if (strcmp(p_args[i], "-mtl") == 0) { if (opt_ptr->texture_module) { opt_ptr->export_mtl = 1; printf("[OPTN] Export materials datas.\n"); } else { printf("[OPTN] Can't export materials datas, RSPTextureLib not found or incorrect version!\n"); } } else { printf("[ERR] Unknown option: %s\n", p_args[i]); } } opt_ptr->input_files_cnt = i; return RSPLIB_SUCCESS; } return RSPLIB_ERROR_ARGS_NULL; } static void createSubDir(char *dirName) { if (dirName == NULL) return; char _dir[1024]; snprintf(_dir, 1024, "%s-out", dirName); #ifdef _WIN32 CreateDirectory(_dir, NULL); #else mkdir(_dir, 0755); #endif } static void dispHelp() { printf("\n"); printf("Options:\n -h Print this message\n"); printf(" -v -vv Activate verbose console output\n"); printf(" -no-subdir Export models inside current folder\n"); printf(" -mtl Export materials datas with model\n"); printf("\n"); printf("Usage: RSEModel [options] \n"); printf("\n"); }