SBSPSS/Utils/Libs/GLib/Niff.cpp
2000-12-04 14:13:40 +00:00

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);
}