123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /* GCSx
- ** LOAD.H
- **
- ** File loading only
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** 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; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #ifndef __GCSx_LOAD_H_
- #define __GCSx_LOAD_H_
- // Structures used internally
- struct BlockHeader {
- Uint32 version; // 0 if not read
- Uint32 headerSize;
- Uint32 contentSize;
- Uint32 compression;
- };
- struct BlockInfo {
- // Current info
- Uint32 offset; // 0 if never written to file
- Uint32 size;
- Uint32 type;
- class LoadOnly* object; // Our object that can read this block
- BlockHeader header; // Header, if not read, version is 0
-
- // New info used when saving to a new file so we don't
- // overwrite old info until save is confirmed
- Uint32 newOffset;
- Uint32 newSize;
- BlockHeader newHeader;
- };
- // Interface for our files that we pass to objects- no seeking except rewind
- class FileRead {
- private:
- class File* filePtr;
- int startOffset;
- int totalSize;
- Uint32 version;
- Uint32 compression;
- int currentOffset;
- int bytesRead;
- // For readStr
- enum {
- COPY_BUFFER_SIZE = 8192,
- };
- static char copyBuffer[COPY_BUFFER_SIZE + 1];
- // ZLIB compression method
- z_stream* zlibStream;
- int zlibStreamInit;
- Byte* zlibBufferIn;
- Uint32 zlibOrigSize;
- enum { ZLIB_BUFFER_SIZE = 8192 };
- void zlibNextBuffer() throw_File;
- public:
- // Doesn't assume filePtr is seeked properly or anything like that, on ANY read
- FileRead(class File* myFilePtr, int offset, int size, Uint32 myVersion, Uint32 myCompression) throw_File;
- ~FileRead();
-
- // What version of data?
- Uint32 getVersion() const { return version; }
-
- // How large is our data, total? (uncompressed)
- int getSize() const;
- // Any more data for us? (actually returns total bytes remaining)
- int moreData() const;
- // Read X more bytes; throws an exception if size is greater than the bytes
- // we've been allocated to read
- void read(void* ptr, int size) throw_File;
- Uint32 readInt() throw_File;
- void readIntBulk(Uint32* ptr, int count) throw_File;
- Uint16 readInt16() throw_File;
- Uint8 readInt8() throw_File;
- // NON-REENTRANT
- void readStr(std::string& str) throw_File;
- void rewind() throw_File;
- };
- // Interface for objects that just load
- class LoadOnly {
- public:
- // Generic informational functions, so we can also use LoadOnly as
- // a generic "GCSx object" supertype
- virtual int getId() const = 0;
- // Returns BLOCKTYPE_UNUSED if not a directly writable object
- virtual int getBlockType() const = 0;
-
- // Load header
- // Discard FileRead object when done
- virtual void loadHeader(class FileRead* file) = 0;
-
- // Content, by choice of the object, can be cached
- // The FileRead pointer will be good any time the object
- // wishes to load as long as the object doesn't modify
- // itself; object MUST DEALLOCATE this pointer when done
- // Object MUST DEALLOCATE even if exception/throw!
- virtual void loadContent(class FileRead* file) = 0;
- // Typically used internally, and if excepts, should leave uncached entirely
- virtual void cacheLoad() = 0; // (ensures not cached)
- virtual int isContentCached() const = 0;
-
- // Mark or unmark an object as being used; lock should
- // be incremental; return current lock value, > 0 is locked,
- // 0 is locked. This should also load from cache. Content
- // cannot be returned to cache until unlocked down to 0.
- // This is the only required use of lock (to prevent cacheing)
- // Other functions do NOT need to check cache- outside sources
- // should call markLock appropriately.
- virtual int markLock() = 0;
- virtual int markUnlock() = 0;
- virtual int isLocked() const = 0;
- };
- // World file storage- All data is stored LITTLE ENDIAN
- // Bytes 00-03 GCSx
- // Bytes 04-19 Version, 4 int32s major minor bugfix build
- // Bytes 20-23 Reserved (may become pointer within file to world info block)
- // Bytes 24-27 Reserved
- // Bytes 28-31 Number of blocks
- // Per block-
- // Bytes 00-03 Offset, 0 if no block in this spot
- // Bytes 04-07 Overall block size as stored, 0 if no block in this spot
- // Bytes 08-11 Block type, 0 if no block or if block is unused and available
- // Bytes 12-15 Reserved
- // At block offset-
- // Bytes 00-03 Block version code
- // Bytes 04-07 Size of header data
- // Bytes 08-11 Size of (compressed) content data
- // Bytes 12-15 Compression type (applies to content only)
- // Bytes 16- Header data, followed by content data
- class WorldFileLoad {
- protected:
- Uint32 fileVersion[4];
- Uint32 numBlocks;
- std::vector<BlockInfo> blocks; // BlockInfo id is index
- class File* filePtr;
- const std::string* filename;
- Uint32 scanNextBlock;
-
- static const char* correctCookie;
- static const Uint32 currentVersion[4];
-
- WorldFileLoad();
-
- public:
- // Block types
- enum {
- // Unused blocks can't be claimed, but their position/size
- // are still relevant
- // Do not change the order/numbering of these!
- BLOCKTYPE_UNUSED = 0,
- BLOCKTYPE_WORLDINFO = 1,
- BLOCKTYPE_TILESET = 2,
- BLOCKTYPE_SCENE = 3,
- BLOCKTYPE_ANIMGROUP = 4,
- BLOCKTYPE_SCRIPT = 5,
- BLOCKTYPE_FOLDER = 6,
- };
-
- // Compression types
- enum {
- BLOCKCOMPRESSION_NONE = 0,
- BLOCKCOMPRESSION_ZLIB = 1,
- };
- // Pointer must remain valid
- WorldFileLoad(const std::string* openFile, int mode = File::FILE_MODE_READ) throw_File; // Open existing
- virtual ~WorldFileLoad(); // Closes the file
-
- // Use this to loop through all in-use blocks, to load
- // This initializes or "rewinds" the nextBlock() sequence.
- // You may loop through as many times as needed, but cannot claimBlock more
- // than once per block
- void scanBlocks();
-
- // Returns true if there was a "next" block- returns type and
- // a unique ID for the next block; construct object and tell
- // the object to load the block by it's ID; This skips unused blocks
- int nextBlock(Uint32* getType, Uint32* getID);
-
- // An object uses this to "claim" a block by it's ID; it will
- // then have both load functions called; cannot claim an id
- // more than once
- void claimBlock(Uint32 id, LoadOnly* claimingObject) throw_File;
- };
- #endif
|