Finish PNG export tool
Some checks failed
JCS-Prod/RSE-Texture/pipeline/pr-master There was a failure building this commit
Some checks failed
JCS-Prod/RSE-Texture/pipeline/pr-master There was a failure building this commit
This commit is contained in:
parent
3b1b358363
commit
f5c817b384
@ -23,6 +23,7 @@ This module can do:
|
|||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- Discover all last unknowns fields, etc.
|
- Discover all last unknowns fields, etc.
|
||||||
|
- Parse TEXT format for terrain module
|
||||||
|
|
||||||
### Using
|
### Using
|
||||||
|
|
||||||
@ -63,14 +64,14 @@ On Windows system, I can suggest you to use Conan support to help you with depen
|
|||||||
```shell
|
```shell
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
conan install .. --build=libpng --build=zlib
|
conan install .. --build=missing
|
||||||
cmake .. -G "MinGW Makefiles"
|
cmake .. -G "MinGW Makefiles"
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to do it manually without Conan support, you will probably need to specify the dependency flags for CMake. Ex:
|
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):
|
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
|
mkdir build && cd build
|
||||||
cmake -DGNU_HOST=x86_64-w64-mingw32 \
|
cmake -DGNU_HOST=x86_64-w64-mingw32 \
|
||||||
-DCMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake \
|
-DCMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake \
|
||||||
-D"ZLIB_INCLUDE_DIR=zlib/1.2.11/include" \
|
-D"ZLIB_INCLUDE_DIR=zlib/1.2.12/include" \
|
||||||
-D"ZLIB_LIBRARY=zlib/1.2.11/lib/libzlib.dll.a" \
|
-D"ZLIB_LIBRARY=zlib/1.2.12/lib/libzlib.dll.a" \
|
||||||
-D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" \
|
-D"PNG_PNG_INCLUDE_DIR=libpng/1.6.37/include" \
|
||||||
-D"PNG_LIBRARY=libpng/1.6.37/lib/libpng.dll.a" \
|
-D"PNG_LIBRARY=libpng/1.6.37/lib/libpng.dll.a" \
|
||||||
..
|
..
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
#ifndef HMT_PARSER_H_
|
|
||||||
#define HMT_PARSER_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <stdio_ext.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#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
|
|
@ -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; y<img->height; y++) {
|
|
||||||
png_byte *row = png_malloc(png_ptr, img->width*sizeof(PIXEL_A));
|
|
||||||
row_ptrs[y] = row;
|
|
||||||
for (x=0; x<img->width; 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; y<img->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 EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#ifndef IMAGE_EXPORTER_H_
|
|
||||||
#define IMAGE_EXPORTER_H_
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "RS_images.h"
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <png.h>
|
|
||||||
|
|
||||||
|
|
||||||
int saveToPNG(RS_IMAGE *img, char *tex_name, char *hmt_fileName);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,77 +1,165 @@
|
|||||||
/*
|
/**
|
||||||
================================================================================
|
* @file RSETexture.c
|
||||||
Name : Texture-Extractor.c
|
* @date 28/08/2022
|
||||||
Author : JackCarterSmith
|
* @author JackCarterSmith
|
||||||
License : GPL-v3.0
|
* @copyright GPL-v3.0
|
||||||
Description : DAT textures extractor to PNG format with enhanced function in C
|
* @brief HMT texture parser and export to PNG format.
|
||||||
================================================================================
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Texture-Extractor.h"
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#include "options.h"
|
||||||
|
#include <RSPTexture.h>
|
||||||
|
#include <RSPTexture_errordefs.h>
|
||||||
|
#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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// Init buffer vars
|
T_PROG_OPTIONS _opts;
|
||||||
HMT_FILE *hmt_fdatas = NULL;
|
unsigned char p;
|
||||||
int file_index;
|
|
||||||
|
|
||||||
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) {
|
if (argc < 2) {
|
||||||
printf("\n[ERR] No input file/commands specified!\n");
|
printf("\n[ERR] No input file/commands specified!\n");
|
||||||
dispHelp();
|
dispHelp();
|
||||||
return EXIT_FAILURE; //TODO: implement own error codes system
|
return RSPLIB_ERROR_ARGS_NULL;
|
||||||
}
|
|
||||||
_options = checkArgs(argv, argc); // Analyse program arguments
|
|
||||||
if (_options == -1) return EXIT_SUCCESS;
|
|
||||||
|
|
||||||
// Do the work
|
|
||||||
for (file_index=(_options >> 8) & 0xFF; file_index<argc; file_index++) { // Manage multiple inputs files
|
|
||||||
hmt_fdatas = extractDatasFromHMT(argv[file_index]);
|
|
||||||
if (hmt_fdatas == NULL) return EXIT_FAILURE;
|
|
||||||
if (exportTextures(hmt_fdatas, argv[file_index]) == EXIT_FAILURE) return EXIT_FAILURE;
|
|
||||||
purgeHMTFromMemory(hmt_fdatas); // Clean up memory (because I'm a good boy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
// Create options for programs according to user's arguments.
|
||||||
|
p = checkInputArgs(&_opts, argc, argv);
|
||||||
|
if ( p == RSPLIB_ERROR_GENERIC ) return RSPLIB_SUCCESS;
|
||||||
|
else if ( p != RSPLIB_SUCCESS ) return p;
|
||||||
|
|
||||||
|
return mainProcess(argc, argv, &_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int checkArgs(char *args[], int arg_nbr) {
|
|
||||||
int _o = 0x0002; // Default options parameters
|
/*
|
||||||
|
* Private functions definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS* p_opts) {
|
||||||
|
unsigned short file_index;
|
||||||
|
RSPTEXTURE_PARAMETERS libParams;
|
||||||
|
T_RSPTEXTURE_HMT* hmtStruct = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
libParams.raw = p_opts->raw & 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];
|
char test[256];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (arg_nbr > 1) {
|
// Set default options
|
||||||
for (i=1; i<arg_nbr; i++) {
|
opt_ptr->raw = 0;
|
||||||
strcpy(test, args[i]);
|
opt_ptr->output_dir = 1;
|
||||||
if (args[i][0] != '-') break;
|
|
||||||
if (strcmp(args[i], "-h") == 0) {
|
if (p_arg_nbr > 1) {
|
||||||
|
for ( i = 1; i < p_arg_nbr; i++) {
|
||||||
|
strcpy(test, p_args[i]);
|
||||||
|
if (p_args[i][0] != '-') break;
|
||||||
|
if (strcmp(p_args[i], "-h") == 0) {
|
||||||
dispHelp();
|
dispHelp();
|
||||||
return -1;
|
return RSPLIB_ERROR_GENERIC;
|
||||||
} else if (strcmp(args[i], "-v") == 0) {
|
} else if (strcmp(p_args[i], "-v") == 0) {
|
||||||
_o |= VERBOSE_ENABLED;
|
opt_ptr->verbose_mode = 1;
|
||||||
printf("[OPTN] Verbose enabled.\n");
|
printf("[OPTN] Verbose enabled.\n");
|
||||||
} else if (strcmp(args[i], "-no-subdir") == 0) {
|
} else if (strcmp(p_args[i], "-vv") == 0) {
|
||||||
_o &= ~OUTPUT_DIR;
|
opt_ptr->verbose_mode = 1;
|
||||||
printf("[OPTN] Extract to current directory.\n");
|
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 {
|
} 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;
|
if (dirName == NULL) return;
|
||||||
char _dir[260]; //TODO: Change directory management
|
char _dir[1024];
|
||||||
strcpy(_dir, dirName);
|
|
||||||
strcat(_dir, "-out");
|
snprintf(_dir, 1024, "%s-out", dirName);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CreateDirectory(_dir, NULL);
|
CreateDirectory(_dir, NULL);
|
||||||
@ -80,54 +168,12 @@ void createSubDir(char *dirName) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
HMT_FILE *extractDatasFromHMT(char *hmt_filename) {
|
static void dispHelp() {
|
||||||
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; i<hmt_f->texture_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() {
|
|
||||||
printf("\n");
|
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("\n");
|
||||||
printf("Usage: RSE-Texture_%s [options] <hmt files...>\n", VERSION);
|
printf("Usage: RSETexture [options] <hmt_files...>\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
@ -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<div(sampling,2).quot; i++) {
|
|
||||||
v = samples_tab[i];
|
|
||||||
pixels_tab[i*2]._red = div((v >> 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<div(size,2).quot; i++) {
|
|
||||||
index = samples_tab[i];
|
|
||||||
pixels_tab[i*2]._red = pal[(index >> 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<size; i++) {
|
|
||||||
index = samples_tab[i];
|
|
||||||
pixels_tab[i]._red = pal[index]._red;
|
|
||||||
pixels_tab[i]._green = pal[index]._green;
|
|
||||||
pixels_tab[i]._blue = pal[index]._blue;
|
|
||||||
if (isTransparentColor(&(pixels_tab[i]), transp_color) == 0) pixels_tab[i]._alpha = 0xFF - transp_color->_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;
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
#ifndef RS_IMAGES_H_
|
|
||||||
#define RS_IMAGES_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
//#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
|
|
@ -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_
|
#ifndef OPTIONS_H_
|
||||||
#define OPTIONS_H_
|
#define OPTIONS_H_
|
||||||
|
|
||||||
#define VERBOSE_ENABLED 0x0001
|
/// Options structure
|
||||||
#define OUTPUT_DIR 0x0002
|
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_ */
|
||||||
|
96
RSETexture/src/texture_export.c
Normal file
96
RSETexture/src/texture_export.c
Normal file
@ -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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <png.h>
|
||||||
|
#include "options.h"
|
||||||
|
#include <RSPTexture_datatypes.h>
|
||||||
|
#include <RSPTexture_errordefs.h>
|
||||||
|
#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;
|
||||||
|
}
|
15
RSETexture/src/texture_export.h
Normal file
15
RSETexture/src/texture_export.h
Normal file
@ -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_ */
|
@ -37,30 +37,17 @@ unsigned short RSPTexture_processHMTFileMemory( T_RSPTEXTURE_HMT* hmtStruct, con
|
|||||||
return RSP_TextureLib_ParseHMTMemFile((MEMFILE)memFilePtr, hmtStruct, ¶ms);
|
return RSP_TextureLib_ParseHMTMemFile((MEMFILE)memFilePtr, hmtStruct, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RSPTexture_freeHMT(T_RSPTEXTURE_HMT* hmtStruct) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (hmtStruct == NULL) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
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);
|
if (hmtStruct->materials) free(hmtStruct->materials);
|
||||||
|
|
||||||
free(_f);
|
free(hmtStruct);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@ -110,7 +110,7 @@ static unsigned short ExtractTextureHMT(T_RSPTEXTURE_HMT* pHmtStruct, const MEMF
|
|||||||
// Get global infos
|
// Get global infos
|
||||||
pHmtStruct->materials_count = ((T_HMTFILE_HEADER1 *)pMemfile)->materials_count;
|
pHmtStruct->materials_count = ((T_HMTFILE_HEADER1 *)pMemfile)->materials_count;
|
||||||
pHmtStruct->texture_offset = ((T_HMTFILE_HEADER1 *)pMemfile)->textures_offset;
|
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] > Materials count: %d\n", pHmtStruct->materials_count);
|
||||||
printf("[INFO] > Textures count: %d\n", pHmtStruct->textures_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
|
// Get material name
|
||||||
//memcpy(pHmt->materials[i].name, ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->name, 16);
|
//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
|
// Get material datas
|
||||||
pHmt->materials[i].type = ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->type;
|
pHmt->materials[i].type = ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
pHmt->materials[i].texture_index = ((T_HMTFILE_MATERIAL *)(pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1)))->texture_index;
|
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) {
|
if (pParams->verbose_mode) {
|
||||||
printf("[INFO] > Material name: %s\n", pHmt->materials[i].name);
|
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);
|
printf("[INFO] > Material text. index: %d\n", pHmt->materials[i].texture_index);
|
||||||
}
|
}
|
||||||
if (pParams->debug_mode) {
|
if (pParams->debug_mode) {
|
||||||
printf("[DBG] > Material reserved0: %.8f\n", ((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved0);
|
printf("[DBG] > Material reserved0: %.8f\n", ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
printf("[DBG] > Material reserved1: %.8f\n", ((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved1);
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved0);
|
||||||
if (((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved2 != 0
|
printf("[DBG] > Material reserved1: %.8f\n", ((T_HMTFILE_MATERIAL *)(pMemfile +
|
||||||
|| ((T_HMTFILE_MATERIAL *)pMemfile + sizeof(T_HMTFILE_MATERIAL) * (i + 1))->reserved3 == 0xA)
|
sizeof(T_HMTFILE_HEADER1) + sizeof(T_HMTFILE_MATERIAL) * i))->reserved1);
|
||||||
printf("[DBG] > Material: Zero/0xA different.\n");
|
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);
|
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);
|
if (pParams->debug_mode) printf("\n-----------------------Begin of texture #%d-------------------------\n", i);
|
||||||
|
|
||||||
// Get texture size infos
|
// Get texture size infos
|
||||||
pHmt->textures[i].width = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1))
|
pHmt->textures[i].width = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
)->tex_width;
|
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_TEXTURE_HEADER) * (i + 1))
|
pHmt->textures[i].height = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
)->tex_height;
|
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_TEXTURE_HEADER) * (i + 1))
|
pHmt->textures[i].type = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
)->tex_format.type;
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->tex_format.type;
|
||||||
switch (pHmt->textures[i].type) {
|
switch (pHmt->textures[i].type) {
|
||||||
case 0:
|
case 0:
|
||||||
pHmt->textures[i].sample_bits = 4;
|
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].sample_bits = 0;
|
||||||
pHmt->textures[i].palette_entries = 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
|
// Get texture datas offsets
|
||||||
pHmt->textures[i].pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset + sizeof(T_HMTFILE_TEXTURE_HEADER) * (i + 1))
|
pHmt->textures[i].pixels_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
)->pixels_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_TEXTURE_HEADER) * (i + 1))
|
pHmt->textures[i].palette_offset = ((T_HMTFILE_TEXTURE_HEADER *)(pMemfile + pHmt->texture_offset +
|
||||||
)->palette_offset;
|
sizeof(T_HMTFILE_HEADER2) + sizeof(T_HMTFILE_TEXTURE_HEADER) * i))->palette_offset;
|
||||||
|
|
||||||
// Get texture name
|
// 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);
|
//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) {
|
if (pParams->verbose_mode) {
|
||||||
printf("[INFO] > Texture name: %s\n", pHmt->textures[i].name);
|
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] > Texture type: %d\n", pHmt->textures[i].type);
|
||||||
printf("[INFO] > Samplebits: %d\n", pHmt->textures[i].sample_bits);
|
printf("[INFO] > Samplebits: %d\n", pHmt->textures[i].sample_bits);
|
||||||
printf("[INFO] > Palette entries: %d\n", pHmt->textures[i].palette_entries);
|
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);
|
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) {
|
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);
|
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_TEXTURE_HEADER) * (i + 1)))->tex_format.reserved0 != 1)
|
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: Always 1 different.\n");
|
||||||
printf("[DBG] > Texture palette offset: 0x%X\n", pHmt->textures[i].palette_offset);
|
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);
|
printf("[DBG] > Texture pixels offset: 0x%X\n", pHmt->textures[i].pixels_offset);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user