453 lines
9.5 KiB
C++
453 lines
9.5 KiB
C++
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ ³
|
|
³ IA - Deluxe Paint 3 Animation player ³
|
|
³ ³
|
|
³ NIFF.CPP ³
|
|
³ ³
|
|
³ Written by Gary Liddon 27 May 1991 ³
|
|
³ Modified by Carl Muller 30 Oct 1991 ³
|
|
³ ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
|
|
|
|
#include "stdio.h"
|
|
#include "conio.h"
|
|
|
|
#include "niff.hpp"
|
|
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ IFF error messages ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
|
|
char *niff_error_text[] =
|
|
{
|
|
NULL,
|
|
"Error opening IFF file",
|
|
"Not an IFF file",
|
|
"Can't find FORM",
|
|
"Can't find HUNK",
|
|
"Corrupted bit map header in picture file",
|
|
"Can't find BODY",
|
|
"All out of memory",
|
|
"Mangled IFF file",
|
|
"Can't find CMAP",
|
|
"No ILBM's yet",
|
|
"Error with passed IFF file",
|
|
"Error with ILBM in ANIM",
|
|
"Not aksed for FORM type",
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Create an IFF descriptor from a filename ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
niff::niff(char const *name, U32 form)
|
|
{
|
|
form_mounted = FALSE;
|
|
err_no = NO_ERROR;
|
|
|
|
file_opened = FALSE;
|
|
fp = NULL;
|
|
passed_file = FALSE;
|
|
|
|
if (name)
|
|
open(name,form);
|
|
|
|
}
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Create an IFF descriptor from a file pointer ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
niff::niff(FILE * new_file, U32 form)
|
|
{
|
|
form_mounted = FALSE;
|
|
err_no = NO_ERROR;
|
|
file_opened = TRUE; // File pre-opened
|
|
|
|
fp = new_file;
|
|
iff_base = ftell(fp); // Get base pos
|
|
passed_file = TRUE; // This is a passed file
|
|
|
|
if (!mount_form(form))
|
|
err_no = PASSED_ERR;
|
|
}
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Open an IFF file for reading ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
BOOL niff::open(char const *name, U32 form)
|
|
{
|
|
if (passed_file) // Passed files can't be re-opened
|
|
{
|
|
err_no = OPEN_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if (file_opened) // Already open so don't bother
|
|
{
|
|
err_no = OPEN_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(fp = fopen(name,"rb")))
|
|
{
|
|
err_no = OPEN_ERROR;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!mount_form(form)) // Mount this form
|
|
{
|
|
fclose(fp);
|
|
if (!err_no)
|
|
err_no = NOT_FORM;
|
|
return FALSE;
|
|
}
|
|
|
|
iff_base = 0L; // Set position to zero
|
|
file_opened = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Read an IFF hunk into memory ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
U8 *niff::get_hunk()
|
|
{
|
|
if ((!file_opened) && (!form_mounted))
|
|
return NULL;
|
|
|
|
U8 *hunk=NULL;
|
|
long name,len,temp;
|
|
|
|
temp = ftell(fp);
|
|
|
|
fread(&name, 1, sizeof(U32), fp);
|
|
fread(&len, 1, sizeof(U32), fp);
|
|
|
|
len = rev_long(len);
|
|
|
|
|
|
hunk = new U8[len];
|
|
|
|
splen = len;
|
|
|
|
if (hunk)
|
|
fread(hunk,1,len,fp);
|
|
|
|
fseek(fp,temp,SEEK_SET);
|
|
|
|
return hunk;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Reset to beginning of form ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
void niff::goto_form_start()
|
|
{
|
|
fseek(fp, form_start, SEEK_SET);
|
|
}
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Mount form at filepos ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
BOOL niff::mount_form(U32 form)
|
|
{
|
|
form_mounted=FALSE;
|
|
U32 temp,temp_name; // Check to see if we've an iff
|
|
|
|
if (fread(&temp,sizeof(U32),1,fp) != 1)
|
|
{
|
|
err_no= MANGLED_IFF;
|
|
return(false);
|
|
}
|
|
|
|
if (temp != FORM) // We haven't.
|
|
return FALSE;
|
|
|
|
fread(&temp,1,sizeof(U32),fp);
|
|
form_end = full_len(temp)+ftell(fp);
|
|
|
|
fread (&temp_name,1,sizeof(U32),fp);
|
|
|
|
if (form) // Are we checking for a specific
|
|
{ // form?
|
|
if (temp_name != form)
|
|
return FALSE;
|
|
}
|
|
|
|
form_name=temp_name;
|
|
form_start=ftell(fp);
|
|
form_mounted=TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Goto a hunk ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
BOOL niff::goto_hunk(U32 form)
|
|
{
|
|
U32 len, namer;
|
|
|
|
if ((!form_mounted) || (!file_opened))
|
|
return FALSE;
|
|
|
|
goto_form_start();
|
|
fread(&namer, 1, sizeof(U32), fp);
|
|
fread(&len, 1, sizeof(U32), fp);
|
|
|
|
goto_form_start();
|
|
|
|
if (namer == form)
|
|
return TRUE;
|
|
|
|
return next_hunk(form);
|
|
}
|
|
|
|
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Get the number of hunks of a certain name in this file
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
int niff::GetNumOfHunks(U32 FormName)
|
|
{
|
|
int NumOfHunks=0;
|
|
|
|
if (goto_hunk(FormName))
|
|
{
|
|
do
|
|
{
|
|
NumOfHunks++;
|
|
}
|
|
while (next_hunk(FormName));
|
|
}
|
|
|
|
return NumOfHunks;
|
|
}
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Goto next hunk in current form ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
BOOL niff::next_hunk(U32 form)
|
|
{
|
|
if ((!form_mounted) || (!file_opened))
|
|
return FALSE;
|
|
|
|
U32 temp = ftell(fp);
|
|
long len;
|
|
U32 name = 0L;
|
|
BOOL found = FALSE;
|
|
|
|
fread(&name, 1, sizeof(U32), fp);
|
|
fread(&len, 1, sizeof(U32), fp);
|
|
|
|
while ((ftell(fp) < form_end) && (!found))
|
|
{
|
|
fseek(fp, full_len(len), SEEK_CUR);
|
|
fread(&name, 1, sizeof(U32), fp);
|
|
fread(&len, 1, sizeof(U32), fp);
|
|
|
|
if (form)
|
|
{
|
|
if (form == name)
|
|
found = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (form != FORM)
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
if (found && (ftell(fp) < form_end))
|
|
{
|
|
fseek(fp, -8L, SEEK_CUR);
|
|
return TRUE;
|
|
}
|
|
|
|
fseek(fp, temp, SEEK_SET);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Goto Next form in current form ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
BOOL niff::next_form(U32 form)
|
|
{
|
|
if ((!form_mounted) || (!file_opened))
|
|
return FALSE;
|
|
|
|
U32 len;
|
|
U32 name = 0L;
|
|
U32 fname = 0L;
|
|
BOOL found=FALSE;
|
|
|
|
fread(&name, 1, sizeof(U32), fp);
|
|
fread(&len, 1, sizeof(U32), fp);
|
|
|
|
do {
|
|
fseek(fp, full_len(len), SEEK_CUR);
|
|
|
|
fread(&name, 1, sizeof(U32), fp);
|
|
fread(&len, 1, sizeof(U32), fp);
|
|
|
|
if (name == FORM)
|
|
{
|
|
fread(&fname, 1, sizeof(U32), fp);
|
|
if (!form)
|
|
found = TRUE;
|
|
else if (form == fname)
|
|
found = TRUE;
|
|
len -= 4L;
|
|
}
|
|
} while (!found && (ftell(fp) < form_end));
|
|
|
|
if (found) // If we got what we wanted
|
|
{ // then seek back to start of
|
|
fseek(fp, -12L, SEEK_CUR); // header and flag success
|
|
return TRUE;
|
|
}
|
|
|
|
goto_form_start(); // Else back to start of form
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Close an IFF file ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
BOOL niff::close()
|
|
{
|
|
if (passed_file || (!file_opened)) // Passed or unopened files
|
|
return FALSE; // can't be closed
|
|
else if (fclose(fp) == 0) // If close succesful
|
|
{
|
|
file_opened=FALSE; // Flag file as closed
|
|
return TRUE; // Return Success
|
|
}
|
|
else
|
|
return FALSE; // Else an error
|
|
}
|
|
|
|
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Do a Iff file seek
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
int niff::seek(long offset,int orig)
|
|
{
|
|
return fseek(fp,offset,orig);
|
|
}
|
|
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Do a Iff file seek
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
long niff::tell()
|
|
{
|
|
return ftell(fp);
|
|
}
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Read Data from current pos
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
void niff::Read(U8 *Buf,long bytes)
|
|
{
|
|
fread(Buf,bytes,1,fp);
|
|
}
|
|
|
|
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Return an Intel Word from current file pos
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
U16 niff::GetIntelWord()
|
|
{
|
|
U16 Word=0;
|
|
|
|
if (file_opened)
|
|
{
|
|
fread((U8 *) &Word,sizeof(U16),1,fp);
|
|
return rev_word(Word);
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
}
|
|
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Return an Intel U32 from current file pos
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
U32 niff::GetIntelLong()
|
|
{
|
|
U32 Long=0;
|
|
|
|
if (file_opened)
|
|
{
|
|
fread((U8 *) &Long,sizeof(U32),1,fp);
|
|
return rev_long(Long);
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
//ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
// Return the error string
|
|
// ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
char *niff::error()
|
|
{
|
|
return niff_error_text[err_no];
|
|
}
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Destroy an IFF descriptor ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
niff::~niff()
|
|
{
|
|
close();
|
|
}
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Return full chunk length ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
U32 niff::full_len(U32 val)
|
|
{
|
|
return (rev_long(val)+1)&0xfffffffeL;
|
|
}
|
|
|
|
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Reverse a long: Motorola <-> Intel ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
U32 niff::rev_long(U32 val)
|
|
{
|
|
return ((val >> 24) & 0x000000ff) | ((val >> 8) & 0x0000ff00) |
|
|
((val << 24) & 0xff000000) | ((val << 8) & 0x00ff0000);
|
|
}
|
|
|
|
/* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
³ Reverse a long: Motorola <-> Intel ³
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
|
|
U16 niff::rev_word(U16 val)
|
|
{
|
|
return ((val >> 8) & 0x000000ff) | ((val << 8) & 0x0000ff00);
|
|
}
|