diff --git a/Libraries/FileHandler/CMakeLists.txt b/Libraries/FileHandler/CMakeLists.txt index 58d34a8..4626e34 100644 --- a/Libraries/FileHandler/CMakeLists.txt +++ b/Libraries/FileHandler/CMakeLists.txt @@ -19,14 +19,17 @@ set(FILEHANDLER_SOURCES File.cpp Image.cpp cst/cst.c - iff/stbl.c - iff/bhav.c + iff/stbl.c + iff/bhav.c + iff/sprite.c iff/chunks.c iff/iff.c ) include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler) +include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler/libpng) + add_library(FileHandler_static STATIC ${FILEHANDLER_SOURCES}) set_target_properties(FileHandler_static PROPERTIES OUTPUT_NAME "FileHandler${FILEHANDLER_SERIES}" @@ -41,4 +44,4 @@ set_target_properties(FileHandler_shared PROPERTIES PREFIX "" IMPORT_PREFIX "" CLEAN_DIRECT_OUTPUT 1) -target_link_libraries(FileHandler_shared kernel32 jpegturbo_static) \ No newline at end of file +target_link_libraries(FileHandler_shared kernel32 jpegturbo_static zlib_shared libpng_static) \ No newline at end of file diff --git a/Libraries/FileHandler/iff/CMakeLists.txt b/Libraries/FileHandler/iff/CMakeLists.txt index 1c364d4..8a1662e 100644 --- a/Libraries/FileHandler/iff/CMakeLists.txt +++ b/Libraries/FileHandler/iff/CMakeLists.txt @@ -2,10 +2,13 @@ cmake_minimum_required(VERSION 2.6) project(iff) set(IFF_SOURCES - bhav.c - stbl.c - chunks.c + bhav.c + stbl.c + sprite.c + chunks.c iff.c ) +include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler/libpng) + add_executable(iffexport iffexport.c ${IFF_SOURCES}) \ No newline at end of file diff --git a/Libraries/FileHandler/iff/bhav.c b/Libraries/FileHandler/iff/bhav.c new file mode 100644 index 0000000..94eef93 --- /dev/null +++ b/Libraries/FileHandler/iff/bhav.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include "iff.h" + +int iff_parse_bhav(IFFChunk * ChunkInfo, const uint8_t * Buffer) +{ + IFF_TREETABLE * TreeTableData; + if(ChunkInfo->Size < 12) + return 0; + ChunkInfo->FormattedData = malloc(17); + if(ChunkInfo->FormattedData == NULL) + return 0; + memset(ChunkInfo->FormattedData, 0, 17); + TreeTableData = (IFF_TREETABLE *)ChunkInfo->FormattedData; + + memcpy (TreeTableData, Buffer, 2); + + int nodeCount = 0; + if (TreeTableData->StreamVersion == 0x8003) + { + memcpy (((char *)TreeTableData)+2, Buffer+2, 7); + memcpy (&nodeCount, Buffer+9, 4); + } + else if ((TreeTableData->StreamVersion == 0x8000) || (TreeTableData->StreamVersion == 0x8001) || (TreeTableData->StreamVersion == 0x8002)) + { + memcpy (&nodeCount, Buffer+2, 2); + memcpy (((char *)TreeTableData)+2, Buffer+4, 3); + memcpy (((char *)TreeTableData)+5, Buffer+8, 4); + switch (TreeTableData->StreamVersion) + { + case 0x8002: + break; + case 0x8001: + if (TreeTableData->NumParams > 4) { TreeTableData->NumParams = 4; } + if (TreeTableData->NumLocals > 4) { TreeTableData->NumLocals = 4; } + break; + case 0x8000: + TreeTableData->NumParams = 4; + TreeTableData->NumLocals = 0; + break; + default: + break; + } + } + + printf("Node Count: %d", nodeCount); + TreeTableData->NodesBegin = (IFF_TREETABLENODE *)malloc(12 * nodeCount); + TreeTableData->NodesEnd = TreeTableData->NodesBegin + nodeCount; + memcpy(TreeTableData->NodesBegin, Buffer+((TreeTableData->StreamVersion == 0x8003) ? 13 : 12), 12 * nodeCount); + + return 1; +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/bhav.h b/Libraries/FileHandler/iff/bhav.h new file mode 100644 index 0000000..b24f835 --- /dev/null +++ b/Libraries/FileHandler/iff/bhav.h @@ -0,0 +1,29 @@ +/* BHAV chunk */ + +typedef struct TreeNodeParams +{ + uint16_t Param0; + uint16_t Param1; + uint16_t Param2; + uint16_t Param3; +} IFF_TRETABLENODEPARAMS; + +typedef struct TreeTableNode +{ + uint16_t PrimitiveNumber; + uint8_t TransitionTrue; + uint8_t TransitionFalse; + IFF_TRETABLENODEPARAMS Parameters; +} IFF_TREETABLENODE; + +typedef struct TreeTable +{ + uint16_t StreamVersion; + uint8_t Type; + uint8_t NumParams; + uint8_t NumLocals; + uint32_t TreeVersion; + + IFF_TREETABLENODE *NodesBegin; + IFF_TREETABLENODE *NodesEnd; +} IFF_TREETABLE; \ No newline at end of file diff --git a/Libraries/FileHandler/iff/chunks.c b/Libraries/FileHandler/iff/chunks.c index 367b732..8a2bd24 100644 --- a/Libraries/FileHandler/iff/chunks.c +++ b/Libraries/FileHandler/iff/chunks.c @@ -19,16 +19,19 @@ #include #include "iff.h" -int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){ +int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, IFFFile *SourceFile){ if( !strcmp(ChunkInfo->Type, "STR#") || !strcmp(ChunkInfo->Type, "CTSS") || !strcmp(ChunkInfo->Type, "FAMs") || !strcmp(ChunkInfo->Type, "TTAs") ) return iff_parse_str(ChunkInfo, Buffer); - else if (!strcmp(ChunkInfo->Type, "BHAV")) - return iff_parse_bhav(ChunkInfo, (const char *)Buffer); - else - return 0; + else if (!strcmp(ChunkInfo->Type, "BHAV")) + return iff_parse_bhav(ChunkInfo, Buffer); + else if (!strcmp(ChunkInfo->Type, "SPR#") || !strcmp(ChunkInfo->Type, "SPR2")) + return iff_parse_sprite(ChunkInfo, Buffer, SourceFile); + else if (!strcmp(ChunkInfo->Type, "PALT")) + return iff_parse_pmap(ChunkInfo, Buffer); + return 0; } int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){ diff --git a/Libraries/FileHandler/iff/iff.c b/Libraries/FileHandler/iff/iff.c index 9b4d38c..60c0569 100644 --- a/Libraries/FileHandler/iff/iff.c +++ b/Libraries/FileHandler/iff/iff.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "iff.h" #ifndef __inline @@ -36,10 +37,11 @@ IFFFile * iff_create() return ptr; } -int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize) +int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize, char *FileName) { unsigned offset; + if(!FileSize) FileSize = ~0; else if(FileSize < 64) return 0; @@ -47,6 +49,8 @@ int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned File if(memcmp(Buffer, Header_IFF, 60)) return 0; memcpy(IFFFileInfo->Header, Buffer, 60); + + IFFFileInfo->FileName = FileName; offset = read_uint32be(Buffer+60); if(offset > FileSize - 28) @@ -101,7 +105,8 @@ IFFChunkNode * iff_add_chunk(IFFFile * IFFFileInfo, int Position) node->NextChunk = ptr; } } - + + IFFFileInfo->ChunkCount++; return ptr; } @@ -147,4 +152,20 @@ int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize -= chunk->Chunk.Size; } return 1; +} + +IFFChunk *iff_find_first_chunk(IFFFile *IFFFileInfo, const char *type, uint16_t id) +{ + IFFChunkNode *currentNode = IFFFileInfo->FirstChunk; + do + { + if (type == NULL || !memcmp(type, currentNode->Chunk.Type, 4) && + (id == 0 || id == currentNode->Chunk.ChunkID)) + return ¤tNode->Chunk; + + currentNode = currentNode->NextChunk; + } + while (currentNode != IFFFileInfo->LastChunk); + + return NULL; } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iff.h b/Libraries/FileHandler/iff/iff.h index ed53bda..94d8446 100644 --- a/Libraries/FileHandler/iff/iff.h +++ b/Libraries/FileHandler/iff/iff.h @@ -15,6 +15,7 @@ */ #include "stbl.h" #include "bhav.h" +#include "sprite.h" #ifndef read_uint32be #define read_int32be(x) (signed)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0))) @@ -60,6 +61,8 @@ typedef struct IFFChunkNode_struct typedef struct IFFFile_struct { uint8_t Header[64]; + + char *FileName; uint32_t ChunkCount; IFFChunkNode * FirstChunk; @@ -82,7 +85,7 @@ extern "C" { */ IFFFile * iff_create(); -int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize); +int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize, char *FileName); IFFChunkNode * iff_add_chunk(IFFFile * IFFFileInfo, int Position); int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize); @@ -96,10 +99,12 @@ void iff_delete(IFFFile * IFFFileInfo); ** IFF chunk functions */ +IFFChunk *iff_find_first_chunk(IFFFile *IFFFileInfo, const char *type, uint16_t id); int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize); -int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer); +int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, IFFFile *SourceFile); int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer); int iff_parse_bhav(IFFChunk * ChunkInfo, const uint8_t * Buffer); +int iff_parse_sprite(IFFChunk * ChunkInfo, const uint8_t * Buffer, IFFFile *SourceFile); #ifdef __cplusplus } diff --git a/Libraries/FileHandler/iff/iffexport.c b/Libraries/FileHandler/iff/iffexport.c index 96a4a8f..8e13314 100644 --- a/Libraries/FileHandler/iff/iffexport.c +++ b/Libraries/FileHandler/iff/iffexport.c @@ -89,7 +89,7 @@ int main(int argc, char *argv[]){ printf("%sMemory for this file could not be allocated.", "iffexport: error: "); return -1; } - if(!iff_read_header(IFFFileInfo, IFFData, FileSize)){ + if(!iff_read_header(IFFFileInfo, IFFData, FileSize, InFile)){ printf("%sNot a valid IFF file.", "iffexport: error: "); return -1; } diff --git a/Libraries/FileHandler/iff/sprite.c b/Libraries/FileHandler/iff/sprite.c new file mode 100644 index 0000000..820b8fc --- /dev/null +++ b/Libraries/FileHandler/iff/sprite.c @@ -0,0 +1,518 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iff.h" + + +int sprite_frame_set_texel(IFFSpriteFrame *frame, uint32_t column, uint32_t row, IFFSpriteColor color); +int sprite_frame_export_as_targa(IFFSpriteFrame *frame, const char *filename); +int sprite_frame_export_as_png(IFFSpriteFrame *frame, const char *filename); + +int iff_parse_sprite(IFFChunk * ChunkInfo, const uint8_t * Buffer, IFFFile *SourceFile) +{ + uint32_t frameCount = 0; + uint32_t paletteID = 0; + + uint32_t *offsets; + + IFFChunk *PaletteMap; + IFFPMap *PMap; + + IFFSprite *Sprite; + IFFSpriteFrame *Frame; + + uint32_t i = 0; + uint32_t l = 0; + + uint32_t row = 0; + uint32_t column = 0; + uint8_t quit = 0; + uint32_t numCodesTillNewline = 0; + + uint16_t encrypted = 0; + uint16_t encryptedb = 0; + uint16_t decrypted1 = 0; + uint16_t decrypted2 = 0; + uint16_t decryptedb3 = 0; + uint16_t decryptedb4 = 0; + + uint32_t bytesRead = 0; + uint8_t Z; + IFFSpriteColor clr; + + uint32_t rowHeader[2]; + uint32_t rowHeader2[2]; + + uint8_t b; + uint8_t b1; + + +#ifdef IFF2HTML + char *outputPath; + char *dummyName; + char *folderName; +#endif + + uint32_t version = read_uint32le(Buffer); + Buffer += 4; + + if (version == 1001) + { + paletteID = read_uint32le(Buffer); + Buffer += 4; + frameCount = read_uint32le(Buffer); + Buffer += 4; + } + else + { + frameCount = read_uint32le(Buffer); + Buffer += 4; + paletteID = read_uint32le(Buffer); + Buffer += 4; + } + + /* Try to load the appropriate palette */ + PaletteMap = iff_find_first_chunk(SourceFile, "PALT", paletteID); + /* If that didn't work, try loading any palette from the IFF file */ + /* Some sprites in IFFs containing only one PALT don't bother to specify a correct PALT ID */ + if (PaletteMap == NULL) + { + PaletteMap = iff_find_first_chunk(SourceFile, "PALT", 0); + /* If there is no existing palette data, there can be no coherent image. */ + if (PaletteMap == NULL) + return 0; + } + PMap = (IFFPMap *)PaletteMap->FormattedData; + + offsets = (uint32_t *)malloc(sizeof(uint32_t) * frameCount); + memset(offsets, 0, sizeof(uint32_t) * frameCount); + + if (version == 1000) + { + for (i = 0; i < frameCount; i++) + { + offsets[i] = read_uint32le(Buffer); + Buffer += 4; + } + } + + Sprite = (IFFSprite *)malloc(sizeof(IFFSprite)); + Sprite->FrameCount = frameCount; + Sprite->Frames = (IFFSpriteFrame **)malloc(sizeof (IFFSpriteFrame *) * frameCount); + +#ifdef IFF2HTML + Sprite->Version = version; +#endif + + for (l = 0; l < frameCount; l++) + { + Frame = (IFFSpriteFrame *)malloc(sizeof(IFFSpriteFrame)); + + /* Version 1000 specifies offsets for each frame of image data */ + if (version == 1000) + Buffer = ChunkInfo->Data + offsets[l]; + + /* There are two "+=" statements here for clarity. That is optimized away by a decent compiler */ + if (version == 1001) + { + Buffer += 4; /* Version */ + Buffer += 4; /* Size */ + } + if (version != 1000 && version != 1001) /* for SPR# resources */ + { + Frame->YLocation = read_uint16le(Buffer); + Buffer += 2; + Frame->YLocation = read_uint16le(Buffer); + Buffer += 2; + Frame->Height = read_uint16le(Buffer); + Buffer += 2; + Frame->Width = read_uint16le(Buffer); + Buffer += 2; + } + else + { + Frame->Width = read_uint16le(Buffer); + Buffer += 2; + Frame->Height = read_uint16le(Buffer); + Buffer += 2; + } + + Frame->Flag = read_uint16le(Buffer); + Buffer += 2; + + if (version == 1000 || version == 1001) + { + Buffer += 2; + Frame->PaletteID = read_uint16le(Buffer); /* This is unused or the same as the master PALT ID */ + Buffer += 2; + Frame->TransparentPixel = PMap->Colors[read_uint16le(Buffer)]; + Buffer += 2; + Frame->YLocation = read_uint16le(Buffer); + Buffer += 2; + Frame->XLocation = read_uint16le(Buffer); + Buffer += 2; + } + + /* Now that we know the frame size, allocate the buffer to hold its texels */ + Frame->Texels = (IFFSpriteColor *)malloc(sizeof(IFFSpriteColor) * Frame->Width * Frame->Height); + + if (version == 1000 || version == 1001) + { + while (quit == 0) + { + encrypted = read_uint16le(Buffer); + encryptedb = 0; + decrypted1 = encrypted>>13; + decrypted2 = encrypted&0x1FFF; + + + + decryptedb3 = 0; + decryptedb4 = 0; + Buffer += 2; + + + + + switch (decrypted1) + { + case 0: + column = 0; + numCodesTillNewline = decrypted2; + + bytesRead = 0; + for (bytesRead = 0; bytesRead < numCodesTillNewline - 2; bytesRead += 2) + { + encryptedb = read_uint16le(Buffer); + Buffer += 2; + + decryptedb3 = encryptedb>>13; + decryptedb4 = encryptedb&0x1FFF; + + switch (decryptedb3) + { + case 1: + + for (i = 0; i < decryptedb4; i++) + { + Z = *Buffer++; /* TODO: Use the z-buffer */ + b = *Buffer++; + sprite_frame_set_texel(Frame, column++, row, PMap->Colors[b]); + /*c = PMap->Colors[b]; This variable is not used */ + bytesRead += 2; + } + break; + case 2: + i = 0; + for (i = 0; i < decryptedb4; i++) + { + Z = *Buffer++; /* TODO: Use the z-buffer */ + b = *Buffer++; + + clr = PMap->Colors[b]; + clr.A = *Buffer++; + sprite_frame_set_texel(Frame, column++, row, clr); + bytesRead += 3; + } + if ((Buffer - ChunkInfo->Data) % 2 == 1) + { + Buffer++; + bytesRead++; + } + break; + case 3: + column += decryptedb4; + break; + case 6: + i = 0; + for (i = 0; i < decryptedb4; i++) + { + b = *Buffer++; + sprite_frame_set_texel(Frame, column++, row, PMap->Colors[b]); + bytesRead++; + } + + if ((Buffer - ChunkInfo->Data) % 2 == 1) + { + Buffer++; + bytesRead++; + } + + break; + default: + break; + } + } + row++; + + break; + + case 4: + i = 0; + for (i = 0; i < decrypted2; i++) + { + row++; + column = 0; + } + break; + case 5: + quit = 1; + break; + default: + /* Error reading code */ + return 0; + } + + if ((uint32_t)(Buffer - ChunkInfo->Data) == ChunkInfo->Size) + break; + } + } + else + { + while (quit == 0) + { + b = 0; + b1 = 0; + /*b2 = 0; This variable is unused */ + rowHeader[0] = *Buffer++; + rowHeader[1] = *Buffer++; + switch (rowHeader[0]) + { + case 4: + column = 0; + numCodesTillNewline = rowHeader[1]; + + bytesRead = 0; + for (bytesRead = 0; bytesRead < numCodesTillNewline - 2; bytesRead += 2) + { + rowHeader2[0] = *Buffer++; + rowHeader2[1] = *Buffer++; + + switch (rowHeader2[0]) + { + case 3: + i = 0; + for (i = 0; i < rowHeader2[1]; i++) + { + b = *Buffer++; + sprite_frame_set_texel(Frame, column++, row, PMap->Colors[b]); + /*c = PMap->Colors[b]; This variable is not used */ + bytesRead += 1; + } + + if ((Buffer - ChunkInfo->Data) % 2 == 1) + { + Buffer++; + bytesRead++; + } + break; + case 2: + b1 = *Buffer++; + /*b2 = *Buffer++; this variable is unused */ + Buffer++; + + clr = PMap->Colors[b1]; + i = 0; + for (i = 0; i < rowHeader2[1]; i++) + { + sprite_frame_set_texel(Frame, column++, row, clr); + } + + bytesRead += 2; + break; + case 1: + column += rowHeader2[1]; + break; + default: + /* Error */ + return 0; + } + } + + row++; + break; + case 9: + i = 0; + for (i = 0; i < rowHeader[1]; i++) + { + row++; + column = 0; + } + break; + case 5: + quit = 1; + break; + default: + /* Error */ + return 0; + } + + if ((uint32_t)(Buffer - ChunkInfo->Data) == ChunkInfo->Size) + break; + + } + } + +#ifdef IFF2HTML + outputPath = (char *)malloc(sizeof(char) * 255); + + folderName = (char *)malloc(sizeof(char) * 255); + dummyName = (char *)malloc(sizeof(char) * 255); + strcpy(folderName, SourceFile->FileName); + *strchr(folderName, (int)'.') = '\0'; + sprintf(outputPath, "./%s/%s (%d) Frame %d.png", folderName, ChunkInfo->Label, ChunkInfo->ChunkID, l); + /*printf(outputPath); + fflush(stdout);*/ + sprite_frame_export_as_png (Frame, outputPath); /* The images export faster and look better as targa. This tells me I'm doing something wrong in the PNG exporter code */ + Sprite->Frames[l] = Frame; + Sprite->Frames[l]->filePath = outputPath; +#endif + } + + /* By adding this to the ChunkInfo at the success point, we ensure that no corrupt or partial sprite appears ingame */ + ChunkInfo->FormattedData = Sprite; + + return 1; +} + +/* This function never returns zero because it is capable of producing logical output independent of the input's validity. */ +int iff_parse_pmap(IFFChunk * ChunkInfo, uint8_t * Buffer) +{ + uint32_t i; + + IFFPMap *PMap = malloc(sizeof(IFFPMap)); + Buffer = ChunkInfo->Data; + + PMap->Colors = (IFFSpriteColor *)malloc(sizeof(IFFSpriteColor) * 256); + + Buffer += 16; + if (*Buffer == 0) + Buffer += 64; /* TSO-only (this took a while to figure out) Why EA does this is beyond me... */ + + + /* In every single one of EA's PALT resources, there have been 256 colors. */ + for (i = 0; i < 256; i++) + { + if ((uint32_t)(Buffer - ChunkInfo->Data) < ChunkInfo->Size + 3) /* Are there 3 more bytes left to read? */ + { + PMap->Colors[i].R = *(Buffer++); + PMap->Colors[i].G = *(Buffer++); + PMap->Colors[i].B = *(Buffer++); + PMap->Colors[i].A = 255; + } + else + { + PMap->Colors[i].R = 128; + PMap->Colors[i].G = 128; + PMap->Colors[i].B = 128; + PMap->Colors[i].A = 255; + } + } + + ChunkInfo->FormattedData = PMap; + + return 1; +} + +int sprite_frame_set_texel(IFFSpriteFrame *frame, uint32_t column, uint32_t row, IFFSpriteColor color) +{ + /*printf("Index: %d out of %d", frame->Width * row + column, frame->Width*frame->Height);*/ + + memcpy(&frame->Texels[frame->Width * row + column], &color, sizeof(IFFSpriteColor)); + + return 1; +} + +int sprite_frame_export_as_targa(IFFSpriteFrame *frame, const char *filename) +{ + int i; + + FILE *targaFile = fopen(filename, "w"); + putc(0, targaFile); + putc(0, targaFile); + putc(2, targaFile); + putc(0, targaFile); putc(0, targaFile); + putc(0, targaFile); putc(0, targaFile); + putc(0, targaFile); + fwrite(&frame->XLocation, 2, 1, targaFile); + fwrite(&frame->YLocation, 2, 1, targaFile); + fwrite(&frame->Width, 2, 1, targaFile); + fwrite(&frame->Height, 2, 1, targaFile); + putc(32, targaFile); + putc(0, targaFile); + + for (i = 0; i < frame->Width * frame->Height; i++) + { + putc(frame->Texels[i].B, targaFile); + putc(frame->Texels[i].G, targaFile); + putc(frame->Texels[i].R, targaFile); + putc(frame->Texels[i].A, targaFile); + } + + fclose(targaFile); + + return 1; +} + +int sprite_frame_export_as_png(IFFSpriteFrame *frame, const char *filename) +{ + png_structp png_ptr; + png_infop info_ptr; + png_bytepp row_pointers; + int h; + int w; + FILE *pngFile = fopen(filename, "wb"); + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + info_ptr = png_create_info_struct(png_ptr); + + setjmp(png_jmpbuf(png_ptr)); + + png_init_io(png_ptr, pngFile); + + setjmp(png_jmpbuf(png_ptr)); + + png_set_IHDR(png_ptr, info_ptr, frame->Width, frame->Height, + 8, 6, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + setjmp(png_jmpbuf(png_ptr)); + + + + row_pointers = (png_bytepp) malloc (frame->Height * sizeof (png_bytep)); + for (h = 0; h < frame->Height; h++) { + row_pointers[frame->Height-h-1] = (png_bytep) malloc (frame->Width*4); + for (w = 0; w < frame->Width; w++) { + row_pointers[frame->Height-h-1][w*4] = frame->Texels[frame->Width*h + w].R; + row_pointers[frame->Height-h-1][w*4+1] = frame->Texels[frame->Width*h + w].G; + row_pointers[frame->Height-h-1][w*4+2] = frame->Texels[frame->Width*h + w].B; + row_pointers[frame->Height-h-1][w*4+3] = frame->Texels[frame->Width*h + w].A; + } + } + + png_write_image(png_ptr, row_pointers); + + setjmp(png_jmpbuf(png_ptr)); + + png_write_end(png_ptr, NULL); + + for (h = 0; h < frame->Height; h++) { + free((row_pointers)[h]); + } + free(row_pointers); + + fclose(pngFile); + + return 1; +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/sprite.h b/Libraries/FileHandler/iff/sprite.h new file mode 100644 index 0000000..8318934 --- /dev/null +++ b/Libraries/FileHandler/iff/sprite.h @@ -0,0 +1,41 @@ +#define IFF2HTML + +typedef struct IFFSpriteColor_struct +{ + uint8_t A; + uint8_t R; + uint8_t G; + uint8_t B; +} IFFSpriteColor; + +typedef struct IFFPixelMap_struct +{ + IFFSpriteColor *Colors; /* This is 255 b/c sometimes SPR2 and SPR resource go out of bounds (safety first!) */ +} IFFPMap; + +typedef struct IFFSpriteFrame_struct +{ + uint16_t XLocation; + uint16_t YLocation; + uint16_t Width; + uint16_t Height; + uint16_t Flag; + uint16_t PaletteID; + IFFSpriteColor TransparentPixel; + + IFFSpriteColor *Texels; + +#ifdef IFF2HTML + char *filePath; +#endif + +} IFFSpriteFrame; + +typedef struct IFFSprite_struct +{ + IFFSpriteFrame **Frames; + uint16_t FrameCount; +#ifdef IFF2HTML + uint32_t Version; +#endif +} IFFSprite; diff --git a/Libraries/FileHandler/iff/stbl.c b/Libraries/FileHandler/iff/stbl.c new file mode 100644 index 0000000..d4278ea --- /dev/null +++ b/Libraries/FileHandler/iff/stbl.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include "iff.h" + +int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + /* No bounds checking yet */ + IFF_STR * StringData; + unsigned Size = ChunkInfo->Size - 76; + if(Size < 2) + return 0; + ChunkInfo->FormattedData = malloc(sizeof(IFF_STR)); + if(ChunkInfo->FormattedData == NULL) + return 0; + memset(ChunkInfo->FormattedData, 0, sizeof(IFF_STR)); + StringData = (IFF_STR*) ChunkInfo->FormattedData; + StringData->Format = read_int16le(Buffer); + Buffer += 2; + if(Size-2 < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */ + return 1; + + switch(StringData->Format){ + + case 0: { + unsigned i; + IFFStringPairNode * PrevPair = NULL; + + StringData->LanguageSets[0].PairCount = read_uint16le(Buffer); + Buffer += 2; + if(StringData->LanguageSets[0].PairCount == 0) + return 1; + + for(i=0; iLanguageSets[0].PairCount; i++){ + IFFStringPairNode * CurrentPair; + unsigned length; + CurrentPair = malloc(sizeof(IFFStringPairNode)); + memset(CurrentPair, 0, sizeof(IFFStringPairNode)); + + if(i == 0) StringData->LanguageSets[0].FirstPair = CurrentPair; + else PrevPair->NextPair = CurrentPair; + CurrentPair->PrevPair = PrevPair; + + /* Key */ + length = read_uint8le(Buffer); + if(length != 0){ + CurrentPair->Pair.Key = malloc(length+1); + memcpy(CurrentPair->Pair.Key, Buffer+1, length); + CurrentPair->Pair.Key[length] = 0x00; + } + Buffer += length+1; + + PrevPair = CurrentPair; + } + StringData->LanguageSets[0].LastPair = PrevPair; + } return 1; + + case -1: { + unsigned i; + IFFStringPairNode * PrevPair = NULL; + + StringData->LanguageSets[0].PairCount = read_uint16le(Buffer); + Buffer += 2; + if(StringData->LanguageSets[0].PairCount == 0) + return 1; + + for(i=0; iLanguageSets[0].PairCount; i++){ + IFFStringPairNode * CurrentPair; + unsigned length; + CurrentPair = malloc(sizeof(IFFStringPairNode)); + memset(CurrentPair, 0, sizeof(IFFStringPairNode)); + + if(i == 0) StringData->LanguageSets[0].FirstPair = CurrentPair; + else PrevPair->NextPair = CurrentPair; + CurrentPair->PrevPair = PrevPair; + + /* Key */ + length = strlen((char*)Buffer); + if(length != 0){ + CurrentPair->Pair.Key = malloc(length+1); + strcpy(CurrentPair->Pair.Key, (char*)Buffer); + } + Buffer += length+1; + + PrevPair = CurrentPair; + } + StringData->LanguageSets[0].LastPair = PrevPair; + } return 1; + + case -2: { + unsigned i; + IFFStringPairNode * PrevPair = NULL; + + StringData->LanguageSets[0].PairCount = read_uint16le(Buffer); + Buffer += 2; + if(StringData->LanguageSets[0].PairCount == 0) + return 1; + + for(i=0; iLanguageSets[0].PairCount; i++){ + IFFStringPairNode * CurrentPair; + unsigned length; + CurrentPair = malloc(sizeof(IFFStringPairNode)); + memset(CurrentPair, 0, sizeof(IFFStringPairNode)); + + if(i == 0) StringData->LanguageSets[0].FirstPair = CurrentPair; + else PrevPair->NextPair = CurrentPair; + CurrentPair->PrevPair = PrevPair; + + /* Key */ + length = strlen((char*)Buffer); + if(length != 0){ + CurrentPair->Pair.Key = malloc(length+1); + strcpy(CurrentPair->Pair.Key, (char*)Buffer); + } + Buffer += length+1; + + /* Value */ + length = strlen((char*)Buffer); + if(length != 0){ + CurrentPair->Pair.Value = malloc(length+1); + strcpy(CurrentPair->Pair.Value, (char*)Buffer); + } + Buffer += length+1; + + PrevPair = CurrentPair; + } + StringData->LanguageSets[0].LastPair = PrevPair; + } return 1; + + case -3: { + unsigned i, TotalPairCount; + + TotalPairCount = read_uint16le(Buffer); + Buffer += 2; + if(TotalPairCount == 0) + return 1; + + for(i=0; iPair.LanguageSet = read_uint8le(Buffer) - 1; + Buffer++; + + /* Key */ + length = strlen((char*)Buffer); + if(length != 0){ + Pair->Pair.Key = malloc(length+1); + strcpy(Pair->Pair.Key, (char*)Buffer); + } + Buffer += length+1; + + /* Value */ + length = strlen((char*)Buffer); + if(length != 0){ + Pair->Pair.Value = malloc(length+1); + strcpy(Pair->Pair.Value, (char*)Buffer); + } + Buffer += length+1; + + /* Add the pair to the end of the associated language set */ + Pair->PrevPair = StringData->LanguageSets[0].LastPair; + if(StringData->LanguageSets[0].PairCount == 0) + StringData->LanguageSets[0].FirstPair = Pair; + else + StringData->LanguageSets[0].LastPair->NextPair = Pair; + StringData->LanguageSets[0].PairCount++; + StringData->LanguageSets[0].LastPair = Pair; + } + } return 1; + + case -4: { + unsigned LanguageSet; + unsigned LanguageSetCount = read_uint8le(Buffer); + Buffer++; + if(LanguageSetCount > 20) LanguageSetCount = 20; + + for(LanguageSet=0; LanguageSetLanguageSets[LanguageSet].PairCount = read_uint16le(Buffer); + Buffer += 2; + if(StringData->LanguageSets[LanguageSet].PairCount == 0) + continue; + + for(i=0; iLanguageSets[LanguageSet].PairCount; i++){ + IFFStringPairNode * CurrentPair; + unsigned length; + CurrentPair = malloc(sizeof(IFFStringPairNode)); + memset(CurrentPair, 0, sizeof(IFFStringPairNode)); + + if(i == 0) StringData->LanguageSets[LanguageSet].FirstPair = CurrentPair; + else PrevPair->NextPair = CurrentPair; + CurrentPair->PrevPair = PrevPair; + + Buffer++; /* Skip over LanguageSet */ + + /* Key */ + length = read_uint8le(Buffer); + if(length > 127){ + length = (length & 127) | (read_uint8le(Buffer+1) << 7); + Buffer++; + } + if(length != 0){ + CurrentPair->Pair.Key = malloc(length+1); + memcpy(CurrentPair->Pair.Key, Buffer+1, length); + CurrentPair->Pair.Key[length] = 0x00; + } + Buffer += length + 1; + + /* Value */ + length = read_uint8le(Buffer); + if(length > 127){ + length = (length & 127) | (read_uint8le(Buffer+1) << 7); + Buffer++; + } + if(length != 0){ + CurrentPair->Pair.Value = malloc(length+1); + memcpy(CurrentPair->Pair.Value, Buffer+1, length); + CurrentPair->Pair.Value[length] = 0x00; + } + Buffer += length + 1; + + PrevPair = CurrentPair; + } + StringData->LanguageSets[LanguageSet].LastPair = PrevPair; + } + } return 1; + + } + return 0; +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/stbl.h b/Libraries/FileHandler/iff/stbl.h new file mode 100644 index 0000000..e2480f7 --- /dev/null +++ b/Libraries/FileHandler/iff/stbl.h @@ -0,0 +1,52 @@ +/* STR# chunk */ + +enum IFFLanguage { + IFFLANG_DEFAULT = 0, + IFFLANG_EN_US = 1, + IFFLANG_EN_INTERNATIONAL = 2, + IFFLANG_FRENCH = 3, + IFFLANG_GERMAN = 4, + IFFLANG_ITALIAN = 5, + IFFLANG_SPANISH = 6, + IFFLANG_DUTCH = 7, + IFFLANG_DANISH = 8, + IFFLANG_SWEDISH = 9, + IFFLANG_NORWEGIAN = 10, + IFFLANG_FINNISH = 11, + IFFLANG_HEBREW = 12, + IFFLANG_RUSSIAN = 13, + IFFLANG_PORTUGUESE = 14, + IFFLANG_JAPANESE = 15, + IFFLANG_POLISH = 16, + IFFLANG_CHINESE_SIMPLIFIED = 17, + IFFLANG_CHINESE_TRADITIONAL = 18, + IFFLANG_THAI = 19, + IFFLANG_KOREAN = 20 +}; + +typedef struct IFFStringPair_struct +{ + uint8_t LanguageSet; + char * Key; + char * Value; +} IFFStringPair; + +typedef struct IFFStringPairNode_struct +{ + IFFStringPair Pair; + struct IFFStringPairNode_struct * PrevPair; + struct IFFStringPairNode_struct * NextPair; +} IFFStringPairNode; + +typedef struct IFFLanguageSet_struct +{ + uint16_t PairCount; + IFFStringPairNode * FirstPair; + IFFStringPairNode * LastPair; +} IFFLanguageSet; + +typedef struct IFF_STR_struct +{ + int16_t Format; + IFFLanguageSet LanguageSets[20]; +} IFF_STR; \ No newline at end of file diff --git a/Tools/FARDive/windows/Dialog/NewArchive.cpp b/Tools/FARDive/windows/Dialog/NewArchive.cpp index 1052b60..2df7b40 100644 --- a/Tools/FARDive/windows/Dialog/NewArchive.cpp +++ b/Tools/FARDive/windows/Dialog/NewArchive.cpp @@ -16,7 +16,7 @@ void SetType(HWND hDlg, int type){ } INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ - switch (message){ + switch (message){ case WM_INITDIALOG: { CenterDialog(hDlg); @@ -43,15 +43,15 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ //Create the tooltips HWND FARInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, - WS_POPUP | TTS_NOPREFIX | TTS_BALLOON | TTS_ALWAYSTIP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hDlg, NULL, hInst, NULL), - DBPFInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, - WS_POPUP | TTS_NOPREFIX | TTS_BALLOON | TTS_ALWAYSTIP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hDlg, NULL, hInst, NULL); + WS_POPUP | TTS_NOPREFIX | 0x40 | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hDlg, NULL, hInst, NULL), + DBPFInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_NOPREFIX | 0x40 | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hDlg, NULL, hInst, NULL); TOOLINFO tinfo = { sizeof(TOOLINFO), //cbSize @@ -67,9 +67,9 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ L"FAR version 1a is found in The Sims 1.\r\n\r\n" L"Version 1b appears to be a mistake, in which it was intended to take on the version number 2.\r\n\r\n" L"1b and 3 are both found exclusively in The Sims Online."; - SendMessage(FARInfo, TTM_SETMAXTIPWIDTH, 2000, 200); - SendMessage(FARInfo, TTM_SETTITLE, TTI_INFO_LARGE, (LPARAM) L"FAR version"); - SendMessage(FARInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo); + SendMessage(FARInfo, (WM_USER + 24), 2000, 200); + SendMessage(FARInfo, (WM_USER + 32), TTI_INFO_LARGE, (LPARAM) L"FAR version"); + SendMessage(FARInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo); SendMessage(FARInfo, TTM_SETDELAYTIME, TTDT_AUTOPOP, 12000); tinfo.uId = (UINT_PTR) GetDlgItem(hDlg, IDC_NA_DBPFINFO); tinfo.lpszText = (wchar_t*) @@ -78,21 +78,21 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ L"DBPF 1.0;i7.0 is found in The Sims Online and SimCity 4.\r\n\r\n" L"1.0;i7.0 and 1.1;i7.1 are found in The Sims 2.\r\n\r\n" L"2.0;i3.0 is found in Spore."; - SendMessage(DBPFInfo, TTM_SETMAXTIPWIDTH, 2000, 200); - SendMessage(DBPFInfo, TTM_SETTITLE, TTI_INFO_LARGE, (LPARAM) L"DBPF version"); - SendMessage(DBPFInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo); + SendMessage(DBPFInfo, (WM_USER + 24), 2000, 200); + SendMessage(DBPFInfo, (WM_USER + 32), TTI_INFO_LARGE, (LPARAM) L"DBPF version"); + SendMessage(DBPFInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo); SendMessage(DBPFInfo, TTM_SETDELAYTIME, TTDT_AUTOPOP, 20000); SetType(hDlg, TYPE_FAR); } return TRUE; case WM_CTLCOLORSTATIC: - if((HWND) lParam == GetDlgItem(hDlg, IDC_NA_TYPETEXT)){ - SetBkColor((HDC) wParam, GetSysColor(COLOR_WINDOW)); - return (INT_PTR) GetSysColorBrush(COLOR_WINDOW); - } - break; - case WM_COMMAND: - switch(LOWORD(wParam)){ + if((HWND) lParam == GetDlgItem(hDlg, IDC_NA_TYPETEXT)){ + SetBkColor((HDC) wParam, GetSysColor(COLOR_WINDOW)); + return (INT_PTR) GetSysColorBrush(COLOR_WINDOW); + } + break; + case WM_COMMAND: + switch(LOWORD(wParam)){ case IDC_NA_TYPE: if(HIWORD(wParam) == CBN_SELCHANGE) SetType(hDlg, SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0)); @@ -110,7 +110,7 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ EndDialog(hDlg, 0); } break; case WM_CLOSE: - EndDialog(hDlg, 0); + EndDialog(hDlg, 0); } return 0; } diff --git a/Tools/FARDive/windows/Interaction.cpp b/Tools/FARDive/windows/Interaction.cpp index dd85869..474982b 100644 --- a/Tools/FARDive/windows/Interaction.cpp +++ b/Tools/FARDive/windows/Interaction.cpp @@ -30,8 +30,8 @@ bool Close(){ Archive::IsOpen = false; - SetWindowText(hWnd, L"FARDive"); - SendMessage(statusbar, SB_SETTEXT, 0, (LPARAM) L""); + SetWindowText(hWnd, L"FARDive"); + SendMessage(statusbar, SB_SETTEXT, 0, (LPARAM) L""); MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); @@ -86,7 +86,7 @@ bool PopulateEntries(){ item.mask = LVIF_TEXT; item.iItem = 0; item.pszText = (LPTSTR) L"Test"; - SendMessage(hList, LVM_SETITEMCOUNT, EntryCount, LVSICF_NOSCROLL); + SendMessage(hList, LVM_SETITEMCOUNT, EntryCount, 0x00000002); SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM) &item); wchar_t buffer[17]; @@ -162,7 +162,7 @@ bool SetWorkspace(){ RECT ClientRect; GetClientRect(hWnd, &ClientRect); - hList = CreateWindowEx(WS_EX_CLIENTEDGE | LVS_EX_DOUBLEBUFFER | WS_EX_COMPOSITED, WC_LISTVIEW, NULL, LVS_LIST | LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE, + hList = CreateWindowEx(WS_EX_CLIENTEDGE | 0x00010000 | WS_EX_COMPOSITED, WC_LISTVIEW, NULL, LVS_LIST | LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE, 5, 5, 192, ClientRect.bottom-statusbarheight-10, hWnd, NULL, NULL, NULL); SetWindowTheme(hList, L"Explorer", NULL); diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index 8906db3..968f143 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -13,6 +13,7 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define IFF2HTML #include #include @@ -58,6 +59,9 @@ int main(int argc, char *argv[]){ unsigned chunk = 0; IFFFile * IFFFileInfo; IFFChunkNode * ChunkNode; + IFF_TREETABLENODE *currentNode; /* for iterating through BHAVs */ + char *dummyValue; + char *resourceDir; if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: iff2html [-f] infile (outfile)\n" @@ -94,7 +98,17 @@ int main(int argc, char *argv[]){ /**** ** Open the file and read in entire contents to memory */ - + + resourceDir = (char *)malloc(sizeof(char) * 255); + dummyValue = (char *)malloc(sizeof(char) * 255); + strcpy(resourceDir+2, InFile); + *strchr(resourceDir+2, (int)'.') = '\0'; + resourceDir[0] = '.'; + resourceDir[1] = '/'; + CreateDirectory(resourceDir, NULL); + printf(resourceDir); + fflush(stdout); + hFile = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); hFile = fopen(InFile, "rb"); if(hFile == NULL){ @@ -119,6 +133,9 @@ int main(int argc, char *argv[]){ return -1; } fclose(hFile); + + + /**** ** Load header information @@ -129,7 +146,7 @@ int main(int argc, char *argv[]){ printf("%sMemory for this file could not be allocated.", "iff2html: error: "); return -1; } - if(!iff_read_header(IFFFileInfo, IFFData, FileSize)){ + if(!iff_read_header(IFFFileInfo, IFFData, FileSize, InFile)){ printf("%sNot a valid IFF file.", "iff2html: error: "); return -1; } @@ -150,7 +167,7 @@ int main(int argc, char *argv[]){ free(IFFData); for(chunk = 1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, chunk++) - iff_parse_chunk(&ChunkNode->Chunk, ChunkNode->Chunk.Data); + iff_parse_chunk(&ChunkNode->Chunk, ChunkNode->Chunk.Data, IFFFileInfo); /**** @@ -286,8 +303,8 @@ int main(int argc, char *argv[]){ !strcmp(ChunkNode->Chunk.Type, "FAMs") || !strcmp(ChunkNode->Chunk.Type, "TTAs") ){ - IFF_STR * StringData = (IFF_STR*) ChunkNode->Chunk.FormattedData; - + IFF_STR * StringData = (IFF_STR*) ChunkNode->Chunk.FormattedData; + /**** ** STR# parsing */ @@ -352,11 +369,11 @@ int main(int argc, char *argv[]){ fprintf(hFile, "\n"); } } - else if (!strcmp(ChunkNode->Chunk.Type, "BHAV") ) - { - IFF_TREETABLE * TreeTableData = (IFF_TREETABLE*) ChunkNode->Chunk.FormattedData; - - fprintf(hFile, "\n"); + else if (!strcmp(ChunkNode->Chunk.Type, "BHAV") ) + { + IFF_TREETABLE * TreeTableData = (IFF_TREETABLE*) ChunkNode->Chunk.FormattedData; + + fprintf(hFile, "
\n"); fprintf(hFile, "\n"); - - fprintf(hFile, "\n"); - - fprintf(hFile, "\n"); - - fprintf(hFile, "\n"); - - fprintf(hFile, "\n"); - - fprintf(hFile, "\n"); - + fprintf(hFile, "
Stream Version:"); switch(TreeTableData->StreamVersion){ case 0x8000: fprintf(hFile, "0x8000 (0)"); break; @@ -366,58 +383,100 @@ int main(int argc, char *argv[]){ default: fprintf(hFile, "Unrecognized"); break; } fprintf(hFile, "
Tree Version:"); + + fprintf(hFile, "
Tree Version:"); fprintf(hFile, "%-#10X (%u)", TreeTableData->TreeVersion, TreeTableData->TreeVersion); fprintf(hFile, "
Tree Type:"); + + fprintf(hFile, "
Tree Type:"); fprintf(hFile, "%-#4X (%u)", TreeTableData->Type, TreeTableData->Type); fprintf(hFile, "
Number of Parameters:"); + + fprintf(hFile, "
Number of Parameters:"); fprintf(hFile, "%u", TreeTableData->NumParams); fprintf(hFile, "
Number of Local Variables:"); + + fprintf(hFile, "
Number of Local Variables:"); fprintf(hFile, "%u", TreeTableData->NumLocals); fprintf(hFile, "
Number of Tree Nodes:"); + + fprintf(hFile, "
Number of Tree Nodes:"); fprintf(hFile, "%u", (TreeTableData->NodesEnd - TreeTableData->NodesBegin)); fprintf(hFile, "
\n"); if(TreeTableData->StreamVersion >= 0x8000 && TreeTableData->StreamVersion <= 0x8003) - { + { fprintf(hFile, "
\n"); fprintf(hFile, "\n"); fprintf(hFile, "\n"); - IFF_TREETABLENODE *currentNode; for (currentNode = TreeTableData->NodesBegin; currentNode != TreeTableData->NodesEnd; currentNode++) - { - fprintf(hFile, "\n", (currentNode-TreeTableData->NodesBegin)); + { + fprintf(hFile, "\n", (currentNode-TreeTableData->NodesBegin)); fprintf(hFile, "\n", currentNode->PrimitiveNumber, currentNode->PrimitiveNumber); - if (currentNode->TransitionTrue < 253) - fprintf(hFile, "\n", currentNode->TransitionTrue, currentNode->TransitionTrue); - else - fprintf(hFile, "\n", currentNode->TransitionTrue == 253 ? "error" : currentNode->TransitionTrue == 254 ? "true" : "false"); - - - if (currentNode->TransitionFalse < 253) - fprintf(hFile, "\n", currentNode->TransitionFalse, currentNode->TransitionFalse); - else - fprintf(hFile, "\n", currentNode->TransitionFalse == 253 ? "error" : currentNode->TransitionFalse == 254 ? "true" : "false"); - fprintf(hFile, "\n", currentNode->Parameters.Param0, currentNode->Parameters.Param0); - fprintf(hFile, "\n", currentNode->Parameters.Param1, currentNode->Parameters.Param1); - fprintf(hFile, "\n", currentNode->Parameters.Param2, currentNode->Parameters.Param2); - fprintf(hFile, "\n", currentNode->Parameters.Param3, currentNode->Parameters.Param3); + if (currentNode->TransitionTrue < 253) + fprintf(hFile, "\n", currentNode->TransitionTrue, currentNode->TransitionTrue); + else + fprintf(hFile, "\n", currentNode->TransitionTrue == 253 ? "error" : currentNode->TransitionTrue == 254 ? "true" : "false"); + + + if (currentNode->TransitionFalse < 253) + fprintf(hFile, "\n", currentNode->TransitionFalse, currentNode->TransitionFalse); + else + fprintf(hFile, "\n", currentNode->TransitionFalse == 253 ? "error" : currentNode->TransitionFalse == 254 ? "true" : "false"); + fprintf(hFile, "\n", currentNode->Parameters.Param0, currentNode->Parameters.Param0); + fprintf(hFile, "\n", currentNode->Parameters.Param1, currentNode->Parameters.Param1); + fprintf(hFile, "\n", currentNode->Parameters.Param2, currentNode->Parameters.Param2); + fprintf(hFile, "\n", currentNode->Parameters.Param3, currentNode->Parameters.Param3); } fprintf(hFile, "
Node IDPrimitive #Transition TrueTransition FalseParameter 0Parameter 1Parameter 2Parameter 3
%d
%d%d (%-#6X)%d (%-#4X)%s%d (%-#4X)%s%d (%-#6X)%d (%-#6X)%d (%-#6X)%d (%-#6X)%d (%-#4X)%s%d (%-#4X)%s%d (%-#6X)%d (%-#6X)%d (%-#6X)%d (%-#6X)
\n"); } - } + } + else if (!strcmp(ChunkNode->Chunk.Type, "SPR#") || !strcmp(ChunkNode->Chunk.Type, "SPR2")) + { + IFFSprite * Sprite = (IFFSprite*) ChunkNode->Chunk.FormattedData; + + fprintf(hFile, "\n"); + fprintf(hFile, "\n"); + + fprintf(hFile, "\n"); + + fprintf(hFile, "\n"); + + fprintf(hFile, "
Sprite Version:"); + fprintf(hFile, "%-#6X", Sprite->Version); + fprintf(hFile, "
Sprite Type:"); + fprintf(hFile, "%s", ChunkNode->Chunk.Type); + fprintf(hFile, "
Number of Frames:"); + fprintf(hFile, "%u", Sprite->FrameCount); + fprintf(hFile, "
\n"); + if(Sprite->Version >= 500 && Sprite->Version <= 1001) + { + fprintf(hFile, "
\n"); + fprintf(hFile, "\n"); + fprintf(hFile, "\n"); + + for (i = 0; i < Sprite->FrameCount; i++) + { + fprintf(hFile, "\n", Sprite->Frames[i]->filePath); + fprintf(hFile, "\n", Sprite->Frames[i]->XLocation); + fprintf(hFile, "\n", Sprite->Frames[i]->YLocation); + fprintf(hFile, "\n", Sprite->Frames[i]->Width); + fprintf(hFile, "\n", Sprite->Frames[i]->Height); + fprintf(hFile, "\n", Sprite->Frames[i]->Flag); + fprintf(hFile, "\n", Sprite->Frames[i]->PaletteID); + fprintf(hFile, "\n", Sprite->Frames[i]->TransparentPixel.R, Sprite->Frames[i]->TransparentPixel.G, Sprite->Frames[i]->TransparentPixel.B); + } + + fprintf(hFile, "
ImageX LocationY LocationWidthHeightFlagPalette IDTransparent Pixel
%d%d%d%d%d%d
\n"); + } + } + else + { + fprintf(hFile, "The contents of this chunk could not be parsed.\n"); + } fprintf(hFile, "\n\n"); } diff --git a/Tools/iff2html/paramparse.cpp b/Tools/iff2html/paramparse.cpp new file mode 100644 index 0000000..8724fc5 --- /dev/null +++ b/Tools/iff2html/paramparse.cpp @@ -0,0 +1,46 @@ +int dummy = 0; +char *someString = &dummy; + +someString += '('; +int currentParamIdx = 0; +unsigned short currentParam; +unsigned short param0; +do +{ + currentParam = *(¶m0 + currentParamIdx); + if (currentParamIdx > 0) + someString += ' '; + + // Now, we iterate through the nibbles, starting at the high nibble and working our way down + int shiftingAmountForCurrentNibble = 12; + do + { + char nibbleType = 0; + int currentNibble = (currentParam >> shiftingAmountForCurrentNibble) & 0xF; + if (currentNibble > 9) + { + if (currentNibble > 15) //((currentNibble - 10) > 5) + nibbleType = 120; + else + nibbleType = currentNibble + 55; + } + else + nibbleType = currentNibble + 48; + + char *unk = &nibbleType; + char oldVal; + do + { + oldVal = *unk; + } + while (*unk) + + + bool outOfBounds = shiftingAmountForCurrentNibble - 4 < 0; + shiftingAmountForCurrentNibble -= 4; + } + while (!outOfBounds); + +} +while (currentParamIdx < 4); +someString += ')'; \ No newline at end of file