diff --git a/README.md b/README.md index 1af4cb8..90d3f1b 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ This module can do: ## TODO - Discover all last unknowns fields, etc. +- Parse TEXT format for terrain module ### Using @@ -63,14 +64,14 @@ On Windows system, I can suggest you to use Conan support to help you with depen ```shell mkdir build cd build -conan install .. --build=libpng --build=zlib +conan install .. --build=missing cmake .. -G "MinGW Makefiles" make ``` If you want to do it manually without Conan support, you will probably need to specify the dependency flags for CMake. Ex: -`cmake.exe -D"ZLIB_INCLUDE_DIR=zlib/1.2.11/include" -D"ZLIB_LIBRARY=zlib/1.2.11/lib/libzlib.dll.a" -D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" -D"PNG_LIBRARY=libpng/1.6.37/lib/libpng.dll.a" . -G "MinGW Makefiles"` +`cmake.exe -D"ZLIB_INCLUDE_DIR=zlib/1.2.12/include" -D"ZLIB_LIBRARY=zlib/1.2.12/lib/libzlib.dll.a" -D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" -D"PNG_LIBRARY=libpng/1.6.37/lib/libpng.dll.a" . -G "MinGW Makefiles"` We can also use cross-compilation (after installing `mingw64` and `cmake` packages on your distrib): @@ -78,8 +79,8 @@ We can also use cross-compilation (after installing `mingw64` and `cmake` packag mkdir build && cd build cmake -DGNU_HOST=x86_64-w64-mingw32 \ -DCMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake \ - -D"ZLIB_INCLUDE_DIR=zlib/1.2.11/include" \ - -D"ZLIB_LIBRARY=zlib/1.2.11/lib/libzlib.dll.a" \ + -D"ZLIB_INCLUDE_DIR=zlib/1.2.12/include" \ + -D"ZLIB_LIBRARY=zlib/1.2.12/lib/libzlib.dll.a" \ -D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" \ -D"PNG_LIBRARY=libpng/1.6.37/lib/libpng.dll.a" \ .. diff --git a/RSETexture/src/HMT_Parser.c b/RSETexture/src/HMT_Parser.c deleted file mode 100644 index ac3dada..0000000 --- a/RSETexture/src/HMT_Parser.c +++ /dev/null @@ -1,167 +0,0 @@ -#include "HMT_Parser.h" - - -HMT_FILE *parseHMTFile(FILE *hmt_src) { - int i; - HMT_FILE *_buff = NULL; - - if (hmt_src == NULL) return NULL; - _buff = calloc(1, sizeof(HMT_FILE)); - - rewind(hmt_src); //Rewind file at the start - fread(&(_buff->material_count), 4, 1, hmt_src); // Extract first usefull datas - fread(&(_buff->texture_offset), 4, 1, hmt_src); - - // Read materials - printf("[INFO] Materials detected: %d\n", _buff->material_count); - _buff->materials_list = calloc(_buff->material_count, sizeof(HMT_MATERIAL)); // Create a big list of materials entries - for (i=0; i<_buff->material_count; i++) { - // Extract materials datas - if (readMaterial(&(_buff->materials_list[i]), hmt_src) != 0) { - purgeHMTFromMemory(_buff); - return NULL; - } - } - - // Read textures - fseek(hmt_src, _buff->texture_offset, SEEK_SET); - fread(&(_buff->texture_count), 4, 1, hmt_src); - printf("[INFO] Textures detected: %d\n", _buff->texture_count); - if (_buff->texture_count > 0) { - _buff->textures_list = calloc(_buff->texture_count, sizeof(HMT_TEXTURE)); // Create a big list of textures entries - for (i=0; i<_buff->texture_count; i++) { - // Extract textures datas - if (readTexture(&(_buff->textures_list[i]), hmt_src) != 0) { - purgeHMTFromMemory(_buff); - return NULL; - } - } - } - - return _buff; -} - -int readMaterial(HMT_MATERIAL *mat, FILE *hmt_src) { - if (mat == NULL || hmt_src == NULL) return EXIT_FAILURE; - - fread(mat, sizeof(HMT_MATERIAL), 1, hmt_src); - - if (_options & 0x1) { - if (mat->zero != 0 || mat->hex_a != 0x0A) printf("\n Uncommon file detected!\n"); - printf(" Material type: %d\n Texture index: %d\n\n", mat->type_, mat->texture_index); //TODO: To develop?! - } - - return EXIT_SUCCESS; -} - -int readTexture(HMT_TEXTURE *tex, FILE *hmt_src) { - unsigned char u0,u1,bpp; - long pos; - RS_IMAGE_DESC desc; - - fread(&(tex->data_offset), 4, 1, hmt_src); - fseek(hmt_src, 28, SEEK_CUR); // Skip zeros area - fread(&(tex->palette_offset), 4, 1, hmt_src); - fread(&(tex->textureName_offset), 4, 1, hmt_src); - fread(&(tex->width), 2, 1, hmt_src); - fread(&(tex->height), 2, 1, hmt_src); - - fread(&u0, 1, 1, hmt_src); - fread(&bpp, 1, 1, hmt_src); - fread(&(tex->image.type_), 1, 1, hmt_src); - fread(&u1, 1, 1, hmt_src); - fread(&(tex->image.alpha_color._red), 1, 1, hmt_src); - fread(&(tex->image.alpha_color._green), 1, 1, hmt_src); - fread(&(tex->image.alpha_color._blue), 1, 1, hmt_src); - fread(&(tex->image.alpha_color._alpha), 1, 1, hmt_src); - - pos = ftell(hmt_src); - fseek(hmt_src, tex->textureName_offset, SEEK_SET); - fread(&(tex->name), 16, 1, hmt_src); - fseek(hmt_src, pos, SEEK_SET); - - desc = getImageDescFromType(tex->image.type_); - tex->image.paletteEntries = desc.palette_entries; - tex->image.sampleBits = desc.sample_bits; - tex->image.width = tex->width; - tex->image.height = tex->height; - - if (_options & VERBOSE_ENABLED) { - printf(" Texture name: %s\n", tex->name); - printf(" Size w: %ld h: %ld\n", tex->width, tex->height); - printf(" u0: %d u1: %d\n", u0, u1); - printf(" Texture type: %d\n", tex->image.type_); - printf(" Samplebits: %d\n", tex->image.sampleBits); - printf(" Palette entries: %d\n", tex->image.paletteEntries); - printf(" Transparent color (RGB): %X %X %X\n", tex->image.alpha_color._red, tex->image.alpha_color._green, tex->image.alpha_color._blue); - printf(" Palette offset: %d\n", tex->palette_offset); - printf(" Data offset: %d\n", tex->data_offset); - printf("\n"); - } - - if (tex->palette_offset > 0) { - if (_options & VERBOSE_ENABLED) printf("\nPalette entries: %d\n", tex->image.paletteEntries); - fseek(hmt_src, tex->palette_offset, SEEK_SET); - getPaletteFromFile(&(tex->image), hmt_src); - } - fseek(hmt_src, tex->data_offset, SEEK_SET); - getSamplesFromFile(&(tex->image), hmt_src); - decodePixels(&(tex->image)); - - fseek(hmt_src, pos, SEEK_SET); - - return EXIT_SUCCESS; -} - -int getPaletteFromFile(RS_IMAGE *img, FILE *f) { - int entries = img->paletteEntries; - - switch (entries) { - case 16: - case 256: - fread(img->palette, sizeof(PIXEL), entries, f); - break; - default: - break; - } - - return EXIT_SUCCESS; -} - -int getSamplesFromFile(RS_IMAGE *img, FILE *f) { - int sample_bits = img->sampleBits; - int size = div(img->width*img->height*sample_bits, 8).quot; - - #ifdef _WIN32 - if (f->_bufsiz >= ftell(f)+size) { - printf("[ERR] WARNING! Please fix size/sample."); - return EXIT_FAILURE; - } - #else - if (__fbufsize(f) >= ftell(f)+size) { - printf("[ERR] WARNING! Please fix size/sample."); - return EXIT_FAILURE; - } - #endif - - - img->samples = calloc(1, size); - fread(img->samples, size, 1, f); - if (img->type_ == 2) fread(img->samples, div(size, 4).quot, 1, f); - - return EXIT_SUCCESS; -} - -void purgeHMTFromMemory(HMT_FILE *_f) { - if (_f == NULL) return; - - if (_f->textures_list != NULL) { - if (_f->textures_list->image.pixels != NULL) free(_f->textures_list->image.pixels); - if (_f->textures_list->image.samples != NULL) free(_f->textures_list->image.samples); - } - free(_f->textures_list); - - if (_f->materials_list != NULL) free(_f->materials_list); - - free(_f); -} diff --git a/RSETexture/src/HMT_Parser.h b/RSETexture/src/HMT_Parser.h deleted file mode 100644 index 3600f5c..0000000 --- a/RSETexture/src/HMT_Parser.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef HMT_PARSER_H_ -#define HMT_PARSER_H_ - -#include -#ifndef _WIN32 - #include -#endif -#include -#include "options.h" -#include "RS_images.h" - -///////////////////////////// -///// Define HMT types ////// -///////////////////////////// - -/** - * @brief Material struct inside HMT file type - * - * Actual RE material struct:\n - * 4B material entry count MC\n - * 4B offset after material entries / offset to textures\n - * MC * material entry (36B)\n - * [\n - * 2B int material/texture type:\n - * 1 - material with texture\n - * 2 - material without texture\n - * 2B int texture index\n - * 4B float (scale factor?)\n - * 4B float (always 1.0)\n - * 4B int zero\n - * 4B int 0x0A\n - * 16B name\n - * ]\n - * - * @image html hmt_materialDef.png - */ -typedef struct HMTMaterial { - short type_; /**< Material type:\n 1 = Material with texture\n 2 = Material without texture */ - short texture_index; - float unknow1,unknow2; - int zero; - int hex_a; - char name[16]; -}HMT_MATERIAL; - -/** - * @brief Texture struct inside HMT file type - * - * Actual RE texture struct:\n - * 4B int texcount Tc\n - * TC * texture entry 52B\n - * [\n - * 4B int pixel offset\n - * 28B zero\n - * 4B int palette offset, 0 = no palette\n - * 4B int texname offset\n - * 2B int width\n - * 2B int height\n - * 8B texture format [\n - * 1B int : always 1?\n - * 1B int : bits per sample?\n - * 1B int : subtype:\n - * -0 - palette 16x3B RGB, 4bit per pixel\n - * -1 - 256x3B palette RGB, 8bit per pixel\n - * -3 - RGBA 32bpp\n - * -4 - greyscale, 4bpp\n - * -5 - grayscale, 8bpp\n - * 1B int ? 0, 0x40, 0x80\n - * 4B RGBA transparent color?\n - * ]\n - * ]\n - * - * @image html hmt_textureDef.png - */ -typedef struct HMTTexture { - int data_offset; - int palette_offset; - int textureName_offset; - unsigned long width, height; - char name[16]; - RS_IMAGE image; -}HMT_TEXTURE; - -/** - * @brief Instance of HMTFile in memory - * This structure contain all parsed data for a single HMT file. - */ -typedef struct HMTFile { - int material_count; /**< Number of materials registered inside HMTFile instance. */ - int texture_offset; /**< Address from which texture data begins. */ - int texture_count; /**< Number of textures registered inside HMTFile instance. */ - HMT_MATERIAL *materials_list; /**< Starting pointer of the materials list. Managed like an array and declared as a pointer */ - HMT_TEXTURE *textures_list; /**< Starting pointer of the textures list. Managed like an array and declared as a pointer*/ -}HMT_FILE; - - -///////////////////////////// -///// Declare functions ///// -///////////////////////////// -HMT_FILE *parseHMTFile(FILE *hmt_src); -int readMaterial(HMT_MATERIAL *mat, FILE *hmt_src); -int readTexture(HMT_TEXTURE *tex, FILE *hmt_src); -HMT_MATERIAL *getMaterialFromIndex(int i); -HMT_MATERIAL *getMaterialFromName(char *matName); -HMT_TEXTURE *getTextureFromIndex(int i); -HMT_TEXTURE *getTextureFromMaterial(HMT_MATERIAL *mat); -int getPaletteFromFile(RS_IMAGE *img, FILE *f); -int getSamplesFromFile(RS_IMAGE *img, FILE *f); -void purgeHMTFromMemory(HMT_FILE *_f); - -#endif diff --git a/RSETexture/src/Image_Exporter.c b/RSETexture/src/Image_Exporter.c deleted file mode 100644 index dd43284..0000000 --- a/RSETexture/src/Image_Exporter.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "Image_Exporter.h" - - -int saveToPNG(RS_IMAGE *img, char *tex_path, char *hmt_fileName) { - if (tex_path == NULL || img == NULL) return EXIT_FAILURE; - char export_path[128]; - FILE *_png_f = NULL; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - size_t x,y; - png_byte **row_ptrs = NULL; - PIXEL_A *pixel = NULL; - //int pixel_size = 3; - //int depth = 8; //bit par color channel (RGB) - - if (_options & OUTPUT_DIR) { - strcpy(export_path, hmt_fileName); - #ifdef _WIN32 - strcat(export_path, "-out\\"); - #else - strcat(export_path, "-out/"); - #endif - strcat(export_path, tex_path); - } else { - strcpy(export_path, tex_path); - } - strcat(export_path, ".png"); - _png_f = fopen(export_path, "wb"); - if (_png_f == NULL) return EXIT_FAILURE; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - fclose(_png_f); - return EXIT_FAILURE; - } - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - fclose(_png_f); - return EXIT_FAILURE; - } - - // Set image attributes - png_set_IHDR(png_ptr, info_ptr, img->width, img->height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - // Init PNG datas - row_ptrs = png_malloc(png_ptr, img->height * sizeof(png_byte *)); - for (y=0; yheight; y++) { - png_byte *row = png_malloc(png_ptr, img->width*sizeof(PIXEL_A)); - row_ptrs[y] = row; - for (x=0; xwidth; x++) { - pixel = pixelAt(img, x , y); - if(pixel == NULL) return EXIT_FAILURE; - - *row++ = pixel->_red; - *row++ = pixel->_green; - *row++ = pixel->_blue; - *row++ = pixel->_alpha; - } - } - - png_init_io(png_ptr, _png_f); - png_set_rows(png_ptr, info_ptr, row_ptrs); - png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - for (y=0; yheight; y++) { - png_free(png_ptr, row_ptrs[y]); - } - png_free(png_ptr, row_ptrs); - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(_png_f); - - return EXIT_SUCCESS; -} diff --git a/RSETexture/src/Image_Exporter.h b/RSETexture/src/Image_Exporter.h deleted file mode 100644 index d552081..0000000 --- a/RSETexture/src/Image_Exporter.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef IMAGE_EXPORTER_H_ -#define IMAGE_EXPORTER_H_ - -#include "options.h" -#include "RS_images.h" -#include -#include - - -int saveToPNG(RS_IMAGE *img, char *tex_name, char *hmt_fileName); - -#endif diff --git a/RSETexture/src/RSETexture.c b/RSETexture/src/RSETexture.c index 8871502..b612315 100644 --- a/RSETexture/src/RSETexture.c +++ b/RSETexture/src/RSETexture.c @@ -1,77 +1,165 @@ -/* - ================================================================================ - Name : Texture-Extractor.c - Author : JackCarterSmith - License : GPL-v3.0 - Description : DAT textures extractor to PNG format with enhanced function in C - ================================================================================ +/** + * @file RSETexture.c + * @date 28/08/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief HMT texture parser and export to PNG format. + * */ -#include "Texture-Extractor.h" +#include +#include +#include +#if defined(_WIN32) + #include +#else + #include + #include +#endif +#include "options.h" +#include +#include +#include "texture_export.h" -int _options; // Global options settings variable +/* + * 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[]) { - // Init buffer vars - HMT_FILE *hmt_fdatas = NULL; - int file_index; + T_PROG_OPTIONS _opts; + unsigned char p; - printf("\n*** RogueSquadron Extractor (RSE) - TEXTURE module - v%s ***\n", VERSION); + // Hello world! + printf("\n*~[ Rogue Squadron Extractor (RSE) - RSPTextureLib v%s ]~*\n", RSPTexture_getVersion()); - // Check if filenames arguments exist + // Check for arguments if (argc < 2) { printf("\n[ERR] No input file/commands specified!\n"); dispHelp(); - return EXIT_FAILURE; //TODO: implement own error codes system - } - _options = checkArgs(argv, argc); // Analyse program arguments - if (_options == -1) return EXIT_SUCCESS; - - // Do the work - for (file_index=(_options >> 8) & 0xFF; file_indexraw & 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_RSPTEXTURE_HMT structure to store extracted datas. + hmtStruct = calloc(1, sizeof(T_RSPTEXTURE_HMT)); + if (hmtStruct) { + // Parse data from HMT file and put in T_RSPTEXTURE_HMT structure. + if (RSPTexture_processHMTFile(hmtStruct, args_value[file_index], libParams) != RSPLIB_SUCCESS) { + printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]); + RSPTexture_freeHMT(hmtStruct); + return RSPLIB_ERROR_PROCESS; + } + } else return RSPLIB_ERROR_MEMORY; + + // Create output folders structure. + if (p_opts->output_dir) createSubDir(args_value[file_index]); + + // Export each texture as a PNG picture. + for ( i = 0; i < hmtStruct->textures_count; i++ ) { + switch (hmtStruct->textures[i].type) { + case 0: + case 1: + case 3: + case 4: + case 5: + if (exportPNGTexture(&(hmtStruct->textures[i]), args_value[file_index], p_opts) == RSPLIB_SUCCESS) + printf("[INFO] Successfully exported texture %s to PNG format.\n", hmtStruct->textures[i].name); + else + printf("[ERR] Failed to export texture %s to PNG format!\n", hmtStruct->textures[i].name); + break; + default: + printf("[WARN] Can't export %s ! Image type %d not currently supported!\n", hmtStruct->textures[i].name, hmtStruct->textures[i].type); + } + } + + RSPTexture_freeHMT(hmtStruct); + } + + return RSPLIB_SUCCESS; +} + +static unsigned short checkInputArgs(T_PROG_OPTIONS* opt_ptr, int p_arg_nbr, char* p_args[]) { char test[256]; int i; - if (arg_nbr > 1) { - for (i=1; iraw = 0; + 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 -1; - } else if (strcmp(args[i], "-v") == 0) { - _o |= VERBOSE_ENABLED; + 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(args[i], "-no-subdir") == 0) { - _o &= ~OUTPUT_DIR; - printf("[OPTN] Extract to current directory.\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 { - printf("[ERR] Unknown option: %s\n", args[i]); + printf("[ERR] Unknown option: %s\n", p_args[i]); } } - _o = (i << 8) | (_o & 0x00FF); + + opt_ptr->input_files_cnt = i; + return RSPLIB_SUCCESS; } - return _o; + return RSPLIB_ERROR_ARGS_NULL; } -void createSubDir(char *dirName) { +static void createSubDir(char *dirName) { if (dirName == NULL) return; - char _dir[260]; //TODO: Change directory management - strcpy(_dir, dirName); - strcat(_dir, "-out"); + char _dir[1024]; + + snprintf(_dir, 1024, "%s-out", dirName); #ifdef _WIN32 CreateDirectory(_dir, NULL); @@ -80,54 +168,12 @@ void createSubDir(char *dirName) { #endif } -HMT_FILE *extractDatasFromHMT(char *hmt_filename) { - FILE *_hmtFile = NULL; - HMT_FILE *hmt_fdatas = NULL; - - _hmtFile = fopen(hmt_filename, "rb"); - if (_hmtFile != NULL) { - printf("\n=============================================\n[INFO] - Parsing file: %s ...\n", hmt_filename); - hmt_fdatas = parseHMTFile(_hmtFile); - if (hmt_fdatas == NULL) printf("[ERR] Failed to parse datas from %s\n", hmt_filename); - } else { - printf("\n[ERR] Input file %s not found!\n", hmt_filename); - } - fclose(_hmtFile); - - return hmt_fdatas; -} - -int exportTextures(HMT_FILE *hmt_f, char *filename) { - int i; - - if(hmt_f->texture_count > 0) { - if (_options & OUTPUT_DIR) createSubDir(filename); - for (i=0; itexture_count; i++) { - switch (hmt_f->textures_list[i].image.type_) { - case 0: - case 1: - case 3: - case 4: - case 5: - if (saveToPNG(&(hmt_f->textures_list[i].image), hmt_f->textures_list[i].name, filename)) { - printf("[ERR] Failed saving image file: %s\n", hmt_f->textures_list[i].name); - return EXIT_FAILURE; - } else printf("[INFO] Saved image file: %s\n", hmt_f->textures_list[i].name); - break; - default: - printf("[WARN] Can't export %s ! Image type %d not currently supported! (WIP)\n", hmt_f->textures_list[i].name, hmt_f->textures_list[i].image.type_); - } - - } - } - - return EXIT_SUCCESS; -} - -void dispHelp() { +static void dispHelp() { printf("\n"); - printf("Options:\n -h Print this message\n -v Activate verbose console output\n -no-subdir Extract textures inside current folder\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("\n"); - printf("Usage: RSE-Texture_%s [options] \n", VERSION); + printf("Usage: RSETexture [options] \n"); printf("\n"); } diff --git a/RSETexture/src/RS_images.c b/RSETexture/src/RS_images.c deleted file mode 100644 index b52ad8d..0000000 --- a/RSETexture/src/RS_images.c +++ /dev/null @@ -1,152 +0,0 @@ -#include "RS_images.h" - - -//extern int _options; // Global options settings variable - -void decodePixels(RS_IMAGE *img) { - int size; - - //img->pixels = NULL; - if (!(img->type_ == 0 || - img->type_ == 1 || - img->type_ == 2 || - img->type_ == 3 || - img->type_ == 4 || - img->type_ == 5)) return; - - size = img->height * img->width; - switch (img->sampleBits) { - case 32: - img->pixels = calloc(1, size * sizeof(PIXEL_A)); - memcpy(img->pixels, img->samples, size * sizeof(PIXEL_A)); - break; - case 4: - img->pixels = calloc(1, size * sizeof(PIXEL_A)); - if (img->paletteEntries == 0) { - convert4bitsGreyTo32bitsRGBA(img->samples, img->pixels, size, &(img->alpha_color)); - } else if (img->paletteEntries == 16) { - convert4bitsTo32bitsRGBA(img->samples, img->pixels, size, img->palette, &(img->alpha_color)); - } - break; - case 8: - if (img->paletteEntries == 0) { - img->pixels = calloc(1, size); - memcpy(img->pixels, img->samples, size); - } else if (img->paletteEntries == 256) { - img->pixels = calloc(1, size * sizeof(PIXEL_A)); - convert8bitsTo32bitsRGBA(img->samples, img->pixels, size, img->palette, &(img->alpha_color)); - } - break; - case 16: - img->pixels = calloc(1, size); - useOddBytes(img->samples, img->pixels, size); - break; - default: - break; - } -} - -int isTransparentColor(PIXEL_A *testColor, PIXEL_A *transp_color) { - if (transp_color == NULL || testColor == NULL) return -2; - - if (!(testColor->_red == transp_color->_red)) return -1; - if (!(testColor->_green == transp_color->_green)) return -1; - if (!(testColor->_blue == transp_color->_blue)) return -1; - - return 0; -} - -void convert4bitsGreyTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int sampling, PIXEL_A *transp_color) { - int i; - unsigned char v; - - for(i=0; i> 4 & 0xF) * 256, 16).quot; - pixels_tab[i*2]._green = div((v >> 4 & 0xF) * 256, 16).quot; - pixels_tab[i*2]._blue = div((v >> 4 & 0xF) * 256, 16).quot; - if (isTransparentColor(&(pixels_tab[i*2]), transp_color) == 0) pixels_tab[i*2]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer - pixels_tab[i*2+1]._red = div((v & 0xF) * 256, 16).quot; - pixels_tab[i*2+1]._green = div((v & 0xF) * 256, 16).quot; - pixels_tab[i*2+1]._blue = div((v & 0xF) * 256, 16).quot; - if (isTransparentColor(&(pixels_tab[i*2+1]), transp_color) == 0) pixels_tab[i*2+1]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2+1]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer - } -} - -void convert4bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color) { - int i,index; - - for(i=0; i> 4) & 0xF]._red; - pixels_tab[i*2]._green = pal[(index >> 4) & 0xF]._green; - pixels_tab[i*2]._blue = pal[(index >> 4) & 0xF]._blue; - if (isTransparentColor(&(pixels_tab[i*2]), transp_color) == 0) pixels_tab[i*2]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer - pixels_tab[i*2+1]._red = pal[index & 0xF]._red; - pixels_tab[i*2+1]._green = pal[index & 0xF]._green; - pixels_tab[i*2+1]._blue = pal[index & 0xF]._blue; - if (isTransparentColor(&(pixels_tab[i*2+1]), transp_color) == 0) pixels_tab[i*2]._alpha = 0xFF - transp_color->_alpha; else pixels_tab[i*2+1]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer - } -} - -void convert8bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color) { - int i,index; - - for(i=0; i_alpha; else pixels_tab[i]._alpha = 0xFF; // Test if color is a transparent color and adjust alpha layer - } -} - -void useOddBytes(unsigned char *src, PIXEL_A *dst, int size) { - int i; - - for(i=0; i<(size-1); i++) { - //dst[i] = src[i*2+1]; //FIXME: Implement optimized byte shifting - //dst[i]._red = src[i*2+1]; - //dst[i]._green = src[i*2+1]; - //dst[i]._blue = src[i*2+1]; - } -} - -PIXEL_A *pixelAt(RS_IMAGE *img, int posX , int posY) { - return img->pixels + img->width * posY + posX; -} - -RS_IMAGE_DESC getImageDescFromType(unsigned char type) { - RS_IMAGE_DESC desc; - - switch(type) { - case 0: - desc.palette_entries = 16; - desc.sample_bits = 4; - break; - case 1: - desc.palette_entries = 256; - desc.sample_bits = 8; - break; - case 2: - desc.palette_entries = 0; - desc.sample_bits = 16; - break; - case 3: - desc.palette_entries = 0; - desc.sample_bits = 32; - break; - case 4: - desc.palette_entries = 0; - desc.sample_bits = 4; - break; - case 5: - desc.palette_entries = 0; - desc.sample_bits = 8; - break; - default: - break; - } - - return desc; -} diff --git a/RSETexture/src/RS_images.h b/RSETexture/src/RS_images.h deleted file mode 100644 index f24c7c5..0000000 --- a/RSETexture/src/RS_images.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef RS_IMAGES_H_ -#define RS_IMAGES_H_ - -#include -#include -#include -//#include "options.h" - -/** - * @brief Constant contain the number of channel inside a PIXEL definition. - */ -#define PIXEL_MEMBERS_NBR 4 - - -///////////////////////////// -///// Define new types ////// -///////////////////////////// - -/** - * @brief RGBA pixel structure, used to store datas for implementation inside PNG files. - */ -typedef struct PixelRGBA { - unsigned char _red; - unsigned char _green; - unsigned char _blue; - unsigned char _alpha; -}PIXEL_A; - -/** - * @brief RGB pixel structure, used to store datas for implementation inside PNG files, optimised version without alpha channel support. - */ -typedef struct PixelRGB { - unsigned char _red; - unsigned char _green; - unsigned char _blue; -}PIXEL; - -/** - * @brief Image definition from Rogue Squadron HMT files - */ -typedef struct RSImage { - int data_size; /**< Image bytes size */ - int width, height; - unsigned char type_; /**< Image type (0 = RBG/4bits per pixel, 1 = RBG/8bpp, 3 = RGBA/32bpp , 4 = grayscale/4bpp, 5 = grayscale/8bpp */ - unsigned char sampleBits; /**< Bits per samble */ - int paletteEntries; - PIXEL_A alpha_color; - PIXEL_A *pixels; /**< Image pixels list, managed like an array and declared as a pointer */ - unsigned char *samples; /**< Image samples list managed like an array and declared as a pointer */ - PIXEL palette[256]; /**< Image palette definition */ //TODO: Create union struct type instead -}RS_IMAGE; - -typedef struct RSImage_desc { - int palette_entries; - int sample_bits; -}RS_IMAGE_DESC; - - -///////////////////////////// -///// Declare functions ///// -///////////////////////////// - -/** - * @brief Conversion table for image type using RS_IMAGE_DESC. - * Return RS_IMAGE_DESC by providing image type as int\n - * - * Detailed conversion:\n\n - * Type 0 -> Palette entries: 16 ; Sample bits: 4\n - * Type 1 -> Palette entries: 256 ; Sample bits: 8\n - * Type 2 -> Palette entries: 0 ; Sample bits: 16\n - * Type 3 -> Palette entries: 0 ; Sample bits: 32\n - * Type 4 -> Palette entries: 0 ; Sample bits: 4\n - * Type 5 -> Palette entries: 0 ; Sample bits: 8\n - */ -RS_IMAGE_DESC getImageDescFromType(unsigned char type); //TODO: Optimise function - -int isTransparentColor(PIXEL_A *testColor, PIXEL_A *transp_color); -void convert4bitsGreyTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int sampling, PIXEL_A *transp_color); -void convert4bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color); -void convert8bitsTo32bitsRGBA(unsigned char *samples_tab, PIXEL_A *pixels_tab, int size, PIXEL *pal, PIXEL_A *transp_color); -void useOddBytes(unsigned char *src, PIXEL_A *dst, int size); -void decodePixels(RS_IMAGE *img); -PIXEL_A *pixelAt(RS_IMAGE *img, int posX , int posY); - -#endif diff --git a/RSETexture/src/options.h b/RSETexture/src/options.h index b8f77ca..b6173a4 100644 --- a/RSETexture/src/options.h +++ b/RSETexture/src/options.h @@ -1,9 +1,29 @@ +/** + * @file options.h + * @date 29/07/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Shared options structure definition and declaration. + * + */ + #ifndef OPTIONS_H_ #define OPTIONS_H_ -#define VERBOSE_ENABLED 0x0001 -#define OUTPUT_DIR 0x0002 +/// Options structure +typedef union u_prog_options { + struct { + unsigned char verbose_mode:1; //!< Output simple details about ID and other "light" things. + 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. -extern int _options; + unsigned char output_dir:1; //!< Export extracted datas to a sub-directory. -#endif + unsigned short reserved0:12; //!< 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_ */ diff --git a/RSETexture/src/texture_export.c b/RSETexture/src/texture_export.c new file mode 100644 index 0000000..d7f9f3d --- /dev/null +++ b/RSETexture/src/texture_export.c @@ -0,0 +1,96 @@ +/** + * @file texture_export.c + * @date 29/08/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Export texture datas to PNG format. + * + */ + +#include +#include +#include +#include +#include "options.h" +#include +#include +#include "texture_export.h" + + +static inline T_R8G8B8A8 *getPixelAt(const T_RSPTEXTURE_TEXTURE *tex, const unsigned int posX , const unsigned int posY) { + return tex->pixels + tex->width * posY + posX; +} + +unsigned char exportPNGTexture(const T_RSPTEXTURE_TEXTURE* pTextureObj, const char* out_path, T_PROG_OPTIONS* p_opts) { + char export_path[1024]; + FILE *_png_f = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + size_t x,y; + png_byte **row_ptrs = NULL; + T_R8G8B8A8 *pixel = NULL; + //int pixel_size = 3; + //int depth = 8; //bit par color channel (RGB) + + if (pTextureObj == NULL || out_path == NULL) + return RSPLIB_ERROR_ARGS_NULL; + +#ifdef _WIN32 + if (p_opts->output_dir) + snprintf(export_path, 1024, "%s-out\\%s.png", out_path, pTextureObj->name); + else + snprintf(export_path, 1024, "%s.png", pTextureObj->name); +#else + if (p_opts->output_dir) + snprintf(export_path, 1024, "%s-out/%s.png", out_path, pTextureObj->name); + else + snprintf(export_path, 1024, "%s.png", pTextureObj->name); +#endif + + // Open export file and add PNG header + _png_f = fopen(export_path, "wb"); + if (_png_f == NULL) return RSPLIB_ERROR_MEMORY; + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + fclose(_png_f); + return RSPLIB_ERROR_MEMORY; + } + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + fclose(_png_f); + return RSPLIB_ERROR_MEMORY; + } + + // Set image attributes + png_set_IHDR(png_ptr, info_ptr, pTextureObj->width, pTextureObj->height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // Store PNG datas in buffer + row_ptrs = png_malloc(png_ptr, pTextureObj->height * sizeof(png_byte *)); + for ( y = 0; y < pTextureObj->height; y++ ) { + png_byte *row = png_malloc(png_ptr, pTextureObj->width * sizeof(T_R8G8B8A8)); + row_ptrs[y] = row; + for ( x = 0; x < pTextureObj->width; x++ ) { + pixel = getPixelAt(pTextureObj, x , y); + *row++ = pixel->r; + *row++ = pixel->g; + *row++ = pixel->b; + *row++ = pixel->a; + } + } + + // Write pixels datas + png_init_io(png_ptr, _png_f); + png_set_rows(png_ptr, info_ptr, row_ptrs); + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + // Clean up + for ( y = 0; y < pTextureObj->height; y++ ) { + png_free(png_ptr, row_ptrs[y]); + } + png_free(png_ptr, row_ptrs); + png_destroy_write_struct(&png_ptr, &info_ptr); + + fclose(_png_f); + + return RSPLIB_SUCCESS; +} diff --git a/RSETexture/src/texture_export.h b/RSETexture/src/texture_export.h new file mode 100644 index 0000000..a79d7b0 --- /dev/null +++ b/RSETexture/src/texture_export.h @@ -0,0 +1,15 @@ +/** + * @file texture_export.h + * @date 29/08/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Export texture datas to PNG format. + * + */ + +#ifndef TEXTURE_EXPORT_H_ +#define TEXTURE_EXPORT_H_ + +unsigned char exportPNGTexture(const T_RSPTEXTURE_TEXTURE* pTextureObj, const char* out_path, T_PROG_OPTIONS* p_opts); + +#endif /* TEXTURE_EXPORT_H_ */ diff --git a/RSPTextureLib/src/RSPTexture.c b/RSPTextureLib/src/RSPTexture.c index 9c06cfa..e32518e 100644 --- a/RSPTextureLib/src/RSPTexture.c +++ b/RSPTextureLib/src/RSPTexture.c @@ -37,30 +37,17 @@ unsigned short RSPTexture_processHMTFileMemory( T_RSPTEXTURE_HMT* hmtStruct, con return RSP_TextureLib_ParseHMTMemFile((MEMFILE)memFilePtr, hmtStruct, ¶ms); } +void RSPTexture_freeHMT(T_RSPTEXTURE_HMT* hmtStruct) { + unsigned int i; + if (hmtStruct == NULL) return; - - - - - - - - - - -/* -void purgeHMTFromMemory(HMT_FILE *_f) { - if (_f == NULL) return; - - if (_f->textures_list != NULL) { - if (_f->textures_list->image.pixels != NULL) free(_f->textures_list->image.pixels); - if (_f->textures_list->image.samples != NULL) free(_f->textures_list->image.samples); + if ((hmtStruct->textures_count > 0) && hmtStruct->textures) { + for ( i = 0; i < hmtStruct->textures_count; i++ ) + if (hmtStruct->textures[i].pixels) free(hmtStruct->textures[i].pixels); } - free(_f->textures_list); - if (_f->materials_list != NULL) free(_f->materials_list); + if (hmtStruct->materials) free(hmtStruct->materials); - free(_f); + free(hmtStruct); } -*/ diff --git a/RSPTextureLib/src/hmt_parser.c b/RSPTextureLib/src/hmt_parser.c index 55be5b1..ee81379 100644 --- a/RSPTextureLib/src/hmt_parser.c +++ b/RSPTextureLib/src/hmt_parser.c @@ -110,7 +110,7 @@ static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT* pHmtStruct, const MEMF // Get global infos pHmtStruct->materials_count = ((T_HMTFILE_HEADER1 *)pMemfile)->materials_count; pHmtStruct->texture_offset = ((T_HMTFILE_HEADER1 *)pMemfile)->textures_offset; - pHmtStruct->textures_count = ((T_HMTFILE_HEADER2 *)pMemfile + pHmtStruct->texture_offset)->textures_count; + pHmtStruct->textures_count = ((T_HMTFILE_HEADER2 *)(pMemfile + pHmtStruct->texture_offset))->textures_count; printf("[INFO] > Materials count: %d\n", pHmtStruct->materials_count); printf("[INFO] > Textures count: %d\n", pHmtStruct->textures_count); @@ -150,11 +150,14 @@ static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMe // Get material name //memcpy(pHmt->materials[i].name, ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->name, 16); - snprintf((char *)pHmt->materials[i].name, 16, "%s", ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->name); + snprintf((char *)pHmt->materials[i].name, 16, "%s", ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->name); // Get material datas - pHmt->materials[i].type = ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->type; - pHmt->materials[i].texture_index = ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->texture_index; + pHmt->materials[i].type = ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->type; + pHmt->materials[i].texture_index = ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->texture_index; if (pParams->verbose_mode) { printf("[INFO] > Material name: %s\n", pHmt->materials[i].name); @@ -162,11 +165,14 @@ static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMe printf("[INFO] > Material text. index: %d\n", pHmt->materials[i].texture_index); } if (pParams->debug_mode) { - printf("[DBG] > Material reserved0: %.8f\n", ((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved0); - printf("[DBG] > Material reserved1: %.8f\n", ((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved1); - if (((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved2 != 0 - || ((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved3 == 0xA) - printf("[DBG] > Material: Zero/0xA different.\n"); + printf("[DBG] > Material reserved0: %.8f\n", ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved0); + printf("[DBG] > Material reserved1: %.8f\n", ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved1); + printf("[DBG] > Material reserved2 (zero): 0x%X\n", ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved2); + printf("[DBG] > Material reserved3 (0xA): 0x%X\n", ((T_HMTFILE_MATERIAL *)(pMemfile + + sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved3); } if (pParams->debug_mode) printf("\n-----------------------End of material #%d---------------------------\n", i); @@ -198,12 +204,12 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem if (pParams->debug_mode) printf("\n-----------------------Begin of texture #%d-------------------------\n", i); // Get texture size infos - pHmt->textures[i].width = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)) - )->tex_width; - pHmt->textures[i].height = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)) - )->tex_height; - pHmt->textures[i].type = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)) - )->tex_format.type; + pHmt->textures[i].width = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_width; + pHmt->textures[i].height = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_height; + pHmt->textures[i].type = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.type; switch (pHmt->textures[i].type) { case 0: pHmt->textures[i].sample_bits = 4; @@ -233,17 +239,19 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem pHmt->textures[i].sample_bits = 0; pHmt->textures[i].palette_entries = 0; } - memcpy(&pHmt->textures[i].alpha_color, &((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->tex_format.transparent_color, sizeof(T_R8G8B8A8)); + memcpy(&pHmt->textures[i].alpha_color, &((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.transparent_color, sizeof(T_R8G8B8A8)); // Get texture datas offsets - pHmt->textures[i].pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)) - )->pixels_offset; - pHmt->textures[i].palette_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)) - )->palette_offset; + pHmt->textures[i].pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->pixels_offset; + pHmt->textures[i].palette_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->palette_offset; // Get texture name //memcpy(pHmt->textures[i].name, pMemfile + ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->texname_offset, 16); - snprintf((char *)pHmt->textures[i].name, 16, "%s", pMemfile + ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->texname_offset); + snprintf((char *)pHmt->textures[i].name, 16, "%s", pMemfile + ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->texname_offset); if (pParams->verbose_mode) { printf("[INFO] > Texture name: %s\n", pHmt->textures[i].name); @@ -251,12 +259,12 @@ static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMem printf("[INFO] > Texture type: %d\n", pHmt->textures[i].type); printf("[INFO] > Samplebits: %d\n", pHmt->textures[i].sample_bits); printf("[INFO] > Palette entries: %d\n", pHmt->textures[i].palette_entries); - printf("[INFO] > Texture bits per sample: %d\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->tex_format.sample_bitsize); + printf("[INFO] > Texture bits per sample: %d\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.sample_bitsize); printf("[INFO] > Texture transparent color: %d %d %d %d\n", pHmt->textures[i].alpha_color.r, pHmt->textures[i].alpha_color.g, pHmt->textures[i].alpha_color.b, pHmt->textures[i].alpha_color.a); } if (pParams->debug_mode) { - printf("[DBG] > Texture unknown0: 0x%X\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->tex_format.unknown0); - if (((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1)))->tex_format.reserved0 != 1) + printf("[DBG] > Texture unknown0: 0x%X\n", ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.unknown0); + if (((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.reserved0 != 1) printf("[DBG] > Texture: Always 1 different.\n"); printf("[DBG] > Texture palette offset: 0x%X\n", pHmt->textures[i].palette_offset); printf("[DBG] > Texture pixels offset: 0x%X\n", pHmt->textures[i].pixels_offset);