Initial revision
This commit is contained in:
parent
218ca90543
commit
2186d5f3f9
572 changed files with 2 additions and 29666 deletions
|
@ -1,599 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "chunk.hpp"
|
||||
|
||||
#if engine
|
||||
|
||||
#define UseLocalAssert No
|
||||
#include "ourasert.h"
|
||||
#define assert(x) GLOBALASSERT(x)
|
||||
|
||||
#else
|
||||
|
||||
#if cencon
|
||||
#include "ccassert.h"
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if cencon
|
||||
#include "environs.hpp"
|
||||
#else
|
||||
#define twprintf printf
|
||||
|
||||
#ifdef cencon
|
||||
#define new my_new
|
||||
#endif
|
||||
|
||||
char * users_name = "Player";
|
||||
#endif
|
||||
|
||||
#include "hash_tem.hpp"
|
||||
Chunk * Parent_File;
|
||||
|
||||
// Non class functions ( only one as yet )
|
||||
|
||||
void list_chunks_in_file(List<int> * pList, HANDLE hand, char const * chunk_id)
|
||||
{
|
||||
unsigned long bytes_read;
|
||||
|
||||
char buffer[8];
|
||||
BOOL ok = TRUE;
|
||||
|
||||
while (pList->size())
|
||||
pList->delete_first_entry();
|
||||
|
||||
// assuming we start at the front of a parent chunk,
|
||||
// containing the child chunk specified
|
||||
|
||||
int init_file_pos = SetFilePointer (hand,0,0,FILE_CURRENT);
|
||||
int file_pos;
|
||||
int file_length = GetFileSize(hand, 0);
|
||||
|
||||
SetFilePointer (hand,8,0,FILE_CURRENT);
|
||||
|
||||
int chunk_length;
|
||||
int sub_chunk_ln;
|
||||
|
||||
ReadFile (hand, (long *) &chunk_length, 4, &bytes_read, 0);
|
||||
|
||||
if ((init_file_pos + chunk_length) > file_length) return;
|
||||
|
||||
while ((file_pos = SetFilePointer (hand,0,0,FILE_CURRENT))
|
||||
< (init_file_pos + chunk_length) && ok) {
|
||||
|
||||
ok = ReadFile (hand, (long *) buffer, 8, &bytes_read, 0);
|
||||
if (strncmp(buffer, chunk_id, 8) == 0)
|
||||
pList->add_entry(file_pos);
|
||||
|
||||
ok = ReadFile (hand, (long *) &sub_chunk_ln, 4, &bytes_read, 0);
|
||||
|
||||
SetFilePointer (hand,sub_chunk_ln-12,0,FILE_CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef RIFF_OPTIMIZE
|
||||
List<int> list_chunks_in_file (HANDLE & hand, const char * chunk_id)
|
||||
{
|
||||
|
||||
List<int> chunk_list;
|
||||
|
||||
list_chunks_in_file(&chunk_list, hand, chunk_id);
|
||||
|
||||
return chunk_list;
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
// Class Chunk functions
|
||||
|
||||
Chunk::~Chunk()
|
||||
{
|
||||
if (parent) {
|
||||
if (parent->children == this) {
|
||||
parent->children = next;
|
||||
if (next)
|
||||
next->previous = previous;
|
||||
}
|
||||
else {
|
||||
if (previous)
|
||||
previous->next = next;
|
||||
if (next)
|
||||
next->previous = previous;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Chunk::Chunk(Chunk_With_Children * _parent, const char * _identifier)
|
||||
: error_code(0)
|
||||
{
|
||||
strncpy (identifier_store, _identifier, 8);
|
||||
identifier_store[8] = 0;
|
||||
identifier = identifier_store;
|
||||
parent = _parent;
|
||||
next = NULL;
|
||||
previous = NULL;
|
||||
|
||||
if (parent){
|
||||
if (parent->children) {
|
||||
Chunk * pTail = parent->children;
|
||||
while (pTail->next)
|
||||
pTail = pTail->next;
|
||||
pTail->next = this;
|
||||
previous = pTail;
|
||||
}
|
||||
else
|
||||
parent->children = this;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Chunk::output_chunk (HANDLE & hand)
|
||||
{
|
||||
unsigned long junk;
|
||||
BOOL ok;
|
||||
char * data_block;
|
||||
|
||||
data_block = make_data_block_from_chunk();
|
||||
|
||||
if (data_block)
|
||||
{
|
||||
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
|
||||
delete [] data_block;
|
||||
|
||||
if (!ok) return FALSE;
|
||||
}
|
||||
else if (chunk_size)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char * Chunk::make_data_block_from_chunk ()
|
||||
{
|
||||
char * data_block;
|
||||
size_t block_size;
|
||||
|
||||
block_size = size_chunk();
|
||||
|
||||
if (!chunk_size)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
data_block = new char [block_size];
|
||||
|
||||
this->fill_data_block(data_block);
|
||||
|
||||
return data_block;
|
||||
}
|
||||
|
||||
char * Chunk::make_data_block_for_process ()
|
||||
{
|
||||
char * data_block;
|
||||
size_t block_size;
|
||||
|
||||
block_size = size_chunk_for_process();
|
||||
|
||||
if (!chunk_size)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
data_block = new char [block_size];
|
||||
|
||||
fill_data_block_for_process(data_block);
|
||||
|
||||
return data_block;
|
||||
}
|
||||
|
||||
|
||||
size_t Chunk::size_chunk_for_process()
|
||||
{
|
||||
return size_chunk();
|
||||
}
|
||||
|
||||
|
||||
void Chunk::fill_data_block_for_process(char * data_start)
|
||||
{
|
||||
fill_data_block(data_start);
|
||||
}
|
||||
|
||||
Chunk_With_Children * Chunk::GetRootChunk(void)
|
||||
{
|
||||
Chunk * retp = this;
|
||||
|
||||
while (retp->parent) retp = retp->parent;
|
||||
|
||||
return (Chunk_With_Children *) retp;
|
||||
}
|
||||
|
||||
Chunk_With_Children const * Chunk::GetRootChunk(void) const
|
||||
{
|
||||
Chunk const * retp = this;
|
||||
|
||||
while (retp->parent) retp = retp->parent;
|
||||
|
||||
return (Chunk_With_Children const *) retp;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
|
||||
// Class Miscellaneous_Chunk functions
|
||||
|
||||
Miscellaneous_Chunk::Miscellaneous_Chunk (Chunk_With_Children * parent, const char * identifier,
|
||||
const char * _data, size_t _data_size)
|
||||
: Chunk (parent, identifier),
|
||||
data(NULL), data_size (_data_size)
|
||||
{
|
||||
if (data_size)
|
||||
{
|
||||
data_store = new char [data_size];
|
||||
|
||||
*((char **) &data) = data_store;
|
||||
|
||||
for (int i = 0; i < (signed)data_size; i++)
|
||||
data_store[i] = _data[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
data_store = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Miscellaneous_Chunk::fill_data_block (char * data_start)
|
||||
{
|
||||
strncpy (data_start, identifier, 8);
|
||||
|
||||
data_start += 8;
|
||||
|
||||
*((int *) data_start) = chunk_size;
|
||||
|
||||
data_start += 4;
|
||||
|
||||
for (int i = 0; i<(signed)(chunk_size-12); i++)
|
||||
data_start[i] = data[i];
|
||||
}
|
||||
|
||||
Miscellaneous_Chunk::~Miscellaneous_Chunk ()
|
||||
{
|
||||
delete [] data_store;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
|
||||
// Class Chunk_With_Children functions
|
||||
|
||||
Chunk_With_Children::~Chunk_With_Children()
|
||||
{
|
||||
while (children)
|
||||
delete children;
|
||||
}
|
||||
|
||||
size_t Chunk_With_Children::size_chunk ()
|
||||
{
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
chunk_size = 12; // identifier + length
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
chunk_size += child_ptr->size_chunk();
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
return chunk_size;
|
||||
|
||||
}
|
||||
|
||||
BOOL Chunk_With_Children::output_chunk (HANDLE &hand)
|
||||
{
|
||||
unsigned long junk;
|
||||
Chunk * child_ptr = children;
|
||||
BOOL ok;
|
||||
|
||||
ok = WriteFile (hand, (long *) identifier, 8, &junk, 0);
|
||||
|
||||
if (!ok) return FALSE;
|
||||
|
||||
ok = WriteFile (hand, (long *) &chunk_size, 4, &junk, 0);
|
||||
|
||||
if (!ok) return FALSE;
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL && ok){
|
||||
ok = child_ptr->output_chunk(hand);
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
if (!ok) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
size_t Chunk_With_Children::size_chunk_for_process()
|
||||
{
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
chunk_size = 12; // identifier + length
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
chunk_size += child_ptr->size_chunk_for_process();
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
return chunk_size;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Chunk_With_Children::fill_data_block_for_process(char * data_start)
|
||||
{
|
||||
strncpy (data_start, identifier, 8);
|
||||
|
||||
data_start += 8;
|
||||
|
||||
*((int *) data_start) = chunk_size;
|
||||
|
||||
data_start += 4;
|
||||
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
child_ptr->fill_data_block_for_process (data_start);
|
||||
data_start += child_ptr->chunk_size;
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Chunk_With_Children::fill_data_block(char * data_start)
|
||||
{
|
||||
strncpy (data_start, identifier, 8);
|
||||
|
||||
data_start += 8;
|
||||
|
||||
*((int *) data_start) = chunk_size;
|
||||
|
||||
data_start += 4;
|
||||
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
child_ptr->fill_data_block (data_start);
|
||||
data_start += child_ptr->chunk_size;
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef RIFF_OPTIMIZE
|
||||
List<Chunk *> Chunk_With_Children::lookup_child (const char * class_ident) const
|
||||
{
|
||||
List<Chunk *> child_list;
|
||||
|
||||
lookup_child(class_ident,child_list);
|
||||
|
||||
return child_list;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Chunk_With_Children::lookup_child (const char * class_ident,List<Chunk*>& child_list) const
|
||||
{
|
||||
//make sure the list is empty first
|
||||
while(child_list.size())
|
||||
{
|
||||
child_list.delete_first_entry();
|
||||
}
|
||||
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
|
||||
{
|
||||
assert (!child_ptr->r_u_miscellaneous());
|
||||
child_list.add_entry(child_ptr);
|
||||
}
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
unsigned Chunk_With_Children::count_children (char const * class_ident) const
|
||||
{
|
||||
unsigned nChildren = 0;
|
||||
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
|
||||
{
|
||||
assert (!child_ptr->r_u_miscellaneous());
|
||||
++ nChildren;
|
||||
}
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
|
||||
return nChildren;
|
||||
}
|
||||
|
||||
Chunk* Chunk_With_Children::lookup_single_child (const char * class_ident) const
|
||||
{
|
||||
#if debug
|
||||
//if debug make sure there is at most one of the required chunk type
|
||||
Chunk * child_ptr = children;
|
||||
Chunk * chunk_found=0;
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
|
||||
{
|
||||
assert (!child_ptr->r_u_miscellaneous());
|
||||
assert(!chunk_found);
|
||||
chunk_found=child_ptr;
|
||||
}
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
return chunk_found;
|
||||
#else
|
||||
Chunk * child_ptr = children;
|
||||
|
||||
if (children)
|
||||
while (child_ptr != NULL) {
|
||||
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
|
||||
{
|
||||
assert (!child_ptr->r_u_miscellaneous());
|
||||
return child_ptr;
|
||||
}
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Chunk_With_Children::prepare_for_output()
|
||||
{
|
||||
Chunk * child_ptr = children;
|
||||
if (children)
|
||||
while (child_ptr != NULL){
|
||||
child_ptr->prepare_for_output ();
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
void Chunk_With_Children::post_input_processing()
|
||||
{
|
||||
Chunk * child_ptr = children;
|
||||
if (children)
|
||||
while (child_ptr != NULL){
|
||||
child_ptr->post_input_processing ();
|
||||
child_ptr = child_ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
//Chunk registering stuff
|
||||
|
||||
|
||||
class RifRegEntry
|
||||
{
|
||||
public:
|
||||
int chunk_id_1;
|
||||
int chunk_id_2;
|
||||
int parent_id_1;
|
||||
int parent_id_2;
|
||||
Chunk * (* m_pfnCreate) (Chunk_With_Children* parent,const char* data);
|
||||
|
||||
|
||||
/*
|
||||
For two members of this class to be considered similar there chunk_is members must match.
|
||||
If both parent_id members are zero for one of the objects being compared , then they are considered
|
||||
equal regardless of the parent_id members of the other object.
|
||||
Otherwise the parent_id members of the two objects must match.
|
||||
(This is done because not all of the constructors insist on a given parent)
|
||||
*/
|
||||
inline bool operator == (RifRegEntry const & rEntry) const
|
||||
{
|
||||
if(chunk_id_1 != rEntry.chunk_id_1 || chunk_id_2 != rEntry.chunk_id_2) return FALSE;
|
||||
if(parent_id_1 == 0 && parent_id_2 == 0) return TRUE;
|
||||
if(rEntry.parent_id_1 == 0 && rEntry.parent_id_2 == 0) return TRUE;
|
||||
return parent_id_1 == rEntry.parent_id_1 && parent_id_2 == rEntry.parent_id_2;
|
||||
}
|
||||
inline bool operator != (RifRegEntry const & rEntry) const
|
||||
{
|
||||
return ! operator == (rEntry);
|
||||
}
|
||||
};
|
||||
|
||||
inline unsigned HashFunction(RifRegEntry const & rEntry)
|
||||
{
|
||||
return HashFunction(rEntry.chunk_id_1 + rEntry.chunk_id_2);
|
||||
}
|
||||
|
||||
static HashTable<RifRegEntry> * g_pRifRegister = NULL;
|
||||
|
||||
void Chunk::Register(const char* idChunk,const char* idParent, Chunk * (* pfnCreate) (Chunk_With_Children* parent,const char* data) )
|
||||
{
|
||||
static HashTable<RifRegEntry> reg;
|
||||
char temp_id[8];
|
||||
|
||||
g_pRifRegister = ®
|
||||
|
||||
RifRegEntry entry;
|
||||
|
||||
strncpy(temp_id,idChunk,8);
|
||||
entry.chunk_id_1 = *(int*) &temp_id[0];
|
||||
entry.chunk_id_2 = *(int*) &temp_id[4];
|
||||
entry.m_pfnCreate = pfnCreate;
|
||||
|
||||
if(idParent)
|
||||
{
|
||||
strncpy(temp_id,idParent,8);
|
||||
entry.parent_id_1 = *(int*) &temp_id[0];
|
||||
entry.parent_id_2 = *(int*) &temp_id[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.parent_id_1 = 0;
|
||||
entry.parent_id_2 = 0;
|
||||
}
|
||||
|
||||
reg.AddAsserted(entry);
|
||||
}
|
||||
|
||||
Chunk* Chunk_With_Children::DynCreate(const char* data)
|
||||
{
|
||||
/*
|
||||
Look in hash tables for a constructor for this block
|
||||
If none exists , create a Miscellaneous_Chunk
|
||||
*/
|
||||
if (g_pRifRegister)
|
||||
{
|
||||
RifRegEntry test;
|
||||
test.chunk_id_1 = *(int*) data;
|
||||
test.chunk_id_2 = *(int*) &data[4];
|
||||
test.parent_id_1 = *(int*) identifier;
|
||||
test.parent_id_2 = *(int*) &identifier[4];
|
||||
test.m_pfnCreate = NULL;
|
||||
|
||||
RifRegEntry const * pEntry = g_pRifRegister->Contains(test);
|
||||
if (pEntry)
|
||||
{
|
||||
return pEntry->m_pfnCreate(this,data);
|
||||
}
|
||||
}
|
||||
return new Miscellaneous_Chunk(this,data,(data + 12), (*(int *) (data + 8))-12);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue