From 628955d7a083ae6853e814c578a9a9fffa9a56f8 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Mon, 23 Jan 2023 10:58:53 +0100 Subject: [PATCH] Added code and resources for exporting TIM image files directly --- PS1BSP.vcxproj | 7 +++ PS1BSP.vcxproj.filters | 17 +++++-- palette.lmp | Bin 0 -> 768 bytes tim.cpp | 99 +++++++++++++++++++++++++++++++++++++++++ tim.h | 98 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 palette.lmp create mode 100644 tim.cpp create mode 100644 tim.h diff --git a/PS1BSP.vcxproj b/PS1BSP.vcxproj index b0f337a..63d6887 100644 --- a/PS1BSP.vcxproj +++ b/PS1BSP.vcxproj @@ -144,6 +144,7 @@ + @@ -158,6 +159,12 @@ + + + + + Document + diff --git a/PS1BSP.vcxproj.filters b/PS1BSP.vcxproj.filters index 18876d9..01b64a5 100644 --- a/PS1BSP.vcxproj.filters +++ b/PS1BSP.vcxproj.filters @@ -21,11 +21,14 @@ Source Files - - Header Files + + Source Files - Header Files + Source Files + + + Source Files @@ -65,5 +68,13 @@ Header Files + + Header Files + + + + + Resource Files + \ No newline at end of file diff --git a/palette.lmp b/palette.lmp new file mode 100644 index 0000000000000000000000000000000000000000..7eefda1dae07f1db534e11a6f7f32d85e01324c6 GIT binary patch literal 768 zcmYjP9hB=p6uvevFfb4p7#Ii)3Glo_?`Rx0stX|bFP$%qR1Fi6oqrHX_~I<4u``yj@RpT znx@C&@$>UTF!BiI9`+egf@XU`!}wjQPGFEDTzk zD9V#$m8Nx3v}M^j*VpyXH0RCc+I15EAOsi#rN9^n0a7BRkk%-QP?8{HaF*esz-5V@ zBWTeN-~n&|A3yX4lX-2_Of;Nee*taUoZXG4ac_M*V}H@v_-YfN@sE#nOw(4>DX7A3+XXI zskcOl(6v6E-EOd(K3{jKYmKer%!S4VQ6_aFWXOg35C6Ddrn* zl~Pv9REUT%MJZn#OMno-Ag~B30Q1qkZ1if8M)O6J8Gb k^{&6a^7b~5-}A>jF9YZRUI0E8`sIH2^Pkswo{vTL7n(ono&W#< literal 0 HcmV?d00001 diff --git a/tim.cpp b/tim.cpp new file mode 100644 index 0000000..e1edea2 --- /dev/null +++ b/tim.cpp @@ -0,0 +1,99 @@ +#include "tim.h" + + +int tim::ExportFile(const char* fileName, tim::PARAM *param) { + + FILE *fp; + + fopen_s(&fp, fileName, "wb"); + if (!fp) { + return(-1); + } + + + tim::HEADER fileHead={{0}}; + tim::CLUT_HEAD clutHead={0}; + tim::IMG_HEAD imgHead={0}; + + + // Prepare header + fileHead.id.id = 0x10; + fileHead.id.ver = 0; + fileHead.flags.pmode = param->format; + + + // Prepare CLUT data block if image is 8-bit or less and that the pointer to the CLUT data is not NULL + if ((param->format <= 1) && (param->clutData != NULL)) { + fileHead.flags.clut = 1; + clutHead.cw = param->clutWidth; + clutHead.ch = param->clutHeight; + clutHead.cx = param->clutXoffs; + clutHead.cy = param->clutYoffs; + clutHead.len = ((2*param->clutWidth)*param->clutHeight); + clutHead.len += sizeof(clutHead); + } + + + // Prepare image data block + imgHead.w = param->imgWidth; + imgHead.h = param->imgHeight; + imgHead.x = param->imgXoffs; + imgHead.y = param->imgYoffs; + + // Calculate final size of image based on its color depth + switch(param->format) { + case 0: // 4-bit with 16-color CLUT + imgHead.len = param->imgWidth/2; + imgHead.w /= 4; + break; + case 1: // 8-bit with 256-color CLUT + imgHead.len = param->imgWidth; + imgHead.w /= 2; + break; + case 2: // 16-bit RGB5I1 + imgHead.len = param->imgWidth*2; + break; + case 3: // 24-bit RGB8 + imgHead.len = (param->imgWidth*3); + imgHead.w = (u_short)ceil((double)imgHead.w*1.5f); + break; + } + + // Calculate size of image data block + imgHead.len *= param->imgHeight; + imgHead.len += sizeof(imgHead); + + + // Write the header + fwrite(&fileHead, 1, sizeof(fileHead), fp); + + // Write the CLUT data block + if ((param->format <= 1) && (param->clutData != NULL)) { + fwrite(&clutHead, 1, sizeof(clutHead), fp); + fwrite(param->clutData, 1, clutHead.len-sizeof(clutHead), fp); + } + + // Write the image data block + fwrite(&imgHead, 1, sizeof(imgHead), fp); + fwrite(param->imgData, 1, imgHead.len-sizeof(imgHead), fp); + + // Close and return + fclose(fp); + return(0); + +} + + +void tim::FreeParam(tim::PARAM *param) { + + if (param->imgData != NULL) { + free(param->imgData); + param->imgData = NULL; + } + + if (param->clutData != NULL) { + free(param->clutData); + param->clutData = NULL; + } + +} diff --git a/tim.h b/tim.h new file mode 100644 index 0000000..9f9b8f4 --- /dev/null +++ b/tim.h @@ -0,0 +1,98 @@ +#ifndef _TIM_H +#define _TIM_H + +#include +#ifdef _WIN32 +#include +#endif +#include + +#define TIM_OUTPUT_CLUT4 0 +#define TIM_OUTPUT_CLUT8 1 +#define TIM_OUTPUT_RGB5 2 +#define TIM_OUTPUT_RGB24 3 + +namespace tim { + + + // TIM header struct + typedef struct { + + // ID sub-struct + struct HEADER_ID { + u_int id:8; // Always 0x10 + u_int ver:8; // Always 0 + u_int pad:16; // Useless padding + } id; + + // Flags sub-struct + struct HEADER_FLAGS { + u_int pmode:3; // Pixel mode (0: 4-bit, 1: 8-bit, 2:16-bit, 3:24-bit) + u_int clut:1; + u_int pad:24; + } flags; + + } HEADER; + + + // CLUT header struct + typedef struct { + u_int len; + u_short cx,cy; + u_short cw,ch; + } CLUT_HEAD; + + + // Image data block header + typedef struct { + u_int len; + u_short x,y; + u_short w,h; + } IMG_HEAD; + + + typedef struct { + // 0: 4-bit CLUT, 1: 8-bit CLUT, 2:16-bit, 3:24-bit + int format; + // Image data params + void *imgData; + u_short imgWidth,imgHeight; + u_short imgXoffs,imgYoffs; + // CLUT data params + void *clutData; + u_short clutWidth,clutHeight; + u_short clutXoffs,clutYoffs; + } PARAM; + + + // RGB5A1 pixel format struct + typedef struct { + u_short r:5; + u_short g:5; + u_short b:5; + u_short i:1; + } PIX_RGB5; + + typedef struct { + u_char r; + u_char g; + u_char b; + } PIX_RGB24; + + + /*! tim::ExportFile() + * + * /param[in] fileName - Name of TIM file. + * /param[in] *param - tim::PARAM object of TIM export parameters. + * + * /returns Zero if the TIM file was written successfully, otherwise an error occured. + * + */ + int ExportFile(const char* fileName, tim::PARAM *param); + + void FreeParam(tim::PARAM *param); + +}; + + +#endif // _TIM_H