* Updated libpng and zlib

* Added SPR# parsing to the iff library
* iff2html now displays BMP_/FBMP, PALT, and SPR# chunks
This commit is contained in:
Fatbag 2012-05-28 23:37:38 -05:00
parent 78f1ca1d6f
commit 1f7061d98a
10 changed files with 219 additions and 41 deletions

View file

@ -16,6 +16,7 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "read_bmp.h"
@ -33,6 +34,7 @@
#endif
int bmp_read_header(bmpheader_t * BMPHeader, const uint8_t * Buffer, size_t FileSize){
unsigned padding;
if(FileSize < 54) return 0;
BMPHeader->bfType = read_uint16(Buffer);
BMPHeader->bfSize = read_uint32(Buffer+2);
@ -52,25 +54,27 @@ int bmp_read_header(bmpheader_t * BMPHeader, const uint8_t * Buffer, size_t File
BMPHeader->biClrUsed = read_uint32(Buffer+46);
BMPHeader->biClrImportant = read_uint32(Buffer+50);
BMPHeader->CompressedSize = FileSize - BMPHeader->bfOffBits;
if(BMPHeader->bfSize == 0) BMPHeader->bfSize = FileSize;
BMPHeader->CompressedSize = BMPHeader->bfSize - BMPHeader->bfOffBits;
BMPHeader->DecompressedSize = BMPHeader->biWidth * BMPHeader->biHeight * 3;
padding = BMPHeader->biWidth%4;
if(padding != 0) padding = (BMPHeader->biHeight-1)*(4-padding);
if(BMPHeader->bfType != 0x4D42 ||
BMPHeader->bfSize != FileSize ||
BMPHeader->bfSize > FileSize ||
BMPHeader->bfReserved1 != 0 || BMPHeader->bfReserved2 != 0 ||
BMPHeader->biSize != 40 ||
BMPHeader->biWidth == 0 || BMPHeader->biWidth > 4096 || /*< Includes negative check */
BMPHeader->biHeight == 0 || BMPHeader->biHeight > 4096 || /*< by treating as unsigned */
BMPHeader->biPlanes != 1 ||
(BMPHeader->biBitCount != 24 &&
(BMPHeader->biBitCount != 8 || FileSize < 1078 /* We need room for the color palette */)) ||
(BMPHeader->biBitCount != 8 || BMPHeader->bfSize < 1078 /* We need room for the color palette */)) ||
(BMPHeader->biCompression != BI_RGB &&
(BMPHeader->biCompression != BI_RLE8 || BMPHeader->biBitCount > 8)) ||
BMPHeader->bfOffBits >= FileSize ||
BMPHeader->bfOffBits >= BMPHeader->bfSize ||
(BMPHeader->biCompression == BI_RGB &&
((BMPHeader->biBitCount == 24 && BMPHeader->CompressedSize < BMPHeader->DecompressedSize) ||
(BMPHeader->biBitCount == 8 && BMPHeader->CompressedSize < BMPHeader->DecompressedSize/3 +
BMPHeader->biHeight*(BMPHeader->biWidth%4) /* Account for padding in 8-bit BMPs */)))
((BMPHeader->biBitCount == 24 && BMPHeader->CompressedSize < BMPHeader->DecompressedSize + padding) ||
(BMPHeader->biBitCount == 8 && BMPHeader->CompressedSize < BMPHeader->DecompressedSize/3 + padding)))
) return 0;
return 1;
@ -78,7 +82,24 @@ int bmp_read_header(bmpheader_t * BMPHeader, const uint8_t * Buffer, size_t File
int bmp_read_data(bmpheader_t * BMPHeader, const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer){
if(BMPHeader->biBitCount == 24 && BMPHeader->biCompression == BI_RGB){
memcpy(OutBuffer, InBuffer+BMPHeader->bfOffBits, BMPHeader->DecompressedSize);
unsigned pitch = BMPHeader->biWidth*3;
unsigned i;
unsigned padding = pitch%4;
if(padding != 0) padding = 4-padding;
for(i=0; i<BMPHeader->biHeight; i++)
memcpy(OutBuffer + i*pitch, InBuffer+BMPHeader->bfOffBits + i*(pitch + padding), pitch);
return 1;
}
if(BMPHeader->biBitCount == 32 && BMPHeader->biCompression == BI_RGB){
unsigned i;
for(i=0; i<BMPHeader->biHeight*BMPHeader->biWidth; i++){
*(OutBuffer++) = *(InBuffer++);
*(OutBuffer++) = *(InBuffer++);
*(OutBuffer++) = *(InBuffer++);
InBuffer++;
}
return 1;
}
@ -89,6 +110,8 @@ int bmp_read_data(bmpheader_t * BMPHeader, const uint8_t *__restrict InBuffer, u
if(BMPHeader->biCompression == BI_RGB){
unsigned y, x;
unsigned padding = BMPHeader->biWidth % 4;
if(padding != 0) padding = 4-padding;
for(y=0; y<BMPHeader->biHeight; y++){
for(x=0; x<BMPHeader->biWidth; x++){
unsigned index = 4*(*InBuffer++);

View file

@ -9,6 +9,7 @@ set(IFF_SOURCES
glob.c
palt.c
rsmp.c
spr.c
str.c
string.c
tmpl.c

View file

@ -34,6 +34,7 @@ iff_register(c_string);
iff_register(glob);
iff_register(fcns);
iff_register(palt);
iff_register(spr);
iff_register(tmpl);
iff_register(trcn);
iff_register(rsmp);
@ -47,6 +48,7 @@ const char chunktypes[] =
"BCON"
"FCNS"
"PALT"
"SPR#"
"TMPL"
"TRCN"
"rsmp"
@ -59,6 +61,7 @@ int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
iff_parse_bcon,
iff_parse_fcns,
iff_parse_palt,
iff_parse_spr,
iff_parse_tmpl,
iff_parse_trcn,
iff_parse_rsmp
@ -71,6 +74,7 @@ void (* const iff_free_function[])(void*) = {
iff_free_bcon,
iff_free_fcns,
NULL,
iff_free_spr,
iff_free_tmpl,
iff_free_trcn,
iff_free_rsmp
@ -185,6 +189,17 @@ int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){
return 0;
}
IFFChunk * iff_find_chunk(IFFFile * IFFFileInfo, const char * Type, int ChunkID){
unsigned i;
for(i=0; i<IFFFileInfo->ChunkCount; i++){
IFFChunk * Chunk = &IFFFileInfo->Chunks[i];
if((Type == NULL || !strcmp(Chunk->Type, Type)) &&
(ChunkID == -1 || Chunk->ChunkID == ChunkID))
return Chunk;
}
return NULL;
}
void iff_free_chunk(IFFChunk * ChunkInfo){
unsigned i;
if(ChunkInfo == NULL || ChunkInfo->FormattedData == NULL) return;

View file

@ -109,6 +109,27 @@ typedef struct IFFPalette_s
uint8_t Data[256*3];
} IFFPalette;
/* SPR# chunk */
typedef struct IFFSprite_s
{
uint32_t Reserved;
uint16_t Height;
uint16_t Width;
uint8_t * IndexData;
uint8_t * BGRA32Data;
} IFFSprite;
typedef struct IFFSpriteList_s
{
uint32_t Version;
uint32_t SpriteCount;
uint32_t PaletteID;
IFFSprite * Sprites;
} IFFSpriteList;
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette);
/* STR# chunk */
enum IFFLanguage {
@ -232,6 +253,7 @@ IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo);
int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize);
int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer);
int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize);
IFFChunk * iff_find_chunk(IFFFile * IFFFileInfo, const char * Type, int ChunkID);
void iff_free_chunk(IFFChunk * ChunkInfo);
void iff_delete_chunk(IFFFile * IFFFileInfo, int Position);

View file

@ -266,8 +266,8 @@ void iff_free_str(void * FormattedData){
for(ls=0; ls<20; ls++){
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[ls];
unsigned p;
if(LanguageSet->Pairs){
unsigned p;
for(p=0; p<LanguageSet->PairCount; p++){
free(LanguageSet->Pairs[p].Key);
free(LanguageSet->Pairs[p].Value);

View file

@ -2,6 +2,7 @@ libvitaboy 1.0.1 (2012-03-10) Fatbag
* Corrected the BlendVertices function; blend vertices tug real vertices, not the other way around
* Interleaved all vertex data (coords, texcoords, normals, blend weights) into the VertexData array
* Made reading floats cross-platform (on modern architectures that use IEEE floats) by using unions
libvitaboy 1.0.0 (2012-03-04) Fatbag

View file

@ -70,11 +70,10 @@ class VBFile_t {
}
inline float readfloat(){
//Obviously a platform-dependent implementation
float value;
memcpy(&value, Position, 4);
union { uint32_t i; float f; } value;
value.i = (uint32_t)((Position[0]<<(8*0)) | (Position[1]<<(8*1)) | (Position[2]<<(8*2)) | (Position[3]<<(8*3)));
Position += 4;
return value;
return value.f;
}
inline void readbytes(void* Destination, unsigned length){

View file

@ -16,17 +16,58 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(){
printf("Usage: hitld [-f] [-hsm infile.hsm] [-hot infile.hot]\n"
" outfile.hit INFILES\n"
"Link object files produced by hitasm into a HIT binary, and\n"
"relink the game's HSM and HOT files.\n"
"Use -f to force overwriting without confirmation.\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"hitutils is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\n");
int main(int argc, char *argv[]){
unsigned objectcount;
int arg;
/****
** Parameter extraction
*/
if(argc < 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
printf("Usage: hitld [-f] [-hsm infile.hsm] [-hot infile.hot]\n"
" outfile.hit INFILES\n"
"Link object files produced by hitasm into a HIT binary, and\n"
"relink the game's HSM and HOT files.\n"
"Use -f to force overwriting without confirmation.\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"hitutils is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\n");
return 0;
}
const char * hitfile;
char * hsmfile = NULL, * hotfile = NULL;
bool force = false;
for(arg=1; arg<argc-2; arg++){
if(!strcmp(argv[arg], "-f")) force = true;
else if(arg<argc-3 && !strcmp(argv[arg], "-hsm")) hsmfile = argv[++arg];
else if(arg<argc-3 && !strcmp(argv[arg], "-hot")) hotfile = argv[++arg];
else break;
}
hitfile = argv[arg++];
objectcount = argc-arg; //Guaranteed to be >=1
for(int i=0, length = strlen(hitfile); i<2; i++){
char *& string = (i==0) ? hsmfile : hotfile;
if(!string){
string = (char*) malloc(length+1);
strcpy(string, hitfile);
for(int j=1; j<=3 && j<=length; j++){
const char * ext = "hsmhot";
string[length-j] = ext[3*i + 3-j];
}
}
}
printf("Force: %s\nHSM file: %s\nHOT file: %s\nHIT file: %s\nObject count: %u",
force ? "yes" : "no", hsmfile, hotfile, hitfile, objectcount);
return 0;
}

View file

@ -4,9 +4,11 @@ project(iff2html)
set(IFF2HTML_SOURCES
iff2html.c
md5.c
image.c
../../Libraries/FileHandler/bmp/read_bmp.c
)
include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler)
add_executable(iff2html ${IFF2HTML_SOURCES})
target_link_libraries(iff2html iff_static)
target_link_libraries(iff2html iff_static libpng_static zlib_static)

View file

@ -21,6 +21,7 @@
#include <stdint.h>
#include <iff/iff.h>
#include "md5.h"
#include "image.h"
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
@ -49,15 +50,14 @@ static void printsize(FILE * hFile, size_t FileSize){
}
int main(int argc, char *argv[]){
unsigned i;
unsigned c, slash;
FILE * hFile;
int overwrite = 0;
char *InFile, *OutFile = NULL;
char *InFile, *OutFile = NULL, *OutDir = NULL;
size_t FileSize;
struct MD5Context md5c;
unsigned char digest[16];
uint8_t * IFFData;
unsigned chunk = 0;
IFFFile * IFFFileInfo;
IFFChunk * ChunkData;
@ -93,6 +93,14 @@ int main(int argc, char *argv[]){
strcpy(max(OutFile+length-4, OutFile), ".html");
}
for(c=0, slash=0; OutFile[c]; c++)
if(OutFile[c] == '/' || OutFile[c] == '\\') slash = c;
if(slash != 0){
OutDir = malloc(slash+2);
memcpy(OutDir, OutFile, slash+1);
OutDir[slash+1] = 0x00;
}else OutDir = "";
/****
** Open the file and read in entire contents to memory
*/
@ -150,7 +158,7 @@ int main(int argc, char *argv[]){
MD5Final(digest, &md5c);
free(IFFData);
for(chunk = 0, ChunkData = IFFFileInfo->Chunks; chunk < IFFFileInfo->ChunkCount; chunk++, ChunkData++)
for(c = 0, ChunkData = IFFFileInfo->Chunks; c < IFFFileInfo->ChunkCount; c++, ChunkData++)
iff_parse_chunk(ChunkData, ChunkData->Data);
/****
@ -184,8 +192,8 @@ int main(int argc, char *argv[]){
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
fprintf(hFile, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n");
fprintf(hFile, "<head>\n");
fprintf(hFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
fprintf(hFile, "<meta http-equiv=\"Content-Style-Type\" content=\"text/css; charset=utf-8\" />\n");
fprintf(hFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n");
fprintf(hFile, "<meta http-equiv=\"Content-Style-Type\" content=\"text/css; charset=iso-8859-1\" />\n");
fprintf(hFile, "<meta http-equiv=\"Content-Language\" content=\"en\" />\n");
fprintf(hFile, "<meta name=\"description\" content=\"%s (iff2html)\" />\n", InFile);
fprintf(hFile, "<meta name=\"generator\" content=\"iff2html\" />\n");
@ -243,6 +251,10 @@ int main(int argc, char *argv[]){
fprintf(hFile, ".center {\n");
fprintf(hFile, " margin: auto auto;\n");
fprintf(hFile, "}\n");
fprintf(hFile, ".centerall * {\n");
fprintf(hFile, " text-align: center;\n");
fprintf(hFile, " vertical-align: middle;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, ".palette td, .palette th {\n");
fprintf(hFile, " border: none;\n");
@ -267,8 +279,8 @@ int main(int argc, char *argv[]){
fprintf(hFile, "<h1>%s</h1>\n", InFile);
fprintf(hFile, "<div id=\"attributes\">\n");
fprintf(hFile, "<div>");
for(i=0; i<16; i++)
fprintf(hFile, "%.2x", digest[i]);
for(c=0; c<16; c++)
fprintf(hFile, "%.2x", digest[c]);
fprintf(hFile, " (md5), ");
printsize(hFile, FileSize);
fprintf(hFile, "</div>\n");
@ -276,23 +288,40 @@ int main(int argc, char *argv[]){
fprintf(hFile, "\n");
fprintf(hFile, "<div id=\"toc\"><div><b>Contents</b> &ndash; %u chunks</div>\n", IFFFileInfo->ChunkCount);
fprintf(hFile, "<ul>\n");
for(i=1, ChunkData = IFFFileInfo->Chunks; i <= IFFFileInfo->ChunkCount; i++, ChunkData++)
for(c=1, ChunkData = IFFFileInfo->Chunks; c <= IFFFileInfo->ChunkCount; c++, ChunkData++)
fprintf(hFile, "<li><a href=\"#chunk%u_%.4x\">%u [%s] (%.4X)%s%s</a></li>\n",
i, ChunkData->ChunkID, i, ChunkData->Type, ChunkData->ChunkID,
c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID,
(ChunkData->Label[0] != 0x00) ? " &ndash; " : "", ChunkData->Label);
fprintf(hFile, "</ul>\n");
fprintf(hFile, "</div>\n");
fprintf(hFile, "\n");
for(i=1, ChunkData = IFFFileInfo->Chunks; i <= IFFFileInfo->ChunkCount; i++, ChunkData++){
for(c=1, ChunkData = IFFFileInfo->Chunks; c <= IFFFileInfo->ChunkCount; c++, ChunkData++){
fprintf(hFile, "<h2 id=\"chunk%u_%.4x\">%u [%s] (%.4X)%s%s <a href=\"#chunk%u_%.4x\">(Jump)</a></h2>\n",
i, ChunkData->ChunkID, i, ChunkData->Type, ChunkData->ChunkID,
c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID,
(ChunkData->Label[0] != 0x00) ? " &ndash; " : "", ChunkData->Label,
i, ChunkData->ChunkID);
c, ChunkData->ChunkID);
fprintf(hFile, "<div>\n");
if(ChunkData->FormattedData == NULL){
fprintf(hFile, "The contents of this chunk could not be parsed.\n");
int success = 0;
/* The iff library does not parse BMP_ or FBMP chunks */
if(!strcmp(ChunkData->Type, "BMP_") || !strcmp(ChunkData->Type, "FBMP")){
size_t Width, Height;
char filename[32];
sprintf(filename, "%simg_%u_%.4x.png", OutDir, c, ChunkData->ChunkID);
if(WritePNG(filename, ChunkData, NULL, &Width, &Height)){
fprintf(hFile, "<table class=\"center centerall\">\n");
fprintf(hFile, "<tr><th>Image</th></tr>\n");
fprintf(hFile, "<tr><td><img src=\"img_%u_%.4x.png\" width=\"%u\" height=\"%u\" alt=\"\" /></td></tr>\n",
c, ChunkData->ChunkID, Width, Height);
fprintf(hFile, "</table>\n");
success++;
}
}
if(!success)
fprintf(hFile, "The contents of this chunk could not be parsed.\n");
}else if(!strcmp(ChunkData->Type, "STR#") ||
!strcmp(ChunkData->Type, "CTSS") ||
!strcmp(ChunkData->Type, "FAMs") ||
@ -462,7 +491,8 @@ int main(int argc, char *argv[]){
fprintf(hFile, "<tr><th colspan=\"2\">In use</th><th>Default value</th><th>Name</th>"
"<th>Comment</th><th>Range is enforced</th><th>Minimum</th><th>Maximum</th></tr>\n");
for(i=0, Range=RangeSet->Ranges; i<RangeSet->RangeCount; i++, Range++)
fprintf(hFile, "<tr><td>%u</td><td>%s</td><td>%u</td><td>%s</td><td>%s</td><td>%s</td><td>%u</td><td>%u</td></tr>\n",
fprintf(hFile,
"<tr><td>%u</td><td>%s</td><td>%u</td><td>%s</td><td>%s</td><td>%s</td><td>%u</td><td>%u</td></tr>\n",
i+1,
Range->IsUsed ? "Yes" : "No", Range->DefaultValue,
Range->Name ? Range->Name : "",
@ -488,9 +518,9 @@ int main(int argc, char *argv[]){
fprintf(hFile, "<tr><th>%X</th>", i);
for(j=0; j<16; j++){
if(i*16 + j < Palette->ColorCount){
unsigned blue = *(Data++);
unsigned green = *(Data++);
unsigned red = *(Data++);
unsigned green = *(Data++);
unsigned blue = *(Data++);
fprintf(hFile, "\n<td style=\"background:#%.2x%.2x%.2x\" title=\"%u: #%.2x%.2x%.2x\"></td>",
red, green, blue, i*16 + j, red, green, blue);
@ -500,6 +530,50 @@ int main(int argc, char *argv[]){
fprintf(hFile, "</tr>\n");
}
fprintf(hFile, "</table>\n");
}else if(!strcmp(ChunkData->Type, "SPR#")){
/****
** SPR# parsing
*/
IFFSpriteList * SpriteList = ChunkData->FormattedData;
IFFChunk * Palette = NULL;
IFFPalette BlankPalette;
IFFPalette * PaletteData;
unsigned i;
fprintf(hFile, "<table>\n");
fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", SpriteList->Version);
fprintf(hFile, "<tr><td>Palette ID:</td><td>%.4X</td></tr>\n", SpriteList->PaletteID);
fprintf(hFile, "</table>\n");
if(SpriteList->PaletteID < 0xFFFF){
Palette = iff_find_chunk(IFFFileInfo, "PALT", SpriteList->PaletteID);
if(!Palette || !Palette->FormattedData) Palette = iff_find_chunk(IFFFileInfo, "PALT", ChunkData->ChunkID);
if(!Palette || !Palette->FormattedData) Palette = iff_find_chunk(IFFFileInfo, "PALT", -1);
}
if(!Palette || !Palette->FormattedData){
memset(&BlankPalette, 0, sizeof(IFFPalette));
BlankPalette.Version = 1;
BlankPalette.ColorCount = 256;
PaletteData = &BlankPalette;
}else PaletteData = Palette->FormattedData;
fprintf(hFile, "<table class=\"center centerall\">\n");
fprintf(hFile, "<tr><th colspan=\"2\">Sprite</th></tr>\n");
for(i=0; i<SpriteList->SpriteCount; i++){
IFFSprite * Sprite = &SpriteList->Sprites[i];
char filename[32];
sprintf(filename, "%sspr1_%u_%.4x_%u.png", OutDir, c, ChunkData->ChunkID, i+1);
fprintf(hFile, "<tr><td>%u</td><td>", i+1);
if(iff_depalette(Sprite, PaletteData) && WritePNG(filename, NULL, Sprite, NULL, NULL))
fprintf(hFile, "<img src=\"spr1_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
c, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
else
fprintf(hFile, "This sprite cannot be displayed.");
fprintf(hFile, "</td></tr>\n");
}
fprintf(hFile, "</table>\n");
}else{
fprintf(hFile, "The contents of this chunk cannot be shown on this page.\n");
}