scummvm/engines/glk/streams.h
2018-12-08 19:05:59 -08:00

665 lines
13 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef GLK_STREAMS_H
#define GLK_STREAMS_H
#include "common/scummsys.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/str.h"
#include "glk/glk_types.h"
namespace Glk {
#define SAVEGAME_VERSION 1
class Window;
class Streams;
enum FileUsage {
fileusage_Data = 0x00,
fileusage_SavedGame = 0x01,
fileusage_Transcript = 0x02,
fileusage_InputRecord = 0x03,
fileusage_TypeMask = 0x0f,
fileusage_TextMode = 0x100,
fileusage_BinaryMode = 0x000
};
enum FileMode {
filemode_Write = 0x01,
filemode_Read = 0x02,
filemode_ReadWrite = 0x03,
filemode_WriteAppend = 0x05
};
enum SeekMode {
seekmode_Start = 0,
seekmode_Current = 1,
seekmode_End = 2
};
struct StreamResult {
uint32 _readCount;
uint32 _writeCount;
};
typedef StreamResult stream_result_t;
struct SavegameHeader {
uint8 _version;
byte _interpType;
byte _language;
Common::String _md5;
Common::String _saveName;
int _year, _month, _day;
int _hour, _minute;
int _totalFrames;
/**
* Constructor
*/
SavegameHeader() : _version(0), _interpType(0), _language(0), _year(0), _month(0), _day(0),
_hour(0), _minute(0), _totalFrames(0) {}
};
/**
* File details
*/
struct FileReference {
glui32 _rock;
int _slotNumber;
Common::String _description;
Common::String _filename;
FileUsage _fileType;
bool _textMode;
gidispatch_rock_t _dispRock;
/**
* Constructor
*/
FileReference() : _rock(0), _slotNumber(-1), _fileType(fileusage_Data), _textMode(false) {}
/**
* Constructor
*/
FileReference(int slot, const Common::String &desc, glui32 usage, glui32 rock = 0) :
_rock(rock), _slotNumber(slot), _description(desc),
_fileType((FileUsage)(usage & fileusage_TypeMask)), _textMode(usage & fileusage_TextMode) {}
/**
* Get savegame filename
*/
const Common::String getSaveName() const;
/**
* Returns true if the given file exists
*/
bool exists() const;
/**
* Delete the given file
*/
void deleteFile();
};
typedef FileReference *frefid_t;
typedef Common::Array< Common::SharedPtr<FileReference> > FileRefArray;
/**
* Base class for streams
*/
class Stream {
public:
Streams *_streams;
Stream *_prev;
Stream *_next;
uint32 _rock;
bool _unicode;
uint32 _readCount;
uint32 _writeCount;
bool _readable, _writable;
public:
/**
* Constructor
*/
Stream(Streams *streams, bool readable, bool writable, uint32 rock, bool unicode);
/**
* Destructor
*/
virtual ~Stream();
/**
* Get the next stream
*/
Stream *getNext(uint32 *rock) const;
/**
* Get the rock value for the stream
*/
uint32 getRock() const {
return _rock;
}
/**
* Fill out the total amount read and/or written
*/
void fillResult(StreamResult *result);
/**
* Close and delete the stream
*/
void close(StreamResult *result = nullptr);
/**
* Write a character
*/
virtual void putChar(unsigned char ch) = 0;
/**
* Write a unicode character
*/
virtual void putCharUni(uint32 ch) = 0;
/**
* Write a buffer
*/
virtual void putBuffer(const char *buf, size_t len) = 0;
/**
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) = 0;
/**
* Remove a string from the end of the stream, if indeed it is at the end
*/
virtual void unputBuffer(const char *buf, size_t len) {}
/**
* Remove a string from the end of the stream, if indeed it is at the end
*/
virtual void unputBufferUni(const glui32 *buf, size_t len) {}
/**
* Send a line to the stream with a trailing newline
*/
void echoLine(char *buf, glui32 len) {
putBuffer(buf, len);
putChar('\n');
};
/**
* Send a line to the stream with a trailing newline
*/
void echoLineUni(glui32 *buf, glui32 len) {
putBufferUni(buf, len);
putCharUni('\n');
}
virtual glui32 getPosition() const {
return 0;
}
virtual void setPosition(glsi32 pos, glui32 seekMode) {}
virtual void setStyle(glui32 val) {}
/**
* Get a character from the stream
*/
virtual glsi32 getChar() {
return -1;
}
/**
* Get a unicode character from the stream
*/
virtual glsi32 getCharUni() {
return -1;
}
/**
* Get a buffer
*/
virtual glui32 getBuffer(char *buf, glui32 len) {
return 0;
}
/**
* Get a unicode buffer
*/
virtual glui32 getBufferUni(glui32 *buf, glui32 len) {
return 0;
}
/**
* Get a line
*/
virtual glui32 getLine(char *buf, glui32 len) {
return 0;
}
/**
* Get a unicode line
*/
virtual glui32 getLineUni(glui32 *ubuf, glui32 len) {
return 0;
}
/**
* Set a hyperlink
*/
virtual void setHyperlink(glui32 linkVal) {}
/**
* Set the style colors
*/
virtual void setZColors(glui32 fg, glui32 bg);
/**
* Set the reverse video style
*/
virtual void setReverseVideo(bool reverse);
/**
* Cast a stream to a ScummVM write stream
*/
virtual operator Common::WriteStream *() const { return nullptr; }
/**
* Cast a stream to a ScummVM read stream
*/
virtual operator Common::SeekableReadStream *() const { return nullptr; }
};
typedef Stream *strid_t;
/**
* Implements the stream for writing text to a window
*/
class WindowStream : public Stream {
private:
Window *_window;
public:
/**
* Constructor
*/
WindowStream(Streams *streams, Window *window, uint32 rock = 0, bool unicode = true) :
Stream(streams, false, true, rock, unicode), _window(window) {}
/**
* Destructor
*/
virtual ~WindowStream();
/**
* Close the stream
*/
virtual void close(StreamResult *result = nullptr);
/**
* Write a character
*/
virtual void putChar(unsigned char ch) override;
/**
* Write a unicode character
*/
virtual void putCharUni(uint32 ch) override;
/**
* Write a buffer
*/
virtual void putBuffer(const char *buf, size_t len) override;
/**
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) override;
/**
* Remove a string from the end of the stream, if indeed it is at the end
*/
virtual void unputBuffer(const char *buf, size_t len) override;
/**
* Remove a string from the end of the stream, if indeed it is at the end
*/
virtual void unputBufferUni(const glui32 *buf, size_t len) override;
virtual void setStyle(glui32 val) override;
/**
* Set a hyperlink
*/
virtual void setHyperlink(glui32 linkVal) override;
/**
* Set the style colors
*/
virtual void setZColors(glui32 fg, glui32 bg) override;
/**
* Set the reverse video style
*/
virtual void setReverseVideo(bool reverse) override;
};
/**
* Implements an in-memory stream
*/
class MemoryStream : public Stream {
private:
void *_buf; ///< unsigned char* for latin1, glui32* for unicode
void *_bufPtr;
void *_bufEnd;
void *_bufEof;
size_t _bufLen; ///< # of bytes for latin1, # of 4-byte words for unicode
public:
/**
* Constructor
*/
MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock = 0, bool unicode = true);
/**
* Write a character
*/
virtual void putChar(unsigned char ch) override;
/**
* Write a unicode character
*/
virtual void putCharUni(uint32 ch) override;
/**
* Write a buffer
*/
virtual void putBuffer(const char *buf, size_t len) override;
/**
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) override;
virtual glui32 getPosition() const override;
virtual void setPosition(glsi32 pos, glui32 seekMode) override;
/**
* Get a character from the stream
*/
virtual glsi32 getChar() override;
/**
* Get a unicode character from the stream
*/
virtual glsi32 getCharUni() override;
/**
* Get a buffer
*/
virtual glui32 getBuffer(char *buf, glui32 len) override;
/**
* Get a unicode buffer
*/
virtual glui32 getBufferUni(glui32 *buf, glui32 len) override;
/**
* Get a line
*/
virtual glui32 getLine(char *buf, glui32 len) override;
/**
* Get a unicode line
*/
virtual glui32 getLineUni(glui32 *ubuf, glui32 len) override;
};
/**
* Implements a file stream
*/
class FileStream : public Stream {
private:
Common::File _file;
Common::OutSaveFile *_outFile;
Common::InSaveFile *_inFile;
Common::SeekableReadStream *_inStream;
uint32 _lastOp; ///< 0, filemode_Write, or filemode_Read
bool _textFile;
private:
/**
* Ensure the stream is ready for the given operation
*/
void ensureOp(FileMode mode);
/**
* Put a UTF8 character
*/
void putCharUtf8(glui32 val);
/**
* Get a UTF8 character
*/
glsi32 getCharUtf8();
public:
/**
* Read a savegame header from a stream
*/
static bool readSavegameHeader(Common::SeekableReadStream *stream, SavegameHeader &header);
/**
* Write out a savegame header
*/
static void writeSavegameHeader(Common::WriteStream *stream, const Common::String &saveName);
public:
/**
* Constructor
*/
FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode);
/**
* Destructor
*/
virtual ~FileStream();
/**
* Write a character
*/
virtual void putChar(unsigned char ch) override;
/**
* Write a unicode character
*/
virtual void putCharUni(uint32 ch) override;
/**
* Write a buffer
*/
virtual void putBuffer(const char *buf, size_t len) override;
/**
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) override;
virtual glui32 getPosition() const override;
virtual void setPosition(glsi32 pos, glui32 seekMode) override;
/**
* Get a character from the stream
*/
virtual glsi32 getChar() override;
/**
* Get a unicode character from the stream
*/
virtual glsi32 getCharUni() override;
/**
* Get a buffer
*/
virtual glui32 getBuffer(char *buf, glui32 len) override;
/**
* Get a unicode buffer
*/
virtual glui32 getBufferUni(glui32 *buf, glui32 len) override;
/**
* Get a line
*/
virtual glui32 getLine(char *buf, glui32 len) override;
/**
* Get a unicode line
*/
virtual glui32 getLineUni(glui32 *ubuf, glui32 len) override;
/**
* Cast a stream to a ScummVM write stream
*/
virtual operator Common::WriteStream *() const override { return _outFile; }
/**
* Cast a stream to a ScummVM read stream
*/
virtual operator Common::SeekableReadStream *() const override { return _inStream; }
};
/**
* Streams manager
*/
class Streams {
friend class Stream;
private:
Stream *_streamList;
Stream *_currentStream;
FileRefArray _fileReferences;
private:
/**
* Adds a created stream to the list
*/
void addStream(Stream *stream);
/**
* Remove a stream
*/
void removeStream(Stream *stream);
public:
/**
* Constructor
*/
Streams();
/**
* Destructor
*/
~Streams();
/**
* Open a file stream
*/
FileStream *openFileStream(frefid_t fref, glui32 fmode, glui32 rock = 0, bool unicode = false);
/**
* Open a window stream
*/
WindowStream *openWindowStream(Window *window);
/**
* Open a memory stream
*/
MemoryStream *openMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock = 0, bool unicode = true);
/**
* Delete a stream
*/
void deleteStream(Stream *stream) {
delete stream;
}
/**
* Start an Iteration through streams
*/
Stream *getFirst(uint32 *rock);
/**
* Set the current output stream
*/
void setCurrent(Stream *stream) {
assert(stream->_writable);
_currentStream = stream;
}
/**
* Gets the current output stream
*/
Stream *getCurrent() const {
return _currentStream;
}
/**
* Prompt for a savegame to load or save, and populate a file reference from the result
*/
frefid_t createByPrompt(glui32 usage, FileMode fmode, glui32 rock);
/**
* Create a new file reference
*/
frefid_t createRef(int slot, const Common::String &desc, glui32 usage, glui32 rock);
/**
* Create a new file reference
*/
frefid_t createRef(const Common::String &filename, glui32 usage, glui32 rock);
/**
* Create a new temporary file reference
*/
frefid_t createTemp(glui32 usage, glui32 rock);
/**
* Create a new file reference from an old one
*/
frefid_t createFromRef(frefid_t fref, glui32 usage, glui32 rock);
/**
* Delete a file reference
*/
void deleteRef(frefid_t fref);
/**
* Iterates to the next file reference following the specified one,
* or the first if null is passed
*/
frefid_t iterate(frefid_t fref, glui32 *rock);
};
} // End of namespace Glk
#endif