mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-15 08:11:22 +00:00
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:
parent
02dff475c8
commit
6c85920535
16 changed files with 1150 additions and 84 deletions
|
@ -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)
|
||||
target_link_libraries(FileHandler_shared kernel32 jpegturbo_static zlib_shared libpng_static)
|
|
@ -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})
|
53
Libraries/FileHandler/iff/bhav.c
Normal file
53
Libraries/FileHandler/iff/bhav.c
Normal 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;
|
||||
}
|
29
Libraries/FileHandler/iff/bhav.h
Normal file
29
Libraries/FileHandler/iff/bhav.h
Normal 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;
|
|
@ -19,16 +19,19 @@
|
|||
#include <stdint.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#") ||
|
||||
!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){
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
518
Libraries/FileHandler/iff/sprite.c
Normal file
518
Libraries/FileHandler/iff/sprite.c
Normal 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;
|
||||
}
|
41
Libraries/FileHandler/iff/sprite.h
Normal file
41
Libraries/FileHandler/iff/sprite.h
Normal 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;
|
233
Libraries/FileHandler/iff/stbl.c
Normal file
233
Libraries/FileHandler/iff/stbl.c
Normal 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;
|
||||
}
|
52
Libraries/FileHandler/iff/stbl.h
Normal file
52
Libraries/FileHandler/iff/stbl.h
Normal 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;
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
@ -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, "</table>\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(ChunkNode->Chunk.Type, "BHAV") )
|
||||
{
|
||||
IFF_TREETABLE * TreeTableData = (IFF_TREETABLE*) ChunkNode->Chunk.FormattedData;
|
||||
|
||||
fprintf(hFile, "<table>\n");
|
||||
else if (!strcmp(ChunkNode->Chunk.Type, "BHAV") )
|
||||
{
|
||||
IFF_TREETABLE * TreeTableData = (IFF_TREETABLE*) ChunkNode->Chunk.FormattedData;
|
||||
|
||||
fprintf(hFile, "<table>\n");
|
||||
fprintf(hFile, "<tr><td>Stream Version:</td><td>");
|
||||
switch(TreeTableData->StreamVersion){
|
||||
case 0x8000: fprintf(hFile, "<tt>0x8000</tt> (0)"); break;
|
||||
|
@ -366,58 +383,100 @@ int main(int argc, char *argv[]){
|
|||
default: fprintf(hFile, "Unrecognized"); break;
|
||||
}
|
||||
fprintf(hFile, "</td></tr>\n");
|
||||
|
||||
fprintf(hFile, "<tr><td>Tree Version:</td><td>");
|
||||
|
||||
fprintf(hFile, "<tr><td>Tree Version:</td><td>");
|
||||
fprintf(hFile, "<tt>%-#10X</tt> (%u)", TreeTableData->TreeVersion, TreeTableData->TreeVersion);
|
||||
fprintf(hFile, "</td></tr>\n");
|
||||
|
||||
fprintf(hFile, "<tr><td>Tree Type:</td><td>");
|
||||
|
||||
fprintf(hFile, "<tr><td>Tree Type:</td><td>");
|
||||
fprintf(hFile, "<tt>%-#4X</tt> (%u)", TreeTableData->Type, TreeTableData->Type);
|
||||
fprintf(hFile, "</td></tr>\n");
|
||||
|
||||
fprintf(hFile, "<tr><td>Number of Parameters:</td><td>");
|
||||
|
||||
fprintf(hFile, "<tr><td>Number of Parameters:</td><td>");
|
||||
fprintf(hFile, "<tt>%u</tt>", TreeTableData->NumParams);
|
||||
fprintf(hFile, "</td></tr>\n");
|
||||
|
||||
fprintf(hFile, "<tr><td>Number of Local Variables:</td><td>");
|
||||
|
||||
fprintf(hFile, "<tr><td>Number of Local Variables:</td><td>");
|
||||
fprintf(hFile, "<tt>%u</tt>", TreeTableData->NumLocals);
|
||||
fprintf(hFile, "</td></tr>\n");
|
||||
|
||||
fprintf(hFile, "<tr><td>Number of Tree Nodes:</td><td>");
|
||||
|
||||
fprintf(hFile, "<tr><td>Number of Tree Nodes:</td><td>");
|
||||
fprintf(hFile, "<tt>%u</tt>", (TreeTableData->NodesEnd - TreeTableData->NodesBegin));
|
||||
fprintf(hFile, "</td></tr>\n");
|
||||
|
||||
|
||||
fprintf(hFile, "</table>\n");
|
||||
if(TreeTableData->StreamVersion >= 0x8000 && TreeTableData->StreamVersion <= 0x8003)
|
||||
{
|
||||
{
|
||||
fprintf(hFile, "<br />\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");
|
||||
|
||||
IFF_TREETABLENODE *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));
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->PrimitiveNumber, currentNode->PrimitiveNumber);
|
||||
if (currentNode->TransitionTrue < 253)
|
||||
fprintf(hFile, "<td>%d (%-#4X)</td>\n", currentNode->TransitionTrue, currentNode->TransitionTrue);
|
||||
else
|
||||
fprintf(hFile, "<td>%s</td>\n", currentNode->TransitionTrue == 253 ? "error" : currentNode->TransitionTrue == 254 ? "true" : "false");
|
||||
|
||||
|
||||
if (currentNode->TransitionFalse < 253)
|
||||
fprintf(hFile, "<td>%d (%-#4X)</td>\n", currentNode->TransitionFalse, currentNode->TransitionFalse);
|
||||
else
|
||||
fprintf(hFile, "<td>%s</td>\n", currentNode->TransitionFalse == 253 ? "error" : currentNode->TransitionFalse == 254 ? "true" : "false");
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param0, currentNode->Parameters.Param0);
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param1, currentNode->Parameters.Param1);
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param2, currentNode->Parameters.Param2);
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param3, currentNode->Parameters.Param3);
|
||||
if (currentNode->TransitionTrue < 253)
|
||||
fprintf(hFile, "<td>%d (%-#4X)</td>\n", currentNode->TransitionTrue, currentNode->TransitionTrue);
|
||||
else
|
||||
fprintf(hFile, "<td>%s</td>\n", currentNode->TransitionTrue == 253 ? "error" : currentNode->TransitionTrue == 254 ? "true" : "false");
|
||||
|
||||
|
||||
if (currentNode->TransitionFalse < 253)
|
||||
fprintf(hFile, "<td>%d (%-#4X)</td>\n", currentNode->TransitionFalse, currentNode->TransitionFalse);
|
||||
else
|
||||
fprintf(hFile, "<td>%s</td>\n", currentNode->TransitionFalse == 253 ? "error" : currentNode->TransitionFalse == 254 ? "true" : "false");
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param0, currentNode->Parameters.Param0);
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param1, currentNode->Parameters.Param1);
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param2, currentNode->Parameters.Param2);
|
||||
fprintf(hFile, "<td>%d (%-#6X)</td>\n", currentNode->Parameters.Param3, currentNode->Parameters.Param3);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
46
Tools/iff2html/paramparse.cpp
Normal file
46
Tools/iff2html/paramparse.cpp
Normal file
|
@ -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 += ')';
|
Loading…
Add table
Reference in a new issue