From 65091b25c13be1c5cb319d91fe4ad773ae6fcad0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 20 Oct 2018 12:15:11 -0700 Subject: GLK: Starting to flesh out stream classes --- engines/gargoyle/gargoyle.cpp | 3 + engines/gargoyle/gargoyle.h | 2 + engines/gargoyle/glk.cpp | 34 +++++----- engines/gargoyle/glk.h | 18 ++--- engines/gargoyle/glk_types.h | 1 - engines/gargoyle/stream.cpp | 114 ++++++++++++++++++++++++++++++-- engines/gargoyle/stream.h | 150 ++++++++++++++++++++++++++++++++++++++---- engines/gargoyle/windows.h | 16 ++--- 8 files changed, 281 insertions(+), 57 deletions(-) (limited to 'engines') diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp index 5401b2c513..986a40ab78 100644 --- a/engines/gargoyle/gargoyle.cpp +++ b/engines/gargoyle/gargoyle.cpp @@ -30,6 +30,7 @@ #include "graphics/thumbnail.h" #include "gargoyle/gargoyle.h" #include "gargoyle/events.h" +#include "gargoyle/stream.h" #include "gargoyle/windows.h" namespace Gargoyle { @@ -42,6 +43,7 @@ GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gam GargoyleEngine::~GargoyleEngine() { delete _events; delete _screen; + delete _streams; delete _windows; } @@ -55,6 +57,7 @@ void GargoyleEngine::initialize() { initGraphics(640, 480, false); _screen = new Graphics::Screen(); _events = new Events(); + _streams = new Streams(); _windows = new Windows(_screen); } diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h index c7a7b86ecd..bd977137b4 100644 --- a/engines/gargoyle/gargoyle.h +++ b/engines/gargoyle/gargoyle.h @@ -35,6 +35,7 @@ namespace Gargoyle { class Events; class Windows; +class Streams; enum InterpreterType { INTERPRETER_SCOTT @@ -74,6 +75,7 @@ protected: const GargoyleGameDescription *_gameDescription; Events *_events; Graphics::Screen *_screen; + Streams *_streams; Windows *_windows; Common::RandomSource _random; int _loadSaveSlot; diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp index 3e308d5506..22d02f5237 100644 --- a/engines/gargoyle/glk.cpp +++ b/engines/gargoyle/glk.cpp @@ -139,13 +139,13 @@ void Glk::glk_set_window(winid_t win) { _windows->setCurrent(win ? win->_stream : nullptr); } -strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode, +strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock) { // TODO return nullptr; } -strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) { +strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock) { // TODO return nullptr; } @@ -154,14 +154,17 @@ void Glk::glk_stream_close(strid_t str, stream_result_t *result) { // TODO } -strid_t Glk::glk_stream_iterate(strid_t str, glui32 *rockptr) { - // TODO - return nullptr; +strid_t Glk::glk_stream_iterate(strid_t str, glui32 *rockptr) const { + return str ? str->getNext(rockptr) : _streams->getFirst(rockptr); } -glui32 Glk::glk_stream_get_rock(strid_t str) { - // TODO - return 0; +glui32 Glk::glk_stream_get_rock(strid_t str) const { + if (!str) { + warning("stream_get_rock: invalid ref"); + return 0; + } + + return str->getRock(); } void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) { @@ -257,7 +260,7 @@ frefid_t Glk::glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) return nullptr; } -frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) { +frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock) { // TODO return nullptr; } @@ -383,7 +386,7 @@ void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) { } void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) { - str->writeUint32LE(ch); +// str->writeUint32LE(ch); } void Glk::glk_put_string_stream_uni(strid_t str, const glui32 *s) { @@ -391,8 +394,7 @@ void Glk::glk_put_string_stream_uni(strid_t str, const glui32 *s) { } void Glk::glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len) { - while (len-- > 0) - str->writeUint32LE(*buf++); +// while (len-- > 0) str->writeUint32LE(*buf++); } glsi32 Glk::glk_get_char_stream_uni(strid_t str) { @@ -410,15 +412,13 @@ glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) { return 0; } -strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, glui32 fmode, glui32 rock) { +strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock) { // TODO return nullptr; } -strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, - glui32 fmode, glui32 rock) { - // TODO - return nullptr; +strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock) { + return _streams->addMemoryStream(buf, buflen, fmode, rock, false); } void Glk::glk_request_char_event_uni(winid_t win) { diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h index b0ef1714ac..0029ecf24f 100644 --- a/engines/gargoyle/glk.h +++ b/engines/gargoyle/glk.h @@ -90,13 +90,11 @@ public: strid_t glk_window_get_echo_stream(winid_t win); void glk_set_window(winid_t win); - strid_t glk_stream_open_file(frefid_t fileref, glui32 fmode, - glui32 rock); - strid_t glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, - glui32 rock); + strid_t glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock); + strid_t glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock); void glk_stream_close(strid_t str, stream_result_t *result); - strid_t glk_stream_iterate(strid_t str, glui32 *rockptr); - glui32 glk_stream_get_rock(strid_t str); + strid_t glk_stream_iterate(strid_t str, glui32 *rockptr) const; + glui32 glk_stream_get_rock(strid_t str) const; void glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode); glui32 glk_stream_get_position(strid_t str); void glk_stream_set_current(strid_t str); @@ -125,7 +123,7 @@ public: frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock); frefid_t glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock); - frefid_t glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, + frefid_t glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock); frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock); @@ -178,10 +176,8 @@ public: glui32 glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len); glui32 glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len); - strid_t glk_stream_open_file_uni(frefid_t fileref, glui32 fmode, - glui32 rock); - strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, - glui32 fmode, glui32 rock); + strid_t glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock); + strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock); void glk_request_char_event_uni(winid_t win); void glk_request_line_event_uni(winid_t win, glui32 *buf, diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h index 86b37fc5d7..c7b505e1d9 100644 --- a/engines/gargoyle/glk_types.h +++ b/engines/gargoyle/glk_types.h @@ -50,7 +50,6 @@ class Window; * These types are opaque object identifiers. They're pointers to opaque * C structures, which are defined differently by each library. */ -typedef Common::WriteStream *strid_t; typedef struct glk_fileref_struct *frefid_t; typedef struct glk_schannel_struct *schanid_t; diff --git a/engines/gargoyle/stream.cpp b/engines/gargoyle/stream.cpp index a08579a97d..c447646638 100644 --- a/engines/gargoyle/stream.cpp +++ b/engines/gargoyle/stream.cpp @@ -21,19 +21,121 @@ */ #include "gargoyle/stream.h" +#include "gargoyle/windows.h" namespace Gargoyle { -uint32 WindowStream::write(const void *dataPtr, uint32 dataSize) { - // TODO - return dataSize; +Stream::Stream(bool readable, bool writable, uint32 rock, bool unicode) : + _readable(readable), _writable(writable), _readCount(0), _writeCount(0), + _prev(nullptr), _next(nullptr), _rock(0) { } -bool WindowStream::flush() { - // TODO - return true; +Stream *Stream::getNext(uint32 *rock) const { + Stream *stream = _next; + if (rock) + *rock = stream ? stream->_rock : 0; + return stream; } +void Stream::fillResult(StreamResult *result) { + if (result) { + result->_readCount = _readCount; + result->_writeCount = _writeCount; + } +} + +void Stream::close(StreamResult *result) { + fillResult(result); + +} + +/*--------------------------------------------------------------------------*/ + +void WindowStream::writeChar(unsigned char ch) { + +} + +void WindowStream::writeCharUni(uint32 ch) { + +} + +/*--------------------------------------------------------------------------*/ + +MemoryStream::MemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) : + Stream(mode != filemode_Write, mode != filemode_Read, rock, unicode), + _buf(buf), _buflen(buflen), _bufptr(buf) { + assert(_buf && _buflen); + assert(mode == filemode_Read || mode == filemode_Write || mode == filemode_ReadWrite); + + if (unicode) + _bufend = (uint32 *)buf + buflen; + else + _bufend = (byte *)buf + buflen; + _bufeof = mode == filemode_Write ? _buf : _bufend; +} + +void MemoryStream::writeChar(unsigned char ch) { + +} + +void MemoryStream::writeCharUni(uint32 ch) { + +} + +/*--------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------*/ + +Streams::Streams() : _streamList(nullptr) {} + +Streams::~Streams() { + while (_streamList) + deleteStream(_streamList); +} + +WindowStream *Streams::addWindowStream(Window *window) { + WindowStream *stream = new WindowStream(window); + addStream(stream); + return stream; +} + +MemoryStream *Streams::addMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) { + MemoryStream *stream = new MemoryStream(buf, buflen, mode, rock, unicode); + addStream(stream); + return stream; +} + +void Streams::addStream(Stream *stream) { + stream->_next = _streamList; + _streamList = stream; + if (stream->_next) + stream->_next->_prev = stream; +} + +void Streams::deleteStream(Stream *stream) { + Stream *prev = stream->_prev; + Stream *next = stream->_next; + + if (prev) + prev->_next = next; + else + _streamList = next; + if (next) + next->_prev = prev; + + delete stream; +} + +Stream *Streams::getFirst(uint32 *rock) { + if (rock) + *rock = _streamList ? _streamList->_rock : 0; + return _streamList; +} + +/*--------------------------------------------------------------------------*/ + size_t strlen_uni(const uint32 *s) { size_t len = 0; while (*s++) diff --git a/engines/gargoyle/stream.h b/engines/gargoyle/stream.h index 5a55fbc16a..4effee33ff 100644 --- a/engines/gargoyle/stream.h +++ b/engines/gargoyle/stream.h @@ -23,47 +23,169 @@ #ifndef GARGOYLE_STREAM_H #define GARGOYLE_STREAM_H -#include "common/stream.h" +#include "common/scummsys.h" +#include "gargoyle/glk_types.h" namespace Gargoyle { class Window; +struct StreamResult { + uint32 _readCount; + uint32 _writeCount; +}; + +/** + * Base class for streams + */ +class Stream { +public: + Stream *_prev; + Stream *_next; + uint32 _rock; + bool _unicode; + uint32 _readCount; + uint32 _writeCount; + bool _readable, _writable; +public: + /** + * Constructor + */ + Stream(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 the stream + */ + virtual void close(StreamResult *result = nullptr); + + /** + * Write a character + */ + virtual void writeChar(unsigned char ch) = 0; + + /** + * Write a unicode character + */ + virtual void writeCharUni(uint32 ch) = 0; +}; +typedef Stream *strid_t; + /** * Implements the stream for writing text to a window */ -class WindowStream : public Common::WriteStream { +class WindowStream : public Stream { private: - uint32 _rock; Window *_window; public: /** * Constructor */ - WindowStream(Window *window, uint32 rock = 0) : Common::WriteStream(), - _window(window), _rock(rock) {} + WindowStream(Window *window, uint32 rock = 0, bool unicode = true) : + Stream(true, false, rock, unicode), _window(window) {} /** - * Write to the stream + * Write a character */ - virtual uint32 write(const void *dataPtr, uint32 dataSize); - + virtual void writeChar(unsigned char ch) override; + /** - * Flush the stream + * Write a unicode character */ - virtual bool flush(); + virtual void writeCharUni(uint32 ch) 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(void *buf, size_t buflen, FileMode mode, uint32 rock = 0, bool unicode = true); + + /** + * Write a character + */ + virtual void writeChar(unsigned char ch); + + /** + * Write a unicode character + */ + virtual void writeCharUni(uint32 ch); +}; + +/** + * Streams manager + */ +class Streams { +private: + Stream *_streamList; +private: /** - * Finalize and close this stream + * Adds a created stream to the list */ - virtual void finalize() { flush(); } + void addStream(Stream *stream); +public: + /** + * Constructor + */ + Streams(); + + /** + * Destructor + */ + ~Streams(); + + /** + * Add a window stream + */ + WindowStream *addWindowStream(Window *window); /** - * Returns the stream position + * Add a memory stream */ - virtual int32 pos() const { return 0; } + MemoryStream *addMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock = 0, bool unicode = true); + + /** + * Delete a stream + */ + void deleteStream(Stream *stream); + + /** + * Start an Iteration through streams + */ + Stream *getFirst(uint32 *rock); }; + + /* * Get the length of a unicode string */ diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h index 17e7d16aef..fdb29bb7b1 100644 --- a/engines/gargoyle/windows.h +++ b/engines/gargoyle/windows.h @@ -26,10 +26,10 @@ #include "common/array.h" #include "common/list.h" #include "common/rect.h" -#include "common/stream.h" #include "graphics/screen.h" #include "gargoyle/glk_types.h" #include "gargoyle/picture.h" +#include "gargoyle/stream.h" namespace Gargoyle { @@ -54,7 +54,7 @@ private: bool _moreFocus; bool _claimSelect; WindowMask *_mask; - Common::WriteStream *_currentStr; + Stream *_currentStr; private: /** * Create a new window @@ -116,12 +116,12 @@ public: /** * Set the current output stream */ - void setCurrent(Common::WriteStream *stream) { _currentStr = stream; } + void setCurrent(Stream *stream) { _currentStr = stream; } /** * Gets the current output stream */ - Common::WriteStream *getCurrent() const { return _currentStr; } + Stream *getCurrent() const { return _currentStr; } /** * Repaint an area of the windows @@ -184,12 +184,12 @@ public: glui32 _rock; glui32 _type; - Window *parent; ///< pair window which contains this one + Window *parent; ///< pair window which contains this one Common::Rect bbox; int yadj; - Common::WriteStream *_stream; ///< the window stream. - Common::WriteStream *_echoStream; ///< the window's echo stream, if any. + Stream *_stream; ///< the window stream. + Stream *_echoStream; ///< the window's echo stream, if any. int line_request; int line_request_uni; @@ -210,7 +210,7 @@ public: byte fgcolor[3]; gidispatch_rock_t disprock; - Window *next, *prev; ///< in the big linked list of windows + Window *next, *prev; ///< in the big linked list of windows public: /** * Constructor -- cgit v1.2.3