diff options
Diffstat (limited to 'src/win95/chunk.hpp')
| -rw-r--r-- | src/win95/chunk.hpp | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/src/win95/chunk.hpp b/src/win95/chunk.hpp new file mode 100644 index 0000000..e7afcb4 --- /dev/null +++ b/src/win95/chunk.hpp @@ -0,0 +1,687 @@ +// Chunk library + +#ifndef _chunk_hpp +#define _chunk_hpp 1 + + +#if engine + + #include "3dc.h" + #include "mem3dc.h" // for debug new and delete + + + #include "inline.h" + +#if SupportModules + + #include "module.h" + +#endif + + #include "list_tem.hpp" + + +#endif + +#if cencon + +#include "AFXWIN.H" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#define my_new DEBUG_NEW +#else +#define my_new new +#endif + +#include "list_tem.hpp" + +#endif + +#if objedit || sprite_edit || ANIMEXP +#include "StdAfx.h" +#include "list_tem.hpp" +#endif + +#if shpedit +#include "stdafx.h" +#include "list_tem.hpp" +#endif + +#if standard +#include "advwin32.h" +#include <windows.h> +#include "list_tem.hpp" +#endif + + +#define CHUNK_FAILED_ON_LOAD -1 +#define CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED -2 +#define CHUNK_FAILED_ON_WRITE -3 +#define CHECK_FAILED_NOT_OPEN -4 + +#define DisableLock 1 + +#define GENERAL_FLAG_LOCKED 0x0000001 + +// Non class functions ( only one as yet ) + +// The function will return a list of file pointers +// for the starting position of each chunk within a chunk +// File pointers are offset from the start of the file. + +// we start at the header of the chunk we are in +// so that we can stop at the end of the chunk + +#if cencon +extern char users_name[]; +#endif + +#ifndef RIFF_OPTIMIZE // define this to get compiler errors where you are calling the old slow functions +extern List<int> list_chunks_in_file (HANDLE &, const char * chunk_id); +#endif +extern void list_chunks_in_file (List<int> * pList, HANDLE, const char * chunk_id); + +// Structures for interfacing with the outside application +// these are going to be basically very C-ee so that C +// functions can also read them + + + +// The basic chunk class structure is as follows +// +// Base_Chunk +// | | +// Chunk_With_Children Data Chunks +// | +// File_Chunk +// + +// Most chunk classes are either derived from the Chunk +// class or the Chunk_With_Children class. + +// A chunk with data is derived from the Chunk class as follows + +// class Sample_Data_Chunk : public Chunk +// { +// public: +// +// // Constructors are placed either here or may be private +// // The constructors for most shape data chunks are private +// // as only the Shape_Chunk can call them. This is because +// // the shape chunk deals with the data. +// // +// // Any constuctor should initialise class chunk with the +// // correct identifier for the current chunk. +// // +// // There are normally two constructors - one for constructing +// // from interface data one for constructing from raw data. +// // +// // A destructor can also be placed here or may not be needed +// // +// // Any variables that are made available for the user should also +// // be placed here. +// // +// // The next three functions are vital for the io functions +// // +// virtual BOOL output_chunk (HANDLE &hand); +// // This function will write the chunk data to the file specified +// // by the windows file handle - hand. +// // +// virtual size_t size_chunk (); +// // This function will return the size of the chunk (including the header). +// // IT MUST SET the variable chunk_size to the size it returns +// // +// virtual fill_data_block (char * data_start); +// // This function will fill a data block with data. The data will be +// // the same as the file data. The data is assumed to be pre-allocated +// // with the size given by the size_chunk function. +// // +// } + +// A chunk with children is derived from the Chunk_With_Children class +// as follows +// +// class Sample_Chunk_With_Children : public Chunk +// { +// public: +// +// // Constructors may be used to construct child chunks from +// // interface data. A parsing constructor should be used for +// // constructing from raw data (look at Shape_Chunk). +// // +// // Any constructor should initialise class Chunk_With_Children with +// // the correct identifier for the current chunk. +// // +// // The Destructor does not need to destroy child chunks as the +// // Chunk_With_Children destructor will automatically do this. +// // +// // The three functions (size_chunk, output_chunk and fill_data_block) +// // are not needed as Chunk_With_Children can deal with these - but may +// // be put in. +// // +// } + +// +// + + +// The logic behind the locking is as follows. + +// There are two functions for locking and unlocking chunks +// these are currently only in the shape and object chunks + +// lock_chunk(File_Chunk &) +// will lock a chunk, this must only be called once +// and will return false if it tries to lock a chunk +// that has already been locked by anyone. + +// unlock_chunk (File_Chunk &, BOOL updatedyn) +// will unlock the chunk locally and in the file if it is not to be updated +// If it is to be updated, it will set the updated flag and +// the chunk can only be locked again once it is written to a file. + +// The user may call File_Chunk::update_file() whenever +// (either after every chunk update, or once a minute) +// Note that this fully unlocks locally locked chunks +// that are being written to the file. + +// Another function File_Chunk::update_chunks_from_file() +// will reload those chunks that have been externally upadted +// This must be done with care!! + +// The objects are associated with shapes primarily +// When a shape is being edited, a list of objects will +// be with that shape in the header. These objects will be locked +// also. + + + +/////////////////////////////////////////////// + +class Chunk +{ +public: + + //destructor + virtual ~Chunk (); + + // constructors + Chunk (class Chunk_With_Children * parent, const char * ident); + + virtual size_t size_chunk () = 0; + + virtual BOOL output_chunk (HANDLE &); + + virtual void fill_data_block (char * data_start) = 0; + + // this function is virtual, but will probably not be used elsewhere + virtual char * make_data_block_from_chunk (); + + + // Selective output functions, these are similar to the normal ones + // and will normally call the equivalents. + // special chunks will have there own functions which will only respond + // if they have a flag set + + virtual char * make_data_block_for_process(); + + virtual size_t size_chunk_for_process(); + + virtual void fill_data_block_for_process(char * data_start); + + // these functions are virtual, but will only be used sparingly + + virtual void prepare_for_output() + {} + + virtual void post_input_processing() + {} + + const char * identifier; + + int error_code; + + // this allows chunks with children to trap miscellaneous chunks + // that shouldn't be miscellaneous !!! + virtual BOOL r_u_miscellaneous() + { return FALSE; } + + static void Register(const char* idChunk,const char* idParent ,Chunk * (* pfnCreate) (Chunk_With_Children* parent,const char* data) ); + +private: + + // copy - private to stop chunks + // from being copied + Chunk (const Chunk &); + // ditto + void operator=(const Chunk &); + + // pointers to siblings + + friend class Chunk_With_Children; + friend class Sprite_Header_Chunk; // sprite updating needs to scan through all child chunks + friend class File_Chunk; + friend class RIF_File_Chunk; + friend class Shape_Chunk; + + Chunk * next; + Chunk * previous; + + // identifier store + + char identifier_store[9]; + +protected: + + size_t chunk_size; + + // pointer to parent + class Chunk_With_Children * parent; + +public : + + class Chunk_With_Children * GetRootChunk(void); + class Chunk_With_Children const * GetRootChunk(void) const; + +}; + + +/////////////////////////////////////////////// + +class Miscellaneous_Chunk : public Chunk +{ +public: + + Miscellaneous_Chunk (Chunk_With_Children * parent, const char * identifier, + const char * _data, size_t _data_size); + + + virtual ~Miscellaneous_Chunk (); + + virtual size_t size_chunk () + { + return (chunk_size = (data_size + 12)); + } + + virtual void fill_data_block (char * data_start); + + const size_t data_size; + const char * const data; + + // this allows chunks with children to trap miscellaneous chunks + // that shouldn't be miscellaneous !!! + virtual BOOL r_u_miscellaneous() + { return TRUE; } + +private: + + char * data_store; + +}; + + +/////////////////////////////////////////////// + +class Chunk_With_Children : public Chunk +{ + +public: + + virtual ~Chunk_With_Children(); + + Chunk_With_Children (Chunk_With_Children * parent, const char * identifier) + : Chunk (parent, identifier), children (NULL) {} + + virtual size_t size_chunk (); + + virtual BOOL output_chunk (HANDLE &); + + virtual void fill_data_block (char * data_start); + + virtual void prepare_for_output(); + + virtual void post_input_processing(); + + // look for child chunk(s) + #ifndef RIFF_OPTIMIZE // define this to get compiler errors where you are calling the old slow functions + List<Chunk *> lookup_child (const char *) const; + #endif + void lookup_child (const char *,List<Chunk*>&) const; + Chunk* lookup_single_child(const char*) const; + unsigned count_children(char const *) const; + + // Selective output functions, these are similar to the normal ones + // and will normally call the equivalents. + // special chunks will have there own functions which will only respond + // if they have a flag set + + virtual size_t size_chunk_for_process(); + + virtual void fill_data_block_for_process(char * data_start); + + + Chunk* Chunk_With_Children::DynCreate(const char* data); + +protected: + + friend class Chunk; + friend class File_Chunk; + + // points to a doubly linked list + Chunk * children; + +}; + +///////////////////////////////////////////// +// macros to save typing for chunk with children loader + +extern Chunk * Parent_File; + +#define CHUNK_WITH_CHILDREN_LOADER_PARENT __parent + +#define CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \ +chunkclass::chunkclass(Chunk_With_Children * const CHUNK_WITH_CHILDREN_LOADER_PARENT, char const * __data, size_t const __size) \ +:Chunk_With_Children(CHUNK_WITH_CHILDREN_LOADER_PARENT,id) + +#define CHUNK_WITH_CHILDREN_LOADER_INIT_PT2 { \ + const char * const __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;} + +#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \ +chunkclass::chunkclass(Chunk_With_Children * const CHUNK_WITH_CHILDREN_LOADER_PARENT, char const * __data, size_t const __size) \ +:Lockable_Chunk_With_Children(CHUNK_WITH_CHILDREN_LOADER_PARENT,id) + +#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT2 { \ + const char * const __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;} + +#define CHUNK_WITH_CHILDREN_LOADER_INIT(id,chunkclass) \ + CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \ + CHUNK_WITH_CHILDREN_LOADER_INIT_PT2 + +#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT(id,chunkclass) \ + LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \ + LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT2 + +#define CHUNK_WITH_CHILDREN_LOADER_FOR(id,chunkclass) \ + else if (!strncmp(__data,id,8)){ \ + new chunkclass(this,__data+12,*(int *)(__data+8)-12); \ + __data += *(int *)(__data+8);} + +#define CHUNK_WITH_CHILDREN_LOADER_END \ + else { \ + new Miscellaneous_Chunk (this, __data, (__data + 12), (*(int *) (__data + 8)) -12 ); \ + __data += *(int *)(__data + 8);}}} + +// example: +// +// CHUNK_WITH_CHILDREN_LOADER_INIT("GAMEMODE",Environment_Game_Mode_Chunk) +// CHUNK_WITH_CHILDREN_LOADER_FOR("ENVPALET",Environment_Palette_Chunk) +// CHUNK_WITH_CHILDREN_LOADER_FOR("ENVTXLIT",Environment_TLT_Chunk) +// CHUNK_WITH_CHILDREN_LOADER_FOR("CLRLOOKP",Coloured_Polygons_Lookup_Chunk) +// CHUNK_WITH_CHILDREN_LOADER_FOR("RIFCHILD",RIF_Name_Chunk) +// CHUNK_WITH_CHILDREN_LOADER_END + +/////////////////////////////////////////////// +//macros for use in chunk construction from buffer, assume buffer is called data + +//read variable of type 'type' +#define CHUNK_EXTRACT(var,type) \ + var=*(type*)data; \ + data+=sizeof(type); + +//read 4 byte aligned string +#define CHUNK_EXTRACT_STRING(var) { \ + int __length=strlen(data); \ + if(__length) \ + { \ + var=new char[__length+1]; \ + strcpy(var,data); \ + } \ + else var=0; \ + data+=(__length+4) &~3 ;} + +//read array +//length is an int (filled in by macro) +//pointer is a pointer of type 'type' +#define CHUNK_EXTRACT_ARRAY(length,pointer,type){\ + CHUNK_EXTRACT(length,int) \ + if(length) \ + { \ + pointer=new type[length]; \ + for(int __i=0;__i<length;__i++) \ + { \ + CHUNK_EXTRACT(pointer[__i],type) \ + } \ + } \ + else pointer=0;} + + +//macros for use in fill_data_block + +#define CHUNK_FILL_START \ + strncpy (data, identifier, 8); \ + data += 8; \ + *(int *) data = chunk_size; \ + data += 4; + + +//write variable of type 'type' +#define CHUNK_FILL(var,type) \ + *(type*)data=var; \ + data+=sizeof(type); + +//write 4 byte aligned string +#define CHUNK_FILL_STRING(var) \ + if(var) strcpy(data,var); \ + else *data=0; \ + data+=(strlen(data)+4)&~3; + +#define CHUNK_FILL_ARRAY(length,pointer,type){\ + CHUNK_FILL(length,int) \ + for(int __i=0;__i<length;__i++) \ + { \ + CHUNK_FILL(pointer[__i],type); \ + } \ +} + +//macros for use in size_chunk + +#define CHUNK_SIZE_START \ + chunk_size = 12 + + +//size of variable of type 'type' +#define CHUNK_SIZE(var,type) \ + + sizeof(type) + +//size of 4 byte aligned string +#define CHUNK_SIZE_STRING(string) \ + + (string ? (strlen(string)+4)&~3 : 4) + +#define CHUNK_SIZE_ARRAY(length,pointer,type) \ + + sizeof(int) \ + + (length * sizeof(type)) + +#define CHUNK_SIZE_END ; + +/////////////////////////////////////////////// + +class GodFather_Chunk : public Chunk_With_Children +{ +public: + + GodFather_Chunk () + : Chunk_With_Children (NULL, "REBINFF2") + {} + + GodFather_Chunk (char * buffer, size_t size); +}; + + +/////////////////////////////////////////////// + +/* +Macro for adding chunk class to list of that can be created using DynCreate +Chunks registered this way can be created as a child of any chunk +*/ + +#define RIF_IMPLEMENT_DYNCREATE(idChunk,tokenClassName) _RIF_IMPLEMENT_DYNCREATE_LINE_EX(idChunk,tokenClassName,__LINE__) +#define _RIF_IMPLEMENT_DYNCREATE_LINE_EX(idChunk,tokenClassName,nLine) _RIF_IMPLEMENT_DYNCREATE_LINE(idChunk,tokenClassName,nLine) + +#define _RIF_IMPLEMENT_DYNCREATE_LINE(idChunk,tokenClassName,nLine) \ +static Chunk * RifCreateClassObject ## tokenClassName ##_## nLine (Chunk_With_Children* parent,const char* data) { \ + Chunk * pChunk = new tokenClassName(parent,data+12,(*(int *) (data + 8))-12); \ + return pChunk; \ +} \ + class RegisterRifChunkClass ## tokenClassName ##_## nLine { \ + public: RegisterRifChunkClass ## tokenClassName ##_## nLine () { \ + Chunk::Register(idChunk ,0,RifCreateClassObject ## tokenClassName ##_## nLine); \ + } \ +} rifcc ## tokenClassName ##_## nLine; + +/* +Macro for adding chunk class to list of that can be created using DynCreate. +Chunks registered this way will only be created as children of the parent named +*/ + + +#define RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT(idChunk,tokenClassName,idParent,parentClassName) _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE_EX(idChunk,tokenClassName,idParent,parentClassName,__LINE__) +#define _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE_EX(idChunk,tokenClassName,idParent,parentClassName,nLine) _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE(idChunk,tokenClassName,idParent,parentClassName,nLine) + +#define _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE(idChunk,tokenClassName,idParent,parentClassName,nLine) \ +static Chunk * RifCreateClassObject ## tokenClassName ##_## nLine (Chunk_With_Children* parent,const char* data) { \ + Chunk * pChunk = new tokenClassName((parentClassName*)parent,data+12,(*(int *) (data + 8))-12); \ + return pChunk; \ +} \ + class RegisterRifChunkClass ## tokenClassName ##_## nLine { \ + public: RegisterRifChunkClass ## tokenClassName ##_## nLine () { \ + Chunk::Register(idChunk ,idParent,RifCreateClassObject ## tokenClassName ##_## nLine); \ + } \ +} rifcc ## tokenClassName ##_## nLine; + + +/* +Load from buffer function for standard Chunk_With_Children +*/ + +#define CHUNK_WITH_CHILDREN_LOADER(id,chunk_class) \ +chunk_class::chunk_class(Chunk_With_Children * const parent,char const * __data, size_t const __size)\ +:Chunk_With_Children(parent,id)\ +{\ + 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);\ + }\ +} +/* +Load from buffer function for standard Lockable_Chunk_With_Children +*/ + +#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER(id,chunk_class) \ +chunk_class::chunk_class(Chunk_With_Children * const parent,char const * __data, size_t const __size)\ +:Lockable_Chunk_With_Children(parent,id)\ +{\ + 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);\ + }\ +} + + +//macros for forcing inclusion of chunk files from a library +#define FORCE_CHUNK_INCLUDE_START //not needed anymore + +#define FORCE_CHUNK_INCLUDE(filename)\ + extern int __Chunk_Include_##filename;\ + int* p__Chunk_Include_##filename =& __Chunk_Include_##filename; + +#define FORCE_CHUNK_INCLUDE_END //not needed anymore + + +#define FORCE_CHUNK_INCLUDE_IMPLEMENT(filename) int __Chunk_Include_##filename; + +/* +//eg. +FORCE_CHUNK_INCLUDE_START +FORCE_CHUNK_INCLUDE(mishchnk) +FORCE_CHUNK_INCLUDE(shpchunk) +FORCE_CHUNK_INCLUDE(obchunk) +FORCE_CHUNK_INCLUDE(envchunk) +FORCE_CHUNK_INCLUDE(animchnk) +FORCE_CHUNK_INCLUDE(hierchnk) +FORCE_CHUNK_INCLUDE(animobs) +FORCE_CHUNK_INCLUDE(sndchunk) +FORCE_CHUNK_INCLUDE(avpchunk) +FORCE_CHUNK_INCLUDE(bmpnames) +FORCE_CHUNK_INCLUDE(chunkpal) +FORCE_CHUNK_INCLUDE(dummyobjectchunk) +FORCE_CHUNK_INCLUDE(enumchnk) +FORCE_CHUNK_INCLUDE(enumsch) +FORCE_CHUNK_INCLUDE(fragchnk) +FORCE_CHUNK_INCLUDE(gsprchnk) +FORCE_CHUNK_INCLUDE(hierplace) +FORCE_CHUNK_INCLUDE(ltchunk) +FORCE_CHUNK_INCLUDE(oechunk) +FORCE_CHUNK_INCLUDE(pathchnk) +FORCE_CHUNK_INCLUDE(sprchunk) +FORCE_CHUNK_INCLUDE(strachnk) +FORCE_CHUNK_INCLUDE(toolchnk) +FORCE_CHUNK_INCLUDE(wpchunk) +FORCE_CHUNK_INCLUDE_END +*/ + +#endif // !included + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + |
