Added MSVC support and cleaned degug infos #8

Merged
JackCarterSmith merged 3 commits from develop into master 2022-07-29 21:35:12 +02:00
11 changed files with 231 additions and 145 deletions

View File

@ -42,10 +42,10 @@ add_executable(rse-model ${RSE_MOD_SRCS} ${RSE_MOD_HRDS})
set_target_properties(rse-model PROPERTIES OUTPUT_NAME ${RSE_MOD_NAME}) set_target_properties(rse-model PROPERTIES OUTPUT_NAME ${RSE_MOD_NAME})
if(MSVC) if(MSVC)
# msvc does not append 'lib' - do it here to have consistent name # msvc does not append 'lib' - do it here to have consistent name
set_target_properties(rse-model PROPERTIES PREFIX "lib") #set_target_properties(rse-model PROPERTIES PREFIX "lib")
set_target_properties(rse-model PROPERTIES IMPORT_PREFIX "lib") set_target_properties(rse-model PROPERTIES IMPORT_PREFIX "lib")
endif() endif()
target_link_libraries(rse-model m) target_link_libraries(rse-model)
# add GPG signature command # add GPG signature command
#add_custom_command( #add_custom_command(

2
Jenkinsfile vendored
View File

@ -5,7 +5,7 @@ pipeline {
} }
environment { environment {
CI_OUTPUT_NAME = "RSE_Model" CI_OUTPUT_NAME = "RSE_Model"
CI_VERSION = "1.0.0" CI_VERSION = "1.0.1"
CI_BUILD_NUMBER = "$BUILD_NUMBER" CI_BUILD_NUMBER = "$BUILD_NUMBER"
} }
stages { stages {

View File

@ -46,7 +46,7 @@ Due to issue with copyrights, I can't provide samples... You need to extract HOB
You can compile on both Windows (MinGW) or native Linux system thanks to CMake. You can compile on both Windows (MinGW) or native Linux system thanks to CMake.
To compile, just clone and launch cmake: To compile, just clone (**don't forget git submodules**) and launch cmake:
```shell ```shell
cmake . cmake .

View File

@ -1,10 +1,9 @@
/* /**
================================================================================ * \file Model-Extractor.c
Name : Model-Extractor.c * \date 25/07/2022
Author : JackCarterSmith * \author JackCarterSmith
License : GPL-v3.0 * \copyright GPL-v3.0
Description : HOB model parser and export to Waveform OBJ format. * \brief HOB model parser and export to Waveform OBJ format.
================================================================================
*/ */
#include <stdio.h> #include <stdio.h>
@ -28,40 +27,36 @@
* Internal functions declarations * Internal functions declarations
*/ */
static unsigned int mainProcess(int args_cnt, char *args_value[]); static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* opt_ptr);
static void createSubDir(char *dirName); static void createSubDir(char *dirName);
static int checkInputArgs(int arg_nbr, char *args[]); static unsigned char checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]);
static void cleanUpMemory(T_HOB* hobStruct); static void cleanUpMemory(T_HOB* hobStruct);
//int exportTextures(HMT_FILE *hmt_f, char *filename); static void dispHelp();
static inline void dispHelp();
/*
* Global variables declaration
*/
int _options; // Global options settings variable
/* /*
* - MAIN - * - MAIN -
*/ */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Init buffer vars T_PROG_OPTIONS _opts;
unsigned char p;
// Hello world!
printf("\n*** RogueSquadron Extractor (RSE) - MODEL module - v%s ***\n", VERSION); printf("\n*** RogueSquadron Extractor (RSE) - MODEL module - v%s ***\n", VERSION);
// Check if filenames arguments exist // Check for arguments
if (argc < 2) { if (argc < 2) {
printf("\n[ERR] No input file/commands specified!\n"); printf("\n[ERR] No input file/commands specified!\n");
dispHelp(); dispHelp();
return ERROR_ARGS_NULL; return ERROR_ARGS_NULL;
} }
_options = checkInputArgs(argc, argv); // Analyse program arguments
if (_options == -1) return NO_ERROR;
return mainProcess(argc, argv); // Create options for programs according to user's arguments.
p = checkInputArgs(&_opts, argc, argv);
if ( p == ERROR_GENERIC ) return NO_ERROR;
else if ( p != NO_ERROR ) return p;
return mainProcess(argc, argv, &_opts);
} }
@ -69,28 +64,28 @@ int main(int argc, char *argv[]) {
* Private functions definition * Private functions definition
*/ */
static unsigned int mainProcess(int args_cnt, char *args_value[]) { static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* p_opts) {
unsigned short file_index; unsigned short file_index;
T_HOB* hobStruct = NULL; T_HOB* hobStruct = NULL;
int i; int i;
// Manage multiple inputs files // Manage multiple inputs files
for (file_index=(_options >> 8) & 0xFF; file_index < args_cnt; file_index++) 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]); printf("\n=============================================\n[INFO] - Parsing file: %s ...\n", args_value[file_index]);
hobStruct = calloc(1, sizeof(T_HOB)); hobStruct = calloc(1, sizeof(T_HOB));
// Parse data from HOB file and put in T_HOB structure. // Parse data from HOB file and put in T_HOB structure.
if (parseHOBFile(args_value[file_index], hobStruct) != NO_ERROR) { if (parseHOBFile(args_value[file_index], hobStruct, p_opts) != NO_ERROR) {
printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]); printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]);
free(hobStruct); free(hobStruct);
return ERROR_PROCESS; return ERROR_PROCESS;
} }
if (hobStruct->obj_count > 0) { if (hobStruct->obj_count > 0) {
if (_options & OUTPUT_DIR) createSubDir(args_value[file_index]); if (p_opts->output_dir) createSubDir(args_value[file_index]);
for ( i = 0; i < hobStruct->obj_count; i++ ) { for ( i = 0; i < hobStruct->obj_count; i++ ) {
if (exportOBJModel(&(hobStruct->objects[i]), args_value[file_index]) != NO_ERROR) if (exportOBJModel(&(hobStruct->objects[i]), args_value[file_index], p_opts) != NO_ERROR)
printf("[ERR] Failed to export %s object in OBJ format!\n", hobStruct->objects[i].name); printf("[ERR] Failed to export %s object in OBJ format!\n", hobStruct->objects[i].name);
else else
printf("[INFO] Successfully exported %s object in OBJ format.\n", hobStruct->objects[i].name); printf("[INFO] Successfully exported %s object in OBJ format.\n", hobStruct->objects[i].name);
@ -103,35 +98,47 @@ static unsigned int mainProcess(int args_cnt, char *args_value[]) {
return NO_ERROR; return NO_ERROR;
} }
static int checkInputArgs(int arg_nbr, char *args[]) { static unsigned char checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]) {
int _o = (OUTPUT_DIR | EXPORT_MTL); // Default options parameters
char test[256]; char test[256];
int i; int i;
if (arg_nbr > 1) { // Set default options
for (i=1; i<arg_nbr; i++) { opt_ptr->raw = 0;
strcpy(test, args[i]); opt_ptr->output_dir = 1;
if (args[i][0] != '-') break; opt_ptr->export_mtl = 1;
if (strcmp(args[i], "-h") == 0) {
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(); dispHelp();
return -1; return ERROR_GENERIC;
} else if (strcmp(args[i], "-v") == 0) { } else if (strcmp(p_args[i], "-v") == 0) {
_o |= VERBOSE_ENABLED; opt_ptr->verbose_mode = 1;
printf("[OPTN] Verbose enabled.\n"); printf("[OPTN] Verbose enabled.\n");
} else if (strcmp(args[i], "-no-subdir") == 0) { } else if (strcmp(p_args[i], "-vv") == 0) {
_o &= ~OUTPUT_DIR; opt_ptr->debug_mode = 1;
printf("[OPTN] Debug enabled.\n");
} else if (strcmp(p_args[i], "-vvv") == 0) {
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"); printf("[OPTN] Export to current directory.\n");
} else if (strcmp(args[i], "-mtl") == 0) { } else if (strcmp(p_args[i], "-mtl") == 0) {
_o &= ~EXPORT_MTL; opt_ptr->export_mtl = 0;
printf("[OPTN] No materials datas.\n"); printf("[OPTN] No materials datas.\n");
} else { } else {
printf("[ERR] Unknown option: %s\n", args[i]); printf("[ERR] Unknown option: %s\n", p_args[i]);
} }
} }
_o = (i << 8) | (_o & 0x00FF);
}
return _o; opt_ptr->input_files_cnt = i;
return NO_ERROR;
}
return ERROR_ARGS_NULL;
} }
static void createSubDir(char *dirName) { static void createSubDir(char *dirName) {
@ -164,10 +171,10 @@ static void cleanUpMemory(T_HOB* hobStruct) {
free(hobStruct); free(hobStruct);
} }
static inline void dispHelp() { static void dispHelp() {
printf("\n"); printf("\n");
printf("Options:\n -h Print this message\n"); printf("Options:\n -h Print this message\n");
printf(" -v Activate verbose console output\n"); printf(" -v -vv Activate verbose console output\n");
printf(" -no-subdir Export models inside current folder\n"); printf(" -no-subdir Export models inside current folder\n");
printf(" -no-mtl Disable materials datas export with model\n"); printf(" -no-mtl Disable materials datas export with model\n");
printf("\n"); printf("\n");

View File

@ -5,12 +5,15 @@
* Author: JackCarterSmith * Author: JackCarterSmith
*/ */
#include "error.h" //TODO: use it as base for error ID //#include "error.h" //TODO: use it as base for error ID
#ifndef SRC_ERRORS_TYPES_H_ #ifndef SRC_ERRORS_TYPES_H_
#define SRC_ERRORS_TYPES_H_ #define SRC_ERRORS_TYPES_H_
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0 #define NO_ERROR 0
#define ERROR_GENERIC 1 #define ERROR_GENERIC 1
#define ERROR_MEMORY 2 #define ERROR_MEMORY 2

View File

@ -1,8 +1,9 @@
/* /**
* hob_parser.c * \file hob_parser.c
* * \date 26/07/2022
* Created on: 26 juil. 2022 * \author JackCarterSmith
* Author: JackCarterSmith * \copyright GPL-v3.0
* \brief Decode HOB file structure.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -14,7 +15,7 @@
#include "hob_parser.h" #include "hob_parser.h"
unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) { unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct, T_PROG_OPTIONS* p_opts) {
unsigned char err = NO_ERROR; unsigned char err = NO_ERROR;
long fileSize; long fileSize;
FILE* fStream = NULL; FILE* fStream = NULL;
@ -32,7 +33,7 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
fseek(fStream, 0, SEEK_END); fseek(fStream, 0, SEEK_END);
fileSize = ftell(fStream); fileSize = ftell(fStream);
fseek(fStream, 0, SEEK_SET); fseek(fStream, 0, SEEK_SET);
if (_options & VERBOSE_ENABLED) printf("[DBG] > Input file size: %ld bytes\n", fileSize); if (p_opts->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize);
memFile = malloc(fileSize + 1); memFile = malloc(fileSize + 1);
if (memFile != NULL) { if (memFile != NULL) {
@ -48,67 +49,74 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
// Populate HOB structure with object descriptor // Populate HOB structure with object descriptor
hob_struct->objects = calloc(hob_struct->obj_count, sizeof(T_HOB_OBJECT)); hob_struct->objects = calloc(hob_struct->obj_count, sizeof(T_HOB_OBJECT));
for ( i = 0; i < hob_struct->obj_count; i++ ) { for ( i = 0; i < hob_struct->obj_count; i++ ) {
if (p_opts->debug_mode) printf("\n-=====================-Begin of Object part-======================-\n");
// Get object name // Get object name
memcpy(hob_struct->objects[i].name, ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile memcpy(hob_struct->objects[i].name, ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile
+ sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_HEADER)
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_name, 16); + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_name, 16);
if (_options & VERBOSE_ENABLED) printf("\n"); if (p_opts->verbose_mode) printf("\n");
printf("[INFO] - Process %s object...\n", hob_struct->objects[i].name); printf("[INFO] - Process %s object...\n", hob_struct->objects[i].name);
// Get offsets // Get offsets
hob_struct->objects[i].face_group_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile hob_struct->objects[i].face_group_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile
+ sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_HEADER)
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_offset; + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_offset;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group offset: 0x%X\n", hob_struct->objects[i].face_group_offset); if (p_opts->verbose_mode) printf("[DBG] > Face group offset: 0x%X\n", hob_struct->objects[i].face_group_offset);
hob_struct->objects[i].object_part_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile hob_struct->objects[i].object_part_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile
+ sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_HEADER)
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_parts_offset; + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_parts_offset;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group header/object parts offset: 0x%X\n", hob_struct->objects[i].object_part_header_offset); if (p_opts->verbose_mode) printf("[DBG] > Face group header/object parts offset: 0x%X\n", hob_struct->objects[i].object_part_header_offset);
hob_struct->objects[i].face_group_header2_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile hob_struct->objects[i].face_group_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile
+ sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_HEADER)
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_header_2_offset; + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_header_2_offset;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group header2 offset: 0x%X\n", hob_struct->objects[i].face_group_header2_offset); if (p_opts->verbose_mode) printf("[DBG] > Face group header2 offset: 0x%X\n", hob_struct->objects[i].face_group_header_offset);
if (p_opts->god_mode) {
printf("[DBG] > Face group unknown1: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset1);
printf("[DBG] > Face group unknown2: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset2);
printf("[DBG] > Face group unknown3: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset3);
printf("[DBG] > Face group unknown4: %.8f\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknown4);
}
// Get count and offsets from the facegroup header // Get count and offsets from the facegroup header
hob_struct->objects[i].object_part_count = ((T_HOBFILE_FACEGROUP_HEADER *)(memFile
+ hob_struct->objects[i].object_part_header_offset))->object_part_count;
if (p_opts->verbose_mode) printf("[DBG] > Object parts count: %d\n", hob_struct->objects[i].object_part_count);
hob_struct->objects[i].face_group_count = ((T_HOBFILE_FACEGROUP_HEADER *)(memFile hob_struct->objects[i].face_group_count = ((T_HOBFILE_FACEGROUP_HEADER *)(memFile
+ hob_struct->objects[i].object_part_header_offset))->facegroup_count; + hob_struct->objects[i].object_part_header_offset))->facegroup_count;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group count: %d\n", hob_struct->objects[i].face_group_count); if (p_opts->verbose_mode) printf("[DBG] > Face groups count: %d\n", hob_struct->objects[i].face_group_count);
hob_struct->objects[i].face_group_count0 = ((T_HOBFILE_FACEGROUP_HEADER *)(memFile if (hob_struct->objects[i].object_part_count != hob_struct->objects[i].face_group_count && (p_opts->verbose_mode)) printf("[DBG] > Object parts / facegroup count are different!\n");
+ hob_struct->objects[i].object_part_header_offset))->facegroup_count0;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group count0: %d\n", hob_struct->objects[i].face_group_count0);
if (hob_struct->objects[i].face_group_count != hob_struct->objects[i].face_group_count0 && (_options & VERBOSE_ENABLED)) printf("[DBG] > Facegroup count are different!\n");
// Get facegroup datas // Get facegroup datas
offset_index = calloc(hob_struct->objects[i].face_group_count, sizeof(int)); offset_index = calloc(hob_struct->objects[i].object_part_count, sizeof(int));
hob_struct->objects[i].object_parts = calloc(hob_struct->objects[i].face_group_count, sizeof(T_HOB_FACE_GROUP)); hob_struct->objects[i].object_parts = calloc(hob_struct->objects[i].object_part_count, sizeof(T_HOB_FACE_GROUP));
for ( j = 0; j < hob_struct->objects[i].face_group_count; j++ ) { for ( j = 0; j < hob_struct->objects[i].object_part_count; j++ ) {
if (p_opts->debug_mode) printf("\n-----------------------Begin of Mesh part-------------------------\n");
offset_index[j] = ((T_HOBFILE_FACEGROUP_OFFSET *)(memFile + hob_struct->objects[i].object_part_header_offset offset_index[j] = ((T_HOBFILE_FACEGROUP_OFFSET *)(memFile + hob_struct->objects[i].object_part_header_offset
+ sizeof(T_HOBFILE_FACEGROUP_HEADER) + sizeof(T_HOBFILE_FACEGROUP_HEADER)
+ sizeof(T_HOBFILE_FACEGROUP_OFFSET) * j))->facegroup_offset; + sizeof(T_HOBFILE_FACEGROUP_OFFSET) * j))->facegroup_offset;
if (_options & VERBOSE_ENABLED) printf("\n[DBG] > Face group meshdef0 offset: 0x%X\n", offset_index[j]); if (p_opts->verbose_mode) printf("\n[DBG] > Face group meshdef0 offset: 0x%X\n", offset_index[j]);
// Get meshdef0 datas // Get meshdef0 datas
if (_options & VERBOSE_ENABLED) printf("\n[DBG] > Next meshdef0 offset: 0x%X",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->next_meshdef0_offset); if (p_opts->god_mode) printf("[DBG] > meshdef0 offset1: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->offset1);
if (_options & VERBOSE_ENABLED) printf("\n[DBG] > Prev meshdef0 offset: 0x%X",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->prev_meshdef0_offset); if (p_opts->god_mode) printf("[DBG] > meshdef0 offset2: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->offset2);
hob_struct->objects[i].object_parts[j].id = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->object_id; if (p_opts->verbose_mode) printf("[DBG] > Prev meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->prev_meshdef0_offset);
if (_options & VERBOSE_ENABLED) printf("\n[DBG] > Facegroup/object ID: %d\n", hob_struct->objects[i].object_parts[j].id); if (p_opts->verbose_mode) printf("[DBG] > Next meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->next_meshdef0_offset);
hob_struct->objects[i].object_parts[j].transform.x = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_x;
hob_struct->objects[i].object_parts[j].transform.y = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_y; if (p_opts->god_mode) printf("[DBG] > meshdef0 unknown3: %.8f\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->unknown3);
hob_struct->objects[i].object_parts[j].transform.z = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_z; if (p_opts->god_mode) printf("[DBG] > meshdef0 unknown4: %.8f\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->unknown4);
if (_options & VERBOSE_ENABLED) printf("\n[DBG] > Facegroup/object transform matrix: [%.8f %.8f %.8f]\n", if (p_opts->god_mode) printf("[DBG] > meshdef0 unknown5: %.8f\n",((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->unknown5);
hob_struct->objects[i].object_parts[j].transform.x,
hob_struct->objects[i].object_parts[j].transform.y,
hob_struct->objects[i].object_parts[j].transform.z
);
// Get meshdef1 (mesh descriptor) offset // Get meshdef1 (mesh descriptor) offset
hob_struct->objects[i].object_parts[j].meshdef1_offset = ((T_HOBFILE_MESHDEF0 *)(memFile hob_struct->objects[i].object_parts[j].meshdef1_offset = ((T_HOBFILE_MESHDEF0 *)(memFile
+ offset_index[j]))->meshdef1_offset_plus_4; + offset_index[j]))->meshdef1_offset_plus_4;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group meshdef1 offset: 0x%X\n", hob_struct->objects[i].object_parts[j].meshdef1_offset); if (p_opts->verbose_mode) printf("\n[DBG] > Face group meshdef1 offset: 0x%X\n", hob_struct->objects[i].object_parts[j].meshdef1_offset);
if( ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->reserved1 != 0 || if( ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->reserved1 != 0 ||
((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->reserved2 != 0 ) { ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->reserved2 != 0 ) {
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face group meshdef0: no 0!\n"); if (p_opts->god_mode) printf("[DBG] > Face group meshdef0: no 0!\n");
} }
if (hob_struct->objects[i].object_parts[j].meshdef1_offset > 0) { if (hob_struct->objects[i].object_parts[j].meshdef1_offset > 0) {
@ -119,25 +127,27 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
+ hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->vertex_count; + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->vertex_count;
hob_struct->objects[i].object_parts[j].face_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile hob_struct->objects[i].object_parts[j].face_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile
+ hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->faceblock_offset; + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->faceblock_offset;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Faces offset: 0x%X\n", hob_struct->objects[i].object_parts[j].face_block_offset); if (p_opts->verbose_mode) printf("[DBG] > Faces offset: 0x%X\n", hob_struct->objects[i].object_parts[j].face_block_offset);
hob_struct->objects[i].object_parts[j].vertex_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile hob_struct->objects[i].object_parts[j].vertex_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile
+ hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->vertexblocks_offset; + hob_struct->objects[i].object_parts[j].meshdef1_offset - 4))->vertexblocks_offset;
if (_options & VERBOSE_ENABLED) printf("[DBG] > Vertex offset: 0x%X\n\n", hob_struct->objects[i].object_parts[j].vertex_block_offset); if (p_opts->verbose_mode) printf("[DBG] > Vertex offset: 0x%X\n\n", hob_struct->objects[i].object_parts[j].vertex_block_offset);
// Get face datas // Get face datas
if( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->reserved1 != 0 || if( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->reserved1 != 0 ||
((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->reserved2 != 0 ) { ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->reserved2 != 0 ) {
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face block: uncommon zero header!\n"); if (p_opts->god_mode) printf("[DBG] > Face block: uncommon zero header!\n");
} }
if ( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->facesOffset != if ( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].object_parts[j].face_block_offset))->facesOffset !=
hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) { hob_struct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) {
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face block: uncommon face data offset position!\n"); if (p_opts->god_mode) printf("[DBG] > Face block: uncommon face data offset position!\n");
} }
hob_struct->objects[i].object_parts[j].face_count = ((T_HOBFILE_FACEBLOCK *)(memFile hob_struct->objects[i].object_parts[j].face_count = ((T_HOBFILE_FACEBLOCK *)(memFile
+ hob_struct->objects[i].object_parts[j].face_block_offset))->faceCounts; + hob_struct->objects[i].object_parts[j].face_block_offset))->faceCounts;
hob_struct->objects[i].object_parts[j].faces = calloc(hob_struct->objects[i].object_parts[j].face_count, sizeof(T_HOB_FACE)); hob_struct->objects[i].object_parts[j].faces = calloc(hob_struct->objects[i].object_parts[j].face_count, sizeof(T_HOB_FACE));
facesExtraOffset = 0; facesExtraOffset = 0;
for ( k = 0; k < hob_struct->objects[i].object_parts[j].face_count; k++ ) { for ( k = 0; k < hob_struct->objects[i].object_parts[j].face_count; k++ ) {
if (p_opts->debug_mode) printf("\n----------------------Begin of FaceGroup part----------------------\n");
// Get flags // Get flags
hob_struct->objects[i].object_parts[j].faces[k].flags = ((T_HOBFILE_FACES_HEADER *)(memFile hob_struct->objects[i].object_parts[j].faces[k].flags = ((T_HOBFILE_FACES_HEADER *)(memFile
+ hob_struct->objects[i].object_parts[j].face_block_offset + hob_struct->objects[i].object_parts[j].face_block_offset
@ -172,7 +182,7 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACEBLOCK)
+ sizeof(T_HOBFILE_FACES_HEADER) * k + sizeof(T_HOBFILE_FACES_HEADER) * k
+ facesExtraOffset))->headerSeparator != 0) { + facesExtraOffset))->headerSeparator != 0) {
if (_options & VERBOSE_ENABLED) printf("[DBG] > Face header: uncommon separator!\n"); if (p_opts->god_mode) printf("[DBG] > Face header: uncommon separator!\n");
} }
// Get materials index // Get materials index
@ -288,8 +298,8 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
} }
} }
if (_options & VERBOSE_ENABLED) { if (p_opts->debug_mode) {
printf("[DBG] > Face %d details: 0x%X, %d, %d, %d, %d\n", k, printf("[DBG] > Face %d details: flags:0x%X b1:%d b2:%d b3%d bsize:%d\n", k,
hob_struct->objects[i].object_parts[j].faces[k].flags, hob_struct->objects[i].object_parts[j].faces[k].flags,
hob_struct->objects[i].object_parts[j].faces[k].b1, hob_struct->objects[i].object_parts[j].faces[k].b1,
hob_struct->objects[i].object_parts[j].faces[k].b2, hob_struct->objects[i].object_parts[j].faces[k].b2,
@ -337,6 +347,8 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
); );
printf("\n"); printf("\n");
} }
if (p_opts->debug_mode) printf("\n-----------------------End of FaceGroup part-----------------------\n");
} }
// Get vertex datas // Get vertex datas
@ -358,14 +370,32 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
+ hob_struct->objects[i].object_parts[j].vertex_block_offset + hob_struct->objects[i].object_parts[j].vertex_block_offset
+ sizeof(T_VERTEX) * k))->w; // Always 0??? + sizeof(T_VERTEX) * k))->w; // Always 0???
if (_options & VERBOSE_ENABLED) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", k, if (p_opts->debug_mode) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", k,
hob_struct->objects[i].object_parts[j].vertices[k].x, hob_struct->objects[i].object_parts[j].vertices[k].x,
hob_struct->objects[i].object_parts[j].vertices[k].y, hob_struct->objects[i].object_parts[j].vertices[k].y,
hob_struct->objects[i].object_parts[j].vertices[k].z hob_struct->objects[i].object_parts[j].vertices[k].z
); );
} }
} }
// Get object part ID, used by animation? bones?
hob_struct->objects[i].object_parts[j].id = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->object_id;
if (p_opts->verbose_mode) printf("\n[DBG] > Facegroup/object ID: %d\n", hob_struct->objects[i].object_parts[j].id);
// Get the transform matrix, used by at-st and at-at (at this time)
hob_struct->objects[i].object_parts[j].transform.x = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_x;
hob_struct->objects[i].object_parts[j].transform.y = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_y;
hob_struct->objects[i].object_parts[j].transform.z = ((T_HOBFILE_MESHDEF0 *)(memFile + offset_index[j]))->transform_z;
if (p_opts->god_mode) printf("\n[DBG] > Facegroup/object transform matrix: [%.8f %.8f %.8f]\n",
hob_struct->objects[i].object_parts[j].transform.x,
hob_struct->objects[i].object_parts[j].transform.y,
hob_struct->objects[i].object_parts[j].transform.z
);
if (p_opts->debug_mode) printf("\n-----------------------End of Mesh part---------------------------\n");
} }
if (p_opts->debug_mode) printf("\n-=====================-End of Object part-========================-\n");
} }
free(offset_index); free(offset_index);
@ -380,11 +410,11 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) {
} else { } else {
fclose(fStream); fclose(fStream);
err = ERROR_MEMORY; err = ERROR_MEMORY;
if (_options & VERBOSE_ENABLED) printf("[ERR] Can't allocate enough memory for file processing!\n"); if (p_opts->verbose_mode) printf("[ERR] Can't allocate enough memory for file processing!\n");
} }
} else { } else {
err = ERROR_IO; err = ERROR_IO;
if (_options & VERBOSE_ENABLED) printf("[ERR] Input file %s not found!\n", fileName); if (p_opts->verbose_mode) printf("[ERR] Input file %s not found!\n", fileName);
} }
} else err = ERROR_ARGS_NULL; } else err = ERROR_ARGS_NULL;

View File

@ -1,14 +1,15 @@
/* /**
* hob_parser.h * \file hob_parser.h
* * \date 26/07/2022
* Created on: 26 juil. 2022 * \author JackCarterSmith
* Author: JackCarterSmith * \copyright GPL-v3.0
* \brief Decode HOB file structure.
*/ */
#ifndef SRC_HOB_PARSER_H_ #ifndef SRC_HOB_PARSER_H_
#define SRC_HOB_PARSER_H_ #define SRC_HOB_PARSER_H_
unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct); unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct, T_PROG_OPTIONS* p_opts);
#endif /* SRC_HOB_PARSER_H_ */ #endif /* SRC_HOB_PARSER_H_ */

View File

@ -16,6 +16,12 @@
* car = 8bits * car = 8bits
*/ */
#if defined(_MSC_VER)
#define PACK
#elif defined(__GNUC__)
#define PACK __attribute__((packed))
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// HOB file structure // HOB file structure
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -80,10 +86,10 @@ typedef struct hob_object {
char name[16]; char name[16];
unsigned int face_group_offset; unsigned int face_group_offset;
unsigned int object_part_header_offset; unsigned int object_part_header_offset;
unsigned int face_group_header2_offset; unsigned int face_group_header_offset;
unsigned int object_part_count;
unsigned int face_group_count; unsigned int face_group_count;
unsigned int face_group_count0;
T_HOB_FACE_GROUP* object_parts; T_HOB_FACE_GROUP* object_parts;
} T_HOB_OBJECT; } T_HOB_OBJECT;
@ -102,14 +108,19 @@ typedef struct hob {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Declaration of Memory Mapped Structure // Declaration of Memory Mapped Structure
// Caution: the place of variable is important for correct mapping!
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
typedef struct __attribute__((packed)) hobfile_header { #if defined(_MSC_VER)
#pragma pack(push, 1)
#endif
typedef struct PACK hobfile_header {
unsigned int obj_count; unsigned int obj_count;
unsigned int vertices_offset; unsigned int vertices_offset;
} T_HOBFILE_HEADER; } T_HOBFILE_HEADER;
typedef struct __attribute__((packed)) hobfile_obj_descriptor { typedef struct PACK hobfile_obj_descriptor {
unsigned char object_name[16]; unsigned char object_name[16];
unsigned int facegroup_offset; unsigned int facegroup_offset;
unsigned int object_parts_offset; unsigned int object_parts_offset;
@ -119,9 +130,9 @@ typedef struct __attribute__((packed)) hobfile_obj_descriptor {
unsigned int reserved2; unsigned int reserved2;
unsigned int reserved3; unsigned int reserved3;
unsigned int unknown1; unsigned int unknownOffset1;
unsigned int unknown2; unsigned int unknownOffset2;
unsigned int unknown3; unsigned int unknownOffset3;
float unknown4; float unknown4;
unsigned int reserved4; // 12B of zeros unsigned int reserved4; // 12B of zeros
@ -142,21 +153,21 @@ typedef struct __attribute__((packed)) hobfile_obj_descriptor {
float reserved17; float reserved17;
} T_HOBFILE_OBJ_DESCRIPTOR; } T_HOBFILE_OBJ_DESCRIPTOR;
typedef struct __attribute__((packed)) hobfile_facegroup_header { typedef struct PACK hobfile_facegroup_header {
unsigned short object_part_count;
unsigned short facegroup_count; unsigned short facegroup_count;
unsigned short facegroup_count0;
} T_HOBFILE_FACEGROUP_HEADER; } T_HOBFILE_FACEGROUP_HEADER;
typedef struct __attribute__((packed)) hobfile_facegroup_offset { typedef struct PACK hobfile_facegroup_offset {
unsigned int unknown1; unsigned int unknown1;
unsigned int facegroup_offset; unsigned int facegroup_offset;
} T_HOBFILE_FACEGROUP_OFFSET; } T_HOBFILE_FACEGROUP_OFFSET;
typedef struct __attribute__((packed)) hobfile_meshdef0 { typedef struct PACK hobfile_meshdef0 {
unsigned int next_meshdef0_offset; unsigned int offset1;
unsigned int unknown1; unsigned int offset2;
unsigned int unknown2;
unsigned int prev_meshdef0_offset; unsigned int prev_meshdef0_offset;
unsigned int next_meshdef0_offset;
unsigned int meshdef1_offset_plus_4; unsigned int meshdef1_offset_plus_4;
unsigned int reserved1; // 8B of zeros unsigned int reserved1; // 8B of zeros
@ -200,7 +211,7 @@ typedef struct __attribute__((packed)) hobfile_meshdef0 {
float transform_z; float transform_z;
} T_HOBFILE_MESHDEF0; } T_HOBFILE_MESHDEF0;
typedef struct __attribute__((packed)) hobfile_meshdef1 { typedef struct PACK hobfile_meshdef1 {
unsigned int facedef_end_offset; unsigned int facedef_end_offset;
unsigned int reserved1; // 20B of zeros unsigned int reserved1; // 20B of zeros
@ -230,7 +241,7 @@ typedef struct __attribute__((packed)) hobfile_meshdef1 {
unsigned int reserved19; unsigned int reserved19;
} T_HOBFILE_MESHDEF1; } T_HOBFILE_MESHDEF1;
typedef struct __attribute__((packed)) hobfile_faceblock { typedef struct PACK hobfile_faceblock {
unsigned int reserved1; // 8B of zeros unsigned int reserved1; // 8B of zeros
unsigned int reserved2; unsigned int reserved2;
@ -238,7 +249,7 @@ typedef struct __attribute__((packed)) hobfile_faceblock {
unsigned int faceCounts; unsigned int faceCounts;
} T_HOBFILE_FACEBLOCK; } T_HOBFILE_FACEBLOCK;
typedef struct __attribute__((packed)) hobfile_faces_header { typedef struct PACK hobfile_faces_header {
unsigned int flags; unsigned int flags;
unsigned char b1; unsigned char b1;
unsigned char b2; unsigned char b2;
@ -249,29 +260,33 @@ typedef struct __attribute__((packed)) hobfile_faces_header {
unsigned short vertexIndices[4]; // Relative to facegroup, the last value is equal to 0 when it's triangle shape. unsigned short vertexIndices[4]; // Relative to facegroup, the last value is equal to 0 when it's triangle shape.
} T_HOBFILE_FACES_HEADER; } T_HOBFILE_FACES_HEADER;
typedef struct __attribute__((packed)) hobfile_faces_extra_vertex_color { typedef struct PACK hobfile_faces_extra_vertex_color {
T_RGBA v1_rgba; T_RGBA v1_rgba;
T_RGBA v2_rgba; T_RGBA v2_rgba;
T_RGBA v3_rgba; T_RGBA v3_rgba;
T_RGBA v4_rgba; // Used with quad type face T_RGBA v4_rgba; // Used with quad type face
} T_HOBFILE_FACES_VERTEX_COLOR; } T_HOBFILE_FACES_VERTEX_COLOR;
typedef struct __attribute__((packed)) hobfile_faces_extra_color { typedef struct PACK hobfile_faces_extra_color {
T_RGBA rgba; T_RGBA rgba;
} T_HOBFILE_FACES_COLOR; } T_HOBFILE_FACES_COLOR;
typedef struct __attribute__((packed)) hobfile_faces_extra_vertex_texture { typedef struct PACK hobfile_faces_extra_vertex_texture {
T_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range T_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range
T_TEXCOORD v2_texcoord; T_TEXCOORD v2_texcoord;
T_TEXCOORD v3_texcoord; T_TEXCOORD v3_texcoord;
T_TEXCOORD v4_texcoord; // Used with quad type face T_TEXCOORD v4_texcoord; // Used with quad type face
} T_HOBFILE_FACES_VERTEX_TEXTURE; } T_HOBFILE_FACES_VERTEX_TEXTURE;
typedef struct __attribute__((packed)) hobfile_vertex { typedef struct PACK hobfile_vertex {
short x; short x;
short y; short y;
short z; short z;
short w; short w;
} T_HOBFILE_VERTEX; } T_HOBFILE_VERTEX;
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
#endif /* SRC_HOB_STRUCT_H_ */ #endif /* SRC_HOB_STRUCT_H_ */

View File

@ -1,8 +1,9 @@
/* /**
* obj_exporter.c * \file obj_exporter.c
* * \date 27/07/2022
* Created on: 27 juil. 2022 * \author JackCarterSmith
* Author: JackCarterSmith * \copyright GPL-v3.0
* \brief Export datas to Waveform OBJ format.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -17,7 +18,7 @@
static void mtlPathPatch(const char* out_file, const char* obj_name) ; static void mtlPathPatch(const char* out_file, const char* obj_name) ;
unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path) { unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path, T_PROG_OPTIONS* p_opts) {
char objExport_path[128]; char objExport_path[128];
char mtlExport_path[128]; char mtlExport_path[128];
obj* objConstruct = NULL; obj* objConstruct = NULL;
@ -30,7 +31,7 @@ unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path) {
if (hob_objects == NULL || out_path == NULL) if (hob_objects == NULL || out_path == NULL)
return ERROR_ARGS_NULL; return ERROR_ARGS_NULL;
if (_options & OUTPUT_DIR) { if (p_opts->output_dir) {
strcpy(objExport_path, out_path); strcpy(objExport_path, out_path);
#ifdef _WIN32 #ifdef _WIN32
strcat(objExport_path, "-out\\"); strcat(objExport_path, "-out\\");
@ -105,9 +106,11 @@ unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path) {
indexOffset = obj_num_vert(objConstruct); indexOffset = obj_num_vert(objConstruct);
} }
if (_options & EXPORT_MTL) { if (p_opts->export_mtl) {
obj_write(objConstruct, objExport_path, mtlExport_path, 8); obj_write(objConstruct, objExport_path, mtlExport_path, 8);
if (_options & OUTPUT_DIR) mtlPathPatch(objExport_path, hob_objects->name); #if defined(__GNUC__) //TODO: review MSVC file management or include and rewrite obj lib?
if (p_opts->output_dir) mtlPathPatch(objExport_path, hob_objects->name);
#endif
} else obj_write(objConstruct, objExport_path, NULL, 8); } else obj_write(objConstruct, objExport_path, NULL, 8);
obj_delete(objConstruct); obj_delete(objConstruct);
@ -150,7 +153,11 @@ static void mtlPathPatch(const char* out_file, const char* obj_name) {
// Begin rewrite file // Begin rewrite file
obj = fopen(out_file, "w"); obj = fopen(out_file, "w");
fprintf(obj, "mtllib %s", _path); fprintf(obj, "mtllib %s", _path);
#if defined(_MSC_VER)
fwrite(memFile, fileSize - pos , 1, obj);
#elif defined(__GNUC__)
fwrite(memFile, fileSize - (pos + lines), 1, obj); fwrite(memFile, fileSize - (pos + lines), 1, obj);
#endif
free(memFile); free(memFile);
} }

View File

@ -1,8 +1,9 @@
/* /**
* obj_exporter.h * \file obj_exporter.h
* * \date 27/07/2022
* Created on: 27 juil. 2022 * \author JackCarterSmith
* Author: JackCarterSmith * \copyright GPL-v3.0
* \brief Export datas to Waveform OBJ format.
*/ */
#ifndef SRC_OBJ_EXPORTER_H_ #ifndef SRC_OBJ_EXPORTER_H_
@ -15,6 +16,6 @@ typedef struct t_material {
unsigned int gl_tex_id; unsigned int gl_tex_id;
} T_MATERIAL; } T_MATERIAL;
unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path); unsigned char exportOBJModel(T_HOB_OBJECT* hob_objects, const char *out_path, T_PROG_OPTIONS* p_opts);
#endif /* SRC_OBJ_EXPORTER_H_ */ #endif /* SRC_OBJ_EXPORTER_H_ */

View File

@ -1,10 +1,32 @@
/**
* \file options.h
* \date 29/07/2022
* \author JackCarterSmith
* \copyright GPL-v3.0
* \brief Shared options structure definition and declaration.
*/
#ifndef OPTIONS_H_ #ifndef OPTIONS_H_
#define OPTIONS_H_ #define OPTIONS_H_
#define VERBOSE_ENABLED 0x0001 /// Options structure
#define OUTPUT_DIR 0x0002 typedef union u_prog_options {
#define EXPORT_MTL 0x0004 struct {
unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things.
extern int _options; unsigned char output_dir:1; //!< Export extracted datas to a sub-directory.
unsigned char export_mtl:1; //!< Export materials datas with object.
#endif unsigned char reserved0:5; //!< For future use.
unsigned char debug_mode:1; //!< Output all values of faces, indices and vertices and others "heavy" things.
unsigned char god_mode:1; //!< Dev only. Output experimental values.
unsigned char reserved1:6; //!< For future use.
unsigned short input_files_cnt; //!< Internal files counters.
};
unsigned int raw; //!< Raw options access for bit-masking or memory copy/compare.
} T_PROG_OPTIONS ;
#endif /* OPTIONS_H_ */