From e5b3058999640027044beea7597dfa37501e4207 Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Wed, 27 Jul 2022 17:18:07 +0200 Subject: [PATCH] Completed HOB parser --- src/hob_parser.c | 231 +++++++++++++++++++++++++++++++++++++++++++++-- src/hob_struct.h | 105 ++++++++++++++++----- 2 files changed, 303 insertions(+), 33 deletions(-) diff --git a/src/hob_parser.c b/src/hob_parser.c index 3a4fe3f..4a4a19a 100644 --- a/src/hob_parser.c +++ b/src/hob_parser.c @@ -20,6 +20,7 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) { FILE* fStream = NULL; char* memFile = NULL; int i,j,k; + unsigned int facesExtraOffset; int* offset_index = NULL; if (hob_struct != NULL && fileName != NULL) { @@ -51,6 +52,7 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) { memcpy(hob_struct->objects[i].name, ((T_HOBFILE_OBJ_DESCRIPTOR *)(memFile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_name, 16); + if (_options & VERBOSE_ENABLED) printf("\n"); printf("[INFO] - Process %s object...\n", hob_struct->objects[i].name); // Get offsets @@ -101,11 +103,224 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) { if (_options & VERBOSE_ENABLED) printf("[DBG] > Faces offset: 0x%X\n", hob_struct->objects[i].face_groups[j].face_block_offset); hob_struct->objects[i].face_groups[j].vertex_block_offset = ((T_HOBFILE_MESHDEF1 *)(memFile + hob_struct->objects[i].face_groups[j].meshdef1_offset - 4))->vertexblocks_offset; - if (_options & VERBOSE_ENABLED) printf("[DBG] > Vertex offset: 0x%X\n", hob_struct->objects[i].face_groups[j].vertex_block_offset); + if (_options & VERBOSE_ENABLED) printf("[DBG] > Vertex offset: 0x%X\n\n", hob_struct->objects[i].face_groups[j].vertex_block_offset); - //TODO: read Faces + // Get face datas + if( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].face_groups[j].face_block_offset))->reserved1 != 0 || + ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].face_groups[j].face_block_offset))->reserved2 != 0 ) { + if (_options & VERBOSE_ENABLED) printf("[DBG] > Face block: uncommon zero header!\n"); + } + if ( ((T_HOBFILE_FACEBLOCK *)(memFile + hob_struct->objects[i].face_groups[j].face_block_offset))->facesOffset != + hob_struct->objects[i].face_groups[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) { + if (_options & VERBOSE_ENABLED) printf("[DBG] > Face block: uncommon face data offset position!\n"); + } + hob_struct->objects[i].face_groups[j].face_count = ((T_HOBFILE_FACEBLOCK *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset))->faceCounts; + hob_struct->objects[i].face_groups[j].faces = calloc(hob_struct->objects[i].face_groups[j].face_count, sizeof(T_HOB_FACE)); + facesExtraOffset = 0; + for ( k = 0; k < hob_struct->objects[i].face_groups[j].face_count; k++ ) { + // Get flags + hob_struct->objects[i].face_groups[j].faces[k].flags = ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->flags; - // Get vertices datas + // Get unknown bytes + hob_struct->objects[i].face_groups[j].faces[k].b1 = ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->b1; + hob_struct->objects[i].face_groups[j].faces[k].b2 = ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->b2; + hob_struct->objects[i].face_groups[j].faces[k].b3 = ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->b3; + + hob_struct->objects[i].face_groups[j].faces[k].bsize = ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->faceBlockIntSize * 4; // Multiply by 4 to get the bytes exact number + if (((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->headerSeparator != 0) { + if (_options & VERBOSE_ENABLED) printf("[DBG] > Face header: uncommon separator!\n"); + } + + // Get materials index + hob_struct->objects[i].face_groups[j].faces[k].material_index = ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->materialIndex; + + // Get vertex indices + memcpy(hob_struct->objects[i].face_groups[j].faces[k].indices, + ((T_HOBFILE_FACES_HEADER *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->vertexIndices, + sizeof(unsigned short) * 4); + + // Recalculate the dynamic extra bytes offset size - if present + if (hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fHasExtraBytesBeforeColor) facesExtraOffset += 8; + + // Get vertex color - if present + if (hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fHasColor) { + if (hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fSeparateColorVertex) { + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[0] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v1_rgba; + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[1] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v2_rgba; + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[2] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v3_rgba; + if (hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fIsQuad) { + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[3] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v4_rgba; + facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR); + } else { + facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR) - sizeof(T_RGBA); + } + } else { + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[0] = ((T_HOBFILE_FACES_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->rgba; + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[1] = ((T_HOBFILE_FACES_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->rgba; + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[2] = ((T_HOBFILE_FACES_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->rgba; + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[3] = ((T_HOBFILE_FACES_COLOR *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->rgba; + facesExtraOffset += sizeof(T_HOBFILE_FACES_COLOR); + } + } + + // Get UV map - if present + if (hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fHasTexture) { + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[0] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v1_texcoord; + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[1] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v2_texcoord; + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[2] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v3_texcoord; + if (hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fIsQuad) { + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[3] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(memFile + + hob_struct->objects[i].face_groups[j].face_block_offset + + sizeof(T_HOBFILE_FACEBLOCK) + + sizeof(T_HOBFILE_FACES_HEADER) + + sizeof(T_HOBFILE_FACES_HEADER) * k + + facesExtraOffset))->v4_texcoord; + facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE); + } else { + facesExtraOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE) - sizeof(T_TEXCOORD); + } + } + + if (_options & VERBOSE_ENABLED) { + printf("[DBG] > Face %d details: 0x%X, %d, %d, %d, %d\n", k, + hob_struct->objects[i].face_groups[j].faces[k].flags, + hob_struct->objects[i].face_groups[j].faces[k].b1, + hob_struct->objects[i].face_groups[j].faces[k].b2, + hob_struct->objects[i].face_groups[j].faces[k].b3, + hob_struct->objects[i].face_groups[j].faces[k].bsize + ); + printf("[DBG] - Type is Quad: %d\n", hob_struct->objects[i].face_groups[j].faces[k].flags_bits.fIsQuad); + printf("[DBG] - Material offset: 0x%X\n", hob_struct->objects[i].face_groups[j].faces[k].material_index); + printf("[DBG] - Vertex indices: %d, %d, %d, %d\n", + hob_struct->objects[i].face_groups[j].faces[k].indices[0], + hob_struct->objects[i].face_groups[j].faces[k].indices[1], + hob_struct->objects[i].face_groups[j].faces[k].indices[2], + hob_struct->objects[i].face_groups[j].faces[k].indices[3] + ); + printf("[DBG] - Vertex colors: 0x%X, 0x%X, 0x%X, 0x%X\n", + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[0], + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[1], + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[2], + hob_struct->objects[i].face_groups[j].faces[k].vertex_colors[3] + ); + printf("[DBG] - Vertex UV coord (divided by 4096):\n"); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[0].u, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[0].u, + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[0].v, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[0].v + ); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[1].u, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[1].u, + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[1].v, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[1].v + ); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[2].u, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[2].u, + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[2].v, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[2].v + ); + printf("[DBG] > %.8f(%d), %.8f(%d)\n", + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[3].u, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[3].u, + ((double) 1/4096) * hob_struct->objects[i].face_groups[j].faces[k].tex_coords[3].v, + hob_struct->objects[i].face_groups[j].faces[k].tex_coords[3].v + ); + printf("\n"); + } + } + + // Get vertex datas hob_struct->objects[i].face_groups[j].vertices = calloc(hob_struct->objects[i].face_groups[j].vertex_count, sizeof(T_VERTEX)); for ( k = 0; k < hob_struct->objects[i].face_groups[j].vertex_count; k++ ) { hob_struct->objects[i].face_groups[j].vertices[k].x = ((T_HOBFILE_VERTEX *)(memFile @@ -124,11 +339,11 @@ unsigned char parseHOBFile(const char* fileName, T_HOB* hob_struct) { + hob_struct->objects[i].face_groups[j].vertex_block_offset + sizeof(T_VERTEX) * k))->w; // Always 0??? - //if (_options & VERBOSE_ENABLED) printf("[DBG] > Found vertex: (%d, %d, %d)\n", - // hob_struct->objects[i].face_groups[j].vertices[k].x, - // hob_struct->objects[i].face_groups[j].vertices[k].y, - // hob_struct->objects[i].face_groups[j].vertices[k].z - // ); + if (_options & VERBOSE_ENABLED) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", k, + hob_struct->objects[i].face_groups[j].vertices[k].x, + hob_struct->objects[i].face_groups[j].vertices[k].y, + hob_struct->objects[i].face_groups[j].vertices[k].z + ); } } } diff --git a/src/hob_struct.h b/src/hob_struct.h index ff0d2c3..b68df84 100644 --- a/src/hob_struct.h +++ b/src/hob_struct.h @@ -26,15 +26,33 @@ typedef struct vertex { short x,y,z,w; } T_VERTEX; typedef struct tex_coord { unsigned short u,v; } T_TEXCOORD; +typedef struct face_flags { + unsigned int fUnknown0:1; + unsigned int fUnknown1:1; + unsigned int fHasTexture:1; + unsigned int fIsQuad:1; + unsigned int fSeparateColorVertex:1; + unsigned int fHasColor:1; + unsigned int fHasExtraBytesBeforeColor:1; + unsigned int fUnknown7:1; + unsigned int fUnknown8:1; + unsigned int fUnknown9:1; + unsigned int fUnknown10:1; + + unsigned int reserved:21; +} FACE_FLAGS; + typedef struct hob_face { - unsigned int flags; + union { + unsigned int flags; + FACE_FLAGS flags_bits; + }; unsigned char b1; unsigned char b2; unsigned char b3; unsigned char bsize; - unsigned char ftype; // 3-Tri / 4-Quad - unsigned __int64 material_index; //TODO: verify for 64bits width and adapt MinGW dependancy to __int64 - unsigned __int64 indices[4]; //TODO: verify for 64bits width and adapt MinGW dependancy to __int64 + unsigned short material_index; + unsigned short indices[4]; T_RGBA vertex_colors[4]; //TODO: convert in R:8_G:8_B:8_A:8 format? Caution with BE/LE conversion T_TEXCOORD tex_coords[4]; } T_HOB_FACE; @@ -96,10 +114,10 @@ typedef struct __attribute__((packed)) hobfile_obj_descriptor { unsigned int reserved2; unsigned int reserved3; - unsigned int unknow1; - unsigned int unknow2; - unsigned int unknow3; - float unknow4; + unsigned int unknown1; + unsigned int unknown2; + unsigned int unknown3; + float unknown4; unsigned int reserved4; // 12B of zeros unsigned int reserved5; @@ -125,7 +143,7 @@ typedef struct __attribute__((packed)) hobfile_facegroup_header { } T_HOBFILE_FACEGROUP_HEADER; typedef struct __attribute__((packed)) hobfile_facegroup_offset { - unsigned int unknow1; + unsigned int unknown1; unsigned int facegroup_offset; } T_HOBFILE_FACEGROUP_OFFSET; @@ -141,7 +159,7 @@ typedef struct __attribute__((packed)) hobfile_meshdef0_0 { } T_HOBFILE_MESHDEF0_0; typedef struct __attribute__((packed)) hobfile_meshdef0_1 { - float unknow1; + float unknown1; unsigned int reserved1; // 12B of zeros unsigned int reserved2; @@ -149,24 +167,24 @@ typedef struct __attribute__((packed)) hobfile_meshdef0_1 { } T_HOBFILE_MESHDEF0_1; typedef struct __attribute__((packed)) hobfile_meshdef0_2 { - unsigned int unknow1; + unsigned int Unknown1; - float unknow2; // Can be a vector??? - float unknow3; - float unknow4; + float unknown2; // Can be a vector??? + float unknown3; + float unknown4; - float unknow5; // Can be a vector??? - float unknow6; - float unknow7; + float unknown5; // Can be a vector??? + float unknown6; + float unknown7; - float unknow8; // Can be a matrix??? - float unknow9; - float unknow10; - float unknow11; + float unknown8; // Can be a matrix??? + float unknown9; + float unknown10; + float unknown11; - float unknow12; // Can be a vector??? - float unknow13; - float unknow14; + float unknown12; // Can be a vector??? + float unknown13; + float unknown14; } T_HOBFILE_MESHDEF0_2; typedef struct __attribute__((packed)) hobfile_meshdef1 { @@ -179,7 +197,7 @@ typedef struct __attribute__((packed)) hobfile_meshdef1 { unsigned int reserved5; unsigned int vertex_count; - unsigned int unknow1; + unsigned int unknown1; unsigned int reserved6; unsigned int faceblock_offset; unsigned int vertexblocks_offset; @@ -199,6 +217,43 @@ typedef struct __attribute__((packed)) hobfile_meshdef1 { unsigned int reserved19; } T_HOBFILE_MESHDEF1; +typedef struct __attribute__((packed)) hobfile_faceblock { + unsigned int reserved1; // 8B of zeros + unsigned int reserved2; + + unsigned int facesOffset; + unsigned int faceCounts; +} T_HOBFILE_FACEBLOCK; + +typedef struct __attribute__((packed)) hobfile_faces_header { + unsigned int flags; + unsigned char b1; + unsigned char b2; + unsigned char b3; + unsigned char faceBlockIntSize; // Bytes size divided by 4, count as number of UInt32 type. + unsigned short headerSeparator; + unsigned short materialIndex; + unsigned short vertexIndices[4]; // Relative to facegroup, the last value is equal to 0 when it's triangle shape. +} T_HOBFILE_FACES_HEADER; + +typedef struct __attribute__((packed)) hobfile_faces_extra_vertex_color { + T_RGBA v1_rgba; + T_RGBA v2_rgba; + T_RGBA v3_rgba; + T_RGBA v4_rgba; // Used with quad type face +} T_HOBFILE_FACES_VERTEX_COLOR; + +typedef struct __attribute__((packed)) hobfile_faces_extra_color { + T_RGBA rgba; +} T_HOBFILE_FACES_COLOR; + +typedef struct __attribute__((packed)) hobfile_faces_extra_vertex_texture { + T_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range + T_TEXCOORD v2_texcoord; + T_TEXCOORD v3_texcoord; + T_TEXCOORD v4_texcoord; // Used with quad type face +} T_HOBFILE_FACES_VERTEX_TEXTURE; + typedef struct __attribute__((packed)) hobfile_vertex { short x; short y;