Added BHAV support to FileHandler and iff2html

Split "chunk.c" functionality into bhav.h, bhav.c, stbl.h, stbl.c
This commit is contained in:
rothn 2012-04-02 20:07:46 -05:00
parent 4442056335
commit 02dff475c8
5 changed files with 82 additions and 286 deletions

View file

@ -19,6 +19,8 @@ set(FILEHANDLER_SOURCES
File.cpp
Image.cpp
cst/cst.c
iff/stbl.c
iff/bhav.c
iff/chunks.c
iff/iff.c
)

View file

@ -2,7 +2,9 @@ cmake_minimum_required(VERSION 2.6)
project(iff)
set(IFF_SOURCES
chunks.c
bhav.c
stbl.c
chunks.c
iff.c
)

View file

@ -23,238 +23,12 @@ int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){
if( !strcmp(ChunkInfo->Type, "STR#") ||
!strcmp(ChunkInfo->Type, "CTSS") ||
!strcmp(ChunkInfo->Type, "FAMs") ||
!strcmp(ChunkInfo->Type, "TTAs") )
!strcmp(ChunkInfo->Type, "TTAs") )
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 - 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;
else if (!strcmp(ChunkInfo->Type, "BHAV"))
return iff_parse_bhav(ChunkInfo, (const char *)Buffer);
else
return 0;
}
int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){

View file

@ -13,6 +13,8 @@
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "stbl.h"
#include "bhav.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)))
@ -71,59 +73,6 @@ static const uint8_t Header_IFF[] = "IFF FILE 2.5:TYPE FOLLOWED BY SIZE\0 JAMIE
** 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
@ -150,6 +99,7 @@ void iff_delete(IFFFile * IFFFileInfo);
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);
int iff_parse_bhav(IFFChunk * ChunkInfo, const uint8_t * Buffer);
#ifdef __cplusplus
}

View file

@ -272,7 +272,7 @@ int main(int argc, char *argv[]){
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,
@ -286,6 +286,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;
/****
** STR# parsing
*/
@ -350,6 +352,72 @@ 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");
fprintf(hFile, "<tr><td>Stream Version:</td><td>");
switch(TreeTableData->StreamVersion){
case 0x8000: fprintf(hFile, "<tt>0x8000</tt> (0)"); break;
case 0x8001: fprintf(hFile, "<tt>0x8001</tt> (1)"); break;
case 0x8002: fprintf(hFile, "<tt>0x8002</tt> (2)"); break;
case 0x8003: fprintf(hFile, "<tt>0x8003</tt> (3)"); break;
default: fprintf(hFile, "Unrecognized"); break;
}
fprintf(hFile, "</td></tr>\n");
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, "<tt>%-#4X</tt> (%u)", TreeTableData->Type, TreeTableData->Type);
fprintf(hFile, "</td></tr>\n");
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, "<tt>%u</tt>", TreeTableData->NumLocals);
fprintf(hFile, "</td></tr>\n");
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, "<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);
}
fprintf(hFile, "</table>\n");
}
}
fprintf(hFile, "</div>\n\n");
}