/*! \file basestrm.h \brief The interface for the various streams that ASC offers, like file and memory streams. */ // $Id: basestrm.h,v 1.62 2006/04/18 19:29:29 mbickel Exp $ // // $Log: basestrm.h,v $ // Revision 1.62 2006/04/18 19:29:29 mbickel // Fixes to the build system // // Revision 1.61 2005/04/29 17:57:12 mbickel // Prepared 1.16 release // Added object translation // // Revision 1.60 2005/04/24 10:09:30 mbickel // Added object growth // Updated version numbers // Fixed mine and object removal // // Revision 1.59 2004/05/29 15:07:37 mbickel // Fixed maps // Fixed crash with asc.cache // ai speed up // // Revision 1.58 2004/05/16 11:28:00 mbickel // Speed up of startup loading by using a cache file // // Revision 1.57 2004/01/25 19:44:16 mbickel // Many, many bugfixes // Removed #pragma pack whereever possible // // Revision 1.56 2003/11/16 21:46:39 mbickel // Some cleanup and restructuring // Fixed: newly produced units could not leave building // // Revision 1.55 2003/06/01 15:03:16 mbickel // Some updates to the build system for FreeBSD // // Revision 1.54 2003/05/01 18:02:22 mbickel // Fixed: no movement decrease for cargo when transport moved // Fixed: reactionfire not working when descending into range // Fixed: objects not sorted // New map event: add object // // Revision 1.53 2003/03/20 10:08:29 mbickel // KI speed up // mapeditor: added clipboard // Fixed movement issues // // Revision 1.52 2002/10/02 20:21:00 mbickel // Many tweaks to compile ASC with gcc 3.2 (not completed yet) // // Revision 1.51 2002/02/14 20:58:13 mbickel // Started integration of paragui // // Revision 1.50 2002/01/29 20:42:16 mbickel // Improved finding of files with relative path // Added wildcards to music playlist files // // Revision 1.49 2001/10/21 13:16:59 mbickel // Cleanup and documentation // // Revision 1.48 2001/10/08 14:44:22 mbickel // Some cleanup // // Revision 1.47 2001/10/08 14:12:20 mbickel // Fixed crash in AI // Speedup of AI // Map2PCX improvements // Mapeditor usability improvements // // Revision 1.46 2001/08/27 21:03:55 mbickel // Terraintype graphics can now be mounted from any number of PNG files // Several AI improvements // // Revision 1.45 2001/07/28 11:19:10 mbickel // Updated weaponguide // moved item repository from spfst to itemrepository // // Revision 1.44 2001/07/27 21:13:34 mbickel // Added text based file formats // Terraintype and Objecttype restructured // // Revision 1.43 2001/07/14 13:15:17 mbickel // Rewrote sound handling // // Revision 1.42 2001/06/14 14:46:46 mbickel // The resolution of ASC can be specified in the configuration file // The fileselect dialog box shows the file's location // new ascmap2pcx param: outputdir // // Revision 1.41 2001/05/18 22:30:30 mbickel // The data file is now installed in the correct directory // If the installation directory is changed with configure, the new path // will now be compiled directly into ASC // // Revision 1.40 2001/05/16 23:21:01 mbickel // The data file is mounted using automake // Added sgml documentation // Added command line parsing functionality; // integrated it into autoconf/automake // Replaced command line parsing of ASC and ASCmapedit // // Revision 1.39 2001/02/28 14:10:05 mbickel // Added some small editors to linux makefiles // Added even more dirty hacks to basegfx: some more truecolor functions // // Revision 1.38 2001/02/26 22:03:18 mbickel // Some adjustments for Watcom C++ // // Revision 1.37 2001/02/26 21:14:30 mbickel // Added two small editors to the linux makefiles // Added some more truecolor hacks to the graphics engine // // Revision 1.36 2001/02/18 15:37:02 mbickel // Some cleanup and documentation // Restructured: vehicle and building classes into separate files // tmap, tfield and helper classes into separate file (gamemap.h) // basestrm : stream mode now specified by enum instead of int // // Revision 1.35 2001/02/11 11:39:28 mbickel // Some cleanup and documentation // // Revision 1.34 2001/01/28 14:04:03 mbickel // Some restructuring, documentation and cleanup // The resource network functions are now it their own files, the dashboard // as well // Updated the TODO list // // Revision 1.33 2001/01/04 15:13:30 mbickel // configure now checks for libSDL_image // AI only conquers building that cannot be conquered back immediately // tfindfile now returns strings instead of char* // // Revision 1.32 2000/12/21 11:00:44 mbickel // Added some code documentation // // Revision 1.31 2000/11/09 17:48:46 mbickel // The size of a stream can now be queried // PCX loader (in C) can now load unpatched images provided they are not // compressed /* This file is part of Advanced Strategic Command; http://www.asc-hq.de Copyright (C) 1994-1999 Martin Bickel and Marc Schellenberger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef basestrmH #define basestrmH #include #include #include #include #include #include "global.h" #include "basestreaminterface.h" #include "lzw.h" #include "errors.h" #include "tpascal.inc" #include "simplestream.h" #ifdef USE_SYSTEM_BZ2 #include #else extern "C" { #include "libs/bzlib/bzlib.h" } #endif const int maxFileStringSize = 10000; // is used for some character arrays class CharBuf { public: int size; char* buf; CharBuf ( void ); CharBuf ( int _size ); void resize ( int newsize ); ~CharBuf(); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////// Exceptions /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class tcompressionerror : public ASCmsgException { public: tcompressionerror ( const ASCString& msg, int returncode ) : ASCmsgException ( msg ) { message += "\n the returncode is "; message += strrr ( returncode ); }; }; class toutofmem : public ASCexception { public: int required; toutofmem ( int m ) ; }; class tbufferoverflow : public ASCexception { }; class tinvalidversion : public tfileerror { public: tinvalidversion ( const ASCString& fileName, int ex, int fnd ); const int expected; const int found; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////// dynamic data structures /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template class dynamic_array { protected: int blksize; int size; T* buf; virtual void resize ( int newsize ); int maxaccessed; public: dynamic_array ( void ); dynamic_array ( int sze ); virtual ~dynamic_array(); T& operator[]( int a ); int getlength( void ); void reset ( void ); }; template class dynamic_initialized_array : public dynamic_array { T initval; protected: virtual void resize ( int newsize ); public: dynamic_initialized_array ( T ival ); dynamic_initialized_array ( T ival, int sze ); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////// Streams /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class MemoryStreamCopy : public tnstream { void* buf; int size; int pos; public: MemoryStreamCopy ( pnstream stream ); ~MemoryStreamCopy ( ); void writedata ( const void* buf, int size ); int readdata ( void* buf, int size, bool excpt = true ); void seek ( int newpos ); int getPosition ( void ) { return pos; }; int getSize ( void ) { return size; }; ASCString getLocation(); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef pmemorystreambuf_defined #define pmemorystreambuf_defined typedef class tmemorystreambuf* pmemorystreambuf; typedef class tmemorystream* pmemorystream; #endif class tmemorystreambuf { friend class tmemorystream; bool initialized; int used; int allocated; int dummy[10]; char* buf; public: tmemorystreambuf ( void ); void writetostream ( pnstream stream ); void readfromstream ( pnstream stram ); void clear() { used= 0; }; ~tmemorystreambuf ( ); }; class tmemorystream : public tnstream { protected: int blocksize; char* zeiger; IOMode _mode; int actmempos; pmemorystreambuf buf; public: tmemorystream ( pmemorystreambuf lbuf, IOMode mode ); virtual void writedata ( const void* nbuf, int size ); virtual int readdata ( void* nbuf, int size, bool excpt = true ); int dataavail ( void ); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class tlzwstreamcompression { // ********** For writing CountType LZWTotBytesIn; /* no. data bytes in input file */ CountType LZWTotBytesOut; /* no. data bytes in output file */ CountType LZWCurrBytesIn; /* no. data bytes in current frame */ CountType LZWCurrBytesOut; /* no. data bytes in current frame */ unsigned LZWBestRatio; /* best ratio we've had */ unsigned LZWLastRatio; /* last ratio we saw */ /* structure for the data dictionary */ struct Wdictionary { unsigned char c; CodeType code; CodeType parent; }; struct Wdictionary *wdictionary; void LZWOut ( CodeType code ); IndexType LZWFind ( CodeType currcode, int in ); // deklarationen, die in LZWencode drinwaren int in; CountType i; CodeType currcode; IndexType idx; int currcodeloaded; //*********** for reading /* structure for data dictionary */ struct Rdictionary { unsigned char c; CodeType parent; }; /* decode buffer */ unsigned char *DecodeBuffer; unsigned DecodeBufferSize ; unsigned int inchar; unsigned count; CodeType oldcode; /* data rdictionary */ struct Rdictionary *rdictionary; CodeType incode; void LZWIn ( void ); unsigned LZWLoadBuffer ( unsigned count, CodeType code ); int readcnt; // ******* rle uncompression char rlestartbyte; char rlenum; char rledata; // ******* general IndexType freecode; int initread; int initwrite; void initreading( void ); void initwriting( void ); protected: typedef deque CDQ; queue tempbuf; enum tmode { none, reading, writing, readingdirect, readingrle }; tmode mode; public: void writedata ( const void* buf, int size ); int readdata ( void* buf, int size, bool excpt = true ); virtual int readlzwdata ( void* buf, int size, bool excpt = true ) = 0; virtual void writelzwdata ( const void* buf, int size ) = 0; tlzwstreamcompression ( void ); virtual ~tlzwstreamcompression ( void ); protected: void close( void ); }; class t_compressor_stream_interface { public: virtual void writecmpdata ( const void* buf, int size ) = 0; virtual int readcmpdata ( void* buf, int size, bool excpt = true ) = 0; }; /* class t_compressor_2ndbuf_filter : public t_compressor_stream_interface { t_compressor_stream_interface *stream; typedef deque CDQ; queue _queue; public: t_compressor_2ndbuf_filter ( t_compressor_stream_interface* strm ); virtual void writecmpdata ( const void* buf, int size ); virtual int readcmpdata ( void* buf, int size, bool excpt = true ); void insert_data_into_queue ( const void* buf, int size ); virtual ~t_compressor_2ndbuf_filter() {}; }; */ typedef t_compressor_stream_interface *p_compressor_stream_interface; class libbzip_compression { bz_stream bzs; char* outputbuf; int outputbufsize; p_compressor_stream_interface stream; public: void close_compression ( void ); void writedata ( const void* buf, int size ); libbzip_compression ( p_compressor_stream_interface strm ); virtual ~libbzip_compression ( ); }; class libbzip_decompression { bz_stream bzs; char* inputbuf; int inputbufsize; int inputbufused; int inputbufread; p_compressor_stream_interface stream; public: int readdata ( void* buf, int size, bool excpt = true ); libbzip_decompression ( p_compressor_stream_interface strm ); virtual ~libbzip_decompression ( ); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class tanycompression : public t_compressor_stream_interface, public tlzwstreamcompression { typedef deque CDQ; queue _queue; libbzip_compression* bzip_compress; libbzip_decompression* bzip_decompress; int mmd; int status; protected: virtual int readlzwdata ( void* buf, int size, bool excpt = true ); virtual void writelzwdata ( const void* buf, int size ); void close_compression ( void ); public: tanycompression ( int md ); void init ( void ); void writedata ( const void* buf, int size ); int readdata ( void* buf, int size, bool excpt = true ); ~tanycompression ( ); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* class tn_lzw_bufstream : public tnbufstream, protected tlzwstreamcompression { public: void writedata ( const void* buf, int size ); int readdata ( void* buf, int size, bool excpt = true ); int readlzwdata ( void* buf, int size, bool excpt = true ); void writelzwdata ( const void* buf, int size ); ~tn_lzw_bufstream(); }; */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class tn_lzw_file_buf_stream : public tn_file_buf_stream, protected tanycompression { public: tn_lzw_file_buf_stream ( const char* name, IOMode mode ) : tn_file_buf_stream ( name, mode ) , tanycompression ( mode ) { tanycompression :: init ( ); } ; void writedata ( const void* buf, int size ); int readdata ( void* buf, int size, bool excpt = true ); int readcmpdata ( void* buf, int size, bool excpt = true ); void writecmpdata ( const void* buf, int size ); ~tn_lzw_file_buf_stream(); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// typedef class tncontainerstream* pncontainerstream; class tn_c_lzw_filestream : public tnstream, protected tanycompression { tn_file_buf_stream *strm; pncontainerstream containerstream; int inp; ASCString fname; ASCString location; protected: int readcmpdata ( void* buf, int size, bool excpt = true ); void writecmpdata ( const void* buf, int size ); public: tn_c_lzw_filestream ( const ASCString& name, IOMode mode ); void writedata ( const void* buf, int size ); int readdata ( void* buf, int size, bool excpt = true ); virtual ~tn_c_lzw_filestream ( ); virtual time_t get_time ( void ); virtual int getSize( void ); ASCString getLocation(); }; typedef tn_c_lzw_filestream tnfilestream ; typedef tnfilestream* pnfilestream ; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct tcontainerindex { char* name; int start; // das erste Byte int end; // das letzte Byte }; class ContainerIndexer { public: virtual void addfile ( const char* filename, const pncontainerstream stream, int directoryLevel ) = 0; }; class tncontainerstream : public tn_file_buf_stream { tcontainerindex* index; tcontainerindex* actfile; int containerfilepos; int num; int actname; public: tncontainerstream ( const char* containerfilename, ContainerIndexer* indexer, int directoryLevel ); void opencontainerfile ( const char* name ); int getcontainerfilesize ( const char* name ); int readcontainerdata ( void* buf, int size, bool excpt = true ); void closecontainerfile ( void ); char* getfirstname ( void ); char* getnextname ( void ); virtual ~tncontainerstream (); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class ContainerCollector : public ContainerIndexer { public: struct FileIndex { char* name; pncontainerstream container; int directoryLevel; }; protected: dynamic_array index[256]; // not very efficient, but who cares :-) dynamic_array container; int containernum; struct { int alpha; int index; } namesearch; // next entry to return public: ContainerCollector ( void ); void init ( const char* wildcard ); void addfile ( const char* filename, const pncontainerstream stream, int directoryLevel ); // pncontainerstream getfile ( const char* filename ); FileIndex* getfile ( const char* filename ); FileIndex* getfirstname ( void ); FileIndex* getnextname ( void ); virtual ~ContainerCollector(); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //! Searching for files class tfindfile { public: struct FileInfo { ASCString name; int directoryLevel; bool isInContainer; ASCString location; int size; int date; void read ( tnstream& stream ) { int version = stream.readInt(); if ( version != 1 ) throw tinvalidversion( stream.getDeviceName(), 1, version ); name = stream.readString(); directoryLevel = stream.readInt(); isInContainer = stream.readInt() != 0; location = stream.readString(); size = stream.readInt(); date = stream.readInt(); }; void write ( tnstream& stream ) const { stream.writeInt(1 ); // version stream.writeString ( name ); stream.writeInt( directoryLevel ); stream.writeInt ( isInContainer ); stream.writeString ( location ); stream.writeInt ( size ); stream.writeInt ( date ); }; }; private: vector fileInfo; int found; int act; public: enum SearchPosition { DefaultDir, CurrentDir, PrimaryDir, AllDirs }; enum SearchTypes { InsideContainer, OutsideContainer, All }; /** Searches for files matching the wildcard name in all search paths specified for ASC and inside the ASC archive files. If name contains a relative directory entry ( like music / *.mp3 ), searchPosition specifies, which directories will be searched for the file. Note that "Current" may be problemativ in unix environments, because the program may be started from any directory. */ tfindfile ( ASCString name, SearchPosition searchPosition = DefaultDir, SearchTypes searchTypes = All); /** Returns the next entry of the internal file list. Optionally, some additional information about the file can be returned: \param loc contains the number of the directory. ASC can search several directories for files. These directories are specified in the ASC configuration file and CGameOptions \param inContainer returns whether the file is inside a ASC archive file ( like main.con ) \param location contains the directory this file resides in */ ASCString getnextname ( int* loc = NULL, bool* inContainer = NULL, ASCString* location = NULL ); bool getnextname ( FileInfo& fi ); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "basetemp.h" extern const char* asc_configurationfile; extern const int maxfilenamelength; extern int compressrle ( const void* p, void* q); /** checks whether the regular expression pat matches the string str . This functions only understands dos/windows style wildcards: * and ? */ extern bool patimat (const char *pat, const char *str, bool forceCaseInsensitivity = false ); extern int checkforvaliddirectory ( char* dir ); extern char* getnextfilenumname ( const char* first, const char* suffix, int num = -1 ); #define writedata2(a) writedata ( &(a), sizeof(a) ) #define readdata2(a) readdata ( &(a), sizeof(a) ) //! does a file s exist (wildcards allowed) extern bool exist ( const ASCString& s ); extern time_t get_filetime ( const char* devicename ); extern void opencontainer ( const char* wildcard ); extern const char* containermagic; extern const char* filereadmode; extern const char* filewritemode; extern const char* filereadmodetext; extern const char* filewritemodetext; extern int verbosity; //! This class handles filenames. All operations that work on filenames will be added here class FileName : public ASCString { public: /** return the suffix of the file or an empty string if the file doesn't have a suffix. The suffix is the part of the filename after its last period. */ ASCString suffix(); FileName& operator= ( const ASCString& s ) { ASCString::operator=(s); return *this;}; FileName() {}; FileName( const ASCString& s ) : ASCString ( s ) {}; }; extern const char pathdelimitter; extern const char* pathdelimitterstring; extern int filesize( char *name); extern void addSearchPath ( const char* path ); extern void appendbackslash ( char* string ); extern void appendbackslash ( ASCString& string ); extern char* constructFileName( char* buf, int directoryLevel, const char* path, const char* filename ); extern int directoryExist ( const char* path ); extern char* extractPath ( char* buf, const char* filename ); extern char* extractFileName ( char* buf, const char* filename ); extern ASCString extractFileName ( const ASCString& filename ); extern ASCString extractFileName_withoutSuffix ( const ASCString& filename ); extern int createDirectory ( const char* name ); extern int getSearchPathNum(); extern ASCString getSearchPath ( int i ); //! converts path delimitters from foreign operating systems to the ones used by the current operating system. On Linux, this function converts backslashes to slashes, on Windows vice versa extern void convertPathDelimitters ( ASCString& path ); #ifdef _SDL_ #include extern SDL_RWops *SDL_RWFromStream( pnstream stream ); #endif #endif