123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /* GCSx
- ** SAVE.H
- **
- ** File saving and loading
- */
- /*****************************************************************************
- ** 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_SAVE_H_
- #define __GCSx_SAVE_H_
- // Interface for our files that we pass to objects- no seeking!
- class FileWrite {
- private:
- File* filePtr;
- Uint32 compression;
- int bytesWritten;
-
- // Used for compression to go back and store original size
- int seekBegin;
-
- // ZLIB compression method
- z_stream* zlibStream;
- int zlibStreamInit;
- Byte* zlibBufferOut;
- enum { ZLIB_BUFFER_SIZE = 8192 };
- public:
- // Assumes filePtr is seeked properly, all writes must be sequential
- // Allowed to choose compression method
- FileWrite(File* myFilePtr, int noCompression = 0) throw_File;
- ~FileWrite();
- void write(const void* ptr, int size) throw_File;
- void writeInt(Uint32 value) throw_File;
- void writeIntBulk(const Uint32* ptr, int count) throw_File;
- void writeInt16(Uint16 value) throw_File;
- void writeInt8(Uint8 value) throw_File;
- void writeStr(const std::string& str) throw_File;
-
- int getSize() const { return bytesWritten; }
- Uint32 getCompression() const { return compression; }
- // Called when all writing is complete
- void flush() throw_File;
- };
- // Interface for objects that can save/load
- class SaveLoad : public virtual LoadOnly {
- public:
- // All objects are split into Header and Content
- // which are loaded and saved separately; If content
- // is modified, it should NOT be cached! New objects
- // MUST be marked as modified on both even if empty!
- virtual int isHeaderModified() const = 0;
- virtual int isContentModified() const = 0;
-
- // Save header, return version of data being saved
- // Can be called if header isn't modified, but may not
- // Discard FileWrite object when done
- virtual Uint32 saveHeader(FileWrite* file) = 0;
- // Must save; won't be called if content is cached
- // Can be called if content isn't modified, but may not
- // Discard FileWrite object when done
- virtual void saveContent(FileWrite* file) = 0;
-
- // Tells object save was successful, so modified flags
- // may be cleared
- virtual void saveSuccess() = 0;
-
- // After a successful save, all objects are called with
- // cachedContent() so it knows it can revert to being
- // cached if it desires; if oldData is true, the pointer
- // only points to the OLD cached content (a moved file, etc)
- // and the object is just being told to replace it's pointer
- // if it was already cached. If oldData is false,
- // object can choose to deallocate any data and go
- // back to being cached with this pointer
- // Object MUST DEALLOCATE this pointer when done or if not used
- // (as well as any previous cached content pointer it had)
- virtual void cachedContent(FileRead* file, int oldData) = 0;
- };
- class WorldFile : public WorldFileLoad {
- private:
- std::vector<SaveLoad*> blockSaves; // If block is saveable also, here's the ptr
- int inSaving; // If we're saving right now; so we don't try to resave on a crash
- int isModifiedAddDel; // If we're modified due to a new or deleted block
- File* emergencySave; // Currently unused
-
- enum {
- // Number of extra, empty blocks we add as padding to allow for easier quicksaves
- NUM_EMPTY_BLOCK = 10,
- };
-
- public:
- WorldFile() throw_File; // Create new
- // Pointer must remain valid
- WorldFile(const std::string* openFile) throw_File; // Open existing
- ~WorldFile(); // Closes the file without saving remaining changes
-
- // Is file new? (no filename, never saved)
- int isNew();
-
- // A saveable object uses this to "claim" a block by it's ID; it will
- // then have both load functions called
- void claimBlock(Uint32 id, SaveLoad* claimingObject);
-
- // An object uses this to create a new block; nothing will
- // be immediately called
- void newBlock(Uint32 blockType, SaveLoad* claimingObject);
- // An object can tell us to discard their block entirely
- void discardBlock(SaveLoad* claimingObject);
-
- // Saves all objects; this is a "quick save" that, although it
- // produces a usable file, doesn't optimize the file size
- // Can't call if isNew()
- void save() throw_File;
-
- // Saves everything to a new file and that becomes our
- // filename now; overwrites if needed; produces a file
- // of fullSave() quality
- // Pointer must remain valid
- void saveAs(const std::string* newFilename) throw_File;
-
- // Does a full save that produces an "optimized" file
- // Can't call if isNew()
- void fullSave() throw_File;
-
- // Is any object modified?
- int isModified();
- };
- #endif
|