mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-11-21 20:01:13 +00:00
252 lines
9.2 KiB
C++
252 lines
9.2 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
#ifndef __FILE_SAVEGAME_H__
|
|
#define __FILE_SAVEGAME_H__
|
|
|
|
#include "zlib/zlib.h"
|
|
|
|
// Listing of the types of files within a savegame package
|
|
enum saveGameType_t {
|
|
SAVEGAMEFILE_NONE = 0,
|
|
SAVEGAMEFILE_TEXT = BIT( 0 ), // implies that no checksum will be used
|
|
SAVEGAMEFILE_BINARY = BIT( 1 ), // implies that a checksum will also be used
|
|
SAVEGAMEFILE_COMPRESSED = BIT( 2 ),
|
|
SAVEGAMEFILE_PIPELINED = BIT( 3 ),
|
|
SAVEGAMEFILE_THUMB = BIT( 4 ), // for special processing on certain platforms
|
|
SAVEGAMEFILE_BKGRND_IMAGE = BIT( 5 ), // for special processing on certain platforms, large background used on PS3
|
|
SAVEGAMEFILE_AUTO_DELETE = BIT( 6 ), // to be deleted automatically after completed
|
|
SAVEGAMEFILE_OPTIONAL = BIT( 7 ) // if this flag is not set and missing, there is an error
|
|
};
|
|
|
|
/*
|
|
================================================
|
|
idFile_SaveGame
|
|
================================================
|
|
*/
|
|
class idFile_SaveGame : public idFile_Memory {
|
|
public:
|
|
idFile_SaveGame() : type( SAVEGAMEFILE_NONE ), error( false ) {}
|
|
idFile_SaveGame( const char * _name ) : idFile_Memory( _name ), type( SAVEGAMEFILE_NONE ), error( false ) {}
|
|
idFile_SaveGame( const char * _name, int type_ ) : idFile_Memory( _name ), type( type_ ), error( false ) {}
|
|
|
|
virtual ~idFile_SaveGame() { }
|
|
|
|
bool operator==( const idFile_SaveGame & other ) const {
|
|
return idStr::Icmp( GetName(), other.GetName() ) == 0;
|
|
}
|
|
bool operator==( const char * _name ) const {
|
|
return idStr::Icmp( GetName(), _name ) == 0;
|
|
}
|
|
void SetNameAndType( const char *_name, int _type ) {
|
|
name = _name;
|
|
type = _type;
|
|
}
|
|
public: // TODO_KC_CR for now...
|
|
|
|
int type; // helps platform determine what to do with the file (encrypt, checksum, etc.)
|
|
bool error; // when loading, this is set if there is a problem
|
|
};
|
|
|
|
/*
|
|
================================================
|
|
idFile_SaveGamePipelined uses threads to pipeline overlap compression and IO
|
|
================================================
|
|
*/
|
|
class idSGFreadThread;
|
|
class idSGFwriteThread;
|
|
class idSGFdecompressThread;
|
|
class idSGFcompressThread;
|
|
|
|
struct blockForIO_t {
|
|
byte * data;
|
|
size_t bytes;
|
|
};
|
|
|
|
class idFile_SaveGamePipelined : public idFile {
|
|
public:
|
|
// The buffers each hold two blocks of data, so one block can be operated on by
|
|
// the next part of the generate / compress / IO pipeline. The factor of two
|
|
// size difference between the uncompressed and compressed blocks is unrelated
|
|
// to the fact that there are two blocks in each buffer.
|
|
static const int COMPRESSED_BLOCK_SIZE = 128 * 1024;
|
|
static const int UNCOMPRESSED_BLOCK_SIZE = 256 * 1024;
|
|
|
|
|
|
idFile_SaveGamePipelined();
|
|
virtual ~idFile_SaveGamePipelined();
|
|
|
|
bool OpenForReading( const char * const filename, bool useNativeFile );
|
|
bool OpenForWriting( const char * const filename, bool useNativeFile );
|
|
|
|
bool OpenForReading( idFile * file );
|
|
bool OpenForWriting( idFile * file );
|
|
|
|
// Finish any reading or writing.
|
|
void Finish();
|
|
|
|
// Abort any reading or writing.
|
|
void Abort();
|
|
|
|
// Cancel any reading or writing for app termination
|
|
static void CancelToTerminate() { cancelToTerminate = true; }
|
|
|
|
bool ReadBuildVersion();
|
|
const char * GetBuildVersion() const { return buildVersion; }
|
|
|
|
bool ReadSaveFormatVersion();
|
|
int GetSaveFormatVersion() const { return saveFormatVersion; }
|
|
int GetPointerSize() const;
|
|
|
|
//------------------------
|
|
// idFile Interface
|
|
//------------------------
|
|
|
|
virtual const char * GetName() const { return name.c_str(); }
|
|
virtual const char * GetFullPath() const { return name.c_str(); }
|
|
virtual int Read( void * buffer, int len );
|
|
virtual int Write( const void * buffer, int len );
|
|
|
|
// this file is strictly streaming, you can't seek at all
|
|
virtual int Length() const { return compressedLength; }
|
|
virtual void SetLength( size_t len ) { compressedLength = len; }
|
|
virtual int Tell() const { assert( 0 ); return 0; }
|
|
virtual int Seek( long offset, fsOrigin_t origin ) { assert( 0 ); return 0; }
|
|
|
|
virtual ID_TIME_T Timestamp() const { return 0; }
|
|
|
|
//------------------------
|
|
// These can be used by a background thread to read/write data
|
|
// when the file was opened with 'useNativeFile' set to false.
|
|
//------------------------
|
|
|
|
enum mode_t {
|
|
CLOSED,
|
|
WRITE,
|
|
READ
|
|
};
|
|
|
|
// Get the file mode: read/write.
|
|
mode_t GetMode() const { return mode; }
|
|
|
|
// Called by a background thread to get the next block to be written out.
|
|
// This may block until a block has been made available through the pipeline.
|
|
// Pass in NULL to notify the last write failed.
|
|
// Returns false if there are no more blocks.
|
|
bool NextWriteBlock( blockForIO_t * block );
|
|
|
|
// Called by a background thread to get the next block to read data into and to
|
|
// report the number of bytes written to the previous block.
|
|
// This may block until space is available to place the next block.
|
|
// Pass in NULL to notify the end of the file was reached.
|
|
// Returns false if there are no more blocks.
|
|
bool NextReadBlock( blockForIO_t * block, size_t lastReadBytes );
|
|
|
|
private:
|
|
friend class idSGFreadThread;
|
|
friend class idSGFwriteThread;
|
|
friend class idSGFdecompressThread;
|
|
friend class idSGFcompressThread;
|
|
|
|
idStr name; // Name of the file.
|
|
idStr osPath; // OS path.
|
|
mode_t mode; // Open mode.
|
|
size_t compressedLength;
|
|
|
|
static const int COMPRESSED_BUFFER_SIZE = COMPRESSED_BLOCK_SIZE * 2;
|
|
static const int UNCOMPRESSED_BUFFER_SIZE = UNCOMPRESSED_BLOCK_SIZE * 2;
|
|
|
|
byte uncompressed[UNCOMPRESSED_BUFFER_SIZE];
|
|
size_t uncompressedProducedBytes; // not masked
|
|
size_t uncompressedConsumedBytes; // not masked
|
|
|
|
byte compressed[COMPRESSED_BUFFER_SIZE];
|
|
size_t compressedProducedBytes; // not masked
|
|
size_t compressedConsumedBytes; // not masked
|
|
|
|
//------------------------
|
|
// These variables are used to pass data between threads in a thread-safe manner.
|
|
//------------------------
|
|
|
|
byte * dataZlib;
|
|
size_t bytesZlib;
|
|
|
|
byte * dataIO;
|
|
size_t bytesIO;
|
|
|
|
//------------------------
|
|
// These variables are used by CompressBlock() and DecompressBlock().
|
|
//------------------------
|
|
|
|
z_stream zStream;
|
|
int zLibFlushType; // Z_NO_FLUSH or Z_FINISH
|
|
bool zStreamEndHit;
|
|
int numChecksums;
|
|
|
|
//------------------------
|
|
// These variables are used by WriteBlock() and ReadBlock().
|
|
//------------------------
|
|
|
|
idFile * nativeFile;
|
|
bool nativeFileEndHit;
|
|
bool finished;
|
|
|
|
//------------------------
|
|
// The background threads and signals for NextWriteBlock() and NextReadBlock().
|
|
//------------------------
|
|
|
|
idSGFreadThread * readThread;
|
|
idSGFwriteThread * writeThread;
|
|
|
|
idSGFdecompressThread * decompressThread;
|
|
idSGFcompressThread * compressThread;
|
|
|
|
idSysSignal blockRequested;
|
|
idSysSignal blockAvailable;
|
|
idSysSignal blockFinished;
|
|
|
|
idStrStatic< 32 > buildVersion; // build version this file was saved with
|
|
int16 pointerSize; // the number of bytes in a pointer, because different pointer sizes mean different offsets into objects a 64 bit build cannot load games saved from a 32 bit build or vice version (a value of 0 is interpreted as 4 bytes)
|
|
int16 saveFormatVersion; // version number specific to save games (for maintaining save compatibility across builds)
|
|
|
|
//------------------------
|
|
// These variables are used when we want to abort due to the termination of the application
|
|
//------------------------
|
|
static bool cancelToTerminate;
|
|
|
|
void FlushUncompressedBlock();
|
|
void FlushCompressedBlock();
|
|
void CompressBlock();
|
|
void WriteBlock();
|
|
|
|
void PumpUncompressedBlock();
|
|
void PumpCompressedBlock();
|
|
void DecompressBlock();
|
|
void ReadBlock();
|
|
};
|
|
|
|
#endif // !__FILE_SAVEGAME_H__
|