summaryrefslogtreecommitdiff
path: root/src/win95/chunk.hpp
diff options
context:
space:
mode:
authorSteven Fuller <relnev@icculus.org>2001-07-01 00:55:22 +0000
committerPatryk Obara <dreamer.tan@gmail.com>2019-08-20 02:09:04 +0200
commit2186d5f3f95cd74a070a490d899291648d58667a (patch)
tree55241a1afa3e1a22e0b6593a8dead0b703800f44 /src/win95/chunk.hpp
parent218ca90543758a20ac326e444ca0643174ca7384 (diff)
Initial revision
Diffstat (limited to 'src/win95/chunk.hpp')
-rw-r--r--src/win95/chunk.hpp687
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+