Support for sprites was added to libiff.

Support for SPR# and SPR2 was added to iff2html.

*NOTE: The default exporter used is the PNG one, since web browsers
don't like targa. However, since there is a bug in my PNG exporter, I would
recommend that you use the targa exporter for a precise representation of the
loaded sprite frame(s). Feel free to fix the PNG exporter, btw :)
This commit is contained in:
thnor 2012-04-04 00:24:25 -05:00
parent 02dff475c8
commit 6c85920535
16 changed files with 1150 additions and 84 deletions

View file

@ -21,12 +21,15 @@ set(FILEHANDLER_SOURCES
cst/cst.c cst/cst.c
iff/stbl.c iff/stbl.c
iff/bhav.c iff/bhav.c
iff/sprite.c
iff/chunks.c iff/chunks.c
iff/iff.c iff/iff.c
) )
include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler) include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler)
include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler/libpng)
add_library(FileHandler_static STATIC ${FILEHANDLER_SOURCES}) add_library(FileHandler_static STATIC ${FILEHANDLER_SOURCES})
set_target_properties(FileHandler_static PROPERTIES set_target_properties(FileHandler_static PROPERTIES
OUTPUT_NAME "FileHandler${FILEHANDLER_SERIES}" OUTPUT_NAME "FileHandler${FILEHANDLER_SERIES}"
@ -41,4 +44,4 @@ set_target_properties(FileHandler_shared PROPERTIES
PREFIX "" PREFIX ""
IMPORT_PREFIX "" IMPORT_PREFIX ""
CLEAN_DIRECT_OUTPUT 1) CLEAN_DIRECT_OUTPUT 1)
target_link_libraries(FileHandler_shared kernel32 jpegturbo_static) target_link_libraries(FileHandler_shared kernel32 jpegturbo_static zlib_shared libpng_static)

View file

@ -4,8 +4,11 @@ project(iff)
set(IFF_SOURCES set(IFF_SOURCES
bhav.c bhav.c
stbl.c stbl.c
sprite.c
chunks.c chunks.c
iff.c iff.c
) )
include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler/libpng)
add_executable(iffexport iffexport.c ${IFF_SOURCES}) add_executable(iffexport iffexport.c ${IFF_SOURCES})

View file

@ -0,0 +1,53 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#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;
}

View file

@ -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;

View file

@ -19,15 +19,18 @@
#include <stdint.h> #include <stdint.h>
#include "iff.h" #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#") || if( !strcmp(ChunkInfo->Type, "STR#") ||
!strcmp(ChunkInfo->Type, "CTSS") || !strcmp(ChunkInfo->Type, "CTSS") ||
!strcmp(ChunkInfo->Type, "FAMs") || !strcmp(ChunkInfo->Type, "FAMs") ||
!strcmp(ChunkInfo->Type, "TTAs") ) !strcmp(ChunkInfo->Type, "TTAs") )
return iff_parse_str(ChunkInfo, Buffer); return iff_parse_str(ChunkInfo, Buffer);
else if (!strcmp(ChunkInfo->Type, "BHAV")) else if (!strcmp(ChunkInfo->Type, "BHAV"))
return iff_parse_bhav(ChunkInfo, (const char *)Buffer); return iff_parse_bhav(ChunkInfo, Buffer);
else 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; return 0;
} }

View file

@ -17,6 +17,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include "iff.h" #include "iff.h"
#ifndef __inline #ifndef __inline
@ -36,10 +37,11 @@ IFFFile * iff_create()
return ptr; 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; unsigned offset;
if(!FileSize) FileSize = ~0; if(!FileSize) FileSize = ~0;
else if(FileSize < 64) else if(FileSize < 64)
return 0; return 0;
@ -48,6 +50,8 @@ int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned File
return 0; return 0;
memcpy(IFFFileInfo->Header, Buffer, 60); memcpy(IFFFileInfo->Header, Buffer, 60);
IFFFileInfo->FileName = FileName;
offset = read_uint32be(Buffer+60); offset = read_uint32be(Buffer+60);
if(offset > FileSize - 28) if(offset > FileSize - 28)
return 0; return 0;
@ -102,6 +106,7 @@ IFFChunkNode * iff_add_chunk(IFFFile * IFFFileInfo, int Position)
} }
} }
IFFFileInfo->ChunkCount++; IFFFileInfo->ChunkCount++;
return ptr; return ptr;
} }
@ -148,3 +153,19 @@ int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned
} }
return 1; 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 &currentNode->Chunk;
currentNode = currentNode->NextChunk;
}
while (currentNode != IFFFileInfo->LastChunk);
return NULL;
}

