diff options
| author | Rebellion Developments <rebellion@nomail> | 2000-03-16 11:25:00 +0100 |
|---|---|---|
| committer | Patryk Obara <dreamer.tan@gmail.com> | 2019-08-19 05:45:17 +0200 |
| commit | 218ca90543758a20ac326e444ca0643174ca7384 (patch) | |
| tree | 16bfe3e5307f9f515489000f28728224291a0e3b /3dc/win95/Chunk.cpp | |
Import Aliens vs Predator - Gold (Build 116)
Source code release, imported from:
https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code
All text files were converted to Unix format.
Diffstat (limited to '3dc/win95/Chunk.cpp')
| -rw-r--r-- | 3dc/win95/Chunk.cpp | 599 |
1 files changed, 599 insertions, 0 deletions
diff --git a/3dc/win95/Chunk.cpp b/3dc/win95/Chunk.cpp new file mode 100644 index 0000000..a123ba0 --- /dev/null +++ b/3dc/win95/Chunk.cpp @@ -0,0 +1,599 @@ +#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); +} + + + + + + + + + + + |
