summaryrefslogtreecommitdiff
path: root/3dc/win95/OBCHUNK.CPP
diff options
context:
space:
mode:
Diffstat (limited to '3dc/win95/OBCHUNK.CPP')
-rw-r--r--3dc/win95/OBCHUNK.CPP1434
1 files changed, 1434 insertions, 0 deletions
diff --git a/3dc/win95/OBCHUNK.CPP b/3dc/win95/OBCHUNK.CPP
new file mode 100644
index 0000000..86e8857
--- /dev/null
+++ b/3dc/win95/OBCHUNK.CPP
@@ -0,0 +1,1434 @@
+#include "chunk.hpp"
+#include "chnktype.hpp"
+#include "mishchnk.hpp"
+#include "obchunk.hpp"
+#include "shpchunk.hpp"
+#include "envchunk.hpp"
+#include "md5.h"
+// Class Object_Chunk functions
+
+#ifdef cencon
+#define new my_new
+#endif
+//macro for helping to force inclusion of chunks when using libraries
+FORCE_CHUNK_INCLUDE_IMPLEMENT(obchunk)
+
+RIF_IMPLEMENT_DYNCREATE("RBOBJECT",Object_Chunk)
+
+/*
+Children for Object_Chunk :
+
+"OBJHEAD1" Object_Header_Chunk
+"OBINTDT" Object_Interface_Data_Chunk
+"OBJPRJDT" Object_Project_Data_Chunk
+"MODULEDT" Object_Module_Data_Chunk
+"SHPVTINT" Shape_Vertex_Intensities_Chunk
+"OBJTRAK2" Object_Track_Chunk2
+"TRAKSOUN" Object_Track_Sound_Chunk
+"OBANSEQS" Object_Animation_Sequences_Chunk
+"PLOBJLIT" Placed_Object_Light_Chunk
+"ALTLOCAT" Object_Alternate_Locations_Chunk
+*/
+
+
+
+
+
+// from buffer
+Object_Chunk::Object_Chunk(Chunk_With_Children * parent, const char *data, size_t size)
+: Lockable_Chunk_With_Children (parent, "RBOBJECT"),
+ object_data ()
+{
+ const char * buffer_ptr = data;
+
+ object_data_store = (ChunkObject *) &object_data;
+
+ while ((data-buffer_ptr)< (signed) size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed) size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+
+ }
+
+ program_object_index=-1;
+
+}
+
+// from data
+Object_Chunk::Object_Chunk (Chunk_With_Children * parent, ChunkObject &obj)
+: Lockable_Chunk_With_Children (parent, "RBOBJECT"),
+ object_data (obj)
+{
+ object_data_store = (ChunkObject *) &object_data;
+ object_data_store->index_num=-1;
+
+ new Object_Header_Chunk(this);
+ new Object_Interface_Data_Chunk(this);
+
+ //if the parent is a file_chunk get an object index
+ if(!strcmp(parent->identifier,"REBINFF2"))
+ {
+ ((File_Chunk*)parent)->assign_index_to_object(this);
+ }
+ program_object_index=-1;
+
+ CalculateID();
+}
+
+Object_Chunk::~Object_Chunk()
+{
+}
+
+Object_Header_Chunk * Object_Chunk::get_header()
+{
+
+ return (Object_Header_Chunk *) this->lookup_single_child ("OBJHEAD1");
+
+
+}
+
+Shape_Chunk * Object_Chunk::get_assoc_shape()
+{
+ if (!get_header()) return 0;
+
+ return get_header()->associated_shape;
+
+}
+
+BOOL Object_Chunk::assoc_with_shape (Shape_Chunk * shpch)
+{
+ Object_Header_Chunk * obhead = get_header();
+
+ if (!obhead) return 0;
+
+ // check that we are not already associated with this shape
+
+ if (obhead->associated_shape == shpch) return 1;
+
+ Shape_Header_Chunk * shphead = shpch->get_header();
+
+ if (!shphead) return 0;
+
+ // deassociate with the old shape
+
+ if (obhead->associated_shape)
+ deassoc_with_shape (obhead->associated_shape);
+
+ // associate with the new
+
+ obhead->associated_shape = shpch;
+
+ if (!shphead->associated_objects_store.contains(this))
+ shphead->associated_objects_store.add_entry(this);
+
+ return 1;
+
+}
+
+BOOL Object_Chunk::deassoc_with_shape (Shape_Chunk * shpch)
+{
+ Shape_Header_Chunk * shphead = shpch->get_header();
+
+ if (!shphead) return 0;
+
+ if (shphead->associated_objects_store.contains(this))
+ shphead->associated_objects_store.delete_entry(this);
+
+ Object_Header_Chunk * obhead = get_header();
+
+ obhead->associated_shape = 0;
+
+ return 1;
+
+}
+
+BOOL Object_Chunk::file_equals(HANDLE &rif_file)
+{
+ unsigned long bytes_read;
+ char name[50];
+
+ // get header list
+ List<int> obhead;
+ list_chunks_in_file (&obhead, rif_file, "OBJHEAD1");
+
+ if (obhead.size() != 1) return FALSE;
+
+ // get object identifier
+ SetFilePointer(rif_file,obhead.first_entry() + 96,0,FILE_BEGIN);
+ int i = 0;
+ do ReadFile (rif_file, (long *) (name + i), 1, &bytes_read, 0);
+ while (name[i++] != 0);
+
+ if (!strcmp(name, object_data.o_name) ) return (TRUE);
+
+ return (FALSE);
+}
+
+const char * Object_Chunk::get_head_id()
+{
+ Object_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return (0);
+
+ return(hdptr->identifier);
+}
+
+void Object_Chunk::set_lock_user (char * user)
+{
+ Object_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return;
+
+ strncpy (hdptr->lock_user, user,16);
+
+ hdptr->lock_user[16] = 0;
+}
+
+
+BOOL Object_Chunk::inc_v_no ()
+{
+ Object_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return (FALSE);
+
+ hdptr->version_no++;
+
+ return (TRUE);
+}
+
+BOOL Object_Chunk::same_and_updated(Object_Chunk & obj)
+{
+
+ Object_Header_Chunk * hd1ptr = get_header();
+
+ if (!hd1ptr) return (0);
+
+ Object_Header_Chunk * hd2ptr = obj.get_header();
+
+ if (!hd2ptr) return (0);
+
+ return (hd1ptr->version_no < hd2ptr->version_no &&
+ (!strcmp(obj.object_data.o_name, object_data.o_name)) );
+
+}
+
+BOOL Object_Chunk::assoc_with_shape_no(File_Chunk *fc)
+{
+ Object_Header_Chunk * hdptr = get_header();
+ Shape_Chunk * shp = NULL;
+ Shape_Header_Chunk * shphd;
+
+ if (!hdptr) return (FALSE);
+
+ List<Chunk *> chlst;
+ fc->lookup_child("REBSHAPE",chlst);
+
+ for (LIF<Chunk *> l(&chlst); !l.done(); l.next())
+ {
+ shp = (Shape_Chunk *)l();
+ shphd = shp->get_header();
+ if (shphd)
+ {
+ if (hdptr->shape_id_no == shphd->file_id_num)
+ break;
+ }
+ }
+ if (!l.done())
+ {
+ assoc_with_shape(shp);
+ }
+ else
+ {
+ return(FALSE);
+ }
+
+ return(TRUE);
+
+
+}
+
+
+
+
+void Object_Chunk::post_input_processing()
+{
+ CalculateID();
+
+ if (get_header())
+ if (get_header()->flags & GENERAL_FLAG_LOCKED)
+ external_lock = TRUE;
+
+ Chunk_With_Children::post_input_processing();
+
+}
+
+
+VModule_Array_Chunk * Object_Chunk::get_vmod_chunk()
+{
+ Object_Module_Data_Chunk * omdc = 0;
+
+ omdc = (Object_Module_Data_Chunk *) lookup_single_child ("MODULEDT");
+
+
+ if (omdc)
+ {
+ VModule_Array_Chunk * vmac = 0;
+ vmac = (VModule_Array_Chunk *)omdc->lookup_single_child ("VMDARRAY") ;
+
+ if (vmac) return(vmac);
+ }
+
+ return(0);
+
+
+}
+
+void Object_Chunk::destroy(File_Chunk * fc)
+{
+ List<Chunk *> cl;
+ fc->lookup_child("RBOBJECT",cl);
+
+ for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
+ {
+ Object_Chunk * ob = (Object_Chunk *)cli();
+ if (ob == this) continue;
+
+ VModule_Array_Chunk * vmac = ob->get_vmod_chunk();
+
+ BOOL in_object_va = FALSE;
+
+ if (vmac)
+ {
+ int pos=0;
+ for(int i=0;i<vmac->num_array_items;i++)
+ {
+
+ if (vmac->vmod_array[i].object_index==object_data.index_num)
+ {
+ in_object_va=TRUE;
+ //update branch indeces for branches that go beyond this point
+ for(int j=0;j<vmac->num_array_items;j++)
+ {
+ if(vmac->vmod_array[j].branch_no> pos)
+ vmac->vmod_array[j].branch_no--;
+ }
+ }
+ else
+ {
+ if(pos!=i)
+ {
+ vmac->vmod_array[pos]=vmac->vmod_array[i];
+ }
+ pos++;
+ }
+ }
+
+ if(in_object_va)
+ {
+ if(pos==0)
+ {
+ delete vmac;
+ }
+ else
+ {
+ //excess entries should be properly deleted when the array is deleted
+ vmac->num_array_items=pos;
+ }
+
+ }
+
+ }
+
+ //now remove this object from any adjacency data
+
+ Object_Module_Data_Chunk* omdc=(Object_Module_Data_Chunk*)ob->lookup_single_child("MODULEDT");
+ if(omdc)
+ {
+ Adjacent_Module_Entry_Points_Chunk* amepc=(Adjacent_Module_Entry_Points_Chunk*)omdc->lookup_single_child("ADJMDLEP");
+
+ if(amepc)
+ {
+ for(LIF<Adjacent_Module> ad_lif(&amepc->adjacent_modules_list);!ad_lif.done();)
+ {
+ if(ad_lif().object_index==object_data.index_num)
+ ad_lif.delete_current();
+ else
+ ad_lif.next();
+
+ }
+ }
+ }
+
+
+ }
+
+ Shape_Chunk * shp = get_assoc_shape();
+
+ deassoc_with_shape (shp);
+
+ lock_chunk(*fc);
+
+ deleted = TRUE;
+
+ unlock_chunk(*fc,TRUE);
+
+}
+
+
+void Object_Chunk::update_my_chunkobject(ChunkObject & cob)
+{
+ //store the object's index , so that it doesn't get lost
+ int object_index=object_data_store->index_num;
+ *object_data_store = cob;
+ //replace the object index
+ object_data_store->index_num=object_index;
+ //recalculate the object's id in case the name has changed
+ CalculateID();
+}
+
+ObjectID Object_Chunk::CalculateID()
+{
+ ObjectID retval={0,0};
+ List<Chunk*> chlist;
+ parent->lookup_child("REBENVDT",chlist);
+ if(!chlist.size()) return retval;
+ ((Environment_Data_Chunk*)chlist.first_entry())->lookup_child("RIFFNAME",chlist);
+ if(!chlist.size()) return retval;
+ char Name[100];
+
+ #if InterfaceEngine||cencon
+ //need to check for console specific rif files,and skip the 'sat' or 'psx'
+ //so that they get the same ids as the pc
+ const char* r_name=((RIF_Name_Chunk*)chlist.first_entry())->rif_name;
+ if(tolower(r_name[0])=='p' && tolower(r_name[1])=='s' && tolower(r_name[2])=='x' )
+ strcpy(Name,&r_name[3]);
+ else if (tolower(r_name[0])=='s' && tolower(r_name[1])=='a' && tolower(r_name[2])=='t' )
+ strcpy(Name,&r_name[3]);
+ else
+ strcpy(Name,r_name);
+ #else
+ strcpy(Name,((RIF_Name_Chunk*)chlist.first_entry())->rif_name);
+ #endif
+
+ strcat(Name,object_data.o_name);
+ char buffer[16];
+ md5_buffer(Name,strlen(Name),&buffer[0]);
+ buffer[7]=0;
+ object_data_store->ID=*(ObjectID*)&buffer[0];
+ return object_data_store->ID;
+
+}
+
+/////////////////////////////////////////
+
+// Class Object_Header_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("OBJHEAD1",Object_Header_Chunk)
+
+// from buffer
+#if UseOldChunkLoader
+Object_Header_Chunk::Object_Header_Chunk(Object_Chunk * parent, const char * hdata, size_t /*hsize*/)
+: Chunk (parent, "OBJHEAD1"), object_data (parent->object_data_store),
+flags(0), version_no (0), associated_shape (0)
+{
+ flags = *((int *) hdata);
+
+ if (flags & OBJECT_FLAG_BASE_OBJECT)
+ parent->object_data_store->is_base_object = TRUE;
+ else
+ {
+ parent->object_data_store->is_base_object = FALSE;
+ }
+
+ strncpy (lock_user, (hdata + 4), 16);
+ lock_user[16] = '\0';
+
+ parent->object_data_store->float_location = *((ChunkVector *) (hdata + 20));
+ parent->object_data_store->location = parent->object_data_store->float_location;
+
+ parent->object_data_store->orientation.x =- *((double *) (hdata + 44));
+ parent->object_data_store->orientation.y =- *((double *) (hdata + 52));
+ parent->object_data_store->orientation.z =- *((double *) (hdata + 60));
+ parent->object_data_store->orientation.w = *((double *) (hdata + 68));
+
+ version_no = *((int *) (hdata + 76));
+
+ shape_id_no = *((int *) (hdata + 80));
+
+ strcpy (parent->object_data_store->o_name, (hdata + 84));
+ parent->object_data_store->ID.id1=0;
+ parent->object_data_store->ID.id2=0;
+ parent->object_data_store->index_num=-1;
+}
+#else
+Object_Header_Chunk::Object_Header_Chunk(Chunk_With_Children * parent, const char * hdata, size_t /*hsize*/)
+: Chunk (parent, "OBJHEAD1"), object_data (((Object_Chunk*)parent)->object_data_store),
+flags(0), version_no (0), associated_shape (0)
+{
+ Object_Chunk* parent_object = (Object_Chunk*) parent;
+
+ flags = *((int *) hdata);
+
+ if (flags & OBJECT_FLAG_BASE_OBJECT)
+ parent_object->object_data_store->is_base_object = TRUE;
+ else
+ {
+ parent_object->object_data_store->is_base_object = FALSE;
+ }
+
+ strncpy (lock_user, (hdata + 4), 16);
+ lock_user[16] = '\0';
+
+ hdata+=20;
+
+ parent_object->object_data_store->location = *(ChunkVectorInt*) hdata;
+ hdata+=sizeof(ChunkVectorInt);
+
+ parent_object->object_data_store->orientation = *((ChunkQuat *) hdata);
+ hdata+=sizeof(ChunkQuat);
+
+ parent_object->object_data_store->index_num = *(int *) hdata;
+ hdata+=4;
+
+ version_no = *((int *) hdata);
+ hdata+=4;
+
+ shape_id_no = *((int *) hdata);
+ hdata+=4;
+
+ strcpy (parent_object->object_data_store->o_name, hdata);
+ parent_object->object_data_store->ID.id1=0;
+ parent_object->object_data_store->ID.id2=0;
+}
+#endif
+
+//from data
+
+Object_Header_Chunk::Object_Header_Chunk (Object_Chunk * parent)
+: Chunk (parent, "OBJHEAD1"),
+object_data (parent->object_data_store),
+flags (0), version_no (0), associated_shape(0)
+{
+ if (object_data->is_base_object) {
+ flags = OBJECT_FLAG_BASE_OBJECT;
+ }
+}
+
+
+size_t Object_Header_Chunk::size_chunk()
+{
+ int length = 72;
+
+ length += (strlen(object_data->o_name)+1);
+
+ length += (4-length%4)%4;
+
+ chunk_size = length;
+
+ return length;
+}
+
+BOOL Object_Header_Chunk::output_chunk (HANDLE & hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+}
+
+void Object_Header_Chunk::fill_data_block ( char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = flags;
+ strncpy ((data_start + 4), lock_user, 16);
+ data_start+=20;
+
+ *((ChunkVectorInt *) (data_start)) = object_data->location;
+ data_start+=sizeof(ChunkVectorInt);
+
+ *((ChunkQuat *) (data_start)) = object_data->orientation;
+ data_start+=sizeof(ChunkQuat);
+
+ *(int*) data_start=object_data->index_num;
+ data_start+=4;
+
+ *((int *) data_start) = version_no;
+ data_start+=4;
+
+ *((int *) data_start) = shape_id_no;
+ data_start+=4;
+
+ strcpy (data_start, object_data->o_name);
+}
+
+void Object_Header_Chunk::prepare_for_output()
+{
+ version_no ++;
+}
+
+/////////////////////////////////////////
+
+// Class Object_Interface_Data_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("OBINTDT",Object_Interface_Data_Chunk)
+
+/*
+Children for Object_Interface_Data_Chunk :
+
+"OBJNOTES" Object_Notes_Chunk
+*/
+
+// from buffer
+Object_Interface_Data_Chunk::Object_Interface_Data_Chunk(Chunk_With_Children * parent, const char *data, size_t size)
+: Chunk_With_Children (parent, "OBINTDT")
+{
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed) size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed) size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+ }
+}
+
+Object_Interface_Data_Chunk::Object_Interface_Data_Chunk (Object_Chunk * parent)
+: Chunk_With_Children (parent, "OBINTDT")
+{
+ new Object_Notes_Chunk (this, "Enter notes here", strlen("Enter notes here") + 1);
+}
+
+
+///////////////////////////////////////
+
+// Class Object_Notes_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("OBJNOTES",Object_Notes_Chunk)
+
+Object_Notes_Chunk::Object_Notes_Chunk (Chunk_With_Children * parent,
+ const char * _data, size_t _data_size)
+: Chunk(parent, "OBJNOTES"),
+data(NULL), data_size(_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];
+
+}
+
+void Object_Notes_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];
+}
+
+Object_Notes_Chunk::~Object_Notes_Chunk ()
+{
+ delete [] data_store;
+}
+
+BOOL Object_Notes_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+}
+
+
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("MODULEDT",Object_Module_Data_Chunk)
+
+/*
+Children For Object_Module_Data_Chunk :
+
+"VMDARRAY" VModule_Array_Chunk
+"ADJMDLEP" Adjacent_Module_Entry_Points_Chunk
+"MODFLAGS" Module_Flag_Chunk
+"WAYPOINT" Module_Waypoint_Chunk
+"MODACOUS" Module_Acoustics_Chunk
+"AIMODMAS" AI_Module_Master_Chunk
+"AIMODSLA" AI_Module_Slave_Chunk
+
+*/
+
+Object_Module_Data_Chunk::Object_Module_Data_Chunk (Chunk_With_Children * parent,const char * mdata, size_t msize)
+: Chunk_With_Children (parent, "MODULEDT")
+{
+ const char * buffer_ptr = mdata;
+
+ while ((mdata-buffer_ptr)< (signed) msize) {
+
+ if ((*(int *)(mdata + 8)) + (mdata-buffer_ptr) > (signed) msize) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+ DynCreate(mdata);
+ mdata += *(int *)(mdata + 8);
+
+ }
+
+}
+
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("VMDARRAY",VModule_Array_Chunk)
+
+VModule_Array_Chunk::VModule_Array_Chunk(Object_Module_Data_Chunk * parent, VMod_Arr_Item * vma, int num_in_vma)
+: Chunk (parent, "VMDARRAY")
+{
+ int i;
+
+ num_array_items = num_in_vma;
+
+ vmod_array = new VMod_Arr_Item [num_in_vma];
+
+ for (i=0; i<num_in_vma; i++)
+ {
+ vmod_array[i] = vma[i];
+ }
+
+}
+
+
+void VModule_Array_Chunk::fill_data_block (char *data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = num_array_items;
+
+ data_start += 4;
+
+ for (int i=0; i<num_array_items; i++)
+ {
+ *((int *) data_start) = vmod_array[i].object_index;
+ data_start += 4;
+
+ *((int *) data_start) = vmod_array[i].branch_no;
+ data_start += 4;
+
+ *((int *) data_start) = vmod_array[i].flags;
+ data_start += 4;
+
+ *((int *) data_start) = vmod_array[i].spare;
+ data_start += 4;
+
+ }
+
+}
+
+
+size_t VModule_Array_Chunk::size_chunk()
+{
+ chunk_size =16+16*num_array_items;
+ return(chunk_size);
+
+}
+
+#if UseOldChunkLoader
+VModule_Array_Chunk::VModule_Array_Chunk (Object_Module_Data_Chunk * parent, const char * vmdata, size_t /*vmsize*/)
+: Chunk (parent, "VMDARRAY")
+{
+ num_array_items = *((int *) vmdata);
+
+ vmdata += 4;
+
+ vmod_array = new VMod_Arr_Item [num_array_items];
+
+ for (int i=0; i<num_array_items; i++)
+ {
+ //vmod_array[i].type = *((int *) vmdata);
+ vmdata += 4;
+ vmod_array[i].branch_no = *((int *) vmdata);
+ vmdata += 4;
+
+ //vmod_array[i].dir.x = *((double *) vmdata);
+ vmdata += 8;
+ //vmod_array[i].dir.y = *((double *) vmdata);
+ vmdata += 8;
+ //vmod_array[i].dir.z = *((double *) vmdata);
+ vmdata += 8;
+
+ //vmod_array[i].angle = *((double *) vmdata);
+ vmdata += 8;
+
+ vmod_array[i].flags = *((int *) vmdata);
+ vmdata += 4;
+
+ vmod_array[i].spare = *((int *) vmdata);
+ vmdata += 4;
+
+ vmod_array[i].object_index=-1;
+
+ vmod_array[i].o_name = new char [strlen(vmdata) + 1];
+ strcpy (vmod_array[i].o_name, vmdata);
+ vmdata += (strlen(vmod_array[i].o_name) + 1) + (4-(strlen(vmod_array[i].o_name) + 1)%4)%4;
+
+ }
+
+}
+#else
+VModule_Array_Chunk::VModule_Array_Chunk (Chunk_With_Children * parent, const char * vmdata, size_t /*vmsize*/)
+: Chunk (parent, "VMDARRAY")
+{
+ num_array_items = *((int *) vmdata);
+
+ vmdata += 4;
+
+ vmod_array = new VMod_Arr_Item [num_array_items];
+
+ for (int i=0; i<num_array_items; i++)
+ {
+
+ vmod_array[i].object_index = *((int *) vmdata);
+ vmdata += 4;
+
+ vmod_array[i].branch_no = *((int *) vmdata);
+ vmdata += 4;
+
+ vmod_array[i].flags = *((int *) vmdata);
+ vmdata += 4;
+
+ vmod_array[i].spare = *((int *) vmdata);
+ vmdata += 4;
+
+ }
+
+}
+#endif
+
+VModule_Array_Chunk::~VModule_Array_Chunk ()
+{
+ delete [] vmod_array;
+}
+
+///////////////////////////////////////
+#if 0
+void Adjacent_Modules_Chunk::fill_data_block (char *data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = adjacent_modules_list.size();
+
+ data_start += 4;
+
+ for (LIF<Adjacent_Module> ami(&adjacent_modules_list); !ami.done(); ami.next())
+ {
+
+ *((int *) data_start) = 0;
+ data_start += 4;
+
+ *((int *) data_start) = 0;
+ data_start += 4;
+
+ strcpy (data_start, ami().o_name);
+ data_start += (strlen(ami().o_name) + 1) + (4-(strlen(ami().o_name) + 1)%4)%4;
+
+ }
+
+}
+
+size_t Adjacent_Modules_Chunk::size_chunk()
+{
+ int size = 16;
+
+ for (LIF<Adjacent_Module> ami(&adjacent_modules_list); !ami.done(); ami.next())
+ {
+ size += 8;
+ size += (strlen(ami().o_name) + 1) + (4-(strlen(ami().o_name) + 1)%4)%4;
+ }
+
+ chunk_size = size;
+ return(size);
+
+}
+
+Adjacent_Modules_Chunk::Adjacent_Modules_Chunk (Object_Module_Data_Chunk * parent, const char * data, size_t /*size*/)
+: Chunk (parent, "ADJMDLST")
+{
+ int num_array_items = *((int *) data);
+
+ data += 4;
+
+ for (int i=0; i<num_array_items; i++)
+ {
+ Adjacent_Module am;
+
+ data += 8;
+
+ am.o_name = new char [strlen(data) + 1];
+ strcpy (am.o_name, data);
+ data += (strlen(am.o_name) + 1) + (4-(strlen(am.o_name) + 1)%4)%4;
+
+ adjacent_modules_list.add_entry(am);
+
+ }
+}
+#endif
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("ADJMDLEP",Adjacent_Module_Entry_Points_Chunk)
+
+void Adjacent_Module_Entry_Points_Chunk::fill_data_block (char *data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = adjacent_modules_list.size();
+
+ data_start += 4;
+
+ for (LIF<Adjacent_Module> ami(&adjacent_modules_list); !ami.done(); ami.next())
+ {
+
+ *((int *) data_start) = ami().object_index;
+ data_start += 4;
+
+ *((int *) data_start) = ami().flags;
+ data_start += 4;
+
+ *((ChunkVectorInt *) data_start) = ami().entry_point;
+ data_start += sizeof(ChunkVectorInt);
+
+
+ }
+
+}
+
+
+size_t Adjacent_Module_Entry_Points_Chunk::size_chunk()
+{
+ chunk_size = 16+adjacent_modules_list.size()*20;
+ return(chunk_size);
+}
+
+#if UseOldChunkLoader
+Adjacent_Module_Entry_Points_Chunk::Adjacent_Module_Entry_Points_Chunk (Object_Module_Data_Chunk * parent, const char * data, size_t /*size*/)
+: Chunk (parent, "ADJMDLEP")
+{
+ int num_array_items = *((int *) data);
+
+ data += 4;
+
+ for (int i=0; i<num_array_items; i++)
+ {
+ Adjacent_Module am;
+
+ am.flags = *((int *) data);
+ data += 4;
+
+ am.entry_point = *((ChunkVector *) data);
+ data += sizeof(ChunkVector);
+
+ am.o_name = new char [strlen(data) + 1];
+ strcpy (am.o_name, data);
+ data += (strlen(am.o_name) + 4)&~3;
+
+ am.object_index=-1;
+
+ adjacent_modules_list.add_entry(am);
+
+ }
+}
+#else
+Adjacent_Module_Entry_Points_Chunk::Adjacent_Module_Entry_Points_Chunk (Chunk_With_Children * parent, const char * data, size_t /*size*/)
+: Chunk (parent, "ADJMDLEP")
+{
+ int num_array_items = *((int *) data);
+
+ data += 4;
+
+ for (int i=0; i<num_array_items; i++)
+ {
+ Adjacent_Module am;
+
+ am.object_index = *((int *) data);
+ data += 4;
+
+ am.flags = *((int *) data);
+ data += 4;
+
+ am.entry_point = *((ChunkVectorInt *) data);
+ data += sizeof(ChunkVectorInt);
+
+
+ adjacent_modules_list.add_entry(am);
+
+ }
+
+}
+#endif
+
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("MODFLAGS",Module_Flag_Chunk)
+
+Module_Flag_Chunk::Module_Flag_Chunk(Object_Module_Data_Chunk* parent)
+:Chunk(parent,"MODFLAGS")
+{
+ Flags=spare=0;
+}
+
+Module_Flag_Chunk::Module_Flag_Chunk(Chunk_With_Children* parent,const char* data,size_t)
+:Chunk(parent,"MODFLAGS")
+{
+ Flags=*(int*)data;
+ data+=4;
+ spare=*(int*)data;
+}
+
+void Module_Flag_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *(int*)data_start=Flags;
+ data_start+=4;
+ *(int*)data_start=spare;
+
+}
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("MODZONE",Module_Zone_Chunk)
+
+Module_Zone_Chunk::Module_Zone_Chunk(Object_Module_Data_Chunk* parent)
+:Chunk(parent,"MODZONE")
+{
+ Zone=spare=0;
+}
+
+Module_Zone_Chunk::Module_Zone_Chunk(Chunk_With_Children* parent,const char* data,size_t)
+:Chunk(parent,"MODZONE")
+{
+ Zone=*(int*)data;
+ data+=4;
+ spare=*(int*)data;
+}
+
+void Module_Zone_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *(int*)data_start=Zone;
+ data_start+=4;
+ *(int*)data_start=spare;
+
+}
+
+///////////////////////////////////////
+
+RIF_IMPLEMENT_DYNCREATE("MODACOUS",Module_Acoustics_Chunk)
+
+Module_Acoustics_Chunk::Module_Acoustics_Chunk(Object_Module_Data_Chunk* parent)
+:Chunk(parent,"MODACOUS")
+{
+ env_index=-1; //negative means default environment acoustics
+ reverb=-1.0;
+ spare=0;
+}
+
+Module_Acoustics_Chunk::Module_Acoustics_Chunk(Chunk_With_Children* parent,const char* data,size_t)
+:Chunk(parent,"MODACOUS")
+{
+ env_index=*(int*)data;
+ data+=4;
+ reverb=*(float*)data;
+ data+=4;
+ spare=*(int*)data;
+}
+
+void Module_Acoustics_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *(int*)data_start=env_index;
+ data_start+=4;
+ *(float*)data_start=reverb;
+ data_start+=4;
+ *(int*)data_start=spare;
+
+}
+
+
+///////////////////////////////////////
+
+
+RIF_IMPLEMENT_DYNCREATE("OBJTRAK2",Object_Track_Chunk2)
+
+Object_Track_Chunk2::Object_Track_Chunk2(Object_Chunk * parent)
+: Chunk (parent, "OBJTRAK2")
+{
+ num_sections=0;
+ sections=0;
+ flags=timer_start=0;
+}
+
+Object_Track_Chunk2::~Object_Track_Chunk2()
+{
+ if(sections) delete sections;
+}
+
+void Object_Track_Chunk2::fill_data_block (char *data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *(int*)data_start=num_sections;
+ data_start+=4;
+
+ for(int i=0;i<num_sections;i++)
+ {
+ *(ChunkTrackSection*)data_start=sections[i];
+ data_start+=sizeof(ChunkTrackSection);
+ }
+
+ *(int*)data_start=flags;
+ data_start+=4;
+
+ *(int*)data_start=timer_start;
+
+
+
+}
+
+size_t Object_Track_Chunk2::size_chunk ()
+{
+ chunk_size = 12 + 12 +num_sections*sizeof(ChunkTrackSection) ;
+ return(chunk_size);
+}
+
+#if UseOldChunkLoader
+Object_Track_Chunk2::Object_Track_Chunk2 (Chunk_With_Children * parent,const char * data, size_t /*size*/)
+: Chunk (parent, "OBJTRAK2")
+{
+ num_sections=*(int*)data;
+ data+=4;
+
+ if(num_sections)
+ sections=new ChunkTrackSection[num_sections];
+ else
+ sections=0;
+
+ for(int i=0;i<num_sections;i++)
+ {
+ sections[i].quat_start.w=(*(int*)data)/65536.0;
+ data+=4;
+ sections[i].quat_start.x=(*(int*)data)/-65536.0;
+ data+=4;
+ sections[i].quat_start.y=(*(int*)data)/-65536.0;
+ data+=4;
+ sections[i].quat_start.z=(*(int*)data)/-65536.0;
+ data+=4;
+
+ sections[i].quat_end.w=(*(int*)data)/65536.0;
+ data+=4;
+ sections[i].quat_end.x=(*(int*)data)/-65536.0;
+ data+=4;
+ sections[i].quat_end.y=(*(int*)data)/-65536.0;
+ data+=4;
+ sections[i].quat_end.z=(*(int*)data)/-65536.0;
+ data+=4;
+
+
+ sections[i].pivot_start=*(ChunkVector*)data;
+ data+=sizeof(ChunkVector);
+ sections[i].pivot_end=*(ChunkVector*)data;
+ data+=sizeof(ChunkVector);
+ sections[i].object_offset=*(ChunkVector*)data;
+ data+=sizeof(ChunkVector);
+
+ sections[i].time_for_section=*(int*)data;
+ data+=sizeof(int);
+ sections[i].spare=*(int*)data;
+ data+=sizeof(int);
+
+
+ }
+
+ flags=*(int*)data;
+ flags|=TrackFlag_QuatProblemSorted;
+ data+=4;
+ spare2=*(int*)timer_start;
+
+
+}
+#else
+Object_Track_Chunk2::Object_Track_Chunk2 (Chunk_With_Children * parent,const char * data, size_t /*size*/)
+: Chunk (parent, "OBJTRAK2")
+{
+ num_sections=*(int*)data;
+ data+=4;
+
+ if(num_sections)
+ sections=new ChunkTrackSection[num_sections];
+ else
+ sections=0;
+
+ for(int i=0;i<num_sections;i++)
+ {
+ sections[i]=*(ChunkTrackSection*)data;
+ data+=sizeof(ChunkTrackSection);
+ }
+
+ flags=*(int*)data;
+ data+=4;
+ timer_start=*(int*)data;
+
+ if(!(flags & TrackFlag_QuatProblemSorted))
+ {
+ for(i=0;i<num_sections;i++)
+ {
+ ChunkQuat temp=sections[i].quat_start;
+ sections[i].quat_start.x=-temp.w;
+ sections[i].quat_start.y=temp.x;
+ sections[i].quat_start.z=temp.y;
+ sections[i].quat_start.w=-temp.z;
+
+ temp=sections[i].quat_end;
+ sections[i].quat_end.x=-temp.w;
+ sections[i].quat_end.y=temp.x;
+ sections[i].quat_end.z=temp.y;
+ sections[i].quat_end.w=-temp.z;
+ }
+ flags|=TrackFlag_QuatProblemSorted;
+ }
+
+}
+#endif
+
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("TRAKSOUN",Object_Track_Sound_Chunk)
+
+Object_Track_Sound_Chunk::Object_Track_Sound_Chunk(Chunk_With_Children* parent)
+:Chunk(parent,"TRAKSOUN")
+{
+ wav_name=0;
+ inner_range=5000;
+ outer_range=40000;
+ max_volume=127;
+ pitch=0;
+ flags=0;
+ index=0;
+}
+
+Object_Track_Sound_Chunk::Object_Track_Sound_Chunk(Chunk_With_Children* const parent,const char* data,size_t const )
+:Chunk(parent,"TRAKSOUN")
+{
+ inner_range=*(unsigned long*)data;
+ data+=4;
+ outer_range=*(unsigned long*)data;
+ data+=4;
+
+ max_volume=*(int*)data;
+ data+=4;
+ pitch=*(int*)data;
+ data+=4;
+ flags=*(int*)data;
+ data+=4;
+ index=*(int*)data;
+ data+=4;
+
+ wav_name=new char[strlen(data)+1];
+ strcpy(wav_name,data);
+
+}
+
+Object_Track_Sound_Chunk::~Object_Track_Sound_Chunk()
+{
+ if(wav_name) delete wav_name;
+}
+
+void Object_Track_Sound_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ *(unsigned long*)data_start=inner_range;
+ data_start+=4;
+ *(unsigned long*)data_start=outer_range;
+ data_start+=4;
+
+ *(int*)data_start=max_volume;
+ data_start+=4;
+ *(int*)data_start=pitch;
+ data_start+=4;
+ *(int*)data_start=flags;
+ data_start+=4;
+ *(int*)data_start=index;
+ data_start+=4;
+
+ strcpy(data_start,wav_name);
+
+}
+
+size_t Object_Track_Sound_Chunk::size_chunk()
+{
+ chunk_size=12+24;
+ chunk_size+=(strlen(wav_name)+4)&~3;
+ return chunk_size;
+}
+///////////////////////////////////////
+
+RIF_IMPLEMENT_DYNCREATE("ALTLOCAT",Object_Alternate_Locations_Chunk)
+
+Object_Alternate_Locations_Chunk::Object_Alternate_Locations_Chunk(Chunk_With_Children* parent,const char* data,size_t)
+:Chunk(parent,"ALTLOCAT")
+{
+ group=*(int*) data;
+ data+=4;
+ spare2=*(int*) data;
+ data+=4;
+
+ num_locations=*(int*) data;
+ data+=4;
+
+ if(num_locations)
+ locations=new AltObjectLocation[num_locations];
+ else
+ locations=0;
+
+ for(int i=0;i<num_locations;i++)
+ {
+ locations[i] = *(AltObjectLocation*) data;
+ data+=sizeof(AltObjectLocation);
+ }
+}
+
+Object_Alternate_Locations_Chunk::Object_Alternate_Locations_Chunk(Chunk_With_Children* parent)
+:Chunk(parent,"ALTLOCAT")
+{
+ num_locations=0;
+ locations=0;
+ group=spare2=0;
+}
+
+Object_Alternate_Locations_Chunk::~Object_Alternate_Locations_Chunk()
+{
+ if(locations) delete [] locations;
+}
+
+void Object_Alternate_Locations_Chunk::fill_data_block(char* data)
+{
+ strncpy (data, identifier, 8);
+ data += 8;
+ *((int *) data) = chunk_size;
+ data += 4;
+
+ *(int*)data=group;
+ data+=4;
+
+ *(int*)data=spare2;
+ data+=4;
+
+
+ *(int*) data = num_locations;
+ data+=4;
+
+ for(int i=0;i<num_locations;i++)
+ {
+ *(AltObjectLocation*)data=locations[i];
+ data+=sizeof(AltObjectLocation);
+ }
+
+}
+
+size_t Object_Alternate_Locations_Chunk::size_chunk()
+{
+ chunk_size=24+num_locations*sizeof(AltObjectLocation);
+ return chunk_size;
+}
+
+
+/////////////////////////////////////////
+//class Object_Project_Data_Chunk
+
+RIF_IMPLEMENT_DYNCREATE("OBJPRJDT",Object_Project_Data_Chunk)
+
+CHUNK_WITH_CHILDREN_LOADER("OBJPRJDT",Object_Project_Data_Chunk)
+
+/*
+Children for Object_Project_Data_Chunk :
+
+"MAPBLOCK" Map_Block_Chunk
+"STRATEGY" Strategy_Chunk
+"AVPSTRAT" AVP_Strategy_Chunk
+*/