iff2html is working and can properly parse STR# chunks.

I also added my TSOSimulatorClient work to the trunk.
This commit is contained in:
Fatbag 2012-03-13 00:12:27 -05:00
parent a4a7b82bb7
commit 64fddcf78e
16 changed files with 963 additions and 80 deletions

View file

@ -17,6 +17,8 @@ set(FILEHANDLER_MINOR 0)
set(FILEHANDLER_SOURCES
File.cpp
Image.cpp
iff/chunks.c
iff/iff.c
)
include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler)

View file

@ -4,7 +4,6 @@ project(iff)
set(IFF_SOURCES
chunks.c
iff.c
iffexport.c
)
add_executable(iffexport ${IFF_SOURCES})
add_executable(iffexport iffexport.c ${IFF_SOURCES})

View file

@ -19,6 +19,239 @@
#include <stdint.h>
#include "iff.h"
int iff_read_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize, unsigned IFFSize){
int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){
if(!strcmp(ChunkInfo->Type, "STR#"))
return iff_parse_str(ChunkInfo, Buffer);
return 0;
}
int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){
/* No bounds checking yet */
IFF_STR * StringData;
unsigned Size = ChunkInfo->Size - 64;
if(Size < 4)
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;
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;
}
int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){
return 1;
}

View file

@ -15,6 +15,14 @@
*/
#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_int24be(x) (signed)(((x)[0]<<(8*2)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*0)))
#define read_int16be(x) (signed)(((x)[0]<<(8*1)) | ((x)[1]<<(8*0)))
#define read_int8be(x) (signed)(((x)[0]<<(8*0)))
#define read_int32le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_int24le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
#define read_int16le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#define read_int8le(x) (signed)(((x)[0]<<(8*0)))
#define read_uint32be(x) (unsigned)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0)))
#define read_uint24be(x) (unsigned)(((x)[0]<<(8*2)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*0)))
#define read_uint16be(x) (unsigned)(((x)[0]<<(8*1)) | ((x)[1]<<(8*0)))
@ -25,6 +33,10 @@
#define read_uint8le(x) (unsigned)(((x)[0]<<(8*0)))
#endif
/*
** IFF file headers
*/
typedef struct IFFChunk_struct
{
char Type[5];
@ -55,6 +67,63 @@ typedef struct IFFFile_struct
static const uint8_t Header_IFF[] = "IFF FILE 2.5:TYPE FOLLOWED BY SIZE\0 JAMIE DOORNBOS & MAXIS 1";
/*
** IFF chunk structs
*/
/* 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;
#ifdef __cplusplus
extern "C" {
#endif
@ -78,7 +147,9 @@ void iff_delete(IFFFile * IFFFileInfo);
** IFF chunk functions
*/
int iff_read_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize, 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_str(IFFChunk * ChunkInfo, const uint8_t * Buffer);
#ifdef __cplusplus
}

View file