View file

@ -15,6 +15,7 @@
*/ */
#include "stbl.h" #include "stbl.h"
#include "bhav.h" #include "bhav.h"
#include "sprite.h"
#ifndef read_uint32be #ifndef read_uint32be
#define read_int32be(x) (signed)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0))) #define read_int32be(x) (signed)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0)))
@ -61,6 +62,8 @@ typedef struct IFFFile_struct
{ {
uint8_t Header[64]; uint8_t Header[64];
char *FileName;
uint32_t ChunkCount; uint32_t ChunkCount;
IFFChunkNode * FirstChunk; IFFChunkNode * FirstChunk;
IFFChunkNode * LastChunk; IFFChunkNode * LastChunk;
@ -82,7 +85,7 @@ extern "C" {
*/ */
IFFFile * iff_create(); 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); IFFChunkNode * iff_add_chunk(IFFFile * IFFFileInfo, int Position);
int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize); int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize);
@ -96,10 +99,12 @@ void iff_delete(IFFFile * IFFFileInfo);
** IFF chunk functions ** 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_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_str(IFFChunk * ChunkInfo, const uint8_t * Buffer);
int iff_parse_bhav(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 #ifdef __cplusplus
} }

View file

@ -89,7 +89,7 @@ int main(int argc, char *argv[]){
printf("%sMemory for this file could not be allocated.", "iffexport: error: "); printf("%sMemory for this file could not be allocated.", "iffexport: error: ");
return -1; 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: "); printf("%sNot a valid IFF file.", "iffexport: error: ");
return -1; return -1;
} }

View file

@ -0,0 +1,518 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <png.h>
#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;
}

View file

@ -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;

View file

@ -0,0 +1,233 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#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; i<StringData->LanguageSets[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; i<StringData->LanguageSets[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; i<StringData->LanguageSets[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; i<TotalPairCount; i++){
IFFStringPairNode * Pair;
unsigned length;
Pair = malloc(sizeof(IFFStringPairNode));
memset(Pair, 0, sizeof(IFFStringPairNode));
Pair->Pair.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; LanguageSet<LanguageSetCount; LanguageSet++){
unsigned i;
IFFStringPairNode * PrevPair = NULL;
StringData->LanguageSets[LanguageSet].PairCount = read_uint16le(Buffer);
Buffer += 2;
if(StringData->LanguageSets[LanguageSet].PairCount == 0)
continue;
for(i=0; i<StringData->LanguageSets[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;
}

View file

@ -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;

View file

@ -43,12 +43,12 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){
//Create the tooltips //Create the tooltips
HWND FARInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, HWND FARInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_BALLOON | TTS_ALWAYSTIP, WS_POPUP | TTS_NOPREFIX | 0x40 | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hDlg, NULL, hInst, NULL), hDlg, NULL, hInst, NULL),
DBPFInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, DBPFInfo = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_BALLOON | TTS_ALWAYSTIP, WS_POPUP | TTS_NOPREFIX | 0x40 | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hDlg, NULL, hInst, NULL); hDlg, NULL, hInst, NULL);
@ -67,8 +67,8 @@ 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"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"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."; L"1b and 3 are both found exclusively in The Sims Online.";
SendMessage(FARInfo, TTM_SETMAXTIPWIDTH, 2000, 200); SendMessage(FARInfo, (WM_USER + 24), 2000, 200);
SendMessage(FARInfo, TTM_SETTITLE, TTI_INFO_LARGE, (LPARAM) L"FAR version"); SendMessage(FARInfo, (WM_USER + 32), TTI_INFO_LARGE, (LPARAM) L"FAR version");
SendMessage(FARInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo); SendMessage(FARInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo);
SendMessage(FARInfo, TTM_SETDELAYTIME, TTDT_AUTOPOP, 12000); SendMessage(FARInfo, TTM_SETDELAYTIME, TTDT_AUTOPOP, 12000);
tinfo.uId = (UINT_PTR) GetDlgItem(hDlg, IDC_NA_DBPFINFO); tinfo.uId = (UINT_PTR) GetDlgItem(hDlg, IDC_NA_DBPFINFO);
@ -78,8 +78,8 @@ 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"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"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."; L"2.0;i3.0 is found in Spore.";
SendMessage(DBPFInfo, TTM_SETMAXTIPWIDTH, 2000, 200); SendMessage(DBPFInfo, (WM_USER + 24), 2000, 200);
SendMessage(DBPFInfo, TTM_SETTITLE, TTI_INFO_LARGE, (LPARAM) L"DBPF version"); SendMessage(DBPFInfo, (WM_USER + 32), TTI_INFO_LARGE, (LPARAM) L"DBPF version");
SendMessage(DBPFInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo); SendMessage(DBPFInfo, TTM_ADDTOOL, 0, (LPARAM) &tinfo);
SendMessage(DBPFInfo, TTM_SETDELAYTIME, TTDT_AUTOPOP, 20000); SendMessage(DBPFInfo, TTM_SETDELAYTIME, TTDT_AUTOPOP, 20000);

