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_ */