@ -288,8 +288,7 @@ void AdvanceFrame(Skeleton_t& Skeleton, Animation_t& Animation, float TimeDelta)
{
float Duration = (float)Animation.Motions[0].FrameCount/30;
AnimationTime += TimeDelta;
while(AnimationTime >= Duration) AnimationTime -= Duration;
if(AnimationTime<0) AnimationTime = 0; //Safe-guard against rounding error
AnimationTime = fmodf(AnimationTime, Duration); //Loop the animation
for(unsigned i=0; i<Animation.MotionsCount; i++){
unsigned BoneIndex = FindBone(Skeleton, Animation.Motions[i].BoneName, Skeleton.BoneCount);

View file

@ -4,9 +4,9 @@
#define PACKAGE "libvitaboy"
/* Version number of package */
#define VERSION_A 0
#define VERSION_A 1
#define VERSION_B 0
#define VERSION_C 1
#define VERSION_STR "0.0.1"
#define VERSION_STR "1.0.1"
/* You should fill the revision in if you're compiling from the trunk */
#define REVISION 0

View file

@ -85,11 +85,6 @@ void ReadMesh(Mesh_t& Mesh){
//Blended vertex
Mesh.TransformedVertexData[i].BlendData.Weight = BlendData[i-Mesh.RealVertexCount].Weight;
Mesh.TransformedVertexData[i].BlendData.OtherVertex = BlendData[i-Mesh.RealVertexCount].OtherVertex;
//Inherit texture coordinates
TextureVertex_t& Parent = TextureVertexData[Mesh.TransformedVertexData[i].BlendData.OtherVertex];
Mesh.TransformedVertexData[i].TextureCoord.u = Parent.u;
Mesh.TransformedVertexData[i].TextureCoord.v = Parent.v;
}
}

View file

@ -0,0 +1,19 @@
DLLs in The Sims Online (and also SimCity 4 and The Sims 2) use a special
interface, based on Microsoft COM.
These DLLs each export exactly one function:
void * GZDllGetGZCOMDirector(void)
This function creates and sets up a C++ object, with variables and member
functions, and returns a pointer to that object. This is your standard
C++ v-table.
TSOSimulatorClientD.dll is the most important DLL in the game. It implements
the SimAntics virtual machine which executes all the objects in the game.
In our situation, we need to figure out everything it does, because we lack
any information regarding the SimAntics instruction set architecture.
A text dump of this DLL is not nearly enough to find this. The files in the
objectdata/globals folder are not nearly enough. The page on
simtech.sourceforge.net documenting all they know about SimAntics is not
nearly enough. We need to run this DLL in a disassembler and figure out the
meaning of every opcode used in every behavior script of the game.

View file

@ -0,0 +1,40 @@
/*
TSOSimulatorClient.cpp - Copyright (c) 2012 Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <windows.h>
int main(){
HMODULE dllmodule = LoadLibrary("TSOSimulatorClientD.dll");
if(dllmodule == NULL){
printf("TSOSimulatorClient: Error: Failed to load DLL \"TSOSimulatorClientD.dll\".");
return -1;
}
void * (__stdcall *GZDllGetGZCOMDirector)(void) = (void * (__stdcall *)(void)) GetProcAddress(dllmodule, "GZDllGetGZCOMDirector");
if(GZDllGetGZCOMDirector == NULL){
printf("TSOSimulatorClient: Error: Failed to find GZDllGetGZCOMDirector() in TSOSimulatorClientD.dll.");
return -1;
}
printf("TSOSimulatorClient: Calling GZDllGetGZCOMDirector() ...\n");
void * value = GZDllGetGZCOMDirector();
printf("TSOSimulatorClient: Finished calling GZDllGetGZCOMDirector().\nThe value returned was: %p.\n", value);
printf("TSOSimulatorClient: Exiting.\n");
FreeLibrary(dllmodule);
return 0;
}

View file

@ -0,0 +1,116 @@
/*
TSOSimulatorClient.hpp - Copyright (c) 2012 Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <basetyps.h>
DECLARE_INTERFACE(IMMDeviceCollection);
DECLARE_INTERFACE(IMMNotificationClient);
DECLARE_INTERFACE(IPropertyStore);
/*
** IMMDevice
*/
DECLARE_INTERFACE_(IMMDevice, IUnknown)
{
STDMETHOD(Activate) (REFIID iid, DWORD dwClsCtx, PROPVARIANT *pActivationParams, void **ppInterface);
STDMETHOD(OpenPropertyStore) (DWORD stgmAccess, IPropertyStore **ppProperties);
STDMETHOD(GetId) (LPWSTR *ppstrId);
STDMETHOD(GetState) (DWORD *pdwState);
};
/*
** IMMDeviceEnumerator
*/
enum EDataFlow
{
eRender,
eCapture,
eAll
};
enum ERole
{
eConsole,
eMultimedia,
eCommunications
};
DECLARE_INTERFACE_(IMMDeviceEnumerator, IUnknown)
{
STDMETHOD(EnumAudioEndpoints) (EDataFlow dataFlow, DWORD dwStateMask, IMMDeviceCollection **ppDevices);
STDMETHOD(GetDefaultAudioEndpoint) (EDataFlow dataFlow, ERole role, IMMDevice **ppEndpoint);
STDMETHOD(GetDevice) (LPCWSTR pwstrId, IMMDevice **ppDevice);
STDMETHOD(RegisterEndpointNotificationCallback) (IMMNotificationClient *pClient);
STDMETHOD(UnregisterEndpointNotificationCallback) (IMMNotificationClient *pClient);
};
/*
** IAudioClient
*/
enum AUDCLNT_SHAREMODE
{
AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_SHAREMODE_EXCLUSIVE
};
enum AUDCLNT_STREAMFLAGS
{
AUDCLNT_STREAMFLAGS_CROSSPROCESS = 0x00010000,
AUDCLNT_STREAMFLAGS_LOOPBACK = 0x00020000,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK = 0x00040000,
AUDCLNT_STREAMFLAGS_NOPERSIST = 0x00080000,
AUDCLNT_STREAMFLAGS_RATEADJUST = 0x00100000,
AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED = 0x10000000,
AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE = 0x20000000,
AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED = 0x40000000
};
DECLARE_INTERFACE_(IAudioClient, IUnknown)
{
STDMETHOD(Initialize) (AUDCLNT_SHAREMODE ShareMode, DWORD StreamFlags, LONGLONG hnsBufferDuration,
LONGLONG hnsPeriodicity, const WAVEFORMATEX *pFormat, LPCGUID AudioSessionGuid);
STDMETHOD(GetBufferSize) (UINT32 *pNumBufferFrames);
STDMETHOD(GetStreamLatency) (LONGLONG *phnsLatency);
STDMETHOD(GetCurrentPadding) (UINT32 *pNumPaddingFrames);
STDMETHOD(IsFormatSupported) (AUDCLNT_SHAREMODE ShareMode, const WAVEFORMATEX *pFormat, WAVEFORMATEX **ppClosestMatch);
STDMETHOD(GetMixFormat) (WAVEFORMATEX **ppDeviceFormat);
STDMETHOD(GetDevicePeriod) (LONGLONG *phnsDefaultDevicePeriod, LONGLONG *phnsMinimumDevicePeriod);
STDMETHOD(Start) (void);
STDMETHOD(Stop) (void);
STDMETHOD(Reset) (void);
STDMETHOD(SetEventHandle) (HANDLE eventHandle);
STDMETHOD(GetService) (REFIID riid, void **ppv);
};
/*
** IAudioRenderClient
*/
enum AUDCLNT_BUFFERFLAGS
{
AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY = 0x1,
AUDCLNT_BUFFERFLAGS_SILENT = 0x2,
AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR = 0x4
};
DECLARE_INTERFACE_(IAudioRenderClient, IUnknown)
{
STDMETHOD(GetBuffer) (UINT32 NumFramesRequested, BYTE **ppData);
STDMETHOD(ReleaseBuffer) (UINT32 NumFramesWritten, DWORD dwFlags);
};

View file

@ -0,0 +1 @@
gcc -Wall -Wextra -Wabi -pedantic -m32 -o TSOSimulatorClient.exe TSOSimulatorClient.cpp -mconsole

View file

@ -0,0 +1,106 @@
CPU Dump
Address Hex dump
10102AF8 C4 61 0D 10|94 61 0D 10|00 00 00 00|00 00 00 00| 0
10102B08 08 7A 0D 10|F8 30 3D 00|F8 30 3D 00|00 31 3D 00| 4
10102B18 00 00 00 00|00 00 00 00|00 00 00 00|70 3B 3D 00| 8
10102B28 7C 3B 3D 00|80 3B 3D 00|10 10 10 00|E0 32 3D 00| 12
10102B38 E4 35 3D 00|E4 35 3D 00|00 00 00 00|01 00 00 00| 16
10102B48 A4 62 0D 10|78 62 0D 10|00 00 00 00|00 00 00 00| 20
10102B58 08 7A 0D 10|10 31 3D 00|10 31 3D 00|18 31 3D 00| 24
10102B68 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| 28
10102B78 00 00 00 00|00 00 00 00|10 10 10 00|58 3C 3D 00| 32
10102B88 5C 3F 3D 00|5C 3F 3D 00|0D 00 00 00|01 00 00 00| 36
10102B98 00 00 00 00|00 00 00 00|08 7A 0D 10|08 09 3D 00| 40
10102BA8 1D 09 3D 00|1E 09 3D 00|00 00 00 00|00 00 00 00| 44
10102BB8 00 00 00 00|18 31 3D 00|80 3B 3D 00|88 0A 3D 00| 48
10102BC8 A8 2D 3D 00|00 00 00 00|00 00 00 00|00 00 00 00| 52
10102BD8 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| 56
10102BE8 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| 60
10102BF8 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| 64
10102C08 10 0C 00 00|B0 3B 3D 00|40 3C 3D 00|00 00 00 00| 68
Offset: Meaning
0: Pointer to v-table 2 - 100D61C4
1: Pointer to v-table 1 - 100D6194
2: 0
3: 0
4: Pointer to v-table 5 - 100D7A08
5: Pointer
6: Pointer
7: Pointer
8: 0
9: 0
10: 0
11: Pointer
12: Pointer
13: Pointer
14: Flags? - 0x00101010
15: Pointer
16: Pointer
17: Pointer
18: 0
19: 1
20: Pointer to v-table 4 - 100D62A4
21: Pointer to v-table 3 - 100D6278
22: 0
23: 0
24: Pointer to v-table 5 - 100D7A08
25: Pointer
26: Pointer
27: Pointer
28: 0
29: 0
30: 0
31: 0
32: 0
33: 0
34: Flags? - 0x00101010
35: Pointer
36: Pointer
37: Pointer
38: 13
39: 1
40: 0
41: 0
42: Pointer to v-table 5 - 100D7A08
43: Pointer
44: Pointer
45: Pointer
46: 0
47: 0
48: 0
49: Pointer
50: Pointer
51: Pointer
52: Pointer
53: 0
54: 0
55: 0
56: 0
57: 0
58: 0
59: 0
60: 0
61: 0
62: 0
63: 0
64: 0
65: 0
66: 0
67: 0
68: 3088
69: Pointer
70: Pointer
71: 0
5 v-tables:
100D6194 (12 entries)
100D61C4 (17 entries)
100D6278 (11 entries)
100D62A4 (344 entries)
100D7A08 (695 entries)

View file

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 2.6)
project(iff2html)
set(IFF2HTML_SOURCES
iff2html.c
)
include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler)
add_executable(iff2html ${IFF2HTML_SOURCES})
target_link_libraries(iff2html FileHandler_shared)