View file

@ -86,7 +86,7 @@ bool PopulateEntries(){
item.mask = LVIF_TEXT; item.mask = LVIF_TEXT;
item.iItem = 0; item.iItem = 0;
item.pszText = (LPTSTR) L"Test"; 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); SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM) &item);
wchar_t buffer[17]; wchar_t buffer[17];
@ -162,7 +162,7 @@ bool SetWorkspace(){
RECT ClientRect; RECT ClientRect;
GetClientRect(hWnd, &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); 5, 5, 192, ClientRect.bottom-statusbarheight-10, hWnd, NULL, NULL, NULL);
SetWindowTheme(hList, L"Explorer", NULL); SetWindowTheme(hList, L"Explorer", NULL);

View file

@ -13,6 +13,7 @@
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#define IFF2HTML
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -58,6 +59,9 @@ int main(int argc, char *argv[]){
unsigned chunk = 0; unsigned chunk = 0;
IFFFile * IFFFileInfo; IFFFile * IFFFileInfo;
IFFChunkNode * ChunkNode; IFFChunkNode * ChunkNode;
IFF_TREETABLENODE *currentNode; /* for iterating through BHAVs */
char *dummyValue;
char *resourceDir;
if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
printf("Usage: iff2html [-f] infile (outfile)\n" printf("Usage: iff2html [-f] infile (outfile)\n"
@ -95,6 +99,16 @@ int main(int argc, char *argv[]){
** Open the file and read in entire contents to memory ** 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 = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
hFile = fopen(InFile, "rb"); hFile = fopen(InFile, "rb");
if(hFile == NULL){ if(hFile == NULL){
@ -120,6 +134,9 @@ int main(int argc, char *argv[]){
} }
fclose(hFile); fclose(hFile);
/**** /****
** Load header information ** Load header information
*/ */
@ -129,7 +146,7 @@ int main(int argc, char *argv[]){
printf("%sMemory for this file could not be allocated.", "iff2html: error: "); printf("%sMemory for this file could not be allocated.", "iff2html: error: ");
return -1; 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: "); printf("%sNot a valid IFF file.", "iff2html: error: ");
return -1; return -1;
} }
@ -150,7 +167,7 @@ int main(int argc, char *argv[]){
free(IFFData); free(IFFData);
for(chunk = 1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, chunk++) 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);
/**** /****
@ -394,7 +411,6 @@ int main(int argc, char *argv[]){
fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<table class=\"center\">\n");
fprintf(hFile, "<tr><th>Node ID</th><th>Primitive #</th><th>Transition True</th><th>Transition False</th><th>Parameter 0</th><th>Parameter 1</th><th>Parameter 2</th><th>Parameter 3</th></tr>\n"); fprintf(hFile, "<tr><th>Node ID</th><th>Primitive #</th><th>Transition True</th><th>Transition False</th><th>Parameter 0</th><th>Parameter 1</th><th>Parameter 2</th><th>Parameter 3</th></tr>\n");
IFF_TREETABLENODE *currentNode;
for (currentNode = TreeTableData->NodesBegin; currentNode != TreeTableData->NodesEnd; currentNode++) for (currentNode = TreeTableData->NodesBegin; currentNode != TreeTableData->NodesEnd; currentNode++)
{ {
fprintf(hFile, "<tr><td>%d</td>\n", (currentNode-TreeTableData->NodesBegin)); fprintf(hFile, "<tr><td>%d</td>\n", (currentNode-TreeTableData->NodesBegin));
@ -418,6 +434,49 @@ int main(int argc, char *argv[]){
fprintf(hFile, "</table>\n"); fprintf(hFile, "</table>\n");
} }
} }
else if (!strcmp(ChunkNode->Chunk.Type, "SPR#") || !strcmp(ChunkNode->Chunk.Type, "SPR2"))
{
IFFSprite * Sprite = (IFFSprite*) ChunkNode->Chunk.FormattedData;
fprintf(hFile, "<table>\n");
fprintf(hFile, "<tr><td>Sprite Version:</td><td>");
fprintf(hFile, "<tt>%-#6X</tt>", Sprite->Version);
fprintf(hFile, "</td></tr>\n");
fprintf(hFile, "<tr><td>Sprite Type:</td><td>");
fprintf(hFile, "<tt>%s</tt>", ChunkNode->Chunk.Type);
fprintf(hFile, "</td></tr>\n");
fprintf(hFile, "<tr><td>Number of Frames:</td><td>");
fprintf(hFile, "<tt>%u</tt>", Sprite->FrameCount);
fprintf(hFile, "</td></tr>\n");
fprintf(hFile, "</table>\n");
if(Sprite->Version >= 500 && Sprite->Version <= 1001)
{
fprintf(hFile, "<br />\n");
fprintf(hFile, "<table class=\"center\">\n");
fprintf(hFile, "<tr><th>Image</th><th>X Location</th><th>Y Location</th><th>Width</th><th>Height</th><th>Flag</th><th>Palette ID</th><th>Transparent Pixel</th></tr>\n");
for (i = 0; i < Sprite->FrameCount; i++)
{
fprintf(hFile, "<tr><td><img src=\"%s\" /></td>\n", Sprite->Frames[i]->filePath);
fprintf(hFile, "<td>%d</td>\n", Sprite->Frames[i]->XLocation);
fprintf(hFile, "<td>%d</td>\n", Sprite->Frames[i]->YLocation);
fprintf(hFile, "<td>%d</td>\n", Sprite->Frames[i]->Width);
fprintf(hFile, "<td>%d</td>\n", Sprite->Frames[i]->Height);
fprintf(hFile, "<td>%d</td>\n", Sprite->Frames[i]->Flag);
fprintf(hFile, "<td>%d</td>\n", Sprite->Frames[i]->PaletteID);
fprintf(hFile, "<td style=\"background-color:rgb(%d, %d, %d);\"></td>\n", Sprite->Frames[i]->TransparentPixel.R, Sprite->Frames[i]->TransparentPixel.G, Sprite->Frames[i]->TransparentPixel.B);
}
fprintf(hFile, "</table>\n");
}
}
else
{
fprintf(hFile, "The contents of this chunk could not be parsed.\n");
}
fprintf(hFile, "</div>\n\n"); fprintf(hFile, "</div>\n\n");
} }

View file

@ -0,0 +1,46 @@
int dummy = 0;
char *someString = &dummy;
someString += '(';
int currentParamIdx = 0;
unsigned short currentParam;
unsigned short param0;
do
{
currentParam = *(&param0 + 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 += ')';