fix: some file didn't have the svn:eol-style native yet
This commit is contained in:
2846
Extras/iff/IFF.txt
2846
Extras/iff/IFF.txt
File diff suppressed because it is too large
Load Diff
@@ -1,233 +1,233 @@
|
||||
/*---------------------------------------------------------------------*
|
||||
* IFFCheck.C Print out the structure of an IFF-85 file, 11/19/85
|
||||
* checking for structural errors.
|
||||
*
|
||||
* DO NOT USE THIS AS A SKELETAL PROGRAM FOR AN IFF READER!
|
||||
* See ShowILBM.C for a skeletal example.
|
||||
*
|
||||
* Original version was for the Commodore-Amiga computer.
|
||||
/* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#include "iff.h"
|
||||
#include "stdlib.h" //for exit
|
||||
|
||||
/* ---------- IFFCheck -------------------------------------------------*/
|
||||
/* [TBD] More extensive checking could be done on the IDs encountered in the
|
||||
* file. Check that the reserved IDs "FOR1".."FOR9", "LIS1".."LIS9", and
|
||||
* "CAT1".."CAT9" aren't used. Check that reserved IDs aren't used as Form
|
||||
* types. Check that all IDs are made of 4 printable characters (trailing
|
||||
* spaces ok). */
|
||||
|
||||
typedef struct {
|
||||
ClientFrame clientFrame;
|
||||
int levels; /* # groups currently nested within.*/
|
||||
} Frame;
|
||||
|
||||
char MsgOkay[] = { "----- (IFF_OKAY) A good IFF file." };
|
||||
char MsgEndMark[] = {"----- (END_MARK) How did you get this message??" };
|
||||
char MsgDone[] = { "----- (IFF_DONE) How did you get this message??" };
|
||||
char MsgDos[] = { "----- (DOS_ERROR) The DOS gave back an error." };
|
||||
char MsgNot[] = { "----- (NOT_IFF) not an IFF file." };
|
||||
char MsgNoFile[] = { "----- (NO_FILE) no such file found." };
|
||||
char MsgClientError[] = {"----- (CLIENT_ERROR) IFF Checker bug."};
|
||||
char MsgForm[] = { "----- (BAD_FORM) How did you get this message??" };
|
||||
char MsgShort[] = { "----- (SHORT_CHUNK) How did you get this message??" };
|
||||
char MsgBad[] = { "----- (BAD_IFF) a mangled IFF file." };
|
||||
|
||||
/* MUST GET THESE IN RIGHT ORDER!!*/
|
||||
char *IFFPMessages[-LAST_ERROR+1] = {
|
||||
/*IFF_OKAY*/ MsgOkay,
|
||||
/*END_MARK*/ MsgEndMark,
|
||||
/*IFF_DONE*/ MsgDone,
|
||||
/*DOS_ERROR*/ MsgDos,
|
||||
/*NOT_IFF*/ MsgNot,
|
||||
/*NO_FILE*/ MsgNoFile,
|
||||
/*CLIENT_ERROR*/ MsgClientError,
|
||||
/*BAD_FORM*/ MsgForm,
|
||||
/*SHORT_CHUNK*/ MsgShort,
|
||||
/*BAD_IFF*/ MsgBad
|
||||
};
|
||||
|
||||
/* FORWARD REFERENCES */
|
||||
extern IFFP GetList(GroupContext*);
|
||||
extern IFFP GetForm(GroupContext*);
|
||||
extern IFFP GetProp(GroupContext*);
|
||||
extern IFFP GetCat (GroupContext*);
|
||||
|
||||
void IFFCheck(char *name)
|
||||
{
|
||||
IFFP iffp;
|
||||
BPTR file = fopen(name,"rb");//Open(name, MODE_OLDFILE);
|
||||
Frame frame;
|
||||
|
||||
frame.levels = 0;
|
||||
frame.clientFrame.getList = GetList;
|
||||
frame.clientFrame.getForm = GetForm;
|
||||
frame.clientFrame.getProp = GetProp;
|
||||
frame.clientFrame.getCat = GetCat ;
|
||||
|
||||
printf("----- Checking file '%s' -----\n", name);
|
||||
if (file == 0)
|
||||
iffp = NO_FILE;
|
||||
else
|
||||
iffp = ReadIFF(file, (ClientFrame *)&frame);
|
||||
|
||||
fclose(file);
|
||||
printf("%s\n", IFFPMessages[-iffp]);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 1+1) {
|
||||
printf("Usage: 'iffcheck filename'\n");
|
||||
exit(0);
|
||||
}
|
||||
IFFCheck(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------- Put... ---------------------------------------------------*/
|
||||
|
||||
void PutLevels(int count)
|
||||
{
|
||||
for ( ; count > 0; --count) {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
void PutID(int id)
|
||||
{
|
||||
long int i = 1;
|
||||
const char *p = (const char *) &i;
|
||||
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||
{
|
||||
//little endian machine
|
||||
printf("%c%c%c%c ", (char)(id&0x7f) , (char)(id>>8)&0x7f,
|
||||
(char)(id>>16)&0x7f, (char)(id>>24)&0x7f);
|
||||
} else
|
||||
{
|
||||
//big endian machine
|
||||
printf("%c%c%c%c ", (char)(id>>24)&0x7f, (char)(id>>16)&0x7f,
|
||||
(char)(id>>8)&0x7f, (char)(id&0x7f));
|
||||
}
|
||||
/* printf("id = %lx", id); */
|
||||
}
|
||||
|
||||
void PutN(long n)
|
||||
{
|
||||
printf(" %ld ", n);
|
||||
}
|
||||
|
||||
/* Put something like "...BMHD 14" or "...LIST 14 PLBM". */
|
||||
void PutHdr(GroupContext *context)
|
||||
{
|
||||
PutLevels( ((Frame *)context->clientFrame)->levels );
|
||||
PutID(context->ckHdr.ckID);
|
||||
PutN(context->ckHdr.ckSize);
|
||||
|
||||
if (context->subtype != NULL_CHUNK)
|
||||
PutID(context->subtype);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* ---------- AtLeaf ---------------------------------------------------*/
|
||||
|
||||
/* At Leaf chunk. That is, a chunk which does NOT contain other chunks.
|
||||
* Print "int size".*/
|
||||
IFFP AtLeaf(GroupContext *context)
|
||||
{
|
||||
|
||||
PutHdr(context);
|
||||
/* A typical reader would read the chunk's contents, using the "Frame"
|
||||
* for local data, esp. shared property settings (PROP).*/
|
||||
/* IFFReadBytes(context, ...buffer, context->ckHdr->ckSize); */
|
||||
return(IFF_OKAY);
|
||||
}
|
||||
|
||||
/* ---------- GetList --------------------------------------------------*/
|
||||
/* Handle a LIST chunk. Print "LIST size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetList(GroupContext *parent)
|
||||
{
|
||||
Frame newFrame;
|
||||
|
||||
newFrame = *(Frame *)parent->clientFrame; /* copy parent's frame*/
|
||||
newFrame.levels++;
|
||||
|
||||
PutHdr(parent);
|
||||
|
||||
return( ReadIList(parent, (ClientFrame *)&newFrame) );
|
||||
}
|
||||
|
||||
/* ---------- GetForm --------------------------------------------------*/
|
||||
/* Handle a FORM chunk. Print "FORM size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetForm(GroupContext *parent)
|
||||
{
|
||||
/*CompilerBug register*/ IFFP iffp;
|
||||
GroupContext newptr;
|
||||
Frame newFrame;
|
||||
|
||||
newFrame = *(Frame *)parent->clientFrame; /* copy parent's frame*/
|
||||
newFrame.levels++;
|
||||
|
||||
PutHdr(parent);
|
||||
|
||||
iffp = OpenRGroup(parent, &newptr);
|
||||
CheckIFFP();
|
||||
newptr.clientFrame = (ClientFrame *)&newFrame;
|
||||
|
||||
/* FORM reader for Checker. */
|
||||
/* LIST, FORM, PROP, CAT already handled by GetF1ChunkHdr. */
|
||||
do {if ( (iffp = GetF1ChunkHdr(&newptr)) > 0 )
|
||||
iffp = AtLeaf(&newptr);
|
||||
} while (iffp >= IFF_OKAY);
|
||||
|
||||
CloseRGroup(&newptr);
|
||||
return(iffp == END_MARK ? IFF_OKAY : iffp);
|
||||
}
|
||||
|
||||
/* ---------- GetProp --------------------------------------------------*/
|
||||
/* Handle a PROP chunk. Print "PROP size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetProp(GroupContext *listContext)
|
||||
{
|
||||
/*CompilerBug register*/ IFFP iffp;
|
||||
GroupContext newptr;
|
||||
|
||||
PutHdr(listContext);
|
||||
|
||||
iffp = OpenRGroup(listContext, &newptr);
|
||||
CheckIFFP();
|
||||
|
||||
/* PROP reader for Checker. */
|
||||
((Frame *)listContext->clientFrame)->levels++;
|
||||
|
||||
do {if ( (iffp = GetPChunkHdr(&newptr)) > 0 )
|
||||
iffp = AtLeaf(&newptr);
|
||||
} while (iffp >= IFF_OKAY);
|
||||
|
||||
((Frame *)listContext->clientFrame)->levels--;
|
||||
|
||||
CloseRGroup(&newptr);
|
||||
return(iffp == END_MARK ? IFF_OKAY : iffp);
|
||||
}
|
||||
|
||||
/* ---------- GetCat ---------------------------------------------------*/
|
||||
/* Handle a CAT chunk. Print "CAT size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetCat(GroupContext *parent)
|
||||
{
|
||||
IFFP iffp;
|
||||
|
||||
((Frame *)parent->clientFrame)->levels++;
|
||||
|
||||
PutHdr(parent);
|
||||
|
||||
iffp = ReadICat(parent);
|
||||
|
||||
((Frame *)parent->clientFrame)->levels--;
|
||||
return(iffp);
|
||||
}
|
||||
/*---------------------------------------------------------------------*
|
||||
* IFFCheck.C Print out the structure of an IFF-85 file, 11/19/85
|
||||
* checking for structural errors.
|
||||
*
|
||||
* DO NOT USE THIS AS A SKELETAL PROGRAM FOR AN IFF READER!
|
||||
* See ShowILBM.C for a skeletal example.
|
||||
*
|
||||
* Original version was for the Commodore-Amiga computer.
|
||||
/* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#include "iff.h"
|
||||
#include "stdlib.h" //for exit
|
||||
|
||||
/* ---------- IFFCheck -------------------------------------------------*/
|
||||
/* [TBD] More extensive checking could be done on the IDs encountered in the
|
||||
* file. Check that the reserved IDs "FOR1".."FOR9", "LIS1".."LIS9", and
|
||||
* "CAT1".."CAT9" aren't used. Check that reserved IDs aren't used as Form
|
||||
* types. Check that all IDs are made of 4 printable characters (trailing
|
||||
* spaces ok). */
|
||||
|
||||
typedef struct {
|
||||
ClientFrame clientFrame;
|
||||
int levels; /* # groups currently nested within.*/
|
||||
} Frame;
|
||||
|
||||
char MsgOkay[] = { "----- (IFF_OKAY) A good IFF file." };
|
||||
char MsgEndMark[] = {"----- (END_MARK) How did you get this message??" };
|
||||
char MsgDone[] = { "----- (IFF_DONE) How did you get this message??" };
|
||||
char MsgDos[] = { "----- (DOS_ERROR) The DOS gave back an error." };
|
||||
char MsgNot[] = { "----- (NOT_IFF) not an IFF file." };
|
||||
char MsgNoFile[] = { "----- (NO_FILE) no such file found." };
|
||||
char MsgClientError[] = {"----- (CLIENT_ERROR) IFF Checker bug."};
|
||||
char MsgForm[] = { "----- (BAD_FORM) How did you get this message??" };
|
||||
char MsgShort[] = { "----- (SHORT_CHUNK) How did you get this message??" };
|
||||
char MsgBad[] = { "----- (BAD_IFF) a mangled IFF file." };
|
||||
|
||||
/* MUST GET THESE IN RIGHT ORDER!!*/
|
||||
char *IFFPMessages[-LAST_ERROR+1] = {
|
||||
/*IFF_OKAY*/ MsgOkay,
|
||||
/*END_MARK*/ MsgEndMark,
|
||||
/*IFF_DONE*/ MsgDone,
|
||||
/*DOS_ERROR*/ MsgDos,
|
||||
/*NOT_IFF*/ MsgNot,
|
||||
/*NO_FILE*/ MsgNoFile,
|
||||
/*CLIENT_ERROR*/ MsgClientError,
|
||||
/*BAD_FORM*/ MsgForm,
|
||||
/*SHORT_CHUNK*/ MsgShort,
|
||||
/*BAD_IFF*/ MsgBad
|
||||
};
|
||||
|
||||
/* FORWARD REFERENCES */
|
||||
extern IFFP GetList(GroupContext*);
|
||||
extern IFFP GetForm(GroupContext*);
|
||||
extern IFFP GetProp(GroupContext*);
|
||||
extern IFFP GetCat (GroupContext*);
|
||||
|
||||
void IFFCheck(char *name)
|
||||
{
|
||||
IFFP iffp;
|
||||
BPTR file = fopen(name,"rb");//Open(name, MODE_OLDFILE);
|
||||
Frame frame;
|
||||
|
||||
frame.levels = 0;
|
||||
frame.clientFrame.getList = GetList;
|
||||
frame.clientFrame.getForm = GetForm;
|
||||
frame.clientFrame.getProp = GetProp;
|
||||
frame.clientFrame.getCat = GetCat ;
|
||||
|
||||
printf("----- Checking file '%s' -----\n", name);
|
||||
if (file == 0)
|
||||
iffp = NO_FILE;
|
||||
else
|
||||
iffp = ReadIFF(file, (ClientFrame *)&frame);
|
||||
|
||||
fclose(file);
|
||||
printf("%s\n", IFFPMessages[-iffp]);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 1+1) {
|
||||
printf("Usage: 'iffcheck filename'\n");
|
||||
exit(0);
|
||||
}
|
||||
IFFCheck(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------- Put... ---------------------------------------------------*/
|
||||
|
||||
void PutLevels(int count)
|
||||
{
|
||||
for ( ; count > 0; --count) {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
void PutID(int id)
|
||||
{
|
||||
long int i = 1;
|
||||
const char *p = (const char *) &i;
|
||||
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||
{
|
||||
//little endian machine
|
||||
printf("%c%c%c%c ", (char)(id&0x7f) , (char)(id>>8)&0x7f,
|
||||
(char)(id>>16)&0x7f, (char)(id>>24)&0x7f);
|
||||
} else
|
||||
{
|
||||
//big endian machine
|
||||
printf("%c%c%c%c ", (char)(id>>24)&0x7f, (char)(id>>16)&0x7f,
|
||||
(char)(id>>8)&0x7f, (char)(id&0x7f));
|
||||
}
|
||||
/* printf("id = %lx", id); */
|
||||
}
|
||||
|
||||
void PutN(long n)
|
||||
{
|
||||
printf(" %ld ", n);
|
||||
}
|
||||
|
||||
/* Put something like "...BMHD 14" or "...LIST 14 PLBM". */
|
||||
void PutHdr(GroupContext *context)
|
||||
{
|
||||
PutLevels( ((Frame *)context->clientFrame)->levels );
|
||||
PutID(context->ckHdr.ckID);
|
||||
PutN(context->ckHdr.ckSize);
|
||||
|
||||
if (context->subtype != NULL_CHUNK)
|
||||
PutID(context->subtype);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* ---------- AtLeaf ---------------------------------------------------*/
|
||||
|
||||
/* At Leaf chunk. That is, a chunk which does NOT contain other chunks.
|
||||
* Print "int size".*/
|
||||
IFFP AtLeaf(GroupContext *context)
|
||||
{
|
||||
|
||||
PutHdr(context);
|
||||
/* A typical reader would read the chunk's contents, using the "Frame"
|
||||
* for local data, esp. shared property settings (PROP).*/
|
||||
/* IFFReadBytes(context, ...buffer, context->ckHdr->ckSize); */
|
||||
return(IFF_OKAY);
|
||||
}
|
||||
|
||||
/* ---------- GetList --------------------------------------------------*/
|
||||
/* Handle a LIST chunk. Print "LIST size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetList(GroupContext *parent)
|
||||
{
|
||||
Frame newFrame;
|
||||
|
||||
newFrame = *(Frame *)parent->clientFrame; /* copy parent's frame*/
|
||||
newFrame.levels++;
|
||||
|
||||
PutHdr(parent);
|
||||
|
||||
return( ReadIList(parent, (ClientFrame *)&newFrame) );
|
||||
}
|
||||
|
||||
/* ---------- GetForm --------------------------------------------------*/
|
||||
/* Handle a FORM chunk. Print "FORM size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetForm(GroupContext *parent)
|
||||
{
|
||||
/*CompilerBug register*/ IFFP iffp;
|
||||
GroupContext newptr;
|
||||
Frame newFrame;
|
||||
|
||||
newFrame = *(Frame *)parent->clientFrame; /* copy parent's frame*/
|
||||
newFrame.levels++;
|
||||
|
||||
PutHdr(parent);
|
||||
|
||||
iffp = OpenRGroup(parent, &newptr);
|
||||
CheckIFFP();
|
||||
newptr.clientFrame = (ClientFrame *)&newFrame;
|
||||
|
||||
/* FORM reader for Checker. */
|
||||
/* LIST, FORM, PROP, CAT already handled by GetF1ChunkHdr. */
|
||||
do {if ( (iffp = GetF1ChunkHdr(&newptr)) > 0 )
|
||||
iffp = AtLeaf(&newptr);
|
||||
} while (iffp >= IFF_OKAY);
|
||||
|
||||
CloseRGroup(&newptr);
|
||||
return(iffp == END_MARK ? IFF_OKAY : iffp);
|
||||
}
|
||||
|
||||
/* ---------- GetProp --------------------------------------------------*/
|
||||
/* Handle a PROP chunk. Print "PROP size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetProp(GroupContext *listContext)
|
||||
{
|
||||
/*CompilerBug register*/ IFFP iffp;
|
||||
GroupContext newptr;
|
||||
|
||||
PutHdr(listContext);
|
||||
|
||||
iffp = OpenRGroup(listContext, &newptr);
|
||||
CheckIFFP();
|
||||
|
||||
/* PROP reader for Checker. */
|
||||
((Frame *)listContext->clientFrame)->levels++;
|
||||
|
||||
do {if ( (iffp = GetPChunkHdr(&newptr)) > 0 )
|
||||
iffp = AtLeaf(&newptr);
|
||||
} while (iffp >= IFF_OKAY);
|
||||
|
||||
((Frame *)listContext->clientFrame)->levels--;
|
||||
|
||||
CloseRGroup(&newptr);
|
||||
return(iffp == END_MARK ? IFF_OKAY : iffp);
|
||||
}
|
||||
|
||||
/* ---------- GetCat ---------------------------------------------------*/
|
||||
/* Handle a CAT chunk. Print "CAT size subTypeID".
|
||||
* Then dive into it.*/
|
||||
IFFP GetCat(GroupContext *parent)
|
||||
{
|
||||
IFFP iffp;
|
||||
|
||||
((Frame *)parent->clientFrame)->levels++;
|
||||
|
||||
PutHdr(parent);
|
||||
|
||||
iffp = ReadICat(parent);
|
||||
|
||||
((Frame *)parent->clientFrame)->levels--;
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
@@ -1,236 +1,236 @@
|
||||
/*
|
||||
Test read and write IFF-85, Interchange Format File
|
||||
Copyright (c) 2008 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* IFF Support routines for writing IFF-85 files. 12/02/85
|
||||
* (IFF is Interchange Format File.)
|
||||
* By Jerry Morrison and Steve Shaw, Electronic Arts.
|
||||
* This software is in the public domain.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "iff.h"
|
||||
|
||||
IFFP MyReadICat(GroupContext *parent)
|
||||
{
|
||||
printf("Found and skipped a CAT\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IFFP MySkipGroup( GroupContext * )
|
||||
{
|
||||
printf("Found and skipped a LIST\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef UBYTE Masking; /* Choice of masking technique.*/
|
||||
typedef UBYTE Compression; /* Choice of compression algorithm applied to
|
||||
|
||||
/* A BitMapHeader is stored in a BMHD chunk. */
|
||||
typedef struct {
|
||||
|
||||
UWORD w, h; /* raster width & height in pixels */
|
||||
|
||||
WORD x, y; /* position for this image */
|
||||
UBYTE nPlanes; /* # source bitplanes */
|
||||
Masking masking; /* masking technique */
|
||||
Compression compression; /* compression algoithm */
|
||||
UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
|
||||
UWORD transparentColor; /* transparent "color number" */
|
||||
UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
|
||||
WORD pageWidth, pageHeight; /* source "page" size in pixels */
|
||||
|
||||
} BitMapHeader;
|
||||
|
||||
|
||||
#define bufSz 512
|
||||
BYTE bodyBuffer[bufSz];
|
||||
|
||||
static void btSwap(char* a, char* b)
|
||||
{
|
||||
char tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
};
|
||||
|
||||
#define ID_ILBM MakeID('I','L','B','M')
|
||||
#define ID_BMHD MakeID('B','M','H','D')
|
||||
#define ID_CMAP MakeID('C','M','A','P')
|
||||
#define ID_BODY MakeID('B','O','D','Y')
|
||||
|
||||
#define ID_DYNAWORLD MakeID('B','T','D','W')
|
||||
#define ID_RIGIDBODY MakeID('B','T','R','B')
|
||||
#define ID_SID MakeID('S','I','D',' ')
|
||||
#define ID_MASS MakeID('M','A','S','S')
|
||||
#define ID_SHAPE MakeID('S','H','A','P')
|
||||
|
||||
|
||||
#define ID_COLOBJ MakeID('C','O','B','J')
|
||||
#define ID_CUBE MakeID('C','U','B','E')
|
||||
#define ID_DIMENSIONS MakeID('D','I','M','E')
|
||||
|
||||
|
||||
IFFP MyProcessGroup(GroupContext *parent)
|
||||
{
|
||||
/*compilerBug register*/ IFFP iffp;
|
||||
GroupContext rigidbodyContext;
|
||||
|
||||
BitMapHeader bmHeader;
|
||||
bool foundBMHD = false;
|
||||
|
||||
|
||||
if (parent->subtype != ID_ILBM)
|
||||
return(IFF_OKAY); /* just continue scaning the file */
|
||||
|
||||
iffp = OpenRGroup(parent, &rigidbodyContext);
|
||||
CheckIFFP();
|
||||
|
||||
do {
|
||||
iffp = GetFChunkHdr(&rigidbodyContext);
|
||||
if (iffp == ID_BMHD) {
|
||||
printf("found ID_BMHD\n");
|
||||
foundBMHD = true;
|
||||
|
||||
iffp = IFFReadBytes(&rigidbodyContext, (BYTE *)&bmHeader, (long)sizeof(BitMapHeader));
|
||||
//do endian swap
|
||||
bmHeader.w = endianSwap16(bmHeader.w);
|
||||
bmHeader.h = endianSwap16(bmHeader.h);
|
||||
bmHeader.pageWidth = endianSwap16(bmHeader.pageWidth);
|
||||
bmHeader.pageHeight = endianSwap16(bmHeader.pageHeight);
|
||||
}
|
||||
|
||||
else if (iffp == ID_CMAP) {
|
||||
printf("found ID_CMAP\n");
|
||||
|
||||
// ilbmFrame.nColorRegs = maxColorReg; /* we have room for this many */
|
||||
// iffp = GetCMAP(
|
||||
// &rigidbodyContext, (WORD *)&ilbmFrame.colorMap, &ilbmFrame.nColorRegs);
|
||||
}
|
||||
|
||||
else if (iffp == ID_BODY)
|
||||
{
|
||||
printf("found ID_BODY\n");
|
||||
if (!foundBMHD)
|
||||
return BAD_FORM;
|
||||
// if (!ilbmFrame.foundBMHD) return(BAD_FORM); /* No BMHD chunk! */
|
||||
|
||||
int moreBytes = ChunkMoreBytes(&rigidbodyContext);
|
||||
while (moreBytes>0)
|
||||
{
|
||||
int curRead = moreBytes > bufSz? bufSz : moreBytes;
|
||||
//read
|
||||
iffp = IFFReadBytes(&rigidbodyContext, bodyBuffer, curRead);
|
||||
moreBytes -= curRead;
|
||||
|
||||
}
|
||||
printf("remaining=%d\n",moreBytes);
|
||||
if (iffp == IFF_OKAY)
|
||||
iffp = IFF_DONE; /* Eureka */
|
||||
|
||||
|
||||
|
||||
// nPlanes = MIN(ilbmFrame.bmHdr.nPlanes, EXDepth);
|
||||
}
|
||||
|
||||
else if (iffp == END_MARK)
|
||||
iffp = BAD_FORM;
|
||||
|
||||
} while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a
|
||||
* subroutine returned IFF_OKAY (no errors).*/
|
||||
|
||||
if (iffp != IFF_DONE) return(iffp);
|
||||
|
||||
/* If we get this far, there were no errors. */
|
||||
CloseRGroup(&rigidbodyContext);
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CkErr(expression) {if (ifferr == IFF_OKAY) ifferr = (expression);}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
FILE* file = 0;
|
||||
|
||||
{
|
||||
//Create and write an IFF file from scratch
|
||||
file = fopen("test.iff","wb");
|
||||
|
||||
GroupContext fileContext;
|
||||
GroupContext catContext;
|
||||
|
||||
IFFP ifferr=0;
|
||||
|
||||
ifferr = OpenWIFF(file, &fileContext, szNotYetKnown) ;
|
||||
//ifferr = StartWGroup(&fileContext, CAT, szNotYetKnown, ID_DYNAWORLD, &catContext);
|
||||
ifferr = StartWGroup(&fileContext, LIST, szNotYetKnown, ID_DYNAWORLD, &catContext);
|
||||
|
||||
{
|
||||
GroupContext rigidbodyPropContext;
|
||||
ifferr = StartWGroup(&catContext, PROP, szNotYetKnown, ID_MASS, &rigidbodyPropContext);
|
||||
float mass = 0.1f;
|
||||
PutCk(&rigidbodyPropContext, ID_MASS, 4,(char*)&mass);
|
||||
ifferr = EndWGroup(&rigidbodyPropContext) ;
|
||||
|
||||
for (int i=0;i<3;i++)
|
||||
{
|
||||
GroupContext rigidbodyContext;
|
||||
ifferr = StartWGroup(&catContext, FORM, szNotYetKnown, ID_RIGIDBODY, &rigidbodyContext);
|
||||
char sidbuffer[]="rb1";
|
||||
|
||||
float dimensions[3] = {2,2,2};
|
||||
PutCk(&rigidbodyContext, ID_SID, 3,sidbuffer);
|
||||
{
|
||||
GroupContext shapeContext;
|
||||
ifferr = StartWGroup(&rigidbodyContext, FORM, szNotYetKnown, ID_SHAPE, &shapeContext);
|
||||
PutCk(&shapeContext, ID_CUBE, 4,(char*)&mass);
|
||||
PutCk(&shapeContext, ID_DIMENSIONS, sizeof(dimensions),(char*)&dimensions);
|
||||
ifferr = EndWGroup(&shapeContext) ;
|
||||
}
|
||||
ifferr = EndWGroup(&rigidbodyContext) ;
|
||||
}
|
||||
|
||||
}
|
||||
ifferr = EndWGroup(&catContext) ;
|
||||
ifferr = CloseWGroup(&fileContext);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
{
|
||||
//show a very simple way to skim through an ILBM or general IFF file
|
||||
//for more verbose feedback, use iffcheck.c
|
||||
IFFP result;
|
||||
//file = fopen("pe_3000_fall.iff","rb");
|
||||
file = fopen("test.iff","rb");
|
||||
|
||||
ClientFrame clientFrame;
|
||||
|
||||
clientFrame.getList = MySkipGroup;
|
||||
clientFrame.getProp = MySkipGroup;
|
||||
clientFrame.getForm = MyProcessGroup;
|
||||
clientFrame.getCat = MyReadICat ;
|
||||
|
||||
result = ReadIFF(file,&clientFrame);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
Test read and write IFF-85, Interchange Format File
|
||||
Copyright (c) 2008 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* IFF Support routines for writing IFF-85 files. 12/02/85
|
||||
* (IFF is Interchange Format File.)
|
||||
* By Jerry Morrison and Steve Shaw, Electronic Arts.
|
||||
* This software is in the public domain.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "iff.h"
|
||||
|
||||
IFFP MyReadICat(GroupContext *parent)
|
||||
{
|
||||
printf("Found and skipped a CAT\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IFFP MySkipGroup( GroupContext * )
|
||||
{
|
||||
printf("Found and skipped a LIST\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef UBYTE Masking; /* Choice of masking technique.*/
|
||||
typedef UBYTE Compression; /* Choice of compression algorithm applied to
|
||||
|
||||
/* A BitMapHeader is stored in a BMHD chunk. */
|
||||
typedef struct {
|
||||
|
||||
UWORD w, h; /* raster width & height in pixels */
|
||||
|
||||
WORD x, y; /* position for this image */
|
||||
UBYTE nPlanes; /* # source bitplanes */
|
||||
Masking masking; /* masking technique */
|
||||
Compression compression; /* compression algoithm */
|
||||
UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
|
||||
UWORD transparentColor; /* transparent "color number" */
|
||||
UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
|
||||
WORD pageWidth, pageHeight; /* source "page" size in pixels */
|
||||
|
||||
} BitMapHeader;
|
||||
|
||||
|
||||
#define bufSz 512
|
||||
BYTE bodyBuffer[bufSz];
|
||||
|
||||
static void btSwap(char* a, char* b)
|
||||
{
|
||||
char tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
};
|
||||
|
||||
#define ID_ILBM MakeID('I','L','B','M')
|
||||
#define ID_BMHD MakeID('B','M','H','D')
|
||||
#define ID_CMAP MakeID('C','M','A','P')
|
||||
#define ID_BODY MakeID('B','O','D','Y')
|
||||
|
||||
#define ID_DYNAWORLD MakeID('B','T','D','W')
|
||||
#define ID_RIGIDBODY MakeID('B','T','R','B')
|
||||
#define ID_SID MakeID('S','I','D',' ')
|
||||
#define ID_MASS MakeID('M','A','S','S')
|
||||
#define ID_SHAPE MakeID('S','H','A','P')
|
||||
|
||||
|
||||
#define ID_COLOBJ MakeID('C','O','B','J')
|
||||
#define ID_CUBE MakeID('C','U','B','E')
|
||||
#define ID_DIMENSIONS MakeID('D','I','M','E')
|
||||
|
||||
|
||||
IFFP MyProcessGroup(GroupContext *parent)
|
||||
{
|
||||
/*compilerBug register*/ IFFP iffp;
|
||||
GroupContext rigidbodyContext;
|
||||
|
||||
BitMapHeader bmHeader;
|
||||
bool foundBMHD = false;
|
||||
|
||||
|
||||
if (parent->subtype != ID_ILBM)
|
||||
return(IFF_OKAY); /* just continue scaning the file */
|
||||
|
||||
iffp = OpenRGroup(parent, &rigidbodyContext);
|
||||
CheckIFFP();
|
||||
|
||||
do {
|
||||
iffp = GetFChunkHdr(&rigidbodyContext);
|
||||
if (iffp == ID_BMHD) {
|
||||
printf("found ID_BMHD\n");
|
||||
foundBMHD = true;
|
||||
|
||||
iffp = IFFReadBytes(&rigidbodyContext, (BYTE *)&bmHeader, (long)sizeof(BitMapHeader));
|
||||
//do endian swap
|
||||
bmHeader.w = endianSwap16(bmHeader.w);
|
||||
bmHeader.h = endianSwap16(bmHeader.h);
|
||||
bmHeader.pageWidth = endianSwap16(bmHeader.pageWidth);
|
||||
bmHeader.pageHeight = endianSwap16(bmHeader.pageHeight);
|
||||
}
|
||||
|
||||
else if (iffp == ID_CMAP) {
|
||||
printf("found ID_CMAP\n");
|
||||
|
||||
// ilbmFrame.nColorRegs = maxColorReg; /* we have room for this many */
|
||||
// iffp = GetCMAP(
|
||||
// &rigidbodyContext, (WORD *)&ilbmFrame.colorMap, &ilbmFrame.nColorRegs);
|
||||
}
|
||||
|
||||
else if (iffp == ID_BODY)
|
||||
{
|
||||
printf("found ID_BODY\n");
|
||||
if (!foundBMHD)
|
||||
return BAD_FORM;
|
||||
// if (!ilbmFrame.foundBMHD) return(BAD_FORM); /* No BMHD chunk! */
|
||||
|
||||
int moreBytes = ChunkMoreBytes(&rigidbodyContext);
|
||||
while (moreBytes>0)
|
||||
{
|
||||
int curRead = moreBytes > bufSz? bufSz : moreBytes;
|
||||
//read
|
||||
iffp = IFFReadBytes(&rigidbodyContext, bodyBuffer, curRead);
|
||||
moreBytes -= curRead;
|
||||
|
||||
}
|
||||
printf("remaining=%d\n",moreBytes);
|
||||
if (iffp == IFF_OKAY)
|
||||
iffp = IFF_DONE; /* Eureka */
|
||||
|
||||
|
||||
|
||||
// nPlanes = MIN(ilbmFrame.bmHdr.nPlanes, EXDepth);
|
||||
}
|
||||
|
||||
else if (iffp == END_MARK)
|
||||
iffp = BAD_FORM;
|
||||
|
||||
} while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a
|
||||
* subroutine returned IFF_OKAY (no errors).*/
|
||||
|
||||
if (iffp != IFF_DONE) return(iffp);
|
||||
|
||||
/* If we get this far, there were no errors. */
|
||||
CloseRGroup(&rigidbodyContext);
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CkErr(expression) {if (ifferr == IFF_OKAY) ifferr = (expression);}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
FILE* file = 0;
|
||||
|
||||
{
|
||||
//Create and write an IFF file from scratch
|
||||
file = fopen("test.iff","wb");
|
||||
|
||||
GroupContext fileContext;
|
||||
GroupContext catContext;
|
||||
|
||||
IFFP ifferr=0;
|
||||
|
||||
ifferr = OpenWIFF(file, &fileContext, szNotYetKnown) ;
|
||||
//ifferr = StartWGroup(&fileContext, CAT, szNotYetKnown, ID_DYNAWORLD, &catContext);
|
||||
ifferr = StartWGroup(&fileContext, LIST, szNotYetKnown, ID_DYNAWORLD, &catContext);
|
||||
|
||||
{
|
||||
GroupContext rigidbodyPropContext;
|
||||
ifferr = StartWGroup(&catContext, PROP, szNotYetKnown, ID_MASS, &rigidbodyPropContext);
|
||||
float mass = 0.1f;
|
||||
PutCk(&rigidbodyPropContext, ID_MASS, 4,(char*)&mass);
|
||||
ifferr = EndWGroup(&rigidbodyPropContext) ;
|
||||
|
||||
for (int i=0;i<3;i++)
|
||||
{
|
||||
GroupContext rigidbodyContext;
|
||||
ifferr = StartWGroup(&catContext, FORM, szNotYetKnown, ID_RIGIDBODY, &rigidbodyContext);
|
||||
char sidbuffer[]="rb1";
|
||||
|
||||
float dimensions[3] = {2,2,2};
|
||||
PutCk(&rigidbodyContext, ID_SID, 3,sidbuffer);
|
||||
{
|
||||
GroupContext shapeContext;
|
||||
ifferr = StartWGroup(&rigidbodyContext, FORM, szNotYetKnown, ID_SHAPE, &shapeContext);
|
||||
PutCk(&shapeContext, ID_CUBE, 4,(char*)&mass);
|
||||
PutCk(&shapeContext, ID_DIMENSIONS, sizeof(dimensions),(char*)&dimensions);
|
||||
ifferr = EndWGroup(&shapeContext) ;
|
||||
}
|
||||
ifferr = EndWGroup(&rigidbodyContext) ;
|
||||
}
|
||||
|
||||
}
|
||||
ifferr = EndWGroup(&catContext) ;
|
||||
ifferr = CloseWGroup(&fileContext);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
{
|
||||
//show a very simple way to skim through an ILBM or general IFF file
|
||||
//for more verbose feedback, use iffcheck.c
|
||||
IFFP result;
|
||||
//file = fopen("pe_3000_fall.iff","rb");
|
||||
file = fopen("test.iff","rb");
|
||||
|
||||
ClientFrame clientFrame;
|
||||
|
||||
clientFrame.getList = MySkipGroup;
|
||||
clientFrame.getProp = MySkipGroup;
|
||||
clientFrame.getForm = MyProcessGroup;
|
||||
clientFrame.getCat = MyReadICat ;
|
||||
|
||||
result = ReadIFF(file,&clientFrame);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,370 +1,370 @@
|
||||
/*----------------------------------------------------------------------*
|
||||
* IFFR.C Support routines for reading IFF-85 files. 11/15/85
|
||||
* (IFF is Interchange Format File.)
|
||||
*
|
||||
* By Jerry Morrison and Steve Shaw, Electronic Arts.
|
||||
* This software is in the public domain.
|
||||
*
|
||||
* Original version was for the Commodore-Amiga computer.
|
||||
* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#include "iff.h"
|
||||
/* #include "DF1:iff/gio.h" */
|
||||
/* #define OFFSET_BEGINNING OFFSET_BEGINING */
|
||||
|
||||
/** Manx expects INTs as 16 bits, This wont matter on LAttice ***/
|
||||
|
||||
|
||||
|
||||
/* ---------- Read -----------------------------------------------------*/
|
||||
|
||||
extern int PutID(); /** Added as a diagnostic aid, will remove later ***/
|
||||
|
||||
/* ---------- OpenRIFF --------------------------------------------------*/
|
||||
IFFP OpenRIFF(BPTR file0, GroupContext *new0,ClientFrame *clientFrame)
|
||||
{
|
||||
register BPTR file = file0;
|
||||
register GroupContext *newtmp = new0;
|
||||
IFFP iffp = IFF_OKAY;
|
||||
|
||||
newtmp->parent = NL; /* "whole file" has no parent.*/
|
||||
newtmp->clientFrame = clientFrame;
|
||||
newtmp->file = file;
|
||||
newtmp->position = 0;
|
||||
newtmp->ckHdr.ckID = newtmp->subtype = NULL_CHUNK;
|
||||
newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0;
|
||||
|
||||
/* Set newtmp->bound. AmigaDOS specific code.*/
|
||||
if (file <= 0) return(NO_FILE);
|
||||
Seek(file, 0L, OFFSET_END); /* Seek to end of file.*/
|
||||
newtmp->bound = ftell(file);//Seek(file, 0L, OFFSET_CURRENT); /* Pos'n == #bytes in file.*/
|
||||
if (newtmp->bound < 0) return(DOS_ERROR); /* DOS being absurd.*/
|
||||
Seek(file, 0L, OFFSET_BEGINNING); /* Go to file start.*/
|
||||
/* Would just do this if Amiga DOS maintained fh_End: */
|
||||
/* newtmp->bound = (FileHandle *)BADDR(file)->fh_End; */
|
||||
|
||||
if ( newtmp->bound < (long)sizeof(ChunkHeader) )
|
||||
iffp = NOT_IFF;
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- OpenRGroup -----------------------------------------------*/
|
||||
IFFP OpenRGroup(GroupContext* parent0,GroupContext* new0)
|
||||
{
|
||||
register GroupContext *parent = parent0;
|
||||
register GroupContext *newtmp = new0;
|
||||
IFFP iffp = IFF_OKAY;
|
||||
|
||||
newtmp->parent = parent;
|
||||
newtmp->clientFrame = parent->clientFrame;
|
||||
newtmp->file = parent->file;
|
||||
newtmp->position = parent->position;
|
||||
newtmp->bound = parent->position + ChunkMoreBytes(parent);
|
||||
newtmp->ckHdr.ckID = newtmp->subtype = NULL_CHUNK;
|
||||
newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0;
|
||||
|
||||
if ( newtmp->bound > parent->bound || IS_ODD(newtmp->bound) )
|
||||
iffp = BAD_IFF;
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- CloseRGroup -----------------------------------------------*/
|
||||
IFFP CloseRGroup(GroupContext *context)
|
||||
{
|
||||
register int position;
|
||||
|
||||
if (context->parent == NL) {
|
||||
} /* Context for whole file.*/
|
||||
else {
|
||||
position = context->position;
|
||||
context->parent->bytesSoFar += position - context->parent->position;
|
||||
context->parent->position = position;
|
||||
}
|
||||
return(IFF_OKAY);
|
||||
}
|
||||
|
||||
/* ---------- SkipFwd --------------------------------------------------*/
|
||||
/* Skip over bytes in a context. Won't go backwards.*/
|
||||
/* Updates context->position but not context->bytesSoFar.*/
|
||||
/* This implementation is AmigaDOS specific.*/
|
||||
IFFP SkipFwd(GroupContext *context,int bytes)
|
||||
{
|
||||
IFFP iffp = IFF_OKAY;
|
||||
|
||||
if (bytes > 0) {
|
||||
if (-1 == Seek(context->file, bytes, OFFSET_CURRENT))
|
||||
iffp = BAD_IFF; /* Ran out of bytes before chunk complete.*/
|
||||
else
|
||||
context->position += bytes;
|
||||
}
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
short int endianSwap16(short int val)
|
||||
{
|
||||
long int i = 1;
|
||||
const char *p = (const char *) &i;
|
||||
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||
{
|
||||
return (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int endianSwap32(int val)
|
||||
{
|
||||
long int i = 1;
|
||||
const char *p = (const char *) &i;
|
||||
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||
{
|
||||
return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ---------- GetChunkHdr ----------------------------------------------*/
|
||||
int GetChunkHdr(GroupContext *context0)
|
||||
{
|
||||
register GroupContext *context = context0;
|
||||
register IFFP iffp;
|
||||
int remaining;
|
||||
|
||||
/* Skip remainder of previous chunk & padding. */
|
||||
iffp = SkipFwd(context,
|
||||
ChunkMoreBytes(context) + IS_ODD(context->ckHdr.ckSize));
|
||||
CheckIFFP();
|
||||
|
||||
/* Set up to read the newtmp header. */
|
||||
context->ckHdr.ckID = BAD_IFF; /* Until we know it's okay, mark it BAD.*/
|
||||
context->subtype = NULL_CHUNK;
|
||||
context->bytesSoFar = 0;
|
||||
|
||||
/* Generate a psuedo-chunk if at end-of-context. */
|
||||
remaining = context->bound - context->position;
|
||||
if (remaining == 0 ) {
|
||||
context->ckHdr.ckSize = 0;
|
||||
context->ckHdr.ckID = END_MARK;
|
||||
}
|
||||
/* BAD_IFF if not enough bytes in the context for a ChunkHeader.*/
|
||||
else if ((long)sizeof(ChunkHeader) > remaining) {
|
||||
context->ckHdr.ckSize = remaining;
|
||||
}
|
||||
|
||||
/* Read the chunk header (finally). */
|
||||
else {
|
||||
switch (Read(context->file,
|
||||
&context->ckHdr, (long)sizeof(ChunkHeader)))
|
||||
{
|
||||
case -1: return(context->ckHdr.ckID = DOS_ERROR);
|
||||
case 0: return(context->ckHdr.ckID = BAD_IFF);
|
||||
}
|
||||
//swap endian-ness of ckSize on little endian machines
|
||||
context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize);
|
||||
|
||||
|
||||
|
||||
|
||||
/*** $$$ ***
|
||||
PutID(context->ckHdr.ckID);
|
||||
printf("\n");
|
||||
printf("id = %lx\n", context->ckHdr.ckID);
|
||||
**/
|
||||
|
||||
/* Check: Top level chunk must be LIST or FORM or CAT. */
|
||||
if (context->parent == NL) {
|
||||
if (context->ckHdr.ckID != FORM &&
|
||||
context->ckHdr.ckID != LIST &&
|
||||
context->ckHdr.ckID != CAT )
|
||||
return(context->ckHdr.ckID = NOT_IFF);
|
||||
}
|
||||
|
||||
/* Update the context. */
|
||||
context->position += (long)sizeof(ChunkHeader);
|
||||
remaining -= (long)sizeof(ChunkHeader);
|
||||
|
||||
/* Non-positive int values are illegal and used for error codes.*/
|
||||
/* We could check for other illegal IDs...*/
|
||||
if (context->ckHdr.ckID <= 0 )
|
||||
context->ckHdr.ckID = BAD_IFF;
|
||||
|
||||
/* Check: ckSize negative or larger than # bytes left in context? */
|
||||
else if (context->ckHdr.ckSize < 0 ||
|
||||
context->ckHdr.ckSize > remaining) {
|
||||
context->ckHdr.ckSize = remaining;
|
||||
context->ckHdr.ckID = BAD_IFF;
|
||||
}
|
||||
|
||||
/* Automatically read the LIST, FORM, PROP, or CAT subtype int */
|
||||
else {
|
||||
if (context->ckHdr.ckID == LIST ||
|
||||
context->ckHdr.ckID == FORM ||
|
||||
context->ckHdr.ckID == PROP ||
|
||||
context->ckHdr.ckID == CAT) {
|
||||
iffp = IFFReadBytes(context, (BYTE *)&context->subtype,
|
||||
(long)sizeof(int));
|
||||
if (iffp != IFF_OKAY )
|
||||
context->ckHdr.ckID = iffp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(context->ckHdr.ckID);
|
||||
}
|
||||
|
||||
/* ---------- IFFReadBytes ---------------------------------------------*/
|
||||
IFFP IFFReadBytes(GroupContext *context,BYTE *buffer, int nBytes)
|
||||
{
|
||||
register IFFP iffp = IFF_OKAY;
|
||||
|
||||
if (nBytes < 0)
|
||||
iffp = CLIENT_ERROR;
|
||||
|
||||
else if (nBytes > ChunkMoreBytes(context))
|
||||
iffp = SHORT_CHUNK;
|
||||
|
||||
else if (nBytes > 0 )
|
||||
switch ( Read(context->file, buffer, nBytes) ) {
|
||||
case -1: {iffp = DOS_ERROR; break; }
|
||||
case 0: {iffp = BAD_IFF; break; }
|
||||
default: {
|
||||
context->position += nBytes;
|
||||
context->bytesSoFar += nBytes;
|
||||
}
|
||||
}
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- SkipGroup ------------------------------------------------*/
|
||||
IFFP SkipGroup( GroupContext* context)
|
||||
{
|
||||
return 0;
|
||||
} /* Nothing to do, thanks to GetChunkHdr */
|
||||
|
||||
/* ---------- ReadIFF --------------------------------------------------*/
|
||||
IFFP ReadIFF(BPTR file,ClientFrame *clientFrame)
|
||||
{
|
||||
/*CompilerBug register*/ IFFP iffp;
|
||||
GroupContext context;
|
||||
|
||||
iffp = OpenRIFF(file, &context,clientFrame);
|
||||
context.clientFrame = clientFrame;
|
||||
|
||||
if (iffp == IFF_OKAY) {
|
||||
iffp = GetChunkHdr(&context);
|
||||
|
||||
if (iffp == FORM)
|
||||
iffp = (*clientFrame->getForm)(&context);
|
||||
|
||||
else if (iffp == LIST)
|
||||
iffp = (*clientFrame->getList)(&context);
|
||||
|
||||
else if (iffp == CAT)
|
||||
iffp = (*clientFrame->getCat)(&context);
|
||||
}
|
||||
CloseRGroup(&context);
|
||||
|
||||
if (iffp > 0 ) /* Make sure we don't return an int.*/
|
||||
iffp = NOT_IFF; /* GetChunkHdr should've caught this.*/
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- ReadIList ------------------------------------------------*/
|
||||
IFFP ReadIList(GroupContext *parent,ClientFrame *clientFrame)
|
||||
{
|
||||
GroupContext listContext;
|
||||
IFFP iffp;
|
||||
BOOL propOk = TRUE;
|
||||
|
||||
iffp = OpenRGroup(parent, &listContext);
|
||||
CheckIFFP();
|
||||
|
||||
/* One special case test lets us handle CATs as well as LISTs.*/
|
||||
if (parent->ckHdr.ckID == CAT)
|
||||
propOk = FALSE;
|
||||
else
|
||||
listContext.clientFrame = clientFrame;
|
||||
|
||||
do {
|
||||
iffp = GetChunkHdr(&listContext);
|
||||
if (iffp == PROP) {
|
||||
if (propOk)
|
||||
iffp = (*clientFrame->getProp)(&listContext);
|
||||
else
|
||||
iffp = BAD_IFF;
|
||||
}
|
||||
else if (iffp == FORM)
|
||||
iffp = (*clientFrame->getForm)(&listContext);
|
||||
|
||||
else if (iffp == LIST)
|
||||
iffp = (*clientFrame->getList)(&listContext);
|
||||
|
||||
else if (iffp == CAT)
|
||||
iffp = (*clientFrame->getList)(&listContext);
|
||||
|
||||
if (listContext.ckHdr.ckID != PROP)
|
||||
propOk = FALSE; /* No PROPs allowed after this point.*/
|
||||
} while (iffp == IFF_OKAY);
|
||||
|
||||
CloseRGroup(&listContext);
|
||||
|
||||
if (iffp > 0 ) /* Only chunk types above are allowed in a LIST/CAT.*/
|
||||
iffp = BAD_IFF;
|
||||
return(iffp == END_MARK ? IFF_OKAY : iffp);
|
||||
}
|
||||
|
||||
/* ---------- ReadICat -------------------------------------------------*/
|
||||
/* By special arrangement with the ReadIList implement'n, this is trivial.*/
|
||||
IFFP ReadICat(GroupContext *parent)
|
||||
{
|
||||
return( ReadIList(parent, parent->clientFrame));//NL) );
|
||||
}
|
||||
|
||||
/* ---------- GetFChunkHdr ---------------------------------------------*/
|
||||
int GetFChunkHdr(GroupContext *context)
|
||||
{
|
||||
register int id;
|
||||
|
||||
id = GetChunkHdr(context);
|
||||
if (id == PROP)
|
||||
context->ckHdr.ckID = id = BAD_IFF;
|
||||
return(id);
|
||||
}
|
||||
|
||||
/* ---------- GetF1ChunkHdr ---------------------------------------------*/
|
||||
int GetF1ChunkHdr(GroupContext *context)
|
||||
{
|
||||
register int id;
|
||||
register ClientFrame *clientFrame = context->clientFrame;
|
||||
|
||||
id = GetChunkHdr(context);
|
||||
if (id == PROP)
|
||||
id = BAD_IFF;
|
||||
|
||||
else if (id == FORM)
|
||||
id = (*clientFrame->getForm)(context);
|
||||
|
||||
else if (id == LIST)
|
||||
id = (*clientFrame->getForm)(context);
|
||||
|
||||
else if (id == CAT)
|
||||
id = (*clientFrame->getCat)(context);
|
||||
|
||||
return(context->ckHdr.ckID = id);
|
||||
}
|
||||
|
||||
/* ---------- GetPChunkHdr ---------------------------------------------*/
|
||||
int GetPChunkHdr(GroupContext *context)
|
||||
{
|
||||
register int id;
|
||||
|
||||
id = GetChunkHdr(context);
|
||||
if (id == LIST || id == FORM || id == PROP || id == CAT )
|
||||
id = context->ckHdr.ckID = BAD_IFF;
|
||||
return(id);
|
||||
}
|
||||
/*----------------------------------------------------------------------*
|
||||
* IFFR.C Support routines for reading IFF-85 files. 11/15/85
|
||||
* (IFF is Interchange Format File.)
|
||||
*
|
||||
* By Jerry Morrison and Steve Shaw, Electronic Arts.
|
||||
* This software is in the public domain.
|
||||
*
|
||||
* Original version was for the Commodore-Amiga computer.
|
||||
* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#include "iff.h"
|
||||
/* #include "DF1:iff/gio.h" */
|
||||
/* #define OFFSET_BEGINNING OFFSET_BEGINING */
|
||||
|
||||
/** Manx expects INTs as 16 bits, This wont matter on LAttice ***/
|
||||
|
||||
|
||||
|
||||
/* ---------- Read -----------------------------------------------------*/
|
||||
|
||||
extern int PutID(); /** Added as a diagnostic aid, will remove later ***/
|
||||
|
||||
/* ---------- OpenRIFF --------------------------------------------------*/
|
||||
IFFP OpenRIFF(BPTR file0, GroupContext *new0,ClientFrame *clientFrame)
|
||||
{
|
||||
register BPTR file = file0;
|
||||
register GroupContext *newtmp = new0;
|
||||
IFFP iffp = IFF_OKAY;
|
||||
|
||||
newtmp->parent = NL; /* "whole file" has no parent.*/
|
||||
newtmp->clientFrame = clientFrame;
|
||||
newtmp->file = file;
|
||||
newtmp->position = 0;
|
||||
newtmp->ckHdr.ckID = newtmp->subtype = NULL_CHUNK;
|
||||
newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0;
|
||||
|
||||
/* Set newtmp->bound. AmigaDOS specific code.*/
|
||||
if (file <= 0) return(NO_FILE);
|
||||
Seek(file, 0L, OFFSET_END); /* Seek to end of file.*/
|
||||
newtmp->bound = ftell(file);//Seek(file, 0L, OFFSET_CURRENT); /* Pos'n == #bytes in file.*/
|
||||
if (newtmp->bound < 0) return(DOS_ERROR); /* DOS being absurd.*/
|
||||
Seek(file, 0L, OFFSET_BEGINNING); /* Go to file start.*/
|
||||
/* Would just do this if Amiga DOS maintained fh_End: */
|
||||
/* newtmp->bound = (FileHandle *)BADDR(file)->fh_End; */
|
||||
|
||||
if ( newtmp->bound < (long)sizeof(ChunkHeader) )
|
||||
iffp = NOT_IFF;
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- OpenRGroup -----------------------------------------------*/
|
||||
IFFP OpenRGroup(GroupContext* parent0,GroupContext* new0)
|
||||
{
|
||||
register GroupContext *parent = parent0;
|
||||
register GroupContext *newtmp = new0;
|
||||
IFFP iffp = IFF_OKAY;
|
||||
|
||||
newtmp->parent = parent;
|
||||
newtmp->clientFrame = parent->clientFrame;
|
||||
newtmp->file = parent->file;
|
||||
newtmp->position = parent->position;
|
||||
newtmp->bound = parent->position + ChunkMoreBytes(parent);
|
||||
newtmp->ckHdr.ckID = newtmp->subtype = NULL_CHUNK;
|
||||
newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0;
|
||||
|
||||
if ( newtmp->bound > parent->bound || IS_ODD(newtmp->bound) )
|
||||
iffp = BAD_IFF;
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- CloseRGroup -----------------------------------------------*/
|
||||
IFFP CloseRGroup(GroupContext *context)
|
||||
{
|
||||
register int position;
|
||||
|
||||
if (context->parent == NL) {
|
||||
} /* Context for whole file.*/
|
||||
else {
|
||||
position = context->position;
|
||||
context->parent->bytesSoFar += position - context->parent->position;
|
||||
context->parent->position = position;
|
||||
}
|
||||
return(IFF_OKAY);
|
||||
}
|
||||
|
||||
/* ---------- SkipFwd --------------------------------------------------*/
|
||||
/* Skip over bytes in a context. Won't go backwards.*/
|
||||
/* Updates context->position but not context->bytesSoFar.*/
|
||||
/* This implementation is AmigaDOS specific.*/
|
||||
IFFP SkipFwd(GroupContext *context,int bytes)
|
||||
{
|
||||
IFFP iffp = IFF_OKAY;
|
||||
|
||||
if (bytes > 0) {
|
||||
if (-1 == Seek(context->file, bytes, OFFSET_CURRENT))
|
||||
iffp = BAD_IFF; /* Ran out of bytes before chunk complete.*/
|
||||
else
|
||||
context->position += bytes;
|
||||
}
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
short int endianSwap16(short int val)
|
||||
{
|
||||
long int i = 1;
|
||||
const char *p = (const char *) &i;
|
||||
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||
{
|
||||
return (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int endianSwap32(int val)
|
||||
{
|
||||
long int i = 1;
|
||||
const char *p = (const char *) &i;
|
||||
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||
{
|
||||
return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ---------- GetChunkHdr ----------------------------------------------*/
|
||||
int GetChunkHdr(GroupContext *context0)
|
||||
{
|
||||
register GroupContext *context = context0;
|
||||
register IFFP iffp;
|
||||
int remaining;
|
||||
|
||||
/* Skip remainder of previous chunk & padding. */
|
||||
iffp = SkipFwd(context,
|
||||
ChunkMoreBytes(context) + IS_ODD(context->ckHdr.ckSize));
|
||||
CheckIFFP();
|
||||
|
||||
/* Set up to read the newtmp header. */
|
||||
context->ckHdr.ckID = BAD_IFF; /* Until we know it's okay, mark it BAD.*/
|
||||
context->subtype = NULL_CHUNK;
|
||||
context->bytesSoFar = 0;
|
||||
|
||||
/* Generate a psuedo-chunk if at end-of-context. */
|
||||
remaining = context->bound - context->position;
|
||||
if (remaining == 0 ) {
|
||||
context->ckHdr.ckSize = 0;
|
||||
context->ckHdr.ckID = END_MARK;
|
||||
}
|
||||
/* BAD_IFF if not enough bytes in the context for a ChunkHeader.*/
|
||||
else if ((long)sizeof(ChunkHeader) > remaining) {
|
||||
context->ckHdr.ckSize = remaining;
|
||||
}
|
||||
|
||||
/* Read the chunk header (finally). */
|
||||
else {
|
||||
switch (Read(context->file,
|
||||
&context->ckHdr, (long)sizeof(ChunkHeader)))
|
||||
{
|
||||
case -1: return(context->ckHdr.ckID = DOS_ERROR);
|
||||
case 0: return(context->ckHdr.ckID = BAD_IFF);
|
||||
}
|
||||
//swap endian-ness of ckSize on little endian machines
|
||||
context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize);
|
||||
|
||||
|
||||
|
||||
|
||||
/*** $$$ ***
|
||||
PutID(context->ckHdr.ckID);
|
||||
printf("\n");
|
||||
printf("id = %lx\n", context->ckHdr.ckID);
|
||||
**/
|
||||
|
||||
/* Check: Top level chunk must be LIST or FORM or CAT. */
|
||||
if (context->parent == NL) {
|
||||
if (context->ckHdr.ckID != FORM &&
|
||||
context->ckHdr.ckID != LIST &&
|
||||
context->ckHdr.ckID != CAT )
|
||||
return(context->ckHdr.ckID = NOT_IFF);
|
||||
}
|
||||
|
||||
/* Update the context. */
|
||||
context->position += (long)sizeof(ChunkHeader);
|
||||
remaining -= (long)sizeof(ChunkHeader);
|
||||
|
||||
/* Non-positive int values are illegal and used for error codes.*/
|
||||
/* We could check for other illegal IDs...*/
|
||||
if (context->ckHdr.ckID <= 0 )
|
||||
context->ckHdr.ckID = BAD_IFF;
|
||||
|
||||
/* Check: ckSize negative or larger than # bytes left in context? */
|
||||
else if (context->ckHdr.ckSize < 0 ||
|
||||
context->ckHdr.ckSize > remaining) {
|
||||
context->ckHdr.ckSize = remaining;
|
||||
context->ckHdr.ckID = BAD_IFF;
|
||||
}
|
||||
|
||||
/* Automatically read the LIST, FORM, PROP, or CAT subtype int */
|
||||
else {
|
||||
if (context->ckHdr.ckID == LIST ||
|
||||
context->ckHdr.ckID == FORM ||
|
||||
context->ckHdr.ckID == PROP ||
|
||||
context->ckHdr.ckID == CAT) {
|
||||
iffp = IFFReadBytes(context, (BYTE *)&context->subtype,
|
||||
(long)sizeof(int));
|
||||
if (iffp != IFF_OKAY )
|
||||
context->ckHdr.ckID = iffp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(context->ckHdr.ckID);
|
||||
}
|
||||
|
||||
/* ---------- IFFReadBytes ---------------------------------------------*/
|
||||
IFFP IFFReadBytes(GroupContext *context,BYTE *buffer, int nBytes)
|
||||
{
|
||||
register IFFP iffp = IFF_OKAY;
|
||||
|
||||
if (nBytes < 0)
|
||||
iffp = CLIENT_ERROR;
|
||||
|
||||
else if (nBytes > ChunkMoreBytes(context))
|
||||
iffp = SHORT_CHUNK;
|
||||
|
||||
else if (nBytes > 0 )
|
||||
switch ( Read(context->file, buffer, nBytes) ) {
|
||||
case -1: {iffp = DOS_ERROR; break; }
|
||||
case 0: {iffp = BAD_IFF; break; }
|
||||
default: {
|
||||
context->position += nBytes;
|
||||
context->bytesSoFar += nBytes;
|
||||
}
|
||||
}
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- SkipGroup ------------------------------------------------*/
|
||||
IFFP SkipGroup( GroupContext* context)
|
||||
{
|
||||
return 0;
|
||||
} /* Nothing to do, thanks to GetChunkHdr */
|
||||
|
||||
/* ---------- ReadIFF --------------------------------------------------*/
|
||||
IFFP ReadIFF(BPTR file,ClientFrame *clientFrame)
|
||||
{
|
||||
/*CompilerBug register*/ IFFP iffp;
|
||||
GroupContext context;
|
||||
|
||||
iffp = OpenRIFF(file, &context,clientFrame);
|
||||
context.clientFrame = clientFrame;
|
||||
|
||||
if (iffp == IFF_OKAY) {
|
||||
iffp = GetChunkHdr(&context);
|
||||
|
||||
if (iffp == FORM)
|
||||
iffp = (*clientFrame->getForm)(&context);
|
||||
|
||||
else if (iffp == LIST)
|
||||
iffp = (*clientFrame->getList)(&context);
|
||||
|
||||
else if (iffp == CAT)
|
||||
iffp = (*clientFrame->getCat)(&context);
|
||||
}
|
||||
CloseRGroup(&context);
|
||||
|
||||
if (iffp > 0 ) /* Make sure we don't return an int.*/
|
||||
iffp = NOT_IFF; /* GetChunkHdr should've caught this.*/
|
||||
return(iffp);
|
||||
}
|
||||
|
||||
/* ---------- ReadIList ------------------------------------------------*/
|
||||
IFFP ReadIList(GroupContext *parent,ClientFrame *clientFrame)
|
||||
{
|
||||
GroupContext listContext;
|
||||
IFFP iffp;
|
||||
BOOL propOk = TRUE;
|
||||
|
||||
iffp = OpenRGroup(parent, &listContext);
|
||||
CheckIFFP();
|
||||
|
||||
/* One special case test lets us handle CATs as well as LISTs.*/
|
||||
if (parent->ckHdr.ckID == CAT)
|
||||
propOk = FALSE;
|
||||
else
|
||||
listContext.clientFrame = clientFrame;
|
||||
|
||||
do {
|
||||
iffp = GetChunkHdr(&listContext);
|
||||
if (iffp == PROP) {
|
||||
if (propOk)
|
||||
iffp = (*clientFrame->getProp)(&listContext);
|
||||
else
|
||||
iffp = BAD_IFF;
|
||||
}
|
||||
else if (iffp == FORM)
|
||||
iffp = (*clientFrame->getForm)(&listContext);
|
||||
|
||||
else if (iffp == LIST)
|
||||
iffp = (*clientFrame->getList)(&listContext);
|
||||
|
||||
else if (iffp == CAT)
|
||||
iffp = (*clientFrame->getList)(&listContext);
|
||||
|
||||
if (listContext.ckHdr.ckID != PROP)
|
||||
propOk = FALSE; /* No PROPs allowed after this point.*/
|
||||
} while (iffp == IFF_OKAY);
|
||||
|
||||
CloseRGroup(&listContext);
|
||||
|
||||
if (iffp > 0 ) /* Only chunk types above are allowed in a LIST/CAT.*/
|
||||
iffp = BAD_IFF;
|
||||
return(iffp == END_MARK ? IFF_OKAY : iffp);
|
||||
}
|
||||
|
||||
/* ---------- ReadICat -------------------------------------------------*/
|
||||
/* By special arrangement with the ReadIList implement'n, this is trivial.*/
|
||||
IFFP ReadICat(GroupContext *parent)
|
||||
{
|
||||
return( ReadIList(parent, parent->clientFrame));//NL) );
|
||||
}
|
||||
|
||||
/* ---------- GetFChunkHdr ---------------------------------------------*/
|
||||
int GetFChunkHdr(GroupContext *context)
|
||||
{
|
||||
register int id;
|
||||
|
||||
id = GetChunkHdr(context);
|
||||
if (id == PROP)
|
||||
context->ckHdr.ckID = id = BAD_IFF;
|
||||
return(id);
|
||||
}
|
||||
|
||||
/* ---------- GetF1ChunkHdr ---------------------------------------------*/
|
||||
int GetF1ChunkHdr(GroupContext *context)
|
||||
{
|
||||
register int id;
|
||||
register ClientFrame *clientFrame = context->clientFrame;
|
||||
|
||||
id = GetChunkHdr(context);
|
||||
if (id == PROP)
|
||||
id = BAD_IFF;
|
||||
|
||||
else if (id == FORM)
|
||||
id = (*clientFrame->getForm)(context);
|
||||
|
||||
else if (id == LIST)
|
||||
id = (*clientFrame->getForm)(context);
|
||||
|
||||
else if (id == CAT)
|
||||
id = (*clientFrame->getCat)(context);
|
||||
|
||||
return(context->ckHdr.ckID = id);
|
||||
}
|
||||
|
||||
/* ---------- GetPChunkHdr ---------------------------------------------*/
|
||||
int GetPChunkHdr(GroupContext *context)
|
||||
{
|
||||
register int id;
|
||||
|
||||
id = GetChunkHdr(context);
|
||||
if (id == LIST || id == FORM || id == PROP || id == CAT )
|
||||
id = context->ckHdr.ckID = BAD_IFF;
|
||||
return(id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user