View file

@ -17,24 +17,31 @@
#include <stdio.h>
#include <stdint.h>
#include <windows.h>
#include "iff.h"
#include <iff/iff.h>
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
int main(int argc, char *argv[]){
HANDLE hFile;
unsigned i;
FILE * hFile;
int overwrite = 0;
char *InFile, *OutDirectory;
HANDLE ProcessHeap = GetProcessHeap();
char *InFile, *OutFile = NULL;
DWORD FileSize;
DWORD bytestransferred = 0;
uint8_t * IFFData;
unsigned chunkcount, chunk = 0;
unsigned chunk = 0;
IFFFile * IFFFileInfo;
IFFChunkNode * ChunkNode;
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"
"Produce an HTML webpage describing an EA IFF file.\n"
"Use -f to force overwriting without confirmation.\n"
"If outfile is unspecified, file.iff will output to file.html.\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"iff2html is maintained by the Niotso project.\n"
@ -45,10 +52,21 @@ int main(int argc, char *argv[]){
if(argc >= 4 && !strcmp(argv[1], "-f")){
overwrite++;
InFile = argv[2];
OutDirectory = argv[3];
}else{
InFile = argv[1];
OutDirectory = argv[2];
OutFile = argv[3];
}else if(argc == 3){
if(!strcmp(argv[1], "-f")){
overwrite++;
InFile = argv[2];
}else{
InFile = argv[1];
OutFile = argv[2];
}
}else InFile = argv[1];
if(OutFile == NULL){
unsigned length = strlen(InFile);
OutFile = malloc(max(length+2, 6));
strcpy(OutFile, InFile);
strcpy(max(OutFile+length-4, OutFile), ".html");
}
/****
@ -56,29 +74,29 @@ int main(int argc, char *argv[]){
*/
hFile = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE){
if(GetLastError() == ERROR_FILE_NOT_FOUND){
printf("%sThe specified input file does not exist.", "iff2html: error: ");
return -1;
}
printf("%sThe input file could not be opened for reading.", "iff2html: error: ");
hFile = fopen(InFile, "rb");
if(hFile == NULL){
printf("%sThe specified input file does not exist or could not be opened for reading.", "iff2html: error: ");
return -1;
}
FileSize = GetFileSize(hFile, NULL);
fseek(hFile, 0, SEEK_END);
FileSize = ftell(hFile);
if(FileSize < 64){
printf("%sNot a valid IFF file.", "iff2html: error: ");
return -1;
}
IFFData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, FileSize);
fseek(hFile, 0, SEEK_SET);
IFFData = malloc(FileSize);
if(IFFData == NULL){
printf("%sMemory for this file could not be allocated.", "iff2html: error: ");
return -1;
}
if(!ReadFile(hFile, IFFData, FileSize, &bytestransferred, NULL) || bytestransferred != FileSize){
if(!fread(IFFData, FileSize, 1, hFile)){
printf("%sThe input file could not be read.", "iff2html: error: ");
return -1;
}
CloseHandle(hFile);
fclose(hFile);
/****
** Load header information
@ -103,7 +121,200 @@ int main(int argc, char *argv[]){
return -1;
}
chunkcount = IFFFileInfo->ChunkCount;
for(chunk = 1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, chunk++){
printf("Chunk %u:\n", chunk);
iff_parse_chunk(&ChunkNode->Chunk, ChunkNode->Chunk.Data);
}
/****
** Open the output file and write the header
*/
if(!overwrite){
hFile = fopen(OutFile, "rb");
if(hFile != NULL){
/* File exists */
char c;
fclose(hFile);
printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile);
c = getchar();
if(c != 'y' && c != 'Y'){
printf("\nAborted.");
return -1;
}
}
}
hFile = fopen(OutFile, "wb");
if(hFile == NULL){
printf("%sThe output file could not be opened for writing.", "iff2html: error: ");
return -1;
}
/****
** We're splitting fprintf by line to guarantee compatibility;
** even C99 compilers are only required to support 4096 byte strings in printf()-related functions
*/
fprintf(hFile, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
fprintf(hFile, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n");
fprintf(hFile, "<head>\n");
fprintf(hFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
fprintf(hFile, "<meta http-equiv=\"Content-Style-Type\" content=\"text/css; charset=utf-8\" />\n");
fprintf(hFile, "<meta http-equiv=\"Content-Language\" content=\"en\" />\n");
fprintf(hFile, "<meta name=\"description\" content=\"%s (iff2html)\" />\n", InFile);
fprintf(hFile, "<meta name=\"generator\" content=\"iff2html\" />\n");
fprintf(hFile, "<title>%s (iff2html)</title>\n", InFile);
fprintf(hFile, "<style type=\"text/css\" media=\"all\">\n");
fprintf(hFile, "html, body {\n");
fprintf(hFile, " background: #fff;\n");
fprintf(hFile, " color: #000;\n");
fprintf(hFile, " font-family: sans-serif;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, "a:link, a:visited, a:hover, a:active { color: #00f; }\n");
fprintf(hFile, "a:link, a:visited { text-decoration: none; }\n");
fprintf(hFile, "a:hover, a:active { text-decoration: underline; }\n");
fprintf(hFile, "\n");
fprintf(hFile, "#attributes {\n");
fprintf(hFile, " border-left: 2px solid #888; padding-left: 4px; margin-bottom: 1em;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, "#toc {\n");
fprintf(hFile, " display: table-cell;\n");
fprintf(hFile, " margin-top: 1em;\n");
fprintf(hFile, " background: #eee; border: 1px solid #bbb;\n");
fprintf(hFile, " padding: .25em;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "#toc div {\n");
fprintf(hFile, " border-bottom: 1px solid #aaa;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "#toc ul {\n");
fprintf(hFile, " list-style-type: none;\n");
fprintf(hFile, " padding: 0;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "ul ul {\n");
fprintf(hFile, " padding: 2em;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, "h2 {\n");
fprintf(hFile, " border-bottom: 1px solid #888;\n");
fprintf(hFile, " margin: 2em 0 0.25em 0;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "h2 a {\n");
fprintf(hFile, " font-size: 9pt;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, "table {\n");
fprintf(hFile, " border: 1px #aaa solid;\n");
fprintf(hFile, " border-collapse: collapse;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "th, td {\n");
fprintf(hFile, " border: 1px #aaa solid;\n");
fprintf(hFile, " padding: 0.2em;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, ".center {\n");
fprintf(hFile, " margin: auto auto;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "\n");
fprintf(hFile, "#footer {\n");
fprintf(hFile, " margin-top: 2em;\n");
fprintf(hFile, " padding-bottom: 0.5em;\n");
fprintf(hFile, " text-align: center;\n");
fprintf(hFile, "}\n");
fprintf(hFile, "</style>\n");
fprintf(hFile, "</head>\n");
fprintf(hFile, "<body>\n");
fprintf(hFile, "<h1>%s</h1>\n", InFile);
fprintf(hFile, "\n");
fprintf(hFile, "<div id=\"toc\"><div><b>Contents</b> &ndash; %u chunks</div>\n", IFFFileInfo->ChunkCount);
fprintf(hFile, "<ul>\n");
for(i=1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, i++)
fprintf(hFile, "<li><a href=\"#chunk%u_%.4x\">%u [%s] (%.4X)%s%s</a></li>\n",
i, ChunkNode->Chunk.ChunkID, i, ChunkNode->Chunk.Type, ChunkNode->Chunk.ChunkID,
(ChunkNode->Chunk.Label[0] != 0x00) ? " &ndash; " : "", ChunkNode->Chunk.Label);
fprintf(hFile, "</ul>\n");
fprintf(hFile, "</div>\n");
fprintf(hFile, "\n");
for(i=1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, i++){
IFF_STR * StringData = (IFF_STR*) ChunkNode->Chunk.FormattedData;
fprintf(hFile, "<h2 id=\"chunk%u_%.4x\">%u [%s] (%.4X)%s%s <a href=\"#chunk%u_%.4x\">(Jump)</a></h2>\n",
i, ChunkNode->Chunk.ChunkID, i, ChunkNode->Chunk.Type, ChunkNode->Chunk.ChunkID,
(ChunkNode->Chunk.Label[0] != 0x00) ? " &ndash; " : "", ChunkNode->Chunk.Label,
i, ChunkNode->Chunk.ChunkID);
fprintf(hFile, "<div>\n");
if(ChunkNode->Chunk.FormattedData == NULL){
fprintf(hFile, "The contents of this chunk could not be parsed.\n");
}else if(!strcmp(ChunkNode->Chunk.Type, "STR#")){
/****
** STR# parsing
*/
fprintf(hFile, "<table>\n");
fprintf(hFile, "<tr><td>Format:</td><td>");
switch(StringData->Format){
case 0: fprintf(hFile, "<tt>00 00</tt> (0)"); break;
case -1: fprintf(hFile, "<tt>FF FF</tt> (&minus;1)"); break;
case -2: fprintf(hFile, "<tt>FE FF</tt> (&minus;2)"); break;
case -3: fprintf(hFile, "<tt>FD FF</tt> (&minus;3)"); break;
case -4: fprintf(hFile, "<tt>FC FF</tt> (&minus;4)"); break;
default: fprintf(hFile, "Unrecognized"); break;
}
fprintf(hFile, "</td></tr>\n");
fprintf(hFile, "</table>\n");
if(StringData->Format >= -4 && StringData->Format <= 0){
unsigned LanguageSet;
const char * LanguageStrings[] = {
"English (US)",
"English (International)",
"French",
"German",
"Italian",
"Spanish",
"Dutch",
"Danish",
"Swedish",
"Norwegian",
"Finnish",
"Hebrew",
"Russian",
"Portuguese",
"Japanese",
"Polish",
"Simplified Chinese",
"Traditional Chinese",
"Thai",
"Korean"
};
fprintf(hFile, "<br />\n");
fprintf(hFile, "<table class=\"center\">\n");
fprintf(hFile, "<tr><th>Language</th><th colspan=\"3\">String pairs</th></tr>\n");
for(LanguageSet=0; LanguageSet<20; LanguageSet++){
IFFStringPairNode * PairNode;
unsigned PairIndex;
if(StringData->LanguageSets[LanguageSet].PairCount == 0)
continue;
fprintf(hFile, "<tr><td rowspan=\"%u\">%s</td>\n", StringData->LanguageSets[LanguageSet].PairCount,
LanguageStrings[LanguageSet]);
for(PairIndex=1, PairNode = StringData->LanguageSets[LanguageSet].FirstPair; PairNode;
PairNode = PairNode->NextPair, PairIndex++)
fprintf(hFile, "<td>%u</td><td>%s</td><td>%s</td></tr>\n", PairIndex,
(PairNode->Pair.Key) != NULL ? PairNode->Pair.Key : "",
(PairNode->Pair.Value) != NULL ? PairNode->Pair.Value : "");
}
fprintf(hFile, "</table>\n");
}
}
fprintf(hFile, "</div>\n\n");
}
fprintf(hFile, "<div id=\"footer\">This page was generated by the use of <a href=\"http://www.niotso.org/\">iff2html</a>.\n");
fprintf(hFile, "The content of this page may be subject to copyright by the author(s) of the original iff file.</div>\n");
fprintf(hFile, "</body>\n");
fprintf(hFile, "</html>");
fclose(hFile);
return 0;
}

View file

@ -0,0 +1,125 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
<meta name="description" content="behavior.iff (iff2html)" />
<meta name="generator" content="iff2html" />
<title>behavior.iff (iff2html)</title>
<style type="text/css" media="all">
html, body {
background: #fff;
color: #000;
font-family: sans-serif;
}
a:link, a:visited, a:hover, a:active { color: #00f; }
a:link, a:visited { text-decoration: none; }
a:hover, a:active { text-decoration: underline; }
#attributes {
border-left: 2px solid #888; padding-left: 4px; margin-bottom: 1em;
}
#toc {
display: table-cell;
margin-top: 1em;
background: #eee; border: 1px solid #bbb;
padding: .25em;
}
#toc div {
border-bottom: 1px solid #aaa;
}
#toc ul {
list-style-type: none;
padding: 0;
}
ul ul {
padding: 2em;
}
h2 {
border-bottom: 1px solid #888;
margin: 2em 0 0.25em 0;
}
h2 a {
font-size: 9pt;
}
table {
border: 1px #aaa solid;
border-collapse: collapse;
}
th, td {
border: 1px #aaa solid;
padding: 0.2em;
}
.center {
margin: auto auto;
}
#footer {
margin-top: 1.75em;
text-align: center;
}
</style>
</head>
<body>
<h1>behavior.iff</h1>
<div id="attributes">
<div>9809b96803833f2891ddd31e474795a9 (md5), 42.4kB (43,446 bytes)</div>
<div>Dumped by iff2html.</div></div>
<div id="toc"><div><b>Contents</b> &ndash; x chunks</div>
<ul>
<li><a href="#chunk1_00dd">1 [STR#] (00DD) &ndash; neighbor data labels</a></li>
<li><a href="#chunk2_00ea">2 [STR#] (00EA) &ndash; build mode types</a></li>
</ul>
</div>
<h2 id="chunk1_00dd">1 [STR#] (00DD) &ndash; neighbor data labels <a href="#chunk1_00dd">(Jump)</a></h2>
<div>
<table>
<tr><td>Format:</td><td><tt>FC FF</tt> (&minus;4)</td></tr>
</table><br />
<table class="center">
<tr><th>Language</th><th colspan="3">String pairs</th></tr>
<tr><td rowspan="10">English (US)</td>
<td>1</td><td>person instance id</td><td>4</td></tr>
<tr><td>2</td><td>belongs in house</td><td>4</td></tr>
<tr><td>3</td><td>person age</td><td>4</td></tr>
<tr><td>4</td><td>relationship raw score</td><td>4</td></tr>
<tr><td>5</td><td>relationship score</td><td>4</td></tr>
<tr><td>6</td><td>friend count</td><td>4</td></tr>
<tr><td>7</td><td>house number</td><td>4</td></tr>
<tr><td>8</td><td>has telephone</td><td>4</td></tr>
<tr><td>9</td><td>has baby</td><td>4</td></tr>
<tr><td>10</td><td>family friend count</td><td>4</td></tr>
</table>
</div>
<h2 id="chunk2_00ea">2 [STR#] (00EA) &ndash; build mode types <a href="#chunk2_00ea">(Jump)</a></h2>
<div>
<table>
<tr><td>Format:</td><td><tt>FC FF</tt> (&minus;4)</td></tr>
</table><br />
<table class="center">
<tr><th>Language</th><th colspan="3">String pairs</th></tr>
<tr><td rowspan="8">English (US)</td>
<td>1</td><td>none</td><td>4</td></tr>
<tr><td>2</td><td>door</td><td>4</td></tr>
<tr><td>3</td><td>window</td><td>4</td></tr>
<tr><td>4</td><td>stair</td><td>4</td></tr>
<tr><td>5</td><td>plant</td><td>4</td></tr>
<tr><td>6</td><td>fireplace</td><td>4</td></tr>
<tr><td>7</td><td>column</td><td>4</td></tr>
<tr><td>8</td><td>pool equipment</td><td>4</td></tr>
</table>
</div>
<div id="footer">This page was generated by the use of <a href="http://www.niotso.org/">iff2html</a>.
The content of this page may be subject to copyright by the author(s) of the original iff file.</div>
</body>
</html>

View file

@ -1,45 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
<meta name="description" content="behavior.iff (iff2html)" />
<title>behavior.iff (iff2html)</title>
<style type="text/css" media="all">
html, body {
font-family: sans-serif;
}
a:link, a:visited, a:hover; a:active { color: #00f; }
a:link, a:visited { text-decoration: none; }
a:hover, a:active { text-decoration: underline; }
#toc {
display: table-cell;
margin-top: 1em;
background: #eee; border: 1px solid #bbb;
padding: .25em;
}
#toc ul {
list-style-type: none;
padding: 0;
}
ul ul {
padding: 2em;
}
</style>
</head>
<body>
<h1>behavior.iff</h1>
<div style="border-left: 2px solid #888; padding-left: 4px; margin-bottom: 1em">
<div>9809b96803833f2891ddd31e474795a9 (md5), 42.4kB (43,446 bytes)</div>
<div>Dumped by iff2html.</div></div>
<div id="toc"><div><b>Contents</b> &ndash; x chunks</div>
<ul>
<li><a href="#">1 [STR#] (00DD) &ndash; neighbor data labels</a></li>
</ul>
</div>
</body>
</html>