From 3b1b358363d0b75874b58767edbb9a2ffe59bf2b Mon Sep 17 00:00:00 2001 From: JackCarterSmith Date: Sat, 27 Aug 2022 20:15:25 +0200 Subject: [PATCH] Imported old parser --- RSPTextureLib/include/RSPTexture_datatypes.h | 62 ++- RSPTextureLib/src/RSPTexture.c | 32 +- RSPTextureLib/src/RS_images.c | 152 ------ RSPTextureLib/src/RS_images.h | 85 ---- RSPTextureLib/src/Texture-Extractor.h | 26 - RSPTextureLib/src/hmt_parser.c | 501 ++++++++++++++----- RSPTextureLib/src/hmt_parser.h | 136 ++--- RSPTextureLib/src/hmt_struct.h | 116 ++++- 8 files changed, 562 insertions(+), 548 deletions(-) delete mode 100644 RSPTextureLib/src/RS_images.c delete mode 100644 RSPTextureLib/src/RS_images.h delete mode 100644 RSPTextureLib/src/Texture-Extractor.h diff --git a/RSPTextureLib/include/RSPTexture_datatypes.h b/RSPTextureLib/include/RSPTexture_datatypes.h index 08a428c..0c0dce7 100644 --- a/RSPTextureLib/include/RSPTexture_datatypes.h +++ b/RSPTextureLib/include/RSPTexture_datatypes.h @@ -37,49 +37,47 @@ typedef union u_rsptexture_parameters { #ifndef MEMFILE typedef char* MEMFILE; #endif -#ifndef HEIGHTMAP_T -typedef unsigned char** HEIGHTMAP_T; +#ifndef T_R8G8B8 +typedef struct r8g8b8 { unsigned char r,g,b; } T_R8G8B8; #endif -#ifndef T_VECTOR3 -typedef struct vector3 { float x,y,z; } T_VECTOR3; -#endif -#ifndef T_VERTEX -typedef T_VECTOR3 T_VERTEX; +#ifndef T_R8G8B8A8 +typedef struct r8g8b8a8 { unsigned char r,g,b,a; } T_R8G8B8A8; #endif -typedef struct rspterrain_heightmap { +typedef unsigned char T_SAMPLE; + +typedef struct rsptexture_material { + unsigned char name[17]; // 16 + 1 string ending \0 + unsigned short type; + + unsigned short texture_index; //TODO: pointer to a T_RSPTEXTURE_TEXTURE element? +} T_RSPTEXTURE_MATERIAL; + +typedef struct rsptexture_texture { + unsigned char name[17]; // 16 + 1 string ending \0 unsigned short width; unsigned short height; - HEIGHTMAP_T heightmap; -} T_RSPTERRAIN_HEIGHTMAP ; + unsigned char type; + unsigned char sample_bits; + unsigned int palette_entries; -typedef struct rspterrain_mesh { - unsigned short width; - unsigned short height; + T_R8G8B8A8 alpha_color; - unsigned int vertices_count; - T_VERTEX* verticesmap; -} T_RSPTERRAIN_MESH ; + unsigned int palette_offset; //TODO: useless? + unsigned int pixels_offset; //TODO: useless? -typedef struct rspterrain_tile { - unsigned short texmap_id; + T_R8G8B8A8* pixels; +} T_RSPTEXTURE_TEXTURE; - unsigned char low_height; - unsigned char high_height; +typedef struct rsptexture_hmt { + unsigned int materials_count; + unsigned int textures_count; + unsigned int texture_offset; //TODO: useless? - unsigned char height_values[5][5]; -} T_RSPTERRAIN_TILE; - -typedef struct rspterrain_obj { - unsigned short width; - unsigned short height; - - float height_scale; - - unsigned short tiles_count; - T_RSPTERRAIN_TILE* tilesmap; -} T_RSPTERRAIN_HMP ; + T_RSPTEXTURE_MATERIAL* materials; + T_RSPTEXTURE_TEXTURE* textures; +} T_RSPTEXTURE_HMT; #ifdef __cplusplus } diff --git a/RSPTextureLib/src/RSPTexture.c b/RSPTextureLib/src/RSPTexture.c index 56e2712..9c06cfa 100644 --- a/RSPTextureLib/src/RSPTexture.c +++ b/RSPTextureLib/src/RSPTexture.c @@ -14,7 +14,6 @@ #include "RSPTexture_errordefs.h" #include "RSPTexture_datatypes.h" #include "hmt_parser.h" -#include "data_builders.h" #include "RSPTexture.h" @@ -22,7 +21,7 @@ inline char* RSPTexture_getVersion( void ) { return PRG_VERSION; } -unsigned short RSPTexture_processHMPFile( T_RSPTEXTURE_HMT* hmtStruct, const char* const filePath, +unsigned short RSPTexture_processHMTFile( T_RSPTEXTURE_HMT* hmtStruct, const char* const filePath, const RSPTEXTURE_PARAMETERS params ) { if ( hmtStruct == NULL || filePath == NULL ) return RSPLIB_ERROR_ARGS_NULL; @@ -30,7 +29,7 @@ unsigned short RSPTexture_processHMPFile( T_RSPTEXTURE_HMT* hmtStruct, const cha return RSP_TextureLib_ParseHMTFile(filePath, hmtStruct, ¶ms); } -unsigned short RSPTexture_processHMPFileMemory( T_RSPTEXTURE_HMT* hmtStruct, const void* const memFilePtr, +unsigned short RSPTexture_processHMTFileMemory( T_RSPTEXTURE_HMT* hmtStruct, const void* const memFilePtr, const long memFileSize, const RSPTEXTURE_PARAMETERS params ) { if ( hmtStruct == NULL || memFilePtr == NULL ) return RSPLIB_ERROR_ARGS_NULL; @@ -38,3 +37,30 @@ unsigned short RSPTexture_processHMPFileMemory( T_RSPTEXTURE_HMT* hmtStruct, con return RSP_TextureLib_ParseHMTMemFile((MEMFILE)memFilePtr, hmtStruct, ¶ms); } + + + + + + + + + + + + +/* +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/RSPTextureLib/src/RS_images.c b/RSPTextureLib/src/RS_images.c deleted file mode 100644 index b52ad8d..0000000 --- a/RSPTextureLib/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/RSPTextureLib/src/RS_images.h b/RSPTextureLib/src/RS_images.h deleted file mode 100644 index f24c7c5..0000000 --- a/RSPTextureLib/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/RSPTextureLib/src/Texture-Extractor.h b/RSPTextureLib/src/Texture-Extractor.h deleted file mode 100644 index eb11aaf..0000000 --- a/RSPTextureLib/src/Texture-Extractor.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TEXTURE_EXTRACTOR_H_ -#define TEXTURE_EXTRACTOR_H_ - -#include -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include -#endif -#include "config.h" -#include "options.h" -#include "hmt_parser.h" -#include "RS_images.h" -#include "Image_Exporter.h" - - -void createSubDir(char *dirName); -int checkArgs(char *args[], int arg_nbr); -HMT_FILE *extractDatasFromHMT(char* hmt_filename); -int exportTextures(HMT_FILE *hmt_f, char *filename); -void dispHelp(); - -#endif diff --git a/RSPTextureLib/src/hmt_parser.c b/RSPTextureLib/src/hmt_parser.c index 0475f91..55be5b1 100644 --- a/RSPTextureLib/src/hmt_parser.c +++ b/RSPTextureLib/src/hmt_parser.c @@ -1,167 +1,416 @@ +/** + * @file hmt_parser.c + * @date 26/08/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Process HMT file structure and extract its datas. + * + */ + +#include +#include +#include +#include "RSPTexture_errordefs.h" +#include "RSPTexture_datatypes.h" +#include "hmt_struct.h" #include "hmt_parser.h" -HMT_FILE *parseHMTFile(FILE *hmt_src) { - int i; - HMT_FILE *_buff = NULL; +//////////////////////////////////////////////////////////////////////////////// +// Private functions declarations +//////////////////////////////////////////////////////////////////////////////// - if (hmt_src == NULL) return NULL; - _buff = calloc(1, sizeof(HMT_FILE)); +static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT*, const MEMFILE, const RSPTEXTURE_PARAMETERS*); +static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT*, const MEMFILE, const RSPTEXTURE_PARAMETERS*); +static unsigned short ExtractTextures(T_RSPTEXTURE_HMT*, const MEMFILE, const RSPTEXTURE_PARAMETERS*); +static unsigned short TranslatePixels(T_RSPTEXTURE_TEXTURE*, const T_SAMPLE*, const T_R8G8B8*); +static unsigned short isTransparentColor(const T_R8G8B8A8, const T_R8G8B8A8); +static void convert4bitsGreyTo32bitsRGBA(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int, const T_R8G8B8A8); +static void convert4bitsTo32bitsRGBA(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int, const T_R8G8B8*, const T_R8G8B8A8); +static void convert8bitsTo32bitsRGBA(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int, const T_R8G8B8*, const T_R8G8B8A8); +static void useOddBytes(T_R8G8B8A8*, const T_SAMPLE*, const unsigned int); - 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; - } - } +//////////////////////////////////////////////////////////////////////////////// +// Public functions definition +//////////////////////////////////////////////////////////////////////////////// - // 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; +unsigned short RSP_TextureLib_ParseHMTMemFile(const MEMFILE pMemFile, T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams) { + unsigned char err = RSPLIB_SUCCESS; + + if (hmtStruct != NULL && pMemFile != NULL) { + // Do the magic! + err = ExtractTextureHMT(hmtStruct, pMemFile, pParams); + } else err = RSPLIB_ERROR_ARGS_NULL; + + return err; +} + +unsigned short RSP_TextureLib_ParseHMTFile(const char* fileName, T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams) { + unsigned char err = RSPLIB_SUCCESS; + long fileSize; + FILE* fStream = NULL; + MEMFILE memFile = NULL; + + if (hmtStruct != NULL && fileName != NULL) { + // Open file + fStream = fopen(fileName, "rb"); + + if (fStream != NULL) { + // Determine file size in bytes + fseek(fStream, 0, SEEK_END); + fileSize = ftell(fStream); + fseek(fStream, 0, SEEK_SET); + if (pParams->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize); + + memFile = malloc(fileSize + 1); + if (memFile != NULL) { + // Copy file in RAM + fread(memFile, fileSize, 1, fStream); + fclose(fStream); + + // Do the magic! + err = ExtractTextureHMT(hmtStruct, memFile, pParams); + + free(memFile); + + } else { + fclose(fStream); + err = RSPLIB_ERROR_MEMORY; + if (pParams->verbose_mode) printf("[ERR] Can't allocate enough memory for file processing!\n"); } + } else { + err = RSPLIB_ERROR_IO; + if (pParams->verbose_mode) printf("[ERR] Input file %s not found!\n", fileName); } - } + } else err = RSPLIB_ERROR_ARGS_NULL; - return _buff; + return err; } -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); +//////////////////////////////////////////////////////////////////////////////// +// Private functions definition +//////////////////////////////////////////////////////////////////////////////// - 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?! - } +/** + * @brief Extract datas from texture HMT in memory. + * + * @param[out] pHmtStruct Take T_RSPTEXTURE_HMT structure to fill with parsed datas. + * @param[in] pMemfile Pointer to an in-memory file location. + * @param[in] pParams Program option, used to tune parser features. + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT* pHmtStruct, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) { + unsigned short errorCode = RSPLIB_SUCCESS; - return EXIT_SUCCESS; + if (pHmtStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; + + // 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; + + printf("[INFO] > Materials count: %d\n", pHmtStruct->materials_count); + printf("[INFO] > Textures count: %d\n", pHmtStruct->textures_count); + if (pParams->verbose_mode) printf("[DBG] > Texture offset: 0x%X\n", pHmtStruct->texture_offset); + printf("\n"); + + // Get materials if any + if (pHmtStruct->materials_count > 0) + errorCode |= ExtractMaterials(pHmtStruct, pMemfile, pParams); + + // Get textures if any + if (pHmtStruct->textures_count > 0) + errorCode |= ExtractTextures(pHmtStruct, pMemfile, pParams); + + return errorCode; } -int readTexture(HMT_TEXTURE *tex, FILE *hmt_src) { - unsigned char u0,u1,bpp; - long pos; - RS_IMAGE_DESC desc; +/** + * @brief Retrieve materials datas from HMT file. + * + * @param[in|out] pHmt Take HMT structure to get the T_HMTFILE_MATERIAL buffer and header datas. + * @param[in] pMemfile Pointer to an in-memory file location. + * @param[in] pParams Program option, used to tune parser features. + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned short ExtractMaterials(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) { + unsigned int i; - 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); + if (pHmt == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; - 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); + pHmt->materials = (T_RSPTEXTURE_MATERIAL *)calloc(pHmt->materials_count, sizeof(T_RSPTEXTURE_MATERIAL)); + if (pHmt->materials == NULL) return RSPLIB_ERROR_MEMORY; - 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); + for ( i = 0; i < pHmt->materials_count; i++ ) { + if (pParams->debug_mode) printf("\n-----------------------Begin of material #%d-------------------------\n", i); - 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; + // 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); - 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"); + // 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; + + if (pParams->verbose_mode) { + printf("[INFO] > Material name: %s\n", pHmt->materials[i].name); + printf("[INFO] > Material type: %d\n", pHmt->materials[i].type); + 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"); + } + + if (pParams->debug_mode) printf("\n-----------------------End of material #%d---------------------------\n", i); } - 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; + return RSPLIB_SUCCESS; } -int getPaletteFromFile(RS_IMAGE *img, FILE *f) { - int entries = img->paletteEntries; +/** + * @brief Retrieve textures datas from HMT file. + * + * @param[in|out] pHmt Take HMT structure to get the T_HMTFILE_TEXTURE_HEADER buffer and header datas. + * @param[in] pMemfile Pointer to an in-memory file location. + * @param[in] pParams Program option, used to tune parser features. + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned short ExtractTextures(T_RSPTEXTURE_HMT* pHmt, const MEMFILE pMemfile, const RSPTEXTURE_PARAMETERS* pParams) { + T_R8G8B8* _palette = NULL; + T_SAMPLE* _samples = NULL; + unsigned int i; - switch (entries) { + if (pHmt == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL; + + pHmt->textures = (T_RSPTEXTURE_TEXTURE *)calloc(pHmt->textures_count, sizeof(T_RSPTEXTURE_TEXTURE)); + if (pHmt->textures == NULL) return RSPLIB_ERROR_MEMORY; + + for ( i = 0; i < pHmt->textures_count; i++ ) { + 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; + switch (pHmt->textures[i].type) { + case 0: + pHmt->textures[i].sample_bits = 4; + pHmt->textures[i].palette_entries = 16; + break; + case 1: + pHmt->textures[i].sample_bits = 8; + pHmt->textures[i].palette_entries = 256; + break; + case 2: + pHmt->textures[i].sample_bits = 16; + pHmt->textures[i].palette_entries = 0; + break; + case 3: + pHmt->textures[i].sample_bits = 32; + pHmt->textures[i].palette_entries = 0; + break; + case 4: + pHmt->textures[i].sample_bits = 4; + pHmt->textures[i].palette_entries = 0; + break; + case 5: + pHmt->textures[i].sample_bits = 8; + pHmt->textures[i].palette_entries = 0; + break; + default: + 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)); + + // 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; + + // 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); + + if (pParams->verbose_mode) { + printf("[INFO] > Texture name: %s\n", pHmt->textures[i].name); + printf("[INFO] > Texture size: %dx%d\n", pHmt->textures[i].width, pHmt->textures[i].height); + 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 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: 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); + } + + // Retrieve palette datas from HMT file + switch (pHmt->textures[i].palette_entries) { + case 16: + case 256: + _palette = (T_R8G8B8 *)malloc(sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries); + if (_palette) + memcpy(_palette, pMemfile + pHmt->textures[i].palette_offset, sizeof(T_R8G8B8) * pHmt->textures[i].palette_entries); + else return RSPLIB_ERROR_MEMORY; + break; + default: + break; + } + + // Retrieve samples from HMT file + //TODO: better approach? + _samples = (T_SAMPLE *)malloc(pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8); + if (_samples) { + memcpy(_samples, pMemfile + pHmt->textures[i].pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / 8); + //if (pHmt->textures[i].type == 2) memcpy(pHmt->textures[i].samples, pMemfile + pHmt->textures[i].pixels_offset, pHmt->textures[i].width * pHmt->textures[i].height * pHmt->textures[i].sample_bits / (8 * 4)); //TODO: manage texture type 2 + } else return RSPLIB_ERROR_MEMORY; + + // Decode palette and samples to pixels datas + if (_palette && _samples) TranslatePixels(&(pHmt->textures[i]), _samples, _palette); + + if (pParams->debug_mode) printf("\n-----------------------End of texture #%d---------------------------\n", i); + } + + return RSPLIB_SUCCESS; +} + +/** + * @brief Convert samples to pixels using palette and texture informations. + * + * @param[in|out] pTexture Take texture structure to get the pixels buffer and texture datas. + * @param[in] pSamples Pointer to samples buffer. + * @param[in] pPalette Pointer to palette buffer. + * + * @return Error code, RSPLIB_SUCCESS when no error. + */ +static unsigned short TranslatePixels(T_RSPTEXTURE_TEXTURE* pTexture, const T_SAMPLE* pSamples, const T_R8G8B8* pPalette) { + unsigned int size; + + if (pTexture == NULL || pSamples == NULL || pPalette == NULL) return RSPLIB_ERROR_ARGS_NULL; + if (!(pTexture->type == 0 || + pTexture->type == 1 || + pTexture->type == 2 || + pTexture->type == 3 || + pTexture->type == 4 || + pTexture->type == 5)) return RSPLIB_ERROR_PROCESS; + + size = pTexture->height * pTexture->width; + + switch (pTexture->sample_bits) { + case 32: + pTexture->pixels = (T_R8G8B8A8 *)calloc(size, sizeof(T_R8G8B8A8)); + memcpy(pTexture->pixels, pSamples, size * sizeof(T_R8G8B8A8)); + break; + case 4: + pTexture->pixels = (T_R8G8B8A8 *)calloc(size, sizeof(T_R8G8B8A8)); + if (pTexture->palette_entries == 0) { + convert4bitsGreyTo32bitsRGBA(pTexture->pixels, pSamples, size, pTexture->alpha_color); + } else if (pTexture->palette_entries == 16) { + convert4bitsTo32bitsRGBA(pTexture->pixels, pSamples, size, pPalette, pTexture->alpha_color); + } + break; + case 8: + if (pTexture->palette_entries == 0) { + pTexture->pixels = (T_R8G8B8A8 *)calloc(size, 1); + memcpy(pTexture->pixels, pSamples, size); + } else if (pTexture->palette_entries == 256) { + pTexture->pixels = (T_R8G8B8A8 *)calloc(size, sizeof(T_R8G8B8A8)); + convert8bitsTo32bitsRGBA(pTexture->pixels, pSamples, size, pPalette, pTexture->alpha_color); + } + break; case 16: - case 256: - fread(img->palette, sizeof(PIXEL), entries, f); + pTexture->pixels = (T_R8G8B8A8 *)calloc(size, 1); + useOddBytes(pTexture->pixels, pSamples, size); break; default: break; } - return EXIT_SUCCESS; + return RSPLIB_SUCCESS; } -int getSamplesFromFile(RS_IMAGE *img, FILE *f) { - int sample_bits = img->sampleBits; - int size = div(img->width*img->height*sample_bits, 8).quot; +static unsigned short isTransparentColor(const T_R8G8B8A8 testColor, const T_R8G8B8A8 transp_color) { + if (!(testColor.r == transp_color.r)) return RSPLIB_ERROR_PROCESS; + if (!(testColor.g == transp_color.g)) return RSPLIB_ERROR_PROCESS; + if (!(testColor.b == transp_color.b)) return RSPLIB_ERROR_PROCESS; - #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; + return RSPLIB_SUCCESS; } -void purgeHMTFromMemory(HMT_FILE *_f) { - if (_f == NULL) return; +static void convert4bitsGreyTo32bitsRGBA(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling, const T_R8G8B8A8 transp_color) { + unsigned int i; + T_SAMPLE p; - 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); + for ( i = 0; i < (sampling / 2); i++ ) { + p = pSamples[i]; + + pPixels[i * 2].r = div((p >> 4 & 0xF) * 256, 16).quot; + pPixels[i * 2].g = div((p >> 4 & 0xF) * 256, 16).quot; + pPixels[i * 2].b = div((p >> 4 & 0xF) * 256, 16).quot; + pPixels[i * 2].a = isTransparentColor(pPixels[i * 2], transp_color) ? 255 : 255 - transp_color.a; + pPixels[i * 2 + 1].r = div((p & 0xF) * 256, 16).quot; + pPixels[i * 2 + 1].g = div((p & 0xF) * 256, 16).quot; + pPixels[i * 2 + 1].b = div((p & 0xF) * 256, 16).quot; + pPixels[i * 2 + 1].a = isTransparentColor(pPixels[i * 2 + 1], transp_color) ? 255 : 255 - transp_color.a; + } +} + +static void convert4bitsTo32bitsRGBA(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling, const T_R8G8B8* pal, const T_R8G8B8A8 transp_color) { + unsigned int i; + T_SAMPLE p; + + for ( i = 0; i < (sampling / 2); i++ ) { + p = pSamples[i]; + + pPixels[i * 2].r = pal[(p >> 4) & 0xF].r; + pPixels[i * 2].g = pal[(p >> 4) & 0xF].g; + pPixels[i * 2].b = pal[(p >> 4) & 0xF].b; + pPixels[i * 2].a = isTransparentColor(pPixels[i * 2], transp_color) ? 255 : 255 - transp_color.a; + pPixels[i * 2 + 1].r = pal[p & 0xF].r; + pPixels[i * 2 + 1].g = pal[p & 0xF].g; + pPixels[i * 2 + 1].b = pal[p & 0xF].b; + pPixels[i * 2 + 1].a = isTransparentColor(pPixels[i * 2 + 1], transp_color) ? 255 : 255 - transp_color.a; + } +} + +static void convert8bitsTo32bitsRGBA(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling, const T_R8G8B8* pal, const T_R8G8B8A8 transp_color) { + unsigned int i; + T_SAMPLE p; + + for ( i = 0; i < sampling; i++ ) { + p = pSamples[i]; + pPixels[i].r = pal[p].r; + pPixels[i].g = pal[p].g; + pPixels[i].b = pal[p].b; + pPixels[i].a = isTransparentColor(pPixels[i], transp_color) ? 255 : 255 - transp_color.a; + } +} + +static void useOddBytes(T_R8G8B8A8* pPixels, const T_SAMPLE* pSamples, const unsigned int sampling) { + unsigned int i; + + for ( i = 0; i < (sampling - 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]; } - free(_f->textures_list); - - if (_f->materials_list != NULL) free(_f->materials_list); - - free(_f); } diff --git a/RSPTextureLib/src/hmt_parser.h b/RSPTextureLib/src/hmt_parser.h index 3600f5c..01c1905 100644 --- a/RSPTextureLib/src/hmt_parser.h +++ b/RSPTextureLib/src/hmt_parser.h @@ -1,111 +1,51 @@ -#ifndef HMT_PARSER_H_ -#define HMT_PARSER_H_ +/** + * @file hmt_parser.h + * @date 26/08/2022 + * @author JackCarterSmith + * @copyright GPL-v3.0 + * @brief Process HMP file structure and extract its datas. + * + */ -#include -#ifndef _WIN32 - #include -#endif -#include -#include "options.h" -#include "RS_images.h" +#include "RSPTexture_datatypes.h" -///////////////////////////// -///// Define HMT types ////// -///////////////////////////// + +#ifndef RSPTEXTURELIB_HMT_PARSER_H_ +#define RSPTEXTURELIB_HMT_PARSER_H_ /** - * @brief Material struct inside HMT file type + * @brief Process HMT file stored in memory. + * @details Parser will directly extract tiles count and information stored in + * HMT file and store them in T_RSPTEXTURE_HMT structure. + * @note Unmanaged mode * - * 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 + * @param[in] pMemFile Pointer to an in-memory HOB file location. + * @param[out] hmtStruct Allocated empty T_RSPTEXTURE_HMT structure instance to + * be filled with HMP datas. + * @param[in] pParams Parser options. See RSPTEXTURE_PARAMETERS. * - * @image html hmt_materialDef.png + * @return Processing error code, RSPLIB_SUCCESS if no error. */ -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; +unsigned short RSP_TextureLib_ParseHMTMemFile(const MEMFILE pMemFile, + T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams); /** - * @brief Texture struct inside HMT file type + * @brief Process HMT file in file system. + * @details HMP file is dumped in memory before parsing in order to enhance + * performance during parser operation and in optic to protect data + * stored in the original file (read-only). + * Parser will extract tiles count and information stored in HMT file + * and store them in T_RSPTEXTURE_HMT structure. + * @note Managed mode * - * 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 + * @param[in] fileName String value of file name/path. + * @param[out] hmtStruct Allocated empty T_RSPTEXTURE_HMT structure instance to + * be filled with HMP datas. + * @param[in] pParams Parser options. See RSPTEXTURE_PARAMETERS. * - * @image html hmt_textureDef.png + * @return Processing error code, RSPLIB_SUCCESS if no error. */ -typedef struct HMTTexture { - int data_offset; - int palette_offset; - int textureName_offset; - unsigned long width, height; - char name[16]; - RS_IMAGE image; -}HMT_TEXTURE; +unsigned short RSP_TextureLib_ParseHMTFile(const char* fileName, + T_RSPTEXTURE_HMT* hmtStruct, const RSPTEXTURE_PARAMETERS* pParams); -/** - * @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 +#endif /* RSPTEXTURELIB_HMT_PARSER_H_ */ diff --git a/RSPTextureLib/src/hmt_struct.h b/RSPTextureLib/src/hmt_struct.h index 88fb46a..2a4cf18 100644 --- a/RSPTextureLib/src/hmt_struct.h +++ b/RSPTextureLib/src/hmt_struct.h @@ -1,14 +1,14 @@ /** - * @file hmp_struct.h - * @date 22/08/2022 + * @file hmt_struct.h + * @date 26/08/2022 * @author JackCarterSmith * @copyright GPL-v3.0 - * @brief HMP file mapping definition. + * @brief HMT file mapping definition. * */ -#ifndef RSPTERRAINLIB_HMP_STRUCT_H_ -#define RSPTERRAINLIB_HMP_STRUCT_H_ +#ifndef RSPTEXTURELIB_HMT_STRUCT_H_ +#define RSPTEXTURELIB_HMT_STRUCT_H_ /* @@ -33,39 +33,103 @@ #pragma pack(push, 1) #endif -typedef struct PACK hmpfile_header { - unsigned int reserved0; //12B of zeros +typedef struct PACK hmtfile_header1 { + unsigned int materials_count; + unsigned int textures_offset; +} T_HMTFILE_HEADER1; + +typedef struct PACK hmtfile_header2 { + unsigned int textures_count; +} T_HMTFILE_HEADER2; + +typedef struct PACK hmtfile_material { + unsigned short type; // 1 - Material with texture / 2 - Material without texture + unsigned short texture_index; + + float reserved0; // misc. + float reserved1; // Always 1.0f + + unsigned int reserved2; // Zero + unsigned int reserved3; // 0x0A + + unsigned char name[16]; +} T_HMTFILE_MATERIAL; + +typedef struct PACK hmtfile_texture_format { + unsigned char reserved0; // Always 1 ? + unsigned char sample_bitsize; + unsigned char type; + /* + 0 - palette 16x3B RGB, 4bit per pixel + 1 - 256x3B palette RGB, 8bit per pixel + 3 - RGBA 32bpp + 4 - greyscale, 4bpp + 5 - grayscale, 8bpp + */ + unsigned char unknown0; // 0x40 / 0x80 + unsigned int transparent_color; //TODO: replace by T_PIXEL type +} T_HMTFILE_TEXTURE_FORMAT; + +typedef struct PACK hmtfile_texture_header { + unsigned int pixels_offset; + + unsigned int reserved0; // 28B zeros unsigned int reserved1; unsigned int reserved2; + unsigned int reserved3; + unsigned int reserved4; + unsigned int reserved5; + unsigned int reserved6; - float reserved3; // Always 0x3F000000 - float height_scale; - float reserved4; // Always 0x3F000000 + unsigned int palette_offset; // 0 = no palette + unsigned int texname_offset; - unsigned short tiles_count; - unsigned short unknown0; + unsigned short tex_width; + unsigned short tex_height; - unsigned int tiles_start_offset; - unsigned int unknown1; // Offset to some datas? + T_HMTFILE_TEXTURE_FORMAT tex_format; +} T_HMTFILE_TEXTURE_HEADER; - unsigned short width_BLK; - unsigned short height_BLK; -} T_HMPFILE_HEADER; +typedef struct PACK hmtfile_image_attributes { + unsigned short width; // Must be increased to a multiple of 2 if odd. + unsigned short height; -typedef unsigned short T_TILE_INDICES; + unsigned char reserved0; // 0x01 -typedef struct PACK hmpfile_tile { - unsigned short texmap_id; + unsigned char bit_per_pixel; // 0 - 4bits / 1 - 8bits + unsigned char subtype; // 3 - RGBA / 4 - greyscale / 5 - ov_rdir + unsigned char reserved1; // 0x80/128 +} T_HMTFILE_IMAGE_ATTRIBUTES; - unsigned char unknown0; - unsigned char low_height; // LOD application? Clipping? Terrain render quadrants? - unsigned char high_height; +typedef struct PACK hmtfile_image { + unsigned int data_size; + unsigned int pixels_offset; - unsigned char height_values[5][5]; // first and last row/column overlap with a neighboring tile, "glue" for tiles, need to be identical to avoid "hill" effect -} T_HMPFILE_TILE; + unsigned int reserved0; // 32B zeros + unsigned int reserved1; + unsigned int reserved2; + unsigned int reserved3; + unsigned int reserved4; + unsigned int reserved5; + unsigned int reserved6; + unsigned int reserved7; + + unsigned int desc_offset; + + T_HMTFILE_IMAGE_ATTRIBUTES attributes; + + unsigned int transparent_color; //TODO: replace by T_PIXEL type + unsigned int unknown0; +} T_HMTFILE_IMAGE; + +typedef struct PACK hmtfile_texture { + unsigned char name[16]; // Normally = material name + unsigned int RGB_palette; //TODO: to define + unsigned int pixels_samples; //TODO: to define +} T_HMTFILE_TEXTURE; #if defined(_MSC_VER) #pragma pack(pop) #endif -#endif /* RSPTERRAINLIB_HMP_STRUCT_H_ */ +#endif /* RSPTEXTURELIB_HMT_STRUCT_H_ */