From 1f7061d98a246a02c9fd2c1c28ae102bff98b427 Mon Sep 17 00:00:00 2001 From: Fatbag Date: Mon, 28 May 2012 23:37:38 -0500 Subject: [PATCH] * Updated libpng and zlib * Added SPR# parsing to the iff library * iff2html now displays BMP_/FBMP, PALT, and SPR# chunks --- Libraries/FileHandler/bmp/read_bmp.c | 39 ++++++-- Libraries/FileHandler/iff/CMakeLists.txt | 1 + Libraries/FileHandler/iff/iff.c | 15 ++++ Libraries/FileHandler/iff/iff.h | 22 +++++ Libraries/FileHandler/iff/str.c | 2 +- Libraries/libvitaboy/CHANGES | 1 + Libraries/libvitaboy/libvitaboy.hpp | 7 +- Tools/hitutils/hitld.cpp | 61 ++++++++++--- Tools/iff2html/CMakeLists.txt | 4 +- Tools/iff2html/iff2html.c | 108 +++++++++++++++++++---- 10 files changed, 219 insertions(+), 41 deletions(-) diff --git a/Libraries/FileHandler/bmp/read_bmp.c b/Libraries/FileHandler/bmp/read_bmp.c index 4a32a0a..0c0ed3b 100644 --- a/Libraries/FileHandler/bmp/read_bmp.c +++ b/Libraries/FileHandler/bmp/read_bmp.c @@ -16,6 +16,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #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; ibiHeight; 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; ibiHeight*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; ybiHeight; y++){ for(x=0; xbiWidth; x++){ unsigned index = 4*(*InBuffer++); diff --git a/Libraries/FileHandler/iff/CMakeLists.txt b/Libraries/FileHandler/iff/CMakeLists.txt index 3eb9806..21a6f20 100644 --- a/Libraries/FileHandler/iff/CMakeLists.txt +++ b/Libraries/FileHandler/iff/CMakeLists.txt @@ -9,6 +9,7 @@ set(IFF_SOURCES glob.c palt.c rsmp.c + spr.c str.c string.c tmpl.c diff --git a/Libraries/FileHandler/iff/iff.c b/Libraries/FileHandler/iff/iff.c index a49505d..0f7ae79 100644 --- a/Libraries/FileHandler/iff/iff.c +++ b/Libraries/FileHandler/iff/iff.c @@ -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; iChunkCount; 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; diff --git a/Libraries/FileHandler/iff/iff.h b/Libraries/FileHandler/iff/iff.h index 9b8c8b4..40aafcb 100644 --- a/Libraries/FileHandler/iff/iff.h +++ b/Libraries/FileHandler/iff/iff.h @@ -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); diff --git a/Libraries/FileHandler/iff/str.c b/Libraries/FileHandler/iff/str.c index 4afe162..241ada5 100644 --- a/Libraries/FileHandler/iff/str.c +++ b/Libraries/FileHandler/iff/str.c @@ -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; pPairCount; p++){ free(LanguageSet->Pairs[p].Key); free(LanguageSet->Pairs[p].Value); diff --git a/Libraries/libvitaboy/CHANGES b/Libraries/libvitaboy/CHANGES index b64bbff..9ad471a 100644 --- a/Libraries/libvitaboy/CHANGES +++ b/Libraries/libvitaboy/CHANGES @@ -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 diff --git a/Libraries/libvitaboy/libvitaboy.hpp b/Libraries/libvitaboy/libvitaboy.hpp index 9f47f74..a23683c 100644 --- a/Libraries/libvitaboy/libvitaboy.hpp +++ b/Libraries/libvitaboy/libvitaboy.hpp @@ -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){ diff --git a/Tools/hitutils/hitld.cpp b/Tools/hitutils/hitld.cpp index 860d7b5..522571b 100644 --- a/Tools/hitutils/hitld.cpp +++ b/Tools/hitutils/hitld.cpp @@ -16,17 +16,58 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include -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 .\n" - "hitutils is maintained by the Niotso project.\n" - "Home page: \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 .\n" + "hitutils is maintained by the Niotso project.\n" + "Home page: \n"); + return 0; + } + + const char * hitfile; + char * hsmfile = NULL, * hotfile = NULL; + bool force = false; + + for(arg=1; arg=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; } \ No newline at end of file diff --git a/Tools/iff2html/CMakeLists.txt b/Tools/iff2html/CMakeLists.txt index b912b59..7c7f725 100644 --- a/Tools/iff2html/CMakeLists.txt +++ b/Tools/iff2html/CMakeLists.txt @@ -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) \ No newline at end of file +target_link_libraries(iff2html iff_static libpng_static zlib_static) \ No newline at end of file diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index ad7f240..64c3403 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -21,6 +21,7 @@ #include #include #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[]){ "\n"); fprintf(hFile, "\n"); fprintf(hFile, "\n"); - fprintf(hFile, "\n"); - fprintf(hFile, "\n"); + fprintf(hFile, "\n"); + fprintf(hFile, "\n"); fprintf(hFile, "\n"); fprintf(hFile, "\n", InFile); fprintf(hFile, "\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, "

%s

\n", InFile); fprintf(hFile, "
\n"); fprintf(hFile, "
"); - 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, "
\n"); @@ -276,23 +288,40 @@ int main(int argc, char *argv[]){ fprintf(hFile, "\n"); fprintf(hFile, "
Contents – %u chunks
\n", IFFFileInfo->ChunkCount); 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, "
  • %u [%s] (%.4X)%s%s
  • \n", - i, ChunkData->ChunkID, i, ChunkData->Type, ChunkData->ChunkID, + c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID, (ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label); fprintf(hFile, "
\n"); fprintf(hFile, "
\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, "

%u [%s] (%.4X)%s%s (Jump)

\n", - i, ChunkData->ChunkID, i, ChunkData->Type, ChunkData->ChunkID, + c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID, (ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label, - i, ChunkData->ChunkID); + c, ChunkData->ChunkID); fprintf(hFile, "
\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, "\n"); + fprintf(hFile, "\n"); + fprintf(hFile, "\n", + c, ChunkData->ChunkID, Width, Height); + fprintf(hFile, "
Image
\"\"
\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, "In useDefault valueName" "CommentRange is enforcedMinimumMaximum\n"); for(i=0, Range=RangeSet->Ranges; iRangeCount; i++, Range++) - fprintf(hFile, "%u%s%u%s%s%s%u%u\n", + fprintf(hFile, + "%u%s%u%s%s%s%u%u\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, "%X", 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", red, green, blue, i*16 + j, red, green, blue); @@ -500,6 +530,50 @@ int main(int argc, char *argv[]){ fprintf(hFile, "\n"); } fprintf(hFile, "\n"); + }else if(!strcmp(ChunkData->Type, "SPR#")){ + /**** + ** SPR# parsing + */ + + IFFSpriteList * SpriteList = ChunkData->FormattedData; + IFFChunk * Palette = NULL; + IFFPalette BlankPalette; + IFFPalette * PaletteData; + unsigned i; + + fprintf(hFile, "\n"); + fprintf(hFile, "\n", SpriteList->Version); + fprintf(hFile, "\n", SpriteList->PaletteID); + fprintf(hFile, "
Version:%u
Palette ID:%.4X
\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, "\n"); + fprintf(hFile, "\n"); + for(i=0; iSpriteCount; i++){ + IFFSprite * Sprite = &SpriteList->Sprites[i]; + char filename[32]; + sprintf(filename, "%sspr1_%u_%.4x_%u.png", OutDir, c, ChunkData->ChunkID, i+1); + + fprintf(hFile, "\n"); + } + fprintf(hFile, "
Sprite
%u", i+1); + if(iff_depalette(Sprite, PaletteData) && WritePNG(filename, NULL, Sprite, NULL, NULL)) + fprintf(hFile, "\"\"", + c, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height); + else + fprintf(hFile, "This sprite cannot be displayed."); + fprintf(hFile, "
\n"); }else{ fprintf(hFile, "The contents of this chunk cannot be shown on this page.\n"); }