[Scummvm-git-logs] scummvm master -> ac9830614d07d80f0c02d9d7c75d709f9d534466
dreammaster
paulfgilbert at gmail.com
Sun Dec 9 04:09:03 CET 2018
This automated email contains information about 256 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c4d4d48d67 GLK: Initial skeleton engine
9c536cb6bf GLK: Add stub classes for sub-engine components
46aafc3558 GLK: Refactor Glk to derice from Interpreter
b2067f3be7 GLK: Added Glk enums and structures
fa253ddba7 GLK: Added stubs for Glk methods
dcefdd6f62 GLK: More outer engine structure, and cleanup
b62e30b84c GLK: Interpreters now derive from GargoyleEngine via Glk
22648145a9 GLK: SCOTT: Initial conversion of ScottFree
9c6aca1d57 GLK: SCOTT: Minor stream and event loop fixes
db35a9cdc8 GLK: SCOTT: Adding game detection code
ef161922d8 ENGINES: Add optional extra configuration entries when creating new targets
5f626f7a6a GLK: Add detection logic needed for engine startup
74080143da GLK: Detect presence of game file in detectGames
77f357e72f GLK: Add window creation
47a7a1d4e2 GLK: Added setup of text grid windows
89102c42ca GLK: Window setup for text buffer windows
b9bafba382 GLK: Remaining window rearrange code
9e804bf484 GLK: Added glk_set_window
3c9987c0a7 GLK: Fixes for window initialization
256f7ff312 GLK: Skeleton implementation of window text stream
65091b25c1 GLK: Starting to flesh out stream classes
cf5259d3bc GLK: Adding stream open/closing
ef15871fec GLK: Setting up of configuration loading
bbd744ad47 GLK: Further config loading
0bc3da9e80 GLK: Remove duplicated Windows fields that are now in Conf
d314cd39ee GLK: SCOTT: Add detection for other games
cc54beadce GLK: Start of window character output
ac9a122e3d GLK: Renaming of window classes fields
855fd39a9e GLK: Added WindowStream put methods
5bfdffc9dc GLK: Added remaining stream write methods
71389c2dd2 GLK: Added window class destructors
0d3ad2dc8a GLK: Added TextGridWindow methods and support
8708ed4f9a GLK: Split the windows.cpp file into separate files for each window class
ede0323c08 GLK: Windows don't have a non-unicode putChar method
cb2b7d439f GLK: Remove more Window methods that aren't actually present
ba907c9aec GLK: Implementing text buffer window methods
4ddda5cebc GLK: Windows focus / iteration
6939fabbfb GLK: Fleshed out graphics window
fdfb1a5502 GLK: Move Draw class into new Screen class
3d8626081c GLK: Added window closing, some structures cleanup
49b8281ce3 GLK: Window rearrangement methods
594f63f475 GLK: Added window getSize methods
72022042ee GLK: Adding glk window methods
4266f3af13 GLK: Adding more window glk methods
e14424c2b9 GLK: Adding more window glk methods
b231dee01a GLK: More window glk methods
d128249854 GLK: Miscellaneous glk methods
485e899312 GLK: Adding glk stream methods
734366ce89 GLK: Added more glk stream commands
4bb5967920 GLK: More glk stream functions
98f1ddc968 GLK: Added unicode case methods
7436604483 GLK: Added time and date glk functions
76bf2726f8 GLK: Added input window focus, and cleanup of event method stubs
7bbedcd099 GLK: Beginnings of event handling
9eb4debd15 GLK: Logic for keypress event handling
efacc17bd1 GLK: Handle more user events
65fa4fa7cb GLK: Beginnings of font handling
e5854a6bd3 GLK: Add loading of TrueType fonts
6807e646b4 GLK: Fix initialization of text buffer window lines
b23291b977 GLK: SCOTT: Fix loading game data
998cf547ed GLK: SCOTT: Exit game when ScummVM is closed
9d72d6007e GLK: Move font method stubs from Screen to Fonts
13e2838715 GLK: Implement font drawing methods
ffe0f5220b GLK: Converted fillRect to use a Rect to specify bounds
a9f5b3351e GLK: Fix fg/bg window color initialization
4fcffce505 GLK: Changes of NULL to nullptr
48a00e7c00 GLK: Set Windows fields from int to bool
1a889689f8 GLK: Added pair window drawing
0a21220707 GLK: Add game frames to actually render the screen
4fc1c30423 GLK: Fix Attributes equality checks
e004784d23 GLK: Fix calculation of text grid height
0d3495bb3b GLK: Add missing configuration defaults
c5668d9300 GLK: Further configuration fixes
7ebbcc87dc GLK: Fix rendering text in text grid windows
7c7178c419 GLK: Text is partially displaying in the buffer window
666edf52a5 GLK: Don't have borders between windows by default
f17998762d GLK: Add drawCaret method
e9c7b30246 GLK: Proper handling of font baseline and leading
012d4bafbb GLK: Fix placement of input cursor
c0fd6ca3e4 GLK: Cleanup of comments in text window classes
d61a7a9ee6 GLK: Change key handle if block to a switch statement
4229312b22 GLK: Cleanup of formatting in text buffer window class
4b5db1da07 GLK: Fix showing input text to the right of input prompt
d954f70d49 GLK: Fix having space between prmpt and input text
2551927bf6 GLK: Fix processing input after Enter is pressed
e36dbfaf2e GLK: Prompt for keypress when game is exited
55c05a0d7a GLK: SCOTT: Camel case method names
aafaace942 GLK: SCOTT: Switch command line options setup to use ConfigMan
99266b8586 GLK: Beginnings of file reference handling
a24b27b14a GLK: Create glk fileref methods
063cfb35ef GLK: Added glk style methods
f91cdb19bf GLK: Add glk style hint methods
60146c383d GLK: Merge Files class into existing Streams class
db112fc9f0 GLK: Adding file stream opening and closing
30cd230d88 GLK: Fixes for file stream reading
8333aed5c2 GLK: Adding extra fields to the savegame format for validation
ce582aab00 GLK: Further work on game detection
8bb3f55dff GLK: SCOTT: Add custom game Ids for each known Scott Adams game
d2554a73fb GLK: Fix refreshing grid windows when text is changed
0ea7f92b67 GLK: SCOTT: Added saveGameState and loadGameState
2e11923677 GLK: SCOTT: Added startup savegame loading
77a4e99c31 GLK: Add savegame listing
9bd7bc87b6 GLK: Added savegame meta info retrieval
db61f4e050 GLK: Add miscellaneous stream methods
75f1ac769b GLK: SCOTT: Fix loading and saving games
6b39263dab GLK: Workaround to show caret for second line entry onwards
135c3adc94 GLK: In progress adding mouse cursors
c5234c9f72 GLK: Fix display of mouse cursor
8e1be3a95c GLK: Text selection highlighting is now working
88315e7349 GLK: Fix selection area getting removed when mouse button was released
596a36aef0 GLK: Allow video mode to be specified in the configuration
65167bd202 GLK: Added a fonts.dat Zip archive containing the fonts
d6538380d7 GLK: Implemented pasting from clipboard
c4bcb0882f GLK: Merge Clipboard and WindowMask into a new Selection class
3c2fd3e74f GLK: Add copying to clipboard
7cba554fc5 GLK: Don't leading & baseline for fonts go below minimum size
e208e14796 GLK: Get proper baseline and leading from loaded fonts
f73d56f6ba GLK: Setup default font colors to match garglk defaults
671321c45f GLK: Fix loading of font colors and styles from configuration
43bee7a727 GLK: Add GUI options to default detection entry
601e1d486b GLK: Add GLK timer intervals
4bd3a4a9c6 GLK: Cleanup of glk_gestalt_ext switch
c524c5859e GLK: Add garglk_unput_string methods
df8dec156e GLK: Add garglk_set_zcolors methods
7cb69167de GLK: Add the garglk_set_reversevideo methods
5ddf55da6c GLK: SCOTT: Convert comments to single line veresions
a8e656a5de GLK: astyle formatting
a698756c24 GLK: SCOTT: Don't show intro text when loading savegame from launcher
fbed3ed7a3 GLK: SCOTT: Handle negative values in readInts
62315b969d GLK: gcc compilation fixes
cde50e00ed GLK: Fix handling of negative file offsets in MemoryStream::setPosition
43cee5fb0f GLK: Fix setTime converting seconds to a date/time structure
c589b807e2 GLK: FROTZ: Skeleton sub-engine for Frotz interpreter
1aaf2fd145 GLK: FROTZ: Fleshing out detection logic and added some entries
8316c1a5b2 GLK: FROTZ: Beginnings of initialization
7d20a3552b GLK: FROTZ: Added error handling
4497a55a86 GLK: FROTZ: Beginnings of Mem class
b8fcb62dd2 GLK: Added Blorb container file handling
fc4c3293d1 GLK: FROTZ: Add parsing if game file is a Blorb container
f19f92e396 GLK: FROTZ: Move Header to be an ancestor class to Mem
cc9b52e5ac GLK: Implement the removeSaveState method
38a458139a GLK: Add Gargoyle engine to credits.pl
a083eb3d5c GLK: FROTZ: Added bulk of game processor
9fadd84b37 GLK: FROTZ: Add GlkInterface initialize method
ad95130e4f GLK: FROTZ: Added user options initialization from configuration
7a3dd94de1 GLK: FROTZ: Add undo data initialization
fbe7fb7e1a GLK: FROTZ: Merge Buffer class into Processor
53612fa6f7 GLK: FROTZ: Added storeb and storew methods
1b4791f923 GLK: FROTZ: Removal of method stubs that are now implemented
1ca59e74c3 GLK: FROTZ: Added storeb & storew into the Mem class
5507242395 GLK: Fix casting of vardiac retrieval
e1de76b491 GLK: FROTZ: Added remaining memory methods
2c37a94913 GLK: SCOTT: Fix detecting .dat gamefiles, added Windows game versions detections
7a52f21c0b GLK: FROTZ: Added script/record/transcript/replay methods
aab1dfeff8 GLK: FROTZ: Added memory redirect methods
7d2406870e GLK: FROTZ: Add screen message methods
ce7113b34a GLK: FROTZ: Added OS read line and character methods
c19d40fa78 GLK: FROTZ: Implemented Quetzal class for savegames
6b23a72e51 GLK: FROTZ: Merge Err class into Processor
7b90a2b60e GLK: FROTZ: Hook up processor execution to main runGame method
7d670ff157 GLK: FROTZ: Fix stack size
1fb931fbd9 GLK: Changing gargoyle folder to glk
a2104deb4c GLK: Changing class and namespaces from Gargoyle to Glk
454f92cc74 GLK: SCOTT: Centralize the set of game names
67275924b5 GLK: Derive detection from MetaEngine rather than AdvancedMetaEngine
eff0ac80ff GLK: Handle starting the engine directly from the command line
7b1b3935b8 GLK: Fix remaining Gargoyle references identified by digitall
a1d355d0be GLK: FROTZ: Move ostream_* flags from GlkInterface to Processor
f29147ba22 GLK: Fix showing unicode input lines
beddf3853e GLK: FROTZ: Fill out HHGTTG version serial numbers
af081ad322 GLK: FROTZ: Improve fallback detection of Z-code games
d9e7fca83c GLK: FROTZ: Fix exiting when application is forcefully closed
04f42acca0 GLK: FROTZ: Allow exiting ScumMVM when waiting for a keypress
625df27cfc GLK: FROTZ: Adding detection entries for Infocom games
dee20ace65 GLK: FROTZ: Added detection entries for more Infocom games
238022890e GLK: FROTZ: Debug code to generate detection entries for unknown games
bd4bc0a43f GLK: FROTZ: Fix crash clicking screen with mouse without dragging
027240678e GLK: SCOTT: Change engine to use ScummVM String and Arrays
83646598c9 GLK: SCOTT: Renaming of all fields to ScummVM convention
fc2b1edd1f GLK: SCOTT: Extra returns/exits after glk_exit is called
bc4df65bd7 GLK: Fix gcc compiler warnings
e344809eea GLK: FROTZ: Fix gcc warnings, adding extra method comments
3d34cd151f GLK: FROTZ: Remove unused local variable
4b011b2f1c GLK: Freeing of data on exit
813918aaba GLK: Memory leak fixes
326f69136e GLK: SCOTT: Fix memory corruption loading game data
b05a16a0ad GLK: Centralizing more of the savegame code in GlkEngine
3b906cb2bb GLK: Fixes for combined loading/saving code
fc86b3705b GLK: Fix initializing fields of created streams
0167d988fa GLK: Free windows on exit
88b0e5d52f GLK: Change text buffer history array to use Array of U32Strings
41a4378169 GLK: SCOTT: Don't show another line prompt when game is exiting
79f3d946ef GLK: FROTZ: Shift Header class into it's own file
ada80dedc0 GLK: FROTZ: Further merging together of configuration into a new config.cpp file
2a3e6c49bf GLK: FROTZ: Set up default Frotz white on blue screen colors
dfe497cb79 GLK: FROTZ: Move setting default colors to GlkInterface
9bc6379476 GLK: Change lots of comments from multiline to single line
0f0b8ae3b7 GLK: FROTZ: Don't have a Y margin above title bar
bd86fd7bbf GLK: Implementing picture loading
5a05140ac3 GLK: Add picture scaling
f7cb417084 GLK: Add picture drawing
525c09ef38 GLK: In progress transforming Blorb code to be a Common::Archive
13e28c0d0d GLK: Finish refactoring Blorb class
720ef67a7d GLK: FROTZ: Fixed detection of Infocom .dat gamefiles
0b1e695f24 GLK: FROTZ: Beginnings of support for Infocom picture files
3e8ed4eafc GRAPHICS: Add convertToInPlace method to ManagedSurface
6f50812493 GLK: Added RawDecoder class for new raw picture data format
a334cd704e GLK: FROTZ: Further loading of Infocom pictures files
f92b82664d GLK: Fix gcc warnings
0aff016ad9 GLK: FROTZ: Fix deletion of undo_mem
5b9e1a53ad GLK: FROTZ: Fix mismatch allocation/free
c7a632ae2e GLK: FROTZ: Fix initialization of undo data
4a3f517b71 GLK: FROTZ: Prompt for exit when game quits
1c190e50b4 GLK: Mark text strings as translateable
3700919881 GLK: Add POTFILES
62af5ea891 GLK: FROTZ: More work on displaying Beyond Zork title screen
77468312de GLK: FROTZ: Beyond Zork title screen now showing
c2625264fb GLK: Change int 0 to false
5cc3d40c28 GLK: FROTZ: Adding bitmap font class for Infocom character graphics
fb7dbffd59 GLK: Merge Fonts class into Screen class
3a543a1e6d GLK: FROTZ: Add derived Screen class to add Infocom character graphics font
9fa7e9be81 GLK: FROTZ: Fix selection of the character graphics font
6080a1d091 GLK: FROTZ: Draw character graphic chars at the same size as the fixed width font
6e6b285e83 GLK: FROTZ: Savegame listing now reads Quetzal savegames
33a23bca1c GLK: FROTZ: Further reading/writing setup for savegames using Quetzal
2331a0e9fb GLK: FROTZ: Quetzal saving and loading now works
bfbc0ba0ed GLK: FROTZ: Allow loading savegames from launcher
855911d0c0 GLK: FROTZ: Fix display of character graphics in text grid windows
0b7a29c797 GLK: TADS: Skeleton engine
09b682cb63 GLK: TADS: Skeletons for TADS 2 & 3 subengines, extra detection logic
75f4d34070 GLK: TADS: Add first detection entry, further fallback detection
d2836360fb GLK: TADS: GLK window initialization
5ab65b0954 GLK: TADS: TADS2: Add ler file
41b62ab00d GLK: TADS: Add a number of GLK interface methods
d3c46f7078 GLK: TADS: Add Regex class
f20d07381c GLK: TADS: Added cmap file
14871c28bc GLK: TADS: Added Data class
c68542dba8 GLK: TADS: Compilation fix
7212924b1e GLK: TADS: Compilation fixes
1933130dfc GLK: FROTZ: Fix setting cwin field when window changes
63079834fa GLK: FROTZ: Improved rendering of Beyond Zork description area
d7c015a17e GLK: FROTZ: Detect Infocom games using .zip extensions
4894ce2134 GLK: FROTZ: Add all the new V6 methods, commented out until I can fix each one
7fda941302 GLK: FROTZ: Implement some of the V6 opcodes
ab8ff73453 GLK: FROTZ: Fix handling of empty rect picture resources
88b47cdd8b GLK: FROTZ: Added winarg methods
2ae0edd58b GLK: FROTZ: Add sound playing code
f6abb3ea33 GLK: FROTZ: Simplify accessing sounds for Lurking Horror & Sherlock
3661fc61ec GLK: Beginnings of Sounds manager
0cbd51641b GLK: FROTZ: Further sound handling
43283ff561 GLK: FROTZ: Playing sounds now works directly from lhsound.zip and shsound.zip
08db684864 GLK: Add support for secondary Blorb files separate from the gamefile
ecb0c10fdb GLK: FROTZ: Properly flag the detections of Infocom games that have sound effects
754819f928 GLK: FROTZ: Reduce window margin to 0 to have status bar fill entire width
290196946d GLK: GLULXE: Skeleton sub-engine
ac9830614d GLK: GLULXE: Validate game file version
Commit: c4d4d48d67953687b1d21eb1f7e01fb4a508958b
https://github.com/scummvm/scummvm/commit/c4d4d48d67953687b1d21eb1f7e01fb4a508958b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Initial skeleton engine
Changed paths:
A engines/gargoyle/configure.engine
A engines/gargoyle/detection.cpp
A engines/gargoyle/detection_tables.h
A engines/gargoyle/gargoyle.cpp
A engines/gargoyle/gargoyle.h
A engines/gargoyle/module.mk
diff --git a/engines/gargoyle/configure.engine b/engines/gargoyle/configure.engine
new file mode 100644
index 0000000..671f91c
--- /dev/null
+++ b/engines/gargoyle/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine gargoyle "Interactive Fiction games" no
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
new file mode 100644
index 0000000..94fb90f
--- /dev/null
+++ b/engines/gargoyle/detection.cpp
@@ -0,0 +1,129 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/gargoyle.h"
+
+#include "base/plugins.h"
+#include "common/savefile.h"
+#include "common/str-array.h"
+#include "common/memstream.h"
+#include "engines/advancedDetector.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/surface.h"
+
+#define MAX_SAVES 99
+
+namespace Gargoyle {
+
+struct GargoyleGameDescription {
+ ADGameDescription desc;
+};
+
+uint32 GargoyleEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+bool GargoyleEngine::isDemo() const {
+ return (bool)(_gameDescription->desc.flags & ADGF_DEMO);
+}
+
+Common::Language GargoyleEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+} // End of namespace Gargoyle
+
+static const PlainGameDescriptor GargoyleGames[] = {
+ {"Gargoyle", "Gargoyle Games"},
+ {0, 0}
+};
+
+#include "gargoyle/detection_tables.h"
+
+class GargoyleMetaEngine : public AdvancedMetaEngine {
+public:
+ GargoyleMetaEngine() : AdvancedMetaEngine(Gargoyle::gameDescriptions, sizeof(Gargoyle::GargoyleGameDescription), GargoyleGames) {
+ _maxScanDepth = 3;
+ }
+
+ virtual const char *getName() const {
+ return "Gargoyle Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Gargoyle Engine (c)";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail);
+}
+
+bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
+ *engine = new Gargoyle::GargoyleEngine(syst, gd);
+
+ return gd != 0;
+}
+
+SaveStateList GargoyleMetaEngine::listSaves(const char *target) const {
+ SaveStateList saveList;
+ return saveList;
+}
+
+int GargoyleMetaEngine::getMaximumSaveSlot() const {
+ return MAX_SAVES;
+}
+
+void GargoyleMetaEngine::removeSaveState(const char *target, int slot) const {
+}
+
+SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ return SaveStateDescriptor();
+}
+
+
+#if PLUGIN_ENABLED_DYNAMIC(GARGOYLE)
+ REGISTER_PLUGIN_DYNAMIC(Gargoyle, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(GARGOYLE, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
+#endif
diff --git a/engines/gargoyle/detection_tables.h b/engines/gargoyle/detection_tables.h
new file mode 100644
index 0000000..780cfe2
--- /dev/null
+++ b/engines/gargoyle/detection_tables.h
@@ -0,0 +1,41 @@
+/* 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.
+ *
+ */
+
+namespace Gargoyle {
+
+static const GargoyleGameDescription gameDescriptions[] = {
+ {
+ {
+ "Gargoyle",
+ 0,
+ AD_ENTRY1s("dummy", "0", 0),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ },
+
+ { AD_TABLE_END_MARKER }
+};
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
new file mode 100644
index 0000000..79cbaf2
--- /dev/null
+++ b/engines/gargoyle/gargoyle.cpp
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "gargoyle/gargoyle.h"
+
+namespace Gargoyle {
+
+GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc)
+ : _gameDescription(gameDesc), Engine(syst) {
+}
+
+GargoyleEngine::~GargoyleEngine() {
+}
+
+void GargoyleEngine::initialize() {
+ // Set up debug channels
+ DebugMan.addDebugChannel(kDebugCore, "core", "Core engine debug level");
+ DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
+ DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
+ DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
+
+ initGraphics(640, 480, false);
+}
+
+Common::Error GargoyleEngine::run() {
+ initialize();
+
+ return Common::kNoError;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
new file mode 100644
index 0000000..79016ea
--- /dev/null
+++ b/engines/gargoyle/gargoyle.h
@@ -0,0 +1,78 @@
+/* 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 GARGOYLE_GARGOLE_H
+#define GARGOYLE_GARGOLE_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/serializer.h"
+#include "engines/advancedDetector.h"
+#include "engines/engine.h"
+
+namespace Gargoyle {
+
+enum GargoyleDebugChannels {
+ kDebugCore = 1 << 0,
+ kDebugScripts = 1 << 1,
+ kDebugGraphics = 1 << 2,
+ kDebugSound = 1 << 3
+};
+
+#define GARGOYLE_SAVEGAME_VERSION 1
+
+struct GargoyleGameDescription;
+
+struct GargoyleSavegameHeader {
+ uint8 _version;
+ Common::String _saveName;
+ Graphics::Surface *_thumbnail;
+ int _year, _month, _day;
+ int _hour, _minute;
+ int _totalFrames;
+};
+
+class GargoyleEngine : public Engine {
+private:
+ /**
+ * Handles basic initialization
+ */
+ void initialize();
+protected:
+ const GargoyleGameDescription *_gameDescription;
+ int _loadSaveSlot;
+
+ // Engine APIs
+ virtual Common::Error run();
+ virtual bool hasFeature(EngineFeature f) const;
+public:
+ GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
+ virtual ~GargoyleEngine();
+
+ uint32 getFeatures() const;
+ bool isDemo() const;
+ Common::Language getLanguage() const;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
new file mode 100644
index 0000000..81b1389
--- /dev/null
+++ b/engines/gargoyle/module.mk
@@ -0,0 +1,13 @@
+MODULE := engines/gargoyle
+
+MODULE_OBJS := \
+ detection.o \
+ gargoyle.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_GARGOYLE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
Commit: 9c536cb6bff1744b39b20a9d29c9e33315025e2d
https://github.com/scummvm/scummvm/commit/9c536cb6bff1744b39b20a9d29c9e33315025e2d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add stub classes for sub-engine components
Changed paths:
A engines/gargoyle/events.cpp
A engines/gargoyle/events.h
A engines/gargoyle/glk.cpp
A engines/gargoyle/glk.h
A engines/gargoyle/interpreter.cpp
A engines/gargoyle/interpreter.h
A engines/gargoyle/scott/scott.cpp
A engines/gargoyle/scott/scott.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
new file mode 100644
index 0000000..93021ef
--- /dev/null
+++ b/engines/gargoyle/events.cpp
@@ -0,0 +1,31 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/events.h"
+
+namespace Gargoyle {
+
+void Events::pollEvents() {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
new file mode 100644
index 0000000..ac66d0e
--- /dev/null
+++ b/engines/gargoyle/events.h
@@ -0,0 +1,40 @@
+/* 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 GARGOYLE_EVENTS_H
+#define GARGOYLE_EVENTS_H
+
+#include "common/events.h"
+
+namespace Gargoyle {
+
+class Events {
+public:
+ /**
+ * Checks for new events
+ */
+ void pollEvents();
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 79cbaf2..e55e4c5 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -31,8 +31,9 @@
namespace Gargoyle {
-GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc)
- : _gameDescription(gameDesc), Engine(syst) {
+GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+ _gameDescription(gameDesc), Engine(syst), _glk(&_screen),
+ _scott(_glk) {
}
GargoyleEngine::~GargoyleEngine() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 79016ea..5e014b5 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -28,6 +28,10 @@
#include "common/serializer.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
+#include "graphics/screen.h"
+#include "gargoyle/events.h"
+#include "gargoyle/glk.h"
+#include "gargoyle/scott/scott.h"
namespace Gargoyle {
@@ -57,9 +61,13 @@ private:
* Handles basic initialization
*/
void initialize();
-protected:
+private:
const GargoyleGameDescription *_gameDescription;
int _loadSaveSlot;
+ Graphics::Screen _screen;
+ Events _events;
+ Glk _glk;
+ Scott::Scott _scott;
// Engine APIs
virtual Common::Error run();
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
new file mode 100644
index 0000000..82447b5
--- /dev/null
+++ b/engines/gargoyle/glk.cpp
@@ -0,0 +1,28 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/glk.h"
+
+namespace Gargoyle {
+
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
new file mode 100644
index 0000000..86c2353
--- /dev/null
+++ b/engines/gargoyle/glk.h
@@ -0,0 +1,45 @@
+/* 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 GARGOYLE_GLK_H
+#define GARGOYLE_GLK_H
+
+#include "graphics/managed_surface.h"
+
+namespace Gargoyle {
+
+/**
+ * Implements the GLK interface
+ */
+class Glk {
+private:
+ Graphics::ManagedSurface *_surface;
+public:
+ /**
+ * Constructor
+ */
+ Glk(Graphics::ManagedSurface *surface) : _surface(surface) {}
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/interpreter.cpp b/engines/gargoyle/interpreter.cpp
new file mode 100644
index 0000000..10cefd7
--- /dev/null
+++ b/engines/gargoyle/interpreter.cpp
@@ -0,0 +1,28 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/interpreter.h"
+
+namespace Gargoyle {
+
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/interpreter.h b/engines/gargoyle/interpreter.h
new file mode 100644
index 0000000..002b46c
--- /dev/null
+++ b/engines/gargoyle/interpreter.h
@@ -0,0 +1,45 @@
+/* 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 GARGOYLE_INTERPRETER_H
+#define GARGOYLE_INTERPRETER_H
+
+#include "gargoyle/glk.h"
+
+namespace Gargoyle {
+
+/**
+ * Base class for specific interpreters
+ */
+class Interpreter {
+protected:
+ Glk &_glk;
+public:
+ /**
+ * Constructor
+ */
+ Interpreter(Glk &glk) : _glk(glk) {}
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 81b1389..937b814 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -2,7 +2,11 @@ MODULE := engines/gargoyle
MODULE_OBJS := \
detection.o \
- gargoyle.o
+ events.o \
+ gargoyle.o \
+ glk.o \
+ interpreter.o \
+ scott/scott.o
# This module can be built as a plugin
ifeq ($(ENABLE_GARGOYLE), DYNAMIC_PLUGIN)
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
new file mode 100644
index 0000000..b5e537c
--- /dev/null
+++ b/engines/gargoyle/scott/scott.cpp
@@ -0,0 +1,30 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/scott/scott.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
new file mode 100644
index 0000000..a5d734f
--- /dev/null
+++ b/engines/gargoyle/scott/scott.h
@@ -0,0 +1,98 @@
+/* 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 GARGOYLE_SCOTT
+#define GARGOYLE_SCOTT
+
+/*
+ * Controlling block
+ */
+
+#include "common/scummsys.h"
+#include "gargoyle/interpreter.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+#define LIGHT_SOURCE 9 // Always 9 how odd
+#define CARRIED 255 // Carried
+#define DESTROYED 0 // Destroyed
+#define DARKBIT 15
+#define LIGHTOUTBIT 16 // Light gone out
+
+#define YOUARE 1 // You are not I am
+#define SCOTTLIGHT 2 // Authentic Scott Adams light messages
+#define DEBUGGING 4 // Info from database load
+#define TRS80_STYLE 8 // Display in style used on TRS-80
+#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
+
+struct Header {
+ int Unknown;
+ int NumItems;
+ int NumActions;
+ int NumWords; // Smaller of verb/noun is padded to same size
+ int NumRooms;
+ int MaxCarry;
+ int PlayerRoom;
+ int Treasures;
+ int WordLength;
+ int LightTime;
+ int NumMessages;
+ int TreasureRoom;
+};
+
+struct Action {
+ uint Vocab;
+ uint Condition[5];
+ uint action[2];
+};
+
+struct Room {
+ char *Text;
+ short Exits[6];
+};
+
+struct Item {
+ char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
+ byte Location;
+ byte InitialLoc;
+ char *AutoGet;
+};
+
+struct Tail {
+ int Version;
+ int AdventureNumber;
+ int Unknown;
+};
+
+class Scott : public Interpreter {
+public:
+ /**
+ * Constructor
+ */
+ Scott(Glk &glk) : Interpreter(glk) {}
+};
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
+
+#endif
Commit: 46aafc35583baefec5b94bde726ea9bddbdacc59
https://github.com/scummvm/scummvm/commit/46aafc35583baefec5b94bde726ea9bddbdacc59
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Refactor Glk to derice from Interpreter
Changed paths:
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.h
engines/gargoyle/interpreter.h
engines/gargoyle/scott/scott.h
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index e55e4c5..731e38d 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -32,8 +32,7 @@
namespace Gargoyle {
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _glk(&_screen),
- _scott(_glk) {
+ _gameDescription(gameDesc), Engine(syst), _interpreter(nullptr) {
}
GargoyleEngine::~GargoyleEngine() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 5e014b5..c43b5fe 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -66,8 +66,7 @@ private:
int _loadSaveSlot;
Graphics::Screen _screen;
Events _events;
- Glk _glk;
- Scott::Scott _scott;
+ Interpreter *_interpreter;
// Engine APIs
virtual Common::Error run();
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 86c2353..4aade7a 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -24,20 +24,21 @@
#define GARGOYLE_GLK_H
#include "graphics/managed_surface.h"
+#include "gargoyle/interpreter.h"
namespace Gargoyle {
/**
* Implements the GLK interface
*/
-class Glk {
+class Glk : public Interpreter {
private:
Graphics::ManagedSurface *_surface;
public:
/**
* Constructor
*/
- Glk(Graphics::ManagedSurface *surface) : _surface(surface) {}
+ Glk() {}
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/interpreter.h b/engines/gargoyle/interpreter.h
index 002b46c..df9172d 100644
--- a/engines/gargoyle/interpreter.h
+++ b/engines/gargoyle/interpreter.h
@@ -23,21 +23,27 @@
#ifndef GARGOYLE_INTERPRETER_H
#define GARGOYLE_INTERPRETER_H
-#include "gargoyle/glk.h"
-
namespace Gargoyle {
/**
* Base class for specific interpreters
*/
class Interpreter {
-protected:
- Glk &_glk;
public:
/**
* Constructor
*/
- Interpreter(Glk &glk) : _glk(glk) {}
+ Interpreter() {}
+
+ /**
+ * Destructor
+ */
+ virtual ~Interpreter() {}
+
+ /**
+ * Main execution method
+ */
+ virtual void execute() = 0;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index a5d734f..bf13cf8 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -28,7 +28,7 @@
*/
#include "common/scummsys.h"
-#include "gargoyle/interpreter.h"
+#include "gargoyle/glk.h"
namespace Gargoyle {
namespace Scott {
@@ -84,12 +84,15 @@ struct Tail {
int Unknown;
};
-class Scott : public Interpreter {
+/**
+ * Scott Adams game interpreter
+ */
+class Scott : public Glk {
public:
/**
* Constructor
*/
- Scott(Glk &glk) : Interpreter(glk) {}
+ Scott() : Glk() {}
};
} // End of namespace Scott
Commit: b2067f3be797352cf2735e985e2a130a7bf386cb
https://github.com/scummvm/scummvm/commit/b2067f3be797352cf2735e985e2a130a7bf386cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added Glk enums and structures
Changed paths:
engines/gargoyle/glk.h
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 4aade7a..781b196 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -28,6 +28,199 @@
namespace Gargoyle {
+typedef uint32 glui32;
+typedef int32 glsi32;
+
+/**
+ * These are the compile-time conditionals that reveal various Glk optional modules.
+ */
+#define GLK_MODULE_LINE_ECHO
+#define GLK_MODULE_LINE_TERMINATORS
+#define GLK_MODULE_UNICODE
+#define GLK_MODULE_UNICODE_NORM
+#define GLK_MODULE_IMAGE
+#define GLK_MODULE_SOUND
+#define GLK_MODULE_SOUND2
+#define GLK_MODULE_HYPERLINKS
+#define GLK_MODULE_DATETIME
+#define GLK_MODULE_GARGLKTEXT
+
+/**
+ * These types are opaque object identifiers. They're pointers to opaque
+ * C structures, which are defined differently by each library.
+ */
+typedef struct glk_window_struct *winid_t;
+typedef struct glk_stream_struct *strid_t;
+typedef struct glk_fileref_struct *frefid_t;
+typedef struct glk_schannel_struct *schanid_t;
+
+enum Gestalt {
+ gestalt_Version = 0,
+ gestalt_CharInput = 1,
+ gestalt_LineInput = 2,
+ gestalt_CharOutput = 3,
+ gestalt_CharOutput_CannotPrint = 0,
+ gestalt_CharOutput_ApproxPrint = 1,
+ gestalt_CharOutput_ExactPrint = 2,
+ gestalt_MouseInput = 4,
+ gestalt_Timer = 5,
+ gestalt_Graphics = 6,
+ gestalt_DrawImage = 7,
+ gestalt_Sound = 8,
+ gestalt_SoundVolume = 9,
+ gestalt_SoundNotify = 10,
+ gestalt_Hyperlinks = 11,
+ gestalt_HyperlinkInput = 12,
+ gestalt_SoundMusic = 13,
+ gestalt_GraphicsTransparency = 14,
+ gestalt_Unicode = 15,
+ gestalt_UnicodeNorm = 16,
+ gestalt_LineInputEcho = 17,
+ gestalt_LineTerminators = 18,
+ gestalt_LineTerminatorKey = 19,
+ gestalt_DateTime = 20,
+ gestalt_Sound2 = 21,
+ gestalt_GarglkText = 0x1100,
+};
+
+enum EvType {
+ evtype_None = 0,
+ evtype_Timer = 1,
+ evtype_CharInput = 2,
+ evtype_LineInput = 3,
+ evtype_MouseInput = 4,
+ evtype_Arrange = 5,
+ evtype_Redraw = 6,
+ evtype_SoundNotify = 7,
+ evtype_Hyperlink = 8,
+ evtype_VolumeNotify = 9,
+};
+
+enum Keycode {
+ keycode_Unknown = 0xffffffffU,
+ keycode_Left = 0xfffffffeU,
+ keycode_Right = 0xfffffffdU,
+ keycode_Up = 0xfffffffcU,
+ keycode_Down = 0xfffffffbU,
+ keycode_Return = 0xfffffffaU,
+ keycode_Delete = 0xfffffff9U,
+ keycode_Escape = 0xfffffff8U,
+ keycode_Tab = 0xfffffff7U,
+ keycode_PageUp = 0xfffffff6U,
+ keycode_PageDown = 0xfffffff5U,
+ keycode_Home = 0xfffffff4U,
+ keycode_End = 0xfffffff3U,
+ keycode_Func1 = 0xffffffefU,
+ keycode_Func2 = 0xffffffeeU,
+ keycode_Func3 = 0xffffffedU,
+ keycode_Func4 = 0xffffffecU,
+ keycode_Func5 = 0xffffffebU,
+ keycode_Func6 = 0xffffffeaU,
+ keycode_Func7 = 0xffffffe9U,
+ keycode_Func8 = 0xffffffe8U,
+ keycode_Func9 = 0xffffffe7U,
+ keycode_Func10 = 0xffffffe6U,
+ keycode_Func11 = 0xffffffe5U,
+ keycode_Func12 = 0xffffffe4U,
+ // The last keycode is always = 0x100000000 - keycode_MAXVAL)
+ keycode_MAXVAL = 28U,
+};
+
+enum Style {
+ style_Normal = 0,
+ style_Emphasized = 1,
+ style_Preformatted = 2,
+ style_Header = 3,
+ style_Subheader = 4,
+ style_Alert = 5,
+ style_Note = 6,
+ style_BlockQuote = 7,
+ style_Input = 8,
+ style_User1 = 9,
+ style_User2 = 10,
+ style_NUMSTYLES = 11,
+};
+
+enum WinType {
+ wintype_AllTypes = 0,
+ wintype_Pair = 1,
+ wintype_Blank = 2,
+ wintype_TextBuffer = 3,
+ wintype_TextGrid = 4,
+ wintype_Graphics = 5,
+};
+
+enum WinMethod {
+ winmethod_Left = 0x00,
+ winmethod_Right = 0x01,
+ winmethod_Above = 0x02,
+ winmethod_Below = 0x03,
+ winmethod_DirMask = 0x0f,
+
+ winmethod_Fixed = 0x10,
+ winmethod_Proportional = 0x20,
+ winmethod_DivisionMask = 0xf0,
+
+ winmethod_Border = 0x000,
+ winmethod_NoBorder = 0x100,
+ winmethod_BorderMask = 0x100,
+};
+
+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,
+};
+
+enum StyleHint {
+ stylehint_Indentation = 0,
+ stylehint_ParaIndentation = 1,
+ stylehint_Justification = 2,
+ stylehint_Size = 3,
+ stylehint_Weight = 4,
+ stylehint_Oblique = 5,
+ stylehint_Proportional = 6,
+ stylehint_TextColor = 7,
+ stylehint_BackColor = 8,
+ stylehint_ReverseColor = 9,
+ stylehint_NUMHINTS = 10,
+
+ stylehint_just_LeftFlush = 0,
+ stylehint_just_LeftRight = 1,
+ stylehint_just_Centered = 2,
+ stylehint_just_RightFlush = 3,
+};
+
+struct event_t {
+ glui32 type;
+ winid_t win;
+ glui32 val1, val2;
+};
+
+struct stream_result_t {
+ glui32 readcount;
+ glui32 writecount;
+};
+
+
/**
* Implements the GLK interface
*/
Commit: fa253ddba703f68fa60fc57316228d69b936a36e
https://github.com/scummvm/scummvm/commit/fa253ddba703f68fa60fc57316228d69b936a36e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added stubs for Glk methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 82447b5..4ea4ce4 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -4,18 +4,18 @@
* 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
+ * 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
+ * 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
+ * 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
+ * along with this program{} if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
@@ -24,5 +24,510 @@
namespace Gargoyle {
+void Glk::glk_exit(void) {
+}
+
+void Glk::glk_set_interrupt_handler(void(*func)(void)) {
+}
+
+void Glk::glk_tick(void) {
+}
+
+glui32 Glk::glk_gestalt(glui32 sel, glui32 val) {
+ return 0;
+}
+
+glui32 Glk::glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) {
+ return 0;
+}
+
+unsigned char Glk::glk_char_to_lower(unsigned char ch) {
+ return '\0';
+}
+
+unsigned char Glk::glk_char_to_upper(unsigned char ch) {
+ return '\0';
+}
+
+winid_t Glk::glk_window_get_root(void) {
+ return nullptr;
+}
+
+winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock) {
+ return nullptr;
+}
+
+void Glk::glk_window_close(winid_t win, stream_result_t *result) {
+}
+
+void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
+}
+
+void Glk::glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keywin) {
+}
+
+void Glk::glk_window_get_arrangement(winid_t win, glui32 *methodptr,
+ glui32 *sizeptr, winid_t *keywinptr) {
+}
+
+winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
+ return nullptr;
+}
+
+glui32 Glk::glk_window_get_rock(winid_t win) {
+ return 0;
+}
+
+glui32 Glk::glk_window_get_type(winid_t win) {
+ return 0;
+}
+
+winid_t Glk::glk_window_get_parent(winid_t win) {
+ return nullptr;
+}
+
+winid_t Glk::glk_window_get_sibling(winid_t win) {
+ return nullptr;
+}
+
+void Glk::glk_window_clear(winid_t win) {
+}
+
+void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
+}
+
+strid_t Glk::glk_window_get_stream(winid_t win) {
+ return nullptr;
+}
+
+void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
+}
+
+strid_t Glk::glk_window_get_echo_stream(winid_t win) {
+ return nullptr;
+}
+
+void Glk::glk_set_window(winid_t win) {
+}
+
+strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
+ glui32 rock) {
+ return nullptr;
+}
+
+strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) {
+ return nullptr;
+}
+
+void Glk::glk_stream_close(strid_t str, stream_result_t *result) {
+}
+
+strid_t Glk::glk_stream_iterate(strid_t str, glui32 *rockptr) {
+ return nullptr;
+}
+
+glui32 Glk::glk_stream_get_rock(strid_t str) {
+ return 0;
+}
+
+void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) {
+}
+
+glui32 Glk::glk_stream_get_position(strid_t str) {
+ return 0;
+}
+
+void Glk::glk_stream_set_current(strid_t str) {
+}
+
+strid_t Glk::glk_stream_get_current(void) {
+ return nullptr;
+}
+
+void Glk::glk_put_char(unsigned char ch) {
+}
+
+void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
+}
+
+void Glk::glk_put_string(char *s) {
+}
+
+void Glk::glk_put_string_stream(strid_t str, char *s) {
+}
+
+void Glk::glk_put_buffer(char *buf, glui32 len) {
+}
+
+void Glk::glk_put_buffer_stream(strid_t str, char *buf, glui32 len) {
+}
+
+void Glk::glk_set_style(glui32 styl) {
+}
+
+void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
+}
+
+glsi32 Glk::glk_get_char_stream(strid_t str) {
+ return 0;
+}
+
+glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
+ return 0;
+}
+
+glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
+ return 0;
+}
+
+void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) {
+}
+
+void Glk::glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) {
+}
+
+glui32 Glk::glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) {
+ return 0;
+}
+
+glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) {
+ return 0;
+}
+
+frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
+ return nullptr;
+}
+
+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) {
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
+ return nullptr;
+}
+
+void Glk::glk_fileref_destroy(frefid_t fref) {
+}
+
+frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
+ return nullptr;
+}
+
+glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
+ return 0;
+}
+
+void Glk::glk_fileref_delete_file(frefid_t fref) {
+}
+
+glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
+ return 0;
+}
+
+void Glk::glk_select(event_t *event) {
+}
+
+void Glk::glk_select_poll(event_t *event) {
+}
+
+void Glk::glk_request_timer_events(glui32 millisecs) {
+}
+
+void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
+}
+
+void Glk::glk_request_char_event(winid_t win) {
+}
+
+void Glk::glk_request_mouse_event(winid_t win) {
+}
+
+void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
+}
+
+void Glk::glk_cancel_char_event(winid_t win) {
+}
+
+void Glk::glk_cancel_mouse_event(winid_t win) {
+}
+
+#ifdef GLK_MODULE_LINE_ECHO
+
+void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
+}
+
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+
+void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
+}
+
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+#ifdef GLK_MODULE_UNICODE
+
+glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return 0;
+}
+
+glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return 0;
+}
+
+glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest) {
+ return 0;
+}
+
+void Glk::glk_put_char_uni(glui32 ch) {
+}
+
+void Glk::glk_put_string_uni(glui32 *s) {
+}
+
+void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
+}
+
+void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
+}
+
+void Glk::glk_put_string_stream_uni(strid_t str, glui32 *s) {
+}
+
+void Glk::glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+}
+
+glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
+ return 0;
+}
+
+glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ return 0;
+}
+
+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) {
+ return nullptr;
+}
+
+strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen,
+ glui32 fmode, glui32 rock) {
+ return nullptr;
+}
+
+void Glk::glk_request_char_event_uni(winid_t win) {
+}
+
+void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen) {
+}
+
+#endif /* GLK_MODULE_UNICODE */
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars) {
+ return 0;
+}
+
+glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return 0;
+}
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
+ return 0;
+}
+
+glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height) {
+ return 0;
+}
+
+glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
+ return 0;
+}
+
+void Glk::glk_window_flow_break(winid_t win) {
+}
+
+void Glk::glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height) {
+}
+
+void Glk::glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height) {
+}
+
+void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
+}
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+schanid_t Glk::glk_schannel_create(glui32 rock) {
+ return nullptr;
+}
+
+void Glk::glk_schannel_destroy(schanid_t chan) {
+}
+
+schanid_t Glk::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
+ return nullptr;
+}
+
+glui32 Glk::glk_schannel_get_rock(schanid_t chan) {
+ return 0;
+}
+
+glui32 Glk::glk_schannel_play(schanid_t chan, glui32 snd) {
+ return 0;
+}
+
+glui32 Glk::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
+ return 0;
+}
+
+void Glk::glk_schannel_stop(schanid_t chan) {
+}
+
+void Glk::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
+}
+
+void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
+}
+
+#ifdef GLK_MODULE_SOUND2
+
+schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
+ return nullptr;
+}
+
+glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify) {
+ return 0;
+}
+
+void Glk::glk_schannel_pause(schanid_t chan) {
+}
+
+void Glk::glk_schannel_unpause(schanid_t chan) {
+}
+
+void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify) {
+}
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+void Glk::glk_set_hyperlink(glui32 linkval) {
+}
+
+void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
+}
+
+void Glk::glk_request_hyperlink_event(winid_t win) {
+}
+
+void Glk::glk_cancel_hyperlink_event(winid_t win) {
+}
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+void Glk::glk_current_time(glktimeval_t *time) {
+}
+
+glsi32 Glk::glk_current_simple_time(glui32 factor) {
+ return 0;
+}
+
+void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) {
+}
+
+void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) {
+}
+
+void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
+}
+
+void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
+}
+
+void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) {
+}
+
+void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) {
+}
+
+glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) {
+ return 0;
+}
+
+glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
+ return 0;
+}
+
+#endif /* GLK_MODULE_DATETIME */
+
+/* XXX non-official Glk functions that may or may not exist */
+
+char *garglk_fileref_get_name(frefid_t fref) {
+ return nullptr;
+}
+
+void Glk::garglk_set_program_name(const char *name) {
+}
+
+void Glk::garglk_set_program_info(const char *info) {
+}
+
+void Glk::garglk_set_story_name(const char *name) {
+}
+
+void Glk::garglk_set_story_title(const char *title) {
+}
+
+void Glk::garglk_set_config(const char *name) {
+}
+
+/* garglk_unput_string - removes the specified string from the end of the output buffer, if
+* indeed it is there. */
+void Glk::garglk_unput_string(char *str) {
+}
+
+void Glk::garglk_unput_string_uni(glui32 *str) {
+}
+
+void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
+}
+
+void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
+}
+
+void Glk::garglk_set_reversevideo(glui32 reverse) {
+}
+
+void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
+}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 781b196..2e5637b 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -122,8 +122,16 @@ enum Keycode {
keycode_Func10 = 0xffffffe6U,
keycode_Func11 = 0xffffffe5U,
keycode_Func12 = 0xffffffe4U,
+
+ // non standard keycodes
+ keycode_Erase = 0xffffef7fU,
+ keycode_MouseWheelUp = 0xffffeffeU,
+ keycode_MouseWheelDown = 0xffffefffU,
+ keycode_SkipWordLeft = 0xfffff000U,
+ keycode_SkipWordRight = 0xfffff001U,
+
// The last keycode is always = 0x100000000 - keycode_MAXVAL)
- keycode_MAXVAL = 28U,
+ keycode_MAXVAL = 28U
};
enum Style {
@@ -209,17 +217,53 @@ enum StyleHint {
stylehint_just_RightFlush = 3,
};
-struct event_t {
+#ifdef GLK_MODULE_IMAGE
+
+enum ImageAlign {
+ imagealign_InlineUp = 1,
+ imagealign_InlineDown = 2,
+ imagealign_InlineCenter = 3,
+ imagealign_MarginLeft = 4,
+ imagealign_MarginRight = 5
+};
+
+#endif /* GLK_MODULE_IMAGE */
+
+struct event_struct {
glui32 type;
winid_t win;
glui32 val1, val2;
};
+typedef event_struct *event_t;
-struct stream_result_t {
+struct stream_result_struct {
glui32 readcount;
glui32 writecount;
};
+typedef stream_result_struct *stream_result_t;
+#ifdef GLK_MODULE_DATETIME
+
+struct glktimeval_struct {
+ glsi32 high_sec;
+ glui32 low_sec;
+ glsi32 microsec;
+};
+typedef glktimeval_struct *glktimeval_t;
+
+struct glkdate_struct {
+ glsi32 year; /* full (four-digit) year */
+ glsi32 month; /* 1-12, 1 is January */
+ glsi32 day; /* 1-31 */
+ glsi32 weekday; /* 0-6, 0 is Sunday */
+ glsi32 hour; /* 0-23 */
+ glsi32 minute; /* 0-59 */
+ glsi32 second; /* 0-59, maybe 60 during a leap second */
+ glsi32 microsec; /* 0-999999 */
+};
+typedef glkdate_struct *glkdate_t;
+
+#endif /* GLK_MODULE_DATETIME */
/**
* Implements the GLK interface
@@ -232,6 +276,241 @@ public:
* Constructor
*/
Glk() {}
+
+ void glk_exit(void);
+ void glk_set_interrupt_handler(void(*func)(void));
+ void glk_tick(void);
+
+ glui32 glk_gestalt(glui32 sel, glui32 val);
+ glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen);
+
+ unsigned char glk_char_to_lower(unsigned char ch);
+ unsigned char glk_char_to_upper(unsigned char ch);
+
+ winid_t glk_window_get_root(void);
+ winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock);
+ void glk_window_close(winid_t win, stream_result_t *result);
+ void glk_window_get_size(winid_t win, glui32 *widthptr,
+ glui32 *heightptr);
+ void glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keywin);
+ void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
+ glui32 *sizeptr, winid_t *keywinptr);
+ winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
+ glui32 glk_window_get_rock(winid_t win);
+ glui32 glk_window_get_type(winid_t win);
+ winid_t glk_window_get_parent(winid_t win);
+ winid_t glk_window_get_sibling(winid_t win);
+ void glk_window_clear(winid_t win);
+ void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
+
+ strid_t glk_window_get_stream(winid_t win);
+ void glk_window_set_echo_stream(winid_t win, strid_t str);
+ 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);
+ 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);
+ 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);
+ strid_t glk_stream_get_current(void);
+
+ void glk_put_char(unsigned char ch);
+ void glk_put_char_stream(strid_t str, unsigned char ch);
+ void glk_put_string(char *s);
+ void glk_put_string_stream(strid_t str, char *s);
+ void glk_put_buffer(char *buf, glui32 len);
+ void glk_put_buffer_stream(strid_t str, char *buf, glui32 len);
+ void glk_set_style(glui32 styl);
+ void glk_set_style_stream(strid_t str, glui32 styl);
+
+ glsi32 glk_get_char_stream(strid_t str);
+ glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
+ glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
+
+ void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
+ glsi32 val);
+ void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
+ glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
+ glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
+ glui32 *result);
+
+ 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,
+ glui32 rock);
+ frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
+ glui32 rock);
+ void glk_fileref_destroy(frefid_t fref);
+ frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
+ glui32 glk_fileref_get_rock(frefid_t fref);
+ void glk_fileref_delete_file(frefid_t fref);
+ glui32 glk_fileref_does_file_exist(frefid_t fref);
+
+ void glk_select(event_t *event);
+ void glk_select_poll(event_t *event);
+
+ void glk_request_timer_events(glui32 millisecs);
+
+ void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
+ glui32 initlen);
+ void glk_request_char_event(winid_t win);
+ void glk_request_mouse_event(winid_t win);
+
+ void glk_cancel_line_event(winid_t win, event_t *event);
+ void glk_cancel_char_event(winid_t win);
+ void glk_cancel_mouse_event(winid_t win);
+
+#ifdef GLK_MODULE_LINE_ECHO
+ void glk_set_echo_line_event(winid_t win, glui32 val);
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+ void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
+ glui32 count);
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+#ifdef GLK_MODULE_UNICODE
+
+ glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest);
+
+ void glk_put_char_uni(glui32 ch);
+ void glk_put_string_uni(glui32 *s);
+ void glk_put_buffer_uni(glui32 *buf, glui32 len);
+ void glk_put_char_stream_uni(strid_t str, glui32 ch);
+ void glk_put_string_stream_uni(strid_t str, glui32 *s);
+ void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
+
+ glsi32 glk_get_char_stream_uni(strid_t str);
+ 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);
+
+ void glk_request_char_event_uni(winid_t win);
+ void glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen);
+
+#endif /* GLK_MODULE_UNICODE */
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+ glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+ glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
+ glui32 glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height);
+ glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
+
+ void glk_window_flow_break(winid_t win);
+
+ void glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_set_background_color(winid_t win, glui32 color);
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+ schanid_t glk_schannel_create(glui32 rock);
+ void glk_schannel_destroy(schanid_t chan);
+ schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
+ glui32 glk_schannel_get_rock(schanid_t chan);
+
+ glui32 glk_schannel_play(schanid_t chan, glui32 snd);
+ glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
+ glui32 notify);
+ void glk_schannel_stop(schanid_t chan);
+ void glk_schannel_set_volume(schanid_t chan, glui32 vol);
+
+ void glk_sound_load_hint(glui32 snd, glui32 flag);
+
+#ifdef GLK_MODULE_SOUND2
+ /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
+ GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
+
+ schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
+ glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify);
+ void glk_schannel_pause(schanid_t chan);
+ void glk_schannel_unpause(schanid_t chan);
+ void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify);
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+ void glk_set_hyperlink(glui32 linkval);
+ void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
+ void glk_request_hyperlink_event(winid_t win);
+ void glk_cancel_hyperlink_event(winid_t win);
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+ void glk_current_time(glktimeval_t *time);
+ glsi32 glk_current_simple_time(glui32 factor);
+ void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
+ void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
+ void glk_simple_time_to_date_utc(glsi32 time, glui32 factor,
+ glkdate_t *date);
+ void glk_simple_time_to_date_local(glsi32 time, glui32 factor,
+ glkdate_t *date);
+ void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
+ void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
+ glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
+ glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);
+
+#endif /* GLK_MODULE_DATETIME */
+
+ /* XXX non-official Glk functions that may or may not exist */
+ #define GARGLK 1
+
+ char* garglk_fileref_get_name(frefid_t fref);
+
+ void garglk_set_program_name(const char *name);
+ void garglk_set_program_info(const char *info);
+ void garglk_set_story_name(const char *name);
+ void garglk_set_story_title(const char *title);
+ void garglk_set_config(const char *name);
+
+ /* garglk_unput_string - removes the specified string from the end of the output buffer, if
+ * indeed it is there. */
+ void garglk_unput_string(char *str);
+ void garglk_unput_string_uni(glui32 *str);
+
+ void garglk_set_zcolors(glui32 fg, glui32 bg);
+ void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
+ void garglk_set_reversevideo(glui32 reverse);
+ void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
};
} // End of namespace Gargoyle
Commit: dcefdd6f620b07da6f70b01f784716b2e73adcf7
https://github.com/scummvm/scummvm/commit/dcefdd6f620b07da6f70b01f784716b2e73adcf7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: More outer engine structure, and cleanup
Changed paths:
A engines/gargoyle/glk/glk.cpp
A engines/gargoyle/glk/glk.h
A engines/gargoyle/glk/glk_types.h
A engines/gargoyle/interps/scott/scott.cpp
A engines/gargoyle/interps/scott/scott.h
R engines/gargoyle/glk.cpp
R engines/gargoyle/glk.h
R engines/gargoyle/scott/scott.cpp
R engines/gargoyle/scott/scott.h
engines/gargoyle/detection.cpp
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/interpreter.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 94fb90f..f10a70b 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -37,6 +37,7 @@ namespace Gargoyle {
struct GargoyleGameDescription {
ADGameDescription desc;
+ InterpreterType interpType;
};
uint32 GargoyleEngine::getFeatures() const {
@@ -51,6 +52,10 @@ Common::Language GargoyleEngine::getLanguage() const {
return _gameDescription->desc.language;
}
+InterpreterType GargoyleEngine::getInterpreterType() const {
+ return _gameDescription->interpType;
+}
+
} // End of namespace Gargoyle
static const PlainGameDescriptor GargoyleGames[] = {
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 731e38d..b46f2fc 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -28,6 +28,7 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/interps/scott/scott.h"
namespace Gargoyle {
@@ -36,6 +37,7 @@ GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gam
}
GargoyleEngine::~GargoyleEngine() {
+ delete _interpreter;
}
void GargoyleEngine::initialize() {
@@ -46,10 +48,19 @@ void GargoyleEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphics(640, 480, false);
+
+ switch (getInterpreterType()) {
+ case INTERPRETER_SCOTT:
+ _interpreter = new Scott::Scott();
+ break;
+ default:
+ error("Unknown interpreter type");
+ }
}
Common::Error GargoyleEngine::run() {
initialize();
+ _interpreter->execute();
return Common::kNoError;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index c43b5fe..375d9ad 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -28,13 +28,14 @@
#include "common/serializer.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
-#include "graphics/screen.h"
-#include "gargoyle/events.h"
-#include "gargoyle/glk.h"
-#include "gargoyle/scott/scott.h"
+#include "gargoyle/interpreter.h"
namespace Gargoyle {
+enum InterpreterType {
+ INTERPRETER_SCOTT
+};
+
enum GargoyleDebugChannels {
kDebugCore = 1 << 0,
kDebugScripts = 1 << 1,
@@ -42,6 +43,7 @@ enum GargoyleDebugChannels {
kDebugSound = 1 << 3
};
+
#define GARGOYLE_SAVEGAME_VERSION 1
struct GargoyleGameDescription;
@@ -64,8 +66,6 @@ private:
private:
const GargoyleGameDescription *_gameDescription;
int _loadSaveSlot;
- Graphics::Screen _screen;
- Events _events;
Interpreter *_interpreter;
// Engine APIs
@@ -78,6 +78,7 @@ public:
uint32 getFeatures() const;
bool isDemo() const;
Common::Language getLanguage() const;
+ InterpreterType getInterpreterType() const;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
deleted file mode 100644
index 4ea4ce4..0000000
--- a/engines/gargoyle/glk.cpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/glk.h"
-
-namespace Gargoyle {
-
-void Glk::glk_exit(void) {
-}
-
-void Glk::glk_set_interrupt_handler(void(*func)(void)) {
-}
-
-void Glk::glk_tick(void) {
-}
-
-glui32 Glk::glk_gestalt(glui32 sel, glui32 val) {
- return 0;
-}
-
-glui32 Glk::glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) {
- return 0;
-}
-
-unsigned char Glk::glk_char_to_lower(unsigned char ch) {
- return '\0';
-}
-
-unsigned char Glk::glk_char_to_upper(unsigned char ch) {
- return '\0';
-}
-
-winid_t Glk::glk_window_get_root(void) {
- return nullptr;
-}
-
-winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock) {
- return nullptr;
-}
-
-void Glk::glk_window_close(winid_t win, stream_result_t *result) {
-}
-
-void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
-}
-
-void Glk::glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keywin) {
-}
-
-void Glk::glk_window_get_arrangement(winid_t win, glui32 *methodptr,
- glui32 *sizeptr, winid_t *keywinptr) {
-}
-
-winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
- return nullptr;
-}
-
-glui32 Glk::glk_window_get_rock(winid_t win) {
- return 0;
-}
-
-glui32 Glk::glk_window_get_type(winid_t win) {
- return 0;
-}
-
-winid_t Glk::glk_window_get_parent(winid_t win) {
- return nullptr;
-}
-
-winid_t Glk::glk_window_get_sibling(winid_t win) {
- return nullptr;
-}
-
-void Glk::glk_window_clear(winid_t win) {
-}
-
-void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
-}
-
-strid_t Glk::glk_window_get_stream(winid_t win) {
- return nullptr;
-}
-
-void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
-}
-
-strid_t Glk::glk_window_get_echo_stream(winid_t win) {
- return nullptr;
-}
-
-void Glk::glk_set_window(winid_t win) {
-}
-
-strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
- glui32 rock) {
- return nullptr;
-}
-
-strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) {
- return nullptr;
-}
-
-void Glk::glk_stream_close(strid_t str, stream_result_t *result) {
-}
-
-strid_t Glk::glk_stream_iterate(strid_t str, glui32 *rockptr) {
- return nullptr;
-}
-
-glui32 Glk::glk_stream_get_rock(strid_t str) {
- return 0;
-}
-
-void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) {
-}
-
-glui32 Glk::glk_stream_get_position(strid_t str) {
- return 0;
-}
-
-void Glk::glk_stream_set_current(strid_t str) {
-}
-
-strid_t Glk::glk_stream_get_current(void) {
- return nullptr;
-}
-
-void Glk::glk_put_char(unsigned char ch) {
-}
-
-void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
-}
-
-void Glk::glk_put_string(char *s) {
-}
-
-void Glk::glk_put_string_stream(strid_t str, char *s) {
-}
-
-void Glk::glk_put_buffer(char *buf, glui32 len) {
-}
-
-void Glk::glk_put_buffer_stream(strid_t str, char *buf, glui32 len) {
-}
-
-void Glk::glk_set_style(glui32 styl) {
-}
-
-void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
-}
-
-glsi32 Glk::glk_get_char_stream(strid_t str) {
- return 0;
-}
-
-glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
- return 0;
-}
-
-glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
- return 0;
-}
-
-void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) {
-}
-
-void Glk::glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) {
-}
-
-glui32 Glk::glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) {
- return 0;
-}
-
-glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) {
- return 0;
-}
-
-frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
- return nullptr;
-}
-
-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) {
- return nullptr;
-}
-
-frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
- return nullptr;
-}
-
-void Glk::glk_fileref_destroy(frefid_t fref) {
-}
-
-frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
- return nullptr;
-}
-
-glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
- return 0;
-}
-
-void Glk::glk_fileref_delete_file(frefid_t fref) {
-}
-
-glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
- return 0;
-}
-
-void Glk::glk_select(event_t *event) {
-}
-
-void Glk::glk_select_poll(event_t *event) {
-}
-
-void Glk::glk_request_timer_events(glui32 millisecs) {
-}
-
-void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
-}
-
-void Glk::glk_request_char_event(winid_t win) {
-}
-
-void Glk::glk_request_mouse_event(winid_t win) {
-}
-
-void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
-}
-
-void Glk::glk_cancel_char_event(winid_t win) {
-}
-
-void Glk::glk_cancel_mouse_event(winid_t win) {
-}
-
-#ifdef GLK_MODULE_LINE_ECHO
-
-void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
-}
-
-#endif /* GLK_MODULE_LINE_ECHO */
-
-#ifdef GLK_MODULE_LINE_TERMINATORS
-
-void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
-}
-
-#endif /* GLK_MODULE_LINE_TERMINATORS */
-
-#ifdef GLK_MODULE_UNICODE
-
-glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return 0;
-}
-
-glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return 0;
-}
-
-glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest) {
- return 0;
-}
-
-void Glk::glk_put_char_uni(glui32 ch) {
-}
-
-void Glk::glk_put_string_uni(glui32 *s) {
-}
-
-void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
-}
-
-void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
-}
-
-void Glk::glk_put_string_stream_uni(strid_t str, glui32 *s) {
-}
-
-void Glk::glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
-}
-
-glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
- return 0;
-}
-
-glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- return 0;
-}
-
-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) {
- return nullptr;
-}
-
-strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen,
- glui32 fmode, glui32 rock) {
- return nullptr;
-}
-
-void Glk::glk_request_char_event_uni(winid_t win) {
-}
-
-void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen) {
-}
-
-#endif /* GLK_MODULE_UNICODE */
-
-#ifdef GLK_MODULE_UNICODE_NORM
-
-glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars) {
- return 0;
-}
-
-glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return 0;
-}
-
-#endif /* GLK_MODULE_UNICODE_NORM */
-
-#ifdef GLK_MODULE_IMAGE
-
-glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
- return 0;
-}
-
-glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height) {
- return 0;
-}
-
-glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
- return 0;
-}
-
-void Glk::glk_window_flow_break(winid_t win) {
-}
-
-void Glk::glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height) {
-}
-
-void Glk::glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height) {
-}
-
-void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
-}
-
-#endif /* GLK_MODULE_IMAGE */
-
-#ifdef GLK_MODULE_SOUND
-
-schanid_t Glk::glk_schannel_create(glui32 rock) {
- return nullptr;
-}
-
-void Glk::glk_schannel_destroy(schanid_t chan) {
-}
-
-schanid_t Glk::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
- return nullptr;
-}
-
-glui32 Glk::glk_schannel_get_rock(schanid_t chan) {
- return 0;
-}
-
-glui32 Glk::glk_schannel_play(schanid_t chan, glui32 snd) {
- return 0;
-}
-
-glui32 Glk::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
- return 0;
-}
-
-void Glk::glk_schannel_stop(schanid_t chan) {
-}
-
-void Glk::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
-}
-
-void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
-}
-
-#ifdef GLK_MODULE_SOUND2
-
-schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
- return nullptr;
-}
-
-glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify) {
- return 0;
-}
-
-void Glk::glk_schannel_pause(schanid_t chan) {
-}
-
-void Glk::glk_schannel_unpause(schanid_t chan) {
-}
-
-void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify) {
-}
-
-#endif /* GLK_MODULE_SOUND2 */
-#endif /* GLK_MODULE_SOUND */
-
-#ifdef GLK_MODULE_HYPERLINKS
-
-void Glk::glk_set_hyperlink(glui32 linkval) {
-}
-
-void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
-}
-
-void Glk::glk_request_hyperlink_event(winid_t win) {
-}
-
-void Glk::glk_cancel_hyperlink_event(winid_t win) {
-}
-
-#endif /* GLK_MODULE_HYPERLINKS */
-
-#ifdef GLK_MODULE_DATETIME
-
-void Glk::glk_current_time(glktimeval_t *time) {
-}
-
-glsi32 Glk::glk_current_simple_time(glui32 factor) {
- return 0;
-}
-
-void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) {
-}
-
-void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) {
-}
-
-void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
-}
-
-void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
-}
-
-void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) {
-}
-
-void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) {
-}
-
-glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) {
- return 0;
-}
-
-glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
- return 0;
-}
-
-#endif /* GLK_MODULE_DATETIME */
-
-/* XXX non-official Glk functions that may or may not exist */
-
-char *garglk_fileref_get_name(frefid_t fref) {
- return nullptr;
-}
-
-void Glk::garglk_set_program_name(const char *name) {
-}
-
-void Glk::garglk_set_program_info(const char *info) {
-}
-
-void Glk::garglk_set_story_name(const char *name) {
-}
-
-void Glk::garglk_set_story_title(const char *title) {
-}
-
-void Glk::garglk_set_config(const char *name) {
-}
-
-/* garglk_unput_string - removes the specified string from the end of the output buffer, if
-* indeed it is there. */
-void Glk::garglk_unput_string(char *str) {
-}
-
-void Glk::garglk_unput_string_uni(glui32 *str) {
-}
-
-void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
-}
-
-void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
-}
-
-void Glk::garglk_set_reversevideo(glui32 reverse) {
-}
-
-void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
deleted file mode 100644
index 2e5637b..0000000
--- a/engines/gargoyle/glk.h
+++ /dev/null
@@ -1,518 +0,0 @@
-/* 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 GARGOYLE_GLK_H
-#define GARGOYLE_GLK_H
-
-#include "graphics/managed_surface.h"
-#include "gargoyle/interpreter.h"
-
-namespace Gargoyle {
-
-typedef uint32 glui32;
-typedef int32 glsi32;
-
-/**
- * These are the compile-time conditionals that reveal various Glk optional modules.
- */
-#define GLK_MODULE_LINE_ECHO
-#define GLK_MODULE_LINE_TERMINATORS
-#define GLK_MODULE_UNICODE
-#define GLK_MODULE_UNICODE_NORM
-#define GLK_MODULE_IMAGE
-#define GLK_MODULE_SOUND
-#define GLK_MODULE_SOUND2
-#define GLK_MODULE_HYPERLINKS
-#define GLK_MODULE_DATETIME
-#define GLK_MODULE_GARGLKTEXT
-
-/**
- * These types are opaque object identifiers. They're pointers to opaque
- * C structures, which are defined differently by each library.
- */
-typedef struct glk_window_struct *winid_t;
-typedef struct glk_stream_struct *strid_t;
-typedef struct glk_fileref_struct *frefid_t;
-typedef struct glk_schannel_struct *schanid_t;
-
-enum Gestalt {
- gestalt_Version = 0,
- gestalt_CharInput = 1,
- gestalt_LineInput = 2,
- gestalt_CharOutput = 3,
- gestalt_CharOutput_CannotPrint = 0,
- gestalt_CharOutput_ApproxPrint = 1,
- gestalt_CharOutput_ExactPrint = 2,
- gestalt_MouseInput = 4,
- gestalt_Timer = 5,
- gestalt_Graphics = 6,
- gestalt_DrawImage = 7,
- gestalt_Sound = 8,
- gestalt_SoundVolume = 9,
- gestalt_SoundNotify = 10,
- gestalt_Hyperlinks = 11,
- gestalt_HyperlinkInput = 12,
- gestalt_SoundMusic = 13,
- gestalt_GraphicsTransparency = 14,
- gestalt_Unicode = 15,
- gestalt_UnicodeNorm = 16,
- gestalt_LineInputEcho = 17,
- gestalt_LineTerminators = 18,
- gestalt_LineTerminatorKey = 19,
- gestalt_DateTime = 20,
- gestalt_Sound2 = 21,
- gestalt_GarglkText = 0x1100,
-};
-
-enum EvType {
- evtype_None = 0,
- evtype_Timer = 1,
- evtype_CharInput = 2,
- evtype_LineInput = 3,
- evtype_MouseInput = 4,
- evtype_Arrange = 5,
- evtype_Redraw = 6,
- evtype_SoundNotify = 7,
- evtype_Hyperlink = 8,
- evtype_VolumeNotify = 9,
-};
-
-enum Keycode {
- keycode_Unknown = 0xffffffffU,
- keycode_Left = 0xfffffffeU,
- keycode_Right = 0xfffffffdU,
- keycode_Up = 0xfffffffcU,
- keycode_Down = 0xfffffffbU,
- keycode_Return = 0xfffffffaU,
- keycode_Delete = 0xfffffff9U,
- keycode_Escape = 0xfffffff8U,
- keycode_Tab = 0xfffffff7U,
- keycode_PageUp = 0xfffffff6U,
- keycode_PageDown = 0xfffffff5U,
- keycode_Home = 0xfffffff4U,
- keycode_End = 0xfffffff3U,
- keycode_Func1 = 0xffffffefU,
- keycode_Func2 = 0xffffffeeU,
- keycode_Func3 = 0xffffffedU,
- keycode_Func4 = 0xffffffecU,
- keycode_Func5 = 0xffffffebU,
- keycode_Func6 = 0xffffffeaU,
- keycode_Func7 = 0xffffffe9U,
- keycode_Func8 = 0xffffffe8U,
- keycode_Func9 = 0xffffffe7U,
- keycode_Func10 = 0xffffffe6U,
- keycode_Func11 = 0xffffffe5U,
- keycode_Func12 = 0xffffffe4U,
-
- // non standard keycodes
- keycode_Erase = 0xffffef7fU,
- keycode_MouseWheelUp = 0xffffeffeU,
- keycode_MouseWheelDown = 0xffffefffU,
- keycode_SkipWordLeft = 0xfffff000U,
- keycode_SkipWordRight = 0xfffff001U,
-
- // The last keycode is always = 0x100000000 - keycode_MAXVAL)
- keycode_MAXVAL = 28U
-};
-
-enum Style {
- style_Normal = 0,
- style_Emphasized = 1,
- style_Preformatted = 2,
- style_Header = 3,
- style_Subheader = 4,
- style_Alert = 5,
- style_Note = 6,
- style_BlockQuote = 7,
- style_Input = 8,
- style_User1 = 9,
- style_User2 = 10,
- style_NUMSTYLES = 11,
-};
-
-enum WinType {
- wintype_AllTypes = 0,
- wintype_Pair = 1,
- wintype_Blank = 2,
- wintype_TextBuffer = 3,
- wintype_TextGrid = 4,
- wintype_Graphics = 5,
-};
-
-enum WinMethod {
- winmethod_Left = 0x00,
- winmethod_Right = 0x01,
- winmethod_Above = 0x02,
- winmethod_Below = 0x03,
- winmethod_DirMask = 0x0f,
-
- winmethod_Fixed = 0x10,
- winmethod_Proportional = 0x20,
- winmethod_DivisionMask = 0xf0,
-
- winmethod_Border = 0x000,
- winmethod_NoBorder = 0x100,
- winmethod_BorderMask = 0x100,
-};
-
-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,
-};
-
-enum StyleHint {
- stylehint_Indentation = 0,
- stylehint_ParaIndentation = 1,
- stylehint_Justification = 2,
- stylehint_Size = 3,
- stylehint_Weight = 4,
- stylehint_Oblique = 5,
- stylehint_Proportional = 6,
- stylehint_TextColor = 7,
- stylehint_BackColor = 8,
- stylehint_ReverseColor = 9,
- stylehint_NUMHINTS = 10,
-
- stylehint_just_LeftFlush = 0,
- stylehint_just_LeftRight = 1,
- stylehint_just_Centered = 2,
- stylehint_just_RightFlush = 3,
-};
-
-#ifdef GLK_MODULE_IMAGE
-
-enum ImageAlign {
- imagealign_InlineUp = 1,
- imagealign_InlineDown = 2,
- imagealign_InlineCenter = 3,
- imagealign_MarginLeft = 4,
- imagealign_MarginRight = 5
-};
-
-#endif /* GLK_MODULE_IMAGE */
-
-struct event_struct {
- glui32 type;
- winid_t win;
- glui32 val1, val2;
-};
-typedef event_struct *event_t;
-
-struct stream_result_struct {
- glui32 readcount;
- glui32 writecount;
-};
-typedef stream_result_struct *stream_result_t;
-
-#ifdef GLK_MODULE_DATETIME
-
-struct glktimeval_struct {
- glsi32 high_sec;
- glui32 low_sec;
- glsi32 microsec;
-};
-typedef glktimeval_struct *glktimeval_t;
-
-struct glkdate_struct {
- glsi32 year; /* full (four-digit) year */
- glsi32 month; /* 1-12, 1 is January */
- glsi32 day; /* 1-31 */
- glsi32 weekday; /* 0-6, 0 is Sunday */
- glsi32 hour; /* 0-23 */
- glsi32 minute; /* 0-59 */
- glsi32 second; /* 0-59, maybe 60 during a leap second */
- glsi32 microsec; /* 0-999999 */
-};
-typedef glkdate_struct *glkdate_t;
-
-#endif /* GLK_MODULE_DATETIME */
-
-/**
- * Implements the GLK interface
- */
-class Glk : public Interpreter {
-private:
- Graphics::ManagedSurface *_surface;
-public:
- /**
- * Constructor
- */
- Glk() {}
-
- void glk_exit(void);
- void glk_set_interrupt_handler(void(*func)(void));
- void glk_tick(void);
-
- glui32 glk_gestalt(glui32 sel, glui32 val);
- glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen);
-
- unsigned char glk_char_to_lower(unsigned char ch);
- unsigned char glk_char_to_upper(unsigned char ch);
-
- winid_t glk_window_get_root(void);
- winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock);
- void glk_window_close(winid_t win, stream_result_t *result);
- void glk_window_get_size(winid_t win, glui32 *widthptr,
- glui32 *heightptr);
- void glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keywin);
- void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
- glui32 *sizeptr, winid_t *keywinptr);
- winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
- glui32 glk_window_get_rock(winid_t win);
- glui32 glk_window_get_type(winid_t win);
- winid_t glk_window_get_parent(winid_t win);
- winid_t glk_window_get_sibling(winid_t win);
- void glk_window_clear(winid_t win);
- void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
-
- strid_t glk_window_get_stream(winid_t win);
- void glk_window_set_echo_stream(winid_t win, strid_t str);
- 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);
- 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);
- 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);
- strid_t glk_stream_get_current(void);
-
- void glk_put_char(unsigned char ch);
- void glk_put_char_stream(strid_t str, unsigned char ch);
- void glk_put_string(char *s);
- void glk_put_string_stream(strid_t str, char *s);
- void glk_put_buffer(char *buf, glui32 len);
- void glk_put_buffer_stream(strid_t str, char *buf, glui32 len);
- void glk_set_style(glui32 styl);
- void glk_set_style_stream(strid_t str, glui32 styl);
-
- glsi32 glk_get_char_stream(strid_t str);
- glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
- glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
-
- void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
- glsi32 val);
- void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
- glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
- glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
- glui32 *result);
-
- 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,
- glui32 rock);
- frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
- glui32 rock);
- void glk_fileref_destroy(frefid_t fref);
- frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
- glui32 glk_fileref_get_rock(frefid_t fref);
- void glk_fileref_delete_file(frefid_t fref);
- glui32 glk_fileref_does_file_exist(frefid_t fref);
-
- void glk_select(event_t *event);
- void glk_select_poll(event_t *event);
-
- void glk_request_timer_events(glui32 millisecs);
-
- void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
- glui32 initlen);
- void glk_request_char_event(winid_t win);
- void glk_request_mouse_event(winid_t win);
-
- void glk_cancel_line_event(winid_t win, event_t *event);
- void glk_cancel_char_event(winid_t win);
- void glk_cancel_mouse_event(winid_t win);
-
-#ifdef GLK_MODULE_LINE_ECHO
- void glk_set_echo_line_event(winid_t win, glui32 val);
-#endif /* GLK_MODULE_LINE_ECHO */
-
-#ifdef GLK_MODULE_LINE_TERMINATORS
- void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
- glui32 count);
-#endif /* GLK_MODULE_LINE_TERMINATORS */
-
-#ifdef GLK_MODULE_UNICODE
-
- glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest);
-
- void glk_put_char_uni(glui32 ch);
- void glk_put_string_uni(glui32 *s);
- void glk_put_buffer_uni(glui32 *buf, glui32 len);
- void glk_put_char_stream_uni(strid_t str, glui32 ch);
- void glk_put_string_stream_uni(strid_t str, glui32 *s);
- void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
-
- glsi32 glk_get_char_stream_uni(strid_t str);
- 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);
-
- void glk_request_char_event_uni(winid_t win);
- void glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen);
-
-#endif /* GLK_MODULE_UNICODE */
-
-#ifdef GLK_MODULE_UNICODE_NORM
-
- glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
- glui32 numchars);
-
-#endif /* GLK_MODULE_UNICODE_NORM */
-
-#ifdef GLK_MODULE_IMAGE
-
- glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
- glui32 glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height);
- glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
-
- void glk_window_flow_break(winid_t win);
-
- void glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
- void glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
- void glk_window_set_background_color(winid_t win, glui32 color);
-
-#endif /* GLK_MODULE_IMAGE */
-
-#ifdef GLK_MODULE_SOUND
-
- schanid_t glk_schannel_create(glui32 rock);
- void glk_schannel_destroy(schanid_t chan);
- schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
- glui32 glk_schannel_get_rock(schanid_t chan);
-
- glui32 glk_schannel_play(schanid_t chan, glui32 snd);
- glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
- glui32 notify);
- void glk_schannel_stop(schanid_t chan);
- void glk_schannel_set_volume(schanid_t chan, glui32 vol);
-
- void glk_sound_load_hint(glui32 snd, glui32 flag);
-
-#ifdef GLK_MODULE_SOUND2
- /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
- GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
-
- schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
- glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify);
- void glk_schannel_pause(schanid_t chan);
- void glk_schannel_unpause(schanid_t chan);
- void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify);
-
-#endif /* GLK_MODULE_SOUND2 */
-#endif /* GLK_MODULE_SOUND */
-
-#ifdef GLK_MODULE_HYPERLINKS
-
- void glk_set_hyperlink(glui32 linkval);
- void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
- void glk_request_hyperlink_event(winid_t win);
- void glk_cancel_hyperlink_event(winid_t win);
-
-#endif /* GLK_MODULE_HYPERLINKS */
-
-#ifdef GLK_MODULE_DATETIME
-
- void glk_current_time(glktimeval_t *time);
- glsi32 glk_current_simple_time(glui32 factor);
- void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
- void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
- void glk_simple_time_to_date_utc(glsi32 time, glui32 factor,
- glkdate_t *date);
- void glk_simple_time_to_date_local(glsi32 time, glui32 factor,
- glkdate_t *date);
- void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
- void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
- glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
- glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);
-
-#endif /* GLK_MODULE_DATETIME */
-
- /* XXX non-official Glk functions that may or may not exist */
- #define GARGLK 1
-
- char* garglk_fileref_get_name(frefid_t fref);
-
- void garglk_set_program_name(const char *name);
- void garglk_set_program_info(const char *info);
- void garglk_set_story_name(const char *name);
- void garglk_set_story_title(const char *title);
- void garglk_set_config(const char *name);
-
- /* garglk_unput_string - removes the specified string from the end of the output buffer, if
- * indeed it is there. */
- void garglk_unput_string(char *str);
- void garglk_unput_string_uni(glui32 *str);
-
- void garglk_set_zcolors(glui32 fg, glui32 bg);
- void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
- void garglk_set_reversevideo(glui32 reverse);
- void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/glk/glk.cpp b/engines/gargoyle/glk/glk.cpp
new file mode 100644
index 0000000..26755a1
--- /dev/null
+++ b/engines/gargoyle/glk/glk.cpp
@@ -0,0 +1,689 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/glk/glk.h"
+
+namespace Gargoyle {
+
+Glk::Glk() : Interpreter(), _gliFirstEvent(false) {
+}
+
+void Glk::glk_exit(void) {
+ // TODO
+}
+
+void Glk::glk_set_interrupt_handler(void(*func)(void)) {
+ // This library doesn't handle interrupts.
+}
+
+void Glk::glk_tick(void) {
+ // TODO
+}
+
+glui32 Glk::glk_gestalt(glui32 sel, glui32 val) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) {
+ // TODO
+ return 0;
+}
+
+unsigned char Glk::glk_char_to_lower(unsigned char ch) {
+ // TODO
+ return '\0';
+}
+
+unsigned char Glk::glk_char_to_upper(unsigned char ch) {
+ // TODO
+ return '\0';
+}
+
+winid_t Glk::glk_window_get_root(void) {
+ // TODO
+ return nullptr;
+}
+
+winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_window_close(winid_t win, stream_result_t *result) {
+ // TODO
+}
+
+void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
+ // TODO
+}
+
+void Glk::glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keywin) {
+ // TODO
+}
+
+void Glk::glk_window_get_arrangement(winid_t win, glui32 *methodptr,
+ glui32 *sizeptr, winid_t *keywinptr) {
+ // TODO
+}
+
+winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_window_get_rock(winid_t win) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_window_get_type(winid_t win) {
+ // TODO
+ return 0;
+}
+
+winid_t Glk::glk_window_get_parent(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+winid_t Glk::glk_window_get_sibling(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_window_clear(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
+ // TODO
+}
+
+strid_t Glk::glk_window_get_stream(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
+ // TODO
+}
+
+strid_t Glk::glk_window_get_echo_stream(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_set_window(winid_t win) {
+ // TODO
+}
+
+strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
+ glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+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;
+}
+
+glui32 Glk::glk_stream_get_rock(strid_t str) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) {
+ // TODO
+}
+
+glui32 Glk::glk_stream_get_position(strid_t str) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_stream_set_current(strid_t str) {
+ // TODO
+}
+
+strid_t Glk::glk_stream_get_current(void) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_put_char(unsigned char ch) {
+ // TODO
+}
+
+void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
+ // TODO
+}
+
+void Glk::glk_put_string(char *s) {
+ // TODO
+}
+
+void Glk::glk_put_string_stream(strid_t str, char *s) {
+ // TODO
+}
+
+void Glk::glk_put_buffer(char *buf, glui32 len) {
+ // TODO
+}
+
+void Glk::glk_put_buffer_stream(strid_t str, char *buf, glui32 len) {
+ // TODO
+}
+
+void Glk::glk_set_style(glui32 styl) {
+ // TODO
+}
+
+void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
+ // TODO
+}
+
+glsi32 Glk::glk_get_char_stream(strid_t str) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) {
+ // TODO
+}
+
+void Glk::glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) {
+ // TODO
+}
+
+glui32 Glk::glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) {
+ // TODO
+ return 0;
+}
+
+frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_fileref_destroy(frefid_t fref) {
+ // TODO
+}
+
+frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_fileref_delete_file(frefid_t fref) {
+ // TODO
+}
+
+glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_select(event_t *event) {
+ if (!_gliFirstEvent) {
+ gliInputGuessFocus();
+ _gliFirstEvent = true;
+ }
+
+ gliSelect(event, false);
+}
+
+void Glk::glk_select_poll(event_t *event) {
+ if (!_gliFirstEvent) {
+ gliInputGuessFocus();
+ _gliFirstEvent = true;
+ }
+
+ gliSelect(event, true);
+}
+
+void Glk::glk_request_timer_events(glui32 millisecs) {
+ // TODO
+}
+
+void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
+ // TODO
+}
+
+void Glk::glk_request_char_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_request_mouse_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
+ // TODO
+}
+
+void Glk::glk_cancel_char_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_cancel_mouse_event(winid_t win) {
+ // TODO
+}
+
+#ifdef GLK_MODULE_LINE_ECHO
+
+void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+
+void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+#ifdef GLK_MODULE_UNICODE
+
+glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_put_char_uni(glui32 ch) {
+ // TODO
+}
+
+void Glk::glk_put_string_uni(glui32 *s) {
+ // TODO
+}
+
+void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
+ // TODO
+}
+
+void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
+ // TODO
+}
+
+void Glk::glk_put_string_stream_uni(strid_t str, glui32 *s) {
+ // TODO
+}
+
+void Glk::glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ // TODO
+}
+
+glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, glui32 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;
+}
+
+void Glk::glk_request_char_event_uni(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_UNICODE */
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return 0;
+}
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_window_flow_break(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height) {
+ // TODO
+}
+
+void Glk::glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height) {
+ // TODO
+}
+
+void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+schanid_t Glk::glk_schannel_create(glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_schannel_destroy(schanid_t chan) {
+ // TODO
+}
+
+schanid_t Glk::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_schannel_get_rock(schanid_t chan) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_schannel_play(schanid_t chan, glui32 snd) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_schannel_stop(schanid_t chan) {
+ // TODO
+}
+
+void Glk::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
+ // TODO
+}
+
+void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
+ // TODO
+}
+
+#ifdef GLK_MODULE_SOUND2
+
+schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_schannel_pause(schanid_t chan) {
+ // TODO
+}
+
+void Glk::glk_schannel_unpause(schanid_t chan) {
+ // TODO
+}
+
+void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+void Glk::glk_set_hyperlink(glui32 linkval) {
+ // TODO
+}
+
+void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
+ // TODO
+}
+
+void Glk::glk_request_hyperlink_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_cancel_hyperlink_event(winid_t win) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+void Glk::glk_current_time(glktimeval_t *time) {
+ // TODO
+}
+
+glsi32 Glk::glk_current_simple_time(glui32 factor) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) {
+ // TODO
+}
+
+void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) {
+ // TODO
+}
+
+glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) {
+ // TODO
+ return 0;
+}
+
+glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
+ // TODO
+ return 0;
+}
+
+#endif /* GLK_MODULE_DATETIME */
+
+/* XXX non-official Glk functions that may or may not exist */
+
+char *garglk_fileref_get_name(frefid_t fref) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::garglk_set_program_name(const char *name) {
+ // TODO
+}
+
+void Glk::garglk_set_program_info(const char *info) {
+ // TODO
+}
+
+void Glk::garglk_set_story_name(const char *name) {
+ // TODO
+}
+
+void Glk::garglk_set_story_title(const char *title) {
+ // TODO
+}
+
+void Glk::garglk_set_config(const char *name) {
+ // TODO
+}
+
+/* garglk_unput_string - removes the specified string from the end of the output buffer, if
+* indeed it is there. */
+void Glk::garglk_unput_string(char *str) {
+ // TODO
+}
+
+void Glk::garglk_unput_string_uni(glui32 *str) {
+ // TODO
+}
+
+void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
+ // TODO
+}
+
+void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
+ // TODO
+}
+
+void Glk::garglk_set_reversevideo(glui32 reverse) {
+ // TODO
+}
+
+void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
+ // TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Glk::gliInputGuessFocus() {
+ // TODO
+}
+
+void Glk::gliSelect(event_t *event, bool polled) {
+ // TODO
+ event->type = evtype_Quit;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk/glk.h b/engines/gargoyle/glk/glk.h
new file mode 100644
index 0000000..11c8cba
--- /dev/null
+++ b/engines/gargoyle/glk/glk.h
@@ -0,0 +1,289 @@
+/* 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 GARGOYLE_GLK_H
+#define GARGOYLE_GLK_H
+
+#include "graphics/managed_surface.h"
+#include "gargoyle/interpreter.h"
+#include "gargoyle/glk/glk_types.h"
+
+namespace Gargoyle {
+
+/**
+ * Implements the GLK interface
+ */
+class Glk : public Interpreter {
+private:
+ bool _gliFirstEvent;
+private:
+ /**
+ * Pick first window which might want input. This is called after every keystroke.
+ */
+ void gliInputGuessFocus();
+
+ void gliSelect(event_t *event, bool polled);
+public:
+ /**
+ * Constructor
+ */
+ Glk();
+
+ void glk_exit(void);
+ void glk_set_interrupt_handler(void(*func)(void));
+ void glk_tick(void);
+
+ glui32 glk_gestalt(glui32 sel, glui32 val);
+ glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen);
+
+ unsigned char glk_char_to_lower(unsigned char ch);
+ unsigned char glk_char_to_upper(unsigned char ch);
+
+ winid_t glk_window_get_root(void);
+ winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock);
+ void glk_window_close(winid_t win, stream_result_t *result);
+ void glk_window_get_size(winid_t win, glui32 *widthptr,
+ glui32 *heightptr);
+ void glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keywin);
+ void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
+ glui32 *sizeptr, winid_t *keywinptr);
+ winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
+ glui32 glk_window_get_rock(winid_t win);
+ glui32 glk_window_get_type(winid_t win);
+ winid_t glk_window_get_parent(winid_t win);
+ winid_t glk_window_get_sibling(winid_t win);
+ void glk_window_clear(winid_t win);
+ void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
+
+ strid_t glk_window_get_stream(winid_t win);
+ void glk_window_set_echo_stream(winid_t win, strid_t str);
+ 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);
+ 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);
+ 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);
+ strid_t glk_stream_get_current(void);
+
+ void glk_put_char(unsigned char ch);
+ void glk_put_char_stream(strid_t str, unsigned char ch);
+ void glk_put_string(char *s);
+ void glk_put_string_stream(strid_t str, char *s);
+ void glk_put_buffer(char *buf, glui32 len);
+ void glk_put_buffer_stream(strid_t str, char *buf, glui32 len);
+ void glk_set_style(glui32 styl);
+ void glk_set_style_stream(strid_t str, glui32 styl);
+
+ glsi32 glk_get_char_stream(strid_t str);
+ glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
+ glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
+
+ void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
+ glsi32 val);
+ void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
+ glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
+ glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
+ glui32 *result);
+
+ 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,
+ glui32 rock);
+ frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
+ glui32 rock);
+ void glk_fileref_destroy(frefid_t fref);
+ frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
+ glui32 glk_fileref_get_rock(frefid_t fref);
+ void glk_fileref_delete_file(frefid_t fref);
+ glui32 glk_fileref_does_file_exist(frefid_t fref);
+
+ void glk_select(event_t *event);
+ void glk_select_poll(event_t *event);
+
+ void glk_request_timer_events(glui32 millisecs);
+
+ void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
+ glui32 initlen);
+ void glk_request_char_event(winid_t win);
+ void glk_request_mouse_event(winid_t win);
+
+ void glk_cancel_line_event(winid_t win, event_t *event);
+ void glk_cancel_char_event(winid_t win);
+ void glk_cancel_mouse_event(winid_t win);
+
+#ifdef GLK_MODULE_LINE_ECHO
+ void glk_set_echo_line_event(winid_t win, glui32 val);
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+ void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
+ glui32 count);
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+#ifdef GLK_MODULE_UNICODE
+
+ glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest);
+
+ void glk_put_char_uni(glui32 ch);
+ void glk_put_string_uni(glui32 *s);
+ void glk_put_buffer_uni(glui32 *buf, glui32 len);
+ void glk_put_char_stream_uni(strid_t str, glui32 ch);
+ void glk_put_string_stream_uni(strid_t str, glui32 *s);
+ void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
+
+ glsi32 glk_get_char_stream_uni(strid_t str);
+ 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);
+
+ void glk_request_char_event_uni(winid_t win);
+ void glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen);
+
+#endif /* GLK_MODULE_UNICODE */
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+ glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+ glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
+ glui32 glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height);
+ glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
+
+ void glk_window_flow_break(winid_t win);
+
+ void glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_set_background_color(winid_t win, glui32 color);
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+ schanid_t glk_schannel_create(glui32 rock);
+ void glk_schannel_destroy(schanid_t chan);
+ schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
+ glui32 glk_schannel_get_rock(schanid_t chan);
+
+ glui32 glk_schannel_play(schanid_t chan, glui32 snd);
+ glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
+ glui32 notify);
+ void glk_schannel_stop(schanid_t chan);
+ void glk_schannel_set_volume(schanid_t chan, glui32 vol);
+
+ void glk_sound_load_hint(glui32 snd, glui32 flag);
+
+#ifdef GLK_MODULE_SOUND2
+ /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
+ GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
+
+ schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
+ glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify);
+ void glk_schannel_pause(schanid_t chan);
+ void glk_schannel_unpause(schanid_t chan);
+ void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify);
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+ void glk_set_hyperlink(glui32 linkval);
+ void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
+ void glk_request_hyperlink_event(winid_t win);
+ void glk_cancel_hyperlink_event(winid_t win);
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+ void glk_current_time(glktimeval_t *time);
+ glsi32 glk_current_simple_time(glui32 factor);
+ void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
+ void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
+ void glk_simple_time_to_date_utc(glsi32 time, glui32 factor,
+ glkdate_t *date);
+ void glk_simple_time_to_date_local(glsi32 time, glui32 factor,
+ glkdate_t *date);
+ void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
+ void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
+ glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
+ glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);
+
+#endif /* GLK_MODULE_DATETIME */
+
+ /* XXX non-official Glk functions that may or may not exist */
+ #define GARGLK 1
+
+ char* garglk_fileref_get_name(frefid_t fref);
+
+ void garglk_set_program_name(const char *name);
+ void garglk_set_program_info(const char *info);
+ void garglk_set_story_name(const char *name);
+ void garglk_set_story_title(const char *title);
+ void garglk_set_config(const char *name);
+
+ /* garglk_unput_string - removes the specified string from the end of the output buffer, if
+ * indeed it is there. */
+ void garglk_unput_string(char *str);
+ void garglk_unput_string_uni(glui32 *str);
+
+ void garglk_set_zcolors(glui32 fg, glui32 bg);
+ void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
+ void garglk_set_reversevideo(glui32 reverse);
+ void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/glk/glk_types.h b/engines/gargoyle/glk/glk_types.h
new file mode 100644
index 0000000..a822741
--- /dev/null
+++ b/engines/gargoyle/glk/glk_types.h
@@ -0,0 +1,272 @@
+/* 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 GARGOYLE_GLK_TYPES_H
+#define GARGOYLE_GLK_TYPES_H
+
+#include "common/scummsys.h"
+
+namespace Gargoyle {
+
+typedef uint32 glui32;
+typedef int32 glsi32;
+
+/**
+ * These are the compile-time conditionals that reveal various Glk optional modules.
+ */
+#define GLK_MODULE_LINE_ECHO
+#define GLK_MODULE_LINE_TERMINATORS
+#define GLK_MODULE_UNICODE
+#define GLK_MODULE_UNICODE_NORM
+#define GLK_MODULE_IMAGE
+#define GLK_MODULE_SOUND
+#define GLK_MODULE_SOUND2
+#define GLK_MODULE_HYPERLINKS
+#define GLK_MODULE_DATETIME
+#define GLK_MODULE_GARGLKTEXT
+
+/**
+ * These types are opaque object identifiers. They're pointers to opaque
+ * C structures, which are defined differently by each library.
+ */
+typedef struct glk_window_struct *winid_t;
+typedef struct glk_stream_struct *strid_t;
+typedef struct glk_fileref_struct *frefid_t;
+typedef struct glk_schannel_struct *schanid_t;
+
+enum Gestalt {
+ gestalt_Version = 0,
+ gestalt_CharInput = 1,
+ gestalt_LineInput = 2,
+ gestalt_CharOutput = 3,
+ gestalt_CharOutput_CannotPrint = 0,
+ gestalt_CharOutput_ApproxPrint = 1,
+ gestalt_CharOutput_ExactPrint = 2,
+ gestalt_MouseInput = 4,
+ gestalt_Timer = 5,
+ gestalt_Graphics = 6,
+ gestalt_DrawImage = 7,
+ gestalt_Sound = 8,
+ gestalt_SoundVolume = 9,
+ gestalt_SoundNotify = 10,
+ gestalt_Hyperlinks = 11,
+ gestalt_HyperlinkInput = 12,
+ gestalt_SoundMusic = 13,
+ gestalt_GraphicsTransparency = 14,
+ gestalt_Unicode = 15,
+ gestalt_UnicodeNorm = 16,
+ gestalt_LineInputEcho = 17,
+ gestalt_LineTerminators = 18,
+ gestalt_LineTerminatorKey = 19,
+ gestalt_DateTime = 20,
+ gestalt_Sound2 = 21,
+ gestalt_GarglkText = 0x1100,
+};
+
+enum EvType {
+ evtype_None = 0,
+ evtype_Timer = 1,
+ evtype_CharInput = 2,
+ evtype_LineInput = 3,
+ evtype_MouseInput = 4,
+ evtype_Arrange = 5,
+ evtype_Redraw = 6,
+ evtype_SoundNotify = 7,
+ evtype_Hyperlink = 8,
+ evtype_VolumeNotify = 9,
+
+ // ScummVM custom events
+ evtype_Quit = 99
+};
+
+enum Keycode {
+ keycode_Unknown = 0xffffffffU,
+ keycode_Left = 0xfffffffeU,
+ keycode_Right = 0xfffffffdU,
+ keycode_Up = 0xfffffffcU,
+ keycode_Down = 0xfffffffbU,
+ keycode_Return = 0xfffffffaU,
+ keycode_Delete = 0xfffffff9U,
+ keycode_Escape = 0xfffffff8U,
+ keycode_Tab = 0xfffffff7U,
+ keycode_PageUp = 0xfffffff6U,
+ keycode_PageDown = 0xfffffff5U,
+ keycode_Home = 0xfffffff4U,
+ keycode_End = 0xfffffff3U,
+ keycode_Func1 = 0xffffffefU,
+ keycode_Func2 = 0xffffffeeU,
+ keycode_Func3 = 0xffffffedU,
+ keycode_Func4 = 0xffffffecU,
+ keycode_Func5 = 0xffffffebU,
+ keycode_Func6 = 0xffffffeaU,
+ keycode_Func7 = 0xffffffe9U,
+ keycode_Func8 = 0xffffffe8U,
+ keycode_Func9 = 0xffffffe7U,
+ keycode_Func10 = 0xffffffe6U,
+ keycode_Func11 = 0xffffffe5U,
+ keycode_Func12 = 0xffffffe4U,
+
+ // non standard keycodes
+ keycode_Erase = 0xffffef7fU,
+ keycode_MouseWheelUp = 0xffffeffeU,
+ keycode_MouseWheelDown = 0xffffefffU,
+ keycode_SkipWordLeft = 0xfffff000U,
+ keycode_SkipWordRight = 0xfffff001U,
+
+ // The last keycode is always = 0x100000000 - keycode_MAXVAL)
+ keycode_MAXVAL = 28U
+};
+
+enum Style {
+ style_Normal = 0,
+ style_Emphasized = 1,
+ style_Preformatted = 2,
+ style_Header = 3,
+ style_Subheader = 4,
+ style_Alert = 5,
+ style_Note = 6,
+ style_BlockQuote = 7,
+ style_Input = 8,
+ style_User1 = 9,
+ style_User2 = 10,
+ style_NUMSTYLES = 11,
+};
+
+enum WinType {
+ wintype_AllTypes = 0,
+ wintype_Pair = 1,
+ wintype_Blank = 2,
+ wintype_TextBuffer = 3,
+ wintype_TextGrid = 4,
+ wintype_Graphics = 5,
+};
+
+enum WinMethod {
+ winmethod_Left = 0x00,
+ winmethod_Right = 0x01,
+ winmethod_Above = 0x02,
+ winmethod_Below = 0x03,
+ winmethod_DirMask = 0x0f,
+
+ winmethod_Fixed = 0x10,
+ winmethod_Proportional = 0x20,
+ winmethod_DivisionMask = 0xf0,
+
+ winmethod_Border = 0x000,
+ winmethod_NoBorder = 0x100,
+ winmethod_BorderMask = 0x100,
+};
+
+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,
+};
+
+enum StyleHint {
+ stylehint_Indentation = 0,
+ stylehint_ParaIndentation = 1,
+ stylehint_Justification = 2,
+ stylehint_Size = 3,
+ stylehint_Weight = 4,
+ stylehint_Oblique = 5,
+ stylehint_Proportional = 6,
+ stylehint_TextColor = 7,
+ stylehint_BackColor = 8,
+ stylehint_ReverseColor = 9,
+ stylehint_NUMHINTS = 10,
+
+ stylehint_just_LeftFlush = 0,
+ stylehint_just_LeftRight = 1,
+ stylehint_just_Centered = 2,
+ stylehint_just_RightFlush = 3,
+};
+
+#ifdef GLK_MODULE_IMAGE
+
+enum ImageAlign {
+ imagealign_InlineUp = 1,
+ imagealign_InlineDown = 2,
+ imagealign_InlineCenter = 3,
+ imagealign_MarginLeft = 4,
+ imagealign_MarginRight = 5
+};
+
+#endif /* GLK_MODULE_IMAGE */
+
+struct event_struct {
+ glui32 type;
+ winid_t win;
+ glui32 val1, val2;
+};
+typedef event_struct event_t;
+
+struct stream_result_struct {
+ glui32 readcount;
+ glui32 writecount;
+};
+typedef stream_result_struct stream_result_t;
+
+#ifdef GLK_MODULE_DATETIME
+
+struct glktimeval_struct {
+ glsi32 high_sec;
+ glui32 low_sec;
+ glsi32 microsec;
+};
+typedef glktimeval_struct glktimeval_t;
+
+struct glkdate_struct {
+ glsi32 year; ///< full (four-digit) year */
+ glsi32 month; ///< 1-12, 1 is January
+ glsi32 day; ///< 1-31
+ glsi32 weekday; ///< 0-6, 0 is Sunday
+ glsi32 hour; ///< 0-23
+ glsi32 minute; ///< 0-59
+ glsi32 second; ///< 0-59, maybe 60 during a leap second
+ glsi32 microsec; ///< 0-999999
+};
+typedef glkdate_struct glkdate_t;
+
+#endif /* GLK_MODULE_DATETIME */
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/interpreter.h b/engines/gargoyle/interpreter.h
index df9172d..748d417 100644
--- a/engines/gargoyle/interpreter.h
+++ b/engines/gargoyle/interpreter.h
@@ -23,12 +23,16 @@
#ifndef GARGOYLE_INTERPRETER_H
#define GARGOYLE_INTERPRETER_H
+#include "graphics/screen.h"
+
namespace Gargoyle {
/**
* Base class for specific interpreters
*/
class Interpreter {
+protected:
+ Graphics::Screen _screen;
public:
/**
* Constructor
diff --git a/engines/gargoyle/interps/scott/scott.cpp b/engines/gargoyle/interps/scott/scott.cpp
new file mode 100644
index 0000000..b2ea5e2
--- /dev/null
+++ b/engines/gargoyle/interps/scott/scott.cpp
@@ -0,0 +1,41 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/interps/scott/scott.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+void Scott::execute() {
+ event_t ev;
+ do {
+ glk_select(&ev);
+ switch (ev.type) {
+ default:
+ /* do nothing */
+ break;
+ }
+ } while (ev.type != evtype_Quit);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/interps/scott/scott.h b/engines/gargoyle/interps/scott/scott.h
new file mode 100644
index 0000000..7d87ca5
--- /dev/null
+++ b/engines/gargoyle/interps/scott/scott.h
@@ -0,0 +1,106 @@
+/* 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 GARGOYLE_SCOTT
+#define GARGOYLE_SCOTT
+
+/*
+ * Controlling block
+ */
+
+#include "common/scummsys.h"
+#include "gargoyle/glk/glk.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+#define LIGHT_SOURCE 9 // Always 9 how odd
+#define CARRIED 255 // Carried
+#define DESTROYED 0 // Destroyed
+#define DARKBIT 15
+#define LIGHTOUTBIT 16 // Light gone out
+
+#define YOUARE 1 // You are not I am
+#define SCOTTLIGHT 2 // Authentic Scott Adams light messages
+#define DEBUGGING 4 // Info from database load
+#define TRS80_STYLE 8 // Display in style used on TRS-80
+#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
+
+struct Header {
+ int Unknown;
+ int NumItems;
+ int NumActions;
+ int NumWords; // Smaller of verb/noun is padded to same size
+ int NumRooms;
+ int MaxCarry;
+ int PlayerRoom;
+ int Treasures;
+ int WordLength;
+ int LightTime;
+ int NumMessages;
+ int TreasureRoom;
+};
+
+struct Action {
+ uint Vocab;
+ uint Condition[5];
+ uint action[2];
+};
+
+struct Room {
+ char *Text;
+ short Exits[6];
+};
+
+struct Item {
+ char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
+ byte Location;
+ byte InitialLoc;
+ char *AutoGet;
+};
+
+struct Tail {
+ int Version;
+ int AdventureNumber;
+ int Unknown;
+};
+
+/**
+ * Scott Adams game interpreter
+ */
+class Scott : public Glk {
+public:
+ /**
+ * Constructor
+ */
+ Scott() : Glk() {}
+
+ /**
+ * Execute the game
+ */
+ virtual void execute();
+};
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 937b814..6e11ba7 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -4,9 +4,9 @@ MODULE_OBJS := \
detection.o \
events.o \
gargoyle.o \
- glk.o \
+ glk/glk.o \
interpreter.o \
- scott/scott.o
+ interps/scott/scott.o
# This module can be built as a plugin
ifeq ($(ENABLE_GARGOYLE), DYNAMIC_PLUGIN)
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
deleted file mode 100644
index b5e537c..0000000
--- a/engines/gargoyle/scott/scott.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/scott/scott.h"
-
-namespace Gargoyle {
-namespace Scott {
-
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
deleted file mode 100644
index bf13cf8..0000000
--- a/engines/gargoyle/scott/scott.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* 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 GARGOYLE_SCOTT
-#define GARGOYLE_SCOTT
-
-/*
- * Controlling block
- */
-
-#include "common/scummsys.h"
-#include "gargoyle/glk.h"
-
-namespace Gargoyle {
-namespace Scott {
-
-#define LIGHT_SOURCE 9 // Always 9 how odd
-#define CARRIED 255 // Carried
-#define DESTROYED 0 // Destroyed
-#define DARKBIT 15
-#define LIGHTOUTBIT 16 // Light gone out
-
-#define YOUARE 1 // You are not I am
-#define SCOTTLIGHT 2 // Authentic Scott Adams light messages
-#define DEBUGGING 4 // Info from database load
-#define TRS80_STYLE 8 // Display in style used on TRS-80
-#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
-
-struct Header {
- int Unknown;
- int NumItems;
- int NumActions;
- int NumWords; // Smaller of verb/noun is padded to same size
- int NumRooms;
- int MaxCarry;
- int PlayerRoom;
- int Treasures;
- int WordLength;
- int LightTime;
- int NumMessages;
- int TreasureRoom;
-};
-
-struct Action {
- uint Vocab;
- uint Condition[5];
- uint action[2];
-};
-
-struct Room {
- char *Text;
- short Exits[6];
-};
-
-struct Item {
- char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
- byte Location;
- byte InitialLoc;
- char *AutoGet;
-};
-
-struct Tail {
- int Version;
- int AdventureNumber;
- int Unknown;
-};
-
-/**
- * Scott Adams game interpreter
- */
-class Scott : public Glk {
-public:
- /**
- * Constructor
- */
- Scott() : Glk() {}
-};
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
-
-#endif
Commit: b62e30b84c6dfa98942ca094f86ecc0538cebbec
https://github.com/scummvm/scummvm/commit/b62e30b84c6dfa98942ca094f86ecc0538cebbec
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Interpreters now derive from GargoyleEngine via Glk
Changed paths:
A engines/gargoyle/glk.cpp
A engines/gargoyle/glk.h
A engines/gargoyle/glk_types.h
A engines/gargoyle/scott/scott.cpp
A engines/gargoyle/scott/scott.h
R engines/gargoyle/glk/glk.cpp
R engines/gargoyle/glk/glk.h
R engines/gargoyle/glk/glk_types.h
R engines/gargoyle/interpreter.cpp
R engines/gargoyle/interpreter.h
R engines/gargoyle/interps/scott/scott.cpp
R engines/gargoyle/interps/scott/scott.h
engines/gargoyle/detection.cpp
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index f10a70b..93859e6 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -58,16 +58,17 @@ InterpreterType GargoyleEngine::getInterpreterType() const {
} // End of namespace Gargoyle
-static const PlainGameDescriptor GargoyleGames[] = {
- {"Gargoyle", "Gargoyle Games"},
+static const PlainGameDescriptor gargoyleGames[] = {
+ {"scott", "Scott Adams Games"},
{0, 0}
};
#include "gargoyle/detection_tables.h"
+#include "gargoyle/scott/scott.h"
class GargoyleMetaEngine : public AdvancedMetaEngine {
public:
- GargoyleMetaEngine() : AdvancedMetaEngine(Gargoyle::gameDescriptions, sizeof(Gargoyle::GargoyleGameDescription), GargoyleGames) {
+ GargoyleMetaEngine() : AdvancedMetaEngine(Gargoyle::gameDescriptions, sizeof(Gargoyle::GargoyleGameDescription), gargoyleGames) {
_maxScanDepth = 3;
}
@@ -105,7 +106,13 @@ bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
- *engine = new Gargoyle::GargoyleEngine(syst, gd);
+ switch (gd->interpType) {
+ case Gargoyle::INTERPRETER_SCOTT:
+ *engine = new Gargoyle::Scott::Scott(syst, gd);
+ break;
+ default:
+ error("Unknown interpreter");
+ }
return gd != 0;
}
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index b46f2fc..3457f5f 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -28,16 +28,14 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
-#include "gargoyle/interps/scott/scott.h"
namespace Gargoyle {
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _interpreter(nullptr) {
+ _gameDescription(gameDesc), Engine(syst) {
}
GargoyleEngine::~GargoyleEngine() {
- delete _interpreter;
}
void GargoyleEngine::initialize() {
@@ -48,19 +46,11 @@ void GargoyleEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphics(640, 480, false);
-
- switch (getInterpreterType()) {
- case INTERPRETER_SCOTT:
- _interpreter = new Scott::Scott();
- break;
- default:
- error("Unknown interpreter type");
- }
}
Common::Error GargoyleEngine::run() {
initialize();
- _interpreter->execute();
+ main();
return Common::kNoError;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 375d9ad..0940248 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -28,7 +28,6 @@
#include "common/serializer.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
-#include "gargoyle/interpreter.h"
namespace Gargoyle {
@@ -57,20 +56,27 @@ struct GargoyleSavegameHeader {
int _totalFrames;
};
+/**
+ * Base class for the different interpreters
+ */
class GargoyleEngine : public Engine {
private:
/**
* Handles basic initialization
*/
void initialize();
-private:
+protected:
const GargoyleGameDescription *_gameDescription;
int _loadSaveSlot;
- Interpreter *_interpreter;
// Engine APIs
virtual Common::Error run();
virtual bool hasFeature(EngineFeature f) const;
+
+ /**
+ * Main game loop for the individual interpreters
+ */
+ virtual void main() = 0;
public:
GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
virtual ~GargoyleEngine();
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
new file mode 100644
index 0000000..350b40f
--- /dev/null
+++ b/engines/gargoyle/glk.cpp
@@ -0,0 +1,690 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/glk.h"
+
+namespace Gargoyle {
+
+Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+ GargoyleEngine(syst, gameDesc), _gliFirstEvent(false) {
+}
+
+void Glk::glk_exit(void) {
+ // TODO
+}
+
+void Glk::glk_set_interrupt_handler(void(*func)(void)) {
+ // This library doesn't handle interrupts.
+}
+
+void Glk::glk_tick(void) {
+ // TODO
+}
+
+glui32 Glk::glk_gestalt(glui32 sel, glui32 val) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) {
+ // TODO
+ return 0;
+}
+
+unsigned char Glk::glk_char_to_lower(unsigned char ch) {
+ // TODO
+ return '\0';
+}
+
+unsigned char Glk::glk_char_to_upper(unsigned char ch) {
+ // TODO
+ return '\0';
+}
+
+winid_t Glk::glk_window_get_root(void) {
+ // TODO
+ return nullptr;
+}
+
+winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_window_close(winid_t win, stream_result_t *result) {
+ // TODO
+}
+
+void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
+ // TODO
+}
+
+void Glk::glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keywin) {
+ // TODO
+}
+
+void Glk::glk_window_get_arrangement(winid_t win, glui32 *methodptr,
+ glui32 *sizeptr, winid_t *keywinptr) {
+ // TODO
+}
+
+winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_window_get_rock(winid_t win) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_window_get_type(winid_t win) {
+ // TODO
+ return 0;
+}
+
+winid_t Glk::glk_window_get_parent(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+winid_t Glk::glk_window_get_sibling(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_window_clear(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
+ // TODO
+}
+
+strid_t Glk::glk_window_get_stream(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
+ // TODO
+}
+
+strid_t Glk::glk_window_get_echo_stream(winid_t win) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_set_window(winid_t win) {
+ // TODO
+}
+
+strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
+ glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+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;
+}
+
+glui32 Glk::glk_stream_get_rock(strid_t str) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) {
+ // TODO
+}
+
+glui32 Glk::glk_stream_get_position(strid_t str) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_stream_set_current(strid_t str) {
+ // TODO
+}
+
+strid_t Glk::glk_stream_get_current(void) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_put_char(unsigned char ch) {
+ // TODO
+}
+
+void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
+ // TODO
+}
+
+void Glk::glk_put_string(char *s) {
+ // TODO
+}
+
+void Glk::glk_put_string_stream(strid_t str, char *s) {
+ // TODO
+}
+
+void Glk::glk_put_buffer(char *buf, glui32 len) {
+ // TODO
+}
+
+void Glk::glk_put_buffer_stream(strid_t str, char *buf, glui32 len) {
+ // TODO
+}
+
+void Glk::glk_set_style(glui32 styl) {
+ // TODO
+}
+
+void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
+ // TODO
+}
+
+glsi32 Glk::glk_get_char_stream(strid_t str) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) {
+ // TODO
+}
+
+void Glk::glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) {
+ // TODO
+}
+
+glui32 Glk::glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) {
+ // TODO
+ return 0;
+}
+
+frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_fileref_destroy(frefid_t fref) {
+ // TODO
+}
+
+frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_fileref_delete_file(frefid_t fref) {
+ // TODO
+}
+
+glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_select(event_t *event) {
+ if (!_gliFirstEvent) {
+ gliInputGuessFocus();
+ _gliFirstEvent = true;
+ }
+
+ gliSelect(event, false);
+}
+
+void Glk::glk_select_poll(event_t *event) {
+ if (!_gliFirstEvent) {
+ gliInputGuessFocus();
+ _gliFirstEvent = true;
+ }
+
+ gliSelect(event, true);
+}
+
+void Glk::glk_request_timer_events(glui32 millisecs) {
+ // TODO
+}
+
+void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
+ // TODO
+}
+
+void Glk::glk_request_char_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_request_mouse_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
+ // TODO
+}
+
+void Glk::glk_cancel_char_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_cancel_mouse_event(winid_t win) {
+ // TODO
+}
+
+#ifdef GLK_MODULE_LINE_ECHO
+
+void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+
+void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+#ifdef GLK_MODULE_UNICODE
+
+glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_put_char_uni(glui32 ch) {
+ // TODO
+}
+
+void Glk::glk_put_string_uni(glui32 *s) {
+ // TODO
+}
+
+void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
+ // TODO
+}
+
+void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
+ // TODO
+}
+
+void Glk::glk_put_string_stream_uni(strid_t str, glui32 *s) {
+ // TODO
+}
+
+void Glk::glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ // TODO
+}
+
+glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ // TODO
+ return 0;
+}
+
+strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, glui32 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;
+}
+
+void Glk::glk_request_char_event_uni(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_UNICODE */
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return 0;
+}
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_window_flow_break(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height) {
+ // TODO
+}
+
+void Glk::glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height) {
+ // TODO
+}
+
+void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+schanid_t Glk::glk_schannel_create(glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::glk_schannel_destroy(schanid_t chan) {
+ // TODO
+}
+
+schanid_t Glk::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_schannel_get_rock(schanid_t chan) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_schannel_play(schanid_t chan, glui32 snd) {
+ // TODO
+ return 0;
+}
+
+glui32 Glk::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_schannel_stop(schanid_t chan) {
+ // TODO
+}
+
+void Glk::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
+ // TODO
+}
+
+void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
+ // TODO
+}
+
+#ifdef GLK_MODULE_SOUND2
+
+schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
+ // TODO
+ return nullptr;
+}
+
+glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_schannel_pause(schanid_t chan) {
+ // TODO
+}
+
+void Glk::glk_schannel_unpause(schanid_t chan) {
+ // TODO
+}
+
+void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+void Glk::glk_set_hyperlink(glui32 linkval) {
+ // TODO
+}
+
+void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
+ // TODO
+}
+
+void Glk::glk_request_hyperlink_event(winid_t win) {
+ // TODO
+}
+
+void Glk::glk_cancel_hyperlink_event(winid_t win) {
+ // TODO
+}
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+void Glk::glk_current_time(glktimeval_t *time) {
+ // TODO
+}
+
+glsi32 Glk::glk_current_simple_time(glui32 factor) {
+ // TODO
+ return 0;
+}
+
+void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
+ // TODO
+}
+
+void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) {
+ // TODO
+}
+
+void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) {
+ // TODO
+}
+
+glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) {
+ // TODO
+ return 0;
+}
+
+glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
+ // TODO
+ return 0;
+}
+
+#endif /* GLK_MODULE_DATETIME */
+
+/* XXX non-official Glk functions that may or may not exist */
+
+char *garglk_fileref_get_name(frefid_t fref) {
+ // TODO
+ return nullptr;
+}
+
+void Glk::garglk_set_program_name(const char *name) {
+ // TODO
+}
+
+void Glk::garglk_set_program_info(const char *info) {
+ // TODO
+}
+
+void Glk::garglk_set_story_name(const char *name) {
+ // TODO
+}
+
+void Glk::garglk_set_story_title(const char *title) {
+ // TODO
+}
+
+void Glk::garglk_set_config(const char *name) {
+ // TODO
+}
+
+/* garglk_unput_string - removes the specified string from the end of the output buffer, if
+* indeed it is there. */
+void Glk::garglk_unput_string(char *str) {
+ // TODO
+}
+
+void Glk::garglk_unput_string_uni(glui32 *str) {
+ // TODO
+}
+
+void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
+ // TODO
+}
+
+void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
+ // TODO
+}
+
+void Glk::garglk_set_reversevideo(glui32 reverse) {
+ // TODO
+}
+
+void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
+ // TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Glk::gliInputGuessFocus() {
+ // TODO
+}
+
+void Glk::gliSelect(event_t *event, bool polled) {
+ // TODO
+ event->type = evtype_Quit;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
new file mode 100644
index 0000000..eab6f0b
--- /dev/null
+++ b/engines/gargoyle/glk.h
@@ -0,0 +1,288 @@
+/* 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 GARGOYLE_GLK_H
+#define GARGOYLE_GLK_H
+
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+/**
+ * Implements the GLK interface
+ */
+class Glk : public GargoyleEngine {
+private:
+ bool _gliFirstEvent;
+private:
+ /**
+ * Pick first window which might want input. This is called after every keystroke.
+ */
+ void gliInputGuessFocus();
+
+ void gliSelect(event_t *event, bool polled);
+public:
+ /**
+ * Constructor
+ */
+ Glk(OSystem *syst, const GargoyleGameDescription *gameDesc);
+
+ void glk_exit(void);
+ void glk_set_interrupt_handler(void(*func)(void));
+ void glk_tick(void);
+
+ glui32 glk_gestalt(glui32 sel, glui32 val);
+ glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen);
+
+ unsigned char glk_char_to_lower(unsigned char ch);
+ unsigned char glk_char_to_upper(unsigned char ch);
+
+ winid_t glk_window_get_root(void);
+ winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock);
+ void glk_window_close(winid_t win, stream_result_t *result);
+ void glk_window_get_size(winid_t win, glui32 *widthptr,
+ glui32 *heightptr);
+ void glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keywin);
+ void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
+ glui32 *sizeptr, winid_t *keywinptr);
+ winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
+ glui32 glk_window_get_rock(winid_t win);
+ glui32 glk_window_get_type(winid_t win);
+ winid_t glk_window_get_parent(winid_t win);
+ winid_t glk_window_get_sibling(winid_t win);
+ void glk_window_clear(winid_t win);
+ void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
+
+ strid_t glk_window_get_stream(winid_t win);
+ void glk_window_set_echo_stream(winid_t win, strid_t str);
+ 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);
+ 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);
+ 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);
+ strid_t glk_stream_get_current(void);
+
+ void glk_put_char(unsigned char ch);
+ void glk_put_char_stream(strid_t str, unsigned char ch);
+ void glk_put_string(char *s);
+ void glk_put_string_stream(strid_t str, char *s);
+ void glk_put_buffer(char *buf, glui32 len);
+ void glk_put_buffer_stream(strid_t str, char *buf, glui32 len);
+ void glk_set_style(glui32 styl);
+ void glk_set_style_stream(strid_t str, glui32 styl);
+
+ glsi32 glk_get_char_stream(strid_t str);
+ glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
+ glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
+
+ void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
+ glsi32 val);
+ void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
+ glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
+ glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
+ glui32 *result);
+
+ 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,
+ glui32 rock);
+ frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
+ glui32 rock);
+ void glk_fileref_destroy(frefid_t fref);
+ frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
+ glui32 glk_fileref_get_rock(frefid_t fref);
+ void glk_fileref_delete_file(frefid_t fref);
+ glui32 glk_fileref_does_file_exist(frefid_t fref);
+
+ void glk_select(event_t *event);
+ void glk_select_poll(event_t *event);
+
+ void glk_request_timer_events(glui32 millisecs);
+
+ void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
+ glui32 initlen);
+ void glk_request_char_event(winid_t win);
+ void glk_request_mouse_event(winid_t win);
+
+ void glk_cancel_line_event(winid_t win, event_t *event);
+ void glk_cancel_char_event(winid_t win);
+ void glk_cancel_mouse_event(winid_t win);
+
+#ifdef GLK_MODULE_LINE_ECHO
+ void glk_set_echo_line_event(winid_t win, glui32 val);
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+ void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
+ glui32 count);
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+#ifdef GLK_MODULE_UNICODE
+
+ glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest);
+
+ void glk_put_char_uni(glui32 ch);
+ void glk_put_string_uni(glui32 *s);
+ void glk_put_buffer_uni(glui32 *buf, glui32 len);
+ void glk_put_char_stream_uni(strid_t str, glui32 ch);
+ void glk_put_string_stream_uni(strid_t str, glui32 *s);
+ void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
+
+ glsi32 glk_get_char_stream_uni(strid_t str);
+ 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);
+
+ void glk_request_char_event_uni(winid_t win);
+ void glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen);
+
+#endif /* GLK_MODULE_UNICODE */
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+ glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+ glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
+ glui32 glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height);
+ glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
+
+ void glk_window_flow_break(winid_t win);
+
+ void glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_set_background_color(winid_t win, glui32 color);
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+ schanid_t glk_schannel_create(glui32 rock);
+ void glk_schannel_destroy(schanid_t chan);
+ schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
+ glui32 glk_schannel_get_rock(schanid_t chan);
+
+ glui32 glk_schannel_play(schanid_t chan, glui32 snd);
+ glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
+ glui32 notify);
+ void glk_schannel_stop(schanid_t chan);
+ void glk_schannel_set_volume(schanid_t chan, glui32 vol);
+
+ void glk_sound_load_hint(glui32 snd, glui32 flag);
+
+#ifdef GLK_MODULE_SOUND2
+ /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
+ GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
+
+ schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
+ glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify);
+ void glk_schannel_pause(schanid_t chan);
+ void glk_schannel_unpause(schanid_t chan);
+ void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify);
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+ void glk_set_hyperlink(glui32 linkval);
+ void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
+ void glk_request_hyperlink_event(winid_t win);
+ void glk_cancel_hyperlink_event(winid_t win);
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+ void glk_current_time(glktimeval_t *time);
+ glsi32 glk_current_simple_time(glui32 factor);
+ void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
+ void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
+ void glk_simple_time_to_date_utc(glsi32 time, glui32 factor,
+ glkdate_t *date);
+ void glk_simple_time_to_date_local(glsi32 time, glui32 factor,
+ glkdate_t *date);
+ void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
+ void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
+ glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
+ glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);
+
+#endif /* GLK_MODULE_DATETIME */
+
+ /* XXX non-official Glk functions that may or may not exist */
+ #define GARGLK 1
+
+ char* garglk_fileref_get_name(frefid_t fref);
+
+ void garglk_set_program_name(const char *name);
+ void garglk_set_program_info(const char *info);
+ void garglk_set_story_name(const char *name);
+ void garglk_set_story_title(const char *title);
+ void garglk_set_config(const char *name);
+
+ /* garglk_unput_string - removes the specified string from the end of the output buffer, if
+ * indeed it is there. */
+ void garglk_unput_string(char *str);
+ void garglk_unput_string_uni(glui32 *str);
+
+ void garglk_set_zcolors(glui32 fg, glui32 bg);
+ void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
+ void garglk_set_reversevideo(glui32 reverse);
+ void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/glk/glk.cpp b/engines/gargoyle/glk/glk.cpp
deleted file mode 100644
index 26755a1..0000000
--- a/engines/gargoyle/glk/glk.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/glk/glk.h"
-
-namespace Gargoyle {
-
-Glk::Glk() : Interpreter(), _gliFirstEvent(false) {
-}
-
-void Glk::glk_exit(void) {
- // TODO
-}
-
-void Glk::glk_set_interrupt_handler(void(*func)(void)) {
- // This library doesn't handle interrupts.
-}
-
-void Glk::glk_tick(void) {
- // TODO
-}
-
-glui32 Glk::glk_gestalt(glui32 sel, glui32 val) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) {
- // TODO
- return 0;
-}
-
-unsigned char Glk::glk_char_to_lower(unsigned char ch) {
- // TODO
- return '\0';
-}
-
-unsigned char Glk::glk_char_to_upper(unsigned char ch) {
- // TODO
- return '\0';
-}
-
-winid_t Glk::glk_window_get_root(void) {
- // TODO
- return nullptr;
-}
-
-winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_window_close(winid_t win, stream_result_t *result) {
- // TODO
-}
-
-void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
- // TODO
-}
-
-void Glk::glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keywin) {
- // TODO
-}
-
-void Glk::glk_window_get_arrangement(winid_t win, glui32 *methodptr,
- glui32 *sizeptr, winid_t *keywinptr) {
- // TODO
-}
-
-winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
- // TODO
- return nullptr;
-}
-
-glui32 Glk::glk_window_get_rock(winid_t win) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_window_get_type(winid_t win) {
- // TODO
- return 0;
-}
-
-winid_t Glk::glk_window_get_parent(winid_t win) {
- // TODO
- return nullptr;
-}
-
-winid_t Glk::glk_window_get_sibling(winid_t win) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_window_clear(winid_t win) {
- // TODO
-}
-
-void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
- // TODO
-}
-
-strid_t Glk::glk_window_get_stream(winid_t win) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
- // TODO
-}
-
-strid_t Glk::glk_window_get_echo_stream(winid_t win) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_set_window(winid_t win) {
- // TODO
-}
-
-strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
- glui32 rock) {
- // TODO
- return nullptr;
-}
-
-strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) {
- // TODO
- return nullptr;
-}
-
-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;
-}
-
-glui32 Glk::glk_stream_get_rock(strid_t str) {
- // TODO
- return 0;
-}
-
-void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) {
- // TODO
-}
-
-glui32 Glk::glk_stream_get_position(strid_t str) {
- // TODO
- return 0;
-}
-
-void Glk::glk_stream_set_current(strid_t str) {
- // TODO
-}
-
-strid_t Glk::glk_stream_get_current(void) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_put_char(unsigned char ch) {
- // TODO
-}
-
-void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
- // TODO
-}
-
-void Glk::glk_put_string(char *s) {
- // TODO
-}
-
-void Glk::glk_put_string_stream(strid_t str, char *s) {
- // TODO
-}
-
-void Glk::glk_put_buffer(char *buf, glui32 len) {
- // TODO
-}
-
-void Glk::glk_put_buffer_stream(strid_t str, char *buf, glui32 len) {
- // TODO
-}
-
-void Glk::glk_set_style(glui32 styl) {
- // TODO
-}
-
-void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
- // TODO
-}
-
-glsi32 Glk::glk_get_char_stream(strid_t str) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
- // TODO
- return 0;
-}
-
-void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) {
- // TODO
-}
-
-void Glk::glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) {
- // TODO
-}
-
-glui32 Glk::glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) {
- // TODO
- return 0;
-}
-
-frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
- // TODO
- return nullptr;
-}
-
-frefid_t Glk::glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) {
- // TODO
- return nullptr;
-}
-
-frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) {
- // TODO
- return nullptr;
-}
-
-frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_fileref_destroy(frefid_t fref) {
- // TODO
-}
-
-frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
- // TODO
- return nullptr;
-}
-
-glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
- // TODO
- return 0;
-}
-
-void Glk::glk_fileref_delete_file(frefid_t fref) {
- // TODO
-}
-
-glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
- // TODO
- return 0;
-}
-
-void Glk::glk_select(event_t *event) {
- if (!_gliFirstEvent) {
- gliInputGuessFocus();
- _gliFirstEvent = true;
- }
-
- gliSelect(event, false);
-}
-
-void Glk::glk_select_poll(event_t *event) {
- if (!_gliFirstEvent) {
- gliInputGuessFocus();
- _gliFirstEvent = true;
- }
-
- gliSelect(event, true);
-}
-
-void Glk::glk_request_timer_events(glui32 millisecs) {
- // TODO
-}
-
-void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
- // TODO
-}
-
-void Glk::glk_request_char_event(winid_t win) {
- // TODO
-}
-
-void Glk::glk_request_mouse_event(winid_t win) {
- // TODO
-}
-
-void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
- // TODO
-}
-
-void Glk::glk_cancel_char_event(winid_t win) {
- // TODO
-}
-
-void Glk::glk_cancel_mouse_event(winid_t win) {
- // TODO
-}
-
-#ifdef GLK_MODULE_LINE_ECHO
-
-void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
- // TODO
-}
-
-#endif /* GLK_MODULE_LINE_ECHO */
-
-#ifdef GLK_MODULE_LINE_TERMINATORS
-
-void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
- // TODO
-}
-
-#endif /* GLK_MODULE_LINE_TERMINATORS */
-
-#ifdef GLK_MODULE_UNICODE
-
-glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest) {
- // TODO
- return 0;
-}
-
-void Glk::glk_put_char_uni(glui32 ch) {
- // TODO
-}
-
-void Glk::glk_put_string_uni(glui32 *s) {
- // TODO
-}
-
-void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
- // TODO
-}
-
-void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
- // TODO
-}
-
-void Glk::glk_put_string_stream_uni(strid_t str, glui32 *s) {
- // TODO
-}
-
-void Glk::glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- // TODO
-}
-
-glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- // TODO
- return 0;
-}
-
-strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, glui32 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;
-}
-
-void Glk::glk_request_char_event_uni(winid_t win) {
- // TODO
-}
-
-void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen) {
- // TODO
-}
-
-#endif /* GLK_MODULE_UNICODE */
-
-#ifdef GLK_MODULE_UNICODE_NORM
-
-glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return 0;
-}
-
-#endif /* GLK_MODULE_UNICODE_NORM */
-
-#ifdef GLK_MODULE_IMAGE
-
-glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
- // TODO
- return 0;
-}
-
-void Glk::glk_window_flow_break(winid_t win) {
- // TODO
-}
-
-void Glk::glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height) {
- // TODO
-}
-
-void Glk::glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height) {
- // TODO
-}
-
-void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
- // TODO
-}
-
-#endif /* GLK_MODULE_IMAGE */
-
-#ifdef GLK_MODULE_SOUND
-
-schanid_t Glk::glk_schannel_create(glui32 rock) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_schannel_destroy(schanid_t chan) {
- // TODO
-}
-
-schanid_t Glk::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
- // TODO
- return nullptr;
-}
-
-glui32 Glk::glk_schannel_get_rock(schanid_t chan) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_schannel_play(schanid_t chan, glui32 snd) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
- // TODO
- return 0;
-}
-
-void Glk::glk_schannel_stop(schanid_t chan) {
- // TODO
-}
-
-void Glk::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
- // TODO
-}
-
-void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
- // TODO
-}
-
-#ifdef GLK_MODULE_SOUND2
-
-schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
- // TODO
- return nullptr;
-}
-
-glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify) {
- // TODO
- return 0;
-}
-
-void Glk::glk_schannel_pause(schanid_t chan) {
- // TODO
-}
-
-void Glk::glk_schannel_unpause(schanid_t chan) {
- // TODO
-}
-
-void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify) {
- // TODO
-}
-
-#endif /* GLK_MODULE_SOUND2 */
-#endif /* GLK_MODULE_SOUND */
-
-#ifdef GLK_MODULE_HYPERLINKS
-
-void Glk::glk_set_hyperlink(glui32 linkval) {
- // TODO
-}
-
-void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
- // TODO
-}
-
-void Glk::glk_request_hyperlink_event(winid_t win) {
- // TODO
-}
-
-void Glk::glk_cancel_hyperlink_event(winid_t win) {
- // TODO
-}
-
-#endif /* GLK_MODULE_HYPERLINKS */
-
-#ifdef GLK_MODULE_DATETIME
-
-void Glk::glk_current_time(glktimeval_t *time) {
- // TODO
-}
-
-glsi32 Glk::glk_current_simple_time(glui32 factor) {
- // TODO
- return 0;
-}
-
-void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) {
- // TODO
-}
-
-void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) {
- // TODO
-}
-
-void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
- // TODO
-}
-
-void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
- // TODO
-}
-
-void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) {
- // TODO
-}
-
-void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) {
- // TODO
-}
-
-glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) {
- // TODO
- return 0;
-}
-
-glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
- // TODO
- return 0;
-}
-
-#endif /* GLK_MODULE_DATETIME */
-
-/* XXX non-official Glk functions that may or may not exist */
-
-char *garglk_fileref_get_name(frefid_t fref) {
- // TODO
- return nullptr;
-}
-
-void Glk::garglk_set_program_name(const char *name) {
- // TODO
-}
-
-void Glk::garglk_set_program_info(const char *info) {
- // TODO
-}
-
-void Glk::garglk_set_story_name(const char *name) {
- // TODO
-}
-
-void Glk::garglk_set_story_title(const char *title) {
- // TODO
-}
-
-void Glk::garglk_set_config(const char *name) {
- // TODO
-}
-
-/* garglk_unput_string - removes the specified string from the end of the output buffer, if
-* indeed it is there. */
-void Glk::garglk_unput_string(char *str) {
- // TODO
-}
-
-void Glk::garglk_unput_string_uni(glui32 *str) {
- // TODO
-}
-
-void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
- // TODO
-}
-
-void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
- // TODO
-}
-
-void Glk::garglk_set_reversevideo(glui32 reverse) {
- // TODO
-}
-
-void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
-void Glk::gliInputGuessFocus() {
- // TODO
-}
-
-void Glk::gliSelect(event_t *event, bool polled) {
- // TODO
- event->type = evtype_Quit;
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk/glk.h b/engines/gargoyle/glk/glk.h
deleted file mode 100644
index 11c8cba..0000000
--- a/engines/gargoyle/glk/glk.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/* 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 GARGOYLE_GLK_H
-#define GARGOYLE_GLK_H
-
-#include "graphics/managed_surface.h"
-#include "gargoyle/interpreter.h"
-#include "gargoyle/glk/glk_types.h"
-
-namespace Gargoyle {
-
-/**
- * Implements the GLK interface
- */
-class Glk : public Interpreter {
-private:
- bool _gliFirstEvent;
-private:
- /**
- * Pick first window which might want input. This is called after every keystroke.
- */
- void gliInputGuessFocus();
-
- void gliSelect(event_t *event, bool polled);
-public:
- /**
- * Constructor
- */
- Glk();
-
- void glk_exit(void);
- void glk_set_interrupt_handler(void(*func)(void));
- void glk_tick(void);
-
- glui32 glk_gestalt(glui32 sel, glui32 val);
- glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen);
-
- unsigned char glk_char_to_lower(unsigned char ch);
- unsigned char glk_char_to_upper(unsigned char ch);
-
- winid_t glk_window_get_root(void);
- winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock);
- void glk_window_close(winid_t win, stream_result_t *result);
- void glk_window_get_size(winid_t win, glui32 *widthptr,
- glui32 *heightptr);
- void glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keywin);
- void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
- glui32 *sizeptr, winid_t *keywinptr);
- winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
- glui32 glk_window_get_rock(winid_t win);
- glui32 glk_window_get_type(winid_t win);
- winid_t glk_window_get_parent(winid_t win);
- winid_t glk_window_get_sibling(winid_t win);
- void glk_window_clear(winid_t win);
- void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
-
- strid_t glk_window_get_stream(winid_t win);
- void glk_window_set_echo_stream(winid_t win, strid_t str);
- 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);
- 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);
- 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);
- strid_t glk_stream_get_current(void);
-
- void glk_put_char(unsigned char ch);
- void glk_put_char_stream(strid_t str, unsigned char ch);
- void glk_put_string(char *s);
- void glk_put_string_stream(strid_t str, char *s);
- void glk_put_buffer(char *buf, glui32 len);
- void glk_put_buffer_stream(strid_t str, char *buf, glui32 len);
- void glk_set_style(glui32 styl);
- void glk_set_style_stream(strid_t str, glui32 styl);
-
- glsi32 glk_get_char_stream(strid_t str);
- glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
- glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
-
- void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
- glsi32 val);
- void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
- glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
- glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
- glui32 *result);
-
- 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,
- glui32 rock);
- frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
- glui32 rock);
- void glk_fileref_destroy(frefid_t fref);
- frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
- glui32 glk_fileref_get_rock(frefid_t fref);
- void glk_fileref_delete_file(frefid_t fref);
- glui32 glk_fileref_does_file_exist(frefid_t fref);
-
- void glk_select(event_t *event);
- void glk_select_poll(event_t *event);
-
- void glk_request_timer_events(glui32 millisecs);
-
- void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
- glui32 initlen);
- void glk_request_char_event(winid_t win);
- void glk_request_mouse_event(winid_t win);
-
- void glk_cancel_line_event(winid_t win, event_t *event);
- void glk_cancel_char_event(winid_t win);
- void glk_cancel_mouse_event(winid_t win);
-
-#ifdef GLK_MODULE_LINE_ECHO
- void glk_set_echo_line_event(winid_t win, glui32 val);
-#endif /* GLK_MODULE_LINE_ECHO */
-
-#ifdef GLK_MODULE_LINE_TERMINATORS
- void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
- glui32 count);
-#endif /* GLK_MODULE_LINE_TERMINATORS */
-
-#ifdef GLK_MODULE_UNICODE
-
- glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest);
-
- void glk_put_char_uni(glui32 ch);
- void glk_put_string_uni(glui32 *s);
- void glk_put_buffer_uni(glui32 *buf, glui32 len);
- void glk_put_char_stream_uni(strid_t str, glui32 ch);
- void glk_put_string_stream_uni(strid_t str, glui32 *s);
- void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
-
- glsi32 glk_get_char_stream_uni(strid_t str);
- 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);
-
- void glk_request_char_event_uni(winid_t win);
- void glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen);
-
-#endif /* GLK_MODULE_UNICODE */
-
-#ifdef GLK_MODULE_UNICODE_NORM
-
- glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
- glui32 numchars);
-
-#endif /* GLK_MODULE_UNICODE_NORM */
-
-#ifdef GLK_MODULE_IMAGE
-
- glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
- glui32 glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height);
- glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
-
- void glk_window_flow_break(winid_t win);
-
- void glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
- void glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
- void glk_window_set_background_color(winid_t win, glui32 color);
-
-#endif /* GLK_MODULE_IMAGE */
-
-#ifdef GLK_MODULE_SOUND
-
- schanid_t glk_schannel_create(glui32 rock);
- void glk_schannel_destroy(schanid_t chan);
- schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
- glui32 glk_schannel_get_rock(schanid_t chan);
-
- glui32 glk_schannel_play(schanid_t chan, glui32 snd);
- glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
- glui32 notify);
- void glk_schannel_stop(schanid_t chan);
- void glk_schannel_set_volume(schanid_t chan, glui32 vol);
-
- void glk_sound_load_hint(glui32 snd, glui32 flag);
-
-#ifdef GLK_MODULE_SOUND2
- /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
- GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
-
- schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
- glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify);
- void glk_schannel_pause(schanid_t chan);
- void glk_schannel_unpause(schanid_t chan);
- void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify);
-
-#endif /* GLK_MODULE_SOUND2 */
-#endif /* GLK_MODULE_SOUND */
-
-#ifdef GLK_MODULE_HYPERLINKS
-
- void glk_set_hyperlink(glui32 linkval);
- void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
- void glk_request_hyperlink_event(winid_t win);
- void glk_cancel_hyperlink_event(winid_t win);
-
-#endif /* GLK_MODULE_HYPERLINKS */
-
-#ifdef GLK_MODULE_DATETIME
-
- void glk_current_time(glktimeval_t *time);
- glsi32 glk_current_simple_time(glui32 factor);
- void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
- void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
- void glk_simple_time_to_date_utc(glsi32 time, glui32 factor,
- glkdate_t *date);
- void glk_simple_time_to_date_local(glsi32 time, glui32 factor,
- glkdate_t *date);
- void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
- void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
- glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
- glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);
-
-#endif /* GLK_MODULE_DATETIME */
-
- /* XXX non-official Glk functions that may or may not exist */
- #define GARGLK 1
-
- char* garglk_fileref_get_name(frefid_t fref);
-
- void garglk_set_program_name(const char *name);
- void garglk_set_program_info(const char *info);
- void garglk_set_story_name(const char *name);
- void garglk_set_story_title(const char *title);
- void garglk_set_config(const char *name);
-
- /* garglk_unput_string - removes the specified string from the end of the output buffer, if
- * indeed it is there. */
- void garglk_unput_string(char *str);
- void garglk_unput_string_uni(glui32 *str);
-
- void garglk_set_zcolors(glui32 fg, glui32 bg);
- void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
- void garglk_set_reversevideo(glui32 reverse);
- void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/glk/glk_types.h b/engines/gargoyle/glk/glk_types.h
deleted file mode 100644
index a822741..0000000
--- a/engines/gargoyle/glk/glk_types.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/* 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 GARGOYLE_GLK_TYPES_H
-#define GARGOYLE_GLK_TYPES_H
-
-#include "common/scummsys.h"
-
-namespace Gargoyle {
-
-typedef uint32 glui32;
-typedef int32 glsi32;
-
-/**
- * These are the compile-time conditionals that reveal various Glk optional modules.
- */
-#define GLK_MODULE_LINE_ECHO
-#define GLK_MODULE_LINE_TERMINATORS
-#define GLK_MODULE_UNICODE
-#define GLK_MODULE_UNICODE_NORM
-#define GLK_MODULE_IMAGE
-#define GLK_MODULE_SOUND
-#define GLK_MODULE_SOUND2
-#define GLK_MODULE_HYPERLINKS
-#define GLK_MODULE_DATETIME
-#define GLK_MODULE_GARGLKTEXT
-
-/**
- * These types are opaque object identifiers. They're pointers to opaque
- * C structures, which are defined differently by each library.
- */
-typedef struct glk_window_struct *winid_t;
-typedef struct glk_stream_struct *strid_t;
-typedef struct glk_fileref_struct *frefid_t;
-typedef struct glk_schannel_struct *schanid_t;
-
-enum Gestalt {
- gestalt_Version = 0,
- gestalt_CharInput = 1,
- gestalt_LineInput = 2,
- gestalt_CharOutput = 3,
- gestalt_CharOutput_CannotPrint = 0,
- gestalt_CharOutput_ApproxPrint = 1,
- gestalt_CharOutput_ExactPrint = 2,
- gestalt_MouseInput = 4,
- gestalt_Timer = 5,
- gestalt_Graphics = 6,
- gestalt_DrawImage = 7,
- gestalt_Sound = 8,
- gestalt_SoundVolume = 9,
- gestalt_SoundNotify = 10,
- gestalt_Hyperlinks = 11,
- gestalt_HyperlinkInput = 12,
- gestalt_SoundMusic = 13,
- gestalt_GraphicsTransparency = 14,
- gestalt_Unicode = 15,
- gestalt_UnicodeNorm = 16,
- gestalt_LineInputEcho = 17,
- gestalt_LineTerminators = 18,
- gestalt_LineTerminatorKey = 19,
- gestalt_DateTime = 20,
- gestalt_Sound2 = 21,
- gestalt_GarglkText = 0x1100,
-};
-
-enum EvType {
- evtype_None = 0,
- evtype_Timer = 1,
- evtype_CharInput = 2,
- evtype_LineInput = 3,
- evtype_MouseInput = 4,
- evtype_Arrange = 5,
- evtype_Redraw = 6,
- evtype_SoundNotify = 7,
- evtype_Hyperlink = 8,
- evtype_VolumeNotify = 9,
-
- // ScummVM custom events
- evtype_Quit = 99
-};
-
-enum Keycode {
- keycode_Unknown = 0xffffffffU,
- keycode_Left = 0xfffffffeU,
- keycode_Right = 0xfffffffdU,
- keycode_Up = 0xfffffffcU,
- keycode_Down = 0xfffffffbU,
- keycode_Return = 0xfffffffaU,
- keycode_Delete = 0xfffffff9U,
- keycode_Escape = 0xfffffff8U,
- keycode_Tab = 0xfffffff7U,
- keycode_PageUp = 0xfffffff6U,
- keycode_PageDown = 0xfffffff5U,
- keycode_Home = 0xfffffff4U,
- keycode_End = 0xfffffff3U,
- keycode_Func1 = 0xffffffefU,
- keycode_Func2 = 0xffffffeeU,
- keycode_Func3 = 0xffffffedU,
- keycode_Func4 = 0xffffffecU,
- keycode_Func5 = 0xffffffebU,
- keycode_Func6 = 0xffffffeaU,
- keycode_Func7 = 0xffffffe9U,
- keycode_Func8 = 0xffffffe8U,
- keycode_Func9 = 0xffffffe7U,
- keycode_Func10 = 0xffffffe6U,
- keycode_Func11 = 0xffffffe5U,
- keycode_Func12 = 0xffffffe4U,
-
- // non standard keycodes
- keycode_Erase = 0xffffef7fU,
- keycode_MouseWheelUp = 0xffffeffeU,
- keycode_MouseWheelDown = 0xffffefffU,
- keycode_SkipWordLeft = 0xfffff000U,
- keycode_SkipWordRight = 0xfffff001U,
-
- // The last keycode is always = 0x100000000 - keycode_MAXVAL)
- keycode_MAXVAL = 28U
-};
-
-enum Style {
- style_Normal = 0,
- style_Emphasized = 1,
- style_Preformatted = 2,
- style_Header = 3,
- style_Subheader = 4,
- style_Alert = 5,
- style_Note = 6,
- style_BlockQuote = 7,
- style_Input = 8,
- style_User1 = 9,
- style_User2 = 10,
- style_NUMSTYLES = 11,
-};
-
-enum WinType {
- wintype_AllTypes = 0,
- wintype_Pair = 1,
- wintype_Blank = 2,
- wintype_TextBuffer = 3,
- wintype_TextGrid = 4,
- wintype_Graphics = 5,
-};
-
-enum WinMethod {
- winmethod_Left = 0x00,
- winmethod_Right = 0x01,
- winmethod_Above = 0x02,
- winmethod_Below = 0x03,
- winmethod_DirMask = 0x0f,
-
- winmethod_Fixed = 0x10,
- winmethod_Proportional = 0x20,
- winmethod_DivisionMask = 0xf0,
-
- winmethod_Border = 0x000,
- winmethod_NoBorder = 0x100,
- winmethod_BorderMask = 0x100,
-};
-
-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,
-};
-
-enum StyleHint {
- stylehint_Indentation = 0,
- stylehint_ParaIndentation = 1,
- stylehint_Justification = 2,
- stylehint_Size = 3,
- stylehint_Weight = 4,
- stylehint_Oblique = 5,
- stylehint_Proportional = 6,
- stylehint_TextColor = 7,
- stylehint_BackColor = 8,
- stylehint_ReverseColor = 9,
- stylehint_NUMHINTS = 10,
-
- stylehint_just_LeftFlush = 0,
- stylehint_just_LeftRight = 1,
- stylehint_just_Centered = 2,
- stylehint_just_RightFlush = 3,
-};
-
-#ifdef GLK_MODULE_IMAGE
-
-enum ImageAlign {
- imagealign_InlineUp = 1,
- imagealign_InlineDown = 2,
- imagealign_InlineCenter = 3,
- imagealign_MarginLeft = 4,
- imagealign_MarginRight = 5
-};
-
-#endif /* GLK_MODULE_IMAGE */
-
-struct event_struct {
- glui32 type;
- winid_t win;
- glui32 val1, val2;
-};
-typedef event_struct event_t;
-
-struct stream_result_struct {
- glui32 readcount;
- glui32 writecount;
-};
-typedef stream_result_struct stream_result_t;
-
-#ifdef GLK_MODULE_DATETIME
-
-struct glktimeval_struct {
- glsi32 high_sec;
- glui32 low_sec;
- glsi32 microsec;
-};
-typedef glktimeval_struct glktimeval_t;
-
-struct glkdate_struct {
- glsi32 year; ///< full (four-digit) year */
- glsi32 month; ///< 1-12, 1 is January
- glsi32 day; ///< 1-31
- glsi32 weekday; ///< 0-6, 0 is Sunday
- glsi32 hour; ///< 0-23
- glsi32 minute; ///< 0-59
- glsi32 second; ///< 0-59, maybe 60 during a leap second
- glsi32 microsec; ///< 0-999999
-};
-typedef glkdate_struct glkdate_t;
-
-#endif /* GLK_MODULE_DATETIME */
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
new file mode 100644
index 0000000..a822741
--- /dev/null
+++ b/engines/gargoyle/glk_types.h
@@ -0,0 +1,272 @@
+/* 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 GARGOYLE_GLK_TYPES_H
+#define GARGOYLE_GLK_TYPES_H
+
+#include "common/scummsys.h"
+
+namespace Gargoyle {
+
+typedef uint32 glui32;
+typedef int32 glsi32;
+
+/**
+ * These are the compile-time conditionals that reveal various Glk optional modules.
+ */
+#define GLK_MODULE_LINE_ECHO
+#define GLK_MODULE_LINE_TERMINATORS
+#define GLK_MODULE_UNICODE
+#define GLK_MODULE_UNICODE_NORM
+#define GLK_MODULE_IMAGE
+#define GLK_MODULE_SOUND
+#define GLK_MODULE_SOUND2
+#define GLK_MODULE_HYPERLINKS
+#define GLK_MODULE_DATETIME
+#define GLK_MODULE_GARGLKTEXT
+
+/**
+ * These types are opaque object identifiers. They're pointers to opaque
+ * C structures, which are defined differently by each library.
+ */
+typedef struct glk_window_struct *winid_t;
+typedef struct glk_stream_struct *strid_t;
+typedef struct glk_fileref_struct *frefid_t;
+typedef struct glk_schannel_struct *schanid_t;
+
+enum Gestalt {
+ gestalt_Version = 0,
+ gestalt_CharInput = 1,
+ gestalt_LineInput = 2,
+ gestalt_CharOutput = 3,
+ gestalt_CharOutput_CannotPrint = 0,
+ gestalt_CharOutput_ApproxPrint = 1,
+ gestalt_CharOutput_ExactPrint = 2,
+ gestalt_MouseInput = 4,
+ gestalt_Timer = 5,
+ gestalt_Graphics = 6,
+ gestalt_DrawImage = 7,
+ gestalt_Sound = 8,
+ gestalt_SoundVolume = 9,
+ gestalt_SoundNotify = 10,
+ gestalt_Hyperlinks = 11,
+ gestalt_HyperlinkInput = 12,
+ gestalt_SoundMusic = 13,
+ gestalt_GraphicsTransparency = 14,
+ gestalt_Unicode = 15,
+ gestalt_UnicodeNorm = 16,
+ gestalt_LineInputEcho = 17,
+ gestalt_LineTerminators = 18,
+ gestalt_LineTerminatorKey = 19,
+ gestalt_DateTime = 20,
+ gestalt_Sound2 = 21,
+ gestalt_GarglkText = 0x1100,
+};
+
+enum EvType {
+ evtype_None = 0,
+ evtype_Timer = 1,
+ evtype_CharInput = 2,
+ evtype_LineInput = 3,
+ evtype_MouseInput = 4,
+ evtype_Arrange = 5,
+ evtype_Redraw = 6,
+ evtype_SoundNotify = 7,
+ evtype_Hyperlink = 8,
+ evtype_VolumeNotify = 9,
+
+ // ScummVM custom events
+ evtype_Quit = 99
+};
+
+enum Keycode {
+ keycode_Unknown = 0xffffffffU,
+ keycode_Left = 0xfffffffeU,
+ keycode_Right = 0xfffffffdU,
+ keycode_Up = 0xfffffffcU,
+ keycode_Down = 0xfffffffbU,
+ keycode_Return = 0xfffffffaU,
+ keycode_Delete = 0xfffffff9U,
+ keycode_Escape = 0xfffffff8U,
+ keycode_Tab = 0xfffffff7U,
+ keycode_PageUp = 0xfffffff6U,
+ keycode_PageDown = 0xfffffff5U,
+ keycode_Home = 0xfffffff4U,
+ keycode_End = 0xfffffff3U,
+ keycode_Func1 = 0xffffffefU,
+ keycode_Func2 = 0xffffffeeU,
+ keycode_Func3 = 0xffffffedU,
+ keycode_Func4 = 0xffffffecU,
+ keycode_Func5 = 0xffffffebU,
+ keycode_Func6 = 0xffffffeaU,
+ keycode_Func7 = 0xffffffe9U,
+ keycode_Func8 = 0xffffffe8U,
+ keycode_Func9 = 0xffffffe7U,
+ keycode_Func10 = 0xffffffe6U,
+ keycode_Func11 = 0xffffffe5U,
+ keycode_Func12 = 0xffffffe4U,
+
+ // non standard keycodes
+ keycode_Erase = 0xffffef7fU,
+ keycode_MouseWheelUp = 0xffffeffeU,
+ keycode_MouseWheelDown = 0xffffefffU,
+ keycode_SkipWordLeft = 0xfffff000U,
+ keycode_SkipWordRight = 0xfffff001U,
+
+ // The last keycode is always = 0x100000000 - keycode_MAXVAL)
+ keycode_MAXVAL = 28U
+};
+
+enum Style {
+ style_Normal = 0,
+ style_Emphasized = 1,
+ style_Preformatted = 2,
+ style_Header = 3,
+ style_Subheader = 4,
+ style_Alert = 5,
+ style_Note = 6,
+ style_BlockQuote = 7,
+ style_Input = 8,
+ style_User1 = 9,
+ style_User2 = 10,
+ style_NUMSTYLES = 11,
+};
+
+enum WinType {
+ wintype_AllTypes = 0,
+ wintype_Pair = 1,
+ wintype_Blank = 2,
+ wintype_TextBuffer = 3,
+ wintype_TextGrid = 4,
+ wintype_Graphics = 5,
+};
+
+enum WinMethod {
+ winmethod_Left = 0x00,
+ winmethod_Right = 0x01,
+ winmethod_Above = 0x02,
+ winmethod_Below = 0x03,
+ winmethod_DirMask = 0x0f,
+
+ winmethod_Fixed = 0x10,
+ winmethod_Proportional = 0x20,
+ winmethod_DivisionMask = 0xf0,
+
+ winmethod_Border = 0x000,
+ winmethod_NoBorder = 0x100,
+ winmethod_BorderMask = 0x100,
+};
+
+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,
+};
+
+enum StyleHint {
+ stylehint_Indentation = 0,
+ stylehint_ParaIndentation = 1,
+ stylehint_Justification = 2,
+ stylehint_Size = 3,
+ stylehint_Weight = 4,
+ stylehint_Oblique = 5,
+ stylehint_Proportional = 6,
+ stylehint_TextColor = 7,
+ stylehint_BackColor = 8,
+ stylehint_ReverseColor = 9,
+ stylehint_NUMHINTS = 10,
+
+ stylehint_just_LeftFlush = 0,
+ stylehint_just_LeftRight = 1,
+ stylehint_just_Centered = 2,
+ stylehint_just_RightFlush = 3,
+};
+
+#ifdef GLK_MODULE_IMAGE
+
+enum ImageAlign {
+ imagealign_InlineUp = 1,
+ imagealign_InlineDown = 2,
+ imagealign_InlineCenter = 3,
+ imagealign_MarginLeft = 4,
+ imagealign_MarginRight = 5
+};
+
+#endif /* GLK_MODULE_IMAGE */
+
+struct event_struct {
+ glui32 type;
+ winid_t win;
+ glui32 val1, val2;
+};
+typedef event_struct event_t;
+
+struct stream_result_struct {
+ glui32 readcount;
+ glui32 writecount;
+};
+typedef stream_result_struct stream_result_t;
+
+#ifdef GLK_MODULE_DATETIME
+
+struct glktimeval_struct {
+ glsi32 high_sec;
+ glui32 low_sec;
+ glsi32 microsec;
+};
+typedef glktimeval_struct glktimeval_t;
+
+struct glkdate_struct {
+ glsi32 year; ///< full (four-digit) year */
+ glsi32 month; ///< 1-12, 1 is January
+ glsi32 day; ///< 1-31
+ glsi32 weekday; ///< 0-6, 0 is Sunday
+ glsi32 hour; ///< 0-23
+ glsi32 minute; ///< 0-59
+ glsi32 second; ///< 0-59, maybe 60 during a leap second
+ glsi32 microsec; ///< 0-999999
+};
+typedef glkdate_struct glkdate_t;
+
+#endif /* GLK_MODULE_DATETIME */
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/interpreter.cpp b/engines/gargoyle/interpreter.cpp
deleted file mode 100644
index 10cefd7..0000000
--- a/engines/gargoyle/interpreter.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/interpreter.h"
-
-namespace Gargoyle {
-
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/interpreter.h b/engines/gargoyle/interpreter.h
deleted file mode 100644
index 748d417..0000000
--- a/engines/gargoyle/interpreter.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* 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 GARGOYLE_INTERPRETER_H
-#define GARGOYLE_INTERPRETER_H
-
-#include "graphics/screen.h"
-
-namespace Gargoyle {
-
-/**
- * Base class for specific interpreters
- */
-class Interpreter {
-protected:
- Graphics::Screen _screen;
-public:
- /**
- * Constructor
- */
- Interpreter() {}
-
- /**
- * Destructor
- */
- virtual ~Interpreter() {}
-
- /**
- * Main execution method
- */
- virtual void execute() = 0;
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/interps/scott/scott.cpp b/engines/gargoyle/interps/scott/scott.cpp
deleted file mode 100644
index b2ea5e2..0000000
--- a/engines/gargoyle/interps/scott/scott.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/interps/scott/scott.h"
-
-namespace Gargoyle {
-namespace Scott {
-
-void Scott::execute() {
- event_t ev;
- do {
- glk_select(&ev);
- switch (ev.type) {
- default:
- /* do nothing */
- break;
- }
- } while (ev.type != evtype_Quit);
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/interps/scott/scott.h b/engines/gargoyle/interps/scott/scott.h
deleted file mode 100644
index 7d87ca5..0000000
--- a/engines/gargoyle/interps/scott/scott.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* 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 GARGOYLE_SCOTT
-#define GARGOYLE_SCOTT
-
-/*
- * Controlling block
- */
-
-#include "common/scummsys.h"
-#include "gargoyle/glk/glk.h"
-
-namespace Gargoyle {
-namespace Scott {
-
-#define LIGHT_SOURCE 9 // Always 9 how odd
-#define CARRIED 255 // Carried
-#define DESTROYED 0 // Destroyed
-#define DARKBIT 15
-#define LIGHTOUTBIT 16 // Light gone out
-
-#define YOUARE 1 // You are not I am
-#define SCOTTLIGHT 2 // Authentic Scott Adams light messages
-#define DEBUGGING 4 // Info from database load
-#define TRS80_STYLE 8 // Display in style used on TRS-80
-#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
-
-struct Header {
- int Unknown;
- int NumItems;
- int NumActions;
- int NumWords; // Smaller of verb/noun is padded to same size
- int NumRooms;
- int MaxCarry;
- int PlayerRoom;
- int Treasures;
- int WordLength;
- int LightTime;
- int NumMessages;
- int TreasureRoom;
-};
-
-struct Action {
- uint Vocab;
- uint Condition[5];
- uint action[2];
-};
-
-struct Room {
- char *Text;
- short Exits[6];
-};
-
-struct Item {
- char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
- byte Location;
- byte InitialLoc;
- char *AutoGet;
-};
-
-struct Tail {
- int Version;
- int AdventureNumber;
- int Unknown;
-};
-
-/**
- * Scott Adams game interpreter
- */
-class Scott : public Glk {
-public:
- /**
- * Constructor
- */
- Scott() : Glk() {}
-
- /**
- * Execute the game
- */
- virtual void execute();
-};
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 6e11ba7..c1a2867 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -4,9 +4,8 @@ MODULE_OBJS := \
detection.o \
events.o \
gargoyle.o \
- glk/glk.o \
- interpreter.o \
- interps/scott/scott.o
+ glk.o \
+ scott/scott.o
# This module can be built as a plugin
ifeq ($(ENABLE_GARGOYLE), DYNAMIC_PLUGIN)
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
new file mode 100644
index 0000000..9a1a6e3
--- /dev/null
+++ b/engines/gargoyle/scott/scott.cpp
@@ -0,0 +1,41 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/scott/scott.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+void Scott::main() {
+ event_t ev;
+ do {
+ glk_select(&ev);
+ switch (ev.type) {
+ default:
+ /* do nothing */
+ break;
+ }
+ } while (ev.type != evtype_Quit);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
new file mode 100644
index 0000000..0e7d85c
--- /dev/null
+++ b/engines/gargoyle/scott/scott.h
@@ -0,0 +1,106 @@
+/* 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 GARGOYLE_SCOTT
+#define GARGOYLE_SCOTT
+
+/*
+ * Controlling block
+ */
+
+#include "common/scummsys.h"
+#include "gargoyle/glk.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+#define LIGHT_SOURCE 9 // Always 9 how odd
+#define CARRIED 255 // Carried
+#define DESTROYED 0 // Destroyed
+#define DARKBIT 15
+#define LIGHTOUTBIT 16 // Light gone out
+
+#define YOUARE 1 // You are not I am
+#define SCOTTLIGHT 2 // Authentic Scott Adams light messages
+#define DEBUGGING 4 // Info from database load
+#define TRS80_STYLE 8 // Display in style used on TRS-80
+#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
+
+struct Header {
+ int Unknown;
+ int NumItems;
+ int NumActions;
+ int NumWords; // Smaller of verb/noun is padded to same size
+ int NumRooms;
+ int MaxCarry;
+ int PlayerRoom;
+ int Treasures;
+ int WordLength;
+ int LightTime;
+ int NumMessages;
+ int TreasureRoom;
+};
+
+struct Action {
+ uint Vocab;
+ uint Condition[5];
+ uint action[2];
+};
+
+struct Room {
+ char *Text;
+ short Exits[6];
+};
+
+struct Item {
+ char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
+ byte Location;
+ byte InitialLoc;
+ char *AutoGet;
+};
+
+struct Tail {
+ int Version;
+ int AdventureNumber;
+ int Unknown;
+};
+
+/**
+ * Scott Adams game interpreter
+ */
+class Scott : public Glk {
+public:
+ /**
+ * Constructor
+ */
+ Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc) {}
+
+ /**
+ * Execute the game
+ */
+ virtual void main();
+};
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
+
+#endif
Commit: 22648145a91ae42ed0e1ab69b1dc9ad564e9fd1d
https://github.com/scummvm/scummvm/commit/22648145a91ae42ed0e1ab69b1dc9ad564e9fd1d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Initial conversion of ScottFree
Changed paths:
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/scott/scott.cpp
engines/gargoyle/scott/scott.h
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 3457f5f..7953c68 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -32,10 +32,12 @@
namespace Gargoyle {
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst) {
+ _gameDescription(gameDesc), Engine(syst), _random("Gargoyle") {
+ _screen = nullptr;
}
GargoyleEngine::~GargoyleEngine() {
+ delete _screen;
}
void GargoyleEngine::initialize() {
@@ -46,11 +48,14 @@ void GargoyleEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphics(640, 480, false);
+ _screen = new Graphics::Screen();
}
Common::Error GargoyleEngine::run() {
initialize();
- main();
+
+ // TODO: Pass proper gamefile
+ runGame(nullptr);
return Common::kNoError;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 0940248..37c1a22 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -24,10 +24,12 @@
#define GARGOYLE_GARGOLE_H
#include "common/scummsys.h"
+#include "common/random.h"
#include "common/system.h"
#include "common/serializer.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
+#include "graphics/screen.h"
namespace Gargoyle {
@@ -67,6 +69,8 @@ private:
void initialize();
protected:
const GargoyleGameDescription *_gameDescription;
+ Graphics::Screen *_screen;
+ Common::RandomSource _random;
int _loadSaveSlot;
// Engine APIs
@@ -76,7 +80,7 @@ protected:
/**
* Main game loop for the individual interpreters
*/
- virtual void main() = 0;
+ virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
public:
GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
virtual ~GargoyleEngine();
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 350b40f..82943bd 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -191,11 +191,11 @@ void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
// TODO
}
-void Glk::glk_put_string(char *s) {
+void Glk::glk_put_string(const char *s) {
// TODO
}
-void Glk::glk_put_string_stream(strid_t str, char *s) {
+void Glk::glk_put_string_stream(strid_t str, const char *s) {
// TODO
}
@@ -203,7 +203,7 @@ void Glk::glk_put_buffer(char *buf, glui32 len) {
// TODO
}
-void Glk::glk_put_buffer_stream(strid_t str, char *buf, glui32 len) {
+void Glk::glk_put_buffer_stream(strid_t str, const char *buf, glui32 len) {
// TODO
}
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index eab6f0b..55cd563 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -94,10 +94,10 @@ public:
void glk_put_char(unsigned char ch);
void glk_put_char_stream(strid_t str, unsigned char ch);
- void glk_put_string(char *s);
- void glk_put_string_stream(strid_t str, char *s);
+ void glk_put_string(const char *s);
+ void glk_put_string_stream(strid_t str, const char *s);
void glk_put_buffer(char *buf, glui32 len);
- void glk_put_buffer_stream(strid_t str, char *buf, glui32 len);
+ void glk_put_buffer_stream(strid_t str, const char *buf, glui32 len);
void glk_set_style(glui32 styl);
void glk_set_style_stream(strid_t str, glui32 styl);
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 9a1a6e3..02096c6 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -25,16 +25,1265 @@
namespace Gargoyle {
namespace Scott {
-void Scott::main() {
+/*
+glkunix_argumentlist_t glkunix_arguments[] =
+{
+ { "-y", glkunix_arg_NoValue, "-y Generate 'You are', 'You are carrying' type messages for games that use these instead (eg Robin Of Sherwood)" },
+ { "-i", glkunix_arg_NoValue, "-i Generate 'I am' type messages (default)" },
+ { "-d", glkunix_arg_NoValue, "-d Debugging info on load " },
+ { "-s", glkunix_arg_NoValue, "-s Generate authentic Scott Adams driver light messages rather than other driver style ones (Light goes out in n turns..)" },
+ { "-t", glkunix_arg_NoValue, "-t Generate TRS80 style display (terminal width is 64 characters; a line <-----------------> is displayed after the top stuff; objects have periods after them instead of hyphens" },
+ { "-p", glkunix_arg_NoValue, "-p Use for prehistoric databases which don't use bit 16" },
+ { "-w", glkunix_arg_NoValue, "-w Disable upper window" },
+ { "", glkunix_arg_ValueFollows, "filename file to load" },
+
+ { nullptr, glkunix_arg_End, nullptr }
+};
+*/
+
+Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
+ Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
+ Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
+ split_screen(true), Bottom(0), Top(0), BitFlags(0) {
+ Common::fill(&NounText[0], &NounText[16], '\0');
+ Common::fill(&Counters[0], &Counters[16], 0);
+ Common::fill(&RoomSaved[0], &RoomSaved[16], 0);
+}
+
+void Scott::runGame(Common::SeekableReadStream *gameFile) {
+ int vb, no;
+ initialize();
+
+ Bottom = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
+ if (Bottom == nullptr)
+ glk_exit();
+ glk_set_window(Bottom);
+
+ if (Options & TRS80_STYLE) {
+ Width = 64;
+ TopHeight = 11;
+ } else {
+ Width = 80;
+ TopHeight = 10;
+ }
+
+ if (split_screen) {
+ Top = glk_window_open(Bottom, winmethod_Above | winmethod_Fixed, TopHeight, wintype_TextGrid, 0);
+ if (Top == nullptr) {
+ split_screen = 0;
+ Top = Bottom;
+ }
+ } else {
+ Top = Bottom;
+ }
+
+ Output("\
+Scott Free, A Scott Adams game driver in C.\n\
+Release 1.14, (c) 1993,1994,1995 Swansea University Computer Society.\n\
+Distributed under the GNU software license\n\n");
+ LoadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
+
+ while (!shouldQuit()) {
+ glk_tick();
+
+ PerformActions(0, 0);
+
+ Look();
+
+ if (GetInput(&vb, &no) == -1)
+ continue;
+ switch (PerformActions(vb, no)) {
+ case -1:
+ Output("I don't understand your command. ");
+ break;
+ case -2:
+ Output("I can't do that yet. ");
+ break;
+ default:
+ break;
+ }
+
+ /* Brian Howarth games seem to use -1 for forever */
+ if (Items[LIGHT_SOURCE].Location/*==-1*/ != DESTROYED && GameHeader.LightTime != -1) {
+ GameHeader.LightTime--;
+ if (GameHeader.LightTime < 1) {
+ BitFlags |= (1 << LIGHTOUTBIT);
+ if (Items[LIGHT_SOURCE].Location == CARRIED ||
+ Items[LIGHT_SOURCE].Location == MyLoc) {
+ if (Options&SCOTTLIGHT)
+ Output("Light has run out! ");
+ else
+ Output("Your light has run out. ");
+ }
+ if (Options&PREHISTORIC_LAMP)
+ Items[LIGHT_SOURCE].Location = DESTROYED;
+ } else if (GameHeader.LightTime < 25) {
+ if (Items[LIGHT_SOURCE].Location == CARRIED ||
+ Items[LIGHT_SOURCE].Location == MyLoc) {
+
+ if (Options&SCOTTLIGHT) {
+ Output("Light runs out in ");
+ OutputNumber(GameHeader.LightTime);
+ Output(" turns. ");
+ } else {
+ if (GameHeader.LightTime % 5 == 0)
+ Output("Your light is growing dim. ");
+ }
+ }
+ }
+ }
+ }
+}
+
+void Scott::initialize() {
+ /*
+ int argc = data->argc;
+ char **argv = data->argv;
+
+ if (argc < 1)
+ return 0;
+
+ while (argv[1])
+ {
+ if (*argv[1] != '-')
+ break;
+ switch (argv[1][1])
+ {
+ case 'y':
+ Options |= YOUARE;
+ break;
+ case 'i':
+ Options &= ~YOUARE;
+ break;
+ case 'd':
+ Options |= DEBUGGING;
+ break;
+ case 's':
+ Options |= SCOTTLIGHT;
+ break;
+ case 't':
+ Options |= TRS80_STYLE;
+ break;
+ case 'p':
+ Options |= PREHISTORIC_LAMP;
+ break;
+ case 'w':
+ split_screen = 0;
+ break;
+ }
+ argv++;
+ argc--;
+ }
+
+ if (argc == 2)
+ {
+ game_file = argv[1];
+#ifdef GARGLK
+ const char *s;
+ if ((s = strrchr(game_file, '/')) != nullptr || (s = strrchr(game_file, '\\')) != nullptr)
+ {
+ garglk_set_story_name(s + 1);
+ }
+ else
+ {
+ garglk_set_story_name(game_file);
+ }
+#endif
+ }
+ */
+}
+
+void Scott::Display(winid_t w, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ Common::String msg = Common::String::vformat(fmt, ap);
+ va_end(ap);
+
+ glk_put_string_stream(glk_window_get_stream(w), msg.c_str());
+}
+
+void Scott::Delay(int seconds) {
event_t ev;
+
+ if (!glk_gestalt(gestalt_Timer, 0))
+ return;
+
+ glk_request_timer_events(1000 * seconds);
+
+ do
+ {
+ glk_select(&ev);
+ } while (ev.type != evtype_Timer);
+
+ glk_request_timer_events(0);
+}
+
+void Scott::Fatal(const char *x) {
+ error(x);
+}
+
+void Scott::ClearScreen(void) {
+ glk_window_clear(Bottom);
+}
+
+void *Scott::MemAlloc(int size) {
+ void *t = (void *)malloc(size);
+ if (t == nullptr)
+ Fatal("Out of memory");
+ return t;
+}
+
+bool Scott::RandomPercent(uint n) {
+ return _random.getRandomNumber(99) < n;
+}
+
+int Scott::CountCarried(void) {
+ int ct = 0;
+ int n = 0;
+ while (ct <= GameHeader.NumItems) {
+ if (Items[ct].Location == CARRIED)
+ n++;
+ ct++;
+ }
+ return n;
+}
+
+const char *Scott::MapSynonym(const char *word) {
+ int n = 1;
+ const char *tp;
+ static char lastword[16]; /* Last non synonym */
+ while (n <= GameHeader.NumWords) {
+ tp = Nouns[n];
+ if (*tp == '*')
+ tp++;
+ else
+ strcpy(lastword, tp);
+ if (xstrncasecmp(word, tp, GameHeader.WordLength) == 0)
+ return lastword;
+ n++;
+ }
+ return nullptr;
+}
+
+int Scott::MatchUpItem(const char *text, int loc) {
+ const char *word = MapSynonym(text);
+ int ct = 0;
+
+ if (word == nullptr)
+ word = text;
+
+ while (ct <= GameHeader.NumItems) {
+ if (Items[ct].AutoGet && Items[ct].Location == loc &&
+ xstrncasecmp(Items[ct].AutoGet, word, GameHeader.WordLength) == 0)
+ return ct;
+ ct++;
+ }
+
+ return -1;
+}
+
+char *Scott::ReadString(Common::SeekableReadStream *f)
+{
+ char tmp[1024];
+ char *t;
+ int c, nc;
+ int ct = 0;
+ do {
+ c = f->readByte();
+ } while (f->pos() < f->size() && Common::isSpace(c));
+ if (c != '"') {
+ Fatal("Initial quote expected");
+ }
+
+ do {
+ c = f->readByte();
+ if (c == EOF)
+ Fatal("EOF in string");
+ if (c == '"')
+ {
+ nc = f->readByte();
+ if (nc != '"') {
+ f->seek(-1, SEEK_CUR);
+ break;
+ }
+ }
+ if (c == '`')
+ c = '"'; /* pdd */
+
+ /* Ensure a valid Glk newline is sent. */
+ if (c == '\n')
+ tmp[ct++] = 10;
+ /* Special case: assume CR is part of CRLF in a
+ * DOS-formatted file, and ignore it.
+ */
+ else if (c == 13)
+ ;
+ /* Pass only ASCII to Glk; the other reasonable option
+ * would be to pass Latin-1, but it's probably safe to
+ * assume that Scott Adams games are ASCII only.
+ */
+ else if ((c >= 32 && c <= 126))
+ tmp[ct++] = c;
+ else
+ tmp[ct++] = '?';
+ } while (1);
+
+ tmp[ct] = 0;
+ t = (char *)MemAlloc(ct + 1);
+ memcpy(t, tmp, ct + 1);
+ return t;
+}
+
+void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
+ int unused, ni, na, nw, nr, mc, pr, tr, wl, lt, mn, trm;
+ int ct;
+ int lo;
+ Action *ap;
+ Room *rp;
+ Item *ip;
+ /* Load the header */
+
+ readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
+
+ GameHeader.NumItems = ni;
+ Items = (Item *)MemAlloc(sizeof(Item)*(ni + 1));
+ GameHeader.NumActions = na;
+ Actions = (Action *)MemAlloc(sizeof(Action)*(na + 1));
+ GameHeader.NumWords = nw;
+ GameHeader.WordLength = wl;
+ Verbs = (const char **)MemAlloc(sizeof(char *)*(nw + 1));
+ Nouns = (const char **)MemAlloc(sizeof(char *)*(nw + 1));
+ GameHeader.NumRooms = nr;
+ Rooms = (Room *)MemAlloc(sizeof(Room)*(nr + 1));
+ GameHeader.MaxCarry = mc;
+ GameHeader.PlayerRoom = pr;
+ GameHeader.Treasures = tr;
+ GameHeader.LightTime = lt;
+ LightRefill = lt;
+ GameHeader.NumMessages = mn;
+ Messages = (const char **)MemAlloc(sizeof(char *)*(mn + 1));
+ GameHeader.TreasureRoom = trm;
+
+ /* Load the actions */
+
+ ct = 0;
+ ap = Actions;
+ if (loud)
+ debug("Reading %d actions.", na);
+ while (ct < na + 1) {
+ readInts(f, 8,
+ &ap->Vocab,
+ &ap->Condition[0],
+ &ap->Condition[1],
+ &ap->Condition[2],
+ &ap->Condition[3],
+ &ap->Condition[4],
+ &ap->action[0],
+ &ap->action[1]);
+ ap++;
+ ct++;
+ }
+
+ ct = 0;
+ if (loud)
+ debug("Reading %d word pairs.", nw);
+ while (ct<nw + 1) {
+ Verbs[ct] = ReadString(f);
+ Nouns[ct] = ReadString(f);
+ ct++;
+ }
+ ct = 0;
+ rp = Rooms;
+ if (loud)
+ debug("Reading %d rooms.", nr);
+ while (ct<nr + 1) {
+ readInts(f, 6,
+ &rp->Exits[0], &rp->Exits[1], &rp->Exits[2],
+ &rp->Exits[3], &rp->Exits[4], &rp->Exits[5]);
+
+ rp->Text = ReadString(f);
+ ct++;
+ rp++;
+ }
+
+ ct = 0;
+ if (loud)
+ debug("Reading %d messages.", mn);
+ while (ct<mn + 1) {
+ Messages[ct] = ReadString(f);
+ ct++;
+ }
+
+ ct = 0;
+ if (loud)
+ debug("Reading %d items.", ni);
+ ip = Items;
+ while (ct < ni + 1) {
+ ip->Text = ReadString(f);
+ ip->AutoGet = strchr(ip->Text, '/');
+ /* Some games use // to mean no auto get/drop word! */
+ if (ip->AutoGet && strcmp(ip->AutoGet, "//") && strcmp(ip->AutoGet, "/*")) {
+ char *t;
+ *ip->AutoGet++ = 0;
+ t = strchr(ip->AutoGet, '/');
+ if (t != nullptr)
+ *t = 0;
+ }
+
+ readInts(f, 1, &lo);
+ ip->Location = (unsigned char)lo;
+ ip->InitialLoc = ip->Location;
+ ip++;
+ ct++;
+ }
+ ct = 0;
+ /* Discard Comment Strings */
+ while (ct<na + 1) {
+ free(ReadString(f));
+ ct++;
+ }
+
+ readInts(f, 1, &ct);
+ if (loud)
+ debug("Version %d.%02d of Adventure ", ct / 100, ct % 100);
+ readInts(f, 1, &ct);
+
+ if (loud)
+ debug("%d.\nLoad Complete.\n", ct);
+}
+
+void Scott::Output(const char *a) {
+ Display(Bottom, "%s", a);
+}
+
+void Scott::OutputNumber(int a) {
+ Display(Bottom, "%d", a);
+}
+
+void Scott::Look(void) {
+ static char *ExitNames[6] = { "North", "South", "East", "West", "Up", "Down" };
+ Room *r;
+ int ct, f;
+ int pos;
+
+ if (split_screen)
+ glk_window_clear(Top);
+
+ if ((BitFlags&(1 << DARKBIT)) && Items[LIGHT_SOURCE].Location != CARRIED
+ && Items[LIGHT_SOURCE].Location != MyLoc) {
+ if (Options&YOUARE)
+ Display(Top, "You can't see. It is too dark!\n");
+ else
+ Display(Top, "I can't see. It is too dark!\n");
+ if (Options & TRS80_STYLE)
+ Display(Top, TRS80_LINE);
+ return;
+ }
+ r = &Rooms[MyLoc];
+ if (*r->Text == '*')
+ Display(Top, "%s\n", r->Text + 1);
+ else {
+ if (Options&YOUARE)
+ Display(Top, "You are in a %s\n", r->Text);
+ else
+ Display(Top, "I'm in a %s\n", r->Text);
+ }
+
+ ct = 0;
+ f = 0;
+ Display(Top, "\nObvious exits: ");
+ while (ct<6) {
+ if (r->Exits[ct] != 0)
+ {
+ if (f == 0)
+ f = 1;
+ else
+ Display(Top, ", ");
+ Display(Top, "%s", ExitNames[ct]);
+ }
+ ct++;
+ }
+
+ if (f == 0)
+ Display(Top, "none");
+ Display(Top, ".\n");
+ ct = 0;
+ f = 0;
+ pos = 0;
+ while (ct <= GameHeader.NumItems) {
+ if (Items[ct].Location == MyLoc) {
+ if (f == 0) {
+ if (Options & YOUARE) {
+ Display(Top, "\nYou can also see: ");
+ pos = 18;
+ } else {
+ Display(Top, "\nI can also see: ");
+ pos = 16;
+ }
+ f++;
+ } else if (!(Options & TRS80_STYLE)) {
+ Display(Top, " - ");
+ pos += 3;
+ }
+ if (pos + (int)strlen(Items[ct].Text) > (Width - 10)) {
+ pos = 0;
+ Display(Top, "\n");
+ }
+ Display(Top, "%s", Items[ct].Text);
+ pos += strlen(Items[ct].Text);
+ if (Options & TRS80_STYLE) {
+ Display(Top, ". ");
+ pos += 2;
+ }
+ }
+ ct++;
+ }
+
+ Display(Top, "\n");
+ if (Options & TRS80_STYLE)
+ Display(Top, TRS80_LINE);
+}
+
+int Scott::WhichWord(const char *word, const char **list) {
+ int n = 1;
+ int ne = 1;
+ const char *tp;
+ while (ne <= GameHeader.NumWords) {
+ tp = list[ne];
+ if (*tp == '*')
+ tp++;
+ else
+ n = ne;
+ if (xstrncasecmp(word, tp, GameHeader.WordLength) == 0)
+ return n;
+ ne++;
+ }
+ return -1;
+}
+
+void Scott::LineInput(char *buf, size_t n) {
+ event_t ev;
+
+ glk_request_line_event(Bottom, buf, n - 1, 0);
+
do {
glk_select(&ev);
- switch (ev.type) {
- default:
- /* do nothing */
+
+ if (ev.type == evtype_LineInput)
break;
- }
+ else if (ev.type == evtype_Arrange && split_screen)
+ Look();
} while (ev.type != evtype_Quit);
+
+ buf[ev.val1] = 0;
+}
+
+void Scott::SaveGame(void) {
+ strid_t file;
+ frefid_t ref;
+ int ct;
+ Common::String msg;
+
+ ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame, filemode_Write, 0);
+ if (ref == nullptr) return;
+
+ file = glk_stream_open_file(ref, filemode_Write, 0);
+ glk_fileref_destroy(ref);
+ if (file == nullptr) return;
+
+ for (ct = 0; ct < 16; ct++) {
+ msg = Common::String::format("%d %d\n", Counters[ct], RoomSaved[ct]);
+ glk_put_string_stream(file, msg.c_str());
+ }
+
+ msg = Common::String::format("%lu %d %hd %d %d %hd\n",
+ BitFlags, (BitFlags&(1 << DARKBIT)) ? 1 : 0,
+ MyLoc, CurrentCounter, SavedRoom, GameHeader.LightTime);
+ glk_put_string_stream(file, msg.c_str());
+
+ for (ct = 0; ct <= GameHeader.NumItems; ct++) {
+ msg = Common::String::format("%hd\n", (short)Items[ct].Location);
+ glk_put_string_stream(file, msg.c_str());
+ }
+
+ glk_stream_close(file, nullptr);
+ Output("Saved.\n");
+}
+
+void Scott::LoadGame(void) {
+ strid_t file;
+ frefid_t ref;
+ char buf[128];
+ int ct = 0;
+ short lo;
+ short DarkFlag;
+
+ ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame, filemode_Read, 0);
+ if (ref == nullptr) return;
+
+ file = glk_stream_open_file(ref, filemode_Read, 0);
+ glk_fileref_destroy(ref);
+ if (file == nullptr) return;
+
+ for (ct = 0; ct<16; ct++) {
+ glk_get_line_stream(file, buf, sizeof buf);
+ sscanf(buf, "%d %d", &Counters[ct], &RoomSaved[ct]);
+ }
+
+ glk_get_line_stream(file, buf, sizeof buf);
+ sscanf(buf, "%ld %hd %d %d %d %d\n",
+ &BitFlags, &DarkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
+ &GameHeader.LightTime);
+
+ /* Backward compatibility */
+ if (DarkFlag)
+ BitFlags |= (1 << 15);
+ for (ct = 0; ct <= GameHeader.NumItems; ct++) {
+ glk_get_line_stream(file, buf, sizeof buf);
+ sscanf(buf, "%hd\n", &lo);
+ Items[ct].Location = (unsigned char)lo;
+ }
+}
+
+int Scott::GetInput(int *vb, int *no) {
+ char buf[256];
+ char verb[10], noun[10];
+ int vc, nc;
+ int num;
+
+ do {
+ do {
+ Output("\nTell me what to do ? ");
+ LineInput(buf, sizeof buf);
+ num = sscanf(buf, "%9s %9s", verb, noun);
+ } while (num == 0 || *buf == '\n');
+
+ if (xstrcasecmp(verb, "restore") == 0) {
+ LoadGame();
+ return -1;
+ }
+ if (num == 1)
+ *noun = 0;
+ if (*noun == 0 && strlen(verb) == 1) {
+ switch (Common::isUpper((unsigned char)*verb) ? tolower((unsigned char)*verb) : *verb) {
+ case 'n':strcpy(verb, "NORTH"); break;
+ case 'e':strcpy(verb, "EAST"); break;
+ case 's':strcpy(verb, "SOUTH"); break;
+ case 'w':strcpy(verb, "WEST"); break;
+ case 'u':strcpy(verb, "UP"); break;
+ case 'd':strcpy(verb, "DOWN"); break;
+ /* Brian Howarth interpreter also supports this */
+ case 'i':strcpy(verb, "INVENTORY"); break;
+ }
+ }
+ nc = WhichWord(verb, Nouns);
+ /* The Scott Adams system has a hack to avoid typing 'go' */
+ if (nc >= 1 && nc <= 6) {
+ vc = 1;
+ } else {
+ vc = WhichWord(verb, Verbs);
+ nc = WhichWord(noun, Nouns);
+ }
+ *vb = vc;
+ *no = nc;
+ if (vc == -1) {
+ Output("You use word(s) I don't know! ");
+ }
+ } while (vc == -1);
+
+ strcpy(NounText, noun); /* Needed by GET/DROP hack */
+ return 0;
+}
+
+int Scott::PerformLine(int ct) {
+ int continuation = 0;
+ int param[5], pptr = 0;
+ int act[4];
+ int cc = 0;
+
+ while (cc<5) {
+ int cv, dv;
+ cv = Actions[ct].Condition[cc];
+ dv = cv / 20;
+ cv %= 20;
+ switch (cv) {
+ case 0:
+ param[pptr++] = dv;
+ break;
+ case 1:
+ if (Items[dv].Location != CARRIED)
+ return 0;
+ break;
+ case 2:
+ if (Items[dv].Location != MyLoc)
+ return 0;
+ break;
+ case 3:
+ if (Items[dv].Location != CARRIED&&
+ Items[dv].Location != MyLoc)
+ return 0;
+ break;
+ case 4:
+ if (MyLoc != dv)
+ return 0;
+ break;
+ case 5:
+ if (Items[dv].Location == MyLoc)
+ return 0;
+ break;
+ case 6:
+ if (Items[dv].Location == CARRIED)
+ return 0;
+ break;
+ case 7:
+ if (MyLoc == dv)
+ return 0;
+ break;
+ case 8:
+ if ((BitFlags&(1 << dv)) == 0)
+ return 0;
+ break;
+ case 9:
+ if (BitFlags&(1 << dv))
+ return 0;
+ break;
+ case 10:
+ if (CountCarried() == 0)
+ return 0;
+ break;
+ case 11:
+ if (CountCarried())
+ return 0;
+ break;
+ case 12:
+ if (Items[dv].Location == CARRIED || Items[dv].Location == MyLoc)
+ return 0;
+ break;
+ case 13:
+ if (Items[dv].Location == 0)
+ return 0;
+ break;
+ case 14:
+ if (Items[dv].Location)
+ return 0;
+ break;
+ case 15:
+ if (CurrentCounter>dv)
+ return 0;
+ break;
+ case 16:
+ if (CurrentCounter <= dv)
+ return 0;
+ break;
+ case 17:
+ if (Items[dv].Location != Items[dv].InitialLoc)
+ return 0;
+ break;
+ case 18:
+ if (Items[dv].Location == Items[dv].InitialLoc)
+ return 0;
+ break;
+ case 19:/* Only seen in Brian Howarth games so far */
+ if (CurrentCounter != dv)
+ return 0;
+ break;
+ }
+ cc++;
+ }
+ /* Actions */
+ act[0] = Actions[ct].action[0];
+ act[2] = Actions[ct].action[1];
+ act[1] = act[0] % 150;
+ act[3] = act[2] % 150;
+ act[0] /= 150;
+ act[2] /= 150;
+ cc = 0;
+ pptr = 0;
+ while (cc<4)
+ {
+ if (act[cc] >= 1 && act[cc] < 52) {
+ Output(Messages[act[cc]]);
+ Output("\n");
+ } else if (act[cc] > 101) {
+ Output(Messages[act[cc] - 50]);
+ Output("\n");
+ }
+ else {
+ switch (act[cc]) {
+ case 0:/* NOP */
+ break;
+ case 52:
+ if (CountCarried() == GameHeader.MaxCarry)
+ {
+ if (Options&YOUARE)
+ Output("You are carrying too much. ");
+ else
+ Output("I've too much to carry! ");
+ break;
+ }
+ Items[param[pptr++]].Location = CARRIED;
+ break;
+ case 53:
+ Items[param[pptr++]].Location = MyLoc;
+ break;
+ case 54:
+ MyLoc = param[pptr++];
+ break;
+ case 55:
+ Items[param[pptr++]].Location = 0;
+ break;
+ case 56:
+ BitFlags |= 1 << DARKBIT;
+ break;
+ case 57:
+ BitFlags &= ~(1 << DARKBIT);
+ break;
+ case 58:
+ BitFlags |= (1 << param[pptr++]);
+ break;
+ case 59:
+ Items[param[pptr++]].Location = 0;
+ break;
+ case 60:
+ BitFlags &= ~(1 << param[pptr++]);
+ break;
+ case 61:
+ if (Options&YOUARE)
+ Output("You are dead.\n");
+ else
+ Output("I am dead.\n");
+ BitFlags &= ~(1 << DARKBIT);
+ MyLoc = GameHeader.NumRooms;/* It seems to be what the code says! */
+ break;
+ case 62:
+ {
+ /* Bug fix for some systems - before it could get parameters wrong */
+ int i = param[pptr++];
+ Items[i].Location = param[pptr++];
+ break;
+ }
+ case 63:
+ doneit: Output("The game is now over.\n");
+ glk_exit();
+ case 64:
+ break;
+ case 65:
+ {
+ int i = 0;
+ int n = 0;
+ while (i <= GameHeader.NumItems)
+ {
+ if (Items[i].Location == GameHeader.TreasureRoom &&
+ *Items[i].Text == '*')
+ n++;
+ i++;
+ }
+ if (Options&YOUARE)
+ Output("You have stored ");
+ else
+ Output("I've stored ");
+ OutputNumber(n);
+ Output(" treasures. On a scale of 0 to 100, that rates ");
+ OutputNumber((n * 100) / GameHeader.Treasures);
+ Output(".\n");
+ if (n == GameHeader.Treasures)
+ {
+ Output("Well done.\n");
+ goto doneit;
+ }
+ break;
+ }
+ case 66:
+ {
+ int i = 0;
+ int f = 0;
+ if (Options&YOUARE)
+ Output("You are carrying:\n");
+ else
+ Output("I'm carrying:\n");
+ while (i <= GameHeader.NumItems)
+ {
+ if (Items[i].Location == CARRIED)
+ {
+ if (f == 1)
+ {
+ if (Options & TRS80_STYLE)
+ Output(". ");
+ else
+ Output(" - ");
+ }
+ f = 1;
+ Output(Items[i].Text);
+ }
+ i++;
+ }
+ if (f == 0)
+ Output("Nothing");
+ Output(".\n");
+ break;
+ }
+ case 67:
+ BitFlags |= (1 << 0);
+ break;
+ case 68:
+ BitFlags &= ~(1 << 0);
+ break;
+ case 69:
+ GameHeader.LightTime = LightRefill;
+ Items[LIGHT_SOURCE].Location = CARRIED;
+ BitFlags &= ~(1 << LIGHTOUTBIT);
+ break;
+ case 70:
+ ClearScreen(); /* pdd. */
+ break;
+ case 71:
+ SaveGame();
+ break;
+ case 72:
+ {
+ int i1 = param[pptr++];
+ int i2 = param[pptr++];
+ int t = Items[i1].Location;
+ Items[i1].Location = Items[i2].Location;
+ Items[i2].Location = t;
+ break;
+ }
+ case 73:
+ continuation = 1;
+ break;
+ case 74:
+ Items[param[pptr++]].Location = CARRIED;
+ break;
+ case 75:
+ {
+ int i1, i2;
+ i1 = param[pptr++];
+ i2 = param[pptr++];
+ Items[i1].Location = Items[i2].Location;
+ break;
+ }
+ case 76: /* Looking at adventure .. */
+ break;
+ case 77:
+ if (CurrentCounter >= 0)
+ CurrentCounter--;
+ break;
+ case 78:
+ OutputNumber(CurrentCounter);
+ break;
+ case 79:
+ CurrentCounter = param[pptr++];
+ break;
+ case 80:
+ {
+ int t = MyLoc;
+ MyLoc = SavedRoom;
+ SavedRoom = t;
+ break;
+ }
+ case 81:
+ {
+ /* This is somewhat guessed. Claymorgue always
+ seems to do select counter n, thing, select counter n,
+ but uses one value that always seems to exist. Trying
+ a few options I found this gave sane results on ageing */
+ int t = param[pptr++];
+ int c1 = CurrentCounter;
+ CurrentCounter = Counters[t];
+ Counters[t] = c1;
+ break;
+ }
+ case 82:
+ CurrentCounter += param[pptr++];
+ break;
+ case 83:
+ CurrentCounter -= param[pptr++];
+ if (CurrentCounter < -1)
+ CurrentCounter = -1;
+ /* Note: This seems to be needed. I don't yet
+ know if there is a maximum value to limit too */
+ break;
+ case 84:
+ Output(NounText);
+ break;
+ case 85:
+ Output(NounText);
+ Output("\n");
+ break;
+ case 86:
+ Output("\n");
+ break;
+ case 87:
+ {
+ /* Changed this to swap location<->roomflag[x]
+ not roomflag 0 and x */
+ int p = param[pptr++];
+ int sr = MyLoc;
+ MyLoc = RoomSaved[p];
+ RoomSaved[p] = sr;
+ break;
+ }
+ case 88:
+ Delay(2);
+ break;
+ case 89:
+ pptr++;
+ /* SAGA draw picture n */
+ /* Spectrum Seas of Blood - start combat ? */
+ /* Poking this into older spectrum games causes a crash */
+ break;
+ default:
+ error("Unknown action %d [Param begins %d %d]\n",
+ act[cc], param[pptr], param[pptr + 1]);
+ break;
+ }
+ }
+
+ cc++;
+ }
+
+ return 1 + continuation;
+}
+
+int Scott::PerformActions(int vb, int no) {
+ static int disable_sysfunc = 0; /* Recursion lock */
+ int d = BitFlags&(1 << DARKBIT);
+
+ int ct = 0;
+ int fl;
+ int doagain = 0;
+ if (vb == 1 && no == -1) {
+ Output("Give me a direction too.");
+ return 0;
+ }
+ if (vb == 1 && no >= 1 && no <= 6) {
+ int nl;
+ if (Items[LIGHT_SOURCE].Location == MyLoc ||
+ Items[LIGHT_SOURCE].Location == CARRIED)
+ d = 0;
+ if (d)
+ Output("Dangerous to move in the dark! ");
+ nl = Rooms[MyLoc].Exits[no - 1];
+ if (nl != 0) {
+ MyLoc = nl;
+ return 0;
+ }
+ if (d) {
+ if (Options&YOUARE)
+ Output("You fell down and broke your neck. ");
+ else
+ Output("I fell down and broke my neck. ");
+ glk_exit();
+ }
+ if (Options&YOUARE)
+ Output("You can't go in that direction. ");
+ else
+ Output("I can't go in that direction. ");
+ return 0;
+ }
+
+ fl = -1;
+ while (ct <= GameHeader.NumActions) {
+ int vv, nv;
+ vv = Actions[ct].Vocab;
+ /* Think this is now right. If a line we run has an action73
+ run all following lines with vocab of 0,0 */
+ if (vb != 0 && (doagain&&vv != 0))
+ break;
+ /* Oops.. added this minor cockup fix 1.11 */
+ if (vb != 0 && !doagain && fl == 0)
+ break;
+ nv = vv % 150;
+ vv /= 150;
+ if ((vv == vb) || (doagain&&Actions[ct].Vocab == 0)) {
+ if ((vv == 0 && RandomPercent(nv)) || doagain ||
+ (vv != 0 && (nv == no || nv == 0))) {
+ int f2;
+ if (fl == -1)
+ fl = -2;
+ if ((f2 = PerformLine(ct)) > 0) {
+ /* ahah finally figured it out ! */
+ fl = 0;
+ if (f2 == 2)
+ doagain = 1;
+ if (vb != 0 && doagain == 0)
+ return 0;
+ }
+ }
+ }
+ ct++;
+
+ /* Previously this did not check ct against
+ * GameHeader.NumActions and would read past the end of
+ * Actions. I don't know what should happen on the last
+ * action, but doing nothing is better than reading one
+ * past the end.
+ * --Chris
+ */
+ if (ct <= GameHeader.NumActions && Actions[ct].Vocab != 0)
+ doagain = 0;
+ }
+ if (fl != 0 && disable_sysfunc == 0) {
+ int item;
+ if (Items[LIGHT_SOURCE].Location == MyLoc ||
+ Items[LIGHT_SOURCE].Location == CARRIED)
+ d = 0;
+ if (vb == 10 || vb == 18) {
+ /* Yes they really _are_ hardcoded values */
+ if (vb == 10) {
+ if (xstrcasecmp(NounText, "ALL") == 0) {
+ int i = 0;
+ int f = 0;
+
+ if (d) {
+ Output("It is dark.\n");
+ return 0;
+ }
+ while (i <= GameHeader.NumItems) {
+ if (Items[i].Location == MyLoc && Items[i].AutoGet != nullptr && Items[i].AutoGet[0] != '*') {
+ no = WhichWord(Items[i].AutoGet, Nouns);
+ disable_sysfunc = 1; /* Don't recurse into auto get ! */
+ PerformActions(vb, no); /* Recursively check each items table code */
+ disable_sysfunc = 0;
+ if (CountCarried() == GameHeader.MaxCarry) {
+ if (Options&YOUARE)
+ Output("You are carrying too much. ");
+ else
+ Output("I've too much to carry. ");
+ return 0;
+ }
+ Items[i].Location = CARRIED;
+ Output(Items[i].Text);
+ Output(": O.K.\n");
+ f = 1;
+ }
+ i++;
+ }
+ if (f == 0)
+ Output("Nothing taken.");
+ return 0;
+ }
+ if (no == -1)
+ {
+ Output("What ? ");
+ return 0;
+ }
+ if (CountCarried() == GameHeader.MaxCarry)
+ {
+ if (Options&YOUARE)
+ Output("You are carrying too much. ");
+ else
+ Output("I've too much to carry. ");
+ return 0;
+ }
+ item = MatchUpItem(NounText, MyLoc);
+ if (item == -1)
+ {
+ if (Options&YOUARE)
+ Output("It is beyond your power to do that. ");
+ else
+ Output("It's beyond my power to do that. ");
+ return 0;
+ }
+ Items[item].Location = CARRIED;
+ Output("O.K. ");
+ return 0;
+ }
+ if (vb == 18) {
+ if (xstrcasecmp(NounText, "ALL") == 0) {
+ int i = 0;
+ int f = 0;
+ while (i <= GameHeader.NumItems) {
+ if (Items[i].Location == CARRIED && Items[i].AutoGet && Items[i].AutoGet[0] != '*') {
+ no = WhichWord(Items[i].AutoGet, Nouns);
+ disable_sysfunc = 1;
+ PerformActions(vb, no);
+ disable_sysfunc = 0;
+ Items[i].Location = MyLoc;
+ Output(Items[i].Text);
+ Output(": O.K.\n");
+ f = 1;
+ }
+ i++;
+ }
+ if (f == 0)
+ Output("Nothing dropped.\n");
+ return 0;
+ }
+ if (no == -1) {
+ Output("What ? ");
+ return 0;
+ }
+ item = MatchUpItem(NounText, CARRIED);
+ if (item == -1) {
+ if (Options&YOUARE)
+ Output("It's beyond your power to do that.\n");
+ else
+ Output("It's beyond my power to do that.\n");
+ return 0;
+ }
+ Items[item].Location = MyLoc;
+ Output("O.K. ");
+ return 0;
+ }
+ }
+ }
+
+ return fl;
+}
+
+int Scott::xstrcasecmp(const char *s1, const char *s2) {
+ const unsigned char
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ while (tolower(*us1) == tolower(*us2++))
+ if (*us1++ == '\0')
+ return (0);
+ return (tolower(*us1) - tolower(*--us2));
+}
+
+int Scott::xstrncasecmp(const char *s1, const char *s2, size_t n) {
+ if (n != 0) {
+ const unsigned char
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ do {
+ if (tolower(*us1) != tolower(*us2++))
+ return (tolower(*us1) - tolower(*--us2));
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+
+ return 0;
+}
+
+void Scott::readInts(Common::SeekableReadStream *f, size_t count, ...) {
+ va_list va;
+ va_start(va, count);
+ unsigned char c = '\0';
+
+ for (size_t idx = 0; idx < count; ++idx) {
+ if (idx > 0) {
+ while (f->pos() < f->size() && Common::isSpace(c))
+ c = f->readByte();
+ } else {
+ c = f->readByte();
+ }
+
+ // Get the next value
+ int *val = (int *)va_arg(va, int);
+ *val = 0;
+ while (Common::isDigit(c)) {
+ *val = (*val * 10) + (c - '0');
+ c = f->readByte();
+ }
+ }
+
+ va_end(va);
}
} // End of namespace Scott
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index 0e7d85c..52ad560 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -45,6 +45,9 @@ namespace Scott {
#define TRS80_STYLE 8 // Display in style used on TRS-80
#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
+#define TRS80_LINE "\n<------------------------------------------------------------>\n"
+#define MyLoc (GameHeader.PlayerRoom)
+
struct Header {
int Unknown;
int NumItems;
@@ -58,17 +61,30 @@ struct Header {
int LightTime;
int NumMessages;
int TreasureRoom;
+
+ Header() : Unknown(0), NumItems(0), NumActions(0), NumWords(0), NumRooms(0),
+ MaxCarry(0), PlayerRoom(0), Treasures(0), WordLength(0), LightTime(0),
+ NumMessages(0), TreasureRoom(0) {}
};
struct Action {
uint Vocab;
uint Condition[5];
uint action[2];
+
+ Action() : Vocab(0) {
+ Common::fill(&Condition[0], &Condition[5], 0);
+ Common::fill(&action[0], &action[2], 0);
+ }
};
struct Room {
char *Text;
short Exits[6];
+
+ Room() : Text(0) {
+ Common::fill(&Exits[0], &Exits[6], 0);
+ }
};
struct Item {
@@ -76,28 +92,84 @@ struct Item {
byte Location;
byte InitialLoc;
char *AutoGet;
+
+ Item() : Text(nullptr), Location(0), InitialLoc(0), AutoGet(nullptr) {}
};
struct Tail {
int Version;
int AdventureNumber;
int Unknown;
+
+ Tail() : Version(0), AdventureNumber(0), Unknown(0) {}
};
/**
* Scott Adams game interpreter
*/
class Scott : public Glk {
+private:
+ Header GameHeader;
+ Item *Items;
+ Room *Rooms;
+ const char **Verbs;
+ const char **Nouns;
+ const char **Messages;
+ Action *Actions;
+ int LightRefill;
+ char NounText[16];
+ int Counters[16]; ///< Range unknown
+ int CurrentCounter;
+ int SavedRoom;
+ int RoomSaved[16]; ///< Range unknown
+ int Options; ///< Option flags set
+ int Width; ///< Terminal width
+ int TopHeight; ///< Height of top window
+
+ bool split_screen;
+ winid_t Bottom, Top;
+ uint32 BitFlags; ///< Might be >32 flags - I haven't seen >32 yet
+private:
+ /**
+ * Initialization code
+ */
+ void initialize();
+
+ void Display(winid_t w, const char *fmt, ...);
+ void Delay(int seconds);
+ void Fatal(const char *x);
+ void ClearScreen(void);
+ void *MemAlloc(int size);
+ bool RandomPercent(uint n);
+ int CountCarried(void);
+ const char *MapSynonym(const char *word);
+ int MatchUpItem(const char *text, int loc);
+ char *ReadString(Common::SeekableReadStream *f);
+ void LoadDatabase(Common::SeekableReadStream *f, int loud);
+ void Output(const char *a);
+ void OutputNumber(int a);
+ void Look(void);
+ int WhichWord(const char *word, const char **list);
+ void LineInput(char *buf, size_t n);
+ void SaveGame(void);
+ void LoadGame(void);
+ int GetInput(int *vb, int *no);
+ int PerformLine(int ct);
+ int PerformActions(int vb, int no);
+
+ int xstrcasecmp(const char *, const char *);
+ int xstrncasecmp(const char *, const char *, size_t);
+ void readInts(Common::SeekableReadStream *f, size_t count, ...);
public:
/**
* Constructor
*/
- Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc) {}
+ Scott(OSystem *syst, const GargoyleGameDescription *gameDesc);
/**
* Execute the game
*/
- virtual void main();
+ virtual void runGame(Common::SeekableReadStream *gameFile) override;
};
} // End of namespace Scott
Commit: 9c6aca1d5790e0c09dca8313e138f4744b4f9130
https://github.com/scummvm/scummvm/commit/9c6aca1d5790e0c09dca8313e138f4744b4f9130
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Minor stream and event loop fixes
Changed paths:
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 02096c6..42a9088 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -211,10 +211,9 @@ void Scott::Delay(int seconds) {
glk_request_timer_events(1000 * seconds);
- do
- {
+ do {
glk_select(&ev);
- } while (ev.type != evtype_Timer);
+ } while (ev.type != evtype_Timer && ev.type != evtype_Quit);
glk_request_timer_events(0);
}
@@ -283,8 +282,7 @@ int Scott::MatchUpItem(const char *text, int loc) {
return -1;
}
-char *Scott::ReadString(Common::SeekableReadStream *f)
-{
+char *Scott::ReadString(Common::SeekableReadStream *f) {
char tmp[1024];
char *t;
int c, nc;
@@ -296,12 +294,12 @@ char *Scott::ReadString(Common::SeekableReadStream *f)
Fatal("Initial quote expected");
}
- do {
- c = f->readByte();
- if (c == EOF)
+ for (;;) {
+ if (f->pos() >= f->size())
Fatal("EOF in string");
- if (c == '"')
- {
+
+ c = f->readByte();
+ if (c == '"') {
nc = f->readByte();
if (nc != '"') {
f->seek(-1, SEEK_CUR);
Commit: db35a9cdc8832ce7768202126842d64a84afc444
https://github.com/scummvm/scummvm/commit/db35a9cdc8832ce7768202126842d64a84afc444
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Adding game detection code
Changed paths:
A engines/gargoyle/scott/detection.cpp
A engines/gargoyle/scott/detection.h
engines/gargoyle/detection.cpp
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 93859e6..f86e34c 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -64,6 +64,7 @@ static const PlainGameDescriptor gargoyleGames[] = {
};
#include "gargoyle/detection_tables.h"
+#include "gargoyle/scott/detection.h"
#include "gargoyle/scott/scott.h"
class GargoyleMetaEngine : public AdvancedMetaEngine {
@@ -80,12 +81,14 @@ public:
return "Gargoyle Engine (c)";
}
- virtual bool hasFeature(MetaEngineFeature f) const;
- virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const override;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
virtual void removeSaveState(const char *target, int slot) const;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+
+ virtual DetectedGames detectGames(const Common::FSList &fslist) const override;
};
bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -133,6 +136,12 @@ SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, i
return SaveStateDescriptor();
}
+DetectedGames GargoyleMetaEngine::detectGames(const Common::FSList &fslist) const {
+ DetectedGames detectedGames;
+ Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
+
+ return detectedGames;
+}
#if PLUGIN_ENABLED_DYNAMIC(GARGOYLE)
REGISTER_PLUGIN_DYNAMIC(Gargoyle, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index c1a2867..7462f7a 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
events.o \
gargoyle.o \
glk.o \
+ scott/detection.o \
scott/scott.o
# This module can be built as a plugin
diff --git a/engines/gargoyle/scott/detection.cpp b/engines/gargoyle/scott/detection.cpp
new file mode 100644
index 0000000..fdf659e
--- /dev/null
+++ b/engines/gargoyle/scott/detection.cpp
@@ -0,0 +1,70 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/scott/detection.h"
+#include "common/file.h"
+#include "common/md5.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+struct ScottGame {
+ const char *_md5;
+ int32 _filesize;
+ const char *_desc;
+};
+
+const ScottGame SCOTT_GAMES[] = {
+ { "ae541fc1085da2f7d561b72ed20a6bc1", 18003, "Adventureland" },
+ { nullptr, 0, nullptr }
+};
+
+void ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
+ Common::File gameFile;
+ Common::String md5;
+
+ // Loop through the files of the folder
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ if (file->isDirectory() || !file->getName().hasSuffix(".saga"))
+ continue;
+
+ if (gameFile.open(*file)) {
+ md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+
+ // Scan through the Scott game list for a match
+ const ScottGame *p = SCOTT_GAMES;
+ while (p->_md5 && p->_filesize != gameFile.size() && md5 != p->_md5)
+ ++p;
+
+ if (p->_filesize) {
+ // Found a match
+ DetectedGame gd("scott", p->_desc, Common::EN_ANY, Common::kPlatformUnknown, "Scott");
+ gameList.push_back(gd);
+ }
+
+ gameFile.close();
+ }
+ }
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/scott/detection.h b/engines/gargoyle/scott/detection.h
new file mode 100644
index 0000000..07f1476
--- /dev/null
+++ b/engines/gargoyle/scott/detection.h
@@ -0,0 +1,40 @@
+/* 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 GARGOYLE_SCOTT_DETECTION
+#define GARGOYLE_SCOTT_DETECTION
+
+#include "common/fs.h"
+#include "engines/game.h"
+
+namespace Gargoyle {
+namespace Scott {
+
+class ScottMetaEngine {
+public:
+ static void detectGames(const Common::FSList &fslist, DetectedGames &gameList);
+};
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
+
+#endif
Commit: ef161922d85a23ea99d9e86417c6ac8b675dc43d
https://github.com/scummvm/scummvm/commit/ef161922d85a23ea99d9e86417c6ac8b675dc43d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
ENGINES: Add optional extra configuration entries when creating new targets
Changed paths:
base/plugins.cpp
engines/game.h
diff --git a/base/plugins.cpp b/base/plugins.cpp
index f6bbeac..f4d18ef 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -580,6 +580,11 @@ Common::String EngineManager::createTargetForGame(const DetectedGame &game) {
addStringToConf("extra", game.extra, domain);
addStringToConf("guioptions", game.getGUIOptions(), domain);
+ // Add any extra configuration keys
+ for (Common::StringMap::iterator i = game._extraConfigEntries.begin();
+ i != game._extraConfigEntries.end(); ++i)
+ addStringToConf((*i)._key, (*i)._value, domain);
+
// TODO: Setting the description field here has the drawback
// that the user does never notice when we upgrade our descriptions.
// It might be nice to leave this field empty, and only set it to
diff --git a/engines/game.h b/engines/game.h
index 14f9962..304166d 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -148,6 +148,21 @@ struct DetectedGame {
*/
GameSupportLevel gameSupportLevel;
+ /**
+ * A list of extra keys to write to the configuration file
+ */
+ Common::StringMap _extraConfigEntries;
+
+ /**
+ * Allows adding of extra entries to be saved as part of the detection entry
+ * in the configuration file.
+ * @remarks Any entry added using this should not be relied on being present
+ * in the configuration file, since starting games directly from the
+ * command line bypasses the game detection code
+ */
+ void addExtraEntry(const Common::String &key, const Common::String &value) {
+ _extraConfigEntries[key] = value;
+ }
private:
/**
* Update the description string by appending (EXTRA/PLATFORM/LANG) to it.
Commit: 5f626f7a6abbcc2ec18cc50df1ce5ba705f967cd
https://github.com/scummvm/scummvm/commit/5f626f7a6abbcc2ec18cc50df1ce5ba705f967cd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add detection logic needed for engine startup
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/scott/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index f86e34c..b7a32a7 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -37,9 +37,13 @@ namespace Gargoyle {
struct GargoyleGameDescription {
ADGameDescription desc;
+ Common::String filename;
InterpreterType interpType;
};
+const Common::String &GargoyleEngine::getFilename() const {
+ return _gameDescription->filename;
+}
uint32 GargoyleEngine::getFeatures() const {
return _gameDescription->desc.flags;
}
@@ -63,6 +67,7 @@ static const PlainGameDescriptor gargoyleGames[] = {
{0, 0}
};
+#include "common/config-manager.h"
#include "gargoyle/detection_tables.h"
#include "gargoyle/scott/detection.h"
#include "gargoyle/scott/scott.h"
@@ -89,6 +94,8 @@ public:
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
virtual DetectedGames detectGames(const Common::FSList &fslist) const override;
+
+ virtual ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override;
};
bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -108,7 +115,9 @@ bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
}
bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
+ Gargoyle::GargoyleGameDescription *gd = (Gargoyle::GargoyleGameDescription *)desc;
+ gd->filename = ConfMan.get("filename");
+
switch (gd->interpType) {
case Gargoyle::INTERPRETER_SCOTT:
*engine = new Gargoyle::Scott::Scott(syst, gd);
@@ -143,6 +152,24 @@ DetectedGames GargoyleMetaEngine::detectGames(const Common::FSList &fslist) cons
return detectedGames;
}
+static Gargoyle::GargoyleGameDescription gameDescription;
+
+ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
+ ADDetectedGames detectedGames;
+ static char gameId[100];
+ strcpy(gameId, ConfMan.get("gameid").c_str());
+
+ gameDescription.desc.gameId = gameId;
+ gameDescription.desc.language = language;
+ gameDescription.desc.platform = platform;
+ gameDescription.desc.extra = extra.c_str();
+ gameDescription.filename = ConfMan.get("filename");
+
+ ADDetectedGame dg((ADGameDescription *)&gameDescription);
+ detectedGames.push_back(dg);
+ return detectedGames;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(GARGOYLE)
REGISTER_PLUGIN_DYNAMIC(Gargoyle, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
#else
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 7953c68..561f14a 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -24,6 +24,7 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
+#include "common/file.h"
#include "engines/util.h"
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
@@ -54,8 +55,10 @@ void GargoyleEngine::initialize() {
Common::Error GargoyleEngine::run() {
initialize();
- // TODO: Pass proper gamefile
- runGame(nullptr);
+ Common::File f;
+ if (!f.open(getFilename()))
+ error("Could not open game file");
+ runGame(&f);
return Common::kNoError;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 37c1a22..3cfee29 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -75,6 +75,10 @@ protected:
// Engine APIs
virtual Common::Error run();
+
+ /**
+ * Returns true whether a given feature is supported by the engine
+ */
virtual bool hasFeature(EngineFeature f) const;
/**
@@ -85,10 +89,30 @@ public:
GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
virtual ~GargoyleEngine();
+ /**
+ * Returns the bitset of game features
+ */
uint32 getFeatures() const;
+
+ /**
+ * Returns whether the game is a demo
+ */
bool isDemo() const;
+
+ /**
+ * Returns the language
+ */
Common::Language getLanguage() const;
+
+ /**
+ * Returns the running interpreter type
+ */
InterpreterType getInterpreterType() const;
+
+ /**
+ * Returns the primary filename for the game
+ */
+ const Common::String &GargoyleEngine::getFilename() const;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/scott/detection.cpp b/engines/gargoyle/scott/detection.cpp
index fdf659e..d2ed439 100644
--- a/engines/gargoyle/scott/detection.cpp
+++ b/engines/gargoyle/scott/detection.cpp
@@ -58,6 +58,8 @@ void ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
if (p->_filesize) {
// Found a match
DetectedGame gd("scott", p->_desc, Common::EN_ANY, Common::kPlatformUnknown, "Scott");
+ gd.addExtraEntry("filename", file->getName());
+
gameList.push_back(gd);
}
Commit: 74080143da579b2db0521ec204a172719c096bc5
https://github.com/scummvm/scummvm/commit/74080143da579b2db0521ec204a172719c096bc5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Detect presence of game file in detectGames
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/gargoyle.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index b7a32a7..63ada3e 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -68,6 +68,7 @@ static const PlainGameDescriptor gargoyleGames[] = {
};
#include "common/config-manager.h"
+#include "common/file.h"
#include "gargoyle/detection_tables.h"
#include "gargoyle/scott/detection.h"
#include "gargoyle/scott/scott.h"
@@ -158,15 +159,19 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
ADDetectedGames detectedGames;
static char gameId[100];
strcpy(gameId, ConfMan.get("gameid").c_str());
+ Common::String filename = ConfMan.get("filename");
- gameDescription.desc.gameId = gameId;
- gameDescription.desc.language = language;
- gameDescription.desc.platform = platform;
- gameDescription.desc.extra = extra.c_str();
- gameDescription.filename = ConfMan.get("filename");
+ if (parent.getChild(filename).exists()) {
+ gameDescription.desc.gameId = gameId;
+ gameDescription.desc.language = language;
+ gameDescription.desc.platform = platform;
+ gameDescription.desc.extra = extra.c_str();
+ gameDescription.filename = filename;
+
+ ADDetectedGame dg((ADGameDescription *)&gameDescription);
+ detectedGames.push_back(dg);
+ }
- ADDetectedGame dg((ADGameDescription *)&gameDescription);
- detectedGames.push_back(dg);
return detectedGames;
}
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 561f14a..5d3d53c 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -56,9 +56,8 @@ Common::Error GargoyleEngine::run() {
initialize();
Common::File f;
- if (!f.open(getFilename()))
- error("Could not open game file");
- runGame(&f);
+ if (f.open(getFilename()))
+ runGame(&f);
return Common::kNoError;
}
Commit: 77f357e72f1f1bfad93b3b1c54f6f57b67131ba7
https://github.com/scummvm/scummvm/commit/77f357e72f1f1bfad93b3b1c54f6f57b67131ba7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add window creation
Changed paths:
A engines/gargoyle/windows.cpp
A engines/gargoyle/windows.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 5d3d53c..5401b2c 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -29,16 +29,20 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/events.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Gargoyle") {
- _screen = nullptr;
+ _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"),
+ _events(nullptr), _screen(nullptr), _windows(nullptr) {
}
GargoyleEngine::~GargoyleEngine() {
+ delete _events;
delete _screen;
+ delete _windows;
}
void GargoyleEngine::initialize() {
@@ -50,6 +54,8 @@ void GargoyleEngine::initialize() {
initGraphics(640, 480, false);
_screen = new Graphics::Screen();
+ _events = new Events();
+ _windows = new Windows(_screen);
}
Common::Error GargoyleEngine::run() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 3cfee29..c7a7b86 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -33,6 +33,9 @@
namespace Gargoyle {
+class Events;
+class Windows;
+
enum InterpreterType {
INTERPRETER_SCOTT
};
@@ -69,7 +72,9 @@ private:
void initialize();
protected:
const GargoyleGameDescription *_gameDescription;
+ Events *_events;
Graphics::Screen *_screen;
+ Windows *_windows;
Common::RandomSource _random;
int _loadSaveSlot;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 82943bd..278faf5 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -21,6 +21,8 @@
*/
#include "gargoyle/glk.h"
+#include "gargoyle/events.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -60,15 +62,12 @@ unsigned char Glk::glk_char_to_upper(unsigned char ch) {
return '\0';
}
-winid_t Glk::glk_window_get_root(void) {
- // TODO
- return nullptr;
+winid_t Glk::glk_window_get_root(void) const {
+ return _windows->getRoot();
}
-winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock) {
- // TODO
- return nullptr;
+winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, glui32 rock) const {
+ return _windows->windowOpen(split, method, size, wintype, rock);
}
void Glk::glk_window_close(winid_t win, stream_result_t *result) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 55cd563..ce21910 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -25,9 +25,11 @@
#include "gargoyle/gargoyle.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
+
/**
* Implements the GLK interface
*/
@@ -57,9 +59,17 @@ public:
unsigned char glk_char_to_lower(unsigned char ch);
unsigned char glk_char_to_upper(unsigned char ch);
- winid_t glk_window_get_root(void);
+ /**
+ * Get the root window of the window hierarchy
+ */
+ winid_t glk_window_get_root(void) const;
+
+ /**
+ * Open a new window
+ */
winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock);
+ glui32 wintype, glui32 rock = 0) const;
+
void glk_window_close(winid_t win, stream_result_t *result);
void glk_window_get_size(winid_t win, glui32 *widthptr,
glui32 *heightptr);
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index a822741..040d666 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -29,6 +29,7 @@ namespace Gargoyle {
typedef uint32 glui32;
typedef int32 glsi32;
+class Window;
/**
* These are the compile-time conditionals that reveal various Glk optional modules.
@@ -48,7 +49,6 @@ typedef int32 glsi32;
* These types are opaque object identifiers. They're pointers to opaque
* C structures, which are defined differently by each library.
*/
-typedef struct glk_window_struct *winid_t;
typedef struct glk_stream_struct *strid_t;
typedef struct glk_fileref_struct *frefid_t;
typedef struct glk_schannel_struct *schanid_t;
@@ -233,7 +233,7 @@ enum ImageAlign {
struct event_struct {
glui32 type;
- winid_t win;
+ Window *win;
glui32 val1, val2;
};
typedef event_struct event_t;
@@ -265,6 +265,11 @@ struct glkdate_struct {
};
typedef glkdate_struct glkdate_t;
+union gidispatch_rock_t {
+ glui32 num;
+ void *ptr;
+};
+
#endif /* GLK_MODULE_DATETIME */
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 7462f7a..4a535af 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
events.o \
gargoyle.o \
glk.o \
+ windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 42a9088..9632408 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -864,6 +864,7 @@ int Scott::PerformLine(int ct) {
case 63:
doneit: Output("The game is now over.\n");
glk_exit();
+ break;
case 64:
break;
case 65:
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
new file mode 100644
index 0000000..ad03ab8
--- /dev/null
+++ b/engines/gargoyle/windows.cpp
@@ -0,0 +1,244 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/windows.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+
+#define MAGIC_WINDOW_NUM (9876)
+
+Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
+ _windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr) {
+}
+
+Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock) {
+ Window *newwin, *oldparent;
+ PairWindow *pairwin;
+ glui32 val;
+
+ _forceRedraw = true;
+
+ if (!_rootWin) {
+ if (splitwin) {
+ warning("window_open: ref must be NULL");
+ return nullptr;
+ }
+
+ /* ignore method and size now */
+ oldparent = NULL;
+ } else {
+ if (!splitwin) {
+ warning("window_open: ref must not be NULL");
+ return nullptr;
+ }
+
+ val = (method & winmethod_DivisionMask);
+ if (val != winmethod_Fixed && val != winmethod_Proportional)
+ {
+ warning("window_open: invalid method (not fixed or proportional)");
+ return nullptr;
+ }
+
+ val = (method & winmethod_DirMask);
+ if (val != winmethod_Above && val != winmethod_Below
+ && val != winmethod_Left && val != winmethod_Right)
+ {
+ warning("window_open: invalid method (bad direction)");
+ return nullptr;
+ }
+
+ oldparent = splitwin->parent;
+ if (oldparent && oldparent->_type != wintype_Pair)
+ {
+ warning("window_open: parent window is not Pair");
+ return nullptr;
+ }
+ }
+
+ assert(wintype != wintype_Pair);
+ newwin = newWindow(wintype, rock);
+ if (!newwin) {
+ warning("window_open: unable to create window");
+ return nullptr;
+ }
+
+ if (!splitwin) {
+ _rootWin = newwin;
+ } else {
+ // create pairwin, with newwin as the key
+ pairwin = new PairWindow(method, newwin, size);
+ pairwin->child1 = splitwin;
+ pairwin->child2 = newwin;
+
+ splitwin->parent = pairwin;
+ newwin->parent = pairwin;
+ pairwin->parent = oldparent;
+
+ if (oldparent) {
+ PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
+ assert(parentWin);
+ if (parentWin->child1 == splitwin)
+ parentWin->child1 = pairwin;
+ else
+ parentWin->child2 = pairwin;
+ } else {
+ _rootWin = pairwin;
+ }
+ }
+
+ rearrange();
+
+ return newwin;
+}
+
+Window *Windows::newWindow(glui32 type, glui32 rock) {
+ Window *win;
+
+ switch (type) {
+ case wintype_Blank:
+ win = new BlankWindow(rock);
+ break;
+ case wintype_TextGrid:
+ win = new TextGridWindow(rock);
+ break;
+ case wintype_TextBuffer:
+ win = new TextBufferWindow(rock);
+ break;
+ case wintype_Graphics:
+ win = new GraphicsWindow(rock);
+ break;
+ case wintype_Pair:
+ error("Pair windows cannot be created directly");
+ default:
+ error("Unknown window type");
+ }
+
+ win->next = _windowList;
+ _windowList = win;
+ if (win->next)
+ win->next->prev = win;
+
+ return win;
+}
+
+PairWindow *Windows::newPairWindow(glui32 method, Window *key, glui32 size) {
+ PairWindow *pwin = new PairWindow(method, key, size);
+ pwin->next = _windowList;
+ _windowList = pwin;
+ if (pwin->next)
+ pwin->next->prev = pwin;
+
+ return pwin;
+}
+
+void Windows::rearrange() {
+ // TODO
+ /*
+ if (_rootWin) {
+ rect_t box;
+
+ if (gli_conf_lockcols) {
+ int desired_width = gli_wmarginx_save * 2 + gli_cellw * gli_cols;
+ if (desired_width > gli_image_w)
+ gli_wmarginx = gli_wmarginx_save;
+ else
+ gli_wmarginx = (gli_image_w - gli_cellw * gli_cols) / 2;
+ }
+
+ if (gli_conf_lockrows)
+ {
+ int desired_height = gli_wmarginy_save * 2 + gli_cellh * gli_rows;
+ if (desired_height > gli_image_h)
+ gli_wmarginy = gli_wmarginy_save;
+ else
+ gli_wmarginy = (gli_image_h - gli_cellh * gli_rows) / 2;
+ }
+
+ box.x0 = gli_wmarginx;
+ box.y0 = gli_wmarginy;
+ box.x1 = gli_image_w - gli_wmarginx;
+ box.y1 = gli_image_h - gli_wmarginy;
+ gli_window_rearrange(_rootWin, &box);
+ }
+ */
+}
+
+/*--------------------------------------------------------------------------*/
+
+Window::Window(glui32 rock) : _magicnum(MAGIC_WINDOW_NUM), _rock(rock), _type(0),
+ parent(nullptr), next(nullptr), prev(nullptr),
+ yadj(0), line_request(0), line_request_uni(0), char_request(0), char_request_uni(0),
+ mouse_request(0), hyper_request(0), more_request(0), scroll_request(0), image_loaded(0),
+ echo_line_input(true), line_terminators(nullptr), termct(0), str(nullptr), echostr(nullptr) {
+ attr.fgset = 0;
+ attr.bgset = 0;
+ attr.reverse = 0;
+ attr.style = 0;
+ attr.fgcolor = 0;
+ attr.bgcolor = 0;
+ attr.hyper = 0;
+
+ Common::fill(&bgcolor[0], &bgcolor[3], 3);
+ Common::fill(&fgcolor[0], &fgcolor[3], 3);
+ disprock.num = 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+BlankWindow::BlankWindow(uint32 rock) : Window(rock) {
+ _type = wintype_Blank;
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextGridWindow::TextGridWindow(uint32 rock) : Window(rock) {
+ _type = wintype_TextGrid;
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextBufferWindow::TextBufferWindow(uint32 rock) : Window(rock) {
+ _type = wintype_TextBuffer;
+}
+
+/*--------------------------------------------------------------------------*/
+
+GraphicsWindow::GraphicsWindow(uint32 rock) : Window(rock) {
+ _type = wintype_Graphics;
+}
+
+/*--------------------------------------------------------------------------*/
+
+PairWindow::PairWindow(glui32 method, Window *_key, glui32 _size) : Window(0),
+ dir(method & winmethod_DirMask),
+ division(method & winmethod_DivisionMask),
+ wborder((method & winmethod_BorderMask) == winmethod_Border),
+ vertical(dir == winmethod_Left || dir == winmethod_Right),
+ backward(dir == winmethod_Left || dir == winmethod_Above),
+ key(key), size(size), keydamage(0), child1(nullptr), child2(nullptr) {
+ _type = wintype_Pair;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
new file mode 100644
index 0000000..91cbc91
--- /dev/null
+++ b/engines/gargoyle/windows.h
@@ -0,0 +1,223 @@
+/* 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 GARGOYLE_WINDOWS_H
+#define GARGOYLE_WINDOWS_H
+
+#include "common/list.h"
+#include "common/rect.h"
+#include "common/stream.h"
+#include "graphics/screen.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+class Window;
+class PairWindow;
+
+class Windows {
+private:
+ Graphics::Screen *_screen;
+ Window * _windowList; ///< List of all windows
+ Window *_rootWin; ///< The topmost window
+ Window *_focusWin; ///< The window selected by the player
+ bool _forceRedraw;
+ bool _moreFocus;
+private:
+ /**
+ * Create a new window
+ */
+ Window *newWindow(glui32 type, glui32 rock);
+
+ /**
+ * Create a new pair window
+ */
+ PairWindow *newPairWindow(glui32 method, Window *key, glui32 size);
+
+ /**
+ * Rearrange windows
+ */
+ void rearrange();
+public:
+ /**
+ * Constructor
+ */
+ Windows(Graphics::Screen *screen);
+
+ /**
+ * Open a new window
+ */
+ Window *windowOpen(Window *splitwin, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock);
+
+ /**
+ * Return the root window
+ */
+ Window *getRoot() const { return _rootWin; }
+};
+
+/**
+ * Window attributes
+ */
+struct attr_t {
+ unsigned fgset : 1;
+ unsigned bgset : 1;
+ unsigned reverse : 1;
+ unsigned : 1;
+ unsigned style : 4;
+ unsigned fgcolor : 24;
+ unsigned bgcolor : 24;
+ unsigned hyper : 32;
+};
+
+struct WindowPair {
+ Window *owner;
+ Window *child1, *child2;
+
+ // split info...
+ glui32 dir; ///< winmethod_Left, Right, Above, or Below
+ int vertical, backward; ///< flags
+ glui32 division; ///< winmethod_Fixed or winmethod_Proportional
+ Window *key; ///< NULL or a leaf-descendant (not a Pair)
+ int keydamage; ///< used as scratch space in window closing
+ glui32 size; ///< size value
+ glui32 wborder; ///< winMethod_Border, NoBorder
+};
+
+/**
+ * Window definition
+ */
+class Window {
+public:
+ glui32 _magicnum;
+ glui32 _rock;
+ glui32 _type;
+
+ Window *parent; ///< pair window which contains this one
+ Common::Rect bbox;
+ int yadj;
+
+ Common::WriteStream *str; ///< the window stream.
+ Common::WriteStream *echostr; ///< the window's echo stream, if any.
+
+ int line_request;
+ int line_request_uni;
+ int char_request;
+ int char_request_uni;
+ int mouse_request;
+ int hyper_request;
+ int more_request;
+ int scroll_request;
+ int image_loaded;
+
+ glui32 echo_line_input;
+ glui32 *line_terminators;
+ glui32 termct;
+
+ attr_t attr;
+ byte bgcolor[3];
+ byte fgcolor[3];
+
+ gidispatch_rock_t disprock;
+ Window *next, *prev; ///< in the big linked list of windows
+public:
+ /**
+ * Constructor
+ */
+ Window(uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~Window() {}
+};
+typedef Window *winid_t;
+
+/**
+ * Blank window
+ */
+class BlankWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ BlankWindow(uint32 rock);
+};
+
+/**
+ * Text Grid window
+ */
+class TextGridWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ TextGridWindow(uint32 rock);
+};
+
+/**
+ * Text Buffer window
+ */
+class TextBufferWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ TextBufferWindow(uint32 rock);
+};
+
+/**
+ * Graphics window
+ */
+class GraphicsWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ GraphicsWindow(uint32 rock);
+};
+
+/**
+ * Pair window
+ */
+class PairWindow : public Window {
+public:
+ Window *child1, *child2;
+
+ /* split info... */
+ glui32 dir; ///< winmethod_Left, Right, Above, or Below
+ int vertical, backward; ///< flags
+ glui32 division; ///< winmethod_Fixed or winmethod_Proportional
+ Window *key; ///< NULL or a leaf-descendant (not a Pair)
+ int keydamage; ///< used as scratch space in window closing
+ glui32 size; ///< size value
+ glui32 wborder; ///< winMethod_Border, NoBorder
+public:
+ /**
+ * Constructor
+ */
+ PairWindow(glui32 method, Window *_key, glui32 _size);
+};
+
+} // End of namespace Gargoyle
+
+#endif
Commit: 47a7a1d4e2640b3b34e2091be606b26723990efb
https://github.com/scummvm/scummvm/commit/47a7a1d4e2640b3b34e2091be606b26723990efb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added setup of text grid windows
Changed paths:
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index ad03ab8..25af90b 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -28,8 +28,47 @@ namespace Gargoyle {
#define MAGIC_WINDOW_NUM (9876)
+bool Windows::_confLockCols;
+bool Windows::_confLockRows;
+int Windows::_wMarginx;
+int Windows::_wMarginy;
+int Windows::_wPaddingx;
+int Windows::_wPaddingy;
+int Windows::_wBorderx;
+int Windows::_wBordery;
+int Windows::_tMarginx;
+int Windows::_tMarginy;
+int Windows::_wMarginXsave;
+int Windows::_wMarginYsave;
+int Windows::_cols;
+int Windows::_rows;
+int Windows::_imageW;
+int Windows::_imageH;
+int Windows::_cellW;
+int Windows::_cellH;
+int Windows::_baseLine;
+int Windows::_leading;
+
Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
_windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr) {
+ _confLockCols = false;
+ _confLockRows = false;
+ _wMarginx = 15;
+ _wMarginy = 15;
+ _wPaddingx = 0;
+ _wPaddingy = 0;
+ _wBorderx = 1;
+ _wBordery = 1;
+ _tMarginx = 7;
+ _tMarginy = 7;
+ _wMarginXsave = 15;
+ _wMarginYsave = 15;
+ _cols = 60;
+ _rows = 25;
+ _imageW = _imageH = 0;
+ _cellW = _cellH = 0;
+ _baseLine = 15;
+ _leading = 20;
}
Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
@@ -154,35 +193,32 @@ PairWindow *Windows::newPairWindow(glui32 method, Window *key, glui32 size) {
}
void Windows::rearrange() {
- // TODO
- /*
if (_rootWin) {
- rect_t box;
+ Common::Rect box;
- if (gli_conf_lockcols) {
- int desired_width = gli_wmarginx_save * 2 + gli_cellw * gli_cols;
- if (desired_width > gli_image_w)
- gli_wmarginx = gli_wmarginx_save;
+ if (_confLockCols) {
+ int desired_width = _wMarginXsave * 2 + _cellW * _cols;
+ if (desired_width > _imageW)
+ _wMarginx = _wMarginXsave;
else
- gli_wmarginx = (gli_image_w - gli_cellw * gli_cols) / 2;
+ _wMarginx = (_imageW - _cellW * _cols) / 2;
}
- if (gli_conf_lockrows)
- {
- int desired_height = gli_wmarginy_save * 2 + gli_cellh * gli_rows;
- if (desired_height > gli_image_h)
- gli_wmarginy = gli_wmarginy_save;
+ if (_confLockRows) {
+ int desired_height = _wMarginYsave * 2 + _cellH * _rows;
+ if (desired_height > _imageH)
+ _wMarginy = _wMarginYsave;
else
- gli_wmarginy = (gli_image_h - gli_cellh * gli_rows) / 2;
+ _wMarginy = (_imageH - _cellH * _rows) / 2;
}
- box.x0 = gli_wmarginx;
- box.y0 = gli_wmarginy;
- box.x1 = gli_image_w - gli_wmarginx;
- box.y1 = gli_image_h - gli_wmarginy;
- gli_window_rearrange(_rootWin, &box);
+ box.left = _wMarginx;
+ box.top = _wMarginy;
+ box.right = _imageW - _wMarginx;
+ box.bottom = _imageH - _wMarginy;
+
+ _rootWin->rearrange(box);
}
- */
}
/*--------------------------------------------------------------------------*/
@@ -215,6 +251,50 @@ BlankWindow::BlankWindow(uint32 rock) : Window(rock) {
TextGridWindow::TextGridWindow(uint32 rock) : Window(rock) {
_type = wintype_TextGrid;
+ width = height = 0;
+ curx = cury = 0;
+ inbuf = nullptr;
+ inorgx = inorgy = 0;
+ inmax = 0;
+ incurs = inlen = 0;
+ inarrayrock.num = 0;
+ line_terminators = nullptr;
+}
+
+void TextGridWindow::rearrange(const Common::Rect &box) {
+ Window::rearrange(box);
+ int newwid, newhgt;
+
+ newwid = box.width() / Windows::_cellW;
+ newhgt = box.height() / Windows::_cellH;
+
+ if (newwid == width && newhgt == height)
+ return;
+
+ lines.resize(newhgt);
+ for (int y = 0; y < newhgt; ++y) {
+ lines[y].resize(newwid);
+ touch(y);
+ }
+
+ attr.clear();
+ width = newwid;
+ height = newhgt;
+}
+
+void TextGridWindow::touch(int line) {
+// int y = bbox.top + line * Windows::_leading;
+ lines[line].dirty = true;
+ // TODO
+// winrepaint(bbox.left, y, bbox.right, y + Windows::_leading);
+}
+
+void TextGridWindow::TextGridRow::resize(size_t newSize) {
+ chars.clear();
+ attr.clear();
+ chars.resize(newSize);
+ attr.resize(newSize);
+ Common::fill(&chars[0], &chars[0] + newSize, ' ');
}
/*--------------------------------------------------------------------------*/
@@ -241,4 +321,23 @@ PairWindow::PairWindow(glui32 method, Window *_key, glui32 _size) : Window(0),
_type = wintype_Pair;
}
+/*--------------------------------------------------------------------------*/
+
+WindowStyle::WindowStyle() : font(0), reverse(0) {
+ Common::fill(&bg[0], &bg[3], 0);
+ Common::fill(&fg[0], &fg[3], 0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Attributes::clear() {
+ fgset = 0;
+ bgset = 0;
+ fgcolor = 0;
+ bgcolor = 0;
+ reverse = false;
+ hyper = 0;
+ style = 0;
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 91cbc91..45907a8 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -23,6 +23,7 @@
#ifndef GARGOYLE_WINDOWS_H
#define GARGOYLE_WINDOWS_H
+#include "common/array.h"
#include "common/list.h"
#include "common/rect.h"
#include "common/stream.h"
@@ -58,6 +59,24 @@ private:
*/
void rearrange();
public:
+ static bool _confLockCols, _confLockRows;
+ static int _wMarginx;
+ static int _wMarginy;
+ static int _wPaddingx;
+ static int _wPaddingy;
+ static int _wBorderx;
+ static int _wBordery;
+ static int _tMarginx;
+ static int _tMarginy;
+ static int _wMarginXsave;
+ static int _wMarginYsave;
+ static int _cols;
+ static int _rows;
+ static int _imageW, _imageH;
+ static int _cellW, _cellH;
+ static int _baseLine;
+ static int _leading;
+public:
/**
* Constructor
*/
@@ -76,9 +95,21 @@ public:
};
/**
+ * Window styles
+ */
+struct WindowStyle {
+ int font;
+ byte bg[3];
+ byte fg[3];
+ int reverse;
+
+ WindowStyle();
+};
+
+/**
* Window attributes
*/
-struct attr_t {
+struct Attributes {
unsigned fgset : 1;
unsigned bgset : 1;
unsigned reverse : 1;
@@ -87,20 +118,18 @@ struct attr_t {
unsigned fgcolor : 24;
unsigned bgcolor : 24;
unsigned hyper : 32;
-};
-struct WindowPair {
- Window *owner;
- Window *child1, *child2;
+ /**
+ * Constructor
+ */
+ Attributes() {
+ clear();
+ }
- // split info...
- glui32 dir; ///< winmethod_Left, Right, Above, or Below
- int vertical, backward; ///< flags
- glui32 division; ///< winmethod_Fixed or winmethod_Proportional
- Window *key; ///< NULL or a leaf-descendant (not a Pair)
- int keydamage; ///< used as scratch space in window closing
- glui32 size; ///< size value
- glui32 wborder; ///< winMethod_Border, NoBorder
+ /**
+ * Clear
+ */
+ void clear();
};
/**
@@ -133,7 +162,7 @@ public:
glui32 *line_terminators;
glui32 termct;
- attr_t attr;
+ Attributes attr;
byte bgcolor[3];
byte fgcolor[3];
@@ -149,6 +178,11 @@ public:
* Destructor
*/
virtual ~Window() {}
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) { bbox = box; }
};
typedef Window *winid_t;
@@ -167,11 +201,56 @@ public:
* Text Grid window
*/
class TextGridWindow : public Window {
+ /**
+ * Structure for a row within the grid window
+ */
+ struct TextGridRow {
+ Common::Array<uint32> chars;
+ Common::Array<Attributes> attr;
+ bool dirty;
+
+ /**
+ * Constructor
+ */
+ TextGridRow() : dirty(false) {}
+
+ /**
+ * Resize the row
+ */
+ void resize(size_t newSize);
+ };
+ typedef Common::Array<TextGridRow> TextGridRows;
+private:
+ /**
+ * Mark a given text row as modified
+ */
+ void touch(int line);
+public:
+ int width, height;
+ TextGridRows lines;
+
+ int curx, cury; ///< the window cursor position
+
+ ///< for line input
+ void *inbuf; ///< unsigned char* for latin1, glui32* for unicode
+ int inorgx, inorgy;
+ int inmax;
+ int incurs, inlen;
+ Attributes origattr;
+ gidispatch_rock_t inarrayrock;
+ glui32 *line_terminators;
+
+ WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
public:
/**
* Constructor
*/
TextGridWindow(uint32 rock);
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box);
};
/**
Commit: 89102c42cac1bd2367a6322f07286452bab21e11
https://github.com/scummvm/scummvm/commit/89102c42cac1bd2367a6322f07286452bab21e11
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Window setup for text buffer windows
Changed paths:
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 040d666..82f70e3 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -219,6 +219,10 @@ enum StyleHint {
stylehint_just_RightFlush = 3,
};
+enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
+enum TYPES { MONOF, PROPF };
+enum STYLES { FONTR, FONTB, FONTI, FONTZ };
+
#ifdef GLK_MODULE_IMAGE
enum ImageAlign {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 4a535af..e5542a7 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
events.o \
gargoyle.o \
glk.o \
+ picture.o \
windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 25af90b..194002b 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -27,6 +27,7 @@
namespace Gargoyle {
#define MAGIC_WINDOW_NUM (9876)
+#define GLI_SUBPIX 8
bool Windows::_confLockCols;
bool Windows::_confLockRows;
@@ -48,9 +49,47 @@ int Windows::_cellW;
int Windows::_cellH;
int Windows::_baseLine;
int Windows::_leading;
+int Windows::_scrollWidth;
+bool Windows::_overrideReverse;
+bool Windows::_overrideFgSet;
+bool Windows::_overrideBgSet;
+int Windows::_overrideFgVal;
+int Windows::_overrideBgVal;
+
+
+WindowStyle T_STYLES[style_NUMSTYLES] = {
+ { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
+ { PROPI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
+ { PROPZ,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
+ { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
+ { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User1
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User2
+};
+
+WindowStyle G_STYLES[style_NUMSTYLES] = {
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
+ { MONOI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
+ { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
+ { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
+ { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User1
+ { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User2
+};
+
+/*--------------------------------------------------------------------------*/
Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
- _windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr) {
+ _windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr),
+ _claimSelect(0) {
_confLockCols = false;
_confLockRows = false;
_wMarginx = 15;
@@ -69,6 +108,12 @@ Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true)
_cellW = _cellH = 0;
_baseLine = 15;
_leading = 20;
+ _scrollWidth = 0;
+ _overrideReverse = false;
+ _overrideFgSet = false;
+ _overrideBgSet = false;
+ _overrideFgVal = 0;
+ _overrideBgVal = 0;
}
Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
@@ -127,7 +172,7 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
_rootWin = newwin;
} else {
// create pairwin, with newwin as the key
- pairwin = new PairWindow(method, newwin, size);
+ pairwin = newPairWindow(method, newwin, size);
pairwin->child1 = splitwin;
pairwin->child2 = newwin;
@@ -157,16 +202,16 @@ Window *Windows::newWindow(glui32 type, glui32 rock) {
switch (type) {
case wintype_Blank:
- win = new BlankWindow(rock);
+ win = new BlankWindow(this, rock);
break;
case wintype_TextGrid:
- win = new TextGridWindow(rock);
+ win = new TextGridWindow(this, rock);
break;
case wintype_TextBuffer:
- win = new TextBufferWindow(rock);
+ win = new TextBufferWindow(this, rock);
break;
case wintype_Graphics:
- win = new GraphicsWindow(rock);
+ win = new GraphicsWindow(this, rock);
break;
case wintype_Pair:
error("Pair windows cannot be created directly");
@@ -183,7 +228,7 @@ Window *Windows::newWindow(glui32 type, glui32 rock) {
}
PairWindow *Windows::newPairWindow(glui32 method, Window *key, glui32 size) {
- PairWindow *pwin = new PairWindow(method, key, size);
+ PairWindow *pwin = new PairWindow(this, method, key, size);
pwin->next = _windowList;
_windowList = pwin;
if (pwin->next)
@@ -221,10 +266,24 @@ void Windows::rearrange() {
}
}
+void Windows::clearSelection() {
+ if (!_mask) {
+ warning("clear_selection: mask not initialized");
+ return;
+ }
+
+ if (_mask->select.left || _mask->select.right
+ || _mask->select.top || _mask->select.bottom)
+ _forceRedraw = true;
+
+ _mask->select = Common::Rect();
+ _claimSelect = false;
+}
+
/*--------------------------------------------------------------------------*/
-Window::Window(glui32 rock) : _magicnum(MAGIC_WINDOW_NUM), _rock(rock), _type(0),
- parent(nullptr), next(nullptr), prev(nullptr),
+Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
+ _windows(windows), _rock(rock), _type(0), parent(nullptr), next(nullptr), prev(nullptr),
yadj(0), line_request(0), line_request_uni(0), char_request(0), char_request_uni(0),
mouse_request(0), hyper_request(0), more_request(0), scroll_request(0), image_loaded(0),
echo_line_input(true), line_terminators(nullptr), termct(0), str(nullptr), echostr(nullptr) {
@@ -243,13 +302,13 @@ Window::Window(glui32 rock) : _magicnum(MAGIC_WINDOW_NUM), _rock(rock), _type(0)
/*--------------------------------------------------------------------------*/
-BlankWindow::BlankWindow(uint32 rock) : Window(rock) {
+BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
_type = wintype_Blank;
}
/*--------------------------------------------------------------------------*/
-TextGridWindow::TextGridWindow(uint32 rock) : Window(rock) {
+TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
_type = wintype_TextGrid;
width = height = 0;
curx = cury = 0;
@@ -259,6 +318,8 @@ TextGridWindow::TextGridWindow(uint32 rock) : Window(rock) {
incurs = inlen = 0;
inarrayrock.num = 0;
line_terminators = nullptr;
+
+ Common::copy(&G_STYLES[0], &G_STYLES[style_NUMSTYLES], styles);
}
void TextGridWindow::rearrange(const Common::Rect &box) {
@@ -289,6 +350,8 @@ void TextGridWindow::touch(int line) {
// winrepaint(bbox.left, y, bbox.right, y + Windows::_leading);
}
+/*--------------------------------------------------------------------------*/
+
void TextGridWindow::TextGridRow::resize(size_t newSize) {
chars.clear();
attr.clear();
@@ -299,19 +362,452 @@ void TextGridWindow::TextGridRow::resize(size_t newSize) {
/*--------------------------------------------------------------------------*/
-TextBufferWindow::TextBufferWindow(uint32 rock) : Window(rock) {
+TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
+ historypos(0), historyfirst(0), historypresent(0), lastseen(0), scrollpos(0),
+ scrollmax(0), scrollback(SCROLLBACK), width(-1), height(-1), inbuf(nullptr),
+ line_terminators(nullptr), echo_line_input(true), ladjw(0), radjw(0), ladjn(0),
+ radjn(0), numchars(0), chars(nullptr), attrs(nullptr),
+ spaced(0), dashed(0), copybuf(0), copypos(0) {
_type = wintype_TextBuffer;
+ Common::fill(&history[0], &history[HISTORYLEN], nullptr);
+
+ Common::copy(&T_STYLES[0], &T_STYLES[style_NUMSTYLES], styles);
+}
+
+void TextBufferWindow::rearrange(const Common::Rect &box) {
+ Window::rearrange(box);
+ int newwid, newhgt;
+ int rnd;
+
+ newwid = (box.width() - Windows::_tMarginx * 2 - Windows::_scrollWidth) / Windows::_cellW;
+ newhgt = (box.height() - Windows::_tMarginy * 2) / Windows::_cellH;
+
+ /* align text with bottom */
+ rnd = newhgt * Windows::_cellH + Windows::_tMarginy * 2;
+ yadj = (box.height() - rnd);
+ bbox.top += (box.height() - rnd);
+
+ if (newwid != width) {
+ width = newwid;
+ reflow();
+ }
+
+ if (newhgt != height) {
+ /* scroll up if we obscure new lines */
+ if (lastseen >= newhgt - 1)
+ scrollpos += (height - newhgt);
+
+ height = newhgt;
+
+ /* keep window within 'valid' lines */
+ if (scrollpos > scrollmax - height + 1)
+ scrollpos = scrollmax - height + 1;
+ if (scrollpos < 0)
+ scrollpos = 0;
+ touchScroll();
+
+ /* allocate copy buffer */
+ if (copybuf)
+ delete[] copybuf;
+ copybuf = new glui32[height * TBLINELEN];
+
+ for (int i = 0; i < (height * TBLINELEN); i++)
+ copybuf[i] = 0;
+
+ copypos = 0;
+ }
+}
+
+void TextBufferWindow::reflow() {
+ int inputbyte = -1;
+ Attributes curattr, oldattr;
+ int i, k, p, s;
+ int x;
+
+ if (height < 4 || width < 20)
+ return;
+
+ lines[0].len = numchars;
+
+ /* allocate temp buffers */
+ Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
+ glui32 *charbuf = new glui32[SCROLLBACK * TBLINELEN];
+ int *alignbuf = new int[SCROLLBACK];
+ Picture **pictbuf = new Picture *[SCROLLBACK];
+ glui32 *hyperbuf = new glui32[SCROLLBACK];
+ int *offsetbuf = new int[SCROLLBACK];
+
+ if (!attrbuf || !charbuf || !alignbuf || !pictbuf || !hyperbuf || !offsetbuf) {
+ delete[] attrbuf;
+ delete[] charbuf;
+ delete[] alignbuf;
+ delete[] pictbuf;
+ delete[] hyperbuf;
+ delete[] offsetbuf;
+ return;
+ }
+
+ /* copy text to temp buffers */
+
+ oldattr = attr;
+ curattr.clear();
+
+ x = 0;
+ p = 0;
+ s = scrollmax < SCROLLBACK ? scrollmax : SCROLLBACK - 1;
+
+ for (k = s; k >= 0; k--) {
+ if (k == 0 && line_request)
+ inputbyte = p + infence;
+
+ if (lines[k].lpic) {
+ offsetbuf[x] = p;
+ alignbuf[x] = imagealign_MarginLeft;
+ pictbuf[x] = lines[k].lpic;
+
+ if (pictbuf[x]) pictbuf[x]->increment();
+ hyperbuf[x] = lines[k].lhyper;
+ x++;
+ }
+
+ if (lines[k].rpic) {
+ offsetbuf[x] = p;
+ alignbuf[x] = imagealign_MarginRight;
+ pictbuf[x] = lines[k].rpic;
+ if (pictbuf[x]) pictbuf[x]->increment();
+ hyperbuf[x] = lines[k].rhyper;
+ x++;
+ }
+
+ for (i = 0; i < lines[k].len; i++) {
+ attrbuf[p] = curattr = lines[k].attr[i];
+ charbuf[p] = lines[k].chars[i];
+ p++;
+ }
+
+ if (lines[k].newline) {
+ attrbuf[p] = curattr;
+ charbuf[p] = '\n';
+ p++;
+ }
+ }
+
+ offsetbuf[x] = -1;
+
+ /* clear window */
+
+ clear();
+
+ /* and dump text back */
+
+ x = 0;
+ for (i = 0; i < p; i++) {
+ if (i == inputbyte)
+ break;
+ attr = attrbuf[i];
+
+ if (offsetbuf[x] == i) {
+ putPicture(pictbuf[x], alignbuf[x], hyperbuf[x]);
+ x++;
+ }
+
+ putCharUni(charbuf[i]);
+ }
+
+ /* terribly sorry about this... */
+ lastseen = 0;
+ scrollpos = 0;
+
+ if (inputbyte != -1) {
+ infence = numchars;
+ putTextUnit(charbuf + inputbyte, p - inputbyte, numchars, 0);
+ incurs = numchars;
+ }
+
+ // free temp buffers
+ delete[] attrbuf;
+ delete[] charbuf;
+ delete[] alignbuf;
+ delete[] pictbuf;
+ delete[] hyperbuf;
+ delete[] offsetbuf;
+
+ attr = oldattr;
+
+ touchScroll();
+}
+
+void TextBufferWindow::touchScroll() {
+ _windows->clearSelection();
+
+ // TODO
+ //winrepaint(win->bbox.left, win->bbox.top, win->bbox.right, win->bbox.bottom);
+ for (int i = 0; i < scrollmax; i++)
+ lines[i].dirty = true;
+}
+
+void TextBufferWindow::clear() {
+ int i;
+
+ attr.fgset = Windows::_overrideFgSet;
+ attr.bgset = Windows::_overrideBgSet;
+ attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ attr.reverse = false;
+
+ ladjw = radjw = 0;
+ ladjn = radjn = 0;
+
+ spaced = 0;
+ dashed = 0;
+
+ numchars = 0;
+
+ for (i = 0; i < scrollback; i++) {
+ lines[i].len = 0;
+
+ if (lines[i].lpic) lines[i].lpic->decrement();
+ lines[i].lpic = nullptr;
+ if (lines[i].rpic) lines[i].rpic->decrement();
+ lines[i].rpic = nullptr;
+
+ lines[i].lhyper = 0;
+ lines[i].rhyper = 0;
+ lines[i].lm = 0;
+ lines[i].rm = 0;
+ lines[i].newline = 0;
+ lines[i].dirty = 1;
+ lines[i].repaint = 0;
+ }
+
+ lastseen = 0;
+ scrollpos = 0;
+ scrollmax = 0;
+
+ for (i = 0; i < height; i++)
+ touch(i);
+}
+
+bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
+ if (align == imagealign_MarginRight)
+ {
+ if (lines[0].rpic || numchars)
+ return false;
+
+ radjw = (pic->w + Windows::_tMarginx) * GLI_SUBPIX;
+ radjn = (pic->h + Windows::_cellH - 1) / Windows::_cellH;
+ lines[0].rpic = pic;
+ lines[0].rm = radjw;
+ lines[0].rhyper = linkval;
+ } else {
+ if (align != imagealign_MarginLeft && numchars)
+ putCharUni('\n');
+
+ if (lines[0].lpic || numchars)
+ return false;
+
+ ladjw = (pic->w + Windows::_tMarginx) * GLI_SUBPIX;
+ ladjn = (pic->h + Windows::_cellH - 1) / Windows::_cellH;
+ lines[0].lpic = pic;
+ lines[0].lm = ladjw;
+ lines[0].lhyper = linkval;
+
+ if (align != imagealign_MarginLeft)
+ flowBreak();
+ }
+
+ return true ;
+}
+
+void TextBufferWindow::putCharUni(glui32 ch) {
+ /*
+ glui32 bchars[TBLINELEN];
+ Attributes battrs[TBLINELEN];
+ int pw;
+ int bpoint;
+ int saved;
+ int i;
+ int linelen;
+ unsigned char *color;
+
+ gli_tts_speak(&ch, 1);
+
+ pw = (win->bbox.x1 - win->bbox.x0 - Windows::_tMarginx * 2 - gli_scroll_width) * GLI_SUBPIX;
+ pw = pw - 2 * SLOP - radjw - ladjw;
+
+ color = gli_override_bg_set ? gli_window_color : win->bgcolor;
+
+ // oops ... overflow
+ if (numchars + 1 >= TBLINELEN)
+ scrolloneline(dwin, 0);
+
+ if (ch == '\n') {
+ scrolloneline(dwin, 1);
+ return;
+ }
+
+ if (gli_conf_quotes) {
+ // fails for 'tis a wonderful day in the '80s
+ if (gli_conf_quotes > 1 && ch == '\'')
+ {
+ if (numchars == 0 || leftquote(chars[numchars - 1]))
+ ch = UNI_LSQUO;
+ }
+
+ if (ch == '`')
+ ch = UNI_LSQUO;
+
+ if (ch == '\'')
+ ch = UNI_RSQUO;
+
+ if (ch == '"')
+ {
+ if (numchars == 0 || leftquote(chars[numchars - 1]))
+ ch = UNI_LDQUO;
+ else
+ ch = UNI_RDQUO;
+ }
+ }
+
+ if (gli_conf_dashes && win->attr.style != style_Preformatted)
+ {
+ if (ch == '-')
+ {
+ dashed++;
+ if (dashed == 2)
+ {
+ numchars--;
+ if (gli_conf_dashes == 2)
+ ch = UNI_NDASH;
+ else
+ ch = UNI_MDASH;
+ }
+ if (dashed == 3)
+ {
+ numchars--;
+ ch = UNI_MDASH;
+ dashed = 0;
+ }
+ }
+ else
+ dashed = 0;
+ }
+
+ if (gli_conf_spaces && win->attr.style != style_Preformatted
+ && styles[win->attr.style].bg == color
+ && !styles[win->attr.style].reverse)
+ {
+ // turn (period space space) into (period space)
+ if (gli_conf_spaces == 1)
+ {
+ if (ch == '.')
+ spaced = 1;
+ else if (ch == ' ' && spaced == 1)
+ spaced = 2;
+ else if (ch == ' ' && spaced == 2)
+ {
+ spaced = 0;
+ return;
+ }
+ else
+ spaced = 0;
+ }
+
+ // Turn (per sp x) into (per sp sp x)
+ if (gli_conf_spaces == 2)
+ {
+ if (ch == '.')
+ spaced = 1;
+ else if (ch == ' ' && spaced == 1)
+ spaced = 2;
+ else if (ch != ' ' && spaced == 2)
+ {
+ spaced = 0;
+ win_textbuffer_putchar_uni(win, ' ');
+ }
+ else
+ spaced = 0;
+ }
+ }
+
+ chars[numchars] = ch;
+ attrs[numchars] = win->attr;
+ numchars++;
+
+ // kill spaces at the end for line width calculation
+ linelen = numchars;
+ while (linelen > 1 && chars[linelen - 1] == ' '
+ && styles[attrs[linelen - 1].style].bg == color
+ && !styles[attrs[linelen - 1].style].reverse)
+ linelen--;
+
+ if (calcwidth(dwin, chars, attrs, 0, linelen, -1) >= pw)
+ {
+ bpoint = numchars;
+
+ for (i = numchars - 1; i > 0; i--)
+ if (chars[i] == ' ')
+ {
+ bpoint = i + 1; // skip space
+ break;
+ }
+
+ saved = numchars - bpoint;
+
+ memcpy(bchars, chars + bpoint, saved * 4);
+ memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
+ numchars = bpoint;
+
+ scrolloneline(dwin, 0);
+
+ memcpy(chars, bchars, saved * 4);
+ memcpy(attrs, battrs, saved * sizeof(attr_t));
+ numchars = saved;
+ }
+
+ touch(0);
+ */
+}
+
+void TextBufferWindow::putTextUnit(const glui32 *buf, int len, int pos, int oldlen) {
+ // TODO
+}
+
+void TextBufferWindow::flowBreak() {
+ // TODO
+}
+
+void TextBufferWindow::touch(int line) {
+// int y = bbox.top + Windows::_tMarginy + (height - line - 1) * Windows::_leading;
+ lines[line].dirty = 1;
+ _windows->clearSelection();
+ //winrepaint(bbox.left, y - 2, bbox.right, y + Windows::_leading + 2);
}
/*--------------------------------------------------------------------------*/
-GraphicsWindow::GraphicsWindow(uint32 rock) : Window(rock) {
+TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
+ lpic(nullptr), rpic(nullptr), lhyper(0), rhyper(0), lm(0), rm(0) {
+}
+
+void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
+ chars.clear();
+ attr.clear();
+ chars.resize(newSize);
+ attr.resize(newSize);
+ Common::fill(&chars[0], &chars[0] + newSize, ' ');
+}
+
+/*--------------------------------------------------------------------------*/
+
+GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
_type = wintype_Graphics;
}
/*--------------------------------------------------------------------------*/
-PairWindow::PairWindow(glui32 method, Window *_key, glui32 _size) : Window(0),
+PairWindow::PairWindow(Windows *windows, glui32 method, Window *_key, glui32 _size) :
+ Window(windows, 0),
dir(method & winmethod_DirMask),
division(method & winmethod_DivisionMask),
wborder((method & winmethod_BorderMask) == winmethod_Border),
@@ -323,13 +819,6 @@ PairWindow::PairWindow(glui32 method, Window *_key, glui32 _size) : Window(0),
/*--------------------------------------------------------------------------*/
-WindowStyle::WindowStyle() : font(0), reverse(0) {
- Common::fill(&bg[0], &bg[3], 0);
- Common::fill(&fg[0], &fg[3], 0);
-}
-
-/*--------------------------------------------------------------------------*/
-
void Attributes::clear() {
fgset = 0;
bgset = 0;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 45907a8..aad4969 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -29,12 +29,21 @@
#include "common/stream.h"
#include "graphics/screen.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/picture.h"
namespace Gargoyle {
class Window;
class PairWindow;
+struct WindowMask;
+#define HISTORYLEN 100
+#define SCROLLBACK 512
+#define TBLINELEN 300
+
+/**
+ * Main windows manager
+ */
class Windows {
private:
Graphics::Screen *_screen;
@@ -43,6 +52,8 @@ private:
Window *_focusWin; ///< The window selected by the player
bool _forceRedraw;
bool _moreFocus;
+ bool _claimSelect;
+ WindowMask *_mask;
private:
/**
* Create a new window
@@ -76,6 +87,12 @@ public:
static int _cellW, _cellH;
static int _baseLine;
static int _leading;
+ static int _scrollWidth;
+ static bool _overrideReverse;
+ static bool _overrideFgSet;
+ static bool _overrideBgSet;
+ static int _overrideFgVal;
+ static int _overrideBgVal;
public:
/**
* Constructor
@@ -92,6 +109,8 @@ public:
* Return the root window
*/
Window *getRoot() const { return _rootWin; }
+
+ void clearSelection();
};
/**
@@ -102,8 +121,6 @@ struct WindowStyle {
byte bg[3];
byte fg[3];
int reverse;
-
- WindowStyle();
};
/**
@@ -132,11 +149,21 @@ struct Attributes {
void clear();
};
+struct WindowMask {
+ int hor;
+ int ver;
+ glui32 **links;
+ Common::Rect select;
+
+ WindowMask() : hor(0), ver(0), links(nullptr) {}
+};
+
/**
* Window definition
*/
class Window {
public:
+ Windows *_windows;
glui32 _magicnum;
glui32 _rock;
glui32 _type;
@@ -172,7 +199,7 @@ public:
/**
* Constructor
*/
- Window(uint32 rock);
+ Window(Windows *windows, uint32 rock);
/**
* Destructor
@@ -194,7 +221,7 @@ public:
/**
* Constructor
*/
- BlankWindow(uint32 rock);
+ BlankWindow(Windows *windows, uint32 rock);
};
/**
@@ -245,7 +272,7 @@ public:
/**
* Constructor
*/
- TextGridWindow(uint32 rock);
+ TextGridWindow(Windows *windows, uint32 rock);
/**
* Rearranges the window
@@ -257,11 +284,101 @@ public:
* Text Buffer window
*/
class TextBufferWindow : public Window {
+ /**
+ * Structure for a row within the window
+ */
+ struct TextBufferRow {
+ Common::Array<uint32> chars;
+ Common::Array<Attributes> attr;
+ int len, newline;
+ bool dirty, repaint;
+ Picture *lpic, *rpic;
+ glui32 lhyper, rhyper;
+ int lm, rm;
+
+ /**
+ * Constructor
+ */
+ TextBufferRow();
+
+ /**
+ * Resize the row
+ */
+ void resize(size_t newSize);
+ };
+ typedef Common::Array<TextBufferRow> TextBufferRows;
+private:
+ void reflow();
+ void touchScroll();
+ bool putPicture(Picture *pic, glui32 align, glui32 linkval);
+ void putCharUni(glui32 ch);
+ void putTextUnit(const glui32 *buf, int len, int pos, int oldlen);
+ void flowBreak();
+
+ /**
+ * Mark a given text row as modified
+ */
+ void touch(int line);
+public:
+ int width, height;
+ int spaced;
+ int dashed;
+
+ TextBufferRows lines;
+ int scrollback;
+
+ int numchars; ///< number of chars in last line: lines[0]
+ glui32 *chars; ///< alias to lines[0].chars
+ Attributes *attrs; ///< alias to lines[0].attrs
+
+ ///< adjust margins temporarily for images
+ int ladjw;
+ int ladjn;
+ int radjw;
+ int radjn;
+
+ /* Command history. */
+ glui32 *history[HISTORYLEN];
+ int historypos;
+ int historyfirst, historypresent;
+
+ /* for paging */
+ int lastseen;
+ int scrollpos;
+ int scrollmax;
+
+ /* for line input */
+ void *inbuf; ///< unsigned char* for latin1, glui32* for unicode
+ int inmax;
+ long infence;
+ long incurs;
+ Attributes origattr;
+ gidispatch_rock_t inarrayrock;
+
+ glui32 echo_line_input;
+ glui32 *line_terminators;
+
+ /* style hints and settings */
+ WindowStyle styles[style_NUMSTYLES];
+
+ /* for copy selection */
+ glui32 *copybuf;
+ int copypos;
public:
/**
* Constructor
*/
- TextBufferWindow(uint32 rock);
+ TextBufferWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box);
+
+ /**
+ * Clear the window
+ */
+ void clear();
};
/**
@@ -272,7 +389,7 @@ public:
/**
* Constructor
*/
- GraphicsWindow(uint32 rock);
+ GraphicsWindow(Windows *windows, uint32 rock);
};
/**
@@ -294,7 +411,7 @@ public:
/**
* Constructor
*/
- PairWindow(glui32 method, Window *_key, glui32 _size);
+ PairWindow(Windows *windows, glui32 method, Window *_key, glui32 _size);
};
} // End of namespace Gargoyle
Commit: b9bafba382a9756cbedbb2008086208e24834139
https://github.com/scummvm/scummvm/commit/b9bafba382a9756cbedbb2008086208e24834139
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Remaining window rearrange code
Changed paths:
A engines/gargoyle/picture.cpp
A engines/gargoyle/picture.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/picture.cpp b/engines/gargoyle/picture.cpp
new file mode 100644
index 0000000..4b0b892
--- /dev/null
+++ b/engines/gargoyle/picture.cpp
@@ -0,0 +1,38 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/picture.h"
+
+namespace Gargoyle {
+
+void Picture::increment() {
+ ++_refCount;
+}
+
+void Picture::decrement() {
+ if (_refCount > 0 && --_refCount == 0) {
+ free();
+ delete this;
+ }
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/picture.h b/engines/gargoyle/picture.h
new file mode 100644
index 0000000..38f776c
--- /dev/null
+++ b/engines/gargoyle/picture.h
@@ -0,0 +1,53 @@
+/* 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 GARGOYLE_PICTURE_H
+#define GARGOYLE_PICTURE_H
+
+#include "graphics/surface.h"
+
+namespace Gargoyle {
+
+struct Picture : Graphics::Surface {
+ int _refCount;
+ uint32 _id;
+ bool _scaled;
+
+ /**
+ * Constructor
+ */
+ Picture() : Graphics::Surface(), _refCount(0), _id(0), _scaled(0) {}
+
+ /**
+ * Increment reference counter
+ */
+ void increment();
+
+ /**
+ * Decrement reference counter
+ */
+ void decrement();
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 194002b..8dc546a 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -541,7 +541,7 @@ void TextBufferWindow::touchScroll() {
_windows->clearSelection();
// TODO
- //winrepaint(win->bbox.left, win->bbox.top, win->bbox.right, win->bbox.bottom);
+ //winrepaint(bbox.left, bbox.top, bbox.right, bbox.bottom);
for (int i = 0; i < scrollmax; i++)
lines[i].dirty = true;
}
@@ -632,10 +632,10 @@ void TextBufferWindow::putCharUni(glui32 ch) {
gli_tts_speak(&ch, 1);
- pw = (win->bbox.x1 - win->bbox.x0 - Windows::_tMarginx * 2 - gli_scroll_width) * GLI_SUBPIX;
+ pw = (bbox.right - bbox.left - Windows::_tMarginx * 2 - gli_scroll_width) * GLI_SUBPIX;
pw = pw - 2 * SLOP - radjw - ladjw;
- color = gli_override_bg_set ? gli_window_color : win->bgcolor;
+ color = gli_override_bg_set ? gli_window_color : bgcolor;
// oops ... overflow
if (numchars + 1 >= TBLINELEN)
@@ -669,7 +669,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
}
}
- if (gli_conf_dashes && win->attr.style != style_Preformatted)
+ if (gli_conf_dashes && attr.style != style_Preformatted)
{
if (ch == '-')
{
@@ -693,9 +693,9 @@ void TextBufferWindow::putCharUni(glui32 ch) {
dashed = 0;
}
- if (gli_conf_spaces && win->attr.style != style_Preformatted
- && styles[win->attr.style].bg == color
- && !styles[win->attr.style].reverse)
+ if (gli_conf_spaces && attr.style != style_Preformatted
+ && styles[attr.style].bg == color
+ && !styles[attr.style].reverse)
{
// turn (period space space) into (period space)
if (gli_conf_spaces == 1)
@@ -731,7 +731,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
}
chars[numchars] = ch;
- attrs[numchars] = win->attr;
+ attrs[numchars] = attr;
numchars++;
// kill spaces at the end for line width calculation
@@ -800,8 +800,58 @@ void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
/*--------------------------------------------------------------------------*/
-GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
+GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
+ w(0), h(0), dirty(false), _surface(nullptr) {
_type = wintype_Graphics;
+ Common::copy(&bgcolor[0], &bgcolor[3], bgnd);
+}
+
+void GraphicsWindow::rearrange(const Common::Rect &box) {
+ int newwid, newhgt;
+ int bothwid, bothhgt;
+ int oldw, oldh;
+ Graphics::ManagedSurface *newSurface;
+
+ bbox = box;
+
+ newwid = box.width();
+ newhgt = box.height();
+ oldw = w;
+ oldh = h;
+
+ if (newwid <= 0 || newhgt <= 0) {
+ w = 0;
+ h = 0;
+ delete _surface;
+ _surface = NULL;
+ return;
+ }
+
+ bothwid = w;
+ if (newwid < bothwid)
+ bothwid = newwid;
+ bothhgt = h;
+ if (newhgt < bothhgt)
+ bothhgt = newhgt;
+
+ newSurface = new Graphics::ManagedSurface(newwid, newhgt,
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
+
+ // If the new surface is equal or bigger than the old one, copy it over
+ if (_surface && bothwid && bothhgt)
+ newSurface->blitFrom(*_surface);
+
+ delete _surface;
+ _surface = newSurface;
+ w = newwid;
+ h = newhgt;
+
+ touch();
+}
+
+void GraphicsWindow::touch() {
+ dirty = true;
+// winrepaint(bbox.left, bbox.top, bbox.right, bbox.bottom);
}
/*--------------------------------------------------------------------------*/
@@ -817,6 +867,90 @@ PairWindow::PairWindow(Windows *windows, glui32 method, Window *_key, glui32 _si
_type = wintype_Pair;
}
+void PairWindow::rearrange(const Common::Rect &box) {
+ Common::Rect box1, box2;
+ int min, diff, split, splitwid, max;
+ Window *keyWin;
+ Window *ch1, *ch2;
+
+ bbox = box;
+
+ if (vertical) {
+ min = bbox.left;
+ max = bbox.right;
+ } else {
+ min = bbox.top;
+ max = bbox.bottom;
+ }
+ diff = max - min;
+
+ // We now figure split.
+ if (vertical)
+ splitwid = Windows::_wPaddingx; // want border?
+ else
+ splitwid = Windows::_wPaddingy; // want border?
+
+ switch (division) {
+ case winmethod_Proportional:
+ split = (diff * size) / 100;
+ break;
+
+ case winmethod_Fixed:
+ keyWin = key;
+ split = !keyWin ? 0 : keyWin->getSplit(size, vertical);
+ break;
+
+ default:
+ split = diff / 2;
+ break;
+ }
+
+ if (!backward)
+ split = max - split - splitwid;
+ else
+ split = min + split;
+
+ if (min >= max) {
+ split = min;
+ } else {
+ if (split < min)
+ split = min;
+ else if (split > max - splitwid)
+ split = max - splitwid;
+ }
+
+ if (vertical) {
+ box1.left = bbox.left;
+ box1.right = split;
+ box2.left = split + splitwid;
+ box2.right = bbox.right;
+ box1.top = bbox.top;
+ box1.bottom = bbox.bottom;
+ box2.top = bbox.top;
+ box2.bottom = bbox.bottom;
+ } else {
+ box1.top = bbox.top;
+ box1.bottom = split;
+ box2.top = split + splitwid;
+ box2.bottom = bbox.bottom;
+ box1.left = bbox.left;
+ box1.right = bbox.right;
+ box2.left = bbox.left;
+ box2.right = bbox.right;
+ }
+
+ if (!backward) {
+ ch1 = child1;
+ ch2 = child2;
+ } else {
+ ch1 = child2;
+ ch2 = child1;
+ }
+
+ ch1->rearrange(box1);
+ ch2->rearrange(box2);
+}
+
/*--------------------------------------------------------------------------*/
void Attributes::clear() {
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index aad4969..64adf81 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -210,6 +210,11 @@ public:
* Rearranges the window
*/
virtual void rearrange(const Common::Rect &box) { bbox = box; }
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const { return 0; }
};
typedef Window *winid_t;
@@ -277,7 +282,15 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box);
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override {
+ return vertical ? size * Windows::_cellW + Windows::_tMarginx * 2 :
+ size * Windows::_cellH + Windows::_tMarginy * 2;
+ }
};
/**
@@ -373,7 +386,14 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box);
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override {
+ return (vertical) ? size * Windows::_cellW : size * Windows::_cellH;
+ }
/**
* Clear the window
@@ -385,11 +405,30 @@ public:
* Graphics window
*/
class GraphicsWindow : public Window {
+private:
+ void touch();
+public:
+ unsigned char bgnd[3];
+ bool dirty;
+ int w, h;
+ Graphics::ManagedSurface *_surface;
public:
/**
* Constructor
*/
GraphicsWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override {
+ return size;
+ }
};
/**
@@ -412,6 +451,11 @@ public:
* Constructor
*/
PairWindow(Windows *windows, glui32 method, Window *_key, glui32 _size);
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
};
} // End of namespace Gargoyle
Commit: 9e804bf4848d926c32bc3f1fbb5f0ee663fecaa1
https://github.com/scummvm/scummvm/commit/9e804bf4848d926c32bc3f1fbb5f0ee663fecaa1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added glk_set_window
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 278faf5..7274ff2 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -136,7 +136,7 @@ strid_t Glk::glk_window_get_echo_stream(winid_t win) {
}
void Glk::glk_set_window(winid_t win) {
- // TODO
+ _windows->setCurrent(win ? win->str : nullptr);
}
strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 8dc546a..0bc16b2 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -89,7 +89,7 @@ WindowStyle G_STYLES[style_NUMSTYLES] = {
Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
_windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr),
- _claimSelect(0) {
+ _claimSelect(0), _currentStr(nullptr) {
_confLockCols = false;
_confLockRows = false;
_wMarginx = 15;
@@ -280,6 +280,10 @@ void Windows::clearSelection() {
_claimSelect = false;
}
+void Windows::setCurrent(Common::WriteStream *stream) {
+ _currentStr = stream;
+}
+
/*--------------------------------------------------------------------------*/
Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 64adf81..02fa7aa 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -54,6 +54,7 @@ private:
bool _moreFocus;
bool _claimSelect;
WindowMask *_mask;
+ Common::WriteStream *_currentStr;
private:
/**
* Create a new window
@@ -111,6 +112,11 @@ public:
Window *getRoot() const { return _rootWin; }
void clearSelection();
+
+ /**
+ * Set the current output stream
+ */
+ void setCurrent(Common::WriteStream *stream);
};
/**
Commit: 3c9987c0a7566f99da637a83c9a3fe64b160e6e4
https://github.com/scummvm/scummvm/commit/3c9987c0a7566f99da637a83c9a3fe64b160e6e4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fixes for window initialization
Changed paths:
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 0bc16b2..42c5b1a 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -90,6 +90,9 @@ WindowStyle G_STYLES[style_NUMSTYLES] = {
Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
_windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr),
_claimSelect(0), _currentStr(nullptr) {
+ _imageW = _screen->w;
+ _imageH = _screen->h;
+ _cellW = _cellH = 8;
_confLockCols = false;
_confLockRows = false;
_wMarginx = 15;
@@ -104,8 +107,6 @@ Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true)
_wMarginYsave = 15;
_cols = 60;
_rows = 25;
- _imageW = _imageH = 0;
- _cellW = _cellH = 0;
_baseLine = 15;
_leading = 20;
_scrollWidth = 0;
@@ -173,8 +174,8 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
} else {
// create pairwin, with newwin as the key
pairwin = newPairWindow(method, newwin, size);
- pairwin->child1 = splitwin;
- pairwin->child2 = newwin;
+ pairwin->_child1 = splitwin;
+ pairwin->_child2 = newwin;
splitwin->parent = pairwin;
newwin->parent = pairwin;
@@ -183,10 +184,10 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
if (oldparent) {
PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
assert(parentWin);
- if (parentWin->child1 == splitwin)
- parentWin->child1 = pairwin;
+ if (parentWin->_child1 == splitwin)
+ parentWin->_child1 = pairwin;
else
- parentWin->child2 = pairwin;
+ parentWin->_child2 = pairwin;
} else {
_rootWin = pairwin;
}
@@ -284,6 +285,10 @@ void Windows::setCurrent(Common::WriteStream *stream) {
_currentStr = stream;
}
+void Windows::repaint(const Common::Rect &box) {
+ // TODO
+}
+
/*--------------------------------------------------------------------------*/
Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
@@ -348,10 +353,9 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
}
void TextGridWindow::touch(int line) {
-// int y = bbox.top + line * Windows::_leading;
+ int y = bbox.top + line * Windows::_leading;
lines[line].dirty = true;
- // TODO
-// winrepaint(bbox.left, y, bbox.right, y + Windows::_leading);
+ _windows->repaint(Common::Rect(bbox.left, y, bbox.right, y + Windows::_leading));
}
/*--------------------------------------------------------------------------*/
@@ -543,9 +547,8 @@ void TextBufferWindow::reflow() {
void TextBufferWindow::touchScroll() {
_windows->clearSelection();
+ _windows->repaint(bbox);
- // TODO
- //winrepaint(bbox.left, bbox.top, bbox.right, bbox.bottom);
for (int i = 0; i < scrollmax; i++)
lines[i].dirty = true;
}
@@ -580,8 +583,8 @@ void TextBufferWindow::clear() {
lines[i].lm = 0;
lines[i].rm = 0;
lines[i].newline = 0;
- lines[i].dirty = 1;
- lines[i].repaint = 0;
+ lines[i].dirty = true;
+ lines[i].repaint = false;
}
lastseen = 0;
@@ -782,10 +785,10 @@ void TextBufferWindow::flowBreak() {
}
void TextBufferWindow::touch(int line) {
-// int y = bbox.top + Windows::_tMarginy + (height - line - 1) * Windows::_leading;
+ int y = bbox.top + Windows::_tMarginy + (height - line - 1) * Windows::_leading;
lines[line].dirty = 1;
_windows->clearSelection();
- //winrepaint(bbox.left, y - 2, bbox.right, y + Windows::_leading + 2);
+ _windows->repaint(Common::Rect(bbox.left, y - 2, bbox.right, y + Windows::_leading + 2));
}
/*--------------------------------------------------------------------------*/
@@ -855,31 +858,30 @@ void GraphicsWindow::rearrange(const Common::Rect &box) {
void GraphicsWindow::touch() {
dirty = true;
-// winrepaint(bbox.left, bbox.top, bbox.right, bbox.bottom);
+ _windows->repaint(bbox);
}
/*--------------------------------------------------------------------------*/
-PairWindow::PairWindow(Windows *windows, glui32 method, Window *_key, glui32 _size) :
+PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size) :
Window(windows, 0),
- dir(method & winmethod_DirMask),
- division(method & winmethod_DivisionMask),
- wborder((method & winmethod_BorderMask) == winmethod_Border),
- vertical(dir == winmethod_Left || dir == winmethod_Right),
- backward(dir == winmethod_Left || dir == winmethod_Above),
- key(key), size(size), keydamage(0), child1(nullptr), child2(nullptr) {
+ _dir(method & winmethod_DirMask),
+ _division(method & winmethod_DivisionMask),
+ _wborder((method & winmethod_BorderMask) == winmethod_Border),
+ _vertical(_dir == winmethod_Left || _dir == winmethod_Right),
+ _backward(_dir == winmethod_Left || _dir == winmethod_Above),
+ _key(key), _size(size), _keydamage(0), _child1(nullptr), _child2(nullptr) {
_type = wintype_Pair;
}
void PairWindow::rearrange(const Common::Rect &box) {
Common::Rect box1, box2;
int min, diff, split, splitwid, max;
- Window *keyWin;
Window *ch1, *ch2;
bbox = box;
- if (vertical) {
+ if (_vertical) {
min = bbox.left;
max = bbox.right;
} else {
@@ -889,19 +891,18 @@ void PairWindow::rearrange(const Common::Rect &box) {
diff = max - min;
// We now figure split.
- if (vertical)
+ if (_vertical)
splitwid = Windows::_wPaddingx; // want border?
else
splitwid = Windows::_wPaddingy; // want border?
- switch (division) {
+ switch (_division) {
case winmethod_Proportional:
- split = (diff * size) / 100;
+ split = (diff * _size) / 100;
break;
case winmethod_Fixed:
- keyWin = key;
- split = !keyWin ? 0 : keyWin->getSplit(size, vertical);
+ split = !_key ? 0 : _key->getSplit(_size, _vertical);
break;
default:
@@ -909,7 +910,7 @@ void PairWindow::rearrange(const Common::Rect &box) {
break;
}
- if (!backward)
+ if (!_backward)
split = max - split - splitwid;
else
split = min + split;
@@ -923,7 +924,7 @@ void PairWindow::rearrange(const Common::Rect &box) {
split = max - splitwid;
}
- if (vertical) {
+ if (_vertical) {
box1.left = bbox.left;
box1.right = split;
box2.left = split + splitwid;
@@ -943,12 +944,12 @@ void PairWindow::rearrange(const Common::Rect &box) {
box2.right = bbox.right;
}
- if (!backward) {
- ch1 = child1;
- ch2 = child2;
+ if (!_backward) {
+ ch1 = _child1;
+ ch2 = _child2;
} else {
- ch1 = child2;
- ch2 = child1;
+ ch1 = _child2;
+ ch2 = _child1;
}
ch1->rearrange(box1);
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 02fa7aa..112e903 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -117,6 +117,11 @@ public:
* Set the current output stream
*/
void setCurrent(Common::WriteStream *stream);
+
+ /**
+ * Repaint an area of the windows
+ */
+ void repaint(const Common::Rect &box);
};
/**
@@ -442,21 +447,21 @@ public:
*/
class PairWindow : public Window {
public:
- Window *child1, *child2;
+ Window *_child1, *_child2;
/* split info... */
- glui32 dir; ///< winmethod_Left, Right, Above, or Below
- int vertical, backward; ///< flags
- glui32 division; ///< winmethod_Fixed or winmethod_Proportional
- Window *key; ///< NULL or a leaf-descendant (not a Pair)
- int keydamage; ///< used as scratch space in window closing
- glui32 size; ///< size value
- glui32 wborder; ///< winMethod_Border, NoBorder
+ glui32 _dir; ///< winmethod_Left, Right, Above, or Below
+ bool _vertical, _backward; ///< flags
+ glui32 _division; ///< winmethod_Fixed or winmethod_Proportional
+ Window *_key; ///< NULL or a leaf-descendant (not a Pair)
+ int _keydamage; ///< used as scratch space in window closing
+ glui32 _size; ///< size value
+ glui32 _wborder; ///< winMethod_Border, NoBorder
public:
/**
* Constructor
*/
- PairWindow(Windows *windows, glui32 method, Window *_key, glui32 _size);
+ PairWindow(Windows *windows, glui32 method, Window *key, glui32 size);
/**
* Rearranges the window
Commit: 256f7ff31264efcd23b86d1fe79fce8a3597e64a
https://github.com/scummvm/scummvm/commit/256f7ff31264efcd23b86d1fe79fce8a3597e64a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Skeleton implementation of window text stream
Changed paths:
A engines/gargoyle/stream.cpp
A engines/gargoyle/stream.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 7274ff2..3e308d55 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -22,6 +22,7 @@
#include "gargoyle/glk.h"
#include "gargoyle/events.h"
+#include "gargoyle/stream.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -122,8 +123,7 @@ void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
}
strid_t Glk::glk_window_get_stream(winid_t win) {
- // TODO
- return nullptr;
+ return win->_stream;
}
void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
@@ -136,7 +136,7 @@ strid_t Glk::glk_window_get_echo_stream(winid_t win) {
}
void Glk::glk_set_window(winid_t win) {
- _windows->setCurrent(win ? win->str : nullptr);
+ _windows->setCurrent(win ? win->_stream : nullptr);
}
strid_t Glk::glk_stream_open_file(frefid_t fileref, glui32 fmode,
@@ -371,27 +371,28 @@ glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
}
void Glk::glk_put_char_uni(glui32 ch) {
- // TODO
+ glk_put_char_stream_uni(_windows->getCurrent(), ch);
}
void Glk::glk_put_string_uni(glui32 *s) {
- // TODO
+ glk_put_buffer_stream_uni(_windows->getCurrent(), s, strlen_uni(s));
}
void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
- // TODO
+ glk_put_buffer_stream_uni(_windows->getCurrent(), buf, len);
}
void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
- // TODO
+ str->writeUint32LE(ch);
}
-void Glk::glk_put_string_stream_uni(strid_t str, glui32 *s) {
- // TODO
+void Glk::glk_put_string_stream_uni(strid_t str, const glui32 *s) {
+ glk_put_buffer_stream_uni(str, s, strlen_uni(s));
}
-void Glk::glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- // TODO
+void Glk::glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len) {
+ while (len-- > 0)
+ str->writeUint32LE(*buf++);
}
glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index ce21910..b0ef171 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -171,8 +171,8 @@ public:
void glk_put_string_uni(glui32 *s);
void glk_put_buffer_uni(glui32 *buf, glui32 len);
void glk_put_char_stream_uni(strid_t str, glui32 ch);
- void glk_put_string_stream_uni(strid_t str, glui32 *s);
- void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
+ void glk_put_string_stream_uni(strid_t str, const glui32 *s);
+ void glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len);
glsi32 glk_get_char_stream_uni(strid_t str);
glui32 glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len);
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 82f70e3..86b37fc 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -24,6 +24,7 @@
#define GARGOYLE_GLK_TYPES_H
#include "common/scummsys.h"
+#include "common/stream.h"
namespace Gargoyle {
@@ -49,7 +50,7 @@ class Window;
* These types are opaque object identifiers. They're pointers to opaque
* C structures, which are defined differently by each library.
*/
-typedef struct glk_stream_struct *strid_t;
+typedef Common::WriteStream *strid_t;
typedef struct glk_fileref_struct *frefid_t;
typedef struct glk_schannel_struct *schanid_t;
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index e5542a7..5acba6a 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
gargoyle.o \
glk.o \
picture.o \
+ stream.o \
windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/stream.cpp b/engines/gargoyle/stream.cpp
new file mode 100644
index 0000000..a08579a
--- /dev/null
+++ b/engines/gargoyle/stream.cpp
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/stream.h"
+
+namespace Gargoyle {
+
+uint32 WindowStream::write(const void *dataPtr, uint32 dataSize) {
+ // TODO
+ return dataSize;
+}
+
+bool WindowStream::flush() {
+ // TODO
+ return true;
+}
+
+size_t strlen_uni(const uint32 *s) {
+ size_t len = 0;
+ while (*s++)
+ ++len;
+ return len;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/stream.h b/engines/gargoyle/stream.h
new file mode 100644
index 0000000..5a55fbc
--- /dev/null
+++ b/engines/gargoyle/stream.h
@@ -0,0 +1,74 @@
+/* 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 GARGOYLE_STREAM_H
+#define GARGOYLE_STREAM_H
+
+#include "common/stream.h"
+
+namespace Gargoyle {
+
+class Window;
+
+/**
+ * Implements the stream for writing text to a window
+ */
+class WindowStream : public Common::WriteStream {
+private:
+ uint32 _rock;
+ Window *_window;
+public:
+ /**
+ * Constructor
+ */
+ WindowStream(Window *window, uint32 rock = 0) : Common::WriteStream(),
+ _window(window), _rock(rock) {}
+
+ /**
+ * Write to the stream
+ */
+ virtual uint32 write(const void *dataPtr, uint32 dataSize);
+
+ /**
+ * Flush the stream
+ */
+ virtual bool flush();
+
+ /**
+ * Finalize and close this stream
+ */
+ virtual void finalize() { flush(); }
+
+ /**
+ * Returns the stream position
+ */
+ virtual int32 pos() const { return 0; }
+};
+
+/*
+ * Get the length of a unicode string
+ */
+size_t strlen_uni(const uint32 *s);
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 42c5b1a..0abc8a8 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/windows.h"
+#include "gargoyle/stream.h"
#include "common/algorithm.h"
#include "common/textconsole.h"
@@ -281,10 +282,6 @@ void Windows::clearSelection() {
_claimSelect = false;
}
-void Windows::setCurrent(Common::WriteStream *stream) {
- _currentStr = stream;
-}
-
void Windows::repaint(const Common::Rect &box) {
// TODO
}
@@ -295,7 +292,7 @@ Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
_windows(windows), _rock(rock), _type(0), parent(nullptr), next(nullptr), prev(nullptr),
yadj(0), line_request(0), line_request_uni(0), char_request(0), char_request_uni(0),
mouse_request(0), hyper_request(0), more_request(0), scroll_request(0), image_loaded(0),
- echo_line_input(true), line_terminators(nullptr), termct(0), str(nullptr), echostr(nullptr) {
+ echo_line_input(true), line_terminators(nullptr), termct(0), _echoStream(nullptr) {
attr.fgset = 0;
attr.bgset = 0;
attr.reverse = 0;
@@ -307,6 +304,8 @@ Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
Common::fill(&bgcolor[0], &bgcolor[3], 3);
Common::fill(&fgcolor[0], &fgcolor[3], 3);
disprock.num = 0;
+
+ _stream = new WindowStream(this, rock);
}
/*--------------------------------------------------------------------------*/
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 112e903..17e7d16 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -116,7 +116,12 @@ public:
/**
* Set the current output stream
*/
- void setCurrent(Common::WriteStream *stream);
+ void setCurrent(Common::WriteStream *stream) { _currentStr = stream; }
+
+ /**
+ * Gets the current output stream
+ */
+ Common::WriteStream *getCurrent() const { return _currentStr; }
/**
* Repaint an area of the windows
@@ -179,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 *str; ///< the window stream.
- Common::WriteStream *echostr; ///< the window's echo stream, if any.
+ Common::WriteStream *_stream; ///< the window stream.
+ Common::WriteStream *_echoStream; ///< the window's echo stream, if any.
int line_request;
int line_request_uni;
Commit: 65091b25c13be1c5cb319d91fe4ad773ae6fcad0
https://github.com/scummvm/scummvm/commit/65091b25c13be1c5cb319d91fe4ad773ae6fcad0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Starting to flesh out stream classes
Changed paths:
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/stream.cpp
engines/gargoyle/stream.h
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 5401b2c..986a40a 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 c7a7b86..bd97713 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 3e308d55..22d02f5 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 b0ef171..0029ecf 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 86b37fc..c7b505e 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 a08579a..c447646 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 5a55fbc..4effee3 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 17e7d16..fdb29bb 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
Commit: cf5259d3bc279fd73b4ae8bad2d7b04b8ff7265e
https://github.com/scummvm/scummvm/commit/cf5259d3bc279fd73b4ae8bad2d7b04b8ff7265e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding stream open/closing
Changed paths:
A engines/gargoyle/streams.cpp
A engines/gargoyle/streams.h
R engines/gargoyle/stream.cpp
R engines/gargoyle/stream.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/module.mk
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 986a40a..a481ae9 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -30,7 +30,7 @@
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/events.h"
-#include "gargoyle/stream.h"
+#include "gargoyle/streams.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -57,8 +57,8 @@ void GargoyleEngine::initialize() {
initGraphics(640, 480, false);
_screen = new Graphics::Screen();
_events = new Events();
- _streams = new Streams();
- _windows = new Windows(_screen);
+ _streams = new Streams(this);
+ _windows = new Windows(this, _screen);
}
Common::Error GargoyleEngine::run() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index bd97713..e7d5df2 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -73,10 +73,7 @@ private:
void initialize();
protected:
const GargoyleGameDescription *_gameDescription;
- Events *_events;
Graphics::Screen *_screen;
- Streams *_streams;
- Windows *_windows;
Common::RandomSource _random;
int _loadSaveSlot;
@@ -93,6 +90,10 @@ protected:
*/
virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
public:
+ Events *_events;
+ Streams *_streams;
+ Windows *_windows;
+public:
GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
virtual ~GargoyleEngine();
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 22d02f5..b49fb63 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -22,7 +22,7 @@
#include "gargoyle/glk.h"
#include "gargoyle/events.h"
-#include "gargoyle/stream.h"
+#include "gargoyle/streams.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -136,7 +136,7 @@ strid_t Glk::glk_window_get_echo_stream(winid_t win) {
}
void Glk::glk_set_window(winid_t win) {
- _windows->setCurrent(win ? win->_stream : nullptr);
+ _streams->setCurrent(win ? win->_stream : nullptr);
}
strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode,
@@ -374,15 +374,15 @@ glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
}
void Glk::glk_put_char_uni(glui32 ch) {
- glk_put_char_stream_uni(_windows->getCurrent(), ch);
+ glk_put_char_stream_uni(_streams->getCurrent(), ch);
}
void Glk::glk_put_string_uni(glui32 *s) {
- glk_put_buffer_stream_uni(_windows->getCurrent(), s, strlen_uni(s));
+ glk_put_buffer_stream_uni(_streams->getCurrent(), s, strlen_uni(s));
}
void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
- glk_put_buffer_stream_uni(_windows->getCurrent(), buf, len);
+ glk_put_buffer_stream_uni(_streams->getCurrent(), buf, len);
}
void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 5acba6a..05b7f5f 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -6,7 +6,7 @@ MODULE_OBJS := \
gargoyle.o \
glk.o \
picture.o \
- stream.o \
+ streams.o \
windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/stream.cpp b/engines/gargoyle/stream.cpp
deleted file mode 100644
index c447646..0000000
--- a/engines/gargoyle/stream.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/stream.h"
-#include "gargoyle/windows.h"
-
-namespace Gargoyle {
-
-Stream::Stream(bool readable, bool writable, uint32 rock, bool unicode) :
- _readable(readable), _writable(writable), _readCount(0), _writeCount(0),
- _prev(nullptr), _next(nullptr), _rock(0) {
-}
-
-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++)
- ++len;
- return len;
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/stream.h b/engines/gargoyle/stream.h
deleted file mode 100644
index 4effee3..0000000
--- a/engines/gargoyle/stream.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* 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 GARGOYLE_STREAM_H
-#define GARGOYLE_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 Stream {
-private:
- Window *_window;
-public:
- /**
- * Constructor
- */
- WindowStream(Window *window, uint32 rock = 0, bool unicode = true) :
- Stream(true, false, rock, unicode), _window(window) {}
-
- /**
- * Write a character
- */
- virtual void writeChar(unsigned char ch) override;
-
- /**
- * Write a unicode character
- */
- 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:
- /**
- * Adds a created stream to the list
- */
- void addStream(Stream *stream);
-public:
- /**
- * Constructor
- */
- Streams();
-
- /**
- * Destructor
- */
- ~Streams();
-
- /**
- * Add a window stream
- */
- WindowStream *addWindowStream(Window *window);
-
- /**
- * Add a memory stream
- */
- 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
- */
-size_t strlen_uni(const uint32 *s);
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
new file mode 100644
index 0000000..62e43e3
--- /dev/null
+++ b/engines/gargoyle/streams.cpp
@@ -0,0 +1,156 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/streams.h"
+#include "gargoyle/windows.h"
+
+namespace Gargoyle {
+
+Stream::Stream(Streams *streams, bool readable, bool writable, uint32 rock, bool unicode) :
+ _streams(streams), _readable(readable), _writable(writable), _readCount(0),
+ _writeCount(0), _prev(nullptr), _next(nullptr), _rock(0) {
+}
+
+Stream::~Stream() {
+ _streams->removeStream(this);
+}
+
+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) {
+ // Get the read/write totals
+ fillResult(result);
+
+ // Remove the stream
+ delete this;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void WindowStream::close(StreamResult *result) {
+ warning("cannot close window stream");
+}
+
+void WindowStream::writeChar(unsigned char ch) {
+
+}
+
+void WindowStream::writeCharUni(uint32 ch) {
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
+ Stream(streams, 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(GargoyleEngine *engine) : _engine(engine), _streamList(nullptr), _currentStream(nullptr) {
+}
+
+Streams::~Streams() {
+ while (_streamList)
+ deleteStream(_streamList);
+}
+
+WindowStream *Streams::addWindowStream(Window *window) {
+ WindowStream *stream = new WindowStream(this, window);
+ addStream(stream);
+ return stream;
+}
+
+MemoryStream *Streams::addMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) {
+ MemoryStream *stream = new MemoryStream(this, 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::removeStream(Stream *stream) {
+ Stream *prev = stream->_prev;
+ Stream *next = stream->_next;
+
+ if (prev)
+ prev->_next = next;
+ else
+ _streamList = next;
+ if (next)
+ next->_prev = prev;
+}
+
+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++)
+ ++len;
+ return len;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
new file mode 100644
index 0000000..db21d58
--- /dev/null
+++ b/engines/gargoyle/streams.h
@@ -0,0 +1,227 @@
+/* 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 GARGOYLE_STREAMS_H
+#define GARGOYLE_STREAMS_H
+
+#include "common/scummsys.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+class GargoyleEngine;
+class Window;
+class Streams;
+
+struct StreamResult {
+ uint32 _readCount;
+ uint32 _writeCount;
+};
+
+/**
+ * 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 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 Stream {
+private:
+ Window *_window;
+public:
+ /**
+ * Constructor
+ */
+ WindowStream(Streams *streams, Window *window, uint32 rock = 0, bool unicode = true) :
+ Stream(streams, true, false, rock, unicode), _window(window) {}
+
+ /**
+ * Close the stream
+ */
+ virtual void close(StreamResult *result = nullptr);
+
+ /**
+ * Write a character
+ */
+ virtual void writeChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ 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(Streams *streams, 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 {
+ friend class Stream;
+private:
+ GargoyleEngine *_engine;
+ Stream *_streamList;
+ Stream *_currentStream;
+private:
+ /**
+ * Adds a created stream to the list
+ */
+ void addStream(Stream *stream);
+
+ /**
+ * Remove a stream
+ */
+ void removeStream(Stream *stream);
+public:
+ /**
+ * Constructor
+ */
+ Streams(GargoyleEngine *engine);
+
+ /**
+ * Destructor
+ */
+ ~Streams();
+
+ /**
+ * Add a window stream
+ */
+ WindowStream *addWindowStream(Window *window);
+
+ /**
+ * Add a memory stream
+ */
+ MemoryStream *addMemoryStream(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; }
+};
+
+
+
+/*
+ * Get the length of a unicode string
+ */
+size_t strlen_uni(const uint32 *s);
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 0abc8a8..2c8680b 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -21,7 +21,8 @@
*/
#include "gargoyle/windows.h"
-#include "gargoyle/stream.h"
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/streams.h"
#include "common/algorithm.h"
#include "common/textconsole.h"
@@ -88,9 +89,10 @@ WindowStyle G_STYLES[style_NUMSTYLES] = {
/*--------------------------------------------------------------------------*/
-Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
+Windows::Windows(GargoyleEngine *engine, Graphics::Screen *screen) :
+ _engine(engine), _screen(screen), _forceRedraw(true), _moreFocus(false),
_windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr),
- _claimSelect(0), _currentStr(nullptr) {
+ _claimSelect(0) {
_imageW = _screen->w;
_imageH = _screen->h;
_cellW = _cellH = 8;
@@ -305,7 +307,8 @@ Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
Common::fill(&fgcolor[0], &fgcolor[3], 3);
disprock.num = 0;
- _stream = new WindowStream(this, rock);
+ Streams &streams = *windows->_engine->_streams;
+ _stream = streams.addWindowStream(this);
}
/*--------------------------------------------------------------------------*/
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index fdb29bb..95f1ed4 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -29,10 +29,11 @@
#include "graphics/screen.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/picture.h"
-#include "gargoyle/stream.h"
+#include "gargoyle/streams.h"
namespace Gargoyle {
+class GargoyleEngine;
class Window;
class PairWindow;
struct WindowMask;
@@ -45,7 +46,9 @@ struct WindowMask;
* Main windows manager
*/
class Windows {
+ friend class Window;
private:
+ GargoyleEngine *_engine;
Graphics::Screen *_screen;
Window * _windowList; ///< List of all windows
Window *_rootWin; ///< The topmost window
@@ -54,7 +57,6 @@ private:
bool _moreFocus;
bool _claimSelect;
WindowMask *_mask;
- Stream *_currentStr;
private:
/**
* Create a new window
@@ -98,7 +100,7 @@ public:
/**
* Constructor
*/
- Windows(Graphics::Screen *screen);
+ Windows(GargoyleEngine *engine, Graphics::Screen *screen);
/**
* Open a new window
@@ -114,16 +116,6 @@ public:
void clearSelection();
/**
- * Set the current output stream
- */
- void setCurrent(Stream *stream) { _currentStr = stream; }
-
- /**
- * Gets the current output stream
- */
- Stream *getCurrent() const { return _currentStr; }
-
- /**
* Repaint an area of the windows
*/
void repaint(const Common::Rect &box);
Commit: ef15871fec18060420eddc92a9830f595b8cc970
https://github.com/scummvm/scummvm/commit/ef15871fec18060420eddc92a9830f595b8cc970
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Setting up of configuration loading
Changed paths:
A engines/gargoyle/conf.cpp
A engines/gargoyle/conf.h
A engines/gargoyle/fonts.cpp
A engines/gargoyle/fonts.h
A engines/gargoyle/string.cpp
A engines/gargoyle/string.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
new file mode 100644
index 0000000..c296254
--- /dev/null
+++ b/engines/gargoyle/conf.cpp
@@ -0,0 +1,152 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/conf.h"
+#include "gargoyle/fonts.h"
+#include "gargoyle/string.h"
+#include "common/config-manager.h"
+
+namespace Gargoyle {
+
+const byte WHITE[3] = { 0xff, 0xff, 0xff };
+const byte BLUE[3] = { 0x00, 0x00, 0x60 };
+const byte SCROLL_BG[3] = { 0xb0, 0xb0, 0xb0 };
+const byte SCROLL_FG[3] = { 0x80, 0x80, 0x80 };
+
+Conf::Conf() {
+ g_conf = this;
+
+ get("moreprompt", _morePrompt, "\207 more \207");
+ get("morecolor", _moreColor);
+ get("morecolor", _moreSave);
+ get("morefont", _moreFont, PROPB);
+ get("morealign", _moreAlign);
+ get("monoaspect", _monoAspect, 1.0);
+ get("propaspect", _propAspect, 1.0);
+ get("monosize", _monoSize, 12.5);
+ get("monor", _monoR);
+ get("monob", _monoR);
+ get("monoi", _monoI);
+ get("monoz", _monoZ);
+ get("monofont", _monoFont, "Liberation Mono");
+ get("propsize", _propSize, 15.5);
+ get("propr", _propR);
+ get("propb", _propR);
+ get("propi", _propI);
+ get("propz", _propZ);
+ get("propfont", _propFont, "Linux Libertine O");
+ get("leading", _leading);
+ get("baseline", _baseLine);
+ get("rows", _rows, 25);
+ get("cols", _cols, 60);
+
+ if (ConfMan.hasKey("minrows"))
+ _rows = MAX(_rows, strToInt(ConfMan.get("minrows").c_str()));
+ if (ConfMan.hasKey("maxrows"))
+ _rows = MIN(_rows, strToInt(ConfMan.get("maxrows").c_str()));
+ if (ConfMan.hasKey("mincols"))
+ _cols = MAX(_cols, strToInt(ConfMan.get("mincols").c_str()));
+ if (ConfMan.hasKey("maxcols"))
+ _cols = MIN(_cols, strToInt(ConfMan.get("maxcols").c_str()));
+
+ get("lockrows", _lockRows);
+ get("lockcols", _lockCols);
+ get("wmarginx", _wMarginX, 15);
+ get("wmarginy", _wMarginY, 15);
+ _wMarginSaveX = _wMarginX;
+ _wMarginSaveY = _wMarginY;
+
+ get("wpaddingx", _wPaddingX);
+ get("wpaddingy", _wPaddingY);
+ get("wborderx", _wBorderX, 1);
+ get("wbordery", _wBorderY, 1);
+ get("tmarginx", _tMarginX, 7);
+ get("tmarginy", _tMarginY, 7);
+ get("gamma", _gamma, 1.0);
+
+ get("caretcolor", _caretColor);
+ get("caretcolor", _caretSave);
+ get("linkcolor", _linkColor, BLUE);
+ get("linkcolor", _linkSave, BLUE);
+ get("bordercolor", _borderColor);
+ get("bordercolor", _borderSave);
+ get("windowcolor", _windowColor, WHITE);
+ get("windowcolor", _windowSave, WHITE);
+ get("lcd", _lcd, 1);
+ get("caretshape", _caretShape, 2);
+
+ _linkStyle = ConfMan.hasKey("linkstyle") && !strToInt(ConfMan.get("linkstyle").c_str()) ? 0 : 1;
+
+ get("scrollwidth", _scrollWidth);
+ get("scrollbg", _scrollBg, SCROLL_BG);
+ get("scrollfg", _scrollFg, SCROLL_FG);
+ get("justify", _justify);
+ get("quotes", _quotes, 1);
+ get("dashes", _dashes, 1);
+ get("spaces", _spaces);
+ get("caps", _caps);
+ get("graphics", _graphics, 1);
+ get("sound", _sound, 1);
+ get("speak", _speak);
+ get("speak_input", _speakInput);
+ get("speak_language", _speakLanguage);
+ get("stylehint", _styleHint, 1);
+
+}
+
+void Conf::get(const Common::String &key, Common::String &field, const char *defaultVal) {
+ field = ConfMan.hasKey(key) ? ConfMan.get(key) : defaultVal;
+ field.trim();
+}
+
+void Conf::get(const Common::String &key, byte *color, const byte *defaultColor) {
+ char r[3], g[3], b[3];
+ Common::String str;
+
+ if (ConfMan.hasKey(key) && (str = ConfMan.get(key)).size() == 6) {
+ r[0] = str[0]; r[1] = str[1]; r[2] = 0;
+ g[0] = str[2]; g[1] = str[3]; g[2] = 0;
+ b[0] = str[4]; b[1] = str[5]; b[2] = 0;
+
+ color[0] = strtol(r, NULL, 16);
+ color[1] = strtol(g, NULL, 16);
+ color[2] = strtol(b, NULL, 16);
+ } else if (defaultColor) {
+ Common::copy(defaultColor, defaultColor + 3, color);
+ } else {
+ Common::fill(color, color + 3, 0);
+ }
+}
+
+void Conf::get(const Common::String &key, int &field, int defaultVal) {
+ field = ConfMan.hasKey(key) ? strToInt(ConfMan.get(key).c_str()) : defaultVal;
+}
+
+void Conf::get(const Common::String &key, FACES &field, FACES defaultFont) {
+ field = ConfMan.hasKey(key) ? Fonts::getId(ConfMan.get(key)) : defaultFont;
+}
+
+void Conf::get(const Common::String &key, double &field, double defaultVal) {
+ field = ConfMan.hasKey(key) ? atof(ConfMan.get(key).c_str()) : defaultVal;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/conf.h b/engines/gargoyle/conf.h
new file mode 100644
index 0000000..2dbb29f
--- /dev/null
+++ b/engines/gargoyle/conf.h
@@ -0,0 +1,118 @@
+/* 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 GARGOYLE_CONF_H
+#define GARGOYLE_CONF_H
+
+#include "gargoyle/glk_types.h"
+#include "gargoyle/fonts.h"
+
+namespace Gargoyle {
+
+class Conf {
+private:
+ /**
+ * Get a string
+ */
+ void get(const Common::String &key, Common::String &field, const char *defaultVal = nullptr);
+
+ /**
+ * Get a color
+ */
+ void get(const Common::String &key, byte *color, const byte *defaultColor = nullptr);
+
+ /**
+ * Get a font name into a font Id
+ */
+ void get(const Common::String &key, FACES &field, FACES defaultFont);
+
+ /**
+ * Get a numeric value
+ */
+ void get(const Common::String &key, int &field, int defaultVal = 0);
+
+ /**
+ * Get a double
+ */
+ void get(const Common::String &key, double &field, double defaultVal = 0.0);
+
+public:
+ Common::String _morePrompt;
+ byte _moreColor[3], _moreSave[3];
+ FACES _moreFont;
+ int _moreAlign;
+ double _monoAspect;
+ double _propAspect;
+ double _monoSize;
+ Common::String _monoR;
+ Common::String _monoB;
+ Common::String _monoI;
+ Common::String _monoZ;
+ Common::String _monoFont;
+ double _propSize;
+ Common::String _propR;
+ Common::String _propB;
+ Common::String _propI;
+ Common::String _propZ;
+ Common::String _propFont;
+ int _leading;
+ int _baseLine;
+ int _cols, _rows;
+ int _lockCols, _lockRows;
+ int _wMarginX, _wMarginY;
+ int _wMarginSaveX, _wMarginSaveY;
+ int _wPaddingX, _wPaddingY;
+ int _wBorderX, _wBorderY;
+ int _tMarginX, _tMarginY;
+ double _gamma;
+ byte _caretColor[3], _caretSave[3];
+ byte _linkColor[3], _linkSave[3];
+ byte _borderColor[3], _borderSave[3];
+ byte _windowColor[3], _windowSave[3];
+ int _lcd;
+ int _caretShape;
+ int _linkStyle;
+ int _scrollWidth;
+ byte _scrollBg[3], _scrollFg[3];
+ int _justify;
+ int _quotes;
+ int _dashes;
+ int _spaces;
+ int _caps;
+ int _graphics;
+ int _sound;
+ int _speak;
+ int _speakInput;
+ Common::String _speakLanguage;
+ int _styleHint;
+public:
+ /**
+ * Constructor
+ */
+ Conf();
+};
+
+extern Conf *g_conf;
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
new file mode 100644
index 0000000..9c84a12
--- /dev/null
+++ b/engines/gargoyle/fonts.cpp
@@ -0,0 +1,40 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/fonts.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+FACES Fonts::getId(const Common::String &name) {
+ if (name == "monor") return MONOR;
+ if (name == "monob") return MONOB;
+ if (name == "monoi") return MONOI;
+ if (name == "monoz") return MONOZ;
+ if (name == "propr") return PROPR;
+ if (name == "propb") return PROPB;
+ if (name == "propi") return PROPI;
+ if (name == "propz") return PROPZ;
+ return MONOR;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
new file mode 100644
index 0000000..f2f701a
--- /dev/null
+++ b/engines/gargoyle/fonts.h
@@ -0,0 +1,45 @@
+/* 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 GARGOYLE_FONTS_H
+#define GARGOYLE_FONTS_H
+
+#include "gargoyle/glk_types.h"
+#include "common/str.h"
+
+namespace Gargoyle {
+
+enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
+enum TYPES { MONOF, PROPF };
+enum STYLES { FONTR, FONTB, FONTI, FONTZ };
+
+class Fonts {
+public:
+ /**
+ * Get the index/id of a font by name
+ */
+ static FACES getId(const Common::String &name);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index a481ae9..d3dd35b 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -29,6 +29,7 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/conf.h"
#include "gargoyle/events.h"
#include "gargoyle/streams.h"
#include "gargoyle/windows.h"
@@ -36,11 +37,12 @@
namespace Gargoyle {
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"),
+ _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _conf(nullptr),
_events(nullptr), _screen(nullptr), _windows(nullptr) {
}
GargoyleEngine::~GargoyleEngine() {
+ delete _conf;
delete _events;
delete _screen;
delete _streams;
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index e7d5df2..39799d7 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -33,6 +33,7 @@
namespace Gargoyle {
+class Conf;
class Events;
class Windows;
class Streams;
@@ -90,6 +91,7 @@ protected:
*/
virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
public:
+ Conf *_conf;
Events *_events;
Streams *_streams;
Windows *_windows;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index b49fb63..e81e806 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -23,6 +23,7 @@
#include "gargoyle/glk.h"
#include "gargoyle/events.h"
#include "gargoyle/streams.h"
+#include "gargoyle/string.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index c7b505e..b6f0d29 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -219,10 +219,6 @@ enum StyleHint {
stylehint_just_RightFlush = 3,
};
-enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
-enum TYPES { MONOF, PROPF };
-enum STYLES { FONTR, FONTB, FONTI, FONTZ };
-
#ifdef GLK_MODULE_IMAGE
enum ImageAlign {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 05b7f5f..925c66d 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -1,12 +1,15 @@
MODULE := engines/gargoyle
MODULE_OBJS := \
+ conf.o \
detection.o \
events.o \
+ fonts.o \
gargoyle.o \
glk.o \
picture.o \
streams.o \
+ string.o \
windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 62e43e3..382ce28 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -144,13 +144,4 @@ Stream *Streams::getFirst(uint32 *rock) {
return _streamList;
}
-/*--------------------------------------------------------------------------*/
-
-size_t strlen_uni(const uint32 *s) {
- size_t len = 0;
- while (*s++)
- ++len;
- return len;
-}
-
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index db21d58..3a80366 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -215,13 +215,6 @@ public:
Stream *getCurrent() const { return _currentStream; }
};
-
-
-/*
- * Get the length of a unicode string
- */
-size_t strlen_uni(const uint32 *s);
-
} // End of namespace Gargoyle
#endif
diff --git a/engines/gargoyle/string.cpp b/engines/gargoyle/string.cpp
new file mode 100644
index 0000000..4b68978
--- /dev/null
+++ b/engines/gargoyle/string.cpp
@@ -0,0 +1,51 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/conf.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+
+size_t strlen_uni(const uint32 *s) {
+ size_t len = 0;
+ while (*s++)
+ ++len;
+ return len;
+}
+
+int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/string.h b/engines/gargoyle/string.h
new file mode 100644
index 0000000..2ab2925
--- /dev/null
+++ b/engines/gargoyle/string.h
@@ -0,0 +1,43 @@
+/* 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 GARGOYLE_STRING_H
+#define GARGOYLE_STRING_H
+
+#include "gargoyle/string.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+/*
+ * Get the length of a unicode string
+ */
+size_t strlen_uni(const uint32 *s);
+
+/**
+ * Converts a decimal or hexadecimal string into a number
+ */
+int strToInt(const char *s);
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 95f1ed4..0eb5088 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -28,6 +28,7 @@
#include "common/rect.h"
#include "graphics/screen.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/fonts.h"
#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
@@ -125,7 +126,7 @@ public:
* Window styles
*/
struct WindowStyle {
- int font;
+ FACES font;
byte bg[3];
byte fg[3];
int reverse;
Commit: bbd744ad4731784e13c8e92048a75531300e3fe4
https://github.com/scummvm/scummvm/commit/bbd744ad4731784e13c8e92048a75531300e3fe4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Further config loading
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/conf.h
engines/gargoyle/windows.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index c296254..0b8eda8 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -23,6 +23,7 @@
#include "gargoyle/conf.h"
#include "gargoyle/fonts.h"
#include "gargoyle/string.h"
+#include "gargoyle/windows.h"
#include "common/config-manager.h"
namespace Gargoyle {
@@ -32,6 +33,36 @@ const byte BLUE[3] = { 0x00, 0x00, 0x60 };
const byte SCROLL_BG[3] = { 0xb0, 0xb0, 0xb0 };
const byte SCROLL_FG[3] = { 0x80, 0x80, 0x80 };
+WindowStyle T_STYLES[style_NUMSTYLES] = {
+ { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
+ { PROPI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
+ { PROPZ,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
+ { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
+ { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User1
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User2
+};
+
+WindowStyle G_STYLES[style_NUMSTYLES] = {
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
+ { MONOI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
+ { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
+ { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
+ { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
+ { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User1
+ { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User2
+};
+
+Conf *g_conf;
+
Conf::Conf() {
g_conf = this;
@@ -111,6 +142,55 @@ Conf::Conf() {
get("speak_language", _speakLanguage);
get("stylehint", _styleHint, 1);
+ Common::copy(T_STYLES, T_STYLES + style_NUMSTYLES, _tStyles);
+ Common::copy(G_STYLES, G_STYLES + style_NUMSTYLES, _gStyles);
+
+ char buffer[255];
+ const char *const TG_COLOR[2] = { "tcolor", "gcolor" };
+ for (int idx = 0; idx < 2; ++idx) {
+ if (!ConfMan.hasKey(TG_COLOR[idx]))
+ continue;
+
+ strncpy(buffer, ConfMan.get(TG_COLOR[idx]).c_str(), 254);
+ buffer[255] = '\0';
+ char *style = strtok(buffer, "\r\n\t ");
+ char *fg = strtok(nullptr, "\r\n\t ");
+ char *bg = strtok(nullptr, "\r\n\t ");
+
+ int i = atoi(style);
+ if (i < 0 || i >= style_NUMSTYLES)
+ continue;
+
+ if (idx == 0) {
+ parseColor(fg, _tStyles[i].fg);
+ parseColor(bg, _tStyles[i].bg);
+ } else {
+ parseColor(fg, _gStyles[i].fg);
+ parseColor(bg, _gStyles[i].bg);
+ }
+ }
+
+ const char *const TG_FONT[2] = { "tfont", "gfont" };
+ for (int idx = 0; idx < 2; ++idx) {
+ if (!ConfMan.hasKey(TG_FONT[idx]))
+ continue;
+
+ strncpy(buffer, ConfMan.get(TG_FONT[idx]).c_str(), 254);
+ buffer[255] = '\0';
+ char *style = strtok(buffer, "\r\n\t ");
+ char *font = strtok(nullptr, "\r\n\t ");
+ int i = atoi(style);
+ if (i < 0 || i >= style_NUMSTYLES)
+ continue;
+
+ if (idx == 0)
+ _tStyles[i].font = Fonts::getId(font);
+ else
+ _gStyles[i].font = Fonts::getId(font);
+ }
+
+ Common::copy(_tStyles, _tStyles + style_NUMSTYLES, _tStylesDefault);
+ Common::copy(_gStyles, _gStyles + style_NUMSTYLES, _gStylesDefault);
}
void Conf::get(const Common::String &key, Common::String &field, const char *defaultVal) {
@@ -119,17 +199,8 @@ void Conf::get(const Common::String &key, Common::String &field, const char *def
}
void Conf::get(const Common::String &key, byte *color, const byte *defaultColor) {
- char r[3], g[3], b[3];
- Common::String str;
-
- if (ConfMan.hasKey(key) && (str = ConfMan.get(key)).size() == 6) {
- r[0] = str[0]; r[1] = str[1]; r[2] = 0;
- g[0] = str[2]; g[1] = str[3]; g[2] = 0;
- b[0] = str[4]; b[1] = str[5]; b[2] = 0;
-
- color[0] = strtol(r, NULL, 16);
- color[1] = strtol(g, NULL, 16);
- color[2] = strtol(b, NULL, 16);
+ if (ConfMan.hasKey(key)) {
+ parseColor(ConfMan.get(key), color);
} else if (defaultColor) {
Common::copy(defaultColor, defaultColor + 3, color);
} else {
@@ -149,4 +220,18 @@ void Conf::get(const Common::String &key, double &field, double defaultVal) {
field = ConfMan.hasKey(key) ? atof(ConfMan.get(key).c_str()) : defaultVal;
}
+void Conf::parseColor(const Common::String &str, byte *color) {
+ char r[3], g[3], b[3];
+
+ if (str.size() == 6) {
+ r[0] = str[0]; r[1] = str[1]; r[2] = 0;
+ g[0] = str[2]; g[1] = str[3]; g[2] = 0;
+ b[0] = str[4]; b[1] = str[5]; b[2] = 0;
+
+ color[0] = strtol(r, NULL, 16);
+ color[1] = strtol(g, NULL, 16);
+ color[2] = strtol(b, NULL, 16);
+ }
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/conf.h b/engines/gargoyle/conf.h
index 2dbb29f..c63cdc0 100644
--- a/engines/gargoyle/conf.h
+++ b/engines/gargoyle/conf.h
@@ -25,6 +25,7 @@
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -55,6 +56,10 @@ private:
*/
void get(const Common::String &key, double &field, double defaultVal = 0.0);
+ /**
+ * Parse a color
+ */
+ void parseColor(const Common::String &str, byte *color);
public:
Common::String _morePrompt;
byte _moreColor[3], _moreSave[3];
@@ -104,6 +109,10 @@ public:
int _speakInput;
Common::String _speakLanguage;
int _styleHint;
+ WindowStyle _tStyles[style_NUMSTYLES];
+ WindowStyle _gStyles[style_NUMSTYLES];
+ WindowStyle _tStylesDefault[style_NUMSTYLES];
+ WindowStyle _gStylesDefault[style_NUMSTYLES];
public:
/**
* Constructor
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 2c8680b..edea1ab 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/windows.h"
+#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/streams.h"
#include "common/algorithm.h"
@@ -59,34 +60,6 @@ int Windows::_overrideFgVal;
int Windows::_overrideBgVal;
-WindowStyle T_STYLES[style_NUMSTYLES] = {
- { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
- { PROPI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
- { PROPZ,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
- { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
- { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User1
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User2
-};
-
-WindowStyle G_STYLES[style_NUMSTYLES] = {
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
- { MONOI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
- { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
- { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
- { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User1
- { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User2
-};
-
/*--------------------------------------------------------------------------*/
Windows::Windows(GargoyleEngine *engine, Graphics::Screen *screen) :
@@ -330,7 +303,7 @@ TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows,
inarrayrock.num = 0;
line_terminators = nullptr;
- Common::copy(&G_STYLES[0], &G_STYLES[style_NUMSTYLES], styles);
+ Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
}
void TextGridWindow::rearrange(const Common::Rect &box) {
@@ -381,7 +354,7 @@ TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windo
_type = wintype_TextBuffer;
Common::fill(&history[0], &history[HISTORYLEN], nullptr);
- Common::copy(&T_STYLES[0], &T_STYLES[style_NUMSTYLES], styles);
+ Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
}
void TextBufferWindow::rearrange(const Common::Rect &box) {
Commit: 0bc3da9e800b928ac31663180427cd048748814d
https://github.com/scummvm/scummvm/commit/0bc3da9e800b928ac31663180427cd048748814d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Remove duplicated Windows fields that are now in Conf
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/conf.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/streams.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 0b8eda8..4e8b823 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -25,6 +25,7 @@
#include "gargoyle/string.h"
#include "gargoyle/windows.h"
#include "common/config-manager.h"
+#include "common/system.h"
namespace Gargoyle {
@@ -65,6 +66,9 @@ Conf *g_conf;
Conf::Conf() {
g_conf = this;
+ _imageW = g_system->getWidth();
+ _imageH = g_system->getHeight();
+ _cellW = _cellH = 8;
get("moreprompt", _morePrompt, "\207 more \207");
get("morecolor", _moreColor);
diff --git a/engines/gargoyle/conf.h b/engines/gargoyle/conf.h
index c63cdc0..5c4446a 100644
--- a/engines/gargoyle/conf.h
+++ b/engines/gargoyle/conf.h
@@ -113,6 +113,9 @@ public:
WindowStyle _gStyles[style_NUMSTYLES];
WindowStyle _tStylesDefault[style_NUMSTYLES];
WindowStyle _gStylesDefault[style_NUMSTYLES];
+
+ int _imageW, _imageH;
+ int _cellW, _cellH;
public:
/**
* Constructor
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index d3dd35b..a7b819c 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -58,6 +58,7 @@ void GargoyleEngine::initialize() {
initGraphics(640, 480, false);
_screen = new Graphics::Screen();
+ _conf = new Conf();
_events = new Events();
_streams = new Streams(this);
_windows = new Windows(this, _screen);
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 3a80366..e45bcc4 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -104,7 +104,7 @@ public:
* Constructor
*/
WindowStream(Streams *streams, Window *window, uint32 rock = 0, bool unicode = true) :
- Stream(streams, true, false, rock, unicode), _window(window) {}
+ Stream(streams, false, true, rock, unicode), _window(window) {}
/**
* Close the stream
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index edea1ab..e39e542 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -32,27 +32,6 @@ namespace Gargoyle {
#define MAGIC_WINDOW_NUM (9876)
#define GLI_SUBPIX 8
-bool Windows::_confLockCols;
-bool Windows::_confLockRows;
-int Windows::_wMarginx;
-int Windows::_wMarginy;
-int Windows::_wPaddingx;
-int Windows::_wPaddingy;
-int Windows::_wBorderx;
-int Windows::_wBordery;
-int Windows::_tMarginx;
-int Windows::_tMarginy;
-int Windows::_wMarginXsave;
-int Windows::_wMarginYsave;
-int Windows::_cols;
-int Windows::_rows;
-int Windows::_imageW;
-int Windows::_imageH;
-int Windows::_cellW;
-int Windows::_cellH;
-int Windows::_baseLine;
-int Windows::_leading;
-int Windows::_scrollWidth;
bool Windows::_overrideReverse;
bool Windows::_overrideFgSet;
bool Windows::_overrideBgSet;
@@ -66,26 +45,6 @@ Windows::Windows(GargoyleEngine *engine, Graphics::Screen *screen) :
_engine(engine), _screen(screen), _forceRedraw(true), _moreFocus(false),
_windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr),
_claimSelect(0) {
- _imageW = _screen->w;
- _imageH = _screen->h;
- _cellW = _cellH = 8;
- _confLockCols = false;
- _confLockRows = false;
- _wMarginx = 15;
- _wMarginy = 15;
- _wPaddingx = 0;
- _wPaddingy = 0;
- _wBorderx = 1;
- _wBordery = 1;
- _tMarginx = 7;
- _tMarginy = 7;
- _wMarginXsave = 15;
- _wMarginYsave = 15;
- _cols = 60;
- _rows = 25;
- _baseLine = 15;
- _leading = 20;
- _scrollWidth = 0;
_overrideReverse = false;
_overrideFgSet = false;
_overrideBgSet = false;
@@ -218,26 +177,26 @@ void Windows::rearrange() {
if (_rootWin) {
Common::Rect box;
- if (_confLockCols) {
- int desired_width = _wMarginXsave * 2 + _cellW * _cols;
- if (desired_width > _imageW)
- _wMarginx = _wMarginXsave;
+ if (g_conf->_lockCols) {
+ int desired_width = g_conf->_wMarginSaveX * 2 + g_conf->_cellW * g_conf->_cols;
+ if (desired_width > g_conf->_imageW)
+ g_conf->_wMarginX = g_conf->_wMarginSaveX;
else
- _wMarginx = (_imageW - _cellW * _cols) / 2;
+ g_conf->_wMarginX = (g_conf->_imageW - g_conf->_cellW * g_conf->_cols) / 2;
}
- if (_confLockRows) {
- int desired_height = _wMarginYsave * 2 + _cellH * _rows;
- if (desired_height > _imageH)
- _wMarginy = _wMarginYsave;
+ if (g_conf->_lockRows) {
+ int desired_height = g_conf->_wMarginSaveY * 2 + g_conf->_cellH * g_conf->_rows;
+ if (desired_height > g_conf->_imageH)
+ g_conf->_wMarginY = g_conf->_wMarginSaveY;
else
- _wMarginy = (_imageH - _cellH * _rows) / 2;
+ g_conf->_wMarginY = (g_conf->_imageH - g_conf->_cellH * g_conf->_rows) / 2;
}
- box.left = _wMarginx;
- box.top = _wMarginy;
- box.right = _imageW - _wMarginx;
- box.bottom = _imageH - _wMarginy;
+ box.left = g_conf->_wMarginX;
+ box.top = g_conf->_wMarginY;
+ box.right = g_conf->_imageW - g_conf->_wMarginX;
+ box.bottom = g_conf->_imageH - g_conf->_wMarginY;
_rootWin->rearrange(box);
}
@@ -310,8 +269,8 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
Window::rearrange(box);
int newwid, newhgt;
- newwid = box.width() / Windows::_cellW;
- newhgt = box.height() / Windows::_cellH;
+ newwid = box.width() / g_conf->_cellW;
+ newhgt = box.height() / g_conf->_cellH;
if (newwid == width && newhgt == height)
return;
@@ -328,9 +287,14 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
}
void TextGridWindow::touch(int line) {
- int y = bbox.top + line * Windows::_leading;
+ int y = bbox.top + line * g_conf->_leading;
lines[line].dirty = true;
- _windows->repaint(Common::Rect(bbox.left, y, bbox.right, y + Windows::_leading));
+ _windows->repaint(Common::Rect(bbox.left, y, bbox.right, y + g_conf->_leading));
+}
+
+glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
+ return vertical ? size * g_conf->_cellW + g_conf->_tMarginX * 2 :
+ size * g_conf->_cellH + g_conf->_tMarginY * 2;
}
/*--------------------------------------------------------------------------*/
@@ -362,11 +326,11 @@ void TextBufferWindow::rearrange(const Common::Rect &box) {
int newwid, newhgt;
int rnd;
- newwid = (box.width() - Windows::_tMarginx * 2 - Windows::_scrollWidth) / Windows::_cellW;
- newhgt = (box.height() - Windows::_tMarginy * 2) / Windows::_cellH;
+ newwid = (box.width() - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) / g_conf->_cellW;
+ newhgt = (box.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
/* align text with bottom */
- rnd = newhgt * Windows::_cellH + Windows::_tMarginy * 2;
+ rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
yadj = (box.height() - rnd);
bbox.top += (box.height() - rnd);
@@ -576,8 +540,8 @@ bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
if (lines[0].rpic || numchars)
return false;
- radjw = (pic->w + Windows::_tMarginx) * GLI_SUBPIX;
- radjn = (pic->h + Windows::_cellH - 1) / Windows::_cellH;
+ radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
lines[0].rpic = pic;
lines[0].rm = radjw;
lines[0].rhyper = linkval;
@@ -588,8 +552,8 @@ bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
if (lines[0].lpic || numchars)
return false;
- ladjw = (pic->w + Windows::_tMarginx) * GLI_SUBPIX;
- ladjn = (pic->h + Windows::_cellH - 1) / Windows::_cellH;
+ ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
lines[0].lpic = pic;
lines[0].lm = ladjw;
lines[0].lhyper = linkval;
@@ -614,7 +578,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
gli_tts_speak(&ch, 1);
- pw = (bbox.right - bbox.left - Windows::_tMarginx * 2 - gli_scroll_width) * GLI_SUBPIX;
+ pw = (bbox.right - bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
pw = pw - 2 * SLOP - radjw - ladjw;
color = gli_override_bg_set ? gli_window_color : bgcolor;
@@ -760,10 +724,14 @@ void TextBufferWindow::flowBreak() {
}
void TextBufferWindow::touch(int line) {
- int y = bbox.top + Windows::_tMarginy + (height - line - 1) * Windows::_leading;
+ int y = bbox.top + g_conf->_tMarginY + (height - line - 1) * g_conf->_leading;
lines[line].dirty = 1;
_windows->clearSelection();
- _windows->repaint(Common::Rect(bbox.left, y - 2, bbox.right, y + Windows::_leading + 2));
+ _windows->repaint(Common::Rect(bbox.left, y - 2, bbox.right, y + g_conf->_leading + 2));
+}
+
+glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
+ return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
}
/*--------------------------------------------------------------------------*/
@@ -867,9 +835,9 @@ void PairWindow::rearrange(const Common::Rect &box) {
// We now figure split.
if (_vertical)
- splitwid = Windows::_wPaddingx; // want border?
+ splitwid = g_conf->_wPaddingX; // want border?
else
- splitwid = Windows::_wPaddingy; // want border?
+ splitwid = g_conf->_wPaddingY; // want border?
switch (_division) {
case winmethod_Proportional:
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 0eb5088..6f7a016 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -74,24 +74,6 @@ private:
*/
void rearrange();
public:
- static bool _confLockCols, _confLockRows;
- static int _wMarginx;
- static int _wMarginy;
- static int _wPaddingx;
- static int _wPaddingy;
- static int _wBorderx;
- static int _wBordery;
- static int _tMarginx;
- static int _tMarginy;
- static int _wMarginXsave;
- static int _wMarginYsave;
- static int _cols;
- static int _rows;
- static int _imageW, _imageH;
- static int _cellW, _cellH;
- static int _baseLine;
- static int _leading;
- static int _scrollWidth;
static bool _overrideReverse;
static bool _overrideFgSet;
static bool _overrideBgSet;
@@ -296,10 +278,7 @@ public:
/**
* Get window split size within parent pair window
*/
- virtual glui32 getSplit(glui32 size, bool vertical) const override {
- return vertical ? size * Windows::_cellW + Windows::_tMarginx * 2 :
- size * Windows::_cellH + Windows::_tMarginy * 2;
- }
+ virtual glui32 getSplit(glui32 size, bool vertical) const override;
};
/**
@@ -400,9 +379,7 @@ public:
/**
* Get window split size within parent pair window
*/
- virtual glui32 getSplit(glui32 size, bool vertical) const override {
- return (vertical) ? size * Windows::_cellW : size * Windows::_cellH;
- }
+ virtual glui32 getSplit(glui32 size, bool vertical) const override;
/**
* Clear the window
Commit: d314cd39ee42c2b37fde0fa9d384fae67683cbea
https://github.com/scummvm/scummvm/commit/d314cd39ee42c2b37fde0fa9d384fae67683cbea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Add detection for other games
Changed paths:
engines/gargoyle/scott/detection.cpp
diff --git a/engines/gargoyle/scott/detection.cpp b/engines/gargoyle/scott/detection.cpp
index d2ed439..6c9f5c4 100644
--- a/engines/gargoyle/scott/detection.cpp
+++ b/engines/gargoyle/scott/detection.cpp
@@ -35,6 +35,20 @@ struct ScottGame {
const ScottGame SCOTT_GAMES[] = {
{ "ae541fc1085da2f7d561b72ed20a6bc1", 18003, "Adventureland" },
+ { "cbd47ab4fcfe00231ffd71d52378d410", 18482, "Pirate Adventure" },
+ { "9251ab2c64e63559d8a6e9e6246760a5", 17227, "Mission Impossible" },
+ { "be849c5747c7fc3b201984afb4403b8e", 18140, "Voodoo Castle" },
+ { "85b75b6079b5ee572b5259b29a0e5d21", 19999, "The Count" },
+ { "c423cae841ac1927b5b2e503607b21bc", 20115, "Strange Odyssey" },
+ { "326b98b991d401605074e64d474ce566", 19700, "Mystery Fun House" },
+ { "8ef9010399f055da9adb15ce7745a11c", 20320, "Pyramid Of Doom" },
+ { "fcdcca8b2acf76ba2d0006cefa3630a1", 20687, "Ghost Town" },
+ { "c8aaa80f07c40fa8e4b17432644919dc", 22669, "Save Island, Part 1" },
+ { "2add0f28d9b236c866890cdf8d86ee60", 21169, "Savage Island, Part 2" },
+ { "675126bd0477e8ed9230ad3db5afc45f", 21401, "The Golden Voyage" },
+ { "0ef0def798d895ed766041fa99dd28a0", 22346, "Adventure 13" },
+ { "0bf1bcc649422798332a38c88588fdff", 22087, "Adventure 14" },
+ { "a0a5423967287dae9cbeb9abe8324479", 21038, "Buckaroo Banzai" },
{ nullptr, 0, nullptr }
};
Commit: cc54beadce8852c29be883e957fbfe5f548f8946
https://github.com/scummvm/scummvm/commit/cc54beadce8852c29be883e957fbfe5f548f8946
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Start of window character output
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/conf.h
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk_types.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 4e8b823..125e9f4 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -139,12 +139,13 @@ Conf::Conf() {
get("dashes", _dashes, 1);
get("spaces", _spaces);
get("caps", _caps);
- get("graphics", _graphics, 1);
- get("sound", _sound, 1);
+ get("graphics", _graphics, true);
+ get("sound", _sound, true);
get("speak", _speak);
get("speak_input", _speakInput);
get("speak_language", _speakLanguage);
get("stylehint", _styleHint, 1);
+ get("safeclicks", _safeClicks);
Common::copy(T_STYLES, T_STYLES + style_NUMSTYLES, _tStyles);
Common::copy(G_STYLES, G_STYLES + style_NUMSTYLES, _gStyles);
@@ -216,6 +217,10 @@ void Conf::get(const Common::String &key, int &field, int defaultVal) {
field = ConfMan.hasKey(key) ? strToInt(ConfMan.get(key).c_str()) : defaultVal;
}
+void Conf::get(const Common::String &key, bool &field, bool defaultVal) {
+ field = ConfMan.hasKey(key) ? strToInt(ConfMan.get(key).c_str()) != 0 : defaultVal;
+}
+
void Conf::get(const Common::String &key, FACES &field, FACES defaultFont) {
field = ConfMan.hasKey(key) ? Fonts::getId(ConfMan.get(key)) : defaultFont;
}
diff --git a/engines/gargoyle/conf.h b/engines/gargoyle/conf.h
index 5c4446a..05dc6c9 100644
--- a/engines/gargoyle/conf.h
+++ b/engines/gargoyle/conf.h
@@ -52,6 +52,11 @@ private:
void get(const Common::String &key, int &field, int defaultVal = 0);
/**
+ * Get a numeric value
+ */
+ void get(const Common::String &key, bool &field, bool defaultVal = false);
+
+ /**
* Get a double
*/
void get(const Common::String &key, double &field, double defaultVal = 0.0);
@@ -103,12 +108,13 @@ public:
int _dashes;
int _spaces;
int _caps;
- int _graphics;
- int _sound;
- int _speak;
- int _speakInput;
+ bool _graphics;
+ bool _sound;
+ bool _speak;
+ bool _speakInput;
Common::String _speakLanguage;
int _styleHint;
+ bool _safeClicks;
WindowStyle _tStyles[style_NUMSTYLES];
WindowStyle _gStyles[style_NUMSTYLES];
WindowStyle _tStylesDefault[style_NUMSTYLES];
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 93021ef..1f7cc6a 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -28,4 +28,8 @@ void Events::pollEvents() {
// TODO
}
+void Events::clearEvent(Event *ev) {
+ // TODO
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index ac66d0e..476be40 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -27,12 +27,97 @@
namespace Gargoyle {
+class Window;
+
+/**
+ * Event types
+ */
+enum EvType {
+ evtype_None = 0,
+ evtype_Timer = 1,
+ evtype_CharInput = 2,
+ evtype_LineInput = 3,
+ evtype_MouseInput = 4,
+ evtype_Arrange = 5,
+ evtype_Redraw = 6,
+ evtype_SoundNotify = 7,
+ evtype_Hyperlink = 8,
+ evtype_VolumeNotify = 9,
+
+ // ScummVM custom events
+ evtype_Quit = 99
+};
+
+/**
+ * Keycodes
+ */
+enum Keycode {
+ keycode_Unknown = 0xffffffffU,
+ keycode_Left = 0xfffffffeU,
+ keycode_Right = 0xfffffffdU,
+ keycode_Up = 0xfffffffcU,
+ keycode_Down = 0xfffffffbU,
+ keycode_Return = 0xfffffffaU,
+ keycode_Delete = 0xfffffff9U,
+ keycode_Escape = 0xfffffff8U,
+ keycode_Tab = 0xfffffff7U,
+ keycode_PageUp = 0xfffffff6U,
+ keycode_PageDown = 0xfffffff5U,
+ keycode_Home = 0xfffffff4U,
+ keycode_End = 0xfffffff3U,
+ keycode_Func1 = 0xffffffefU,
+ keycode_Func2 = 0xffffffeeU,
+ keycode_Func3 = 0xffffffedU,
+ keycode_Func4 = 0xffffffecU,
+ keycode_Func5 = 0xffffffebU,
+ keycode_Func6 = 0xffffffeaU,
+ keycode_Func7 = 0xffffffe9U,
+ keycode_Func8 = 0xffffffe8U,
+ keycode_Func9 = 0xffffffe7U,
+ keycode_Func10 = 0xffffffe6U,
+ keycode_Func11 = 0xffffffe5U,
+ keycode_Func12 = 0xffffffe4U,
+
+ // non standard keycodes
+ keycode_Erase = 0xffffef7fU,
+ keycode_MouseWheelUp = 0xffffeffeU,
+ keycode_MouseWheelDown = 0xffffefffU,
+ keycode_SkipWordLeft = 0xfffff000U,
+ keycode_SkipWordRight = 0xfffff001U,
+
+ // The last keycode is always = 0x100000000 - keycode_MAXVAL)
+ keycode_MAXVAL = 28U
+};
+
+/**
+ * Event structure
+ */
+struct Event {
+ EvType _type;
+ Window *_window;
+ uint32 _val1, _val2;
+
+ /**
+ * Constructor
+ */
+ Event() : _type(evtype_None), _window(nullptr), _val1(0), _val2(0) {}
+};
+
class Events {
public:
+ bool _forceClick;
+public:
+ /**
+ * Constructor
+ */
+ Events() : _forceClick(false) {}
+
/**
* Checks for new events
*/
void pollEvents();
+
+ void clearEvent(Event *ev);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index a7b819c..2ca14bf 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -36,9 +36,12 @@
namespace Gargoyle {
+GargoyleEngine *g_vm;
+
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _conf(nullptr),
_events(nullptr), _screen(nullptr), _windows(nullptr) {
+ g_vm = this;
}
GargoyleEngine::~GargoyleEngine() {
@@ -60,8 +63,8 @@ void GargoyleEngine::initialize() {
_screen = new Graphics::Screen();
_conf = new Conf();
_events = new Events();
- _streams = new Streams(this);
- _windows = new Windows(this, _screen);
+ _streams = new Streams();
+ _windows = new Windows(_screen);
}
Common::Error GargoyleEngine::run() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 39799d7..976221a 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -125,6 +125,8 @@ public:
const Common::String &GargoyleEngine::getFilename() const;
};
+extern GargoyleEngine *g_vm;
+
} // End of namespace Gargoyle
#endif
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index e81e806..ba62de1 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -187,11 +187,15 @@ strid_t Glk::glk_stream_get_current(void) {
}
void Glk::glk_put_char(unsigned char ch) {
- // TODO
+ _streams->getCurrent()->putChar(ch);
}
void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
- // TODO
+ if (str) {
+ str->putChar(ch);
+ } else {
+ warning("put_char_stream: invalid ref");
+ }
}
void Glk::glk_put_string(const char *s) {
@@ -375,27 +379,39 @@ glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
}
void Glk::glk_put_char_uni(glui32 ch) {
- glk_put_char_stream_uni(_streams->getCurrent(), ch);
+ _streams->getCurrent()->putCharUni(ch);
}
void Glk::glk_put_string_uni(glui32 *s) {
- glk_put_buffer_stream_uni(_streams->getCurrent(), s, strlen_uni(s));
+ _streams->getCurrent()->putBufferUni(s, strlen_uni(s));
}
void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
- glk_put_buffer_stream_uni(_streams->getCurrent(), buf, len);
+ _streams->getCurrent()->putBufferUni(buf, len);
}
void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
-// str->writeUint32LE(ch);
+ if (str) {
+ str->putCharUni(ch);
+ } else {
+ warning("put_char_stream_uni: invalid ref");
+ }
}
void Glk::glk_put_string_stream_uni(strid_t str, const glui32 *s) {
- glk_put_buffer_stream_uni(str, s, strlen_uni(s));
+ if (str) {
+ str->putBufferUni(s, strlen_uni(s));
+ } else {
+ warning("put_string_stream_uni: invalid ref");
+ }
}
void Glk::glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len) {
-// while (len-- > 0) str->writeUint32LE(*buf++);
+ if (str) {
+ str->putBufferUni(buf, len);
+ } else {
+ warning("put_buffer_stream_uni: invalid ref");
+ }
}
glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index b6f0d29..8f84cbe 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -82,60 +82,6 @@ enum Gestalt {
gestalt_GarglkText = 0x1100,
};
-enum EvType {
- evtype_None = 0,
- evtype_Timer = 1,
- evtype_CharInput = 2,
- evtype_LineInput = 3,
- evtype_MouseInput = 4,
- evtype_Arrange = 5,
- evtype_Redraw = 6,
- evtype_SoundNotify = 7,
- evtype_Hyperlink = 8,
- evtype_VolumeNotify = 9,
-
- // ScummVM custom events
- evtype_Quit = 99
-};
-
-enum Keycode {
- keycode_Unknown = 0xffffffffU,
- keycode_Left = 0xfffffffeU,
- keycode_Right = 0xfffffffdU,
- keycode_Up = 0xfffffffcU,
- keycode_Down = 0xfffffffbU,
- keycode_Return = 0xfffffffaU,
- keycode_Delete = 0xfffffff9U,
- keycode_Escape = 0xfffffff8U,
- keycode_Tab = 0xfffffff7U,
- keycode_PageUp = 0xfffffff6U,
- keycode_PageDown = 0xfffffff5U,
- keycode_Home = 0xfffffff4U,
- keycode_End = 0xfffffff3U,
- keycode_Func1 = 0xffffffefU,
- keycode_Func2 = 0xffffffeeU,
- keycode_Func3 = 0xffffffedU,
- keycode_Func4 = 0xffffffecU,
- keycode_Func5 = 0xffffffebU,
- keycode_Func6 = 0xffffffeaU,
- keycode_Func7 = 0xffffffe9U,
- keycode_Func8 = 0xffffffe8U,
- keycode_Func9 = 0xffffffe7U,
- keycode_Func10 = 0xffffffe6U,
- keycode_Func11 = 0xffffffe5U,
- keycode_Func12 = 0xffffffe4U,
-
- // non standard keycodes
- keycode_Erase = 0xffffef7fU,
- keycode_MouseWheelUp = 0xffffeffeU,
- keycode_MouseWheelDown = 0xffffefffU,
- keycode_SkipWordLeft = 0xfffff000U,
- keycode_SkipWordRight = 0xfffff001U,
-
- // The last keycode is always = 0x100000000 - keycode_MAXVAL)
- keycode_MAXVAL = 28U
-};
-
enum Style {
style_Normal = 0,
style_Emphasized = 1,
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 382ce28..b505405 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -21,6 +21,9 @@
*/
#include "gargoyle/streams.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/events.h"
+#include "gargoyle/gargoyle.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -62,12 +65,46 @@ void WindowStream::close(StreamResult *result) {
warning("cannot close window stream");
}
-void WindowStream::writeChar(unsigned char ch) {
+void WindowStream::putChar(unsigned char ch) {
+ if (!_writable)
+ return;
+ ++_writeCount;
+ if (_window->line_request || _window->line_request_uni) {
+ if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
+ _window->cancelLineEvent(nullptr);
+ g_vm->_events->_forceClick = false;
+ } else {
+ warning("putChar: window has pending line request");
+ }
+ }
+
+ _window->putChar(ch);
+ if (_window->_echoStream)
+ _window->_echoStream->putChar(ch);
}
-void WindowStream::writeCharUni(uint32 ch) {
+void WindowStream::putCharUni(uint32 ch) {
+ if (!_writable)
+ return;
+ ++_writeCount;
+
+ //TODO
+}
+
+void WindowStream::putBuffer(const unsigned char *buf, size_t len) {
+ if (!_writable)
+ return;
+ ++_writeCount;
+ //TODO
+
+}
+void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
+ if (!_writable)
+ return;
+ ++_writeCount;
+ //TODO
}
/*--------------------------------------------------------------------------*/
@@ -85,26 +122,56 @@ MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode
_bufeof = mode == filemode_Write ? _buf : _bufend;
}
-void MemoryStream::writeChar(unsigned char ch) {
+void MemoryStream::putChar(unsigned char ch) {
+ //TODO
}
-void MemoryStream::writeCharUni(uint32 ch) {
+void MemoryStream::putCharUni(uint32 ch) {
+ //TODO
}
-/*--------------------------------------------------------------------------*/
+void MemoryStream::putBuffer(const unsigned char *buf, size_t len) {
+ //TODO
+
+}
+
+void MemoryStream::putBufferUni(const uint32 *buf, size_t len) {
+ //TODO
+
+}
/*--------------------------------------------------------------------------*/
+FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) :
+ Stream(streams, true, false, rock, unicode) {
+}
+
+void FileStream::putChar(unsigned char ch) {
+ //TODO
+}
+
+void FileStream::putCharUni(uint32 ch) {
+ //TODO
+}
+
+void FileStream::putBuffer(const unsigned char *buf, size_t len) {
+ //TODO
+}
+
+void FileStream::putBufferUni(const uint32 *buf, size_t len) {
+ //TODO
+}
+
/*--------------------------------------------------------------------------*/
-Streams::Streams(GargoyleEngine *engine) : _engine(engine), _streamList(nullptr), _currentStream(nullptr) {
+Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) {
}
Streams::~Streams() {
while (_streamList)
- deleteStream(_streamList);
+ delete _streamList;
}
WindowStream *Streams::addWindowStream(Window *window) {
@@ -136,6 +203,12 @@ void Streams::removeStream(Stream *stream) {
_streamList = next;
if (next)
next->_prev = prev;
+
+ // Remove the stream as the echo stream of any window
+ for (Windows::iterator i = g_vm->_windows->begin(); i != g_vm->_windows->end(); ++i) {
+ if ((*i)->_echoStream == stream)
+ (*i)->_echoStream = nullptr;
+ }
}
Stream *Streams::getFirst(uint32 *rock) {
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index e45bcc4..c43e2a0 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -28,7 +28,6 @@
namespace Gargoyle {
-class GargoyleEngine;
class Window;
class Streams;
@@ -84,12 +83,22 @@ public:
/**
* Write a character
*/
- virtual void writeChar(unsigned char ch) = 0;
+ virtual void putChar(unsigned char ch) = 0;
/**
* Write a unicode character
*/
- virtual void writeCharUni(uint32 ch) = 0;
+ virtual void putCharUni(uint32 ch) = 0;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) = 0;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) = 0;
};
typedef Stream *strid_t;
@@ -114,12 +123,22 @@ public:
/**
* Write a character
*/
- virtual void writeChar(unsigned char ch) override;
+ virtual void putChar(unsigned char ch) override;
/**
* Write a unicode character
*/
- virtual void writeCharUni(uint32 ch) override;
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
};
/**
@@ -141,12 +160,54 @@ public:
/**
* Write a character
*/
- virtual void writeChar(unsigned char ch);
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+};
+
+/**
+ * Implements a file stream
+ */
+class FileStream : public Stream {
+private:
+public:
+ /**
+ * Constructor
+ */
+ FileStream(Streams *streams, 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 unsigned char *buf, size_t len) override;
/**
* Write a unicode character
*/
- virtual void writeCharUni(uint32 ch);
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
};
/**
@@ -155,7 +216,6 @@ public:
class Streams {
friend class Stream;
private:
- GargoyleEngine *_engine;
Stream *_streamList;
Stream *_currentStream;
private:
@@ -172,7 +232,7 @@ public:
/**
* Constructor
*/
- Streams(GargoyleEngine *engine);
+ Streams();
/**
* Destructor
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index e39e542..3212964 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -38,13 +38,46 @@ bool Windows::_overrideBgSet;
int Windows::_overrideFgVal;
int Windows::_overrideBgVal;
+/*--------------------------------------------------------------------------*/
+
+Windows::iterator &Windows::iterator::operator++() {
+ if (!_current)
+ return *this;
+
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(_current);
+
+ if (pairWin) {
+ _current = !pairWin->_backward ? pairWin->_child1 : pairWin->_child2;
+ } else {
+ while (_current->_parent) {
+ pairWin = dynamic_cast<PairWindow *>(_current->_parent);
+
+ if (!pairWin->_backward) {
+ if (_current == pairWin->_child1) {
+ _current = pairWin->_child2;
+ return *this;
+ }
+ } else {
+ if (_current == pairWin->_child2) {
+ _current = pairWin->_child1;
+ return *this;
+ }
+ }
+
+ _current = pairWin;
+ }
+
+ _current = nullptr;
+ }
+
+ return *this;
+}
/*--------------------------------------------------------------------------*/
-Windows::Windows(GargoyleEngine *engine, Graphics::Screen *screen) :
- _engine(engine), _screen(screen), _forceRedraw(true), _moreFocus(false),
- _windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr),
- _claimSelect(0) {
+Windows::Windows(Graphics::Screen *screen) :
+ _screen(screen), _forceRedraw(true), _moreFocus(false), _windowList(nullptr),
+ _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr), _claimSelect(0) {
_overrideReverse = false;
_overrideFgSet = false;
_overrideBgSet = false;
@@ -89,7 +122,7 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
return nullptr;
}
- oldparent = splitwin->parent;
+ oldparent = splitwin->_parent;
if (oldparent && oldparent->_type != wintype_Pair)
{
warning("window_open: parent window is not Pair");
@@ -112,9 +145,9 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
pairwin->_child1 = splitwin;
pairwin->_child2 = newwin;
- splitwin->parent = pairwin;
- newwin->parent = pairwin;
- pairwin->parent = oldparent;
+ splitwin->_parent = pairwin;
+ newwin->_parent = pairwin;
+ pairwin->_parent = oldparent;
if (oldparent) {
PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
@@ -155,20 +188,20 @@ Window *Windows::newWindow(glui32 type, glui32 rock) {
error("Unknown window type");
}
- win->next = _windowList;
+ win->_next = _windowList;
_windowList = win;
- if (win->next)
- win->next->prev = win;
+ if (win->_next)
+ win->_next->_prev = win;
return win;
}
PairWindow *Windows::newPairWindow(glui32 method, Window *key, glui32 size) {
PairWindow *pwin = new PairWindow(this, method, key, size);
- pwin->next = _windowList;
+ pwin->_next = _windowList;
_windowList = pwin;
- if (pwin->next)
- pwin->next->prev = pwin;
+ if (pwin->_next)
+ pwin->_next->_prev = pwin;
return pwin;
}
@@ -223,7 +256,7 @@ void Windows::repaint(const Common::Rect &box) {
/*--------------------------------------------------------------------------*/
Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
- _windows(windows), _rock(rock), _type(0), parent(nullptr), next(nullptr), prev(nullptr),
+ _windows(windows), _rock(rock), _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr),
yadj(0), line_request(0), line_request_uni(0), char_request(0), char_request_uni(0),
mouse_request(0), hyper_request(0), more_request(0), scroll_request(0), image_loaded(0),
echo_line_input(true), line_terminators(nullptr), termct(0), _echoStream(nullptr) {
@@ -239,10 +272,18 @@ Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
Common::fill(&fgcolor[0], &fgcolor[3], 3);
disprock.num = 0;
- Streams &streams = *windows->_engine->_streams;
+ Streams &streams = *g_vm->_streams;
_stream = streams.addWindowStream(this);
}
+void Window::cancelLineEvent(Event *ev) {
+ Event dummyEv;
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+}
+
/*--------------------------------------------------------------------------*/
BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
@@ -253,14 +294,14 @@ BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock)
TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
_type = wintype_TextGrid;
- width = height = 0;
- curx = cury = 0;
- inbuf = nullptr;
- inorgx = inorgy = 0;
- inmax = 0;
- incurs = inlen = 0;
- inarrayrock.num = 0;
- line_terminators = nullptr;
+ _width = _height = 0;
+ _curX = _curY = 0;
+ _inBuf = nullptr;
+ _inorgX = _inorgY = 0;
+ _inMax = 0;
+ _inCurs = _inLen = 0;
+ _inArrayRock.num = 0;
+ _lineTerminators = nullptr;
Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
}
@@ -272,7 +313,7 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
newwid = box.width() / g_conf->_cellW;
newhgt = box.height() / g_conf->_cellH;
- if (newwid == width && newhgt == height)
+ if (newwid == _width && newhgt == _height)
return;
lines.resize(newhgt);
@@ -282,8 +323,8 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
}
attr.clear();
- width = newwid;
- height = newhgt;
+ _width = newwid;
+ _height = newhgt;
}
void TextGridWindow::touch(int line) {
@@ -297,6 +338,21 @@ glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
size * g_conf->_cellH + g_conf->_tMarginY * 2;
}
+void TextGridWindow::cancelLineEvent(Event *ev) {
+ Event dummyEv;
+
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+
+ if (!line_request && !line_request_uni)
+ return;
+
+
+ // TODO : textgrid_cancel_line
+}
+
/*--------------------------------------------------------------------------*/
void TextGridWindow::TextGridRow::resize(size_t newSize) {
@@ -310,13 +366,13 @@ void TextGridWindow::TextGridRow::resize(size_t newSize) {
/*--------------------------------------------------------------------------*/
TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
- historypos(0), historyfirst(0), historypresent(0), lastseen(0), scrollpos(0),
- scrollmax(0), scrollback(SCROLLBACK), width(-1), height(-1), inbuf(nullptr),
- line_terminators(nullptr), echo_line_input(true), ladjw(0), radjw(0), ladjn(0),
- radjn(0), numchars(0), chars(nullptr), attrs(nullptr),
- spaced(0), dashed(0), copybuf(0), copypos(0) {
+ _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
+ _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
+ _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
+ _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
+ _spaced(0), _dashed(0), copybuf(0), copypos(0) {
_type = wintype_TextBuffer;
- Common::fill(&history[0], &history[HISTORYLEN], nullptr);
+ Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
}
@@ -334,31 +390,31 @@ void TextBufferWindow::rearrange(const Common::Rect &box) {
yadj = (box.height() - rnd);
bbox.top += (box.height() - rnd);
- if (newwid != width) {
- width = newwid;
+ if (newwid != _width) {
+ _width = newwid;
reflow();
}
- if (newhgt != height) {
+ if (newhgt != _height) {
/* scroll up if we obscure new lines */
- if (lastseen >= newhgt - 1)
- scrollpos += (height - newhgt);
+ if (_lastSeen >= newhgt - 1)
+ _scrollPos += (_height - newhgt);
- height = newhgt;
+ _height = newhgt;
/* keep window within 'valid' lines */
- if (scrollpos > scrollmax - height + 1)
- scrollpos = scrollmax - height + 1;
- if (scrollpos < 0)
- scrollpos = 0;
+ if (_scrollPos > _scrollMax - _height + 1)
+ _scrollPos = _scrollMax - _height + 1;
+ if (_scrollPos < 0)
+ _scrollPos = 0;
touchScroll();
/* allocate copy buffer */
if (copybuf)
delete[] copybuf;
- copybuf = new glui32[height * TBLINELEN];
+ copybuf = new glui32[_height * TBLINELEN];
- for (int i = 0; i < (height * TBLINELEN); i++)
+ for (int i = 0; i < (_height * TBLINELEN); i++)
copybuf[i] = 0;
copypos = 0;
@@ -371,10 +427,10 @@ void TextBufferWindow::reflow() {
int i, k, p, s;
int x;
- if (height < 4 || width < 20)
+ if (_height < 4 || _width < 20)
return;
- lines[0].len = numchars;
+ _lines[0].len = _numChars;
/* allocate temp buffers */
Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
@@ -401,38 +457,38 @@ void TextBufferWindow::reflow() {
x = 0;
p = 0;
- s = scrollmax < SCROLLBACK ? scrollmax : SCROLLBACK - 1;
+ s = _scrollMax < SCROLLBACK ? _scrollMax : SCROLLBACK - 1;
for (k = s; k >= 0; k--) {
if (k == 0 && line_request)
- inputbyte = p + infence;
+ inputbyte = p + _inFence;
- if (lines[k].lpic) {
+ if (_lines[k].lpic) {
offsetbuf[x] = p;
alignbuf[x] = imagealign_MarginLeft;
- pictbuf[x] = lines[k].lpic;
+ pictbuf[x] = _lines[k].lpic;
if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = lines[k].lhyper;
+ hyperbuf[x] = _lines[k].lhyper;
x++;
}
- if (lines[k].rpic) {
+ if (_lines[k].rpic) {
offsetbuf[x] = p;
alignbuf[x] = imagealign_MarginRight;
- pictbuf[x] = lines[k].rpic;
+ pictbuf[x] = _lines[k].rpic;
if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = lines[k].rhyper;
+ hyperbuf[x] = _lines[k].rhyper;
x++;
}
- for (i = 0; i < lines[k].len; i++) {
- attrbuf[p] = curattr = lines[k].attr[i];
- charbuf[p] = lines[k].chars[i];
+ for (i = 0; i < _lines[k].len; i++) {
+ attrbuf[p] = curattr = _lines[k].attr[i];
+ charbuf[p] = _lines[k].chars[i];
p++;
}
- if (lines[k].newline) {
+ if (_lines[k].newline) {
attrbuf[p] = curattr;
charbuf[p] = '\n';
p++;
@@ -462,13 +518,13 @@ void TextBufferWindow::reflow() {
}
/* terribly sorry about this... */
- lastseen = 0;
- scrollpos = 0;
+ _lastSeen = 0;
+ _scrollPos = 0;
if (inputbyte != -1) {
- infence = numchars;
- putTextUnit(charbuf + inputbyte, p - inputbyte, numchars, 0);
- incurs = numchars;
+ _inFence = _numChars;
+ putTextUnit(charbuf + inputbyte, p - inputbyte, _numChars, 0);
+ _inCurs = _numChars;
}
// free temp buffers
@@ -488,8 +544,8 @@ void TextBufferWindow::touchScroll() {
_windows->clearSelection();
_windows->repaint(bbox);
- for (int i = 0; i < scrollmax; i++)
- lines[i].dirty = true;
+ for (int i = 0; i < _scrollMax; i++)
+ _lines[i].dirty = true;
}
void TextBufferWindow::clear() {
@@ -501,62 +557,62 @@ void TextBufferWindow::clear() {
attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
attr.reverse = false;
- ladjw = radjw = 0;
- ladjn = radjn = 0;
+ _ladjw = _radjw = 0;
+ _ladjn = _radjn = 0;
- spaced = 0;
- dashed = 0;
+ _spaced = 0;
+ _dashed = 0;
- numchars = 0;
+ _numChars = 0;
- for (i = 0; i < scrollback; i++) {
- lines[i].len = 0;
+ for (i = 0; i < _scrollBack; i++) {
+ _lines[i].len = 0;
- if (lines[i].lpic) lines[i].lpic->decrement();
- lines[i].lpic = nullptr;
- if (lines[i].rpic) lines[i].rpic->decrement();
- lines[i].rpic = nullptr;
+ if (_lines[i].lpic) _lines[i].lpic->decrement();
+ _lines[i].lpic = nullptr;
+ if (_lines[i].rpic) _lines[i].rpic->decrement();
+ _lines[i].rpic = nullptr;
- lines[i].lhyper = 0;
- lines[i].rhyper = 0;
- lines[i].lm = 0;
- lines[i].rm = 0;
- lines[i].newline = 0;
- lines[i].dirty = true;
- lines[i].repaint = false;
+ _lines[i].lhyper = 0;
+ _lines[i].rhyper = 0;
+ _lines[i].lm = 0;
+ _lines[i].rm = 0;
+ _lines[i].newline = 0;
+ _lines[i].dirty = true;
+ _lines[i].repaint = false;
}
- lastseen = 0;
- scrollpos = 0;
- scrollmax = 0;
+ _lastSeen = 0;
+ _scrollPos = 0;
+ _scrollMax = 0;
- for (i = 0; i < height; i++)
+ for (i = 0; i < _height; i++)
touch(i);
}
bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
if (align == imagealign_MarginRight)
{
- if (lines[0].rpic || numchars)
+ if (_lines[0].rpic || _numChars)
return false;
- radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
- radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- lines[0].rpic = pic;
- lines[0].rm = radjw;
- lines[0].rhyper = linkval;
+ _radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ _radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
+ _lines[0].rpic = pic;
+ _lines[0].rm = _radjw;
+ _lines[0].rhyper = linkval;
} else {
- if (align != imagealign_MarginLeft && numchars)
+ if (align != imagealign_MarginLeft && _numChars)
putCharUni('\n');
- if (lines[0].lpic || numchars)
+ if (_lines[0].lpic || _numChars)
return false;
- ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
- ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- lines[0].lpic = pic;
- lines[0].lm = ladjw;
- lines[0].lhyper = linkval;
+ _ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ _ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
+ _lines[0].lpic = pic;
+ _lines[0].lm = _ladjw;
+ _lines[0].lhyper = linkval;
if (align != imagealign_MarginLeft)
flowBreak();
@@ -724,8 +780,8 @@ void TextBufferWindow::flowBreak() {
}
void TextBufferWindow::touch(int line) {
- int y = bbox.top + g_conf->_tMarginY + (height - line - 1) * g_conf->_leading;
- lines[line].dirty = 1;
+ int y = bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
+ _lines[line].dirty = 1;
_windows->clearSelection();
_windows->repaint(Common::Rect(bbox.left, y - 2, bbox.right, y + g_conf->_leading + 2));
}
@@ -734,6 +790,21 @@ glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
}
+void TextBufferWindow::cancelLineEvent(Event *ev) {
+ Event dummyEv;
+
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+
+ if (!line_request && !line_request_uni)
+ return;
+
+
+ // TODO : textbuffer_cancel_line
+}
+
/*--------------------------------------------------------------------------*/
TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 6f7a016..f09ebdb 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -27,6 +27,7 @@
#include "common/list.h"
#include "common/rect.h"
#include "graphics/screen.h"
+#include "gargoyle/events.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
#include "gargoyle/picture.h"
@@ -34,7 +35,6 @@
namespace Gargoyle {
-class GargoyleEngine;
class Window;
class PairWindow;
struct WindowMask;
@@ -47,9 +47,37 @@ struct WindowMask;
* Main windows manager
*/
class Windows {
- friend class Window;
+public:
+ class iterator {
+ private:
+ Window *_current;
+ public:
+ /**
+ * Constructor
+ */
+ iterator(Window *start) : _current(start) {}
+
+ /**
+ * Dereference
+ */
+ Window *operator*() const { return _current; }
+
+ /**
+ * Move to next
+ */
+ iterator &operator++();
+
+ /**
+ * Equality test
+ */
+ bool operator==(const iterator &i) { return _current == i._current; }
+
+ /**
+ * Inequality test
+ */
+ bool operator!=(const iterator &i) { return _current != i._current; }
+ };
private:
- GargoyleEngine *_engine;
Graphics::Screen *_screen;
Window * _windowList; ///< List of all windows
Window *_rootWin; ///< The topmost window
@@ -83,7 +111,7 @@ public:
/**
* Constructor
*/
- Windows(GargoyleEngine *engine, Graphics::Screen *screen);
+ Windows(Graphics::Screen *screen);
/**
* Open a new window
@@ -102,6 +130,16 @@ public:
* Repaint an area of the windows
*/
void repaint(const Common::Rect &box);
+
+ /**
+ * Get an iterator that will move over the tree
+ */
+ iterator begin() { return iterator(_windowList); }
+
+ /**
+ * Returns the end point of window iteration
+ */
+ iterator end() { return iterator(nullptr); }
};
/**
@@ -159,12 +197,13 @@ public:
glui32 _rock;
glui32 _type;
- Window *parent; ///< pair window which contains this one
+ Window *_parent; ///< pair window which contains this one
+ Window *_next, *_prev; ///< in the big linked list of windows
Common::Rect bbox;
int yadj;
- Stream *_stream; ///< the window stream.
- Stream *_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;
@@ -185,7 +224,6 @@ public:
byte fgcolor[3];
gidispatch_rock_t disprock;
- Window *next, *prev; ///< in the big linked list of windows
public:
/**
* Constructor
@@ -206,6 +244,31 @@ public:
* Get window split size within parent pair window
*/
virtual glui32 getSplit(glui32 size, bool vertical) const { return 0; }
+
+ /**
+ * Cancel a line event
+ */
+ virtual void cancelLineEvent(Event *ev);
+
+ /**
+ * Write a character
+ */
+ virtual void putChar(unsigned char ch) { /* TODO */ }
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) { /* TODO */ }
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) { /* TODO */ }
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) { /* TODO */ }
};
typedef Window *winid_t;
@@ -249,19 +312,19 @@ private:
*/
void touch(int line);
public:
- int width, height;
+ int _width, _height;
TextGridRows lines;
- int curx, cury; ///< the window cursor position
+ int _curX, _curY; ///< the window cursor position
- ///< for line input
- void *inbuf; ///< unsigned char* for latin1, glui32* for unicode
- int inorgx, inorgy;
- int inmax;
- int incurs, inlen;
- Attributes origattr;
- gidispatch_rock_t inarrayrock;
- glui32 *line_terminators;
+ ///< for line input
+ void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
+ int _inorgX, _inorgY;
+ int _inMax;
+ int _inCurs, _inLen;
+ Attributes _origAttr;
+ gidispatch_rock_t _inArrayRock;
+ glui32 *_lineTerminators;
WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
public:
@@ -279,6 +342,11 @@ public:
* Get window split size within parent pair window
*/
virtual glui32 getSplit(glui32 size, bool vertical) const override;
+
+ /**
+ * Cancel a line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
};
/**
@@ -321,43 +389,43 @@ private:
*/
void touch(int line);
public:
- int width, height;
- int spaced;
- int dashed;
+ int _width, _height;
+ int _spaced;
+ int _dashed;
- TextBufferRows lines;
- int scrollback;
+ TextBufferRows _lines;
+ int _scrollBack;
- int numchars; ///< number of chars in last line: lines[0]
- glui32 *chars; ///< alias to lines[0].chars
- Attributes *attrs; ///< alias to lines[0].attrs
+ int _numChars; ///< number of chars in last line: lines[0]
+ glui32 *_chars; ///< alias to lines[0].chars
+ Attributes *_attrs; ///< alias to lines[0].attrs
- ///< adjust margins temporarily for images
- int ladjw;
- int ladjn;
- int radjw;
- int radjn;
+ ///< adjust margins temporarily for images
+ int _ladjw;
+ int _ladjn;
+ int _radjw;
+ int _radjn;
/* Command history. */
- glui32 *history[HISTORYLEN];
- int historypos;
- int historyfirst, historypresent;
+ glui32 *_history[HISTORYLEN];
+ int _historyPos;
+ int _historyFirst, _historyPresent;
/* for paging */
- int lastseen;
- int scrollpos;
- int scrollmax;
+ int _lastSeen;
+ int _scrollPos;
+ int _scrollMax;
/* for line input */
- void *inbuf; ///< unsigned char* for latin1, glui32* for unicode
- int inmax;
- long infence;
- long incurs;
- Attributes origattr;
- gidispatch_rock_t inarrayrock;
+ void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
+ int _inMax;
+ long _inFence;
+ long _inCurs;
+ Attributes _origAttr;
+ gidispatch_rock_t _inArrayRock;
- glui32 echo_line_input;
- glui32 *line_terminators;
+ glui32 _echoLineInput;
+ glui32 *_lineTerminators;
/* style hints and settings */
WindowStyle styles[style_NUMSTYLES];
@@ -382,6 +450,11 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const override;
/**
+ * Cancel a line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
+
+ /**
* Clear the window
*/
void clear();
Commit: ac9a122e3d140b2cb2e82c8d9dfeff2ee38fff36
https://github.com/scummvm/scummvm/commit/ac9a122e3d140b2cb2e82c8d9dfeff2ee38fff36
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Renaming of window classes fields
Changed paths:
engines/gargoyle/streams.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index b505405..7b6c1ab 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -70,7 +70,7 @@ void WindowStream::putChar(unsigned char ch) {
return;
++_writeCount;
- if (_window->line_request || _window->line_request_uni) {
+ if (_window->_lineRequest || _window->_lineRequestUni) {
if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
_window->cancelLineEvent(nullptr);
g_vm->_events->_forceClick = false;
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 3212964..bf671ab 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -257,20 +257,20 @@ void Windows::repaint(const Common::Rect &box) {
Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
_windows(windows), _rock(rock), _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr),
- yadj(0), line_request(0), line_request_uni(0), char_request(0), char_request_uni(0),
- mouse_request(0), hyper_request(0), more_request(0), scroll_request(0), image_loaded(0),
- echo_line_input(true), line_terminators(nullptr), termct(0), _echoStream(nullptr) {
- attr.fgset = 0;
- attr.bgset = 0;
- attr.reverse = 0;
- attr.style = 0;
- attr.fgcolor = 0;
- attr.bgcolor = 0;
- attr.hyper = 0;
-
- Common::fill(&bgcolor[0], &bgcolor[3], 3);
- Common::fill(&fgcolor[0], &fgcolor[3], 3);
- disprock.num = 0;
+ yadj(0), _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
+ _mouseRequest(0), _hyperRequest(0), _moreRequest(0), _scrollRequest(0), _imageLoaded(0),
+ _echoLineInput(true), _lineTerminators(nullptr), _termCt(0), _echoStream(nullptr) {
+ _attr.fgset = 0;
+ _attr.bgset = 0;
+ _attr.reverse = 0;
+ _attr.style = 0;
+ _attr.fgcolor = 0;
+ _attr.bgcolor = 0;
+ _attr.hyper = 0;
+
+ Common::fill(&_bgColor[0], &_bgColor[3], 3);
+ Common::fill(&_fgColor[0], &_fgColor[3], 3);
+ _dispRock.num = 0;
Streams &streams = *g_vm->_streams;
_stream = streams.addWindowStream(this);
@@ -322,7 +322,7 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
touch(y);
}
- attr.clear();
+ _attr.clear();
_width = newwid;
_height = newhgt;
}
@@ -346,7 +346,7 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
g_vm->_events->clearEvent(ev);
- if (!line_request && !line_request_uni)
+ if (!_lineRequest && !_lineRequestUni)
return;
@@ -370,7 +370,7 @@ TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windo
_scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
_lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
_radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
- _spaced(0), _dashed(0), copybuf(0), copypos(0) {
+ _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
_type = wintype_TextBuffer;
Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
@@ -410,14 +410,14 @@ void TextBufferWindow::rearrange(const Common::Rect &box) {
touchScroll();
/* allocate copy buffer */
- if (copybuf)
- delete[] copybuf;
- copybuf = new glui32[_height * TBLINELEN];
+ if (_copyBuf)
+ delete[] _copyBuf;
+ _copyBuf = new glui32[_height * TBLINELEN];
for (int i = 0; i < (_height * TBLINELEN); i++)
- copybuf[i] = 0;
+ _copyBuf[i] = 0;
- copypos = 0;
+ _copyPos = 0;
}
}
@@ -452,7 +452,7 @@ void TextBufferWindow::reflow() {
/* copy text to temp buffers */
- oldattr = attr;
+ oldattr = _attr;
curattr.clear();
x = 0;
@@ -460,7 +460,7 @@ void TextBufferWindow::reflow() {
s = _scrollMax < SCROLLBACK ? _scrollMax : SCROLLBACK - 1;
for (k = s; k >= 0; k--) {
- if (k == 0 && line_request)
+ if (k == 0 && _lineRequest)
inputbyte = p + _inFence;
if (_lines[k].lpic) {
@@ -507,7 +507,7 @@ void TextBufferWindow::reflow() {
for (i = 0; i < p; i++) {
if (i == inputbyte)
break;
- attr = attrbuf[i];
+ _attr = attrbuf[i];
if (offsetbuf[x] == i) {
putPicture(pictbuf[x], alignbuf[x], hyperbuf[x]);
@@ -535,7 +535,7 @@ void TextBufferWindow::reflow() {
delete[] hyperbuf;
delete[] offsetbuf;
- attr = oldattr;
+ _attr = oldattr;
touchScroll();
}
@@ -551,11 +551,11 @@ void TextBufferWindow::touchScroll() {
void TextBufferWindow::clear() {
int i;
- attr.fgset = Windows::_overrideFgSet;
- attr.bgset = Windows::_overrideBgSet;
- attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
- attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
- attr.reverse = false;
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
_ladjw = _radjw = 0;
_ladjn = _radjn = 0;
@@ -798,7 +798,7 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
g_vm->_events->clearEvent(ev);
- if (!line_request && !line_request_uni)
+ if (!_lineRequest && !_lineRequestUni)
return;
@@ -822,9 +822,9 @@ void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
/*--------------------------------------------------------------------------*/
GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
- w(0), h(0), dirty(false), _surface(nullptr) {
+_w(0), _h(0), _dirty(false), _surface(nullptr) {
_type = wintype_Graphics;
- Common::copy(&bgcolor[0], &bgcolor[3], bgnd);
+ Common::copy(&_bgColor[0], &_bgColor[3], _bgnd);
}
void GraphicsWindow::rearrange(const Common::Rect &box) {
@@ -837,21 +837,21 @@ void GraphicsWindow::rearrange(const Common::Rect &box) {
newwid = box.width();
newhgt = box.height();
- oldw = w;
- oldh = h;
+ oldw = _w;
+ oldh = _h;
if (newwid <= 0 || newhgt <= 0) {
- w = 0;
- h = 0;
+ _w = 0;
+ _h = 0;
delete _surface;
_surface = NULL;
return;
}
- bothwid = w;
+ bothwid = _w;
if (newwid < bothwid)
bothwid = newwid;
- bothhgt = h;
+ bothhgt = _h;
if (newhgt < bothhgt)
bothhgt = newhgt;
@@ -864,14 +864,14 @@ void GraphicsWindow::rearrange(const Common::Rect &box) {
delete _surface;
_surface = newSurface;
- w = newwid;
- h = newhgt;
+ _w = newwid;
+ _h = newhgt;
touch();
}
void GraphicsWindow::touch() {
- dirty = true;
+ _dirty = true;
_windows->repaint(bbox);
}
@@ -881,10 +881,10 @@ PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size
Window(windows, 0),
_dir(method & winmethod_DirMask),
_division(method & winmethod_DivisionMask),
- _wborder((method & winmethod_BorderMask) == winmethod_Border),
+ _wBorder((method & winmethod_BorderMask) == winmethod_Border),
_vertical(_dir == winmethod_Left || _dir == winmethod_Right),
_backward(_dir == winmethod_Left || _dir == winmethod_Above),
- _key(key), _size(size), _keydamage(0), _child1(nullptr), _child2(nullptr) {
+ _key(key), _size(size), _keyDamage(0), _child1(nullptr), _child2(nullptr) {
_type = wintype_Pair;
}
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index f09ebdb..b84ce27 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -205,25 +205,25 @@ public:
Stream *_stream; ///< the window stream.
Stream *_echoStream; ///< the window's echo stream, if any.
- int line_request;
- int line_request_uni;
- int char_request;
- int char_request_uni;
- int mouse_request;
- int hyper_request;
- int more_request;
- int scroll_request;
- int image_loaded;
-
- glui32 echo_line_input;
- glui32 *line_terminators;
- glui32 termct;
-
- Attributes attr;
- byte bgcolor[3];
- byte fgcolor[3];
-
- gidispatch_rock_t disprock;
+ int _lineRequest;
+ int _lineRequestUni;
+ int _charRequest;
+ int _charRequestUni;
+ int _mouseRequest;
+ int _hyperRequest;
+ int _moreRequest;
+ int _scrollRequest;
+ int _imageLoaded;
+
+ glui32 _echoLineInput;
+ glui32 *_lineTerminators;
+ glui32 _termCt;
+
+ Attributes _attr;
+ byte _bgColor[3];
+ byte _fgColor[3];
+
+ gidispatch_rock_t _dispRock;
public:
/**
* Constructor
@@ -431,8 +431,8 @@ public:
WindowStyle styles[style_NUMSTYLES];
/* for copy selection */
- glui32 *copybuf;
- int copypos;
+ glui32 *_copyBuf;
+ int _copyPos;
public:
/**
* Constructor
@@ -467,9 +467,9 @@ class GraphicsWindow : public Window {
private:
void touch();
public:
- unsigned char bgnd[3];
- bool dirty;
- int w, h;
+ unsigned char _bgnd[3];
+ bool _dirty;
+ int _w, _h;
Graphics::ManagedSurface *_surface;
public:
/**
@@ -502,9 +502,9 @@ public:
bool _vertical, _backward; ///< flags
glui32 _division; ///< winmethod_Fixed or winmethod_Proportional
Window *_key; ///< NULL or a leaf-descendant (not a Pair)
- int _keydamage; ///< used as scratch space in window closing
+ int _keyDamage; ///< used as scratch space in window closing
glui32 _size; ///< size value
- glui32 _wborder; ///< winMethod_Border, NoBorder
+ glui32 _wBorder; ///< winMethod_Border, NoBorder
public:
/**
* Constructor
Commit: 855fd39a9eb6676760d4e374bfc920000ff51f2e
https://github.com/scummvm/scummvm/commit/855fd39a9eb6676760d4e374bfc920000ff51f2e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added WindowStream put methods
Changed paths:
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 2ca14bf..8620e88 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -40,7 +40,8 @@ GargoyleEngine *g_vm;
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _conf(nullptr),
- _events(nullptr), _screen(nullptr), _windows(nullptr) {
+ _events(nullptr), _screen(nullptr), _windows(nullptr),
+ gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 976221a..1d81cb9 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -30,6 +30,7 @@
#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "graphics/screen.h"
+#include "gargoyle/glk_types.h"
namespace Gargoyle {
@@ -95,6 +96,10 @@ public:
Events *_events;
Streams *_streams;
Windows *_windows;
+ void (*gli_unregister_obj)(void *obj, glui32 objclass, gidispatch_rock_t objrock);
+ gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, const char *typecode);
+ void (*gli_unregister_arr)(void *array, glui32 len, const char *typecode, gidispatch_rock_t objrock);
+
public:
GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
virtual ~GargoyleEngine();
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 7b6c1ab..c2a2ff8 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -89,22 +89,60 @@ void WindowStream::putCharUni(uint32 ch) {
return;
++_writeCount;
- //TODO
+ if (_window->_lineRequest || _window->_lineRequestUni) {
+ if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
+ _window->cancelLineEvent(nullptr);
+ g_vm->_events->_forceClick = false;
+ } else {
+ warning("putCharUni: window has pending line request");
+ }
+ }
+
+ _window->putCharUni(ch);
+ if (_window->_echoStream)
+ _window->_echoStream->putCharUni(ch);
}
-void WindowStream::putBuffer(const unsigned char *buf, size_t len) {
+void WindowStream::putBuffer(const char *buf, size_t len) {
if (!_writable)
return;
- ++_writeCount;
- //TODO
+ _writeCount += len;
+
+ if (_window->_lineRequest || _window->_lineRequestUni) {
+ if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
+ _window->cancelLineEvent(nullptr);
+ g_vm->_events->_forceClick = false;
+ } else {
+ warning("putBuffer: window has pending line request");
+ }
+ }
+
+ for (size_t lx = 0; lx < len; lx++, buf++)
+ _window->putChar(*buf);
+ if (_window->_echoStream)
+ _window->_echoStream->putBuffer(buf, len);
}
void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
if (!_writable)
return;
- ++_writeCount;
- //TODO
+ _writeCount += len;
+
+ if (_window->_lineRequest || _window->_lineRequestUni) {
+ if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
+ _window->cancelLineEvent(nullptr);
+ g_vm->_events->_forceClick = false;
+ }
+ else {
+ warning("putBuffer: window has pending line request");
+ }
+ }
+
+ for (size_t lx = 0; lx < len; lx++, buf++)
+ _window->putCharUni(*buf);
+ if (_window->_echoStream)
+ _window->_echoStream->putBufferUni(buf, len);
}
/*--------------------------------------------------------------------------*/
@@ -132,7 +170,7 @@ void MemoryStream::putCharUni(uint32 ch) {
}
-void MemoryStream::putBuffer(const unsigned char *buf, size_t len) {
+void MemoryStream::putBuffer(const char *buf, size_t len) {
//TODO
}
@@ -156,7 +194,7 @@ void FileStream::putCharUni(uint32 ch) {
//TODO
}
-void FileStream::putBuffer(const unsigned char *buf, size_t len) {
+void FileStream::putBuffer(const char *buf, size_t len) {
//TODO
}
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index c43e2a0..fd04a1e 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -93,12 +93,28 @@ public:
/**
* Write a buffer
*/
- virtual void putBuffer(const unsigned char *buf, size_t len) = 0;
+ virtual void putBuffer(const char *buf, size_t len) = 0;
/**
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) = 0;
+
+ /**
+ * 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');
+ }
};
typedef Stream *strid_t;
@@ -133,7 +149,7 @@ public:
/**
* Write a buffer
*/
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
+ virtual void putBuffer(const char *buf, size_t len) override;
/**
* Write a unicode character
@@ -170,7 +186,7 @@ public:
/**
* Write a buffer
*/
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
+ virtual void putBuffer(const char *buf, size_t len) override;
/**
* Write a unicode character
@@ -202,7 +218,7 @@ public:
/**
* Write a buffer
*/
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
+ virtual void putBuffer(const char *buf, size_t len) override;
/**
* Write a unicode character
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index bf671ab..6070128 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -297,7 +297,7 @@ TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows,
_width = _height = 0;
_curX = _curY = 0;
_inBuf = nullptr;
- _inorgX = _inorgY = 0;
+ _inOrgX = _inOrgY = 0;
_inMax = 0;
_inCurs = _inLen = 0;
_inArrayRock.num = 0;
@@ -316,9 +316,9 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
if (newwid == _width && newhgt == _height)
return;
- lines.resize(newhgt);
+ _lines.resize(newhgt);
for (int y = 0; y < newhgt; ++y) {
- lines[y].resize(newwid);
+ _lines[y].resize(newwid);
touch(y);
}
@@ -329,7 +329,7 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
void TextGridWindow::touch(int line) {
int y = bbox.top + line * g_conf->_leading;
- lines[line].dirty = true;
+ _lines[line].dirty = true;
_windows->repaint(Common::Rect(bbox.left, y, bbox.right, y + g_conf->_leading));
}
@@ -339,6 +339,12 @@ glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
}
void TextGridWindow::cancelLineEvent(Event *ev) {
+ int ix;
+ void *inbuf;
+ int inmax;
+ int unicode = _lineRequestUni;
+ gidispatch_rock_t inarrayrock;
+ TextGridRow *ln = &_lines[_inOrgY];
Event dummyEv;
if (!ev)
@@ -350,7 +356,51 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
return;
- // TODO : textgrid_cancel_line
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ if (!unicode) {
+ for (ix = 0; ix<_inLen; ix++)
+ {
+ glui32 ch = ln->chars[_inOrgX + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ if (_echoStream)
+ _echoStream->echoLine((char *)_inBuf, _inLen);
+ } else {
+ for (ix = 0; ix<_inLen; ix++)
+ ((glui32 *)inbuf)[ix] = ln->chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
+ }
+
+ _curY = _inOrgY + 1;
+ _curX = 0;
+ _attr = _origAttr;
+
+ ev->_type = evtype_LineInput;
+ ev->_window = this;
+ ev->_val1 = _inLen;
+ ev->_val2 = 0;
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+
+ if (_lineTerminators) {
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ }
+
+ _inBuf = nullptr;
+ _inMax = 0;
+ _inOrgX = 0;
+ _inOrgY = 0;
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
}
/*--------------------------------------------------------------------------*/
@@ -791,6 +841,12 @@ glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
}
void TextBufferWindow::cancelLineEvent(Event *ev) {
+ gidispatch_rock_t inarrayrock;
+ int ix;
+ int len;
+ void *inbuf;
+ int inmax;
+ int unicode = _lineRequestUni;
Event dummyEv;
if (!ev)
@@ -801,8 +857,61 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
if (!_lineRequest && !_lineRequestUni)
return;
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ len = _numChars - _inFence;
+ if (_echoStream)
+ _echoStream->echoLineUni(_chars + _inFence, len);
+
+ if (len > inmax)
+ len = inmax;
+
+ if (!unicode)
+ {
+ for (ix = 0; ix<len; ix++)
+ {
+ glui32 ch = _chars[_inFence + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ }
+ else
+ {
+ for (ix = 0; ix<len; ix++)
+ ((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
+ }
+
+ _attr = _origAttr;
+
+ ev->_type = evtype_LineInput;
+ ev->_window = this;
+ ev->_val1 = len;
+ ev->_val2 = 0;
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+ if (_lineTerminators) {
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ }
+ _inBuf = nullptr;
+ _inMax = 0;
+
+ if (_echoLineInput) {
+ putCharUni('\n');
+ } else {
+ _numChars = _inFence;
+ touch(0);
+ }
- // TODO : textbuffer_cancel_line
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
}
/*--------------------------------------------------------------------------*/
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index b84ce27..0d635fd 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -313,13 +313,13 @@ private:
void touch(int line);
public:
int _width, _height;
- TextGridRows lines;
+ TextGridRows _lines;
int _curX, _curY; ///< the window cursor position
///< for line input
void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
- int _inorgX, _inorgY;
+ int _inOrgX, _inOrgY;
int _inMax;
int _inCurs, _inLen;
Attributes _origAttr;
Commit: 5bfdffc9dc2b811dccd050c9d70200416465bb50
https://github.com/scummvm/scummvm/commit/5bfdffc9dc2b811dccd050c9d70200416465bb50
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added remaining stream write methods
Changed paths:
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index c2a2ff8..7dec179 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -133,8 +133,7 @@ void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
_window->cancelLineEvent(nullptr);
g_vm->_events->_forceClick = false;
- }
- else {
+ } else {
warning("putBuffer: window has pending line request");
}
}
@@ -149,57 +148,265 @@ void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
Stream(streams, mode != filemode_Write, mode != filemode_Read, rock, unicode),
- _buf(buf), _buflen(buflen), _bufptr(buf) {
- assert(_buf && _buflen);
+ _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;
+ _bufEnd = (uint32 *)buf + buflen;
else
- _bufend = (byte *)buf + buflen;
- _bufeof = mode == filemode_Write ? _buf : _bufend;
+ _bufEnd = (byte *)buf + buflen;
+ _bufEof = mode == filemode_Write ? _buf : _bufEnd;
}
void MemoryStream::putChar(unsigned char ch) {
- //TODO
+ if (!_writable)
+ return;
+ ++_writeCount;
+
+ if (_bufPtr < _bufEnd) {
+ if (_unicode) {
+ *((glui32 *)_bufPtr) = ch;
+ _bufPtr = ((glui32 *)_bufPtr) + 1;
+ } else {
+ *((unsigned char *)_bufPtr) = ch;
+ _bufPtr = ((unsigned char *)_bufPtr) + 1;
+ }
+ if (_bufPtr > _bufEof)
+ _bufEof = _bufPtr;
+ }
}
void MemoryStream::putCharUni(uint32 ch) {
- //TODO
+ if (!_writable)
+ return;
+ ++_writeCount;
+ if (_bufPtr < _bufEnd) {
+ if (_unicode) {
+ *((glui32 *)_bufPtr) = ch;
+ _bufPtr = ((glui32 *)_bufPtr) + 1;
+ } else {
+ *((unsigned char *)_bufPtr) = (unsigned char)ch;
+ _bufPtr = ((unsigned char *)_bufPtr) + 1;
+ }
+ if (_bufPtr > _bufEof)
+ _bufEof = _bufPtr;
+ }
}
void MemoryStream::putBuffer(const char *buf, size_t len) {
- //TODO
+ size_t lx;
+
+ if (!_writable)
+ return;
+ _writeCount += len;
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if (!_unicode) {
+ unsigned char *bp = (unsigned char *)_bufPtr;
+ if (bp + len > (unsigned char *)_bufEnd)
+ {
+ lx = (bp + len) - (unsigned char *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ memmove(bp, buf, len);
+ bp += len;
+ if (bp >(unsigned char *)_bufEof)
+ _bufEof = bp;
+ }
+ _bufPtr = bp;
+ } else {
+ glui32 *bp = (glui32 *)_bufPtr;
+ if (bp + len > (glui32 *)_bufEnd) {
+ lx = (bp + len) - (glui32 *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ glui32 i;
+ for (i = 0; i < len; i++)
+ bp[i] = buf[i];
+ bp += len;
+ if (bp >(glui32 *)_bufEof)
+ _bufEof = bp;
+ }
+ _bufPtr = bp;
+ }
+ }
}
void MemoryStream::putBufferUni(const uint32 *buf, size_t len) {
- //TODO
+ size_t lx;
+
+ if (!_writable)
+ return;
+ _writeCount += len;
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if (!_unicode) {
+ unsigned char *bp = (unsigned char *)_bufPtr;
+ if (bp + len > (unsigned char *)_bufEnd) {
+ lx = (bp + len) - (unsigned char *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ glui32 i;
+ for (i = 0; i < len; i++) {
+ glui32 ch = buf[i];
+ if (ch > 0xff)
+ ch = '?';
+ bp[i] = (unsigned char)ch;
+ }
+ bp += len;
+ if (bp > (unsigned char *)_bufEof)
+ _bufEof = bp;
+ }
+ _bufPtr = bp;
+ } else {
+ glui32 *bp = (glui32 *)_bufPtr;
+ if (bp + len > (glui32 *)_bufEnd) {
+ lx = (bp + len) - (glui32 *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ memmove(bp, buf, len * 4);
+ bp += len;
+ if (bp >(glui32 *)_bufEof)
+ _bufEof = bp;
+ }
+ _bufPtr = bp;
+ }
+ }
}
/*--------------------------------------------------------------------------*/
FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) :
- Stream(streams, true, false, rock, unicode) {
+ Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false) {
+ // TODO: Set up files
+ _outFile = nullptr;
+ _inFile = nullptr;
+}
+
+void FileStream::ensureOp(FileMode mode) {
+ // No implementation
}
void FileStream::putChar(unsigned char ch) {
- //TODO
+ if (!_writable)
+ return;
+ ++_writeCount;
+
+ ensureOp(filemode_Write);
+ if (!_unicode) {
+ _outFile->writeByte(ch);
+ } else if (_textFile) {
+ putCharUtf8((glui32)ch);
+ } else {
+ _outFile->writeUint32BE(ch);
+ }
+
+ _outFile->flush();
}
void FileStream::putCharUni(uint32 ch) {
- //TODO
+ if (!_writable)
+ return;
+ ++_writeCount;
+
+ ensureOp(filemode_Write);
+ if (!_unicode) {
+ if (ch >= 0x100)
+ ch = '?';
+ _outFile->writeByte(ch);
+ } else if (_textFile) {
+ putCharUtf8(ch);
+ } else {
+ _outFile->writeUint32BE(ch);
+ }
+
+ _outFile->flush();
}
void FileStream::putBuffer(const char *buf, size_t len) {
- //TODO
+ if (!_writable)
+ return;
+ _writeCount += len;
+
+ ensureOp(filemode_Write);
+ for (size_t lx = 0; lx < len; lx++) {
+ unsigned char ch = ((unsigned char *)buf)[lx];
+ if (!_unicode) {
+ _outFile->writeByte(ch);
+ } else if (_textFile) {
+ putCharUtf8((glui32)ch);
+ } else {
+ _outFile->writeUint32BE(ch);
+ }
+ }
+
+ _outFile->flush();
}
void FileStream::putBufferUni(const uint32 *buf, size_t len) {
- //TODO
+ if (!_writable)
+ return;
+ _writeCount += len;
+
+
+ ensureOp(filemode_Write);
+ for (size_t lx = 0; lx<len; lx++) {
+ glui32 ch = buf[lx];
+ if (!_unicode) {
+ if (ch >= 0x100)
+ ch = '?';
+ _outFile->writeByte(ch);
+ } else if (_textFile) {
+ putCharUtf8(ch);
+ } else {
+ _outFile->writeUint32BE(ch);
+ }
+ }
+
+ _outFile->flush();
+}
+
+void FileStream::putCharUtf8(glui32 val) {
+ if (val < 0x80) {
+ _outFile->writeByte(val);
+ } else if (val < 0x800) {
+ _outFile->writeByte((0xC0 | ((val & 0x7C0) >> 6)));
+ _outFile->writeByte((0x80 | (val & 0x03F)));
+ } else if (val < 0x10000) {
+ _outFile->writeByte((0xE0 | ((val & 0xF000) >> 12)));
+ _outFile->writeByte((0x80 | ((val & 0x0FC0) >> 6)));
+ _outFile->writeByte((0x80 | (val & 0x003F)));
+ } else if (val < 0x200000) {
+ _outFile->writeByte((0xF0 | ((val & 0x1C0000) >> 18)));
+ _outFile->writeByte((0x80 | ((val & 0x03F000) >> 12)));
+ _outFile->writeByte((0x80 | ((val & 0x000FC0) >> 6)));
+ _outFile->writeByte((0x80 | (val & 0x00003F)));
+ } else {
+ _outFile->writeByte('?');
+ }
}
/*--------------------------------------------------------------------------*/
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index fd04a1e..82d6465 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -24,6 +24,7 @@
#define GARGOYLE_STREAMS_H
#include "common/scummsys.h"
+#include "common/savefile.h"
#include "gargoyle/glk_types.h"
namespace Gargoyle {
@@ -163,10 +164,10 @@ public:
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
+ void *_bufPtr;
+ void *_bufEnd;
+ void *_bufEof;
+ size_t _bufLen; ///< # of bytes for latin1, # of 4-byte words for unicode
public:
/**
* Constructor
@@ -199,6 +200,20 @@ public:
*/
class FileStream : public Stream {
private:
+ Common::OutSaveFile *_outFile;
+ Common::InSaveFile *_inFile;
+ 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);
public:
/**
* Constructor
Commit: 71389c2dd2b0af525c8f458cee723b61dcfeb614
https://github.com/scummvm/scummvm/commit/71389c2dd2b0af525c8f458cee723b61dcfeb614
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added window class destructors
Changed paths:
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 6070128..ac16471 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -306,6 +306,16 @@ TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows,
Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
}
+TextGridWindow::~TextGridWindow() {
+ if (_inBuf) {
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
+ _inBuf = nullptr;
+ }
+
+ delete[] _lineTerminators;
+}
+
void TextGridWindow::rearrange(const Common::Rect &box) {
Window::rearrange(box);
int newwid, newhgt;
@@ -427,6 +437,24 @@ TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windo
Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
}
+TextBufferWindow::~TextBufferWindow() {
+ if (_inBuf) {
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
+ _inBuf = nullptr;
+ }
+
+ delete[] _copyBuf;
+ delete[] _lineTerminators;
+
+ for (int i = 0; i < _scrollBack; i++) {
+ if (_lines[i].lpic)
+ _lines[i].lpic->decrement();
+ if (_lines[i].rpic)
+ _lines[i].rpic->decrement();
+ }
+}
+
void TextBufferWindow::rearrange(const Common::Rect &box) {
Window::rearrange(box);
int newwid, newhgt;
@@ -936,6 +964,10 @@ _w(0), _h(0), _dirty(false), _surface(nullptr) {
Common::copy(&_bgColor[0], &_bgColor[3], _bgnd);
}
+GraphicsWindow::~GraphicsWindow() {
+ delete _surface;
+}
+
void GraphicsWindow::rearrange(const Common::Rect &box) {
int newwid, newhgt;
int bothwid, bothhgt;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 0d635fd..24043c6 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -334,6 +334,11 @@ public:
TextGridWindow(Windows *windows, uint32 rock);
/**
+ * Destructor
+ */
+ virtual ~TextGridWindow();
+
+ /**
* Rearranges the window
*/
virtual void rearrange(const Common::Rect &box) override;
@@ -440,6 +445,11 @@ public:
TextBufferWindow(Windows *windows, uint32 rock);
/**
+ * Destructor
+ */
+ virtual ~TextBufferWindow();
+
+ /**
* Rearranges the window
*/
virtual void rearrange(const Common::Rect &box) override;
@@ -478,6 +488,11 @@ public:
GraphicsWindow(Windows *windows, uint32 rock);
/**
+ * Destructor
+ */
+ virtual ~GraphicsWindow();
+
+ /**
* Rearranges the window
*/
virtual void rearrange(const Common::Rect &box) override;
Commit: 0d3ad2dc8ad49c684e8a74285ec832335d7675e7
https://github.com/scummvm/scummvm/commit/0d3ad2dc8ad49c684e8a74285ec832335d7675e7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added TextGridWindow methods and support
Changed paths:
A engines/gargoyle/draw.cpp
A engines/gargoyle/draw.h
A engines/gargoyle/window_mask.cpp
A engines/gargoyle/window_mask.h
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/draw.cpp b/engines/gargoyle/draw.cpp
new file mode 100644
index 0000000..86d5fb0
--- /dev/null
+++ b/engines/gargoyle/draw.cpp
@@ -0,0 +1,32 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/draw.h"
+
+namespace Gargoyle {
+
+int Draw::drawStringUni(int x, int y, int fidx, byte *rgb, glui32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/draw.h b/engines/gargoyle/draw.h
new file mode 100644
index 0000000..61dfe18
--- /dev/null
+++ b/engines/gargoyle/draw.h
@@ -0,0 +1,38 @@
+/* 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 GARGOYLE_DRAW_H
+#define GARGOYLE_DRAW_H
+
+#include "common/events.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+class Draw {
+protected:
+ int drawStringUni(int x, int y, int fidx, byte *rgb, glui32 *s, int n, int spw);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 1f7cc6a..3373628 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -32,4 +32,8 @@ void Events::clearEvent(Event *ev) {
// TODO
}
+void Events::eventStore(EvType type, Window *win, uint32 val1, uint32 val2) {
+ // TODO
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 476be40..4ee9470 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -118,6 +118,8 @@ public:
void pollEvents();
void clearEvent(Event *ev);
+
+ void eventStore(EvType type, Window *win, uint32 val1 = 0, uint32 val2 = 0);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 8f84cbe..eaebb6f 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -165,6 +165,20 @@ enum StyleHint {
stylehint_just_RightFlush = 3,
};
+/**
+ * These constants define the classes of opaque objects. It's a bit ugly to put
+ * them in this header file, since more classes may be added in the future.
+ * But if you find yourself stuck with an obsolete version of this file,
+ * adding new class definitions will be easy enough -- they will be numbered
+ * sequentially, and the numeric constants can be found in the Glk specification.
+ */
+enum giDisp {
+ gidisp_Class_Window = 0,
+ gidisp_Class_Stream = 1,
+ gidisp_Class_Fileref = 2,
+ gidisp_Class_Schannel = 3,
+};
+
#ifdef GLK_MODULE_IMAGE
enum ImageAlign {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 925c66d..46f2d31 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/gargoyle
MODULE_OBJS := \
conf.o \
detection.o \
+ draw.o \
events.o \
fonts.o \
gargoyle.o \
@@ -10,6 +11,7 @@ MODULE_OBJS := \
picture.o \
streams.o \
string.o \
+ window_mask.o \
windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp
new file mode 100644
index 0000000..f0f6aa3
--- /dev/null
+++ b/engines/gargoyle/window_mask.cpp
@@ -0,0 +1,336 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/window_mask.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/windows.h"
+
+namespace Gargoyle {
+
+int WindowMask::_lastX;
+int WindowMask::_lastY;
+
+WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) {
+ _lastX = _lastY = 0;
+}
+
+void WindowMask::resize(size_t x, size_t y) {
+ // Deallocate old storage
+ for (size_t i = 0; i < _hor; i++) {
+ if (_links[i])
+ delete _links[i];
+ }
+
+ delete _links;
+
+ _hor = x + 1;
+ _ver = y + 1;
+
+ // allocate new storage
+ _links = new glui32 *[_hor];
+ if (!_links) {
+ warning("resize_mask: out of memory");
+ _hor = _ver = 0;
+ return;
+ }
+
+ for (size_t i = 0; i < _hor; i++) {
+ _links[i] = new glui32[_ver];
+ if (!_links[i]) {
+ warning("resize_mask: could not allocate new memory");
+ return;
+ }
+ }
+
+ _select.left = 0;
+ _select.top = 0;
+ _select.right = 0;
+ _select.bottom = 0;
+}
+
+void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1) {
+ uint i, k;
+ size_t tx0 = x0 < x1 ? x0 : x1;
+ size_t tx1 = x0 < x1 ? x1 : x0;
+ size_t ty0 = y0 < y1 ? y0 : y1;
+ size_t ty1 = y0 < y1 ? y1 : y0;
+
+ if (!_hor || !_ver) {
+ warning("putHyperlink: struct not initialized");
+ return;
+ }
+
+ if (tx0 >= _hor
+ || tx1 >= _hor
+ || ty0 >= _ver || ty1 >= _ver
+ || !_links[tx0] || !_links[tx1]) {
+ warning("putHyperlink: invalid range given");
+ return;
+ }
+
+ for (i = tx0; i < tx1; i++) {
+ for (k = ty0; k < ty1; k++)
+ _links[i][k] = linkval;
+ }
+}
+
+glui32 WindowMask::getHyperlink(const Common::Point &pos) {
+ if (!_hor || !_ver) {
+ warning("getHyperlink: struct not initialized");
+ return 0;
+ }
+
+ if (pos.x >= (int16)_hor
+ || pos.y >= (int16)_ver
+ || !_links[pos.x]) {
+ warning("getHyperlink: invalid range given");
+ return 0;
+ }
+
+ return _links[pos.x][pos.y];
+}
+
+void WindowMask::startSelection(const Common::Point &pos) {
+ int tx, ty;
+
+ if (!_hor || !_ver) {
+ warning("startSelection: mask not initialized");
+ return;
+ }
+
+ tx = MIN(pos.x, (int16)_hor);
+ ty = MIN(pos.y, (int16)_ver);
+
+ _select.left = _lastX = tx;
+ _select.top = _lastY = ty;
+ _select.right = 0;
+ _select.bottom = 0;
+
+ g_vm->_windows->selectionChanged();
+}
+
+void WindowMask::moveSelection(const Common::Point &pos) {
+ int tx, ty;
+
+ if (ABS(pos.x - _lastX) < 5 && abs(pos.y - _lastY) < 5)
+ return;
+
+ if (!_hor || !_ver) {
+ warning("moveSelection: mask not initialized");
+ return;
+ }
+
+ tx = MIN(pos.x, (int16)_hor);
+ ty = MIN(pos.y, (int16)_ver);
+
+ _select.right = _lastX = tx;
+ _select.bottom = _lastY = ty;
+
+ g_vm->_windows->selectionChanged();
+}
+
+void WindowMask::clearSelection() {
+ if (_select.left || _select.right
+ || _select.top || _select.bottom)
+ Windows::_forceRedraw = true;
+
+ _select.left = 0;
+ _select.top = 0;
+ _select.right = 0;
+ _select.bottom = 0;
+ g_vm->_windows->clearClaimSelect();
+}
+
+int WindowMask::checkSelection(uint x0, uint y0, uint x1, uint y1) {
+ uint cx0, cx1, cy0, cy1;
+
+ cx0 = _select.left < _select.right
+ ? _select.left
+ : _select.right;
+
+ cx1 = _select.left < _select.right
+ ? _select.right
+ : _select.left;
+
+ cy0 = _select.top < _select.bottom
+ ? _select.top
+ : _select.bottom;
+
+ cy1 = _select.top < _select.bottom
+ ? _select.bottom
+ : _select.top;
+
+ if (!cx0 || !cx1 || !cy0 || !cy1)
+ return false;
+
+ if (cx0 >= x0 && cx0 <= x1
+ && cy0 >= y0 && cy0 <= y1)
+ return true;
+
+ if (cx0 >= x0 && cx0 <= x1
+ && cy1 >= y0 && cy1 <= y1)
+ return true;
+
+ if (cx1 >= x0 && cx1 <= x1
+ && cy0 >= y0 && cy0 <= y1)
+ return true;
+
+ if (cx1 >= x0 && cx1 <= x1
+ && cy1 >= y0 && cy1 <= y1)
+ return true;
+
+ return false;
+}
+
+int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, uint *rx0, uint *rx1) {
+ uint row, upper, lower, above, below;
+ int row_selected, found_left, found_right;
+ int from_right, from_below, is_above, is_below;
+ uint cx0, cx1, cy0, cy1;
+
+ row = (y0 + y1) / 2;
+ upper = row - (row - y0) / 2;
+ lower = row + (y1 - row) / 2;
+ above = upper - (g_conf->_leading) / 2;
+ below = lower + (g_conf->_leading) / 2;
+
+ cx0 = _select.left < _select.right
+ ? _select.left
+ : _select.right;
+
+ cx1 = _select.left < _select.right
+ ? _select.right
+ : _select.left;
+
+ cy0 = _select.top < _select.bottom
+ ? _select.top
+ : _select.bottom;
+
+ cy1 = _select.top < _select.bottom
+ ? _select.bottom
+ : _select.top;
+
+ row_selected = false;
+
+ if ((cy0 >= upper && cy0 <= lower)
+ || (cy1 >= upper && cy1 <= lower))
+ row_selected = true;
+
+ if (row >= cy0 && row <= cy1)
+ row_selected = true;
+
+ if (!row_selected)
+ return false;
+
+ from_right = (_select.left != (int16)cx0);
+ from_below = (_select.top != (int16)cy0);
+ is_above = (above >= cy0 && above <= cy1);
+ is_below = (below >= cy0 && below <= cy1);
+
+ *rx0 = 0;
+ *rx1 = 0;
+
+ found_left = false;
+ found_right = false;
+
+ if (is_above && is_below) {
+ *rx0 = x0;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ } else if (!is_above && is_below) {
+ if (from_below) {
+ if (from_right) {
+ *rx0 = cx0;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx0 = cx1;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ }
+ } else {
+ if (from_right) {
+ *rx0 = cx1;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx1 = x1;
+ found_right = true;
+ }
+ }
+ } else if (is_above && !is_below) {
+ if (from_below) {
+ if (from_right) {
+ *rx0 = x0;
+ *rx1 = cx1;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx0 = x0;
+ *rx1 = cx0;
+ found_left = true;
+ found_right = true;
+ }
+ } else {
+ if (from_right) {
+ if (x0 > cx0)
+ return false;
+ *rx0 = x0;
+ *rx1 = cx0;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx0 = x0;
+ found_left = true;
+ }
+ }
+ }
+
+ if (found_left && found_right)
+ return true;
+
+ for (uint i = x0; i <= x1; i++) {
+ if (i >= cx0 && i <= cx1) {
+ if (!found_left) {
+ *rx0 = i;
+ found_left = true;
+ if (found_right)
+ return true;
+ } else {
+ if (!found_right)
+ *rx1 = i;
+ }
+ }
+ }
+
+ if (rx0 && !rx1)
+ *rx1 = x1;
+
+ return (rx0 && rx1);
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h
new file mode 100644
index 0000000..db0d7e6
--- /dev/null
+++ b/engines/gargoyle/window_mask.h
@@ -0,0 +1,67 @@
+/* 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 GARGOYLE_WINDOW_MASK_H
+#define GARGOYLE_WINDOW_MASK_H
+
+#include "common/rect.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+class Window;
+
+struct WindowMask {
+ size_t _hor, _ver;
+ glui32 **_links;
+ Common::Rect _select;
+
+ static int _lastX, _lastY;
+
+ /**
+ * Constructor
+ */
+ WindowMask();
+
+ /**
+ * Resize the links array
+ */
+ void resize(size_t x, size_t y);
+
+ void putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1);
+
+ glui32 getHyperlink(const Common::Point &pos);
+
+ void startSelection(const Common::Point &pos);
+
+ void moveSelection(const Common::Point &pos);
+
+ void clearSelection();
+
+ int checkSelection(uint x0, uint y0, uint x1, uint y1);
+
+ int getSelection(uint x0, uint y0, uint x1, uint y1, uint *rx0, uint *rx1);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index ac16471..a625040 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -35,8 +35,15 @@ namespace Gargoyle {
bool Windows::_overrideReverse;
bool Windows::_overrideFgSet;
bool Windows::_overrideBgSet;
+bool Windows::_forceRedraw;
int Windows::_overrideFgVal;
int Windows::_overrideBgVal;
+int Windows::_zcolor_fg;
+int Windows::_zcolor_bg;
+byte Windows::_zcolor_LightGrey[3];
+byte Windows::_zcolor_Foreground[3];
+byte Windows::_zcolor_Background[3];
+byte Windows::_zcolor_Bright[3];
/*--------------------------------------------------------------------------*/
@@ -76,13 +83,25 @@ Windows::iterator &Windows::iterator::operator++() {
/*--------------------------------------------------------------------------*/
Windows::Windows(Graphics::Screen *screen) :
- _screen(screen), _forceRedraw(true), _moreFocus(false), _windowList(nullptr),
+ _screen(screen), _moreFocus(false), _windowList(nullptr),
_rootWin(nullptr), _focusWin(nullptr), _mask(nullptr), _claimSelect(0) {
+ _mask = new WindowMask();
_overrideReverse = false;
_overrideFgSet = false;
_overrideBgSet = false;
+ _forceRedraw = true;
_overrideFgVal = 0;
_overrideBgVal = 0;
+ _zcolor_fg = _zcolor_bg = 0;
+
+ _zcolor_LightGrey[0] = _zcolor_LightGrey[1] = _zcolor_LightGrey[2] = 181;
+ _zcolor_Foreground[0] = _zcolor_Foreground[1] = _zcolor_Foreground[2] = 0;
+ _zcolor_Background[0] = _zcolor_Background[1] = _zcolor_Background[2] = 0;
+ _zcolor_Bright[0] = _zcolor_Bright[1] = _zcolor_Bright[2] = 0;
+}
+
+Windows::~Windows() {
+ delete _mask;
}
Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
@@ -235,31 +254,43 @@ void Windows::rearrange() {
}
}
-void Windows::clearSelection() {
- if (!_mask) {
- warning("clear_selection: mask not initialized");
- return;
- }
+void Windows::selectionChanged() {
+ _claimSelect = false;
+ _forceRedraw = true;
+ redraw();
+}
- if (_mask->select.left || _mask->select.right
- || _mask->select.top || _mask->select.bottom)
- _forceRedraw = true;
+void Windows::clearSelection() {
+ _mask->clearSelection();
+}
- _mask->select = Common::Rect();
- _claimSelect = false;
+void Windows::redraw() {
+ // TODO: gli_windows_redraw
}
void Windows::repaint(const Common::Rect &box) {
// TODO
}
+void Windows::drawRect(int x0, int y0, int w, int h, const byte *rgb) {
+ // TODO
+}
+
+byte *Windows::rgbShift(byte *rgb) {
+ _zcolor_Bright[0] = (rgb[0] + 0x30) < 0xff ? (rgb[0] + 0x30) : 0xff;
+ _zcolor_Bright[1] = (rgb[1] + 0x30) < 0xff ? (rgb[1] + 0x30) : 0xff;
+ _zcolor_Bright[2] = (rgb[2] + 0x30) < 0xff ? (rgb[2] + 0x30) : 0xff;
+
+ return _zcolor_Bright;
+}
+
/*--------------------------------------------------------------------------*/
Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
_windows(windows), _rock(rock), _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr),
- yadj(0), _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
+ _yAdj(0), _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
_mouseRequest(0), _hyperRequest(0), _moreRequest(0), _scrollRequest(0), _imageLoaded(0),
- _echoLineInput(true), _lineTerminators(nullptr), _termCt(0), _echoStream(nullptr) {
+ _echoLineInput(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
_attr.fgset = 0;
_attr.bgset = 0;
_attr.reverse = 0;
@@ -276,6 +307,27 @@ Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
_stream = streams.addWindowStream(this);
}
+Window::~Window() {
+ if (g_vm->gli_unregister_obj)
+ (*g_vm->gli_unregister_obj)(this, gidisp_Class_Window, _dispRock);
+
+
+ _echoStream = nullptr;
+ delete _stream;
+
+ delete[] _lineTerminatorsBase;
+
+ Window *prev = _prev;
+ Window *next = _next;
+
+ if (prev)
+ prev->_next = next;
+ else
+ _windows->_windowList = next;
+ if (next)
+ next->_prev = prev;
+}
+
void Window::cancelLineEvent(Event *ev) {
Event dummyEv;
if (!ev)
@@ -284,6 +336,31 @@ void Window::cancelLineEvent(Event *ev) {
g_vm->_events->clearEvent(ev);
}
+void Window::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ warning("requestLineEvent: window does not support keyboard input");
+}
+
+void Window::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ warning("requestLineEventUni: window does not support keyboard input");
+}
+
+void Window::redraw() {
+ if (Windows::_forceRedraw) {
+ unsigned char *color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
+ int y0 = _yAdj ? _bbox.top - _yAdj : _bbox.top;
+ _windows->drawRect(_bbox.left, y0, _bbox.width(), _bbox.bottom - y0, color);
+ }
+}
+
+bool Window::checkTerminator(glui32 ch) {
+ if (ch == keycode_Escape)
+ return true;
+ else if (ch >= keycode_Func12 && ch <= keycode_Func1)
+ return true;
+ else
+ return false;
+}
+
/*--------------------------------------------------------------------------*/
BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
@@ -338,9 +415,9 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
}
void TextGridWindow::touch(int line) {
- int y = bbox.top + line * g_conf->_leading;
+ int y = _bbox.top + line * g_conf->_leading;
_lines[line].dirty = true;
- _windows->repaint(Common::Rect(bbox.left, y, bbox.right, y + g_conf->_leading));
+ _windows->repaint(Common::Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
}
glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
@@ -348,6 +425,251 @@ glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
size * g_conf->_cellH + g_conf->_tMarginY * 2;
}
+void TextGridWindow::putChar(unsigned char ch) {
+
+}
+
+void TextGridWindow::putCharUni(uint32 ch) {
+ TextGridRow *ln;
+
+ // Canonicalize the cursor position. That is, the cursor may have been
+ // left outside the window area; wrap it if necessary.
+ if (_curX < 0) {
+ _curX = 0;
+ } else if (_curX >= _width) {
+ _curX = 0;
+ _curY++;
+ }
+ if (_curY < 0)
+ _curY = 0;
+ else if (_curY >= _height)
+ return; /* outside the window */
+
+ if (ch == '\n') {
+ /* a newline just moves the cursor. */
+ _curY++;
+ _curX = 0;
+ return;
+ }
+
+ touch(_curY);
+
+ ln = &(_lines[_curY]);
+ ln->_chars[_curX] = ch;
+ ln->_attrs[_curX] = _attr;
+
+ _curX++;
+ // We can leave the cursor outside the window, since it will be
+ // canonicalized next time a character is printed.
+}
+
+bool TextGridWindow::unputCharUni(uint32 ch) {
+ TextGridRow *ln;
+ int oldx = _curX, oldy = _curY;
+
+ /* Move the cursor back. */
+ if (_curX >= _width)
+ _curX = _width - 1;
+ else
+ _curX--;
+
+ /* Canonicalize the cursor position. That is, the cursor may have been
+ left outside the window area; wrap it if necessary. */
+ if (_curX < 0) {
+ _curX = _width - 1;
+ _curY--;
+ }
+ if (_curY < 0)
+ _curY = 0;
+ else if (_curY >= _height)
+ return false; // outside the window
+
+ if (ch == '\n') {
+ // a newline just moves the cursor.
+ if (_curX == _width - 1)
+ return 1; // deleted a newline
+ _curX = oldx;
+ _curY = oldy;
+ return 0; // it wasn't there */
+ }
+
+ ln = &(_lines[_curY]);
+ if (ln->_chars[_curX] == ch) {
+ ln->_chars[_curX] = ' ';
+ ln->_attrs[_curX].clear();
+ touch(_curY);
+ return true; // deleted the char
+ } else {
+ _curX = oldx;
+ _curY = oldy;
+ return false; // it wasn't there
+ }
+}
+
+void TextGridWindow::putBuffer(const unsigned char *buf, size_t len) {
+ // TODO
+}
+
+void TextGridWindow::putBufferUni(const uint32 *buf, size_t len) {
+ // TODO
+}
+
+void TextGridWindow::moveCursor(const Common::Point &pos) {
+ // If the values are negative, they're really huge positive numbers --
+ // remember that they were cast from glui32. So set them huge and
+ // let canonicalization take its course.
+ _curX = (pos.x < 0) ? 32767 : pos.x;
+ _curY = (pos.y < 0) ? 32767 : pos.y;
+}
+
+void TextGridWindow::clear() {
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
+
+ for (int k = 0; k < _height; k++) {
+ TextGridRow &ln = _lines[k];
+ touch(k);
+ for (uint j = 0; j < ln._attrs.size(); ++j) {
+ ln._chars[j] = ' ';
+ ln._attrs[j].clear();
+ }
+ }
+
+ _curX = 0;
+ _curY = 0;
+}
+
+void TextGridWindow::click(const Common::Point &newPos) {
+ int x = newPos.x - _bbox.left;
+ int y = newPos.y - _bbox.top;
+
+ if (_lineRequest || _charRequest || _lineRequestUni || _charRequestUni
+ || _moreRequest || _scrollRequest)
+ _windows->setFocus(this);
+
+ if (_mouseRequest) {
+ g_vm->_events->eventStore(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
+ _mouseRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+
+ if (_hyperRequest) {
+ glui32 linkval = _windows->getHyperlink(newPos);
+ if (linkval)
+ {
+ g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
+ _hyperRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+ }
+}
+
+void TextGridWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event: window already has keyboard request");
+ return;
+ }
+
+ if ((int)maxlen > (_width - _curX))
+ maxlen = (_width - _curX);
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inLen = 0;
+ _inCurs = 0;
+ _inOrgX = _curX;
+ _inOrgY = _curY;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ if (initlen > maxlen)
+ initlen = maxlen;
+
+ if (initlen) {
+ TextGridRow *ln = &_lines[_inOrgY];
+
+ for (glui32 ix = 0; ix < initlen; ix++) {
+ ln->_attrs[_inOrgX + ix].set(style_Input);
+ ln->_chars[_inOrgX + ix] = buf[ix];
+ }
+
+ _inCurs += initlen;
+ _inLen += initlen;
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+ }
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Cn");
+}
+
+void TextGridWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
+ warning("requestLineEventUni: window already has keyboard request");
+ return;
+ }
+
+ if ((int)maxlen > (_width - _curX))
+ maxlen = (_width - _curX);
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inLen = 0;
+ _inCurs = 0;
+ _inOrgX = _curX;
+ _inOrgY = _curY;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ if (initlen > maxlen)
+ initlen = maxlen;
+
+ if (initlen) {
+ TextGridRow *ln = &(_lines[_inOrgY]);
+
+ for (glui32 ix = 0; ix<initlen; ix++) {
+ ln->_attrs[_inOrgX + ix].set(style_Input);
+ ln->_chars[_inOrgX + ix] = buf[ix];
+ }
+
+ _inCurs += initlen;
+ _inLen += initlen;
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+ }
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Iu");
+}
+
void TextGridWindow::cancelLineEvent(Event *ev) {
int ix;
void *inbuf;
@@ -373,7 +695,7 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
if (!unicode) {
for (ix = 0; ix<_inLen; ix++)
{
- glui32 ch = ln->chars[_inOrgX + ix];
+ glui32 ch = ln->_chars[_inOrgX + ix];
if (ch > 0xff)
ch = '?';
((char *)inbuf)[ix] = (char)ch;
@@ -382,7 +704,7 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
_echoStream->echoLine((char *)_inBuf, _inLen);
} else {
for (ix = 0; ix<_inLen; ix++)
- ((glui32 *)inbuf)[ix] = ln->chars[_inOrgX + ix];
+ ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
if (_echoStream)
_echoStream->echoLineUni((glui32 *)inbuf, _inLen);
}
@@ -413,14 +735,274 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
(*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
}
+void TextGridWindow::acceptReadChar(glui32 arg) {
+ glui32 key;
+
+ switch (arg)
+ {
+ case keycode_Erase:
+ key = keycode_Delete;
+ break;
+ case keycode_MouseWheelUp:
+ case keycode_MouseWheelDown:
+ return;
+ default:
+ key = arg;
+ }
+
+ if (key > 0xff && key < (0xffffffff - keycode_MAXVAL + 1))
+ {
+ if (!(_charRequestUni) || key > 0x10ffff)
+ key = keycode_Unknown;
+ }
+
+ _charRequest = false;
+ _charRequestUni = false;
+ g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
+}
+
+void TextGridWindow::acceptLine(glui32 keycode) {
+ int ix;
+ void *inbuf;
+ int inmax;
+ gidispatch_rock_t inarrayrock;
+ TextGridRow *ln = &(_lines[_inOrgY]);
+ int unicode = _lineRequestUni;
+
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ if (!unicode) {
+ for (ix = 0; ix<_inLen; ix++)
+ ((char *)inbuf)[ix] = (char)ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLine((char *)inbuf, _inLen);
+ } else {
+ for (ix = 0; ix<_inLen; ix++)
+ ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
+ }
+
+ _curY = _inOrgY + 1;
+ _curX = 0;
+ _attr = _origAttr;
+
+ if (_lineTerminators)
+ {
+ glui32 val2 = keycode;
+ if (val2 == keycode_Return)
+ val2 = 0;
+ g_vm->_events->eventStore(evtype_LineInput, this, _inLen, val2);
+ free(_lineTerminators);
+ _lineTerminators = NULL;
+ } else {
+ g_vm->_events->eventStore(evtype_LineInput, this, _inLen, 0);
+ }
+ _lineRequest = false;
+ _lineRequestUni = false;
+ _inBuf = NULL;
+ _inMax = 0;
+ _inOrgX = 0;
+ _inOrgY = 0;
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextGridWindow::acceptReadLine(glui32 arg) {
+ int ix;
+ TextGridRow *ln = &(_lines[_inOrgY]);
+
+ if (!_inBuf)
+ return;
+
+ if (_lineTerminators && checkTerminator(arg)) {
+ glui32 *cx;
+ for (cx = _lineTerminators; *cx; cx++) {
+ if (*cx == arg) {
+ acceptLine(arg);
+ return;
+ }
+ }
+ }
+
+ switch (arg) {
+
+ /* Delete keys, during line input. */
+
+ case keycode_Delete:
+ if (_inLen <= 0)
+ return;
+ if (_inCurs <= 0)
+ return;
+ for (ix = _inCurs; ix<_inLen; ix++)
+ ln->_chars[_inOrgX + ix - 1] = ln->_chars[_inOrgX + ix];
+ ln->_chars[_inOrgX + _inLen - 1] = ' ';
+ _inCurs--;
+ _inLen--;
+ break;
+
+ case keycode_Erase:
+ if (_inLen <= 0)
+ return;
+ if (_inCurs >= _inLen)
+ return;
+ for (ix = _inCurs; ix<_inLen - 1; ix++)
+ ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix + 1];
+ ln->_chars[_inOrgX + _inLen - 1] = ' ';
+ _inLen--;
+ break;
+
+ case keycode_Escape:
+ if (_inLen <= 0)
+ return;
+ for (ix = 0; ix<_inLen; ix++)
+ ln->_chars[_inOrgX + ix] = ' ';
+ _inLen = 0;
+ _inCurs = 0;
+ break;
+
+ /* Cursor movement keys, during line input. */
+
+ case keycode_Left:
+ if (_inCurs <= 0)
+ return;
+ _inCurs--;
+ break;
+
+ case keycode_Right:
+ if (_inCurs >= _inLen)
+ return;
+ _inCurs++;
+ break;
+
+ case keycode_Home:
+ if (_inCurs <= 0)
+ return;
+ _inCurs = 0;
+ break;
+
+ case keycode_End:
+ if (_inCurs >= _inLen)
+ return;
+ _inCurs = _inLen;
+ break;
+
+ case keycode_Return:
+ acceptLine(arg);
+ break;
+
+ default:
+ if (_inLen >= _inMax)
+ return;
+
+ if (arg < 32 || arg > 0xff)
+ return;
+
+ if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
+ arg -= 0x20;
+
+ for (ix = _inLen; ix>_inCurs; ix--)
+ ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix - 1];
+ ln->_attrs[_inOrgX + _inLen].set(style_Input);
+ ln->_chars[_inOrgX + _inCurs] = arg;
+
+ _inCurs++;
+ _inLen++;
+ }
+
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+}
+
+void TextGridWindow::redraw() {
+ TextGridRow *ln;
+ int x0, y0;
+ int x, y, w;
+ int i, a, b, k, o;
+ glui32 link;
+ int font;
+ byte *fgcolor, *bgcolor;
+
+ x0 = _bbox.left;
+ y0 = _bbox.top;
+
+ for (i = 0; i < _height; i++) {
+ ln = &_lines[i];
+ if (ln->dirty || Windows::_forceRedraw) {
+ ln->dirty = 0;
+
+ x = x0;
+ y = y0 + i * g_conf->_leading;
+
+ /* clear any stored hyperlink coordinates */
+ _windows->setHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
+
+ a = 0;
+ for (b = 0; b < _width; b++) {
+ if (ln->_attrs[a] == ln->_attrs[b]) {
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
+ bgcolor = ln->_attrs[a].attrBg(styles);
+ w = (b - a) * g_conf->_cellW;
+ _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+ o = x;
+
+ for (k = a; k < b; k++) {
+ drawStringUni(o * GLI_SUBPIX,
+ y + g_conf->_baseLine, font, fgcolor,
+ &ln->_chars[k], 1, -1);
+ o += g_conf->_cellW;
+ }
+ if (link) {
+ _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle, g_conf->_linkColor);
+ _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ }
+ x += w;
+ a = b;
+ }
+ }
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
+ bgcolor = ln->_attrs[a].attrBg(styles);
+ w = (b - a) * g_conf->_cellW;
+ w += _bbox.right - (x + w);
+ _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+
+ o = x;
+ for (k = a; k < b; k++) {
+ drawStringUni(o * GLI_SUBPIX,
+ y + g_conf->_baseLine, font, fgcolor,
+ &ln->_chars[k], 1, -1);
+ o += g_conf->_cellW;
+ }
+ if (link) {
+ _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle, g_conf->_linkColor);
+ _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ }
+ }
+ }
+}
+
/*--------------------------------------------------------------------------*/
void TextGridWindow::TextGridRow::resize(size_t newSize) {
- chars.clear();
- attr.clear();
- chars.resize(newSize);
- attr.resize(newSize);
- Common::fill(&chars[0], &chars[0] + newSize, ' ');
+ _chars.clear();
+ _attrs.clear();
+ _chars.resize(newSize);
+ _attrs.resize(newSize);
+ Common::fill(&_chars[0], &_chars[0] + newSize, ' ');
}
/*--------------------------------------------------------------------------*/
@@ -465,8 +1047,8 @@ void TextBufferWindow::rearrange(const Common::Rect &box) {
/* align text with bottom */
rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
- yadj = (box.height() - rnd);
- bbox.top += (box.height() - rnd);
+ _yAdj = (box.height() - rnd);
+ _bbox.top += (box.height() - rnd);
if (newwid != _width) {
_width = newwid;
@@ -601,7 +1183,7 @@ void TextBufferWindow::reflow() {
if (inputbyte != -1) {
_inFence = _numChars;
- putTextUnit(charbuf + inputbyte, p - inputbyte, _numChars, 0);
+ putTextUni(charbuf + inputbyte, p - inputbyte, _numChars, 0);
_inCurs = _numChars;
}
@@ -620,54 +1202,12 @@ void TextBufferWindow::reflow() {
void TextBufferWindow::touchScroll() {
_windows->clearSelection();
- _windows->repaint(bbox);
+ _windows->repaint(_bbox);
for (int i = 0; i < _scrollMax; i++)
_lines[i].dirty = true;
}
-void TextBufferWindow::clear() {
- int i;
-
- _attr.fgset = Windows::_overrideFgSet;
- _attr.bgset = Windows::_overrideBgSet;
- _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
- _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
- _attr.reverse = false;
-
- _ladjw = _radjw = 0;
- _ladjn = _radjn = 0;
-
- _spaced = 0;
- _dashed = 0;
-
- _numChars = 0;
-
- for (i = 0; i < _scrollBack; i++) {
- _lines[i].len = 0;
-
- if (_lines[i].lpic) _lines[i].lpic->decrement();
- _lines[i].lpic = nullptr;
- if (_lines[i].rpic) _lines[i].rpic->decrement();
- _lines[i].rpic = nullptr;
-
- _lines[i].lhyper = 0;
- _lines[i].rhyper = 0;
- _lines[i].lm = 0;
- _lines[i].rm = 0;
- _lines[i].newline = 0;
- _lines[i].dirty = true;
- _lines[i].repaint = false;
- }
-
- _lastSeen = 0;
- _scrollPos = 0;
- _scrollMax = 0;
-
- for (i = 0; i < _height; i++)
- touch(i);
-}
-
bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
if (align == imagealign_MarginRight)
{
@@ -696,7 +1236,29 @@ bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
flowBreak();
}
- return true ;
+ return true;
+}
+
+void TextBufferWindow::flowBreak() {
+ // TODO
+}
+
+void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldlen) {
+ // TODO
+}
+
+void TextBufferWindow::touch(int line) {
+ int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
+ _lines[line].dirty = 1;
+ _windows->clearSelection();
+ _windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
+}
+
+glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
+ return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
+}
+
+void TextBufferWindow::putChar(unsigned char ch) {
}
void TextBufferWindow::putCharUni(glui32 ch) {
@@ -712,10 +1274,10 @@ void TextBufferWindow::putCharUni(glui32 ch) {
gli_tts_speak(&ch, 1);
- pw = (bbox.right - bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
+ pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
pw = pw - 2 * SLOP - radjw - ladjw;
- color = gli_override_bg_set ? gli_window_color : bgcolor;
+ color = Windows::_overrideBgSet ? gli_window_color : bgcolor;
// oops ... overflow
if (numchars + 1 >= TBLINELEN)
@@ -730,7 +1292,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
// fails for 'tis a wonderful day in the '80s
if (gli_conf_quotes > 1 && ch == '\'')
{
- if (numchars == 0 || leftquote(chars[numchars - 1]))
+ if (numchars == 0 || leftquote(_chars[numchars - 1]))
ch = UNI_LSQUO;
}
@@ -742,7 +1304,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
if (ch == '"')
{
- if (numchars == 0 || leftquote(chars[numchars - 1]))
+ if (numchars == 0 || leftquote(_chars[numchars - 1]))
ch = UNI_LDQUO;
else
ch = UNI_RDQUO;
@@ -810,23 +1372,23 @@ void TextBufferWindow::putCharUni(glui32 ch) {
}
}
- chars[numchars] = ch;
+ _chars[numchars] = ch;
attrs[numchars] = attr;
numchars++;
// kill spaces at the end for line width calculation
linelen = numchars;
- while (linelen > 1 && chars[linelen - 1] == ' '
+ while (linelen > 1 && _chars[linelen - 1] == ' '
&& styles[attrs[linelen - 1].style].bg == color
&& !styles[attrs[linelen - 1].style].reverse)
linelen--;
- if (calcwidth(dwin, chars, attrs, 0, linelen, -1) >= pw)
+ if (calcwidth(dwin, _chars, attrs, 0, linelen, -1) >= pw)
{
bpoint = numchars;
for (i = numchars - 1; i > 0; i--)
- if (chars[i] == ' ')
+ if (_chars[i] == ' ')
{
bpoint = i + 1; // skip space
break;
@@ -834,13 +1396,13 @@ void TextBufferWindow::putCharUni(glui32 ch) {
saved = numchars - bpoint;
- memcpy(bchars, chars + bpoint, saved * 4);
+ memcpy(bchars, _chars + bpoint, saved * 4);
memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
numchars = bpoint;
scrolloneline(dwin, 0);
- memcpy(chars, bchars, saved * 4);
+ memcpy(_chars, bchars, saved * 4);
memcpy(attrs, battrs, saved * sizeof(attr_t));
numchars = saved;
}
@@ -849,23 +1411,83 @@ void TextBufferWindow::putCharUni(glui32 ch) {
*/
}
-void TextBufferWindow::putTextUnit(const glui32 *buf, int len, int pos, int oldlen) {
+bool TextBufferWindow::unputCharUni(uint32 ch) {
// TODO
+ return false;
}
-void TextBufferWindow::flowBreak() {
+void TextBufferWindow::putBuffer(const unsigned char *buf, size_t len) {
// TODO
}
-void TextBufferWindow::touch(int line) {
- int y = bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
- _lines[line].dirty = 1;
- _windows->clearSelection();
- _windows->repaint(Common::Rect(bbox.left, y - 2, bbox.right, y + g_conf->_leading + 2));
+void TextBufferWindow::putBufferUni(const uint32 *buf, size_t len) {
+ // TODO
}
-glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
- return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
+void TextBufferWindow::moveCursor(const Common::Point &newPos) {
+ // TODO
+}
+
+void TextBufferWindow::clear() {
+ int i;
+
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
+
+ _ladjw = _radjw = 0;
+ _ladjn = _radjn = 0;
+
+ _spaced = 0;
+ _dashed = 0;
+
+ _numChars = 0;
+
+ for (i = 0; i < _scrollBack; i++) {
+ _lines[i].len = 0;
+
+ if (_lines[i].lpic) _lines[i].lpic->decrement();
+ _lines[i].lpic = nullptr;
+ if (_lines[i].rpic) _lines[i].rpic->decrement();
+ _lines[i].rpic = nullptr;
+
+ _lines[i].lhyper = 0;
+ _lines[i].rhyper = 0;
+ _lines[i].lm = 0;
+ _lines[i].rm = 0;
+ _lines[i].newline = 0;
+ _lines[i].dirty = true;
+ _lines[i].repaint = false;
+ }
+
+ _lastSeen = 0;
+ _scrollPos = 0;
+ _scrollMax = 0;
+
+ for (i = 0; i < _height; i++)
+ touch(i);
+}
+
+void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event: window already has keyboard request");
+ return;
+ }
+
+ // TODO
+}
+
+void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event_uni: window already has keyboard request");
+ return;
+ }
+
+ // TODO
}
void TextBufferWindow::cancelLineEvent(Event *ev) {
@@ -899,18 +1521,15 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
if (len > inmax)
len = inmax;
- if (!unicode)
- {
- for (ix = 0; ix<len; ix++)
- {
+ if (!unicode) {
+ for (ix = 0; ix<len; ix++) {
glui32 ch = _chars[_inFence + ix];
if (ch > 0xff)
ch = '?';
((char *)inbuf)[ix] = (char)ch;
}
}
- else
- {
+ else {
for (ix = 0; ix<len; ix++)
((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
}
@@ -933,7 +1552,8 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
if (_echoLineInput) {
putCharUni('\n');
- } else {
+ }
+ else {
_numChars = _inFence;
touch(0);
}
@@ -942,6 +1562,10 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
(*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
}
+void TextBufferWindow::redraw() {
+ // TODO
+}
+
/*--------------------------------------------------------------------------*/
TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
@@ -974,7 +1598,7 @@ void GraphicsWindow::rearrange(const Common::Rect &box) {
int oldw, oldh;
Graphics::ManagedSurface *newSurface;
- bbox = box;
+ _bbox = box;
newwid = box.width();
newhgt = box.height();
@@ -1013,7 +1637,11 @@ void GraphicsWindow::rearrange(const Common::Rect &box) {
void GraphicsWindow::touch() {
_dirty = true;
- _windows->repaint(bbox);
+ _windows->repaint(_bbox);
+}
+
+void GraphicsWindow::redraw() {
+ // TODO
}
/*--------------------------------------------------------------------------*/
@@ -1034,14 +1662,14 @@ void PairWindow::rearrange(const Common::Rect &box) {
int min, diff, split, splitwid, max;
Window *ch1, *ch2;
- bbox = box;
+ _bbox = box;
if (_vertical) {
- min = bbox.left;
- max = bbox.right;
+ min = _bbox.left;
+ max = _bbox.right;
} else {
- min = bbox.top;
- max = bbox.bottom;
+ min = _bbox.top;
+ max = _bbox.bottom;
}
diff = max - min;
@@ -1080,23 +1708,23 @@ void PairWindow::rearrange(const Common::Rect &box) {
}
if (_vertical) {
- box1.left = bbox.left;
+ box1.left = _bbox.left;
box1.right = split;
box2.left = split + splitwid;
- box2.right = bbox.right;
- box1.top = bbox.top;
- box1.bottom = bbox.bottom;
- box2.top = bbox.top;
- box2.bottom = bbox.bottom;
+ box2.right = _bbox.right;
+ box1.top = _bbox.top;
+ box1.bottom = _bbox.bottom;
+ box2.top = _bbox.top;
+ box2.bottom = _bbox.bottom;
} else {
- box1.top = bbox.top;
+ box1.top = _bbox.top;
box1.bottom = split;
box2.top = split + splitwid;
- box2.bottom = bbox.bottom;
- box1.left = bbox.left;
- box1.right = bbox.right;
- box2.left = bbox.left;
- box2.right = bbox.right;
+ box2.bottom = _bbox.bottom;
+ box1.left = _bbox.left;
+ box1.right = _bbox.right;
+ box2.left = _bbox.left;
+ box2.right = _bbox.right;
}
if (!_backward) {
@@ -1111,6 +1739,10 @@ void PairWindow::rearrange(const Common::Rect &box) {
ch2->rearrange(box2);
}
+void PairWindow::redraw() {
+ // TODO
+}
+
/*--------------------------------------------------------------------------*/
void Attributes::clear() {
@@ -1123,4 +1755,88 @@ void Attributes::clear() {
style = 0;
}
+byte *Attributes::attrBg(WindowStyle *styles) {
+ int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
+
+ int zfset = fgset ? fgset : Windows::_overrideFgSet;
+ int zbset = bgset ? bgset : Windows::_overrideBgSet;
+
+ int zfore = fgset ? fgcolor : Windows::_overrideFgVal;
+ int zback = bgset ? bgcolor : Windows::_overrideBgVal;
+
+ if (zfset && zfore != Windows::_zcolor_fg) {
+ Windows::_zcolor_Foreground[0] = (zfore >> 16) & 0xff;
+ Windows::_zcolor_Foreground[1] = (zfore >> 8) & 0xff;
+ Windows::_zcolor_Foreground[2] = (zfore)& 0xff;
+ Windows::_zcolor_fg = zfore;
+ }
+
+ if (zbset && zback != Windows::_zcolor_bg) {
+ Windows::_zcolor_Background[0] = (zback >> 16) & 0xff;
+ Windows::_zcolor_Background[1] = (zback >> 8) & 0xff;
+ Windows::_zcolor_Background[2] = (zback)& 0xff;
+ Windows::_zcolor_bg = zback;
+ }
+
+ if (!revset) {
+ if (zbset)
+ return Windows::_zcolor_Background;
+ else
+ return styles[style].bg;
+ } else {
+ if (zfset)
+ if (zfore == zback)
+ return Windows::rgbShift(Windows::_zcolor_Foreground);
+ else
+ return Windows::_zcolor_Foreground;
+ else
+ if (zbset && !memcmp(styles[style].fg, Windows::_zcolor_Background, 3))
+ return Windows::_zcolor_LightGrey;
+ else
+ return styles[style].fg;
+ }
+}
+
+byte *Attributes::attrFg(WindowStyle *styles) {
+ int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
+
+ int zfset = fgset ? fgset : Windows::_overrideFgSet;
+ int zbset = bgset ? bgset : Windows::_overrideBgSet;
+
+ int zfore = fgset ? fgcolor : Windows::_overrideFgVal;
+ int zback = bgset ? bgcolor : Windows::_overrideBgVal;
+
+ if (zfset && zfore != Windows::_zcolor_fg) {
+ Windows::_zcolor_Foreground[0] = (zfore >> 16) & 0xff;
+ Windows::_zcolor_Foreground[1] = (zfore >> 8) & 0xff;
+ Windows::_zcolor_Foreground[2] = (zfore)& 0xff;
+ Windows::_zcolor_fg = zfore;
+ }
+
+ if (zbset && zback != Windows::_zcolor_bg) {
+ Windows::_zcolor_Background[0] = (zback >> 16) & 0xff;
+ Windows::_zcolor_Background[1] = (zback >> 8) & 0xff;
+ Windows::_zcolor_Background[2] = (zback)& 0xff;
+ Windows::_zcolor_bg = zback;
+ }
+
+ if (!revset) {
+ if (zfset)
+ if (zfore == zback)
+ return Windows::rgbShift(Windows::_zcolor_Foreground);
+ else
+ return Windows::_zcolor_Foreground;
+ else
+ if (zbset && !memcmp(styles[style].fg, Windows::_zcolor_Background, 3))
+ return Windows::_zcolor_LightGrey;
+ else
+ return styles[style].fg;
+ } else {
+ if (zbset)
+ return Windows::_zcolor_Background;
+ else
+ return styles[style].bg;
+ }
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 24043c6..9a09641 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -27,17 +27,18 @@
#include "common/list.h"
#include "common/rect.h"
#include "graphics/screen.h"
+#include "gargoyle/draw.h"
#include "gargoyle/events.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
+#include "gargoyle/window_mask.h"
namespace Gargoyle {
class Window;
class PairWindow;
-struct WindowMask;
#define HISTORYLEN 100
#define SCROLLBACK 512
@@ -47,6 +48,7 @@ struct WindowMask;
* Main windows manager
*/
class Windows {
+ friend class Window;
public:
class iterator {
private:
@@ -82,7 +84,6 @@ private:
Window * _windowList; ///< List of all windows
Window *_rootWin; ///< The topmost window
Window *_focusWin; ///< The window selected by the player
- bool _forceRedraw;
bool _moreFocus;
bool _claimSelect;
WindowMask *_mask;
@@ -105,8 +106,16 @@ public:
static bool _overrideReverse;
static bool _overrideFgSet;
static bool _overrideBgSet;
+ static bool _forceRedraw;
static int _overrideFgVal;
static int _overrideBgVal;
+ static int _zcolor_fg, _zcolor_bg;
+ static byte _zcolor_LightGrey[3];
+ static byte _zcolor_Foreground[3];
+ static byte _zcolor_Background[3];
+ static byte _zcolor_Bright[3];
+
+ static byte *rgbShift(byte *rgb);
public:
/**
* Constructor
@@ -114,6 +123,11 @@ public:
Windows(Graphics::Screen *screen);
/**
+ * Destructor
+ */
+ ~Windows();
+
+ /**
* Open a new window
*/
Window *windowOpen(Window *splitwin, glui32 method, glui32 size,
@@ -124,14 +138,35 @@ public:
*/
Window *getRoot() const { return _rootWin; }
+ /**
+ * Gets the focused window
+ */
+ Window *getFocusWindow() const { return _focusWin; }
+
+ /**
+ * Setst the focused window
+ */
+ void setFocus(Window *win) { _focusWin = win; }
+
void clearSelection();
+ void selectionChanged();
+
+ void clearClaimSelect() { _claimSelect = false; }
+
+ void redraw();
+
/**
* Repaint an area of the windows
*/
void repaint(const Common::Rect &box);
/**
+ * Draw an area of the windows
+ */
+ void drawRect(int x0, int y0, int w, int h, const byte *rgb);
+
+ /**
* Get an iterator that will move over the tree
*/
iterator begin() { return iterator(_windowList); }
@@ -140,6 +175,18 @@ public:
* Returns the end point of window iteration
*/
iterator end() { return iterator(nullptr); }
+
+ /**
+ * Gets a hyperlink
+ */
+ glui32 getHyperlink(const Common::Point &pos) { return _mask->getHyperlink(pos); }
+
+ /**
+ * Sets a hyperlink
+ */
+ void setHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1) {
+ return _mask->putHyperlink(linkval, x0, y0, x1, y1);
+ }
};
/**
@@ -176,21 +223,37 @@ struct Attributes {
* Clear
*/
void clear();
-};
-struct WindowMask {
- int hor;
- int ver;
- glui32 **links;
- Common::Rect select;
+ /**
+ * Set the style
+ */
+ void set(glui32 s) {
+ clear();
+ style = s;
+ }
+
+ /**
+ * Equality comparison
+ */
+ bool operator==(const Attributes &src) {
+ return fgset == src.fgset && bgset == src.bgset && reverse == src.reverse
+ && style == src.style && fgcolor == src.fgcolor && bgcolor == src.bgcolor
+ && hyper == src.hyper;
+ }
+
+ byte *attrBg(WindowStyle *styles);
+ byte *attrFg(WindowStyle *styles);
- WindowMask() : hor(0), ver(0), links(nullptr) {}
+ /**
+ * Get the font from the attribute's style
+ */
+ FACES attrFont(WindowStyle *styles) const { return styles[style].font; }
};
/**
* Window definition
*/
-class Window {
+class Window : public Draw {
public:
Windows *_windows;
glui32 _magicnum;
@@ -199,8 +262,8 @@ public:
Window *_parent; ///< pair window which contains this one
Window *_next, *_prev; ///< in the big linked list of windows
- Common::Rect bbox;
- int yadj;
+ Common::Rect _bbox;
+ int _yAdj;
Stream *_stream; ///< the window stream.
Stream *_echoStream; ///< the window's echo stream, if any.
@@ -216,7 +279,7 @@ public:
int _imageLoaded;
glui32 _echoLineInput;
- glui32 *_lineTerminators;
+ glui32 *_lineTerminatorsBase;
glui32 _termCt;
Attributes _attr;
@@ -224,6 +287,8 @@ public:
byte _fgColor[3];
gidispatch_rock_t _dispRock;
+protected:
+ bool checkTerminator(glui32 ch);
public:
/**
* Constructor
@@ -233,12 +298,12 @@ public:
/**
* Destructor
*/
- virtual ~Window() {}
+ virtual ~Window();
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box) { bbox = box; }
+ virtual void rearrange(const Common::Rect &box) { _bbox = box; }
/**
* Get window split size within parent pair window
@@ -246,29 +311,74 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const { return 0; }
/**
- * Cancel a line event
+ * Write a character
*/
- virtual void cancelLineEvent(Event *ev);
+ virtual void putChar(unsigned char ch) {}
/**
- * Write a character
+ * Write a unicode character
*/
- virtual void putChar(unsigned char ch) { /* TODO */ }
+ virtual void putCharUni(uint32 ch) {}
/**
- * Write a unicode character
+ * Unput a unicode character
*/
- virtual void putCharUni(uint32 ch) { /* TODO */ }
+ virtual bool unputCharUni(uint32 ch) { return false; }
/**
* Write a buffer
*/
- virtual void putBuffer(const unsigned char *buf, size_t len) { /* TODO */ }
+ virtual void putBuffer(const unsigned char *buf, size_t len) {}
/**
* Write a unicode character
*/
- virtual void putBufferUni(const uint32 *buf, size_t len) { /* TODO */ }
+ virtual void putBufferUni(const uint32 *buf, size_t len) {}
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) {}
+
+ /**
+ * Clear the window
+ */
+ virtual void clear() {}
+
+ /**
+ * Click the window
+ */
+ virtual void click(const Common::Point &newPos) {}
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen);
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen);
+
+ /**
+ * Cancel an input line event
+ */
+ virtual void cancelLineEvent(Event *ev);
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() {}
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() {}
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw();
};
typedef Window *winid_t;
@@ -291,8 +401,8 @@ class TextGridWindow : public Window {
* Structure for a row within the grid window
*/
struct TextGridRow {
- Common::Array<uint32> chars;
- Common::Array<Attributes> attr;
+ Common::Array<uint32> _chars;
+ Common::Array<Attributes> _attrs;
bool dirty;
/**
@@ -311,13 +421,25 @@ private:
* Mark a given text row as modified
*/
void touch(int line);
+
+ void acceptReadChar(glui32 arg);
+
+ /**
+ * Return or enter, during line input. Ends line input.
+ */
+ void acceptLine(glui32 keycode);
+
+ /**
+ * Any regular key, during line input.
+ */
+ void acceptReadLine(glui32 arg);
public:
int _width, _height;
TextGridRows _lines;
int _curX, _curY; ///< the window cursor position
- ///< for line input
+ ///< for line input
void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
int _inOrgX, _inOrgY;
int _inMax;
@@ -349,9 +471,74 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const override;
/**
- * Cancel a line event
+ * Write a character
+ */
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Unput a unicode character
+ */
+ virtual bool unputCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) override;
+
+ /**
+ * Clear the window
+ */
+ virtual void clear() override;
+
+ /**
+ * Click the window
+ */
+ virtual void click(const Common::Point &newPos) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Cancel an input line event
*/
virtual void cancelLineEvent(Event *ev) override;
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() override { _mouseRequest = false; }
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
};
/**
@@ -385,8 +572,7 @@ private:
void reflow();
void touchScroll();
bool putPicture(Picture *pic, glui32 align, glui32 linkval);
- void putCharUni(glui32 ch);
- void putTextUnit(const glui32 *buf, int len, int pos, int oldlen);
+ void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
void flowBreak();
/**
@@ -460,14 +646,64 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const override;
/**
- * Cancel a line event
+ * Write a character
*/
- virtual void cancelLineEvent(Event *ev) override;
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Unput a unicode character
+ */
+ virtual bool unputCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) override;
/**
* Clear the window
*/
- void clear();
+ virtual void clear() override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Cancel an input line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
};
/**
@@ -479,7 +715,7 @@ private:
public:
unsigned char _bgnd[3];
bool _dirty;
- int _w, _h;
+ glui32 _w, _h;
Graphics::ManagedSurface *_surface;
public:
/**
@@ -503,6 +739,29 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const override {
return size;
}
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() override { _mouseRequest = false; }
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+
+ /**
+ * Get the window dimensions
+ */
+ void getSize(glui32 *w, glui32 *h) {
+ *w = _w;
+ *h = _h;
+ }
};
/**
@@ -530,6 +789,11 @@ public:
* Rearranges the window
*/
virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
};
} // End of namespace Gargoyle
Commit: 8708ed4f9aead0876d09dd9b6bb9096407cd961c
https://github.com/scummvm/scummvm/commit/8708ed4f9aead0876d09dd9b6bb9096407cd961c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Split the windows.cpp file into separate files for each window class
Changed paths:
A engines/gargoyle/window_graphics.cpp
A engines/gargoyle/window_graphics.h
A engines/gargoyle/window_pair.cpp
A engines/gargoyle/window_pair.h
A engines/gargoyle/window_text_buffer.cpp
A engines/gargoyle/window_text_buffer.h
A engines/gargoyle/window_text_grid.cpp
A engines/gargoyle/window_text_grid.h
engines/gargoyle/module.mk
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 46f2d31..e684ff9 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -11,8 +11,12 @@ MODULE_OBJS := \
picture.o \
streams.o \
string.o \
- window_mask.o \
windows.o \
+ window_mask.o \
+ window_graphics.o \
+ window_pair.o \
+ window_text_buffer.o \
+ window_text_grid.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
new file mode 100644
index 0000000..cc9a5dd
--- /dev/null
+++ b/engines/gargoyle/window_graphics.cpp
@@ -0,0 +1,89 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/window_graphics.h"
+
+namespace Gargoyle {
+
+GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
+_w(0), _h(0), _dirty(false), _surface(nullptr) {
+ _type = wintype_Graphics;
+ Common::copy(&_bgColor[0], &_bgColor[3], _bgnd);
+}
+
+GraphicsWindow::~GraphicsWindow() {
+ delete _surface;
+}
+
+void GraphicsWindow::rearrange(const Common::Rect &box) {
+ int newwid, newhgt;
+ int bothwid, bothhgt;
+ int oldw, oldh;
+ Graphics::ManagedSurface *newSurface;
+
+ _bbox = box;
+
+ newwid = box.width();
+ newhgt = box.height();
+ oldw = _w;
+ oldh = _h;
+
+ if (newwid <= 0 || newhgt <= 0) {
+ _w = 0;
+ _h = 0;
+ delete _surface;
+ _surface = NULL;
+ return;
+ }
+
+ bothwid = _w;
+ if (newwid < bothwid)
+ bothwid = newwid;
+ bothhgt = _h;
+ if (newhgt < bothhgt)
+ bothhgt = newhgt;
+
+ newSurface = new Graphics::ManagedSurface(newwid, newhgt,
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
+
+ // If the new surface is equal or bigger than the old one, copy it over
+ if (_surface && bothwid && bothhgt)
+ newSurface->blitFrom(*_surface);
+
+ delete _surface;
+ _surface = newSurface;
+ _w = newwid;
+ _h = newhgt;
+
+ touch();
+}
+
+void GraphicsWindow::touch() {
+ _dirty = true;
+ _windows->repaint(_bbox);
+}
+
+void GraphicsWindow::redraw() {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
new file mode 100644
index 0000000..77e4910
--- /dev/null
+++ b/engines/gargoyle/window_graphics.h
@@ -0,0 +1,91 @@
+/* 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 GARGOYLE_WINDOW_GRAPHICS_H
+#define GARGOYLE_WINDOW_GRAPHICS_H
+
+#include "gargoyle/windows.h"
+#include "gargoyle/picture.h"
+
+namespace Gargoyle {
+
+/**
+ * Graphics window
+ */
+class GraphicsWindow : public Window {
+private:
+ void touch();
+public:
+ unsigned char _bgnd[3];
+ bool _dirty;
+ glui32 _w, _h;
+ Graphics::ManagedSurface *_surface;
+public:
+ /**
+ * Constructor
+ */
+ GraphicsWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~GraphicsWindow();
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override {
+ return size;
+ }
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() override { _mouseRequest = false; }
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+
+ /**
+ * Get the window dimensions
+ */
+ void getSize(glui32 *w, glui32 *h) {
+ *w = _w;
+ *h = _h;
+ }
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
new file mode 100644
index 0000000..af3ed4c
--- /dev/null
+++ b/engines/gargoyle/window_pair.cpp
@@ -0,0 +1,125 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/window_pair.h"
+#include "gargoyle/conf.h"
+
+namespace Gargoyle {
+
+PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size) :
+ Window(windows, 0),
+ _dir(method & winmethod_DirMask),
+ _division(method & winmethod_DivisionMask),
+ _wBorder((method & winmethod_BorderMask) == winmethod_Border),
+ _vertical(_dir == winmethod_Left || _dir == winmethod_Right),
+ _backward(_dir == winmethod_Left || _dir == winmethod_Above),
+ _key(key), _size(size), _keyDamage(0), _child1(nullptr), _child2(nullptr) {
+ _type = wintype_Pair;
+}
+
+void PairWindow::rearrange(const Common::Rect &box) {
+ Common::Rect box1, box2;
+ int min, diff, split, splitwid, max;
+ Window *ch1, *ch2;
+
+ _bbox = box;
+
+ if (_vertical) {
+ min = _bbox.left;
+ max = _bbox.right;
+ } else {
+ min = _bbox.top;
+ max = _bbox.bottom;
+ }
+ diff = max - min;
+
+ // We now figure split.
+ if (_vertical)
+ splitwid = g_conf->_wPaddingX; // want border?
+ else
+ splitwid = g_conf->_wPaddingY; // want border?
+
+ switch (_division) {
+ case winmethod_Proportional:
+ split = (diff * _size) / 100;
+ break;
+
+ case winmethod_Fixed:
+ split = !_key ? 0 : _key->getSplit(_size, _vertical);
+ break;
+
+ default:
+ split = diff / 2;
+ break;
+ }
+
+ if (!_backward)
+ split = max - split - splitwid;
+ else
+ split = min + split;
+
+ if (min >= max) {
+ split = min;
+ } else {
+ if (split < min)
+ split = min;
+ else if (split > max - splitwid)
+ split = max - splitwid;
+ }
+
+ if (_vertical) {
+ box1.left = _bbox.left;
+ box1.right = split;
+ box2.left = split + splitwid;
+ box2.right = _bbox.right;
+ box1.top = _bbox.top;
+ box1.bottom = _bbox.bottom;
+ box2.top = _bbox.top;
+ box2.bottom = _bbox.bottom;
+ } else {
+ box1.top = _bbox.top;
+ box1.bottom = split;
+ box2.top = split + splitwid;
+ box2.bottom = _bbox.bottom;
+ box1.left = _bbox.left;
+ box1.right = _bbox.right;
+ box2.left = _bbox.left;
+ box2.right = _bbox.right;
+ }
+
+ if (!_backward) {
+ ch1 = _child1;
+ ch2 = _child2;
+ } else {
+ ch1 = _child2;
+ ch2 = _child1;
+ }
+
+ ch1->rearrange(box1);
+ ch2->rearrange(box2);
+}
+
+void PairWindow::redraw() {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
new file mode 100644
index 0000000..b25b324
--- /dev/null
+++ b/engines/gargoyle/window_pair.h
@@ -0,0 +1,64 @@
+/* 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 GARGOYLE_WINDOW_PAIR_H
+#define GARGOYLE_WINDOW_PAIR_H
+
+#include "gargoyle/windows.h"
+
+namespace Gargoyle {
+
+/**
+ * Pair window
+ */
+class PairWindow : public Window {
+public:
+ Window *_child1, *_child2;
+
+ /* split info... */
+ glui32 _dir; ///< winmethod_Left, Right, Above, or Below
+ bool _vertical, _backward; ///< flags
+ glui32 _division; ///< winmethod_Fixed or winmethod_Proportional
+ Window *_key; ///< NULL or a leaf-descendant (not a Pair)
+ int _keyDamage; ///< used as scratch space in window closing
+ glui32 _size; ///< size value
+ glui32 _wBorder; ///< winMethod_Border, NoBorder
+public:
+ /**
+ * Constructor
+ */
+ PairWindow(Windows *windows, glui32 method, Window *key, glui32 size);
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
new file mode 100644
index 0000000..1e85a24
--- /dev/null
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -0,0 +1,602 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/window_text_buffer.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+
+namespace Gargoyle {
+
+TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
+ _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
+ _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
+ _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
+ _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
+ _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
+ _type = wintype_TextBuffer;
+ Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
+
+ Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
+}
+
+TextBufferWindow::~TextBufferWindow() {
+ if (_inBuf) {
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
+ _inBuf = nullptr;
+ }
+
+ delete[] _copyBuf;
+ delete[] _lineTerminators;
+
+ for (int i = 0; i < _scrollBack; i++) {
+ if (_lines[i].lpic)
+ _lines[i].lpic->decrement();
+ if (_lines[i].rpic)
+ _lines[i].rpic->decrement();
+ }
+}
+
+void TextBufferWindow::rearrange(const Common::Rect &box) {
+ Window::rearrange(box);
+ int newwid, newhgt;
+ int rnd;
+
+ newwid = (box.width() - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) / g_conf->_cellW;
+ newhgt = (box.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
+
+ /* align text with bottom */
+ rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
+ _yAdj = (box.height() - rnd);
+ _bbox.top += (box.height() - rnd);
+
+ if (newwid != _width) {
+ _width = newwid;
+ reflow();
+ }
+
+ if (newhgt != _height) {
+ /* scroll up if we obscure new lines */
+ if (_lastSeen >= newhgt - 1)
+ _scrollPos += (_height - newhgt);
+
+ _height = newhgt;
+
+ /* keep window within 'valid' lines */
+ if (_scrollPos > _scrollMax - _height + 1)
+ _scrollPos = _scrollMax - _height + 1;
+ if (_scrollPos < 0)
+ _scrollPos = 0;
+ touchScroll();
+
+ /* allocate copy buffer */
+ if (_copyBuf)
+ delete[] _copyBuf;
+ _copyBuf = new glui32[_height * TBLINELEN];
+
+ for (int i = 0; i < (_height * TBLINELEN); i++)
+ _copyBuf[i] = 0;
+
+ _copyPos = 0;
+ }
+}
+
+void TextBufferWindow::reflow() {
+ int inputbyte = -1;
+ Attributes curattr, oldattr;
+ int i, k, p, s;
+ int x;
+
+ if (_height < 4 || _width < 20)
+ return;
+
+ _lines[0].len = _numChars;
+
+ /* allocate temp buffers */
+ Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
+ glui32 *charbuf = new glui32[SCROLLBACK * TBLINELEN];
+ int *alignbuf = new int[SCROLLBACK];
+ Picture **pictbuf = new Picture *[SCROLLBACK];
+ glui32 *hyperbuf = new glui32[SCROLLBACK];
+ int *offsetbuf = new int[SCROLLBACK];
+
+ if (!attrbuf || !charbuf || !alignbuf || !pictbuf || !hyperbuf || !offsetbuf) {
+ delete[] attrbuf;
+ delete[] charbuf;
+ delete[] alignbuf;
+ delete[] pictbuf;
+ delete[] hyperbuf;
+ delete[] offsetbuf;
+ return;
+ }
+
+ /* copy text to temp buffers */
+
+ oldattr = _attr;
+ curattr.clear();
+
+ x = 0;
+ p = 0;
+ s = _scrollMax < SCROLLBACK ? _scrollMax : SCROLLBACK - 1;
+
+ for (k = s; k >= 0; k--) {
+ if (k == 0 && _lineRequest)
+ inputbyte = p + _inFence;
+
+ if (_lines[k].lpic) {
+ offsetbuf[x] = p;
+ alignbuf[x] = imagealign_MarginLeft;
+ pictbuf[x] = _lines[k].lpic;
+
+ if (pictbuf[x]) pictbuf[x]->increment();
+ hyperbuf[x] = _lines[k].lhyper;
+ x++;
+ }
+
+ if (_lines[k].rpic) {
+ offsetbuf[x] = p;
+ alignbuf[x] = imagealign_MarginRight;
+ pictbuf[x] = _lines[k].rpic;
+ if (pictbuf[x]) pictbuf[x]->increment();
+ hyperbuf[x] = _lines[k].rhyper;
+ x++;
+ }
+
+ for (i = 0; i < _lines[k].len; i++) {
+ attrbuf[p] = curattr = _lines[k].attr[i];
+ charbuf[p] = _lines[k].chars[i];
+ p++;
+ }
+
+ if (_lines[k].newline) {
+ attrbuf[p] = curattr;
+ charbuf[p] = '\n';
+ p++;
+ }
+ }
+
+ offsetbuf[x] = -1;
+
+ /* clear window */
+
+ clear();
+
+ /* and dump text back */
+
+ x = 0;
+ for (i = 0; i < p; i++) {
+ if (i == inputbyte)
+ break;
+ _attr = attrbuf[i];
+
+ if (offsetbuf[x] == i) {
+ putPicture(pictbuf[x], alignbuf[x], hyperbuf[x]);
+ x++;
+ }
+
+ putCharUni(charbuf[i]);
+ }
+
+ /* terribly sorry about this... */
+ _lastSeen = 0;
+ _scrollPos = 0;
+
+ if (inputbyte != -1) {
+ _inFence = _numChars;
+ putTextUni(charbuf + inputbyte, p - inputbyte, _numChars, 0);
+ _inCurs = _numChars;
+ }
+
+ // free temp buffers
+ delete[] attrbuf;
+ delete[] charbuf;
+ delete[] alignbuf;
+ delete[] pictbuf;
+ delete[] hyperbuf;
+ delete[] offsetbuf;
+
+ _attr = oldattr;
+
+ touchScroll();
+}
+
+void TextBufferWindow::touchScroll() {
+ _windows->clearSelection();
+ _windows->repaint(_bbox);
+
+ for (int i = 0; i < _scrollMax; i++)
+ _lines[i].dirty = true;
+}
+
+bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
+ if (align == imagealign_MarginRight)
+ {
+ if (_lines[0].rpic || _numChars)
+ return false;
+
+ _radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ _radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
+ _lines[0].rpic = pic;
+ _lines[0].rm = _radjw;
+ _lines[0].rhyper = linkval;
+ } else {
+ if (align != imagealign_MarginLeft && _numChars)
+ putCharUni('\n');
+
+ if (_lines[0].lpic || _numChars)
+ return false;
+
+ _ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ _ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
+ _lines[0].lpic = pic;
+ _lines[0].lm = _ladjw;
+ _lines[0].lhyper = linkval;
+
+ if (align != imagealign_MarginLeft)
+ flowBreak();
+ }
+
+ return true;
+}
+
+void TextBufferWindow::flowBreak() {
+ // TODO
+}
+
+void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldlen) {
+ // TODO
+}
+
+void TextBufferWindow::touch(int line) {
+ int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
+ _lines[line].dirty = 1;
+ _windows->clearSelection();
+ _windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
+}
+
+glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
+ return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
+}
+
+void TextBufferWindow::putChar(unsigned char ch) {
+}
+
+void TextBufferWindow::putCharUni(glui32 ch) {
+ /*
+ glui32 bchars[TBLINELEN];
+ Attributes battrs[TBLINELEN];
+ int pw;
+ int bpoint;
+ int saved;
+ int i;
+ int linelen;
+ unsigned char *color;
+
+ gli_tts_speak(&ch, 1);
+
+ pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
+ pw = pw - 2 * SLOP - radjw - ladjw;
+
+ color = Windows::_overrideBgSet ? gli_window_color : bgcolor;
+
+ // oops ... overflow
+ if (numchars + 1 >= TBLINELEN)
+ scrolloneline(dwin, 0);
+
+ if (ch == '\n') {
+ scrolloneline(dwin, 1);
+ return;
+ }
+
+ if (gli_conf_quotes) {
+ // fails for 'tis a wonderful day in the '80s
+ if (gli_conf_quotes > 1 && ch == '\'')
+ {
+ if (numchars == 0 || leftquote(_chars[numchars - 1]))
+ ch = UNI_LSQUO;
+ }
+
+ if (ch == '`')
+ ch = UNI_LSQUO;
+
+ if (ch == '\'')
+ ch = UNI_RSQUO;
+
+ if (ch == '"')
+ {
+ if (numchars == 0 || leftquote(_chars[numchars - 1]))
+ ch = UNI_LDQUO;
+ else
+ ch = UNI_RDQUO;
+ }
+ }
+
+ if (gli_conf_dashes && attr.style != style_Preformatted)
+ {
+ if (ch == '-')
+ {
+ dashed++;
+ if (dashed == 2)
+ {
+ numchars--;
+ if (gli_conf_dashes == 2)
+ ch = UNI_NDASH;
+ else
+ ch = UNI_MDASH;
+ }
+ if (dashed == 3)
+ {
+ numchars--;
+ ch = UNI_MDASH;
+ dashed = 0;
+ }
+ }
+ else
+ dashed = 0;
+ }
+
+ if (gli_conf_spaces && attr.style != style_Preformatted
+ && styles[attr.style].bg == color
+ && !styles[attr.style].reverse)
+ {
+ // turn (period space space) into (period space)
+ if (gli_conf_spaces == 1)
+ {
+ if (ch == '.')
+ spaced = 1;
+ else if (ch == ' ' && spaced == 1)
+ spaced = 2;
+ else if (ch == ' ' && spaced == 2)
+ {
+ spaced = 0;
+ return;
+ }
+ else
+ spaced = 0;
+ }
+
+ // Turn (per sp x) into (per sp sp x)
+ if (gli_conf_spaces == 2)
+ {
+ if (ch == '.')
+ spaced = 1;
+ else if (ch == ' ' && spaced == 1)
+ spaced = 2;
+ else if (ch != ' ' && spaced == 2)
+ {
+ spaced = 0;
+ win_textbuffer_putchar_uni(win, ' ');
+ }
+ else
+ spaced = 0;
+ }
+ }
+
+ _chars[numchars] = ch;
+ attrs[numchars] = attr;
+ numchars++;
+
+ // kill spaces at the end for line width calculation
+ linelen = numchars;
+ while (linelen > 1 && _chars[linelen - 1] == ' '
+ && styles[attrs[linelen - 1].style].bg == color
+ && !styles[attrs[linelen - 1].style].reverse)
+ linelen--;
+
+ if (calcwidth(dwin, _chars, attrs, 0, linelen, -1) >= pw)
+ {
+ bpoint = numchars;
+
+ for (i = numchars - 1; i > 0; i--)
+ if (_chars[i] == ' ')
+ {
+ bpoint = i + 1; // skip space
+ break;
+ }
+
+ saved = numchars - bpoint;
+
+ memcpy(bchars, _chars + bpoint, saved * 4);
+ memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
+ numchars = bpoint;
+
+ scrolloneline(dwin, 0);
+
+ memcpy(_chars, bchars, saved * 4);
+ memcpy(attrs, battrs, saved * sizeof(attr_t));
+ numchars = saved;
+ }
+
+ touch(0);
+ */
+}
+
+bool TextBufferWindow::unputCharUni(uint32 ch) {
+ // TODO
+ return false;
+}
+
+void TextBufferWindow::putBuffer(const unsigned char *buf, size_t len) {
+ // TODO
+}
+
+void TextBufferWindow::putBufferUni(const uint32 *buf, size_t len) {
+ // TODO
+}
+
+void TextBufferWindow::moveCursor(const Common::Point &newPos) {
+ // TODO
+}
+
+void TextBufferWindow::clear() {
+ int i;
+
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
+
+ _ladjw = _radjw = 0;
+ _ladjn = _radjn = 0;
+
+ _spaced = 0;
+ _dashed = 0;
+
+ _numChars = 0;
+
+ for (i = 0; i < _scrollBack; i++) {
+ _lines[i].len = 0;
+
+ if (_lines[i].lpic) _lines[i].lpic->decrement();
+ _lines[i].lpic = nullptr;
+ if (_lines[i].rpic) _lines[i].rpic->decrement();
+ _lines[i].rpic = nullptr;
+
+ _lines[i].lhyper = 0;
+ _lines[i].rhyper = 0;
+ _lines[i].lm = 0;
+ _lines[i].rm = 0;
+ _lines[i].newline = 0;
+ _lines[i].dirty = true;
+ _lines[i].repaint = false;
+ }
+
+ _lastSeen = 0;
+ _scrollPos = 0;
+ _scrollMax = 0;
+
+ for (i = 0; i < _height; i++)
+ touch(i);
+}
+
+void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event: window already has keyboard request");
+ return;
+ }
+
+ // TODO
+}
+
+void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event_uni: window already has keyboard request");
+ return;
+ }
+
+ // TODO
+}
+
+void TextBufferWindow::cancelLineEvent(Event *ev) {
+ gidispatch_rock_t inarrayrock;
+ int ix;
+ int len;
+ void *inbuf;
+ int inmax;
+ int unicode = _lineRequestUni;
+ Event dummyEv;
+
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+
+ if (!_lineRequest && !_lineRequestUni)
+ return;
+
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ len = _numChars - _inFence;
+ if (_echoStream)
+ _echoStream->echoLineUni(_chars + _inFence, len);
+
+ if (len > inmax)
+ len = inmax;
+
+ if (!unicode) {
+ for (ix = 0; ix<len; ix++) {
+ glui32 ch = _chars[_inFence + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ }
+ else {
+ for (ix = 0; ix<len; ix++)
+ ((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
+ }
+
+ _attr = _origAttr;
+
+ ev->_type = evtype_LineInput;
+ ev->_window = this;
+ ev->_val1 = len;
+ ev->_val2 = 0;
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+ if (_lineTerminators) {
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ }
+ _inBuf = nullptr;
+ _inMax = 0;
+
+ if (_echoLineInput) {
+ putCharUni('\n');
+ }
+ else {
+ _numChars = _inFence;
+ touch(0);
+ }
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextBufferWindow::redraw() {
+ // TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
+ lpic(nullptr), rpic(nullptr), lhyper(0), rhyper(0), lm(0), rm(0) {
+}
+
+void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
+ chars.clear();
+ attr.clear();
+ chars.resize(newSize);
+ attr.resize(newSize);
+ Common::fill(&chars[0], &chars[0] + newSize, ' ');
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
new file mode 100644
index 0000000..f7427d7
--- /dev/null
+++ b/engines/gargoyle/window_text_buffer.h
@@ -0,0 +1,198 @@
+/* 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 GARGOYLE_WINDOW_TEXT_BUFFER_H
+#define GARGOYLE_WINDOW_TEXT_BUFFER_H
+
+#include "gargoyle/windows.h"
+#include "gargoyle/picture.h"
+
+namespace Gargoyle {
+
+/**
+ * Text Buffer window
+ */
+class TextBufferWindow : public Window {
+ /**
+ * Structure for a row within the window
+ */
+ struct TextBufferRow {
+ Common::Array<uint32> chars;
+ Common::Array<Attributes> attr;
+ int len, newline;
+ bool dirty, repaint;
+ Picture *lpic, *rpic;
+ glui32 lhyper, rhyper;
+ int lm, rm;
+
+ /**
+ * Constructor
+ */
+ TextBufferRow();
+
+ /**
+ * Resize the row
+ */
+ void resize(size_t newSize);
+ };
+ typedef Common::Array<TextBufferRow> TextBufferRows;
+private:
+ void reflow();
+ void touchScroll();
+ bool putPicture(Picture *pic, glui32 align, glui32 linkval);
+ void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
+ void flowBreak();
+
+ /**
+ * Mark a given text row as modified
+ */
+ void touch(int line);
+public:
+ int _width, _height;
+ int _spaced;
+ int _dashed;
+
+ TextBufferRows _lines;
+ int _scrollBack;
+
+ int _numChars; ///< number of chars in last line: lines[0]
+ glui32 *_chars; ///< alias to lines[0].chars
+ Attributes *_attrs; ///< alias to lines[0].attrs
+
+ ///< adjust margins temporarily for images
+ int _ladjw;
+ int _ladjn;
+ int _radjw;
+ int _radjn;
+
+ /* Command history. */
+ glui32 *_history[HISTORYLEN];
+ int _historyPos;
+ int _historyFirst, _historyPresent;
+
+ /* for paging */
+ int _lastSeen;
+ int _scrollPos;
+ int _scrollMax;
+
+ /* for line input */
+ void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
+ int _inMax;
+ long _inFence;
+ long _inCurs;
+ Attributes _origAttr;
+ gidispatch_rock_t _inArrayRock;
+
+ glui32 _echoLineInput;
+ glui32 *_lineTerminators;
+
+ /* style hints and settings */
+ WindowStyle styles[style_NUMSTYLES];
+
+ /* for copy selection */
+ glui32 *_copyBuf;
+ int _copyPos;
+public:
+ /**
+ * Constructor
+ */
+ TextBufferWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~TextBufferWindow();
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override;
+
+ /**
+ * Write a character
+ */
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Unput a unicode character
+ */
+ virtual bool unputCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) override;
+
+ /**
+ * Clear the window
+ */
+ virtual void clear() override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Cancel an input line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
new file mode 100644
index 0000000..41444ed
--- /dev/null
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -0,0 +1,665 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/window_text_grid.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+
+namespace Gargoyle {
+
+TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
+ _type = wintype_TextGrid;
+ _width = _height = 0;
+ _curX = _curY = 0;
+ _inBuf = nullptr;
+ _inOrgX = _inOrgY = 0;
+ _inMax = 0;
+ _inCurs = _inLen = 0;
+ _inArrayRock.num = 0;
+ _lineTerminators = nullptr;
+
+ Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
+}
+
+TextGridWindow::~TextGridWindow() {
+ if (_inBuf) {
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
+ _inBuf = nullptr;
+ }
+
+ delete[] _lineTerminators;
+}
+
+void TextGridWindow::rearrange(const Common::Rect &box) {
+ Window::rearrange(box);
+ int newwid, newhgt;
+
+ newwid = box.width() / g_conf->_cellW;
+ newhgt = box.height() / g_conf->_cellH;
+
+ if (newwid == _width && newhgt == _height)
+ return;
+
+ _lines.resize(newhgt);
+ for (int y = 0; y < newhgt; ++y) {
+ _lines[y].resize(newwid);
+ touch(y);
+ }
+
+ _attr.clear();
+ _width = newwid;
+ _height = newhgt;
+}
+
+void TextGridWindow::touch(int line) {
+ int y = _bbox.top + line * g_conf->_leading;
+ _lines[line].dirty = true;
+ _windows->repaint(Common::Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
+}
+
+glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
+ return vertical ? size * g_conf->_cellW + g_conf->_tMarginX * 2 :
+ size * g_conf->_cellH + g_conf->_tMarginY * 2;
+}
+
+void TextGridWindow::putChar(unsigned char ch) {
+
+}
+
+void TextGridWindow::putCharUni(uint32 ch) {
+ TextGridRow *ln;
+
+ // Canonicalize the cursor position. That is, the cursor may have been
+ // left outside the window area; wrap it if necessary.
+ if (_curX < 0) {
+ _curX = 0;
+ } else if (_curX >= _width) {
+ _curX = 0;
+ _curY++;
+ }
+ if (_curY < 0)
+ _curY = 0;
+ else if (_curY >= _height)
+ return; /* outside the window */
+
+ if (ch == '\n') {
+ /* a newline just moves the cursor. */
+ _curY++;
+ _curX = 0;
+ return;
+ }
+
+ touch(_curY);
+
+ ln = &(_lines[_curY]);
+ ln->_chars[_curX] = ch;
+ ln->_attrs[_curX] = _attr;
+
+ _curX++;
+ // We can leave the cursor outside the window, since it will be
+ // canonicalized next time a character is printed.
+}
+
+bool TextGridWindow::unputCharUni(uint32 ch) {
+ TextGridRow *ln;
+ int oldx = _curX, oldy = _curY;
+
+ /* Move the cursor back. */
+ if (_curX >= _width)
+ _curX = _width - 1;
+ else
+ _curX--;
+
+ /* Canonicalize the cursor position. That is, the cursor may have been
+ left outside the window area; wrap it if necessary. */
+ if (_curX < 0) {
+ _curX = _width - 1;
+ _curY--;
+ }
+ if (_curY < 0)
+ _curY = 0;
+ else if (_curY >= _height)
+ return false; // outside the window
+
+ if (ch == '\n') {
+ // a newline just moves the cursor.
+ if (_curX == _width - 1)
+ return 1; // deleted a newline
+ _curX = oldx;
+ _curY = oldy;
+ return 0; // it wasn't there */
+ }
+
+ ln = &(_lines[_curY]);
+ if (ln->_chars[_curX] == ch) {
+ ln->_chars[_curX] = ' ';
+ ln->_attrs[_curX].clear();
+ touch(_curY);
+ return true; // deleted the char
+ } else {
+ _curX = oldx;
+ _curY = oldy;
+ return false; // it wasn't there
+ }
+}
+
+void TextGridWindow::putBuffer(const unsigned char *buf, size_t len) {
+ // TODO
+}
+
+void TextGridWindow::putBufferUni(const uint32 *buf, size_t len) {
+ // TODO
+}
+
+void TextGridWindow::moveCursor(const Common::Point &pos) {
+ // If the values are negative, they're really huge positive numbers --
+ // remember that they were cast from glui32. So set them huge and
+ // let canonicalization take its course.
+ _curX = (pos.x < 0) ? 32767 : pos.x;
+ _curY = (pos.y < 0) ? 32767 : pos.y;
+}
+
+void TextGridWindow::clear() {
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
+
+ for (int k = 0; k < _height; k++) {
+ TextGridRow &ln = _lines[k];
+ touch(k);
+ for (uint j = 0; j < ln._attrs.size(); ++j) {
+ ln._chars[j] = ' ';
+ ln._attrs[j].clear();
+ }
+ }
+
+ _curX = 0;
+ _curY = 0;
+}
+
+void TextGridWindow::click(const Common::Point &newPos) {
+ int x = newPos.x - _bbox.left;
+ int y = newPos.y - _bbox.top;
+
+ if (_lineRequest || _charRequest || _lineRequestUni || _charRequestUni
+ || _moreRequest || _scrollRequest)
+ _windows->setFocus(this);
+
+ if (_mouseRequest) {
+ g_vm->_events->eventStore(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
+ _mouseRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+
+ if (_hyperRequest) {
+ glui32 linkval = _windows->getHyperlink(newPos);
+ if (linkval)
+ {
+ g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
+ _hyperRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+ }
+}
+
+void TextGridWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event: window already has keyboard request");
+ return;
+ }
+
+ if ((int)maxlen > (_width - _curX))
+ maxlen = (_width - _curX);
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inLen = 0;
+ _inCurs = 0;
+ _inOrgX = _curX;
+ _inOrgY = _curY;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ if (initlen > maxlen)
+ initlen = maxlen;
+
+ if (initlen) {
+ TextGridRow *ln = &_lines[_inOrgY];
+
+ for (glui32 ix = 0; ix < initlen; ix++) {
+ ln->_attrs[_inOrgX + ix].set(style_Input);
+ ln->_chars[_inOrgX + ix] = buf[ix];
+ }
+
+ _inCurs += initlen;
+ _inLen += initlen;
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+ }
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Cn");
+}
+
+void TextGridWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
+ warning("requestLineEventUni: window already has keyboard request");
+ return;
+ }
+
+ if ((int)maxlen > (_width - _curX))
+ maxlen = (_width - _curX);
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inLen = 0;
+ _inCurs = 0;
+ _inOrgX = _curX;
+ _inOrgY = _curY;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ if (initlen > maxlen)
+ initlen = maxlen;
+
+ if (initlen) {
+ TextGridRow *ln = &(_lines[_inOrgY]);
+
+ for (glui32 ix = 0; ix<initlen; ix++) {
+ ln->_attrs[_inOrgX + ix].set(style_Input);
+ ln->_chars[_inOrgX + ix] = buf[ix];
+ }
+
+ _inCurs += initlen;
+ _inLen += initlen;
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+ }
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Iu");
+}
+
+void TextGridWindow::cancelLineEvent(Event *ev) {
+ int ix;
+ void *inbuf;
+ int inmax;
+ int unicode = _lineRequestUni;
+ gidispatch_rock_t inarrayrock;
+ TextGridRow *ln = &_lines[_inOrgY];
+ Event dummyEv;
+
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+
+ if (!_lineRequest && !_lineRequestUni)
+ return;
+
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ if (!unicode) {
+ for (ix = 0; ix<_inLen; ix++)
+ {
+ glui32 ch = ln->_chars[_inOrgX + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ if (_echoStream)
+ _echoStream->echoLine((char *)_inBuf, _inLen);
+ } else {
+ for (ix = 0; ix<_inLen; ix++)
+ ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
+ }
+
+ _curY = _inOrgY + 1;
+ _curX = 0;
+ _attr = _origAttr;
+
+ ev->_type = evtype_LineInput;
+ ev->_window = this;
+ ev->_val1 = _inLen;
+ ev->_val2 = 0;
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+
+ if (_lineTerminators) {
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ }
+
+ _inBuf = nullptr;
+ _inMax = 0;
+ _inOrgX = 0;
+ _inOrgY = 0;
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextGridWindow::acceptReadChar(glui32 arg) {
+ glui32 key;
+
+ switch (arg)
+ {
+ case keycode_Erase:
+ key = keycode_Delete;
+ break;
+ case keycode_MouseWheelUp:
+ case keycode_MouseWheelDown:
+ return;
+ default:
+ key = arg;
+ }
+
+ if (key > 0xff && key < (0xffffffff - keycode_MAXVAL + 1))
+ {
+ if (!(_charRequestUni) || key > 0x10ffff)
+ key = keycode_Unknown;
+ }
+
+ _charRequest = false;
+ _charRequestUni = false;
+ g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
+}
+
+void TextGridWindow::acceptLine(glui32 keycode) {
+ int ix;
+ void *inbuf;
+ int inmax;
+ gidispatch_rock_t inarrayrock;
+ TextGridRow *ln = &(_lines[_inOrgY]);
+ int unicode = _lineRequestUni;
+
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ if (!unicode) {
+ for (ix = 0; ix<_inLen; ix++)
+ ((char *)inbuf)[ix] = (char)ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLine((char *)inbuf, _inLen);
+ } else {
+ for (ix = 0; ix<_inLen; ix++)
+ ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
+ }
+
+ _curY = _inOrgY + 1;
+ _curX = 0;
+ _attr = _origAttr;
+
+ if (_lineTerminators)
+ {
+ glui32 val2 = keycode;
+ if (val2 == keycode_Return)
+ val2 = 0;
+ g_vm->_events->eventStore(evtype_LineInput, this, _inLen, val2);
+ free(_lineTerminators);
+ _lineTerminators = NULL;
+ } else {
+ g_vm->_events->eventStore(evtype_LineInput, this, _inLen, 0);
+ }
+ _lineRequest = false;
+ _lineRequestUni = false;
+ _inBuf = NULL;
+ _inMax = 0;
+ _inOrgX = 0;
+ _inOrgY = 0;
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextGridWindow::acceptReadLine(glui32 arg) {
+ int ix;
+ TextGridRow *ln = &(_lines[_inOrgY]);
+
+ if (!_inBuf)
+ return;
+
+ if (_lineTerminators && checkTerminator(arg)) {
+ glui32 *cx;
+ for (cx = _lineTerminators; *cx; cx++) {
+ if (*cx == arg) {
+ acceptLine(arg);
+ return;
+ }
+ }
+ }
+
+ switch (arg) {
+
+ /* Delete keys, during line input. */
+
+ case keycode_Delete:
+ if (_inLen <= 0)
+ return;
+ if (_inCurs <= 0)
+ return;
+ for (ix = _inCurs; ix<_inLen; ix++)
+ ln->_chars[_inOrgX + ix - 1] = ln->_chars[_inOrgX + ix];
+ ln->_chars[_inOrgX + _inLen - 1] = ' ';
+ _inCurs--;
+ _inLen--;
+ break;
+
+ case keycode_Erase:
+ if (_inLen <= 0)
+ return;
+ if (_inCurs >= _inLen)
+ return;
+ for (ix = _inCurs; ix<_inLen - 1; ix++)
+ ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix + 1];
+ ln->_chars[_inOrgX + _inLen - 1] = ' ';
+ _inLen--;
+ break;
+
+ case keycode_Escape:
+ if (_inLen <= 0)
+ return;
+ for (ix = 0; ix<_inLen; ix++)
+ ln->_chars[_inOrgX + ix] = ' ';
+ _inLen = 0;
+ _inCurs = 0;
+ break;
+
+ /* Cursor movement keys, during line input. */
+
+ case keycode_Left:
+ if (_inCurs <= 0)
+ return;
+ _inCurs--;
+ break;
+
+ case keycode_Right:
+ if (_inCurs >= _inLen)
+ return;
+ _inCurs++;
+ break;
+
+ case keycode_Home:
+ if (_inCurs <= 0)
+ return;
+ _inCurs = 0;
+ break;
+
+ case keycode_End:
+ if (_inCurs >= _inLen)
+ return;
+ _inCurs = _inLen;
+ break;
+
+ case keycode_Return:
+ acceptLine(arg);
+ break;
+
+ default:
+ if (_inLen >= _inMax)
+ return;
+
+ if (arg < 32 || arg > 0xff)
+ return;
+
+ if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
+ arg -= 0x20;
+
+ for (ix = _inLen; ix>_inCurs; ix--)
+ ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix - 1];
+ ln->_attrs[_inOrgX + _inLen].set(style_Input);
+ ln->_chars[_inOrgX + _inCurs] = arg;
+
+ _inCurs++;
+ _inLen++;
+ }
+
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+}
+
+void TextGridWindow::redraw() {
+ TextGridRow *ln;
+ int x0, y0;
+ int x, y, w;
+ int i, a, b, k, o;
+ glui32 link;
+ int font;
+ byte *fgcolor, *bgcolor;
+
+ x0 = _bbox.left;
+ y0 = _bbox.top;
+
+ for (i = 0; i < _height; i++) {
+ ln = &_lines[i];
+ if (ln->dirty || Windows::_forceRedraw) {
+ ln->dirty = 0;
+
+ x = x0;
+ y = y0 + i * g_conf->_leading;
+
+ /* clear any stored hyperlink coordinates */
+ _windows->setHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
+
+ a = 0;
+ for (b = 0; b < _width; b++) {
+ if (ln->_attrs[a] == ln->_attrs[b]) {
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
+ bgcolor = ln->_attrs[a].attrBg(styles);
+ w = (b - a) * g_conf->_cellW;
+ _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+ o = x;
+
+ for (k = a; k < b; k++) {
+ drawStringUni(o * GLI_SUBPIX,
+ y + g_conf->_baseLine, font, fgcolor,
+ &ln->_chars[k], 1, -1);
+ o += g_conf->_cellW;
+ }
+ if (link) {
+ _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle, g_conf->_linkColor);
+ _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ }
+ x += w;
+ a = b;
+ }
+ }
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
+ bgcolor = ln->_attrs[a].attrBg(styles);
+ w = (b - a) * g_conf->_cellW;
+ w += _bbox.right - (x + w);
+ _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+
+ o = x;
+ for (k = a; k < b; k++) {
+ drawStringUni(o * GLI_SUBPIX,
+ y + g_conf->_baseLine, font, fgcolor,
+ &ln->_chars[k], 1, -1);
+ o += g_conf->_cellW;
+ }
+ if (link) {
+ _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle, g_conf->_linkColor);
+ _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void TextGridWindow::TextGridRow::resize(size_t newSize) {
+ _chars.clear();
+ _attrs.clear();
+ _chars.resize(newSize);
+ _attrs.resize(newSize);
+ Common::fill(&_chars[0], &_chars[0] + newSize, ' ');
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
new file mode 100644
index 0000000..2c72dde
--- /dev/null
+++ b/engines/gargoyle/window_text_grid.h
@@ -0,0 +1,180 @@
+/* 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 GARGOYLE_WINDOW_TEXT_GRID_H
+#define GARGOYLE_WINDOW_TEXT_GRID_H
+
+#include "gargoyle/windows.h"
+
+namespace Gargoyle {
+
+/**
+ * Text Grid window
+ */
+class TextGridWindow : public Window {
+ /**
+ * Structure for a row within the grid window
+ */
+ struct TextGridRow {
+ Common::Array<uint32> _chars;
+ Common::Array<Attributes> _attrs;
+ bool dirty;
+
+ /**
+ * Constructor
+ */
+ TextGridRow() : dirty(false) {}
+
+ /**
+ * Resize the row
+ */
+ void resize(size_t newSize);
+ };
+ typedef Common::Array<TextGridRow> TextGridRows;
+private:
+ /**
+ * Mark a given text row as modified
+ */
+ void touch(int line);
+
+ void acceptReadChar(glui32 arg);
+
+ /**
+ * Return or enter, during line input. Ends line input.
+ */
+ void acceptLine(glui32 keycode);
+
+ /**
+ * Any regular key, during line input.
+ */
+ void acceptReadLine(glui32 arg);
+public:
+ int _width, _height;
+ TextGridRows _lines;
+
+ int _curX, _curY; ///< the window cursor position
+
+ ///< for line input
+ void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
+ int _inOrgX, _inOrgY;
+ int _inMax;
+ int _inCurs, _inLen;
+ Attributes _origAttr;
+ gidispatch_rock_t _inArrayRock;
+ glui32 *_lineTerminators;
+
+ WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
+public:
+ /**
+ * Constructor
+ */
+ TextGridWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~TextGridWindow();
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override;
+
+ /**
+ * Write a character
+ */
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Unput a unicode character
+ */
+ virtual bool unputCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) override;
+
+ /**
+ * Clear the window
+ */
+ virtual void clear() override;
+
+ /**
+ * Click the window
+ */
+ virtual void click(const Common::Point &newPos) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Cancel an input line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() override { _mouseRequest = false; }
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index a625040..cf9b7de 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -21,6 +21,10 @@
*/
#include "gargoyle/windows.h"
+#include "gargoyle/window_graphics.h"
+#include "gargoyle/window_pair.h"
+#include "gargoyle/window_text_buffer.h"
+#include "gargoyle/window_text_grid.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/streams.h"
@@ -29,9 +33,6 @@
namespace Gargoyle {
-#define MAGIC_WINDOW_NUM (9876)
-#define GLI_SUBPIX 8
-
bool Windows::_overrideReverse;
bool Windows::_overrideFgSet;
bool Windows::_overrideBgSet;
@@ -47,41 +48,6 @@ byte Windows::_zcolor_Bright[3];
/*--------------------------------------------------------------------------*/
-Windows::iterator &Windows::iterator::operator++() {
- if (!_current)
- return *this;
-
- PairWindow *pairWin = dynamic_cast<PairWindow *>(_current);
-
- if (pairWin) {
- _current = !pairWin->_backward ? pairWin->_child1 : pairWin->_child2;
- } else {
- while (_current->_parent) {
- pairWin = dynamic_cast<PairWindow *>(_current->_parent);
-
- if (!pairWin->_backward) {
- if (_current == pairWin->_child1) {
- _current = pairWin->_child2;
- return *this;
- }
- } else {
- if (_current == pairWin->_child2) {
- _current = pairWin->_child1;
- return *this;
- }
- }
-
- _current = pairWin;
- }
-
- _current = nullptr;
- }
-
- return *this;
-}
-
-/*--------------------------------------------------------------------------*/
-
Windows::Windows(Graphics::Screen *screen) :
_screen(screen), _moreFocus(false), _windowList(nullptr),
_rootWin(nullptr), _focusWin(nullptr), _mask(nullptr), _claimSelect(0) {
@@ -286,9 +252,44 @@ byte *Windows::rgbShift(byte *rgb) {
/*--------------------------------------------------------------------------*/
-Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
- _windows(windows), _rock(rock), _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr),
- _yAdj(0), _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
+Windows::iterator &Windows::iterator::operator++() {
+ if (!_current)
+ return *this;
+
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(_current);
+
+ if (pairWin) {
+ _current = !pairWin->_backward ? pairWin->_child1 : pairWin->_child2;
+ } else {
+ while (_current->_parent) {
+ pairWin = dynamic_cast<PairWindow *>(_current->_parent);
+
+ if (!pairWin->_backward) {
+ if (_current == pairWin->_child1) {
+ _current = pairWin->_child2;
+ return *this;
+ }
+ } else {
+ if (_current == pairWin->_child2) {
+ _current = pairWin->_child1;
+ return *this;
+ }
+ }
+
+ _current = pairWin;
+ }
+
+ _current = nullptr;
+ }
+
+ return *this;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Window::Window(Windows *windows, glui32 rock) : _windows(windows), _rock(rock),
+ _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr), _yAdj(0),
+ _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
_mouseRequest(0), _hyperRequest(0), _moreRequest(0), _scrollRequest(0), _imageLoaded(0),
_echoLineInput(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
_attr.fgset = 0;
@@ -369,1382 +370,6 @@ BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock)
/*--------------------------------------------------------------------------*/
-TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
- _type = wintype_TextGrid;
- _width = _height = 0;
- _curX = _curY = 0;
- _inBuf = nullptr;
- _inOrgX = _inOrgY = 0;
- _inMax = 0;
- _inCurs = _inLen = 0;
- _inArrayRock.num = 0;
- _lineTerminators = nullptr;
-
- Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
-}
-
-TextGridWindow::~TextGridWindow() {
- if (_inBuf) {
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
- _inBuf = nullptr;
- }
-
- delete[] _lineTerminators;
-}
-
-void TextGridWindow::rearrange(const Common::Rect &box) {
- Window::rearrange(box);
- int newwid, newhgt;
-
- newwid = box.width() / g_conf->_cellW;
- newhgt = box.height() / g_conf->_cellH;
-
- if (newwid == _width && newhgt == _height)
- return;
-
- _lines.resize(newhgt);
- for (int y = 0; y < newhgt; ++y) {
- _lines[y].resize(newwid);
- touch(y);
- }
-
- _attr.clear();
- _width = newwid;
- _height = newhgt;
-}
-
-void TextGridWindow::touch(int line) {
- int y = _bbox.top + line * g_conf->_leading;
- _lines[line].dirty = true;
- _windows->repaint(Common::Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
-}
-
-glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
- return vertical ? size * g_conf->_cellW + g_conf->_tMarginX * 2 :
- size * g_conf->_cellH + g_conf->_tMarginY * 2;
-}
-
-void TextGridWindow::putChar(unsigned char ch) {
-
-}
-
-void TextGridWindow::putCharUni(uint32 ch) {
- TextGridRow *ln;
-
- // Canonicalize the cursor position. That is, the cursor may have been
- // left outside the window area; wrap it if necessary.
- if (_curX < 0) {
- _curX = 0;
- } else if (_curX >= _width) {
- _curX = 0;
- _curY++;
- }
- if (_curY < 0)
- _curY = 0;
- else if (_curY >= _height)
- return; /* outside the window */
-
- if (ch == '\n') {
- /* a newline just moves the cursor. */
- _curY++;
- _curX = 0;
- return;
- }
-
- touch(_curY);
-
- ln = &(_lines[_curY]);
- ln->_chars[_curX] = ch;
- ln->_attrs[_curX] = _attr;
-
- _curX++;
- // We can leave the cursor outside the window, since it will be
- // canonicalized next time a character is printed.
-}
-
-bool TextGridWindow::unputCharUni(uint32 ch) {
- TextGridRow *ln;
- int oldx = _curX, oldy = _curY;
-
- /* Move the cursor back. */
- if (_curX >= _width)
- _curX = _width - 1;
- else
- _curX--;
-
- /* Canonicalize the cursor position. That is, the cursor may have been
- left outside the window area; wrap it if necessary. */
- if (_curX < 0) {
- _curX = _width - 1;
- _curY--;
- }
- if (_curY < 0)
- _curY = 0;
- else if (_curY >= _height)
- return false; // outside the window
-
- if (ch == '\n') {
- // a newline just moves the cursor.
- if (_curX == _width - 1)
- return 1; // deleted a newline
- _curX = oldx;
- _curY = oldy;
- return 0; // it wasn't there */
- }
-
- ln = &(_lines[_curY]);
- if (ln->_chars[_curX] == ch) {
- ln->_chars[_curX] = ' ';
- ln->_attrs[_curX].clear();
- touch(_curY);
- return true; // deleted the char
- } else {
- _curX = oldx;
- _curY = oldy;
- return false; // it wasn't there
- }
-}
-
-void TextGridWindow::putBuffer(const unsigned char *buf, size_t len) {
- // TODO
-}
-
-void TextGridWindow::putBufferUni(const uint32 *buf, size_t len) {
- // TODO
-}
-
-void TextGridWindow::moveCursor(const Common::Point &pos) {
- // If the values are negative, they're really huge positive numbers --
- // remember that they were cast from glui32. So set them huge and
- // let canonicalization take its course.
- _curX = (pos.x < 0) ? 32767 : pos.x;
- _curY = (pos.y < 0) ? 32767 : pos.y;
-}
-
-void TextGridWindow::clear() {
- _attr.fgset = Windows::_overrideFgSet;
- _attr.bgset = Windows::_overrideBgSet;
- _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
- _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
- _attr.reverse = false;
-
- for (int k = 0; k < _height; k++) {
- TextGridRow &ln = _lines[k];
- touch(k);
- for (uint j = 0; j < ln._attrs.size(); ++j) {
- ln._chars[j] = ' ';
- ln._attrs[j].clear();
- }
- }
-
- _curX = 0;
- _curY = 0;
-}
-
-void TextGridWindow::click(const Common::Point &newPos) {
- int x = newPos.x - _bbox.left;
- int y = newPos.y - _bbox.top;
-
- if (_lineRequest || _charRequest || _lineRequestUni || _charRequestUni
- || _moreRequest || _scrollRequest)
- _windows->setFocus(this);
-
- if (_mouseRequest) {
- g_vm->_events->eventStore(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
- _mouseRequest = false;
- if (g_conf->_safeClicks)
- g_vm->_events->_forceClick = true;
- }
-
- if (_hyperRequest) {
- glui32 linkval = _windows->getHyperlink(newPos);
- if (linkval)
- {
- g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
- _hyperRequest = false;
- if (g_conf->_safeClicks)
- g_vm->_events->_forceClick = true;
- }
- }
-}
-
-void TextGridWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
- warning("request_line_event: window already has keyboard request");
- return;
- }
-
- if ((int)maxlen > (_width - _curX))
- maxlen = (_width - _curX);
-
- _inBuf = buf;
- _inMax = maxlen;
- _inLen = 0;
- _inCurs = 0;
- _inOrgX = _curX;
- _inOrgY = _curY;
- _origAttr = _attr;
- _attr.set(style_Input);
-
- if (initlen > maxlen)
- initlen = maxlen;
-
- if (initlen) {
- TextGridRow *ln = &_lines[_inOrgY];
-
- for (glui32 ix = 0; ix < initlen; ix++) {
- ln->_attrs[_inOrgX + ix].set(style_Input);
- ln->_chars[_inOrgX + ix] = buf[ix];
- }
-
- _inCurs += initlen;
- _inLen += initlen;
- _curX = _inOrgX + _inCurs;
- _curY = _inOrgY;
-
- touch(_inOrgY);
- }
-
- if (_lineTerminatorsBase && _termCt) {
- _lineTerminators = new glui32[_termCt + 1];
-
- if (_lineTerminators) {
- memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
- _lineTerminators[_termCt] = 0;
- }
- }
-
- if (g_vm->gli_register_arr)
- _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Cn");
-}
-
-void TextGridWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
- warning("requestLineEventUni: window already has keyboard request");
- return;
- }
-
- if ((int)maxlen > (_width - _curX))
- maxlen = (_width - _curX);
-
- _inBuf = buf;
- _inMax = maxlen;
- _inLen = 0;
- _inCurs = 0;
- _inOrgX = _curX;
- _inOrgY = _curY;
- _origAttr = _attr;
- _attr.set(style_Input);
-
- if (initlen > maxlen)
- initlen = maxlen;
-
- if (initlen) {
- TextGridRow *ln = &(_lines[_inOrgY]);
-
- for (glui32 ix = 0; ix<initlen; ix++) {
- ln->_attrs[_inOrgX + ix].set(style_Input);
- ln->_chars[_inOrgX + ix] = buf[ix];
- }
-
- _inCurs += initlen;
- _inLen += initlen;
- _curX = _inOrgX + _inCurs;
- _curY = _inOrgY;
-
- touch(_inOrgY);
- }
-
- if (_lineTerminatorsBase && _termCt) {
- _lineTerminators = new glui32[_termCt + 1];
-
- if (_lineTerminators) {
- memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
- _lineTerminators[_termCt] = 0;
- }
- }
-
- if (g_vm->gli_register_arr)
- _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Iu");
-}
-
-void TextGridWindow::cancelLineEvent(Event *ev) {
- int ix;
- void *inbuf;
- int inmax;
- int unicode = _lineRequestUni;
- gidispatch_rock_t inarrayrock;
- TextGridRow *ln = &_lines[_inOrgY];
- Event dummyEv;
-
- if (!ev)
- ev = &dummyEv;
-
- g_vm->_events->clearEvent(ev);
-
- if (!_lineRequest && !_lineRequestUni)
- return;
-
-
- inbuf = _inBuf;
- inmax = _inMax;
- inarrayrock = _inArrayRock;
-
- if (!unicode) {
- for (ix = 0; ix<_inLen; ix++)
- {
- glui32 ch = ln->_chars[_inOrgX + ix];
- if (ch > 0xff)
- ch = '?';
- ((char *)inbuf)[ix] = (char)ch;
- }
- if (_echoStream)
- _echoStream->echoLine((char *)_inBuf, _inLen);
- } else {
- for (ix = 0; ix<_inLen; ix++)
- ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
- if (_echoStream)
- _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
- }
-
- _curY = _inOrgY + 1;
- _curX = 0;
- _attr = _origAttr;
-
- ev->_type = evtype_LineInput;
- ev->_window = this;
- ev->_val1 = _inLen;
- ev->_val2 = 0;
-
- _lineRequest = false;
- _lineRequestUni = false;
-
- if (_lineTerminators) {
- free(_lineTerminators);
- _lineTerminators = nullptr;
- }
-
- _inBuf = nullptr;
- _inMax = 0;
- _inOrgX = 0;
- _inOrgY = 0;
-
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
-}
-
-void TextGridWindow::acceptReadChar(glui32 arg) {
- glui32 key;
-
- switch (arg)
- {
- case keycode_Erase:
- key = keycode_Delete;
- break;
- case keycode_MouseWheelUp:
- case keycode_MouseWheelDown:
- return;
- default:
- key = arg;
- }
-
- if (key > 0xff && key < (0xffffffff - keycode_MAXVAL + 1))
- {
- if (!(_charRequestUni) || key > 0x10ffff)
- key = keycode_Unknown;
- }
-
- _charRequest = false;
- _charRequestUni = false;
- g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
-}
-
-void TextGridWindow::acceptLine(glui32 keycode) {
- int ix;
- void *inbuf;
- int inmax;
- gidispatch_rock_t inarrayrock;
- TextGridRow *ln = &(_lines[_inOrgY]);
- int unicode = _lineRequestUni;
-
- if (!_inBuf)
- return;
-
- inbuf = _inBuf;
- inmax = _inMax;
- inarrayrock = _inArrayRock;
-
- if (!unicode) {
- for (ix = 0; ix<_inLen; ix++)
- ((char *)inbuf)[ix] = (char)ln->_chars[_inOrgX + ix];
- if (_echoStream)
- _echoStream->echoLine((char *)inbuf, _inLen);
- } else {
- for (ix = 0; ix<_inLen; ix++)
- ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
- if (_echoStream)
- _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
- }
-
- _curY = _inOrgY + 1;
- _curX = 0;
- _attr = _origAttr;
-
- if (_lineTerminators)
- {
- glui32 val2 = keycode;
- if (val2 == keycode_Return)
- val2 = 0;
- g_vm->_events->eventStore(evtype_LineInput, this, _inLen, val2);
- free(_lineTerminators);
- _lineTerminators = NULL;
- } else {
- g_vm->_events->eventStore(evtype_LineInput, this, _inLen, 0);
- }
- _lineRequest = false;
- _lineRequestUni = false;
- _inBuf = NULL;
- _inMax = 0;
- _inOrgX = 0;
- _inOrgY = 0;
-
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
-}
-
-void TextGridWindow::acceptReadLine(glui32 arg) {
- int ix;
- TextGridRow *ln = &(_lines[_inOrgY]);
-
- if (!_inBuf)
- return;
-
- if (_lineTerminators && checkTerminator(arg)) {
- glui32 *cx;
- for (cx = _lineTerminators; *cx; cx++) {
- if (*cx == arg) {
- acceptLine(arg);
- return;
- }
- }
- }
-
- switch (arg) {
-
- /* Delete keys, during line input. */
-
- case keycode_Delete:
- if (_inLen <= 0)
- return;
- if (_inCurs <= 0)
- return;
- for (ix = _inCurs; ix<_inLen; ix++)
- ln->_chars[_inOrgX + ix - 1] = ln->_chars[_inOrgX + ix];
- ln->_chars[_inOrgX + _inLen - 1] = ' ';
- _inCurs--;
- _inLen--;
- break;
-
- case keycode_Erase:
- if (_inLen <= 0)
- return;
- if (_inCurs >= _inLen)
- return;
- for (ix = _inCurs; ix<_inLen - 1; ix++)
- ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix + 1];
- ln->_chars[_inOrgX + _inLen - 1] = ' ';
- _inLen--;
- break;
-
- case keycode_Escape:
- if (_inLen <= 0)
- return;
- for (ix = 0; ix<_inLen; ix++)
- ln->_chars[_inOrgX + ix] = ' ';
- _inLen = 0;
- _inCurs = 0;
- break;
-
- /* Cursor movement keys, during line input. */
-
- case keycode_Left:
- if (_inCurs <= 0)
- return;
- _inCurs--;
- break;
-
- case keycode_Right:
- if (_inCurs >= _inLen)
- return;
- _inCurs++;
- break;
-
- case keycode_Home:
- if (_inCurs <= 0)
- return;
- _inCurs = 0;
- break;
-
- case keycode_End:
- if (_inCurs >= _inLen)
- return;
- _inCurs = _inLen;
- break;
-
- case keycode_Return:
- acceptLine(arg);
- break;
-
- default:
- if (_inLen >= _inMax)
- return;
-
- if (arg < 32 || arg > 0xff)
- return;
-
- if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
- arg -= 0x20;
-
- for (ix = _inLen; ix>_inCurs; ix--)
- ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix - 1];
- ln->_attrs[_inOrgX + _inLen].set(style_Input);
- ln->_chars[_inOrgX + _inCurs] = arg;
-
- _inCurs++;
- _inLen++;
- }
-
- _curX = _inOrgX + _inCurs;
- _curY = _inOrgY;
-
- touch(_inOrgY);
-}
-
-void TextGridWindow::redraw() {
- TextGridRow *ln;
- int x0, y0;
- int x, y, w;
- int i, a, b, k, o;
- glui32 link;
- int font;
- byte *fgcolor, *bgcolor;
-
- x0 = _bbox.left;
- y0 = _bbox.top;
-
- for (i = 0; i < _height; i++) {
- ln = &_lines[i];
- if (ln->dirty || Windows::_forceRedraw) {
- ln->dirty = 0;
-
- x = x0;
- y = y0 + i * g_conf->_leading;
-
- /* clear any stored hyperlink coordinates */
- _windows->setHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
-
- a = 0;
- for (b = 0; b < _width; b++) {
- if (ln->_attrs[a] == ln->_attrs[b]) {
- link = ln->_attrs[a].hyper;
- font = ln->_attrs[a].attrFont(styles);
- fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
- bgcolor = ln->_attrs[a].attrBg(styles);
- w = (b - a) * g_conf->_cellW;
- _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
- o = x;
-
- for (k = a; k < b; k++) {
- drawStringUni(o * GLI_SUBPIX,
- y + g_conf->_baseLine, font, fgcolor,
- &ln->_chars[k], 1, -1);
- o += g_conf->_cellW;
- }
- if (link) {
- _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
- g_conf->_linkStyle, g_conf->_linkColor);
- _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
- }
- x += w;
- a = b;
- }
- }
- link = ln->_attrs[a].hyper;
- font = ln->_attrs[a].attrFont(styles);
- fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
- bgcolor = ln->_attrs[a].attrBg(styles);
- w = (b - a) * g_conf->_cellW;
- w += _bbox.right - (x + w);
- _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
-
- o = x;
- for (k = a; k < b; k++) {
- drawStringUni(o * GLI_SUBPIX,
- y + g_conf->_baseLine, font, fgcolor,
- &ln->_chars[k], 1, -1);
- o += g_conf->_cellW;
- }
- if (link) {
- _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
- g_conf->_linkStyle, g_conf->_linkColor);
- _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
- }
- }
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-void TextGridWindow::TextGridRow::resize(size_t newSize) {
- _chars.clear();
- _attrs.clear();
- _chars.resize(newSize);
- _attrs.resize(newSize);
- Common::fill(&_chars[0], &_chars[0] + newSize, ' ');
-}
-
-/*--------------------------------------------------------------------------*/
-
-TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
- _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
- _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
- _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
- _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
- _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
- _type = wintype_TextBuffer;
- Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
-
- Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
-}
-
-TextBufferWindow::~TextBufferWindow() {
- if (_inBuf) {
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
- _inBuf = nullptr;
- }
-
- delete[] _copyBuf;
- delete[] _lineTerminators;
-
- for (int i = 0; i < _scrollBack; i++) {
- if (_lines[i].lpic)
- _lines[i].lpic->decrement();
- if (_lines[i].rpic)
- _lines[i].rpic->decrement();
- }
-}
-
-void TextBufferWindow::rearrange(const Common::Rect &box) {
- Window::rearrange(box);
- int newwid, newhgt;
- int rnd;
-
- newwid = (box.width() - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) / g_conf->_cellW;
- newhgt = (box.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
-
- /* align text with bottom */
- rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
- _yAdj = (box.height() - rnd);
- _bbox.top += (box.height() - rnd);
-
- if (newwid != _width) {
- _width = newwid;
- reflow();
- }
-
- if (newhgt != _height) {
- /* scroll up if we obscure new lines */
- if (_lastSeen >= newhgt - 1)
- _scrollPos += (_height - newhgt);
-
- _height = newhgt;
-
- /* keep window within 'valid' lines */
- if (_scrollPos > _scrollMax - _height + 1)
- _scrollPos = _scrollMax - _height + 1;
- if (_scrollPos < 0)
- _scrollPos = 0;
- touchScroll();
-
- /* allocate copy buffer */
- if (_copyBuf)
- delete[] _copyBuf;
- _copyBuf = new glui32[_height * TBLINELEN];
-
- for (int i = 0; i < (_height * TBLINELEN); i++)
- _copyBuf[i] = 0;
-
- _copyPos = 0;
- }
-}
-
-void TextBufferWindow::reflow() {
- int inputbyte = -1;
- Attributes curattr, oldattr;
- int i, k, p, s;
- int x;
-
- if (_height < 4 || _width < 20)
- return;
-
- _lines[0].len = _numChars;
-
- /* allocate temp buffers */
- Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
- glui32 *charbuf = new glui32[SCROLLBACK * TBLINELEN];
- int *alignbuf = new int[SCROLLBACK];
- Picture **pictbuf = new Picture *[SCROLLBACK];
- glui32 *hyperbuf = new glui32[SCROLLBACK];
- int *offsetbuf = new int[SCROLLBACK];
-
- if (!attrbuf || !charbuf || !alignbuf || !pictbuf || !hyperbuf || !offsetbuf) {
- delete[] attrbuf;
- delete[] charbuf;
- delete[] alignbuf;
- delete[] pictbuf;
- delete[] hyperbuf;
- delete[] offsetbuf;
- return;
- }
-
- /* copy text to temp buffers */
-
- oldattr = _attr;
- curattr.clear();
-
- x = 0;
- p = 0;
- s = _scrollMax < SCROLLBACK ? _scrollMax : SCROLLBACK - 1;
-
- for (k = s; k >= 0; k--) {
- if (k == 0 && _lineRequest)
- inputbyte = p + _inFence;
-
- if (_lines[k].lpic) {
- offsetbuf[x] = p;
- alignbuf[x] = imagealign_MarginLeft;
- pictbuf[x] = _lines[k].lpic;
-
- if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = _lines[k].lhyper;
- x++;
- }
-
- if (_lines[k].rpic) {
- offsetbuf[x] = p;
- alignbuf[x] = imagealign_MarginRight;
- pictbuf[x] = _lines[k].rpic;
- if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = _lines[k].rhyper;
- x++;
- }
-
- for (i = 0; i < _lines[k].len; i++) {
- attrbuf[p] = curattr = _lines[k].attr[i];
- charbuf[p] = _lines[k].chars[i];
- p++;
- }
-
- if (_lines[k].newline) {
- attrbuf[p] = curattr;
- charbuf[p] = '\n';
- p++;
- }
- }
-
- offsetbuf[x] = -1;
-
- /* clear window */
-
- clear();
-
- /* and dump text back */
-
- x = 0;
- for (i = 0; i < p; i++) {
- if (i == inputbyte)
- break;
- _attr = attrbuf[i];
-
- if (offsetbuf[x] == i) {
- putPicture(pictbuf[x], alignbuf[x], hyperbuf[x]);
- x++;
- }
-
- putCharUni(charbuf[i]);
- }
-
- /* terribly sorry about this... */
- _lastSeen = 0;
- _scrollPos = 0;
-
- if (inputbyte != -1) {
- _inFence = _numChars;
- putTextUni(charbuf + inputbyte, p - inputbyte, _numChars, 0);
- _inCurs = _numChars;
- }
-
- // free temp buffers
- delete[] attrbuf;
- delete[] charbuf;
- delete[] alignbuf;
- delete[] pictbuf;
- delete[] hyperbuf;
- delete[] offsetbuf;
-
- _attr = oldattr;
-
- touchScroll();
-}
-
-void TextBufferWindow::touchScroll() {
- _windows->clearSelection();
- _windows->repaint(_bbox);
-
- for (int i = 0; i < _scrollMax; i++)
- _lines[i].dirty = true;
-}
-
-bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
- if (align == imagealign_MarginRight)
- {
- if (_lines[0].rpic || _numChars)
- return false;
-
- _radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
- _radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- _lines[0].rpic = pic;
- _lines[0].rm = _radjw;
- _lines[0].rhyper = linkval;
- } else {
- if (align != imagealign_MarginLeft && _numChars)
- putCharUni('\n');
-
- if (_lines[0].lpic || _numChars)
- return false;
-
- _ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
- _ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- _lines[0].lpic = pic;
- _lines[0].lm = _ladjw;
- _lines[0].lhyper = linkval;
-
- if (align != imagealign_MarginLeft)
- flowBreak();
- }
-
- return true;
-}
-
-void TextBufferWindow::flowBreak() {
- // TODO
-}
-
-void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldlen) {
- // TODO
-}
-
-void TextBufferWindow::touch(int line) {
- int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
- _lines[line].dirty = 1;
- _windows->clearSelection();
- _windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
-}
-
-glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
- return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
-}
-
-void TextBufferWindow::putChar(unsigned char ch) {
-}
-
-void TextBufferWindow::putCharUni(glui32 ch) {
- /*
- glui32 bchars[TBLINELEN];
- Attributes battrs[TBLINELEN];
- int pw;
- int bpoint;
- int saved;
- int i;
- int linelen;
- unsigned char *color;
-
- gli_tts_speak(&ch, 1);
-
- pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
- pw = pw - 2 * SLOP - radjw - ladjw;
-
- color = Windows::_overrideBgSet ? gli_window_color : bgcolor;
-
- // oops ... overflow
- if (numchars + 1 >= TBLINELEN)
- scrolloneline(dwin, 0);
-
- if (ch == '\n') {
- scrolloneline(dwin, 1);
- return;
- }
-
- if (gli_conf_quotes) {
- // fails for 'tis a wonderful day in the '80s
- if (gli_conf_quotes > 1 && ch == '\'')
- {
- if (numchars == 0 || leftquote(_chars[numchars - 1]))
- ch = UNI_LSQUO;
- }
-
- if (ch == '`')
- ch = UNI_LSQUO;
-
- if (ch == '\'')
- ch = UNI_RSQUO;
-
- if (ch == '"')
- {
- if (numchars == 0 || leftquote(_chars[numchars - 1]))
- ch = UNI_LDQUO;
- else
- ch = UNI_RDQUO;
- }
- }
-
- if (gli_conf_dashes && attr.style != style_Preformatted)
- {
- if (ch == '-')
- {
- dashed++;
- if (dashed == 2)
- {
- numchars--;
- if (gli_conf_dashes == 2)
- ch = UNI_NDASH;
- else
- ch = UNI_MDASH;
- }
- if (dashed == 3)
- {
- numchars--;
- ch = UNI_MDASH;
- dashed = 0;
- }
- }
- else
- dashed = 0;
- }
-
- if (gli_conf_spaces && attr.style != style_Preformatted
- && styles[attr.style].bg == color
- && !styles[attr.style].reverse)
- {
- // turn (period space space) into (period space)
- if (gli_conf_spaces == 1)
- {
- if (ch == '.')
- spaced = 1;
- else if (ch == ' ' && spaced == 1)
- spaced = 2;
- else if (ch == ' ' && spaced == 2)
- {
- spaced = 0;
- return;
- }
- else
- spaced = 0;
- }
-
- // Turn (per sp x) into (per sp sp x)
- if (gli_conf_spaces == 2)
- {
- if (ch == '.')
- spaced = 1;
- else if (ch == ' ' && spaced == 1)
- spaced = 2;
- else if (ch != ' ' && spaced == 2)
- {
- spaced = 0;
- win_textbuffer_putchar_uni(win, ' ');
- }
- else
- spaced = 0;
- }
- }
-
- _chars[numchars] = ch;
- attrs[numchars] = attr;
- numchars++;
-
- // kill spaces at the end for line width calculation
- linelen = numchars;
- while (linelen > 1 && _chars[linelen - 1] == ' '
- && styles[attrs[linelen - 1].style].bg == color
- && !styles[attrs[linelen - 1].style].reverse)
- linelen--;
-
- if (calcwidth(dwin, _chars, attrs, 0, linelen, -1) >= pw)
- {
- bpoint = numchars;
-
- for (i = numchars - 1; i > 0; i--)
- if (_chars[i] == ' ')
- {
- bpoint = i + 1; // skip space
- break;
- }
-
- saved = numchars - bpoint;
-
- memcpy(bchars, _chars + bpoint, saved * 4);
- memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
- numchars = bpoint;
-
- scrolloneline(dwin, 0);
-
- memcpy(_chars, bchars, saved * 4);
- memcpy(attrs, battrs, saved * sizeof(attr_t));
- numchars = saved;
- }
-
- touch(0);
- */
-}
-
-bool TextBufferWindow::unputCharUni(uint32 ch) {
- // TODO
- return false;
-}
-
-void TextBufferWindow::putBuffer(const unsigned char *buf, size_t len) {
- // TODO
-}
-
-void TextBufferWindow::putBufferUni(const uint32 *buf, size_t len) {
- // TODO
-}
-
-void TextBufferWindow::moveCursor(const Common::Point &newPos) {
- // TODO
-}
-
-void TextBufferWindow::clear() {
- int i;
-
- _attr.fgset = Windows::_overrideFgSet;
- _attr.bgset = Windows::_overrideBgSet;
- _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
- _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
- _attr.reverse = false;
-
- _ladjw = _radjw = 0;
- _ladjn = _radjn = 0;
-
- _spaced = 0;
- _dashed = 0;
-
- _numChars = 0;
-
- for (i = 0; i < _scrollBack; i++) {
- _lines[i].len = 0;
-
- if (_lines[i].lpic) _lines[i].lpic->decrement();
- _lines[i].lpic = nullptr;
- if (_lines[i].rpic) _lines[i].rpic->decrement();
- _lines[i].rpic = nullptr;
-
- _lines[i].lhyper = 0;
- _lines[i].rhyper = 0;
- _lines[i].lm = 0;
- _lines[i].rm = 0;
- _lines[i].newline = 0;
- _lines[i].dirty = true;
- _lines[i].repaint = false;
- }
-
- _lastSeen = 0;
- _scrollPos = 0;
- _scrollMax = 0;
-
- for (i = 0; i < _height; i++)
- touch(i);
-}
-
-void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
- warning("request_line_event: window already has keyboard request");
- return;
- }
-
- // TODO
-}
-
-void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
- warning("request_line_event_uni: window already has keyboard request");
- return;
- }
-
- // TODO
-}
-
-void TextBufferWindow::cancelLineEvent(Event *ev) {
- gidispatch_rock_t inarrayrock;
- int ix;
- int len;
- void *inbuf;
- int inmax;
- int unicode = _lineRequestUni;
- Event dummyEv;
-
- if (!ev)
- ev = &dummyEv;
-
- g_vm->_events->clearEvent(ev);
-
- if (!_lineRequest && !_lineRequestUni)
- return;
-
- if (!_inBuf)
- return;
-
- inbuf = _inBuf;
- inmax = _inMax;
- inarrayrock = _inArrayRock;
-
- len = _numChars - _inFence;
- if (_echoStream)
- _echoStream->echoLineUni(_chars + _inFence, len);
-
- if (len > inmax)
- len = inmax;
-
- if (!unicode) {
- for (ix = 0; ix<len; ix++) {
- glui32 ch = _chars[_inFence + ix];
- if (ch > 0xff)
- ch = '?';
- ((char *)inbuf)[ix] = (char)ch;
- }
- }
- else {
- for (ix = 0; ix<len; ix++)
- ((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
- }
-
- _attr = _origAttr;
-
- ev->_type = evtype_LineInput;
- ev->_window = this;
- ev->_val1 = len;
- ev->_val2 = 0;
-
- _lineRequest = false;
- _lineRequestUni = false;
- if (_lineTerminators) {
- free(_lineTerminators);
- _lineTerminators = nullptr;
- }
- _inBuf = nullptr;
- _inMax = 0;
-
- if (_echoLineInput) {
- putCharUni('\n');
- }
- else {
- _numChars = _inFence;
- touch(0);
- }
-
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
-}
-
-void TextBufferWindow::redraw() {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
-TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
- lpic(nullptr), rpic(nullptr), lhyper(0), rhyper(0), lm(0), rm(0) {
-}
-
-void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
- chars.clear();
- attr.clear();
- chars.resize(newSize);
- attr.resize(newSize);
- Common::fill(&chars[0], &chars[0] + newSize, ' ');
-}
-
-/*--------------------------------------------------------------------------*/
-
-GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
-_w(0), _h(0), _dirty(false), _surface(nullptr) {
- _type = wintype_Graphics;
- Common::copy(&_bgColor[0], &_bgColor[3], _bgnd);
-}
-
-GraphicsWindow::~GraphicsWindow() {
- delete _surface;
-}
-
-void GraphicsWindow::rearrange(const Common::Rect &box) {
- int newwid, newhgt;
- int bothwid, bothhgt;
- int oldw, oldh;
- Graphics::ManagedSurface *newSurface;
-
- _bbox = box;
-
- newwid = box.width();
- newhgt = box.height();
- oldw = _w;
- oldh = _h;
-
- if (newwid <= 0 || newhgt <= 0) {
- _w = 0;
- _h = 0;
- delete _surface;
- _surface = NULL;
- return;
- }
-
- bothwid = _w;
- if (newwid < bothwid)
- bothwid = newwid;
- bothhgt = _h;
- if (newhgt < bothhgt)
- bothhgt = newhgt;
-
- newSurface = new Graphics::ManagedSurface(newwid, newhgt,
- Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
-
- // If the new surface is equal or bigger than the old one, copy it over
- if (_surface && bothwid && bothhgt)
- newSurface->blitFrom(*_surface);
-
- delete _surface;
- _surface = newSurface;
- _w = newwid;
- _h = newhgt;
-
- touch();
-}
-
-void GraphicsWindow::touch() {
- _dirty = true;
- _windows->repaint(_bbox);
-}
-
-void GraphicsWindow::redraw() {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
-PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size) :
- Window(windows, 0),
- _dir(method & winmethod_DirMask),
- _division(method & winmethod_DivisionMask),
- _wBorder((method & winmethod_BorderMask) == winmethod_Border),
- _vertical(_dir == winmethod_Left || _dir == winmethod_Right),
- _backward(_dir == winmethod_Left || _dir == winmethod_Above),
- _key(key), _size(size), _keyDamage(0), _child1(nullptr), _child2(nullptr) {
- _type = wintype_Pair;
-}
-
-void PairWindow::rearrange(const Common::Rect &box) {
- Common::Rect box1, box2;
- int min, diff, split, splitwid, max;
- Window *ch1, *ch2;
-
- _bbox = box;
-
- if (_vertical) {
- min = _bbox.left;
- max = _bbox.right;
- } else {
- min = _bbox.top;
- max = _bbox.bottom;
- }
- diff = max - min;
-
- // We now figure split.
- if (_vertical)
- splitwid = g_conf->_wPaddingX; // want border?
- else
- splitwid = g_conf->_wPaddingY; // want border?
-
- switch (_division) {
- case winmethod_Proportional:
- split = (diff * _size) / 100;
- break;
-
- case winmethod_Fixed:
- split = !_key ? 0 : _key->getSplit(_size, _vertical);
- break;
-
- default:
- split = diff / 2;
- break;
- }
-
- if (!_backward)
- split = max - split - splitwid;
- else
- split = min + split;
-
- if (min >= max) {
- split = min;
- } else {
- if (split < min)
- split = min;
- else if (split > max - splitwid)
- split = max - splitwid;
- }
-
- if (_vertical) {
- box1.left = _bbox.left;
- box1.right = split;
- box2.left = split + splitwid;
- box2.right = _bbox.right;
- box1.top = _bbox.top;
- box1.bottom = _bbox.bottom;
- box2.top = _bbox.top;
- box2.bottom = _bbox.bottom;
- } else {
- box1.top = _bbox.top;
- box1.bottom = split;
- box2.top = split + splitwid;
- box2.bottom = _bbox.bottom;
- box1.left = _bbox.left;
- box1.right = _bbox.right;
- box2.left = _bbox.left;
- box2.right = _bbox.right;
- }
-
- if (!_backward) {
- ch1 = _child1;
- ch2 = _child2;
- } else {
- ch1 = _child2;
- ch2 = _child1;
- }
-
- ch1->rearrange(box1);
- ch2->rearrange(box2);
-}
-
-void PairWindow::redraw() {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
void Attributes::clear() {
fgset = 0;
bgset = 0;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 9a09641..a5bc2f4 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -31,7 +31,6 @@
#include "gargoyle/events.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
-#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
#include "gargoyle/window_mask.h"
@@ -43,6 +42,8 @@ class PairWindow;
#define HISTORYLEN 100
#define SCROLLBACK 512
#define TBLINELEN 300
+#define GLI_SUBPIX 8
+
/**
* Main windows manager
@@ -256,7 +257,6 @@ struct Attributes {
class Window : public Draw {
public:
Windows *_windows;
- glui32 _magicnum;
glui32 _rock;
glui32 _type;
@@ -393,409 +393,6 @@ public:
BlankWindow(Windows *windows, uint32 rock);
};
-/**
- * Text Grid window
- */
-class TextGridWindow : public Window {
- /**
- * Structure for a row within the grid window
- */
- struct TextGridRow {
- Common::Array<uint32> _chars;
- Common::Array<Attributes> _attrs;
- bool dirty;
-
- /**
- * Constructor
- */
- TextGridRow() : dirty(false) {}
-
- /**
- * Resize the row
- */
- void resize(size_t newSize);
- };
- typedef Common::Array<TextGridRow> TextGridRows;
-private:
- /**
- * Mark a given text row as modified
- */
- void touch(int line);
-
- void acceptReadChar(glui32 arg);
-
- /**
- * Return or enter, during line input. Ends line input.
- */
- void acceptLine(glui32 keycode);
-
- /**
- * Any regular key, during line input.
- */
- void acceptReadLine(glui32 arg);
-public:
- int _width, _height;
- TextGridRows _lines;
-
- int _curX, _curY; ///< the window cursor position
-
- ///< for line input
- void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
- int _inOrgX, _inOrgY;
- int _inMax;
- int _inCurs, _inLen;
- Attributes _origAttr;
- gidispatch_rock_t _inArrayRock;
- glui32 *_lineTerminators;
-
- WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
-public:
- /**
- * Constructor
- */
- TextGridWindow(Windows *windows, uint32 rock);
-
- /**
- * Destructor
- */
- virtual ~TextGridWindow();
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Get window split size within parent pair window
- */
- virtual glui32 getSplit(glui32 size, bool vertical) const override;
-
- /**
- * Write a character
- */
- virtual void putChar(unsigned char ch) override;
-
- /**
- * Write a unicode character
- */
- virtual void putCharUni(uint32 ch) override;
-
- /**
- * Unput a unicode character
- */
- virtual bool unputCharUni(uint32 ch) override;
-
- /**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) override;
-
- /**
- * Move the cursor
- */
- virtual void moveCursor(const Common::Point &newPos) override;
-
- /**
- * Clear the window
- */
- virtual void clear() override;
-
- /**
- * Click the window
- */
- virtual void click(const Common::Point &newPos) override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Cancel an input line event
- */
- virtual void cancelLineEvent(Event *ev) override;
-
- /**
- * Cancel a mouse event
- */
- virtual void cancelMouseEvent() override { _mouseRequest = false; }
-
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-};
-
-/**
- * Text Buffer window
- */
-class TextBufferWindow : public Window {
- /**
- * Structure for a row within the window
- */
- struct TextBufferRow {
- Common::Array<uint32> chars;
- Common::Array<Attributes> attr;
- int len, newline;
- bool dirty, repaint;
- Picture *lpic, *rpic;
- glui32 lhyper, rhyper;
- int lm, rm;
-
- /**
- * Constructor
- */
- TextBufferRow();
-
- /**
- * Resize the row
- */
- void resize(size_t newSize);
- };
- typedef Common::Array<TextBufferRow> TextBufferRows;
-private:
- void reflow();
- void touchScroll();
- bool putPicture(Picture *pic, glui32 align, glui32 linkval);
- void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
- void flowBreak();
-
- /**
- * Mark a given text row as modified
- */
- void touch(int line);
-public:
- int _width, _height;
- int _spaced;
- int _dashed;
-
- TextBufferRows _lines;
- int _scrollBack;
-
- int _numChars; ///< number of chars in last line: lines[0]
- glui32 *_chars; ///< alias to lines[0].chars
- Attributes *_attrs; ///< alias to lines[0].attrs
-
- ///< adjust margins temporarily for images
- int _ladjw;
- int _ladjn;
- int _radjw;
- int _radjn;
-
- /* Command history. */
- glui32 *_history[HISTORYLEN];
- int _historyPos;
- int _historyFirst, _historyPresent;
-
- /* for paging */
- int _lastSeen;
- int _scrollPos;
- int _scrollMax;
-
- /* for line input */
- void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
- int _inMax;
- long _inFence;
- long _inCurs;
- Attributes _origAttr;
- gidispatch_rock_t _inArrayRock;
-
- glui32 _echoLineInput;
- glui32 *_lineTerminators;
-
- /* style hints and settings */
- WindowStyle styles[style_NUMSTYLES];
-
- /* for copy selection */
- glui32 *_copyBuf;
- int _copyPos;
-public:
- /**
- * Constructor
- */
- TextBufferWindow(Windows *windows, uint32 rock);
-
- /**
- * Destructor
- */
- virtual ~TextBufferWindow();
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Get window split size within parent pair window
- */
- virtual glui32 getSplit(glui32 size, bool vertical) const override;
-
- /**
- * Write a character
- */
- virtual void putChar(unsigned char ch) override;
-
- /**
- * Write a unicode character
- */
- virtual void putCharUni(uint32 ch) override;
-
- /**
- * Unput a unicode character
- */
- virtual bool unputCharUni(uint32 ch) override;
-
- /**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) override;
-
- /**
- * Move the cursor
- */
- virtual void moveCursor(const Common::Point &newPos) override;
-
- /**
- * Clear the window
- */
- virtual void clear() override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Cancel an input line event
- */
- virtual void cancelLineEvent(Event *ev) override;
-
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-};
-
-/**
- * Graphics window
- */
-class GraphicsWindow : public Window {
-private:
- void touch();
-public:
- unsigned char _bgnd[3];
- bool _dirty;
- glui32 _w, _h;
- Graphics::ManagedSurface *_surface;
-public:
- /**
- * Constructor
- */
- GraphicsWindow(Windows *windows, uint32 rock);
-
- /**
- * Destructor
- */
- virtual ~GraphicsWindow();
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Get window split size within parent pair window
- */
- virtual glui32 getSplit(glui32 size, bool vertical) const override {
- return size;
- }
-
- /**
- * Cancel a mouse event
- */
- virtual void cancelMouseEvent() override { _mouseRequest = false; }
-
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-
- /**
- * Get the window dimensions
- */
- void getSize(glui32 *w, glui32 *h) {
- *w = _w;
- *h = _h;
- }
-};
-
-/**
- * Pair window
- */
-class PairWindow : public Window {
-public:
- Window *_child1, *_child2;
-
- /* split info... */
- glui32 _dir; ///< winmethod_Left, Right, Above, or Below
- bool _vertical, _backward; ///< flags
- glui32 _division; ///< winmethod_Fixed or winmethod_Proportional
- Window *_key; ///< NULL or a leaf-descendant (not a Pair)
- int _keyDamage; ///< used as scratch space in window closing
- glui32 _size; ///< size value
- glui32 _wBorder; ///< winMethod_Border, NoBorder
-public:
- /**
- * Constructor
- */
- PairWindow(Windows *windows, glui32 method, Window *key, glui32 size);
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-};
-
} // End of namespace Gargoyle
#endif
Commit: ede0323c08fc7d5853736d42c7f5910c18ff1fd1
https://github.com/scummvm/scummvm/commit/ede0323c08fc7d5853736d42c7f5910c18ff1fd1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Windows don't have a non-unicode putChar method
Changed paths:
engines/gargoyle/streams.cpp
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 7dec179..7499991 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -79,7 +79,7 @@ void WindowStream::putChar(unsigned char ch) {
}
}
- _window->putChar(ch);
+ _window->putCharUni(ch);
if (_window->_echoStream)
_window->_echoStream->putChar(ch);
}
@@ -118,7 +118,7 @@ void WindowStream::putBuffer(const char *buf, size_t len) {
}
for (size_t lx = 0; lx < len; lx++, buf++)
- _window->putChar(*buf);
+ _window->putCharUni(*buf);
if (_window->_echoStream)
_window->_echoStream->putBuffer(buf, len);
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 1e85a24..9b1268e 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -277,9 +277,6 @@ glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
}
-void TextBufferWindow::putChar(unsigned char ch) {
-}
-
void TextBufferWindow::putCharUni(glui32 ch) {
/*
glui32 bchars[TBLINELEN];
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index f7427d7..0e6ee2c 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -133,11 +133,6 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const override;
/**
- * Write a character
- */
- virtual void putChar(unsigned char ch) override;
-
- /**
* Write a unicode character
*/
virtual void putCharUni(uint32 ch) override;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 41444ed..92bdcf5 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -82,10 +82,6 @@ glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
size * g_conf->_cellH + g_conf->_tMarginY * 2;
}
-void TextGridWindow::putChar(unsigned char ch) {
-
-}
-
void TextGridWindow::putCharUni(uint32 ch) {
TextGridRow *ln;
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 2c72dde..8ebaf82 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -105,11 +105,6 @@ public:
virtual glui32 getSplit(glui32 size, bool vertical) const override;
/**
- * Write a character
- */
- virtual void putChar(unsigned char ch) override;
-
- /**
* Write a unicode character
*/
virtual void putCharUni(uint32 ch) override;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index a5bc2f4..60f6bb4 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -313,11 +313,6 @@ public:
/**
* Write a character
*/
- virtual void putChar(unsigned char ch) {}
-
- /**
- * Write a unicode character
- */
virtual void putCharUni(uint32 ch) {}
/**
Commit: cb2b7d439fb9cb89f2758d103ba2ea710e4f0a72
https://github.com/scummvm/scummvm/commit/cb2b7d439fb9cb89f2758d103ba2ea710e4f0a72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Remove more Window methods that aren't actually present
Changed paths:
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 9b1268e..b916fc4 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -432,14 +432,6 @@ bool TextBufferWindow::unputCharUni(uint32 ch) {
return false;
}
-void TextBufferWindow::putBuffer(const unsigned char *buf, size_t len) {
- // TODO
-}
-
-void TextBufferWindow::putBufferUni(const uint32 *buf, size_t len) {
- // TODO
-}
-
void TextBufferWindow::moveCursor(const Common::Point &newPos) {
// TODO
}
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 0e6ee2c..ebba2b4 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -143,16 +143,6 @@ public:
virtual bool unputCharUni(uint32 ch) override;
/**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) override;
-
- /**
* Move the cursor
*/
virtual void moveCursor(const Common::Point &newPos) override;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 92bdcf5..17bb222 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -159,14 +159,6 @@ bool TextGridWindow::unputCharUni(uint32 ch) {
}
}
-void TextGridWindow::putBuffer(const unsigned char *buf, size_t len) {
- // TODO
-}
-
-void TextGridWindow::putBufferUni(const uint32 *buf, size_t len) {
- // TODO
-}
-
void TextGridWindow::moveCursor(const Common::Point &pos) {
// If the values are negative, they're really huge positive numbers --
// remember that they were cast from glui32. So set them huge and
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 8ebaf82..0cf6d5e 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -115,16 +115,6 @@ public:
virtual bool unputCharUni(uint32 ch) override;
/**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) override;
-
- /**
* Move the cursor
*/
virtual void moveCursor(const Common::Point &newPos) override;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 60f6bb4..5e6374c 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -321,16 +321,6 @@ public:
virtual bool unputCharUni(uint32 ch) { return false; }
/**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) {}
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) {}
-
- /**
* Move the cursor
*/
virtual void moveCursor(const Common::Point &newPos) {}
Commit: ba907c9aec333903acb013e9d3a25962c69b6ca6
https://github.com/scummvm/scummvm/commit/ba907c9aec333903acb013e9d3a25962c69b6ca6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Implementing text buffer window methods
Changed paths:
A engines/gargoyle/speech.h
engines/gargoyle/draw.cpp
engines/gargoyle/draw.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk_types.h
engines/gargoyle/picture.cpp
engines/gargoyle/picture.h
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_mask.cpp
engines/gargoyle/window_mask.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/draw.cpp b/engines/gargoyle/draw.cpp
index 86d5fb0..f16d1a5 100644
--- a/engines/gargoyle/draw.cpp
+++ b/engines/gargoyle/draw.cpp
@@ -24,9 +24,28 @@
namespace Gargoyle {
-int Draw::drawStringUni(int x, int y, int fidx, byte *rgb, glui32 *s, int n, int spw) {
+int Draw::drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw) {
// TODO
return 0;
}
+int Draw::drawStringUni(int x, int y, int fidx, const byte *rgb, const glui32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Draw::stringWidth(int fidx, const char *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Draw::stringWidthUni(int fidx, const glui32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+void Draw::drawCaret(const Common::Point &pos) {
+ // TODO
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/draw.h b/engines/gargoyle/draw.h
index 61dfe18..e0ec133 100644
--- a/engines/gargoyle/draw.h
+++ b/engines/gargoyle/draw.h
@@ -23,14 +23,22 @@
#ifndef GARGOYLE_DRAW_H
#define GARGOYLE_DRAW_H
-#include "common/events.h"
+#include "common/rect.h"
#include "gargoyle/glk_types.h"
namespace Gargoyle {
class Draw {
protected:
- int drawStringUni(int x, int y, int fidx, byte *rgb, glui32 *s, int n, int spw);
+ int drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw);
+
+ int drawStringUni(int x, int y, int fidx, const byte *rgb, const glui32 *s, int n, int spw);
+
+ int stringWidth(int fidx, const char *s, int n, int spw);
+
+ int stringWidthUni(int fidx, const glui32 *s, int n, int spw);
+
+ void drawCaret(const Common::Point &pos);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 8620e88..37df6d1 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -31,8 +31,10 @@
#include "gargoyle/gargoyle.h"
#include "gargoyle/conf.h"
#include "gargoyle/events.h"
+#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
#include "gargoyle/windows.h"
+#include "gargoyle/window_mask.h"
namespace Gargoyle {
@@ -40,7 +42,8 @@ GargoyleEngine *g_vm;
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _conf(nullptr),
- _events(nullptr), _screen(nullptr), _windows(nullptr),
+ _events(nullptr), _picList(nullptr), _screen(nullptr), _windows(nullptr),
+ _windowMask(nullptr), _copySelect(false),
gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
}
@@ -48,9 +51,11 @@ GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gam
GargoyleEngine::~GargoyleEngine() {
delete _conf;
delete _events;
+ delete _picList;
delete _screen;
delete _streams;
delete _windows;
+ delete _windowMask;
}
void GargoyleEngine::initialize() {
@@ -64,8 +69,10 @@ void GargoyleEngine::initialize() {
_screen = new Graphics::Screen();
_conf = new Conf();
_events = new Events();
+ _picList = new PicList();
_streams = new Streams();
_windows = new Windows(_screen);
+ _windowMask = new WindowMask();
}
Common::Error GargoyleEngine::run() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 1d81cb9..b99b7b4 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -36,7 +36,9 @@ namespace Gargoyle {
class Conf;
class Events;
+class PicList;
class Windows;
+class WindowMask;
class Streams;
enum InterpreterType {
@@ -94,8 +96,11 @@ protected:
public:
Conf *_conf;
Events *_events;
+ PicList *_picList;
Streams *_streams;
Windows *_windows;
+ WindowMask *_windowMask;
+ bool _copySelect;
void (*gli_unregister_obj)(void *obj, glui32 objclass, gidispatch_rock_t objrock);
gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, const char *typecode);
void (*gli_unregister_arr)(void *array, glui32 len, const char *typecode, gidispatch_rock_t objrock);
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index eaebb6f..a25a413 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -53,6 +53,35 @@ class Window;
typedef struct glk_fileref_struct *frefid_t;
typedef struct glk_schannel_struct *schanid_t;
+/**
+ * Usurp C1 space for ligatures and smart typography glyphs
+ */
+enum Enc {
+ ENC_LIG_FI = 128,
+ ENC_LIG_FL = 129,
+ ENC_LSQUO = 130,
+ ENC_RSQUO = 131,
+ ENC_LDQUO = 132,
+ ENC_RDQUO = 133,
+ ENC_NDASH = 134,
+ ENC_MDASH = 135,
+ ENC_FLOWBREAK = 136
+};
+
+/**
+ * These are the Unicode versions
+ */
+enum UniChars {
+ UNI_LIG_FI = 0xFB01,
+ UNI_LIG_FL = 0xFB02,
+ UNI_LSQUO = 0x2018,
+ UNI_RSQUO = 0x2019,
+ UNI_LDQUO = 0x201c,
+ UNI_RDQUO = 0x201d,
+ UNI_NDASH = 0x2013,
+ UNI_MDASH = 0x2014
+};
+
enum Gestalt {
gestalt_Version = 0,
gestalt_CharInput = 1,
diff --git a/engines/gargoyle/picture.cpp b/engines/gargoyle/picture.cpp
index 4b0b892..fd33e71 100644
--- a/engines/gargoyle/picture.cpp
+++ b/engines/gargoyle/picture.cpp
@@ -24,6 +24,16 @@
namespace Gargoyle {
+void PicList::increment() {
+ // TODO
+}
+
+void PicList::decrement() {
+ // TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
void Picture::increment() {
++_refCount;
}
@@ -35,4 +45,19 @@ void Picture::decrement() {
}
}
+Picture *Picture::load(uint32 id) {
+ // TODO: gli_picture_load
+ return nullptr;
+}
+
+Picture *Picture::scale(int sx, int sy) {
+ // TODO: gli_picture_scale
+ return nullptr;
+}
+
+void Picture::drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1) {
+ // TODO: drawPicture
+}
+
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/picture.h b/engines/gargoyle/picture.h
index 38f776c..c9527c5 100644
--- a/engines/gargoyle/picture.h
+++ b/engines/gargoyle/picture.h
@@ -27,7 +27,17 @@
namespace Gargoyle {
+class PicList {
+public:
+ void increment();
+
+ void decrement();
+};
+
struct Picture : Graphics::Surface {
+public:
+ static Picture *load(uint32 id);
+public:
int _refCount;
uint32 _id;
bool _scaled;
@@ -46,6 +56,16 @@ struct Picture : Graphics::Surface {
* Decrement reference counter
*/
void decrement();
+
+ /**
+ * Rescale the picture to a new picture of a given size
+ */
+ Picture *scale(int sx, int sy);
+
+ /**
+ * Draw the picture
+ */
+ void drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/speech.h b/engines/gargoyle/speech.h
new file mode 100644
index 0000000..1ff2cb1
--- /dev/null
+++ b/engines/gargoyle/speech.h
@@ -0,0 +1,49 @@
+/* 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 GARGOYLE_SPEECH_H
+#define GARGOYLE_SPEECH_H
+
+#include "common/events.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+/**
+ * Currently not implemented
+ */
+class Speech {
+protected:
+ void gli_initialize_tts(void) {}
+
+ void gli_tts_flush(void) {}
+
+ void gli_tts_purge(void) {}
+
+ void gli_tts_speak(const glui32 *buf, size_t len) {}
+
+ void gli_free_tts(void) {}
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index cc9a5dd..732686d 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -86,4 +86,9 @@ void GraphicsWindow::redraw() {
// TODO
}
+glui32 GraphicsWindow::imageDraw(glui32 image, glui32 align, bool scaled, glui32 width, glui32 height) {
+ // TODO: win_graphics_draw_picture
+ return 0;
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index 77e4910..b0f53fa 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -77,6 +77,9 @@ public:
*/
virtual void redraw() override;
+ virtual glui32 imageDraw(glui32 image, glui32 align, bool scaled, glui32 width = 0,
+ glui32 height = 0) override;
+
/**
* Get the window dimensions
*/
diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp
index f0f6aa3..fe1d463 100644
--- a/engines/gargoyle/window_mask.cpp
+++ b/engines/gargoyle/window_mask.cpp
@@ -202,7 +202,7 @@ int WindowMask::checkSelection(uint x0, uint y0, uint x1, uint y1) {
return false;
}
-int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, uint *rx0, uint *rx1) {
+int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *rx1) {
uint row, upper, lower, above, below;
int row_selected, found_left, found_right;
int from_right, from_below, is_above, is_below;
diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h
index db0d7e6..9dc5826 100644
--- a/engines/gargoyle/window_mask.h
+++ b/engines/gargoyle/window_mask.h
@@ -30,13 +30,14 @@ namespace Gargoyle {
class Window;
-struct WindowMask {
+class WindowMask {
+public:
size_t _hor, _ver;
glui32 **_links;
Common::Rect _select;
static int _lastX, _lastY;
-
+public:
/**
* Constructor
*/
@@ -59,7 +60,7 @@ struct WindowMask {
int checkSelection(uint x0, uint y0, uint x1, uint y1);
- int getSelection(uint x0, uint y0, uint x1, uint y1, uint *rx0, uint *rx1);
+ int getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *rx1);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index b916fc4..3df2e5c 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -23,9 +23,17 @@
#include "gargoyle/window_text_buffer.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/string.h"
namespace Gargoyle {
+/**
+ *
+ * How many pixels we add to left/right margins
+ */
+#define SLOP (2 * GLI_SUBPIX)
+
+
TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
_historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
_scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
@@ -35,7 +43,7 @@ TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windo
_type = wintype_TextBuffer;
Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
- Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
+ Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], _styles);
}
TextBufferWindow::~TextBufferWindow() {
@@ -49,10 +57,10 @@ TextBufferWindow::~TextBufferWindow() {
delete[] _lineTerminators;
for (int i = 0; i < _scrollBack; i++) {
- if (_lines[i].lpic)
- _lines[i].lpic->decrement();
- if (_lines[i].rpic)
- _lines[i].rpic->decrement();
+ if (_lines[i]._lPic)
+ _lines[i]._lPic->decrement();
+ if (_lines[i]._rPic)
+ _lines[i]._rPic->decrement();
}
}
@@ -109,7 +117,7 @@ void TextBufferWindow::reflow() {
if (_height < 4 || _width < 20)
return;
- _lines[0].len = _numChars;
+ _lines[0]._len = _numChars;
/* allocate temp buffers */
Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
@@ -142,32 +150,32 @@ void TextBufferWindow::reflow() {
if (k == 0 && _lineRequest)
inputbyte = p + _inFence;
- if (_lines[k].lpic) {
+ if (_lines[k]._lPic) {
offsetbuf[x] = p;
alignbuf[x] = imagealign_MarginLeft;
- pictbuf[x] = _lines[k].lpic;
+ pictbuf[x] = _lines[k]._lPic;
if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = _lines[k].lhyper;
+ hyperbuf[x] = _lines[k]._lHyper;
x++;
}
- if (_lines[k].rpic) {
+ if (_lines[k]._rPic) {
offsetbuf[x] = p;
alignbuf[x] = imagealign_MarginRight;
- pictbuf[x] = _lines[k].rpic;
+ pictbuf[x] = _lines[k]._rPic;
if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = _lines[k].rhyper;
+ hyperbuf[x] = _lines[k]._rHyper;
x++;
}
- for (i = 0; i < _lines[k].len; i++) {
- attrbuf[p] = curattr = _lines[k].attr[i];
- charbuf[p] = _lines[k].chars[i];
+ for (i = 0; i < _lines[k]._len; i++) {
+ attrbuf[p] = curattr = _lines[k]._attrs[i];
+ charbuf[p] = _lines[k]._chars[i];
p++;
}
- if (_lines[k].newline) {
+ if (_lines[k]._newLine) {
attrbuf[p] = curattr;
charbuf[p] = '\n';
p++;
@@ -224,32 +232,32 @@ void TextBufferWindow::touchScroll() {
_windows->repaint(_bbox);
for (int i = 0; i < _scrollMax; i++)
- _lines[i].dirty = true;
+ _lines[i]._dirty = true;
}
bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
if (align == imagealign_MarginRight)
{
- if (_lines[0].rpic || _numChars)
+ if (_lines[0]._rPic || _numChars)
return false;
_radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
_radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- _lines[0].rpic = pic;
- _lines[0].rm = _radjw;
- _lines[0].rhyper = linkval;
+ _lines[0]._rPic = pic;
+ _lines[0]._rm = _radjw;
+ _lines[0]._rHyper = linkval;
} else {
if (align != imagealign_MarginLeft && _numChars)
putCharUni('\n');
- if (_lines[0].lpic || _numChars)
+ if (_lines[0]._lPic || _numChars)
return false;
_ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
_ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- _lines[0].lpic = pic;
- _lines[0].lm = _ladjw;
- _lines[0].lhyper = linkval;
+ _lines[0]._lPic = pic;
+ _lines[0]._lm = _ladjw;
+ _lines[0]._lHyper = linkval;
if (align != imagealign_MarginLeft)
flowBreak();
@@ -258,17 +266,110 @@ bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
return true;
}
-void TextBufferWindow::flowBreak() {
- // TODO
+glui32 TextBufferWindow::imageDraw(glui32 image, glui32 align, bool scaled, glui32 width, glui32 height) {
+ Picture *pic;
+ glui32 hyperlink;
+ int error;
+
+ pic = Picture::load(image);
+
+ if (!pic)
+ return false;
+
+ if (!_imageLoaded) {
+ g_vm->_picList->increment();
+ _imageLoaded = true;
+ }
+
+ if (scaled) {
+ Picture *tmp;
+ tmp = pic->scale(width, height);
+ pic = tmp;
+ }
+
+ hyperlink = _attr.hyper;
+
+ pic->increment();
+ error = putPicture(pic, align, hyperlink);
+
+ return error;
+}
+
+bool TextBufferWindow::flowBreak() {
+ while (_ladjn || _radjn)
+ putCharUni('\n');
+ return true;
+}
+
+void TextBufferWindow::putText(const char *buf, int len, int pos, int oldlen) {
+ int diff = len - oldlen;
+
+ if (_numChars + diff >= TBLINELEN)
+ return;
+
+ if (diff != 0 && pos + oldlen < _numChars)
+ {
+ memmove(_chars + pos + len,
+ _chars + pos + oldlen,
+ (_numChars - (pos + oldlen)) * 4);
+ memmove(_attrs + pos + len,
+ _attrs + pos + oldlen,
+ (_numChars - (pos + oldlen)) * sizeof(Attributes));
+ }
+ if (len > 0) {
+ int i;
+ for (i = 0; i < len; i++) {
+ _chars[pos + i] = buf[i];
+ _attrs[pos + i].set(style_Input);
+ }
+ }
+ _numChars += diff;
+
+ if (_inBuf) {
+ if (_inCurs >= pos + oldlen)
+ _inCurs += diff;
+ else if (_inCurs >= pos)
+ _inCurs = pos + len;
+ }
+
+ touch(0);
}
void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldlen) {
- // TODO
+ int diff = len - oldlen;
+
+ if (_numChars + diff >= TBLINELEN)
+ return;
+
+ if (diff != 0 && pos + oldlen < _numChars) {
+ memmove(_chars + pos + len,
+ _chars + pos + oldlen,
+ (_numChars - (pos + oldlen)) * 4);
+ memmove(_attrs + pos + len,
+ _attrs + pos + oldlen,
+ (_numChars - (pos + oldlen)) * sizeof(Attributes));
+ }
+ if (len > 0) {
+ int i;
+ memmove(_chars + pos, buf, len * 4);
+ for (i = 0; i < len; i++)
+ _attrs[pos + i].set(style_Input);
+ }
+ _numChars += diff;
+
+ if (_inBuf) {
+ if (_inCurs >= pos + oldlen)
+ _inCurs += diff;
+ else if (_inCurs >= pos)
+ _inCurs = pos + len;
+ }
+
+ touch(0);
}
void TextBufferWindow::touch(int line) {
int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
- _lines[line].dirty = 1;
+ _lines[line]._dirty = 1;
_windows->clearSelection();
_windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
}
@@ -278,7 +379,6 @@ glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
}
void TextBufferWindow::putCharUni(glui32 ch) {
- /*
glui32 bchars[TBLINELEN];
Attributes battrs[TBLINELEN];
int pw;
@@ -286,29 +386,28 @@ void TextBufferWindow::putCharUni(glui32 ch) {
int saved;
int i;
int linelen;
- unsigned char *color;
+ byte *color;
gli_tts_speak(&ch, 1);
- pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
- pw = pw - 2 * SLOP - radjw - ladjw;
+ pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) * GLI_SUBPIX;
+ pw = pw - 2 * SLOP - _radjw - _ladjw;
- color = Windows::_overrideBgSet ? gli_window_color : bgcolor;
+ color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
// oops ... overflow
- if (numchars + 1 >= TBLINELEN)
- scrolloneline(dwin, 0);
+ if (_numChars + 1 >= TBLINELEN)
+ scrollOneLine(0);
if (ch == '\n') {
- scrolloneline(dwin, 1);
+ scrollOneLine(1);
return;
}
- if (gli_conf_quotes) {
+ if (g_conf->_quotes) {
// fails for 'tis a wonderful day in the '80s
- if (gli_conf_quotes > 1 && ch == '\'')
- {
- if (numchars == 0 || leftquote(_chars[numchars - 1]))
+ if (g_conf->_quotes > 1 && ch == '\'') {
+ if (_numChars == 0 || leftquote(_chars[_numChars - 1]))
ch = UNI_LSQUO;
}
@@ -318,122 +417,112 @@ void TextBufferWindow::putCharUni(glui32 ch) {
if (ch == '\'')
ch = UNI_RSQUO;
- if (ch == '"')
- {
- if (numchars == 0 || leftquote(_chars[numchars - 1]))
+ if (ch == '"') {
+ if (_numChars == 0 || leftquote(_chars[_numChars - 1]))
ch = UNI_LDQUO;
else
ch = UNI_RDQUO;
}
}
- if (gli_conf_dashes && attr.style != style_Preformatted)
- {
- if (ch == '-')
- {
- dashed++;
- if (dashed == 2)
- {
- numchars--;
- if (gli_conf_dashes == 2)
+ if (g_conf->_dashes && _attr.style != style_Preformatted) {
+ if (ch == '-') {
+ _dashed++;
+ if (_dashed == 2) {
+ _numChars--;
+ if (g_conf->_dashes == 2)
ch = UNI_NDASH;
else
ch = UNI_MDASH;
}
- if (dashed == 3)
- {
- numchars--;
+ if (_dashed == 3) {
+ _numChars--;
ch = UNI_MDASH;
- dashed = 0;
+ _dashed = 0;
}
+ } else {
+ _dashed = 0;
}
- else
- dashed = 0;
}
- if (gli_conf_spaces && attr.style != style_Preformatted
- && styles[attr.style].bg == color
- && !styles[attr.style].reverse)
+ if (g_conf->_spaces && _attr.style != style_Preformatted
+ && _styles[_attr.style].bg == color
+ && !_styles[_attr.style].reverse)
{
// turn (period space space) into (period space)
- if (gli_conf_spaces == 1)
- {
+ if (g_conf->_spaces == 1) {
if (ch == '.')
- spaced = 1;
- else if (ch == ' ' && spaced == 1)
- spaced = 2;
- else if (ch == ' ' && spaced == 2)
- {
- spaced = 0;
+ _spaced = 1;
+ else if (ch == ' ' && _spaced == 1)
+ _spaced = 2;
+ else if (ch == ' ' && _spaced == 2) {
+ _spaced = 0;
return;
+ } else {
+ _spaced = 0;
}
- else
- spaced = 0;
}
// Turn (per sp x) into (per sp sp x)
- if (gli_conf_spaces == 2)
- {
+ if (g_conf->_spaces == 2) {
if (ch == '.')
- spaced = 1;
- else if (ch == ' ' && spaced == 1)
- spaced = 2;
- else if (ch != ' ' && spaced == 2)
+ _spaced = 1;
+ else if (ch == ' ' && _spaced == 1)
+ _spaced = 2;
+ else if (ch != ' ' && _spaced == 2)
{
- spaced = 0;
- win_textbuffer_putchar_uni(win, ' ');
+ _spaced = 0;
+ putCharUni(' ');
+ } else {
+ _spaced = 0;
}
- else
- spaced = 0;
}
}
- _chars[numchars] = ch;
- attrs[numchars] = attr;
- numchars++;
+ _chars[_numChars] = ch;
+ _attrs[_numChars] = _attr;
+ _numChars++;
// kill spaces at the end for line width calculation
- linelen = numchars;
+ linelen = _numChars;
while (linelen > 1 && _chars[linelen - 1] == ' '
- && styles[attrs[linelen - 1].style].bg == color
- && !styles[attrs[linelen - 1].style].reverse)
+ && _styles[_attrs[linelen - 1].style].bg == color
+ && !_styles[_attrs[linelen - 1].style].reverse)
linelen--;
- if (calcwidth(dwin, _chars, attrs, 0, linelen, -1) >= pw)
- {
- bpoint = numchars;
+ if (calcWidth(_chars, _attrs, 0, linelen, -1) >= pw) {
+ bpoint = _numChars;
- for (i = numchars - 1; i > 0; i--)
- if (_chars[i] == ' ')
- {
+ for (i = _numChars - 1; i > 0; i--)
+ if (_chars[i] == ' ') {
bpoint = i + 1; // skip space
break;
}
- saved = numchars - bpoint;
+ saved = _numChars - bpoint;
memcpy(bchars, _chars + bpoint, saved * 4);
- memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
- numchars = bpoint;
+ memcpy(battrs, _attrs + bpoint, saved * sizeof(Attributes));
+ _numChars = bpoint;
- scrolloneline(dwin, 0);
+ scrollOneLine(0);
memcpy(_chars, bchars, saved * 4);
- memcpy(attrs, battrs, saved * sizeof(attr_t));
- numchars = saved;
+ memcpy(_attrs, battrs, saved * sizeof(Attributes));
+ _numChars = saved;
}
touch(0);
- */
}
bool TextBufferWindow::unputCharUni(uint32 ch) {
- // TODO
- return false;
-}
+ if (_numChars > 0 && _chars[_numChars - 1] == ch) {
+ _numChars--;
+ touch(0);
+ return true;
+ }
-void TextBufferWindow::moveCursor(const Common::Point &newPos) {
- // TODO
+ return false;
}
void TextBufferWindow::clear() {
@@ -454,20 +543,20 @@ void TextBufferWindow::clear() {
_numChars = 0;
for (i = 0; i < _scrollBack; i++) {
- _lines[i].len = 0;
-
- if (_lines[i].lpic) _lines[i].lpic->decrement();
- _lines[i].lpic = nullptr;
- if (_lines[i].rpic) _lines[i].rpic->decrement();
- _lines[i].rpic = nullptr;
-
- _lines[i].lhyper = 0;
- _lines[i].rhyper = 0;
- _lines[i].lm = 0;
- _lines[i].rm = 0;
- _lines[i].newline = 0;
- _lines[i].dirty = true;
- _lines[i].repaint = false;
+ _lines[i]._len = 0;
+
+ if (_lines[i]._lPic) _lines[i]._lPic->decrement();
+ _lines[i]._lPic = nullptr;
+ if (_lines[i]._rPic) _lines[i]._rPic->decrement();
+ _lines[i]._rPic = nullptr;
+
+ _lines[i]._lHyper = 0;
+ _lines[i]._rHyper = 0;
+ _lines[i]._lm = 0;
+ _lines[i]._rm = 0;
+ _lines[i]._newLine = 0;
+ _lines[i]._dirty = true;
+ _lines[i]._repaint = false;
}
_lastSeen = 0;
@@ -478,24 +567,146 @@ void TextBufferWindow::clear() {
touch(i);
}
+void TextBufferWindow::click(const Common::Point &newPos) {
+ int gh = false;
+ int gs = false;
+
+ if (_lineRequest || _charRequest
+ || _lineRequestUni || _charRequestUni
+ || _moreRequest || _scrollRequest)
+ _windows->setFocus(this);
+
+ if (_hyperRequest) {
+ glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
+ if (linkval) {
+ g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
+ _hyperRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = 1;
+ gh = true;
+ }
+ }
+
+ if (newPos.x > _bbox.right - g_conf->_scrollWidth) {
+ if (newPos.y < _bbox.top + g_conf->_tMarginY + g_conf->_scrollWidth)
+ acceptScroll(keycode_Up);
+ else if (newPos.y > _bbox.bottom - g_conf->_tMarginY - g_conf->_scrollWidth)
+ acceptScroll(keycode_Down);
+ else if (newPos.y < (_bbox.top + _bbox.bottom) / 2)
+ acceptScroll(keycode_PageUp);
+ else
+ acceptScroll(keycode_PageDown);
+ gs = true;
+ }
+
+ if (!gh && !gs) {
+ g_vm->_copySelect = true;
+ g_vm->_windowMask->startSelection(newPos);
+ }
+}
+
void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
warning("request_line_event: window already has keyboard request");
return;
}
- // TODO
+ int pw;
+
+ gli_tts_flush();
+
+ /* because '>' prompt is ugly without extra space */
+ if (_numChars && _chars[_numChars - 1] == '>')
+ putCharUni(' ');
+ if (_numChars && _chars[_numChars - 1] == '?')
+ putCharUni(' ');
+
+ /* make sure we have some space left for typing... */
+ pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2) * GLI_SUBPIX;
+ pw = pw - 2 * SLOP - _radjw + _ladjw;
+ if (calcWidth(_chars, _attrs, 0, _numChars, -1) >= pw * 3 / 4)
+ putCharUni('\n');
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inFence = _numChars;
+ _inCurs = _numChars;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ _historyPos = _historyPresent;
+
+ if (initlen) {
+ touch(0);
+ putText(buf, initlen, _inCurs, 0);
+ }
+
+ _echoLineInput = _echoLineInputBase;
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Cn");
}
void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
warning("request_line_event_uni: window already has keyboard request");
return;
}
- // TODO
+ int pw;
+
+ gli_tts_flush();
+
+ /* because '>' prompt is ugly without extra space */
+ if (_numChars && _chars[_numChars - 1] == '>')
+ putCharUni(' ');
+ if (_numChars && _chars[_numChars - 1] == '?')
+ putCharUni(' ');
+
+ /* make sure we have some space left for typing... */
+ pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2) * GLI_SUBPIX;
+ pw = pw - 2 * SLOP - _radjw + _ladjw;
+ if (calcWidth(_chars, _attrs, 0, _numChars, -1) >= pw * 3 / 4)
+ putCharUni('\n');
+
+ //_lastSeen = 0;
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inFence = _numChars;
+ _inCurs = _numChars;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ _historyPos = _historyPresent;
+
+ if (initlen) {
+ touch(0);
+ putTextUni(buf, initlen, _inCurs, 0);
+ }
+
+ _echoLineInput = _echoLineInputBase;
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Iu");
}
void TextBufferWindow::cancelLineEvent(Event *ev) {
@@ -571,21 +782,857 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
}
void TextBufferWindow::redraw() {
- // TODO
+ TextBufferRow *ln;
+ int linelen;
+ int nsp, spw, pw;
+ int x0, y0, x1, y1;
+ int x, y, w;
+ int a, b;
+ glui32 link;
+ int font;
+ unsigned char *color;
+ int i;
+ int hx0, hx1, hy0, hy1;
+ int selbuf, selrow, selchar, sx0, sx1, selleft, selright;
+ int tx, tsc, tsw, lsc, rsc;
+
+ _lines[0]._len = _numChars;
+
+ ln = new TextBufferRow();
+ if (!ln)
+ return;
+
+ x0 = (_bbox.left + g_conf->_tMarginX) * GLI_SUBPIX;
+ x1 = (_bbox.right - g_conf->_tMarginX - g_conf->_scrollWidth) * GLI_SUBPIX;
+ y0 = _bbox.top + g_conf->_tMarginY;
+ y1 = _bbox.bottom - g_conf->_tMarginY;
+
+ pw = x1 - x0 - 2 * GLI_SUBPIX;
+
+ /* check if any part of buffer is selected */
+ selbuf = g_vm->_windowMask->checkSelection(x0/GLI_SUBPIX,y0,x1/GLI_SUBPIX,y1);
+
+ for (i = _scrollPos + _height - 1; i >= _scrollPos; i--) {
+ /* top of line */
+ y = y0 + (_height - (i - _scrollPos) - 1) * g_conf->_leading;
+
+ /* check if part of line is selected */
+ if (selbuf) {
+ selrow = g_vm->_windowMask->getSelection(x0/GLI_SUBPIX, y,
+ x1/GLI_SUBPIX, y + g_conf->_leading,
+ &sx0, &sx1);
+ selleft = (sx0 == x0/GLI_SUBPIX);
+ selright = (sx1 == x1/GLI_SUBPIX);
+ } else {
+ selrow = false;
+ }
+
+ /* mark selected line dirty */
+ if (selrow)
+ _lines[i]._dirty = true;
+
+ memcpy(ln, &_lines[i], sizeof(TextBufferRow));
+
+ /* skip if we can */
+ if (!ln->_dirty && !ln->_repaint && !Windows::_forceRedraw && _scrollPos == 0)
+ continue;
+
+ /* repaint previously selected lines if needed */
+ if (ln->_repaint && !Windows::_forceRedraw)
+ _windows->redrawRect(Common::Rect(x0 / GLI_SUBPIX, y,
+ x1/GLI_SUBPIX, y + g_conf->_leading));
+
+ /* keep selected line dirty and flag for repaint */
+ if (!selrow) {
+ _lines[i]._dirty = false;
+ _lines[i]._repaint = false;
+ } else {
+ _lines[i]._repaint = true;
+ }
+
+ /* leave bottom line blank for [more] prompt */
+ if (i == _scrollPos && i > 0)
+ continue;
+
+ linelen = ln->_len;
+
+ /* kill spaces at the end unless they're a different color*/
+ color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
+ while (i > 0 && linelen > 1 && ln->_chars[linelen-1] == ' '
+ && _styles[ln->_attrs[linelen-1].style].bg == color
+ && !_styles[ln->_attrs[linelen-1].style].reverse)
+ linelen --;
+
+ /* kill characters that would overwrite the scroll bar */
+ while (linelen > 1 && calcWidth(ln->_chars, ln->_attrs, 0, linelen, -1) >= pw)
+ linelen --;
+
+ /*
+ * count spaces and width for justification
+ */
+ if (g_conf->_justify && !ln->_newLine && i > 0) {
+ for (a = 0, nsp = 0; a < linelen; a++)
+ if (ln->_chars[a] == ' ')
+ nsp ++;
+ w = calcWidth(ln->_chars, ln->_attrs, 0, linelen, 0);
+ if (nsp)
+ spw = (x1 - x0 - ln->_lm - ln->_rm - 2 * SLOP - w) / nsp;
+ else
+ spw = 0;
+ } else {
+ spw = -1;
+ }
+
+ /* find and highlight selected characters */
+ if (selrow && !Windows::_claimSelect) {
+ lsc = 0;
+ rsc = 0;
+ selchar = false;
+ /* optimized case for all chars selected */
+ if (selleft && selright) {
+ rsc = linelen > 0 ? linelen - 1 : 0;
+ selchar = calcWidth(ln->_chars, ln->_attrs, lsc, rsc, spw)/GLI_SUBPIX;
+ } else {
+ /* optimized case for leftmost char selected */
+ if (selleft) {
+ tsc = linelen > 0 ? linelen - 1 : 0;
+ selchar = calcWidth(ln->_chars, ln->_attrs, lsc, tsc, spw)/GLI_SUBPIX;
+ } else {
+ /* find the substring contained by the selection */
+ tx = (x0 + SLOP + ln->_lm)/GLI_SUBPIX;
+ /* measure string widths until we find left char */
+ for (tsc = 0; tsc < linelen; tsc++) {
+ tsw = calcWidth(ln->_chars, ln->_attrs, 0, tsc, spw)/GLI_SUBPIX;
+ if (tsw + tx >= sx0 ||
+ tsw + tx + GLI_SUBPIX >= sx0 && ln->_chars[tsc] != ' ') {
+ lsc = tsc;
+ selchar = true;
+ break;
+ }
+ }
+ }
+ if (selchar) {
+ /* optimized case for rightmost char selected */
+ if (selright) {
+ rsc = linelen > 0 ? linelen - 1 : 0;
+ } else {
+ /* measure string widths until we find right char */
+ for (tsc = lsc; tsc < linelen; tsc++) {
+ tsw = calcWidth(ln->_chars, ln->_attrs, lsc, tsc, spw)/GLI_SUBPIX;
+ if (tsw + sx0 < sx1)
+ rsc = tsc;
+ }
+ if (lsc && !rsc)
+ rsc = lsc;
+ }
+ }
+ }
+ /* reverse colors for selected chars */
+ if (selchar) {
+ for (tsc = lsc; tsc <= rsc; tsc++) {
+ ln->_attrs[tsc].reverse = !ln->_attrs[tsc].reverse;
+ _copyBuf[_copyPos] = ln->_chars[tsc];
+ _copyPos++;
+ }
+ }
+ /* add newline if we reach the end of the line */
+ if (ln->_len == 0 || ln->_len == (rsc+1)) {
+ _copyBuf[_copyPos] = '\n';
+ _copyPos++;
+ }
+ }
+
+ /* clear any stored hyperlink coordinates */
+ g_vm->_windowMask->putHyperlink(0, x0/GLI_SUBPIX, y,
+ x1/GLI_SUBPIX, y + g_conf->_leading);
+
+ /*
+ * fill in background colors
+ */
+ color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
+ _windows->drawRect(x0/GLI_SUBPIX, y,
+ (x1-x0) / GLI_SUBPIX, g_conf->_leading,
+ color);
+
+ x = x0 + SLOP + ln->_lm;
+ a = 0;
+ for (b = 0; b < linelen; b++)
+ {
+ if (ln->_attrs[a] == ln->_attrs[b]) {
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(_styles);
+ color = ln->_attrs[a].attrBg(_styles);
+ w = stringWidthUni(font, ln->_chars + a, b - a, spw);
+ _windows->drawRect(x/GLI_SUBPIX, y,
+ w/GLI_SUBPIX, g_conf->_leading,
+ color);
+ if (link) {
+ _windows->drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ w/GLI_SUBPIX + 1, g_conf->_linkStyle,
+ g_conf->_linkColor);
+ g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
+ x/GLI_SUBPIX + w/GLI_SUBPIX,
+ y + g_conf->_leading);
+ }
+ x += w;
+ a = b;
+ }
+ }
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(_styles);
+ color = ln->_attrs[a].attrBg(_styles);
+ w = stringWidthUni(font, ln->_chars + a, b - a, spw);
+ _windows->drawRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
+ g_conf->_leading, color);
+ if (link) {
+ _windows->drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ w/GLI_SUBPIX + 1, g_conf->_linkStyle,
+ g_conf->_linkColor);
+ g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
+ x/GLI_SUBPIX + w/GLI_SUBPIX,
+ y + g_conf->_leading);
+ }
+ x += w;
+
+ color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
+ _windows->drawRect(x/GLI_SUBPIX, y,
+ x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
+ color);
+
+ /*
+ * draw caret
+ */
+
+ if (_windows->getFocusWindow() == this && i == 0 && (_lineRequest || _lineRequestUni)) {
+ w = calcWidth(_chars, _attrs, 0, _inCurs, spw);
+ if (w < pw - g_conf->_caretShape * 2 * GLI_SUBPIX)
+ drawCaret(Common::Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
+ }
+
+ /*
+ * draw text
+ */
+
+ x = x0 + SLOP + ln->_lm;
+ a = 0;
+ for (b = 0; b < linelen; b++)
+ {
+ if (ln->_attrs[a] == ln->_attrs[b]) {
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(_styles);
+ color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
+ x = drawStringUni(x, y + g_conf->_baseLine,
+ font, color, ln->_chars + a, b - a, spw);
+ a = b;
+ }
+ }
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(_styles);
+ color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
+ drawStringUni(x, y + g_conf->_baseLine,
+ font, color, ln->_chars + a, linelen - a, spw);
+ }
+
+ /*
+ * draw more prompt
+ */
+ if (_scrollPos && _height > 1)
+ {
+ x = x0 + SLOP;
+ y = y0 + (_height - 1) * g_conf->_leading;
+
+ g_vm->_windowMask->putHyperlink(0, x0/GLI_SUBPIX, y,
+ x1/GLI_SUBPIX, y + g_conf->_leading);
+
+ color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
+ _windows->drawRect(x/GLI_SUBPIX, y,
+ x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
+ color);
+
+ w = stringWidth(g_conf->_moreFont,
+ g_conf->_morePrompt.c_str(), g_conf->_morePrompt.size(), -1);
+
+ if (g_conf->_moreAlign == 1) /* center */
+ x = x0 + SLOP + (x1 - x0 - w - SLOP * 2) / 2;
+ if (g_conf->_moreAlign == 2) /* right */
+ x = x1 - SLOP - w;
+
+ color = Windows::_overrideFgSet ? g_conf->_moreColor : _fgColor;
+ drawString(x, y + g_conf->_baseLine,
+ g_conf->_moreFont, color,
+ g_conf->_morePrompt.c_str(), g_conf->_morePrompt.size(), -1);
+ y1 = y; /* don't want pictures overdrawing "[more]" */
+
+ /* try to claim the focus */
+ _moreRequest = true;
+ Windows::_moreFocus = true;
+ } else {
+ _moreRequest = false;
+ y1 = y0 + _height * g_conf->_leading;
+ }
+
+ /*
+ * draw the images
+ */
+ for (i = 0; i < _scrollBack; i++) {
+ memcpy(ln, &_lines[i], sizeof(TextBufferRow));
+
+ y = y0 + (_height - (i - _scrollPos) - 1) * g_conf->_leading;
+
+ if (ln->_lPic) {
+ if (y < y1 && y + ln->_lPic->h > y0) {
+ ln->_lPic->drawPicture(x0/GLI_SUBPIX, y, x0/GLI_SUBPIX, y0, x1/GLI_SUBPIX, y1);
+ link = ln->_lHyper;
+ hy0 = y > y0 ? y : y0;
+ hy1 = y + ln->_lPic->h < y1 ? y + ln->_lPic->h : y1;
+ hx0 = x0/GLI_SUBPIX;
+ hx1 = x0/GLI_SUBPIX + ln->_lPic->w < x1/GLI_SUBPIX
+ ? x0/GLI_SUBPIX + ln->_lPic->w
+ : x1/GLI_SUBPIX;
+ g_vm->_windowMask->putHyperlink(link, hx0, hy0, hx1, hy1);
+ }
+ }
+
+ if (ln->_rPic) {
+ if (y < y1 && y + ln->_rPic->h > y0) {
+ ln->_rPic->drawPicture(x1/GLI_SUBPIX - ln->_rPic->w, y,
+ x0/GLI_SUBPIX, y0, x1/GLI_SUBPIX, y1);
+ link = ln->_rHyper;
+ hy0 = y > y0 ? y : y0;
+ hy1 = y + ln->_rPic->h < y1 ? y + ln->_rPic->h : y1;
+ hx0 = x1/GLI_SUBPIX - ln->_rPic->w > x0/GLI_SUBPIX
+ ? x1/GLI_SUBPIX - ln->_rPic->w
+ : x0/GLI_SUBPIX;
+ hx1 = x1/GLI_SUBPIX;
+ g_vm->_windowMask->putHyperlink(link, hx0, hy0, hx1, hy1);
+ }
+ }
+ }
+
+ /*
+ * Draw the scrollbar
+ */
+
+ /* try to claim scroll keys */
+ _scrollRequest = _scrollMax > _height;
+
+ if (_scrollRequest && g_conf->_scrollWidth)
+ {
+ int t0, t1;
+ x0 = _bbox.right - g_conf->_scrollWidth;
+ x1 = _bbox.right;
+ y0 = _bbox.top + g_conf->_tMarginY;
+ y1 = _bbox.bottom - g_conf->_tMarginY;
+
+ g_vm->_windowMask->putHyperlink(0, x0, y0, x1, y1);
+
+ y0 += g_conf->_scrollWidth / 2;
+ y1 -= g_conf->_scrollWidth / 2;
+
+ // pos = thbot, pos - ht = thtop, max = wtop, 0 = wbot
+ t0 = (_scrollMax - _scrollPos) - (_height - 1);
+ t1 = (_scrollMax - _scrollPos);
+ if (_scrollMax > _height) {
+ t0 = t0 * (y1 - y0) / _scrollMax + y0;
+ t1 = t1 * (y1 - y0) / _scrollMax + y0;
+ } else {
+ t0 = t1 = y0;
+ }
+
+ _windows->drawRect(x0+1, y0, x1-x0-2, y1-y0, g_conf->_scrollBg);
+ _windows->drawRect(x0+1, t0, x1-x0-2, t1-t0, g_conf->_scrollFg);
+
+ for (i = 0; i < g_conf->_scrollWidth / 2 + 1; i++) {
+ _windows->drawRect(x0+g_conf->_scrollWidth/2-i,
+ y0 - g_conf->_scrollWidth/2 + i,
+ i*2, 1, g_conf->_scrollFg);
+ _windows->drawRect(x0+g_conf->_scrollWidth/2-i,
+ y1 + g_conf->_scrollWidth/2 - i,
+ i*2, 1, g_conf->_scrollFg);
+ }
+ }
+
+ /* send selected text to clipboard */
+ if (selbuf && _copyPos) {
+ Windows::_claimSelect = true;
+
+ copyTextToClipboard(_copyBuf, _copyPos);
+ for (i = 0; i < _copyPos; i++)
+ _copyBuf[i] = 0;
+ _copyPos = 0;
+ }
+
+ /* no more prompt means all text has been seen */
+ if (!_moreRequest)
+ _lastSeen = 0;
+
+ free(ln);
}
-/*--------------------------------------------------------------------------*/
+int TextBufferWindow::acceptScroll(glui32 arg) {
+ int pageht = _height - 2; /* 1 for prompt, 1 for overlap */
+ int startpos = _scrollPos;
+
+ switch (arg) {
+ case keycode_PageUp:
+ _scrollPos += pageht;
+ break;
+ case keycode_End:
+ _scrollPos = 0;
+ break;
+ case keycode_Up:
+ _scrollPos++;
+ break;
+ case keycode_Down:
+ case keycode_Return:
+ _scrollPos--;
+ break;
+ case keycode_MouseWheelUp:
+ _scrollPos += 3;
+ startpos = true;
+ break;
+ case keycode_MouseWheelDown:
+ _scrollPos -= 3;
+ startpos = true;
+ break;
+ case ' ':
+ case keycode_PageDown:
+ //default:
+ if (pageht)
+ _scrollPos -= pageht;
+ else
+ _scrollPos = 0;
+ break;
+ }
+
+ if (_scrollPos > _scrollMax - _height + 1)
+ _scrollPos = _scrollMax - _height + 1;
+ if (_scrollPos < 0)
+ _scrollPos = 0;
+ touchScroll();
+
+ return (startpos || _scrollPos);
+}
+
+void TextBufferWindow::acceptReadChar(glui32 arg) {
+ glui32 key;
+
+ if (_height < 2)
+ _scrollPos = 0;
+
+ if (_scrollPos
+ || arg == keycode_PageUp
+ || arg == keycode_MouseWheelUp) {
+ acceptScroll(arg);
+ return;
+ }
+
+ switch (arg) {
+ case keycode_Erase:
+ key = keycode_Delete;
+ break;
+ case keycode_MouseWheelUp:
+ case keycode_MouseWheelDown:
+ return;
+ default:
+ key = arg;
+ }
+
+ gli_tts_purge();
+
+ if (key > 0xff && key < (0xffffffff - keycode_MAXVAL + 1)) {
+ if (!(_charRequestUni) || key > 0x10ffff)
+ key = keycode_Unknown;
+ }
+
+ _charRequest = false;
+ _charRequestUni = false;
+ g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
+}
+
+void TextBufferWindow::acceptReadLine(glui32 arg) {
+ glui32 *cx;
+ int len;
+
+ if (_height < 2)
+ _scrollPos = 0;
+
+ if (_scrollPos
+ || arg == keycode_PageUp
+ || arg == keycode_MouseWheelUp)
+ {
+ acceptScroll(arg);
+ return;
+ }
+
+ if (!_inBuf)
+ return;
+
+ if (_lineTerminators && checkTerminator(arg)) {
+ for (cx = _lineTerminators; *cx; cx++) {
+ if (*cx == arg) {
+ acceptLine(arg);
+ return;
+ }
+ }
+ }
+
+ switch (arg) {
+
+ /* History keys (up and down) */
+
+ case keycode_Up:
+ if (_historyPos == _historyFirst)
+ return;
+ if (_historyPos == _historyPresent) {
+ len = _numChars - _inFence;
+ if (len > 0) {
+ cx = new glui32[len + 1];
+ memcpy(cx, &(_chars[_inFence]), len * 4);
+ cx[len] = 0;
+ } else {
+ cx = nullptr;
+ }
+ if (_history[_historyPos])
+ free(_history[_historyPos]);
+ _history[_historyPos] = cx;
+ }
+ _historyPos--;
+ if (_historyPos < 0)
+ _historyPos += HISTORYLEN;
+ cx = _history[_historyPos];
+ putTextUni(cx, cx ? strlen_uni(cx) : 0, _inFence,
+ _numChars - _inFence);
+ break;
+
+ case keycode_Down:
+ if (_historyPos == _historyPresent)
+ return;
+ _historyPos++;
+ if (_historyPos >= HISTORYLEN)
+ _historyPos -= HISTORYLEN;
+ cx = _history[_historyPos];
+ putTextUni(cx, cx ? strlen_uni(cx) : 0, _inFence,
+ _numChars - _inFence);
+ break;
+
+ /* Cursor movement keys, during line input. */
+
+ case keycode_Left:
+ if (_inCurs <= _inFence)
+ return;
+ _inCurs--;
+ break;
+
+ case keycode_Right:
+ if (_inCurs >= _numChars)
+ return;
+ _inCurs++;
+ break;
+
+ case keycode_Home:
+ if (_inCurs <= _inFence)
+ return;
+ _inCurs = _inFence;
+ break;
+
+ case keycode_End:
+ if (_inCurs >= _numChars)
+ return;
+ _inCurs = _numChars;
+ break;
+
+ case keycode_SkipWordLeft:
+ while (_inCurs > _inFence && _chars[_inCurs - 1] == ' ')
+ _inCurs--;
+ while (_inCurs > _inFence && _chars[_inCurs - 1] != ' ')
+ _inCurs--;
+ break;
+
+ case keycode_SkipWordRight:
+ while (_inCurs < _numChars && _chars[_inCurs] != ' ')
+ _inCurs++;
+ while (_inCurs < _numChars && _chars[_inCurs] == ' ')
+ _inCurs++;
+ break;
+
+ /* Delete keys, during line input. */
+
+ case keycode_Delete:
+ if (_inCurs <= _inFence)
+ return;
+ putTextUni(nullptr, 0, _inCurs - 1, 1);
+ break;
+
+ case keycode_Erase:
+ if (_inCurs >= _numChars)
+ return;
+ putTextUni(nullptr, 0, _inCurs, 1);
+ break;
+
+ case keycode_Escape:
+ if (_inFence >= _numChars)
+ return;
+ putTextUni(nullptr, 0, _inFence, _numChars - _inFence);
+ break;
+
+ /* Regular keys */
+
+ case keycode_Return:
+ acceptLine(arg);
+ break;
+
+ default:
+ if (arg >= 32 && arg <= 0x10FFFF)
+ {
+ if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
+ arg -= 0x20;
+ putTextUni(&arg, 1, _inCurs, 0);
+ }
+ break;
+ }
-TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
- lpic(nullptr), rpic(nullptr), lhyper(0), rhyper(0), lm(0), rm(0) {
+ touch(0);
}
-void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
- chars.clear();
- attr.clear();
- chars.resize(newSize);
- attr.resize(newSize);
- Common::fill(&chars[0], &chars[0] + newSize, ' ');
+/* Return or enter, during line input. Ends line input. */
+void TextBufferWindow::acceptLine(glui32 keycode) {
+ int ix;
+ int len, olen;
+ void *inbuf;
+ glui32 *s, *o;
+ int inmax;
+ gidispatch_rock_t inarrayrock;
+ int unicode = _lineRequestUni;
+
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ len = _numChars - _inFence;
+ if (_echoStream)
+ _echoStream->echoLineUni(_chars + _inFence, len);
+
+ gli_tts_purge();
+ if (g_conf->_speakInput) {
+ const uint32 NEWLINE = '\n';
+ gli_tts_speak(_chars + _inFence, len);
+ gli_tts_speak((const glui32 *)&NEWLINE, 1);
+ }
+
+ /*
+ * Store in history.
+ * The history is a ring buffer, with historypresent being the index of the most recent
+ * element and historyfirst the index of the oldest element.
+ * A history entry should not repeat the string from the entry before it.
+ */
+ if (len) {
+ s = new glui32[len + 1];
+ memcpy(s, _chars + _inFence, len * sizeof(glui32));
+ s[len] = 0;
+
+ free(_history[_historyPresent]);
+ _history[_historyPresent] = nullptr;
+
+ o = _history[(_historyPresent == 0 ? HISTORYLEN : _historyPresent) - 1];
+ olen = o ? strlen_uni(o) : 0;
+
+ if (len != olen || memcmp(s, o, olen * sizeof(glui32))) {
+ _history[_historyPresent] = s;
+
+ _historyPresent++;
+ if (_historyPresent == HISTORYLEN)
+ _historyPresent = 0;
+
+ if (_historyPresent == _historyFirst) {
+ _historyFirst++;
+ if (_historyFirst == HISTORYLEN)
+ _historyFirst = 0;
+ }
+ } else {
+ free(s);
+ }
+ }
+
+ /* Store in event buffer. */
+
+ if (len > inmax)
+ len = inmax;
+
+ if (!unicode) {
+ for (ix = 0; ix<len; ix++) {
+ glui32 ch = _chars[_inFence + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ } else {
+ for (ix = 0; ix<len; ix++)
+ ((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
+ }
+
+ _attr = _origAttr;
+
+ if (_lineTerminators) {
+ glui32 val2 = keycode;
+ if (val2 == keycode_Return)
+ val2 = 0;
+ g_vm->_events->eventStore(evtype_LineInput, this, len, val2);
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ } else {
+ g_vm->_events->eventStore(evtype_LineInput, this, len, 0);
+ }
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+ _inBuf = nullptr;
+ _inMax = 0;
+
+ if (_echoLineInput) {
+ putCharUni('\n');
+ } else {
+ _numChars = _inFence;
+ touch(0);
+ }
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+bool TextBufferWindow::leftquote(glui32 c) {
+ switch (c) {
+ case '(': case '[':
+
+ /* The following are Unicode characters in the "Separator, Space" category. */
+ case 0x0020: case 0x00a0: case 0x1680: case 0x2000:
+ case 0x2001: case 0x2002: case 0x2003: case 0x2004:
+ case 0x2005: case 0x2006: case 0x2007: case 0x2008:
+ case 0x2009: case 0x200a: case 0x202f: case 0x205f:
+ case 0x3000:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void TextBufferWindow::scrollOneLine(bool forced) {
+ _lastSeen++;
+ _scrollMax++;
+
+ if (_scrollMax > _scrollBack - 1
+ || _lastSeen > _scrollBack - 1)
+ scrollResize();
+
+ if (_lastSeen >= _height)
+ _scrollPos++;
+
+ if (_scrollPos > _scrollMax - _height + 1)
+ _scrollPos = _scrollMax - _height + 1;
+ if (_scrollPos < 0)
+ _scrollPos = 0;
+
+ if (forced)
+ _dashed = 0;
+ _spaced = 0;
+
+ _lines[0]._len = _numChars;
+ _lines[0]._newLine = forced;
+
+ for (int i = _scrollBack - 1; i > 0; i--) {
+ memcpy(&_lines[i], &_lines[i - 1], sizeof(TextBufferRow));
+ if (i < _height)
+ touch(i);
+ }
+
+ if (_radjn)
+ _radjn--;
+ if (_radjn == 0)
+ _radjw = 0;
+ if (_ladjn)
+ _ladjn--;
+ if (_ladjn == 0)
+ _ladjw = 0;
+
+ touch(0);
+ _lines[0]._len = 0;
+ _lines[0]._newLine = 0;
+ _lines[0]._lm = _ladjw;
+ _lines[0]._rm = _radjw;
+ _lines[0]._lPic = nullptr;
+ _lines[0]._rPic = nullptr;
+ _lines[0]._lHyper = 0;
+ _lines[0]._rHyper = 0;
+ memset(_chars, ' ', TBLINELEN * 4);
+ memset(_attrs, 0, TBLINELEN * sizeof(Attributes));
+
+ _numChars = 0;
+
+ touchScroll();
+
+}
+
+void TextBufferWindow::scrollResize() {
+ int i;
+
+ _lines.clear();
+ _lines.resize(_scrollBack + SCROLLBACK);
+
+ _chars = _lines[0]._chars;
+ _attrs = _lines[0]._attrs;
+
+ for (i = _scrollBack; i < (_scrollBack + SCROLLBACK); i++)
+ {
+ _lines[i]._dirty = 0;
+ _lines[i]._repaint = 0;
+ _lines[i]._lm = 0;
+ _lines[i]._rm = 0;
+ _lines[i]._lPic = 0;
+ _lines[i]._rPic = 0;
+ _lines[i]._lHyper = 0;
+ _lines[i]._rHyper = 0;
+ _lines[i]._len = 0;
+ _lines[i]._newLine = 0;
+ memset(_lines[i]._chars, ' ', sizeof _lines[i]._chars);
+ memset(_lines[i]._attrs, 0, sizeof _lines[i]._attrs);
+ }
+
+ _scrollBack += SCROLLBACK;
+}
+
+int TextBufferWindow::calcWidth(glui32 *chars, Attributes *attrs, int startchar,
+ int numChars, int spw) {
+ int w = 0;
+ int a, b;
+
+ a = startchar;
+ for (b = startchar; b < numChars; b++) {
+ if (attrs[a] == attrs[b]) {
+ w += stringWidthUni(attrs[a].attrFont(_styles),
+ chars + a, b - a, spw);
+ a = b;
+ }
+ }
+
+ w += stringWidthUni(attrs[a].attrFont(_styles),
+ chars + a, b - a, spw);
+
+ return w;
+}
+
+void TextBufferWindow::copyTextToClipboard(const glui32 *text, size_t len) {
+ // TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextBufferWindow::TextBufferRow::TextBufferRow() : _len(0), _newLine(0), _dirty(false),
+ _repaint(false), _lPic(nullptr), _rPic(nullptr), _lHyper(0), _rHyper(0),
+ _lm(0), _rm(0) {
+ Common::fill(&_chars[0], &_chars[TBLINELEN], 0);
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index ebba2b4..2a1c1f7 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -25,47 +25,72 @@
#include "gargoyle/windows.h"
#include "gargoyle/picture.h"
+#include "gargoyle/speech.h"
namespace Gargoyle {
/**
* Text Buffer window
*/
-class TextBufferWindow : public Window {
+class TextBufferWindow : public Window, Speech {
/**
* Structure for a row within the window
*/
struct TextBufferRow {
- Common::Array<uint32> chars;
- Common::Array<Attributes> attr;
- int len, newline;
- bool dirty, repaint;
- Picture *lpic, *rpic;
- glui32 lhyper, rhyper;
- int lm, rm;
+ glui32 _chars[TBLINELEN];
+ Attributes _attrs[TBLINELEN];
+ int _len, _newLine;
+ bool _dirty, _repaint;
+ Picture *_lPic, *_rPic;
+ glui32 _lHyper, _rHyper;
+ int _lm, _rm;
/**
* Constructor
*/
TextBufferRow();
-
- /**
- * Resize the row
- */
- void resize(size_t newSize);
};
typedef Common::Array<TextBufferRow> TextBufferRows;
private:
void reflow();
void touchScroll();
bool putPicture(Picture *pic, glui32 align, glui32 linkval);
+
+ /**
+ * @remarks Only for input text
+ */
+ void putText(const char *buf, int len, int pos, int oldlen);
+
+ /**
+ * @remarks Only for input text
+ */
void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
- void flowBreak();
+
+ bool flowBreak();
+
+ void acceptLine(glui32 keycode);
+
+ /**
+ * Return true if a following quotation mark should be an opening mark,
+ * false if it should be a closing mark. Opening quotation marks will
+ * appear following an open parenthesis, open square bracket, or
+ * whitespace.
+ */
+ bool leftquote(glui32 c);
/**
* Mark a given text row as modified
*/
void touch(int line);
+
+ void scrollOneLine(bool forced);
+ void scrollResize();
+ int calcWidth(glui32 *chars, Attributes *attrs, int startchar, int numchars, int spw);
+
+ /**
+ * Copy the passed text to the clipboard
+ */
+ void copyTextToClipboard(const glui32 *text, size_t len);
public:
int _width, _height;
int _spaced;
@@ -106,7 +131,7 @@ public:
glui32 *_lineTerminators;
/* style hints and settings */
- WindowStyle styles[style_NUMSTYLES];
+ WindowStyle _styles[style_NUMSTYLES];
/* for copy selection */
glui32 *_copyBuf;
@@ -143,14 +168,14 @@ public:
virtual bool unputCharUni(uint32 ch) override;
/**
- * Move the cursor
+ * Clear the window
*/
- virtual void moveCursor(const Common::Point &newPos) override;
+ virtual void clear() override;
/**
- * Clear the window
+ * Click the window
*/
- virtual void clear() override;
+ virtual void click(const Common::Point &newPos) override;
/**
* Prepare for inputing a line
@@ -176,6 +201,15 @@ public:
* Redraw the window
*/
virtual void redraw() override;
+
+ virtual glui32 imageDraw(glui32 image, glui32 align, bool scaled, glui32 width = 0,
+ glui32 height = 0) override;
+
+ virtual void acceptReadLine(glui32 arg) override;
+
+ virtual void acceptReadChar(glui32 arg) override;
+
+ int acceptScroll(glui32 arg);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 17bb222..91331d7 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -23,6 +23,7 @@
#include "gargoyle/window_text_grid.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/window_mask.h"
namespace Gargoyle {
@@ -203,7 +204,7 @@ void TextGridWindow::click(const Common::Point &newPos) {
}
if (_hyperRequest) {
- glui32 linkval = _windows->getHyperlink(newPos);
+ glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
if (linkval)
{
g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
@@ -588,7 +589,7 @@ void TextGridWindow::redraw() {
y = y0 + i * g_conf->_leading;
/* clear any stored hyperlink coordinates */
- _windows->setHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
+ g_vm->_windowMask->putHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
a = 0;
for (b = 0; b < _width; b++) {
@@ -610,7 +611,7 @@ void TextGridWindow::redraw() {
if (link) {
_windows->drawRect(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle, g_conf->_linkColor);
- _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
x += w;
a = b;
@@ -634,7 +635,7 @@ void TextGridWindow::redraw() {
if (link) {
_windows->drawRect(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle, g_conf->_linkColor);
- _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
}
}
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 0cf6d5e..2c5a0a8 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -56,17 +56,10 @@ private:
*/
void touch(int line);
- void acceptReadChar(glui32 arg);
-
/**
* Return or enter, during line input. Ends line input.
*/
void acceptLine(glui32 keycode);
-
- /**
- * Any regular key, during line input.
- */
- void acceptReadLine(glui32 arg);
public:
int _width, _height;
TextGridRows _lines;
@@ -158,6 +151,10 @@ public:
* Redraw the window
*/
virtual void redraw() override;
+
+ virtual void acceptReadLine(glui32 arg) override;
+
+ virtual void acceptReadChar(glui32 arg) override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index cf9b7de..c1c28e5 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -37,6 +37,8 @@ bool Windows::_overrideReverse;
bool Windows::_overrideFgSet;
bool Windows::_overrideBgSet;
bool Windows::_forceRedraw;
+bool Windows::_claimSelect;
+bool Windows::_moreFocus;
int Windows::_overrideFgVal;
int Windows::_overrideBgVal;
int Windows::_zcolor_fg;
@@ -48,14 +50,15 @@ byte Windows::_zcolor_Bright[3];
/*--------------------------------------------------------------------------*/
-Windows::Windows(Graphics::Screen *screen) :
- _screen(screen), _moreFocus(false), _windowList(nullptr),
- _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr), _claimSelect(0) {
+Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullptr),
+ _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr) {
_mask = new WindowMask();
_overrideReverse = false;
_overrideFgSet = false;
_overrideBgSet = false;
_forceRedraw = true;
+ _claimSelect = false;
+ _moreFocus = false;
_overrideFgVal = 0;
_overrideBgVal = 0;
_zcolor_fg = _zcolor_bg = 0;
@@ -234,6 +237,10 @@ void Windows::redraw() {
// TODO: gli_windows_redraw
}
+void Windows::redrawRect(const Common::Rect &r) {
+ // TODO: gli_redraw_rect
+}
+
void Windows::repaint(const Common::Rect &box) {
// TODO
}
@@ -291,7 +298,7 @@ Window::Window(Windows *windows, glui32 rock) : _windows(windows), _rock(rock),
_type(0), _parent(nullptr), _next(nullptr), _prev(nullptr), _yAdj(0),
_lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
_mouseRequest(0), _hyperRequest(0), _moreRequest(0), _scrollRequest(0), _imageLoaded(0),
- _echoLineInput(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
+ _echoLineInputBase(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
_attr.fgset = 0;
_attr.bgset = 0;
_attr.reverse = 0;
@@ -337,6 +344,10 @@ void Window::cancelLineEvent(Event *ev) {
g_vm->_events->clearEvent(ev);
}
+void Window::moveCursor(const Common::Point &newPos) {
+ warning("moveCursor: not a TextGrid window");
+}
+
void Window::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
warning("requestLineEvent: window does not support keyboard input");
}
@@ -353,6 +364,14 @@ void Window::redraw() {
}
}
+void Window::acceptReadLine(glui32 arg) {
+ warning("acceptReadLine:: window does not support keyboard input");
+}
+
+void Window::acceptReadChar(glui32 arg) {
+ warning("acceptReadChar:: window does not support keyboard input");
+}
+
bool Window::checkTerminator(glui32 ch) {
if (ch == keycode_Escape)
return true;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 5e6374c..3f5c0bc 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -85,8 +85,6 @@ private:
Window * _windowList; ///< List of all windows
Window *_rootWin; ///< The topmost window
Window *_focusWin; ///< The window selected by the player
- bool _moreFocus;
- bool _claimSelect;
WindowMask *_mask;
private:
/**
@@ -108,6 +106,8 @@ public:
static bool _overrideFgSet;
static bool _overrideBgSet;
static bool _forceRedraw;
+ static bool _claimSelect;
+ static bool _moreFocus;
static int _overrideFgVal;
static int _overrideBgVal;
static int _zcolor_fg, _zcolor_bg;
@@ -157,6 +157,8 @@ public:
void redraw();
+ void redrawRect(const Common::Rect &r);
+
/**
* Repaint an area of the windows
*/
@@ -176,18 +178,6 @@ public:
* Returns the end point of window iteration
*/
iterator end() { return iterator(nullptr); }
-
- /**
- * Gets a hyperlink
- */
- glui32 getHyperlink(const Common::Point &pos) { return _mask->getHyperlink(pos); }
-
- /**
- * Sets a hyperlink
- */
- void setHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1) {
- return _mask->putHyperlink(linkval, x0, y0, x1, y1);
- }
};
/**
@@ -278,7 +268,7 @@ public:
int _scrollRequest;
int _imageLoaded;
- glui32 _echoLineInput;
+ glui32 _echoLineInputBase;
glui32 *_lineTerminatorsBase;
glui32 _termCt;
@@ -323,7 +313,7 @@ public:
/**
* Move the cursor
*/
- virtual void moveCursor(const Common::Point &newPos) {}
+ virtual void moveCursor(const Common::Point &newPos);
/**
* Clear the window
@@ -364,6 +354,15 @@ public:
* Redraw the window
*/
virtual void redraw();
+
+ virtual glui32 imageDraw(glui32 image, glui32 align, bool scaled, glui32 width = 0,
+ glui32 height = 0) { return false; }
+
+ virtual void acceptReadLine(glui32 arg);
+
+ virtual void acceptReadChar(glui32 arg);
+
+ int acceptScroll(glui32 arg);
};
typedef Window *winid_t;
Commit: 4ddda5cebc3d0f11cc10746e4dcac5bd0e1a7b19
https://github.com/scummvm/scummvm/commit/4ddda5cebc3d0f11cc10746e4dcac5bd0e1a7b19
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Windows focus / iteration
Changed paths:
engines/gargoyle/draw.cpp
engines/gargoyle/draw.h
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_pair.cpp
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/draw.cpp b/engines/gargoyle/draw.cpp
index f16d1a5..64c9a10 100644
--- a/engines/gargoyle/draw.cpp
+++ b/engines/gargoyle/draw.cpp
@@ -48,4 +48,8 @@ void Draw::drawCaret(const Common::Point &pos) {
// TODO
}
+void Draw::fillArea(const byte *rgb) {
+ // TODO: gli_draw_clear
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/draw.h b/engines/gargoyle/draw.h
index e0ec133..f60d573 100644
--- a/engines/gargoyle/draw.h
+++ b/engines/gargoyle/draw.h
@@ -39,6 +39,8 @@ protected:
int stringWidthUni(int fidx, const glui32 *s, int n, int spw);
void drawCaret(const Common::Point &pos);
+
+ void fillArea(const byte *rgb);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index 732686d..feddf4e 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -83,6 +83,8 @@ void GraphicsWindow::touch() {
}
void GraphicsWindow::redraw() {
+ Window::redraw();
+
// TODO
}
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
index af3ed4c..7a11597 100644
--- a/engines/gargoyle/window_pair.cpp
+++ b/engines/gargoyle/window_pair.cpp
@@ -119,6 +119,8 @@ void PairWindow::rearrange(const Common::Rect &box) {
}
void PairWindow::redraw() {
+ Window::redraw();
+
// TODO
}
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 3df2e5c..99bef25 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -228,7 +228,7 @@ void TextBufferWindow::reflow() {
}
void TextBufferWindow::touchScroll() {
- _windows->clearSelection();
+ g_vm->_windowMask->clearSelection();
_windows->repaint(_bbox);
for (int i = 0; i < _scrollMax; i++)
@@ -370,7 +370,7 @@ void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldle
void TextBufferWindow::touch(int line) {
int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
_lines[line]._dirty = 1;
- _windows->clearSelection();
+ g_vm->_windowMask->clearSelection();
_windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
}
@@ -796,7 +796,10 @@ void TextBufferWindow::redraw() {
int selbuf, selrow, selchar, sx0, sx1, selleft, selright;
int tx, tsc, tsw, lsc, rsc;
+ Window::redraw();
+
_lines[0]._len = _numChars;
+ sx0 = sx1 = selleft = selright = 0;
ln = new TextBufferRow();
if (!ln)
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 91331d7..c20bafe 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -577,6 +577,8 @@ void TextGridWindow::redraw() {
int font;
byte *fgcolor, *bgcolor;
+ Window::redraw();
+
x0 = _bbox.left;
y0 = _bbox.top;
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index c1c28e5..9c8e22c 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -51,8 +51,7 @@ byte Windows::_zcolor_Bright[3];
/*--------------------------------------------------------------------------*/
Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullptr),
- _rootWin(nullptr), _focusWin(nullptr), _mask(nullptr) {
- _mask = new WindowMask();
+ _rootWin(nullptr), _focusWin(nullptr) {
_overrideReverse = false;
_overrideFgSet = false;
_overrideBgSet = false;
@@ -62,6 +61,7 @@ Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullpt
_overrideFgVal = 0;
_overrideBgVal = 0;
_zcolor_fg = _zcolor_bg = 0;
+ _drawSelect = false;
_zcolor_LightGrey[0] = _zcolor_LightGrey[1] = _zcolor_LightGrey[2] = 181;
_zcolor_Foreground[0] = _zcolor_Foreground[1] = _zcolor_Foreground[2] = 0;
@@ -69,10 +69,6 @@ Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullpt
_zcolor_Bright[0] = _zcolor_Bright[1] = _zcolor_Bright[2] = 0;
}
-Windows::~Windows() {
- delete _mask;
-}
-
Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
glui32 wintype, glui32 rock) {
Window *newwin, *oldparent;
@@ -229,20 +225,30 @@ void Windows::selectionChanged() {
redraw();
}
-void Windows::clearSelection() {
- _mask->clearSelection();
-}
-
void Windows::redraw() {
- // TODO: gli_windows_redraw
+ _claimSelect = false;
+
+ if (_forceRedraw) {
+ repaint(Common::Rect(0, 0, g_conf->_imageW, g_conf->_imageH));
+ fillArea(g_conf->_windowColor);
+ }
+
+ if (_rootWin)
+ _rootWin->redraw();
+
+ if (_moreFocus)
+ refocus(_focusWin);
+
+ _forceRedraw = 0;
}
void Windows::redrawRect(const Common::Rect &r) {
- // TODO: gli_redraw_rect
+ _drawSelect = true;
+ repaint(r);
}
void Windows::repaint(const Common::Rect &box) {
- // TODO
+ // No implementation
}
void Windows::drawRect(int x0, int y0, int w, int h, const byte *rgb) {
@@ -260,36 +266,52 @@ byte *Windows::rgbShift(byte *rgb) {
/*--------------------------------------------------------------------------*/
Windows::iterator &Windows::iterator::operator++() {
- if (!_current)
- return *this;
+ _current = _windows->iterateTreeOrder(_current);
+ return *this;
+}
+
+void Windows::refocus(Window *win) {
+ Window *focus = win;
+ do {
+ if (focus && focus->_moreRequest) {
+ _focusWin = focus;
+ return;
+ }
- PairWindow *pairWin = dynamic_cast<PairWindow *>(_current);
+ focus = iterateTreeOrder(focus);
+ } while (focus != win);
+
+ _moreFocus = false;
+}
+Window *Windows::iterateTreeOrder(Window *win) {
+ if (!win)
+ return _rootWin;
+
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(win);
if (pairWin) {
- _current = !pairWin->_backward ? pairWin->_child1 : pairWin->_child2;
+ if (!pairWin->_backward)
+ return pairWin->_child1;
+ else
+ return pairWin->_child2;
} else {
- while (_current->_parent) {
- pairWin = dynamic_cast<PairWindow *>(_current->_parent);
+ while (win->_parent) {
+ pairWin = dynamic_cast<PairWindow *>(win->_parent);
+ assert(pairWin);
if (!pairWin->_backward) {
- if (_current == pairWin->_child1) {
- _current = pairWin->_child2;
- return *this;
- }
+ if (win == pairWin->_child1)
+ return pairWin->_child2;
} else {
- if (_current == pairWin->_child2) {
- _current = pairWin->_child1;
- return *this;
- }
+ if (win == pairWin->_child2)
+ return pairWin->_child1;
}
- _current = pairWin;
+ win = pairWin;
}
- _current = nullptr;
+ return nullptr;
}
-
- return *this;
}
/*--------------------------------------------------------------------------*/
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 3f5c0bc..1f15720 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -48,17 +48,18 @@ class PairWindow;
/**
* Main windows manager
*/
-class Windows {
+class Windows : public Draw {
friend class Window;
public:
class iterator {
private:
+ Windows *_windows;
Window *_current;
public:
/**
* Constructor
*/
- iterator(Window *start) : _current(start) {}
+ iterator(Windows *windows, Window *start) : _windows(windows), _current(start) {}
/**
* Dereference
@@ -80,12 +81,13 @@ public:
*/
bool operator!=(const iterator &i) { return _current != i._current; }
};
+ friend class iterator;
private:
Graphics::Screen *_screen;
Window * _windowList; ///< List of all windows
Window *_rootWin; ///< The topmost window
Window *_focusWin; ///< The window selected by the player
- WindowMask *_mask;
+ bool _drawSelect;
private:
/**
* Create a new window
@@ -101,6 +103,10 @@ private:
* Rearrange windows
*/
void rearrange();
+
+ void refocus(Window *win);
+
+ Window *iterateTreeOrder(Window *win);
public:
static bool _overrideReverse;
static bool _overrideFgSet;
@@ -124,11 +130,6 @@ public:
Windows(Graphics::Screen *screen);
/**
- * Destructor
- */
- ~Windows();
-
- /**
* Open a new window
*/
Window *windowOpen(Window *splitwin, glui32 method, glui32 size,
@@ -149,8 +150,6 @@ public:
*/
void setFocus(Window *win) { _focusWin = win; }
- void clearSelection();
-
void selectionChanged();
void clearClaimSelect() { _claimSelect = false; }
@@ -172,12 +171,12 @@ public:
/**
* Get an iterator that will move over the tree
*/
- iterator begin() { return iterator(_windowList); }
+ iterator begin() { return iterator(this, _windowList); }
/**
* Returns the end point of window iteration
*/
- iterator end() { return iterator(nullptr); }
+ iterator end() { return iterator(this, nullptr); }
};
/**
Commit: 6939fabbfb9ce63c10f1fcd8cd3c0b7f66ff9bb9
https://github.com/scummvm/scummvm/commit/6939fabbfb9ce63c10f1fcd8cd3c0b7f66ff9bb9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fleshed out graphics window
Changed paths:
engines/gargoyle/draw.cpp
engines/gargoyle/draw.h
engines/gargoyle/gargoyle.h
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/draw.cpp b/engines/gargoyle/draw.cpp
index 64c9a10..59acb96 100644
--- a/engines/gargoyle/draw.cpp
+++ b/engines/gargoyle/draw.cpp
@@ -52,4 +52,8 @@ void Draw::fillArea(const byte *rgb) {
// TODO: gli_draw_clear
}
+void Draw::drawRect(int x0, int y0, int w, int h, const byte *rgb) {
+ // TODO: gli_draw_rect
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/draw.h b/engines/gargoyle/draw.h
index f60d573..7b74f45 100644
--- a/engines/gargoyle/draw.h
+++ b/engines/gargoyle/draw.h
@@ -41,6 +41,8 @@ protected:
void drawCaret(const Common::Point &pos);
void fillArea(const byte *rgb);
+
+ void drawRect(int x0, int y0, int w, int h, const byte *rgb);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index b99b7b4..a8af85a 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -77,7 +77,6 @@ private:
void initialize();
protected:
const GargoyleGameDescription *_gameDescription;
- Graphics::Screen *_screen;
Common::RandomSource _random;
int _loadSaveSlot;
@@ -97,6 +96,7 @@ public:
Conf *_conf;
Events *_events;
PicList *_picList;
+ Graphics::Screen *_screen;
Streams *_streams;
Windows *_windows;
WindowMask *_windowMask;
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index feddf4e..bb002bd 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/window_graphics.h"
+#include "gargoyle/gargoyle.h"
namespace Gargoyle {
@@ -85,12 +86,164 @@ void GraphicsWindow::touch() {
void GraphicsWindow::redraw() {
Window::redraw();
- // TODO
+ if (_dirty || Windows::_forceRedraw) {
+ _dirty = 0;
+
+ if (_surface)
+ g_vm->_screen->blitFrom(*_surface, Common::Point(_bbox.left, _bbox.top));
+ }
+}
+
+glui32 GraphicsWindow::drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int scale,
+ glui32 imagewidth, glui32 imageheight) {
+ Picture *pic = Picture::load(image);
+ glui32 hyperlink = _attr.hyper;
+
+ if (!pic)
+ return false;
+
+ if (!_imageLoaded) {
+ g_vm->_picList->increment();
+ _imageLoaded = true;
+ }
+
+ if (!scale) {
+ imagewidth = pic->w;
+ imageheight = pic->h;
+ }
+
+ drawPicture(pic, xpos, ypos, imagewidth, imageheight, hyperlink);
+ touch();
+
+ return true;
}
-glui32 GraphicsWindow::imageDraw(glui32 image, glui32 align, bool scaled, glui32 width, glui32 height) {
- // TODO: win_graphics_draw_picture
- return 0;
+void GraphicsWindow::eraseRect(int whole, glsi32 x0, glsi32 y0, glui32 width, glui32 height) {
+ int x1 = x0 + width;
+ int y1 = y0 + height;
+ int x, y;
+ int hx0, hx1, hy0, hy1;
+
+ if (whole) {
+ x0 = 0;
+ y0 = 0;
+ x1 = _w;
+ y1 = _h;
+ }
+
+ if (x0 < 0) x0 = 0;
+ if (y0 < 0) y0 = 0;
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if ((glui32)x0 >= _w) x0 = _w;
+ if ((glui32)y0 >= _h) y0 = _h;
+ if ((glui32)x1 >= _w) x1 = _w;
+ if ((glui32)y1 >= _h) y1 = _h;
+
+ hx0 = _bbox.left + x0;
+ hx1 = _bbox.left + x1;
+ hy0 = _bbox.top + y0;
+ hy1 = _bbox.top + y1;
+
+ /* zero out hyperlinks for these coordinates */
+ g_vm->_windowMask->putHyperlink(0, hx0, hy0, hx1, hy1);
+
+ _surface->fillRect(Common::Rect(x0, y0, x1, y1), MKTAG(_bgnd[0], _bgnd[1], _bgnd[2], 0));
+ touch();
+}
+
+void GraphicsWindow::fillRect(glui32 color, glsi32 x0, glsi32 y0, glui32 width, glui32 height) {
+ unsigned char col[3];
+ int x1 = x0 + width;
+ int y1 = y0 + height;
+ int x, y;
+ int hx0, hx1, hy0, hy1;
+
+ col[0] = (color >> 16) & 0xff;
+ col[1] = (color >> 8) & 0xff;
+ col[2] = (color >> 0) & 0xff;
+
+ if (x0 < 0) x0 = 0;
+ if (y0 < 0) y0 = 0;
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if ((glui32)x0 > _w) x0 = _w;
+ if ((glui32)y0 > _h) y0 = _h;
+ if ((glui32)x1 > _w) x1 = _w;
+ if ((glui32)y1 > _h) y1 = _h;
+
+ hx0 = _bbox.left + x0;
+ hx1 = _bbox.left + x1;
+ hy0 = _bbox.top + y0;
+ hy1 = _bbox.top + y1;
+
+ /* zero out hyperlinks for these coordinates */
+ g_vm->_windowMask->putHyperlink(0, hx0, hy0, hx1, hy1);
+
+ _surface->fillRect(Common::Rect(x0, y0, x1, y1), MKTAG(col[0], col[1], col[2], 0));
+ touch();
+}
+
+void GraphicsWindow::setBackgroundColor(glui32 color) {
+ _bgnd[0] = (color >> 16) & 0xff;
+ _bgnd[1] = (color >> 8) & 0xff;
+ _bgnd[2] = (color >> 0) & 0xff;
+}
+
+void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int height, glui32 linkval) {
+ unsigned char *sp, *dp;
+ int dx1, dy1, x1, y1, sx0, sy0, sx1, sy1;
+ int x, y, w, h;
+ int hx0, hx1, hy0, hy1;
+
+ if (width != src->w || height != src->h)
+ {
+ src = src->scale(width, height);
+ if (!src)
+ return;
+ }
+
+ sx0 = 0;
+ sy0 = 0;
+ sx1 = src->w;
+ sy1 = src->h;
+ dx1 = _w;
+ dy1 = _h;
+
+ x1 = x0 + src->w;
+ y1 = y0 + src->h;
+
+ if (x1 <= 0 || x0 >= dx1) return;
+ if (y1 <= 0 || y0 >= dy1) return;
+ if (x0 < 0) {
+ sx0 -= x0;
+ x0 = 0;
+ }
+ if (y0 < 0) {
+ sy0 -= y0;
+ y0 = 0;
+ }
+ if (x1 > dx1) {
+ sx1 += dx1 - x1;
+ x1 = dx1;
+ }
+ if (y1 > dy1) {
+ sy1 += dy1 - y1;
+ y1 = dy1;
+ }
+
+ hx0 = _bbox.left + x0;
+ hx1 = _bbox.left + x1;
+ hy0 = _bbox.top + y0;
+ hy1 = _bbox.top + y1;
+
+ /* zero out or set hyperlink for these coordinates */
+ g_vm->_windowMask->putHyperlink(linkval, hx0, hy0, hx1, hy1);
+
+ w = sx1 - sx0;
+ h = sy1 - sy0;
+
+ _surface->blitFrom(*g_vm->_screen, Common::Rect(sx0, sy0, sx0 + w, sy0 + h), Common::Point(0, 0));
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index b0f53fa..8e97b56 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -34,6 +34,11 @@ namespace Gargoyle {
class GraphicsWindow : public Window {
private:
void touch();
+
+ void eraseRect(int whole, glsi32 x0, glsi32 y0, glui32 width, glui32 height);
+ void fillRect(glui32 color, glsi32 x0, glsi32 y0, glui32 width, glui32 height);
+ void setBackgroundColor(glui32 color);
+ void drawPicture(Picture *src, int x0, int y0, int width, int height, glui32 linkval);
public:
unsigned char _bgnd[3];
bool _dirty;
@@ -77,8 +82,8 @@ public:
*/
virtual void redraw() override;
- virtual glui32 imageDraw(glui32 image, glui32 align, bool scaled, glui32 width = 0,
- glui32 height = 0) override;
+ glui32 drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int scale,
+ glui32 imagewidth, glui32 imageheight);
/**
* Get the window dimensions
@@ -87,6 +92,14 @@ public:
*w = _w;
*h = _h;
}
+
+ /**
+ * Set the window dimensions
+ */
+ void setSize(glui32 w, glui32 h) {
+ _w = w;
+ _h = h;
+ }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 99bef25..6df3ac4 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -266,7 +266,7 @@ bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
return true;
}
-glui32 TextBufferWindow::imageDraw(glui32 image, glui32 align, bool scaled, glui32 width, glui32 height) {
+glui32 TextBufferWindow::drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height) {
Picture *pic;
glui32 hyperlink;
int error;
@@ -953,7 +953,7 @@ void TextBufferWindow::redraw() {
* fill in background colors
*/
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- _windows->drawRect(x0/GLI_SUBPIX, y,
+ drawRect(x0/GLI_SUBPIX, y,
(x1-x0) / GLI_SUBPIX, g_conf->_leading,
color);
@@ -966,11 +966,11 @@ void TextBufferWindow::redraw() {
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
w = stringWidthUni(font, ln->_chars + a, b - a, spw);
- _windows->drawRect(x/GLI_SUBPIX, y,
+ drawRect(x/GLI_SUBPIX, y,
w/GLI_SUBPIX, g_conf->_leading,
color);
if (link) {
- _windows->drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
w/GLI_SUBPIX + 1, g_conf->_linkStyle,
g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
@@ -985,10 +985,10 @@ void TextBufferWindow::redraw() {
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
w = stringWidthUni(font, ln->_chars + a, b - a, spw);
- _windows->drawRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
+ drawRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
g_conf->_leading, color);
if (link) {
- _windows->drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
w/GLI_SUBPIX + 1, g_conf->_linkStyle,
g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
@@ -998,7 +998,7 @@ void TextBufferWindow::redraw() {
x += w;
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- _windows->drawRect(x/GLI_SUBPIX, y,
+ drawRect(x/GLI_SUBPIX, y,
x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
color);
@@ -1048,7 +1048,7 @@ void TextBufferWindow::redraw() {
x1/GLI_SUBPIX, y + g_conf->_leading);
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- _windows->drawRect(x/GLI_SUBPIX, y,
+ drawRect(x/GLI_SUBPIX, y,
x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
color);
@@ -1142,14 +1142,14 @@ void TextBufferWindow::redraw() {
t0 = t1 = y0;
}
- _windows->drawRect(x0+1, y0, x1-x0-2, y1-y0, g_conf->_scrollBg);
- _windows->drawRect(x0+1, t0, x1-x0-2, t1-t0, g_conf->_scrollFg);
+ drawRect(x0+1, y0, x1-x0-2, y1-y0, g_conf->_scrollBg);
+ drawRect(x0+1, t0, x1-x0-2, t1-t0, g_conf->_scrollFg);
for (i = 0; i < g_conf->_scrollWidth / 2 + 1; i++) {
- _windows->drawRect(x0+g_conf->_scrollWidth/2-i,
+ drawRect(x0+g_conf->_scrollWidth/2-i,
y0 - g_conf->_scrollWidth/2 + i,
i*2, 1, g_conf->_scrollFg);
- _windows->drawRect(x0+g_conf->_scrollWidth/2-i,
+ drawRect(x0+g_conf->_scrollWidth/2-i,
y1 + g_conf->_scrollWidth/2 - i,
i*2, 1, g_conf->_scrollFg);
}
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 2a1c1f7..4741877 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -202,14 +202,13 @@ public:
*/
virtual void redraw() override;
- virtual glui32 imageDraw(glui32 image, glui32 align, bool scaled, glui32 width = 0,
- glui32 height = 0) override;
-
virtual void acceptReadLine(glui32 arg) override;
virtual void acceptReadChar(glui32 arg) override;
int acceptScroll(glui32 arg);
+
+ glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index c20bafe..483d556 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -601,7 +601,7 @@ void TextGridWindow::redraw() {
fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
bgcolor = ln->_attrs[a].attrBg(styles);
w = (b - a) * g_conf->_cellW;
- _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+ drawRect(x, y, w, g_conf->_leading, bgcolor);
o = x;
for (k = a; k < b; k++) {
@@ -611,7 +611,7 @@ void TextGridWindow::redraw() {
o += g_conf->_cellW;
}
if (link) {
- _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ drawRect(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle, g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
@@ -625,7 +625,7 @@ void TextGridWindow::redraw() {
bgcolor = ln->_attrs[a].attrBg(styles);
w = (b - a) * g_conf->_cellW;
w += _bbox.right - (x + w);
- _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+ drawRect(x, y, w, g_conf->_leading, bgcolor);
o = x;
for (k = a; k < b; k++) {
@@ -635,7 +635,7 @@ void TextGridWindow::redraw() {
o += g_conf->_cellW;
}
if (link) {
- _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ drawRect(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle, g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 9c8e22c..0dc500e 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -251,10 +251,6 @@ void Windows::repaint(const Common::Rect &box) {
// No implementation
}
-void Windows::drawRect(int x0, int y0, int w, int h, const byte *rgb) {
- // TODO
-}
-
byte *Windows::rgbShift(byte *rgb) {
_zcolor_Bright[0] = (rgb[0] + 0x30) < 0xff ? (rgb[0] + 0x30) : 0xff;
_zcolor_Bright[1] = (rgb[1] + 0x30) < 0xff ? (rgb[1] + 0x30) : 0xff;
@@ -403,6 +399,21 @@ bool Window::checkTerminator(glui32 ch) {
return false;
}
+bool Window::imageDraw(glui32 image, glui32 align, glsi32 val1, glsi32 val2) {
+ if (!g_conf->_graphics)
+ return false;
+
+ TextBufferWindow *bufWin = dynamic_cast<TextBufferWindow *>(this);
+ GraphicsWindow *graWin = dynamic_cast<GraphicsWindow *>(this);
+
+ if (bufWin)
+ return bufWin->drawPicture(image, val1, false, 0, 0);
+ if (graWin)
+ return graWin->drawPicture(image, val1, val2, false, 0, 0);
+
+ return false;
+}
+
/*--------------------------------------------------------------------------*/
BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 1f15720..9092ea4 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -164,11 +164,6 @@ public:
void repaint(const Common::Rect &box);
/**
- * Draw an area of the windows
- */
- void drawRect(int x0, int y0, int w, int h, const byte *rgb);
-
- /**
* Get an iterator that will move over the tree
*/
iterator begin() { return iterator(this, _windowList); }
@@ -354,8 +349,9 @@ public:
*/
virtual void redraw();
- virtual glui32 imageDraw(glui32 image, glui32 align, bool scaled, glui32 width = 0,
- glui32 height = 0) { return false; }
+ bool imageDraw(glui32 image, glui32 align, glsi32 val1, glsi32 val2);
+
+ virtual glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height) { return false; }
virtual void acceptReadLine(glui32 arg);
Commit: fdfb1a55028400c976a7b0aa2df2e8cee0428b7d
https://github.com/scummvm/scummvm/commit/fdfb1a55028400c976a7b0aa2df2e8cee0428b7d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Move Draw class into new Screen class
Changed paths:
A engines/gargoyle/screen.cpp
A engines/gargoyle/screen.h
R engines/gargoyle/draw.cpp
R engines/gargoyle/draw.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/module.mk
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/draw.cpp b/engines/gargoyle/draw.cpp
deleted file mode 100644
index 59acb96..0000000
--- a/engines/gargoyle/draw.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/draw.h"
-
-namespace Gargoyle {
-
-int Draw::drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-int Draw::drawStringUni(int x, int y, int fidx, const byte *rgb, const glui32 *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-int Draw::stringWidth(int fidx, const char *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-int Draw::stringWidthUni(int fidx, const glui32 *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-void Draw::drawCaret(const Common::Point &pos) {
- // TODO
-}
-
-void Draw::fillArea(const byte *rgb) {
- // TODO: gli_draw_clear
-}
-
-void Draw::drawRect(int x0, int y0, int w, int h, const byte *rgb) {
- // TODO: gli_draw_rect
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/draw.h b/engines/gargoyle/draw.h
deleted file mode 100644
index 7b74f45..0000000
--- a/engines/gargoyle/draw.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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 GARGOYLE_DRAW_H
-#define GARGOYLE_DRAW_H
-
-#include "common/rect.h"
-#include "gargoyle/glk_types.h"
-
-namespace Gargoyle {
-
-class Draw {
-protected:
- int drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw);
-
- int drawStringUni(int x, int y, int fidx, const byte *rgb, const glui32 *s, int n, int spw);
-
- int stringWidth(int fidx, const char *s, int n, int spw);
-
- int stringWidthUni(int fidx, const glui32 *s, int n, int spw);
-
- void drawCaret(const Common::Point &pos);
-
- void fillArea(const byte *rgb);
-
- void drawRect(int x0, int y0, int w, int h, const byte *rgb);
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 37df6d1..1a8cc61 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -32,6 +32,7 @@
#include "gargoyle/conf.h"
#include "gargoyle/events.h"
#include "gargoyle/picture.h"
+#include "gargoyle/screen.h"
#include "gargoyle/streams.h"
#include "gargoyle/windows.h"
#include "gargoyle/window_mask.h"
@@ -66,7 +67,7 @@ void GargoyleEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphics(640, 480, false);
- _screen = new Graphics::Screen();
+ _screen = new Screen();
_conf = new Conf();
_events = new Events();
_picList = new PicList();
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index a8af85a..c34538b 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -29,7 +29,6 @@
#include "common/serializer.h"
#include "engines/advancedDetector.h"
#include "engines/engine.h"
-#include "graphics/screen.h"
#include "gargoyle/glk_types.h"
namespace Gargoyle {
@@ -37,9 +36,10 @@ namespace Gargoyle {
class Conf;
class Events;
class PicList;
+class Screen;
+class Streams;
class Windows;
class WindowMask;
-class Streams;
enum InterpreterType {
INTERPRETER_SCOTT
@@ -96,7 +96,7 @@ public:
Conf *_conf;
Events *_events;
PicList *_picList;
- Graphics::Screen *_screen;
+ Screen *_screen;
Streams *_streams;
Windows *_windows;
WindowMask *_windowMask;
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index e684ff9..e2584b4 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -3,12 +3,12 @@ MODULE := engines/gargoyle
MODULE_OBJS := \
conf.o \
detection.o \
- draw.o \
events.o \
fonts.o \
gargoyle.o \
glk.o \
picture.o \
+ screen.o \
streams.o \
string.o \
windows.o \
diff --git a/engines/gargoyle/screen.cpp b/engines/gargoyle/screen.cpp
new file mode 100644
index 0000000..dad3e6d
--- /dev/null
+++ b/engines/gargoyle/screen.cpp
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/screen.h"
+
+namespace Gargoyle {
+
+void Screen::fill(const byte *rgb) {
+ uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ clear(color);
+}
+
+void Screen::fillRect(uint x, uint y, uint w, uint h, const byte *rgb) {
+ uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ Graphics::Screen::fillRect(Common::Rect(x, y, x + w, y + h), color);
+}
+
+int Screen::drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Screen::drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Screen::stringWidth(int fidx, const char *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Screen::stringWidthUni(int fidx, const uint32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+void Screen::drawCaret(const Common::Point &pos) {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
new file mode 100644
index 0000000..ce9088d
--- /dev/null
+++ b/engines/gargoyle/screen.h
@@ -0,0 +1,55 @@
+/* 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 GARGOYLE_DRAW_H
+#define GARGOYLE_DRAW_H
+
+#include "graphics/screen.h"
+
+namespace Gargoyle {
+
+class Screen : public Graphics::Screen {
+public:
+ /**
+ * Fills the screen with a given rgb color
+ */
+ void fill(const byte *rgb);
+
+ /**
+ * Fill a given area of the screen with an rgb color
+ */
+ void fillRect(uint x, uint y, uint w, uint h, const byte *rgb);
+
+ int drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw);
+
+ int drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw);
+
+ int stringWidth(int fidx, const char *s, int n, int spw);
+
+ int stringWidthUni(int fidx, const uint32 *s, int n, int spw);
+
+ void drawCaret(const Common::Point &pos);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index bb002bd..caf51a2 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -22,6 +22,7 @@
#include "gargoyle/window_graphics.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/screen.h"
namespace Gargoyle {
@@ -84,13 +85,14 @@ void GraphicsWindow::touch() {
}
void GraphicsWindow::redraw() {
+ Screen &screen = *g_vm->_screen;
Window::redraw();
if (_dirty || Windows::_forceRedraw) {
_dirty = 0;
if (_surface)
- g_vm->_screen->blitFrom(*_surface, Common::Point(_bbox.left, _bbox.top));
+ screen.blitFrom(*_surface, Common::Point(_bbox.left, _bbox.top));
}
}
@@ -121,7 +123,6 @@ glui32 GraphicsWindow::drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int s
void GraphicsWindow::eraseRect(int whole, glsi32 x0, glsi32 y0, glui32 width, glui32 height) {
int x1 = x0 + width;
int y1 = y0 + height;
- int x, y;
int hx0, hx1, hy0, hy1;
if (whole) {
@@ -156,7 +157,6 @@ void GraphicsWindow::fillRect(glui32 color, glsi32 x0, glsi32 y0, glui32 width,
unsigned char col[3];
int x1 = x0 + width;
int y1 = y0 + height;
- int x, y;
int hx0, hx1, hy0, hy1;
col[0] = (color >> 16) & 0xff;
@@ -191,13 +191,11 @@ void GraphicsWindow::setBackgroundColor(glui32 color) {
}
void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int height, glui32 linkval) {
- unsigned char *sp, *dp;
int dx1, dy1, x1, y1, sx0, sy0, sx1, sy1;
- int x, y, w, h;
int hx0, hx1, hy0, hy1;
+ int w, h;
- if (width != src->w || height != src->h)
- {
+ if (width != src->w || height != src->h) {
src = src->scale(width, height);
if (!src)
return;
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 6df3ac4..b940fe6 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -23,6 +23,7 @@
#include "gargoyle/window_text_buffer.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/screen.h"
#include "gargoyle/string.h"
namespace Gargoyle {
@@ -795,6 +796,7 @@ void TextBufferWindow::redraw() {
int hx0, hx1, hy0, hy1;
int selbuf, selrow, selchar, sx0, sx1, selleft, selright;
int tx, tsc, tsw, lsc, rsc;
+ Screen &screen = *g_vm->_screen;
Window::redraw();
@@ -953,7 +955,7 @@ void TextBufferWindow::redraw() {
* fill in background colors
*/
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- drawRect(x0/GLI_SUBPIX, y,
+ screen.fillRect(x0/GLI_SUBPIX, y,
(x1-x0) / GLI_SUBPIX, g_conf->_leading,
color);
@@ -965,12 +967,12 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
- w = stringWidthUni(font, ln->_chars + a, b - a, spw);
- drawRect(x/GLI_SUBPIX, y,
+ w = screen.stringWidthUni(font, ln->_chars + a, b - a, spw);
+ screen.fillRect(x/GLI_SUBPIX, y,
w/GLI_SUBPIX, g_conf->_leading,
color);
if (link) {
- drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ screen.fillRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
w/GLI_SUBPIX + 1, g_conf->_linkStyle,
g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
@@ -984,11 +986,11 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
- w = stringWidthUni(font, ln->_chars + a, b - a, spw);
- drawRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
+ w = screen.stringWidthUni(font, ln->_chars + a, b - a, spw);
+ screen.fillRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
g_conf->_leading, color);
if (link) {
- drawRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ screen.fillRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
w/GLI_SUBPIX + 1, g_conf->_linkStyle,
g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
@@ -998,7 +1000,7 @@ void TextBufferWindow::redraw() {
x += w;
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- drawRect(x/GLI_SUBPIX, y,
+ screen.fillRect(x/GLI_SUBPIX, y,
x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
color);
@@ -1009,7 +1011,7 @@ void TextBufferWindow::redraw() {
if (_windows->getFocusWindow() == this && i == 0 && (_lineRequest || _lineRequestUni)) {
w = calcWidth(_chars, _attrs, 0, _inCurs, spw);
if (w < pw - g_conf->_caretShape * 2 * GLI_SUBPIX)
- drawCaret(Common::Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
+ screen.drawCaret(Common::Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
}
/*
@@ -1024,7 +1026,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- x = drawStringUni(x, y + g_conf->_baseLine,
+ x = screen.drawStringUni(x, y + g_conf->_baseLine,
font, color, ln->_chars + a, b - a, spw);
a = b;
}
@@ -1032,7 +1034,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- drawStringUni(x, y + g_conf->_baseLine,
+ screen.drawStringUni(x, y + g_conf->_baseLine,
font, color, ln->_chars + a, linelen - a, spw);
}
@@ -1048,11 +1050,11 @@ void TextBufferWindow::redraw() {
x1/GLI_SUBPIX, y + g_conf->_leading);
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- drawRect(x/GLI_SUBPIX, y,
+ screen.fillRect(x/GLI_SUBPIX, y,
x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
color);
- w = stringWidth(g_conf->_moreFont,
+ w = screen.stringWidth(g_conf->_moreFont,
g_conf->_morePrompt.c_str(), g_conf->_morePrompt.size(), -1);
if (g_conf->_moreAlign == 1) /* center */
@@ -1061,7 +1063,7 @@ void TextBufferWindow::redraw() {
x = x1 - SLOP - w;
color = Windows::_overrideFgSet ? g_conf->_moreColor : _fgColor;
- drawString(x, y + g_conf->_baseLine,
+ screen.drawString(x, y + g_conf->_baseLine,
g_conf->_moreFont, color,
g_conf->_morePrompt.c_str(), g_conf->_morePrompt.size(), -1);
y1 = y; /* don't want pictures overdrawing "[more]" */
@@ -1142,14 +1144,14 @@ void TextBufferWindow::redraw() {
t0 = t1 = y0;
}
- drawRect(x0+1, y0, x1-x0-2, y1-y0, g_conf->_scrollBg);
- drawRect(x0+1, t0, x1-x0-2, t1-t0, g_conf->_scrollFg);
+ screen.fillRect(x0+1, y0, x1-x0-2, y1-y0, g_conf->_scrollBg);
+ screen.fillRect(x0+1, t0, x1-x0-2, t1-t0, g_conf->_scrollFg);
for (i = 0; i < g_conf->_scrollWidth / 2 + 1; i++) {
- drawRect(x0+g_conf->_scrollWidth/2-i,
+ screen.fillRect(x0+g_conf->_scrollWidth/2-i,
y0 - g_conf->_scrollWidth/2 + i,
i*2, 1, g_conf->_scrollFg);
- drawRect(x0+g_conf->_scrollWidth/2-i,
+ screen.fillRect(x0+g_conf->_scrollWidth/2-i,
y1 + g_conf->_scrollWidth/2 - i,
i*2, 1, g_conf->_scrollFg);
}
@@ -1608,19 +1610,20 @@ void TextBufferWindow::scrollResize() {
int TextBufferWindow::calcWidth(glui32 *chars, Attributes *attrs, int startchar,
int numChars, int spw) {
+ Screen &screen = *g_vm->_screen;
int w = 0;
int a, b;
a = startchar;
for (b = startchar; b < numChars; b++) {
if (attrs[a] == attrs[b]) {
- w += stringWidthUni(attrs[a].attrFont(_styles),
+ w += screen.stringWidthUni(attrs[a].attrFont(_styles),
chars + a, b - a, spw);
a = b;
}
}
- w += stringWidthUni(attrs[a].attrFont(_styles),
+ w += screen.stringWidthUni(attrs[a].attrFont(_styles),
chars + a, b - a, spw);
return w;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 483d556..bf0f39c 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -23,6 +23,7 @@
#include "gargoyle/window_text_grid.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/screen.h"
#include "gargoyle/window_mask.h"
namespace Gargoyle {
@@ -576,6 +577,7 @@ void TextGridWindow::redraw() {
glui32 link;
int font;
byte *fgcolor, *bgcolor;
+ Screen &screen = *g_vm->_screen;
Window::redraw();
@@ -601,17 +603,17 @@ void TextGridWindow::redraw() {
fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
bgcolor = ln->_attrs[a].attrBg(styles);
w = (b - a) * g_conf->_cellW;
- drawRect(x, y, w, g_conf->_leading, bgcolor);
+ screen.fillRect(x, y, w, g_conf->_leading, bgcolor);
o = x;
for (k = a; k < b; k++) {
- drawStringUni(o * GLI_SUBPIX,
+ screen.drawStringUni(o * GLI_SUBPIX,
y + g_conf->_baseLine, font, fgcolor,
&ln->_chars[k], 1, -1);
o += g_conf->_cellW;
}
if (link) {
- drawRect(x, y + g_conf->_baseLine + 1, w,
+ screen.fillRect(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle, g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
@@ -625,17 +627,17 @@ void TextGridWindow::redraw() {
bgcolor = ln->_attrs[a].attrBg(styles);
w = (b - a) * g_conf->_cellW;
w += _bbox.right - (x + w);
- drawRect(x, y, w, g_conf->_leading, bgcolor);
+ screen.fillRect(x, y, w, g_conf->_leading, bgcolor);
o = x;
for (k = a; k < b; k++) {
- drawStringUni(o * GLI_SUBPIX,
+ screen.drawStringUni(o * GLI_SUBPIX,
y + g_conf->_baseLine, font, fgcolor,
&ln->_chars[k], 1, -1);
o += g_conf->_cellW;
}
if (link) {
- drawRect(x, y + g_conf->_baseLine + 1, w,
+ screen.fillRect(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle, g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 0dc500e..6fb834d 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -27,6 +27,7 @@
#include "gargoyle/window_text_grid.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/screen.h"
#include "gargoyle/streams.h"
#include "common/algorithm.h"
#include "common/textconsole.h"
@@ -230,7 +231,7 @@ void Windows::redraw() {
if (_forceRedraw) {
repaint(Common::Rect(0, 0, g_conf->_imageW, g_conf->_imageH));
- fillArea(g_conf->_windowColor);
+ g_vm->_screen->fill(g_conf->_windowColor);
}
if (_rootWin)
@@ -378,7 +379,7 @@ void Window::redraw() {
if (Windows::_forceRedraw) {
unsigned char *color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
int y0 = _yAdj ? _bbox.top - _yAdj : _bbox.top;
- _windows->drawRect(_bbox.left, y0, _bbox.width(), _bbox.bottom - y0, color);
+ g_vm->_screen->fillRect(_bbox.left, y0, _bbox.width(), _bbox.bottom - y0, color);
}
}
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 9092ea4..ba9cb92 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -27,7 +27,6 @@
#include "common/list.h"
#include "common/rect.h"
#include "graphics/screen.h"
-#include "gargoyle/draw.h"
#include "gargoyle/events.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
@@ -48,7 +47,7 @@ class PairWindow;
/**
* Main windows manager
*/
-class Windows : public Draw {
+class Windows {
friend class Window;
public:
class iterator {
@@ -238,7 +237,7 @@ struct Attributes {
/**
* Window definition
*/
-class Window : public Draw {
+class Window {
public:
Windows *_windows;
glui32 _rock;
Commit: 3d8626081ce6a03d533009e07699b397f70b834b
https://github.com/scummvm/scummvm/commit/3d8626081ce6a03d533009e07699b397f70b834b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added window closing, some structures cleanup
Changed paths:
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk_types.h
engines/gargoyle/streams.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 4ee9470..939e691 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -93,15 +93,16 @@ enum Keycode {
* Event structure
*/
struct Event {
- EvType _type;
- Window *_window;
- uint32 _val1, _val2;
+ EvType type;
+ Window *window;
+ uint32 val1, val2;
/**
* Constructor
*/
- Event() : _type(evtype_None), _window(nullptr), _val1(0), _val2(0) {}
+ Event() : type(evtype_None), window(nullptr), val1(0), val2(0) {}
};
+typedef Event event_t;
class Events {
public:
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index ba62de1..26b8349 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -73,7 +73,13 @@ winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 w
}
void Glk::glk_window_close(winid_t win, stream_result_t *result) {
- // TODO
+ _windows->_forceRedraw = true;
+
+ if (!win) {
+ warning("glk_window_close: invalid ref");
+ } else {
+ _windows->windowClose(win, result);
+ }
}
void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index a25a413..81d05ac 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -220,19 +220,6 @@ enum ImageAlign {
#endif /* GLK_MODULE_IMAGE */
-struct event_struct {
- glui32 type;
- Window *win;
- glui32 val1, val2;
-};
-typedef event_struct event_t;
-
-struct stream_result_struct {
- glui32 readcount;
- glui32 writecount;
-};
-typedef stream_result_struct stream_result_t;
-
#ifdef GLK_MODULE_DATETIME
struct glktimeval_struct {
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 82d6465..51ab484 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -36,6 +36,7 @@ struct StreamResult {
uint32 _readCount;
uint32 _writeCount;
};
+typedef StreamResult stream_result_t;
/**
* Base class for streams
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index b940fe6..a32a64f 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -756,10 +756,10 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
_attr = _origAttr;
- ev->_type = evtype_LineInput;
- ev->_window = this;
- ev->_val1 = len;
- ev->_val2 = 0;
+ ev->type = evtype_LineInput;
+ ev->window = this;
+ ev->val1 = len;
+ ev->val2 = 0;
_lineRequest = false;
_lineRequestUni = false;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index bf0f39c..d9550bf 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -360,10 +360,10 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
_curX = 0;
_attr = _origAttr;
- ev->_type = evtype_LineInput;
- ev->_window = this;
- ev->_val1 = _inLen;
- ev->_val2 = 0;
+ ev->type = evtype_LineInput;
+ ev->window = this;
+ ev->val1 = _inLen;
+ ev->val2 = 0;
_lineRequest = false;
_lineRequestUni = false;
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 6fb834d..42db6f7 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -73,7 +73,7 @@ Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullpt
Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
glui32 wintype, glui32 rock) {
Window *newwin, *oldparent;
- PairWindow *pairwin;
+ PairWindow *pairWin;
glui32 val;
_forceRedraw = true;
@@ -125,24 +125,24 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
if (!splitwin) {
_rootWin = newwin;
} else {
- // create pairwin, with newwin as the key
- pairwin = newPairWindow(method, newwin, size);
- pairwin->_child1 = splitwin;
- pairwin->_child2 = newwin;
+ // create pairWin, with newwin as the key
+ pairWin = newPairWindow(method, newwin, size);
+ pairWin->_child1 = splitwin;
+ pairWin->_child2 = newwin;
- splitwin->_parent = pairwin;
- newwin->_parent = pairwin;
- pairwin->_parent = oldparent;
+ splitwin->_parent = pairWin;
+ newwin->_parent = pairWin;
+ pairWin->_parent = oldparent;
if (oldparent) {
PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
assert(parentWin);
if (parentWin->_child1 == splitwin)
- parentWin->_child1 = pairwin;
+ parentWin->_child1 = pairWin;
else
- parentWin->_child2 = pairwin;
+ parentWin->_child2 = pairWin;
} else {
- _rootWin = pairwin;
+ _rootWin = pairWin;
}
}
@@ -151,6 +151,62 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
return newwin;
}
+void Windows::windowClose(Window *win, StreamResult *result) {
+ if (win == _rootWin || win->_parent == nullptr) {
+ // Close the root window, which means all windows.
+ _rootWin = nullptr;
+
+ // Begin (simpler) closation
+ win->_stream->fillResult(result);
+ win->close(true);
+ } else {
+ // Have to jigger parent
+ Window *sibWin;
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(win->_parent);
+ PairWindow *grandparWin;
+
+ if (win == pairWin->_child1) {
+ sibWin = pairWin->_child2;
+ } else if (win == pairWin->_child2) {
+ sibWin = pairWin->_child1;
+ } else {
+ warning("windowClose: window tree is corrupted");
+ return;
+ }
+
+ grandparWin = dynamic_cast<PairWindow *>(pairWin->_parent);
+ if (!grandparWin) {
+ _rootWin = sibWin;
+ sibWin->_parent = nullptr;
+ } else {
+ if (grandparWin->_child1 == pairWin)
+ grandparWin->_child1 = sibWin;
+ else
+ grandparWin->_child2 = sibWin;
+ sibWin->_parent = grandparWin;
+ }
+
+ // Begin closation
+ win->_stream->fillResult(result);
+
+ // Close the child window (and descendants), so that key-deletion can
+ // crawl up the tree to the root window.
+ win->close(true);
+
+ // This probably isn't necessary, but the child *is* gone, so just in case.
+ if (win == pairWin->_child1)
+ pairWin->_child1 = nullptr;
+ else if (win == pairWin->_child2)
+ pairWin->_child2 = nullptr;
+
+ // Now we can delete the parent pair.
+ pairWin->close(false);
+
+ // Sort out the arrangements
+ rearrange();
+ }
+}
+
Window *Windows::newWindow(glui32 type, glui32 rock) {
Window *win;
@@ -355,6 +411,30 @@ Window::~Window() {
next->_prev = prev;
}
+void Window::close(bool recurse) {
+ if (_windows->getFocusWindow() == this)
+ // Focused window is being removed
+ _windows->setFocus(nullptr);
+
+ for (Window *wx = _parent; wx; wx = wx->_parent) {
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(wx);
+
+ if (pairWin && pairWin->_key == this) {
+ pairWin->_key = nullptr;
+ pairWin->_keyDamage = true;
+ }
+ }
+
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(this);
+ if (pairWin) {
+ pairWin->_child1->close(recurse);
+ pairWin->_child2->close(recurse);
+ }
+
+ // Finally, delete the window
+ delete this;
+}
+
void Window::cancelLineEvent(Event *ev) {
Event dummyEv;
if (!ev)
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index ba9cb92..f52bbdd 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -135,6 +135,11 @@ public:
glui32 wintype, glui32 rock);
/**
+ * Close an existing window
+ */
+ void windowClose(Window *win, StreamResult *result = nullptr);
+
+ /**
* Return the root window
*/
Window *getRoot() const { return _rootWin; }
@@ -284,6 +289,11 @@ public:
virtual ~Window();
/**
+ * Close and delete the window
+ */
+ void close(bool recurse = true);
+
+ /**
* Rearranges the window
*/
virtual void rearrange(const Common::Rect &box) { _bbox = box; }
Commit: 49b8281ce3590642673db3fca67f7c94d5f710c1
https://github.com/scummvm/scummvm/commit/49b8281ce3590642673db3fca67f7c94d5f710c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Window rearrangement methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/window_pair.cpp
engines/gargoyle/window_pair.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 26b8349..4dc5e53 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -25,6 +25,7 @@
#include "gargoyle/streams.h"
#include "gargoyle/string.h"
#include "gargoyle/windows.h"
+#include "gargoyle/window_pair.h"
namespace Gargoyle {
@@ -86,14 +87,21 @@ void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr)
// TODO
}
-void Glk::glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keywin) {
- // TODO
+void Glk::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keywin) {
+ if (!win) {
+ warning("window_set_arrangement: invalid ref");
+ } else {
+ win->setArrangement(method, size, keywin);
+ }
}
-void Glk::glk_window_get_arrangement(winid_t win, glui32 *methodptr,
- glui32 *sizeptr, winid_t *keywinptr) {
- // TODO
+void Glk::glk_window_get_arrangement(winid_t win, glui32 *method,
+ glui32 *size, winid_t *keyWin) {
+ if (!win) {
+ warning("window_get_arrangement: invalid ref");
+ } else {
+ win->getArrangement(method, size, keyWin);
+ }
}
winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 0029ecf..5a822f8 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -75,8 +75,8 @@ public:
glui32 *heightptr);
void glk_window_set_arrangement(winid_t win, glui32 method,
glui32 size, winid_t keywin);
- void glk_window_get_arrangement(winid_t win, glui32 *methodptr,
- glui32 *sizeptr, winid_t *keywinptr);
+ void glk_window_get_arrangement(winid_t win, glui32 *method,
+ glui32 *size, winid_t *keywin);
winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
glui32 glk_window_get_rock(winid_t win);
glui32 glk_window_get_type(winid_t win);
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
index 7a11597..b8d593e 100644
--- a/engines/gargoyle/window_pair.cpp
+++ b/engines/gargoyle/window_pair.cpp
@@ -124,4 +124,85 @@ void PairWindow::redraw() {
// TODO
}
+void PairWindow::getArrangement(glui32 *method, glui32 *size, Window **keyWin) {
+ glui32 val = _dir | _division;
+ if (!_wBorder)
+ val |= winmethod_NoBorder;
+
+ if (size)
+ *size = _size;
+ if (keyWin) {
+ if (_key)
+ *keyWin = _key;
+ else
+ *keyWin = nullptr;
+ }
+
+ if (method)
+ *method = val;
+}
+
+void PairWindow::setArrangement(glui32 method, glui32 size, Window *keyWin) {
+ glui32 newDir;
+ bool newVertical, newBackward;
+
+ if (_key) {
+ Window *wx;
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(_key);
+
+ if (pairWin) {
+ warning("setArrangement: keywin cannot be a Pair");
+ return;
+ }
+
+ for (wx = _key; wx; wx = wx->_parent) {
+ if (wx == this)
+ break;
+ }
+ if (wx == nullptr) {
+ warning("setArrangement: keywin must be a descendant");
+ return;
+ }
+ }
+
+ newDir = method & winmethod_DirMask;
+ newVertical = (newDir == winmethod_Left || newDir == winmethod_Right);
+ newBackward = (newDir == winmethod_Left || newDir == winmethod_Above);
+ if (!keyWin)
+ keyWin = _key;
+
+ if ((newVertical && !_vertical) || (!newVertical && _vertical)) {
+ if (!_vertical)
+ warning("setArrangement: split must stay horizontal");
+ else
+ warning("setArrangement: split must stay vertical");
+ return;
+ }
+
+ if (keyWin && dynamic_cast<BlankWindow *>(keyWin)
+ && (method & winmethod_DivisionMask) == winmethod_Fixed) {
+ warning("setArrangement: a Blank window cannot have a fixed size");
+ return;
+ }
+
+ if ((newBackward && !_backward) || (!newBackward && _backward)) {
+ // switch the children
+ Window *tmpWin = _child1;
+ _child1 = _child2;
+ _child2 = tmpWin;
+ }
+
+ // set up everything else
+ _dir = newDir;
+ _division = method & winmethod_DivisionMask;
+ _key = keyWin;
+ _size = size;
+ _wBorder = ((method & winmethod_BorderMask) == winmethod_Border);
+
+ _vertical = (_dir == winmethod_Left || _dir == winmethod_Right);
+ _backward = (_dir == winmethod_Left || _dir == winmethod_Above);
+
+ _windows->rearrange();
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
index b25b324..8e80f79 100644
--- a/engines/gargoyle/window_pair.h
+++ b/engines/gargoyle/window_pair.h
@@ -57,6 +57,10 @@ public:
* Redraw the window
*/
virtual void redraw() override;
+
+ virtual void getArrangement(glui32 *method, glui32 *size, Window **keyWin) override;
+
+ virtual void setArrangement(glui32 method, glui32 size, Window *keyWin) override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 42db6f7..53feed2 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -471,6 +471,14 @@ void Window::acceptReadChar(glui32 arg) {
warning("acceptReadChar:: window does not support keyboard input");
}
+void Window::getArrangement(glui32 *method, glui32 *size, Window **keyWin) {
+ warning("getArrangement: not a Pair window");
+}
+
+void Window::setArrangement(glui32 method, glui32 size, Window *keyWin) {
+ warning("setArrangement: not a Pair window");
+}
+
bool Window::checkTerminator(glui32 ch) {
if (ch == keycode_Escape)
return true;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index f52bbdd..1e4dfd8 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -98,11 +98,6 @@ private:
*/
PairWindow *newPairWindow(glui32 method, Window *key, glui32 size);
- /**
- * Rearrange windows
- */
- void rearrange();
-
void refocus(Window *win);
Window *iterateTreeOrder(Window *win);
@@ -158,6 +153,11 @@ public:
void clearClaimSelect() { _claimSelect = false; }
+ /**
+ * Rearrange windows
+ */
+ void rearrange();
+
void redraw();
void redrawRect(const Common::Rect &r);
@@ -366,6 +366,10 @@ public:
virtual void acceptReadChar(glui32 arg);
+ virtual void getArrangement(glui32 *method, glui32 *size, Window **keyWin);
+
+ virtual void setArrangement(glui32 method, glui32 size, Window *keyWin);
+
int acceptScroll(glui32 arg);
};
typedef Window *winid_t;
Commit: 594f63f4752dcc3f2924ee34bc3b3fe33f895704
https://github.com/scummvm/scummvm/commit/594f63f4752dcc3f2924ee34bc3b3fe33f895704
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added window getSize methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/window_graphics.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 4dc5e53..4e5c465 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -83,8 +83,12 @@ void Glk::glk_window_close(winid_t win, stream_result_t *result) {
}
}
-void Glk::glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) {
- // TODO
+void Glk::glk_window_get_size(winid_t win, glui32 *width, glui32 *height) {
+ if (!win) {
+ warning("window_get_size: invalid ref");
+ } else {
+ win->getSize(width, height);
+ }
}
void Glk::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keywin) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 5a822f8..4b300f5 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -71,12 +71,11 @@ public:
glui32 wintype, glui32 rock = 0) const;
void glk_window_close(winid_t win, stream_result_t *result);
- void glk_window_get_size(winid_t win, glui32 *widthptr,
- glui32 *heightptr);
+ void glk_window_get_size(winid_t win, glui32 *width, glui32 *height);
void glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keywin);
+ glui32 size, winid_t keyWin);
void glk_window_get_arrangement(winid_t win, glui32 *method,
- glui32 *size, winid_t *keywin);
+ glui32 *size, winid_t *keyWin);
winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
glui32 glk_window_get_rock(winid_t win);
glui32 glk_window_get_type(winid_t win);
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index 8e97b56..5d08125 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -82,24 +82,10 @@ public:
*/
virtual void redraw() override;
+ virtual void getSize(glui32 *width, glui32 *height) override;
+
glui32 drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int scale,
glui32 imagewidth, glui32 imageheight);
-
- /**
- * Get the window dimensions
- */
- void getSize(glui32 *w, glui32 *h) {
- *w = _w;
- *h = _h;
- }
-
- /**
- * Set the window dimensions
- */
- void setSize(glui32 w, glui32 h) {
- _w = w;
- _h = h;
- }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index a32a64f..4368883 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -1633,6 +1633,13 @@ void TextBufferWindow::copyTextToClipboard(const glui32 *text, size_t len) {
// TODO
}
+void TextBufferWindow::getSize(glui32 *width, glui32 *height) {
+ if (width)
+ *width = (_bbox.width() - g_conf->_tMarginX * 2) / g_conf->_cellW;
+ if (height)
+ *height = (_bbox.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
+}
+
/*--------------------------------------------------------------------------*/
TextBufferWindow::TextBufferRow::TextBufferRow() : _len(0), _newLine(0), _dirty(false),
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 4741877..0c59cd2 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -206,6 +206,8 @@ public:
virtual void acceptReadChar(glui32 arg) override;
+ virtual void getSize(glui32 *width, glui32 *height) override;
+
int acceptScroll(glui32 arg);
glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height);
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index d9550bf..b249223 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -645,6 +645,13 @@ void TextGridWindow::redraw() {
}
}
+void TextGridWindow::getSize(glui32 *width, glui32 *height) {
+ if (width)
+ *width = _bbox.width() / g_conf->_cellW;
+ if (height)
+ *height = _bbox.height() / g_conf->_cellH;
+}
+
/*--------------------------------------------------------------------------*/
void TextGridWindow::TextGridRow::resize(size_t newSize) {
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 2c5a0a8..2b8448c 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -155,6 +155,8 @@ public:
virtual void acceptReadLine(glui32 arg) override;
virtual void acceptReadChar(glui32 arg) override;
+
+ virtual void getSize(glui32 *width, glui32 *height) override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 53feed2..400689c 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -503,6 +503,13 @@ bool Window::imageDraw(glui32 image, glui32 align, glsi32 val1, glsi32 val2) {
return false;
}
+void Window::getSize(glui32 *width, glui32 *height) {
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+}
+
/*--------------------------------------------------------------------------*/
BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 1e4dfd8..5a4c022 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -360,6 +360,8 @@ public:
bool imageDraw(glui32 image, glui32 align, glsi32 val1, glsi32 val2);
+ int acceptScroll(glui32 arg);
+
virtual glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height) { return false; }
virtual void acceptReadLine(glui32 arg);
@@ -370,7 +372,7 @@ public:
virtual void setArrangement(glui32 method, glui32 size, Window *keyWin);
- int acceptScroll(glui32 arg);
+ virtual void getSize(glui32 *width, glui32 *height);
};
typedef Window *winid_t;
Commit: 72022042ee303fde02eef2264d430d56526768ed
https://github.com/scummvm/scummvm/commit/72022042ee303fde02eef2264d430d56526768ed
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding glk window methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/window_graphics.cpp
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 4e5c465..1e6dfa3 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -108,28 +108,63 @@ void Glk::glk_window_get_arrangement(winid_t win, glui32 *method,
}
}
-winid_t Glk::glk_window_iterate(winid_t win, glui32 *rockptr) {
- // TODO
+winid_t Glk::glk_window_iterate(winid_t win, glui32 *rock) {
+ win = win ? win->_next : _windows->getRoot();
+
+ if (win) {
+ if (rock)
+ *rock = win->_rock;
+ return win;
+ }
+
+ if (rock)
+ *rock = 0;
+
return nullptr;
}
glui32 Glk::glk_window_get_rock(winid_t win) {
- // TODO
- return 0;
+ if (!win) {
+ warning("window_get_rock: invalid ref.");
+ return 0;
+ }
+
+ return win->_rock;
}
glui32 Glk::glk_window_get_type(winid_t win) {
- // TODO
- return 0;
+ if (!win) {
+ warning("window_get_parent: invalid ref");
+ return 0;
+ }
+
+ return win->_type;
}
winid_t Glk::glk_window_get_parent(winid_t win) {
- // TODO
- return nullptr;
+ if (!win) {
+ warning("window_get_parent: invalid ref");
+ return 0;
+ }
+
+ return win->_parent;
}
winid_t Glk::glk_window_get_sibling(winid_t win) {
- // TODO
+ if (!win) {
+ warning("window_get_sibling: invalid ref");
+ return nullptr;
+ }
+
+ PairWindow *parentWin = dynamic_cast<PairWindow *>(win->_parent);
+ if (!parentWin)
+ return nullptr;
+
+ if (parentWin->_child1 == win)
+ return parentWin->_child2;
+ else if (parentWin->_child2 == win)
+ return parentWin->_child1;
+
return nullptr;
}
@@ -142,16 +177,29 @@ void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
}
strid_t Glk::glk_window_get_stream(winid_t win) {
+ if (!win) {
+ warning("window_get_stream: invalid ref");
+ return nullptr;
+ }
+
return win->_stream;
}
void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
- // TODO
+ if (!win) {
+ warning("window_set_echo_stream: invalid window id");
+ } else {
+ win->_echoStream = str;
+ }
}
strid_t Glk::glk_window_get_echo_stream(winid_t win) {
- // TODO
- return nullptr;
+ if (!win) {
+ warning("window_get_echo_stream: invalid ref");
+ return nullptr;
+ }
+
+ return win->_echoStream;
}
void Glk::glk_set_window(winid_t win) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 4b300f5..0e97600 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -76,7 +76,7 @@ public:
glui32 size, winid_t keyWin);
void glk_window_get_arrangement(winid_t win, glui32 *method,
glui32 *size, winid_t *keyWin);
- winid_t glk_window_iterate(winid_t win, glui32 *rockptr);
+ winid_t glk_window_iterate(winid_t win, glui32 *rock);
glui32 glk_window_get_rock(winid_t win);
glui32 glk_window_get_type(winid_t win);
winid_t glk_window_get_parent(winid_t win);
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index caf51a2..3af2555 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -244,4 +244,9 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
_surface->blitFrom(*g_vm->_screen, Common::Rect(sx0, sy0, sx0 + w, sy0 + h), Common::Point(0, 0));
}
+void GraphicsWindow::getSize(glui32 *width, glui32 *height) {
+ *width = _bbox.width();
+ *height = _bbox.height();
+}
+
} // End of namespace Gargoyle
Commit: 4266f3af130ddeddbed5da9d6c7aa4826ad94d96
https://github.com/scummvm/scummvm/commit/4266f3af130ddeddbed5da9d6c7aa4826ad94d96
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding more window glk methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 1e6dfa3..43ba646 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -387,11 +387,25 @@ void Glk::glk_request_timer_events(glui32 millisecs) {
}
void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
- // TODO
+ if (!win) {
+ warning("request_line_event: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_line_event: window already has keyboard request");
+ } else {
+ win->requestLineEvent(buf, maxlen, initlen);
+ }
}
void Glk::glk_request_char_event(winid_t win) {
- // TODO
+ if (!win) {
+ warning("request_char_event: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_char_event: window already has keyboard request");
+ } else {
+ win->requestCharEvent();
+ }
}
void Glk::glk_request_mouse_event(winid_t win) {
@@ -413,7 +427,11 @@ void Glk::glk_cancel_mouse_event(winid_t win) {
#ifdef GLK_MODULE_LINE_ECHO
void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
- // TODO
+ if (!win) {
+ warning("set_echo_line_event: invalid ref");
+ } else {
+ win->setEchoLineEvent(val);
+ }
}
#endif /* GLK_MODULE_LINE_ECHO */
@@ -421,7 +439,11 @@ void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
#ifdef GLK_MODULE_LINE_TERMINATORS
void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
- // TODO
+ if (!win) {
+ warning("set_terminators_line_event: invalid ref");
+ } else {
+ win->setTerminatorsLineEvent(keycodes, count);
+ }
}
#endif /* GLK_MODULE_LINE_TERMINATORS */
@@ -505,12 +527,25 @@ strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmo
}
void Glk::glk_request_char_event_uni(winid_t win) {
- // TODO
+ if (!win) {
+ warning("request_char_event_uni: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_char_event_uni: window already has keyboard request");
+ } else {
+ win->requestCharEvent();
+ }
}
-void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen) {
- // TODO
+void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (!win) {
+ warning("request_line_event_uni: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_line_event_uni: window already has keyboard request");
+ } else {
+ win->requestLineEventUni(buf, maxlen, initlen);
+ }
}
#endif /* GLK_MODULE_UNICODE */
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 0c59cd2..094d6d0 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -208,6 +208,12 @@ public:
virtual void getSize(glui32 *width, glui32 *height) override;
+ virtual void requestCharEvent() override { _charRequest = true; }
+
+ virtual void requestCharEventUni() override { _charRequestUni = true; }
+
+ virtual void setEchoLineEvent(glui32 val) override { _echoLineInput = val != 0; }
+
int acceptScroll(glui32 arg);
glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height);
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 2b8448c..17fa96f 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -157,6 +157,10 @@ public:
virtual void acceptReadChar(glui32 arg) override;
virtual void getSize(glui32 *width, glui32 *height) override;
+
+ virtual void requestCharEvent() override { _charRequest = true; }
+
+ virtual void requestCharEventUni() override { _charRequestUni = true; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 400689c..7c5b259 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -479,6 +479,34 @@ void Window::setArrangement(glui32 method, glui32 size, Window *keyWin) {
warning("setArrangement: not a Pair window");
}
+void Window::requestCharEvent() {
+ warning("requestCharEvent: window does not support keyboard input");
+}
+
+void Window::requestCharEventUni() {
+ warning("requestCharEventUni: window does not support keyboard input");
+}
+
+void Window::setTerminatorsLineEvent(glui32 *keycodes, glui32 count) {
+ if (dynamic_cast<TextBufferWindow *>(this) || dynamic_cast<TextGridWindow *>(this)) {
+ delete _lineTerminatorsBase;
+ _lineTerminatorsBase = nullptr;
+
+ if (!keycodes || count == 0) {
+ _termCt = 0;
+ } else {
+ _lineTerminatorsBase = new glui32[count + 1];
+ if (_lineTerminatorsBase) {
+ memcpy(_lineTerminatorsBase, keycodes, count * sizeof(glui32));
+ _lineTerminatorsBase[count] = 0;
+ _termCt = count;
+ }
+ }
+ } else {
+ warning("setTerminatorsLineEvent: window does not support keyboard input");
+ }
+}
+
bool Window::checkTerminator(glui32 ch) {
if (ch == keycode_Escape)
return true;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 5a4c022..3c419e5 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -362,6 +362,8 @@ public:
int acceptScroll(glui32 arg);
+ void setTerminatorsLineEvent(glui32 *keycodes, glui32 count);
+
virtual glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height) { return false; }
virtual void acceptReadLine(glui32 arg);
@@ -373,6 +375,12 @@ public:
virtual void setArrangement(glui32 method, glui32 size, Window *keyWin);
virtual void getSize(glui32 *width, glui32 *height);
+
+ virtual void requestCharEvent();
+
+ virtual void requestCharEventUni();
+
+ virtual void setEchoLineEvent(glui32 val) {}
};
typedef Window *winid_t;
Commit: e14424c2b944ae9a9c5ce34158bd5e7e361ee994
https://github.com/scummvm/scummvm/commit/e14424c2b944ae9a9c5ce34158bd5e7e361ee994
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding more window glk methods
Changed paths:
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 939e691..f49d9ff 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -101,6 +101,15 @@ struct Event {
* Constructor
*/
Event() : type(evtype_None), window(nullptr), val1(0), val2(0) {}
+
+ /**
+ * Clear
+ */
+ void clear() {
+ type = evtype_None;
+ window = nullptr;
+ val1 = val2 = 0;
+ }
};
typedef Event event_t;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 43ba646..c309f72 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -409,19 +409,35 @@ void Glk::glk_request_char_event(winid_t win) {
}
void Glk::glk_request_mouse_event(winid_t win) {
- // TODO
+ if (!win) {
+ warning("request_mouse_event: invalid ref");
+ } else {
+ win->requestMouseEvent();
+ }
}
void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
- // TODO
+ if (!win) {
+ warning("cancel_line_event: invalid ref");
+ } else {
+ win->cancelLineEvent(event);
+ }
}
void Glk::glk_cancel_char_event(winid_t win) {
- // TODO
+ if (!win) {
+ warning("glk_cancel_char_event: invalid ref");
+ } else {
+ win->cancelCharEvent();
+ }
}
void Glk::glk_cancel_mouse_event(winid_t win) {
- // TODO
+ if (!win) {
+ warning("cancel_mouse_event: invalid ref");
+ } else {
+ win->cancelMouseEvent();
+ }
}
#ifdef GLK_MODULE_LINE_ECHO
@@ -685,7 +701,11 @@ void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
}
void Glk::glk_request_hyperlink_event(winid_t win) {
- // TODO
+ if (!win) {
+ warning("request_hyperlink_event: invalid ref");
+ } else {
+ win->requestHyperlinkEvent();
+ }
}
void Glk::glk_cancel_hyperlink_event(winid_t win) {
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index 3af2555..0ec2bee 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -244,7 +244,7 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
_surface->blitFrom(*g_vm->_screen, Common::Rect(sx0, sy0, sx0 + w, sy0 + h), Common::Point(0, 0));
}
-void GraphicsWindow::getSize(glui32 *width, glui32 *height) {
+void GraphicsWindow::getSize(glui32 *width, glui32 *height) const {
*width = _bbox.width();
*height = _bbox.height();
}
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index 5d08125..166b03a 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -55,6 +55,9 @@ public:
*/
virtual ~GraphicsWindow();
+ glui32 drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int scale,
+ glui32 imagewidth, glui32 imageheight);
+
/**
* Rearranges the window
*/
@@ -77,15 +80,16 @@ public:
*/
virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+ virtual void requestMouseEvent() override { _mouseRequest = true; }
+
+ virtual void requestHyperlinkEvent() override { _hyperRequest = true; }
+
/**
* Redraw the window
*/
virtual void redraw() override;
- virtual void getSize(glui32 *width, glui32 *height) override;
-
- glui32 drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int scale,
- glui32 imagewidth, glui32 imageheight);
+ virtual void getSize(glui32 *width, glui32 *height) const override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 4368883..c428dac 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -1633,7 +1633,7 @@ void TextBufferWindow::copyTextToClipboard(const glui32 *text, size_t len) {
// TODO
}
-void TextBufferWindow::getSize(glui32 *width, glui32 *height) {
+void TextBufferWindow::getSize(glui32 *width, glui32 *height) const {
if (width)
*width = (_bbox.width() - g_conf->_tMarginX * 2) / g_conf->_cellW;
if (height)
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 094d6d0..774bd66 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -147,6 +147,10 @@ public:
*/
virtual ~TextBufferWindow();
+ int acceptScroll(glui32 arg);
+
+ glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height);
+
/**
* Rearranges the window
*/
@@ -206,7 +210,7 @@ public:
virtual void acceptReadChar(glui32 arg) override;
- virtual void getSize(glui32 *width, glui32 *height) override;
+ virtual void getSize(glui32 *width, glui32 *height) const override;
virtual void requestCharEvent() override { _charRequest = true; }
@@ -214,9 +218,9 @@ public:
virtual void setEchoLineEvent(glui32 val) override { _echoLineInput = val != 0; }
- int acceptScroll(glui32 arg);
+ virtual void requestHyperlinkEvent() override { _hyperRequest = true; }
- glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height);
+ virtual void cancelCharEvent() override { _charRequest = _charRequestUni = false; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index b249223..01c3193 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -645,7 +645,7 @@ void TextGridWindow::redraw() {
}
}
-void TextGridWindow::getSize(glui32 *width, glui32 *height) {
+void TextGridWindow::getSize(glui32 *width, glui32 *height) const {
if (width)
*width = _bbox.width() / g_conf->_cellW;
if (height)
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 17fa96f..9ff588b 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -123,6 +123,24 @@ public:
virtual void click(const Common::Point &newPos) override;
/**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+
+ virtual void acceptReadLine(glui32 arg) override;
+
+ virtual void acceptReadChar(glui32 arg) override;
+
+ virtual void getSize(glui32 *width, glui32 *height) const override;
+
+ virtual void requestCharEvent() override { _charRequest = true; }
+
+ /**
* Prepare for inputing a line
*/
virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
@@ -142,25 +160,13 @@ public:
*/
virtual void cancelMouseEvent() override { _mouseRequest = false; }
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-
- virtual void acceptReadLine(glui32 arg) override;
-
- virtual void acceptReadChar(glui32 arg) override;
+ virtual void requestCharEventUni() override { _charRequestUni = true; }
- virtual void getSize(glui32 *width, glui32 *height) override;
+ virtual void requestMouseEvent() override { _mouseRequest = true; }
- virtual void requestCharEvent() override { _charRequest = true; }
+ virtual void requestHyperlinkEvent() override { _hyperRequest = true; }
- virtual void requestCharEventUni() override { _charRequestUni = true; }
+ virtual void cancelCharEvent() override { _charRequest = _charRequestUni = false; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 7c5b259..cc23e47 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -531,7 +531,7 @@ bool Window::imageDraw(glui32 image, glui32 align, glsi32 val1, glsi32 val2) {
return false;
}
-void Window::getSize(glui32 *width, glui32 *height) {
+void Window::getSize(glui32 *width, glui32 *height) const {
if (width)
*width = 0;
if (height)
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 3c419e5..b7d701f 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -344,6 +344,11 @@ public:
virtual void cancelLineEvent(Event *ev);
/**
+ * Cancel a character event
+ */
+ virtual void cancelCharEvent() {}
+
+ /**
* Cancel a mouse event
*/
virtual void cancelMouseEvent() {}
@@ -374,13 +379,17 @@ public:
virtual void setArrangement(glui32 method, glui32 size, Window *keyWin);
- virtual void getSize(glui32 *width, glui32 *height);
+ virtual void getSize(glui32 *width, glui32 *height) const;
virtual void requestCharEvent();
virtual void requestCharEventUni();
virtual void setEchoLineEvent(glui32 val) {}
+
+ virtual void requestMouseEvent() {}
+
+ virtual void requestHyperlinkEvent() {}
};
typedef Window *winid_t;
Commit: b231dee01a92f263c95311d68657f01b003141ca
https://github.com/scummvm/scummvm/commit/b231dee01a92f263c95311d68657f01b003141ca
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: More window glk methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index c309f72..8f9df23 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -21,7 +21,9 @@
*/
#include "gargoyle/glk.h"
+#include "gargoyle/conf.h"
#include "gargoyle/events.h"
+#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
#include "gargoyle/string.h"
#include "gargoyle/windows.h"
@@ -169,11 +171,27 @@ winid_t Glk::glk_window_get_sibling(winid_t win) {
}
void Glk::glk_window_clear(winid_t win) {
- // TODO
+ if (!win) {
+ warning("window_clear: invalid ref");
+ } else if (win->_lineRequest || win->_lineRequestUni) {
+ if (g_conf->_safeClicks && _events->_forceClick) {
+ glk_cancel_line_event(win, NULL);
+ _events->_forceClick = false;
+
+ win->clear();
+ } else {
+ warning("window_clear: window has pending line request");
+ return;
+ }
+ }
}
void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
- // TODO
+ if (!win) {
+ warning("window_move_cursor: invalid ref");
+ } else {
+ win->moveCursor(Common::Point(xpos, ypos));
+ }
}
strid_t Glk::glk_window_get_stream(winid_t win) {
@@ -583,8 +601,14 @@ glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numch
#ifdef GLK_MODULE_IMAGE
glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
- // TODO
- return 0;
+/*
+ if (!win) {
+ warning("image_draw: invalid ref");
+ } else if (g_conf->_graphics) {
+ win->imageDraw(image, val1, val2, );
+ }
+ */
+ return false;
}
glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
@@ -594,22 +618,44 @@ glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
}
glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
- // TODO
- return 0;
+ if (!g_conf->_graphics)
+ return false;
+
+ Picture *pic = Picture::load(image);
+ if (!pic)
+ return false;
+
+ if (width)
+ *width = pic->w;
+ if (height)
+ *height = pic->h;
+
+ return true;
}
void Glk::glk_window_flow_break(winid_t win) {
- // TODO
+ if (!win) {
+ warning("window_erase_rect: invalid ref");
+ } else {
+ win->flowBreak();
+ }
}
-void Glk::glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height) {
- // TODO
+void Glk::glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 height) {
+ if (!win) {
+ warning("window_erase_rect: invalid ref");
+ } else {
+ win->eraseRect(false, Common::Rect(left, top, left + width, top + height));
+ }
}
-void Glk::glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height) {
- // TODO
+void Glk::glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top,
+ glui32 width, glui32 height) {
+ if (!win) {
+ warning("window_fill_rect: invalid ref");
+ } else {
+ win->eraseRect(color, Common::Rect(left, top, left + width, top + height));
+ }
}
void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index 0ec2bee..0ea5876 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -120,9 +120,8 @@ glui32 GraphicsWindow::drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int s
return true;
}
-void GraphicsWindow::eraseRect(int whole, glsi32 x0, glsi32 y0, glui32 width, glui32 height) {
- int x1 = x0 + width;
- int y1 = y0 + height;
+void GraphicsWindow::eraseRect(bool whole, const Common::Rect &box) {
+ int x0 = box.left, y0 = box.top, x1 = box.right, y1 = box.bottom;
int hx0, hx1, hy0, hy1;
if (whole) {
@@ -153,10 +152,9 @@ void GraphicsWindow::eraseRect(int whole, glsi32 x0, glsi32 y0, glui32 width, gl
touch();
}
-void GraphicsWindow::fillRect(glui32 color, glsi32 x0, glsi32 y0, glui32 width, glui32 height) {
+void GraphicsWindow::fillRect(glui32 color, const Common::Rect &box) {
unsigned char col[3];
- int x1 = x0 + width;
- int y1 = y0 + height;
+ int x0 = box.left, y0 = box.top, x1 = box.right, y1 = box.bottom;
int hx0, hx1, hy0, hy1;
col[0] = (color >> 16) & 0xff;
@@ -184,12 +182,6 @@ void GraphicsWindow::fillRect(glui32 color, glsi32 x0, glsi32 y0, glui32 width,
touch();
}
-void GraphicsWindow::setBackgroundColor(glui32 color) {
- _bgnd[0] = (color >> 16) & 0xff;
- _bgnd[1] = (color >> 8) & 0xff;
- _bgnd[2] = (color >> 0) & 0xff;
-}
-
void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int height, glui32 linkval) {
int dx1, dy1, x1, y1, sx0, sy0, sx1, sy1;
int hx0, hx1, hy0, hy1;
@@ -249,4 +241,10 @@ void GraphicsWindow::getSize(glui32 *width, glui32 *height) const {
*height = _bbox.height();
}
+void GraphicsWindow::setBackgroundColor(glui32 color) {
+ _bgnd[0] = (color >> 16) & 0xff;
+ _bgnd[1] = (color >> 8) & 0xff;
+ _bgnd[2] = (color >> 0) & 0xff;
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index 166b03a..8c2724e 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -35,9 +35,6 @@ class GraphicsWindow : public Window {
private:
void touch();
- void eraseRect(int whole, glsi32 x0, glsi32 y0, glui32 width, glui32 height);
- void fillRect(glui32 color, glsi32 x0, glsi32 y0, glui32 width, glui32 height);
- void setBackgroundColor(glui32 color);
void drawPicture(Picture *src, int x0, int y0, int width, int height, glui32 linkval);
public:
unsigned char _bgnd[3];
@@ -89,7 +86,13 @@ public:
*/
virtual void redraw() override;
+ virtual void eraseRect(bool whole, const Common::Rect &box) override;
+
+ virtual void fillRect(glui32 color, const Common::Rect &box) override;
+
virtual void getSize(glui32 *width, glui32 *height) const override;
+
+ virtual void setBackgroundColor(glui32 color) override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index c428dac..05705cc 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -296,12 +296,6 @@ glui32 TextBufferWindow::drawPicture(glui32 image, glui32 align, glui32 scaled,
return error;
}
-bool TextBufferWindow::flowBreak() {
- while (_ladjn || _radjn)
- putCharUni('\n');
- return true;
-}
-
void TextBufferWindow::putText(const char *buf, int len, int pos, int oldlen) {
int diff = len - oldlen;
@@ -1640,6 +1634,11 @@ void TextBufferWindow::getSize(glui32 *width, glui32 *height) const {
*height = (_bbox.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
}
+void TextBufferWindow::flowBreak() {
+ while (_ladjn || _radjn)
+ putCharUni('\n');
+}
+
/*--------------------------------------------------------------------------*/
TextBufferWindow::TextBufferRow::TextBufferRow() : _len(0), _newLine(0), _dirty(false),
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 774bd66..be9ffcb 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -66,8 +66,6 @@ private:
*/
void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
- bool flowBreak();
-
void acceptLine(glui32 keycode);
/**
@@ -221,6 +219,8 @@ public:
virtual void requestHyperlinkEvent() override { _hyperRequest = true; }
virtual void cancelCharEvent() override { _charRequest = _charRequestUni = false; }
+
+ virtual void flowBreak() override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index cc23e47..2f2008c 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -487,6 +487,22 @@ void Window::requestCharEventUni() {
warning("requestCharEventUni: window does not support keyboard input");
}
+void Window::flowBreak() {
+ warning("flowBreak: not a text buffer window");
+}
+
+void Window::eraseRect(bool whole, const Common::Rect &box) {
+ warning("eraseRect: not a graphics window");
+}
+
+void Window::fillRect(glui32 color, const Common::Rect &box) {
+ warning("fillRect: not a graphics window");
+}
+
+void Window::setBackgroundColor(glui32 color) {
+ warning("setBackgroundColor: not a graphics window");
+}
+
void Window::setTerminatorsLineEvent(glui32 *keycodes, glui32 count) {
if (dynamic_cast<TextBufferWindow *>(this) || dynamic_cast<TextGridWindow *>(this)) {
delete _lineTerminatorsBase;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index b7d701f..03ab1b0 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -390,6 +390,14 @@ public:
virtual void requestMouseEvent() {}
virtual void requestHyperlinkEvent() {}
+
+ virtual void flowBreak();
+
+ virtual void eraseRect(bool whole, const Common::Rect &box);
+
+ virtual void fillRect(glui32 color, const Common::Rect &box);
+
+ virtual void setBackgroundColor(glui32 color);
};
typedef Window *winid_t;
Commit: d1282498542b87ee0d807e5d4a2a09232a8dc677
https://github.com/scummvm/scummvm/commit/d1282498542b87ee0d807e5d4a2a09232a8dc677
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Miscellaneous glk methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 8f9df23..d81ddf5 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -27,16 +27,39 @@
#include "gargoyle/streams.h"
#include "gargoyle/string.h"
#include "gargoyle/windows.h"
+#include "gargoyle/window_graphics.h"
+#include "gargoyle/window_text_buffer.h"
#include "gargoyle/window_pair.h"
+
namespace Gargoyle {
Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GargoyleEngine(syst, gameDesc), _gliFirstEvent(false) {
+ GargoyleEngine(syst, gameDesc), _gliFirstEvent(false) {
+ // Set uppercase/lowercase tables
+ int ix, res;
+ for (ix = 0; ix < 256; ix++) {
+ _charToupperTable[ix] = ix;
+ _charTolowerTable[ix] = ix;
+ }
+
+ for (ix = 0; ix < 256; ix++) {
+ if (ix >= 'A' && ix <= 'Z')
+ res = ix + ('a' - 'A');
+ else if (ix >= 0xC0 && ix <= 0xDE && ix != 0xD7)
+ res = ix + 0x20;
+ else
+ res = 0;
+
+ if (res) {
+ _charTolowerTable[ix] = res;
+ _charToupperTable[res] = ix;
+ }
+ }
}
void Glk::glk_exit(void) {
- // TODO
+ quitGame();
}
void Glk::glk_set_interrupt_handler(void(*func)(void)) {
@@ -44,27 +67,109 @@ void Glk::glk_set_interrupt_handler(void(*func)(void)) {
}
void Glk::glk_tick(void) {
- // TODO
+ // Nothing needed
}
-glui32 Glk::glk_gestalt(glui32 sel, glui32 val) {
- // TODO
- return 0;
+glui32 Glk::glk_gestalt(glui32 id, glui32 val) {
+ return glk_gestalt_ext(id, val, nullptr, 0);
}
-glui32 Glk::glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen) {
- // TODO
- return 0;
+glui32 Glk::glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen) {
+ switch (id) {
+ case gestalt_Version:
+ return 0x00000703;
+
+ case gestalt_LineInput:
+ if (val >= 32 && val < 0x10ffff)
+ return true;
+ else
+ return false;
+
+ case gestalt_CharInput:
+ if (val >= 32 && val < 0x10ffff)
+ return true;
+ else if (val == keycode_Return)
+ return true;
+ else
+ return false;
+
+ case gestalt_CharOutput:
+ if (val >= 32 && val < 0x10ffff) {
+ if (arr && arrlen >= 1)
+ arr[0] = 1;
+ return gestalt_CharOutput_ExactPrint;
+ } else {
+ // cheaply, we don't do any translation of printed characters,
+ // so the output is always one character even if it's wrong.
+ if (arr && arrlen >= 1)
+ arr[0] = 1;
+ return gestalt_CharOutput_CannotPrint;
+ }
+
+ case gestalt_MouseInput:
+ if (val == wintype_TextGrid)
+ return true;
+ if (val == wintype_Graphics)
+ return true;
+ return false;
+
+ case gestalt_Timer:
+ return true;
+
+ case gestalt_Graphics:
+ case gestalt_GraphicsTransparency:
+ return g_conf->_graphics;
+
+ case gestalt_DrawImage:
+ if (val == wintype_TextBuffer)
+ return g_conf->_graphics;
+ if (val == wintype_Graphics)
+ return g_conf->_graphics;
+ return false;
+
+ case gestalt_Sound:
+ case gestalt_SoundVolume:
+ case gestalt_SoundMusic:
+ case gestalt_SoundNotify:
+ return g_conf->_sound;
+
+ case gestalt_Sound2:
+ return false;
+
+ case gestalt_Unicode:
+ return true;
+ case gestalt_UnicodeNorm:
+ return true;
+
+ case gestalt_Hyperlinks:
+ return true;
+ case gestalt_HyperlinkInput:
+ return true;
+
+ case gestalt_LineInputEcho:
+ return true;
+ case gestalt_LineTerminators:
+ return true;
+ case gestalt_LineTerminatorKey:
+ return Window::checkTerminator(val);
+
+ case gestalt_DateTime:
+ return true;
+
+ case gestalt_GarglkText:
+ return true;
+
+ default:
+ return false;
+ }
}
unsigned char Glk::glk_char_to_lower(unsigned char ch) {
- // TODO
- return '\0';
+ return _charTolowerTable[ch];
}
unsigned char Glk::glk_char_to_upper(unsigned char ch) {
- // TODO
- return '\0';
+ return _charToupperTable[ch];
}
winid_t Glk::glk_window_get_root(void) const {
@@ -224,8 +329,7 @@ void Glk::glk_set_window(winid_t win) {
_streams->setCurrent(win ? win->_stream : nullptr);
}
-strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode,
- glui32 rock) {
+strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock) {
// TODO
return nullptr;
}
@@ -601,20 +705,36 @@ glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numch
#ifdef GLK_MODULE_IMAGE
glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
-/*
if (!win) {
warning("image_draw: invalid ref");
} else if (g_conf->_graphics) {
- win->imageDraw(image, val1, val2, );
+ TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
+ GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
+
+ if (textWin)
+ textWin->drawPicture(image, val1, false, 0, 0);
+ else if (gfxWin)
+ gfxWin->drawPicture(image, val1, val2, false, 0, 0);
}
- */
+
return false;
}
-glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height) {
- // TODO
- return 0;
+glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2,
+ glui32 width, glui32 height) {
+ if (!win) {
+ warning("image_draw_scaled: invalid ref");
+ } else if (g_conf->_graphics) {
+ TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
+ GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
+
+ if (textWin)
+ textWin->drawPicture(image, val1, true, width, height);
+ else if (gfxWin)
+ gfxWin->drawPicture(image, val1, val2, true, width, height);
+ }
+
+ return false;
}
glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
@@ -659,7 +779,11 @@ void Glk::glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 to
}
void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
- // TODO
+ if (!win) {
+ warning("window_set_background_color: invalid ref");
+ } else {
+ win->setBackgroundColor(color);
+ }
}
#endif /* GLK_MODULE_IMAGE */
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 0e97600..e1923b7 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -36,6 +36,8 @@ namespace Gargoyle {
class Glk : public GargoyleEngine {
private:
bool _gliFirstEvent;
+ unsigned char _charTolowerTable[256];
+ unsigned char _charToupperTable[256];
private:
/**
* Pick first window which might want input. This is called after every keystroke.
@@ -53,8 +55,8 @@ public:
void glk_set_interrupt_handler(void(*func)(void));
void glk_tick(void);
- glui32 glk_gestalt(glui32 sel, glui32 val);
- glui32 glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen);
+ glui32 glk_gestalt(glui32 id, glui32 val);
+ glui32 glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen);
unsigned char glk_char_to_lower(unsigned char ch);
unsigned char glk_char_to_upper(unsigned char ch);
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 03ab1b0..2c03c15 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -275,8 +275,8 @@ public:
byte _fgColor[3];
gidispatch_rock_t _dispRock;
-protected:
- bool checkTerminator(glui32 ch);
+public:
+ static bool checkTerminator(glui32 ch);
public:
/**
* Constructor
@@ -369,8 +369,6 @@ public:
void setTerminatorsLineEvent(glui32 *keycodes, glui32 count);
- virtual glui32 drawPicture(glui32 image, glui32 align, glui32 scaled, glui32 width, glui32 height) { return false; }
-
virtual void acceptReadLine(glui32 arg);
virtual void acceptReadChar(glui32 arg);
Commit: 485e899312d1cf092e7cb52927593be21ef0f263
https://github.com/scummvm/scummvm/commit/485e899312d1cf092e7cb52927593be21ef0f263
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding glk stream methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index d81ddf5..1993375 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -335,12 +335,11 @@ strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock)
}
strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock) {
- // TODO
- return nullptr;
+ return _streams->addMemoryStream(buf, buflen, fmode, rock, false);
}
void Glk::glk_stream_close(strid_t str, stream_result_t *result) {
- // TODO
+ str->close(result);
}
strid_t Glk::glk_stream_iterate(strid_t str, glui32 *rockptr) const {
@@ -356,22 +355,29 @@ glui32 Glk::glk_stream_get_rock(strid_t str) const {
return str->getRock();
}
-void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) {
- // TODO
+void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekMode) {
+ if (!str) {
+ warning("stream_set_position: invalid ref");
+ } else {
+ str->setPosition(pos, seekMode);
+ }
}
-glui32 Glk::glk_stream_get_position(strid_t str) {
- // TODO
- return 0;
+glui32 Glk::glk_stream_get_position(strid_t str) const {
+ if (!str) {
+ warning("stream_get_position: invalid ref");
+ return 0;
+ } else {
+ return str->getPosition();
+ }
}
void Glk::glk_stream_set_current(strid_t str) {
- // TODO
+ _streams->setCurrent(str);
}
strid_t Glk::glk_stream_get_current(void) {
- // TODO
- return nullptr;
+ return _streams->getCurrent();
}
void Glk::glk_put_char(unsigned char ch) {
@@ -387,32 +393,40 @@ void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
}
void Glk::glk_put_string(const char *s) {
- // TODO
+ _streams->getCurrent()->putBuffer(s, strlen(s));
}
void Glk::glk_put_string_stream(strid_t str, const char *s) {
- // TODO
+ str->putBuffer(s, strlen(s));
}
void Glk::glk_put_buffer(char *buf, glui32 len) {
- // TODO
+ _streams->getCurrent()->putBuffer(buf, len);
}
void Glk::glk_put_buffer_stream(strid_t str, const char *buf, glui32 len) {
- // TODO
+ str->putBuffer(buf, len);
}
void Glk::glk_set_style(glui32 styl) {
- // TODO
+ _streams->getCurrent()->setStyle(styl);
}
void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
- // TODO
+ if (str) {
+ str->setStyle(styl);
+ } else {
+ warning("set_style_stream: invalid ref");
+ }
}
glsi32 Glk::glk_get_char_stream(strid_t str) {
- // TODO
- return 0;
+ if (str) {
+ warning("get_char_stream: invalid ref");
+ return -1;
+ } else {
+ return str->getChar();
+ }
}
glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
@@ -661,7 +675,7 @@ strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 r
}
strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock) {
- return _streams->addMemoryStream(buf, buflen, fmode, rock, false);
+ return _streams->addMemoryStream(buf, buflen, fmode, rock, true);
}
void Glk::glk_request_char_event_uni(winid_t win) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index e1923b7..3b49421 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -96,8 +96,8 @@ public:
void glk_stream_close(strid_t str, stream_result_t *result);
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_position(strid_t str, glsi32 pos, glui32 seekMode);
+ glui32 glk_stream_get_position(strid_t str) const;
void glk_stream_set_current(strid_t str);
strid_t glk_stream_get_current(void);
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 81d05ac..a521548 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -46,11 +46,6 @@ class Window;
#define GLK_MODULE_DATETIME
#define GLK_MODULE_GARGLKTEXT
-/**
- * These types are opaque object identifiers. They're pointers to opaque
- * C structures, which are defined differently by each library.
- */
-typedef struct glk_fileref_struct *frefid_t;
typedef struct glk_schannel_struct *schanid_t;
/**
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 7499991..6a73c5b 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -144,6 +144,18 @@ void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
_window->_echoStream->putBufferUni(buf, len);
}
+void WindowStream::setStyle(glui32 val) {
+ if (!_writable)
+ return;
+
+ if (val >= style_NUMSTYLES)
+ val = 0;
+
+ _window->_attr.style = val;
+ if (_window->_echoStream)
+ _window->_echoStream->setStyle(val);
+}
+
/*--------------------------------------------------------------------------*/
MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
@@ -297,6 +309,66 @@ void MemoryStream::putBufferUni(const uint32 *buf, size_t len) {
}
}
+glui32 MemoryStream::getPosition() const {
+ if (_unicode)
+ return ((glui32 *)_bufPtr - (glui32 *)_buf);
+ else
+ return ((unsigned char *)_bufPtr - (unsigned char *)_buf);
+}
+
+void MemoryStream::setPosition(glui32 pos, glui32 seekMode) {
+ if (!_unicode)
+ {
+ if (seekMode == seekmode_Current)
+ pos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + pos;
+ else if (seekMode == seekmode_End)
+ pos = ((unsigned char *)_bufEof - (unsigned char *)_buf) + pos;
+ else
+ /* pos = pos */;
+ if (pos < 0)
+ pos = 0;
+ if (pos > (glui32)((unsigned char *)_bufEof - (unsigned char *)_buf))
+ pos = ((unsigned char *)_bufEof - (unsigned char *)_buf);
+ _bufPtr = (unsigned char *)_buf + pos;
+ } else {
+ if (seekMode == seekmode_Current)
+ pos = ((glui32 *)_bufPtr - (glui32 *)_buf) + pos;
+ else if (seekMode == seekmode_End)
+ pos = ((glui32 *)_bufEof - (glui32 *)_buf) + pos;
+
+ if (pos < 0)
+ pos = 0;
+ if (pos > (glui32)((glui32 *)_bufEof - (glui32 *)_buf))
+ pos = ((glui32 *)_bufEof - (glui32 *)_buf);
+ _bufPtr = (glui32 *)_buf + pos;
+ }
+}
+
+glsi32 MemoryStream::getChar() {
+ if (!_readable)
+ return -1;
+
+ if (_bufPtr < _bufEnd) {
+ if (!_unicode) {
+ unsigned char ch;
+ ch = *((unsigned char *)_bufPtr);
+ _bufPtr = ((unsigned char *)_bufPtr) + 1;
+ _readCount++;
+ return ch;
+ } else {
+ glui32 ch;
+ ch = *((glui32 *)_bufPtr);
+ _bufPtr = ((glui32 *)_bufPtr) + 1;
+ _readCount++;
+ if (ch > 0xff)
+ ch = '?';
+ return ch;
+ }
+ } else {
+ return -1;
+ }
+}
+
/*--------------------------------------------------------------------------*/
FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) :
@@ -409,6 +481,148 @@ void FileStream::putCharUtf8(glui32 val) {
}
}
+glsi32 FileStream::getCharUtf8() {
+ glui32 res;
+ glui32 val0, val1, val2, val3;
+
+ if (_inFile->eos())
+ return -1;
+ val0 = _inFile->readByte();
+ if (val0 < 0x80) {
+ res = val0;
+ return res;
+ }
+
+ if ((val0 & 0xe0) == 0xc0) {
+ if (_inFile->eos()) {
+ warning("incomplete two-byte character");
+ return -1;
+ }
+
+ val1 = _inFile->readByte();
+ if ((val1 & 0xc0) != 0x80) {
+ warning("malformed two-byte character");
+ return '?';
+ }
+
+ res = (val0 & 0x1f) << 6;
+ res |= (val1 & 0x3f);
+ return res;
+ }
+
+ if ((val0 & 0xf0) == 0xe0) {
+ val1 = _inFile->readByte();
+ val2 = _inFile->readByte();
+ if (_inFile->eos()) {
+ warning("incomplete three-byte character");
+ return -1;
+ }
+ if ((val1 & 0xc0) != 0x80) {
+ warning("malformed three-byte character");
+ return '?';
+ }
+ if ((val2 & 0xc0) != 0x80) {
+ warning("malformed three-byte character");
+ return '?';
+ }
+
+ res = (((val0 & 0xf) << 12) & 0x0000f000);
+ res |= (((val1 & 0x3f) << 6) & 0x00000fc0);
+ res |= (((val2 & 0x3f)) & 0x0000003f);
+ return res;
+ }
+
+ if ((val0 & 0xf0) == 0xf0) {
+ if ((val0 & 0xf8) != 0xf0) {
+ warning("malformed four-byte character");
+ return '?';
+ }
+
+ val1 = _inFile->readByte();
+ val2 = _inFile->readByte();
+ val3 = _inFile->readByte();
+ if (_inFile->eos()) {
+ warning("incomplete four-byte character");
+ return -1;
+ }
+ if ((val1 & 0xc0) != 0x80) {
+ warning("malformed four-byte character");
+ return '?';
+ }
+ if ((val2 & 0xc0) != 0x80) {
+ warning("malformed four-byte character");
+ return '?';
+ }
+ if ((val3 & 0xc0) != 0x80) {
+ warning("malformed four-byte character");
+ return '?';
+ }
+
+ res = (((val0 & 0x7) << 18) & 0x1c0000);
+ res |= (((val1 & 0x3f) << 12) & 0x03f000);
+ res |= (((val2 & 0x3f) << 6) & 0x000fc0);
+ res |= (((val3 & 0x3f)) & 0x00003f);
+ return res;
+ }
+
+ warning("malformed character");
+ return '?';
+}
+
+glui32 FileStream::getPosition() const {
+ return _outFile->pos();
+}
+
+void FileStream::setPosition(glui32 pos, glui32 seekMode) {
+ _lastOp = 0;
+ if (_unicode)
+ pos *= 4;
+
+ error("FileStream::setPosition - seek not yet supported");
+// fseek(str->file, pos, ((seekmode == seekmode_Current) ? 1 :
+ // ((seekmode == seekmode_End) ? 2 : 0)));
+}
+
+glsi32 FileStream::getChar() {
+ if (!_readable)
+ return -1;
+
+ ensureOp(filemode_Read);
+ int res;
+ if (!_unicode) {
+ res = _inFile->readByte();
+ } else if (_textFile) {
+ res = getCharUtf8();
+ } else {
+ glui32 ch;
+ res = _inFile->readByte();
+ if (_inFile->eos())
+ return -1;
+ ch = (res & 0xFF);
+ res = _inFile->readByte();
+ if (_inFile->eos())
+ return -1;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (_inFile->eos())
+ return -1;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (_inFile->eos())
+ return -1;
+ ch = (ch << 8) | (res & 0xFF);
+ res = ch;
+ }
+ if (res != -1) {
+ _readCount++;
+ if (res >= 0x100)
+ return '?';
+ return (glsi32)res;
+ } else {
+ return -1;
+ }
+}
+
/*--------------------------------------------------------------------------*/
Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) {
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 51ab484..8b7da6f 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -32,6 +32,15 @@ namespace Gargoyle {
class Window;
class Streams;
+struct FileReference {
+ glui32 _rock;
+ Common::String _filename;
+ int _fileType;
+ int _textMode;
+ gidispatch_rock_t _dispRock;
+};
+typedef FileReference *frefid_t;
+
struct StreamResult {
uint32 _readCount;
uint32 _writeCount;
@@ -117,6 +126,14 @@ public:
putBufferUni(buf, len);
putCharUni('\n');
}
+
+ virtual glui32 getPosition() const { return 0; }
+
+ virtual void setPosition(glui32 pos, glui32 seekMode) {}
+
+ virtual void setStyle(glui32 val) {}
+
+ virtual glsi32 getChar() { return -1; }
};
typedef Stream *strid_t;
@@ -157,6 +174,8 @@ public:
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ virtual void setStyle(glui32 val) override;
};
/**
@@ -194,6 +213,12 @@ public:
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ virtual glui32 getPosition() const override;
+
+ virtual void setPosition(glui32 pos, glui32 seekMode) override;
+
+ virtual glsi32 getChar() override;
};
/**
@@ -215,6 +240,11 @@ private:
* Put a UTF8 character
*/
void putCharUtf8(glui32 val);
+
+ /**
+ * Get a UTF8 character
+ */
+ glsi32 getCharUtf8();
public:
/**
* Constructor
@@ -240,6 +270,12 @@ public:
* Write a unicode character
*/
virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ virtual glui32 getPosition() const override;
+
+ virtual void setPosition(glui32 pos, glui32 seekMode) override;
+
+ virtual glsi32 getChar() override;
};
/**
Commit: 734366ce8919824336a1bbe543130e9d96b1e464
https://github.com/scummvm/scummvm/commit/734366ce8919824336a1bbe543130e9d96b1e464
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added more glk stream commands
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 1993375..2f26aee 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -655,13 +655,21 @@ void Glk::glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len)
}
glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
- // TODO
- return 0;
+ if (str) {
+ return str->getCharUni();
+ } else {
+ warning("get_char_stream_uni: invalid ref");
+ return -1;
+ }
}
glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- // TODO
- return 0;
+ if (str) {
+ return str->getBufferUni(buf, len);
+ } else {
+ warning("get_buffer_stream_uni: invalid ref");
+ return 0;
+ }
}
glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 6a73c5b..42b89eb 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -369,6 +369,81 @@ glsi32 MemoryStream::getChar() {
}
}
+glsi32 MemoryStream::getCharUni() {
+ if (!_readable)
+ return -1;
+
+ if (_bufPtr < _bufEnd) {
+ if (!_unicode) {
+ unsigned char ch;
+ ch = *((unsigned char *)_bufPtr);
+ _bufPtr = ((unsigned char *)_bufPtr) + 1;
+ _readCount++;
+ return ch;
+ } else {
+ glui32 ch;
+ ch = *((glui32 *)_bufPtr);
+ _bufPtr = ((glui32 *)_bufPtr) + 1;
+ _readCount++;
+ return ch;
+ }
+ } else {
+ return -1;
+ }
+}
+
+glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
+ if (!_readable)
+ return 0;
+
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if (!_unicode) {
+ unsigned char *bp = (unsigned char *)_bufPtr;
+ if (bp + len > (unsigned char *)_bufEnd)
+ {
+ glui32 lx;
+ lx = (bp + len) - (unsigned char *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ glui32 i;
+ for (i = 0; i < len; i++)
+ buf[i] = bp[i];
+ bp += len;
+ if (bp >(unsigned char *)_bufEof)
+ _bufEof = bp;
+ }
+ _readCount += len;
+ _bufPtr = bp;
+ } else {
+ glui32 *bp = (glui32 *)_bufPtr;
+ if (bp + len > (glui32 *)_bufEnd) {
+ glui32 lx;
+ lx = (bp + len) - (glui32 *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ memcpy(buf, bp, len * 4);
+ bp += len;
+ if (bp >(glui32 *)_bufEof)
+ _bufEof = bp;
+ }
+ _readCount += len;
+ _bufPtr = bp;
+ }
+ }
+
+ return len;
+}
+
/*--------------------------------------------------------------------------*/
FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) :
@@ -623,6 +698,103 @@ glsi32 FileStream::getChar() {
}
}
+glsi32 FileStream::getCharUni() {
+ if (!_readable)
+ return -1;
+
+ ensureOp(filemode_Read);
+ int res;
+ if (!_unicode) {
+ res = _inFile->readByte();
+ } else if (_textFile) {
+ res = getCharUtf8();
+ } else {
+ glui32 ch;
+ res = _inFile->readByte();
+ if (res == -1)
+ return -1;
+ ch = (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ return -1;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ return -1;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ return -1;
+ ch = (ch << 8) | (res & 0xFF);
+ res = ch;
+ }
+ if (res != -1) {
+ _readCount++;
+ return (glsi32)res;
+ } else {
+ return -1;
+ }
+}
+
+
+glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
+ if (!_readable)
+ return 0;
+
+ ensureOp(filemode_Read);
+ if (!_unicode) {
+ glui32 lx;
+ for (lx = 0; lx<len; lx++) {
+ int res;
+ glui32 ch;
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (res & 0xFF);
+ _readCount++;
+ buf[lx] = ch;
+ }
+ return lx;
+ } else if (_textFile) {
+ glui32 lx;
+ for (lx = 0; lx<len; lx++) {
+ glui32 ch;
+ ch = getCharUtf8();
+ if (ch == -1)
+ break;
+ _readCount++;
+ buf[lx] = ch;
+ }
+ return lx;
+ } else {
+ glui32 lx;
+ for (lx = 0; lx<len; lx++)
+ {
+ int res;
+ glui32 ch;
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ _readCount++;
+ buf[lx] = ch;
+ }
+ return lx;
+ }
+}
+
/*--------------------------------------------------------------------------*/
Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) {
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 8b7da6f..ff0f9be 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -133,7 +133,20 @@ public:
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 unicode buffer
+ */
+ virtual glui32 getBufferUni(glui32 *buf, glui32 len) { return 0; }
};
typedef Stream *strid_t;
@@ -218,7 +231,20 @@ public:
virtual void setPosition(glui32 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 unicode buffer
+ */
+ virtual glui32 getBufferUni(glui32 *buf, glui32 len) override;
};
/**
@@ -275,7 +301,20 @@ public:
virtual void setPosition(glui32 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 unicode buffer
+ */
+ virtual glui32 getBufferUni(glui32 *buf, glui32 len) override;
};
/**
Commit: 4bb596792005f3a696a29fdd038809133bfb8119
https://github.com/scummvm/scummvm/commit/4bb596792005f3a696a29fdd038809133bfb8119
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: More glk stream functions
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 2f26aee..35b8563 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -673,8 +673,12 @@ glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
}
glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- // TODO
- return 0;
+ if (str) {
+ return str->getLineUni(buf, len);
+ } else {
+ warning("get_line_stream_uni: invalid ref");
+ return -1;
+ }
}
strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock) {
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 42b89eb..1942ddf 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -444,6 +444,60 @@ glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
return len;
}
+glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) {
+ bool gotNewline;
+ int lx;
+
+ if (!_readable || len == 0)
+ return 0;
+
+ len -= 1; // for the terminal null
+ if (!_unicode) {
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if ((char *)_bufPtr + len > (char *)_bufEnd) {
+ lx = ((char *)_bufPtr + len) - (char *)_bufEnd;
+ if (lx < (int)len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ }
+ gotNewline = false;
+ for (lx = 0; lx < (int)len && !gotNewline; lx++) {
+ ubuf[lx] = ((unsigned char *)_bufPtr)[lx];
+ gotNewline = (ubuf[lx] == '\n');
+ }
+ ubuf[lx] = '\0';
+ _bufPtr = ((unsigned char *)_bufPtr) + lx;
+ } else {
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if ((glui32 *)_bufPtr + len > (glui32 *)_bufEnd) {
+ lx = ((glui32 *)_bufPtr + len) - (glui32 *)_bufEnd;
+ if (lx < (int)len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ }
+ gotNewline = false;
+ for (lx = 0; lx < (int)len && !gotNewline; lx++) {
+ glui32 ch;
+ ch = ((glui32 *)_bufPtr)[lx];
+ ubuf[lx] = ch;
+ gotNewline = (ch == '\n');
+ }
+ ubuf[lx] = '\0';
+ _bufPtr = ((glui32 *)_bufPtr) + lx;
+ }
+
+ _readCount += lx;
+ return lx;
+}
+
/*--------------------------------------------------------------------------*/
FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) :
@@ -795,6 +849,75 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
}
}
+glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
+ bool gotNewline;
+ int lx;
+
+ if (!_readable || len == 0)
+ return 0;
+
+ ensureOp(filemode_Read);
+ if (!_unicode) {
+ len -= 1; // for the terminal null
+ gotNewline = false;
+ for (lx = 0; lx < (int)len && !gotNewline; lx++) {
+ int res;
+ glui32 ch;
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (res & 0xFF);
+ _readCount++;
+ ubuf[lx] = ch;
+ gotNewline = (ch == '\n');
+ }
+ ubuf[lx] = '\0';
+ return lx;
+ } else if (_textFile) {
+ len -= 1; /* for the terminal null */
+ gotNewline = false;
+ for (lx = 0; lx < (int)len && !gotNewline; lx++) {
+ glui32 ch;
+ ch = getCharUtf8();
+ if (ch == -1)
+ break;
+ _readCount++;
+ ubuf[lx] = ch;
+ gotNewline = (ch == '\n');
+ }
+ ubuf[lx] = '\0';
+ return lx;
+ } else {
+ len -= 1; // for the terminal null
+ gotNewline = false;
+ for (lx = 0; lx < (int)len && !gotNewline; lx++) {
+ int res;
+ glui32 ch;
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inFile->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ _readCount++;
+ ubuf[lx] = ch;
+ gotNewline = (ch == '\n');
+ }
+ ubuf[lx] = '\0';
+ return lx;
+ }
+}
+
/*--------------------------------------------------------------------------*/
Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) {
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index ff0f9be..77ae8cb 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -147,6 +147,12 @@ public:
* Get a unicode buffer
*/
virtual glui32 getBufferUni(glui32 *buf, glui32 len) { return 0; }
+
+ /**
+ * Get a unicode line
+ */
+ virtual glui32 getLineUni(glui32 *ubuf, glui32 len) { return 0; }
+
};
typedef Stream *strid_t;
@@ -245,6 +251,11 @@ public:
* Get a unicode buffer
*/
virtual glui32 getBufferUni(glui32 *buf, glui32 len) override;
+
+ /**
+ * Get a unicode line
+ */
+ virtual glui32 getLineUni(glui32 *ubuf, glui32 len) override;
};
/**
@@ -315,6 +326,11 @@ public:
* Get a unicode buffer
*/
virtual glui32 getBufferUni(glui32 *buf, glui32 len) override;
+
+ /**
+ * Get a unicode line
+ */
+ virtual glui32 getLineUni(glui32 *ubuf, glui32 len) override;
};
/**
Commit: 98f1ddc968152df85790380aef73f8cc6ca50f13
https://github.com/scummvm/scummvm/commit/98f1ddc968152df85790380aef73f8cc6ca50f13
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added unicode case methods
Changed paths:
A engines/gargoyle/unicode.cpp
A engines/gargoyle/unicode.h
A engines/gargoyle/unicode_gen.cpp
A engines/gargoyle/unicode_gen.h
R engines/gargoyle/string.cpp
R engines/gargoyle/string.h
engines/gargoyle/conf.cpp
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/module.mk
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 125e9f4..e2b8d04 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -22,7 +22,7 @@
#include "gargoyle/conf.h"
#include "gargoyle/fonts.h"
-#include "gargoyle/string.h"
+#include "gargoyle/unicode.h"
#include "gargoyle/windows.h"
#include "common/config-manager.h"
#include "common/system.h"
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 35b8563..c385482 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -25,7 +25,7 @@
#include "gargoyle/events.h"
#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
-#include "gargoyle/string.h"
+#include "gargoyle/unicode.h"
#include "gargoyle/windows.h"
#include "gargoyle/window_graphics.h"
#include "gargoyle/window_text_buffer.h"
@@ -576,8 +576,6 @@ void Glk::glk_cancel_mouse_event(winid_t win) {
}
}
-#ifdef GLK_MODULE_LINE_ECHO
-
void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
if (!win) {
warning("set_echo_line_event: invalid ref");
@@ -586,10 +584,6 @@ void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
}
}
-#endif /* GLK_MODULE_LINE_ECHO */
-
-#ifdef GLK_MODULE_LINE_TERMINATORS
-
void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
if (!win) {
warning("set_terminators_line_event: invalid ref");
@@ -598,24 +592,17 @@ void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 c
}
}
-#endif /* GLK_MODULE_LINE_TERMINATORS */
-
-#ifdef GLK_MODULE_UNICODE
-
glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- // TODO
- return 0;
+ return bufferChangeCase(buf, len, numchars, CASE_LOWER, COND_ALL, true);
}
glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- // TODO
- return 0;
+ return bufferChangeCase(buf, len, numchars, CASE_UPPER, COND_ALL, true);
}
glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
glui32 numchars, glui32 lowerrest) {
- // TODO
- return 0;
+ return bufferChangeCase(buf, len, numchars, CASE_TITLE, COND_LINESTART, lowerrest);
}
void Glk::glk_put_char_uni(glui32 ch) {
@@ -677,7 +664,7 @@ glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
return str->getLineUni(buf, len);
} else {
warning("get_line_stream_uni: invalid ref");
- return -1;
+ return (glui32 )-1;
}
}
@@ -712,10 +699,6 @@ void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, gl
}
}
-#endif /* GLK_MODULE_UNICODE */
-
-#ifdef GLK_MODULE_UNICODE_NORM
-
glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
glui32 numchars) {
// TODO
@@ -726,10 +709,6 @@ glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numch
return 0;
}
-#endif /* GLK_MODULE_UNICODE_NORM */
-
-#ifdef GLK_MODULE_IMAGE
-
glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
if (!win) {
warning("image_draw: invalid ref");
@@ -812,10 +791,6 @@ void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
}
}
-#endif /* GLK_MODULE_IMAGE */
-
-#ifdef GLK_MODULE_SOUND
-
schanid_t Glk::glk_schannel_create(glui32 rock) {
// TODO
return nullptr;
@@ -857,8 +832,6 @@ void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
// TODO
}
-#ifdef GLK_MODULE_SOUND2
-
schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
// TODO
return nullptr;
@@ -883,11 +856,6 @@ void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
// TODO
}
-#endif /* GLK_MODULE_SOUND2 */
-#endif /* GLK_MODULE_SOUND */
-
-#ifdef GLK_MODULE_HYPERLINKS
-
void Glk::glk_set_hyperlink(glui32 linkval) {
// TODO
}
@@ -908,10 +876,6 @@ void Glk::glk_cancel_hyperlink_event(winid_t win) {
// TODO
}
-#endif /* GLK_MODULE_HYPERLINKS */
-
-#ifdef GLK_MODULE_DATETIME
-
void Glk::glk_current_time(glktimeval_t *time) {
// TODO
}
@@ -955,8 +919,6 @@ glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
return 0;
}
-#endif /* GLK_MODULE_DATETIME */
-
/* XXX non-official Glk functions that may or may not exist */
char *garglk_fileref_get_name(frefid_t fref) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 3b49421..34531c0 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -157,7 +157,9 @@ public:
glui32 count);
#endif /* GLK_MODULE_LINE_TERMINATORS */
-#ifdef GLK_MODULE_UNICODE
+ /** \addtogroup Unicode
+ * @{
+ */
glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
glui32 numchars);
@@ -184,7 +186,7 @@ public:
void glk_request_line_event_uni(winid_t win, glui32 *buf,
glui32 maxlen, glui32 initlen);
-#endif /* GLK_MODULE_UNICODE */
+ /** @}*/
#ifdef GLK_MODULE_UNICODE_NORM
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index e2584b4..d3cf7a1 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -10,7 +10,8 @@ MODULE_OBJS := \
picture.o \
screen.o \
streams.o \
- string.o \
+ unicode.o \
+ unicode_gen.o \
windows.o \
window_mask.o \
window_graphics.o \
diff --git a/engines/gargoyle/string.cpp b/engines/gargoyle/string.cpp
deleted file mode 100644
index 4b68978..0000000
--- a/engines/gargoyle/string.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/conf.h"
-#include "common/textconsole.h"
-
-namespace Gargoyle {
-
-size_t strlen_uni(const uint32 *s) {
- size_t len = 0;
- while (*s++)
- ++len;
- return len;
-}
-
-int strToInt(const char *s) {
- if (!*s)
- // No string at all
- return 0;
- else if (toupper(s[strlen(s) - 1]) != 'H')
- // Standard decimal string
- return atoi(s);
-
- // Hexadecimal string
- uint tmp = 0;
- int read = sscanf(s, "%xh", &tmp);
- if (read < 1)
- error("strToInt failed on string \"%s\"", s);
- return (int)tmp;
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/string.h b/engines/gargoyle/string.h
deleted file mode 100644
index 2ab2925..0000000
--- a/engines/gargoyle/string.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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 GARGOYLE_STRING_H
-#define GARGOYLE_STRING_H
-
-#include "gargoyle/string.h"
-#include "gargoyle/glk_types.h"
-
-namespace Gargoyle {
-
-/*
- * Get the length of a unicode string
- */
-size_t strlen_uni(const uint32 *s);
-
-/**
- * Converts a decimal or hexadecimal string into a number
- */
-int strToInt(const char *s);
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/unicode.cpp b/engines/gargoyle/unicode.cpp
new file mode 100644
index 0000000..601d8f0
--- /dev/null
+++ b/engines/gargoyle/unicode.cpp
@@ -0,0 +1,168 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/unicode.h"
+#include "gargoyle/unicode_gen.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+
+size_t strlen_uni(const uint32 *s) {
+ size_t len = 0;
+ while (*s++)
+ ++len;
+ return len;
+}
+
+int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCase destcase,
+ BufferChangeCond cond, int changerest) {
+ glui32 ix, jx;
+ glui32 *outbuf;
+ glui32 *newoutbuf;
+ glui32 outcount;
+ int dest_block_rest = 0, dest_block_first = 0;
+ int dest_spec_rest = 0, dest_spec_first = 0;
+
+ switch (cond) {
+ case COND_ALL:
+ dest_spec_rest = destcase;
+ dest_spec_first = destcase;
+ break;
+ case COND_LINESTART:
+ if (changerest)
+ dest_spec_rest = CASE_LOWER;
+ else
+ dest_spec_rest = CASE_IDENT;
+ dest_spec_first = destcase;
+ break;
+ }
+
+ dest_block_rest = dest_spec_rest;
+ if (dest_block_rest == CASE_TITLE)
+ dest_block_rest = CASE_UPPER;
+ dest_block_first = dest_spec_first;
+ if (dest_block_first == CASE_TITLE)
+ dest_block_first = CASE_UPPER;
+
+ newoutbuf = NULL;
+ outcount = 0;
+ outbuf = buf;
+
+ for (ix = 0; ix < numchars; ix++) {
+ int target;
+ int isfirst;
+ glui32 res;
+ glui32 *special;
+ glui32 *ptr;
+ glui32 speccount;
+ glui32 ch = buf[ix];
+
+ isfirst = (ix == 0);
+
+ target = (isfirst ? dest_block_first : dest_block_rest);
+
+ if (target == CASE_IDENT) {
+ res = ch;
+ } else {
+ gli_case_block_t *block;
+
+ GET_CASE_BLOCK(ch, &block);
+ if (!block)
+ res = ch;
+ else
+ res = block[ch & 0xFF][target];
+ }
+
+ if (res != 0xFFFFFFFF || res == ch)
+ {
+ /* simple case */
+ if (outcount < len)
+ outbuf[outcount] = res;
+ outcount++;
+ continue;
+ }
+
+ target = (isfirst ? dest_spec_first : dest_spec_rest);
+
+ /* complicated cases */
+ GET_CASE_SPECIAL(ch, &special);
+ if (!special) {
+ warning("inconsistency in cgunigen.c");
+ continue;
+ }
+ ptr = &unigen_special_array[special[target]];
+ speccount = *(ptr++);
+
+ if (speccount == 1) {
+ /* simple after all */
+ if (outcount < len)
+ outbuf[outcount] = ptr[0];
+ outcount++;
+ continue;
+ }
+
+ // Now we have to allocate a new buffer, if we haven't already.
+ if (!newoutbuf) {
+ newoutbuf = new glui32[len + 1];
+ if (!newoutbuf)
+ return 0;
+ if (outcount)
+ memcpy(newoutbuf, buf, outcount * sizeof(glui32));
+ outbuf = newoutbuf;
+ }
+
+ for (jx = 0; jx<speccount; jx++) {
+ if (outcount < len)
+ outbuf[outcount] = ptr[jx];
+ outcount++;
+ }
+ }
+
+ if (newoutbuf) {
+ glui32 finallen = outcount;
+ if (finallen > len)
+ finallen = len;
+ if (finallen)
+ memcpy(buf, newoutbuf, finallen * sizeof(glui32));
+ free(newoutbuf);
+ }
+
+ return outcount;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/unicode.h b/engines/gargoyle/unicode.h
new file mode 100644
index 0000000..806a63f
--- /dev/null
+++ b/engines/gargoyle/unicode.h
@@ -0,0 +1,56 @@
+/* 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 GARGOYLE_UNICODE_H
+#define GARGOYLE_UNICODE_H
+
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+typedef glui32 gli_case_block_t[2]; /* upper, lower */
+enum BufferChangeCase { CASE_UPPER = 0, CASE_LOWER = 1, CASE_TITLE = 2, CASE_IDENT = 3 };
+enum BufferChangeCond { COND_ALL = 0, COND_LINESTART = 1 };
+
+/*
+ * Get the length of a unicode string
+ */
+size_t strlen_uni(const uint32 *s);
+
+/**
+ * Apply a case change to the buffer. The len is the length of the buffer
+ * array; numchars is the number of characters originally in it. (This
+ * may be less than len.) The result will be clipped to fit len, but
+ * the return value will be the full number of characters that the
+ *converted string should have contained.
+ */
+extern glui32 bufferChangeCase(glui32 *buf, glui32 len,
+ glui32 numchars, BufferChangeCase destcase, BufferChangeCond cond, int changerest);
+
+/**
+ * Converts a decimal or hexadecimal string into a number
+ */
+int strToInt(const char *s);
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/unicode_gen.cpp b/engines/gargoyle/unicode_gen.cpp
new file mode 100644
index 0000000..a6b0bc5
--- /dev/null
+++ b/engines/gargoyle/unicode_gen.cpp
@@ -0,0 +1,11825 @@
+/* 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.
+ *
+ */
+
+/**
+ * This file is based on one that was generated by casemap.py.
+ * Derived from Unicode data files, Unicode version 4.0.1.
+ */
+
+#include "gargoyle/unicode_gen.h"
+
+namespace Gargoyle {
+
+gli_case_block_t unigen_case_block_0x0[256] = {
+ { 0x0, 0x0 },
+ { 0x1, 0x1 },
+ { 0x2, 0x2 },
+ { 0x3, 0x3 },
+ { 0x4, 0x4 },
+ { 0x5, 0x5 },
+ { 0x6, 0x6 },
+ { 0x7, 0x7 },
+ { 0x8, 0x8 },
+ { 0x9, 0x9 },
+ { 0xa, 0xa },
+ { 0xb, 0xb },
+ { 0xc, 0xc },
+ { 0xd, 0xd },
+ { 0xe, 0xe },
+ { 0xf, 0xf },
+ { 0x10, 0x10 },
+ { 0x11, 0x11 },
+ { 0x12, 0x12 },
+ { 0x13, 0x13 },
+ { 0x14, 0x14 },
+ { 0x15, 0x15 },
+ { 0x16, 0x16 },
+ { 0x17, 0x17 },
+ { 0x18, 0x18 },
+ { 0x19, 0x19 },
+ { 0x1a, 0x1a },
+ { 0x1b, 0x1b },
+ { 0x1c, 0x1c },
+ { 0x1d, 0x1d },
+ { 0x1e, 0x1e },
+ { 0x1f, 0x1f },
+ { 0x20, 0x20 },
+ { 0x21, 0x21 },
+ { 0x22, 0x22 },
+ { 0x23, 0x23 },
+ { 0x24, 0x24 },
+ { 0x25, 0x25 },
+ { 0x26, 0x26 },
+ { 0x27, 0x27 },
+ { 0x28, 0x28 },
+ { 0x29, 0x29 },
+ { 0x2a, 0x2a },
+ { 0x2b, 0x2b },
+ { 0x2c, 0x2c },
+ { 0x2d, 0x2d },
+ { 0x2e, 0x2e },
+ { 0x2f, 0x2f },
+ { 0x30, 0x30 },
+ { 0x31, 0x31 },
+ { 0x32, 0x32 },
+ { 0x33, 0x33 },
+ { 0x34, 0x34 },
+ { 0x35, 0x35 },
+ { 0x36, 0x36 },
+ { 0x37, 0x37 },
+ { 0x38, 0x38 },
+ { 0x39, 0x39 },
+ { 0x3a, 0x3a },
+ { 0x3b, 0x3b },
+ { 0x3c, 0x3c },
+ { 0x3d, 0x3d },
+ { 0x3e, 0x3e },
+ { 0x3f, 0x3f },
+ { 0x40, 0x40 },
+ { 0x41, 0x61 }, /* upper */
+ { 0x42, 0x62 }, /* upper */
+ { 0x43, 0x63 }, /* upper */
+ { 0x44, 0x64 }, /* upper */
+ { 0x45, 0x65 }, /* upper */
+ { 0x46, 0x66 }, /* upper */
+ { 0x47, 0x67 }, /* upper */
+ { 0x48, 0x68 }, /* upper */
+ { 0x49, 0x69 }, /* upper */
+ { 0x4a, 0x6a }, /* upper */
+ { 0x4b, 0x6b }, /* upper */
+ { 0x4c, 0x6c }, /* upper */
+ { 0x4d, 0x6d }, /* upper */
+ { 0x4e, 0x6e }, /* upper */
+ { 0x4f, 0x6f }, /* upper */
+ { 0x50, 0x70 }, /* upper */
+ { 0x51, 0x71 }, /* upper */
+ { 0x52, 0x72 }, /* upper */
+ { 0x53, 0x73 }, /* upper */
+ { 0x54, 0x74 }, /* upper */
+ { 0x55, 0x75 }, /* upper */
+ { 0x56, 0x76 }, /* upper */
+ { 0x57, 0x77 }, /* upper */
+ { 0x58, 0x78 }, /* upper */
+ { 0x59, 0x79 }, /* upper */
+ { 0x5a, 0x7a }, /* upper */
+ { 0x5b, 0x5b },
+ { 0x5c, 0x5c },
+ { 0x5d, 0x5d },
+ { 0x5e, 0x5e },
+ { 0x5f, 0x5f },
+ { 0x60, 0x60 },
+ { 0x41, 0x61 }, /* lower */
+ { 0x42, 0x62 }, /* lower */
+ { 0x43, 0x63 }, /* lower */
+ { 0x44, 0x64 }, /* lower */
+ { 0x45, 0x65 }, /* lower */
+ { 0x46, 0x66 }, /* lower */
+ { 0x47, 0x67 }, /* lower */
+ { 0x48, 0x68 }, /* lower */
+ { 0x49, 0x69 }, /* lower */
+ { 0x4a, 0x6a }, /* lower */
+ { 0x4b, 0x6b }, /* lower */
+ { 0x4c, 0x6c }, /* lower */
+ { 0x4d, 0x6d }, /* lower */
+ { 0x4e, 0x6e }, /* lower */
+ { 0x4f, 0x6f }, /* lower */
+ { 0x50, 0x70 }, /* lower */
+ { 0x51, 0x71 }, /* lower */
+ { 0x52, 0x72 }, /* lower */
+ { 0x53, 0x73 }, /* lower */
+ { 0x54, 0x74 }, /* lower */
+ { 0x55, 0x75 }, /* lower */
+ { 0x56, 0x76 }, /* lower */
+ { 0x57, 0x77 }, /* lower */
+ { 0x58, 0x78 }, /* lower */
+ { 0x59, 0x79 }, /* lower */
+ { 0x5a, 0x7a }, /* lower */
+ { 0x7b, 0x7b },
+ { 0x7c, 0x7c },
+ { 0x7d, 0x7d },
+ { 0x7e, 0x7e },
+ { 0x7f, 0x7f },
+ { 0x80, 0x80 },
+ { 0x81, 0x81 },
+ { 0x82, 0x82 },
+ { 0x83, 0x83 },
+ { 0x84, 0x84 },
+ { 0x85, 0x85 },
+ { 0x86, 0x86 },
+ { 0x87, 0x87 },
+ { 0x88, 0x88 },
+ { 0x89, 0x89 },
+ { 0x8a, 0x8a },
+ { 0x8b, 0x8b },
+ { 0x8c, 0x8c },
+ { 0x8d, 0x8d },
+ { 0x8e, 0x8e },
+ { 0x8f, 0x8f },
+ { 0x90, 0x90 },
+ { 0x91, 0x91 },
+ { 0x92, 0x92 },
+ { 0x93, 0x93 },
+ { 0x94, 0x94 },
+ { 0x95, 0x95 },
+ { 0x96, 0x96 },
+ { 0x97, 0x97 },
+ { 0x98, 0x98 },
+ { 0x99, 0x99 },
+ { 0x9a, 0x9a },
+ { 0x9b, 0x9b },
+ { 0x9c, 0x9c },
+ { 0x9d, 0x9d },
+ { 0x9e, 0x9e },
+ { 0x9f, 0x9f },
+ { 0xa0, 0xa0 },
+ { 0xa1, 0xa1 },
+ { 0xa2, 0xa2 },
+ { 0xa3, 0xa3 },
+ { 0xa4, 0xa4 },
+ { 0xa5, 0xa5 },
+ { 0xa6, 0xa6 },
+ { 0xa7, 0xa7 },
+ { 0xa8, 0xa8 },
+ { 0xa9, 0xa9 },
+ { 0xaa, 0xaa },
+ { 0xab, 0xab },
+ { 0xac, 0xac },
+ { 0xad, 0xad },
+ { 0xae, 0xae },
+ { 0xaf, 0xaf },
+ { 0xb0, 0xb0 },
+ { 0xb1, 0xb1 },
+ { 0xb2, 0xb2 },
+ { 0xb3, 0xb3 },
+ { 0xb4, 0xb4 },
+ { 0x39c, 0xb5 }, /* lower */
+ { 0xb6, 0xb6 },
+ { 0xb7, 0xb7 },
+ { 0xb8, 0xb8 },
+ { 0xb9, 0xb9 },
+ { 0xba, 0xba },
+ { 0xbb, 0xbb },
+ { 0xbc, 0xbc },
+ { 0xbd, 0xbd },
+ { 0xbe, 0xbe },
+ { 0xbf, 0xbf },
+ { 0xc0, 0xe0 }, /* upper */
+ { 0xc1, 0xe1 }, /* upper */
+ { 0xc2, 0xe2 }, /* upper */
+ { 0xc3, 0xe3 }, /* upper */
+ { 0xc4, 0xe4 }, /* upper */
+ { 0xc5, 0xe5 }, /* upper */
+ { 0xc6, 0xe6 }, /* upper */
+ { 0xc7, 0xe7 }, /* upper */
+ { 0xc8, 0xe8 }, /* upper */
+ { 0xc9, 0xe9 }, /* upper */
+ { 0xca, 0xea }, /* upper */
+ { 0xcb, 0xeb }, /* upper */
+ { 0xcc, 0xec }, /* upper */
+ { 0xcd, 0xed }, /* upper */
+ { 0xce, 0xee }, /* upper */
+ { 0xcf, 0xef }, /* upper */
+ { 0xd0, 0xf0 }, /* upper */
+ { 0xd1, 0xf1 }, /* upper */
+ { 0xd2, 0xf2 }, /* upper */
+ { 0xd3, 0xf3 }, /* upper */
+ { 0xd4, 0xf4 }, /* upper */
+ { 0xd5, 0xf5 }, /* upper */
+ { 0xd6, 0xf6 }, /* upper */
+ { 0xd7, 0xd7 },
+ { 0xd8, 0xf8 }, /* upper */
+ { 0xd9, 0xf9 }, /* upper */
+ { 0xda, 0xfa }, /* upper */
+ { 0xdb, 0xfb }, /* upper */
+ { 0xdc, 0xfc }, /* upper */
+ { 0xdd, 0xfd }, /* upper */
+ { 0xde, 0xfe }, /* upper */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xc0, 0xe0 }, /* lower */
+ { 0xc1, 0xe1 }, /* lower */
+ { 0xc2, 0xe2 }, /* lower */
+ { 0xc3, 0xe3 }, /* lower */
+ { 0xc4, 0xe4 }, /* lower */
+ { 0xc5, 0xe5 }, /* lower */
+ { 0xc6, 0xe6 }, /* lower */
+ { 0xc7, 0xe7 }, /* lower */
+ { 0xc8, 0xe8 }, /* lower */
+ { 0xc9, 0xe9 }, /* lower */
+ { 0xca, 0xea }, /* lower */
+ { 0xcb, 0xeb }, /* lower */
+ { 0xcc, 0xec }, /* lower */
+ { 0xcd, 0xed }, /* lower */
+ { 0xce, 0xee }, /* lower */
+ { 0xcf, 0xef }, /* lower */
+ { 0xd0, 0xf0 }, /* lower */
+ { 0xd1, 0xf1 }, /* lower */
+ { 0xd2, 0xf2 }, /* lower */
+ { 0xd3, 0xf3 }, /* lower */
+ { 0xd4, 0xf4 }, /* lower */
+ { 0xd5, 0xf5 }, /* lower */
+ { 0xd6, 0xf6 }, /* lower */
+ { 0xf7, 0xf7 },
+ { 0xd8, 0xf8 }, /* lower */
+ { 0xd9, 0xf9 }, /* lower */
+ { 0xda, 0xfa }, /* lower */
+ { 0xdb, 0xfb }, /* lower */
+ { 0xdc, 0xfc }, /* lower */
+ { 0xdd, 0xfd }, /* lower */
+ { 0xde, 0xfe }, /* lower */
+ { 0x178, 0xff }, /* lower */
+};
+
+gli_case_block_t unigen_case_block_0x1[256] = {
+ { 0x100, 0x101 }, /* upper */
+ { 0x100, 0x101 }, /* lower */
+ { 0x102, 0x103 }, /* upper */
+ { 0x102, 0x103 }, /* lower */
+ { 0x104, 0x105 }, /* upper */
+ { 0x104, 0x105 }, /* lower */
+ { 0x106, 0x107 }, /* upper */
+ { 0x106, 0x107 }, /* lower */
+ { 0x108, 0x109 }, /* upper */
+ { 0x108, 0x109 }, /* lower */
+ { 0x10a, 0x10b }, /* upper */
+ { 0x10a, 0x10b }, /* lower */
+ { 0x10c, 0x10d }, /* upper */
+ { 0x10c, 0x10d }, /* lower */
+ { 0x10e, 0x10f }, /* upper */
+ { 0x10e, 0x10f }, /* lower */
+ { 0x110, 0x111 }, /* upper */
+ { 0x110, 0x111 }, /* lower */
+ { 0x112, 0x113 }, /* upper */
+ { 0x112, 0x113 }, /* lower */
+ { 0x114, 0x115 }, /* upper */
+ { 0x114, 0x115 }, /* lower */
+ { 0x116, 0x117 }, /* upper */
+ { 0x116, 0x117 }, /* lower */
+ { 0x118, 0x119 }, /* upper */
+ { 0x118, 0x119 }, /* lower */
+ { 0x11a, 0x11b }, /* upper */
+ { 0x11a, 0x11b }, /* lower */
+ { 0x11c, 0x11d }, /* upper */
+ { 0x11c, 0x11d }, /* lower */
+ { 0x11e, 0x11f }, /* upper */
+ { 0x11e, 0x11f }, /* lower */
+ { 0x120, 0x121 }, /* upper */
+ { 0x120, 0x121 }, /* lower */
+ { 0x122, 0x123 }, /* upper */
+ { 0x122, 0x123 }, /* lower */
+ { 0x124, 0x125 }, /* upper */
+ { 0x124, 0x125 }, /* lower */
+ { 0x126, 0x127 }, /* upper */
+ { 0x126, 0x127 }, /* lower */
+ { 0x128, 0x129 }, /* upper */
+ { 0x128, 0x129 }, /* lower */
+ { 0x12a, 0x12b }, /* upper */
+ { 0x12a, 0x12b }, /* lower */
+ { 0x12c, 0x12d }, /* upper */
+ { 0x12c, 0x12d }, /* lower */
+ { 0x12e, 0x12f }, /* upper */
+ { 0x12e, 0x12f }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x49, 0x131 }, /* lower */
+ { 0x132, 0x133 }, /* upper */
+ { 0x132, 0x133 }, /* lower */
+ { 0x134, 0x135 }, /* upper */
+ { 0x134, 0x135 }, /* lower */
+ { 0x136, 0x137 }, /* upper */
+ { 0x136, 0x137 }, /* lower */
+ { 0x138, 0x138 },
+ { 0x139, 0x13a }, /* upper */
+ { 0x139, 0x13a }, /* lower */
+ { 0x13b, 0x13c }, /* upper */
+ { 0x13b, 0x13c }, /* lower */
+ { 0x13d, 0x13e }, /* upper */
+ { 0x13d, 0x13e }, /* lower */
+ { 0x13f, 0x140 }, /* upper */
+ { 0x13f, 0x140 }, /* lower */
+ { 0x141, 0x142 }, /* upper */
+ { 0x141, 0x142 }, /* lower */
+ { 0x143, 0x144 }, /* upper */
+ { 0x143, 0x144 }, /* lower */
+ { 0x145, 0x146 }, /* upper */
+ { 0x145, 0x146 }, /* lower */
+ { 0x147, 0x148 }, /* upper */
+ { 0x147, 0x148 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x14a, 0x14b }, /* upper */
+ { 0x14a, 0x14b }, /* lower */
+ { 0x14c, 0x14d }, /* upper */
+ { 0x14c, 0x14d }, /* lower */
+ { 0x14e, 0x14f }, /* upper */
+ { 0x14e, 0x14f }, /* lower */
+ { 0x150, 0x151 }, /* upper */
+ { 0x150, 0x151 }, /* lower */
+ { 0x152, 0x153 }, /* upper */
+ { 0x152, 0x153 }, /* lower */
+ { 0x154, 0x155 }, /* upper */
+ { 0x154, 0x155 }, /* lower */
+ { 0x156, 0x157 }, /* upper */
+ { 0x156, 0x157 }, /* lower */
+ { 0x158, 0x159 }, /* upper */
+ { 0x158, 0x159 }, /* lower */
+ { 0x15a, 0x15b }, /* upper */
+ { 0x15a, 0x15b }, /* lower */
+ { 0x15c, 0x15d }, /* upper */
+ { 0x15c, 0x15d }, /* lower */
+ { 0x15e, 0x15f }, /* upper */
+ { 0x15e, 0x15f }, /* lower */
+ { 0x160, 0x161 }, /* upper */
+ { 0x160, 0x161 }, /* lower */
+ { 0x162, 0x163 }, /* upper */
+ { 0x162, 0x163 }, /* lower */
+ { 0x164, 0x165 }, /* upper */
+ { 0x164, 0x165 }, /* lower */
+ { 0x166, 0x167 }, /* upper */
+ { 0x166, 0x167 }, /* lower */
+ { 0x168, 0x169 }, /* upper */
+ { 0x168, 0x169 }, /* lower */
+ { 0x16a, 0x16b }, /* upper */
+ { 0x16a, 0x16b }, /* lower */
+ { 0x16c, 0x16d }, /* upper */
+ { 0x16c, 0x16d }, /* lower */
+ { 0x16e, 0x16f }, /* upper */
+ { 0x16e, 0x16f }, /* lower */
+ { 0x170, 0x171 }, /* upper */
+ { 0x170, 0x171 }, /* lower */
+ { 0x172, 0x173 }, /* upper */
+ { 0x172, 0x173 }, /* lower */
+ { 0x174, 0x175 }, /* upper */
+ { 0x174, 0x175 }, /* lower */
+ { 0x176, 0x177 }, /* upper */
+ { 0x176, 0x177 }, /* lower */
+ { 0x178, 0xff }, /* upper */
+ { 0x179, 0x17a }, /* upper */
+ { 0x179, 0x17a }, /* lower */
+ { 0x17b, 0x17c }, /* upper */
+ { 0x17b, 0x17c }, /* lower */
+ { 0x17d, 0x17e }, /* upper */
+ { 0x17d, 0x17e }, /* lower */
+ { 0x53, 0x17f }, /* lower */
+ { 0x180, 0x180 },
+ { 0x181, 0x253 }, /* upper */
+ { 0x182, 0x183 }, /* upper */
+ { 0x182, 0x183 }, /* lower */
+ { 0x184, 0x185 }, /* upper */
+ { 0x184, 0x185 }, /* lower */
+ { 0x186, 0x254 }, /* upper */
+ { 0x187, 0x188 }, /* upper */
+ { 0x187, 0x188 }, /* lower */
+ { 0x189, 0x256 }, /* upper */
+ { 0x18a, 0x257 }, /* upper */
+ { 0x18b, 0x18c }, /* upper */
+ { 0x18b, 0x18c }, /* lower */
+ { 0x18d, 0x18d },
+ { 0x18e, 0x1dd }, /* upper */
+ { 0x18f, 0x259 }, /* upper */
+ { 0x190, 0x25b }, /* upper */
+ { 0x191, 0x192 }, /* upper */
+ { 0x191, 0x192 }, /* lower */
+ { 0x193, 0x260 }, /* upper */
+ { 0x194, 0x263 }, /* upper */
+ { 0x1f6, 0x195 }, /* lower */
+ { 0x196, 0x269 }, /* upper */
+ { 0x197, 0x268 }, /* upper */
+ { 0x198, 0x199 }, /* upper */
+ { 0x198, 0x199 }, /* lower */
+ { 0x19a, 0x19a },
+ { 0x19b, 0x19b },
+ { 0x19c, 0x26f }, /* upper */
+ { 0x19d, 0x272 }, /* upper */
+ { 0x220, 0x19e }, /* lower */
+ { 0x19f, 0x275 }, /* upper */
+ { 0x1a0, 0x1a1 }, /* upper */
+ { 0x1a0, 0x1a1 }, /* lower */
+ { 0x1a2, 0x1a3 }, /* upper */
+ { 0x1a2, 0x1a3 }, /* lower */
+ { 0x1a4, 0x1a5 }, /* upper */
+ { 0x1a4, 0x1a5 }, /* lower */
+ { 0x1a6, 0x280 }, /* upper */
+ { 0x1a7, 0x1a8 }, /* upper */
+ { 0x1a7, 0x1a8 }, /* lower */
+ { 0x1a9, 0x283 }, /* upper */
+ { 0x1aa, 0x1aa },
+ { 0x1ab, 0x1ab },
+ { 0x1ac, 0x1ad }, /* upper */
+ { 0x1ac, 0x1ad }, /* lower */
+ { 0x1ae, 0x288 }, /* upper */
+ { 0x1af, 0x1b0 }, /* upper */
+ { 0x1af, 0x1b0 }, /* lower */
+ { 0x1b1, 0x28a }, /* upper */
+ { 0x1b2, 0x28b }, /* upper */
+ { 0x1b3, 0x1b4 }, /* upper */
+ { 0x1b3, 0x1b4 }, /* lower */
+ { 0x1b5, 0x1b6 }, /* upper */
+ { 0x1b5, 0x1b6 }, /* lower */
+ { 0x1b7, 0x292 }, /* upper */
+ { 0x1b8, 0x1b9 }, /* upper */
+ { 0x1b8, 0x1b9 }, /* lower */
+ { 0x1ba, 0x1ba },
+ { 0x1bb, 0x1bb },
+ { 0x1bc, 0x1bd }, /* upper */
+ { 0x1bc, 0x1bd }, /* lower */
+ { 0x1be, 0x1be },
+ { 0x1f7, 0x1bf }, /* lower */
+ { 0x1c0, 0x1c0 },
+ { 0x1c1, 0x1c1 },
+ { 0x1c2, 0x1c2 },
+ { 0x1c3, 0x1c3 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1cd, 0x1ce }, /* upper */
+ { 0x1cd, 0x1ce }, /* lower */
+ { 0x1cf, 0x1d0 }, /* upper */
+ { 0x1cf, 0x1d0 }, /* lower */
+ { 0x1d1, 0x1d2 }, /* upper */
+ { 0x1d1, 0x1d2 }, /* lower */
+ { 0x1d3, 0x1d4 }, /* upper */
+ { 0x1d3, 0x1d4 }, /* lower */
+ { 0x1d5, 0x1d6 }, /* upper */
+ { 0x1d5, 0x1d6 }, /* lower */
+ { 0x1d7, 0x1d8 }, /* upper */
+ { 0x1d7, 0x1d8 }, /* lower */
+ { 0x1d9, 0x1da }, /* upper */
+ { 0x1d9, 0x1da }, /* lower */
+ { 0x1db, 0x1dc }, /* upper */
+ { 0x1db, 0x1dc }, /* lower */
+ { 0x18e, 0x1dd }, /* lower */
+ { 0x1de, 0x1df }, /* upper */
+ { 0x1de, 0x1df }, /* lower */
+ { 0x1e0, 0x1e1 }, /* upper */
+ { 0x1e0, 0x1e1 }, /* lower */
+ { 0x1e2, 0x1e3 }, /* upper */
+ { 0x1e2, 0x1e3 }, /* lower */
+ { 0x1e4, 0x1e5 }, /* upper */
+ { 0x1e4, 0x1e5 }, /* lower */
+ { 0x1e6, 0x1e7 }, /* upper */
+ { 0x1e6, 0x1e7 }, /* lower */
+ { 0x1e8, 0x1e9 }, /* upper */
+ { 0x1e8, 0x1e9 }, /* lower */
+ { 0x1ea, 0x1eb }, /* upper */
+ { 0x1ea, 0x1eb }, /* lower */
+ { 0x1ec, 0x1ed }, /* upper */
+ { 0x1ec, 0x1ed }, /* lower */
+ { 0x1ee, 0x1ef }, /* upper */
+ { 0x1ee, 0x1ef }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1f4, 0x1f5 }, /* upper */
+ { 0x1f4, 0x1f5 }, /* lower */
+ { 0x1f6, 0x195 }, /* upper */
+ { 0x1f7, 0x1bf }, /* upper */
+ { 0x1f8, 0x1f9 }, /* upper */
+ { 0x1f8, 0x1f9 }, /* lower */
+ { 0x1fa, 0x1fb }, /* upper */
+ { 0x1fa, 0x1fb }, /* lower */
+ { 0x1fc, 0x1fd }, /* upper */
+ { 0x1fc, 0x1fd }, /* lower */
+ { 0x1fe, 0x1ff }, /* upper */
+ { 0x1fe, 0x1ff }, /* lower */
+};
+
+gli_case_block_t unigen_case_block_0x2[256] = {
+ { 0x200, 0x201 }, /* upper */
+ { 0x200, 0x201 }, /* lower */
+ { 0x202, 0x203 }, /* upper */
+ { 0x202, 0x203 }, /* lower */
+ { 0x204, 0x205 }, /* upper */
+ { 0x204, 0x205 }, /* lower */
+ { 0x206, 0x207 }, /* upper */
+ { 0x206, 0x207 }, /* lower */
+ { 0x208, 0x209 }, /* upper */
+ { 0x208, 0x209 }, /* lower */
+ { 0x20a, 0x20b }, /* upper */
+ { 0x20a, 0x20b }, /* lower */
+ { 0x20c, 0x20d }, /* upper */
+ { 0x20c, 0x20d }, /* lower */
+ { 0x20e, 0x20f }, /* upper */
+ { 0x20e, 0x20f }, /* lower */
+ { 0x210, 0x211 }, /* upper */
+ { 0x210, 0x211 }, /* lower */
+ { 0x212, 0x213 }, /* upper */
+ { 0x212, 0x213 }, /* lower */
+ { 0x214, 0x215 }, /* upper */
+ { 0x214, 0x215 }, /* lower */
+ { 0x216, 0x217 }, /* upper */
+ { 0x216, 0x217 }, /* lower */
+ { 0x218, 0x219 }, /* upper */
+ { 0x218, 0x219 }, /* lower */
+ { 0x21a, 0x21b }, /* upper */
+ { 0x21a, 0x21b }, /* lower */
+ { 0x21c, 0x21d }, /* upper */
+ { 0x21c, 0x21d }, /* lower */
+ { 0x21e, 0x21f }, /* upper */
+ { 0x21e, 0x21f }, /* lower */
+ { 0x220, 0x19e }, /* upper */
+ { 0x221, 0x221 },
+ { 0x222, 0x223 }, /* upper */
+ { 0x222, 0x223 }, /* lower */
+ { 0x224, 0x225 }, /* upper */
+ { 0x224, 0x225 }, /* lower */
+ { 0x226, 0x227 }, /* upper */
+ { 0x226, 0x227 }, /* lower */
+ { 0x228, 0x229 }, /* upper */
+ { 0x228, 0x229 }, /* lower */
+ { 0x22a, 0x22b }, /* upper */
+ { 0x22a, 0x22b }, /* lower */
+ { 0x22c, 0x22d }, /* upper */
+ { 0x22c, 0x22d }, /* lower */
+ { 0x22e, 0x22f }, /* upper */
+ { 0x22e, 0x22f }, /* lower */
+ { 0x230, 0x231 }, /* upper */
+ { 0x230, 0x231 }, /* lower */
+ { 0x232, 0x233 }, /* upper */
+ { 0x232, 0x233 }, /* lower */
+ { 0x234, 0x234 },
+ { 0x235, 0x235 },
+ { 0x236, 0x236 },
+ { 0x237, 0x237 },
+ { 0x238, 0x238 },
+ { 0x239, 0x239 },
+ { 0x23a, 0x23a },
+ { 0x23b, 0x23b },
+ { 0x23c, 0x23c },
+ { 0x23d, 0x23d },
+ { 0x23e, 0x23e },
+ { 0x23f, 0x23f },
+ { 0x240, 0x240 },
+ { 0x241, 0x241 },
+ { 0x242, 0x242 },
+ { 0x243, 0x243 },
+ { 0x244, 0x244 },
+ { 0x245, 0x245 },
+ { 0x246, 0x246 },
+ { 0x247, 0x247 },
+ { 0x248, 0x248 },
+ { 0x249, 0x249 },
+ { 0x24a, 0x24a },
+ { 0x24b, 0x24b },
+ { 0x24c, 0x24c },
+ { 0x24d, 0x24d },
+ { 0x24e, 0x24e },
+ { 0x24f, 0x24f },
+ { 0x250, 0x250 },
+ { 0x251, 0x251 },
+ { 0x252, 0x252 },
+ { 0x181, 0x253 }, /* lower */
+ { 0x186, 0x254 }, /* lower */
+ { 0x255, 0x255 },
+ { 0x189, 0x256 }, /* lower */
+ { 0x18a, 0x257 }, /* lower */
+ { 0x258, 0x258 },
+ { 0x18f, 0x259 }, /* lower */
+ { 0x25a, 0x25a },
+ { 0x190, 0x25b }, /* lower */
+ { 0x25c, 0x25c },
+ { 0x25d, 0x25d },
+ { 0x25e, 0x25e },
+ { 0x25f, 0x25f },
+ { 0x193, 0x260 }, /* lower */
+ { 0x261, 0x261 },
+ { 0x262, 0x262 },
+ { 0x194, 0x263 }, /* lower */
+ { 0x264, 0x264 },
+ { 0x265, 0x265 },
+ { 0x266, 0x266 },
+ { 0x267, 0x267 },
+ { 0x197, 0x268 }, /* lower */
+ { 0x196, 0x269 }, /* lower */
+ { 0x26a, 0x26a },
+ { 0x26b, 0x26b },
+ { 0x26c, 0x26c },
+ { 0x26d, 0x26d },
+ { 0x26e, 0x26e },
+ { 0x19c, 0x26f }, /* lower */
+ { 0x270, 0x270 },
+ { 0x271, 0x271 },
+ { 0x19d, 0x272 }, /* lower */
+ { 0x273, 0x273 },
+ { 0x274, 0x274 },
+ { 0x19f, 0x275 }, /* lower */
+ { 0x276, 0x276 },
+ { 0x277, 0x277 },
+ { 0x278, 0x278 },
+ { 0x279, 0x279 },
+ { 0x27a, 0x27a },
+ { 0x27b, 0x27b },
+ { 0x27c, 0x27c },
+ { 0x27d, 0x27d },
+ { 0x27e, 0x27e },
+ { 0x27f, 0x27f },
+ { 0x1a6, 0x280 }, /* lower */
+ { 0x281, 0x281 },
+ { 0x282, 0x282 },
+ { 0x1a9, 0x283 }, /* lower */
+ { 0x284, 0x284 },
+ { 0x285, 0x285 },
+ { 0x286, 0x286 },
+ { 0x287, 0x287 },
+ { 0x1ae, 0x288 }, /* lower */
+ { 0x289, 0x289 },
+ { 0x1b1, 0x28a }, /* lower */
+ { 0x1b2, 0x28b }, /* lower */
+ { 0x28c, 0x28c },
+ { 0x28d, 0x28d },
+ { 0x28e, 0x28e },
+ { 0x28f, 0x28f },
+ { 0x290, 0x290 },
+ { 0x291, 0x291 },
+ { 0x1b7, 0x292 }, /* lower */
+ { 0x293, 0x293 },
+ { 0x294, 0x294 },
+ { 0x295, 0x295 },
+ { 0x296, 0x296 },
+ { 0x297, 0x297 },
+ { 0x298, 0x298 },
+ { 0x299, 0x299 },
+ { 0x29a, 0x29a },
+ { 0x29b, 0x29b },
+ { 0x29c, 0x29c },
+ { 0x29d, 0x29d },
+ { 0x29e, 0x29e },
+ { 0x29f, 0x29f },
+ { 0x2a0, 0x2a0 },
+ { 0x2a1, 0x2a1 },
+ { 0x2a2, 0x2a2 },
+ { 0x2a3, 0x2a3 },
+ { 0x2a4, 0x2a4 },
+ { 0x2a5, 0x2a5 },
+ { 0x2a6, 0x2a6 },
+ { 0x2a7, 0x2a7 },
+ { 0x2a8, 0x2a8 },
+ { 0x2a9, 0x2a9 },
+ { 0x2aa, 0x2aa },
+ { 0x2ab, 0x2ab },
+ { 0x2ac, 0x2ac },
+ { 0x2ad, 0x2ad },
+ { 0x2ae, 0x2ae },
+ { 0x2af, 0x2af },
+ { 0x2b0, 0x2b0 },
+ { 0x2b1, 0x2b1 },
+ { 0x2b2, 0x2b2 },
+ { 0x2b3, 0x2b3 },
+ { 0x2b4, 0x2b4 },
+ { 0x2b5, 0x2b5 },
+ { 0x2b6, 0x2b6 },
+ { 0x2b7, 0x2b7 },
+ { 0x2b8, 0x2b8 },
+ { 0x2b9, 0x2b9 },
+ { 0x2ba, 0x2ba },
+ { 0x2bb, 0x2bb },
+ { 0x2bc, 0x2bc },
+ { 0x2bd, 0x2bd },
+ { 0x2be, 0x2be },
+ { 0x2bf, 0x2bf },
+ { 0x2c0, 0x2c0 },
+ { 0x2c1, 0x2c1 },
+ { 0x2c2, 0x2c2 },
+ { 0x2c3, 0x2c3 },
+ { 0x2c4, 0x2c4 },
+ { 0x2c5, 0x2c5 },
+ { 0x2c6, 0x2c6 },
+ { 0x2c7, 0x2c7 },
+ { 0x2c8, 0x2c8 },
+ { 0x2c9, 0x2c9 },
+ { 0x2ca, 0x2ca },
+ { 0x2cb, 0x2cb },
+ { 0x2cc, 0x2cc },
+ { 0x2cd, 0x2cd },
+ { 0x2ce, 0x2ce },
+ { 0x2cf, 0x2cf },
+ { 0x2d0, 0x2d0 },
+ { 0x2d1, 0x2d1 },
+ { 0x2d2, 0x2d2 },
+ { 0x2d3, 0x2d3 },
+ { 0x2d4, 0x2d4 },
+ { 0x2d5, 0x2d5 },
+ { 0x2d6, 0x2d6 },
+ { 0x2d7, 0x2d7 },
+ { 0x2d8, 0x2d8 },
+ { 0x2d9, 0x2d9 },
+ { 0x2da, 0x2da },
+ { 0x2db, 0x2db },
+ { 0x2dc, 0x2dc },
+ { 0x2dd, 0x2dd },
+ { 0x2de, 0x2de },
+ { 0x2df, 0x2df },
+ { 0x2e0, 0x2e0 },
+ { 0x2e1, 0x2e1 },
+ { 0x2e2, 0x2e2 },
+ { 0x2e3, 0x2e3 },
+ { 0x2e4, 0x2e4 },
+ { 0x2e5, 0x2e5 },
+ { 0x2e6, 0x2e6 },
+ { 0x2e7, 0x2e7 },
+ { 0x2e8, 0x2e8 },
+ { 0x2e9, 0x2e9 },
+ { 0x2ea, 0x2ea },
+ { 0x2eb, 0x2eb },
+ { 0x2ec, 0x2ec },
+ { 0x2ed, 0x2ed },
+ { 0x2ee, 0x2ee },
+ { 0x2ef, 0x2ef },
+ { 0x2f0, 0x2f0 },
+ { 0x2f1, 0x2f1 },
+ { 0x2f2, 0x2f2 },
+ { 0x2f3, 0x2f3 },
+ { 0x2f4, 0x2f4 },
+ { 0x2f5, 0x2f5 },
+ { 0x2f6, 0x2f6 },
+ { 0x2f7, 0x2f7 },
+ { 0x2f8, 0x2f8 },
+ { 0x2f9, 0x2f9 },
+ { 0x2fa, 0x2fa },
+ { 0x2fb, 0x2fb },
+ { 0x2fc, 0x2fc },
+ { 0x2fd, 0x2fd },
+ { 0x2fe, 0x2fe },
+ { 0x2ff, 0x2ff },
+};
+
+gli_case_block_t unigen_case_block_0x3[256] = {
+ { 0x300, 0x300 },
+ { 0x301, 0x301 },
+ { 0x302, 0x302 },
+ { 0x303, 0x303 },
+ { 0x304, 0x304 },
+ { 0x305, 0x305 },
+ { 0x306, 0x306 },
+ { 0x307, 0x307 },
+ { 0x308, 0x308 },
+ { 0x309, 0x309 },
+ { 0x30a, 0x30a },
+ { 0x30b, 0x30b },
+ { 0x30c, 0x30c },
+ { 0x30d, 0x30d },
+ { 0x30e, 0x30e },
+ { 0x30f, 0x30f },
+ { 0x310, 0x310 },
+ { 0x311, 0x311 },
+ { 0x312, 0x312 },
+ { 0x313, 0x313 },
+ { 0x314, 0x314 },
+ { 0x315, 0x315 },
+ { 0x316, 0x316 },
+ { 0x317, 0x317 },
+ { 0x318, 0x318 },
+ { 0x319, 0x319 },
+ { 0x31a, 0x31a },
+ { 0x31b, 0x31b },
+ { 0x31c, 0x31c },
+ { 0x31d, 0x31d },
+ { 0x31e, 0x31e },
+ { 0x31f, 0x31f },
+ { 0x320, 0x320 },
+ { 0x321, 0x321 },
+ { 0x322, 0x322 },
+ { 0x323, 0x323 },
+ { 0x324, 0x324 },
+ { 0x325, 0x325 },
+ { 0x326, 0x326 },
+ { 0x327, 0x327 },
+ { 0x328, 0x328 },
+ { 0x329, 0x329 },
+ { 0x32a, 0x32a },
+ { 0x32b, 0x32b },
+ { 0x32c, 0x32c },
+ { 0x32d, 0x32d },
+ { 0x32e, 0x32e },
+ { 0x32f, 0x32f },
+ { 0x330, 0x330 },
+ { 0x331, 0x331 },
+ { 0x332, 0x332 },
+ { 0x333, 0x333 },
+ { 0x334, 0x334 },
+ { 0x335, 0x335 },
+ { 0x336, 0x336 },
+ { 0x337, 0x337 },
+ { 0x338, 0x338 },
+ { 0x339, 0x339 },
+ { 0x33a, 0x33a },
+ { 0x33b, 0x33b },
+ { 0x33c, 0x33c },
+ { 0x33d, 0x33d },
+ { 0x33e, 0x33e },
+ { 0x33f, 0x33f },
+ { 0x340, 0x340 },
+ { 0x341, 0x341 },
+ { 0x342, 0x342 },
+ { 0x343, 0x343 },
+ { 0x344, 0x344 },
+ { 0x399, 0x345 }, /* lower */
+ { 0x346, 0x346 },
+ { 0x347, 0x347 },
+ { 0x348, 0x348 },
+ { 0x349, 0x349 },
+ { 0x34a, 0x34a },
+ { 0x34b, 0x34b },
+ { 0x34c, 0x34c },
+ { 0x34d, 0x34d },
+ { 0x34e, 0x34e },
+ { 0x34f, 0x34f },
+ { 0x350, 0x350 },
+ { 0x351, 0x351 },
+ { 0x352, 0x352 },
+ { 0x353, 0x353 },
+ { 0x354, 0x354 },
+ { 0x355, 0x355 },
+ { 0x356, 0x356 },
+ { 0x357, 0x357 },
+ { 0x358, 0x358 },
+ { 0x359, 0x359 },
+ { 0x35a, 0x35a },
+ { 0x35b, 0x35b },
+ { 0x35c, 0x35c },
+ { 0x35d, 0x35d },
+ { 0x35e, 0x35e },
+ { 0x35f, 0x35f },
+ { 0x360, 0x360 },
+ { 0x361, 0x361 },
+ { 0x362, 0x362 },
+ { 0x363, 0x363 },
+ { 0x364, 0x364 },
+ { 0x365, 0x365 },
+ { 0x366, 0x366 },
+ { 0x367, 0x367 },
+ { 0x368, 0x368 },
+ { 0x369, 0x369 },
+ { 0x36a, 0x36a },
+ { 0x36b, 0x36b },
+ { 0x36c, 0x36c },
+ { 0x36d, 0x36d },
+ { 0x36e, 0x36e },
+ { 0x36f, 0x36f },
+ { 0x370, 0x370 },
+ { 0x371, 0x371 },
+ { 0x372, 0x372 },
+ { 0x373, 0x373 },
+ { 0x374, 0x374 },
+ { 0x375, 0x375 },
+ { 0x376, 0x376 },
+ { 0x377, 0x377 },
+ { 0x378, 0x378 },
+ { 0x379, 0x379 },
+ { 0x37a, 0x37a },
+ { 0x37b, 0x37b },
+ { 0x37c, 0x37c },
+ { 0x37d, 0x37d },
+ { 0x37e, 0x37e },
+ { 0x37f, 0x37f },
+ { 0x380, 0x380 },
+ { 0x381, 0x381 },
+ { 0x382, 0x382 },
+ { 0x383, 0x383 },
+ { 0x384, 0x384 },
+ { 0x385, 0x385 },
+ { 0x386, 0x3ac }, /* upper */
+ { 0x387, 0x387 },
+ { 0x388, 0x3ad }, /* upper */
+ { 0x389, 0x3ae }, /* upper */
+ { 0x38a, 0x3af }, /* upper */
+ { 0x38b, 0x38b },
+ { 0x38c, 0x3cc }, /* upper */
+ { 0x38d, 0x38d },
+ { 0x38e, 0x3cd }, /* upper */
+ { 0x38f, 0x3ce }, /* upper */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x391, 0x3b1 }, /* upper */
+ { 0x392, 0x3b2 }, /* upper */
+ { 0x393, 0x3b3 }, /* upper */
+ { 0x394, 0x3b4 }, /* upper */
+ { 0x395, 0x3b5 }, /* upper */
+ { 0x396, 0x3b6 }, /* upper */
+ { 0x397, 0x3b7 }, /* upper */
+ { 0x398, 0x3b8 }, /* upper */
+ { 0x399, 0x3b9 }, /* upper */
+ { 0x39a, 0x3ba }, /* upper */
+ { 0x39b, 0x3bb }, /* upper */
+ { 0x39c, 0x3bc }, /* upper */
+ { 0x39d, 0x3bd }, /* upper */
+ { 0x39e, 0x3be }, /* upper */
+ { 0x39f, 0x3bf }, /* upper */
+ { 0x3a0, 0x3c0 }, /* upper */
+ { 0x3a1, 0x3c1 }, /* upper */
+ { 0x3a2, 0x3a2 },
+ { 0x3a3, 0x3c3 }, /* upper */
+ { 0x3a4, 0x3c4 }, /* upper */
+ { 0x3a5, 0x3c5 }, /* upper */
+ { 0x3a6, 0x3c6 }, /* upper */
+ { 0x3a7, 0x3c7 }, /* upper */
+ { 0x3a8, 0x3c8 }, /* upper */
+ { 0x3a9, 0x3c9 }, /* upper */
+ { 0x3aa, 0x3ca }, /* upper */
+ { 0x3ab, 0x3cb }, /* upper */
+ { 0x386, 0x3ac }, /* lower */
+ { 0x388, 0x3ad }, /* lower */
+ { 0x389, 0x3ae }, /* lower */
+ { 0x38a, 0x3af }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x391, 0x3b1 }, /* lower */
+ { 0x392, 0x3b2 }, /* lower */
+ { 0x393, 0x3b3 }, /* lower */
+ { 0x394, 0x3b4 }, /* lower */
+ { 0x395, 0x3b5 }, /* lower */
+ { 0x396, 0x3b6 }, /* lower */
+ { 0x397, 0x3b7 }, /* lower */
+ { 0x398, 0x3b8 }, /* lower */
+ { 0x399, 0x3b9 }, /* lower */
+ { 0x39a, 0x3ba }, /* lower */
+ { 0x39b, 0x3bb }, /* lower */
+ { 0x39c, 0x3bc }, /* lower */
+ { 0x39d, 0x3bd }, /* lower */
+ { 0x39e, 0x3be }, /* lower */
+ { 0x39f, 0x3bf }, /* lower */
+ { 0x3a0, 0x3c0 }, /* lower */
+ { 0x3a1, 0x3c1 }, /* lower */
+ { 0x3a3, 0x3c2 }, /* lower */
+ { 0x3a3, 0x3c3 }, /* lower */
+ { 0x3a4, 0x3c4 }, /* lower */
+ { 0x3a5, 0x3c5 }, /* lower */
+ { 0x3a6, 0x3c6 }, /* lower */
+ { 0x3a7, 0x3c7 }, /* lower */
+ { 0x3a8, 0x3c8 }, /* lower */
+ { 0x3a9, 0x3c9 }, /* lower */
+ { 0x3aa, 0x3ca }, /* lower */
+ { 0x3ab, 0x3cb }, /* lower */
+ { 0x38c, 0x3cc }, /* lower */
+ { 0x38e, 0x3cd }, /* lower */
+ { 0x38f, 0x3ce }, /* lower */
+ { 0x3cf, 0x3cf },
+ { 0x392, 0x3d0 }, /* lower */
+ { 0x398, 0x3d1 }, /* lower */
+ { 0x3d2, 0x3d2 },
+ { 0x3d3, 0x3d3 },
+ { 0x3d4, 0x3d4 },
+ { 0x3a6, 0x3d5 }, /* lower */
+ { 0x3a0, 0x3d6 }, /* lower */
+ { 0x3d7, 0x3d7 },
+ { 0x3d8, 0x3d9 }, /* upper */
+ { 0x3d8, 0x3d9 }, /* lower */
+ { 0x3da, 0x3db }, /* upper */
+ { 0x3da, 0x3db }, /* lower */
+ { 0x3dc, 0x3dd }, /* upper */
+ { 0x3dc, 0x3dd }, /* lower */
+ { 0x3de, 0x3df }, /* upper */
+ { 0x3de, 0x3df }, /* lower */
+ { 0x3e0, 0x3e1 }, /* upper */
+ { 0x3e0, 0x3e1 }, /* lower */
+ { 0x3e2, 0x3e3 }, /* upper */
+ { 0x3e2, 0x3e3 }, /* lower */
+ { 0x3e4, 0x3e5 }, /* upper */
+ { 0x3e4, 0x3e5 }, /* lower */
+ { 0x3e6, 0x3e7 }, /* upper */
+ { 0x3e6, 0x3e7 }, /* lower */
+ { 0x3e8, 0x3e9 }, /* upper */
+ { 0x3e8, 0x3e9 }, /* lower */
+ { 0x3ea, 0x3eb }, /* upper */
+ { 0x3ea, 0x3eb }, /* lower */
+ { 0x3ec, 0x3ed }, /* upper */
+ { 0x3ec, 0x3ed }, /* lower */
+ { 0x3ee, 0x3ef }, /* upper */
+ { 0x3ee, 0x3ef }, /* lower */
+ { 0x39a, 0x3f0 }, /* lower */
+ { 0x3a1, 0x3f1 }, /* lower */
+ { 0x3f9, 0x3f2 }, /* lower */
+ { 0x3f3, 0x3f3 },
+ { 0x3f4, 0x3b8 }, /* upper */
+ { 0x395, 0x3f5 }, /* lower */
+ { 0x3f6, 0x3f6 },
+ { 0x3f7, 0x3f8 }, /* upper */
+ { 0x3f7, 0x3f8 }, /* lower */
+ { 0x3f9, 0x3f2 }, /* upper */
+ { 0x3fa, 0x3fb }, /* upper */
+ { 0x3fa, 0x3fb }, /* lower */
+ { 0x3fc, 0x3fc },
+ { 0x3fd, 0x3fd },
+ { 0x3fe, 0x3fe },
+ { 0x3ff, 0x3ff },
+};
+
+gli_case_block_t unigen_case_block_0x4[256] = {
+ { 0x400, 0x450 }, /* upper */
+ { 0x401, 0x451 }, /* upper */
+ { 0x402, 0x452 }, /* upper */
+ { 0x403, 0x453 }, /* upper */
+ { 0x404, 0x454 }, /* upper */
+ { 0x405, 0x455 }, /* upper */
+ { 0x406, 0x456 }, /* upper */
+ { 0x407, 0x457 }, /* upper */
+ { 0x408, 0x458 }, /* upper */
+ { 0x409, 0x459 }, /* upper */
+ { 0x40a, 0x45a }, /* upper */
+ { 0x40b, 0x45b }, /* upper */
+ { 0x40c, 0x45c }, /* upper */
+ { 0x40d, 0x45d }, /* upper */
+ { 0x40e, 0x45e }, /* upper */
+ { 0x40f, 0x45f }, /* upper */
+ { 0x410, 0x430 }, /* upper */
+ { 0x411, 0x431 }, /* upper */
+ { 0x412, 0x432 }, /* upper */
+ { 0x413, 0x433 }, /* upper */
+ { 0x414, 0x434 }, /* upper */
+ { 0x415, 0x435 }, /* upper */
+ { 0x416, 0x436 }, /* upper */
+ { 0x417, 0x437 }, /* upper */
+ { 0x418, 0x438 }, /* upper */
+ { 0x419, 0x439 }, /* upper */
+ { 0x41a, 0x43a }, /* upper */
+ { 0x41b, 0x43b }, /* upper */
+ { 0x41c, 0x43c }, /* upper */
+ { 0x41d, 0x43d }, /* upper */
+ { 0x41e, 0x43e }, /* upper */
+ { 0x41f, 0x43f }, /* upper */
+ { 0x420, 0x440 }, /* upper */
+ { 0x421, 0x441 }, /* upper */
+ { 0x422, 0x442 }, /* upper */
+ { 0x423, 0x443 }, /* upper */
+ { 0x424, 0x444 }, /* upper */
+ { 0x425, 0x445 }, /* upper */
+ { 0x426, 0x446 }, /* upper */
+ { 0x427, 0x447 }, /* upper */
+ { 0x428, 0x448 }, /* upper */
+ { 0x429, 0x449 }, /* upper */
+ { 0x42a, 0x44a }, /* upper */
+ { 0x42b, 0x44b }, /* upper */
+ { 0x42c, 0x44c }, /* upper */
+ { 0x42d, 0x44d }, /* upper */
+ { 0x42e, 0x44e }, /* upper */
+ { 0x42f, 0x44f }, /* upper */
+ { 0x410, 0x430 }, /* lower */
+ { 0x411, 0x431 }, /* lower */
+ { 0x412, 0x432 }, /* lower */
+ { 0x413, 0x433 }, /* lower */
+ { 0x414, 0x434 }, /* lower */
+ { 0x415, 0x435 }, /* lower */
+ { 0x416, 0x436 }, /* lower */
+ { 0x417, 0x437 }, /* lower */
+ { 0x418, 0x438 }, /* lower */
+ { 0x419, 0x439 }, /* lower */
+ { 0x41a, 0x43a }, /* lower */
+ { 0x41b, 0x43b }, /* lower */
+ { 0x41c, 0x43c }, /* lower */
+ { 0x41d, 0x43d }, /* lower */
+ { 0x41e, 0x43e }, /* lower */
+ { 0x41f, 0x43f }, /* lower */
+ { 0x420, 0x440 }, /* lower */
+ { 0x421, 0x441 }, /* lower */
+ { 0x422, 0x442 }, /* lower */
+ { 0x423, 0x443 }, /* lower */
+ { 0x424, 0x444 }, /* lower */
+ { 0x425, 0x445 }, /* lower */
+ { 0x426, 0x446 }, /* lower */
+ { 0x427, 0x447 }, /* lower */
+ { 0x428, 0x448 }, /* lower */
+ { 0x429, 0x449 }, /* lower */
+ { 0x42a, 0x44a }, /* lower */
+ { 0x42b, 0x44b }, /* lower */
+ { 0x42c, 0x44c }, /* lower */
+ { 0x42d, 0x44d }, /* lower */
+ { 0x42e, 0x44e }, /* lower */
+ { 0x42f, 0x44f }, /* lower */
+ { 0x400, 0x450 }, /* lower */
+ { 0x401, 0x451 }, /* lower */
+ { 0x402, 0x452 }, /* lower */
+ { 0x403, 0x453 }, /* lower */
+ { 0x404, 0x454 }, /* lower */
+ { 0x405, 0x455 }, /* lower */
+ { 0x406, 0x456 }, /* lower */
+ { 0x407, 0x457 }, /* lower */
+ { 0x408, 0x458 }, /* lower */
+ { 0x409, 0x459 }, /* lower */
+ { 0x40a, 0x45a }, /* lower */
+ { 0x40b, 0x45b }, /* lower */
+ { 0x40c, 0x45c }, /* lower */
+ { 0x40d, 0x45d }, /* lower */
+ { 0x40e, 0x45e }, /* lower */
+ { 0x40f, 0x45f }, /* lower */
+ { 0x460, 0x461 }, /* upper */
+ { 0x460, 0x461 }, /* lower */
+ { 0x462, 0x463 }, /* upper */
+ { 0x462, 0x463 }, /* lower */
+ { 0x464, 0x465 }, /* upper */
+ { 0x464, 0x465 }, /* lower */
+ { 0x466, 0x467 }, /* upper */
+ { 0x466, 0x467 }, /* lower */
+ { 0x468, 0x469 }, /* upper */
+ { 0x468, 0x469 }, /* lower */
+ { 0x46a, 0x46b }, /* upper */
+ { 0x46a, 0x46b }, /* lower */
+ { 0x46c, 0x46d }, /* upper */
+ { 0x46c, 0x46d }, /* lower */
+ { 0x46e, 0x46f }, /* upper */
+ { 0x46e, 0x46f }, /* lower */
+ { 0x470, 0x471 }, /* upper */
+ { 0x470, 0x471 }, /* lower */
+ { 0x472, 0x473 }, /* upper */
+ { 0x472, 0x473 }, /* lower */
+ { 0x474, 0x475 }, /* upper */
+ { 0x474, 0x475 }, /* lower */
+ { 0x476, 0x477 }, /* upper */
+ { 0x476, 0x477 }, /* lower */
+ { 0x478, 0x479 }, /* upper */
+ { 0x478, 0x479 }, /* lower */
+ { 0x47a, 0x47b }, /* upper */
+ { 0x47a, 0x47b }, /* lower */
+ { 0x47c, 0x47d }, /* upper */
+ { 0x47c, 0x47d }, /* lower */
+ { 0x47e, 0x47f }, /* upper */
+ { 0x47e, 0x47f }, /* lower */
+ { 0x480, 0x481 }, /* upper */
+ { 0x480, 0x481 }, /* lower */
+ { 0x482, 0x482 },
+ { 0x483, 0x483 },
+ { 0x484, 0x484 },
+ { 0x485, 0x485 },
+ { 0x486, 0x486 },
+ { 0x487, 0x487 },
+ { 0x488, 0x488 },
+ { 0x489, 0x489 },
+ { 0x48a, 0x48b }, /* upper */
+ { 0x48a, 0x48b }, /* lower */
+ { 0x48c, 0x48d }, /* upper */
+ { 0x48c, 0x48d }, /* lower */
+ { 0x48e, 0x48f }, /* upper */
+ { 0x48e, 0x48f }, /* lower */
+ { 0x490, 0x491 }, /* upper */
+ { 0x490, 0x491 }, /* lower */
+ { 0x492, 0x493 }, /* upper */
+ { 0x492, 0x493 }, /* lower */
+ { 0x494, 0x495 }, /* upper */
+ { 0x494, 0x495 }, /* lower */
+ { 0x496, 0x497 }, /* upper */
+ { 0x496, 0x497 }, /* lower */
+ { 0x498, 0x499 }, /* upper */
+ { 0x498, 0x499 }, /* lower */
+ { 0x49a, 0x49b }, /* upper */
+ { 0x49a, 0x49b }, /* lower */
+ { 0x49c, 0x49d }, /* upper */
+ { 0x49c, 0x49d }, /* lower */
+ { 0x49e, 0x49f }, /* upper */
+ { 0x49e, 0x49f }, /* lower */
+ { 0x4a0, 0x4a1 }, /* upper */
+ { 0x4a0, 0x4a1 }, /* lower */
+ { 0x4a2, 0x4a3 }, /* upper */
+ { 0x4a2, 0x4a3 }, /* lower */
+ { 0x4a4, 0x4a5 }, /* upper */
+ { 0x4a4, 0x4a5 }, /* lower */
+ { 0x4a6, 0x4a7 }, /* upper */
+ { 0x4a6, 0x4a7 }, /* lower */
+ { 0x4a8, 0x4a9 }, /* upper */
+ { 0x4a8, 0x4a9 }, /* lower */
+ { 0x4aa, 0x4ab }, /* upper */
+ { 0x4aa, 0x4ab }, /* lower */
+ { 0x4ac, 0x4ad }, /* upper */
+ { 0x4ac, 0x4ad }, /* lower */
+ { 0x4ae, 0x4af }, /* upper */
+ { 0x4ae, 0x4af }, /* lower */
+ { 0x4b0, 0x4b1 }, /* upper */
+ { 0x4b0, 0x4b1 }, /* lower */
+ { 0x4b2, 0x4b3 }, /* upper */
+ { 0x4b2, 0x4b3 }, /* lower */
+ { 0x4b4, 0x4b5 }, /* upper */
+ { 0x4b4, 0x4b5 }, /* lower */
+ { 0x4b6, 0x4b7 }, /* upper */
+ { 0x4b6, 0x4b7 }, /* lower */
+ { 0x4b8, 0x4b9 }, /* upper */
+ { 0x4b8, 0x4b9 }, /* lower */
+ { 0x4ba, 0x4bb }, /* upper */
+ { 0x4ba, 0x4bb }, /* lower */
+ { 0x4bc, 0x4bd }, /* upper */
+ { 0x4bc, 0x4bd }, /* lower */
+ { 0x4be, 0x4bf }, /* upper */
+ { 0x4be, 0x4bf }, /* lower */
+ { 0x4c0, 0x4c0 },
+ { 0x4c1, 0x4c2 }, /* upper */
+ { 0x4c1, 0x4c2 }, /* lower */
+ { 0x4c3, 0x4c4 }, /* upper */
+ { 0x4c3, 0x4c4 }, /* lower */
+ { 0x4c5, 0x4c6 }, /* upper */
+ { 0x4c5, 0x4c6 }, /* lower */
+ { 0x4c7, 0x4c8 }, /* upper */
+ { 0x4c7, 0x4c8 }, /* lower */
+ { 0x4c9, 0x4ca }, /* upper */
+ { 0x4c9, 0x4ca }, /* lower */
+ { 0x4cb, 0x4cc }, /* upper */
+ { 0x4cb, 0x4cc }, /* lower */
+ { 0x4cd, 0x4ce }, /* upper */
+ { 0x4cd, 0x4ce }, /* lower */
+ { 0x4cf, 0x4cf },
+ { 0x4d0, 0x4d1 }, /* upper */
+ { 0x4d0, 0x4d1 }, /* lower */
+ { 0x4d2, 0x4d3 }, /* upper */
+ { 0x4d2, 0x4d3 }, /* lower */
+ { 0x4d4, 0x4d5 }, /* upper */
+ { 0x4d4, 0x4d5 }, /* lower */
+ { 0x4d6, 0x4d7 }, /* upper */
+ { 0x4d6, 0x4d7 }, /* lower */
+ { 0x4d8, 0x4d9 }, /* upper */
+ { 0x4d8, 0x4d9 }, /* lower */
+ { 0x4da, 0x4db }, /* upper */
+ { 0x4da, 0x4db }, /* lower */
+ { 0x4dc, 0x4dd }, /* upper */
+ { 0x4dc, 0x4dd }, /* lower */
+ { 0x4de, 0x4df }, /* upper */
+ { 0x4de, 0x4df }, /* lower */
+ { 0x4e0, 0x4e1 }, /* upper */
+ { 0x4e0, 0x4e1 }, /* lower */
+ { 0x4e2, 0x4e3 }, /* upper */
+ { 0x4e2, 0x4e3 }, /* lower */
+ { 0x4e4, 0x4e5 }, /* upper */
+ { 0x4e4, 0x4e5 }, /* lower */
+ { 0x4e6, 0x4e7 }, /* upper */
+ { 0x4e6, 0x4e7 }, /* lower */
+ { 0x4e8, 0x4e9 }, /* upper */
+ { 0x4e8, 0x4e9 }, /* lower */
+ { 0x4ea, 0x4eb }, /* upper */
+ { 0x4ea, 0x4eb }, /* lower */
+ { 0x4ec, 0x4ed }, /* upper */
+ { 0x4ec, 0x4ed }, /* lower */
+ { 0x4ee, 0x4ef }, /* upper */
+ { 0x4ee, 0x4ef }, /* lower */
+ { 0x4f0, 0x4f1 }, /* upper */
+ { 0x4f0, 0x4f1 }, /* lower */
+ { 0x4f2, 0x4f3 }, /* upper */
+ { 0x4f2, 0x4f3 }, /* lower */
+ { 0x4f4, 0x4f5 }, /* upper */
+ { 0x4f4, 0x4f5 }, /* lower */
+ { 0x4f6, 0x4f6 },
+ { 0x4f7, 0x4f7 },
+ { 0x4f8, 0x4f9 }, /* upper */
+ { 0x4f8, 0x4f9 }, /* lower */
+ { 0x4fa, 0x4fa },
+ { 0x4fb, 0x4fb },
+ { 0x4fc, 0x4fc },
+ { 0x4fd, 0x4fd },
+ { 0x4fe, 0x4fe },
+ { 0x4ff, 0x4ff },
+};
+
+gli_case_block_t unigen_case_block_0x5[256] = {
+ { 0x500, 0x501 }, /* upper */
+ { 0x500, 0x501 }, /* lower */
+ { 0x502, 0x503 }, /* upper */
+ { 0x502, 0x503 }, /* lower */
+ { 0x504, 0x505 }, /* upper */
+ { 0x504, 0x505 }, /* lower */
+ { 0x506, 0x507 }, /* upper */
+ { 0x506, 0x507 }, /* lower */
+ { 0x508, 0x509 }, /* upper */
+ { 0x508, 0x509 }, /* lower */
+ { 0x50a, 0x50b }, /* upper */
+ { 0x50a, 0x50b }, /* lower */
+ { 0x50c, 0x50d }, /* upper */
+ { 0x50c, 0x50d }, /* lower */
+ { 0x50e, 0x50f }, /* upper */
+ { 0x50e, 0x50f }, /* lower */
+ { 0x510, 0x510 },
+ { 0x511, 0x511 },
+ { 0x512, 0x512 },
+ { 0x513, 0x513 },
+ { 0x514, 0x514 },
+ { 0x515, 0x515 },
+ { 0x516, 0x516 },
+ { 0x517, 0x517 },
+ { 0x518, 0x518 },
+ { 0x519, 0x519 },
+ { 0x51a, 0x51a },
+ { 0x51b, 0x51b },
+ { 0x51c, 0x51c },
+ { 0x51d, 0x51d },
+ { 0x51e, 0x51e },
+ { 0x51f, 0x51f },
+ { 0x520, 0x520 },
+ { 0x521, 0x521 },
+ { 0x522, 0x522 },
+ { 0x523, 0x523 },
+ { 0x524, 0x524 },
+ { 0x525, 0x525 },
+ { 0x526, 0x526 },
+ { 0x527, 0x527 },
+ { 0x528, 0x528 },
+ { 0x529, 0x529 },
+ { 0x52a, 0x52a },
+ { 0x52b, 0x52b },
+ { 0x52c, 0x52c },
+ { 0x52d, 0x52d },
+ { 0x52e, 0x52e },
+ { 0x52f, 0x52f },
+ { 0x530, 0x530 },
+ { 0x531, 0x561 }, /* upper */
+ { 0x532, 0x562 }, /* upper */
+ { 0x533, 0x563 }, /* upper */
+ { 0x534, 0x564 }, /* upper */
+ { 0x535, 0x565 }, /* upper */
+ { 0x536, 0x566 }, /* upper */
+ { 0x537, 0x567 }, /* upper */
+ { 0x538, 0x568 }, /* upper */
+ { 0x539, 0x569 }, /* upper */
+ { 0x53a, 0x56a }, /* upper */
+ { 0x53b, 0x56b }, /* upper */
+ { 0x53c, 0x56c }, /* upper */
+ { 0x53d, 0x56d }, /* upper */
+ { 0x53e, 0x56e }, /* upper */
+ { 0x53f, 0x56f }, /* upper */
+ { 0x540, 0x570 }, /* upper */
+ { 0x541, 0x571 }, /* upper */
+ { 0x542, 0x572 }, /* upper */
+ { 0x543, 0x573 }, /* upper */
+ { 0x544, 0x574 }, /* upper */
+ { 0x545, 0x575 }, /* upper */
+ { 0x546, 0x576 }, /* upper */
+ { 0x547, 0x577 }, /* upper */
+ { 0x548, 0x578 }, /* upper */
+ { 0x549, 0x579 }, /* upper */
+ { 0x54a, 0x57a }, /* upper */
+ { 0x54b, 0x57b }, /* upper */
+ { 0x54c, 0x57c }, /* upper */
+ { 0x54d, 0x57d }, /* upper */
+ { 0x54e, 0x57e }, /* upper */
+ { 0x54f, 0x57f }, /* upper */
+ { 0x550, 0x580 }, /* upper */
+ { 0x551, 0x581 }, /* upper */
+ { 0x552, 0x582 }, /* upper */
+ { 0x553, 0x583 }, /* upper */
+ { 0x554, 0x584 }, /* upper */
+ { 0x555, 0x585 }, /* upper */
+ { 0x556, 0x586 }, /* upper */
+ { 0x557, 0x557 },
+ { 0x558, 0x558 },
+ { 0x559, 0x559 },
+ { 0x55a, 0x55a },
+ { 0x55b, 0x55b },
+ { 0x55c, 0x55c },
+ { 0x55d, 0x55d },
+ { 0x55e, 0x55e },
+ { 0x55f, 0x55f },
+ { 0x560, 0x560 },
+ { 0x531, 0x561 }, /* lower */
+ { 0x532, 0x562 }, /* lower */
+ { 0x533, 0x563 }, /* lower */
+ { 0x534, 0x564 }, /* lower */
+ { 0x535, 0x565 }, /* lower */
+ { 0x536, 0x566 }, /* lower */
+ { 0x537, 0x567 }, /* lower */
+ { 0x538, 0x568 }, /* lower */
+ { 0x539, 0x569 }, /* lower */
+ { 0x53a, 0x56a }, /* lower */
+ { 0x53b, 0x56b }, /* lower */
+ { 0x53c, 0x56c }, /* lower */
+ { 0x53d, 0x56d }, /* lower */
+ { 0x53e, 0x56e }, /* lower */
+ { 0x53f, 0x56f }, /* lower */
+ { 0x540, 0x570 }, /* lower */
+ { 0x541, 0x571 }, /* lower */
+ { 0x542, 0x572 }, /* lower */
+ { 0x543, 0x573 }, /* lower */
+ { 0x544, 0x574 }, /* lower */
+ { 0x545, 0x575 }, /* lower */
+ { 0x546, 0x576 }, /* lower */
+ { 0x547, 0x577 }, /* lower */
+ { 0x548, 0x578 }, /* lower */
+ { 0x549, 0x579 }, /* lower */
+ { 0x54a, 0x57a }, /* lower */
+ { 0x54b, 0x57b }, /* lower */
+ { 0x54c, 0x57c }, /* lower */
+ { 0x54d, 0x57d }, /* lower */
+ { 0x54e, 0x57e }, /* lower */
+ { 0x54f, 0x57f }, /* lower */
+ { 0x550, 0x580 }, /* lower */
+ { 0x551, 0x581 }, /* lower */
+ { 0x552, 0x582 }, /* lower */
+ { 0x553, 0x583 }, /* lower */
+ { 0x554, 0x584 }, /* lower */
+ { 0x555, 0x585 }, /* lower */
+ { 0x556, 0x586 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x588, 0x588 },
+ { 0x589, 0x589 },
+ { 0x58a, 0x58a },
+ { 0x58b, 0x58b },
+ { 0x58c, 0x58c },
+ { 0x58d, 0x58d },
+ { 0x58e, 0x58e },
+ { 0x58f, 0x58f },
+ { 0x590, 0x590 },
+ { 0x591, 0x591 },
+ { 0x592, 0x592 },
+ { 0x593, 0x593 },
+ { 0x594, 0x594 },
+ { 0x595, 0x595 },
+ { 0x596, 0x596 },
+ { 0x597, 0x597 },
+ { 0x598, 0x598 },
+ { 0x599, 0x599 },
+ { 0x59a, 0x59a },
+ { 0x59b, 0x59b },
+ { 0x59c, 0x59c },
+ { 0x59d, 0x59d },
+ { 0x59e, 0x59e },
+ { 0x59f, 0x59f },
+ { 0x5a0, 0x5a0 },
+ { 0x5a1, 0x5a1 },
+ { 0x5a2, 0x5a2 },
+ { 0x5a3, 0x5a3 },
+ { 0x5a4, 0x5a4 },
+ { 0x5a5, 0x5a5 },
+ { 0x5a6, 0x5a6 },
+ { 0x5a7, 0x5a7 },
+ { 0x5a8, 0x5a8 },
+ { 0x5a9, 0x5a9 },
+ { 0x5aa, 0x5aa },
+ { 0x5ab, 0x5ab },
+ { 0x5ac, 0x5ac },
+ { 0x5ad, 0x5ad },
+ { 0x5ae, 0x5ae },
+ { 0x5af, 0x5af },
+ { 0x5b0, 0x5b0 },
+ { 0x5b1, 0x5b1 },
+ { 0x5b2, 0x5b2 },
+ { 0x5b3, 0x5b3 },
+ { 0x5b4, 0x5b4 },
+ { 0x5b5, 0x5b5 },
+ { 0x5b6, 0x5b6 },
+ { 0x5b7, 0x5b7 },
+ { 0x5b8, 0x5b8 },
+ { 0x5b9, 0x5b9 },
+ { 0x5ba, 0x5ba },
+ { 0x5bb, 0x5bb },
+ { 0x5bc, 0x5bc },
+ { 0x5bd, 0x5bd },
+ { 0x5be, 0x5be },
+ { 0x5bf, 0x5bf },
+ { 0x5c0, 0x5c0 },
+ { 0x5c1, 0x5c1 },
+ { 0x5c2, 0x5c2 },
+ { 0x5c3, 0x5c3 },
+ { 0x5c4, 0x5c4 },
+ { 0x5c5, 0x5c5 },
+ { 0x5c6, 0x5c6 },
+ { 0x5c7, 0x5c7 },
+ { 0x5c8, 0x5c8 },
+ { 0x5c9, 0x5c9 },
+ { 0x5ca, 0x5ca },
+ { 0x5cb, 0x5cb },
+ { 0x5cc, 0x5cc },
+ { 0x5cd, 0x5cd },
+ { 0x5ce, 0x5ce },
+ { 0x5cf, 0x5cf },
+ { 0x5d0, 0x5d0 },
+ { 0x5d1, 0x5d1 },
+ { 0x5d2, 0x5d2 },
+ { 0x5d3, 0x5d3 },
+ { 0x5d4, 0x5d4 },
+ { 0x5d5, 0x5d5 },
+ { 0x5d6, 0x5d6 },
+ { 0x5d7, 0x5d7 },
+ { 0x5d8, 0x5d8 },
+ { 0x5d9, 0x5d9 },
+ { 0x5da, 0x5da },
+ { 0x5db, 0x5db },
+ { 0x5dc, 0x5dc },
+ { 0x5dd, 0x5dd },
+ { 0x5de, 0x5de },
+ { 0x5df, 0x5df },
+ { 0x5e0, 0x5e0 },
+ { 0x5e1, 0x5e1 },
+ { 0x5e2, 0x5e2 },
+ { 0x5e3, 0x5e3 },
+ { 0x5e4, 0x5e4 },
+ { 0x5e5, 0x5e5 },
+ { 0x5e6, 0x5e6 },
+ { 0x5e7, 0x5e7 },
+ { 0x5e8, 0x5e8 },
+ { 0x5e9, 0x5e9 },
+ { 0x5ea, 0x5ea },
+ { 0x5eb, 0x5eb },
+ { 0x5ec, 0x5ec },
+ { 0x5ed, 0x5ed },
+ { 0x5ee, 0x5ee },
+ { 0x5ef, 0x5ef },
+ { 0x5f0, 0x5f0 },
+ { 0x5f1, 0x5f1 },
+ { 0x5f2, 0x5f2 },
+ { 0x5f3, 0x5f3 },
+ { 0x5f4, 0x5f4 },
+ { 0x5f5, 0x5f5 },
+ { 0x5f6, 0x5f6 },
+ { 0x5f7, 0x5f7 },
+ { 0x5f8, 0x5f8 },
+ { 0x5f9, 0x5f9 },
+ { 0x5fa, 0x5fa },
+ { 0x5fb, 0x5fb },
+ { 0x5fc, 0x5fc },
+ { 0x5fd, 0x5fd },
+ { 0x5fe, 0x5fe },
+ { 0x5ff, 0x5ff },
+};
+
+gli_case_block_t unigen_case_block_0x1e[256] = {
+ { 0x1e00, 0x1e01 }, /* upper */
+ { 0x1e00, 0x1e01 }, /* lower */
+ { 0x1e02, 0x1e03 }, /* upper */
+ { 0x1e02, 0x1e03 }, /* lower */
+ { 0x1e04, 0x1e05 }, /* upper */
+ { 0x1e04, 0x1e05 }, /* lower */
+ { 0x1e06, 0x1e07 }, /* upper */
+ { 0x1e06, 0x1e07 }, /* lower */
+ { 0x1e08, 0x1e09 }, /* upper */
+ { 0x1e08, 0x1e09 }, /* lower */
+ { 0x1e0a, 0x1e0b }, /* upper */
+ { 0x1e0a, 0x1e0b }, /* lower */
+ { 0x1e0c, 0x1e0d }, /* upper */
+ { 0x1e0c, 0x1e0d }, /* lower */
+ { 0x1e0e, 0x1e0f }, /* upper */
+ { 0x1e0e, 0x1e0f }, /* lower */
+ { 0x1e10, 0x1e11 }, /* upper */
+ { 0x1e10, 0x1e11 }, /* lower */
+ { 0x1e12, 0x1e13 }, /* upper */
+ { 0x1e12, 0x1e13 }, /* lower */
+ { 0x1e14, 0x1e15 }, /* upper */
+ { 0x1e14, 0x1e15 }, /* lower */
+ { 0x1e16, 0x1e17 }, /* upper */
+ { 0x1e16, 0x1e17 }, /* lower */
+ { 0x1e18, 0x1e19 }, /* upper */
+ { 0x1e18, 0x1e19 }, /* lower */
+ { 0x1e1a, 0x1e1b }, /* upper */
+ { 0x1e1a, 0x1e1b }, /* lower */
+ { 0x1e1c, 0x1e1d }, /* upper */
+ { 0x1e1c, 0x1e1d }, /* lower */
+ { 0x1e1e, 0x1e1f }, /* upper */
+ { 0x1e1e, 0x1e1f }, /* lower */
+ { 0x1e20, 0x1e21 }, /* upper */
+ { 0x1e20, 0x1e21 }, /* lower */
+ { 0x1e22, 0x1e23 }, /* upper */
+ { 0x1e22, 0x1e23 }, /* lower */
+ { 0x1e24, 0x1e25 }, /* upper */
+ { 0x1e24, 0x1e25 }, /* lower */
+ { 0x1e26, 0x1e27 }, /* upper */
+ { 0x1e26, 0x1e27 }, /* lower */
+ { 0x1e28, 0x1e29 }, /* upper */
+ { 0x1e28, 0x1e29 }, /* lower */
+ { 0x1e2a, 0x1e2b }, /* upper */
+ { 0x1e2a, 0x1e2b }, /* lower */
+ { 0x1e2c, 0x1e2d }, /* upper */
+ { 0x1e2c, 0x1e2d }, /* lower */
+ { 0x1e2e, 0x1e2f }, /* upper */
+ { 0x1e2e, 0x1e2f }, /* lower */
+ { 0x1e30, 0x1e31 }, /* upper */
+ { 0x1e30, 0x1e31 }, /* lower */
+ { 0x1e32, 0x1e33 }, /* upper */
+ { 0x1e32, 0x1e33 }, /* lower */
+ { 0x1e34, 0x1e35 }, /* upper */
+ { 0x1e34, 0x1e35 }, /* lower */
+ { 0x1e36, 0x1e37 }, /* upper */
+ { 0x1e36, 0x1e37 }, /* lower */
+ { 0x1e38, 0x1e39 }, /* upper */
+ { 0x1e38, 0x1e39 }, /* lower */
+ { 0x1e3a, 0x1e3b }, /* upper */
+ { 0x1e3a, 0x1e3b }, /* lower */
+ { 0x1e3c, 0x1e3d }, /* upper */
+ { 0x1e3c, 0x1e3d }, /* lower */
+ { 0x1e3e, 0x1e3f }, /* upper */
+ { 0x1e3e, 0x1e3f }, /* lower */
+ { 0x1e40, 0x1e41 }, /* upper */
+ { 0x1e40, 0x1e41 }, /* lower */
+ { 0x1e42, 0x1e43 }, /* upper */
+ { 0x1e42, 0x1e43 }, /* lower */
+ { 0x1e44, 0x1e45 }, /* upper */
+ { 0x1e44, 0x1e45 }, /* lower */
+ { 0x1e46, 0x1e47 }, /* upper */
+ { 0x1e46, 0x1e47 }, /* lower */
+ { 0x1e48, 0x1e49 }, /* upper */
+ { 0x1e48, 0x1e49 }, /* lower */
+ { 0x1e4a, 0x1e4b }, /* upper */
+ { 0x1e4a, 0x1e4b }, /* lower */
+ { 0x1e4c, 0x1e4d }, /* upper */
+ { 0x1e4c, 0x1e4d }, /* lower */
+ { 0x1e4e, 0x1e4f }, /* upper */
+ { 0x1e4e, 0x1e4f }, /* lower */
+ { 0x1e50, 0x1e51 }, /* upper */
+ { 0x1e50, 0x1e51 }, /* lower */
+ { 0x1e52, 0x1e53 }, /* upper */
+ { 0x1e52, 0x1e53 }, /* lower */
+ { 0x1e54, 0x1e55 }, /* upper */
+ { 0x1e54, 0x1e55 }, /* lower */
+ { 0x1e56, 0x1e57 }, /* upper */
+ { 0x1e56, 0x1e57 }, /* lower */
+ { 0x1e58, 0x1e59 }, /* upper */
+ { 0x1e58, 0x1e59 }, /* lower */
+ { 0x1e5a, 0x1e5b }, /* upper */
+ { 0x1e5a, 0x1e5b }, /* lower */
+ { 0x1e5c, 0x1e5d }, /* upper */
+ { 0x1e5c, 0x1e5d }, /* lower */
+ { 0x1e5e, 0x1e5f }, /* upper */
+ { 0x1e5e, 0x1e5f }, /* lower */
+ { 0x1e60, 0x1e61 }, /* upper */
+ { 0x1e60, 0x1e61 }, /* lower */
+ { 0x1e62, 0x1e63 }, /* upper */
+ { 0x1e62, 0x1e63 }, /* lower */
+ { 0x1e64, 0x1e65 }, /* upper */
+ { 0x1e64, 0x1e65 }, /* lower */
+ { 0x1e66, 0x1e67 }, /* upper */
+ { 0x1e66, 0x1e67 }, /* lower */
+ { 0x1e68, 0x1e69 }, /* upper */
+ { 0x1e68, 0x1e69 }, /* lower */
+ { 0x1e6a, 0x1e6b }, /* upper */
+ { 0x1e6a, 0x1e6b }, /* lower */
+ { 0x1e6c, 0x1e6d }, /* upper */
+ { 0x1e6c, 0x1e6d }, /* lower */
+ { 0x1e6e, 0x1e6f }, /* upper */
+ { 0x1e6e, 0x1e6f }, /* lower */
+ { 0x1e70, 0x1e71 }, /* upper */
+ { 0x1e70, 0x1e71 }, /* lower */
+ { 0x1e72, 0x1e73 }, /* upper */
+ { 0x1e72, 0x1e73 }, /* lower */
+ { 0x1e74, 0x1e75 }, /* upper */
+ { 0x1e74, 0x1e75 }, /* lower */
+ { 0x1e76, 0x1e77 }, /* upper */
+ { 0x1e76, 0x1e77 }, /* lower */
+ { 0x1e78, 0x1e79 }, /* upper */
+ { 0x1e78, 0x1e79 }, /* lower */
+ { 0x1e7a, 0x1e7b }, /* upper */
+ { 0x1e7a, 0x1e7b }, /* lower */
+ { 0x1e7c, 0x1e7d }, /* upper */
+ { 0x1e7c, 0x1e7d }, /* lower */
+ { 0x1e7e, 0x1e7f }, /* upper */
+ { 0x1e7e, 0x1e7f }, /* lower */
+ { 0x1e80, 0x1e81 }, /* upper */
+ { 0x1e80, 0x1e81 }, /* lower */
+ { 0x1e82, 0x1e83 }, /* upper */
+ { 0x1e82, 0x1e83 }, /* lower */
+ { 0x1e84, 0x1e85 }, /* upper */
+ { 0x1e84, 0x1e85 }, /* lower */
+ { 0x1e86, 0x1e87 }, /* upper */
+ { 0x1e86, 0x1e87 }, /* lower */
+ { 0x1e88, 0x1e89 }, /* upper */
+ { 0x1e88, 0x1e89 }, /* lower */
+ { 0x1e8a, 0x1e8b }, /* upper */
+ { 0x1e8a, 0x1e8b }, /* lower */
+ { 0x1e8c, 0x1e8d }, /* upper */
+ { 0x1e8c, 0x1e8d }, /* lower */
+ { 0x1e8e, 0x1e8f }, /* upper */
+ { 0x1e8e, 0x1e8f }, /* lower */
+ { 0x1e90, 0x1e91 }, /* upper */
+ { 0x1e90, 0x1e91 }, /* lower */
+ { 0x1e92, 0x1e93 }, /* upper */
+ { 0x1e92, 0x1e93 }, /* lower */
+ { 0x1e94, 0x1e95 }, /* upper */
+ { 0x1e94, 0x1e95 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1e60, 0x1e9b }, /* lower */
+ { 0x1e9c, 0x1e9c },
+ { 0x1e9d, 0x1e9d },
+ { 0x1e9e, 0x1e9e },
+ { 0x1e9f, 0x1e9f },
+ { 0x1ea0, 0x1ea1 }, /* upper */
+ { 0x1ea0, 0x1ea1 }, /* lower */
+ { 0x1ea2, 0x1ea3 }, /* upper */
+ { 0x1ea2, 0x1ea3 }, /* lower */
+ { 0x1ea4, 0x1ea5 }, /* upper */
+ { 0x1ea4, 0x1ea5 }, /* lower */
+ { 0x1ea6, 0x1ea7 }, /* upper */
+ { 0x1ea6, 0x1ea7 }, /* lower */
+ { 0x1ea8, 0x1ea9 }, /* upper */
+ { 0x1ea8, 0x1ea9 }, /* lower */
+ { 0x1eaa, 0x1eab }, /* upper */
+ { 0x1eaa, 0x1eab }, /* lower */
+ { 0x1eac, 0x1ead }, /* upper */
+ { 0x1eac, 0x1ead }, /* lower */
+ { 0x1eae, 0x1eaf }, /* upper */
+ { 0x1eae, 0x1eaf }, /* lower */
+ { 0x1eb0, 0x1eb1 }, /* upper */
+ { 0x1eb0, 0x1eb1 }, /* lower */
+ { 0x1eb2, 0x1eb3 }, /* upper */
+ { 0x1eb2, 0x1eb3 }, /* lower */
+ { 0x1eb4, 0x1eb5 }, /* upper */
+ { 0x1eb4, 0x1eb5 }, /* lower */
+ { 0x1eb6, 0x1eb7 }, /* upper */
+ { 0x1eb6, 0x1eb7 }, /* lower */
+ { 0x1eb8, 0x1eb9 }, /* upper */
+ { 0x1eb8, 0x1eb9 }, /* lower */
+ { 0x1eba, 0x1ebb }, /* upper */
+ { 0x1eba, 0x1ebb }, /* lower */
+ { 0x1ebc, 0x1ebd }, /* upper */
+ { 0x1ebc, 0x1ebd }, /* lower */
+ { 0x1ebe, 0x1ebf }, /* upper */
+ { 0x1ebe, 0x1ebf }, /* lower */
+ { 0x1ec0, 0x1ec1 }, /* upper */
+ { 0x1ec0, 0x1ec1 }, /* lower */
+ { 0x1ec2, 0x1ec3 }, /* upper */
+ { 0x1ec2, 0x1ec3 }, /* lower */
+ { 0x1ec4, 0x1ec5 }, /* upper */
+ { 0x1ec4, 0x1ec5 }, /* lower */
+ { 0x1ec6, 0x1ec7 }, /* upper */
+ { 0x1ec6, 0x1ec7 }, /* lower */
+ { 0x1ec8, 0x1ec9 }, /* upper */
+ { 0x1ec8, 0x1ec9 }, /* lower */
+ { 0x1eca, 0x1ecb }, /* upper */
+ { 0x1eca, 0x1ecb }, /* lower */
+ { 0x1ecc, 0x1ecd }, /* upper */
+ { 0x1ecc, 0x1ecd }, /* lower */
+ { 0x1ece, 0x1ecf }, /* upper */
+ { 0x1ece, 0x1ecf }, /* lower */
+ { 0x1ed0, 0x1ed1 }, /* upper */
+ { 0x1ed0, 0x1ed1 }, /* lower */
+ { 0x1ed2, 0x1ed3 }, /* upper */
+ { 0x1ed2, 0x1ed3 }, /* lower */
+ { 0x1ed4, 0x1ed5 }, /* upper */
+ { 0x1ed4, 0x1ed5 }, /* lower */
+ { 0x1ed6, 0x1ed7 }, /* upper */
+ { 0x1ed6, 0x1ed7 }, /* lower */
+ { 0x1ed8, 0x1ed9 }, /* upper */
+ { 0x1ed8, 0x1ed9 }, /* lower */
+ { 0x1eda, 0x1edb }, /* upper */
+ { 0x1eda, 0x1edb }, /* lower */
+ { 0x1edc, 0x1edd }, /* upper */
+ { 0x1edc, 0x1edd }, /* lower */
+ { 0x1ede, 0x1edf }, /* upper */
+ { 0x1ede, 0x1edf }, /* lower */
+ { 0x1ee0, 0x1ee1 }, /* upper */
+ { 0x1ee0, 0x1ee1 }, /* lower */
+ { 0x1ee2, 0x1ee3 }, /* upper */
+ { 0x1ee2, 0x1ee3 }, /* lower */
+ { 0x1ee4, 0x1ee5 }, /* upper */
+ { 0x1ee4, 0x1ee5 }, /* lower */
+ { 0x1ee6, 0x1ee7 }, /* upper */
+ { 0x1ee6, 0x1ee7 }, /* lower */
+ { 0x1ee8, 0x1ee9 }, /* upper */
+ { 0x1ee8, 0x1ee9 }, /* lower */
+ { 0x1eea, 0x1eeb }, /* upper */
+ { 0x1eea, 0x1eeb }, /* lower */
+ { 0x1eec, 0x1eed }, /* upper */
+ { 0x1eec, 0x1eed }, /* lower */
+ { 0x1eee, 0x1eef }, /* upper */
+ { 0x1eee, 0x1eef }, /* lower */
+ { 0x1ef0, 0x1ef1 }, /* upper */
+ { 0x1ef0, 0x1ef1 }, /* lower */
+ { 0x1ef2, 0x1ef3 }, /* upper */
+ { 0x1ef2, 0x1ef3 }, /* lower */
+ { 0x1ef4, 0x1ef5 }, /* upper */
+ { 0x1ef4, 0x1ef5 }, /* lower */
+ { 0x1ef6, 0x1ef7 }, /* upper */
+ { 0x1ef6, 0x1ef7 }, /* lower */
+ { 0x1ef8, 0x1ef9 }, /* upper */
+ { 0x1ef8, 0x1ef9 }, /* lower */
+ { 0x1efa, 0x1efa },
+ { 0x1efb, 0x1efb },
+ { 0x1efc, 0x1efc },
+ { 0x1efd, 0x1efd },
+ { 0x1efe, 0x1efe },
+ { 0x1eff, 0x1eff },
+};
+
+gli_case_block_t unigen_case_block_0x1f[256] = {
+ { 0x1f08, 0x1f00 }, /* lower */
+ { 0x1f09, 0x1f01 }, /* lower */
+ { 0x1f0a, 0x1f02 }, /* lower */
+ { 0x1f0b, 0x1f03 }, /* lower */
+ { 0x1f0c, 0x1f04 }, /* lower */
+ { 0x1f0d, 0x1f05 }, /* lower */
+ { 0x1f0e, 0x1f06 }, /* lower */
+ { 0x1f0f, 0x1f07 }, /* lower */
+ { 0x1f08, 0x1f00 }, /* upper */
+ { 0x1f09, 0x1f01 }, /* upper */
+ { 0x1f0a, 0x1f02 }, /* upper */
+ { 0x1f0b, 0x1f03 }, /* upper */
+ { 0x1f0c, 0x1f04 }, /* upper */
+ { 0x1f0d, 0x1f05 }, /* upper */
+ { 0x1f0e, 0x1f06 }, /* upper */
+ { 0x1f0f, 0x1f07 }, /* upper */
+ { 0x1f18, 0x1f10 }, /* lower */
+ { 0x1f19, 0x1f11 }, /* lower */
+ { 0x1f1a, 0x1f12 }, /* lower */
+ { 0x1f1b, 0x1f13 }, /* lower */
+ { 0x1f1c, 0x1f14 }, /* lower */
+ { 0x1f1d, 0x1f15 }, /* lower */
+ { 0x1f16, 0x1f16 },
+ { 0x1f17, 0x1f17 },
+ { 0x1f18, 0x1f10 }, /* upper */
+ { 0x1f19, 0x1f11 }, /* upper */
+ { 0x1f1a, 0x1f12 }, /* upper */
+ { 0x1f1b, 0x1f13 }, /* upper */
+ { 0x1f1c, 0x1f14 }, /* upper */
+ { 0x1f1d, 0x1f15 }, /* upper */
+ { 0x1f1e, 0x1f1e },
+ { 0x1f1f, 0x1f1f },
+ { 0x1f28, 0x1f20 }, /* lower */
+ { 0x1f29, 0x1f21 }, /* lower */
+ { 0x1f2a, 0x1f22 }, /* lower */
+ { 0x1f2b, 0x1f23 }, /* lower */
+ { 0x1f2c, 0x1f24 }, /* lower */
+ { 0x1f2d, 0x1f25 }, /* lower */
+ { 0x1f2e, 0x1f26 }, /* lower */
+ { 0x1f2f, 0x1f27 }, /* lower */
+ { 0x1f28, 0x1f20 }, /* upper */
+ { 0x1f29, 0x1f21 }, /* upper */
+ { 0x1f2a, 0x1f22 }, /* upper */
+ { 0x1f2b, 0x1f23 }, /* upper */
+ { 0x1f2c, 0x1f24 }, /* upper */
+ { 0x1f2d, 0x1f25 }, /* upper */
+ { 0x1f2e, 0x1f26 }, /* upper */
+ { 0x1f2f, 0x1f27 }, /* upper */
+ { 0x1f38, 0x1f30 }, /* lower */
+ { 0x1f39, 0x1f31 }, /* lower */
+ { 0x1f3a, 0x1f32 }, /* lower */
+ { 0x1f3b, 0x1f33 }, /* lower */
+ { 0x1f3c, 0x1f34 }, /* lower */
+ { 0x1f3d, 0x1f35 }, /* lower */
+ { 0x1f3e, 0x1f36 }, /* lower */
+ { 0x1f3f, 0x1f37 }, /* lower */
+ { 0x1f38, 0x1f30 }, /* upper */
+ { 0x1f39, 0x1f31 }, /* upper */
+ { 0x1f3a, 0x1f32 }, /* upper */
+ { 0x1f3b, 0x1f33 }, /* upper */
+ { 0x1f3c, 0x1f34 }, /* upper */
+ { 0x1f3d, 0x1f35 }, /* upper */
+ { 0x1f3e, 0x1f36 }, /* upper */
+ { 0x1f3f, 0x1f37 }, /* upper */
+ { 0x1f48, 0x1f40 }, /* lower */
+ { 0x1f49, 0x1f41 }, /* lower */
+ { 0x1f4a, 0x1f42 }, /* lower */
+ { 0x1f4b, 0x1f43 }, /* lower */
+ { 0x1f4c, 0x1f44 }, /* lower */
+ { 0x1f4d, 0x1f45 }, /* lower */
+ { 0x1f46, 0x1f46 },
+ { 0x1f47, 0x1f47 },
+ { 0x1f48, 0x1f40 }, /* upper */
+ { 0x1f49, 0x1f41 }, /* upper */
+ { 0x1f4a, 0x1f42 }, /* upper */
+ { 0x1f4b, 0x1f43 }, /* upper */
+ { 0x1f4c, 0x1f44 }, /* upper */
+ { 0x1f4d, 0x1f45 }, /* upper */
+ { 0x1f4e, 0x1f4e },
+ { 0x1f4f, 0x1f4f },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1f59, 0x1f51 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1f5b, 0x1f53 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1f5d, 0x1f55 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1f5f, 0x1f57 }, /* lower */
+ { 0x1f58, 0x1f58 },
+ { 0x1f59, 0x1f51 }, /* upper */
+ { 0x1f5a, 0x1f5a },
+ { 0x1f5b, 0x1f53 }, /* upper */
+ { 0x1f5c, 0x1f5c },
+ { 0x1f5d, 0x1f55 }, /* upper */
+ { 0x1f5e, 0x1f5e },
+ { 0x1f5f, 0x1f57 }, /* upper */
+ { 0x1f68, 0x1f60 }, /* lower */
+ { 0x1f69, 0x1f61 }, /* lower */
+ { 0x1f6a, 0x1f62 }, /* lower */
+ { 0x1f6b, 0x1f63 }, /* lower */
+ { 0x1f6c, 0x1f64 }, /* lower */
+ { 0x1f6d, 0x1f65 }, /* lower */
+ { 0x1f6e, 0x1f66 }, /* lower */
+ { 0x1f6f, 0x1f67 }, /* lower */
+ { 0x1f68, 0x1f60 }, /* upper */
+ { 0x1f69, 0x1f61 }, /* upper */
+ { 0x1f6a, 0x1f62 }, /* upper */
+ { 0x1f6b, 0x1f63 }, /* upper */
+ { 0x1f6c, 0x1f64 }, /* upper */
+ { 0x1f6d, 0x1f65 }, /* upper */
+ { 0x1f6e, 0x1f66 }, /* upper */
+ { 0x1f6f, 0x1f67 }, /* upper */
+ { 0x1fba, 0x1f70 }, /* lower */
+ { 0x1fbb, 0x1f71 }, /* lower */
+ { 0x1fc8, 0x1f72 }, /* lower */
+ { 0x1fc9, 0x1f73 }, /* lower */
+ { 0x1fca, 0x1f74 }, /* lower */
+ { 0x1fcb, 0x1f75 }, /* lower */
+ { 0x1fda, 0x1f76 }, /* lower */
+ { 0x1fdb, 0x1f77 }, /* lower */
+ { 0x1ff8, 0x1f78 }, /* lower */
+ { 0x1ff9, 0x1f79 }, /* lower */
+ { 0x1fea, 0x1f7a }, /* lower */
+ { 0x1feb, 0x1f7b }, /* lower */
+ { 0x1ffa, 0x1f7c }, /* lower */
+ { 0x1ffb, 0x1f7d }, /* lower */
+ { 0x1f7e, 0x1f7e },
+ { 0x1f7f, 0x1f7f },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fb8, 0x1fb0 }, /* lower */
+ { 0x1fb9, 0x1fb1 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fb5, 0x1fb5 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fb8, 0x1fb0 }, /* upper */
+ { 0x1fb9, 0x1fb1 }, /* upper */
+ { 0x1fba, 0x1f70 }, /* upper */
+ { 0x1fbb, 0x1f71 }, /* upper */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fbd, 0x1fbd },
+ { 0x399, 0x1fbe }, /* lower */
+ { 0x1fbf, 0x1fbf },
+ { 0x1fc0, 0x1fc0 },
+ { 0x1fc1, 0x1fc1 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fc5, 0x1fc5 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fc8, 0x1f72 }, /* upper */
+ { 0x1fc9, 0x1f73 }, /* upper */
+ { 0x1fca, 0x1f74 }, /* upper */
+ { 0x1fcb, 0x1f75 }, /* upper */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fcd, 0x1fcd },
+ { 0x1fce, 0x1fce },
+ { 0x1fcf, 0x1fcf },
+ { 0x1fd8, 0x1fd0 }, /* lower */
+ { 0x1fd9, 0x1fd1 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fd4, 0x1fd4 },
+ { 0x1fd5, 0x1fd5 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fd8, 0x1fd0 }, /* upper */
+ { 0x1fd9, 0x1fd1 }, /* upper */
+ { 0x1fda, 0x1f76 }, /* upper */
+ { 0x1fdb, 0x1f77 }, /* upper */
+ { 0x1fdc, 0x1fdc },
+ { 0x1fdd, 0x1fdd },
+ { 0x1fde, 0x1fde },
+ { 0x1fdf, 0x1fdf },
+ { 0x1fe8, 0x1fe0 }, /* lower */
+ { 0x1fe9, 0x1fe1 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fec, 0x1fe5 }, /* lower */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1fe8, 0x1fe0 }, /* upper */
+ { 0x1fe9, 0x1fe1 }, /* upper */
+ { 0x1fea, 0x1f7a }, /* upper */
+ { 0x1feb, 0x1f7b }, /* upper */
+ { 0x1fec, 0x1fe5 }, /* upper */
+ { 0x1fed, 0x1fed },
+ { 0x1fee, 0x1fee },
+ { 0x1fef, 0x1fef },
+ { 0x1ff0, 0x1ff0 },
+ { 0x1ff1, 0x1ff1 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1ff5, 0x1ff5 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1ff8, 0x1f78 }, /* upper */
+ { 0x1ff9, 0x1f79 }, /* upper */
+ { 0x1ffa, 0x1f7c }, /* upper */
+ { 0x1ffb, 0x1f7d }, /* upper */
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0x1ffd, 0x1ffd },
+ { 0x1ffe, 0x1ffe },
+ { 0x1fff, 0x1fff },
+};
+
+gli_case_block_t unigen_case_block_0x21[256] = {
+ { 0x2100, 0x2100 },
+ { 0x2101, 0x2101 },
+ { 0x2102, 0x2102 },
+ { 0x2103, 0x2103 },
+ { 0x2104, 0x2104 },
+ { 0x2105, 0x2105 },
+ { 0x2106, 0x2106 },
+ { 0x2107, 0x2107 },
+ { 0x2108, 0x2108 },
+ { 0x2109, 0x2109 },
+ { 0x210a, 0x210a },
+ { 0x210b, 0x210b },
+ { 0x210c, 0x210c },
+ { 0x210d, 0x210d },
+ { 0x210e, 0x210e },
+ { 0x210f, 0x210f },
+ { 0x2110, 0x2110 },
+ { 0x2111, 0x2111 },
+ { 0x2112, 0x2112 },
+ { 0x2113, 0x2113 },
+ { 0x2114, 0x2114 },
+ { 0x2115, 0x2115 },
+ { 0x2116, 0x2116 },
+ { 0x2117, 0x2117 },
+ { 0x2118, 0x2118 },
+ { 0x2119, 0x2119 },
+ { 0x211a, 0x211a },
+ { 0x211b, 0x211b },
+ { 0x211c, 0x211c },
+ { 0x211d, 0x211d },
+ { 0x211e, 0x211e },
+ { 0x211f, 0x211f },
+ { 0x2120, 0x2120 },
+ { 0x2121, 0x2121 },
+ { 0x2122, 0x2122 },
+ { 0x2123, 0x2123 },
+ { 0x2124, 0x2124 },
+ { 0x2125, 0x2125 },
+ { 0x2126, 0x3c9 }, /* upper */
+ { 0x2127, 0x2127 },
+ { 0x2128, 0x2128 },
+ { 0x2129, 0x2129 },
+ { 0x212a, 0x6b }, /* upper */
+ { 0x212b, 0xe5 }, /* upper */
+ { 0x212c, 0x212c },
+ { 0x212d, 0x212d },
+ { 0x212e, 0x212e },
+ { 0x212f, 0x212f },
+ { 0x2130, 0x2130 },
+ { 0x2131, 0x2131 },
+ { 0x2132, 0x2132 },
+ { 0x2133, 0x2133 },
+ { 0x2134, 0x2134 },
+ { 0x2135, 0x2135 },
+ { 0x2136, 0x2136 },
+ { 0x2137, 0x2137 },
+ { 0x2138, 0x2138 },
+ { 0x2139, 0x2139 },
+ { 0x213a, 0x213a },
+ { 0x213b, 0x213b },
+ { 0x213c, 0x213c },
+ { 0x213d, 0x213d },
+ { 0x213e, 0x213e },
+ { 0x213f, 0x213f },
+ { 0x2140, 0x2140 },
+ { 0x2141, 0x2141 },
+ { 0x2142, 0x2142 },
+ { 0x2143, 0x2143 },
+ { 0x2144, 0x2144 },
+ { 0x2145, 0x2145 },
+ { 0x2146, 0x2146 },
+ { 0x2147, 0x2147 },
+ { 0x2148, 0x2148 },
+ { 0x2149, 0x2149 },
+ { 0x214a, 0x214a },
+ { 0x214b, 0x214b },
+ { 0x214c, 0x214c },
+ { 0x214d, 0x214d },
+ { 0x214e, 0x214e },
+ { 0x214f, 0x214f },
+ { 0x2150, 0x2150 },
+ { 0x2151, 0x2151 },
+ { 0x2152, 0x2152 },
+ { 0x2153, 0x2153 },
+ { 0x2154, 0x2154 },
+ { 0x2155, 0x2155 },
+ { 0x2156, 0x2156 },
+ { 0x2157, 0x2157 },
+ { 0x2158, 0x2158 },
+ { 0x2159, 0x2159 },
+ { 0x215a, 0x215a },
+ { 0x215b, 0x215b },
+ { 0x215c, 0x215c },
+ { 0x215d, 0x215d },
+ { 0x215e, 0x215e },
+ { 0x215f, 0x215f },
+ { 0x2160, 0x2170 }, /* upper */
+ { 0x2161, 0x2171 }, /* upper */
+ { 0x2162, 0x2172 }, /* upper */
+ { 0x2163, 0x2173 }, /* upper */
+ { 0x2164, 0x2174 }, /* upper */
+ { 0x2165, 0x2175 }, /* upper */
+ { 0x2166, 0x2176 }, /* upper */
+ { 0x2167, 0x2177 }, /* upper */
+ { 0x2168, 0x2178 }, /* upper */
+ { 0x2169, 0x2179 }, /* upper */
+ { 0x216a, 0x217a }, /* upper */
+ { 0x216b, 0x217b }, /* upper */
+ { 0x216c, 0x217c }, /* upper */
+ { 0x216d, 0x217d }, /* upper */
+ { 0x216e, 0x217e }, /* upper */
+ { 0x216f, 0x217f }, /* upper */
+ { 0x2160, 0x2170 }, /* lower */
+ { 0x2161, 0x2171 }, /* lower */
+ { 0x2162, 0x2172 }, /* lower */
+ { 0x2163, 0x2173 }, /* lower */
+ { 0x2164, 0x2174 }, /* lower */
+ { 0x2165, 0x2175 }, /* lower */
+ { 0x2166, 0x2176 }, /* lower */
+ { 0x2167, 0x2177 }, /* lower */
+ { 0x2168, 0x2178 }, /* lower */
+ { 0x2169, 0x2179 }, /* lower */
+ { 0x216a, 0x217a }, /* lower */
+ { 0x216b, 0x217b }, /* lower */
+ { 0x216c, 0x217c }, /* lower */
+ { 0x216d, 0x217d }, /* lower */
+ { 0x216e, 0x217e }, /* lower */
+ { 0x216f, 0x217f }, /* lower */
+ { 0x2180, 0x2180 },
+ { 0x2181, 0x2181 },
+ { 0x2182, 0x2182 },
+ { 0x2183, 0x2183 },
+ { 0x2184, 0x2184 },
+ { 0x2185, 0x2185 },
+ { 0x2186, 0x2186 },
+ { 0x2187, 0x2187 },
+ { 0x2188, 0x2188 },
+ { 0x2189, 0x2189 },
+ { 0x218a, 0x218a },
+ { 0x218b, 0x218b },
+ { 0x218c, 0x218c },
+ { 0x218d, 0x218d },
+ { 0x218e, 0x218e },
+ { 0x218f, 0x218f },
+ { 0x2190, 0x2190 },
+ { 0x2191, 0x2191 },
+ { 0x2192, 0x2192 },
+ { 0x2193, 0x2193 },
+ { 0x2194, 0x2194 },
+ { 0x2195, 0x2195 },
+ { 0x2196, 0x2196 },
+ { 0x2197, 0x2197 },
+ { 0x2198, 0x2198 },
+ { 0x2199, 0x2199 },
+ { 0x219a, 0x219a },
+ { 0x219b, 0x219b },
+ { 0x219c, 0x219c },
+ { 0x219d, 0x219d },
+ { 0x219e, 0x219e },
+ { 0x219f, 0x219f },
+ { 0x21a0, 0x21a0 },
+ { 0x21a1, 0x21a1 },
+ { 0x21a2, 0x21a2 },
+ { 0x21a3, 0x21a3 },
+ { 0x21a4, 0x21a4 },
+ { 0x21a5, 0x21a5 },
+ { 0x21a6, 0x21a6 },
+ { 0x21a7, 0x21a7 },
+ { 0x21a8, 0x21a8 },
+ { 0x21a9, 0x21a9 },
+ { 0x21aa, 0x21aa },
+ { 0x21ab, 0x21ab },
+ { 0x21ac, 0x21ac },
+ { 0x21ad, 0x21ad },
+ { 0x21ae, 0x21ae },
+ { 0x21af, 0x21af },
+ { 0x21b0, 0x21b0 },
+ { 0x21b1, 0x21b1 },
+ { 0x21b2, 0x21b2 },
+ { 0x21b3, 0x21b3 },
+ { 0x21b4, 0x21b4 },
+ { 0x21b5, 0x21b5 },
+ { 0x21b6, 0x21b6 },
+ { 0x21b7, 0x21b7 },
+ { 0x21b8, 0x21b8 },
+ { 0x21b9, 0x21b9 },
+ { 0x21ba, 0x21ba },
+ { 0x21bb, 0x21bb },
+ { 0x21bc, 0x21bc },
+ { 0x21bd, 0x21bd },
+ { 0x21be, 0x21be },
+ { 0x21bf, 0x21bf },
+ { 0x21c0, 0x21c0 },
+ { 0x21c1, 0x21c1 },
+ { 0x21c2, 0x21c2 },
+ { 0x21c3, 0x21c3 },
+ { 0x21c4, 0x21c4 },
+ { 0x21c5, 0x21c5 },
+ { 0x21c6, 0x21c6 },
+ { 0x21c7, 0x21c7 },
+ { 0x21c8, 0x21c8 },
+ { 0x21c9, 0x21c9 },
+ { 0x21ca, 0x21ca },
+ { 0x21cb, 0x21cb },
+ { 0x21cc, 0x21cc },
+ { 0x21cd, 0x21cd },
+ { 0x21ce, 0x21ce },
+ { 0x21cf, 0x21cf },
+ { 0x21d0, 0x21d0 },
+ { 0x21d1, 0x21d1 },
+ { 0x21d2, 0x21d2 },
+ { 0x21d3, 0x21d3 },
+ { 0x21d4, 0x21d4 },
+ { 0x21d5, 0x21d5 },
+ { 0x21d6, 0x21d6 },
+ { 0x21d7, 0x21d7 },
+ { 0x21d8, 0x21d8 },
+ { 0x21d9, 0x21d9 },
+ { 0x21da, 0x21da },
+ { 0x21db, 0x21db },
+ { 0x21dc, 0x21dc },
+ { 0x21dd, 0x21dd },
+ { 0x21de, 0x21de },
+ { 0x21df, 0x21df },
+ { 0x21e0, 0x21e0 },
+ { 0x21e1, 0x21e1 },
+ { 0x21e2, 0x21e2 },
+ { 0x21e3, 0x21e3 },
+ { 0x21e4, 0x21e4 },
+ { 0x21e5, 0x21e5 },
+ { 0x21e6, 0x21e6 },
+ { 0x21e7, 0x21e7 },
+ { 0x21e8, 0x21e8 },
+ { 0x21e9, 0x21e9 },
+ { 0x21ea, 0x21ea },
+ { 0x21eb, 0x21eb },
+ { 0x21ec, 0x21ec },
+ { 0x21ed, 0x21ed },
+ { 0x21ee, 0x21ee },
+ { 0x21ef, 0x21ef },
+ { 0x21f0, 0x21f0 },
+ { 0x21f1, 0x21f1 },
+ { 0x21f2, 0x21f2 },
+ { 0x21f3, 0x21f3 },
+ { 0x21f4, 0x21f4 },
+ { 0x21f5, 0x21f5 },
+ { 0x21f6, 0x21f6 },
+ { 0x21f7, 0x21f7 },
+ { 0x21f8, 0x21f8 },
+ { 0x21f9, 0x21f9 },
+ { 0x21fa, 0x21fa },
+ { 0x21fb, 0x21fb },
+ { 0x21fc, 0x21fc },
+ { 0x21fd, 0x21fd },
+ { 0x21fe, 0x21fe },
+ { 0x21ff, 0x21ff },
+};
+
+gli_case_block_t unigen_case_block_0x24[256] = {
+ { 0x2400, 0x2400 },
+ { 0x2401, 0x2401 },
+ { 0x2402, 0x2402 },
+ { 0x2403, 0x2403 },
+ { 0x2404, 0x2404 },
+ { 0x2405, 0x2405 },
+ { 0x2406, 0x2406 },
+ { 0x2407, 0x2407 },
+ { 0x2408, 0x2408 },
+ { 0x2409, 0x2409 },
+ { 0x240a, 0x240a },
+ { 0x240b, 0x240b },
+ { 0x240c, 0x240c },
+ { 0x240d, 0x240d },
+ { 0x240e, 0x240e },
+ { 0x240f, 0x240f },
+ { 0x2410, 0x2410 },
+ { 0x2411, 0x2411 },
+ { 0x2412, 0x2412 },
+ { 0x2413, 0x2413 },
+ { 0x2414, 0x2414 },
+ { 0x2415, 0x2415 },
+ { 0x2416, 0x2416 },
+ { 0x2417, 0x2417 },
+ { 0x2418, 0x2418 },
+ { 0x2419, 0x2419 },
+ { 0x241a, 0x241a },
+ { 0x241b, 0x241b },
+ { 0x241c, 0x241c },
+ { 0x241d, 0x241d },
+ { 0x241e, 0x241e },
+ { 0x241f, 0x241f },
+ { 0x2420, 0x2420 },
+ { 0x2421, 0x2421 },
+ { 0x2422, 0x2422 },
+ { 0x2423, 0x2423 },
+ { 0x2424, 0x2424 },
+ { 0x2425, 0x2425 },
+ { 0x2426, 0x2426 },
+ { 0x2427, 0x2427 },
+ { 0x2428, 0x2428 },
+ { 0x2429, 0x2429 },
+ { 0x242a, 0x242a },
+ { 0x242b, 0x242b },
+ { 0x242c, 0x242c },
+ { 0x242d, 0x242d },
+ { 0x242e, 0x242e },
+ { 0x242f, 0x242f },
+ { 0x2430, 0x2430 },
+ { 0x2431, 0x2431 },
+ { 0x2432, 0x2432 },
+ { 0x2433, 0x2433 },
+ { 0x2434, 0x2434 },
+ { 0x2435, 0x2435 },
+ { 0x2436, 0x2436 },
+ { 0x2437, 0x2437 },
+ { 0x2438, 0x2438 },
+ { 0x2439, 0x2439 },
+ { 0x243a, 0x243a },
+ { 0x243b, 0x243b },
+ { 0x243c, 0x243c },
+ { 0x243d, 0x243d },
+ { 0x243e, 0x243e },
+ { 0x243f, 0x243f },
+ { 0x2440, 0x2440 },
+ { 0x2441, 0x2441 },
+ { 0x2442, 0x2442 },
+ { 0x2443, 0x2443 },
+ { 0x2444, 0x2444 },
+ { 0x2445, 0x2445 },
+ { 0x2446, 0x2446 },
+ { 0x2447, 0x2447 },
+ { 0x2448, 0x2448 },
+ { 0x2449, 0x2449 },
+ { 0x244a, 0x244a },
+ { 0x244b, 0x244b },
+ { 0x244c, 0x244c },
+ { 0x244d, 0x244d },
+ { 0x244e, 0x244e },
+ { 0x244f, 0x244f },
+ { 0x2450, 0x2450 },
+ { 0x2451, 0x2451 },
+ { 0x2452, 0x2452 },
+ { 0x2453, 0x2453 },
+ { 0x2454, 0x2454 },
+ { 0x2455, 0x2455 },
+ { 0x2456, 0x2456 },
+ { 0x2457, 0x2457 },
+ { 0x2458, 0x2458 },
+ { 0x2459, 0x2459 },
+ { 0x245a, 0x245a },
+ { 0x245b, 0x245b },
+ { 0x245c, 0x245c },
+ { 0x245d, 0x245d },
+ { 0x245e, 0x245e },
+ { 0x245f, 0x245f },
+ { 0x2460, 0x2460 },
+ { 0x2461, 0x2461 },
+ { 0x2462, 0x2462 },
+ { 0x2463, 0x2463 },
+ { 0x2464, 0x2464 },
+ { 0x2465, 0x2465 },
+ { 0x2466, 0x2466 },
+ { 0x2467, 0x2467 },
+ { 0x2468, 0x2468 },
+ { 0x2469, 0x2469 },
+ { 0x246a, 0x246a },
+ { 0x246b, 0x246b },
+ { 0x246c, 0x246c },
+ { 0x246d, 0x246d },
+ { 0x246e, 0x246e },
+ { 0x246f, 0x246f },
+ { 0x2470, 0x2470 },
+ { 0x2471, 0x2471 },
+ { 0x2472, 0x2472 },
+ { 0x2473, 0x2473 },
+ { 0x2474, 0x2474 },
+ { 0x2475, 0x2475 },
+ { 0x2476, 0x2476 },
+ { 0x2477, 0x2477 },
+ { 0x2478, 0x2478 },
+ { 0x2479, 0x2479 },
+ { 0x247a, 0x247a },
+ { 0x247b, 0x247b },
+ { 0x247c, 0x247c },
+ { 0x247d, 0x247d },
+ { 0x247e, 0x247e },
+ { 0x247f, 0x247f },
+ { 0x2480, 0x2480 },
+ { 0x2481, 0x2481 },
+ { 0x2482, 0x2482 },
+ { 0x2483, 0x2483 },
+ { 0x2484, 0x2484 },
+ { 0x2485, 0x2485 },
+ { 0x2486, 0x2486 },
+ { 0x2487, 0x2487 },
+ { 0x2488, 0x2488 },
+ { 0x2489, 0x2489 },
+ { 0x248a, 0x248a },
+ { 0x248b, 0x248b },
+ { 0x248c, 0x248c },
+ { 0x248d, 0x248d },
+ { 0x248e, 0x248e },
+ { 0x248f, 0x248f },
+ { 0x2490, 0x2490 },
+ { 0x2491, 0x2491 },
+ { 0x2492, 0x2492 },
+ { 0x2493, 0x2493 },
+ { 0x2494, 0x2494 },
+ { 0x2495, 0x2495 },
+ { 0x2496, 0x2496 },
+ { 0x2497, 0x2497 },
+ { 0x2498, 0x2498 },
+ { 0x2499, 0x2499 },
+ { 0x249a, 0x249a },
+ { 0x249b, 0x249b },
+ { 0x249c, 0x249c },
+ { 0x249d, 0x249d },
+ { 0x249e, 0x249e },
+ { 0x249f, 0x249f },
+ { 0x24a0, 0x24a0 },
+ { 0x24a1, 0x24a1 },
+ { 0x24a2, 0x24a2 },
+ { 0x24a3, 0x24a3 },
+ { 0x24a4, 0x24a4 },
+ { 0x24a5, 0x24a5 },
+ { 0x24a6, 0x24a6 },
+ { 0x24a7, 0x24a7 },
+ { 0x24a8, 0x24a8 },
+ { 0x24a9, 0x24a9 },
+ { 0x24aa, 0x24aa },
+ { 0x24ab, 0x24ab },
+ { 0x24ac, 0x24ac },
+ { 0x24ad, 0x24ad },
+ { 0x24ae, 0x24ae },
+ { 0x24af, 0x24af },
+ { 0x24b0, 0x24b0 },
+ { 0x24b1, 0x24b1 },
+ { 0x24b2, 0x24b2 },
+ { 0x24b3, 0x24b3 },
+ { 0x24b4, 0x24b4 },
+ { 0x24b5, 0x24b5 },
+ { 0x24b6, 0x24d0 }, /* upper */
+ { 0x24b7, 0x24d1 }, /* upper */
+ { 0x24b8, 0x24d2 }, /* upper */
+ { 0x24b9, 0x24d3 }, /* upper */
+ { 0x24ba, 0x24d4 }, /* upper */
+ { 0x24bb, 0x24d5 }, /* upper */
+ { 0x24bc, 0x24d6 }, /* upper */
+ { 0x24bd, 0x24d7 }, /* upper */
+ { 0x24be, 0x24d8 }, /* upper */
+ { 0x24bf, 0x24d9 }, /* upper */
+ { 0x24c0, 0x24da }, /* upper */
+ { 0x24c1, 0x24db }, /* upper */
+ { 0x24c2, 0x24dc }, /* upper */
+ { 0x24c3, 0x24dd }, /* upper */
+ { 0x24c4, 0x24de }, /* upper */
+ { 0x24c5, 0x24df }, /* upper */
+ { 0x24c6, 0x24e0 }, /* upper */
+ { 0x24c7, 0x24e1 }, /* upper */
+ { 0x24c8, 0x24e2 }, /* upper */
+ { 0x24c9, 0x24e3 }, /* upper */
+ { 0x24ca, 0x24e4 }, /* upper */
+ { 0x24cb, 0x24e5 }, /* upper */
+ { 0x24cc, 0x24e6 }, /* upper */
+ { 0x24cd, 0x24e7 }, /* upper */
+ { 0x24ce, 0x24e8 }, /* upper */
+ { 0x24cf, 0x24e9 }, /* upper */
+ { 0x24b6, 0x24d0 }, /* lower */
+ { 0x24b7, 0x24d1 }, /* lower */
+ { 0x24b8, 0x24d2 }, /* lower */
+ { 0x24b9, 0x24d3 }, /* lower */
+ { 0x24ba, 0x24d4 }, /* lower */
+ { 0x24bb, 0x24d5 }, /* lower */
+ { 0x24bc, 0x24d6 }, /* lower */
+ { 0x24bd, 0x24d7 }, /* lower */
+ { 0x24be, 0x24d8 }, /* lower */
+ { 0x24bf, 0x24d9 }, /* lower */
+ { 0x24c0, 0x24da }, /* lower */
+ { 0x24c1, 0x24db }, /* lower */
+ { 0x24c2, 0x24dc }, /* lower */
+ { 0x24c3, 0x24dd }, /* lower */
+ { 0x24c4, 0x24de }, /* lower */
+ { 0x24c5, 0x24df }, /* lower */
+ { 0x24c6, 0x24e0 }, /* lower */
+ { 0x24c7, 0x24e1 }, /* lower */
+ { 0x24c8, 0x24e2 }, /* lower */
+ { 0x24c9, 0x24e3 }, /* lower */
+ { 0x24ca, 0x24e4 }, /* lower */
+ { 0x24cb, 0x24e5 }, /* lower */
+ { 0x24cc, 0x24e6 }, /* lower */
+ { 0x24cd, 0x24e7 }, /* lower */
+ { 0x24ce, 0x24e8 }, /* lower */
+ { 0x24cf, 0x24e9 }, /* lower */
+ { 0x24ea, 0x24ea },
+ { 0x24eb, 0x24eb },
+ { 0x24ec, 0x24ec },
+ { 0x24ed, 0x24ed },
+ { 0x24ee, 0x24ee },
+ { 0x24ef, 0x24ef },
+ { 0x24f0, 0x24f0 },
+ { 0x24f1, 0x24f1 },
+ { 0x24f2, 0x24f2 },
+ { 0x24f3, 0x24f3 },
+ { 0x24f4, 0x24f4 },
+ { 0x24f5, 0x24f5 },
+ { 0x24f6, 0x24f6 },
+ { 0x24f7, 0x24f7 },
+ { 0x24f8, 0x24f8 },
+ { 0x24f9, 0x24f9 },
+ { 0x24fa, 0x24fa },
+ { 0x24fb, 0x24fb },
+ { 0x24fc, 0x24fc },
+ { 0x24fd, 0x24fd },
+ { 0x24fe, 0x24fe },
+ { 0x24ff, 0x24ff },
+};
+
+gli_case_block_t unigen_case_block_0xfb[256] = {
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xfb07, 0xfb07 },
+ { 0xfb08, 0xfb08 },
+ { 0xfb09, 0xfb09 },
+ { 0xfb0a, 0xfb0a },
+ { 0xfb0b, 0xfb0b },
+ { 0xfb0c, 0xfb0c },
+ { 0xfb0d, 0xfb0d },
+ { 0xfb0e, 0xfb0e },
+ { 0xfb0f, 0xfb0f },
+ { 0xfb10, 0xfb10 },
+ { 0xfb11, 0xfb11 },
+ { 0xfb12, 0xfb12 },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0xfb18, 0xfb18 },
+ { 0xfb19, 0xfb19 },
+ { 0xfb1a, 0xfb1a },
+ { 0xfb1b, 0xfb1b },
+ { 0xfb1c, 0xfb1c },
+ { 0xfb1d, 0xfb1d },
+ { 0xfb1e, 0xfb1e },
+ { 0xfb1f, 0xfb1f },
+ { 0xfb20, 0xfb20 },
+ { 0xfb21, 0xfb21 },
+ { 0xfb22, 0xfb22 },
+ { 0xfb23, 0xfb23 },
+ { 0xfb24, 0xfb24 },
+ { 0xfb25, 0xfb25 },
+ { 0xfb26, 0xfb26 },
+ { 0xfb27, 0xfb27 },
+ { 0xfb28, 0xfb28 },
+ { 0xfb29, 0xfb29 },
+ { 0xfb2a, 0xfb2a },
+ { 0xfb2b, 0xfb2b },
+ { 0xfb2c, 0xfb2c },
+ { 0xfb2d, 0xfb2d },
+ { 0xfb2e, 0xfb2e },
+ { 0xfb2f, 0xfb2f },
+ { 0xfb30, 0xfb30 },
+ { 0xfb31, 0xfb31 },
+ { 0xfb32, 0xfb32 },
+ { 0xfb33, 0xfb33 },
+ { 0xfb34, 0xfb34 },
+ { 0xfb35, 0xfb35 },
+ { 0xfb36, 0xfb36 },
+ { 0xfb37, 0xfb37 },
+ { 0xfb38, 0xfb38 },
+ { 0xfb39, 0xfb39 },
+ { 0xfb3a, 0xfb3a },
+ { 0xfb3b, 0xfb3b },
+ { 0xfb3c, 0xfb3c },
+ { 0xfb3d, 0xfb3d },
+ { 0xfb3e, 0xfb3e },
+ { 0xfb3f, 0xfb3f },
+ { 0xfb40, 0xfb40 },
+ { 0xfb41, 0xfb41 },
+ { 0xfb42, 0xfb42 },
+ { 0xfb43, 0xfb43 },
+ { 0xfb44, 0xfb44 },
+ { 0xfb45, 0xfb45 },
+ { 0xfb46, 0xfb46 },
+ { 0xfb47, 0xfb47 },
+ { 0xfb48, 0xfb48 },
+ { 0xfb49, 0xfb49 },
+ { 0xfb4a, 0xfb4a },
+ { 0xfb4b, 0xfb4b },
+ { 0xfb4c, 0xfb4c },
+ { 0xfb4d, 0xfb4d },
+ { 0xfb4e, 0xfb4e },
+ { 0xfb4f, 0xfb4f },
+ { 0xfb50, 0xfb50 },
+ { 0xfb51, 0xfb51 },
+ { 0xfb52, 0xfb52 },
+ { 0xfb53, 0xfb53 },
+ { 0xfb54, 0xfb54 },
+ { 0xfb55, 0xfb55 },
+ { 0xfb56, 0xfb56 },
+ { 0xfb57, 0xfb57 },
+ { 0xfb58, 0xfb58 },
+ { 0xfb59, 0xfb59 },
+ { 0xfb5a, 0xfb5a },
+ { 0xfb5b, 0xfb5b },
+ { 0xfb5c, 0xfb5c },
+ { 0xfb5d, 0xfb5d },
+ { 0xfb5e, 0xfb5e },
+ { 0xfb5f, 0xfb5f },
+ { 0xfb60, 0xfb60 },
+ { 0xfb61, 0xfb61 },
+ { 0xfb62, 0xfb62 },
+ { 0xfb63, 0xfb63 },
+ { 0xfb64, 0xfb64 },
+ { 0xfb65, 0xfb65 },
+ { 0xfb66, 0xfb66 },
+ { 0xfb67, 0xfb67 },
+ { 0xfb68, 0xfb68 },
+ { 0xfb69, 0xfb69 },
+ { 0xfb6a, 0xfb6a },
+ { 0xfb6b, 0xfb6b },
+ { 0xfb6c, 0xfb6c },
+ { 0xfb6d, 0xfb6d },
+ { 0xfb6e, 0xfb6e },
+ { 0xfb6f, 0xfb6f },
+ { 0xfb70, 0xfb70 },
+ { 0xfb71, 0xfb71 },
+ { 0xfb72, 0xfb72 },
+ { 0xfb73, 0xfb73 },
+ { 0xfb74, 0xfb74 },
+ { 0xfb75, 0xfb75 },
+ { 0xfb76, 0xfb76 },
+ { 0xfb77, 0xfb77 },
+ { 0xfb78, 0xfb78 },
+ { 0xfb79, 0xfb79 },
+ { 0xfb7a, 0xfb7a },
+ { 0xfb7b, 0xfb7b },
+ { 0xfb7c, 0xfb7c },
+ { 0xfb7d, 0xfb7d },
+ { 0xfb7e, 0xfb7e },
+ { 0xfb7f, 0xfb7f },
+ { 0xfb80, 0xfb80 },
+ { 0xfb81, 0xfb81 },
+ { 0xfb82, 0xfb82 },
+ { 0xfb83, 0xfb83 },
+ { 0xfb84, 0xfb84 },
+ { 0xfb85, 0xfb85 },
+ { 0xfb86, 0xfb86 },
+ { 0xfb87, 0xfb87 },
+ { 0xfb88, 0xfb88 },
+ { 0xfb89, 0xfb89 },
+ { 0xfb8a, 0xfb8a },
+ { 0xfb8b, 0xfb8b },
+ { 0xfb8c, 0xfb8c },
+ { 0xfb8d, 0xfb8d },
+ { 0xfb8e, 0xfb8e },
+ { 0xfb8f, 0xfb8f },
+ { 0xfb90, 0xfb90 },
+ { 0xfb91, 0xfb91 },
+ { 0xfb92, 0xfb92 },
+ { 0xfb93, 0xfb93 },
+ { 0xfb94, 0xfb94 },
+ { 0xfb95, 0xfb95 },
+ { 0xfb96, 0xfb96 },
+ { 0xfb97, 0xfb97 },
+ { 0xfb98, 0xfb98 },
+ { 0xfb99, 0xfb99 },
+ { 0xfb9a, 0xfb9a },
+ { 0xfb9b, 0xfb9b },
+ { 0xfb9c, 0xfb9c },
+ { 0xfb9d, 0xfb9d },
+ { 0xfb9e, 0xfb9e },
+ { 0xfb9f, 0xfb9f },
+ { 0xfba0, 0xfba0 },
+ { 0xfba1, 0xfba1 },
+ { 0xfba2, 0xfba2 },
+ { 0xfba3, 0xfba3 },
+ { 0xfba4, 0xfba4 },
+ { 0xfba5, 0xfba5 },
+ { 0xfba6, 0xfba6 },
+ { 0xfba7, 0xfba7 },
+ { 0xfba8, 0xfba8 },
+ { 0xfba9, 0xfba9 },
+ { 0xfbaa, 0xfbaa },
+ { 0xfbab, 0xfbab },
+ { 0xfbac, 0xfbac },
+ { 0xfbad, 0xfbad },
+ { 0xfbae, 0xfbae },
+ { 0xfbaf, 0xfbaf },
+ { 0xfbb0, 0xfbb0 },
+ { 0xfbb1, 0xfbb1 },
+ { 0xfbb2, 0xfbb2 },
+ { 0xfbb3, 0xfbb3 },
+ { 0xfbb4, 0xfbb4 },
+ { 0xfbb5, 0xfbb5 },
+ { 0xfbb6, 0xfbb6 },
+ { 0xfbb7, 0xfbb7 },
+ { 0xfbb8, 0xfbb8 },
+ { 0xfbb9, 0xfbb9 },
+ { 0xfbba, 0xfbba },
+ { 0xfbbb, 0xfbbb },
+ { 0xfbbc, 0xfbbc },
+ { 0xfbbd, 0xfbbd },
+ { 0xfbbe, 0xfbbe },
+ { 0xfbbf, 0xfbbf },
+ { 0xfbc0, 0xfbc0 },
+ { 0xfbc1, 0xfbc1 },
+ { 0xfbc2, 0xfbc2 },
+ { 0xfbc3, 0xfbc3 },
+ { 0xfbc4, 0xfbc4 },
+ { 0xfbc5, 0xfbc5 },
+ { 0xfbc6, 0xfbc6 },
+ { 0xfbc7, 0xfbc7 },
+ { 0xfbc8, 0xfbc8 },
+ { 0xfbc9, 0xfbc9 },
+ { 0xfbca, 0xfbca },
+ { 0xfbcb, 0xfbcb },
+ { 0xfbcc, 0xfbcc },
+ { 0xfbcd, 0xfbcd },
+ { 0xfbce, 0xfbce },
+ { 0xfbcf, 0xfbcf },
+ { 0xfbd0, 0xfbd0 },
+ { 0xfbd1, 0xfbd1 },
+ { 0xfbd2, 0xfbd2 },
+ { 0xfbd3, 0xfbd3 },
+ { 0xfbd4, 0xfbd4 },
+ { 0xfbd5, 0xfbd5 },
+ { 0xfbd6, 0xfbd6 },
+ { 0xfbd7, 0xfbd7 },
+ { 0xfbd8, 0xfbd8 },
+ { 0xfbd9, 0xfbd9 },
+ { 0xfbda, 0xfbda },
+ { 0xfbdb, 0xfbdb },
+ { 0xfbdc, 0xfbdc },
+ { 0xfbdd, 0xfbdd },
+ { 0xfbde, 0xfbde },
+ { 0xfbdf, 0xfbdf },
+ { 0xfbe0, 0xfbe0 },
+ { 0xfbe1, 0xfbe1 },
+ { 0xfbe2, 0xfbe2 },
+ { 0xfbe3, 0xfbe3 },
+ { 0xfbe4, 0xfbe4 },
+ { 0xfbe5, 0xfbe5 },
+ { 0xfbe6, 0xfbe6 },
+ { 0xfbe7, 0xfbe7 },
+ { 0xfbe8, 0xfbe8 },
+ { 0xfbe9, 0xfbe9 },
+ { 0xfbea, 0xfbea },
+ { 0xfbeb, 0xfbeb },
+ { 0xfbec, 0xfbec },
+ { 0xfbed, 0xfbed },
+ { 0xfbee, 0xfbee },
+ { 0xfbef, 0xfbef },
+ { 0xfbf0, 0xfbf0 },
+ { 0xfbf1, 0xfbf1 },
+ { 0xfbf2, 0xfbf2 },
+ { 0xfbf3, 0xfbf3 },
+ { 0xfbf4, 0xfbf4 },
+ { 0xfbf5, 0xfbf5 },
+ { 0xfbf6, 0xfbf6 },
+ { 0xfbf7, 0xfbf7 },
+ { 0xfbf8, 0xfbf8 },
+ { 0xfbf9, 0xfbf9 },
+ { 0xfbfa, 0xfbfa },
+ { 0xfbfb, 0xfbfb },
+ { 0xfbfc, 0xfbfc },
+ { 0xfbfd, 0xfbfd },
+ { 0xfbfe, 0xfbfe },
+ { 0xfbff, 0xfbff },
+};
+
+gli_case_block_t unigen_case_block_0xff[256] = {
+ { 0xff00, 0xff00 },
+ { 0xff01, 0xff01 },
+ { 0xff02, 0xff02 },
+ { 0xff03, 0xff03 },
+ { 0xff04, 0xff04 },
+ { 0xff05, 0xff05 },
+ { 0xff06, 0xff06 },
+ { 0xff07, 0xff07 },
+ { 0xff08, 0xff08 },
+ { 0xff09, 0xff09 },
+ { 0xff0a, 0xff0a },
+ { 0xff0b, 0xff0b },
+ { 0xff0c, 0xff0c },
+ { 0xff0d, 0xff0d },
+ { 0xff0e, 0xff0e },
+ { 0xff0f, 0xff0f },
+ { 0xff10, 0xff10 },
+ { 0xff11, 0xff11 },
+ { 0xff12, 0xff12 },
+ { 0xff13, 0xff13 },
+ { 0xff14, 0xff14 },
+ { 0xff15, 0xff15 },
+ { 0xff16, 0xff16 },
+ { 0xff17, 0xff17 },
+ { 0xff18, 0xff18 },
+ { 0xff19, 0xff19 },
+ { 0xff1a, 0xff1a },
+ { 0xff1b, 0xff1b },
+ { 0xff1c, 0xff1c },
+ { 0xff1d, 0xff1d },
+ { 0xff1e, 0xff1e },
+ { 0xff1f, 0xff1f },
+ { 0xff20, 0xff20 },
+ { 0xff21, 0xff41 }, /* upper */
+ { 0xff22, 0xff42 }, /* upper */
+ { 0xff23, 0xff43 }, /* upper */
+ { 0xff24, 0xff44 }, /* upper */
+ { 0xff25, 0xff45 }, /* upper */
+ { 0xff26, 0xff46 }, /* upper */
+ { 0xff27, 0xff47 }, /* upper */
+ { 0xff28, 0xff48 }, /* upper */
+ { 0xff29, 0xff49 }, /* upper */
+ { 0xff2a, 0xff4a }, /* upper */
+ { 0xff2b, 0xff4b }, /* upper */
+ { 0xff2c, 0xff4c }, /* upper */
+ { 0xff2d, 0xff4d }, /* upper */
+ { 0xff2e, 0xff4e }, /* upper */
+ { 0xff2f, 0xff4f }, /* upper */
+ { 0xff30, 0xff50 }, /* upper */
+ { 0xff31, 0xff51 }, /* upper */
+ { 0xff32, 0xff52 }, /* upper */
+ { 0xff33, 0xff53 }, /* upper */
+ { 0xff34, 0xff54 }, /* upper */
+ { 0xff35, 0xff55 }, /* upper */
+ { 0xff36, 0xff56 }, /* upper */
+ { 0xff37, 0xff57 }, /* upper */
+ { 0xff38, 0xff58 }, /* upper */
+ { 0xff39, 0xff59 }, /* upper */
+ { 0xff3a, 0xff5a }, /* upper */
+ { 0xff3b, 0xff3b },
+ { 0xff3c, 0xff3c },
+ { 0xff3d, 0xff3d },
+ { 0xff3e, 0xff3e },
+ { 0xff3f, 0xff3f },
+ { 0xff40, 0xff40 },
+ { 0xff21, 0xff41 }, /* lower */
+ { 0xff22, 0xff42 }, /* lower */
+ { 0xff23, 0xff43 }, /* lower */
+ { 0xff24, 0xff44 }, /* lower */
+ { 0xff25, 0xff45 }, /* lower */
+ { 0xff26, 0xff46 }, /* lower */
+ { 0xff27, 0xff47 }, /* lower */
+ { 0xff28, 0xff48 }, /* lower */
+ { 0xff29, 0xff49 }, /* lower */
+ { 0xff2a, 0xff4a }, /* lower */
+ { 0xff2b, 0xff4b }, /* lower */
+ { 0xff2c, 0xff4c }, /* lower */
+ { 0xff2d, 0xff4d }, /* lower */
+ { 0xff2e, 0xff4e }, /* lower */
+ { 0xff2f, 0xff4f }, /* lower */
+ { 0xff30, 0xff50 }, /* lower */
+ { 0xff31, 0xff51 }, /* lower */
+ { 0xff32, 0xff52 }, /* lower */
+ { 0xff33, 0xff53 }, /* lower */
+ { 0xff34, 0xff54 }, /* lower */
+ { 0xff35, 0xff55 }, /* lower */
+ { 0xff36, 0xff56 }, /* lower */
+ { 0xff37, 0xff57 }, /* lower */
+ { 0xff38, 0xff58 }, /* lower */
+ { 0xff39, 0xff59 }, /* lower */
+ { 0xff3a, 0xff5a }, /* lower */
+ { 0xff5b, 0xff5b },
+ { 0xff5c, 0xff5c },
+ { 0xff5d, 0xff5d },
+ { 0xff5e, 0xff5e },
+ { 0xff5f, 0xff5f },
+ { 0xff60, 0xff60 },
+ { 0xff61, 0xff61 },
+ { 0xff62, 0xff62 },
+ { 0xff63, 0xff63 },
+ { 0xff64, 0xff64 },
+ { 0xff65, 0xff65 },
+ { 0xff66, 0xff66 },
+ { 0xff67, 0xff67 },
+ { 0xff68, 0xff68 },
+ { 0xff69, 0xff69 },
+ { 0xff6a, 0xff6a },
+ { 0xff6b, 0xff6b },
+ { 0xff6c, 0xff6c },
+ { 0xff6d, 0xff6d },
+ { 0xff6e, 0xff6e },
+ { 0xff6f, 0xff6f },
+ { 0xff70, 0xff70 },
+ { 0xff71, 0xff71 },
+ { 0xff72, 0xff72 },
+ { 0xff73, 0xff73 },
+ { 0xff74, 0xff74 },
+ { 0xff75, 0xff75 },
+ { 0xff76, 0xff76 },
+ { 0xff77, 0xff77 },
+ { 0xff78, 0xff78 },
+ { 0xff79, 0xff79 },
+ { 0xff7a, 0xff7a },
+ { 0xff7b, 0xff7b },
+ { 0xff7c, 0xff7c },
+ { 0xff7d, 0xff7d },
+ { 0xff7e, 0xff7e },
+ { 0xff7f, 0xff7f },
+ { 0xff80, 0xff80 },
+ { 0xff81, 0xff81 },
+ { 0xff82, 0xff82 },
+ { 0xff83, 0xff83 },
+ { 0xff84, 0xff84 },
+ { 0xff85, 0xff85 },
+ { 0xff86, 0xff86 },
+ { 0xff87, 0xff87 },
+ { 0xff88, 0xff88 },
+ { 0xff89, 0xff89 },
+ { 0xff8a, 0xff8a },
+ { 0xff8b, 0xff8b },
+ { 0xff8c, 0xff8c },
+ { 0xff8d, 0xff8d },
+ { 0xff8e, 0xff8e },
+ { 0xff8f, 0xff8f },
+ { 0xff90, 0xff90 },
+ { 0xff91, 0xff91 },
+ { 0xff92, 0xff92 },
+ { 0xff93, 0xff93 },
+ { 0xff94, 0xff94 },
+ { 0xff95, 0xff95 },
+ { 0xff96, 0xff96 },
+ { 0xff97, 0xff97 },
+ { 0xff98, 0xff98 },
+ { 0xff99, 0xff99 },
+ { 0xff9a, 0xff9a },
+ { 0xff9b, 0xff9b },
+ { 0xff9c, 0xff9c },
+ { 0xff9d, 0xff9d },
+ { 0xff9e, 0xff9e },
+ { 0xff9f, 0xff9f },
+ { 0xffa0, 0xffa0 },
+ { 0xffa1, 0xffa1 },
+ { 0xffa2, 0xffa2 },
+ { 0xffa3, 0xffa3 },
+ { 0xffa4, 0xffa4 },
+ { 0xffa5, 0xffa5 },
+ { 0xffa6, 0xffa6 },
+ { 0xffa7, 0xffa7 },
+ { 0xffa8, 0xffa8 },
+ { 0xffa9, 0xffa9 },
+ { 0xffaa, 0xffaa },
+ { 0xffab, 0xffab },
+ { 0xffac, 0xffac },
+ { 0xffad, 0xffad },
+ { 0xffae, 0xffae },
+ { 0xffaf, 0xffaf },
+ { 0xffb0, 0xffb0 },
+ { 0xffb1, 0xffb1 },
+ { 0xffb2, 0xffb2 },
+ { 0xffb3, 0xffb3 },
+ { 0xffb4, 0xffb4 },
+ { 0xffb5, 0xffb5 },
+ { 0xffb6, 0xffb6 },
+ { 0xffb7, 0xffb7 },
+ { 0xffb8, 0xffb8 },
+ { 0xffb9, 0xffb9 },
+ { 0xffba, 0xffba },
+ { 0xffbb, 0xffbb },
+ { 0xffbc, 0xffbc },
+ { 0xffbd, 0xffbd },
+ { 0xffbe, 0xffbe },
+ { 0xffbf, 0xffbf },
+ { 0xffc0, 0xffc0 },
+ { 0xffc1, 0xffc1 },
+ { 0xffc2, 0xffc2 },
+ { 0xffc3, 0xffc3 },
+ { 0xffc4, 0xffc4 },
+ { 0xffc5, 0xffc5 },
+ { 0xffc6, 0xffc6 },
+ { 0xffc7, 0xffc7 },
+ { 0xffc8, 0xffc8 },
+ { 0xffc9, 0xffc9 },
+ { 0xffca, 0xffca },
+ { 0xffcb, 0xffcb },
+ { 0xffcc, 0xffcc },
+ { 0xffcd, 0xffcd },
+ { 0xffce, 0xffce },
+ { 0xffcf, 0xffcf },
+ { 0xffd0, 0xffd0 },
+ { 0xffd1, 0xffd1 },
+ { 0xffd2, 0xffd2 },
+ { 0xffd3, 0xffd3 },
+ { 0xffd4, 0xffd4 },
+ { 0xffd5, 0xffd5 },
+ { 0xffd6, 0xffd6 },
+ { 0xffd7, 0xffd7 },
+ { 0xffd8, 0xffd8 },
+ { 0xffd9, 0xffd9 },
+ { 0xffda, 0xffda },
+ { 0xffdb, 0xffdb },
+ { 0xffdc, 0xffdc },
+ { 0xffdd, 0xffdd },
+ { 0xffde, 0xffde },
+ { 0xffdf, 0xffdf },
+ { 0xffe0, 0xffe0 },
+ { 0xffe1, 0xffe1 },
+ { 0xffe2, 0xffe2 },
+ { 0xffe3, 0xffe3 },
+ { 0xffe4, 0xffe4 },
+ { 0xffe5, 0xffe5 },
+ { 0xffe6, 0xffe6 },
+ { 0xffe7, 0xffe7 },
+ { 0xffe8, 0xffe8 },
+ { 0xffe9, 0xffe9 },
+ { 0xffea, 0xffea },
+ { 0xffeb, 0xffeb },
+ { 0xffec, 0xffec },
+ { 0xffed, 0xffed },
+ { 0xffee, 0xffee },
+ { 0xffef, 0xffef },
+ { 0xfff0, 0xfff0 },
+ { 0xfff1, 0xfff1 },
+ { 0xfff2, 0xfff2 },
+ { 0xfff3, 0xfff3 },
+ { 0xfff4, 0xfff4 },
+ { 0xfff5, 0xfff5 },
+ { 0xfff6, 0xfff6 },
+ { 0xfff7, 0xfff7 },
+ { 0xfff8, 0xfff8 },
+ { 0xfff9, 0xfff9 },
+ { 0xfffa, 0xfffa },
+ { 0xfffb, 0xfffb },
+ { 0xfffc, 0xfffc },
+ { 0xfffd, 0xfffd },
+ { 0xfffe, 0xfffe },
+ { 0xffff, 0xffff },
+};
+
+gli_case_block_t unigen_case_block_0x104[256] = {
+ { 0x10400, 0x10428 }, /* upper */
+ { 0x10401, 0x10429 }, /* upper */
+ { 0x10402, 0x1042a }, /* upper */
+ { 0x10403, 0x1042b }, /* upper */
+ { 0x10404, 0x1042c }, /* upper */
+ { 0x10405, 0x1042d }, /* upper */
+ { 0x10406, 0x1042e }, /* upper */
+ { 0x10407, 0x1042f }, /* upper */
+ { 0x10408, 0x10430 }, /* upper */
+ { 0x10409, 0x10431 }, /* upper */
+ { 0x1040a, 0x10432 }, /* upper */
+ { 0x1040b, 0x10433 }, /* upper */
+ { 0x1040c, 0x10434 }, /* upper */
+ { 0x1040d, 0x10435 }, /* upper */
+ { 0x1040e, 0x10436 }, /* upper */
+ { 0x1040f, 0x10437 }, /* upper */
+ { 0x10410, 0x10438 }, /* upper */
+ { 0x10411, 0x10439 }, /* upper */
+ { 0x10412, 0x1043a }, /* upper */
+ { 0x10413, 0x1043b }, /* upper */
+ { 0x10414, 0x1043c }, /* upper */
+ { 0x10415, 0x1043d }, /* upper */
+ { 0x10416, 0x1043e }, /* upper */
+ { 0x10417, 0x1043f }, /* upper */
+ { 0x10418, 0x10440 }, /* upper */
+ { 0x10419, 0x10441 }, /* upper */
+ { 0x1041a, 0x10442 }, /* upper */
+ { 0x1041b, 0x10443 }, /* upper */
+ { 0x1041c, 0x10444 }, /* upper */
+ { 0x1041d, 0x10445 }, /* upper */
+ { 0x1041e, 0x10446 }, /* upper */
+ { 0x1041f, 0x10447 }, /* upper */
+ { 0x10420, 0x10448 }, /* upper */
+ { 0x10421, 0x10449 }, /* upper */
+ { 0x10422, 0x1044a }, /* upper */
+ { 0x10423, 0x1044b }, /* upper */
+ { 0x10424, 0x1044c }, /* upper */
+ { 0x10425, 0x1044d }, /* upper */
+ { 0x10426, 0x1044e }, /* upper */
+ { 0x10427, 0x1044f }, /* upper */
+ { 0x10400, 0x10428 }, /* lower */
+ { 0x10401, 0x10429 }, /* lower */
+ { 0x10402, 0x1042a }, /* lower */
+ { 0x10403, 0x1042b }, /* lower */
+ { 0x10404, 0x1042c }, /* lower */
+ { 0x10405, 0x1042d }, /* lower */
+ { 0x10406, 0x1042e }, /* lower */
+ { 0x10407, 0x1042f }, /* lower */
+ { 0x10408, 0x10430 }, /* lower */
+ { 0x10409, 0x10431 }, /* lower */
+ { 0x1040a, 0x10432 }, /* lower */
+ { 0x1040b, 0x10433 }, /* lower */
+ { 0x1040c, 0x10434 }, /* lower */
+ { 0x1040d, 0x10435 }, /* lower */
+ { 0x1040e, 0x10436 }, /* lower */
+ { 0x1040f, 0x10437 }, /* lower */
+ { 0x10410, 0x10438 }, /* lower */
+ { 0x10411, 0x10439 }, /* lower */
+ { 0x10412, 0x1043a }, /* lower */
+ { 0x10413, 0x1043b }, /* lower */
+ { 0x10414, 0x1043c }, /* lower */
+ { 0x10415, 0x1043d }, /* lower */
+ { 0x10416, 0x1043e }, /* lower */
+ { 0x10417, 0x1043f }, /* lower */
+ { 0x10418, 0x10440 }, /* lower */
+ { 0x10419, 0x10441 }, /* lower */
+ { 0x1041a, 0x10442 }, /* lower */
+ { 0x1041b, 0x10443 }, /* lower */
+ { 0x1041c, 0x10444 }, /* lower */
+ { 0x1041d, 0x10445 }, /* lower */
+ { 0x1041e, 0x10446 }, /* lower */
+ { 0x1041f, 0x10447 }, /* lower */
+ { 0x10420, 0x10448 }, /* lower */
+ { 0x10421, 0x10449 }, /* lower */
+ { 0x10422, 0x1044a }, /* lower */
+ { 0x10423, 0x1044b }, /* lower */
+ { 0x10424, 0x1044c }, /* lower */
+ { 0x10425, 0x1044d }, /* lower */
+ { 0x10426, 0x1044e }, /* lower */
+ { 0x10427, 0x1044f }, /* lower */
+ { 0x10450, 0x10450 },
+ { 0x10451, 0x10451 },
+ { 0x10452, 0x10452 },
+ { 0x10453, 0x10453 },
+ { 0x10454, 0x10454 },
+ { 0x10455, 0x10455 },
+ { 0x10456, 0x10456 },
+ { 0x10457, 0x10457 },
+ { 0x10458, 0x10458 },
+ { 0x10459, 0x10459 },
+ { 0x1045a, 0x1045a },
+ { 0x1045b, 0x1045b },
+ { 0x1045c, 0x1045c },
+ { 0x1045d, 0x1045d },
+ { 0x1045e, 0x1045e },
+ { 0x1045f, 0x1045f },
+ { 0x10460, 0x10460 },
+ { 0x10461, 0x10461 },
+ { 0x10462, 0x10462 },
+ { 0x10463, 0x10463 },
+ { 0x10464, 0x10464 },
+ { 0x10465, 0x10465 },
+ { 0x10466, 0x10466 },
+ { 0x10467, 0x10467 },
+ { 0x10468, 0x10468 },
+ { 0x10469, 0x10469 },
+ { 0x1046a, 0x1046a },
+ { 0x1046b, 0x1046b },
+ { 0x1046c, 0x1046c },
+ { 0x1046d, 0x1046d },
+ { 0x1046e, 0x1046e },
+ { 0x1046f, 0x1046f },
+ { 0x10470, 0x10470 },
+ { 0x10471, 0x10471 },
+ { 0x10472, 0x10472 },
+ { 0x10473, 0x10473 },
+ { 0x10474, 0x10474 },
+ { 0x10475, 0x10475 },
+ { 0x10476, 0x10476 },
+ { 0x10477, 0x10477 },
+ { 0x10478, 0x10478 },
+ { 0x10479, 0x10479 },
+ { 0x1047a, 0x1047a },
+ { 0x1047b, 0x1047b },
+ { 0x1047c, 0x1047c },
+ { 0x1047d, 0x1047d },
+ { 0x1047e, 0x1047e },
+ { 0x1047f, 0x1047f },
+ { 0x10480, 0x10480 },
+ { 0x10481, 0x10481 },
+ { 0x10482, 0x10482 },
+ { 0x10483, 0x10483 },
+ { 0x10484, 0x10484 },
+ { 0x10485, 0x10485 },
+ { 0x10486, 0x10486 },
+ { 0x10487, 0x10487 },
+ { 0x10488, 0x10488 },
+ { 0x10489, 0x10489 },
+ { 0x1048a, 0x1048a },
+ { 0x1048b, 0x1048b },
+ { 0x1048c, 0x1048c },
+ { 0x1048d, 0x1048d },
+ { 0x1048e, 0x1048e },
+ { 0x1048f, 0x1048f },
+ { 0x10490, 0x10490 },
+ { 0x10491, 0x10491 },
+ { 0x10492, 0x10492 },
+ { 0x10493, 0x10493 },
+ { 0x10494, 0x10494 },
+ { 0x10495, 0x10495 },
+ { 0x10496, 0x10496 },
+ { 0x10497, 0x10497 },
+ { 0x10498, 0x10498 },
+ { 0x10499, 0x10499 },
+ { 0x1049a, 0x1049a },
+ { 0x1049b, 0x1049b },
+ { 0x1049c, 0x1049c },
+ { 0x1049d, 0x1049d },
+ { 0x1049e, 0x1049e },
+ { 0x1049f, 0x1049f },
+ { 0x104a0, 0x104a0 },
+ { 0x104a1, 0x104a1 },
+ { 0x104a2, 0x104a2 },
+ { 0x104a3, 0x104a3 },
+ { 0x104a4, 0x104a4 },
+ { 0x104a5, 0x104a5 },
+ { 0x104a6, 0x104a6 },
+ { 0x104a7, 0x104a7 },
+ { 0x104a8, 0x104a8 },
+ { 0x104a9, 0x104a9 },
+ { 0x104aa, 0x104aa },
+ { 0x104ab, 0x104ab },
+ { 0x104ac, 0x104ac },
+ { 0x104ad, 0x104ad },
+ { 0x104ae, 0x104ae },
+ { 0x104af, 0x104af },
+ { 0x104b0, 0x104b0 },
+ { 0x104b1, 0x104b1 },
+ { 0x104b2, 0x104b2 },
+ { 0x104b3, 0x104b3 },
+ { 0x104b4, 0x104b4 },
+ { 0x104b5, 0x104b5 },
+ { 0x104b6, 0x104b6 },
+ { 0x104b7, 0x104b7 },
+ { 0x104b8, 0x104b8 },
+ { 0x104b9, 0x104b9 },
+ { 0x104ba, 0x104ba },
+ { 0x104bb, 0x104bb },
+ { 0x104bc, 0x104bc },
+ { 0x104bd, 0x104bd },
+ { 0x104be, 0x104be },
+ { 0x104bf, 0x104bf },
+ { 0x104c0, 0x104c0 },
+ { 0x104c1, 0x104c1 },
+ { 0x104c2, 0x104c2 },
+ { 0x104c3, 0x104c3 },
+ { 0x104c4, 0x104c4 },
+ { 0x104c5, 0x104c5 },
+ { 0x104c6, 0x104c6 },
+ { 0x104c7, 0x104c7 },
+ { 0x104c8, 0x104c8 },
+ { 0x104c9, 0x104c9 },
+ { 0x104ca, 0x104ca },
+ { 0x104cb, 0x104cb },
+ { 0x104cc, 0x104cc },
+ { 0x104cd, 0x104cd },
+ { 0x104ce, 0x104ce },
+ { 0x104cf, 0x104cf },
+ { 0x104d0, 0x104d0 },
+ { 0x104d1, 0x104d1 },
+ { 0x104d2, 0x104d2 },
+ { 0x104d3, 0x104d3 },
+ { 0x104d4, 0x104d4 },
+ { 0x104d5, 0x104d5 },
+ { 0x104d6, 0x104d6 },
+ { 0x104d7, 0x104d7 },
+ { 0x104d8, 0x104d8 },
+ { 0x104d9, 0x104d9 },
+ { 0x104da, 0x104da },
+ { 0x104db, 0x104db },
+ { 0x104dc, 0x104dc },
+ { 0x104dd, 0x104dd },
+ { 0x104de, 0x104de },
+ { 0x104df, 0x104df },
+ { 0x104e0, 0x104e0 },
+ { 0x104e1, 0x104e1 },
+ { 0x104e2, 0x104e2 },
+ { 0x104e3, 0x104e3 },
+ { 0x104e4, 0x104e4 },
+ { 0x104e5, 0x104e5 },
+ { 0x104e6, 0x104e6 },
+ { 0x104e7, 0x104e7 },
+ { 0x104e8, 0x104e8 },
+ { 0x104e9, 0x104e9 },
+ { 0x104ea, 0x104ea },
+ { 0x104eb, 0x104eb },
+ { 0x104ec, 0x104ec },
+ { 0x104ed, 0x104ed },
+ { 0x104ee, 0x104ee },
+ { 0x104ef, 0x104ef },
+ { 0x104f0, 0x104f0 },
+ { 0x104f1, 0x104f1 },
+ { 0x104f2, 0x104f2 },
+ { 0x104f3, 0x104f3 },
+ { 0x104f4, 0x104f4 },
+ { 0x104f5, 0x104f5 },
+ { 0x104f6, 0x104f6 },
+ { 0x104f7, 0x104f7 },
+ { 0x104f8, 0x104f8 },
+ { 0x104f9, 0x104f9 },
+ { 0x104fa, 0x104fa },
+ { 0x104fb, 0x104fb },
+ { 0x104fc, 0x104fc },
+ { 0x104fd, 0x104fd },
+ { 0x104fe, 0x104fe },
+ { 0x104ff, 0x104ff },
+};
+
+glui32 unigen_special_array[] = {
+ 2, 0x53, 0x53, /* 0xdf upcase */
+ 1, 0xdf, /* 0xdf downcase */
+ 2, 0x53, 0x73, /* 0xdf titlecase */
+ 1, 0x130, /* 0x130 upcase */
+ 2, 0x69, 0x307, /* 0x130 downcase */
+ 1, 0x130, /* 0x130 titlecase */
+ 2, 0x2bc, 0x4e, /* 0x149 upcase */
+ 1, 0x149, /* 0x149 downcase */
+ 2, 0x2bc, 0x4e, /* 0x149 titlecase */
+ 1, 0x1c4, /* 0x1c4 upcase */
+ 1, 0x1c6, /* 0x1c4 downcase */
+ 1, 0x1c5, /* 0x1c4 titlecase */
+ 1, 0x1c4, /* 0x1c5 upcase */
+ 1, 0x1c6, /* 0x1c5 downcase */
+ 1, 0x1c5, /* 0x1c5 titlecase */
+ 1, 0x1c4, /* 0x1c6 upcase */
+ 1, 0x1c6, /* 0x1c6 downcase */
+ 1, 0x1c5, /* 0x1c6 titlecase */
+ 1, 0x1c7, /* 0x1c7 upcase */
+ 1, 0x1c9, /* 0x1c7 downcase */
+ 1, 0x1c8, /* 0x1c7 titlecase */
+ 1, 0x1c7, /* 0x1c8 upcase */
+ 1, 0x1c9, /* 0x1c8 downcase */
+ 1, 0x1c8, /* 0x1c8 titlecase */
+ 1, 0x1c7, /* 0x1c9 upcase */
+ 1, 0x1c9, /* 0x1c9 downcase */
+ 1, 0x1c8, /* 0x1c9 titlecase */
+ 1, 0x1ca, /* 0x1ca upcase */
+ 1, 0x1cc, /* 0x1ca downcase */
+ 1, 0x1cb, /* 0x1ca titlecase */
+ 1, 0x1ca, /* 0x1cb upcase */
+ 1, 0x1cc, /* 0x1cb downcase */
+ 1, 0x1cb, /* 0x1cb titlecase */
+ 1, 0x1ca, /* 0x1cc upcase */
+ 1, 0x1cc, /* 0x1cc downcase */
+ 1, 0x1cb, /* 0x1cc titlecase */
+ 2, 0x4a, 0x30c, /* 0x1f0 upcase */
+ 1, 0x1f0, /* 0x1f0 downcase */
+ 2, 0x4a, 0x30c, /* 0x1f0 titlecase */
+ 1, 0x1f1, /* 0x1f1 upcase */
+ 1, 0x1f3, /* 0x1f1 downcase */
+ 1, 0x1f2, /* 0x1f1 titlecase */
+ 1, 0x1f1, /* 0x1f2 upcase */
+ 1, 0x1f3, /* 0x1f2 downcase */
+ 1, 0x1f2, /* 0x1f2 titlecase */
+ 1, 0x1f1, /* 0x1f3 upcase */
+ 1, 0x1f3, /* 0x1f3 downcase */
+ 1, 0x1f2, /* 0x1f3 titlecase */
+ 3, 0x399, 0x308, 0x301, /* 0x390 upcase */
+ 1, 0x390, /* 0x390 downcase */
+ 3, 0x399, 0x308, 0x301, /* 0x390 titlecase */
+ 3, 0x3a5, 0x308, 0x301, /* 0x3b0 upcase */
+ 1, 0x3b0, /* 0x3b0 downcase */
+ 3, 0x3a5, 0x308, 0x301, /* 0x3b0 titlecase */
+ 2, 0x535, 0x552, /* 0x587 upcase */
+ 1, 0x587, /* 0x587 downcase */
+ 2, 0x535, 0x582, /* 0x587 titlecase */
+ 2, 0x48, 0x331, /* 0x1e96 upcase */
+ 1, 0x1e96, /* 0x1e96 downcase */
+ 2, 0x48, 0x331, /* 0x1e96 titlecase */
+ 2, 0x54, 0x308, /* 0x1e97 upcase */
+ 1, 0x1e97, /* 0x1e97 downcase */
+ 2, 0x54, 0x308, /* 0x1e97 titlecase */
+ 2, 0x57, 0x30a, /* 0x1e98 upcase */
+ 1, 0x1e98, /* 0x1e98 downcase */
+ 2, 0x57, 0x30a, /* 0x1e98 titlecase */
+ 2, 0x59, 0x30a, /* 0x1e99 upcase */
+ 1, 0x1e99, /* 0x1e99 downcase */
+ 2, 0x59, 0x30a, /* 0x1e99 titlecase */
+ 2, 0x41, 0x2be, /* 0x1e9a upcase */
+ 1, 0x1e9a, /* 0x1e9a downcase */
+ 2, 0x41, 0x2be, /* 0x1e9a titlecase */
+ 2, 0x3a5, 0x313, /* 0x1f50 upcase */
+ 1, 0x1f50, /* 0x1f50 downcase */
+ 2, 0x3a5, 0x313, /* 0x1f50 titlecase */
+ 3, 0x3a5, 0x313, 0x300, /* 0x1f52 upcase */
+ 1, 0x1f52, /* 0x1f52 downcase */
+ 3, 0x3a5, 0x313, 0x300, /* 0x1f52 titlecase */
+ 3, 0x3a5, 0x313, 0x301, /* 0x1f54 upcase */
+ 1, 0x1f54, /* 0x1f54 downcase */
+ 3, 0x3a5, 0x313, 0x301, /* 0x1f54 titlecase */
+ 3, 0x3a5, 0x313, 0x342, /* 0x1f56 upcase */
+ 1, 0x1f56, /* 0x1f56 downcase */
+ 3, 0x3a5, 0x313, 0x342, /* 0x1f56 titlecase */
+ 2, 0x1f08, 0x399, /* 0x1f80 upcase */
+ 1, 0x1f80, /* 0x1f80 downcase */
+ 1, 0x1f88, /* 0x1f80 titlecase */
+ 2, 0x1f09, 0x399, /* 0x1f81 upcase */
+ 1, 0x1f81, /* 0x1f81 downcase */
+ 1, 0x1f89, /* 0x1f81 titlecase */
+ 2, 0x1f0a, 0x399, /* 0x1f82 upcase */
+ 1, 0x1f82, /* 0x1f82 downcase */
+ 1, 0x1f8a, /* 0x1f82 titlecase */
+ 2, 0x1f0b, 0x399, /* 0x1f83 upcase */
+ 1, 0x1f83, /* 0x1f83 downcase */
+ 1, 0x1f8b, /* 0x1f83 titlecase */
+ 2, 0x1f0c, 0x399, /* 0x1f84 upcase */
+ 1, 0x1f84, /* 0x1f84 downcase */
+ 1, 0x1f8c, /* 0x1f84 titlecase */
+ 2, 0x1f0d, 0x399, /* 0x1f85 upcase */
+ 1, 0x1f85, /* 0x1f85 downcase */
+ 1, 0x1f8d, /* 0x1f85 titlecase */
+ 2, 0x1f0e, 0x399, /* 0x1f86 upcase */
+ 1, 0x1f86, /* 0x1f86 downcase */
+ 1, 0x1f8e, /* 0x1f86 titlecase */
+ 2, 0x1f0f, 0x399, /* 0x1f87 upcase */
+ 1, 0x1f87, /* 0x1f87 downcase */
+ 1, 0x1f8f, /* 0x1f87 titlecase */
+ 2, 0x1f08, 0x399, /* 0x1f88 upcase */
+ 1, 0x1f80, /* 0x1f88 downcase */
+ 1, 0x1f88, /* 0x1f88 titlecase */
+ 2, 0x1f09, 0x399, /* 0x1f89 upcase */
+ 1, 0x1f81, /* 0x1f89 downcase */
+ 1, 0x1f89, /* 0x1f89 titlecase */
+ 2, 0x1f0a, 0x399, /* 0x1f8a upcase */
+ 1, 0x1f82, /* 0x1f8a downcase */
+ 1, 0x1f8a, /* 0x1f8a titlecase */
+ 2, 0x1f0b, 0x399, /* 0x1f8b upcase */
+ 1, 0x1f83, /* 0x1f8b downcase */
+ 1, 0x1f8b, /* 0x1f8b titlecase */
+ 2, 0x1f0c, 0x399, /* 0x1f8c upcase */
+ 1, 0x1f84, /* 0x1f8c downcase */
+ 1, 0x1f8c, /* 0x1f8c titlecase */
+ 2, 0x1f0d, 0x399, /* 0x1f8d upcase */
+ 1, 0x1f85, /* 0x1f8d downcase */
+ 1, 0x1f8d, /* 0x1f8d titlecase */
+ 2, 0x1f0e, 0x399, /* 0x1f8e upcase */
+ 1, 0x1f86, /* 0x1f8e downcase */
+ 1, 0x1f8e, /* 0x1f8e titlecase */
+ 2, 0x1f0f, 0x399, /* 0x1f8f upcase */
+ 1, 0x1f87, /* 0x1f8f downcase */
+ 1, 0x1f8f, /* 0x1f8f titlecase */
+ 2, 0x1f28, 0x399, /* 0x1f90 upcase */
+ 1, 0x1f90, /* 0x1f90 downcase */
+ 1, 0x1f98, /* 0x1f90 titlecase */
+ 2, 0x1f29, 0x399, /* 0x1f91 upcase */
+ 1, 0x1f91, /* 0x1f91 downcase */
+ 1, 0x1f99, /* 0x1f91 titlecase */
+ 2, 0x1f2a, 0x399, /* 0x1f92 upcase */
+ 1, 0x1f92, /* 0x1f92 downcase */
+ 1, 0x1f9a, /* 0x1f92 titlecase */
+ 2, 0x1f2b, 0x399, /* 0x1f93 upcase */
+ 1, 0x1f93, /* 0x1f93 downcase */
+ 1, 0x1f9b, /* 0x1f93 titlecase */
+ 2, 0x1f2c, 0x399, /* 0x1f94 upcase */
+ 1, 0x1f94, /* 0x1f94 downcase */
+ 1, 0x1f9c, /* 0x1f94 titlecase */
+ 2, 0x1f2d, 0x399, /* 0x1f95 upcase */
+ 1, 0x1f95, /* 0x1f95 downcase */
+ 1, 0x1f9d, /* 0x1f95 titlecase */
+ 2, 0x1f2e, 0x399, /* 0x1f96 upcase */
+ 1, 0x1f96, /* 0x1f96 downcase */
+ 1, 0x1f9e, /* 0x1f96 titlecase */
+ 2, 0x1f2f, 0x399, /* 0x1f97 upcase */
+ 1, 0x1f97, /* 0x1f97 downcase */
+ 1, 0x1f9f, /* 0x1f97 titlecase */
+ 2, 0x1f28, 0x399, /* 0x1f98 upcase */
+ 1, 0x1f90, /* 0x1f98 downcase */
+ 1, 0x1f98, /* 0x1f98 titlecase */
+ 2, 0x1f29, 0x399, /* 0x1f99 upcase */
+ 1, 0x1f91, /* 0x1f99 downcase */
+ 1, 0x1f99, /* 0x1f99 titlecase */
+ 2, 0x1f2a, 0x399, /* 0x1f9a upcase */
+ 1, 0x1f92, /* 0x1f9a downcase */
+ 1, 0x1f9a, /* 0x1f9a titlecase */
+ 2, 0x1f2b, 0x399, /* 0x1f9b upcase */
+ 1, 0x1f93, /* 0x1f9b downcase */
+ 1, 0x1f9b, /* 0x1f9b titlecase */
+ 2, 0x1f2c, 0x399, /* 0x1f9c upcase */
+ 1, 0x1f94, /* 0x1f9c downcase */
+ 1, 0x1f9c, /* 0x1f9c titlecase */
+ 2, 0x1f2d, 0x399, /* 0x1f9d upcase */
+ 1, 0x1f95, /* 0x1f9d downcase */
+ 1, 0x1f9d, /* 0x1f9d titlecase */
+ 2, 0x1f2e, 0x399, /* 0x1f9e upcase */
+ 1, 0x1f96, /* 0x1f9e downcase */
+ 1, 0x1f9e, /* 0x1f9e titlecase */
+ 2, 0x1f2f, 0x399, /* 0x1f9f upcase */
+ 1, 0x1f97, /* 0x1f9f downcase */
+ 1, 0x1f9f, /* 0x1f9f titlecase */
+ 2, 0x1f68, 0x399, /* 0x1fa0 upcase */
+ 1, 0x1fa0, /* 0x1fa0 downcase */
+ 1, 0x1fa8, /* 0x1fa0 titlecase */
+ 2, 0x1f69, 0x399, /* 0x1fa1 upcase */
+ 1, 0x1fa1, /* 0x1fa1 downcase */
+ 1, 0x1fa9, /* 0x1fa1 titlecase */
+ 2, 0x1f6a, 0x399, /* 0x1fa2 upcase */
+ 1, 0x1fa2, /* 0x1fa2 downcase */
+ 1, 0x1faa, /* 0x1fa2 titlecase */
+ 2, 0x1f6b, 0x399, /* 0x1fa3 upcase */
+ 1, 0x1fa3, /* 0x1fa3 downcase */
+ 1, 0x1fab, /* 0x1fa3 titlecase */
+ 2, 0x1f6c, 0x399, /* 0x1fa4 upcase */
+ 1, 0x1fa4, /* 0x1fa4 downcase */
+ 1, 0x1fac, /* 0x1fa4 titlecase */
+ 2, 0x1f6d, 0x399, /* 0x1fa5 upcase */
+ 1, 0x1fa5, /* 0x1fa5 downcase */
+ 1, 0x1fad, /* 0x1fa5 titlecase */
+ 2, 0x1f6e, 0x399, /* 0x1fa6 upcase */
+ 1, 0x1fa6, /* 0x1fa6 downcase */
+ 1, 0x1fae, /* 0x1fa6 titlecase */
+ 2, 0x1f6f, 0x399, /* 0x1fa7 upcase */
+ 1, 0x1fa7, /* 0x1fa7 downcase */
+ 1, 0x1faf, /* 0x1fa7 titlecase */
+ 2, 0x1f68, 0x399, /* 0x1fa8 upcase */
+ 1, 0x1fa0, /* 0x1fa8 downcase */
+ 1, 0x1fa8, /* 0x1fa8 titlecase */
+ 2, 0x1f69, 0x399, /* 0x1fa9 upcase */
+ 1, 0x1fa1, /* 0x1fa9 downcase */
+ 1, 0x1fa9, /* 0x1fa9 titlecase */
+ 2, 0x1f6a, 0x399, /* 0x1faa upcase */
+ 1, 0x1fa2, /* 0x1faa downcase */
+ 1, 0x1faa, /* 0x1faa titlecase */
+ 2, 0x1f6b, 0x399, /* 0x1fab upcase */
+ 1, 0x1fa3, /* 0x1fab downcase */
+ 1, 0x1fab, /* 0x1fab titlecase */
+ 2, 0x1f6c, 0x399, /* 0x1fac upcase */
+ 1, 0x1fa4, /* 0x1fac downcase */
+ 1, 0x1fac, /* 0x1fac titlecase */
+ 2, 0x1f6d, 0x399, /* 0x1fad upcase */
+ 1, 0x1fa5, /* 0x1fad downcase */
+ 1, 0x1fad, /* 0x1fad titlecase */
+ 2, 0x1f6e, 0x399, /* 0x1fae upcase */
+ 1, 0x1fa6, /* 0x1fae downcase */
+ 1, 0x1fae, /* 0x1fae titlecase */
+ 2, 0x1f6f, 0x399, /* 0x1faf upcase */
+ 1, 0x1fa7, /* 0x1faf downcase */
+ 1, 0x1faf, /* 0x1faf titlecase */
+ 2, 0x1fba, 0x399, /* 0x1fb2 upcase */
+ 1, 0x1fb2, /* 0x1fb2 downcase */
+ 2, 0x1fba, 0x345, /* 0x1fb2 titlecase */
+ 2, 0x391, 0x399, /* 0x1fb3 upcase */
+ 1, 0x1fb3, /* 0x1fb3 downcase */
+ 1, 0x1fbc, /* 0x1fb3 titlecase */
+ 2, 0x386, 0x399, /* 0x1fb4 upcase */
+ 1, 0x1fb4, /* 0x1fb4 downcase */
+ 2, 0x386, 0x345, /* 0x1fb4 titlecase */
+ 2, 0x391, 0x342, /* 0x1fb6 upcase */
+ 1, 0x1fb6, /* 0x1fb6 downcase */
+ 2, 0x391, 0x342, /* 0x1fb6 titlecase */
+ 3, 0x391, 0x342, 0x399, /* 0x1fb7 upcase */
+ 1, 0x1fb7, /* 0x1fb7 downcase */
+ 3, 0x391, 0x342, 0x345, /* 0x1fb7 titlecase */
+ 2, 0x391, 0x399, /* 0x1fbc upcase */
+ 1, 0x1fb3, /* 0x1fbc downcase */
+ 1, 0x1fbc, /* 0x1fbc titlecase */
+ 2, 0x1fca, 0x399, /* 0x1fc2 upcase */
+ 1, 0x1fc2, /* 0x1fc2 downcase */
+ 2, 0x1fca, 0x345, /* 0x1fc2 titlecase */
+ 2, 0x397, 0x399, /* 0x1fc3 upcase */
+ 1, 0x1fc3, /* 0x1fc3 downcase */
+ 1, 0x1fcc, /* 0x1fc3 titlecase */
+ 2, 0x389, 0x399, /* 0x1fc4 upcase */
+ 1, 0x1fc4, /* 0x1fc4 downcase */
+ 2, 0x389, 0x345, /* 0x1fc4 titlecase */
+ 2, 0x397, 0x342, /* 0x1fc6 upcase */
+ 1, 0x1fc6, /* 0x1fc6 downcase */
+ 2, 0x397, 0x342, /* 0x1fc6 titlecase */
+ 3, 0x397, 0x342, 0x399, /* 0x1fc7 upcase */
+ 1, 0x1fc7, /* 0x1fc7 downcase */
+ 3, 0x397, 0x342, 0x345, /* 0x1fc7 titlecase */
+ 2, 0x397, 0x399, /* 0x1fcc upcase */
+ 1, 0x1fc3, /* 0x1fcc downcase */
+ 1, 0x1fcc, /* 0x1fcc titlecase */
+ 3, 0x399, 0x308, 0x300, /* 0x1fd2 upcase */
+ 1, 0x1fd2, /* 0x1fd2 downcase */
+ 3, 0x399, 0x308, 0x300, /* 0x1fd2 titlecase */
+ 3, 0x399, 0x308, 0x301, /* 0x1fd3 upcase */
+ 1, 0x1fd3, /* 0x1fd3 downcase */
+ 3, 0x399, 0x308, 0x301, /* 0x1fd3 titlecase */
+ 2, 0x399, 0x342, /* 0x1fd6 upcase */
+ 1, 0x1fd6, /* 0x1fd6 downcase */
+ 2, 0x399, 0x342, /* 0x1fd6 titlecase */
+ 3, 0x399, 0x308, 0x342, /* 0x1fd7 upcase */
+ 1, 0x1fd7, /* 0x1fd7 downcase */
+ 3, 0x399, 0x308, 0x342, /* 0x1fd7 titlecase */
+ 3, 0x3a5, 0x308, 0x300, /* 0x1fe2 upcase */
+ 1, 0x1fe2, /* 0x1fe2 downcase */
+ 3, 0x3a5, 0x308, 0x300, /* 0x1fe2 titlecase */
+ 3, 0x3a5, 0x308, 0x301, /* 0x1fe3 upcase */
+ 1, 0x1fe3, /* 0x1fe3 downcase */
+ 3, 0x3a5, 0x308, 0x301, /* 0x1fe3 titlecase */
+ 2, 0x3a1, 0x313, /* 0x1fe4 upcase */
+ 1, 0x1fe4, /* 0x1fe4 downcase */
+ 2, 0x3a1, 0x313, /* 0x1fe4 titlecase */
+ 2, 0x3a5, 0x342, /* 0x1fe6 upcase */
+ 1, 0x1fe6, /* 0x1fe6 downcase */
+ 2, 0x3a5, 0x342, /* 0x1fe6 titlecase */
+ 3, 0x3a5, 0x308, 0x342, /* 0x1fe7 upcase */
+ 1, 0x1fe7, /* 0x1fe7 downcase */
+ 3, 0x3a5, 0x308, 0x342, /* 0x1fe7 titlecase */
+ 2, 0x1ffa, 0x399, /* 0x1ff2 upcase */
+ 1, 0x1ff2, /* 0x1ff2 downcase */
+ 2, 0x1ffa, 0x345, /* 0x1ff2 titlecase */
+ 2, 0x3a9, 0x399, /* 0x1ff3 upcase */
+ 1, 0x1ff3, /* 0x1ff3 downcase */
+ 1, 0x1ffc, /* 0x1ff3 titlecase */
+ 2, 0x38f, 0x399, /* 0x1ff4 upcase */
+ 1, 0x1ff4, /* 0x1ff4 downcase */
+ 2, 0x38f, 0x345, /* 0x1ff4 titlecase */
+ 2, 0x3a9, 0x342, /* 0x1ff6 upcase */
+ 1, 0x1ff6, /* 0x1ff6 downcase */
+ 2, 0x3a9, 0x342, /* 0x1ff6 titlecase */
+ 3, 0x3a9, 0x342, 0x399, /* 0x1ff7 upcase */
+ 1, 0x1ff7, /* 0x1ff7 downcase */
+ 3, 0x3a9, 0x342, 0x345, /* 0x1ff7 titlecase */
+ 2, 0x3a9, 0x399, /* 0x1ffc upcase */
+ 1, 0x1ff3, /* 0x1ffc downcase */
+ 1, 0x1ffc, /* 0x1ffc titlecase */
+ 2, 0x46, 0x46, /* 0xfb00 upcase */
+ 1, 0xfb00, /* 0xfb00 downcase */
+ 2, 0x46, 0x66, /* 0xfb00 titlecase */
+ 2, 0x46, 0x49, /* 0xfb01 upcase */
+ 1, 0xfb01, /* 0xfb01 downcase */
+ 2, 0x46, 0x69, /* 0xfb01 titlecase */
+ 2, 0x46, 0x4c, /* 0xfb02 upcase */
+ 1, 0xfb02, /* 0xfb02 downcase */
+ 2, 0x46, 0x6c, /* 0xfb02 titlecase */
+ 3, 0x46, 0x46, 0x49, /* 0xfb03 upcase */
+ 1, 0xfb03, /* 0xfb03 downcase */
+ 3, 0x46, 0x66, 0x69, /* 0xfb03 titlecase */
+ 3, 0x46, 0x46, 0x4c, /* 0xfb04 upcase */
+ 1, 0xfb04, /* 0xfb04 downcase */
+ 3, 0x46, 0x66, 0x6c, /* 0xfb04 titlecase */
+ 2, 0x53, 0x54, /* 0xfb05 upcase */
+ 1, 0xfb05, /* 0xfb05 downcase */
+ 2, 0x53, 0x74, /* 0xfb05 titlecase */
+ 2, 0x53, 0x54, /* 0xfb06 upcase */
+ 1, 0xfb06, /* 0xfb06 downcase */
+ 2, 0x53, 0x74, /* 0xfb06 titlecase */
+ 2, 0x544, 0x546, /* 0xfb13 upcase */
+ 1, 0xfb13, /* 0xfb13 downcase */
+ 2, 0x544, 0x576, /* 0xfb13 titlecase */
+ 2, 0x544, 0x535, /* 0xfb14 upcase */
+ 1, 0xfb14, /* 0xfb14 downcase */
+ 2, 0x544, 0x565, /* 0xfb14 titlecase */
+ 2, 0x544, 0x53b, /* 0xfb15 upcase */
+ 1, 0xfb15, /* 0xfb15 downcase */
+ 2, 0x544, 0x56b, /* 0xfb15 titlecase */
+ 2, 0x54e, 0x546, /* 0xfb16 upcase */
+ 1, 0xfb16, /* 0xfb16 downcase */
+ 2, 0x54e, 0x576, /* 0xfb16 titlecase */
+ 2, 0x544, 0x53d, /* 0xfb17 upcase */
+ 1, 0xfb17, /* 0xfb17 downcase */
+ 2, 0x544, 0x56d, /* 0xfb17 titlecase */
+};
+
+gli_case_special_t unigen_special_0xdf = { 0, 3, 5 };
+gli_case_special_t unigen_special_0x130 = { 8, 10, 13 };
+gli_case_special_t unigen_special_0x149 = { 15, 18, 20 };
+gli_case_special_t unigen_special_0x1c4 = { 23, 25, 27 };
+gli_case_special_t unigen_special_0x1c5 = { 29, 31, 33 };
+gli_case_special_t unigen_special_0x1c6 = { 35, 37, 39 };
+gli_case_special_t unigen_special_0x1c7 = { 41, 43, 45 };
+gli_case_special_t unigen_special_0x1c8 = { 47, 49, 51 };
+gli_case_special_t unigen_special_0x1c9 = { 53, 55, 57 };
+gli_case_special_t unigen_special_0x1ca = { 59, 61, 63 };
+gli_case_special_t unigen_special_0x1cb = { 65, 67, 69 };
+gli_case_special_t unigen_special_0x1cc = { 71, 73, 75 };
+gli_case_special_t unigen_special_0x1f0 = { 77, 80, 82 };
+gli_case_special_t unigen_special_0x1f1 = { 85, 87, 89 };
+gli_case_special_t unigen_special_0x1f2 = { 91, 93, 95 };
+gli_case_special_t unigen_special_0x1f3 = { 97, 99, 101 };
+gli_case_special_t unigen_special_0x390 = { 103, 107, 109 };
+gli_case_special_t unigen_special_0x3b0 = { 113, 117, 119 };
+gli_case_special_t unigen_special_0x587 = { 123, 126, 128 };
+gli_case_special_t unigen_special_0x1e96 = { 131, 134, 136 };
+gli_case_special_t unigen_special_0x1e97 = { 139, 142, 144 };
+gli_case_special_t unigen_special_0x1e98 = { 147, 150, 152 };
+gli_case_special_t unigen_special_0x1e99 = { 155, 158, 160 };
+gli_case_special_t unigen_special_0x1e9a = { 163, 166, 168 };
+gli_case_special_t unigen_special_0x1f50 = { 171, 174, 176 };
+gli_case_special_t unigen_special_0x1f52 = { 179, 183, 185 };
+gli_case_special_t unigen_special_0x1f54 = { 189, 193, 195 };
+gli_case_special_t unigen_special_0x1f56 = { 199, 203, 205 };
+gli_case_special_t unigen_special_0x1f80 = { 209, 212, 214 };
+gli_case_special_t unigen_special_0x1f81 = { 216, 219, 221 };
+gli_case_special_t unigen_special_0x1f82 = { 223, 226, 228 };
+gli_case_special_t unigen_special_0x1f83 = { 230, 233, 235 };
+gli_case_special_t unigen_special_0x1f84 = { 237, 240, 242 };
+gli_case_special_t unigen_special_0x1f85 = { 244, 247, 249 };
+gli_case_special_t unigen_special_0x1f86 = { 251, 254, 256 };
+gli_case_special_t unigen_special_0x1f87 = { 258, 261, 263 };
+gli_case_special_t unigen_special_0x1f88 = { 265, 268, 270 };
+gli_case_special_t unigen_special_0x1f89 = { 272, 275, 277 };
+gli_case_special_t unigen_special_0x1f8a = { 279, 282, 284 };
+gli_case_special_t unigen_special_0x1f8b = { 286, 289, 291 };
+gli_case_special_t unigen_special_0x1f8c = { 293, 296, 298 };
+gli_case_special_t unigen_special_0x1f8d = { 300, 303, 305 };
+gli_case_special_t unigen_special_0x1f8e = { 307, 310, 312 };
+gli_case_special_t unigen_special_0x1f8f = { 314, 317, 319 };
+gli_case_special_t unigen_special_0x1f90 = { 321, 324, 326 };
+gli_case_special_t unigen_special_0x1f91 = { 328, 331, 333 };
+gli_case_special_t unigen_special_0x1f92 = { 335, 338, 340 };
+gli_case_special_t unigen_special_0x1f93 = { 342, 345, 347 };
+gli_case_special_t unigen_special_0x1f94 = { 349, 352, 354 };
+gli_case_special_t unigen_special_0x1f95 = { 356, 359, 361 };
+gli_case_special_t unigen_special_0x1f96 = { 363, 366, 368 };
+gli_case_special_t unigen_special_0x1f97 = { 370, 373, 375 };
+gli_case_special_t unigen_special_0x1f98 = { 377, 380, 382 };
+gli_case_special_t unigen_special_0x1f99 = { 384, 387, 389 };
+gli_case_special_t unigen_special_0x1f9a = { 391, 394, 396 };
+gli_case_special_t unigen_special_0x1f9b = { 398, 401, 403 };
+gli_case_special_t unigen_special_0x1f9c = { 405, 408, 410 };
+gli_case_special_t unigen_special_0x1f9d = { 412, 415, 417 };
+gli_case_special_t unigen_special_0x1f9e = { 419, 422, 424 };
+gli_case_special_t unigen_special_0x1f9f = { 426, 429, 431 };
+gli_case_special_t unigen_special_0x1fa0 = { 433, 436, 438 };
+gli_case_special_t unigen_special_0x1fa1 = { 440, 443, 445 };
+gli_case_special_t unigen_special_0x1fa2 = { 447, 450, 452 };
+gli_case_special_t unigen_special_0x1fa3 = { 454, 457, 459 };
+gli_case_special_t unigen_special_0x1fa4 = { 461, 464, 466 };
+gli_case_special_t unigen_special_0x1fa5 = { 468, 471, 473 };
+gli_case_special_t unigen_special_0x1fa6 = { 475, 478, 480 };
+gli_case_special_t unigen_special_0x1fa7 = { 482, 485, 487 };
+gli_case_special_t unigen_special_0x1fa8 = { 489, 492, 494 };
+gli_case_special_t unigen_special_0x1fa9 = { 496, 499, 501 };
+gli_case_special_t unigen_special_0x1faa = { 503, 506, 508 };
+gli_case_special_t unigen_special_0x1fab = { 510, 513, 515 };
+gli_case_special_t unigen_special_0x1fac = { 517, 520, 522 };
+gli_case_special_t unigen_special_0x1fad = { 524, 527, 529 };
+gli_case_special_t unigen_special_0x1fae = { 531, 534, 536 };
+gli_case_special_t unigen_special_0x1faf = { 538, 541, 543 };
+gli_case_special_t unigen_special_0x1fb2 = { 545, 548, 550 };
+gli_case_special_t unigen_special_0x1fb3 = { 553, 556, 558 };
+gli_case_special_t unigen_special_0x1fb4 = { 560, 563, 565 };
+gli_case_special_t unigen_special_0x1fb6 = { 568, 571, 573 };
+gli_case_special_t unigen_special_0x1fb7 = { 576, 580, 582 };
+gli_case_special_t unigen_special_0x1fbc = { 586, 589, 591 };
+gli_case_special_t unigen_special_0x1fc2 = { 593, 596, 598 };
+gli_case_special_t unigen_special_0x1fc3 = { 601, 604, 606 };
+gli_case_special_t unigen_special_0x1fc4 = { 608, 611, 613 };
+gli_case_special_t unigen_special_0x1fc6 = { 616, 619, 621 };
+gli_case_special_t unigen_special_0x1fc7 = { 624, 628, 630 };
+gli_case_special_t unigen_special_0x1fcc = { 634, 637, 639 };
+gli_case_special_t unigen_special_0x1fd2 = { 641, 645, 647 };
+gli_case_special_t unigen_special_0x1fd3 = { 651, 655, 657 };
+gli_case_special_t unigen_special_0x1fd6 = { 661, 664, 666 };
+gli_case_special_t unigen_special_0x1fd7 = { 669, 673, 675 };
+gli_case_special_t unigen_special_0x1fe2 = { 679, 683, 685 };
+gli_case_special_t unigen_special_0x1fe3 = { 689, 693, 695 };
+gli_case_special_t unigen_special_0x1fe4 = { 699, 702, 704 };
+gli_case_special_t unigen_special_0x1fe6 = { 707, 710, 712 };
+gli_case_special_t unigen_special_0x1fe7 = { 715, 719, 721 };
+gli_case_special_t unigen_special_0x1ff2 = { 725, 728, 730 };
+gli_case_special_t unigen_special_0x1ff3 = { 733, 736, 738 };
+gli_case_special_t unigen_special_0x1ff4 = { 740, 743, 745 };
+gli_case_special_t unigen_special_0x1ff6 = { 748, 751, 753 };
+gli_case_special_t unigen_special_0x1ff7 = { 756, 760, 762 };
+gli_case_special_t unigen_special_0x1ffc = { 766, 769, 771 };
+gli_case_special_t unigen_special_0xfb00 = { 773, 776, 778 };
+gli_case_special_t unigen_special_0xfb01 = { 781, 784, 786 };
+gli_case_special_t unigen_special_0xfb02 = { 789, 792, 794 };
+gli_case_special_t unigen_special_0xfb03 = { 797, 801, 803 };
+gli_case_special_t unigen_special_0xfb04 = { 807, 811, 813 };
+gli_case_special_t unigen_special_0xfb05 = { 817, 820, 822 };
+gli_case_special_t unigen_special_0xfb06 = { 825, 828, 830 };
+gli_case_special_t unigen_special_0xfb13 = { 833, 836, 838 };
+gli_case_special_t unigen_special_0xfb14 = { 841, 844, 846 };
+gli_case_special_t unigen_special_0xfb15 = { 849, 852, 854 };
+gli_case_special_t unigen_special_0xfb16 = { 857, 860, 862 };
+gli_case_special_t unigen_special_0xfb17 = { 865, 868, 870 };
+
+#define RETURN_COMBINING_CLASS(ch) \
+switch ((glui32)(ch) >> 8) { \
+case 3: \
+switch (ch) { \
+ case 820: \
+ case 821: \
+ case 822: \
+ case 823: \
+ case 824: \
+ return 1; \
+ case 801: \
+ case 802: \
+ case 807: \
+ case 808: \
+ return 202; \
+ case 795: \
+ return 216; \
+ case 790: \
+ case 791: \
+ case 792: \
+ case 793: \
+ case 796: \
+ case 797: \
+ case 798: \
+ case 799: \
+ case 800: \
+ case 803: \
+ case 804: \
+ case 805: \
+ case 806: \
+ case 809: \
+ case 810: \
+ case 811: \
+ case 812: \
+ case 813: \
+ case 814: \
+ case 815: \
+ case 816: \
+ case 817: \
+ case 818: \
+ case 819: \
+ case 825: \
+ case 826: \
+ case 827: \
+ case 828: \
+ case 839: \
+ case 840: \
+ case 841: \
+ case 845: \
+ case 846: \
+ case 851: \
+ case 852: \
+ case 853: \
+ case 854: \
+ return 220; \
+ case 768: \
+ case 769: \
+ case 770: \
+ case 771: \
+ case 772: \
+ case 773: \
+ case 774: \
+ case 775: \
+ case 776: \
+ case 777: \
+ case 778: \
+ case 779: \
+ case 780: \
+ case 781: \
+ case 782: \
+ case 783: \
+ case 784: \
+ case 785: \
+ case 786: \
+ case 787: \
+ case 788: \
+ case 829: \
+ case 830: \
+ case 831: \
+ case 832: \
+ case 833: \
+ case 834: \
+ case 835: \
+ case 836: \
+ case 838: \
+ case 842: \
+ case 843: \
+ case 844: \
+ case 848: \
+ case 849: \
+ case 850: \
+ case 855: \
+ case 867: \
+ case 868: \
+ case 869: \
+ case 870: \
+ case 871: \
+ case 872: \
+ case 873: \
+ case 874: \
+ case 875: \
+ case 876: \
+ case 877: \
+ case 878: \
+ case 879: \
+ return 230; \
+ case 789: \
+ case 794: \
+ return 232; \
+ case 863: \
+ case 866: \
+ return 233; \
+ case 861: \
+ case 862: \
+ case 864: \
+ case 865: \
+ return 234; \
+ case 837: \
+ return 240; \
+} \
+return 0; \
+case 4: \
+switch (ch) { \
+ case 1155: \
+ case 1156: \
+ case 1157: \
+ case 1158: \
+ return 230; \
+} \
+return 0; \
+case 5: \
+switch (ch) { \
+ case 1456: \
+ return 10; \
+ case 1457: \
+ return 11; \
+ case 1458: \
+ return 12; \
+ case 1459: \
+ return 13; \
+ case 1460: \
+ return 14; \
+ case 1461: \
+ return 15; \
+ case 1462: \
+ return 16; \
+ case 1463: \
+ return 17; \
+ case 1464: \
+ return 18; \
+ case 1465: \
+ return 19; \
+ case 1467: \
+ return 20; \
+ case 1468: \
+ return 21; \
+ case 1469: \
+ return 22; \
+ case 1471: \
+ return 23; \
+ case 1473: \
+ return 24; \
+ case 1474: \
+ return 25; \
+ case 1425: \
+ case 1430: \
+ case 1435: \
+ case 1443: \
+ case 1444: \
+ case 1445: \
+ case 1446: \
+ case 1447: \
+ case 1450: \
+ return 220; \
+ case 1434: \
+ case 1453: \
+ return 222; \
+ case 1454: \
+ return 228; \
+ case 1426: \
+ case 1427: \
+ case 1428: \
+ case 1429: \
+ case 1431: \
+ case 1432: \
+ case 1433: \
+ case 1436: \
+ case 1437: \
+ case 1438: \
+ case 1439: \
+ case 1440: \
+ case 1441: \
+ case 1448: \
+ case 1449: \
+ case 1451: \
+ case 1452: \
+ case 1455: \
+ case 1476: \
+ return 230; \
+} \
+return 0; \
+case 6: \
+switch (ch) { \
+ case 1611: \
+ return 27; \
+ case 1612: \
+ return 28; \
+ case 1613: \
+ return 29; \
+ case 1614: \
+ return 30; \
+ case 1615: \
+ return 31; \
+ case 1616: \
+ return 32; \
+ case 1617: \
+ return 33; \
+ case 1618: \
+ return 34; \
+ case 1648: \
+ return 35; \
+ case 1621: \
+ case 1622: \
+ case 1763: \
+ case 1770: \
+ case 1773: \
+ return 220; \
+ case 1552: \
+ case 1553: \
+ case 1554: \
+ case 1555: \
+ case 1556: \
+ case 1557: \
+ case 1619: \
+ case 1620: \
+ case 1623: \
+ case 1624: \
+ case 1750: \
+ case 1751: \
+ case 1752: \
+ case 1753: \
+ case 1754: \
+ case 1755: \
+ case 1756: \
+ case 1759: \
+ case 1760: \
+ case 1761: \
+ case 1762: \
+ case 1764: \
+ case 1767: \
+ case 1768: \
+ case 1771: \
+ case 1772: \
+ return 230; \
+} \
+return 0; \
+case 7: \
+switch (ch) { \
+ case 1809: \
+ return 36; \
+ case 1841: \
+ case 1844: \
+ case 1847: \
+ case 1848: \
+ case 1849: \
+ case 1851: \
+ case 1852: \
+ case 1854: \
+ case 1858: \
+ case 1860: \
+ case 1862: \
+ case 1864: \
+ return 220; \
+ case 1840: \
+ case 1842: \
+ case 1843: \
+ case 1845: \
+ case 1846: \
+ case 1850: \
+ case 1853: \
+ case 1855: \
+ case 1856: \
+ case 1857: \
+ case 1859: \
+ case 1861: \
+ case 1863: \
+ case 1865: \
+ case 1866: \
+ return 230; \
+} \
+return 0; \
+case 9: \
+switch (ch) { \
+ case 2364: \
+ case 2492: \
+ return 7; \
+ case 2381: \
+ case 2509: \
+ return 9; \
+ case 2386: \
+ return 220; \
+ case 2385: \
+ case 2387: \
+ case 2388: \
+ return 230; \
+} \
+return 0; \
+case 10: \
+switch (ch) { \
+ case 2620: \
+ case 2748: \
+ return 7; \
+ case 2637: \
+ case 2765: \
+ return 9; \
+} \
+return 0; \
+case 11: \
+switch (ch) { \
+ case 2876: \
+ return 7; \
+ case 2893: \
+ case 3021: \
+ return 9; \
+} \
+return 0; \
+case 12: \
+switch (ch) { \
+ case 3260: \
+ return 7; \
+ case 3149: \
+ case 3277: \
+ return 9; \
+ case 3157: \
+ return 84; \
+ case 3158: \
+ return 91; \
+} \
+return 0; \
+case 13: \
+switch (ch) { \
+ case 3405: \
+ case 3530: \
+ return 9; \
+} \
+return 0; \
+case 14: \
+switch (ch) { \
+ case 3642: \
+ return 9; \
+ case 3640: \
+ case 3641: \
+ return 103; \
+ case 3656: \
+ case 3657: \
+ case 3658: \
+ case 3659: \
+ return 107; \
+ case 3768: \
+ case 3769: \
+ return 118; \
+ case 3784: \
+ case 3785: \
+ case 3786: \
+ case 3787: \
+ return 122; \
+} \
+return 0; \
+case 15: \
+switch (ch) { \
+ case 3972: \
+ return 9; \
+ case 3953: \
+ return 129; \
+ case 3954: \
+ case 3962: \
+ case 3963: \
+ case 3964: \
+ case 3965: \
+ case 3968: \
+ return 130; \
+ case 3956: \
+ return 132; \
+ case 3897: \
+ return 216; \
+ case 3864: \
+ case 3865: \
+ case 3893: \
+ case 3895: \
+ case 4038: \
+ return 220; \
+ case 3970: \
+ case 3971: \
+ case 3974: \
+ case 3975: \
+ return 230; \
+} \
+return 0; \
+case 16: \
+switch (ch) { \
+ case 4151: \
+ return 7; \
+ case 4153: \
+ return 9; \
+} \
+return 0; \
+case 23: \
+switch (ch) { \
+ case 5908: \
+ case 5940: \
+ case 6098: \
+ return 9; \
+ case 6109: \
+ return 230; \
+} \
+return 0; \
+case 24: \
+switch (ch) { \
+ case 6313: \
+ return 228; \
+} \
+return 0; \
+case 25: \
+switch (ch) { \
+ case 6459: \
+ return 220; \
+ case 6457: \
+ return 222; \
+ case 6458: \
+ return 230; \
+} \
+return 0; \
+case 32: \
+switch (ch) { \
+ case 8402: \
+ case 8403: \
+ case 8408: \
+ case 8409: \
+ case 8410: \
+ case 8421: \
+ case 8422: \
+ case 8426: \
+ return 1; \
+ case 8424: \
+ return 220; \
+ case 8400: \
+ case 8401: \
+ case 8404: \
+ case 8405: \
+ case 8406: \
+ case 8407: \
+ case 8411: \
+ case 8412: \
+ case 8417: \
+ case 8423: \
+ case 8425: \
+ return 230; \
+} \
+return 0; \
+case 48: \
+switch (ch) { \
+ case 12441: \
+ case 12442: \
+ return 8; \
+ case 12330: \
+ return 218; \
+ case 12333: \
+ return 222; \
+ case 12334: \
+ case 12335: \
+ return 224; \
+ case 12331: \
+ return 228; \
+ case 12332: \
+ return 232; \
+} \
+return 0; \
+case 251: \
+switch (ch) { \
+ case 64286: \
+ return 26; \
+} \
+return 0; \
+case 254: \
+switch (ch) { \
+ case 65056: \
+ case 65057: \
+ case 65058: \
+ case 65059: \
+ return 230; \
+} \
+return 0; \
+case 465: \
+switch (ch) { \
+ case 119143: \
+ case 119144: \
+ case 119145: \
+ return 1; \
+ case 119141: \
+ case 119142: \
+ case 119150: \
+ case 119151: \
+ case 119152: \
+ case 119153: \
+ case 119154: \
+ return 216; \
+ case 119163: \
+ case 119164: \
+ case 119165: \
+ case 119166: \
+ case 119167: \
+ case 119168: \
+ case 119169: \
+ case 119170: \
+ case 119178: \
+ case 119179: \
+ return 220; \
+ case 119149: \
+ return 226; \
+ case 119173: \
+ case 119174: \
+ case 119175: \
+ case 119176: \
+ case 119177: \
+ case 119210: \
+ case 119211: \
+ case 119212: \
+ case 119213: \
+ return 230; \
+} \
+return 0; \
+} \
+return 0;
+
+#define RETURN_COMPOSITION(ch1, ch2) \
+switch ((glui32)(ch1) >> 8) { \
+case 0: \
+switch (ch1) { \
+ case 60: \
+ switch (ch2) { \
+ case 824: return 8814; \
+ } \
+ return 0; \
+ case 61: \
+ switch (ch2) { \
+ case 824: return 8800; \
+ } \
+ return 0; \
+ case 62: \
+ switch (ch2) { \
+ case 824: return 8815; \
+ } \
+ return 0; \
+ case 65: \
+ switch (ch2) { \
+ case 768: return 192; \
+ case 769: return 193; \
+ case 770: return 194; \
+ case 771: return 195; \
+ case 772: return 256; \
+ case 774: return 258; \
+ case 775: return 550; \
+ case 776: return 196; \
+ case 777: return 7842; \
+ case 778: return 197; \
+ case 780: return 461; \
+ case 783: return 512; \
+ case 785: return 514; \
+ case 803: return 7840; \
+ case 805: return 7680; \
+ case 808: return 260; \
+ } \
+ return 0; \
+ case 66: \
+ switch (ch2) { \
+ case 775: return 7682; \
+ case 803: return 7684; \
+ case 817: return 7686; \
+ } \
+ return 0; \
+ case 67: \
+ switch (ch2) { \
+ case 769: return 262; \
+ case 770: return 264; \
+ case 775: return 266; \
+ case 780: return 268; \
+ case 807: return 199; \
+ } \
+ return 0; \
+ case 68: \
+ switch (ch2) { \
+ case 775: return 7690; \
+ case 780: return 270; \
+ case 803: return 7692; \
+ case 807: return 7696; \
+ case 813: return 7698; \
+ case 817: return 7694; \
+ } \
+ return 0; \
+ case 69: \
+ switch (ch2) { \
+ case 768: return 200; \
+ case 769: return 201; \
+ case 770: return 202; \
+ case 771: return 7868; \
+ case 772: return 274; \
+ case 774: return 276; \
+ case 775: return 278; \
+ case 776: return 203; \
+ case 777: return 7866; \
+ case 780: return 282; \
+ case 783: return 516; \
+ case 785: return 518; \
+ case 803: return 7864; \
+ case 807: return 552; \
+ case 808: return 280; \
+ case 813: return 7704; \
+ case 816: return 7706; \
+ } \
+ return 0; \
+ case 70: \
+ switch (ch2) { \
+ case 775: return 7710; \
+ } \
+ return 0; \
+ case 71: \
+ switch (ch2) { \
+ case 769: return 500; \
+ case 770: return 284; \
+ case 772: return 7712; \
+ case 774: return 286; \
+ case 775: return 288; \
+ case 780: return 486; \
+ case 807: return 290; \
+ } \
+ return 0; \
+ case 72: \
+ switch (ch2) { \
+ case 770: return 292; \
+ case 775: return 7714; \
+ case 776: return 7718; \
+ case 780: return 542; \
+ case 803: return 7716; \
+ case 807: return 7720; \
+ case 814: return 7722; \
+ } \
+ return 0; \
+ case 73: \
+ switch (ch2) { \
+ case 768: return 204; \
+ case 769: return 205; \
+ case 770: return 206; \
+ case 771: return 296; \
+ case 772: return 298; \
+ case 774: return 300; \
+ case 775: return 304; \
+ case 776: return 207; \
+ case 777: return 7880; \
+ case 780: return 463; \
+ case 783: return 520; \
+ case 785: return 522; \
+ case 803: return 7882; \
+ case 808: return 302; \
+ case 816: return 7724; \
+ } \
+ return 0; \
+ case 74: \
+ switch (ch2) { \
+ case 770: return 308; \
+ } \
+ return 0; \
+ case 75: \
+ switch (ch2) { \
+ case 769: return 7728; \
+ case 780: return 488; \
+ case 803: return 7730; \
+ case 807: return 310; \
+ case 817: return 7732; \
+ } \
+ return 0; \
+ case 76: \
+ switch (ch2) { \
+ case 769: return 313; \
+ case 780: return 317; \
+ case 803: return 7734; \
+ case 807: return 315; \
+ case 813: return 7740; \
+ case 817: return 7738; \
+ } \
+ return 0; \
+ case 77: \
+ switch (ch2) { \
+ case 769: return 7742; \
+ case 775: return 7744; \
+ case 803: return 7746; \
+ } \
+ return 0; \
+ case 78: \
+ switch (ch2) { \
+ case 768: return 504; \
+ case 769: return 323; \
+ case 771: return 209; \
+ case 775: return 7748; \
+ case 780: return 327; \
+ case 803: return 7750; \
+ case 807: return 325; \
+ case 813: return 7754; \
+ case 817: return 7752; \
+ } \
+ return 0; \
+ case 79: \
+ switch (ch2) { \
+ case 768: return 210; \
+ case 769: return 211; \
+ case 770: return 212; \
+ case 771: return 213; \
+ case 772: return 332; \
+ case 774: return 334; \
+ case 775: return 558; \
+ case 776: return 214; \
+ case 777: return 7886; \
+ case 779: return 336; \
+ case 780: return 465; \
+ case 783: return 524; \
+ case 785: return 526; \
+ case 795: return 416; \
+ case 803: return 7884; \
+ case 808: return 490; \
+ } \
+ return 0; \
+ case 80: \
+ switch (ch2) { \
+ case 769: return 7764; \
+ case 775: return 7766; \
+ } \
+ return 0; \
+ case 82: \
+ switch (ch2) { \
+ case 769: return 340; \
+ case 775: return 7768; \
+ case 780: return 344; \
+ case 783: return 528; \
+ case 785: return 530; \
+ case 803: return 7770; \
+ case 807: return 342; \
+ case 817: return 7774; \
+ } \
+ return 0; \
+ case 83: \
+ switch (ch2) { \
+ case 769: return 346; \
+ case 770: return 348; \
+ case 775: return 7776; \
+ case 780: return 352; \
+ case 803: return 7778; \
+ case 806: return 536; \
+ case 807: return 350; \
+ } \
+ return 0; \
+ case 84: \
+ switch (ch2) { \
+ case 775: return 7786; \
+ case 780: return 356; \
+ case 803: return 7788; \
+ case 806: return 538; \
+ case 807: return 354; \
+ case 813: return 7792; \
+ case 817: return 7790; \
+ } \
+ return 0; \
+ case 85: \
+ switch (ch2) { \
+ case 768: return 217; \
+ case 769: return 218; \
+ case 770: return 219; \
+ case 771: return 360; \
+ case 772: return 362; \
+ case 774: return 364; \
+ case 776: return 220; \
+ case 777: return 7910; \
+ case 778: return 366; \
+ case 779: return 368; \
+ case 780: return 467; \
+ case 783: return 532; \
+ case 785: return 534; \
+ case 795: return 431; \
+ case 803: return 7908; \
+ case 804: return 7794; \
+ case 808: return 370; \
+ case 813: return 7798; \
+ case 816: return 7796; \
+ } \
+ return 0; \
+ case 86: \
+ switch (ch2) { \
+ case 771: return 7804; \
+ case 803: return 7806; \
+ } \
+ return 0; \
+ case 87: \
+ switch (ch2) { \
+ case 768: return 7808; \
+ case 769: return 7810; \
+ case 770: return 372; \
+ case 775: return 7814; \
+ case 776: return 7812; \
+ case 803: return 7816; \
+ } \
+ return 0; \
+ case 88: \
+ switch (ch2) { \
+ case 775: return 7818; \
+ case 776: return 7820; \
+ } \
+ return 0; \
+ case 89: \
+ switch (ch2) { \
+ case 768: return 7922; \
+ case 769: return 221; \
+ case 770: return 374; \
+ case 771: return 7928; \
+ case 772: return 562; \
+ case 775: return 7822; \
+ case 776: return 376; \
+ case 777: return 7926; \
+ case 803: return 7924; \
+ } \
+ return 0; \
+ case 90: \
+ switch (ch2) { \
+ case 769: return 377; \
+ case 770: return 7824; \
+ case 775: return 379; \
+ case 780: return 381; \
+ case 803: return 7826; \
+ case 817: return 7828; \
+ } \
+ return 0; \
+ case 97: \
+ switch (ch2) { \
+ case 768: return 224; \
+ case 769: return 225; \
+ case 770: return 226; \
+ case 771: return 227; \
+ case 772: return 257; \
+ case 774: return 259; \
+ case 775: return 551; \
+ case 776: return 228; \
+ case 777: return 7843; \
+ case 778: return 229; \
+ case 780: return 462; \
+ case 783: return 513; \
+ case 785: return 515; \
+ case 803: return 7841; \
+ case 805: return 7681; \
+ case 808: return 261; \
+ } \
+ return 0; \
+ case 98: \
+ switch (ch2) { \
+ case 775: return 7683; \
+ case 803: return 7685; \
+ case 817: return 7687; \
+ } \
+ return 0; \
+ case 99: \
+ switch (ch2) { \
+ case 769: return 263; \
+ case 770: return 265; \
+ case 775: return 267; \
+ case 780: return 269; \
+ case 807: return 231; \
+ } \
+ return 0; \
+ case 100: \
+ switch (ch2) { \
+ case 775: return 7691; \
+ case 780: return 271; \
+ case 803: return 7693; \
+ case 807: return 7697; \
+ case 813: return 7699; \
+ case 817: return 7695; \
+ } \
+ return 0; \
+ case 101: \
+ switch (ch2) { \
+ case 768: return 232; \
+ case 769: return 233; \
+ case 770: return 234; \
+ case 771: return 7869; \
+ case 772: return 275; \
+ case 774: return 277; \
+ case 775: return 279; \
+ case 776: return 235; \
+ case 777: return 7867; \
+ case 780: return 283; \
+ case 783: return 517; \
+ case 785: return 519; \
+ case 803: return 7865; \
+ case 807: return 553; \
+ case 808: return 281; \
+ case 813: return 7705; \
+ case 816: return 7707; \
+ } \
+ return 0; \
+ case 102: \
+ switch (ch2) { \
+ case 775: return 7711; \
+ } \
+ return 0; \
+ case 103: \
+ switch (ch2) { \
+ case 769: return 501; \
+ case 770: return 285; \
+ case 772: return 7713; \
+ case 774: return 287; \
+ case 775: return 289; \
+ case 780: return 487; \
+ case 807: return 291; \
+ } \
+ return 0; \
+ case 104: \
+ switch (ch2) { \
+ case 770: return 293; \
+ case 775: return 7715; \
+ case 776: return 7719; \
+ case 780: return 543; \
+ case 803: return 7717; \
+ case 807: return 7721; \
+ case 814: return 7723; \
+ case 817: return 7830; \
+ } \
+ return 0; \
+ case 105: \
+ switch (ch2) { \
+ case 768: return 236; \
+ case 769: return 237; \
+ case 770: return 238; \
+ case 771: return 297; \
+ case 772: return 299; \
+ case 774: return 301; \
+ case 776: return 239; \
+ case 777: return 7881; \
+ case 780: return 464; \
+ case 783: return 521; \
+ case 785: return 523; \
+ case 803: return 7883; \
+ case 808: return 303; \
+ case 816: return 7725; \
+ } \
+ return 0; \
+ case 106: \
+ switch (ch2) { \
+ case 770: return 309; \
+ case 780: return 496; \
+ } \
+ return 0; \
+ case 107: \
+ switch (ch2) { \
+ case 769: return 7729; \
+ case 780: return 489; \
+ case 803: return 7731; \
+ case 807: return 311; \
+ case 817: return 7733; \
+ } \
+ return 0; \
+ case 108: \
+ switch (ch2) { \
+ case 769: return 314; \
+ case 780: return 318; \
+ case 803: return 7735; \
+ case 807: return 316; \
+ case 813: return 7741; \
+ case 817: return 7739; \
+ } \
+ return 0; \
+ case 109: \
+ switch (ch2) { \
+ case 769: return 7743; \
+ case 775: return 7745; \
+ case 803: return 7747; \
+ } \
+ return 0; \
+ case 110: \
+ switch (ch2) { \
+ case 768: return 505; \
+ case 769: return 324; \
+ case 771: return 241; \
+ case 775: return 7749; \
+ case 780: return 328; \
+ case 803: return 7751; \
+ case 807: return 326; \
+ case 813: return 7755; \
+ case 817: return 7753; \
+ } \
+ return 0; \
+ case 111: \
+ switch (ch2) { \
+ case 768: return 242; \
+ case 769: return 243; \
+ case 770: return 244; \
+ case 771: return 245; \
+ case 772: return 333; \
+ case 774: return 335; \
+ case 775: return 559; \
+ case 776: return 246; \
+ case 777: return 7887; \
+ case 779: return 337; \
+ case 780: return 466; \
+ case 783: return 525; \
+ case 785: return 527; \
+ case 795: return 417; \
+ case 803: return 7885; \
+ case 808: return 491; \
+ } \
+ return 0; \
+ case 112: \
+ switch (ch2) { \
+ case 769: return 7765; \
+ case 775: return 7767; \
+ } \
+ return 0; \
+ case 114: \
+ switch (ch2) { \
+ case 769: return 341; \
+ case 775: return 7769; \
+ case 780: return 345; \
+ case 783: return 529; \
+ case 785: return 531; \
+ case 803: return 7771; \
+ case 807: return 343; \
+ case 817: return 7775; \
+ } \
+ return 0; \
+ case 115: \
+ switch (ch2) { \
+ case 769: return 347; \
+ case 770: return 349; \
+ case 775: return 7777; \
+ case 780: return 353; \
+ case 803: return 7779; \
+ case 806: return 537; \
+ case 807: return 351; \
+ } \
+ return 0; \
+ case 116: \
+ switch (ch2) { \
+ case 775: return 7787; \
+ case 776: return 7831; \
+ case 780: return 357; \
+ case 803: return 7789; \
+ case 806: return 539; \
+ case 807: return 355; \
+ case 813: return 7793; \
+ case 817: return 7791; \
+ } \
+ return 0; \
+ case 117: \
+ switch (ch2) { \
+ case 768: return 249; \
+ case 769: return 250; \
+ case 770: return 251; \
+ case 771: return 361; \
+ case 772: return 363; \
+ case 774: return 365; \
+ case 776: return 252; \
+ case 777: return 7911; \
+ case 778: return 367; \
+ case 779: return 369; \
+ case 780: return 468; \
+ case 783: return 533; \
+ case 785: return 535; \
+ case 795: return 432; \
+ case 803: return 7909; \
+ case 804: return 7795; \
+ case 808: return 371; \
+ case 813: return 7799; \
+ case 816: return 7797; \
+ } \
+ return 0; \
+ case 118: \
+ switch (ch2) { \
+ case 771: return 7805; \
+ case 803: return 7807; \
+ } \
+ return 0; \
+ case 119: \
+ switch (ch2) { \
+ case 768: return 7809; \
+ case 769: return 7811; \
+ case 770: return 373; \
+ case 775: return 7815; \
+ case 776: return 7813; \
+ case 778: return 7832; \
+ case 803: return 7817; \
+ } \
+ return 0; \
+ case 120: \
+ switch (ch2) { \
+ case 775: return 7819; \
+ case 776: return 7821; \
+ } \
+ return 0; \
+ case 121: \
+ switch (ch2) { \
+ case 768: return 7923; \
+ case 769: return 253; \
+ case 770: return 375; \
+ case 771: return 7929; \
+ case 772: return 563; \
+ case 775: return 7823; \
+ case 776: return 255; \
+ case 777: return 7927; \
+ case 778: return 7833; \
+ case 803: return 7925; \
+ } \
+ return 0; \
+ case 122: \
+ switch (ch2) { \
+ case 769: return 378; \
+ case 770: return 7825; \
+ case 775: return 380; \
+ case 780: return 382; \
+ case 803: return 7827; \
+ case 817: return 7829; \
+ } \
+ return 0; \
+ case 168: \
+ switch (ch2) { \
+ case 768: return 8173; \
+ case 769: return 901; \
+ case 834: return 8129; \
+ } \
+ return 0; \
+ case 194: \
+ switch (ch2) { \
+ case 768: return 7846; \
+ case 769: return 7844; \
+ case 771: return 7850; \
+ case 777: return 7848; \
+ } \
+ return 0; \
+ case 196: \
+ switch (ch2) { \
+ case 772: return 478; \
+ } \
+ return 0; \
+ case 197: \
+ switch (ch2) { \
+ case 769: return 506; \
+ } \
+ return 0; \
+ case 198: \
+ switch (ch2) { \
+ case 769: return 508; \
+ case 772: return 482; \
+ } \
+ return 0; \
+ case 199: \
+ switch (ch2) { \
+ case 769: return 7688; \
+ } \
+ return 0; \
+ case 202: \
+ switch (ch2) { \
+ case 768: return 7872; \
+ case 769: return 7870; \
+ case 771: return 7876; \
+ case 777: return 7874; \
+ } \
+ return 0; \
+ case 207: \
+ switch (ch2) { \
+ case 769: return 7726; \
+ } \
+ return 0; \
+ case 212: \
+ switch (ch2) { \
+ case 768: return 7890; \
+ case 769: return 7888; \
+ case 771: return 7894; \
+ case 777: return 7892; \
+ } \
+ return 0; \
+ case 213: \
+ switch (ch2) { \
+ case 769: return 7756; \
+ case 772: return 556; \
+ case 776: return 7758; \
+ } \
+ return 0; \
+ case 214: \
+ switch (ch2) { \
+ case 772: return 554; \
+ } \
+ return 0; \
+ case 216: \
+ switch (ch2) { \
+ case 769: return 510; \
+ } \
+ return 0; \
+ case 220: \
+ switch (ch2) { \
+ case 768: return 475; \
+ case 769: return 471; \
+ case 772: return 469; \
+ case 780: return 473; \
+ } \
+ return 0; \
+ case 226: \
+ switch (ch2) { \
+ case 768: return 7847; \
+ case 769: return 7845; \
+ case 771: return 7851; \
+ case 777: return 7849; \
+ } \
+ return 0; \
+ case 228: \
+ switch (ch2) { \
+ case 772: return 479; \
+ } \
+ return 0; \
+ case 229: \
+ switch (ch2) { \
+ case 769: return 507; \
+ } \
+ return 0; \
+ case 230: \
+ switch (ch2) { \
+ case 769: return 509; \
+ case 772: return 483; \
+ } \
+ return 0; \
+ case 231: \
+ switch (ch2) { \
+ case 769: return 7689; \
+ } \
+ return 0; \
+ case 234: \
+ switch (ch2) { \
+ case 768: return 7873; \
+ case 769: return 7871; \
+ case 771: return 7877; \
+ case 777: return 7875; \
+ } \
+ return 0; \
+ case 239: \
+ switch (ch2) { \
+ case 769: return 7727; \
+ } \
+ return 0; \
+ case 244: \
+ switch (ch2) { \
+ case 768: return 7891; \
+ case 769: return 7889; \
+ case 771: return 7895; \
+ case 777: return 7893; \
+ } \
+ return 0; \
+ case 245: \
+ switch (ch2) { \
+ case 769: return 7757; \
+ case 772: return 557; \
+ case 776: return 7759; \
+ } \
+ return 0; \
+ case 246: \
+ switch (ch2) { \
+ case 772: return 555; \
+ } \
+ return 0; \
+ case 248: \
+ switch (ch2) { \
+ case 769: return 511; \
+ } \
+ return 0; \
+ case 252: \
+ switch (ch2) { \
+ case 768: return 476; \
+ case 769: return 472; \
+ case 772: return 470; \
+ case 780: return 474; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 1: \
+switch (ch1) { \
+ case 258: \
+ switch (ch2) { \
+ case 768: return 7856; \
+ case 769: return 7854; \
+ case 771: return 7860; \
+ case 777: return 7858; \
+ } \
+ return 0; \
+ case 259: \
+ switch (ch2) { \
+ case 768: return 7857; \
+ case 769: return 7855; \
+ case 771: return 7861; \
+ case 777: return 7859; \
+ } \
+ return 0; \
+ case 274: \
+ switch (ch2) { \
+ case 768: return 7700; \
+ case 769: return 7702; \
+ } \
+ return 0; \
+ case 275: \
+ switch (ch2) { \
+ case 768: return 7701; \
+ case 769: return 7703; \
+ } \
+ return 0; \
+ case 332: \
+ switch (ch2) { \
+ case 768: return 7760; \
+ case 769: return 7762; \
+ } \
+ return 0; \
+ case 333: \
+ switch (ch2) { \
+ case 768: return 7761; \
+ case 769: return 7763; \
+ } \
+ return 0; \
+ case 346: \
+ switch (ch2) { \
+ case 775: return 7780; \
+ } \
+ return 0; \
+ case 347: \
+ switch (ch2) { \
+ case 775: return 7781; \
+ } \
+ return 0; \
+ case 352: \
+ switch (ch2) { \
+ case 775: return 7782; \
+ } \
+ return 0; \
+ case 353: \
+ switch (ch2) { \
+ case 775: return 7783; \
+ } \
+ return 0; \
+ case 360: \
+ switch (ch2) { \
+ case 769: return 7800; \
+ } \
+ return 0; \
+ case 361: \
+ switch (ch2) { \
+ case 769: return 7801; \
+ } \
+ return 0; \
+ case 362: \
+ switch (ch2) { \
+ case 776: return 7802; \
+ } \
+ return 0; \
+ case 363: \
+ switch (ch2) { \
+ case 776: return 7803; \
+ } \
+ return 0; \
+ case 383: \
+ switch (ch2) { \
+ case 775: return 7835; \
+ } \
+ return 0; \
+ case 416: \
+ switch (ch2) { \
+ case 768: return 7900; \
+ case 769: return 7898; \
+ case 771: return 7904; \
+ case 777: return 7902; \
+ case 803: return 7906; \
+ } \
+ return 0; \
+ case 417: \
+ switch (ch2) { \
+ case 768: return 7901; \
+ case 769: return 7899; \
+ case 771: return 7905; \
+ case 777: return 7903; \
+ case 803: return 7907; \
+ } \
+ return 0; \
+ case 431: \
+ switch (ch2) { \
+ case 768: return 7914; \
+ case 769: return 7912; \
+ case 771: return 7918; \
+ case 777: return 7916; \
+ case 803: return 7920; \
+ } \
+ return 0; \
+ case 432: \
+ switch (ch2) { \
+ case 768: return 7915; \
+ case 769: return 7913; \
+ case 771: return 7919; \
+ case 777: return 7917; \
+ case 803: return 7921; \
+ } \
+ return 0; \
+ case 439: \
+ switch (ch2) { \
+ case 780: return 494; \
+ } \
+ return 0; \
+ case 490: \
+ switch (ch2) { \
+ case 772: return 492; \
+ } \
+ return 0; \
+ case 491: \
+ switch (ch2) { \
+ case 772: return 493; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 2: \
+switch (ch1) { \
+ case 550: \
+ switch (ch2) { \
+ case 772: return 480; \
+ } \
+ return 0; \
+ case 551: \
+ switch (ch2) { \
+ case 772: return 481; \
+ } \
+ return 0; \
+ case 552: \
+ switch (ch2) { \
+ case 774: return 7708; \
+ } \
+ return 0; \
+ case 553: \
+ switch (ch2) { \
+ case 774: return 7709; \
+ } \
+ return 0; \
+ case 558: \
+ switch (ch2) { \
+ case 772: return 560; \
+ } \
+ return 0; \
+ case 559: \
+ switch (ch2) { \
+ case 772: return 561; \
+ } \
+ return 0; \
+ case 658: \
+ switch (ch2) { \
+ case 780: return 495; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 3: \
+switch (ch1) { \
+ case 776: \
+ switch (ch2) { \
+ case 769: return 836; \
+ } \
+ return 0; \
+ case 913: \
+ switch (ch2) { \
+ case 768: return 8122; \
+ case 769: return 902; \
+ case 772: return 8121; \
+ case 774: return 8120; \
+ case 787: return 7944; \
+ case 788: return 7945; \
+ case 837: return 8124; \
+ } \
+ return 0; \
+ case 917: \
+ switch (ch2) { \
+ case 768: return 8136; \
+ case 769: return 904; \
+ case 787: return 7960; \
+ case 788: return 7961; \
+ } \
+ return 0; \
+ case 919: \
+ switch (ch2) { \
+ case 768: return 8138; \
+ case 769: return 905; \
+ case 787: return 7976; \
+ case 788: return 7977; \
+ case 837: return 8140; \
+ } \
+ return 0; \
+ case 921: \
+ switch (ch2) { \
+ case 768: return 8154; \
+ case 769: return 906; \
+ case 772: return 8153; \
+ case 774: return 8152; \
+ case 776: return 938; \
+ case 787: return 7992; \
+ case 788: return 7993; \
+ } \
+ return 0; \
+ case 927: \
+ switch (ch2) { \
+ case 768: return 8184; \
+ case 769: return 908; \
+ case 787: return 8008; \
+ case 788: return 8009; \
+ } \
+ return 0; \
+ case 929: \
+ switch (ch2) { \
+ case 788: return 8172; \
+ } \
+ return 0; \
+ case 933: \
+ switch (ch2) { \
+ case 768: return 8170; \
+ case 769: return 910; \
+ case 772: return 8169; \
+ case 774: return 8168; \
+ case 776: return 939; \
+ case 788: return 8025; \
+ } \
+ return 0; \
+ case 937: \
+ switch (ch2) { \
+ case 768: return 8186; \
+ case 769: return 911; \
+ case 787: return 8040; \
+ case 788: return 8041; \
+ case 837: return 8188; \
+ } \
+ return 0; \
+ case 940: \
+ switch (ch2) { \
+ case 837: return 8116; \
+ } \
+ return 0; \
+ case 942: \
+ switch (ch2) { \
+ case 837: return 8132; \
+ } \
+ return 0; \
+ case 945: \
+ switch (ch2) { \
+ case 768: return 8048; \
+ case 769: return 940; \
+ case 772: return 8113; \
+ case 774: return 8112; \
+ case 787: return 7936; \
+ case 788: return 7937; \
+ case 834: return 8118; \
+ case 837: return 8115; \
+ } \
+ return 0; \
+ case 949: \
+ switch (ch2) { \
+ case 768: return 8050; \
+ case 769: return 941; \
+ case 787: return 7952; \
+ case 788: return 7953; \
+ } \
+ return 0; \
+ case 951: \
+ switch (ch2) { \
+ case 768: return 8052; \
+ case 769: return 942; \
+ case 787: return 7968; \
+ case 788: return 7969; \
+ case 834: return 8134; \
+ case 837: return 8131; \
+ } \
+ return 0; \
+ case 953: \
+ switch (ch2) { \
+ case 768: return 8054; \
+ case 769: return 943; \
+ case 772: return 8145; \
+ case 774: return 8144; \
+ case 776: return 970; \
+ case 787: return 7984; \
+ case 788: return 7985; \
+ case 834: return 8150; \
+ } \
+ return 0; \
+ case 959: \
+ switch (ch2) { \
+ case 768: return 8056; \
+ case 769: return 972; \
+ case 787: return 8000; \
+ case 788: return 8001; \
+ } \
+ return 0; \
+ case 961: \
+ switch (ch2) { \
+ case 787: return 8164; \
+ case 788: return 8165; \
+ } \
+ return 0; \
+ case 965: \
+ switch (ch2) { \
+ case 768: return 8058; \
+ case 769: return 973; \
+ case 772: return 8161; \
+ case 774: return 8160; \
+ case 776: return 971; \
+ case 787: return 8016; \
+ case 788: return 8017; \
+ case 834: return 8166; \
+ } \
+ return 0; \
+ case 969: \
+ switch (ch2) { \
+ case 768: return 8060; \
+ case 769: return 974; \
+ case 787: return 8032; \
+ case 788: return 8033; \
+ case 834: return 8182; \
+ case 837: return 8179; \
+ } \
+ return 0; \
+ case 970: \
+ switch (ch2) { \
+ case 768: return 8146; \
+ case 769: return 912; \
+ case 834: return 8151; \
+ } \
+ return 0; \
+ case 971: \
+ switch (ch2) { \
+ case 768: return 8162; \
+ case 769: return 944; \
+ case 834: return 8167; \
+ } \
+ return 0; \
+ case 974: \
+ switch (ch2) { \
+ case 837: return 8180; \
+ } \
+ return 0; \
+ case 978: \
+ switch (ch2) { \
+ case 769: return 979; \
+ case 776: return 980; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 4: \
+switch (ch1) { \
+ case 1030: \
+ switch (ch2) { \
+ case 776: return 1031; \
+ } \
+ return 0; \
+ case 1040: \
+ switch (ch2) { \
+ case 774: return 1232; \
+ case 776: return 1234; \
+ } \
+ return 0; \
+ case 1043: \
+ switch (ch2) { \
+ case 769: return 1027; \
+ } \
+ return 0; \
+ case 1045: \
+ switch (ch2) { \
+ case 768: return 1024; \
+ case 774: return 1238; \
+ case 776: return 1025; \
+ } \
+ return 0; \
+ case 1046: \
+ switch (ch2) { \
+ case 774: return 1217; \
+ case 776: return 1244; \
+ } \
+ return 0; \
+ case 1047: \
+ switch (ch2) { \
+ case 776: return 1246; \
+ } \
+ return 0; \
+ case 1048: \
+ switch (ch2) { \
+ case 768: return 1037; \
+ case 772: return 1250; \
+ case 774: return 1049; \
+ case 776: return 1252; \
+ } \
+ return 0; \
+ case 1050: \
+ switch (ch2) { \
+ case 769: return 1036; \
+ } \
+ return 0; \
+ case 1054: \
+ switch (ch2) { \
+ case 776: return 1254; \
+ } \
+ return 0; \
+ case 1059: \
+ switch (ch2) { \
+ case 772: return 1262; \
+ case 774: return 1038; \
+ case 776: return 1264; \
+ case 779: return 1266; \
+ } \
+ return 0; \
+ case 1063: \
+ switch (ch2) { \
+ case 776: return 1268; \
+ } \
+ return 0; \
+ case 1067: \
+ switch (ch2) { \
+ case 776: return 1272; \
+ } \
+ return 0; \
+ case 1069: \
+ switch (ch2) { \
+ case 776: return 1260; \
+ } \
+ return 0; \
+ case 1072: \
+ switch (ch2) { \
+ case 774: return 1233; \
+ case 776: return 1235; \
+ } \
+ return 0; \
+ case 1075: \
+ switch (ch2) { \
+ case 769: return 1107; \
+ } \
+ return 0; \
+ case 1077: \
+ switch (ch2) { \
+ case 768: return 1104; \
+ case 774: return 1239; \
+ case 776: return 1105; \
+ } \
+ return 0; \
+ case 1078: \
+ switch (ch2) { \
+ case 774: return 1218; \
+ case 776: return 1245; \
+ } \
+ return 0; \
+ case 1079: \
+ switch (ch2) { \
+ case 776: return 1247; \
+ } \
+ return 0; \
+ case 1080: \
+ switch (ch2) { \
+ case 768: return 1117; \
+ case 772: return 1251; \
+ case 774: return 1081; \
+ case 776: return 1253; \
+ } \
+ return 0; \
+ case 1082: \
+ switch (ch2) { \
+ case 769: return 1116; \
+ } \
+ return 0; \
+ case 1086: \
+ switch (ch2) { \
+ case 776: return 1255; \
+ } \
+ return 0; \
+ case 1091: \
+ switch (ch2) { \
+ case 772: return 1263; \
+ case 774: return 1118; \
+ case 776: return 1265; \
+ case 779: return 1267; \
+ } \
+ return 0; \
+ case 1095: \
+ switch (ch2) { \
+ case 776: return 1269; \
+ } \
+ return 0; \
+ case 1099: \
+ switch (ch2) { \
+ case 776: return 1273; \
+ } \
+ return 0; \
+ case 1101: \
+ switch (ch2) { \
+ case 776: return 1261; \
+ } \
+ return 0; \
+ case 1110: \
+ switch (ch2) { \
+ case 776: return 1111; \
+ } \
+ return 0; \
+ case 1140: \
+ switch (ch2) { \
+ case 783: return 1142; \
+ } \
+ return 0; \
+ case 1141: \
+ switch (ch2) { \
+ case 783: return 1143; \
+ } \
+ return 0; \
+ case 1240: \
+ switch (ch2) { \
+ case 776: return 1242; \
+ } \
+ return 0; \
+ case 1241: \
+ switch (ch2) { \
+ case 776: return 1243; \
+ } \
+ return 0; \
+ case 1256: \
+ switch (ch2) { \
+ case 776: return 1258; \
+ } \
+ return 0; \
+ case 1257: \
+ switch (ch2) { \
+ case 776: return 1259; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 5: \
+switch (ch1) { \
+ case 1488: \
+ switch (ch2) { \
+ case 1463: return 64302; \
+ case 1464: return 64303; \
+ case 1468: return 64304; \
+ } \
+ return 0; \
+ case 1489: \
+ switch (ch2) { \
+ case 1468: return 64305; \
+ case 1471: return 64332; \
+ } \
+ return 0; \
+ case 1490: \
+ switch (ch2) { \
+ case 1468: return 64306; \
+ } \
+ return 0; \
+ case 1491: \
+ switch (ch2) { \
+ case 1468: return 64307; \
+ } \
+ return 0; \
+ case 1492: \
+ switch (ch2) { \
+ case 1468: return 64308; \
+ } \
+ return 0; \
+ case 1493: \
+ switch (ch2) { \
+ case 1465: return 64331; \
+ case 1468: return 64309; \
+ } \
+ return 0; \
+ case 1494: \
+ switch (ch2) { \
+ case 1468: return 64310; \
+ } \
+ return 0; \
+ case 1496: \
+ switch (ch2) { \
+ case 1468: return 64312; \
+ } \
+ return 0; \
+ case 1497: \
+ switch (ch2) { \
+ case 1460: return 64285; \
+ case 1468: return 64313; \
+ } \
+ return 0; \
+ case 1498: \
+ switch (ch2) { \
+ case 1468: return 64314; \
+ } \
+ return 0; \
+ case 1499: \
+ switch (ch2) { \
+ case 1468: return 64315; \
+ case 1471: return 64333; \
+ } \
+ return 0; \
+ case 1500: \
+ switch (ch2) { \
+ case 1468: return 64316; \
+ } \
+ return 0; \
+ case 1502: \
+ switch (ch2) { \
+ case 1468: return 64318; \
+ } \
+ return 0; \
+ case 1504: \
+ switch (ch2) { \
+ case 1468: return 64320; \
+ } \
+ return 0; \
+ case 1505: \
+ switch (ch2) { \
+ case 1468: return 64321; \
+ } \
+ return 0; \
+ case 1507: \
+ switch (ch2) { \
+ case 1468: return 64323; \
+ } \
+ return 0; \
+ case 1508: \
+ switch (ch2) { \
+ case 1468: return 64324; \
+ case 1471: return 64334; \
+ } \
+ return 0; \
+ case 1510: \
+ switch (ch2) { \
+ case 1468: return 64326; \
+ } \
+ return 0; \
+ case 1511: \
+ switch (ch2) { \
+ case 1468: return 64327; \
+ } \
+ return 0; \
+ case 1512: \
+ switch (ch2) { \
+ case 1468: return 64328; \
+ } \
+ return 0; \
+ case 1513: \
+ switch (ch2) { \
+ case 1468: return 64329; \
+ case 1473: return 64298; \
+ case 1474: return 64299; \
+ } \
+ return 0; \
+ case 1514: \
+ switch (ch2) { \
+ case 1468: return 64330; \
+ } \
+ return 0; \
+ case 1522: \
+ switch (ch2) { \
+ case 1463: return 64287; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 6: \
+switch (ch1) { \
+ case 1575: \
+ switch (ch2) { \
+ case 1619: return 1570; \
+ case 1620: return 1571; \
+ case 1621: return 1573; \
+ } \
+ return 0; \
+ case 1608: \
+ switch (ch2) { \
+ case 1620: return 1572; \
+ } \
+ return 0; \
+ case 1610: \
+ switch (ch2) { \
+ case 1620: return 1574; \
+ } \
+ return 0; \
+ case 1729: \
+ switch (ch2) { \
+ case 1620: return 1730; \
+ } \
+ return 0; \
+ case 1746: \
+ switch (ch2) { \
+ case 1620: return 1747; \
+ } \
+ return 0; \
+ case 1749: \
+ switch (ch2) { \
+ case 1620: return 1728; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 9: \
+switch (ch1) { \
+ case 2325: \
+ switch (ch2) { \
+ case 2364: return 2392; \
+ } \
+ return 0; \
+ case 2326: \
+ switch (ch2) { \
+ case 2364: return 2393; \
+ } \
+ return 0; \
+ case 2327: \
+ switch (ch2) { \
+ case 2364: return 2394; \
+ } \
+ return 0; \
+ case 2332: \
+ switch (ch2) { \
+ case 2364: return 2395; \
+ } \
+ return 0; \
+ case 2337: \
+ switch (ch2) { \
+ case 2364: return 2396; \
+ } \
+ return 0; \
+ case 2338: \
+ switch (ch2) { \
+ case 2364: return 2397; \
+ } \
+ return 0; \
+ case 2344: \
+ switch (ch2) { \
+ case 2364: return 2345; \
+ } \
+ return 0; \
+ case 2347: \
+ switch (ch2) { \
+ case 2364: return 2398; \
+ } \
+ return 0; \
+ case 2351: \
+ switch (ch2) { \
+ case 2364: return 2399; \
+ } \
+ return 0; \
+ case 2352: \
+ switch (ch2) { \
+ case 2364: return 2353; \
+ } \
+ return 0; \
+ case 2355: \
+ switch (ch2) { \
+ case 2364: return 2356; \
+ } \
+ return 0; \
+ case 2465: \
+ switch (ch2) { \
+ case 2492: return 2524; \
+ } \
+ return 0; \
+ case 2466: \
+ switch (ch2) { \
+ case 2492: return 2525; \
+ } \
+ return 0; \
+ case 2479: \
+ switch (ch2) { \
+ case 2492: return 2527; \
+ } \
+ return 0; \
+ case 2503: \
+ switch (ch2) { \
+ case 2494: return 2507; \
+ case 2519: return 2508; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 10: \
+switch (ch1) { \
+ case 2582: \
+ switch (ch2) { \
+ case 2620: return 2649; \
+ } \
+ return 0; \
+ case 2583: \
+ switch (ch2) { \
+ case 2620: return 2650; \
+ } \
+ return 0; \
+ case 2588: \
+ switch (ch2) { \
+ case 2620: return 2651; \
+ } \
+ return 0; \
+ case 2603: \
+ switch (ch2) { \
+ case 2620: return 2654; \
+ } \
+ return 0; \
+ case 2610: \
+ switch (ch2) { \
+ case 2620: return 2611; \
+ } \
+ return 0; \
+ case 2616: \
+ switch (ch2) { \
+ case 2620: return 2614; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 11: \
+switch (ch1) { \
+ case 2849: \
+ switch (ch2) { \
+ case 2876: return 2908; \
+ } \
+ return 0; \
+ case 2850: \
+ switch (ch2) { \
+ case 2876: return 2909; \
+ } \
+ return 0; \
+ case 2887: \
+ switch (ch2) { \
+ case 2878: return 2891; \
+ case 2902: return 2888; \
+ case 2903: return 2892; \
+ } \
+ return 0; \
+ case 2962: \
+ switch (ch2) { \
+ case 3031: return 2964; \
+ } \
+ return 0; \
+ case 3014: \
+ switch (ch2) { \
+ case 3006: return 3018; \
+ case 3031: return 3020; \
+ } \
+ return 0; \
+ case 3015: \
+ switch (ch2) { \
+ case 3006: return 3019; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 12: \
+switch (ch1) { \
+ case 3142: \
+ switch (ch2) { \
+ case 3158: return 3144; \
+ } \
+ return 0; \
+ case 3263: \
+ switch (ch2) { \
+ case 3285: return 3264; \
+ } \
+ return 0; \
+ case 3270: \
+ switch (ch2) { \
+ case 3266: return 3274; \
+ case 3285: return 3271; \
+ case 3286: return 3272; \
+ } \
+ return 0; \
+ case 3274: \
+ switch (ch2) { \
+ case 3285: return 3275; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 13: \
+switch (ch1) { \
+ case 3398: \
+ switch (ch2) { \
+ case 3390: return 3402; \
+ case 3415: return 3404; \
+ } \
+ return 0; \
+ case 3399: \
+ switch (ch2) { \
+ case 3390: return 3403; \
+ } \
+ return 0; \
+ case 3545: \
+ switch (ch2) { \
+ case 3530: return 3546; \
+ case 3535: return 3548; \
+ case 3551: return 3550; \
+ } \
+ return 0; \
+ case 3548: \
+ switch (ch2) { \
+ case 3530: return 3549; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 15: \
+switch (ch1) { \
+ case 3904: \
+ switch (ch2) { \
+ case 4021: return 3945; \
+ } \
+ return 0; \
+ case 3906: \
+ switch (ch2) { \
+ case 4023: return 3907; \
+ } \
+ return 0; \
+ case 3916: \
+ switch (ch2) { \
+ case 4023: return 3917; \
+ } \
+ return 0; \
+ case 3921: \
+ switch (ch2) { \
+ case 4023: return 3922; \
+ } \
+ return 0; \
+ case 3926: \
+ switch (ch2) { \
+ case 4023: return 3927; \
+ } \
+ return 0; \
+ case 3931: \
+ switch (ch2) { \
+ case 4023: return 3932; \
+ } \
+ return 0; \
+ case 3953: \
+ switch (ch2) { \
+ case 3954: return 3955; \
+ case 3956: return 3957; \
+ case 3968: return 3969; \
+ } \
+ return 0; \
+ case 3984: \
+ switch (ch2) { \
+ case 4021: return 4025; \
+ } \
+ return 0; \
+ case 3986: \
+ switch (ch2) { \
+ case 4023: return 3987; \
+ } \
+ return 0; \
+ case 3996: \
+ switch (ch2) { \
+ case 4023: return 3997; \
+ } \
+ return 0; \
+ case 4001: \
+ switch (ch2) { \
+ case 4023: return 4002; \
+ } \
+ return 0; \
+ case 4006: \
+ switch (ch2) { \
+ case 4023: return 4007; \
+ } \
+ return 0; \
+ case 4011: \
+ switch (ch2) { \
+ case 4023: return 4012; \
+ } \
+ return 0; \
+ case 4018: \
+ switch (ch2) { \
+ case 3968: return 3958; \
+ } \
+ return 0; \
+ case 4019: \
+ switch (ch2) { \
+ case 3968: return 3960; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 16: \
+switch (ch1) { \
+ case 4133: \
+ switch (ch2) { \
+ case 4142: return 4134; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 30: \
+switch (ch1) { \
+ case 7734: \
+ switch (ch2) { \
+ case 772: return 7736; \
+ } \
+ return 0; \
+ case 7735: \
+ switch (ch2) { \
+ case 772: return 7737; \
+ } \
+ return 0; \
+ case 7770: \
+ switch (ch2) { \
+ case 772: return 7772; \
+ } \
+ return 0; \
+ case 7771: \
+ switch (ch2) { \
+ case 772: return 7773; \
+ } \
+ return 0; \
+ case 7778: \
+ switch (ch2) { \
+ case 775: return 7784; \
+ } \
+ return 0; \
+ case 7779: \
+ switch (ch2) { \
+ case 775: return 7785; \
+ } \
+ return 0; \
+ case 7840: \
+ switch (ch2) { \
+ case 770: return 7852; \
+ case 774: return 7862; \
+ } \
+ return 0; \
+ case 7841: \
+ switch (ch2) { \
+ case 770: return 7853; \
+ case 774: return 7863; \
+ } \
+ return 0; \
+ case 7864: \
+ switch (ch2) { \
+ case 770: return 7878; \
+ } \
+ return 0; \
+ case 7865: \
+ switch (ch2) { \
+ case 770: return 7879; \
+ } \
+ return 0; \
+ case 7884: \
+ switch (ch2) { \
+ case 770: return 7896; \
+ } \
+ return 0; \
+ case 7885: \
+ switch (ch2) { \
+ case 770: return 7897; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 31: \
+switch (ch1) { \
+ case 7936: \
+ switch (ch2) { \
+ case 768: return 7938; \
+ case 769: return 7940; \
+ case 834: return 7942; \
+ case 837: return 8064; \
+ } \
+ return 0; \
+ case 7937: \
+ switch (ch2) { \
+ case 768: return 7939; \
+ case 769: return 7941; \
+ case 834: return 7943; \
+ case 837: return 8065; \
+ } \
+ return 0; \
+ case 7938: \
+ switch (ch2) { \
+ case 837: return 8066; \
+ } \
+ return 0; \
+ case 7939: \
+ switch (ch2) { \
+ case 837: return 8067; \
+ } \
+ return 0; \
+ case 7940: \
+ switch (ch2) { \
+ case 837: return 8068; \
+ } \
+ return 0; \
+ case 7941: \
+ switch (ch2) { \
+ case 837: return 8069; \
+ } \
+ return 0; \
+ case 7942: \
+ switch (ch2) { \
+ case 837: return 8070; \
+ } \
+ return 0; \
+ case 7943: \
+ switch (ch2) { \
+ case 837: return 8071; \
+ } \
+ return 0; \
+ case 7944: \
+ switch (ch2) { \
+ case 768: return 7946; \
+ case 769: return 7948; \
+ case 834: return 7950; \
+ case 837: return 8072; \
+ } \
+ return 0; \
+ case 7945: \
+ switch (ch2) { \
+ case 768: return 7947; \
+ case 769: return 7949; \
+ case 834: return 7951; \
+ case 837: return 8073; \
+ } \
+ return 0; \
+ case 7946: \
+ switch (ch2) { \
+ case 837: return 8074; \
+ } \
+ return 0; \
+ case 7947: \
+ switch (ch2) { \
+ case 837: return 8075; \
+ } \
+ return 0; \
+ case 7948: \
+ switch (ch2) { \
+ case 837: return 8076; \
+ } \
+ return 0; \
+ case 7949: \
+ switch (ch2) { \
+ case 837: return 8077; \
+ } \
+ return 0; \
+ case 7950: \
+ switch (ch2) { \
+ case 837: return 8078; \
+ } \
+ return 0; \
+ case 7951: \
+ switch (ch2) { \
+ case 837: return 8079; \
+ } \
+ return 0; \
+ case 7952: \
+ switch (ch2) { \
+ case 768: return 7954; \
+ case 769: return 7956; \
+ } \
+ return 0; \
+ case 7953: \
+ switch (ch2) { \
+ case 768: return 7955; \
+ case 769: return 7957; \
+ } \
+ return 0; \
+ case 7960: \
+ switch (ch2) { \
+ case 768: return 7962; \
+ case 769: return 7964; \
+ } \
+ return 0; \
+ case 7961: \
+ switch (ch2) { \
+ case 768: return 7963; \
+ case 769: return 7965; \
+ } \
+ return 0; \
+ case 7968: \
+ switch (ch2) { \
+ case 768: return 7970; \
+ case 769: return 7972; \
+ case 834: return 7974; \
+ case 837: return 8080; \
+ } \
+ return 0; \
+ case 7969: \
+ switch (ch2) { \
+ case 768: return 7971; \
+ case 769: return 7973; \
+ case 834: return 7975; \
+ case 837: return 8081; \
+ } \
+ return 0; \
+ case 7970: \
+ switch (ch2) { \
+ case 837: return 8082; \
+ } \
+ return 0; \
+ case 7971: \
+ switch (ch2) { \
+ case 837: return 8083; \
+ } \
+ return 0; \
+ case 7972: \
+ switch (ch2) { \
+ case 837: return 8084; \
+ } \
+ return 0; \
+ case 7973: \
+ switch (ch2) { \
+ case 837: return 8085; \
+ } \
+ return 0; \
+ case 7974: \
+ switch (ch2) { \
+ case 837: return 8086; \
+ } \
+ return 0; \
+ case 7975: \
+ switch (ch2) { \
+ case 837: return 8087; \
+ } \
+ return 0; \
+ case 7976: \
+ switch (ch2) { \
+ case 768: return 7978; \
+ case 769: return 7980; \
+ case 834: return 7982; \
+ case 837: return 8088; \
+ } \
+ return 0; \
+ case 7977: \
+ switch (ch2) { \
+ case 768: return 7979; \
+ case 769: return 7981; \
+ case 834: return 7983; \
+ case 837: return 8089; \
+ } \
+ return 0; \
+ case 7978: \
+ switch (ch2) { \
+ case 837: return 8090; \
+ } \
+ return 0; \
+ case 7979: \
+ switch (ch2) { \
+ case 837: return 8091; \
+ } \
+ return 0; \
+ case 7980: \
+ switch (ch2) { \
+ case 837: return 8092; \
+ } \
+ return 0; \
+ case 7981: \
+ switch (ch2) { \
+ case 837: return 8093; \
+ } \
+ return 0; \
+ case 7982: \
+ switch (ch2) { \
+ case 837: return 8094; \
+ } \
+ return 0; \
+ case 7983: \
+ switch (ch2) { \
+ case 837: return 8095; \
+ } \
+ return 0; \
+ case 7984: \
+ switch (ch2) { \
+ case 768: return 7986; \
+ case 769: return 7988; \
+ case 834: return 7990; \
+ } \
+ return 0; \
+ case 7985: \
+ switch (ch2) { \
+ case 768: return 7987; \
+ case 769: return 7989; \
+ case 834: return 7991; \
+ } \
+ return 0; \
+ case 7992: \
+ switch (ch2) { \
+ case 768: return 7994; \
+ case 769: return 7996; \
+ case 834: return 7998; \
+ } \
+ return 0; \
+ case 7993: \
+ switch (ch2) { \
+ case 768: return 7995; \
+ case 769: return 7997; \
+ case 834: return 7999; \
+ } \
+ return 0; \
+ case 8000: \
+ switch (ch2) { \
+ case 768: return 8002; \
+ case 769: return 8004; \
+ } \
+ return 0; \
+ case 8001: \
+ switch (ch2) { \
+ case 768: return 8003; \
+ case 769: return 8005; \
+ } \
+ return 0; \
+ case 8008: \
+ switch (ch2) { \
+ case 768: return 8010; \
+ case 769: return 8012; \
+ } \
+ return 0; \
+ case 8009: \
+ switch (ch2) { \
+ case 768: return 8011; \
+ case 769: return 8013; \
+ } \
+ return 0; \
+ case 8016: \
+ switch (ch2) { \
+ case 768: return 8018; \
+ case 769: return 8020; \
+ case 834: return 8022; \
+ } \
+ return 0; \
+ case 8017: \
+ switch (ch2) { \
+ case 768: return 8019; \
+ case 769: return 8021; \
+ case 834: return 8023; \
+ } \
+ return 0; \
+ case 8025: \
+ switch (ch2) { \
+ case 768: return 8027; \
+ case 769: return 8029; \
+ case 834: return 8031; \
+ } \
+ return 0; \
+ case 8032: \
+ switch (ch2) { \
+ case 768: return 8034; \
+ case 769: return 8036; \
+ case 834: return 8038; \
+ case 837: return 8096; \
+ } \
+ return 0; \
+ case 8033: \
+ switch (ch2) { \
+ case 768: return 8035; \
+ case 769: return 8037; \
+ case 834: return 8039; \
+ case 837: return 8097; \
+ } \
+ return 0; \
+ case 8034: \
+ switch (ch2) { \
+ case 837: return 8098; \
+ } \
+ return 0; \
+ case 8035: \
+ switch (ch2) { \
+ case 837: return 8099; \
+ } \
+ return 0; \
+ case 8036: \
+ switch (ch2) { \
+ case 837: return 8100; \
+ } \
+ return 0; \
+ case 8037: \
+ switch (ch2) { \
+ case 837: return 8101; \
+ } \
+ return 0; \
+ case 8038: \
+ switch (ch2) { \
+ case 837: return 8102; \
+ } \
+ return 0; \
+ case 8039: \
+ switch (ch2) { \
+ case 837: return 8103; \
+ } \
+ return 0; \
+ case 8040: \
+ switch (ch2) { \
+ case 768: return 8042; \
+ case 769: return 8044; \
+ case 834: return 8046; \
+ case 837: return 8104; \
+ } \
+ return 0; \
+ case 8041: \
+ switch (ch2) { \
+ case 768: return 8043; \
+ case 769: return 8045; \
+ case 834: return 8047; \
+ case 837: return 8105; \
+ } \
+ return 0; \
+ case 8042: \
+ switch (ch2) { \
+ case 837: return 8106; \
+ } \
+ return 0; \
+ case 8043: \
+ switch (ch2) { \
+ case 837: return 8107; \
+ } \
+ return 0; \
+ case 8044: \
+ switch (ch2) { \
+ case 837: return 8108; \
+ } \
+ return 0; \
+ case 8045: \
+ switch (ch2) { \
+ case 837: return 8109; \
+ } \
+ return 0; \
+ case 8046: \
+ switch (ch2) { \
+ case 837: return 8110; \
+ } \
+ return 0; \
+ case 8047: \
+ switch (ch2) { \
+ case 837: return 8111; \
+ } \
+ return 0; \
+ case 8048: \
+ switch (ch2) { \
+ case 837: return 8114; \
+ } \
+ return 0; \
+ case 8052: \
+ switch (ch2) { \
+ case 837: return 8130; \
+ } \
+ return 0; \
+ case 8060: \
+ switch (ch2) { \
+ case 837: return 8178; \
+ } \
+ return 0; \
+ case 8118: \
+ switch (ch2) { \
+ case 837: return 8119; \
+ } \
+ return 0; \
+ case 8127: \
+ switch (ch2) { \
+ case 768: return 8141; \
+ case 769: return 8142; \
+ case 834: return 8143; \
+ } \
+ return 0; \
+ case 8134: \
+ switch (ch2) { \
+ case 837: return 8135; \
+ } \
+ return 0; \
+ case 8182: \
+ switch (ch2) { \
+ case 837: return 8183; \
+ } \
+ return 0; \
+ case 8190: \
+ switch (ch2) { \
+ case 768: return 8157; \
+ case 769: return 8158; \
+ case 834: return 8159; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 33: \
+switch (ch1) { \
+ case 8592: \
+ switch (ch2) { \
+ case 824: return 8602; \
+ } \
+ return 0; \
+ case 8594: \
+ switch (ch2) { \
+ case 824: return 8603; \
+ } \
+ return 0; \
+ case 8596: \
+ switch (ch2) { \
+ case 824: return 8622; \
+ } \
+ return 0; \
+ case 8656: \
+ switch (ch2) { \
+ case 824: return 8653; \
+ } \
+ return 0; \
+ case 8658: \
+ switch (ch2) { \
+ case 824: return 8655; \
+ } \
+ return 0; \
+ case 8660: \
+ switch (ch2) { \
+ case 824: return 8654; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 34: \
+switch (ch1) { \
+ case 8707: \
+ switch (ch2) { \
+ case 824: return 8708; \
+ } \
+ return 0; \
+ case 8712: \
+ switch (ch2) { \
+ case 824: return 8713; \
+ } \
+ return 0; \
+ case 8715: \
+ switch (ch2) { \
+ case 824: return 8716; \
+ } \
+ return 0; \
+ case 8739: \
+ switch (ch2) { \
+ case 824: return 8740; \
+ } \
+ return 0; \
+ case 8741: \
+ switch (ch2) { \
+ case 824: return 8742; \
+ } \
+ return 0; \
+ case 8764: \
+ switch (ch2) { \
+ case 824: return 8769; \
+ } \
+ return 0; \
+ case 8771: \
+ switch (ch2) { \
+ case 824: return 8772; \
+ } \
+ return 0; \
+ case 8773: \
+ switch (ch2) { \
+ case 824: return 8775; \
+ } \
+ return 0; \
+ case 8776: \
+ switch (ch2) { \
+ case 824: return 8777; \
+ } \
+ return 0; \
+ case 8781: \
+ switch (ch2) { \
+ case 824: return 8813; \
+ } \
+ return 0; \
+ case 8801: \
+ switch (ch2) { \
+ case 824: return 8802; \
+ } \
+ return 0; \
+ case 8804: \
+ switch (ch2) { \
+ case 824: return 8816; \
+ } \
+ return 0; \
+ case 8805: \
+ switch (ch2) { \
+ case 824: return 8817; \
+ } \
+ return 0; \
+ case 8818: \
+ switch (ch2) { \
+ case 824: return 8820; \
+ } \
+ return 0; \
+ case 8819: \
+ switch (ch2) { \
+ case 824: return 8821; \
+ } \
+ return 0; \
+ case 8822: \
+ switch (ch2) { \
+ case 824: return 8824; \
+ } \
+ return 0; \
+ case 8823: \
+ switch (ch2) { \
+ case 824: return 8825; \
+ } \
+ return 0; \
+ case 8826: \
+ switch (ch2) { \
+ case 824: return 8832; \
+ } \
+ return 0; \
+ case 8827: \
+ switch (ch2) { \
+ case 824: return 8833; \
+ } \
+ return 0; \
+ case 8828: \
+ switch (ch2) { \
+ case 824: return 8928; \
+ } \
+ return 0; \
+ case 8829: \
+ switch (ch2) { \
+ case 824: return 8929; \
+ } \
+ return 0; \
+ case 8834: \
+ switch (ch2) { \
+ case 824: return 8836; \
+ } \
+ return 0; \
+ case 8835: \
+ switch (ch2) { \
+ case 824: return 8837; \
+ } \
+ return 0; \
+ case 8838: \
+ switch (ch2) { \
+ case 824: return 8840; \
+ } \
+ return 0; \
+ case 8839: \
+ switch (ch2) { \
+ case 824: return 8841; \
+ } \
+ return 0; \
+ case 8849: \
+ switch (ch2) { \
+ case 824: return 8930; \
+ } \
+ return 0; \
+ case 8850: \
+ switch (ch2) { \
+ case 824: return 8931; \
+ } \
+ return 0; \
+ case 8866: \
+ switch (ch2) { \
+ case 824: return 8876; \
+ } \
+ return 0; \
+ case 8872: \
+ switch (ch2) { \
+ case 824: return 8877; \
+ } \
+ return 0; \
+ case 8873: \
+ switch (ch2) { \
+ case 824: return 8878; \
+ } \
+ return 0; \
+ case 8875: \
+ switch (ch2) { \
+ case 824: return 8879; \
+ } \
+ return 0; \
+ case 8882: \
+ switch (ch2) { \
+ case 824: return 8938; \
+ } \
+ return 0; \
+ case 8883: \
+ switch (ch2) { \
+ case 824: return 8939; \
+ } \
+ return 0; \
+ case 8884: \
+ switch (ch2) { \
+ case 824: return 8940; \
+ } \
+ return 0; \
+ case 8885: \
+ switch (ch2) { \
+ case 824: return 8941; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 42: \
+switch (ch1) { \
+ case 10973: \
+ switch (ch2) { \
+ case 824: return 10972; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 48: \
+switch (ch1) { \
+ case 12358: \
+ switch (ch2) { \
+ case 12441: return 12436; \
+ } \
+ return 0; \
+ case 12363: \
+ switch (ch2) { \
+ case 12441: return 12364; \
+ } \
+ return 0; \
+ case 12365: \
+ switch (ch2) { \
+ case 12441: return 12366; \
+ } \
+ return 0; \
+ case 12367: \
+ switch (ch2) { \
+ case 12441: return 12368; \
+ } \
+ return 0; \
+ case 12369: \
+ switch (ch2) { \
+ case 12441: return 12370; \
+ } \
+ return 0; \
+ case 12371: \
+ switch (ch2) { \
+ case 12441: return 12372; \
+ } \
+ return 0; \
+ case 12373: \
+ switch (ch2) { \
+ case 12441: return 12374; \
+ } \
+ return 0; \
+ case 12375: \
+ switch (ch2) { \
+ case 12441: return 12376; \
+ } \
+ return 0; \
+ case 12377: \
+ switch (ch2) { \
+ case 12441: return 12378; \
+ } \
+ return 0; \
+ case 12379: \
+ switch (ch2) { \
+ case 12441: return 12380; \
+ } \
+ return 0; \
+ case 12381: \
+ switch (ch2) { \
+ case 12441: return 12382; \
+ } \
+ return 0; \
+ case 12383: \
+ switch (ch2) { \
+ case 12441: return 12384; \
+ } \
+ return 0; \
+ case 12385: \
+ switch (ch2) { \
+ case 12441: return 12386; \
+ } \
+ return 0; \
+ case 12388: \
+ switch (ch2) { \
+ case 12441: return 12389; \
+ } \
+ return 0; \
+ case 12390: \
+ switch (ch2) { \
+ case 12441: return 12391; \
+ } \
+ return 0; \
+ case 12392: \
+ switch (ch2) { \
+ case 12441: return 12393; \
+ } \
+ return 0; \
+ case 12399: \
+ switch (ch2) { \
+ case 12441: return 12400; \
+ case 12442: return 12401; \
+ } \
+ return 0; \
+ case 12402: \
+ switch (ch2) { \
+ case 12441: return 12403; \
+ case 12442: return 12404; \
+ } \
+ return 0; \
+ case 12405: \
+ switch (ch2) { \
+ case 12441: return 12406; \
+ case 12442: return 12407; \
+ } \
+ return 0; \
+ case 12408: \
+ switch (ch2) { \
+ case 12441: return 12409; \
+ case 12442: return 12410; \
+ } \
+ return 0; \
+ case 12411: \
+ switch (ch2) { \
+ case 12441: return 12412; \
+ case 12442: return 12413; \
+ } \
+ return 0; \
+ case 12445: \
+ switch (ch2) { \
+ case 12441: return 12446; \
+ } \
+ return 0; \
+ case 12454: \
+ switch (ch2) { \
+ case 12441: return 12532; \
+ } \
+ return 0; \
+ case 12459: \
+ switch (ch2) { \
+ case 12441: return 12460; \
+ } \
+ return 0; \
+ case 12461: \
+ switch (ch2) { \
+ case 12441: return 12462; \
+ } \
+ return 0; \
+ case 12463: \
+ switch (ch2) { \
+ case 12441: return 12464; \
+ } \
+ return 0; \
+ case 12465: \
+ switch (ch2) { \
+ case 12441: return 12466; \
+ } \
+ return 0; \
+ case 12467: \
+ switch (ch2) { \
+ case 12441: return 12468; \
+ } \
+ return 0; \
+ case 12469: \
+ switch (ch2) { \
+ case 12441: return 12470; \
+ } \
+ return 0; \
+ case 12471: \
+ switch (ch2) { \
+ case 12441: return 12472; \
+ } \
+ return 0; \
+ case 12473: \
+ switch (ch2) { \
+ case 12441: return 12474; \
+ } \
+ return 0; \
+ case 12475: \
+ switch (ch2) { \
+ case 12441: return 12476; \
+ } \
+ return 0; \
+ case 12477: \
+ switch (ch2) { \
+ case 12441: return 12478; \
+ } \
+ return 0; \
+ case 12479: \
+ switch (ch2) { \
+ case 12441: return 12480; \
+ } \
+ return 0; \
+ case 12481: \
+ switch (ch2) { \
+ case 12441: return 12482; \
+ } \
+ return 0; \
+ case 12484: \
+ switch (ch2) { \
+ case 12441: return 12485; \
+ } \
+ return 0; \
+ case 12486: \
+ switch (ch2) { \
+ case 12441: return 12487; \
+ } \
+ return 0; \
+ case 12488: \
+ switch (ch2) { \
+ case 12441: return 12489; \
+ } \
+ return 0; \
+ case 12495: \
+ switch (ch2) { \
+ case 12441: return 12496; \
+ case 12442: return 12497; \
+ } \
+ return 0; \
+ case 12498: \
+ switch (ch2) { \
+ case 12441: return 12499; \
+ case 12442: return 12500; \
+ } \
+ return 0; \
+ case 12501: \
+ switch (ch2) { \
+ case 12441: return 12502; \
+ case 12442: return 12503; \
+ } \
+ return 0; \
+ case 12504: \
+ switch (ch2) { \
+ case 12441: return 12505; \
+ case 12442: return 12506; \
+ } \
+ return 0; \
+ case 12507: \
+ switch (ch2) { \
+ case 12441: return 12508; \
+ case 12442: return 12509; \
+ } \
+ return 0; \
+ case 12527: \
+ switch (ch2) { \
+ case 12441: return 12535; \
+ } \
+ return 0; \
+ case 12528: \
+ switch (ch2) { \
+ case 12441: return 12536; \
+ } \
+ return 0; \
+ case 12529: \
+ switch (ch2) { \
+ case 12441: return 12537; \
+ } \
+ return 0; \
+ case 12530: \
+ switch (ch2) { \
+ case 12441: return 12538; \
+ } \
+ return 0; \
+ case 12541: \
+ switch (ch2) { \
+ case 12441: return 12542; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 251: \
+switch (ch1) { \
+ case 64329: \
+ switch (ch2) { \
+ case 1473: return 64300; \
+ case 1474: return 64301; \
+ } \
+ return 0; \
+} \
+return 0; \
+case 465: \
+switch (ch1) { \
+ case 119127: \
+ switch (ch2) { \
+ case 119141: return 119134; \
+ } \
+ return 0; \
+ case 119128: \
+ switch (ch2) { \
+ case 119141: return 119135; \
+ } \
+ return 0; \
+ case 119135: \
+ switch (ch2) { \
+ case 119150: return 119136; \
+ case 119151: return 119137; \
+ case 119152: return 119138; \
+ case 119153: return 119139; \
+ case 119154: return 119140; \
+ } \
+ return 0; \
+ case 119225: \
+ switch (ch2) { \
+ case 119141: return 119227; \
+ } \
+ return 0; \
+ case 119226: \
+ switch (ch2) { \
+ case 119141: return 119228; \
+ } \
+ return 0; \
+ case 119227: \
+ switch (ch2) { \
+ case 119150: return 119229; \
+ case 119151: return 119231; \
+ } \
+ return 0; \
+ case 119228: \
+ switch (ch2) { \
+ case 119150: return 119230; \
+ case 119151: return 119232; \
+ } \
+ return 0; \
+} \
+return 0; \
+} \
+return 0;
+
+glui32 unigen_decomp_data[3247] = {
+ 0x41, 0x300, 0x41, 0x301, 0x41, 0x302, 0x41, 0x303,
+ 0x41, 0x308, 0x41, 0x30a, 0x43, 0x327, 0x45, 0x300,
+ 0x45, 0x301, 0x45, 0x302, 0x45, 0x308, 0x49, 0x300,
+ 0x49, 0x301, 0x49, 0x302, 0x49, 0x308, 0x4e, 0x303,
+ 0x4f, 0x300, 0x4f, 0x301, 0x4f, 0x302, 0x4f, 0x303,
+ 0x4f, 0x308, 0x55, 0x300, 0x55, 0x301, 0x55, 0x302,
+ 0x55, 0x308, 0x59, 0x301, 0x61, 0x300, 0x61, 0x301,
+ 0x61, 0x302, 0x61, 0x303, 0x61, 0x308, 0x61, 0x30a,
+ 0x63, 0x327, 0x65, 0x300, 0x65, 0x301, 0x65, 0x302,
+ 0x65, 0x308, 0x69, 0x300, 0x69, 0x301, 0x69, 0x302,
+ 0x69, 0x308, 0x6e, 0x303, 0x6f, 0x300, 0x6f, 0x301,
+ 0x6f, 0x302, 0x6f, 0x303, 0x6f, 0x308, 0x75, 0x300,
+ 0x75, 0x301, 0x75, 0x302, 0x75, 0x308, 0x79, 0x301,
+ 0x79, 0x308, 0x41, 0x304, 0x61, 0x304, 0x41, 0x306,
+ 0x61, 0x306, 0x41, 0x328, 0x61, 0x328, 0x43, 0x301,
+ 0x63, 0x301, 0x43, 0x302, 0x63, 0x302, 0x43, 0x307,
+ 0x63, 0x307, 0x43, 0x30c, 0x63, 0x30c, 0x44, 0x30c,
+ 0x64, 0x30c, 0x45, 0x304, 0x65, 0x304, 0x45, 0x306,
+ 0x65, 0x306, 0x45, 0x307, 0x65, 0x307, 0x45, 0x328,
+ 0x65, 0x328, 0x45, 0x30c, 0x65, 0x30c, 0x47, 0x302,
+ 0x67, 0x302, 0x47, 0x306, 0x67, 0x306, 0x47, 0x307,
+ 0x67, 0x307, 0x47, 0x327, 0x67, 0x327, 0x48, 0x302,
+ 0x68, 0x302, 0x49, 0x303, 0x69, 0x303, 0x49, 0x304,
+ 0x69, 0x304, 0x49, 0x306, 0x69, 0x306, 0x49, 0x328,
+ 0x69, 0x328, 0x49, 0x307, 0x4a, 0x302, 0x6a, 0x302,
+ 0x4b, 0x327, 0x6b, 0x327, 0x4c, 0x301, 0x6c, 0x301,
+ 0x4c, 0x327, 0x6c, 0x327, 0x4c, 0x30c, 0x6c, 0x30c,
+ 0x4e, 0x301, 0x6e, 0x301, 0x4e, 0x327, 0x6e, 0x327,
+ 0x4e, 0x30c, 0x6e, 0x30c, 0x4f, 0x304, 0x6f, 0x304,
+ 0x4f, 0x306, 0x6f, 0x306, 0x4f, 0x30b, 0x6f, 0x30b,
+ 0x52, 0x301, 0x72, 0x301, 0x52, 0x327, 0x72, 0x327,
+ 0x52, 0x30c, 0x72, 0x30c, 0x53, 0x301, 0x73, 0x301,
+ 0x53, 0x302, 0x73, 0x302, 0x53, 0x327, 0x73, 0x327,
+ 0x53, 0x30c, 0x73, 0x30c, 0x54, 0x327, 0x74, 0x327,
+ 0x54, 0x30c, 0x74, 0x30c, 0x55, 0x303, 0x75, 0x303,
+ 0x55, 0x304, 0x75, 0x304, 0x55, 0x306, 0x75, 0x306,
+ 0x55, 0x30a, 0x75, 0x30a, 0x55, 0x30b, 0x75, 0x30b,
+ 0x55, 0x328, 0x75, 0x328, 0x57, 0x302, 0x77, 0x302,
+ 0x59, 0x302, 0x79, 0x302, 0x59, 0x308, 0x5a, 0x301,
+ 0x7a, 0x301, 0x5a, 0x307, 0x7a, 0x307, 0x5a, 0x30c,
+ 0x7a, 0x30c, 0x4f, 0x31b, 0x6f, 0x31b, 0x55, 0x31b,
+ 0x75, 0x31b, 0x41, 0x30c, 0x61, 0x30c, 0x49, 0x30c,
+ 0x69, 0x30c, 0x4f, 0x30c, 0x6f, 0x30c, 0x55, 0x30c,
+ 0x75, 0x30c, 0x55, 0x308, 0x304, 0x75, 0x308, 0x304,
+ 0x55, 0x308, 0x301, 0x75, 0x308, 0x301, 0x55, 0x308,
+ 0x30c, 0x75, 0x308, 0x30c, 0x55, 0x308, 0x300, 0x75,
+ 0x308, 0x300, 0x41, 0x308, 0x304, 0x61, 0x308, 0x304,
+ 0x41, 0x307, 0x304, 0x61, 0x307, 0x304, 0xc6, 0x304,
+ 0xe6, 0x304, 0x47, 0x30c, 0x67, 0x30c, 0x4b, 0x30c,
+ 0x6b, 0x30c, 0x4f, 0x328, 0x6f, 0x328, 0x4f, 0x328,
+ 0x304, 0x6f, 0x328, 0x304, 0x1b7, 0x30c, 0x292, 0x30c,
+ 0x6a, 0x30c, 0x47, 0x301, 0x67, 0x301, 0x4e, 0x300,
+ 0x6e, 0x300, 0x41, 0x30a, 0x301, 0x61, 0x30a, 0x301,
+ 0xc6, 0x301, 0xe6, 0x301, 0xd8, 0x301, 0xf8, 0x301,
+ 0x41, 0x30f, 0x61, 0x30f, 0x41, 0x311, 0x61, 0x311,
+ 0x45, 0x30f, 0x65, 0x30f, 0x45, 0x311, 0x65, 0x311,
+ 0x49, 0x30f, 0x69, 0x30f, 0x49, 0x311, 0x69, 0x311,
+ 0x4f, 0x30f, 0x6f, 0x30f, 0x4f, 0x311, 0x6f, 0x311,
+ 0x52, 0x30f, 0x72, 0x30f, 0x52, 0x311, 0x72, 0x311,
+ 0x55, 0x30f, 0x75, 0x30f, 0x55, 0x311, 0x75, 0x311,
+ 0x53, 0x326, 0x73, 0x326, 0x54, 0x326, 0x74, 0x326,
+ 0x48, 0x30c, 0x68, 0x30c, 0x41, 0x307, 0x61, 0x307,
+ 0x45, 0x327, 0x65, 0x327, 0x4f, 0x308, 0x304, 0x6f,
+ 0x308, 0x304, 0x4f, 0x303, 0x304, 0x6f, 0x303, 0x304,
+ 0x4f, 0x307, 0x6f, 0x307, 0x4f, 0x307, 0x304, 0x6f,
+ 0x307, 0x304, 0x59, 0x304, 0x79, 0x304, 0x300, 0x301,
+ 0x313, 0x308, 0x301, 0x2b9, 0x3b, 0xa8, 0x301, 0x391,
+ 0x301, 0xb7, 0x395, 0x301, 0x397, 0x301, 0x399, 0x301,
+ 0x39f, 0x301, 0x3a5, 0x301, 0x3a9, 0x301, 0x3b9, 0x308,
+ 0x301, 0x399, 0x308, 0x3a5, 0x308, 0x3b1, 0x301, 0x3b5,
+ 0x301, 0x3b7, 0x301, 0x3b9, 0x301, 0x3c5, 0x308, 0x301,
+ 0x3b9, 0x308, 0x3c5, 0x308, 0x3bf, 0x301, 0x3c5, 0x301,
+ 0x3c9, 0x301, 0x3d2, 0x301, 0x3d2, 0x308, 0x415, 0x300,
+ 0x415, 0x308, 0x413, 0x301, 0x406, 0x308, 0x41a, 0x301,
+ 0x418, 0x300, 0x423, 0x306, 0x418, 0x306, 0x438, 0x306,
+ 0x435, 0x300, 0x435, 0x308, 0x433, 0x301, 0x456, 0x308,
+ 0x43a, 0x301, 0x438, 0x300, 0x443, 0x306, 0x474, 0x30f,
+ 0x475, 0x30f, 0x416, 0x306, 0x436, 0x306, 0x410, 0x306,
+ 0x430, 0x306, 0x410, 0x308, 0x430, 0x308, 0x415, 0x306,
+ 0x435, 0x306, 0x4d8, 0x308, 0x4d9, 0x308, 0x416, 0x308,
+ 0x436, 0x308, 0x417, 0x308, 0x437, 0x308, 0x418, 0x304,
+ 0x438, 0x304, 0x418, 0x308, 0x438, 0x308, 0x41e, 0x308,
+ 0x43e, 0x308, 0x4e8, 0x308, 0x4e9, 0x308, 0x42d, 0x308,
+ 0x44d, 0x308, 0x423, 0x304, 0x443, 0x304, 0x423, 0x308,
+ 0x443, 0x308, 0x423, 0x30b, 0x443, 0x30b, 0x427, 0x308,
+ 0x447, 0x308, 0x42b, 0x308, 0x44b, 0x308, 0x627, 0x653,
+ 0x627, 0x654, 0x648, 0x654, 0x627, 0x655, 0x64a, 0x654,
+ 0x6d5, 0x654, 0x6c1, 0x654, 0x6d2, 0x654, 0x928, 0x93c,
+ 0x930, 0x93c, 0x933, 0x93c, 0x915, 0x93c, 0x916, 0x93c,
+ 0x917, 0x93c, 0x91c, 0x93c, 0x921, 0x93c, 0x922, 0x93c,
+ 0x92b, 0x93c, 0x92f, 0x93c, 0x9c7, 0x9be, 0x9c7, 0x9d7,
+ 0x9a1, 0x9bc, 0x9a2, 0x9bc, 0x9af, 0x9bc, 0xa32, 0xa3c,
+ 0xa38, 0xa3c, 0xa16, 0xa3c, 0xa17, 0xa3c, 0xa1c, 0xa3c,
+ 0xa2b, 0xa3c, 0xb47, 0xb56, 0xb47, 0xb3e, 0xb47, 0xb57,
+ 0xb21, 0xb3c, 0xb22, 0xb3c, 0xb92, 0xbd7, 0xbc6, 0xbbe,
+ 0xbc7, 0xbbe, 0xbc6, 0xbd7, 0xc46, 0xc56, 0xcbf, 0xcd5,
+ 0xcc6, 0xcd5, 0xcc6, 0xcd6, 0xcc6, 0xcc2, 0xcc6, 0xcc2,
+ 0xcd5, 0xd46, 0xd3e, 0xd47, 0xd3e, 0xd46, 0xd57, 0xdd9,
+ 0xdca, 0xdd9, 0xdcf, 0xdd9, 0xdcf, 0xdca, 0xdd9, 0xddf,
+ 0xf42, 0xfb7, 0xf4c, 0xfb7, 0xf51, 0xfb7, 0xf56, 0xfb7,
+ 0xf5b, 0xfb7, 0xf40, 0xfb5, 0xf71, 0xf72, 0xf71, 0xf74,
+ 0xfb2, 0xf80, 0xfb3, 0xf80, 0xf71, 0xf80, 0xf92, 0xfb7,
+ 0xf9c, 0xfb7, 0xfa1, 0xfb7, 0xfa6, 0xfb7, 0xfab, 0xfb7,
+ 0xf90, 0xfb5, 0x1025, 0x102e, 0x41, 0x325, 0x61, 0x325,
+ 0x42, 0x307, 0x62, 0x307, 0x42, 0x323, 0x62, 0x323,
+ 0x42, 0x331, 0x62, 0x331, 0x43, 0x327, 0x301, 0x63,
+ 0x327, 0x301, 0x44, 0x307, 0x64, 0x307, 0x44, 0x323,
+ 0x64, 0x323, 0x44, 0x331, 0x64, 0x331, 0x44, 0x327,
+ 0x64, 0x327, 0x44, 0x32d, 0x64, 0x32d, 0x45, 0x304,
+ 0x300, 0x65, 0x304, 0x300, 0x45, 0x304, 0x301, 0x65,
+ 0x304, 0x301, 0x45, 0x32d, 0x65, 0x32d, 0x45, 0x330,
+ 0x65, 0x330, 0x45, 0x327, 0x306, 0x65, 0x327, 0x306,
+ 0x46, 0x307, 0x66, 0x307, 0x47, 0x304, 0x67, 0x304,
+ 0x48, 0x307, 0x68, 0x307, 0x48, 0x323, 0x68, 0x323,
+ 0x48, 0x308, 0x68, 0x308, 0x48, 0x327, 0x68, 0x327,
+ 0x48, 0x32e, 0x68, 0x32e, 0x49, 0x330, 0x69, 0x330,
+ 0x49, 0x308, 0x301, 0x69, 0x308, 0x301, 0x4b, 0x301,
+ 0x6b, 0x301, 0x4b, 0x323, 0x6b, 0x323, 0x4b, 0x331,
+ 0x6b, 0x331, 0x4c, 0x323, 0x6c, 0x323, 0x4c, 0x323,
+ 0x304, 0x6c, 0x323, 0x304, 0x4c, 0x331, 0x6c, 0x331,
+ 0x4c, 0x32d, 0x6c, 0x32d, 0x4d, 0x301, 0x6d, 0x301,
+ 0x4d, 0x307, 0x6d, 0x307, 0x4d, 0x323, 0x6d, 0x323,
+ 0x4e, 0x307, 0x6e, 0x307, 0x4e, 0x323, 0x6e, 0x323,
+ 0x4e, 0x331, 0x6e, 0x331, 0x4e, 0x32d, 0x6e, 0x32d,
+ 0x4f, 0x303, 0x301, 0x6f, 0x303, 0x301, 0x4f, 0x303,
+ 0x308, 0x6f, 0x303, 0x308, 0x4f, 0x304, 0x300, 0x6f,
+ 0x304, 0x300, 0x4f, 0x304, 0x301, 0x6f, 0x304, 0x301,
+ 0x50, 0x301, 0x70, 0x301, 0x50, 0x307, 0x70, 0x307,
+ 0x52, 0x307, 0x72, 0x307, 0x52, 0x323, 0x72, 0x323,
+ 0x52, 0x323, 0x304, 0x72, 0x323, 0x304, 0x52, 0x331,
+ 0x72, 0x331, 0x53, 0x307, 0x73, 0x307, 0x53, 0x323,
+ 0x73, 0x323, 0x53, 0x301, 0x307, 0x73, 0x301, 0x307,
+ 0x53, 0x30c, 0x307, 0x73, 0x30c, 0x307, 0x53, 0x323,
+ 0x307, 0x73, 0x323, 0x307, 0x54, 0x307, 0x74, 0x307,
+ 0x54, 0x323, 0x74, 0x323, 0x54, 0x331, 0x74, 0x331,
+ 0x54, 0x32d, 0x74, 0x32d, 0x55, 0x324, 0x75, 0x324,
+ 0x55, 0x330, 0x75, 0x330, 0x55, 0x32d, 0x75, 0x32d,
+ 0x55, 0x303, 0x301, 0x75, 0x303, 0x301, 0x55, 0x304,
+ 0x308, 0x75, 0x304, 0x308, 0x56, 0x303, 0x76, 0x303,
+ 0x56, 0x323, 0x76, 0x323, 0x57, 0x300, 0x77, 0x300,
+ 0x57, 0x301, 0x77, 0x301, 0x57, 0x308, 0x77, 0x308,
+ 0x57, 0x307, 0x77, 0x307, 0x57, 0x323, 0x77, 0x323,
+ 0x58, 0x307, 0x78, 0x307, 0x58, 0x308, 0x78, 0x308,
+ 0x59, 0x307, 0x79, 0x307, 0x5a, 0x302, 0x7a, 0x302,
+ 0x5a, 0x323, 0x7a, 0x323, 0x5a, 0x331, 0x7a, 0x331,
+ 0x68, 0x331, 0x74, 0x308, 0x77, 0x30a, 0x79, 0x30a,
+ 0x17f, 0x307, 0x41, 0x323, 0x61, 0x323, 0x41, 0x309,
+ 0x61, 0x309, 0x41, 0x302, 0x301, 0x61, 0x302, 0x301,
+ 0x41, 0x302, 0x300, 0x61, 0x302, 0x300, 0x41, 0x302,
+ 0x309, 0x61, 0x302, 0x309, 0x41, 0x302, 0x303, 0x61,
+ 0x302, 0x303, 0x41, 0x323, 0x302, 0x61, 0x323, 0x302,
+ 0x41, 0x306, 0x301, 0x61, 0x306, 0x301, 0x41, 0x306,
+ 0x300, 0x61, 0x306, 0x300, 0x41, 0x306, 0x309, 0x61,
+ 0x306, 0x309, 0x41, 0x306, 0x303, 0x61, 0x306, 0x303,
+ 0x41, 0x323, 0x306, 0x61, 0x323, 0x306, 0x45, 0x323,
+ 0x65, 0x323, 0x45, 0x309, 0x65, 0x309, 0x45, 0x303,
+ 0x65, 0x303, 0x45, 0x302, 0x301, 0x65, 0x302, 0x301,
+ 0x45, 0x302, 0x300, 0x65, 0x302, 0x300, 0x45, 0x302,
+ 0x309, 0x65, 0x302, 0x309, 0x45, 0x302, 0x303, 0x65,
+ 0x302, 0x303, 0x45, 0x323, 0x302, 0x65, 0x323, 0x302,
+ 0x49, 0x309, 0x69, 0x309, 0x49, 0x323, 0x69, 0x323,
+ 0x4f, 0x323, 0x6f, 0x323, 0x4f, 0x309, 0x6f, 0x309,
+ 0x4f, 0x302, 0x301, 0x6f, 0x302, 0x301, 0x4f, 0x302,
+ 0x300, 0x6f, 0x302, 0x300, 0x4f, 0x302, 0x309, 0x6f,
+ 0x302, 0x309, 0x4f, 0x302, 0x303, 0x6f, 0x302, 0x303,
+ 0x4f, 0x323, 0x302, 0x6f, 0x323, 0x302, 0x4f, 0x31b,
+ 0x301, 0x6f, 0x31b, 0x301, 0x4f, 0x31b, 0x300, 0x6f,
+ 0x31b, 0x300, 0x4f, 0x31b, 0x309, 0x6f, 0x31b, 0x309,
+ 0x4f, 0x31b, 0x303, 0x6f, 0x31b, 0x303, 0x4f, 0x31b,
+ 0x323, 0x6f, 0x31b, 0x323, 0x55, 0x323, 0x75, 0x323,
+ 0x55, 0x309, 0x75, 0x309, 0x55, 0x31b, 0x301, 0x75,
+ 0x31b, 0x301, 0x55, 0x31b, 0x300, 0x75, 0x31b, 0x300,
+ 0x55, 0x31b, 0x309, 0x75, 0x31b, 0x309, 0x55, 0x31b,
+ 0x303, 0x75, 0x31b, 0x303, 0x55, 0x31b, 0x323, 0x75,
+ 0x31b, 0x323, 0x59, 0x300, 0x79, 0x300, 0x59, 0x323,
+ 0x79, 0x323, 0x59, 0x309, 0x79, 0x309, 0x59, 0x303,
+ 0x79, 0x303, 0x3b1, 0x313, 0x3b1, 0x314, 0x3b1, 0x313,
+ 0x300, 0x3b1, 0x314, 0x300, 0x3b1, 0x313, 0x301, 0x3b1,
+ 0x314, 0x301, 0x3b1, 0x313, 0x342, 0x3b1, 0x314, 0x342,
+ 0x391, 0x313, 0x391, 0x314, 0x391, 0x313, 0x300, 0x391,
+ 0x314, 0x300, 0x391, 0x313, 0x301, 0x391, 0x314, 0x301,
+ 0x391, 0x313, 0x342, 0x391, 0x314, 0x342, 0x3b5, 0x313,
+ 0x3b5, 0x314, 0x3b5, 0x313, 0x300, 0x3b5, 0x314, 0x300,
+ 0x3b5, 0x313, 0x301, 0x3b5, 0x314, 0x301, 0x395, 0x313,
+ 0x395, 0x314, 0x395, 0x313, 0x300, 0x395, 0x314, 0x300,
+ 0x395, 0x313, 0x301, 0x395, 0x314, 0x301, 0x3b7, 0x313,
+ 0x3b7, 0x314, 0x3b7, 0x313, 0x300, 0x3b7, 0x314, 0x300,
+ 0x3b7, 0x313, 0x301, 0x3b7, 0x314, 0x301, 0x3b7, 0x313,
+ 0x342, 0x3b7, 0x314, 0x342, 0x397, 0x313, 0x397, 0x314,
+ 0x397, 0x313, 0x300, 0x397, 0x314, 0x300, 0x397, 0x313,
+ 0x301, 0x397, 0x314, 0x301, 0x397, 0x313, 0x342, 0x397,
+ 0x314, 0x342, 0x3b9, 0x313, 0x3b9, 0x314, 0x3b9, 0x313,
+ 0x300, 0x3b9, 0x314, 0x300, 0x3b9, 0x313, 0x301, 0x3b9,
+ 0x314, 0x301, 0x3b9, 0x313, 0x342, 0x3b9, 0x314, 0x342,
+ 0x399, 0x313, 0x399, 0x314, 0x399, 0x313, 0x300, 0x399,
+ 0x314, 0x300, 0x399, 0x313, 0x301, 0x399, 0x314, 0x301,
+ 0x399, 0x313, 0x342, 0x399, 0x314, 0x342, 0x3bf, 0x313,
+ 0x3bf, 0x314, 0x3bf, 0x313, 0x300, 0x3bf, 0x314, 0x300,
+ 0x3bf, 0x313, 0x301, 0x3bf, 0x314, 0x301, 0x39f, 0x313,
+ 0x39f, 0x314, 0x39f, 0x313, 0x300, 0x39f, 0x314, 0x300,
+ 0x39f, 0x313, 0x301, 0x39f, 0x314, 0x301, 0x3c5, 0x313,
+ 0x3c5, 0x314, 0x3c5, 0x313, 0x300, 0x3c5, 0x314, 0x300,
+ 0x3c5, 0x313, 0x301, 0x3c5, 0x314, 0x301, 0x3c5, 0x313,
+ 0x342, 0x3c5, 0x314, 0x342, 0x3a5, 0x314, 0x3a5, 0x314,
+ 0x300, 0x3a5, 0x314, 0x301, 0x3a5, 0x314, 0x342, 0x3c9,
+ 0x313, 0x3c9, 0x314, 0x3c9, 0x313, 0x300, 0x3c9, 0x314,
+ 0x300, 0x3c9, 0x313, 0x301, 0x3c9, 0x314, 0x301, 0x3c9,
+ 0x313, 0x342, 0x3c9, 0x314, 0x342, 0x3a9, 0x313, 0x3a9,
+ 0x314, 0x3a9, 0x313, 0x300, 0x3a9, 0x314, 0x300, 0x3a9,
+ 0x313, 0x301, 0x3a9, 0x314, 0x301, 0x3a9, 0x313, 0x342,
+ 0x3a9, 0x314, 0x342, 0x3b1, 0x300, 0x3b1, 0x301, 0x3b5,
+ 0x300, 0x3b5, 0x301, 0x3b7, 0x300, 0x3b7, 0x301, 0x3b9,
+ 0x300, 0x3b9, 0x301, 0x3bf, 0x300, 0x3bf, 0x301, 0x3c5,
+ 0x300, 0x3c5, 0x301, 0x3c9, 0x300, 0x3c9, 0x301, 0x3b1,
+ 0x313, 0x345, 0x3b1, 0x314, 0x345, 0x3b1, 0x313, 0x300,
+ 0x345, 0x3b1, 0x314, 0x300, 0x345, 0x3b1, 0x313, 0x301,
+ 0x345, 0x3b1, 0x314, 0x301, 0x345, 0x3b1, 0x313, 0x342,
+ 0x345, 0x3b1, 0x314, 0x342, 0x345, 0x391, 0x313, 0x345,
+ 0x391, 0x314, 0x345, 0x391, 0x313, 0x300, 0x345, 0x391,
+ 0x314, 0x300, 0x345, 0x391, 0x313, 0x301, 0x345, 0x391,
+ 0x314, 0x301, 0x345, 0x391, 0x313, 0x342, 0x345, 0x391,
+ 0x314, 0x342, 0x345, 0x3b7, 0x313, 0x345, 0x3b7, 0x314,
+ 0x345, 0x3b7, 0x313, 0x300, 0x345, 0x3b7, 0x314, 0x300,
+ 0x345, 0x3b7, 0x313, 0x301, 0x345, 0x3b7, 0x314, 0x301,
+ 0x345, 0x3b7, 0x313, 0x342, 0x345, 0x3b7, 0x314, 0x342,
+ 0x345, 0x397, 0x313, 0x345, 0x397, 0x314, 0x345, 0x397,
+ 0x313, 0x300, 0x345, 0x397, 0x314, 0x300, 0x345, 0x397,
+ 0x313, 0x301, 0x345, 0x397, 0x314, 0x301, 0x345, 0x397,
+ 0x313, 0x342, 0x345, 0x397, 0x314, 0x342, 0x345, 0x3c9,
+ 0x313, 0x345, 0x3c9, 0x314, 0x345, 0x3c9, 0x313, 0x300,
+ 0x345, 0x3c9, 0x314, 0x300, 0x345, 0x3c9, 0x313, 0x301,
+ 0x345, 0x3c9, 0x314, 0x301, 0x345, 0x3c9, 0x313, 0x342,
+ 0x345, 0x3c9, 0x314, 0x342, 0x345, 0x3a9, 0x313, 0x345,
+ 0x3a9, 0x314, 0x345, 0x3a9, 0x313, 0x300, 0x345, 0x3a9,
+ 0x314, 0x300, 0x345, 0x3a9, 0x313, 0x301, 0x345, 0x3a9,
+ 0x314, 0x301, 0x345, 0x3a9, 0x313, 0x342, 0x345, 0x3a9,
+ 0x314, 0x342, 0x345, 0x3b1, 0x306, 0x3b1, 0x304, 0x3b1,
+ 0x300, 0x345, 0x3b1, 0x345, 0x3b1, 0x301, 0x345, 0x3b1,
+ 0x342, 0x3b1, 0x342, 0x345, 0x391, 0x306, 0x391, 0x304,
+ 0x391, 0x300, 0x391, 0x301, 0x391, 0x345, 0x3b9, 0xa8,
+ 0x342, 0x3b7, 0x300, 0x345, 0x3b7, 0x345, 0x3b7, 0x301,
+ 0x345, 0x3b7, 0x342, 0x3b7, 0x342, 0x345, 0x395, 0x300,
+ 0x395, 0x301, 0x397, 0x300, 0x397, 0x301, 0x397, 0x345,
+ 0x1fbf, 0x300, 0x1fbf, 0x301, 0x1fbf, 0x342, 0x3b9, 0x306,
+ 0x3b9, 0x304, 0x3b9, 0x308, 0x300, 0x3b9, 0x308, 0x301,
+ 0x3b9, 0x342, 0x3b9, 0x308, 0x342, 0x399, 0x306, 0x399,
+ 0x304, 0x399, 0x300, 0x399, 0x301, 0x1ffe, 0x300, 0x1ffe,
+ 0x301, 0x1ffe, 0x342, 0x3c5, 0x306, 0x3c5, 0x304, 0x3c5,
+ 0x308, 0x300, 0x3c5, 0x308, 0x301, 0x3c1, 0x313, 0x3c1,
+ 0x314, 0x3c5, 0x342, 0x3c5, 0x308, 0x342, 0x3a5, 0x306,
+ 0x3a5, 0x304, 0x3a5, 0x300, 0x3a5, 0x301, 0x3a1, 0x314,
+ 0xa8, 0x300, 0xa8, 0x301, 0x60, 0x3c9, 0x300, 0x345,
+ 0x3c9, 0x345, 0x3c9, 0x301, 0x345, 0x3c9, 0x342, 0x3c9,
+ 0x342, 0x345, 0x39f, 0x300, 0x39f, 0x301, 0x3a9, 0x300,
+ 0x3a9, 0x301, 0x3a9, 0x345, 0xb4, 0x2002, 0x2003, 0x3a9,
+ 0x4b, 0x41, 0x30a, 0x2190, 0x338, 0x2192, 0x338, 0x2194,
+ 0x338, 0x21d0, 0x338, 0x21d4, 0x338, 0x21d2, 0x338, 0x2203,
+ 0x338, 0x2208, 0x338, 0x220b, 0x338, 0x2223, 0x338, 0x2225,
+ 0x338, 0x223c, 0x338, 0x2243, 0x338, 0x2245, 0x338, 0x2248,
+ 0x338, 0x3d, 0x338, 0x2261, 0x338, 0x224d, 0x338, 0x3c,
+ 0x338, 0x3e, 0x338, 0x2264, 0x338, 0x2265, 0x338, 0x2272,
+ 0x338, 0x2273, 0x338, 0x2276, 0x338, 0x2277, 0x338, 0x227a,
+ 0x338, 0x227b, 0x338, 0x2282, 0x338, 0x2283, 0x338, 0x2286,
+ 0x338, 0x2287, 0x338, 0x22a2, 0x338, 0x22a8, 0x338, 0x22a9,
+ 0x338, 0x22ab, 0x338, 0x227c, 0x338, 0x227d, 0x338, 0x2291,
+ 0x338, 0x2292, 0x338, 0x22b2, 0x338, 0x22b3, 0x338, 0x22b4,
+ 0x338, 0x22b5, 0x338, 0x3008, 0x3009, 0x2add, 0x338, 0x304b,
+ 0x3099, 0x304d, 0x3099, 0x304f, 0x3099, 0x3051, 0x3099, 0x3053,
+ 0x3099, 0x3055, 0x3099, 0x3057, 0x3099, 0x3059, 0x3099, 0x305b,
+ 0x3099, 0x305d, 0x3099, 0x305f, 0x3099, 0x3061, 0x3099, 0x3064,
+ 0x3099, 0x3066, 0x3099, 0x3068, 0x3099, 0x306f, 0x3099, 0x306f,
+ 0x309a, 0x3072, 0x3099, 0x3072, 0x309a, 0x3075, 0x3099, 0x3075,
+ 0x309a, 0x3078, 0x3099, 0x3078, 0x309a, 0x307b, 0x3099, 0x307b,
+ 0x309a, 0x3046, 0x3099, 0x309d, 0x3099, 0x30ab, 0x3099, 0x30ad,
+ 0x3099, 0x30af, 0x3099, 0x30b1, 0x3099, 0x30b3, 0x3099, 0x30b5,
+ 0x3099, 0x30b7, 0x3099, 0x30b9, 0x3099, 0x30bb, 0x3099, 0x30bd,
+ 0x3099, 0x30bf, 0x3099, 0x30c1, 0x3099, 0x30c4, 0x3099, 0x30c6,
+ 0x3099, 0x30c8, 0x3099, 0x30cf, 0x3099, 0x30cf, 0x309a, 0x30d2,
+ 0x3099, 0x30d2, 0x309a, 0x30d5, 0x3099, 0x30d5, 0x309a, 0x30d8,
+ 0x3099, 0x30d8, 0x309a, 0x30db, 0x3099, 0x30db, 0x309a, 0x30a6,
+ 0x3099, 0x30ef, 0x3099, 0x30f0, 0x3099, 0x30f1, 0x3099, 0x30f2,
+ 0x3099, 0x30fd, 0x3099, 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1,
+ 0x4e32, 0x53e5, 0x9f9c, 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948,
+ 0x61f6, 0x7669, 0x7f85, 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02,
+ 0x6d1b, 0x70d9, 0x73de, 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375,
+ 0x6b04, 0x721b, 0x862d, 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964,
+ 0x62c9, 0x81d8, 0x881f, 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x90ce,
+ 0x4f86, 0x51b7, 0x52de, 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001,
+ 0x8606, 0x865c, 0x8def, 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f,
+ 0x7da0, 0x83c9, 0x9304, 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60,
+ 0x807e, 0x7262, 0x78ca, 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13,
+ 0x6dda, 0x6f0f, 0x7d2f, 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc,
+ 0x51cc, 0x7a1c, 0x7dbe, 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02,
+ 0x8afe, 0x4e39, 0x5be7, 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb,
+ 0x4fbf, 0x5fa9, 0x4e0d, 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e,
+ 0x7701, 0x8449, 0x8aaa, 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5,
+ 0x63a0, 0x7565, 0x4eae, 0x5169, 0x51c9, 0x6881, 0x7ce7, 0x826f,
+ 0x8ad2, 0x91cf, 0x52f5, 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe,
+ 0x792a, 0x95ad, 0x9a6a, 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77,
+ 0x8f62, 0x5e74, 0x6190, 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489,
+ 0x79ca, 0x7df4, 0x806f, 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217,
+ 0x52a3, 0x54bd, 0x70c8, 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b,
+ 0x6bae, 0x7c3e, 0x7375, 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c,
+ 0x73b2, 0x7469, 0x7f9a, 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818,
+ 0x4f8b, 0x79ae, 0x91b4, 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee,
+ 0x5c3f, 0x6599, 0x6a02, 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d,
+ 0x6688, 0x962e, 0x5289, 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409,
+ 0x7559, 0x786b, 0x7d10, 0x985e, 0x516d, 0x622e, 0x9678, 0x502b,
+ 0x5d19, 0x6dea, 0x8f2a, 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686,
+ 0x5229, 0x540f, 0x5c65, 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406,
+ 0x75e2, 0x7f79, 0x88cf, 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba,
+ 0x541d, 0x71d0, 0x7498, 0x85fa, 0x96a3, 0x9c57, 0x9e9f, 0x6797,
+ 0x6dcb, 0x81e8, 0x7acb, 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58,
+ 0x4ec0, 0x8336, 0x523a, 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85,
+ 0x6d1e, 0x66b4, 0x8f3b, 0x884c, 0x964d, 0x898b, 0x5ed3, 0x5140,
+ 0x55c0, 0x585a, 0x6674, 0x51de, 0x732a, 0x76ca, 0x793c, 0x795e,
+ 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x8612, 0x8af8, 0x9038,
+ 0x90fd, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x4fae, 0x50e7, 0x514d,
+ 0x52c9, 0x52e4, 0x5351, 0x559d, 0x5606, 0x5668, 0x5840, 0x58a8,
+ 0x5c64, 0x5c6e, 0x6094, 0x6168, 0x618e, 0x61f2, 0x654f, 0x65e2,
+ 0x6691, 0x6885, 0x6d77, 0x6e1a, 0x6f22, 0x716e, 0x722b, 0x7422,
+ 0x7891, 0x793e, 0x7949, 0x7948, 0x7950, 0x7956, 0x795d, 0x798d,
+ 0x798e, 0x7a40, 0x7a81, 0x7bc0, 0x7df4, 0x7e09, 0x7e41, 0x7f72,
+ 0x8005, 0x81ed, 0x8279, 0x8279, 0x8457, 0x8910, 0x8996, 0x8b01,
+ 0x8b39, 0x8cd3, 0x8d08, 0x8fb6, 0x9038, 0x96e3, 0x97ff, 0x983b,
+ 0x5d9, 0x5b4, 0x5f2, 0x5b7, 0x5e9, 0x5c1, 0x5e9, 0x5c2,
+ 0x5e9, 0x5bc, 0x5c1, 0x5e9, 0x5bc, 0x5c2, 0x5d0, 0x5b7,
+ 0x5d0, 0x5b8, 0x5d0, 0x5bc, 0x5d1, 0x5bc, 0x5d2, 0x5bc,
+ 0x5d3, 0x5bc, 0x5d4, 0x5bc, 0x5d5, 0x5bc, 0x5d6, 0x5bc,
+ 0x5d8, 0x5bc, 0x5d9, 0x5bc, 0x5da, 0x5bc, 0x5db, 0x5bc,
+ 0x5dc, 0x5bc, 0x5de, 0x5bc, 0x5e0, 0x5bc, 0x5e1, 0x5bc,
+ 0x5e3, 0x5bc, 0x5e4, 0x5bc, 0x5e6, 0x5bc, 0x5e7, 0x5bc,
+ 0x5e8, 0x5bc, 0x5e9, 0x5bc, 0x5ea, 0x5bc, 0x5d5, 0x5b9,
+ 0x5d1, 0x5bf, 0x5db, 0x5bf, 0x5e4, 0x5bf, 0x1d157, 0x1d165,
+ 0x1d158, 0x1d165, 0x1d158, 0x1d165, 0x1d16e, 0x1d158, 0x1d165, 0x1d16f,
+ 0x1d158, 0x1d165, 0x1d170, 0x1d158, 0x1d165, 0x1d171, 0x1d158, 0x1d165,
+ 0x1d172, 0x1d1b9, 0x1d165, 0x1d1ba, 0x1d165, 0x1d1b9, 0x1d165, 0x1d16e,
+ 0x1d1ba, 0x1d165, 0x1d16e, 0x1d1b9, 0x1d165, 0x1d16f, 0x1d1ba, 0x1d165,
+ 0x1d16f, 0x4e3d, 0x4e38, 0x4e41, 0x20122, 0x4f60, 0x4fae, 0x4fbb,
+ 0x5002, 0x507a, 0x5099, 0x50e7, 0x50cf, 0x349e, 0x2063a, 0x514d,
+ 0x5154, 0x5164, 0x5177, 0x2051c, 0x34b9, 0x5167, 0x518d, 0x2054b,
+ 0x5197, 0x51a4, 0x4ecc, 0x51ac, 0x51b5, 0x291df, 0x51f5, 0x5203,
+ 0x34df, 0x523b, 0x5246, 0x5272, 0x5277, 0x3515, 0x52c7, 0x52c9,
+ 0x52e4, 0x52fa, 0x5305, 0x5306, 0x5317, 0x5349, 0x5351, 0x535a,
+ 0x5373, 0x537d, 0x537f, 0x537f, 0x537f, 0x20a2c, 0x7070, 0x53ca,
+ 0x53df, 0x20b63, 0x53eb, 0x53f1, 0x5406, 0x549e, 0x5438, 0x5448,
+ 0x5468, 0x54a2, 0x54f6, 0x5510, 0x5553, 0x5563, 0x5584, 0x5584,
+ 0x5599, 0x55ab, 0x55b3, 0x55c2, 0x5716, 0x5606, 0x5717, 0x5651,
+ 0x5674, 0x5207, 0x58ee, 0x57ce, 0x57f4, 0x580d, 0x578b, 0x5832,
+ 0x5831, 0x58ac, 0x214e4, 0x58f2, 0x58f7, 0x5906, 0x591a, 0x5922,
+ 0x5962, 0x216a8, 0x216ea, 0x59ec, 0x5a1b, 0x5a27, 0x59d8, 0x5a66,
+ 0x36ee, 0x36fc, 0x5b08, 0x5b3e, 0x5b3e, 0x219c8, 0x5bc3, 0x5bd8,
+ 0x5be7, 0x5bf3, 0x21b18, 0x5bff, 0x5c06, 0x5f53, 0x5c22, 0x3781,
+ 0x5c60, 0x5c6e, 0x5cc0, 0x5c8d, 0x21de4, 0x5d43, 0x21de6, 0x5d6e,
+ 0x5d6b, 0x5d7c, 0x5de1, 0x5de2, 0x382f, 0x5dfd, 0x5e28, 0x5e3d,
+ 0x5e69, 0x3862, 0x22183, 0x387c, 0x5eb0, 0x5eb3, 0x5eb6, 0x5eca,
+ 0x2a392, 0x5efe, 0x22331, 0x22331, 0x8201, 0x5f22, 0x5f22, 0x38c7,
+ 0x232b8, 0x261da, 0x5f62, 0x5f6b, 0x38e3, 0x5f9a, 0x5fcd, 0x5fd7,
+ 0x5ff9, 0x6081, 0x393a, 0x391c, 0x6094, 0x226d4, 0x60c7, 0x6148,
+ 0x614c, 0x614e, 0x614c, 0x617a, 0x618e, 0x61b2, 0x61a4, 0x61af,
+ 0x61de, 0x61f2, 0x61f6, 0x6210, 0x621b, 0x625d, 0x62b1, 0x62d4,
+ 0x6350, 0x22b0c, 0x633d, 0x62fc, 0x6368, 0x6383, 0x63e4, 0x22bf1,
+ 0x6422, 0x63c5, 0x63a9, 0x3a2e, 0x6469, 0x647e, 0x649d, 0x6477,
+ 0x3a6c, 0x654f, 0x656c, 0x2300a, 0x65e3, 0x66f8, 0x6649, 0x3b19,
+ 0x6691, 0x3b08, 0x3ae4, 0x5192, 0x5195, 0x6700, 0x669c, 0x80ad,
+ 0x43d9, 0x6717, 0x671b, 0x6721, 0x675e, 0x6753, 0x233c3, 0x3b49,
+ 0x67fa, 0x6785, 0x6852, 0x6885, 0x2346d, 0x688e, 0x681f, 0x6914,
+ 0x3b9d, 0x6942, 0x69a3, 0x69ea, 0x6aa8, 0x236a3, 0x6adb, 0x3c18,
+ 0x6b21, 0x238a7, 0x6b54, 0x3c4e, 0x6b72, 0x6b9f, 0x6bba, 0x6bbb,
+ 0x23a8d, 0x21d0b, 0x23afa, 0x6c4e, 0x23cbc, 0x6cbf, 0x6ccd, 0x6c67,
+ 0x6d16, 0x6d3e, 0x6d77, 0x6d41, 0x6d69, 0x6d78, 0x6d85, 0x23d1e,
+ 0x6d34, 0x6e2f, 0x6e6e, 0x3d33, 0x6ecb, 0x6ec7, 0x23ed1, 0x6df9,
+ 0x6f6e, 0x23f5e, 0x23f8e, 0x6fc6, 0x7039, 0x701e, 0x701b, 0x3d96,
+ 0x704a, 0x707d, 0x7077, 0x70ad, 0x20525, 0x7145, 0x24263, 0x719c,
+ 0x243ab, 0x7228, 0x7235, 0x7250, 0x24608, 0x7280, 0x7295, 0x24735,
+ 0x24814, 0x737a, 0x738b, 0x3eac, 0x73a5, 0x3eb8, 0x3eb8, 0x7447,
+ 0x745c, 0x7471, 0x7485, 0x74ca, 0x3f1b, 0x7524, 0x24c36, 0x753e,
+ 0x24c92, 0x7570, 0x2219f, 0x7610, 0x24fa1, 0x24fb8, 0x25044, 0x3ffc,
+ 0x4008, 0x76f4, 0x250f3, 0x250f2, 0x25119, 0x25133, 0x771e, 0x771f,
+ 0x771f, 0x774a, 0x4039, 0x778b, 0x4046, 0x4096, 0x2541d, 0x784e,
+ 0x788c, 0x78cc, 0x40e3, 0x25626, 0x7956, 0x2569a, 0x256c5, 0x798f,
+ 0x79eb, 0x412f, 0x7a40, 0x7a4a, 0x7a4f, 0x2597c, 0x25aa7, 0x25aa7,
+ 0x7aee, 0x4202, 0x25bab, 0x7bc6, 0x7bc9, 0x4227, 0x25c80, 0x7cd2,
+ 0x42a0, 0x7ce8, 0x7ce3, 0x7d00, 0x25f86, 0x7d63, 0x4301, 0x7dc7,
+ 0x7e02, 0x7e45, 0x4334, 0x26228, 0x26247, 0x4359, 0x262d9, 0x7f7a,
+ 0x2633e, 0x7f95, 0x7ffa, 0x8005, 0x264da, 0x26523, 0x8060, 0x265a8,
+ 0x8070, 0x2335f, 0x43d5, 0x80b2, 0x8103, 0x440b, 0x813e, 0x5ab5,
+ 0x267a7, 0x267b5, 0x23393, 0x2339c, 0x8201, 0x8204, 0x8f9e, 0x446b,
+ 0x8291, 0x828b, 0x829d, 0x52b3, 0x82b1, 0x82b3, 0x82bd, 0x82e6,
+ 0x26b3c, 0x82e5, 0x831d, 0x8363, 0x83ad, 0x8323, 0x83bd, 0x83e7,
+ 0x8457, 0x8353, 0x83ca, 0x83cc, 0x83dc, 0x26c36, 0x26d6b, 0x26cd5,
+ 0x452b, 0x84f1, 0x84f3, 0x8516, 0x273ca, 0x8564, 0x26f2c, 0x455d,
+ 0x4561, 0x26fb1, 0x270d2, 0x456b, 0x8650, 0x865c, 0x8667, 0x8669,
+ 0x86a9, 0x8688, 0x870e, 0x86e2, 0x8779, 0x8728, 0x876b, 0x8786,
+ 0x45d7, 0x87e1, 0x8801, 0x45f9, 0x8860, 0x8863, 0x27667, 0x88d7,
+ 0x88de, 0x4635, 0x88fa, 0x34bb, 0x278ae, 0x27966, 0x46be, 0x46c7,
+ 0x8aa0, 0x8aed, 0x8b8a, 0x8c55, 0x27ca8, 0x8cab, 0x8cc1, 0x8d1b,
+ 0x8d77, 0x27f2f, 0x20804, 0x8dcb, 0x8dbc, 0x8df0, 0x208de, 0x8ed4,
+ 0x8f38, 0x285d2, 0x285ed, 0x9094, 0x90f1, 0x9111, 0x2872e, 0x911b,
+ 0x9238, 0x92d7, 0x92d8, 0x927c, 0x93f9, 0x9415, 0x28bfa, 0x958b,
+ 0x4995, 0x95b7, 0x28d77, 0x49e6, 0x96c3, 0x5db2, 0x9723, 0x29145,
+ 0x2921a, 0x4a6e, 0x4a76, 0x97e0, 0x2940a, 0x4ab2, 0x29496, 0x980b,
+ 0x980b, 0x9829, 0x295b6, 0x98e2, 0x4b33, 0x9929, 0x99a7, 0x99c2,
+ 0x99fe, 0x4bce, 0x29b30, 0x9b12, 0x9c40, 0x9cfd, 0x4cce, 0x4ced,
+ 0x9d67, 0x2a0ce, 0x4cf8, 0x2a105, 0x2a20e, 0x2a291, 0x9ebb, 0x4d56,
+ 0x9ef9, 0x9efe, 0x9f05, 0x9f0f, 0x9f16, 0x9f3b, 0x2a600, };
+
+gli_decomp_block_t unigen_decomp_block_0x0[256] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 0 },
+ { 2, 2 },
+ { 2, 4 },
+ { 2, 6 },
+ { 2, 8 },
+ { 2, 10 },
+ { 0, 0 },
+ { 2, 12 },
+ { 2, 14 },
+ { 2, 16 },
+ { 2, 18 },
+ { 2, 20 },
+ { 2, 22 },
+ { 2, 24 },
+ { 2, 26 },
+ { 2, 28 },
+ { 0, 0 },
+ { 2, 30 },
+ { 2, 32 },
+ { 2, 34 },
+ { 2, 36 },
+ { 2, 38 },
+ { 2, 40 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 42 },
+ { 2, 44 },
+ { 2, 46 },
+ { 2, 48 },
+ { 2, 50 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 52 },
+ { 2, 54 },
+ { 2, 56 },
+ { 2, 58 },
+ { 2, 60 },
+ { 2, 62 },
+ { 0, 0 },
+ { 2, 64 },
+ { 2, 66 },
+ { 2, 68 },
+ { 2, 70 },
+ { 2, 72 },
+ { 2, 74 },
+ { 2, 76 },
+ { 2, 78 },
+ { 2, 80 },
+ { 0, 0 },
+ { 2, 82 },
+ { 2, 84 },
+ { 2, 86 },
+ { 2, 88 },
+ { 2, 90 },
+ { 2, 92 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 94 },
+ { 2, 96 },
+ { 2, 98 },
+ { 2, 100 },
+ { 2, 102 },
+ { 0, 0 },
+ { 2, 104 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x1[256] = {
+ { 2, 106 },
+ { 2, 108 },
+ { 2, 110 },
+ { 2, 112 },
+ { 2, 114 },
+ { 2, 116 },
+ { 2, 118 },
+ { 2, 120 },
+ { 2, 122 },
+ { 2, 124 },
+ { 2, 126 },
+ { 2, 128 },
+ { 2, 130 },
+ { 2, 132 },
+ { 2, 134 },
+ { 2, 136 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 138 },
+ { 2, 140 },
+ { 2, 142 },
+ { 2, 144 },
+ { 2, 146 },
+ { 2, 148 },
+ { 2, 150 },
+ { 2, 152 },
+ { 2, 154 },
+ { 2, 156 },
+ { 2, 158 },
+ { 2, 160 },
+ { 2, 162 },
+ { 2, 164 },
+ { 2, 166 },
+ { 2, 168 },
+ { 2, 170 },
+ { 2, 172 },
+ { 2, 174 },
+ { 2, 176 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 178 },
+ { 2, 180 },
+ { 2, 182 },
+ { 2, 184 },
+ { 2, 186 },
+ { 2, 188 },
+ { 2, 190 },
+ { 2, 192 },
+ { 2, 194 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 196 },
+ { 2, 198 },
+ { 2, 200 },
+ { 2, 202 },
+ { 0, 0 },
+ { 2, 204 },
+ { 2, 206 },
+ { 2, 208 },
+ { 2, 210 },
+ { 2, 212 },
+ { 2, 214 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 216 },
+ { 2, 218 },
+ { 2, 220 },
+ { 2, 222 },
+ { 2, 224 },
+ { 2, 226 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 228 },
+ { 2, 230 },
+ { 2, 232 },
+ { 2, 234 },
+ { 2, 236 },
+ { 2, 238 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 240 },
+ { 2, 242 },
+ { 2, 244 },
+ { 2, 246 },
+ { 2, 248 },
+ { 2, 250 },
+ { 2, 252 },
+ { 2, 254 },
+ { 2, 256 },
+ { 2, 258 },
+ { 2, 260 },
+ { 2, 262 },
+ { 2, 264 },
+ { 2, 266 },
+ { 2, 268 },
+ { 2, 270 },
+ { 2, 272 },
+ { 2, 274 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 276 },
+ { 2, 278 },
+ { 2, 280 },
+ { 2, 282 },
+ { 2, 284 },
+ { 2, 286 },
+ { 2, 288 },
+ { 2, 290 },
+ { 2, 292 },
+ { 2, 294 },
+ { 2, 296 },
+ { 2, 298 },
+ { 2, 300 },
+ { 2, 302 },
+ { 2, 304 },
+ { 2, 306 },
+ { 2, 308 },
+ { 2, 310 },
+ { 2, 312 },
+ { 2, 314 },
+ { 2, 316 },
+ { 2, 318 },
+ { 2, 320 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 322 },
+ { 2, 324 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 326 },
+ { 2, 328 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 330 },
+ { 2, 332 },
+ { 2, 334 },
+ { 2, 336 },
+ { 2, 338 },
+ { 2, 340 },
+ { 2, 342 },
+ { 2, 344 },
+ { 3, 346 },
+ { 3, 349 },
+ { 3, 352 },
+ { 3, 355 },
+ { 3, 358 },
+ { 3, 361 },
+ { 3, 364 },
+ { 3, 367 },
+ { 0, 0 },
+ { 3, 370 },
+ { 3, 373 },
+ { 3, 376 },
+ { 3, 379 },
+ { 2, 382 },
+ { 2, 384 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 386 },
+ { 2, 388 },
+ { 2, 390 },
+ { 2, 392 },
+ { 2, 394 },
+ { 2, 396 },
+ { 3, 398 },
+ { 3, 401 },
+ { 2, 404 },
+ { 2, 406 },
+ { 2, 408 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 410 },
+ { 2, 412 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 414 },
+ { 2, 416 },
+ { 3, 418 },
+ { 3, 421 },
+ { 2, 424 },
+ { 2, 426 },
+ { 2, 428 },
+ { 2, 430 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x2[256] = {
+ { 2, 432 },
+ { 2, 434 },
+ { 2, 436 },
+ { 2, 438 },
+ { 2, 440 },
+ { 2, 442 },
+ { 2, 444 },
+ { 2, 446 },
+ { 2, 448 },
+ { 2, 450 },
+ { 2, 452 },
+ { 2, 454 },
+ { 2, 456 },
+ { 2, 458 },
+ { 2, 460 },
+ { 2, 462 },
+ { 2, 464 },
+ { 2, 466 },
+ { 2, 468 },
+ { 2, 470 },
+ { 2, 472 },
+ { 2, 474 },
+ { 2, 476 },
+ { 2, 478 },
+ { 2, 480 },
+ { 2, 482 },
+ { 2, 484 },
+ { 2, 486 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 488 },
+ { 2, 490 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 492 },
+ { 2, 494 },
+ { 2, 496 },
+ { 2, 498 },
+ { 3, 500 },
+ { 3, 503 },
+ { 3, 506 },
+ { 3, 509 },
+ { 2, 512 },
+ { 2, 514 },
+ { 3, 516 },
+ { 3, 519 },
+ { 2, 522 },
+ { 2, 524 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x3[256] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 1, 526 },
+ { 1, 527 },
+ { 0, 0 },
+ { 1, 528 },
+ { 2, 529 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 1, 531 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 1, 532 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 533 },
+ { 2, 535 },
+ { 1, 537 },
+ { 2, 538 },
+ { 2, 540 },
+ { 2, 542 },
+ { 0, 0 },
+ { 2, 544 },
+ { 0, 0 },
+ { 2, 546 },
+ { 2, 548 },
+ { 3, 550 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 553 },
+ { 2, 555 },
+ { 2, 557 },
+ { 2, 559 },
+ { 2, 561 },
+ { 2, 563 },
+ { 3, 565 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 568 },
+ { 2, 570 },
+ { 2, 572 },
+ { 2, 574 },
+ { 2, 576 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 578 },
+ { 2, 580 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x4[256] = {
+ { 2, 582 },
+ { 2, 584 },
+ { 0, 0 },
+ { 2, 586 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 588 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 590 },
+ { 2, 592 },
+ { 2, 594 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 596 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 598 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 600 },
+ { 2, 602 },
+ { 0, 0 },
+ { 2, 604 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 606 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 608 },
+ { 2, 610 },
+ { 2, 612 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 614 },
+ { 2, 616 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 618 },
+ { 2, 620 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 622 },
+ { 2, 624 },
+ { 2, 626 },
+ { 2, 628 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 630 },
+ { 2, 632 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 634 },
+ { 2, 636 },
+ { 2, 638 },
+ { 2, 640 },
+ { 2, 642 },
+ { 2, 644 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 646 },
+ { 2, 648 },
+ { 2, 650 },
+ { 2, 652 },
+ { 2, 654 },
+ { 2, 656 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 658 },
+ { 2, 660 },
+ { 2, 662 },
+ { 2, 664 },
+ { 2, 666 },
+ { 2, 668 },
+ { 2, 670 },
+ { 2, 672 },
+ { 2, 674 },
+ { 2, 676 },
+ { 2, 678 },
+ { 2, 680 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 682 },
+ { 2, 684 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x1e[256] = {
+ { 2, 828 },
+ { 2, 830 },
+ { 2, 832 },
+ { 2, 834 },
+ { 2, 836 },
+ { 2, 838 },
+ { 2, 840 },
+ { 2, 842 },
+ { 3, 844 },
+ { 3, 847 },
+ { 2, 850 },
+ { 2, 852 },
+ { 2, 854 },
+ { 2, 856 },
+ { 2, 858 },
+ { 2, 860 },
+ { 2, 862 },
+ { 2, 864 },
+ { 2, 866 },
+ { 2, 868 },
+ { 3, 870 },
+ { 3, 873 },
+ { 3, 876 },
+ { 3, 879 },
+ { 2, 882 },
+ { 2, 884 },
+ { 2, 886 },
+ { 2, 888 },
+ { 3, 890 },
+ { 3, 893 },
+ { 2, 896 },
+ { 2, 898 },
+ { 2, 900 },
+ { 2, 902 },
+ { 2, 904 },
+ { 2, 906 },
+ { 2, 908 },
+ { 2, 910 },
+ { 2, 912 },
+ { 2, 914 },
+ { 2, 916 },
+ { 2, 918 },
+ { 2, 920 },
+ { 2, 922 },
+ { 2, 924 },
+ { 2, 926 },
+ { 3, 928 },
+ { 3, 931 },
+ { 2, 934 },
+ { 2, 936 },
+ { 2, 938 },
+ { 2, 940 },
+ { 2, 942 },
+ { 2, 944 },
+ { 2, 946 },
+ { 2, 948 },
+ { 3, 950 },
+ { 3, 953 },
+ { 2, 956 },
+ { 2, 958 },
+ { 2, 960 },
+ { 2, 962 },
+ { 2, 964 },
+ { 2, 966 },
+ { 2, 968 },
+ { 2, 970 },
+ { 2, 972 },
+ { 2, 974 },
+ { 2, 976 },
+ { 2, 978 },
+ { 2, 980 },
+ { 2, 982 },
+ { 2, 984 },
+ { 2, 986 },
+ { 2, 988 },
+ { 2, 990 },
+ { 3, 992 },
+ { 3, 995 },
+ { 3, 998 },
+ { 3, 1001 },
+ { 3, 1004 },
+ { 3, 1007 },
+ { 3, 1010 },
+ { 3, 1013 },
+ { 2, 1016 },
+ { 2, 1018 },
+ { 2, 1020 },
+ { 2, 1022 },
+ { 2, 1024 },
+ { 2, 1026 },
+ { 2, 1028 },
+ { 2, 1030 },
+ { 3, 1032 },
+ { 3, 1035 },
+ { 2, 1038 },
+ { 2, 1040 },
+ { 2, 1042 },
+ { 2, 1044 },
+ { 2, 1046 },
+ { 2, 1048 },
+ { 3, 1050 },
+ { 3, 1053 },
+ { 3, 1056 },
+ { 3, 1059 },
+ { 3, 1062 },
+ { 3, 1065 },
+ { 2, 1068 },
+ { 2, 1070 },
+ { 2, 1072 },
+ { 2, 1074 },
+ { 2, 1076 },
+ { 2, 1078 },
+ { 2, 1080 },
+ { 2, 1082 },
+ { 2, 1084 },
+ { 2, 1086 },
+ { 2, 1088 },
+ { 2, 1090 },
+ { 2, 1092 },
+ { 2, 1094 },
+ { 3, 1096 },
+ { 3, 1099 },
+ { 3, 1102 },
+ { 3, 1105 },
+ { 2, 1108 },
+ { 2, 1110 },
+ { 2, 1112 },
+ { 2, 1114 },
+ { 2, 1116 },
+ { 2, 1118 },
+ { 2, 1120 },
+ { 2, 1122 },
+ { 2, 1124 },
+ { 2, 1126 },
+ { 2, 1128 },
+ { 2, 1130 },
+ { 2, 1132 },
+ { 2, 1134 },
+ { 2, 1136 },
+ { 2, 1138 },
+ { 2, 1140 },
+ { 2, 1142 },
+ { 2, 1144 },
+ { 2, 1146 },
+ { 2, 1148 },
+ { 2, 1150 },
+ { 2, 1152 },
+ { 2, 1154 },
+ { 2, 1156 },
+ { 2, 1158 },
+ { 2, 1160 },
+ { 2, 1162 },
+ { 2, 1164 },
+ { 2, 1166 },
+ { 0, 0 },
+ { 2, 1168 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1170 },
+ { 2, 1172 },
+ { 2, 1174 },
+ { 2, 1176 },
+ { 3, 1178 },
+ { 3, 1181 },
+ { 3, 1184 },
+ { 3, 1187 },
+ { 3, 1190 },
+ { 3, 1193 },
+ { 3, 1196 },
+ { 3, 1199 },
+ { 3, 1202 },
+ { 3, 1205 },
+ { 3, 1208 },
+ { 3, 1211 },
+ { 3, 1214 },
+ { 3, 1217 },
+ { 3, 1220 },
+ { 3, 1223 },
+ { 3, 1226 },
+ { 3, 1229 },
+ { 3, 1232 },
+ { 3, 1235 },
+ { 2, 1238 },
+ { 2, 1240 },
+ { 2, 1242 },
+ { 2, 1244 },
+ { 2, 1246 },
+ { 2, 1248 },
+ { 3, 1250 },
+ { 3, 1253 },
+ { 3, 1256 },
+ { 3, 1259 },
+ { 3, 1262 },
+ { 3, 1265 },
+ { 3, 1268 },
+ { 3, 1271 },
+ { 3, 1274 },
+ { 3, 1277 },
+ { 2, 1280 },
+ { 2, 1282 },
+ { 2, 1284 },
+ { 2, 1286 },
+ { 2, 1288 },
+ { 2, 1290 },
+ { 2, 1292 },
+ { 2, 1294 },
+ { 3, 1296 },
+ { 3, 1299 },
+ { 3, 1302 },
+ { 3, 1305 },
+ { 3, 1308 },
+ { 3, 1311 },
+ { 3, 1314 },
+ { 3, 1317 },
+ { 3, 1320 },
+ { 3, 1323 },
+ { 3, 1326 },
+ { 3, 1329 },
+ { 3, 1332 },
+ { 3, 1335 },
+ { 3, 1338 },
+ { 3, 1341 },
+ { 3, 1344 },
+ { 3, 1347 },
+ { 3, 1350 },
+ { 3, 1353 },
+ { 2, 1356 },
+ { 2, 1358 },
+ { 2, 1360 },
+ { 2, 1362 },
+ { 3, 1364 },
+ { 3, 1367 },
+ { 3, 1370 },
+ { 3, 1373 },
+ { 3, 1376 },
+ { 3, 1379 },
+ { 3, 1382 },
+ { 3, 1385 },
+ { 3, 1388 },
+ { 3, 1391 },
+ { 2, 1394 },
+ { 2, 1396 },
+ { 2, 1398 },
+ { 2, 1400 },
+ { 2, 1402 },
+ { 2, 1404 },
+ { 2, 1406 },
+ { 2, 1408 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x1f[256] = {
+ { 2, 1410 },
+ { 2, 1412 },
+ { 3, 1414 },
+ { 3, 1417 },
+ { 3, 1420 },
+ { 3, 1423 },
+ { 3, 1426 },
+ { 3, 1429 },
+ { 2, 1432 },
+ { 2, 1434 },
+ { 3, 1436 },
+ { 3, 1439 },
+ { 3, 1442 },
+ { 3, 1445 },
+ { 3, 1448 },
+ { 3, 1451 },
+ { 2, 1454 },
+ { 2, 1456 },
+ { 3, 1458 },
+ { 3, 1461 },
+ { 3, 1464 },
+ { 3, 1467 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1470 },
+ { 2, 1472 },
+ { 3, 1474 },
+ { 3, 1477 },
+ { 3, 1480 },
+ { 3, 1483 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1486 },
+ { 2, 1488 },
+ { 3, 1490 },
+ { 3, 1493 },
+ { 3, 1496 },
+ { 3, 1499 },
+ { 3, 1502 },
+ { 3, 1505 },
+ { 2, 1508 },
+ { 2, 1510 },
+ { 3, 1512 },
+ { 3, 1515 },
+ { 3, 1518 },
+ { 3, 1521 },
+ { 3, 1524 },
+ { 3, 1527 },
+ { 2, 1530 },
+ { 2, 1532 },
+ { 3, 1534 },
+ { 3, 1537 },
+ { 3, 1540 },
+ { 3, 1543 },
+ { 3, 1546 },
+ { 3, 1549 },
+ { 2, 1552 },
+ { 2, 1554 },
+ { 3, 1556 },
+ { 3, 1559 },
+ { 3, 1562 },
+ { 3, 1565 },
+ { 3, 1568 },
+ { 3, 1571 },
+ { 2, 1574 },
+ { 2, 1576 },
+ { 3, 1578 },
+ { 3, 1581 },
+ { 3, 1584 },
+ { 3, 1587 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1590 },
+ { 2, 1592 },
+ { 3, 1594 },
+ { 3, 1597 },
+ { 3, 1600 },
+ { 3, 1603 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1606 },
+ { 2, 1608 },
+ { 3, 1610 },
+ { 3, 1613 },
+ { 3, 1616 },
+ { 3, 1619 },
+ { 3, 1622 },
+ { 3, 1625 },
+ { 0, 0 },
+ { 2, 1628 },
+ { 0, 0 },
+ { 3, 1630 },
+ { 0, 0 },
+ { 3, 1633 },
+ { 0, 0 },
+ { 3, 1636 },
+ { 2, 1639 },
+ { 2, 1641 },
+ { 3, 1643 },
+ { 3, 1646 },
+ { 3, 1649 },
+ { 3, 1652 },
+ { 3, 1655 },
+ { 3, 1658 },
+ { 2, 1661 },
+ { 2, 1663 },
+ { 3, 1665 },
+ { 3, 1668 },
+ { 3, 1671 },
+ { 3, 1674 },
+ { 3, 1677 },
+ { 3, 1680 },
+ { 2, 1683 },
+ { 2, 1685 },
+ { 2, 1687 },
+ { 2, 1689 },
+ { 2, 1691 },
+ { 2, 1693 },
+ { 2, 1695 },
+ { 2, 1697 },
+ { 2, 1699 },
+ { 2, 1701 },
+ { 2, 1703 },
+ { 2, 1705 },
+ { 2, 1707 },
+ { 2, 1709 },
+ { 0, 0 },
+ { 0, 0 },
+ { 3, 1711 },
+ { 3, 1714 },
+ { 4, 1717 },
+ { 4, 1721 },
+ { 4, 1725 },
+ { 4, 1729 },
+ { 4, 1733 },
+ { 4, 1737 },
+ { 3, 1741 },
+ { 3, 1744 },
+ { 4, 1747 },
+ { 4, 1751 },
+ { 4, 1755 },
+ { 4, 1759 },
+ { 4, 1763 },
+ { 4, 1767 },
+ { 3, 1771 },
+ { 3, 1774 },
+ { 4, 1777 },
+ { 4, 1781 },
+ { 4, 1785 },
+ { 4, 1789 },
+ { 4, 1793 },
+ { 4, 1797 },
+ { 3, 1801 },
+ { 3, 1804 },
+ { 4, 1807 },
+ { 4, 1811 },
+ { 4, 1815 },
+ { 4, 1819 },
+ { 4, 1823 },
+ { 4, 1827 },
+ { 3, 1831 },
+ { 3, 1834 },
+ { 4, 1837 },
+ { 4, 1841 },
+ { 4, 1845 },
+ { 4, 1849 },
+ { 4, 1853 },
+ { 4, 1857 },
+ { 3, 1861 },
+ { 3, 1864 },
+ { 4, 1867 },
+ { 4, 1871 },
+ { 4, 1875 },
+ { 4, 1879 },
+ { 4, 1883 },
+ { 4, 1887 },
+ { 2, 1891 },
+ { 2, 1893 },
+ { 3, 1895 },
+ { 2, 1898 },
+ { 3, 1900 },
+ { 0, 0 },
+ { 2, 1903 },
+ { 3, 1905 },
+ { 2, 1908 },
+ { 2, 1910 },
+ { 2, 1912 },
+ { 2, 1914 },
+ { 2, 1916 },
+ { 0, 0 },
+ { 1, 1918 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1919 },
+ { 3, 1921 },
+ { 2, 1924 },
+ { 3, 1926 },
+ { 0, 0 },
+ { 2, 1929 },
+ { 3, 1931 },
+ { 2, 1934 },
+ { 2, 1936 },
+ { 2, 1938 },
+ { 2, 1940 },
+ { 2, 1942 },
+ { 2, 1944 },
+ { 2, 1946 },
+ { 2, 1948 },
+ { 2, 1950 },
+ { 2, 1952 },
+ { 3, 1954 },
+ { 3, 1957 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 1960 },
+ { 3, 1962 },
+ { 2, 1965 },
+ { 2, 1967 },
+ { 2, 1969 },
+ { 2, 1971 },
+ { 0, 0 },
+ { 2, 1973 },
+ { 2, 1975 },
+ { 2, 1977 },
+ { 2, 1979 },
+ { 2, 1981 },
+ { 3, 1983 },
+ { 3, 1986 },
+ { 2, 1989 },
+ { 2, 1991 },
+ { 2, 1993 },
+ { 3, 1995 },
+ { 2, 1998 },
+ { 2, 2000 },
+ { 2, 2002 },
+ { 2, 2004 },
+ { 2, 2006 },
+ { 2, 2008 },
+ { 2, 2010 },
+ { 1, 2012 },
+ { 0, 0 },
+ { 0, 0 },
+ { 3, 2013 },
+ { 2, 2016 },
+ { 3, 2018 },
+ { 0, 0 },
+ { 2, 2021 },
+ { 3, 2023 },
+ { 2, 2026 },
+ { 2, 2028 },
+ { 2, 2030 },
+ { 2, 2032 },
+ { 2, 2034 },
+ { 1, 2036 },
+ { 0, 0 },
+ { 0, 0 },
+};
+
+gli_decomp_block_t unigen_decomp_block_0x22[256] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 2055 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 2057 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 2059 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 2, 2061 },
+ { 0, 0 },
+ { 2, 2063 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
Commit: 743660448317ac0a0e806f27945fe75e358e2b3d
https://github.com/scummvm/scummvm/commit/743660448317ac0a0e806f27945fe75e358e2b3d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added time and date glk functions
Changed paths:
A engines/gargoyle/time.cpp
A engines/gargoyle/time.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index c385482..f1b24cb 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -857,11 +857,12 @@ void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
}
void Glk::glk_set_hyperlink(glui32 linkval) {
- // TODO
+ _streams->getCurrent()->setHyperlink(linkval);
}
void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
- // TODO
+ if (str)
+ str->setHyperlink(linkval);
}
void Glk::glk_request_hyperlink_event(winid_t win) {
@@ -873,50 +874,64 @@ void Glk::glk_request_hyperlink_event(winid_t win) {
}
void Glk::glk_cancel_hyperlink_event(winid_t win) {
- // TODO
+ if (win) {
+ win->cancelHyperlinkEvent();
+ } else {
+ warning("cancel_hyperlink_event: invalid ref");
+ }
}
void Glk::glk_current_time(glktimeval_t *time) {
- // TODO
+ TimeAndDate td;
+ *time = td;
}
glsi32 Glk::glk_current_simple_time(glui32 factor) {
- // TODO
- return 0;
+ assert(factor);
+ TimeAndDate td;
+
+ return td / factor;
}
-void Glk::glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date) {
- // TODO
+void Glk::glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date) {
+ // TODO: timezones aren't currently supported
+ *date = TimeAndDate(*time);
}
-void Glk::glk_time_to_date_local(glktimeval_t *time, glkdate_t *date) {
- // TODO
+void Glk::glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date) {
+ *date = TimeAndDate(*time);
}
void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
- // TODO
+ TimeSeconds secs = (int64)time * factor;
+ *date = TimeAndDate(secs);
}
void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
- // TODO
+ TimeSeconds secs = (int64)time * factor;
+ *date = TimeAndDate(secs);
}
-void Glk::glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time) {
- // TODO
+void Glk::glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time) {
+ // TODO: timezones aren't currently supported
+ *time = TimeAndDate(*date);
}
-void Glk::glk_date_to_time_local(glkdate_t *date, glktimeval_t *time) {
- // TODO
+void Glk::glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time) {
+ *time = TimeAndDate(*date);
}
-glsi32 Glk::glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor) {
- // TODO
- return 0;
+glsi32 Glk::glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor) {
+ // TODO: timezones aren't currently supported
+ assert(factor);
+ TimeSeconds ts = TimeAndDate(*date);
+ return ts / factor;
}
-glsi32 Glk::glk_date_to_simple_time_local(glkdate_t *date, glui32 factor) {
- // TODO
- return 0;
+glsi32 Glk::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor) {
+ assert(factor);
+ TimeSeconds ts = TimeAndDate(*date);
+ return ts / factor;
}
/* XXX non-official Glk functions that may or may not exist */
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 34531c0..cf06474 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -25,11 +25,11 @@
#include "gargoyle/gargoyle.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/time.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
-
/**
* Implements the GLK interface
*/
@@ -257,16 +257,14 @@ public:
void glk_current_time(glktimeval_t *time);
glsi32 glk_current_simple_time(glui32 factor);
- void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
- void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);
- void glk_simple_time_to_date_utc(glsi32 time, glui32 factor,
- glkdate_t *date);
- void glk_simple_time_to_date_local(glsi32 time, glui32 factor,
- glkdate_t *date);
- void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
- void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);
- glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
- glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);
+ void glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date);
+ void glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date);
+ void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date);
+ void glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date);
+ void glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time);
+ void glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time);
+ glsi32 glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor);
+ glsi32 glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor);
#endif /* GLK_MODULE_DATETIME */
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index a521548..274443a 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -215,34 +215,11 @@ enum ImageAlign {
#endif /* GLK_MODULE_IMAGE */
-#ifdef GLK_MODULE_DATETIME
-
-struct glktimeval_struct {
- glsi32 high_sec;
- glui32 low_sec;
- glsi32 microsec;
-};
-typedef glktimeval_struct glktimeval_t;
-
-struct glkdate_struct {
- glsi32 year; ///< full (four-digit) year */
- glsi32 month; ///< 1-12, 1 is January
- glsi32 day; ///< 1-31
- glsi32 weekday; ///< 0-6, 0 is Sunday
- glsi32 hour; ///< 0-23
- glsi32 minute; ///< 0-59
- glsi32 second; ///< 0-59, maybe 60 during a leap second
- glsi32 microsec; ///< 0-999999
-};
-typedef glkdate_struct glkdate_t;
-
union gidispatch_rock_t {
glui32 num;
void *ptr;
};
-#endif /* GLK_MODULE_DATETIME */
-
} // End of namespace Gargoyle
#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index d3cf7a1..b8ef788 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
picture.o \
screen.o \
streams.o \
+ time.o \
unicode.o \
unicode_gen.o \
windows.o \
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 1942ddf..3ebb98b 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -156,6 +156,11 @@ void WindowStream::setStyle(glui32 val) {
_window->_echoStream->setStyle(val);
}
+void WindowStream::setHyperlink(glui32 linkVal) {
+ if (_writable)
+ _window->_attr.hyper = linkVal;
+}
+
/*--------------------------------------------------------------------------*/
MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 77ae8cb..de8b704 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -153,6 +153,10 @@ public:
*/
virtual glui32 getLineUni(glui32 *ubuf, glui32 len) { return 0; }
+ /**
+ * Set a hyperlink
+ */
+ virtual void setHyperlink(glui32 linkVal) {}
};
typedef Stream *strid_t;
@@ -195,6 +199,11 @@ public:
virtual void putBufferUni(const uint32 *buf, size_t len) override;
virtual void setStyle(glui32 val) override;
+
+ /**
+ * Set a hyperlink
+ */
+ virtual void setHyperlink(glui32 linkVal) override;
};
/**
diff --git a/engines/gargoyle/time.cpp b/engines/gargoyle/time.cpp
new file mode 100644
index 0000000..9a99d3b
--- /dev/null
+++ b/engines/gargoyle/time.cpp
@@ -0,0 +1,118 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/time.h"
+#include "common/system.h"
+
+namespace Gargoyle {
+
+TimeAndDate::TimeAndDate() {
+ ::TimeDate t;
+ g_system->getTimeAndDate(t);
+
+ year = t.tm_year;
+ month = t.tm_mon;
+ day = t.tm_mday;
+ weekday = t.tm_wday;
+ hour = t.tm_hour;
+ minute = t.tm_min;
+ second = t.tm_sec;
+ microsec = 0;
+}
+
+TimeAndDate::TimeAndDate(const TimeSeconds &ts) {
+ setTime(ts);
+}
+
+TimeAndDate::TimeAndDate(const Timestamp &t) {
+ setTime(((int64)t.high_sec << 32) | t.low_sec);
+}
+
+TimeAndDate::operator TimeSeconds() const {
+ return getTime();
+}
+
+TimeAndDate::operator Timestamp() const {
+ TimeSeconds secs = getTime();
+ Timestamp ts;
+ ts.high_sec = secs >> 32;
+ ts.low_sec = secs & 0xffffffff;
+ ts.microsec = 0;
+
+ return ts;
+}
+
+void TimeAndDate::setTime(const TimeSeconds &ts) {
+ TimeSeconds total = ts;
+ int daysInYear, secsInYear;
+
+ // Figure out the year
+ this->year = 1969;
+ do {
+ ++this->year;
+ daysInYear = ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 365 : 365;
+ secsInYear = daysInYear * 24 * 60 * 60;
+ } while (total >= daysInYear);
+
+ // Figure out month and day
+ int dayInYear = total / (24 * 60 * 60);
+ total %= 24 * 60 * 60;
+
+ int MONTH_DAYS[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ this->month = 1;
+ while (dayInYear >= MONTH_DAYS[this->month - 1]) {
+ dayInYear -= MONTH_DAYS[this->month - 1];
+ this->month++;
+ }
+
+ this->day = dayInYear + 1;
+
+ // set the time within the day
+ this->hour = total / (60 * 60);
+ total %= (60 * 60);
+ this->minute = total / 60;
+ this->second = total % 60;
+ this->microsec = 0;
+}
+
+TimeSeconds TimeAndDate::getTime() const {
+ uint32 days = day - 1;
+ for (int i = 1970; i < year; ++i)
+ if ((i % 4 == 0 && i % 100 != 0) || (i % 400 == 0))
+ days += 366;
+ else
+ days += 365;
+
+ int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ for (int i = 1; i < month; ++i) {
+ days += mdays[i - 1];
+ if (i == 2)
+ if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
+ days += 1;
+ }
+
+ int64 totalHours = days * 24 + hour;
+ int64 totalMinutes = totalHours * 60 + minute;
+ return totalMinutes * 60 + second;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/time.h b/engines/gargoyle/time.h
new file mode 100644
index 0000000..3e658d2
--- /dev/null
+++ b/engines/gargoyle/time.h
@@ -0,0 +1,93 @@
+/* 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 GARGOYLE_TIME_H
+#define GARGOYLE_TIME_H
+
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+typedef int64 TimeSeconds;
+
+struct Timestamp {
+ glsi32 high_sec;
+ glui32 low_sec;
+ glsi32 microsec;
+};
+typedef Timestamp glktimeval_t;
+
+struct TimeAndDate {
+ glsi32 year; ///< full (four-digit) year
+ glsi32 month; ///< 1-12, 1 is January
+ glsi32 day; ///< 1-31
+ glsi32 weekday; ///< 0-6, 0 is Sunday
+ glsi32 hour; ///< 0-23
+ glsi32 minute; ///< 0-59
+ glsi32 second; ///< 0-59, maybe 60 during a leap second
+ glsi32 microsec; ///< 0-999999
+private:
+ /**
+ * Get the number of seconds since the start of 1970
+ */
+ int64 getSecondsSince1970() const;
+
+ /**
+ * Convert a time in seconds to the structure
+ */
+ void setTime(const TimeSeconds &ts);
+
+ /**
+ * Get time in seconds from the structure
+ */
+ TimeSeconds getTime() const;
+public:
+ /**
+ * Constructor
+ */
+ TimeAndDate();
+
+ /**
+ * Constructor
+ */
+ TimeAndDate(const TimeSeconds &ts);
+
+ /**
+ * Constructor
+ */
+ TimeAndDate(const Timestamp &t);
+
+ /**
+ * Convert to seconds
+ */
+ operator TimeSeconds() const;
+
+ /**
+ * Convert to time stamp
+ */
+ operator Timestamp() const;
+};
+typedef TimeAndDate glkdate_t;
+
+} // End of namespace Gargoyle
+
+#endif
Commit: 76bf2726f804a059d48ead24ecca6e1654fb1fb7
https://github.com/scummvm/scummvm/commit/76bf2726f804a059d48ead24ecca6e1654fb1fb7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added input window focus, and cleanup of event method stubs
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 3373628..a4dadcb 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -24,11 +24,7 @@
namespace Gargoyle {
-void Events::pollEvents() {
- // TODO
-}
-
-void Events::clearEvent(Event *ev) {
+void Events::getEvent(event_t *event, bool polled) {
// TODO
}
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index f49d9ff..6140dc4 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -123,12 +123,13 @@ public:
Events() : _forceClick(false) {}
/**
- * Checks for new events
- */
- void pollEvents();
-
- void clearEvent(Event *ev);
+ * Get any pending event
+ */
+ void getEvent(event_t *event, bool polled);
+ /**
+ * Store an event for retrieval
+ */
void eventStore(EvType type, Window *win, uint32 val1 = 0, uint32 val2 = 0);
};
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index f1b24cb..736ed3e 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -502,20 +502,20 @@ glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
void Glk::glk_select(event_t *event) {
if (!_gliFirstEvent) {
- gliInputGuessFocus();
+ _windows->inputGuessFocus();
_gliFirstEvent = true;
}
- gliSelect(event, false);
+ _events->getEvent(event, false);
}
void Glk::glk_select_poll(event_t *event) {
if (!_gliFirstEvent) {
- gliInputGuessFocus();
+ _windows->inputGuessFocus();
_gliFirstEvent = true;
}
- gliSelect(event, true);
+ _events->getEvent(event, true);
}
void Glk::glk_request_timer_events(glui32 millisecs) {
@@ -881,6 +881,8 @@ void Glk::glk_cancel_hyperlink_event(winid_t win) {
}
}
+/*--------------------------------------------------------------------------*/
+
void Glk::glk_current_time(glktimeval_t *time) {
TimeAndDate td;
*time = td;
@@ -934,6 +936,8 @@ glsi32 Glk::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor)
return ts / factor;
}
+/*--------------------------------------------------------------------------*/
+
/* XXX non-official Glk functions that may or may not exist */
char *garglk_fileref_get_name(frefid_t fref) {
@@ -987,15 +991,4 @@ void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
// TODO
}
-/*--------------------------------------------------------------------------*/
-
-void Glk::gliInputGuessFocus() {
- // TODO
-}
-
-void Glk::gliSelect(event_t *event, bool polled) {
- // TODO
- event->type = evtype_Quit;
-}
-
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index cf06474..6bfffd6 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -38,13 +38,6 @@ private:
bool _gliFirstEvent;
unsigned char _charTolowerTable[256];
unsigned char _charToupperTable[256];
-private:
- /**
- * Pick first window which might want input. This is called after every keystroke.
- */
- void gliInputGuessFocus();
-
- void gliSelect(event_t *event, bool polled);
public:
/**
* Constructor
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 2cfaebd..26244e3 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -716,7 +716,7 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
if (!ev)
ev = &dummyEv;
- g_vm->_events->clearEvent(ev);
+ ev->clear();
if (!_lineRequest && !_lineRequestUni)
return;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 01c3193..4786d02 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -329,7 +329,7 @@ void TextGridWindow::cancelLineEvent(Event *ev) {
if (!ev)
ev = &dummyEv;
- g_vm->_events->clearEvent(ev);
+ ev->clear();
if (!_lineRequest && !_lineRequestUni)
return;
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 2f2008c..19f61ba 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -276,6 +276,24 @@ void Windows::rearrange() {
}
}
+void Windows::inputGuessFocus() {
+ Window *altWin = _focusWin;
+
+ do {
+ if (altWin
+ && (altWin->_lineRequest || altWin->_charRequest ||
+ altWin->_lineRequestUni || altWin->_charRequestUni))
+ break;
+ altWin = iterateTreeOrder(altWin);
+ } while (altWin != _focusWin);
+
+ if (_focusWin != altWin) {
+ _focusWin = altWin;
+ _forceRedraw = true;
+ redraw();
+ }
+}
+
void Windows::selectionChanged() {
_claimSelect = false;
_forceRedraw = true;
@@ -440,7 +458,7 @@ void Window::cancelLineEvent(Event *ev) {
if (!ev)
ev = &dummyEv;
- g_vm->_events->clearEvent(ev);
+ ev->clear();
}
void Window::moveCursor(const Common::Point &newPos) {
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 2c03c15..b0ee311 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -149,6 +149,11 @@ public:
*/
void setFocus(Window *win) { _focusWin = win; }
+ /**
+ * Pick first window which might want input. This is called after every keystroke.
+ */
+ void inputGuessFocus();
+
void selectionChanged();
void clearClaimSelect() { _claimSelect = false; }
Commit: 7bbedcd099dfe552547b97482c1d974318d3ce16
https://github.com/scummvm/scummvm/commit/7bbedcd099dfe552547b97482c1d974318d3ce16
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Beginnings of event handling
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index a4dadcb..6fcf634 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -28,8 +28,36 @@ void Events::getEvent(event_t *event, bool polled) {
// TODO
}
-void Events::eventStore(EvType type, Window *win, uint32 val1, uint32 val2) {
- // TODO
+void Events::store(EvType type, Window *win, uint32 val1, uint32 val2) {
+ Event ev(type, win, val1, val2);
+
+ switch (type) {
+ case evtype_Arrange:
+ case evtype_Redraw:
+ case evtype_SoundNotify:
+ case evtype_Timer:
+ _eventsPolled.push(ev);
+ break;
+
+ default:
+ _eventsLogged.push(ev);
+ break;
+ }
+}
+
+void Events::dispatchEvent(Event &ev, bool polled) {
+ Event dispatch;
+
+ if (!polled) {
+ dispatch = _eventsLogged.retrieve();
+ if (dispatch)
+ dispatch = _eventsPolled.retrieve();
+ } else {
+ dispatch = _eventsPolled.retrieve();
+ }
+
+ if (dispatch)
+ ev = dispatch;
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 6140dc4..54a2774 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -100,7 +100,17 @@ struct Event {
/**
* Constructor
*/
- Event() : type(evtype_None), window(nullptr), val1(0), val2(0) {}
+ Event() { clear(); }
+
+ /**
+ * Constructor
+ */
+ Event(EvType evType, Window *evWindow, uint32 evVal1, uint32 evVal2) {
+ type = evType;
+ window = evWindow;
+ val1 = evVal1;
+ val2 = evVal2;
+ }
/**
* Clear
@@ -110,10 +120,30 @@ struct Event {
window = nullptr;
val1 = val2 = 0;
}
+
+ /**
+ * Boolean cast to allow checking whether event is filled out
+ */
+ operator bool() const { return type != evtype_None; }
};
typedef Event event_t;
+class EventQueue : public Common::Queue<Event> {
+public:
+ /**
+ * Retrieve a pending event, if any
+ */
+ Event retrieve() {
+ return empty() ? Event() : pop();
+ }
+};
+
class Events {
+private:
+ EventQueue _eventsPolled;
+ EventQueue _eventsLogged;
+private:
+ void dispatchEvent(Event &ev, bool polled);
public:
bool _forceClick;
public:
@@ -130,7 +160,7 @@ public:
/**
* Store an event for retrieval
*/
- void eventStore(EvType type, Window *win, uint32 val1 = 0, uint32 val2 = 0);
+ void store(EvType type, Window *win, uint32 val1 = 0, uint32 val2 = 0);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 26244e3..fa8a7cc 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -574,7 +574,7 @@ void TextBufferWindow::click(const Common::Point &newPos) {
if (_hyperRequest) {
glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
if (linkval) {
- g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
+ g_vm->_events->store(evtype_Hyperlink, this, linkval, 0);
_hyperRequest = false;
if (g_conf->_safeClicks)
g_vm->_events->_forceClick = 1;
@@ -1246,7 +1246,7 @@ void TextBufferWindow::acceptReadChar(glui32 arg) {
_charRequest = false;
_charRequestUni = false;
- g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
+ g_vm->_events->store(evtype_CharInput, this, key, 0);
}
void TextBufferWindow::acceptReadLine(glui32 arg) {
@@ -1479,11 +1479,11 @@ void TextBufferWindow::acceptLine(glui32 keycode) {
glui32 val2 = keycode;
if (val2 == keycode_Return)
val2 = 0;
- g_vm->_events->eventStore(evtype_LineInput, this, len, val2);
+ g_vm->_events->store(evtype_LineInput, this, len, val2);
free(_lineTerminators);
_lineTerminators = nullptr;
} else {
- g_vm->_events->eventStore(evtype_LineInput, this, len, 0);
+ g_vm->_events->store(evtype_LineInput, this, len, 0);
}
_lineRequest = false;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 4786d02..e2ee06e 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -198,7 +198,7 @@ void TextGridWindow::click(const Common::Point &newPos) {
_windows->setFocus(this);
if (_mouseRequest) {
- g_vm->_events->eventStore(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
+ g_vm->_events->store(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
_mouseRequest = false;
if (g_conf->_safeClicks)
g_vm->_events->_forceClick = true;
@@ -208,7 +208,7 @@ void TextGridWindow::click(const Common::Point &newPos) {
glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
if (linkval)
{
- g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
+ g_vm->_events->store(evtype_Hyperlink, this, linkval, 0);
_hyperRequest = false;
if (g_conf->_safeClicks)
g_vm->_events->_forceClick = true;
@@ -405,7 +405,7 @@ void TextGridWindow::acceptReadChar(glui32 arg) {
_charRequest = false;
_charRequestUni = false;
- g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
+ g_vm->_events->store(evtype_CharInput, this, key, 0);
}
void TextGridWindow::acceptLine(glui32 keycode) {
@@ -444,11 +444,11 @@ void TextGridWindow::acceptLine(glui32 keycode) {
glui32 val2 = keycode;
if (val2 == keycode_Return)
val2 = 0;
- g_vm->_events->eventStore(evtype_LineInput, this, _inLen, val2);
+ g_vm->_events->store(evtype_LineInput, this, _inLen, val2);
free(_lineTerminators);
_lineTerminators = NULL;
} else {
- g_vm->_events->eventStore(evtype_LineInput, this, _inLen, 0);
+ g_vm->_events->store(evtype_LineInput, this, _inLen, 0);
}
_lineRequest = false;
_lineRequestUni = false;
Commit: 9eb4debd158f0348c9a13f548c788d9f9d721f70
https://github.com/scummvm/scummvm/commit/9eb4debd158f0348c9a13f548c788d9f9d721f70
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Logic for keypress event handling
Changed paths:
A engines/gargoyle/clipboard.cpp
A engines/gargoyle/clipboard.h
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/module.mk
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/clipboard.cpp b/engines/gargoyle/clipboard.cpp
new file mode 100644
index 0000000..ef11d55
--- /dev/null
+++ b/engines/gargoyle/clipboard.cpp
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/clipboard.h"
+
+namespace Gargoyle {
+
+void Clipboard::store(const uint32 *text, size_t len) {
+ // TODO
+}
+
+void Clipboard::send() {
+ // TODO
+}
+
+void Clipboard::receive() {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/clipboard.h b/engines/gargoyle/clipboard.h
new file mode 100644
index 0000000..ccd8d79
--- /dev/null
+++ b/engines/gargoyle/clipboard.h
@@ -0,0 +1,43 @@
+/* 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 GARGOYLE_CLIPBOARD_H
+#define GARGOYLE_CLIPBOARD_H
+
+#include "common/array.h"
+
+namespace Gargoyle {
+
+class Clipboard {
+private:
+ Common::Array<uint32> _text;
+public:
+ void store(const uint32 *text, size_t len);
+
+ void send();
+
+ void receive();
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 6fcf634..00adce8 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -21,11 +21,35 @@
*/
#include "gargoyle/events.h"
+#include "gargoyle/clipboard.h"
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
void Events::getEvent(event_t *event, bool polled) {
- // TODO
+ _currentEvent = event;
+ event->clear();
+
+ Common::Event ev;
+ dispatchEvent(*_currentEvent, polled);
+
+ if (!polled) {
+ while (!g_vm->shouldQuit() && _currentEvent->type == evtype_None && !_timeouts) {
+ pollEvents();
+ g_system->delayMillis(10);
+
+ dispatchEvent(*_currentEvent, polled);
+ }
+ }
+
+ if (_currentEvent->type == evtype_None && _timeouts) {
+ store(evtype_Timer, NULL, 0, 0);
+ dispatchEvent(*_currentEvent, polled);
+ _timeouts = false;
+ }
+
+ _currentEvent = nullptr;
}
void Events::store(EvType type, Window *win, uint32 val1, uint32 val2) {
@@ -60,4 +84,76 @@ void Events::dispatchEvent(Event &ev, bool polled) {
ev = dispatch;
}
+void Events::pollEvents() {
+ Common::Event event;
+
+ do {
+ g_system->getEventManager()->pollEvent(event);
+
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ handleKeyDown(event.kbd);
+ return;
+ default:
+ break;
+ }
+ } while (event.type == Common::EVENT_MOUSEMOVE);
+}
+
+void Events::handleKeyDown(const Common::KeyState &ks) {
+ Clipboard &clipboard = *g_vm->_clipboard;
+ Windows &windows = *g_vm->_windows;
+
+ if (ks.flags & Common::KBD_CTRL) {
+ if (ks.keycode == Common::KEYCODE_a)
+ windows.inputHandleKey(keycode_Home);
+ else if (ks.keycode == Common::KEYCODE_c)
+ clipboard.send();
+ else if (ks.keycode == Common::KEYCODE_e)
+ windows.inputHandleKey(keycode_End);
+ else if (ks.keycode == Common::KEYCODE_u)
+ windows.inputHandleKey(keycode_Escape);
+ else if (ks.keycode == Common::KEYCODE_v)
+ clipboard.receive();
+ else if (ks.keycode == Common::KEYCODE_x)
+ clipboard.send();
+ else if (ks.keycode == Common::KEYCODE_LEFT || ks.keycode == Common::KEYCODE_KP4)
+ windows.inputHandleKey(keycode_SkipWordLeft);
+ else if (ks.keycode == Common::KEYCODE_RIGHT || ks.keycode == Common::KEYCODE_KP6)
+ windows.inputHandleKey(keycode_SkipWordRight);
+
+ return;
+ }
+
+ if (ks.flags & Common::KBD_ALT)
+ return;
+
+ if (ks.keycode == Common::KEYCODE_RETURN) windows.inputHandleKey(keycode_Return);
+ else if (ks.keycode == Common::KEYCODE_BACKSPACE) windows.inputHandleKey(keycode_Delete);
+ else if (ks.keycode == Common::KEYCODE_DELETE) windows.inputHandleKey(keycode_Erase);
+ else if (ks.keycode == Common::KEYCODE_TAB) windows.inputHandleKey(keycode_Tab);
+ else if (ks.keycode == Common::KEYCODE_UP) windows.inputHandleKey(keycode_PageUp);
+ else if (ks.keycode == Common::KEYCODE_PAGEDOWN) windows.inputHandleKey(keycode_PageDown);
+ else if (ks.keycode == Common::KEYCODE_HOME) windows.inputHandleKey(keycode_Home);
+ else if (ks.keycode == Common::KEYCODE_END) windows.inputHandleKey(keycode_End);
+ else if (ks.keycode == Common::KEYCODE_LEFT) windows.inputHandleKey(keycode_Left);
+ else if (ks.keycode == Common::KEYCODE_RIGHT) windows.inputHandleKey(keycode_Right);
+ else if (ks.keycode == Common::KEYCODE_UP) windows.inputHandleKey(keycode_Up);
+ else if (ks.keycode == Common::KEYCODE_DOWN) windows.inputHandleKey(keycode_Down);
+ else if (ks.keycode == Common::KEYCODE_ESCAPE) windows.inputHandleKey(keycode_Escape);
+ else if (ks.keycode == Common::KEYCODE_F1) windows.inputHandleKey(keycode_Func1);
+ else if (ks.keycode == Common::KEYCODE_F2) windows.inputHandleKey(keycode_Func2);
+ else if (ks.keycode == Common::KEYCODE_F3) windows.inputHandleKey(keycode_Func3);
+ else if (ks.keycode == Common::KEYCODE_F4) windows.inputHandleKey(keycode_Func4);
+ else if (ks.keycode == Common::KEYCODE_F5) windows.inputHandleKey(keycode_Func5);
+ else if (ks.keycode == Common::KEYCODE_F6) windows.inputHandleKey(keycode_Func6);
+ else if (ks.keycode == Common::KEYCODE_F7) windows.inputHandleKey(keycode_Func7);
+ else if (ks.keycode == Common::KEYCODE_F8) windows.inputHandleKey(keycode_Func8);
+ else if (ks.keycode == Common::KEYCODE_F9) windows.inputHandleKey(keycode_Func9);
+ else if (ks.keycode == Common::KEYCODE_F10) windows.inputHandleKey(keycode_Func10);
+ else if (ks.keycode == Common::KEYCODE_F11) windows.inputHandleKey(keycode_Func11);
+ else if (ks.keycode == Common::KEYCODE_F12) windows.inputHandleKey(keycode_Func12);
+ else windows.inputHandleKey(ks.ascii);
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 54a2774..cd0a3a6 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -138,19 +138,37 @@ public:
}
};
+/**
+ * Events manager
+ */
class Events {
private:
- EventQueue _eventsPolled;
- EventQueue _eventsLogged;
+ EventQueue _eventsPolled; ///< User generated events
+ EventQueue _eventsLogged; ///< Custom events generated by game code
+ Event *_currentEvent; ///< Event pointer passed during event retrieval
+ bool _timeouts; ///< Timer timeouts flag
private:
+ /**
+ * Dispatches an event
+ */
void dispatchEvent(Event &ev, bool polled);
+
+ /**
+ * Poll for user events
+ */
+ void pollEvents();
+
+ /**
+ * Handle a key down event
+ */
+ void handleKeyDown(const Common::KeyState &ks);
public:
bool _forceClick;
public:
/**
* Constructor
*/
- Events() : _forceClick(false) {}
+ Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false) {}
/**
* Get any pending event
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 1a8cc61..1f74c31 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -29,6 +29,7 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/events.h"
#include "gargoyle/picture.h"
@@ -42,14 +43,15 @@ namespace Gargoyle {
GargoyleEngine *g_vm;
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _conf(nullptr),
- _events(nullptr), _picList(nullptr), _screen(nullptr), _windows(nullptr),
- _windowMask(nullptr), _copySelect(false),
+ _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _clipboard(nullptr),
+ _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr), _windows(nullptr),
+ _windowMask(nullptr), _copySelect(false), _terminated(false),
gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
}
GargoyleEngine::~GargoyleEngine() {
+ delete _clipboard;
delete _conf;
delete _events;
delete _picList;
@@ -68,6 +70,7 @@ void GargoyleEngine::initialize() {
initGraphics(640, 480, false);
_screen = new Screen();
+ _clipboard = new Clipboard();
_conf = new Conf();
_events = new Events();
_picList = new PicList();
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index c34538b..9677d67 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -33,6 +33,7 @@
namespace Gargoyle {
+class Clipboard;
class Conf;
class Events;
class PicList;
@@ -93,6 +94,7 @@ protected:
*/
virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
public:
+ Clipboard *_clipboard;
Conf *_conf;
Events *_events;
PicList *_picList;
@@ -101,6 +103,7 @@ public:
Windows *_windows;
WindowMask *_windowMask;
bool _copySelect;
+ bool _terminated;
void (*gli_unregister_obj)(void *obj, glui32 objclass, gidispatch_rock_t objrock);
gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, const char *typecode);
void (*gli_unregister_arr)(void *array, glui32 len, const char *typecode, gidispatch_rock_t objrock);
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index b8ef788..a45608f 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/gargoyle
MODULE_OBJS := \
+ clipboard.o \
conf.o \
detection.o \
events.o \
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index fa8a7cc..c322127 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/window_text_buffer.h"
+#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/screen.h"
@@ -1155,7 +1156,7 @@ void TextBufferWindow::redraw() {
if (selbuf && _copyPos) {
Windows::_claimSelect = true;
- copyTextToClipboard(_copyBuf, _copyPos);
+ g_vm->_clipboard->store(_copyBuf, _copyPos);
for (i = 0; i < _copyPos; i++)
_copyBuf[i] = 0;
_copyPos = 0;
@@ -1623,10 +1624,6 @@ int TextBufferWindow::calcWidth(glui32 *chars, Attributes *attrs, int startchar,
return w;
}
-void TextBufferWindow::copyTextToClipboard(const glui32 *text, size_t len) {
- // TODO
-}
-
void TextBufferWindow::getSize(glui32 *width, glui32 *height) const {
if (width)
*width = (_bbox.width() - g_conf->_tMarginX * 2) / g_conf->_cellW;
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index be9ffcb..61b30e2 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -84,11 +84,6 @@ private:
void scrollOneLine(bool forced);
void scrollResize();
int calcWidth(glui32 *chars, Attributes *attrs, int startchar, int numchars, int spw);
-
- /**
- * Copy the passed text to the clipboard
- */
- void copyTextToClipboard(const glui32 *text, size_t len);
public:
int _width, _height;
int _spaced;
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 19f61ba..06b83e1 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -294,6 +294,96 @@ void Windows::inputGuessFocus() {
}
}
+void Windows::inputMoreFocus() {
+ Window *altWin = _focusWin;
+
+ do {
+ if (altWin && altWin->_moreRequest)
+ break;
+ altWin = iterateTreeOrder(altWin);
+ } while (altWin != _focusWin);
+
+ _focusWin = altWin;
+}
+
+void Windows::inputNextFocus() {
+ Window *altWin = _focusWin;
+
+ do
+ {
+ altWin = iterateTreeOrder(altWin);
+ if (altWin
+ && (altWin->_lineRequest || altWin->_charRequest ||
+ altWin->_lineRequestUni || altWin->_charRequestUni))
+ break;
+ } while (altWin != _focusWin);
+
+ if (_focusWin != altWin) {
+ _focusWin = altWin;
+ _forceRedraw = true;
+ redraw();
+ }
+}
+
+void Windows::inputScrollFocus() {
+ Window *altWin = _focusWin;
+
+ do {
+ if (altWin && altWin->_scrollRequest)
+ break;
+ altWin = iterateTreeOrder(altWin);
+ } while (altWin != _focusWin);
+
+ _focusWin = altWin;
+}
+
+void Windows::inputHandleKey(glui32 key) {
+ if (_moreFocus) {
+ inputMoreFocus();
+ } else {
+ switch (key) {
+ case keycode_Tab:
+ inputNextFocus();
+ return;
+ case keycode_PageUp:
+ case keycode_PageDown:
+ case keycode_MouseWheelUp:
+ case keycode_MouseWheelDown:
+ inputScrollFocus();
+ break;
+ default:
+ inputGuessFocus();
+ break;
+ }
+ }
+
+ Window *win = _focusWin;
+ if (!win)
+ return;
+
+ bool deferExit = false;
+
+ TextGridWindow *gridWindow = dynamic_cast<TextGridWindow *>(win);
+ TextBufferWindow *bufWindow = dynamic_cast<TextBufferWindow *>(win);
+
+ if (gridWindow) {
+ if (gridWindow->_charRequest || gridWindow->_charRequestUni)
+ gridWindow->acceptReadChar(key);
+ else if (gridWindow->_lineRequest || gridWindow->_lineRequestUni)
+ gridWindow->acceptReadLine(key);
+ } else if (bufWindow) {
+ if (bufWindow->_charRequest || bufWindow->_charRequestUni)
+ bufWindow->acceptReadChar(key);
+ else if (bufWindow->_lineRequest || bufWindow->_lineRequestUni)
+ bufWindow->acceptReadLine(key);
+ else if (bufWindow->_moreRequest || bufWindow->_scrollRequest)
+ deferExit = bufWindow->acceptScroll(key);
+ }
+
+ if (!deferExit && g_vm->_terminated)
+ g_vm->quitGame();
+}
+
void Windows::selectionChanged() {
_claimSelect = false;
_forceRedraw = true;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index b0ee311..0840822 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -101,6 +101,23 @@ private:
void refocus(Window *win);
Window *iterateTreeOrder(Window *win);
+
+
+ /**
+ * Pick first window which has a more request
+ */
+ void inputMoreFocus();
+
+ /**
+ *
+ */
+ void inputNextFocus();
+
+ /**
+ * Pick first window which might want scrolling.
+ * This is called after pressing page keys.
+ */
+ void inputScrollFocus();
public:
static bool _overrideReverse;
static bool _overrideFgSet;
@@ -154,6 +171,11 @@ public:
*/
void inputGuessFocus();
+ /**
+ * Handle input keypress
+ */
+ void inputHandleKey(glui32 key);
+
void selectionChanged();
void clearClaimSelect() { _claimSelect = false; }
Commit: efacc17bd1bea3f0ca316c57f90a5ca9849932b6
https://github.com/scummvm/scummvm/commit/efacc17bd1bea3f0ca316c57f90a5ca9849932b6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Handle more user events
Changed paths:
engines/gargoyle/clipboard.cpp
engines/gargoyle/clipboard.h
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/clipboard.cpp b/engines/gargoyle/clipboard.cpp
index ef11d55..69ef8f8 100644
--- a/engines/gargoyle/clipboard.cpp
+++ b/engines/gargoyle/clipboard.cpp
@@ -28,11 +28,11 @@ void Clipboard::store(const uint32 *text, size_t len) {
// TODO
}
-void Clipboard::send() {
+void Clipboard::send(ClipSource source) {
// TODO
}
-void Clipboard::receive() {
+void Clipboard::receive(ClipSource source) {
// TODO
}
diff --git a/engines/gargoyle/clipboard.h b/engines/gargoyle/clipboard.h
index ccd8d79..23e7aaf 100644
--- a/engines/gargoyle/clipboard.h
+++ b/engines/gargoyle/clipboard.h
@@ -27,15 +27,17 @@
namespace Gargoyle {
+enum ClipSource { PRIMARY = 0, CLIPBOARD = 1 };
+
class Clipboard {
private:
Common::Array<uint32> _text;
public:
void store(const uint32 *text, size_t len);
- void send();
+ void send(ClipSource source);
- void receive();
+ void receive(ClipSource source);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 00adce8..b1f1823 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -94,6 +94,13 @@ void Events::pollEvents() {
case Common::EVENT_KEYDOWN:
handleKeyDown(event.kbd);
return;
+ case Common::EVENT_WHEELUP:
+ case Common::EVENT_WHEELDOWN:
+ handleScroll(event.type == Common::EVENT_WHEELUP);
+ return;
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+
default:
break;
}
@@ -108,15 +115,15 @@ void Events::handleKeyDown(const Common::KeyState &ks) {
if (ks.keycode == Common::KEYCODE_a)
windows.inputHandleKey(keycode_Home);
else if (ks.keycode == Common::KEYCODE_c)
- clipboard.send();
+ clipboard.send(CLIPBOARD);
else if (ks.keycode == Common::KEYCODE_e)
windows.inputHandleKey(keycode_End);
else if (ks.keycode == Common::KEYCODE_u)
windows.inputHandleKey(keycode_Escape);
else if (ks.keycode == Common::KEYCODE_v)
- clipboard.receive();
+ clipboard.receive(CLIPBOARD);
else if (ks.keycode == Common::KEYCODE_x)
- clipboard.send();
+ clipboard.send(CLIPBOARD);
else if (ks.keycode == Common::KEYCODE_LEFT || ks.keycode == Common::KEYCODE_KP4)
windows.inputHandleKey(keycode_SkipWordLeft);
else if (ks.keycode == Common::KEYCODE_RIGHT || ks.keycode == Common::KEYCODE_KP6)
@@ -156,4 +163,38 @@ void Events::handleKeyDown(const Common::KeyState &ks) {
else windows.inputHandleKey(ks.ascii);
}
+void Events::handleScroll(bool wheelUp) {
+ g_vm->_windows->inputHandleKey(wheelUp ? keycode_MouseWheelUp : keycode_MouseWheelDown);
+}
+
+void Events::handleMouseMove(const Common::Point &pos) {
+ // hyperlinks and selection
+ // TODO: Properly handle commented out lines
+ if (g_vm->_copySelect) {
+ //gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_ibeam);
+ g_vm->_windowMask->moveSelection(pos);
+ } else {
+ if (g_vm->_windowMask->getHyperlink(pos)) {
+ //gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_hand);
+ } else {
+ //gdk_window_set_cursor((GTK_WIDGET(widget)->window), NULL);
+ }
+ }
+}
+
+void Events::handleButtonDown(bool isLeft, const Common::Point &pos) {
+ if (isLeft)
+ g_vm->_windows->inputHandleClick(pos);
+ else
+ g_vm->_clipboard->receive(PRIMARY);
+}
+
+void Events::handleButtonUp(bool isLeft, const Common::Point &pos) {
+ if (isLeft) {
+ g_vm->_copySelect = false;
+ //gdk_window_set_cursor((GTK_WIDGET(widget)->window), NULL);
+ g_vm->_clipboard->send(PRIMARY);
+ }
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index cd0a3a6..544b524 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -162,6 +162,26 @@ private:
* Handle a key down event
*/
void handleKeyDown(const Common::KeyState &ks);
+
+ /**
+ * Handle scroll events
+ */
+ void handleScroll(bool wheelUp);
+
+ /**
+ * Handle mouse move events
+ */
+ void handleMouseMove(const Common::Point &pos);
+
+ /**
+ * Handle mouse down events
+ */
+ void handleButtonDown(bool isLeft, const Common::Point &pos);
+
+ /**
+ * Handle mouse up events
+ */
+ void handleButtonUp(bool isLeft, const Common::Point &pos);
public:
bool _forceClick;
public:
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 06b83e1..0f1c9eb 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -384,6 +384,11 @@ void Windows::inputHandleKey(glui32 key) {
g_vm->quitGame();
}
+void Windows::inputHandleClick(const Common::Point &pos) {
+ if (_rootWin)
+ _rootWin->click(pos);
+}
+
void Windows::selectionChanged() {
_claimSelect = false;
_forceRedraw = true;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 0840822..643fecf 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -176,6 +176,11 @@ public:
*/
void inputHandleKey(glui32 key);
+ /**
+ * Handle mouse clicks
+ */
+ void inputHandleClick(const Common::Point &pos);
+
void selectionChanged();
void clearClaimSelect() { _claimSelect = false; }
Commit: 65fa4fa7cbfeb5eae8da6e8a4a077f3c8e1866f6
https://github.com/scummvm/scummvm/commit/65fa4fa7cbfeb5eae8da6e8a4a077f3c8e1866f6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Beginnings of font handling
Changed paths:
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/screen.h
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 9c84a12..9264db2 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -22,9 +22,54 @@
#include "gargoyle/fonts.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/conf.h"
namespace Gargoyle {
+const char *gli_conf_propr = "NotoSerif-Regular";
+const char *gli_conf_propb = "NotoSerif-Bold";
+const char *gli_conf_propi = "NotoSerif-Italic";
+const char *gli_conf_propz = "NotoSerif-BoldItalic";
+
+const char *gli_conf_monor = "GoMono-Regular";
+const char *gli_conf_monob = "GoMono-Bold";
+const char *gli_conf_monoi = "GoMono-Italic";
+const char *gli_conf_monoz = "GoMono-BoldItalic";
+
+#ifdef BUNDLED_FONTS
+const char *gli_conf_monofont = "";
+const char *gli_conf_propfont = "";
+const double gli_conf_monosize = 12.5; ///< good size for GoMono
+const double gli_conf_propsize = 13.4; ///< good size for NotoSerif
+#else
+const char *gli_conf_monofont = "Liberation Mono";
+const char *gli_conf_propfont = "Linux Libertine O";
+const double gli_conf_monosize = 12.5; ///< good size for LiberationMono
+const double gli_conf_propsize = 15.5; ///< good size for Libertine
+#endif
+
+Fonts::Fonts() {
+ double monoAspect = g_conf->_monoAspect;
+ double propAspect = g_conf->_propAspect;
+ double monoSize = g_conf->_monoSize;
+ double propSize = g_conf->_propSize;
+
+ _fontTable[0] = new Font(gli_conf_monor, monoSize, monoAspect, FONTR);
+ _fontTable[1] = new Font(gli_conf_monob, monoSize, monoAspect, FONTB);
+ _fontTable[2] = new Font(gli_conf_monoi, monoSize, monoAspect, FONTI);
+ _fontTable[3] = new Font(gli_conf_monoz, monoSize, monoAspect, FONTZ);
+
+ _fontTable[4] = new Font(gli_conf_propr, propSize, propAspect, FONTR);
+ _fontTable[5] = new Font(gli_conf_propb, propSize, propAspect, FONTB);
+ _fontTable[6] = new Font(gli_conf_propi, propSize, propAspect, FONTI);
+ _fontTable[7] = new Font(gli_conf_propz, propSize, propAspect, FONTZ);
+}
+
+Fonts::~Fonts() {
+ for (int idx = 0; idx < FONTS_TOTAL; ++idx)
+ delete _fontTable[idx];
+}
+
FACES Fonts::getId(const Common::String &name) {
if (name == "monor") return MONOR;
if (name == "monob") return MONOB;
@@ -37,4 +82,8 @@ FACES Fonts::getId(const Common::String &name) {
return MONOR;
}
+/*--------------------------------------------------------------------------*/
+
+
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index f2f701a..c303474 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -28,16 +28,40 @@
namespace Gargoyle {
+#define FONTS_TOTAL 8
+
enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
enum TYPES { MONOF, PROPF };
enum STYLES { FONTR, FONTB, FONTI, FONTZ };
+class Font {
+public:
+ /**
+ * Constructor
+ */
+ Font(const char *name, double size, double aspect, STYLES style) {
+ // TODO
+ }
+};
+
class Fonts {
+private:
+ Font *_fontTable[FONTS_TOTAL];
public:
/**
* Get the index/id of a font by name
*/
static FACES getId(const Common::String &name);
+public:
+ /**
+ * Constructor
+ */
+ Fonts();
+
+ /**
+ * Destructor
+ */
+ virtual ~Fonts();
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 1f74c31..3135fcb 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -69,9 +69,10 @@ void GargoyleEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphics(640, 480, false);
+ _conf = new Conf();
_screen = new Screen();
+
_clipboard = new Clipboard();
- _conf = new Conf();
_events = new Events();
_picList = new PicList();
_streams = new Streams();
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
index ce9088d..b1d24fa 100644
--- a/engines/gargoyle/screen.h
+++ b/engines/gargoyle/screen.h
@@ -24,10 +24,11 @@
#define GARGOYLE_DRAW_H
#include "graphics/screen.h"
+#include "gargoyle/fonts.h"
namespace Gargoyle {
-class Screen : public Graphics::Screen {
+class Screen : public Graphics::Screen, Fonts {
public:
/**
* Fills the screen with a given rgb color
Commit: e5854a6bd35fb29912bc185af32a3443598dc3cb
https://github.com/scummvm/scummvm/commit/e5854a6bd35fb29912bc185af32a3443598dc3cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add loading of TrueType fonts
Changed paths:
engines/gargoyle/configure.engine
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
diff --git a/engines/gargoyle/configure.engine b/engines/gargoyle/configure.engine
index 671f91c..3569297 100644
--- a/engines/gargoyle/configure.engine
+++ b/engines/gargoyle/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine gargoyle "Interactive Fiction games" no
+add_engine gargoyle "Interactive Fiction games" no "" "" "freetype2"
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 9264db2..41067a5 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -23,6 +23,8 @@
#include "gargoyle/fonts.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/conf.h"
+#include "common/file.h"
+#include "graphics/fonts/ttf.h"
namespace Gargoyle {
@@ -54,15 +56,15 @@ Fonts::Fonts() {
double monoSize = g_conf->_monoSize;
double propSize = g_conf->_propSize;
- _fontTable[0] = new Font(gli_conf_monor, monoSize, monoAspect, FONTR);
- _fontTable[1] = new Font(gli_conf_monob, monoSize, monoAspect, FONTB);
- _fontTable[2] = new Font(gli_conf_monoi, monoSize, monoAspect, FONTI);
- _fontTable[3] = new Font(gli_conf_monoz, monoSize, monoAspect, FONTZ);
+ _fontTable[0] = loadFont(MONOR, monoSize, monoAspect, FONTR);
+ _fontTable[1] = loadFont(MONOB, monoSize, monoAspect, FONTB);
+ _fontTable[2] = loadFont(MONOI, monoSize, monoAspect, FONTI);
+ _fontTable[3] = loadFont(MONOZ, monoSize, monoAspect, FONTZ);
- _fontTable[4] = new Font(gli_conf_propr, propSize, propAspect, FONTR);
- _fontTable[5] = new Font(gli_conf_propb, propSize, propAspect, FONTB);
- _fontTable[6] = new Font(gli_conf_propi, propSize, propAspect, FONTI);
- _fontTable[7] = new Font(gli_conf_propz, propSize, propAspect, FONTZ);
+ _fontTable[4] = loadFont(PROPR, propSize, propAspect, FONTR);
+ _fontTable[5] = loadFont(PROPB, propSize, propAspect, FONTB);
+ _fontTable[6] = loadFont(PROPI, propSize, propAspect, FONTI);
+ _fontTable[7] = loadFont(PROPZ, propSize, propAspect, FONTZ);
}
Fonts::~Fonts() {
@@ -82,8 +84,24 @@ FACES Fonts::getId(const Common::String &name) {
return MONOR;
}
-/*--------------------------------------------------------------------------*/
+Graphics::Font *Fonts::loadFont(FACES face, double size, double aspect, int style) {
+ static const char *const MAP[8] = {
+ "Go-Mono-Regular",
+ "Go-Mono-Bold",
+ "Go-Mono-Italic",
+ "Go-Mono-BoldItalic",
+ "NotoSerif-Regular",
+ "NotoSerif-Bold",
+ "NotoSerif-Italic",
+ "NotoSerif-BoldItalic"
+ };
+ Common::File f;
+ if (!f.open(Common::String::format("%s.ttf", MAP[face])))
+ return nullptr;
+
+ return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
+}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index c303474..be00a8d 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -25,6 +25,7 @@
#include "gargoyle/glk_types.h"
#include "common/str.h"
+#include "graphics/font.h"
namespace Gargoyle {
@@ -34,19 +35,19 @@ enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
enum TYPES { MONOF, PROPF };
enum STYLES { FONTR, FONTB, FONTI, FONTZ };
+/*
class Font {
+
public:
- /**
- * Constructor
- */
- Font(const char *name, double size, double aspect, STYLES style) {
- // TODO
- }
+ Font(const char *name, double size, double aspect, STYLES style);
};
+*/
class Fonts {
private:
- Font *_fontTable[FONTS_TOTAL];
+ Graphics::Font *_fontTable[FONTS_TOTAL];
+private:
+ Graphics::Font *loadFont(FACES face, double size, double aspect, int style);
public:
/**
* Get the index/id of a font by name
Commit: 6807e646b48a7b3850496bda890809b53a3093f5
https://github.com/scummvm/scummvm/commit/6807e646b48a7b3850496bda890809b53a3093f5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix initialization of text buffer window lines
Changed paths:
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index c322127..818bcf0 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -45,6 +45,10 @@ TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windo
_type = wintype_TextBuffer;
Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
+ _lines.resize(SCROLLBACK);
+ _chars = _lines[0]._chars;
+ _attrs = _lines[0]._attrs;
+
Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], _styles);
}
Commit: b23291b9777311d73363bd97f2392402d2b2eb6c
https://github.com/scummvm/scummvm/commit/b23291b9777311d73363bd97f2392402d2b2eb6c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Fix loading game data
Changed paths:
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 9632408..d533a7e 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -325,7 +325,7 @@ char *Scott::ReadString(Common::SeekableReadStream *f) {
tmp[ct++] = c;
else
tmp[ct++] = '?';
- } while (1);
+ }
tmp[ct] = 0;
t = (char *)MemAlloc(ct + 1);
@@ -1263,15 +1263,11 @@ int Scott::xstrncasecmp(const char *s1, const char *s2, size_t n) {
void Scott::readInts(Common::SeekableReadStream *f, size_t count, ...) {
va_list va;
va_start(va, count);
- unsigned char c = '\0';
+ unsigned char c = f->readByte();
for (size_t idx = 0; idx < count; ++idx) {
- if (idx > 0) {
- while (f->pos() < f->size() && Common::isSpace(c))
- c = f->readByte();
- } else {
+ while (f->pos() < f->size() && Common::isSpace(c))
c = f->readByte();
- }
// Get the next value
int *val = (int *)va_arg(va, int);
Commit: 998cf547eda31ac7b3c67c5dd0e2d1249ddf4741
https://github.com/scummvm/scummvm/commit/998cf547eda31ac7b3c67c5dd0e2d1249ddf4741
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Exit game when ScummVM is closed
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index b1f1823..bba9df1 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -31,7 +31,6 @@ void Events::getEvent(event_t *event, bool polled) {
_currentEvent = event;
event->clear();
- Common::Event ev;
dispatchEvent(*_currentEvent, polled);
if (!polled) {
@@ -41,6 +40,9 @@ void Events::getEvent(event_t *event, bool polled) {
dispatchEvent(*_currentEvent, polled);
}
+
+ if (g_vm->shouldQuit())
+ _currentEvent->type = evtype_Quit;
}
if (_currentEvent->type == evtype_None && _timeouts) {
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index d533a7e..3812392 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -92,6 +92,9 @@ Distributed under the GNU software license\n\n");
if (GetInput(&vb, &no) == -1)
continue;
+ if (g_vm->shouldQuit())
+ return;
+
switch (PerformActions(vb, no)) {
case -1:
Output("I don't understand your command. ");
@@ -567,8 +570,9 @@ void Scott::LineInput(char *buf, size_t n) {
do {
glk_select(&ev);
-
- if (ev.type == evtype_LineInput)
+ if (ev.type == evtype_Quit)
+ return;
+ else if (ev.type == evtype_LineInput)
break;
else if (ev.type == evtype_Arrange && split_screen)
Look();
@@ -654,6 +658,9 @@ int Scott::GetInput(int *vb, int *no) {
do {
Output("\nTell me what to do ? ");
LineInput(buf, sizeof buf);
+ if (g_vm->shouldQuit())
+ return 0;
+
num = sscanf(buf, "%9s %9s", verb, noun);
} while (num == 0 || *buf == '\n');
Commit: 9d72d6007e10ebdfcede91e03385eb486f452a7c
https://github.com/scummvm/scummvm/commit/9d72d6007e10ebdfcede91e03385eb486f452a7c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Move font method stubs from Screen to Fonts
Changed paths:
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
engines/gargoyle/screen.cpp
engines/gargoyle/screen.h
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 41067a5..41b2f65 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -50,7 +50,7 @@ const double gli_conf_monosize = 12.5; ///< good size for LiberationMono
const double gli_conf_propsize = 15.5; ///< good size for Libertine
#endif
-Fonts::Fonts() {
+Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface) {
double monoAspect = g_conf->_monoAspect;
double propAspect = g_conf->_propAspect;
double monoSize = g_conf->_monoSize;
@@ -103,5 +103,24 @@ Graphics::Font *Fonts::loadFont(FACES face, double size, double aspect, int styl
return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
}
+int Fonts::drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Fonts::drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Fonts::stringWidth(int fidx, const char *s, int n, int spw) {
+ // TODO
+ return 0;
+}
+
+int Fonts::stringWidthUni(int fidx, const uint32 *s, int n, int spw) {
+ // TODO
+ return 0;
+}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index be00a8d..35db815 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -35,16 +35,9 @@ enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
enum TYPES { MONOF, PROPF };
enum STYLES { FONTR, FONTB, FONTI, FONTZ };
-/*
-class Font {
-
-public:
- Font(const char *name, double size, double aspect, STYLES style);
-};
-*/
-
class Fonts {
private:
+ Graphics::ManagedSurface *_surface;
Graphics::Font *_fontTable[FONTS_TOTAL];
private:
Graphics::Font *loadFont(FACES face, double size, double aspect, int style);
@@ -57,12 +50,20 @@ public:
/**
* Constructor
*/
- Fonts();
+ Fonts(Graphics::ManagedSurface *surface);
/**
* Destructor
*/
virtual ~Fonts();
+
+ int drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw);
+
+ int drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw);
+
+ int stringWidth(int fidx, const char *s, int n, int spw);
+
+ int stringWidthUni(int fidx, const uint32 *s, int n, int spw);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/screen.cpp b/engines/gargoyle/screen.cpp
index dad3e6d..f541b76 100644
--- a/engines/gargoyle/screen.cpp
+++ b/engines/gargoyle/screen.cpp
@@ -34,26 +34,6 @@ void Screen::fillRect(uint x, uint y, uint w, uint h, const byte *rgb) {
Graphics::Screen::fillRect(Common::Rect(x, y, x + w, y + h), color);
}
-int Screen::drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-int Screen::drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-int Screen::stringWidth(int fidx, const char *s, int n, int spw) {
- // TODO
- return 0;
-}
-
-int Screen::stringWidthUni(int fidx, const uint32 *s, int n, int spw) {
- // TODO
- return 0;
-}
-
void Screen::drawCaret(const Common::Point &pos) {
// TODO
}
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
index b1d24fa..8cdf988 100644
--- a/engines/gargoyle/screen.h
+++ b/engines/gargoyle/screen.h
@@ -28,9 +28,14 @@
namespace Gargoyle {
-class Screen : public Graphics::Screen, Fonts {
+class Screen : public Graphics::Screen, public Fonts {
public:
/**
+ * Constructor
+ */
+ Screen() : Graphics::Screen(), Fonts(this) {}
+
+ /**
* Fills the screen with a given rgb color
*/
void fill(const byte *rgb);
@@ -40,14 +45,6 @@ public:
*/
void fillRect(uint x, uint y, uint w, uint h, const byte *rgb);
- int drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw);
-
- int drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw);
-
- int stringWidth(int fidx, const char *s, int n, int spw);
-
- int stringWidthUni(int fidx, const uint32 *s, int n, int spw);
-
void drawCaret(const Common::Point &pos);
};
Commit: 13e2838715247b6b6ca5b17d61f80fa516d23c34
https://github.com/scummvm/scummvm/commit/13e2838715247b6b6ca5b17d61f80fa516d23c34
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Implement font drawing methods
Changed paths:
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 41b2f65..45f8671 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -103,24 +103,31 @@ Graphics::Font *Fonts::loadFont(FACES face, double size, double aspect, int styl
return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
}
-int Fonts::drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw) {
- // TODO
- return 0;
+int Fonts::drawString(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
+ Graphics::Font *font = _fontTable[fontIdx];
+ const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ font->drawString(_surface, text, pos.x, pos.y, _surface->w - pos.x, color);
+ return font->getBoundingBox(text, pos.x, pos.y, _surface->w - pos.x).right;
}
-int Fonts::drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw) {
- // TODO
- return 0;
+int Fonts::drawStringUni(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
+ Graphics::Font *font = _fontTable[fontIdx];
+ const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ font->drawString(_surface, text, pos.x, pos.y, _surface->w - pos.x, color);
+
+ return font->getBoundingBox(text, pos.x, pos.y, _surface->w - pos.x).right;
}
-int Fonts::stringWidth(int fidx, const char *s, int n, int spw) {
- // TODO
- return 0;
+size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
+ // TODO: Handle spw
+ Graphics::Font *font = _fontTable[fontIdx];
+ return font->getStringWidth(text);
}
-int Fonts::stringWidthUni(int fidx, const uint32 *s, int n, int spw) {
- // TODO
- return 0;
+size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
+ // TODO: Handle spw
+ Graphics::Font *font = _fontTable[fontIdx];
+ return font->getStringWidth(text);
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index 35db815..a486a01 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -25,6 +25,7 @@
#include "gargoyle/glk_types.h"
#include "common/str.h"
+#include "common/ustr.h"
#include "graphics/font.h"
namespace Gargoyle {
@@ -57,13 +58,13 @@ public:
*/
virtual ~Fonts();
- int drawString(int x, int y, int fidx, const byte *rgb, const char *s, int n, int spw);
+ int drawString(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
- int drawStringUni(int x, int y, int fidx, const byte *rgb, const uint32 *s, int n, int spw);
+ int drawStringUni(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
- int stringWidth(int fidx, const char *s, int n, int spw);
+ size_t stringWidth(int fontIdx, const Common::String &text, int spw = -1);
- int stringWidthUni(int fidx, const uint32 *s, int n, int spw);
+ size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = -1);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 818bcf0..ebce9c3 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -966,7 +966,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
- w = screen.stringWidthUni(font, ln->_chars + a, b - a, spw);
+ w = screen.stringWidthUni(font, Common::U32String(ln->_chars + a, b - a), spw);
screen.fillRect(x/GLI_SUBPIX, y,
w/GLI_SUBPIX, g_conf->_leading,
color);
@@ -985,7 +985,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
- w = screen.stringWidthUni(font, ln->_chars + a, b - a, spw);
+ w = screen.stringWidthUni(font, Common::U32String(ln->_chars + a, b - a), spw);
screen.fillRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
g_conf->_leading, color);
if (link) {
@@ -1025,16 +1025,16 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- x = screen.drawStringUni(x, y + g_conf->_baseLine,
- font, color, ln->_chars + a, b - a, spw);
+ x = screen.drawStringUni(Common::Point(x, y + g_conf->_baseLine),
+ font, color, Common::U32String(ln->_chars + a, b - a), spw);
a = b;
}
}
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- screen.drawStringUni(x, y + g_conf->_baseLine,
- font, color, ln->_chars + a, linelen - a, spw);
+ screen.drawStringUni(Common::Point(x, y + g_conf->_baseLine),
+ font, color, Common::U32String(ln->_chars + a, linelen - a), spw);
}
/*
@@ -1053,8 +1053,7 @@ void TextBufferWindow::redraw() {
x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
color);
- w = screen.stringWidth(g_conf->_moreFont,
- g_conf->_morePrompt.c_str(), g_conf->_morePrompt.size(), -1);
+ w = screen.stringWidth(g_conf->_moreFont, g_conf->_morePrompt);
if (g_conf->_moreAlign == 1) /* center */
x = x0 + SLOP + (x1 - x0 - w - SLOP * 2) / 2;
@@ -1062,9 +1061,8 @@ void TextBufferWindow::redraw() {
x = x1 - SLOP - w;
color = Windows::_overrideFgSet ? g_conf->_moreColor : _fgColor;
- screen.drawString(x, y + g_conf->_baseLine,
- g_conf->_moreFont, color,
- g_conf->_morePrompt.c_str(), g_conf->_morePrompt.size(), -1);
+ screen.drawString(Common::Point(x, y + g_conf->_baseLine),
+ g_conf->_moreFont, color, g_conf->_morePrompt);
y1 = y; /* don't want pictures overdrawing "[more]" */
/* try to claim the focus */
@@ -1617,13 +1615,12 @@ int TextBufferWindow::calcWidth(glui32 *chars, Attributes *attrs, int startchar,
for (b = startchar; b < numChars; b++) {
if (attrs[a] == attrs[b]) {
w += screen.stringWidthUni(attrs[a].attrFont(_styles),
- chars + a, b - a, spw);
+ Common::U32String(chars + a, b - a), spw);
a = b;
}
}
- w += screen.stringWidthUni(attrs[a].attrFont(_styles),
- chars + a, b - a, spw);
+ w += screen.stringWidthUni(attrs[a].attrFont(_styles), Common::U32String(chars + a, b - a), spw);
return w;
}
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index e2ee06e..7b349a5 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -607,9 +607,8 @@ void TextGridWindow::redraw() {
o = x;
for (k = a; k < b; k++) {
- screen.drawStringUni(o * GLI_SUBPIX,
- y + g_conf->_baseLine, font, fgcolor,
- &ln->_chars[k], 1, -1);
+ screen.drawStringUni(Common::Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
+ font, fgcolor, Common::U32String(&ln->_chars[k], 1), -1);
o += g_conf->_cellW;
}
if (link) {
@@ -631,9 +630,8 @@ void TextGridWindow::redraw() {
o = x;
for (k = a; k < b; k++) {
- screen.drawStringUni(o * GLI_SUBPIX,
- y + g_conf->_baseLine, font, fgcolor,
- &ln->_chars[k], 1, -1);
+ screen.drawStringUni(Common::Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
+ font, fgcolor, Common::U32String(&ln->_chars[k], 1));
o += g_conf->_cellW;
}
if (link) {
Commit: ffe0f5220bef728938847f54bdc4e489739d6ded
https://github.com/scummvm/scummvm/commit/ffe0f5220bef728938847f54bdc4e489739d6ded
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Converted fillRect to use a Rect to specify bounds
Changed paths:
A engines/gargoyle/utils.cpp
A engines/gargoyle/utils.h
engines/gargoyle/conf.cpp
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
engines/gargoyle/glk.cpp
engines/gargoyle/module.mk
engines/gargoyle/screen.cpp
engines/gargoyle/screen.h
engines/gargoyle/unicode.cpp
engines/gargoyle/unicode.h
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_mask.cpp
engines/gargoyle/window_mask.h
engines/gargoyle/window_pair.cpp
engines/gargoyle/window_pair.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index e2b8d04..a684889 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -22,7 +22,7 @@
#include "gargoyle/conf.h"
#include "gargoyle/fonts.h"
-#include "gargoyle/unicode.h"
+#include "gargoyle/utils.h"
#include "gargoyle/windows.h"
#include "common/config-manager.h"
#include "common/system.h"
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index bba9df1..6836faf 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -169,7 +169,7 @@ void Events::handleScroll(bool wheelUp) {
g_vm->_windows->inputHandleKey(wheelUp ? keycode_MouseWheelUp : keycode_MouseWheelDown);
}
-void Events::handleMouseMove(const Common::Point &pos) {
+void Events::handleMouseMove(const Point &pos) {
// hyperlinks and selection
// TODO: Properly handle commented out lines
if (g_vm->_copySelect) {
@@ -184,14 +184,14 @@ void Events::handleMouseMove(const Common::Point &pos) {
}
}
-void Events::handleButtonDown(bool isLeft, const Common::Point &pos) {
+void Events::handleButtonDown(bool isLeft, const Point &pos) {
if (isLeft)
g_vm->_windows->inputHandleClick(pos);
else
g_vm->_clipboard->receive(PRIMARY);
}
-void Events::handleButtonUp(bool isLeft, const Common::Point &pos) {
+void Events::handleButtonUp(bool isLeft, const Point &pos) {
if (isLeft) {
g_vm->_copySelect = false;
//gdk_window_set_cursor((GTK_WIDGET(widget)->window), NULL);
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 544b524..f49ef35 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -24,6 +24,7 @@
#define GARGOYLE_EVENTS_H
#include "common/events.h"
+#include "gargoyle/utils.h"
namespace Gargoyle {
@@ -171,17 +172,17 @@ private:
/**
* Handle mouse move events
*/
- void handleMouseMove(const Common::Point &pos);
+ void handleMouseMove(const Point &pos);
/**
* Handle mouse down events
*/
- void handleButtonDown(bool isLeft, const Common::Point &pos);
+ void handleButtonDown(bool isLeft, const Point &pos);
/**
* Handle mouse up events
*/
- void handleButtonUp(bool isLeft, const Common::Point &pos);
+ void handleButtonUp(bool isLeft, const Point &pos);
public:
bool _forceClick;
public:
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 45f8671..bcb129c 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -103,14 +103,14 @@ Graphics::Font *Fonts::loadFont(FACES face, double size, double aspect, int styl
return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
}
-int Fonts::drawString(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
+int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pos.x, pos.y, _surface->w - pos.x, color);
return font->getBoundingBox(text, pos.x, pos.y, _surface->w - pos.x).right;
}
-int Fonts::drawStringUni(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
+int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pos.x, pos.y, _surface->w - pos.x, color);
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index a486a01..4472025 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -24,6 +24,7 @@
#define GARGOYLE_FONTS_H
#include "gargoyle/glk_types.h"
+#include "gargoyle/utils.h"
#include "common/str.h"
#include "common/ustr.h"
#include "graphics/font.h"
@@ -58,9 +59,9 @@ public:
*/
virtual ~Fonts();
- int drawString(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
+ int drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
- int drawStringUni(const Common::Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
+ int drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
size_t stringWidth(int fontIdx, const Common::String &text, int spw = -1);
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 736ed3e..abc4d2c 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -295,7 +295,7 @@ void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
if (!win) {
warning("window_move_cursor: invalid ref");
} else {
- win->moveCursor(Common::Point(xpos, ypos));
+ win->moveCursor(Point(xpos, ypos));
}
}
@@ -770,7 +770,7 @@ void Glk::glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 wid
if (!win) {
warning("window_erase_rect: invalid ref");
} else {
- win->eraseRect(false, Common::Rect(left, top, left + width, top + height));
+ win->eraseRect(false, Rect(left, top, left + width, top + height));
}
}
@@ -779,7 +779,7 @@ void Glk::glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 to
if (!win) {
warning("window_fill_rect: invalid ref");
} else {
- win->eraseRect(color, Common::Rect(left, top, left + width, top + height));
+ win->eraseRect(color, Rect(left, top, left + width, top + height));
}
}
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index a45608f..f4422b0 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
time.o \
unicode.o \
unicode_gen.o \
+ utils.o \
windows.o \
window_mask.o \
window_graphics.o \
diff --git a/engines/gargoyle/screen.cpp b/engines/gargoyle/screen.cpp
index f541b76..f500b86 100644
--- a/engines/gargoyle/screen.cpp
+++ b/engines/gargoyle/screen.cpp
@@ -29,12 +29,12 @@ void Screen::fill(const byte *rgb) {
clear(color);
}
-void Screen::fillRect(uint x, uint y, uint w, uint h, const byte *rgb) {
+void Screen::fillRect(const Rect &box, const byte *rgb) {
uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- Graphics::Screen::fillRect(Common::Rect(x, y, x + w, y + h), color);
+ Graphics::Screen::fillRect(box, color);
}
-void Screen::drawCaret(const Common::Point &pos) {
+void Screen::drawCaret(const Point &pos) {
// TODO
}
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
index 8cdf988..3974096 100644
--- a/engines/gargoyle/screen.h
+++ b/engines/gargoyle/screen.h
@@ -43,9 +43,9 @@ public:
/**
* Fill a given area of the screen with an rgb color
*/
- void fillRect(uint x, uint y, uint w, uint h, const byte *rgb);
+ void fillRect(const Rect &box, const byte *rgb);
- void drawCaret(const Common::Point &pos);
+ void drawCaret(const Point &pos);
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/unicode.cpp b/engines/gargoyle/unicode.cpp
index 601d8f0..c547d2b 100644
--- a/engines/gargoyle/unicode.cpp
+++ b/engines/gargoyle/unicode.cpp
@@ -33,22 +33,6 @@ size_t strlen_uni(const uint32 *s) {
return len;
}
-int strToInt(const char *s) {
- if (!*s)
- // No string at all
- return 0;
- else if (toupper(s[strlen(s) - 1]) != 'H')
- // Standard decimal string
- return atoi(s);
-
- // Hexadecimal string
- uint tmp = 0;
- int read = sscanf(s, "%xh", &tmp);
- if (read < 1)
- error("strToInt failed on string \"%s\"", s);
- return (int)tmp;
-}
-
glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCase destcase,
BufferChangeCond cond, int changerest) {
glui32 ix, jx;
diff --git a/engines/gargoyle/unicode.h b/engines/gargoyle/unicode.h
index 806a63f..2392c1a 100644
--- a/engines/gargoyle/unicode.h
+++ b/engines/gargoyle/unicode.h
@@ -46,11 +46,6 @@ size_t strlen_uni(const uint32 *s);
extern glui32 bufferChangeCase(glui32 *buf, glui32 len,
glui32 numchars, BufferChangeCase destcase, BufferChangeCond cond, int changerest);
-/**
- * Converts a decimal or hexadecimal string into a number
- */
-int strToInt(const char *s);
-
} // End of namespace Gargoyle
#endif
diff --git a/engines/gargoyle/utils.cpp b/engines/gargoyle/utils.cpp
new file mode 100644
index 0000000..6857301
--- /dev/null
+++ b/engines/gargoyle/utils.cpp
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/utils.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+
+int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/utils.h b/engines/gargoyle/utils.h
new file mode 100644
index 0000000..b8a8e02
--- /dev/null
+++ b/engines/gargoyle/utils.h
@@ -0,0 +1,51 @@
+/* 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 GARGOYLE_UTILS_H
+#define GARGOYLE_UTILS_H
+
+#include "common/rect.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+typedef Common::Point Point;
+
+struct Rect : public Common::Rect {
+public:
+ static Rect fromXYWH(int x, int y, int w, int h) {
+ return Rect(x, y, x + w, y + h);
+ }
+
+ Rect() : Common::Rect() {}
+ Rect(int16 w, int16 h) : Common::Rect(w, h) {}
+ Rect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1, y1, x2, y2) {}
+};
+
+/**
+ * Converts a decimal or hexadecimal string into a number
+ */
+int strToInt(const char *s);
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index 0ea5876..6609f0a 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -36,7 +36,7 @@ GraphicsWindow::~GraphicsWindow() {
delete _surface;
}
-void GraphicsWindow::rearrange(const Common::Rect &box) {
+void GraphicsWindow::rearrange(const Rect &box) {
int newwid, newhgt;
int bothwid, bothhgt;
int oldw, oldh;
@@ -92,7 +92,7 @@ void GraphicsWindow::redraw() {
_dirty = 0;
if (_surface)
- screen.blitFrom(*_surface, Common::Point(_bbox.left, _bbox.top));
+ screen.blitFrom(*_surface, Point(_bbox.left, _bbox.top));
}
}
@@ -120,7 +120,7 @@ glui32 GraphicsWindow::drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int s
return true;
}
-void GraphicsWindow::eraseRect(bool whole, const Common::Rect &box) {
+void GraphicsWindow::eraseRect(bool whole, const Rect &box) {
int x0 = box.left, y0 = box.top, x1 = box.right, y1 = box.bottom;
int hx0, hx1, hy0, hy1;
@@ -148,11 +148,11 @@ void GraphicsWindow::eraseRect(bool whole, const Common::Rect &box) {
/* zero out hyperlinks for these coordinates */
g_vm->_windowMask->putHyperlink(0, hx0, hy0, hx1, hy1);
- _surface->fillRect(Common::Rect(x0, y0, x1, y1), MKTAG(_bgnd[0], _bgnd[1], _bgnd[2], 0));
+ _surface->fillRect(Rect(x0, y0, x1, y1), MKTAG(_bgnd[0], _bgnd[1], _bgnd[2], 0));
touch();
}
-void GraphicsWindow::fillRect(glui32 color, const Common::Rect &box) {
+void GraphicsWindow::fillRect(glui32 color, const Rect &box) {
unsigned char col[3];
int x0 = box.left, y0 = box.top, x1 = box.right, y1 = box.bottom;
int hx0, hx1, hy0, hy1;
@@ -178,7 +178,7 @@ void GraphicsWindow::fillRect(glui32 color, const Common::Rect &box) {
/* zero out hyperlinks for these coordinates */
g_vm->_windowMask->putHyperlink(0, hx0, hy0, hx1, hy1);
- _surface->fillRect(Common::Rect(x0, y0, x1, y1), MKTAG(col[0], col[1], col[2], 0));
+ _surface->fillRect(Rect(x0, y0, x1, y1), MKTAG(col[0], col[1], col[2], 0));
touch();
}
@@ -233,7 +233,7 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
w = sx1 - sx0;
h = sy1 - sy0;
- _surface->blitFrom(*g_vm->_screen, Common::Rect(sx0, sy0, sx0 + w, sy0 + h), Common::Point(0, 0));
+ _surface->blitFrom(*g_vm->_screen, Rect(sx0, sy0, sx0 + w, sy0 + h), Point(0, 0));
}
void GraphicsWindow::getSize(glui32 *width, glui32 *height) const {
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index 8c2724e..f271444 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -58,7 +58,7 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box) override;
+ virtual void rearrange(const Rect &box) override;
/**
* Get window split size within parent pair window
@@ -86,9 +86,9 @@ public:
*/
virtual void redraw() override;
- virtual void eraseRect(bool whole, const Common::Rect &box) override;
+ virtual void eraseRect(bool whole, const Rect &box) override;
- virtual void fillRect(glui32 color, const Common::Rect &box) override;
+ virtual void fillRect(glui32 color, const Rect &box) override;
virtual void getSize(glui32 *width, glui32 *height) const override;
diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp
index fe1d463..b3b629b 100644
--- a/engines/gargoyle/window_mask.cpp
+++ b/engines/gargoyle/window_mask.cpp
@@ -94,7 +94,7 @@ void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1
}
}
-glui32 WindowMask::getHyperlink(const Common::Point &pos) {
+glui32 WindowMask::getHyperlink(const Point &pos) {
if (!_hor || !_ver) {
warning("getHyperlink: struct not initialized");
return 0;
@@ -110,7 +110,7 @@ glui32 WindowMask::getHyperlink(const Common::Point &pos) {
return _links[pos.x][pos.y];
}
-void WindowMask::startSelection(const Common::Point &pos) {
+void WindowMask::startSelection(const Point &pos) {
int tx, ty;
if (!_hor || !_ver) {
@@ -129,7 +129,7 @@ void WindowMask::startSelection(const Common::Point &pos) {
g_vm->_windows->selectionChanged();
}
-void WindowMask::moveSelection(const Common::Point &pos) {
+void WindowMask::moveSelection(const Point &pos) {
int tx, ty;
if (ABS(pos.x - _lastX) < 5 && abs(pos.y - _lastY) < 5)
diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h
index 9dc5826..e9030a2 100644
--- a/engines/gargoyle/window_mask.h
+++ b/engines/gargoyle/window_mask.h
@@ -25,6 +25,7 @@
#include "common/rect.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/utils.h"
namespace Gargoyle {
@@ -34,7 +35,7 @@ class WindowMask {
public:
size_t _hor, _ver;
glui32 **_links;
- Common::Rect _select;
+ Rect _select;
static int _lastX, _lastY;
public:
@@ -50,11 +51,11 @@ public:
void putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1);
- glui32 getHyperlink(const Common::Point &pos);
+ glui32 getHyperlink(const Point &pos);
- void startSelection(const Common::Point &pos);
+ void startSelection(const Point &pos);
- void moveSelection(const Common::Point &pos);
+ void moveSelection(const Point &pos);
void clearSelection();
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
index b8d593e..3f0f294 100644
--- a/engines/gargoyle/window_pair.cpp
+++ b/engines/gargoyle/window_pair.cpp
@@ -36,8 +36,8 @@ PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size
_type = wintype_Pair;
}
-void PairWindow::rearrange(const Common::Rect &box) {
- Common::Rect box1, box2;
+void PairWindow::rearrange(const Rect &box) {
+ Rect box1, box2;
int min, diff, split, splitwid, max;
Window *ch1, *ch2;
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
index 8e80f79..2037b3d 100644
--- a/engines/gargoyle/window_pair.h
+++ b/engines/gargoyle/window_pair.h
@@ -51,7 +51,7 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box) override;
+ virtual void rearrange(const Rect &box) override;
/**
* Redraw the window
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index ebce9c3..3946771 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -70,7 +70,7 @@ TextBufferWindow::~TextBufferWindow() {
}
}
-void TextBufferWindow::rearrange(const Common::Rect &box) {
+void TextBufferWindow::rearrange(const Rect &box) {
Window::rearrange(box);
int newwid, newhgt;
int rnd;
@@ -371,7 +371,7 @@ void TextBufferWindow::touch(int line) {
int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
_lines[line]._dirty = 1;
g_vm->_windowMask->clearSelection();
- _windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
+ _windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
}
glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
@@ -567,7 +567,7 @@ void TextBufferWindow::clear() {
touch(i);
}
-void TextBufferWindow::click(const Common::Point &newPos) {
+void TextBufferWindow::click(const Point &newPos) {
int gh = false;
int gs = false;
@@ -843,7 +843,7 @@ void TextBufferWindow::redraw() {
/* repaint previously selected lines if needed */
if (ln->_repaint && !Windows::_forceRedraw)
- _windows->redrawRect(Common::Rect(x0 / GLI_SUBPIX, y,
+ _windows->redrawRect(Rect(x0 / GLI_SUBPIX, y,
x1/GLI_SUBPIX, y + g_conf->_leading));
/* keep selected line dirty and flag for repaint */
@@ -954,8 +954,7 @@ void TextBufferWindow::redraw() {
* fill in background colors
*/
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- screen.fillRect(x0/GLI_SUBPIX, y,
- (x1-x0) / GLI_SUBPIX, g_conf->_leading,
+ screen.fillRect(Rect::fromXYWH(x0 / GLI_SUBPIX, y, (x1-x0) / GLI_SUBPIX, g_conf->_leading),
color);
x = x0 + SLOP + ln->_lm;
@@ -967,13 +966,11 @@ void TextBufferWindow::redraw() {
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
w = screen.stringWidthUni(font, Common::U32String(ln->_chars + a, b - a), spw);
- screen.fillRect(x/GLI_SUBPIX, y,
- w/GLI_SUBPIX, g_conf->_leading,
+ screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX, y, w / GLI_SUBPIX, g_conf->_leading),
color);
if (link) {
- screen.fillRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
- w/GLI_SUBPIX + 1, g_conf->_linkStyle,
- g_conf->_linkColor);
+ screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ w / GLI_SUBPIX + 1, g_conf->_linkStyle), g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
x/GLI_SUBPIX + w/GLI_SUBPIX,
y + g_conf->_leading);
@@ -986,22 +983,18 @@ void TextBufferWindow::redraw() {
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
w = screen.stringWidthUni(font, Common::U32String(ln->_chars + a, b - a), spw);
- screen.fillRect(x/GLI_SUBPIX, y, w/GLI_SUBPIX,
- g_conf->_leading, color);
+ screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX, y, w / GLI_SUBPIX, g_conf->_leading), color);
if (link) {
- screen.fillRect(x/GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
- w/GLI_SUBPIX + 1, g_conf->_linkStyle,
- g_conf->_linkColor);
- g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
- x/GLI_SUBPIX + w/GLI_SUBPIX,
+ screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
+ w/GLI_SUBPIX + 1, g_conf->_linkStyle), g_conf->_linkColor);
+ g_vm->_windowMask->putHyperlink(link, x / GLI_SUBPIX, y,
+ x / GLI_SUBPIX + w / GLI_SUBPIX,
y + g_conf->_leading);
}
x += w;
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- screen.fillRect(x/GLI_SUBPIX, y,
- x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
- color);
+ screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX, y, x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading), color);
/*
* draw caret
@@ -1010,7 +1003,7 @@ void TextBufferWindow::redraw() {
if (_windows->getFocusWindow() == this && i == 0 && (_lineRequest || _lineRequestUni)) {
w = calcWidth(_chars, _attrs, 0, _inCurs, spw);
if (w < pw - g_conf->_caretShape * 2 * GLI_SUBPIX)
- screen.drawCaret(Common::Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
+ screen.drawCaret(Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
}
/*
@@ -1025,7 +1018,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- x = screen.drawStringUni(Common::Point(x, y + g_conf->_baseLine),
+ x = screen.drawStringUni(Point(x, y + g_conf->_baseLine),
font, color, Common::U32String(ln->_chars + a, b - a), spw);
a = b;
}
@@ -1033,7 +1026,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- screen.drawStringUni(Common::Point(x, y + g_conf->_baseLine),
+ screen.drawStringUni(Point(x, y + g_conf->_baseLine),
font, color, Common::U32String(ln->_chars + a, linelen - a), spw);
}
@@ -1049,9 +1042,7 @@ void TextBufferWindow::redraw() {
x1/GLI_SUBPIX, y + g_conf->_leading);
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
- screen.fillRect(x/GLI_SUBPIX, y,
- x1/GLI_SUBPIX - x/GLI_SUBPIX, g_conf->_leading,
- color);
+ screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX, y, x1 / GLI_SUBPIX - x / GLI_SUBPIX, g_conf->_leading), color);
w = screen.stringWidth(g_conf->_moreFont, g_conf->_morePrompt);
@@ -1061,7 +1052,7 @@ void TextBufferWindow::redraw() {
x = x1 - SLOP - w;
color = Windows::_overrideFgSet ? g_conf->_moreColor : _fgColor;
- screen.drawString(Common::Point(x, y + g_conf->_baseLine),
+ screen.drawString(Point(x, y + g_conf->_baseLine),
g_conf->_moreFont, color, g_conf->_morePrompt);
y1 = y; /* don't want pictures overdrawing "[more]" */
@@ -1141,16 +1132,14 @@ void TextBufferWindow::redraw() {
t0 = t1 = y0;
}
- screen.fillRect(x0+1, y0, x1-x0-2, y1-y0, g_conf->_scrollBg);
- screen.fillRect(x0+1, t0, x1-x0-2, t1-t0, g_conf->_scrollFg);
+ screen.fillRect(Rect::fromXYWH(x0 + 1, y0, x1-x0 - 2, y1 - y0), g_conf->_scrollBg);
+ screen.fillRect(Rect::fromXYWH(x0 + 1, t0, x1-x0 - 2, t1 - t0), g_conf->_scrollFg);
for (i = 0; i < g_conf->_scrollWidth / 2 + 1; i++) {
- screen.fillRect(x0+g_conf->_scrollWidth/2-i,
- y0 - g_conf->_scrollWidth/2 + i,
- i*2, 1, g_conf->_scrollFg);
- screen.fillRect(x0+g_conf->_scrollWidth/2-i,
- y1 + g_conf->_scrollWidth/2 - i,
- i*2, 1, g_conf->_scrollFg);
+ screen.fillRect(Rect::fromXYWH(x0 + g_conf->_scrollWidth / 2 - i,
+ y0 - g_conf->_scrollWidth/2 + i, i * 2, 1), g_conf->_scrollFg);
+ screen.fillRect(Rect::fromXYWH(x0 + g_conf->_scrollWidth / 2 - i,
+ y1 + g_conf->_scrollWidth / 2 - i, i * 2, 1), g_conf->_scrollFg);
}
}
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 61b30e2..ab7890a 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -147,7 +147,7 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box) override;
+ virtual void rearrange(const Rect &box) override;
/**
* Get window split size within parent pair window
@@ -172,7 +172,7 @@ public:
/**
* Click the window
*/
- virtual void click(const Common::Point &newPos) override;
+ virtual void click(const Point &newPos) override;
/**
* Prepare for inputing a line
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 7b349a5..b1effc4 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -52,7 +52,7 @@ TextGridWindow::~TextGridWindow() {
delete[] _lineTerminators;
}
-void TextGridWindow::rearrange(const Common::Rect &box) {
+void TextGridWindow::rearrange(const Rect &box) {
Window::rearrange(box);
int newwid, newhgt;
@@ -76,7 +76,7 @@ void TextGridWindow::rearrange(const Common::Rect &box) {
void TextGridWindow::touch(int line) {
int y = _bbox.top + line * g_conf->_leading;
_lines[line].dirty = true;
- _windows->repaint(Common::Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
+ _windows->repaint(Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
}
glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
@@ -161,7 +161,7 @@ bool TextGridWindow::unputCharUni(uint32 ch) {
}
}
-void TextGridWindow::moveCursor(const Common::Point &pos) {
+void TextGridWindow::moveCursor(const Point &pos) {
// If the values are negative, they're really huge positive numbers --
// remember that they were cast from glui32. So set them huge and
// let canonicalization take its course.
@@ -189,7 +189,7 @@ void TextGridWindow::clear() {
_curY = 0;
}
-void TextGridWindow::click(const Common::Point &newPos) {
+void TextGridWindow::click(const Point &newPos) {
int x = newPos.x - _bbox.left;
int y = newPos.y - _bbox.top;
@@ -603,17 +603,17 @@ void TextGridWindow::redraw() {
fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
bgcolor = ln->_attrs[a].attrBg(styles);
w = (b - a) * g_conf->_cellW;
- screen.fillRect(x, y, w, g_conf->_leading, bgcolor);
+ screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
o = x;
for (k = a; k < b; k++) {
- screen.drawStringUni(Common::Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
+ screen.drawStringUni(Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
font, fgcolor, Common::U32String(&ln->_chars[k], 1), -1);
o += g_conf->_cellW;
}
if (link) {
- screen.fillRect(x, y + g_conf->_baseLine + 1, w,
- g_conf->_linkStyle, g_conf->_linkColor);
+ screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle), g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
x += w;
@@ -626,17 +626,17 @@ void TextGridWindow::redraw() {
bgcolor = ln->_attrs[a].attrBg(styles);
w = (b - a) * g_conf->_cellW;
w += _bbox.right - (x + w);
- screen.fillRect(x, y, w, g_conf->_leading, bgcolor);
+ screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
o = x;
for (k = a; k < b; k++) {
- screen.drawStringUni(Common::Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
+ screen.drawStringUni(Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
font, fgcolor, Common::U32String(&ln->_chars[k], 1));
o += g_conf->_cellW;
}
if (link) {
- screen.fillRect(x, y + g_conf->_baseLine + 1, w,
- g_conf->_linkStyle, g_conf->_linkColor);
+ screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w, g_conf->_linkStyle),
+ g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
}
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 9ff588b..1fba707 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -90,7 +90,7 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box) override;
+ virtual void rearrange(const Rect &box) override;
/**
* Get window split size within parent pair window
@@ -110,7 +110,7 @@ public:
/**
* Move the cursor
*/
- virtual void moveCursor(const Common::Point &newPos) override;
+ virtual void moveCursor(const Point &newPos) override;
/**
* Clear the window
@@ -120,7 +120,7 @@ public:
/**
* Click the window
*/
- virtual void click(const Common::Point &newPos) override;
+ virtual void click(const Point &newPos) override;
/**
* Cancel a hyperlink event
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 0f1c9eb..22c2701 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -249,7 +249,7 @@ PairWindow *Windows::newPairWindow(glui32 method, Window *key, glui32 size) {
void Windows::rearrange() {
if (_rootWin) {
- Common::Rect box;
+ Rect box;
if (g_conf->_lockCols) {
int desired_width = g_conf->_wMarginSaveX * 2 + g_conf->_cellW * g_conf->_cols;
@@ -384,7 +384,7 @@ void Windows::inputHandleKey(glui32 key) {
g_vm->quitGame();
}
-void Windows::inputHandleClick(const Common::Point &pos) {
+void Windows::inputHandleClick(const Point &pos) {
if (_rootWin)
_rootWin->click(pos);
}
@@ -399,7 +399,7 @@ void Windows::redraw() {
_claimSelect = false;
if (_forceRedraw) {
- repaint(Common::Rect(0, 0, g_conf->_imageW, g_conf->_imageH));
+ repaint(Rect(0, 0, g_conf->_imageW, g_conf->_imageH));
g_vm->_screen->fill(g_conf->_windowColor);
}
@@ -412,12 +412,12 @@ void Windows::redraw() {
_forceRedraw = 0;
}
-void Windows::redrawRect(const Common::Rect &r) {
+void Windows::redrawRect(const Rect &r) {
_drawSelect = true;
repaint(r);
}
-void Windows::repaint(const Common::Rect &box) {
+void Windows::repaint(const Rect &box) {
// No implementation
}
@@ -556,7 +556,7 @@ void Window::cancelLineEvent(Event *ev) {
ev->clear();
}
-void Window::moveCursor(const Common::Point &newPos) {
+void Window::moveCursor(const Point &newPos) {
warning("moveCursor: not a TextGrid window");
}
@@ -572,7 +572,7 @@ void Window::redraw() {
if (Windows::_forceRedraw) {
unsigned char *color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
int y0 = _yAdj ? _bbox.top - _yAdj : _bbox.top;
- g_vm->_screen->fillRect(_bbox.left, y0, _bbox.width(), _bbox.bottom - y0, color);
+ g_vm->_screen->fillRect(Rect(_bbox.left, y0, _bbox.right, _bbox.bottom), color);
}
}
@@ -604,11 +604,11 @@ void Window::flowBreak() {
warning("flowBreak: not a text buffer window");
}
-void Window::eraseRect(bool whole, const Common::Rect &box) {
+void Window::eraseRect(bool whole, const Rect &box) {
warning("eraseRect: not a graphics window");
}
-void Window::fillRect(glui32 color, const Common::Rect &box) {
+void Window::fillRect(glui32 color, const Rect &box) {
warning("fillRect: not a graphics window");
}
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 643fecf..231ed67 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -179,7 +179,7 @@ public:
/**
* Handle mouse clicks
*/
- void inputHandleClick(const Common::Point &pos);
+ void inputHandleClick(const Point &pos);
void selectionChanged();
@@ -192,12 +192,12 @@ public:
void redraw();
- void redrawRect(const Common::Rect &r);
+ void redrawRect(const Rect &r);
/**
* Repaint an area of the windows
*/
- void repaint(const Common::Rect &box);
+ void repaint(const Rect &box);
/**
* Get an iterator that will move over the tree
@@ -282,7 +282,7 @@ public:
Window *_parent; ///< pair window which contains this one
Window *_next, *_prev; ///< in the big linked list of windows
- Common::Rect _bbox;
+ Rect _bbox;
int _yAdj;
Stream *_stream; ///< the window stream.
@@ -328,7 +328,7 @@ public:
/**
* Rearranges the window
*/
- virtual void rearrange(const Common::Rect &box) { _bbox = box; }
+ virtual void rearrange(const Rect &box) { _bbox = box; }
/**
* Get window split size within parent pair window
@@ -348,7 +348,7 @@ public:
/**
* Move the cursor
*/
- virtual void moveCursor(const Common::Point &newPos);
+ virtual void moveCursor(const Point &newPos);
/**
* Clear the window
@@ -358,7 +358,7 @@ public:
/**
* Click the window
*/
- virtual void click(const Common::Point &newPos) {}
+ virtual void click(const Point &newPos) {}
/**
* Prepare for inputing a line
@@ -423,9 +423,9 @@ public:
virtual void flowBreak();
- virtual void eraseRect(bool whole, const Common::Rect &box);
+ virtual void eraseRect(bool whole, const Rect &box);
- virtual void fillRect(glui32 color, const Common::Rect &box);
+ virtual void fillRect(glui32 color, const Rect &box);
virtual void setBackgroundColor(glui32 color);
};
Commit: a9f5b3351e1daedbd2fc301254048060bc464b58
https://github.com/scummvm/scummvm/commit/a9f5b3351e1daedbd2fc301254048060bc464b58
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix fg/bg window color initialization
Changed paths:
engines/gargoyle/windows.cpp
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 22c2701..bf126eb 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -495,8 +495,8 @@ Window::Window(Windows *windows, glui32 rock) : _windows(windows), _rock(rock),
_attr.bgcolor = 0;
_attr.hyper = 0;
- Common::fill(&_bgColor[0], &_bgColor[3], 3);
- Common::fill(&_fgColor[0], &_fgColor[3], 3);
+ Common::copy(&g_conf->_windowColor[0], &g_conf->_windowColor[3], &_bgColor[0]);
+ Common::copy(&g_conf->_moreColor[0], &g_conf->_moreColor[3], _fgColor);
_dispRock.num = 0;
Streams &streams = *g_vm->_streams;
Commit: 4fcffce50568bb3c202720bbb90bd92cfefbc83f
https://github.com/scummvm/scummvm/commit/4fcffce50568bb3c202720bbb90bd92cfefbc83f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Changes of NULL to nullptr
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/events.cpp
engines/gargoyle/glk.cpp
engines/gargoyle/unicode.cpp
engines/gargoyle/unicode_gen.cpp
engines/gargoyle/unicode_gen.h
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_pair.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index a684889..3902db3 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -237,9 +237,9 @@ void Conf::parseColor(const Common::String &str, byte *color) {
g[0] = str[2]; g[1] = str[3]; g[2] = 0;
b[0] = str[4]; b[1] = str[5]; b[2] = 0;
- color[0] = strtol(r, NULL, 16);
- color[1] = strtol(g, NULL, 16);
- color[2] = strtol(b, NULL, 16);
+ color[0] = strtol(r, nullptr, 16);
+ color[1] = strtol(g, nullptr, 16);
+ color[2] = strtol(b, nullptr, 16);
}
}
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 6836faf..23a8baf 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -46,7 +46,7 @@ void Events::getEvent(event_t *event, bool polled) {
}
if (_currentEvent->type == evtype_None && _timeouts) {
- store(evtype_Timer, NULL, 0, 0);
+ store(evtype_Timer, nullptr, 0, 0);
dispatchEvent(*_currentEvent, polled);
_timeouts = false;
}
@@ -179,7 +179,7 @@ void Events::handleMouseMove(const Point &pos) {
if (g_vm->_windowMask->getHyperlink(pos)) {
//gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_hand);
} else {
- //gdk_window_set_cursor((GTK_WIDGET(widget)->window), NULL);
+ //gdk_window_set_cursor((GTK_WIDGET(widget)->window), nullptr);
}
}
}
@@ -194,7 +194,7 @@ void Events::handleButtonDown(bool isLeft, const Point &pos) {
void Events::handleButtonUp(bool isLeft, const Point &pos) {
if (isLeft) {
g_vm->_copySelect = false;
- //gdk_window_set_cursor((GTK_WIDGET(widget)->window), NULL);
+ //gdk_window_set_cursor((GTK_WIDGET(widget)->window), nullptr);
g_vm->_clipboard->send(PRIMARY);
}
}
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index abc4d2c..c9823a9 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -181,8 +181,6 @@ winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 w
}
void Glk::glk_window_close(winid_t win, stream_result_t *result) {
- _windows->_forceRedraw = true;
-
if (!win) {
warning("glk_window_close: invalid ref");
} else {
@@ -280,7 +278,7 @@ void Glk::glk_window_clear(winid_t win) {
warning("window_clear: invalid ref");
} else if (win->_lineRequest || win->_lineRequestUni) {
if (g_conf->_safeClicks && _events->_forceClick) {
- glk_cancel_line_event(win, NULL);
+ glk_cancel_line_event(win, nullptr);
_events->_forceClick = false;
win->clear();
diff --git a/engines/gargoyle/unicode.cpp b/engines/gargoyle/unicode.cpp
index c547d2b..c783915 100644
--- a/engines/gargoyle/unicode.cpp
+++ b/engines/gargoyle/unicode.cpp
@@ -63,7 +63,7 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
if (dest_block_first == CASE_TITLE)
dest_block_first = CASE_UPPER;
- newoutbuf = NULL;
+ newoutbuf = nullptr;
outcount = 0;
outbuf = buf;
diff --git a/engines/gargoyle/unicode_gen.cpp b/engines/gargoyle/unicode_gen.cpp
index a6b0bc5..c9ad570 100644
--- a/engines/gargoyle/unicode_gen.cpp
+++ b/engines/gargoyle/unicode_gen.cpp
@@ -11522,7 +11522,7 @@ switch ((glui32)(ch) >> 8) { \
*blockptr = unigen_decomp_block_0x2fa; \
break; \
default: \
- *blockptr = NULL; \
+ *blockptr = nullptr; \
}
#define GET_DECOMP_SPECIAL(ch, countptr, posptr) \
diff --git a/engines/gargoyle/unicode_gen.h b/engines/gargoyle/unicode_gen.h
index f621a93..1539ec4 100644
--- a/engines/gargoyle/unicode_gen.h
+++ b/engines/gargoyle/unicode_gen.h
@@ -69,7 +69,7 @@ case 0x104: \
*blockptr = unigen_case_block_0x104; \
break; \
default: \
- *blockptr = NULL; \
+ *blockptr = nullptr; \
}
#define GET_CASE_SPECIAL(ch, specptr) \
@@ -420,7 +420,7 @@ case 0xfb17: \
*specptr = unigen_special_0xfb17; \
break; \
default: \
- *specptr = NULL; \
+ *specptr = nullptr; \
}
typedef glui32 gli_case_block_t[2]; ///< upper, lower
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index 6609f0a..b31d620 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -53,7 +53,7 @@ void GraphicsWindow::rearrange(const Rect &box) {
_w = 0;
_h = 0;
delete _surface;
- _surface = NULL;
+ _surface = nullptr;
return;
}
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
index 2037b3d..7e6178e 100644
--- a/engines/gargoyle/window_pair.h
+++ b/engines/gargoyle/window_pair.h
@@ -38,7 +38,7 @@ public:
glui32 _dir; ///< winmethod_Left, Right, Above, or Below
bool _vertical, _backward; ///< flags
glui32 _division; ///< winmethod_Fixed or winmethod_Proportional
- Window *_key; ///< NULL or a leaf-descendant (not a Pair)
+ Window *_key; ///< nullptr or a leaf-descendant (not a Pair)
int _keyDamage; ///< used as scratch space in window closing
glui32 _size; ///< size value
glui32 _wBorder; ///< winMethod_Border, NoBorder
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index b1effc4..55ccdcc 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -446,13 +446,13 @@ void TextGridWindow::acceptLine(glui32 keycode) {
val2 = 0;
g_vm->_events->store(evtype_LineInput, this, _inLen, val2);
free(_lineTerminators);
- _lineTerminators = NULL;
+ _lineTerminators = nullptr;
} else {
g_vm->_events->store(evtype_LineInput, this, _inLen, 0);
}
_lineRequest = false;
_lineRequestUni = false;
- _inBuf = NULL;
+ _inBuf = nullptr;
_inMax = 0;
_inOrgX = 0;
_inOrgY = 0;
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index bf126eb..6d09d82 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -80,15 +80,15 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
if (!_rootWin) {
if (splitwin) {
- warning("window_open: ref must be NULL");
+ warning("window_open: ref must be nullptr");
return nullptr;
}
/* ignore method and size now */
- oldparent = NULL;
+ oldparent = nullptr;
} else {
if (!splitwin) {
- warning("window_open: ref must not be NULL");
+ warning("window_open: ref must not be nullptr");
return nullptr;
}
@@ -152,6 +152,8 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
}
void Windows::windowClose(Window *win, StreamResult *result) {
+ _forceRedraw = true;
+
if (win == _rootWin || win->_parent == nullptr) {
// Close the root window, which means all windows.
_rootWin = nullptr;
Commit: 48a00e7c0019ea2cc0681342baa828d9cfb6c00d
https://github.com/scummvm/scummvm/commit/48a00e7c0019ea2cc0681342baa828d9cfb6c00d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Set Windows fields from int to bool
Changed paths:
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 231ed67..93d7ac2 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -288,15 +288,15 @@ public:
Stream *_stream; ///< the window stream.
Stream *_echoStream; ///< the window's echo stream, if any.
- int _lineRequest;
- int _lineRequestUni;
- int _charRequest;
- int _charRequestUni;
- int _mouseRequest;
- int _hyperRequest;
- int _moreRequest;
- int _scrollRequest;
- int _imageLoaded;
+ bool _lineRequest;
+ bool _lineRequestUni;
+ bool _charRequest;
+ bool _charRequestUni;
+ bool _mouseRequest;
+ bool _hyperRequest;
+ bool _moreRequest;
+ bool _scrollRequest;
+ bool _imageLoaded;
glui32 _echoLineInputBase;
glui32 *_lineTerminatorsBase;
Commit: 1a889689f863b58cf3afdf09e4cb7d98f2ef1477
https://github.com/scummvm/scummvm/commit/1a889689f863b58cf3afdf09e4cb7d98f2ef1477
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added pair window drawing
Changed paths:
engines/gargoyle/window_pair.cpp
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
index 3f0f294..26903cd 100644
--- a/engines/gargoyle/window_pair.cpp
+++ b/engines/gargoyle/window_pair.cpp
@@ -22,6 +22,8 @@
#include "gargoyle/window_pair.h"
#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/screen.h"
namespace Gargoyle {
@@ -121,7 +123,25 @@ void PairWindow::rearrange(const Rect &box) {
void PairWindow::redraw() {
Window::redraw();
- // TODO
+ _child1->redraw();
+ _child2->redraw();
+
+ Window *child = !_backward ? _child1 : _child2;
+ Rect box(child->_bbox.left, child->_yAdj ? child->_bbox.top - child->_yAdj : child->_bbox.top,
+ child->_bbox.right, child->_bbox.bottom);
+
+ if (_vertical) {
+ int xBord = _wBorder ? g_conf->_wBorderX : 0;
+ int xPad = (g_conf->_wPaddingX - xBord) / 2;
+
+ g_vm->_screen->fillRect(Rect(box.right + xPad, box.top, box.right + xPad + xBord, box.bottom),
+ g_conf->_borderColor);
+ } else {
+ int yBord = _wBorder ? g_conf->_wBorderY : 0;
+ int yPad = (g_conf->_wPaddingY - yBord) / 2;
+ g_vm->_screen->fillRect(Rect(box.left, box.bottom + yPad, box.right, box.bottom + yPad + yBord),
+ g_conf->_borderColor);
+ }
}
void PairWindow::getArrangement(glui32 *method, glui32 *size, Window **keyWin) {
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 3946771..d40dcf1 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -611,6 +611,7 @@ void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen
return;
}
+ _lineRequest = true;
int pw;
gli_tts_flush();
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 55ccdcc..cad18af 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -223,6 +223,8 @@ void TextGridWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen)
return;
}
+ _lineRequest = true;
+
if ((int)maxlen > (_width - _curX))
maxlen = (_width - _curX);
Commit: 0a21220707b879b5fcfe0cbed1774e808ddac68f
https://github.com/scummvm/scummvm/commit/0a21220707b879b5fcfe0cbed1774e808ddac68f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add game frames to actually render the screen
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/window_mask.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 23a8baf..ef4c59d 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -23,10 +23,28 @@
#include "gargoyle/events.h"
#include "gargoyle/clipboard.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/screen.h"
#include "gargoyle/windows.h"
namespace Gargoyle {
+Events::Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false),
+ _priorFrameTime(0), _frameCounter(0) {
+}
+
+bool Events::checkForNextFrameCounter() {
+ // Check for next game frame
+ uint32 milli = g_system->getMillis();
+ if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
+ ++_frameCounter;
+ _priorFrameTime = milli;
+
+ return true;
+ }
+
+ return false;
+}
+
void Events::getEvent(event_t *event, bool polled) {
_currentEvent = event;
event->clear();
@@ -89,6 +107,11 @@ void Events::dispatchEvent(Event &ev, bool polled) {
void Events::pollEvents() {
Common::Event event;
+ if (checkForNextFrameCounter()) {
+ // Update the screen
+ g_vm->_screen->update();
+ }
+
do {
g_system->getEventManager()->pollEvent(event);
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index f49ef35..4d9e49b 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -28,6 +28,9 @@
namespace Gargoyle {
+#define GAME_FRAME_RATE 100
+#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
+
class Window;
/**
@@ -148,8 +151,15 @@ private:
EventQueue _eventsLogged; ///< Custom events generated by game code
Event *_currentEvent; ///< Event pointer passed during event retrieval
bool _timeouts; ///< Timer timeouts flag
+ uint32 _priorFrameTime; ///< Time of prior game frame
+ uint32 _frameCounter; ///< Frame counter
private:
/**
+ * Checks for whether it's time for the next game frame
+ */
+ bool checkForNextFrameCounter();
+
+ /**
* Dispatches an event
*/
void dispatchEvent(Event &ev, bool polled);
@@ -189,7 +199,7 @@ public:
/**
* Constructor
*/
- Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false) {}
+ Events();
/**
* Get any pending event
diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp
index b3b629b..6c85789 100644
--- a/engines/gargoyle/window_mask.cpp
+++ b/engines/gargoyle/window_mask.cpp
@@ -24,6 +24,7 @@
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/windows.h"
+#include "common/system.h"
namespace Gargoyle {
@@ -32,6 +33,7 @@ int WindowMask::_lastY;
WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) {
_lastX = _lastY = 0;
+ resize(g_system->getWidth(), g_system->getHeight());
}
void WindowMask::resize(size_t x, size_t y) {
Commit: 4fc1c30423aa8e161a3ea2edd1f45c4ad681a92a
https://github.com/scummvm/scummvm/commit/4fc1c30423aa8e161a3ea2edd1f45c4ad681a92a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix Attributes equality checks
Changed paths:
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index d40dcf1..4db0bf9 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -960,9 +960,8 @@ void TextBufferWindow::redraw() {
x = x0 + SLOP + ln->_lm;
a = 0;
- for (b = 0; b < linelen; b++)
- {
- if (ln->_attrs[a] == ln->_attrs[b]) {
+ for (b = 0; b < linelen; b++) {
+ if (ln->_attrs[a] != ln->_attrs[b]) {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = ln->_attrs[a].attrBg(_styles);
@@ -1015,7 +1014,7 @@ void TextBufferWindow::redraw() {
a = 0;
for (b = 0; b < linelen; b++)
{
- if (ln->_attrs[a] == ln->_attrs[b]) {
+ if (ln->_attrs[a] != ln->_attrs[b]) {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
@@ -1603,7 +1602,7 @@ int TextBufferWindow::calcWidth(glui32 *chars, Attributes *attrs, int startchar,
a = startchar;
for (b = startchar; b < numChars; b++) {
- if (attrs[a] == attrs[b]) {
+ if (attrs[a] != attrs[b]) {
w += screen.stringWidthUni(attrs[a].attrFont(_styles),
Common::U32String(chars + a, b - a), spw);
a = b;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index cad18af..6d1aff4 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -599,7 +599,7 @@ void TextGridWindow::redraw() {
a = 0;
for (b = 0; b < _width; b++) {
- if (ln->_attrs[a] == ln->_attrs[b]) {
+ if (ln->_attrs[a] != ln->_attrs[b]) {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(styles);
fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 93d7ac2..d753d53 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -261,12 +261,27 @@ struct Attributes {
&& style == src.style && fgcolor == src.fgcolor && bgcolor == src.bgcolor
&& hyper == src.hyper;
}
+ /**
+ * Inequality comparison
+ */
+ bool operator!=(const Attributes &src) {
+ return fgset != src.fgset || bgset != src.bgset || reverse != src.reverse
+ || style != src.style || fgcolor != src.fgcolor || bgcolor != src.bgcolor
+ || hyper != src.hyper;
+ }
+ /**
+ * Return the background color for the current font style
+ */
byte *attrBg(WindowStyle *styles);
+
+ /**
+ * Return the foreground color for the current font style
+ */
byte *attrFg(WindowStyle *styles);
/**
- * Get the font from the attribute's style
+ * Get the font for the current font style
*/
FACES attrFont(WindowStyle *styles) const { return styles[style].font; }
};
Commit: e004784d23bf14c8176a1a394c32fbe01c7c488f
https://github.com/scummvm/scummvm/commit/e004784d23bf14c8176a1a394c32fbe01c7c488f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix calculation of text grid height
Changed paths:
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 6d1aff4..6945aca 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -80,8 +80,7 @@ void TextGridWindow::touch(int line) {
}
glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
- return vertical ? size * g_conf->_cellW + g_conf->_tMarginX * 2 :
- size * g_conf->_cellH + g_conf->_tMarginY * 2;
+ return vertical ? size * g_conf->_cellW : size * g_conf->_cellH;
}
void TextGridWindow::putCharUni(uint32 ch) {
Commit: 0d3495bb3b9bf172452e7bdc9ebbc9b23fe6b947
https://github.com/scummvm/scummvm/commit/0d3495bb3b9bf172452e7bdc9ebbc9b23fe6b947
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add missing configuration defaults
Changed paths:
engines/gargoyle/conf.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 3902db3..553f02c 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -89,8 +89,8 @@ Conf::Conf() {
get("propi", _propI);
get("propz", _propZ);
get("propfont", _propFont, "Linux Libertine O");
- get("leading", _leading);
- get("baseline", _baseLine);
+ get("leading", _leading, 20);
+ get("baseline", _baseLine, 15);
get("rows", _rows, 25);
get("cols", _cols, 60);
Commit: c5668d9300a78fb7d459b53fb2f9d03a418fd63b
https://github.com/scummvm/scummvm/commit/c5668d9300a78fb7d459b53fb2f9d03a418fd63b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Further configuration fixes
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/fonts.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 553f02c..7e11a2f 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -89,7 +89,7 @@ Conf::Conf() {
get("propi", _propI);
get("propz", _propZ);
get("propfont", _propFont, "Linux Libertine O");
- get("leading", _leading, 20);
+ get("leading", _leading, 8);
get("baseline", _baseLine, 15);
get("rows", _rows, 25);
get("cols", _cols, 60);
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index bcb129c..307144b 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -65,6 +65,9 @@ Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface) {
_fontTable[5] = loadFont(PROPB, propSize, propAspect, FONTB);
_fontTable[6] = loadFont(PROPI, propSize, propAspect, FONTI);
_fontTable[7] = loadFont(PROPZ, propSize, propAspect, FONTZ);
+
+ g_conf->_cellW = _fontTable[0]->getStringWidth("0");
+ g_conf->_cellH = _fontTable[0]->getFontHeight();
}
Fonts::~Fonts() {
Commit: 7ebbcc87dc5f53a66092b34975f16e4c0629590b
https://github.com/scummvm/scummvm/commit/7ebbcc87dc5f53a66092b34975f16e4c0629590b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix rendering text in text grid windows
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/fonts.cpp
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 7e11a2f..31e2c5f 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -69,6 +69,8 @@ Conf::Conf() {
_imageW = g_system->getWidth();
_imageH = g_system->getHeight();
_cellW = _cellH = 8;
+ _leading = 8;
+ _baseLine = 0;
get("moreprompt", _morePrompt, "\207 more \207");
get("morecolor", _moreColor);
@@ -89,11 +91,18 @@ Conf::Conf() {
get("propi", _propI);
get("propz", _propZ);
get("propfont", _propFont, "Linux Libertine O");
- get("leading", _leading, 8);
- get("baseline", _baseLine, 15);
get("rows", _rows, 25);
get("cols", _cols, 60);
+ /* Disabled for now, since Fonts constructor resets them
+ if (ConfMan.hasKey("leading"))
+ _leading = atof(ConfMan.get("leading").c_str()) + 0.5;
+ if (ConfMan.hasKey("baseline"))
+ _baseLine = atof(ConfMan.get("baseline").c_str()) + 0.5;
+ if (!_baseLine)
+ _baseLine = _propSize + 0.5;
+ */
+
if (ConfMan.hasKey("minrows"))
_rows = MAX(_rows, strToInt(ConfMan.get("minrows").c_str()));
if (ConfMan.hasKey("maxrows"))
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 307144b..7aaf27b 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -38,18 +38,6 @@ const char *gli_conf_monob = "GoMono-Bold";
const char *gli_conf_monoi = "GoMono-Italic";
const char *gli_conf_monoz = "GoMono-BoldItalic";
-#ifdef BUNDLED_FONTS
-const char *gli_conf_monofont = "";
-const char *gli_conf_propfont = "";
-const double gli_conf_monosize = 12.5; ///< good size for GoMono
-const double gli_conf_propsize = 13.4; ///< good size for NotoSerif
-#else
-const char *gli_conf_monofont = "Liberation Mono";
-const char *gli_conf_propfont = "Linux Libertine O";
-const double gli_conf_monosize = 12.5; ///< good size for LiberationMono
-const double gli_conf_propsize = 15.5; ///< good size for Libertine
-#endif
-
Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface) {
double monoAspect = g_conf->_monoAspect;
double propAspect = g_conf->_propAspect;
@@ -68,6 +56,7 @@ Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface) {
g_conf->_cellW = _fontTable[0]->getStringWidth("0");
g_conf->_cellH = _fontTable[0]->getFontHeight();
+ g_conf->_leading = g_conf->_baseLine = g_conf->_cellH;
}
Fonts::~Fonts() {
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 6945aca..455655f 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -588,7 +588,7 @@ void TextGridWindow::redraw() {
for (i = 0; i < _height; i++) {
ln = &_lines[i];
if (ln->dirty || Windows::_forceRedraw) {
- ln->dirty = 0;
+ ln->dirty = false;
x = x0;
y = y0 + i * g_conf->_leading;
@@ -607,16 +607,15 @@ void TextGridWindow::redraw() {
screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
o = x;
- for (k = a; k < b; k++) {
- screen.drawStringUni(Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
- font, fgcolor, Common::U32String(&ln->_chars[k], 1), -1);
- o += g_conf->_cellW;
+ for (k = a, o = x; k < b; k++, o += g_conf->_cellW) {
+ screen.drawStringUni(Point(o, y), font, fgcolor, Common::U32String(&ln->_chars[k], 1), -1);
}
if (link) {
screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle), g_conf->_linkColor);
g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
+
x += w;
a = b;
}
@@ -629,11 +628,8 @@ void TextGridWindow::redraw() {
w += _bbox.right - (x + w);
screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
- o = x;
- for (k = a; k < b; k++) {
- screen.drawStringUni(Point(o * GLI_SUBPIX, y + g_conf->_baseLine),
- font, fgcolor, Common::U32String(&ln->_chars[k], 1));
- o += g_conf->_cellW;
+ for (k = a, o = x; k < b; k++, o += g_conf->_cellW) {
+ screen.drawStringUni(Point(o, y), font, fgcolor, Common::U32String(&ln->_chars[k], 1));
}
if (link) {
screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w, g_conf->_linkStyle),
Commit: 7c7178c4191b734805cca49e375beafdc8fc4315
https://github.com/scummvm/scummvm/commit/7c7178c4191b734805cca49e375beafdc8fc4315
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Text is partially displaying in the buffer window
Changed paths:
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 4db0bf9..ff60345 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -1012,13 +1012,12 @@ void TextBufferWindow::redraw() {
x = x0 + SLOP + ln->_lm;
a = 0;
- for (b = 0; b < linelen; b++)
- {
+ for (b = 0; b < linelen; b++) {
if (ln->_attrs[a] != ln->_attrs[b]) {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- x = screen.drawStringUni(Point(x, y + g_conf->_baseLine),
+ x = screen.drawStringUni(Point(x / GLI_SUBPIX, y),
font, color, Common::U32String(ln->_chars + a, b - a), spw);
a = b;
}
@@ -1026,8 +1025,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- screen.drawStringUni(Point(x, y + g_conf->_baseLine),
- font, color, Common::U32String(ln->_chars + a, linelen - a), spw);
+ screen.drawStringUni(Point(x / GLI_SUBPIX, y), font, color, Common::U32String(ln->_chars + a, linelen - a), spw);
}
/*
Commit: 666edf52a5965d12a1ef4218a62c6ec5cf5fec46
https://github.com/scummvm/scummvm/commit/666edf52a5965d12a1ef4218a62c6ec5cf5fec46
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Don't have borders between windows by default
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/window_pair.h
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 31e2c5f..383bddb 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -121,8 +121,8 @@ Conf::Conf() {
get("wpaddingx", _wPaddingX);
get("wpaddingy", _wPaddingY);
- get("wborderx", _wBorderX, 1);
- get("wbordery", _wBorderY, 1);
+ get("wborderx", _wBorderX);
+ get("wbordery", _wBorderY);
get("tmarginx", _tMarginX, 7);
get("tmarginy", _tMarginY, 7);
get("gamma", _gamma, 1.0);
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
index 7e6178e..a28f7fd0 100644
--- a/engines/gargoyle/window_pair.h
+++ b/engines/gargoyle/window_pair.h
@@ -41,7 +41,7 @@ public:
Window *_key; ///< nullptr or a leaf-descendant (not a Pair)
int _keyDamage; ///< used as scratch space in window closing
glui32 _size; ///< size value
- glui32 _wBorder; ///< winMethod_Border, NoBorder
+ bool _wBorder; ///< If windows are separated by border
public:
/**
* Constructor
Commit: f17998762d632fd79075bc2164c21272304ba232
https://github.com/scummvm/scummvm/commit/f17998762d632fd79075bc2164c21272304ba232
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add drawCaret method
Changed paths:
engines/gargoyle/screen.cpp
engines/gargoyle/screen.h
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/screen.cpp b/engines/gargoyle/screen.cpp
index f500b86..ab49ac9 100644
--- a/engines/gargoyle/screen.cpp
+++ b/engines/gargoyle/screen.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/screen.h"
+#include "gargoyle/conf.h"
namespace Gargoyle {
@@ -35,7 +36,36 @@ void Screen::fillRect(const Rect &box, const byte *rgb) {
}
void Screen::drawCaret(const Point &pos) {
- // TODO
+ const byte *rgb = g_conf->_caretColor;
+ uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+
+ switch (g_conf->_caretShape) {
+ case SMALL_DOT:
+ hLine(pos.x + 0, pos.y + 1, pos.x + 0, color);
+ hLine(pos.x - 1, pos.y + 2, pos.x + 1, color);
+ hLine(pos.x - 2, pos.y + 3, pos.x + 2, color);
+ break;
+
+ case FAT_DOT:
+ hLine(pos.x + 0, pos.y + 1, pos.x + 0, color);
+ hLine(pos.x - 1, pos.y + 2, pos.x + 1, color);
+ hLine(pos.x - 2, pos.y + 3, pos.x + 2, color);
+ hLine(pos.x - 3, pos.y + 4, pos.x + 3, color);
+ break;
+
+ case THIN_LINE:
+ vLine(pos.x, pos.y - g_conf->_baseLine + 1, pos.y - 1, color);
+ break;
+
+ case FAT_LINE:
+ Graphics::Screen::fillRect(Rect(pos.x, pos.y - g_conf->_baseLine + 1, pos.x + 1, pos.y - 1), color);
+ break;
+
+ default:
+ // BLOCK
+ Graphics::Screen::fillRect(Rect(pos.x, pos.y - g_conf->_baseLine + 1, pos.x + g_conf->_cellW, pos.y - 1), color);
+ break;
+ }
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
index 3974096..66553c3 100644
--- a/engines/gargoyle/screen.h
+++ b/engines/gargoyle/screen.h
@@ -28,6 +28,13 @@
namespace Gargoyle {
+enum CaretShape {
+ SMALL_DOT = 0, FAT_DOT = 1, THIN_LINE = 2, FAT_LINE = 3, BLOCK = 4
+};
+
+/**
+ * Screen surface class
+ */
class Screen : public Graphics::Screen, public Fonts {
public:
/**
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index ff60345..b22246d 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -1003,7 +1003,7 @@ void TextBufferWindow::redraw() {
if (_windows->getFocusWindow() == this && i == 0 && (_lineRequest || _lineRequestUni)) {
w = calcWidth(_chars, _attrs, 0, _inCurs, spw);
if (w < pw - g_conf->_caretShape * 2 * GLI_SUBPIX)
- screen.drawCaret(Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
+ screen.drawCaret(Point((x0 + SLOP + ln->_lm + w) / GLI_SUBPIX, y + g_conf->_baseLine));
}
/*
Commit: e9c7b302461f73bdb387aebdc56add59e4c887e3
https://github.com/scummvm/scummvm/commit/e9c7b302461f73bdb387aebdc56add59e4c887e3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Proper handling of font baseline and leading
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
engines/gargoyle/screen.cpp
engines/gargoyle/screen.h
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 383bddb..ae67a8a 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -69,7 +69,7 @@ Conf::Conf() {
_imageW = g_system->getWidth();
_imageH = g_system->getHeight();
_cellW = _cellH = 8;
- _leading = 8;
+ _leading = 0;
_baseLine = 0;
get("moreprompt", _morePrompt, "\207 more \207");
@@ -79,13 +79,13 @@ Conf::Conf() {
get("morealign", _moreAlign);
get("monoaspect", _monoAspect, 1.0);
get("propaspect", _propAspect, 1.0);
- get("monosize", _monoSize, 12.5);
+ get("monosize", _monoSize, 8);
get("monor", _monoR);
get("monob", _monoR);
get("monoi", _monoI);
get("monoz", _monoZ);
get("monofont", _monoFont, "Liberation Mono");
- get("propsize", _propSize, 15.5);
+ get("propsize", _propSize, 12);
get("propr", _propR);
get("propb", _propR);
get("propi", _propI);
@@ -94,14 +94,10 @@ Conf::Conf() {
get("rows", _rows, 25);
get("cols", _cols, 60);
- /* Disabled for now, since Fonts constructor resets them
if (ConfMan.hasKey("leading"))
_leading = atof(ConfMan.get("leading").c_str()) + 0.5;
if (ConfMan.hasKey("baseline"))
_baseLine = atof(ConfMan.get("baseline").c_str()) + 0.5;
- if (!_baseLine)
- _baseLine = _propSize + 0.5;
- */
if (ConfMan.hasKey("minrows"))
_rows = MAX(_rows, strToInt(ConfMan.get("minrows").c_str()));
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 7aaf27b..7cf4e1d 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -54,9 +54,13 @@ Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface) {
_fontTable[6] = loadFont(PROPI, propSize, propAspect, FONTI);
_fontTable[7] = loadFont(PROPZ, propSize, propAspect, FONTZ);
+ if (!g_conf->_leading)
+ g_conf->_leading = g_conf->_propSize + 2;
+ if (!g_conf->_baseLine)
+ g_conf->_baseLine = g_conf->_propSize + 0.5;
+
g_conf->_cellW = _fontTable[0]->getStringWidth("0");
- g_conf->_cellH = _fontTable[0]->getFontHeight();
- g_conf->_leading = g_conf->_baseLine = g_conf->_cellH;
+ g_conf->_cellH = g_conf->_leading;
}
Fonts::~Fonts() {
@@ -96,18 +100,20 @@ Graphics::Font *Fonts::loadFont(FACES face, double size, double aspect, int styl
}
int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
+ Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- font->drawString(_surface, text, pos.x, pos.y, _surface->w - pos.x, color);
- return font->getBoundingBox(text, pos.x, pos.y, _surface->w - pos.x).right;
+ font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
+ return font->getBoundingBox(text, pt.x, pt.y, _surface->w - pt.x).right;
}
int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
+ Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- font->drawString(_surface, text, pos.x, pos.y, _surface->w - pos.x, color);
+ font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
- return font->getBoundingBox(text, pos.x, pos.y, _surface->w - pos.x).right;
+ return font->getBoundingBox(text, pt.x, pt.y, _surface->w - pt.x).right;
}
size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index 4472025..f2a6eb8 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -59,12 +59,40 @@ public:
*/
virtual ~Fonts();
+ /**
+ * Draws a string using the specified font at the given co-ordinates
+ * @param pos Position for the bottom-left corner the text will be drawn with
+ * @param fontIdx Which font to use
+ * @param rgb RGB tuplet specifying the text color
+ * @param text The text to draw
+ * @param spw ??
+ */
int drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
+ /**
+ * Draws a unicode string using the specified font at the given co-ordinates
+ * @param pos Position for the bottom-left corner the text will be drawn with
+ * @param fontIdx Which font to use
+ * @param rgb RGB tuplet specifying the text color
+ * @param text The text to draw
+ * @param spw ??
+ */
int drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
+ /**
+ * Get the width in pixels of a string
+ * @param fontIdx Which font to use
+ * @param text Text to get the width of
+ * @param spw ???
+ */
size_t stringWidth(int fontIdx, const Common::String &text, int spw = -1);
+ /**
+ * Get the width in pixels of a unicode string
+ * @param fontIdx Which font to use
+ * @param text Text to get the width of
+ * @param spw ???
+ */
size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = -1);
};
diff --git a/engines/gargoyle/screen.cpp b/engines/gargoyle/screen.cpp
index ab49ac9..6aed8f9 100644
--- a/engines/gargoyle/screen.cpp
+++ b/engines/gargoyle/screen.cpp
@@ -38,32 +38,33 @@ void Screen::fillRect(const Rect &box, const byte *rgb) {
void Screen::drawCaret(const Point &pos) {
const byte *rgb = g_conf->_caretColor;
uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ int x = pos.x / GLI_SUBPIX, y = pos.y;
switch (g_conf->_caretShape) {
case SMALL_DOT:
- hLine(pos.x + 0, pos.y + 1, pos.x + 0, color);
- hLine(pos.x - 1, pos.y + 2, pos.x + 1, color);
- hLine(pos.x - 2, pos.y + 3, pos.x + 2, color);
+ hLine(x + 0, y + 1, x + 0, color);
+ hLine(x - 1, y + 2, x + 1, color);
+ hLine(x - 2, y + 3, x + 2, color);
break;
case FAT_DOT:
- hLine(pos.x + 0, pos.y + 1, pos.x + 0, color);
- hLine(pos.x - 1, pos.y + 2, pos.x + 1, color);
- hLine(pos.x - 2, pos.y + 3, pos.x + 2, color);
- hLine(pos.x - 3, pos.y + 4, pos.x + 3, color);
+ hLine(x + 0, y + 1, x + 0, color);
+ hLine(x - 1, y + 2, x + 1, color);
+ hLine(x - 2, y + 3, x + 2, color);
+ hLine(x - 3, y + 4, x + 3, color);
break;
case THIN_LINE:
- vLine(pos.x, pos.y - g_conf->_baseLine + 1, pos.y - 1, color);
+ vLine(x, y - g_conf->_baseLine + 1, y - 1, color);
break;
case FAT_LINE:
- Graphics::Screen::fillRect(Rect(pos.x, pos.y - g_conf->_baseLine + 1, pos.x + 1, pos.y - 1), color);
+ Graphics::Screen::fillRect(Rect(x, y - g_conf->_baseLine + 1, x + 1, y - 1), color);
break;
default:
// BLOCK
- Graphics::Screen::fillRect(Rect(pos.x, pos.y - g_conf->_baseLine + 1, pos.x + g_conf->_cellW, pos.y - 1), color);
+ Graphics::Screen::fillRect(Rect(x, y - g_conf->_baseLine + 1, x + g_conf->_cellW, y - 1), color);
break;
}
}
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
index 66553c3..d7631ef 100644
--- a/engines/gargoyle/screen.h
+++ b/engines/gargoyle/screen.h
@@ -52,6 +52,11 @@ public:
*/
void fillRect(const Rect &box, const byte *rgb);
+ /**
+ * Draws the text input caret at the given position
+ * @remarks The position specifies the caret's bottom-left corner,
+ * and the X position is in multiples of GLI_SUBPIX
+ */
void drawCaret(const Point &pos);
};
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index b22246d..34addcc 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -1003,7 +1003,7 @@ void TextBufferWindow::redraw() {
if (_windows->getFocusWindow() == this && i == 0 && (_lineRequest || _lineRequestUni)) {
w = calcWidth(_chars, _attrs, 0, _inCurs, spw);
if (w < pw - g_conf->_caretShape * 2 * GLI_SUBPIX)
- screen.drawCaret(Point((x0 + SLOP + ln->_lm + w) / GLI_SUBPIX, y + g_conf->_baseLine));
+ screen.drawCaret(Point(x0 + SLOP + ln->_lm + w, y + g_conf->_baseLine));
}
/*
@@ -1017,7 +1017,7 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- x = screen.drawStringUni(Point(x / GLI_SUBPIX, y),
+ x = screen.drawStringUni(Point(x, y + g_conf->_baseLine),
font, color, Common::U32String(ln->_chars + a, b - a), spw);
a = b;
}
@@ -1025,14 +1025,13 @@ void TextBufferWindow::redraw() {
link = ln->_attrs[a].hyper;
font = ln->_attrs[a].attrFont(_styles);
color = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
- screen.drawStringUni(Point(x / GLI_SUBPIX, y), font, color, Common::U32String(ln->_chars + a, linelen - a), spw);
+ screen.drawStringUni(Point(x, y + g_conf->_baseLine), font, color, Common::U32String(ln->_chars + a, linelen - a), spw);
}
/*
* draw more prompt
*/
- if (_scrollPos && _height > 1)
- {
+ if (_scrollPos && _height > 1) {
x = x0 + SLOP;
y = y0 + (_height - 1) * g_conf->_leading;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 455655f..05c45fa 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -608,7 +608,8 @@ void TextGridWindow::redraw() {
o = x;
for (k = a, o = x; k < b; k++, o += g_conf->_cellW) {
- screen.drawStringUni(Point(o, y), font, fgcolor, Common::U32String(&ln->_chars[k], 1), -1);
+ screen.drawStringUni(Point(o * GLI_SUBPIX, y + g_conf->_baseLine), font,
+ fgcolor, Common::U32String(&ln->_chars[k], 1), -1);
}
if (link) {
screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w,
@@ -629,7 +630,8 @@ void TextGridWindow::redraw() {
screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
for (k = a, o = x; k < b; k++, o += g_conf->_cellW) {
- screen.drawStringUni(Point(o, y), font, fgcolor, Common::U32String(&ln->_chars[k], 1));
+ screen.drawStringUni(Point(o * GLI_SUBPIX, y + g_conf->_baseLine), font,
+ fgcolor, Common::U32String(&ln->_chars[k], 1));
}
if (link) {
screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w, g_conf->_linkStyle),
Commit: 012d4bafbb44f3717fa4f7bfdddeb83eb6e906f2
https://github.com/scummvm/scummvm/commit/012d4bafbb44f3717fa4f7bfdddeb83eb6e906f2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix placement of input cursor
Changed paths:
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 7cf4e1d..4f298b0 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -119,13 +119,13 @@ int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const C
size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
// TODO: Handle spw
Graphics::Font *font = _fontTable[fontIdx];
- return font->getStringWidth(text);
+ return font->getStringWidth(text) * GLI_SUBPIX;
}
size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
// TODO: Handle spw
Graphics::Font *font = _fontTable[fontIdx];
- return font->getStringWidth(text);
+ return font->getStringWidth(text) * GLI_SUBPIX;
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index f2a6eb8..dc0bfd8 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -84,6 +84,7 @@ public:
* @param fontIdx Which font to use
* @param text Text to get the width of
* @param spw ???
+ * @returns Width of string multiplied by GLI_SUBPIX
*/
size_t stringWidth(int fontIdx, const Common::String &text, int spw = -1);
@@ -92,6 +93,7 @@ public:
* @param fontIdx Which font to use
* @param text Text to get the width of
* @param spw ???
+ * @returns Width of string multiplied by GLI_SUBPIX
*/
size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = -1);
};
Commit: c0fd6ca3e4d528d1a82daaf1140792853c243e45
https://github.com/scummvm/scummvm/commit/c0fd6ca3e4d528d1a82daaf1140792853c243e45
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Cleanup of comments in text window classes
Changed paths:
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 34addcc..668fc3a 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -78,7 +78,7 @@ void TextBufferWindow::rearrange(const Rect &box) {
newwid = (box.width() - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) / g_conf->_cellW;
newhgt = (box.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
- /* align text with bottom */
+ // align text with bottom
rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
_yAdj = (box.height() - rnd);
_bbox.top += (box.height() - rnd);
@@ -89,20 +89,20 @@ void TextBufferWindow::rearrange(const Rect &box) {
}
if (newhgt != _height) {
- /* scroll up if we obscure new lines */
+ // scroll up if we obscure new lines
if (_lastSeen >= newhgt - 1)
_scrollPos += (_height - newhgt);
_height = newhgt;
- /* keep window within 'valid' lines */
+ // keep window within 'valid' lines
if (_scrollPos > _scrollMax - _height + 1)
_scrollPos = _scrollMax - _height + 1;
if (_scrollPos < 0)
_scrollPos = 0;
touchScroll();
- /* allocate copy buffer */
+ // allocate copy buffer
if (_copyBuf)
delete[] _copyBuf;
_copyBuf = new glui32[_height * TBLINELEN];
@@ -125,7 +125,7 @@ void TextBufferWindow::reflow() {
_lines[0]._len = _numChars;
- /* allocate temp buffers */
+ // allocate temp buffers
Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
glui32 *charbuf = new glui32[SCROLLBACK * TBLINELEN];
int *alignbuf = new int[SCROLLBACK];
@@ -143,7 +143,7 @@ void TextBufferWindow::reflow() {
return;
}
- /* copy text to temp buffers */
+ // copy text to temp buffers
oldattr = _attr;
curattr.clear();
@@ -190,11 +190,11 @@ void TextBufferWindow::reflow() {
offsetbuf[x] = -1;
- /* clear window */
+ // clear window
clear();
- /* and dump text back */
+ // and dump text back
x = 0;
for (i = 0; i < p; i++) {
@@ -210,7 +210,7 @@ void TextBufferWindow::reflow() {
putCharUni(charbuf[i]);
}
- /* terribly sorry about this... */
+ // terribly sorry about this...
_lastSeen = 0;
_scrollPos = 0;
@@ -369,7 +369,7 @@ void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldle
void TextBufferWindow::touch(int line) {
int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
- _lines[line]._dirty = 1;
+ _lines[line]._dirty = true;
g_vm->_windowMask->clearSelection();
_windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
}
@@ -447,8 +447,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
if (g_conf->_spaces && _attr.style != style_Preformatted
&& _styles[_attr.style].bg == color
- && !_styles[_attr.style].reverse)
- {
+ && !_styles[_attr.style].reverse) {
// turn (period space space) into (period space)
if (g_conf->_spaces == 1) {
if (ch == '.')
@@ -616,13 +615,13 @@ void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen
gli_tts_flush();
- /* because '>' prompt is ugly without extra space */
+ // because '>' prompt is ugly without extra space
if (_numChars && _chars[_numChars - 1] == '>')
putCharUni(' ');
if (_numChars && _chars[_numChars - 1] == '?')
putCharUni(' ');
- /* make sure we have some space left for typing... */
+ // make sure we have some space left for typing...
pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2) * GLI_SUBPIX;
pw = pw - 2 * SLOP - _radjw + _ladjw;
if (calcWidth(_chars, _attrs, 0, _numChars, -1) >= pw * 3 / 4)
@@ -667,13 +666,13 @@ void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 in
gli_tts_flush();
- /* because '>' prompt is ugly without extra space */
+ // because '>' prompt is ugly without extra space
if (_numChars && _chars[_numChars - 1] == '>')
putCharUni(' ');
if (_numChars && _chars[_numChars - 1] == '?')
putCharUni(' ');
- /* make sure we have some space left for typing... */
+ // make sure we have some space left for typing...
pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2) * GLI_SUBPIX;
pw = pw - 2 * SLOP - _radjw + _ladjw;
if (calcWidth(_chars, _attrs, 0, _numChars, -1) >= pw * 3 / 4)
@@ -814,14 +813,14 @@ void TextBufferWindow::redraw() {
pw = x1 - x0 - 2 * GLI_SUBPIX;
- /* check if any part of buffer is selected */
+ // check if any part of buffer is selected
selbuf = g_vm->_windowMask->checkSelection(x0/GLI_SUBPIX,y0,x1/GLI_SUBPIX,y1);
for (i = _scrollPos + _height - 1; i >= _scrollPos; i--) {
- /* top of line */
+ // top of line
y = y0 + (_height - (i - _scrollPos) - 1) * g_conf->_leading;
- /* check if part of line is selected */
+ // check if part of line is selected
if (selbuf) {
selrow = g_vm->_windowMask->getSelection(x0/GLI_SUBPIX, y,
x1/GLI_SUBPIX, y + g_conf->_leading,
@@ -832,22 +831,22 @@ void TextBufferWindow::redraw() {
selrow = false;
}
- /* mark selected line dirty */
+ // mark selected line dirty
if (selrow)
_lines[i]._dirty = true;
memcpy(ln, &_lines[i], sizeof(TextBufferRow));
- /* skip if we can */
+ // skip if we can
if (!ln->_dirty && !ln->_repaint && !Windows::_forceRedraw && _scrollPos == 0)
continue;
- /* repaint previously selected lines if needed */
+ // repaint previously selected lines if needed
if (ln->_repaint && !Windows::_forceRedraw)
_windows->redrawRect(Rect(x0 / GLI_SUBPIX, y,
x1/GLI_SUBPIX, y + g_conf->_leading));
- /* keep selected line dirty and flag for repaint */
+ // keep selected line dirty and flag for repaint
if (!selrow) {
_lines[i]._dirty = false;
_lines[i]._repaint = false;
@@ -855,20 +854,20 @@ void TextBufferWindow::redraw() {
_lines[i]._repaint = true;
}
- /* leave bottom line blank for [more] prompt */
+ // leave bottom line blank for [more] prompt
if (i == _scrollPos && i > 0)
continue;
linelen = ln->_len;
- /* kill spaces at the end unless they're a different color*/
+ // kill spaces at the end unless they're a different color
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
while (i > 0 && linelen > 1 && ln->_chars[linelen-1] == ' '
&& _styles[ln->_attrs[linelen-1].style].bg == color
&& !_styles[ln->_attrs[linelen-1].style].reverse)
linelen --;
- /* kill characters that would overwrite the scroll bar */
+ // kill characters that would overwrite the scroll bar
while (linelen > 1 && calcWidth(ln->_chars, ln->_attrs, 0, linelen, -1) >= pw)
linelen --;
@@ -888,24 +887,24 @@ void TextBufferWindow::redraw() {
spw = -1;
}
- /* find and highlight selected characters */
+ // find and highlight selected characters
if (selrow && !Windows::_claimSelect) {
lsc = 0;
rsc = 0;
selchar = false;
- /* optimized case for all chars selected */
+ // optimized case for all chars selected
if (selleft && selright) {
rsc = linelen > 0 ? linelen - 1 : 0;
selchar = calcWidth(ln->_chars, ln->_attrs, lsc, rsc, spw)/GLI_SUBPIX;
} else {
- /* optimized case for leftmost char selected */
+ // optimized case for leftmost char selected
if (selleft) {
tsc = linelen > 0 ? linelen - 1 : 0;
selchar = calcWidth(ln->_chars, ln->_attrs, lsc, tsc, spw)/GLI_SUBPIX;
} else {
- /* find the substring contained by the selection */
+ // find the substring contained by the selection
tx = (x0 + SLOP + ln->_lm)/GLI_SUBPIX;
- /* measure string widths until we find left char */
+ // measure string widths until we find left char
for (tsc = 0; tsc < linelen; tsc++) {
tsw = calcWidth(ln->_chars, ln->_attrs, 0, tsc, spw)/GLI_SUBPIX;
if (tsw + tx >= sx0 ||
@@ -917,11 +916,11 @@ void TextBufferWindow::redraw() {
}
}
if (selchar) {
- /* optimized case for rightmost char selected */
+ // optimized case for rightmost char selected
if (selright) {
rsc = linelen > 0 ? linelen - 1 : 0;
} else {
- /* measure string widths until we find right char */
+ // measure string widths until we find right char
for (tsc = lsc; tsc < linelen; tsc++) {
tsw = calcWidth(ln->_chars, ln->_attrs, lsc, tsc, spw)/GLI_SUBPIX;
if (tsw + sx0 < sx1)
@@ -932,7 +931,7 @@ void TextBufferWindow::redraw() {
}
}
}
- /* reverse colors for selected chars */
+ // reverse colors for selected chars
if (selchar) {
for (tsc = lsc; tsc <= rsc; tsc++) {
ln->_attrs[tsc].reverse = !ln->_attrs[tsc].reverse;
@@ -940,14 +939,14 @@ void TextBufferWindow::redraw() {
_copyPos++;
}
}
- /* add newline if we reach the end of the line */
+ // add newline if we reach the end of the line
if (ln->_len == 0 || ln->_len == (rsc+1)) {
_copyBuf[_copyPos] = '\n';
_copyPos++;
}
}
- /* clear any stored hyperlink coordinates */
+ // clear any stored hyperlink coordinates
g_vm->_windowMask->putHyperlink(0, x0/GLI_SUBPIX, y,
x1/GLI_SUBPIX, y + g_conf->_leading);
@@ -1043,17 +1042,19 @@ void TextBufferWindow::redraw() {
w = screen.stringWidth(g_conf->_moreFont, g_conf->_morePrompt);
- if (g_conf->_moreAlign == 1) /* center */
+ if (g_conf->_moreAlign == 1)
+ // center
x = x0 + SLOP + (x1 - x0 - w - SLOP * 2) / 2;
- if (g_conf->_moreAlign == 2) /* right */
+ if (g_conf->_moreAlign == 2)
+ // right
x = x1 - SLOP - w;
color = Windows::_overrideFgSet ? g_conf->_moreColor : _fgColor;
screen.drawString(Point(x, y + g_conf->_baseLine),
g_conf->_moreFont, color, g_conf->_morePrompt);
- y1 = y; /* don't want pictures overdrawing "[more]" */
+ y1 = y; // don't want pictures overdrawing "[more]"
- /* try to claim the focus */
+ // try to claim the focus
_moreRequest = true;
Windows::_moreFocus = true;
} else {
@@ -1103,7 +1104,7 @@ void TextBufferWindow::redraw() {
* Draw the scrollbar
*/
- /* try to claim scroll keys */
+ // try to claim scroll keys
_scrollRequest = _scrollMax > _height;
if (_scrollRequest && g_conf->_scrollWidth)
@@ -1140,7 +1141,7 @@ void TextBufferWindow::redraw() {
}
}
- /* send selected text to clipboard */
+ // send selected text to clipboard
if (selbuf && _copyPos) {
Windows::_claimSelect = true;
@@ -1150,7 +1151,7 @@ void TextBufferWindow::redraw() {
_copyPos = 0;
}
- /* no more prompt means all text has been seen */
+ // no more prompt means all text has been seen
if (!_moreRequest)
_lastSeen = 0;
@@ -1158,7 +1159,7 @@ void TextBufferWindow::redraw() {
}
int TextBufferWindow::acceptScroll(glui32 arg) {
- int pageht = _height - 2; /* 1 for prompt, 1 for overlap */
+ int pageht = _height - 2; // 1 for prompt, 1 for overlap
int startpos = _scrollPos;
switch (arg) {
@@ -1266,9 +1267,7 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
}
switch (arg) {
-
- /* History keys (up and down) */
-
+ // History keys (up and down)
case keycode_Up:
if (_historyPos == _historyFirst)
return;
@@ -1304,8 +1303,7 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
_numChars - _inFence);
break;
- /* Cursor movement keys, during line input. */
-
+ // Cursor movement keys, during line input.
case keycode_Left:
if (_inCurs <= _inFence)
return;
@@ -1344,8 +1342,7 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
_inCurs++;
break;
- /* Delete keys, during line input. */
-
+ // Delete keys, during line input.
case keycode_Delete:
if (_inCurs <= _inFence)
return;
@@ -1364,8 +1361,7 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
putTextUni(nullptr, 0, _inFence, _numChars - _inFence);
break;
- /* Regular keys */
-
+ // Regular keys
case keycode_Return:
acceptLine(arg);
break;
@@ -1383,7 +1379,6 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
touch(0);
}
-/* Return or enter, during line input. Ends line input. */
void TextBufferWindow::acceptLine(glui32 keycode) {
int ix;
int len, olen;
@@ -1445,8 +1440,7 @@ void TextBufferWindow::acceptLine(glui32 keycode) {
}
}
- /* Store in event buffer. */
-
+ // Store in event buffer.
if (len > inmax)
len = inmax;
@@ -1495,7 +1489,7 @@ bool TextBufferWindow::leftquote(glui32 c) {
switch (c) {
case '(': case '[':
- /* The following are Unicode characters in the "Separator, Space" category. */
+ // The following are Unicode characters in the "Separator, Space" category.
case 0x0020: case 0x00a0: case 0x1680: case 0x2000:
case 0x2001: case 0x2002: case 0x2003: case 0x2004:
case 0x2005: case 0x2006: case 0x2007: case 0x2008:
@@ -1572,10 +1566,9 @@ void TextBufferWindow::scrollResize() {
_chars = _lines[0]._chars;
_attrs = _lines[0]._attrs;
- for (i = _scrollBack; i < (_scrollBack + SCROLLBACK); i++)
- {
- _lines[i]._dirty = 0;
- _lines[i]._repaint = 0;
+ for (i = _scrollBack; i < (_scrollBack + SCROLLBACK); i++) {
+ _lines[i]._dirty = false;
+ _lines[i]._repaint = false;
_lines[i]._lm = 0;
_lines[i]._rm = 0;
_lines[i]._lPic = 0;
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index ab7890a..fdca1d8 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -66,6 +66,9 @@ private:
*/
void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
+ /**
+ * Return or enter, during line input. Ends line input.
+ */
void acceptLine(glui32 keycode);
/**
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 05c45fa..283922c 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -97,10 +97,10 @@ void TextGridWindow::putCharUni(uint32 ch) {
if (_curY < 0)
_curY = 0;
else if (_curY >= _height)
- return; /* outside the window */
+ return; // outside the window
if (ch == '\n') {
- /* a newline just moves the cursor. */
+ // a newline just moves the cursor.
_curY++;
_curX = 0;
return;
@@ -121,14 +121,14 @@ bool TextGridWindow::unputCharUni(uint32 ch) {
TextGridRow *ln;
int oldx = _curX, oldy = _curY;
- /* Move the cursor back. */
+ // Move the cursor back.
if (_curX >= _width)
_curX = _width - 1;
else
_curX--;
- /* Canonicalize the cursor position. That is, the cursor may have been
- left outside the window area; wrap it if necessary. */
+ // Canonicalize the cursor position. That is, the cursor may have been
+ // left outside the window area; wrap it if necessary.
if (_curX < 0) {
_curX = _width - 1;
_curY--;
@@ -144,7 +144,7 @@ bool TextGridWindow::unputCharUni(uint32 ch) {
return 1; // deleted a newline
_curX = oldx;
_curY = oldy;
- return 0; // it wasn't there */
+ return 0; // it wasn't there
}
ln = &(_lines[_curY]);
@@ -481,8 +481,7 @@ void TextGridWindow::acceptReadLine(glui32 arg) {
switch (arg) {
- /* Delete keys, during line input. */
-
+ // Delete keys, during line input.
case keycode_Delete:
if (_inLen <= 0)
return;
@@ -515,8 +514,7 @@ void TextGridWindow::acceptReadLine(glui32 arg) {
_inCurs = 0;
break;
- /* Cursor movement keys, during line input. */
-
+ // Cursor movement keys, during line input.
case keycode_Left:
if (_inCurs <= 0)
return;
@@ -593,7 +591,7 @@ void TextGridWindow::redraw() {
x = x0;
y = y0 + i * g_conf->_leading;
- /* clear any stored hyperlink coordinates */
+ // clear any stored hyperlink coordinates
g_vm->_windowMask->putHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
a = 0;
Commit: d61a7a9ee68a9c3373647fb94ad5fb5cba574f4c
https://github.com/scummvm/scummvm/commit/d61a7a9ee68a9c3373647fb94ad5fb5cba574f4c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Change key handle if block to a switch statement
Changed paths:
engines/gargoyle/events.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index ef4c59d..02c3d8d 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -160,32 +160,36 @@ void Events::handleKeyDown(const Common::KeyState &ks) {
if (ks.flags & Common::KBD_ALT)
return;
- if (ks.keycode == Common::KEYCODE_RETURN) windows.inputHandleKey(keycode_Return);
- else if (ks.keycode == Common::KEYCODE_BACKSPACE) windows.inputHandleKey(keycode_Delete);
- else if (ks.keycode == Common::KEYCODE_DELETE) windows.inputHandleKey(keycode_Erase);
- else if (ks.keycode == Common::KEYCODE_TAB) windows.inputHandleKey(keycode_Tab);
- else if (ks.keycode == Common::KEYCODE_UP) windows.inputHandleKey(keycode_PageUp);
- else if (ks.keycode == Common::KEYCODE_PAGEDOWN) windows.inputHandleKey(keycode_PageDown);
- else if (ks.keycode == Common::KEYCODE_HOME) windows.inputHandleKey(keycode_Home);
- else if (ks.keycode == Common::KEYCODE_END) windows.inputHandleKey(keycode_End);
- else if (ks.keycode == Common::KEYCODE_LEFT) windows.inputHandleKey(keycode_Left);
- else if (ks.keycode == Common::KEYCODE_RIGHT) windows.inputHandleKey(keycode_Right);
- else if (ks.keycode == Common::KEYCODE_UP) windows.inputHandleKey(keycode_Up);
- else if (ks.keycode == Common::KEYCODE_DOWN) windows.inputHandleKey(keycode_Down);
- else if (ks.keycode == Common::KEYCODE_ESCAPE) windows.inputHandleKey(keycode_Escape);
- else if (ks.keycode == Common::KEYCODE_F1) windows.inputHandleKey(keycode_Func1);
- else if (ks.keycode == Common::KEYCODE_F2) windows.inputHandleKey(keycode_Func2);
- else if (ks.keycode == Common::KEYCODE_F3) windows.inputHandleKey(keycode_Func3);
- else if (ks.keycode == Common::KEYCODE_F4) windows.inputHandleKey(keycode_Func4);
- else if (ks.keycode == Common::KEYCODE_F5) windows.inputHandleKey(keycode_Func5);
- else if (ks.keycode == Common::KEYCODE_F6) windows.inputHandleKey(keycode_Func6);
- else if (ks.keycode == Common::KEYCODE_F7) windows.inputHandleKey(keycode_Func7);
- else if (ks.keycode == Common::KEYCODE_F8) windows.inputHandleKey(keycode_Func8);
- else if (ks.keycode == Common::KEYCODE_F9) windows.inputHandleKey(keycode_Func9);
- else if (ks.keycode == Common::KEYCODE_F10) windows.inputHandleKey(keycode_Func10);
- else if (ks.keycode == Common::KEYCODE_F11) windows.inputHandleKey(keycode_Func11);
- else if (ks.keycode == Common::KEYCODE_F12) windows.inputHandleKey(keycode_Func12);
- else windows.inputHandleKey(ks.ascii);
+ switch (ks.keycode) {
+ case Common::KEYCODE_RETURN: windows.inputHandleKey(keycode_Return); break;
+ case Common::KEYCODE_BACKSPACE: windows.inputHandleKey(keycode_Delete); break;
+ case Common::KEYCODE_DELETE: windows.inputHandleKey(keycode_Erase); break;
+ case Common::KEYCODE_TAB: windows.inputHandleKey(keycode_Tab); break;
+ case Common::KEYCODE_PAGEUP: windows.inputHandleKey(keycode_PageUp); break;
+ case Common::KEYCODE_PAGEDOWN: windows.inputHandleKey(keycode_PageDown); break;
+ case Common::KEYCODE_HOME: windows.inputHandleKey(keycode_Home); break;
+ case Common::KEYCODE_END: windows.inputHandleKey(keycode_End); break;
+ case Common::KEYCODE_LEFT: windows.inputHandleKey(keycode_Left); break;
+ case Common::KEYCODE_RIGHT: windows.inputHandleKey(keycode_Right); break;
+ case Common::KEYCODE_UP: windows.inputHandleKey(keycode_Up); break;
+ case Common::KEYCODE_DOWN: windows.inputHandleKey(keycode_Down); break;
+ case Common::KEYCODE_ESCAPE: windows.inputHandleKey(keycode_Escape); break;
+ case Common::KEYCODE_F1: windows.inputHandleKey(keycode_Func1); break;
+ case Common::KEYCODE_F2: windows.inputHandleKey(keycode_Func2); break;
+ case Common::KEYCODE_F3: windows.inputHandleKey(keycode_Func3); break;
+ case Common::KEYCODE_F4: windows.inputHandleKey(keycode_Func4); break;
+ case Common::KEYCODE_F5: windows.inputHandleKey(keycode_Func5); break;
+ case Common::KEYCODE_F6: windows.inputHandleKey(keycode_Func6); break;
+ case Common::KEYCODE_F7: windows.inputHandleKey(keycode_Func7); break;
+ case Common::KEYCODE_F8: windows.inputHandleKey(keycode_Func8); break;
+ case Common::KEYCODE_F9: windows.inputHandleKey(keycode_Func9); break;
+ case Common::KEYCODE_F10: windows.inputHandleKey(keycode_Func10); break;
+ case Common::KEYCODE_F11: windows.inputHandleKey(keycode_Func11); break;
+ case Common::KEYCODE_F12: windows.inputHandleKey(keycode_Func12); break;
+ default:
+ windows.inputHandleKey(ks.ascii); break;
+ break;
+ }
}
void Events::handleScroll(bool wheelUp) {
Commit: 4229312b227dc62f721d7de3cdfdee8a6310f22f
https://github.com/scummvm/scummvm/commit/4229312b227dc62f721d7de3cdfdee8a6310f22f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Cleanup of formatting in text buffer window class
Changed paths:
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 668fc3a..61cf92a 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -191,11 +191,9 @@ void TextBufferWindow::reflow() {
offsetbuf[x] = -1;
// clear window
-
clear();
// and dump text back
-
x = 0;
for (i = 0; i < p; i++) {
if (i == inputbyte)
@@ -242,8 +240,7 @@ void TextBufferWindow::touchScroll() {
}
bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
- if (align == imagealign_MarginRight)
- {
+ if (align == imagealign_MarginRight) {
if (_lines[0]._rPic || _numChars)
return false;
@@ -307,8 +304,7 @@ void TextBufferWindow::putText(const char *buf, int len, int pos, int oldlen) {
if (_numChars + diff >= TBLINELEN)
return;
- if (diff != 0 && pos + oldlen < _numChars)
- {
+ if (diff != 0 && pos + oldlen < _numChars) {
memmove(_chars + pos + len,
_chars + pos + oldlen,
(_numChars - (pos + oldlen)) * 4);
@@ -317,8 +313,7 @@ void TextBufferWindow::putText(const char *buf, int len, int pos, int oldlen) {
(_numChars - (pos + oldlen)) * sizeof(Attributes));
}
if (len > 0) {
- int i;
- for (i = 0; i < len; i++) {
+ for (int i = 0; i < len; i++) {
_chars[pos + i] = buf[i];
_attrs[pos + i].set(style_Input);
}
@@ -368,10 +363,11 @@ void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldle
}
void TextBufferWindow::touch(int line) {
- int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
_lines[line]._dirty = true;
g_vm->_windowMask->clearSelection();
- _windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
+ //int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
+ //_windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
+ redraw();
}
glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
@@ -468,8 +464,7 @@ void TextBufferWindow::putCharUni(glui32 ch) {
_spaced = 1;
else if (ch == ' ' && _spaced == 1)
_spaced = 2;
- else if (ch != ' ' && _spaced == 2)
- {
+ else if (ch != ' ' && _spaced == 2) {
_spaced = 0;
putCharUni(' ');
} else {
@@ -492,11 +487,12 @@ void TextBufferWindow::putCharUni(glui32 ch) {
if (calcWidth(_chars, _attrs, 0, linelen, -1) >= pw) {
bpoint = _numChars;
- for (i = _numChars - 1; i > 0; i--)
+ for (i = _numChars - 1; i > 0; i--) {
if (_chars[i] == ' ') {
bpoint = i + 1; // skip space
break;
}
+ }
saved = _numChars - bpoint;
@@ -747,8 +743,7 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
ch = '?';
((char *)inbuf)[ix] = (char)ch;
}
- }
- else {
+ } else {
for (ix = 0; ix<len; ix++)
((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
}
@@ -771,8 +766,7 @@ void TextBufferWindow::cancelLineEvent(Event *ev) {
if (_echoLineInput) {
putCharUni('\n');
- }
- else {
+ } else {
_numChars = _inFence;
touch(0);
}
@@ -1107,8 +1101,7 @@ void TextBufferWindow::redraw() {
// try to claim scroll keys
_scrollRequest = _scrollMax > _height;
- if (_scrollRequest && g_conf->_scrollWidth)
- {
+ if (_scrollRequest && g_conf->_scrollWidth) {
int t0, t1;
x0 = _bbox.right - g_conf->_scrollWidth;
x1 = _bbox.right;
@@ -1155,7 +1148,7 @@ void TextBufferWindow::redraw() {
if (!_moreRequest)
_lastSeen = 0;
- free(ln);
+ delete ln;
}
int TextBufferWindow::acceptScroll(glui32 arg) {
@@ -1225,6 +1218,7 @@ void TextBufferWindow::acceptReadChar(glui32 arg) {
return;
default:
key = arg;
+ break;
}
gli_tts_purge();
@@ -1246,10 +1240,7 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
if (_height < 2)
_scrollPos = 0;
- if (_scrollPos
- || arg == keycode_PageUp
- || arg == keycode_MouseWheelUp)
- {
+ if (_scrollPos || arg == keycode_PageUp || arg == keycode_MouseWheelUp) {
acceptScroll(arg);
return;
}
@@ -1367,8 +1358,7 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
break;
default:
- if (arg >= 32 && arg <= 0x10FFFF)
- {
+ if (arg >= 32 && arg <= 0x10FFFF) {
if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
arg -= 0x20;
putTextUni(&arg, 1, _inCurs, 0);
Commit: 4b5db1da07572eca7a69e40e32c4935921908b3c
https://github.com/scummvm/scummvm/commit/4b5db1da07572eca7a69e40e32c4935921908b3c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix showing input text to the right of input prompt
Changed paths:
engines/gargoyle/fonts.cpp
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 4f298b0..e523ecb 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -113,7 +113,7 @@ int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const C
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
- return font->getBoundingBox(text, pt.x, pt.y, _surface->w - pt.x).right;
+ return font->getBoundingBox(text, pt.x, pt.y, _surface->w - pt.x).right * GLI_SUBPIX;
}
size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
Commit: d954f70d499c9cd96b2bedbfbec59bf7ed4f715a
https://github.com/scummvm/scummvm/commit/d954f70d499c9cd96b2bedbfbec59bf7ed4f715a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix having space between prmpt and input text
Changed paths:
engines/gargoyle/fonts.cpp
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index e523ecb..8172c78 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -104,7 +104,9 @@ int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Comm
Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
- return font->getBoundingBox(text, pt.x, pt.y, _surface->w - pt.x).right;
+
+ pt.x += font->getStringWidth(text);
+ return MIN((int)pt.x, (int)_surface->w) * GLI_SUBPIX;
}
int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
@@ -113,7 +115,8 @@ int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const C
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
- return font->getBoundingBox(text, pt.x, pt.y, _surface->w - pt.x).right * GLI_SUBPIX;
+ pt.x += font->getStringWidth(text);
+ return MIN((int)pt.x, (int)_surface->w) * GLI_SUBPIX;
}
size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
Commit: 2551927bf68dfbd43997756821737ac41adc7dfb
https://github.com/scummvm/scummvm/commit/2551927bf68dfbd43997756821737ac41adc7dfb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix processing input after Enter is pressed
Changed paths:
engines/gargoyle/events.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 02c3d8d..93b9141 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -94,7 +94,7 @@ void Events::dispatchEvent(Event &ev, bool polled) {
if (!polled) {
dispatch = _eventsLogged.retrieve();
- if (dispatch)
+ if (!dispatch)
dispatch = _eventsPolled.retrieve();
} else {
dispatch = _eventsPolled.retrieve();
Commit: e36dbfaf2e9d8d44502a7011717bcc97155212ad
https://github.com/scummvm/scummvm/commit/e36dbfaf2e9d8d44502a7011717bcc97155212ad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Prompt for keypress when game is exited
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
engines/gargoyle/scott/scott.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 93b9141..d5eccfe 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -226,4 +226,20 @@ void Events::handleButtonUp(bool isLeft, const Point &pos) {
}
}
+void Events::waitForPress() {
+ Common::Event e;
+
+ do {
+ g_system->getEventManager()->pollEvent(e);
+ g_system->delayMillis(10);
+
+ if (checkForNextFrameCounter()) {
+ // Update the screen
+ g_vm->_screen->update();
+ }
+ } while (!g_vm->shouldQuit() && e.type != Common::EVENT_KEYDOWN &&
+ e.type != Common::EVENT_LBUTTONDOWN && e.type != Common::EVENT_RBUTTONDOWN &&
+ e.type != Common::EVENT_MBUTTONDOWN);
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 4d9e49b..3860dc2 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -210,6 +210,11 @@ public:
* Store an event for retrieval
*/
void store(EvType type, Window *win, uint32 val1 = 0, uint32 val2 = 0);
+
+ /**
+ * Wait for a keyboard or mouse press
+ */
+ void waitForPress();
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index c9823a9..bda0fa7 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -59,6 +59,9 @@ Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
}
void Glk::glk_exit(void) {
+ glk_put_string("[ press any key to exit ]");
+ _events->waitForPress();
+
quitGame();
}
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 3812392..3a085ea 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -93,7 +93,7 @@ Distributed under the GNU software license\n\n");
if (GetInput(&vb, &no) == -1)
continue;
if (g_vm->shouldQuit())
- return;
+ break;
switch (PerformActions(vb, no)) {
case -1:
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 3ebb98b..cdc2e7d 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -121,7 +121,6 @@ void WindowStream::putBuffer(const char *buf, size_t len) {
_window->putCharUni(*buf);
if (_window->_echoStream)
_window->_echoStream->putBuffer(buf, len);
-
}
void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index d753d53..20ce03d 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -98,11 +98,16 @@ private:
*/
PairWindow *newPairWindow(glui32 method, Window *key, glui32 size);
+ /**
+ * Set the window focus
+ */
void refocus(Window *win);
+ /**
+ * Used to loop over windows in tree order
+ */
Window *iterateTreeOrder(Window *win);
-
/**
* Pick first window which has a more request
*/
Commit: 55c05a0d7ae6ee03f2be8ece75437bce9adb14f7
https://github.com/scummvm/scummvm/commit/55c05a0d7ae6ee03f2be8ece75437bce9adb14f7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Camel case method names
Changed paths:
engines/gargoyle/scott/scott.cpp
engines/gargoyle/scott/scott.h
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 3a085ea..ef25495 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -77,30 +77,30 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
Top = Bottom;
}
- Output("\
+ output("\
Scott Free, A Scott Adams game driver in C.\n\
Release 1.14, (c) 1993,1994,1995 Swansea University Computer Society.\n\
Distributed under the GNU software license\n\n");
- LoadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
+ loadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
while (!shouldQuit()) {
glk_tick();
- PerformActions(0, 0);
+ performActions(0, 0);
- Look();
+ look();
- if (GetInput(&vb, &no) == -1)
+ if (getInput(&vb, &no) == -1)
continue;
if (g_vm->shouldQuit())
break;
- switch (PerformActions(vb, no)) {
+ switch (performActions(vb, no)) {
case -1:
- Output("I don't understand your command. ");
+ output("I don't understand your command. ");
break;
case -2:
- Output("I can't do that yet. ");
+ output("I can't do that yet. ");
break;
default:
break;
@@ -114,9 +114,9 @@ Distributed under the GNU software license\n\n");
if (Items[LIGHT_SOURCE].Location == CARRIED ||
Items[LIGHT_SOURCE].Location == MyLoc) {
if (Options&SCOTTLIGHT)
- Output("Light has run out! ");
+ output("Light has run out! ");
else
- Output("Your light has run out. ");
+ output("Your light has run out. ");
}
if (Options&PREHISTORIC_LAMP)
Items[LIGHT_SOURCE].Location = DESTROYED;
@@ -125,12 +125,12 @@ Distributed under the GNU software license\n\n");
Items[LIGHT_SOURCE].Location == MyLoc) {
if (Options&SCOTTLIGHT) {
- Output("Light runs out in ");
- OutputNumber(GameHeader.LightTime);
- Output(" turns. ");
+ output("Light runs out in ");
+ outputNumber(GameHeader.LightTime);
+ output(" turns. ");
} else {
if (GameHeader.LightTime % 5 == 0)
- Output("Your light is growing dim. ");
+ output("Your light is growing dim. ");
}
}
}
@@ -196,7 +196,7 @@ void Scott::initialize() {
*/
}
-void Scott::Display(winid_t w, const char *fmt, ...) {
+void Scott::display(winid_t w, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
@@ -206,7 +206,7 @@ void Scott::Display(winid_t w, const char *fmt, ...) {
glk_put_string_stream(glk_window_get_stream(w), msg.c_str());
}
-void Scott::Delay(int seconds) {
+void Scott::delay(int seconds) {
event_t ev;
if (!glk_gestalt(gestalt_Timer, 0))
@@ -221,26 +221,26 @@ void Scott::Delay(int seconds) {
glk_request_timer_events(0);
}
-void Scott::Fatal(const char *x) {
+void Scott::fatal(const char *x) {
error(x);
}
-void Scott::ClearScreen(void) {
+void Scott::clearScreen(void) {
glk_window_clear(Bottom);
}
-void *Scott::MemAlloc(int size) {
+void *Scott::memAlloc(int size) {
void *t = (void *)malloc(size);
if (t == nullptr)
- Fatal("Out of memory");
+ fatal("Out of memory");
return t;
}
-bool Scott::RandomPercent(uint n) {
+bool Scott::randomPercent(uint n) {
return _random.getRandomNumber(99) < n;
}
-int Scott::CountCarried(void) {
+int Scott::countCarried(void) {
int ct = 0;
int n = 0;
while (ct <= GameHeader.NumItems) {
@@ -251,7 +251,7 @@ int Scott::CountCarried(void) {
return n;
}
-const char *Scott::MapSynonym(const char *word) {
+const char *Scott::mapSynonym(const char *word) {
int n = 1;
const char *tp;
static char lastword[16]; /* Last non synonym */
@@ -268,8 +268,8 @@ const char *Scott::MapSynonym(const char *word) {
return nullptr;
}
-int Scott::MatchUpItem(const char *text, int loc) {
- const char *word = MapSynonym(text);
+int Scott::matchUpItem(const char *text, int loc) {
+ const char *word = mapSynonym(text);
int ct = 0;
if (word == nullptr)
@@ -285,7 +285,7 @@ int Scott::MatchUpItem(const char *text, int loc) {
return -1;
}
-char *Scott::ReadString(Common::SeekableReadStream *f) {
+char *Scott::readString(Common::SeekableReadStream *f) {
char tmp[1024];
char *t;
int c, nc;
@@ -294,12 +294,12 @@ char *Scott::ReadString(Common::SeekableReadStream *f) {
c = f->readByte();
} while (f->pos() < f->size() && Common::isSpace(c));
if (c != '"') {
- Fatal("Initial quote expected");
+ fatal("Initial quote expected");
}
for (;;) {
if (f->pos() >= f->size())
- Fatal("EOF in string");
+ fatal("EOF in string");
c = f->readByte();
if (c == '"') {
@@ -331,12 +331,12 @@ char *Scott::ReadString(Common::SeekableReadStream *f) {
}
tmp[ct] = 0;
- t = (char *)MemAlloc(ct + 1);
+ t = (char *)memAlloc(ct + 1);
memcpy(t, tmp, ct + 1);
return t;
}
-void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
+void Scott::loadDatabase(Common::SeekableReadStream *f, int loud) {
int unused, ni, na, nw, nr, mc, pr, tr, wl, lt, mn, trm;
int ct;
int lo;
@@ -348,22 +348,22 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
GameHeader.NumItems = ni;
- Items = (Item *)MemAlloc(sizeof(Item)*(ni + 1));
+ Items = (Item *)memAlloc(sizeof(Item)*(ni + 1));
GameHeader.NumActions = na;
- Actions = (Action *)MemAlloc(sizeof(Action)*(na + 1));
+ Actions = (Action *)memAlloc(sizeof(Action)*(na + 1));
GameHeader.NumWords = nw;
GameHeader.WordLength = wl;
- Verbs = (const char **)MemAlloc(sizeof(char *)*(nw + 1));
- Nouns = (const char **)MemAlloc(sizeof(char *)*(nw + 1));
+ Verbs = (const char **)memAlloc(sizeof(char *)*(nw + 1));
+ Nouns = (const char **)memAlloc(sizeof(char *)*(nw + 1));
GameHeader.NumRooms = nr;
- Rooms = (Room *)MemAlloc(sizeof(Room)*(nr + 1));
+ Rooms = (Room *)memAlloc(sizeof(Room)*(nr + 1));
GameHeader.MaxCarry = mc;
GameHeader.PlayerRoom = pr;
GameHeader.Treasures = tr;
GameHeader.LightTime = lt;
LightRefill = lt;
GameHeader.NumMessages = mn;
- Messages = (const char **)MemAlloc(sizeof(char *)*(mn + 1));
+ Messages = (const char **)memAlloc(sizeof(char *)*(mn + 1));
GameHeader.TreasureRoom = trm;
/* Load the actions */
@@ -390,8 +390,8 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
if (loud)
debug("Reading %d word pairs.", nw);
while (ct<nw + 1) {
- Verbs[ct] = ReadString(f);
- Nouns[ct] = ReadString(f);
+ Verbs[ct] = readString(f);
+ Nouns[ct] = readString(f);
ct++;
}
ct = 0;
@@ -403,7 +403,7 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
&rp->Exits[0], &rp->Exits[1], &rp->Exits[2],
&rp->Exits[3], &rp->Exits[4], &rp->Exits[5]);
- rp->Text = ReadString(f);
+ rp->Text = readString(f);
ct++;
rp++;
}
@@ -412,7 +412,7 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
if (loud)
debug("Reading %d messages.", mn);
while (ct<mn + 1) {
- Messages[ct] = ReadString(f);
+ Messages[ct] = readString(f);
ct++;
}
@@ -421,7 +421,7 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
debug("Reading %d items.", ni);
ip = Items;
while (ct < ni + 1) {
- ip->Text = ReadString(f);
+ ip->Text = readString(f);
ip->AutoGet = strchr(ip->Text, '/');
/* Some games use // to mean no auto get/drop word! */
if (ip->AutoGet && strcmp(ip->AutoGet, "//") && strcmp(ip->AutoGet, "/*")) {
@@ -441,7 +441,7 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
ct = 0;
/* Discard Comment Strings */
while (ct<na + 1) {
- free(ReadString(f));
+ free(readString(f));
ct++;
}
@@ -454,15 +454,15 @@ void Scott::LoadDatabase(Common::SeekableReadStream *f, int loud) {
debug("%d.\nLoad Complete.\n", ct);
}
-void Scott::Output(const char *a) {
- Display(Bottom, "%s", a);
+void Scott::output(const char *a) {
+ display(Bottom, "%s", a);
}
-void Scott::OutputNumber(int a) {
- Display(Bottom, "%d", a);
+void Scott::outputNumber(int a) {
+ display(Bottom, "%d", a);
}
-void Scott::Look(void) {
+void Scott::look(void) {
static char *ExitNames[6] = { "North", "South", "East", "West", "Up", "Down" };
Room *r;
int ct, f;
@@ -474,41 +474,41 @@ void Scott::Look(void) {
if ((BitFlags&(1 << DARKBIT)) && Items[LIGHT_SOURCE].Location != CARRIED
&& Items[LIGHT_SOURCE].Location != MyLoc) {
if (Options&YOUARE)
- Display(Top, "You can't see. It is too dark!\n");
+ display(Top, "You can't see. It is too dark!\n");
else
- Display(Top, "I can't see. It is too dark!\n");
+ display(Top, "I can't see. It is too dark!\n");
if (Options & TRS80_STYLE)
- Display(Top, TRS80_LINE);
+ display(Top, TRS80_LINE);
return;
}
r = &Rooms[MyLoc];
if (*r->Text == '*')
- Display(Top, "%s\n", r->Text + 1);
+ display(Top, "%s\n", r->Text + 1);
else {
if (Options&YOUARE)
- Display(Top, "You are in a %s\n", r->Text);
+ display(Top, "You are in a %s\n", r->Text);
else
- Display(Top, "I'm in a %s\n", r->Text);
+ display(Top, "I'm in a %s\n", r->Text);
}
ct = 0;
f = 0;
- Display(Top, "\nObvious exits: ");
+ display(Top, "\nObvious exits: ");
while (ct<6) {
if (r->Exits[ct] != 0)
{
if (f == 0)
f = 1;
else
- Display(Top, ", ");
- Display(Top, "%s", ExitNames[ct]);
+ display(Top, ", ");
+ display(Top, "%s", ExitNames[ct]);
}
ct++;
}
if (f == 0)
- Display(Top, "none");
- Display(Top, ".\n");
+ display(Top, "none");
+ display(Top, ".\n");
ct = 0;
f = 0;
pos = 0;
@@ -516,37 +516,37 @@ void Scott::Look(void) {
if (Items[ct].Location == MyLoc) {
if (f == 0) {
if (Options & YOUARE) {
- Display(Top, "\nYou can also see: ");
+ display(Top, "\nYou can also see: ");
pos = 18;
} else {
- Display(Top, "\nI can also see: ");
+ display(Top, "\nI can also see: ");
pos = 16;
}
f++;
} else if (!(Options & TRS80_STYLE)) {
- Display(Top, " - ");
+ display(Top, " - ");
pos += 3;
}
if (pos + (int)strlen(Items[ct].Text) > (Width - 10)) {
pos = 0;
- Display(Top, "\n");
+ display(Top, "\n");
}
- Display(Top, "%s", Items[ct].Text);
+ display(Top, "%s", Items[ct].Text);
pos += strlen(Items[ct].Text);
if (Options & TRS80_STYLE) {
- Display(Top, ". ");
+ display(Top, ". ");
pos += 2;
}
}
ct++;
}
- Display(Top, "\n");
+ display(Top, "\n");
if (Options & TRS80_STYLE)
- Display(Top, TRS80_LINE);
+ display(Top, TRS80_LINE);
}
-int Scott::WhichWord(const char *word, const char **list) {
+int Scott::whichWord(const char *word, const char **list) {
int n = 1;
int ne = 1;
const char *tp;
@@ -563,7 +563,7 @@ int Scott::WhichWord(const char *word, const char **list) {
return -1;
}
-void Scott::LineInput(char *buf, size_t n) {
+void Scott::lineInput(char *buf, size_t n) {
event_t ev;
glk_request_line_event(Bottom, buf, n - 1, 0);
@@ -575,13 +575,13 @@ void Scott::LineInput(char *buf, size_t n) {
else if (ev.type == evtype_LineInput)
break;
else if (ev.type == evtype_Arrange && split_screen)
- Look();
+ look();
} while (ev.type != evtype_Quit);
buf[ev.val1] = 0;
}
-void Scott::SaveGame(void) {
+void Scott::saveGame(void) {
strid_t file;
frefid_t ref;
int ct;
@@ -610,10 +610,10 @@ void Scott::SaveGame(void) {
}
glk_stream_close(file, nullptr);
- Output("Saved.\n");
+ output("Saved.\n");
}
-void Scott::LoadGame(void) {
+void Scott::loadGame(void) {
strid_t file;
frefid_t ref;
char buf[128];
@@ -648,7 +648,7 @@ void Scott::LoadGame(void) {
}
}
-int Scott::GetInput(int *vb, int *no) {
+int Scott::getInput(int *vb, int *no) {
char buf[256];
char verb[10], noun[10];
int vc, nc;
@@ -656,8 +656,8 @@ int Scott::GetInput(int *vb, int *no) {
do {
do {
- Output("\nTell me what to do ? ");
- LineInput(buf, sizeof buf);
+ output("\nTell me what to do ? ");
+ lineInput(buf, sizeof buf);
if (g_vm->shouldQuit())
return 0;
@@ -665,7 +665,7 @@ int Scott::GetInput(int *vb, int *no) {
} while (num == 0 || *buf == '\n');
if (xstrcasecmp(verb, "restore") == 0) {
- LoadGame();
+ loadGame();
return -1;
}
if (num == 1)
@@ -682,18 +682,18 @@ int Scott::GetInput(int *vb, int *no) {
case 'i':strcpy(verb, "INVENTORY"); break;
}
}
- nc = WhichWord(verb, Nouns);
+ nc = whichWord(verb, Nouns);
/* The Scott Adams system has a hack to avoid typing 'go' */
if (nc >= 1 && nc <= 6) {
vc = 1;
} else {
- vc = WhichWord(verb, Verbs);
- nc = WhichWord(noun, Nouns);
+ vc = whichWord(verb, Verbs);
+ nc = whichWord(noun, Nouns);
}
*vb = vc;
*no = nc;
if (vc == -1) {
- Output("You use word(s) I don't know! ");
+ output("You use word(s) I don't know! ");
}
} while (vc == -1);
@@ -701,7 +701,7 @@ int Scott::GetInput(int *vb, int *no) {
return 0;
}
-int Scott::PerformLine(int ct) {
+int Scott::performLine(int ct) {
int continuation = 0;
int param[5], pptr = 0;
int act[4];
@@ -754,11 +754,11 @@ int Scott::PerformLine(int ct) {
return 0;
break;
case 10:
- if (CountCarried() == 0)
+ if (countCarried() == 0)
return 0;
break;
case 11:
- if (CountCarried())
+ if (countCarried())
return 0;
break;
case 12:
@@ -808,23 +808,23 @@ int Scott::PerformLine(int ct) {
while (cc<4)
{
if (act[cc] >= 1 && act[cc] < 52) {
- Output(Messages[act[cc]]);
- Output("\n");
+ output(Messages[act[cc]]);
+ output("\n");
} else if (act[cc] > 101) {
- Output(Messages[act[cc] - 50]);
- Output("\n");
+ output(Messages[act[cc] - 50]);
+ output("\n");
}
else {
switch (act[cc]) {
case 0:/* NOP */
break;
case 52:
- if (CountCarried() == GameHeader.MaxCarry)
+ if (countCarried() == GameHeader.MaxCarry)
{
if (Options&YOUARE)
- Output("You are carrying too much. ");
+ output("You are carrying too much. ");
else
- Output("I've too much to carry! ");
+ output("I've too much to carry! ");
break;
}
Items[param[pptr++]].Location = CARRIED;
@@ -855,9 +855,9 @@ int Scott::PerformLine(int ct) {
break;
case 61:
if (Options&YOUARE)
- Output("You are dead.\n");
+ output("You are dead.\n");
else
- Output("I am dead.\n");
+ output("I am dead.\n");
BitFlags &= ~(1 << DARKBIT);
MyLoc = GameHeader.NumRooms;/* It seems to be what the code says! */
break;
@@ -869,7 +869,7 @@ int Scott::PerformLine(int ct) {
break;
}
case 63:
- doneit: Output("The game is now over.\n");
+ doneit: output("The game is now over.\n");
glk_exit();
break;
case 64:
@@ -886,16 +886,16 @@ int Scott::PerformLine(int ct) {
i++;
}
if (Options&YOUARE)
- Output("You have stored ");
+ output("You have stored ");
else
- Output("I've stored ");
- OutputNumber(n);
- Output(" treasures. On a scale of 0 to 100, that rates ");
- OutputNumber((n * 100) / GameHeader.Treasures);
- Output(".\n");
+ output("I've stored ");
+ outputNumber(n);
+ output(" treasures. On a scale of 0 to 100, that rates ");
+ outputNumber((n * 100) / GameHeader.Treasures);
+ output(".\n");
if (n == GameHeader.Treasures)
{
- Output("Well done.\n");
+ output("Well done.\n");
goto doneit;
}
break;
@@ -905,9 +905,9 @@ int Scott::PerformLine(int ct) {
int i = 0;
int f = 0;
if (Options&YOUARE)
- Output("You are carrying:\n");
+ output("You are carrying:\n");
else
- Output("I'm carrying:\n");
+ output("I'm carrying:\n");
while (i <= GameHeader.NumItems)
{
if (Items[i].Location == CARRIED)
@@ -915,18 +915,18 @@ int Scott::PerformLine(int ct) {
if (f == 1)
{
if (Options & TRS80_STYLE)
- Output(". ");
+ output(". ");
else
- Output(" - ");
+ output(" - ");
}
f = 1;
- Output(Items[i].Text);
+ output(Items[i].Text);
}
i++;
}
if (f == 0)
- Output("Nothing");
- Output(".\n");
+ output("Nothing");
+ output(".\n");
break;
}
case 67:
@@ -941,10 +941,10 @@ int Scott::PerformLine(int ct) {
BitFlags &= ~(1 << LIGHTOUTBIT);
break;
case 70:
- ClearScreen(); /* pdd. */
+ clearScreen(); /* pdd. */
break;
case 71:
- SaveGame();
+ saveGame();
break;
case 72:
{
@@ -976,7 +976,7 @@ int Scott::PerformLine(int ct) {
CurrentCounter--;
break;
case 78:
- OutputNumber(CurrentCounter);
+ outputNumber(CurrentCounter);
break;
case 79:
CurrentCounter = param[pptr++];
@@ -1011,14 +1011,14 @@ int Scott::PerformLine(int ct) {
know if there is a maximum value to limit too */
break;
case 84:
- Output(NounText);
+ output(NounText);
break;
case 85:
- Output(NounText);
- Output("\n");
+ output(NounText);
+ output("\n");
break;
case 86:
- Output("\n");
+ output("\n");
break;
case 87:
{
@@ -1031,7 +1031,7 @@ int Scott::PerformLine(int ct) {
break;
}
case 88:
- Delay(2);
+ delay(2);
break;
case 89:
pptr++;
@@ -1052,7 +1052,7 @@ int Scott::PerformLine(int ct) {
return 1 + continuation;
}
-int Scott::PerformActions(int vb, int no) {
+int Scott::performActions(int vb, int no) {
static int disable_sysfunc = 0; /* Recursion lock */
int d = BitFlags&(1 << DARKBIT);
@@ -1060,7 +1060,7 @@ int Scott::PerformActions(int vb, int no) {
int fl;
int doagain = 0;
if (vb == 1 && no == -1) {
- Output("Give me a direction too.");
+ output("Give me a direction too.");
return 0;
}
if (vb == 1 && no >= 1 && no <= 6) {
@@ -1069,7 +1069,7 @@ int Scott::PerformActions(int vb, int no) {
Items[LIGHT_SOURCE].Location == CARRIED)
d = 0;
if (d)
- Output("Dangerous to move in the dark! ");
+ output("Dangerous to move in the dark! ");
nl = Rooms[MyLoc].Exits[no - 1];
if (nl != 0) {
MyLoc = nl;
@@ -1077,15 +1077,15 @@ int Scott::PerformActions(int vb, int no) {
}
if (d) {
if (Options&YOUARE)
- Output("You fell down and broke your neck. ");
+ output("You fell down and broke your neck. ");
else
- Output("I fell down and broke my neck. ");
+ output("I fell down and broke my neck. ");
glk_exit();
}
if (Options&YOUARE)
- Output("You can't go in that direction. ");
+ output("You can't go in that direction. ");
else
- Output("I can't go in that direction. ");
+ output("I can't go in that direction. ");
return 0;
}
@@ -1103,12 +1103,12 @@ int Scott::PerformActions(int vb, int no) {
nv = vv % 150;
vv /= 150;
if ((vv == vb) || (doagain&&Actions[ct].Vocab == 0)) {
- if ((vv == 0 && RandomPercent(nv)) || doagain ||
+ if ((vv == 0 && randomPercent(nv)) || doagain ||
(vv != 0 && (nv == no || nv == 0))) {
int f2;
if (fl == -1)
fl = -2;
- if ((f2 = PerformLine(ct)) > 0) {
+ if ((f2 = performLine(ct)) > 0) {
/* ahah finally figured it out ! */
fl = 0;
if (f2 == 2)
@@ -1143,57 +1143,57 @@ int Scott::PerformActions(int vb, int no) {
int f = 0;
if (d) {
- Output("It is dark.\n");
+ output("It is dark.\n");
return 0;
}
while (i <= GameHeader.NumItems) {
if (Items[i].Location == MyLoc && Items[i].AutoGet != nullptr && Items[i].AutoGet[0] != '*') {
- no = WhichWord(Items[i].AutoGet, Nouns);
+ no = whichWord(Items[i].AutoGet, Nouns);
disable_sysfunc = 1; /* Don't recurse into auto get ! */
- PerformActions(vb, no); /* Recursively check each items table code */
+ performActions(vb, no); /* Recursively check each items table code */
disable_sysfunc = 0;
- if (CountCarried() == GameHeader.MaxCarry) {
+ if (countCarried() == GameHeader.MaxCarry) {
if (Options&YOUARE)
- Output("You are carrying too much. ");
+ output("You are carrying too much. ");
else
- Output("I've too much to carry. ");
+ output("I've too much to carry. ");
return 0;
}
Items[i].Location = CARRIED;
- Output(Items[i].Text);
- Output(": O.K.\n");
+ output(Items[i].Text);
+ output(": O.K.\n");
f = 1;
}
i++;
}
if (f == 0)
- Output("Nothing taken.");
+ output("Nothing taken.");
return 0;
}
if (no == -1)
{
- Output("What ? ");
+ output("What ? ");
return 0;
}
- if (CountCarried() == GameHeader.MaxCarry)
+ if (countCarried() == GameHeader.MaxCarry)
{
if (Options&YOUARE)
- Output("You are carrying too much. ");
+ output("You are carrying too much. ");
else
- Output("I've too much to carry. ");
+ output("I've too much to carry. ");
return 0;
}
- item = MatchUpItem(NounText, MyLoc);
+ item = matchUpItem(NounText, MyLoc);
if (item == -1)
{
if (Options&YOUARE)
- Output("It is beyond your power to do that. ");
+ output("It is beyond your power to do that. ");
else
- Output("It's beyond my power to do that. ");
+ output("It's beyond my power to do that. ");
return 0;
}
Items[item].Location = CARRIED;
- Output("O.K. ");
+ output("O.K. ");
return 0;
}
if (vb == 18) {
@@ -1202,35 +1202,35 @@ int Scott::PerformActions(int vb, int no) {
int f = 0;
while (i <= GameHeader.NumItems) {
if (Items[i].Location == CARRIED && Items[i].AutoGet && Items[i].AutoGet[0] != '*') {
- no = WhichWord(Items[i].AutoGet, Nouns);
+ no = whichWord(Items[i].AutoGet, Nouns);
disable_sysfunc = 1;
- PerformActions(vb, no);
+ performActions(vb, no);
disable_sysfunc = 0;
Items[i].Location = MyLoc;
- Output(Items[i].Text);
- Output(": O.K.\n");
+ output(Items[i].Text);
+ output(": O.K.\n");
f = 1;
}
i++;
}
if (f == 0)
- Output("Nothing dropped.\n");
+ output("Nothing dropped.\n");
return 0;
}
if (no == -1) {
- Output("What ? ");
+ output("What ? ");
return 0;
}
- item = MatchUpItem(NounText, CARRIED);
+ item = matchUpItem(NounText, CARRIED);
if (item == -1) {
if (Options&YOUARE)
- Output("It's beyond your power to do that.\n");
+ output("It's beyond your power to do that.\n");
else
- Output("It's beyond my power to do that.\n");
+ output("It's beyond my power to do that.\n");
return 0;
}
Items[item].Location = MyLoc;
- Output("O.K. ");
+ output("O.K. ");
return 0;
}
}
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index 52ad560..35a84fa 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -39,11 +39,13 @@ namespace Scott {
#define DARKBIT 15
#define LIGHTOUTBIT 16 // Light gone out
-#define YOUARE 1 // You are not I am
-#define SCOTTLIGHT 2 // Authentic Scott Adams light messages
-#define DEBUGGING 4 // Info from database load
-#define TRS80_STYLE 8 // Display in style used on TRS-80
-#define PREHISTORIC_LAMP 16 // Destroy the lamp (very old databases)
+enum GameOption {
+ YOUARE = 1, ///< You are not I am
+ SCOTTLIGHT = 2, ///< Authentic Scott Adams light messages
+ DEBUGGING = 4, ///< Info from database load
+ TRS80_STYLE = 8, ///< Display in style used on TRS-80
+ PREHISTORIC_LAMP = 16 ///< Destroy the lamp (very old databases)
+};
#define TRS80_LINE "\n<------------------------------------------------------------>\n"
#define MyLoc (GameHeader.PlayerRoom)
@@ -52,7 +54,7 @@ struct Header {
int Unknown;
int NumItems;
int NumActions;
- int NumWords; // Smaller of verb/noun is padded to same size
+ int NumWords; ///< Smaller of verb/noun is padded to same size
int NumRooms;
int MaxCarry;
int PlayerRoom;
@@ -135,27 +137,27 @@ private:
*/
void initialize();
- void Display(winid_t w, const char *fmt, ...);
- void Delay(int seconds);
- void Fatal(const char *x);
- void ClearScreen(void);
- void *MemAlloc(int size);
- bool RandomPercent(uint n);
- int CountCarried(void);
- const char *MapSynonym(const char *word);
- int MatchUpItem(const char *text, int loc);
- char *ReadString(Common::SeekableReadStream *f);
- void LoadDatabase(Common::SeekableReadStream *f, int loud);
- void Output(const char *a);
- void OutputNumber(int a);
- void Look(void);
- int WhichWord(const char *word, const char **list);
- void LineInput(char *buf, size_t n);
- void SaveGame(void);
- void LoadGame(void);
- int GetInput(int *vb, int *no);
- int PerformLine(int ct);
- int PerformActions(int vb, int no);
+ void display(winid_t w, const char *fmt, ...);
+ void delay(int seconds);
+ void fatal(const char *x);
+ void clearScreen(void);
+ void *memAlloc(int size);
+ bool randomPercent(uint n);
+ int countCarried(void);
+ const char *mapSynonym(const char *word);
+ int matchUpItem(const char *text, int loc);
+ char *readString(Common::SeekableReadStream *f);
+ void loadDatabase(Common::SeekableReadStream *f, int loud);
+ void output(const char *a);
+ void outputNumber(int a);
+ void look(void);
+ int whichWord(const char *word, const char **list);
+ void lineInput(char *buf, size_t n);
+ void saveGame(void);
+ void loadGame(void);
+ int getInput(int *vb, int *no);
+ int performLine(int ct);
+ int performActions(int vb, int no);
int xstrcasecmp(const char *, const char *);
int xstrncasecmp(const char *, const char *, size_t);
Commit: aafaace942f6291682d4d2fb2d0af944844bb906
https://github.com/scummvm/scummvm/commit/aafaace942f6291682d4d2fb2d0af944844bb906
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Switch command line options setup to use ConfigMan
Changed paths:
engines/gargoyle/scott/scott.cpp
engines/gargoyle/scott/scott.h
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index ef25495..a19fb00 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -21,26 +21,11 @@
*/
#include "gargoyle/scott/scott.h"
+#include "common/config-manager.h"
namespace Gargoyle {
namespace Scott {
-/*
-glkunix_argumentlist_t glkunix_arguments[] =
-{
- { "-y", glkunix_arg_NoValue, "-y Generate 'You are', 'You are carrying' type messages for games that use these instead (eg Robin Of Sherwood)" },
- { "-i", glkunix_arg_NoValue, "-i Generate 'I am' type messages (default)" },
- { "-d", glkunix_arg_NoValue, "-d Debugging info on load " },
- { "-s", glkunix_arg_NoValue, "-s Generate authentic Scott Adams driver light messages rather than other driver style ones (Light goes out in n turns..)" },
- { "-t", glkunix_arg_NoValue, "-t Generate TRS80 style display (terminal width is 64 characters; a line <-----------------> is displayed after the top stuff; objects have periods after them instead of hyphens" },
- { "-p", glkunix_arg_NoValue, "-p Use for prehistoric databases which don't use bit 16" },
- { "-w", glkunix_arg_NoValue, "-w Disable upper window" },
- { "", glkunix_arg_ValueFollows, "filename file to load" },
-
- { nullptr, glkunix_arg_End, nullptr }
-};
-*/
-
Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
@@ -139,61 +124,20 @@ Distributed under the GNU software license\n\n");
}
void Scott::initialize() {
- /*
- int argc = data->argc;
- char **argv = data->argv;
-
- if (argc < 1)
- return 0;
-
- while (argv[1])
- {
- if (*argv[1] != '-')
- break;
- switch (argv[1][1])
- {
- case 'y':
+ if (ConfMan.hasKey("YOUARE")) {
+ if (ConfMan.getBool("YOUARE"))
Options |= YOUARE;
- break;
- case 'i':
- Options &= ~YOUARE;
- break;
- case 'd':
- Options |= DEBUGGING;
- break;
- case 's':
- Options |= SCOTTLIGHT;
- break;
- case 't':
- Options |= TRS80_STYLE;
- break;
- case 'p':
- Options |= PREHISTORIC_LAMP;
- break;
- case 'w':
- split_screen = 0;
- break;
- }
- argv++;
- argc--;
- }
-
- if (argc == 2)
- {
- game_file = argv[1];
-#ifdef GARGLK
- const char *s;
- if ((s = strrchr(game_file, '/')) != nullptr || (s = strrchr(game_file, '\\')) != nullptr)
- {
- garglk_set_story_name(s + 1);
- }
else
- {
- garglk_set_story_name(game_file);
- }
-#endif
+ Options &= ~YOUARE;
}
- */
+ if (gDebugLevel > 0)
+ Options |= DEBUGGING;
+ if (ConfMan.hasKey("SCOTTLIGHT") && ConfMan.getBool("SCOTTLIGHT"))
+ Options |= SCOTTLIGHT;
+ if (ConfMan.hasKey("TRS80_STYLE") && ConfMan.getBool("TRS80_STYLE"))
+ Options |= TRS80_STYLE;
+ if (ConfMan.hasKey("PREHISTORIC_LAMP") && ConfMan.getBool("PREHISTORIC_LAMP"))
+ Options |= PREHISTORIC_LAMP;
}
void Scott::display(winid_t w, const char *fmt, ...) {
@@ -336,7 +280,7 @@ char *Scott::readString(Common::SeekableReadStream *f) {
return t;
}
-void Scott::loadDatabase(Common::SeekableReadStream *f, int loud) {
+void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
int unused, ni, na, nw, nr, mc, pr, tr, wl, lt, mn, trm;
int ct;
int lo;
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index 35a84fa..f2fe769 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -147,7 +147,7 @@ private:
const char *mapSynonym(const char *word);
int matchUpItem(const char *text, int loc);
char *readString(Common::SeekableReadStream *f);
- void loadDatabase(Common::SeekableReadStream *f, int loud);
+ void loadDatabase(Common::SeekableReadStream *f, bool loud);
void output(const char *a);
void outputNumber(int a);
void look(void);
Commit: 99266b85868beaf1baa37ddc9764ae289c315881
https://github.com/scummvm/scummvm/commit/99266b85868beaf1baa37ddc9764ae289c315881
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Beginnings of file reference handling
Changed paths:
A engines/gargoyle/files.cpp
A engines/gargoyle/files.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/files.cpp b/engines/gargoyle/files.cpp
new file mode 100644
index 0000000..c3f1367
--- /dev/null
+++ b/engines/gargoyle/files.cpp
@@ -0,0 +1,97 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/files.h"
+#include "gui/saveload.h"
+#include "common/translation.h"
+
+namespace Gargoyle {
+
+frefid_t Files::prompt(glui32 usage, FileMode fmode, glui32 rock) {
+ switch (usage & fileusage_TypeMask) {
+ case fileusage_SavedGame: {
+ if (fmode == filemode_Write) {
+ // Select a savegame slot
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ Common::String desc = dialog->getResultString();
+ return createRef(slot, desc, usage, rock);
+ }
+ } else if (fmode == filemode_Read) {
+ // Load a savegame slot
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ return createRef(slot, "", usage, rock);
+ }
+ } else {
+ error("Unsupport file mode");
+ }
+ break;
+ }
+
+ case fileusage_Transcript:
+ return createRef("transcript.txt", fmode, rock);
+
+ default:
+ error("Unsupport file mode");
+ break;
+ }
+
+ return nullptr;
+}
+
+frefid_t Files::createRef(int slot, const Common::String &desc, glui32 usage, glui32 rock) {
+ _fileReferences.push_back(FileReference());
+ frefid_t fref = &_fileReferences.back();
+
+ fref->_slotNumber = slot;
+ fref->_description = desc;
+ fref->_textMode = ((usage & fileusage_TextMode) != 0);
+ fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
+ return fref;
+}
+
+frefid_t Files::createRef(const Common::String &filename, glui32 usage, glui32 rock) {
+ _fileReferences.push_back(FileReference());
+ frefid_t fref = &_fileReferences.back();
+
+ fref->_filename = filename;
+ fref->_textMode = ((usage & fileusage_TextMode) != 0);
+ fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
+ return fref;
+}
+
+void Files::deleteRef(frefid_t fref) {
+ for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
+ if (&_fileReferences[idx] == fref) {
+ _fileReferences.remove_at(idx);
+ return;
+ }
+ }
+}
+
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/files.h b/engines/gargoyle/files.h
new file mode 100644
index 0000000..cfd757b
--- /dev/null
+++ b/engines/gargoyle/files.h
@@ -0,0 +1,98 @@
+/* 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 GARGOYLE_FILES_H
+#define GARGOYLE_FILES_H
+
+#include "gargoyle/glk_types.h"
+#include "common/array.h"
+#include "common/str.h"
+
+namespace Gargoyle {
+
+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,
+};
+
+
+/**
+ * File details
+ */
+struct FileReference {
+ glui32 _rock;
+ int _slotNumber;
+ Common::String _description;
+ Common::String _filename;
+ FileUsage _fileType;
+ bool _textMode;
+ gidispatch_rock_t _dispRock;
+};
+typedef FileReference *frefid_t;
+
+class Files {
+private:
+ Common::Array<FileReference> _fileReferences;
+public:
+ /**
+ * Prompt for a file
+ */
+ frefid_t prompt(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);
+
+ /**
+ * Delete a file reference
+ */
+ void deleteRef(frefid_t fref);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 3135fcb..503cf1c 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -32,6 +32,7 @@
#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/events.h"
+#include "gargoyle/files.h"
#include "gargoyle/picture.h"
#include "gargoyle/screen.h"
#include "gargoyle/streams.h"
@@ -54,6 +55,7 @@ GargoyleEngine::~GargoyleEngine() {
delete _clipboard;
delete _conf;
delete _events;
+ delete _files;
delete _picList;
delete _screen;
delete _streams;
@@ -74,6 +76,7 @@ void GargoyleEngine::initialize() {
_clipboard = new Clipboard();
_events = new Events();
+ _files = new Files();
_picList = new PicList();
_streams = new Streams();
_windows = new Windows(_screen);
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 9677d67..3538b4c 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -36,6 +36,7 @@ namespace Gargoyle {
class Clipboard;
class Conf;
class Events;
+class Files;
class PicList;
class Screen;
class Streams;
@@ -97,6 +98,7 @@ public:
Clipboard *_clipboard;
Conf *_conf;
Events *_events;
+ Files *_files;
PicList *_picList;
Screen *_screen;
Streams *_streams;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index bda0fa7..2f9f57e 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -479,7 +479,7 @@ frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui3
}
void Glk::glk_fileref_destroy(frefid_t fref) {
- // TODO
+ _files->deleteRef(fref);
}
frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 6bfffd6..0124cb1 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -24,6 +24,7 @@
#define GARGOYLE_GLK_H
#include "gargoyle/gargoyle.h"
+#include "gargoyle/files.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/time.h"
#include "gargoyle/windows.h"
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 274443a..6ea4408 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -146,30 +146,6 @@ enum WinMethod {
winmethod_BorderMask = 0x100,
};
-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,
-};
-
enum StyleHint {
stylehint_Indentation = 0,
stylehint_ParaIndentation = 1,
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index f4422b0..306ac8b 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
conf.o \
detection.o \
events.o \
+ files.o \
fonts.o \
gargoyle.o \
glk.o \
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index de8b704..08d97cb 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/savefile.h"
+#include "gargoyle/files.h"
#include "gargoyle/glk_types.h"
namespace Gargoyle {
@@ -32,15 +33,6 @@ namespace Gargoyle {
class Window;
class Streams;
-struct FileReference {
- glui32 _rock;
- Common::String _filename;
- int _fileType;
- int _textMode;
- gidispatch_rock_t _dispRock;
-};
-typedef FileReference *frefid_t;
-
struct StreamResult {
uint32 _readCount;
uint32 _writeCount;
Commit: a24b27b14ac72f5f88d9dce57f79f5b9039fe482
https://github.com/scummvm/scummvm/commit/a24b27b14ac72f5f88d9dce57f79f5b9039fe482
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Create glk fileref methods
Changed paths:
engines/gargoyle/files.cpp
engines/gargoyle/files.h
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
diff --git a/engines/gargoyle/files.cpp b/engines/gargoyle/files.cpp
index c3f1367..e14a315 100644
--- a/engines/gargoyle/files.cpp
+++ b/engines/gargoyle/files.cpp
@@ -21,12 +21,15 @@
*/
#include "gargoyle/files.h"
+#include "gargoyle/gargoyle.h"
#include "gui/saveload.h"
+#include "common/file.h"
+#include "common/savefile.h"
#include "common/translation.h"
namespace Gargoyle {
-frefid_t Files::prompt(glui32 usage, FileMode fmode, glui32 rock) {
+frefid_t Files::createByPrompt(glui32 usage, FileMode fmode, glui32 rock) {
switch (usage & fileusage_TypeMask) {
case fileusage_SavedGame: {
if (fmode == filemode_Write) {
@@ -64,34 +67,94 @@ frefid_t Files::prompt(glui32 usage, FileMode fmode, glui32 rock) {
}
frefid_t Files::createRef(int slot, const Common::String &desc, glui32 usage, glui32 rock) {
- _fileReferences.push_back(FileReference());
- frefid_t fref = &_fileReferences.back();
-
+ frefid_t fref = new FileReference();
fref->_slotNumber = slot;
fref->_description = desc;
fref->_textMode = ((usage & fileusage_TextMode) != 0);
fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
+
+ _fileReferences.push_back(FileRefArray::value_type(fref));
return fref;
}
frefid_t Files::createRef(const Common::String &filename, glui32 usage, glui32 rock) {
- _fileReferences.push_back(FileReference());
- frefid_t fref = &_fileReferences.back();
-
+ frefid_t fref = new FileReference();
fref->_filename = filename;
fref->_textMode = ((usage & fileusage_TextMode) != 0);
fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
+
+ _fileReferences.push_back(FileRefArray::value_type(fref));
return fref;
}
+frefid_t Files::createTemp(glui32 usage, glui32 rock) {
+ return createRef(Common::String::format("%s.tmp", g_vm->getTargetName().c_str()),
+ usage, rock);
+}
+
+frefid_t Files::createFromRef(frefid_t fref, glui32 usage, glui32 rock) {
+ return createRef(fref->_filename, usage, rock);
+}
+
void Files::deleteRef(frefid_t fref) {
for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
- if (&_fileReferences[idx] == fref) {
+ if (_fileReferences[idx].get() == fref) {
_fileReferences.remove_at(idx);
return;
}
}
}
+frefid_t Files::iterate(frefid_t fref, glui32 *rock) {
+ // Find reference following the specified one
+ int index = -1;
+ for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
+ if (fref == nullptr || _fileReferences[idx].get() == fref) {
+ if (idx < (_fileReferences.size() - 1))
+ index = idx + 1;
+ break;
+ }
+ }
+
+ if (index != -1) {
+ if (rock)
+ *rock = _fileReferences[index].get()->_rock;
+ return _fileReferences[index].get();
+ }
+
+ if (rock)
+ *rock = 0;
+ return nullptr;
+}
+
+/*--------------------------------------------------------------------------*/
+
+const Common::String FileReference::getSaveName() const {
+ assert(_slotNumber != -1);
+ return Common::String::format("%s.%.3d", g_vm->getTargetName().c_str(), _slotNumber);
+}
+
+bool FileReference::exists() const {
+ Common::String filename;
+
+ if (_slotNumber == -1) {
+ if (Common::File::exists(_filename))
+ return true;
+ filename = _filename;
+ } else {
+ filename = getSaveName();
+ }
+
+ // Check for a savegame (or other file in the save folder) with that name
+ Common::InSaveFile *inSave = g_system->getSavefileManager()->openForLoading(filename);
+ bool result = inSave != nullptr;
+ delete inSave;
+ return result;
+}
+
+void FileReference::deleteFile() {
+ Common::String filename = (_slotNumber == -1) ? _filename : getSaveName();
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/files.h b/engines/gargoyle/files.h
index cfd757b..7e7ebfb 100644
--- a/engines/gargoyle/files.h
+++ b/engines/gargoyle/files.h
@@ -25,6 +25,7 @@
#include "gargoyle/glk_types.h"
#include "common/array.h"
+#include "common/ptr.h"
#include "common/str.h"
namespace Gargoyle {
@@ -65,17 +66,39 @@ struct FileReference {
FileUsage _fileType;
bool _textMode;
gidispatch_rock_t _dispRock;
+
+ /**
+ * Constructor
+ */
+ FileReference() : _rock(0), _slotNumber(-1), _fileType(fileusage_Data), _textMode(false) {}
+
+ /**
+ * 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;
class Files {
private:
- Common::Array<FileReference> _fileReferences;
+ FileRefArray _fileReferences;
public:
/**
- * Prompt for a file
+ * Prompt for a savegame to load or save, and populate a file reference from the result
*/
- frefid_t prompt(glui32 usage, FileMode fmode, glui32 rock);
+ frefid_t createByPrompt(glui32 usage, FileMode fmode, glui32 rock);
/**
* Create a new file reference
@@ -88,9 +111,25 @@ public:
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 Gargoyle
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 3538b4c..651499e 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -138,6 +138,11 @@ public:
* Returns the primary filename for the game
*/
const Common::String &GargoyleEngine::getFilename() const;
+
+ /**
+ * Return the game engine's target name
+ */
+ const Common::String &getTargetName() const { return _targetName; }
};
extern GargoyleEngine *g_vm;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 2f9f57e..7805207 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -459,23 +459,31 @@ glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *res
}
frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
- // TODO
- return nullptr;
+ return _files->createTemp(usage, rock);
}
-frefid_t Glk::glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) {
- // TODO
- return nullptr;
+frefid_t Glk::glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock) {
+ // Take out all dangerous characters
+ Common::String tempName(name);
+ for (uint idx = 0; idx < tempName.size(); ++idx) {
+ if (tempName[idx] == '/' || tempName[idx] == '\\' || tempName[idx] == ':')
+ tempName.setChar(idx, '-');
+ }
+
+ return _files->createRef(tempName, usage, rock);
}
frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock) {
- // TODO
- return nullptr;
+ return _files->createByPrompt(usage, fmode, rock);
}
frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
- // TODO
- return nullptr;
+ if (!fref) {
+ warning("fileref_create_from_fileref: invalid ref");
+ return nullptr;
+ } else {
+ return _files->createFromRef(fref, usage, rock);
+ }
}
void Glk::glk_fileref_destroy(frefid_t fref) {
@@ -483,22 +491,24 @@ void Glk::glk_fileref_destroy(frefid_t fref) {
}
frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
- // TODO
- return nullptr;
+ return _files->iterate(fref, rockptr);
}
glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
- // TODO
- return 0;
+ if (!fref) {
+ warning("fileref_get_rock: invalid ref.");
+ return 0;
+ } else {
+ return fref->_rock;
+ }
}
void Glk::glk_fileref_delete_file(frefid_t fref) {
- // TODO
+ fref->deleteFile();
}
glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
- // TODO
- return 0;
+ return fref->exists();
}
void Glk::glk_select(event_t *event) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 0124cb1..ccd2e5b 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -112,16 +112,12 @@ public:
glsi32 val);
void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
- glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint,
- glui32 *result);
+ glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result);
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, FileMode fmode,
- glui32 rock);
- frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref,
- glui32 rock);
+ frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock);
+ 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);
void glk_fileref_destroy(frefid_t fref);
frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
glui32 glk_fileref_get_rock(frefid_t fref);
Commit: 063cfb35efa155e6383a0262b20baa656732a89a
https://github.com/scummvm/scummvm/commit/063cfb35efa155e6383a0262b20baa656732a89a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added glk style methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 7805207..3148fa1 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -444,18 +444,74 @@ void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val
// TODO
}
-void Glk::glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint) {
+void Glk::glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint) {
// TODO
}
-glui32 Glk::glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2) {
- // TODO
- return 0;
+glui32 Glk::glk_style_distinguish(winid_t win, glui32 style1, glui32 style2) {
+ const WindowStyle *styles = win->getStyles();
+ if (!styles)
+ return false;
+
+ return styles[style1] == styles[style2] ? 0 : 1;
}
-glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result) {
- // TODO
- return 0;
+bool Glk::glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result) {
+ const WindowStyle *styles = win->getStyles();
+ if (!styles)
+ return false;
+
+ switch (hint) {
+ case stylehint_Indentation:
+ case stylehint_ParaIndentation:
+ *result = 0;
+ break;
+
+ case stylehint_Justification:
+ *result = stylehint_just_LeftFlush;
+ break;
+
+ case stylehint_Size:
+ *result = 1;
+ break;
+
+ case stylehint_Weight:
+ *result =
+ (styles[style].font == PROPB || styles[style].font == PROPZ ||
+ styles[style].font == MONOB || styles[style].font == MONOZ);
+ break;
+
+ case stylehint_Oblique:
+ *result =
+ (styles[style].font == PROPI || styles[style].font == PROPZ ||
+ styles[style].font == MONOI || styles[style].font == MONOZ);
+ break;
+
+ case stylehint_Proportional:
+ *result =
+ (styles[style].font == PROPR || styles[style].font == PROPI ||
+ styles[style].font == PROPB || styles[style].font == PROPZ);
+ break;
+
+ case stylehint_TextColor:
+ *result =
+ (styles[style].fg[0] << 16) | (styles[style].fg[1] << 8) | (styles[style].fg[2]);
+ break;
+
+ case stylehint_BackColor:
+ *result =
+ (styles[style].bg[0] << 16) | (styles[style].bg[1] << 8) | (styles[style].bg[2]);
+ break;
+
+ case stylehint_ReverseColor:
+ *result = styles[style].reverse;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
}
frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index ccd2e5b..bef6280 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -110,9 +110,9 @@ public:
void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
glsi32 val);
- void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint);
- glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2);
- glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result);
+ void glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint);
+ glui32 glk_style_distinguish(winid_t win, glui32 style1, glui32 style2);
+ bool glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result);
frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock);
frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock);
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index fdca1d8..5359d4e 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -126,9 +126,6 @@ public:
glui32 _echoLineInput;
glui32 *_lineTerminators;
- /* style hints and settings */
- WindowStyle _styles[style_NUMSTYLES];
-
/* for copy selection */
glui32 *_copyBuf;
int _copyPos;
@@ -219,6 +216,11 @@ public:
virtual void cancelCharEvent() override { _charRequest = _charRequestUni = false; }
virtual void flowBreak() override;
+
+ /**
+ * Returns a pointer to the styles for the window
+ */
+ virtual const WindowStyle *getStyles() const override { return _styles; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 283922c..351d9fb 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -39,7 +39,7 @@ TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows,
_inArrayRock.num = 0;
_lineTerminators = nullptr;
- Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
+ Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], _styles);
}
TextGridWindow::~TextGridWindow() {
@@ -598,9 +598,9 @@ void TextGridWindow::redraw() {
for (b = 0; b < _width; b++) {
if (ln->_attrs[a] != ln->_attrs[b]) {
link = ln->_attrs[a].hyper;
- font = ln->_attrs[a].attrFont(styles);
- fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
- bgcolor = ln->_attrs[a].attrBg(styles);
+ font = ln->_attrs[a].attrFont(_styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
+ bgcolor = ln->_attrs[a].attrBg(_styles);
w = (b - a) * g_conf->_cellW;
screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
o = x;
@@ -620,9 +620,9 @@ void TextGridWindow::redraw() {
}
}
link = ln->_attrs[a].hyper;
- font = ln->_attrs[a].attrFont(styles);
- fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
- bgcolor = ln->_attrs[a].attrBg(styles);
+ font = ln->_attrs[a].attrFont(_styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(_styles);
+ bgcolor = ln->_attrs[a].attrBg(_styles);
w = (b - a) * g_conf->_cellW;
w += _bbox.right - (x + w);
screen.fillRect(Rect::fromXYWH(x, y, w, g_conf->_leading), bgcolor);
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 1fba707..0040b19 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -74,8 +74,6 @@ public:
Attributes _origAttr;
gidispatch_rock_t _inArrayRock;
glui32 *_lineTerminators;
-
- WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
public:
/**
* Constructor
@@ -167,6 +165,11 @@ public:
virtual void requestHyperlinkEvent() override { _hyperRequest = true; }
virtual void cancelCharEvent() override { _charRequest = _charRequestUni = false; }
+
+ /**
+ * Returns a pointer to the styles for the window
+ */
+ virtual const WindowStyle *getStyles() const override { return _styles; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 6d09d82..8911881 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -618,6 +618,11 @@ void Window::setBackgroundColor(glui32 color) {
warning("setBackgroundColor: not a graphics window");
}
+const WindowStyle *Window::getStyles() const {
+ warning("getStyles: not a text window");
+ return nullptr;
+}
+
void Window::setTerminatorsLineEvent(glui32 *keycodes, glui32 count) {
if (dynamic_cast<TextBufferWindow *>(this) || dynamic_cast<TextGridWindow *>(this)) {
delete _lineTerminatorsBase;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 20ce03d..bd24892 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -222,7 +222,14 @@ struct WindowStyle {
FACES font;
byte bg[3];
byte fg[3];
- int reverse;
+ bool reverse;
+
+ /**
+ * Equality comparison
+ */
+ bool operator==(const WindowStyle &src) const {
+ return !memcmp(this, &src, sizeof(WindowStyle));
+ }
};
/**
@@ -295,6 +302,8 @@ struct Attributes {
* Window definition
*/
class Window {
+protected:
+ WindowStyle _styles[style_NUMSTYLES]; ///< style hints and settings for grid and buffer windows
public:
Windows *_windows;
glui32 _rock;
@@ -448,6 +457,11 @@ public:
virtual void fillRect(glui32 color, const Rect &box);
virtual void setBackgroundColor(glui32 color);
+
+ /**
+ * Returns a pointer to the styles for the window
+ */
+ virtual const WindowStyle *getStyles() const;
};
typedef Window *winid_t;
Commit: f91cdb19bf2f96ffcb50de7d796bc32fcda38f34
https://github.com/scummvm/scummvm/commit/f91cdb19bf2f96ffcb50de7d796bc32fcda38f34
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add glk style hint methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 3148fa1..a50c7a6 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -440,12 +440,123 @@ glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
return 0;
}
-void Glk::glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint, glsi32 val) {
- // TODO
+void Glk::glk_stylehint_set(glui32 wintype, glui32 style, glui32 hint, glsi32 val) {
+ WindowStyle *styles;
+ bool p, b, i;
+
+ if (wintype == wintype_AllTypes) {
+ glk_stylehint_set(wintype_TextGrid, style, hint, val);
+ glk_stylehint_set(wintype_TextBuffer, style, hint, val);
+ return;
+ }
+
+ if (wintype == wintype_TextGrid)
+ styles = g_conf->_gStyles;
+ else if (wintype == wintype_TextBuffer)
+ styles = g_conf->_tStyles;
+ else
+ return;
+
+ if (!g_conf->_styleHint)
+ return;
+
+ switch (hint) {
+ case stylehint_TextColor:
+ styles[style].fg[0] = (val >> 16) & 0xff;
+ styles[style].fg[1] = (val >> 8) & 0xff;
+ styles[style].fg[2] = (val) & 0xff;
+ break;
+
+ case stylehint_BackColor:
+ styles[style].bg[0] = (val >> 16) & 0xff;
+ styles[style].bg[1] = (val >> 8) & 0xff;
+ styles[style].bg[2] = (val) & 0xff;
+ break;
+
+ case stylehint_ReverseColor:
+ styles[style].reverse = (val != 0);
+ break;
+
+ case stylehint_Proportional:
+ if (wintype == wintype_TextBuffer) {
+ p = val > 0;
+ b = styles[style].isBold();
+ i = styles[style].isItalic();
+ styles[style].font = WindowStyle::makeFont(p, b, i);
+ }
+ break;
+
+ case stylehint_Weight:
+ p = styles[style].isProp();
+ b = val > 0;
+ i = styles[style].isItalic();
+ styles[style].font = WindowStyle::makeFont(p, b, i);
+ break;
+
+ case stylehint_Oblique:
+ p = styles[style].isProp();
+ b = styles[style].isBold();
+ i = val > 0;
+ styles[style].font = WindowStyle::makeFont(p, b, i);
+ break;
+ }
+
+ if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_BackColor) {
+ memcpy(g_conf->_windowColor, styles[style].bg, 3);
+ }
+
+ if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_TextColor) {
+ memcpy(g_conf->_moreColor, styles[style].fg, 3);
+ memcpy(g_conf->_caretColor, styles[style].fg, 3);
+ }
}
void Glk::glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint) {
- // TODO
+ WindowStyle *styles;
+ const WindowStyle *defaults;
+
+ if (wintype == wintype_AllTypes) {
+ glk_stylehint_clear(wintype_TextGrid, style, hint);
+ glk_stylehint_clear(wintype_TextBuffer, style, hint);
+ return;
+ }
+
+ if (wintype == wintype_TextGrid) {
+ styles = g_conf->_gStyles;
+ defaults = g_conf->_gStylesDefault;
+ } else if (wintype == wintype_TextBuffer) {
+ styles = g_conf->_tStyles;
+ defaults = g_conf->_tStylesDefault;
+ } else {
+ return;
+ }
+
+ if (!g_conf->_styleHint)
+ return;
+
+ switch (hint) {
+ case stylehint_TextColor:
+ styles[style].fg[0] = defaults[style].fg[0];
+ styles[style].fg[1] = defaults[style].fg[1];
+ styles[style].fg[2] = defaults[style].fg[2];
+ break;
+
+ case stylehint_BackColor:
+ styles[style].bg[0] = defaults[style].bg[0];
+ styles[style].bg[1] = defaults[style].bg[1];
+ styles[style].bg[2] = defaults[style].bg[2];
+ break;
+
+ case stylehint_ReverseColor:
+ styles[style].reverse = defaults[style].reverse;
+ break;
+
+ case stylehint_Proportional:
+ case stylehint_Weight:
+ case stylehint_Oblique:
+ styles[style].font = defaults[style].font;
+ break;
+ }
}
glui32 Glk::glk_style_distinguish(winid_t win, glui32 style1, glui32 style2) {
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
index 5359d4e..9f0e20c 100644
--- a/engines/gargoyle/window_text_buffer.h
+++ b/engines/gargoyle/window_text_buffer.h
@@ -126,6 +126,9 @@ public:
glui32 _echoLineInput;
glui32 *_lineTerminators;
+ /* style hints and settings */
+ WindowStyle _styles[style_NUMSTYLES];
+
/* for copy selection */
glui32 *_copyBuf;
int _copyPos;
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
index 0040b19..8470c36 100644
--- a/engines/gargoyle/window_text_grid.h
+++ b/engines/gargoyle/window_text_grid.h
@@ -74,6 +74,8 @@ public:
Attributes _origAttr;
gidispatch_rock_t _inArrayRock;
glui32 *_lineTerminators;
+
+ WindowStyle _styles[style_NUMSTYLES]; ///< style hints and settings
public:
/**
* Constructor
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index bd24892..5830c7c 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -230,6 +230,42 @@ struct WindowStyle {
bool operator==(const WindowStyle &src) const {
return !memcmp(this, &src, sizeof(WindowStyle));
}
+
+ /**
+ * Returns true if the font is proportinate
+ */
+ bool isProp() const {
+ return font == PROPR || font == PROPI || font == PROPB || font == PROPZ;
+ }
+
+ /**
+ * Returns true ifont the font is bold
+ */
+ bool isBold() const {
+ return font == PROPB || font == PROPZ || font == MONOB || font == MONOZ;
+ }
+
+ /**
+ * Returns true ifont the font is italic
+ */
+ bool isItalic() const {
+ return font == PROPI || font == PROPZ || font == MONOI || font == MONOZ;
+ }
+
+ /**
+ * Returns a font that has the following combination of proportinate, bold, and italic
+ */
+ static FACES makeFont(bool p, bool b, bool i) {
+ if (p && !b && !i) return PROPR;
+ if (p && !b && i) return PROPI;
+ if (p && b && !i) return PROPB;
+ if (p && b && i) return PROPZ;
+ if (!p && !b && !i) return MONOR;
+ if (!p && !b && i) return MONOI;
+ if (!p && b && !i) return MONOB;
+ if (!p && b && i) return MONOZ;
+ return PROPR;
+ }
};
/**
@@ -302,8 +338,6 @@ struct Attributes {
* Window definition
*/
class Window {
-protected:
- WindowStyle _styles[style_NUMSTYLES]; ///< style hints and settings for grid and buffer windows
public:
Windows *_windows;
glui32 _rock;
Commit: 60146c383d4b69920c6ba326611f9de66a513529
https://github.com/scummvm/scummvm/commit/60146c383d4b69920c6ba326611f9de66a513529
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Merge Files class into existing Streams class
Changed paths:
R engines/gargoyle/files.cpp
R engines/gargoyle/files.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/module.mk
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/files.cpp b/engines/gargoyle/files.cpp
deleted file mode 100644
index e14a315..0000000
--- a/engines/gargoyle/files.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/files.h"
-#include "gargoyle/gargoyle.h"
-#include "gui/saveload.h"
-#include "common/file.h"
-#include "common/savefile.h"
-#include "common/translation.h"
-
-namespace Gargoyle {
-
-frefid_t Files::createByPrompt(glui32 usage, FileMode fmode, glui32 rock) {
- switch (usage & fileusage_TypeMask) {
- case fileusage_SavedGame: {
- if (fmode == filemode_Write) {
- // Select a savegame slot
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
-
- int slot = dialog->runModalWithCurrentTarget();
- if (slot >= 0) {
- Common::String desc = dialog->getResultString();
- return createRef(slot, desc, usage, rock);
- }
- } else if (fmode == filemode_Read) {
- // Load a savegame slot
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
-
- int slot = dialog->runModalWithCurrentTarget();
- if (slot >= 0) {
- return createRef(slot, "", usage, rock);
- }
- } else {
- error("Unsupport file mode");
- }
- break;
- }
-
- case fileusage_Transcript:
- return createRef("transcript.txt", fmode, rock);
-
- default:
- error("Unsupport file mode");
- break;
- }
-
- return nullptr;
-}
-
-frefid_t Files::createRef(int slot, const Common::String &desc, glui32 usage, glui32 rock) {
- frefid_t fref = new FileReference();
- fref->_slotNumber = slot;
- fref->_description = desc;
- fref->_textMode = ((usage & fileusage_TextMode) != 0);
- fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
-
- _fileReferences.push_back(FileRefArray::value_type(fref));
- return fref;
-}
-
-frefid_t Files::createRef(const Common::String &filename, glui32 usage, glui32 rock) {
- frefid_t fref = new FileReference();
- fref->_filename = filename;
- fref->_textMode = ((usage & fileusage_TextMode) != 0);
- fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
-
- _fileReferences.push_back(FileRefArray::value_type(fref));
- return fref;
-}
-
-frefid_t Files::createTemp(glui32 usage, glui32 rock) {
- return createRef(Common::String::format("%s.tmp", g_vm->getTargetName().c_str()),
- usage, rock);
-}
-
-frefid_t Files::createFromRef(frefid_t fref, glui32 usage, glui32 rock) {
- return createRef(fref->_filename, usage, rock);
-}
-
-void Files::deleteRef(frefid_t fref) {
- for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
- if (_fileReferences[idx].get() == fref) {
- _fileReferences.remove_at(idx);
- return;
- }
- }
-}
-
-frefid_t Files::iterate(frefid_t fref, glui32 *rock) {
- // Find reference following the specified one
- int index = -1;
- for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
- if (fref == nullptr || _fileReferences[idx].get() == fref) {
- if (idx < (_fileReferences.size() - 1))
- index = idx + 1;
- break;
- }
- }
-
- if (index != -1) {
- if (rock)
- *rock = _fileReferences[index].get()->_rock;
- return _fileReferences[index].get();
- }
-
- if (rock)
- *rock = 0;
- return nullptr;
-}
-
-/*--------------------------------------------------------------------------*/
-
-const Common::String FileReference::getSaveName() const {
- assert(_slotNumber != -1);
- return Common::String::format("%s.%.3d", g_vm->getTargetName().c_str(), _slotNumber);
-}
-
-bool FileReference::exists() const {
- Common::String filename;
-
- if (_slotNumber == -1) {
- if (Common::File::exists(_filename))
- return true;
- filename = _filename;
- } else {
- filename = getSaveName();
- }
-
- // Check for a savegame (or other file in the save folder) with that name
- Common::InSaveFile *inSave = g_system->getSavefileManager()->openForLoading(filename);
- bool result = inSave != nullptr;
- delete inSave;
- return result;
-}
-
-void FileReference::deleteFile() {
- Common::String filename = (_slotNumber == -1) ? _filename : getSaveName();
- g_system->getSavefileManager()->removeSavefile(filename);
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/files.h b/engines/gargoyle/files.h
deleted file mode 100644
index 7e7ebfb..0000000
--- a/engines/gargoyle/files.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* 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 GARGOYLE_FILES_H
-#define GARGOYLE_FILES_H
-
-#include "gargoyle/glk_types.h"
-#include "common/array.h"
-#include "common/ptr.h"
-#include "common/str.h"
-
-namespace Gargoyle {
-
-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,
-};
-
-
-/**
- * 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) {}
-
- /**
- * 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;
-
-class Files {
-private:
- FileRefArray _fileReferences;
-public:
- /**
- * 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 Gargoyle
-
-#endif
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 503cf1c..3135fcb 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -32,7 +32,6 @@
#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/events.h"
-#include "gargoyle/files.h"
#include "gargoyle/picture.h"
#include "gargoyle/screen.h"
#include "gargoyle/streams.h"
@@ -55,7 +54,6 @@ GargoyleEngine::~GargoyleEngine() {
delete _clipboard;
delete _conf;
delete _events;
- delete _files;
delete _picList;
delete _screen;
delete _streams;
@@ -76,7 +74,6 @@ void GargoyleEngine::initialize() {
_clipboard = new Clipboard();
_events = new Events();
- _files = new Files();
_picList = new PicList();
_streams = new Streams();
_windows = new Windows(_screen);
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 651499e..88859b4 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -36,7 +36,6 @@ namespace Gargoyle {
class Clipboard;
class Conf;
class Events;
-class Files;
class PicList;
class Screen;
class Streams;
@@ -98,7 +97,6 @@ public:
Clipboard *_clipboard;
Conf *_conf;
Events *_events;
- Files *_files;
PicList *_picList;
Screen *_screen;
Streams *_streams;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index a50c7a6..f386f22 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -626,7 +626,7 @@ bool Glk::glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *resu
}
frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
- return _files->createTemp(usage, rock);
+ return _streams->createTemp(usage, rock);
}
frefid_t Glk::glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock) {
@@ -637,11 +637,11 @@ frefid_t Glk::glk_fileref_create_by_name(glui32 usage, const char *name, glui32
tempName.setChar(idx, '-');
}
- return _files->createRef(tempName, usage, rock);
+ return _streams->createRef(tempName, usage, rock);
}
frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock) {
- return _files->createByPrompt(usage, fmode, rock);
+ return _streams->createByPrompt(usage, fmode, rock);
}
frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
@@ -649,16 +649,16 @@ frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui3
warning("fileref_create_from_fileref: invalid ref");
return nullptr;
} else {
- return _files->createFromRef(fref, usage, rock);
+ return _streams->createFromRef(fref, usage, rock);
}
}
void Glk::glk_fileref_destroy(frefid_t fref) {
- _files->deleteRef(fref);
+ _streams->deleteRef(fref);
}
frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
- return _files->iterate(fref, rockptr);
+ return _streams->iterate(fref, rockptr);
}
glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 306ac8b..f4422b0 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -5,7 +5,6 @@ MODULE_OBJS := \
conf.o \
detection.o \
events.o \
- files.o \
fonts.o \
gargoyle.o \
glk.o \
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index cdc2e7d..93335b9 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -25,6 +25,10 @@
#include "gargoyle/events.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/windows.h"
+#include "gui/saveload.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/translation.h"
namespace Gargoyle {
@@ -975,4 +979,136 @@ Stream *Streams::getFirst(uint32 *rock) {
return _streamList;
}
+
+frefid_t Streams::createByPrompt(glui32 usage, FileMode fmode, glui32 rock) {
+ switch (usage & fileusage_TypeMask) {
+ case fileusage_SavedGame: {
+ if (fmode == filemode_Write) {
+ // Select a savegame slot
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ Common::String desc = dialog->getResultString();
+ return createRef(slot, desc, usage, rock);
+ }
+ }
+ else if (fmode == filemode_Read) {
+ // Load a savegame slot
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ return createRef(slot, "", usage, rock);
+ }
+ }
+ else {
+ error("Unsupport file mode");
+ }
+ break;
+ }
+
+ case fileusage_Transcript:
+ return createRef("transcript.txt", fmode, rock);
+
+ default:
+ error("Unsupport file mode");
+ break;
+ }
+
+ return nullptr;
+}
+
+frefid_t Streams::createRef(int slot, const Common::String &desc, glui32 usage, glui32 rock) {
+ frefid_t fref = new FileReference();
+ fref->_slotNumber = slot;
+ fref->_description = desc;
+ fref->_textMode = ((usage & fileusage_TextMode) != 0);
+ fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
+
+ _fileReferences.push_back(FileRefArray::value_type(fref));
+ return fref;
+}
+
+frefid_t Streams::createRef(const Common::String &filename, glui32 usage, glui32 rock) {
+ frefid_t fref = new FileReference();
+ fref->_filename = filename;
+ fref->_textMode = ((usage & fileusage_TextMode) != 0);
+ fref->_fileType = (FileUsage)(usage & fileusage_TypeMask);
+
+ _fileReferences.push_back(FileRefArray::value_type(fref));
+ return fref;
+}
+
+frefid_t Streams::createTemp(glui32 usage, glui32 rock) {
+ return createRef(Common::String::format("%s.tmp", g_vm->getTargetName().c_str()),
+ usage, rock);
+}
+
+frefid_t Streams::createFromRef(frefid_t fref, glui32 usage, glui32 rock) {
+ return createRef(fref->_filename, usage, rock);
+}
+
+void Streams::deleteRef(frefid_t fref) {
+ for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
+ if (_fileReferences[idx].get() == fref) {
+ _fileReferences.remove_at(idx);
+ return;
+ }
+ }
+}
+
+frefid_t Streams::iterate(frefid_t fref, glui32 *rock) {
+ // Find reference following the specified one
+ int index = -1;
+ for (uint idx = 0; idx < _fileReferences.size(); ++idx) {
+ if (fref == nullptr || _fileReferences[idx].get() == fref) {
+ if (idx < (_fileReferences.size() - 1))
+ index = idx + 1;
+ break;
+ }
+ }
+
+ if (index != -1) {
+ if (rock)
+ *rock = _fileReferences[index].get()->_rock;
+ return _fileReferences[index].get();
+ }
+
+ if (rock)
+ *rock = 0;
+ return nullptr;
+}
+
+/*--------------------------------------------------------------------------*/
+
+const Common::String FileReference::getSaveName() const {
+ assert(_slotNumber != -1);
+ return Common::String::format("%s.%.3d", g_vm->getTargetName().c_str(), _slotNumber);
+}
+
+bool FileReference::exists() const {
+ Common::String filename;
+
+ if (_slotNumber == -1) {
+ if (Common::File::exists(_filename))
+ return true;
+ filename = _filename;
+ }
+ else {
+ filename = getSaveName();
+ }
+
+ // Check for a savegame (or other file in the save folder) with that name
+ Common::InSaveFile *inSave = g_system->getSavefileManager()->openForLoading(filename);
+ bool result = inSave != nullptr;
+ delete inSave;
+ return result;
+}
+
+void FileReference::deleteFile() {
+ Common::String filename = (_slotNumber == -1) ? _filename : getSaveName();
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 08d97cb..264190c 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -33,12 +33,74 @@ namespace Gargoyle {
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;
+
+/**
+ * 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) {}
+
+ /**
+ * 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
*/
@@ -342,6 +404,7 @@ class Streams {
private:
Stream *_streamList;
Stream *_currentStream;
+ FileRefArray _fileReferences;
private:
/**
* Adds a created stream to the list
@@ -397,6 +460,42 @@ public:
* 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 Gargoyle
Commit: db112fc9f02e2a49b47a62d85f4920332b285728
https://github.com/scummvm/scummvm/commit/db112fc9f02e2a49b47a62d85f4920332b285728
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding file stream opening and closing
Changed paths:
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
engines/gargoyle/windows.cpp
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 3860dc2..70e7af4 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -215,6 +215,16 @@ public:
* Wait for a keyboard or mouse press
*/
void waitForPress();
+
+ /**
+ * Get the total number of frames played
+ */
+ uint32 getTotalPlayTicks() const { return _frameCounter; }
+
+ /**
+ * Set the total number of frames played
+ */
+ void Events::setTotalPlayTicks(uint frames) { _frameCounter = frames; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index f386f22..fb140a3 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -331,12 +331,11 @@ void Glk::glk_set_window(winid_t win) {
}
strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock) {
- // TODO
- return nullptr;
+ return _streams->openFileStream(fileref, fmode, rock, false);
}
strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock) {
- return _streams->addMemoryStream(buf, buflen, fmode, rock, false);
+ return _streams->openMemoryStream(buf, buflen, fmode, rock, false);
}
void Glk::glk_stream_close(strid_t str, stream_result_t *result) {
@@ -847,12 +846,11 @@ glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
}
strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock) {
- // TODO
- return nullptr;
+ return _streams->openFileStream(fileref, fmode, rock, true);
}
strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock) {
- return _streams->addMemoryStream(buf, buflen, fmode, rock, true);
+ return _streams->openMemoryStream(buf, buflen, fmode, rock, true);
}
void Glk::glk_request_char_event_uni(winid_t win) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index bef6280..7312a35 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -24,7 +24,6 @@
#define GARGOYLE_GLK_H
#include "gargoyle/gargoyle.h"
-#include "gargoyle/files.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/time.h"
#include "gargoyle/windows.h"
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 93335b9..99ced12 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -508,11 +508,47 @@ glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) {
/*--------------------------------------------------------------------------*/
-FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) :
- Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false) {
- // TODO: Set up files
- _outFile = nullptr;
- _inFile = nullptr;
+FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode) :
+ Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false),
+ _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) {
+ Common::String fname = fref->_slotNumber == -1 ? fref->_filename : fref->getSaveName();
+
+ if (fmode == filemode_Write || fmode == filemode_ReadWrite || fmode == filemode_WriteAppend) {
+ _outFile = g_system->getSavefileManager()->openForSaving(fname, fref->_slotNumber != -1);
+ if (!_outFile)
+ error("Could open file for writing - %s", fname.c_str());
+
+ if (fref->_slotNumber != -1)
+ writeSavegameHeader(_outFile, fref->_description);
+ } else if (fmode == filemode_Read) {
+ if (_file.open(fname)) {
+ _inStream = &_file;
+ } else {
+ _inFile = g_system->getSavefileManager()->openForLoading(fname);
+ _inStream = _inFile;
+ }
+
+ if (!_inStream)
+ error("Could not open for reading - %s", fname.c_str());
+
+ if (_inFile) {
+ // It's a save file, so skip over the header
+ SavegameHeader header;
+ if (!readSavegameHeader(_inStream, header))
+ error("Invalid savegame");
+
+ g_vm->_events->setTotalPlayTicks(header._totalFrames);
+ }
+ }
+}
+
+FileStream::~FileStream() {
+ _file.close();
+ delete _inFile;
+ if (_outFile) {
+ _outFile->finalize();
+ delete _outFile;
+ }
}
void FileStream::ensureOp(FileMode mode) {
@@ -798,7 +834,6 @@ glsi32 FileStream::getCharUni() {
}
}
-
glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
if (!_readable)
return 0;
@@ -926,6 +961,55 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
}
}
+bool FileStream::readSavegameHeader(Common::SeekableReadStream *stream, SavegameHeader &header) {
+ header._totalFrames = 0;
+
+ // Validate the header Id
+ if (stream->readUint32BE() != MKTAG('G', 'A', 'R', 'G'))
+ return false;
+
+ // Check the savegame version
+ header._version = stream->readByte();
+ if (header._version > SAVEGAME_VERSION)
+ error("Savegame is too recent");
+
+ // Read in name
+ char c;
+ while ((c = stream->readByte()) != '\0')
+ header._saveName += c;
+
+ // Read in save date/time
+ header._year = stream->readUint16LE();
+ header._month = stream->readUint16LE();
+ header._day = stream->readUint16LE();
+ header._hour = stream->readUint16LE();
+ header._minute = stream->readUint16LE();
+ header._totalFrames = stream->readUint32LE();
+
+ return true;
+}
+
+void FileStream::writeSavegameHeader(Common::WriteStream *stream, const Common::String &saveName) {
+ // Write out a savegame header
+ stream->writeUint32BE(MKTAG('G', 'A', 'R', 'G'));
+
+ stream->writeByte(SAVEGAME_VERSION);
+
+ // Write savegame name
+ stream->write(saveName.c_str(), saveName.size());
+ stream->writeByte('\0');
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ stream->writeUint16LE(td.tm_year + 1900);
+ stream->writeUint16LE(td.tm_mon + 1);
+ stream->writeUint16LE(td.tm_mday);
+ stream->writeUint16LE(td.tm_hour);
+ stream->writeUint16LE(td.tm_min);
+ stream->writeUint32LE(g_vm->_events->getTotalPlayTicks());
+}
+
/*--------------------------------------------------------------------------*/
Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) {
@@ -936,13 +1020,19 @@ Streams::~Streams() {
delete _streamList;
}
-WindowStream *Streams::addWindowStream(Window *window) {
+FileStream *Streams::openFileStream(frefid_t fref, glui32 fmode, glui32 rock, bool unicode) {
+ FileStream *stream = new FileStream(this, fref, fmode, rock, unicode);
+ addStream(stream);
+ return stream;
+}
+
+WindowStream *Streams::openWindowStream(Window *window) {
WindowStream *stream = new WindowStream(this, window);
addStream(stream);
return stream;
}
-MemoryStream *Streams::addMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) {
+MemoryStream *Streams::openMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) {
MemoryStream *stream = new MemoryStream(this, buf, buflen, mode, rock, unicode);
addStream(stream);
return stream;
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 264190c..517192a 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -24,12 +24,15 @@
#define GARGOYLE_STREAMS_H
#include "common/scummsys.h"
+#include "common/file.h"
#include "common/savefile.h"
-#include "gargoyle/files.h"
+#include "common/str.h"
#include "gargoyle/glk_types.h"
namespace Gargoyle {
+#define SAVEGAME_VERSION 1
+
class Window;
class Streams;
@@ -63,6 +66,19 @@ struct StreamResult {
};
typedef StreamResult stream_result_t;
+struct SavegameHeader {
+ uint8 _version;
+ Common::String _saveName;
+ int _year, _month, _day;
+ int _hour, _minute;
+ int _totalFrames;
+
+ /**
+ * Constructor
+ */
+ SavegameHeader() : _version(0), _year(0), _month(0), _day(0), _hour(0),
+ _minute(0), _totalFrames(0) {}
+};
/**
* File details
@@ -326,8 +342,10 @@ public:
*/
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:
@@ -347,9 +365,24 @@ private:
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, uint32 rock = 0, bool unicode = true);
+ FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode);
+
+ /**
+ * Destructor
+ */
+ virtual ~FileStream();
/**
* Write a character
@@ -427,14 +460,19 @@ public:
~Streams();
/**
- * Add a window stream
+ * Open a file stream
+ */
+ FileStream *openFileStream(frefid_t fref, glui32 fmode, glui32 rock, bool unicode);
+
+ /**
+ * Open a window stream
*/
- WindowStream *addWindowStream(Window *window);
+ WindowStream *openWindowStream(Window *window);
/**
- * Add a memory stream
+ * Open a memory stream
*/
- MemoryStream *addMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock = 0, bool unicode = true);
+ MemoryStream *openMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock = 0, bool unicode = true);
/**
* Delete a stream
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index 8911881..b0f1cd7 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -502,7 +502,7 @@ Window::Window(Windows *windows, glui32 rock) : _windows(windows), _rock(rock),
_dispRock.num = 0;
Streams &streams = *g_vm->_streams;
- _stream = streams.addWindowStream(this);
+ _stream = streams.openWindowStream(this);
}
Window::~Window() {
Commit: 30cd230d883091397c7e6ca73442d560824efd0d
https://github.com/scummvm/scummvm/commit/30cd230d883091397c7e6ca73442d560824efd0d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fixes for file stream reading
Changed paths:
engines/gargoyle/streams.cpp
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 99ced12..7995f4d 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -658,21 +658,21 @@ glsi32 FileStream::getCharUtf8() {
glui32 res;
glui32 val0, val1, val2, val3;
- if (_inFile->eos())
+ if (_inStream->eos())
return -1;
- val0 = _inFile->readByte();
+ val0 = _inStream->readByte();
if (val0 < 0x80) {
res = val0;
return res;
}
if ((val0 & 0xe0) == 0xc0) {
- if (_inFile->eos()) {
+ if (_inStream->eos()) {
warning("incomplete two-byte character");
return -1;
}
- val1 = _inFile->readByte();
+ val1 = _inStream->readByte();
if ((val1 & 0xc0) != 0x80) {
warning("malformed two-byte character");
return '?';
@@ -684,9 +684,9 @@ glsi32 FileStream::getCharUtf8() {
}
if ((val0 & 0xf0) == 0xe0) {
- val1 = _inFile->readByte();
- val2 = _inFile->readByte();
- if (_inFile->eos()) {
+ val1 = _inStream->readByte();
+ val2 = _inStream->readByte();
+ if (_inStream->eos()) {
warning("incomplete three-byte character");
return -1;
}
@@ -711,10 +711,10 @@ glsi32 FileStream::getCharUtf8() {
return '?';
}
- val1 = _inFile->readByte();
- val2 = _inFile->readByte();
- val3 = _inFile->readByte();
- if (_inFile->eos()) {
+ val1 = _inStream->readByte();
+ val2 = _inStream->readByte();
+ val3 = _inStream->readByte();
+ if (_inStream->eos()) {
warning("incomplete four-byte character");
return -1;
}
@@ -743,7 +743,7 @@ glsi32 FileStream::getCharUtf8() {
}
glui32 FileStream::getPosition() const {
- return _outFile->pos();
+ return _outFile ? _outFile->pos() : _inStream->pos();
}
void FileStream::setPosition(glui32 pos, glui32 seekMode) {
@@ -751,9 +751,11 @@ void FileStream::setPosition(glui32 pos, glui32 seekMode) {
if (_unicode)
pos *= 4;
- error("FileStream::setPosition - seek not yet supported");
-// fseek(str->file, pos, ((seekmode == seekmode_Current) ? 1 :
- // ((seekmode == seekmode_End) ? 2 : 0)));
+ if (_inStream) {
+ _inStream->seek(pos, SEEK_SET);
+ } else {
+ error("seek not supported for writing files");
+ }
}
glsi32 FileStream::getChar() {
@@ -763,25 +765,25 @@ glsi32 FileStream::getChar() {
ensureOp(filemode_Read);
int res;
if (!_unicode) {
- res = _inFile->readByte();
+ res = _inStream->readByte();
} else if (_textFile) {
res = getCharUtf8();
} else {
glui32 ch;
- res = _inFile->readByte();
- if (_inFile->eos())
+ res = _inStream->readByte();
+ if (_inStream->eos())
return -1;
ch = (res & 0xFF);
- res = _inFile->readByte();
- if (_inFile->eos())
+ res = _inStream->readByte();
+ if (_inStream->eos())
return -1;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
- if (_inFile->eos())
+ res = _inStream->readByte();
+ if (_inStream->eos())
return -1;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
- if (_inFile->eos())
+ res = _inStream->readByte();
+ if (_inStream->eos())
return -1;
ch = (ch << 8) | (res & 0xFF);
res = ch;
@@ -803,24 +805,24 @@ glsi32 FileStream::getCharUni() {
ensureOp(filemode_Read);
int res;
if (!_unicode) {
- res = _inFile->readByte();
+ res = _inStream->readByte();
} else if (_textFile) {
res = getCharUtf8();
} else {
glui32 ch;
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
return -1;
ch = (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
return -1;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
return -1;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
return -1;
ch = (ch << 8) | (res & 0xFF);
@@ -844,7 +846,7 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
for (lx = 0; lx<len; lx++) {
int res;
glui32 ch;
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (res & 0xFF);
@@ -869,19 +871,19 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
{
int res;
glui32 ch;
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (ch << 8) | (res & 0xFF);
@@ -906,7 +908,7 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
for (lx = 0; lx < (int)len && !gotNewline; lx++) {
int res;
glui32 ch;
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (res & 0xFF);
@@ -936,19 +938,19 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
for (lx = 0; lx < (int)len && !gotNewline; lx++) {
int res;
glui32 ch;
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (ch << 8) | (res & 0xFF);
- res = _inFile->readByte();
+ res = _inStream->readByte();
if (res == -1)
break;
ch = (ch << 8) | (res & 0xFF);
Commit: 8333aed5c2952ff7aa46870cac93acb595a67f14
https://github.com/scummvm/scummvm/commit/8333aed5c2952ff7aa46870cac93acb595a67f14
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Adding extra fields to the savegame format for validation
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 63ada3e..ffd7fa9 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -23,11 +23,12 @@
#include "gargoyle/gargoyle.h"
#include "base/plugins.h"
+#include "common/md5.h"
+#include "common/memstream.h"
#include "common/savefile.h"
#include "common/str-array.h"
-#include "common/memstream.h"
-#include "engines/advancedDetector.h"
#include "common/system.h"
+#include "engines/advancedDetector.h"
#include "graphics/colormasks.h"
#include "graphics/surface.h"
@@ -36,28 +37,33 @@
namespace Gargoyle {
struct GargoyleGameDescription {
- ADGameDescription desc;
- Common::String filename;
- InterpreterType interpType;
+ ADGameDescription _desc;
+ Common::String _filename;
+ InterpreterType _interpType;
+ Common::String _md5;
};
const Common::String &GargoyleEngine::getFilename() const {
- return _gameDescription->filename;
+ return _gameDescription->_filename;
}
uint32 GargoyleEngine::getFeatures() const {
- return _gameDescription->desc.flags;
+ return _gameDescription->_desc.flags;
}
bool GargoyleEngine::isDemo() const {
- return (bool)(_gameDescription->desc.flags & ADGF_DEMO);
+ return (bool)(_gameDescription->_desc.flags & ADGF_DEMO);
}
Common::Language GargoyleEngine::getLanguage() const {
- return _gameDescription->desc.language;
+ return _gameDescription->_desc.language;
}
InterpreterType GargoyleEngine::getInterpreterType() const {
- return _gameDescription->interpType;
+ return _gameDescription->_interpType;
+}
+
+const Common::String &GargoyleEngine::getGameMD5() const {
+ return _gameDescription->_md5;
}
} // End of namespace Gargoyle
@@ -117,9 +123,9 @@ bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
Gargoyle::GargoyleGameDescription *gd = (Gargoyle::GargoyleGameDescription *)desc;
- gd->filename = ConfMan.get("filename");
+ gd->_filename = ConfMan.get("filename");
- switch (gd->interpType) {
+ switch (gd->_interpType) {
case Gargoyle::INTERPRETER_SCOTT:
*engine = new Gargoyle::Scott::Scott(syst, gd);
break;
@@ -160,13 +166,15 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
static char gameId[100];
strcpy(gameId, ConfMan.get("gameid").c_str());
Common::String filename = ConfMan.get("filename");
-
- if (parent.getChild(filename).exists()) {
- gameDescription.desc.gameId = gameId;
- gameDescription.desc.language = language;
- gameDescription.desc.platform = platform;
- gameDescription.desc.extra = extra.c_str();
- gameDescription.filename = filename;
+ Common::File f;
+
+ if (f.open(parent.getChild(filename))) {
+ gameDescription._desc.gameId = gameId;
+ gameDescription._desc.language = language;
+ gameDescription._desc.platform = platform;
+ gameDescription._desc.extra = extra.c_str();
+ gameDescription._filename = filename;
+ gameDescription._md5 = Common::computeStreamMD5AsString(f, 5000);
ADDetectedGame dg((ADGameDescription *)&gameDescription);
detectedGames.push_back(dg);
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 88859b4..5ec804e 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -43,7 +43,21 @@ class Windows;
class WindowMask;
enum InterpreterType {
- INTERPRETER_SCOTT
+ INTERPRETER_ADVSYS = 0,
+ INTERPRETER_AGILITY = 1,
+ INTERPRETER_ALAN2 = 2,
+ INTERPRETER_ALAN3 = 3,
+ INTERPRETER_BOCFEL = 4,
+ INTERPRETER_FROTZ = 5,
+ INTERPRETER_GEAS = 6,
+ INTERPRETER_HUGO = 7,
+ INTERPRETER_JACL = 8,
+ INTERPRETER_LEVEL9 = 9,
+ INTERPRETER_MAGNETIC = 10,
+ INTERPRETER_NITFOL = 11,
+ INTERPRETER_SCARE = 12,
+ INTERPRETER_SCOTT = 13,
+ INTERPRETER_TADS = 14
};
enum GargoyleDebugChannels {
@@ -133,6 +147,11 @@ public:
InterpreterType getInterpreterType() const;
/**
+ * Returns the game's md5
+ */
+ const Common::String &getGameMD5() const;
+
+ /**
* Returns the primary filename for the game
*/
const Common::String &GargoyleEngine::getFilename() const;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index fb140a3..2f0f0b4 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -59,7 +59,7 @@ Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
}
void Glk::glk_exit(void) {
- glk_put_string("[ press any key to exit ]");
+ glk_put_string("[ press any key to exit ]");
_events->waitForPress();
quitGame();
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 7995f4d..a8c85a1 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -963,6 +963,15 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
}
}
+static Common::String readString(Common::ReadStream *src) {
+ char c;
+ Common::String result;
+ while ((c = src->readByte()) != 0)
+ result += c;
+
+ return result;
+}
+
bool FileStream::readSavegameHeader(Common::SeekableReadStream *stream, SavegameHeader &header) {
header._totalFrames = 0;
@@ -975,10 +984,17 @@ bool FileStream::readSavegameHeader(Common::SeekableReadStream *stream, Savegame
if (header._version > SAVEGAME_VERSION)
error("Savegame is too recent");
+ // Read the interpreter, language, and game Id
+ header._interpType = stream->readByte();
+ header._language = stream->readByte();
+ header._md5 = readString(stream);
+
+ if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
+ || header._md5 != g_vm->getGameMD5())
+ return false;
+
// Read in name
- char c;
- while ((c = stream->readByte()) != '\0')
- header._saveName += c;
+ header._saveName = readString(stream);
// Read in save date/time
header._year = stream->readUint16LE();
@@ -994,9 +1010,15 @@ bool FileStream::readSavegameHeader(Common::SeekableReadStream *stream, Savegame
void FileStream::writeSavegameHeader(Common::WriteStream *stream, const Common::String &saveName) {
// Write out a savegame header
stream->writeUint32BE(MKTAG('G', 'A', 'R', 'G'));
-
stream->writeByte(SAVEGAME_VERSION);
+ // Write out intrepreter type, language, and game Id
+ stream->writeByte(g_vm->getInterpreterType());
+ stream->writeByte(g_vm->getLanguage());
+ Common::String md5 = g_vm->getGameMD5();
+ stream->write(md5.c_str(), md5.size());
+ stream->writeByte('\0');
+
// Write savegame name
stream->write(saveName.c_str(), saveName.size());
stream->writeByte('\0');
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 517192a..dad6781 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -68,6 +68,9 @@ 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;
@@ -76,8 +79,8 @@ struct SavegameHeader {
/**
* Constructor
*/
- SavegameHeader() : _version(0), _year(0), _month(0), _day(0), _hour(0),
- _minute(0), _totalFrames(0) {}
+ SavegameHeader() : _version(0), _interpType(0), _language(0), _year(0), _month(0), _day(0),
+ _hour(0), _minute(0), _totalFrames(0) {}
};
/**
Commit: ce582aab000187a646dab6cc978b821da4660940
https://github.com/scummvm/scummvm/commit/ce582aab000187a646dab6cc978b821da4660940
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Further work on game detection
Changed paths:
engines/gargoyle/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index ffd7fa9..5167440 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -162,25 +162,32 @@ DetectedGames GargoyleMetaEngine::detectGames(const Common::FSList &fslist) cons
static Gargoyle::GargoyleGameDescription gameDescription;
ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
- ADDetectedGames detectedGames;
static char gameId[100];
strcpy(gameId, ConfMan.get("gameid").c_str());
Common::String filename = ConfMan.get("filename");
+
+ Common::FSList fslist;
+ DetectedGames detectedGames;
+ fslist.push_back(parent.getChild(filename));
+ ADDetectedGames results;
Common::File f;
- if (f.open(parent.getChild(filename))) {
+ Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
+ if (detectedGames.size() > 0 && f.open(parent.getChild(filename))) {
+ DetectedGame gd = detectedGames.front();
+
+ gameDescription._interpType = Gargoyle::INTERPRETER_SCOTT;
gameDescription._desc.gameId = gameId;
- gameDescription._desc.language = language;
- gameDescription._desc.platform = platform;
- gameDescription._desc.extra = extra.c_str();
+ gameDescription._desc.language = gd.language;
+ gameDescription._desc.platform = gd.platform;
gameDescription._filename = filename;
gameDescription._md5 = Common::computeStreamMD5AsString(f, 5000);
ADDetectedGame dg((ADGameDescription *)&gameDescription);
- detectedGames.push_back(dg);
+ results.push_back(dg);
}
- return detectedGames;
+ return results;
}
#if PLUGIN_ENABLED_DYNAMIC(GARGOYLE)
Commit: 8bb3f55dff3dfe82a2d85783d06c17ffa8aa3f60
https://github.com/scummvm/scummvm/commit/8bb3f55dff3dfe82a2d85783d06c17ffa8aa3f60
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Add custom game Ids for each known Scott Adams game
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/scott/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 5167440..8c0580a 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -69,7 +69,25 @@ const Common::String &GargoyleEngine::getGameMD5() const {
} // End of namespace Gargoyle
static const PlainGameDescriptor gargoyleGames[] = {
- {"scott", "Scott Adams Games"},
+ {"scottadams", "Scott Adams Games"},
+
+ // Scott Adams games
+ { "adventureland", "Adventureland" },
+ { "pirateadventure", "Pirate Adventure" },
+ { "missionimpossible", "Mission Impossible" },
+ { "voodoocastle", "Voodoo Castle" },
+ { "thecount", "The Count" },
+ { "strangeodyssey", "Strange Odyssey" },
+ { "mysteryfunhouse", "Mystery Fun House" },
+ { "pyramidofdoom", "Pyramid Of Doom" },
+ { "ghosttown", "Ghost Town" },
+ { "savageisland1", "Savage Island, Part 1" },
+ { "savageisland2", "Savage Island, Part 2" },
+ { "goldenvoyage", "The Golden Voyage" },
+ { "adventure13", "Adventure 13" },
+ { "adventure14", "Adventure 14" },
+ { "buckaroobonzai", "Buckaroo Banzai" },
+
{0, 0}
};
@@ -90,7 +108,7 @@ public:
}
virtual const char *getOriginalCopyright() const {
- return "Gargoyle Engine (c)";
+ return "Gargoyle Engine (c) 2018";
}
virtual bool hasFeature(MetaEngineFeature f) const override;
diff --git a/engines/gargoyle/scott/detection.cpp b/engines/gargoyle/scott/detection.cpp
index 6c9f5c4..04d4f83 100644
--- a/engines/gargoyle/scott/detection.cpp
+++ b/engines/gargoyle/scott/detection.cpp
@@ -29,27 +29,28 @@ namespace Scott {
struct ScottGame {
const char *_md5;
+ const char *_gameId;
int32 _filesize;
const char *_desc;
};
const ScottGame SCOTT_GAMES[] = {
- { "ae541fc1085da2f7d561b72ed20a6bc1", 18003, "Adventureland" },
- { "cbd47ab4fcfe00231ffd71d52378d410", 18482, "Pirate Adventure" },
- { "9251ab2c64e63559d8a6e9e6246760a5", 17227, "Mission Impossible" },
- { "be849c5747c7fc3b201984afb4403b8e", 18140, "Voodoo Castle" },
- { "85b75b6079b5ee572b5259b29a0e5d21", 19999, "The Count" },
- { "c423cae841ac1927b5b2e503607b21bc", 20115, "Strange Odyssey" },
- { "326b98b991d401605074e64d474ce566", 19700, "Mystery Fun House" },
- { "8ef9010399f055da9adb15ce7745a11c", 20320, "Pyramid Of Doom" },
- { "fcdcca8b2acf76ba2d0006cefa3630a1", 20687, "Ghost Town" },
- { "c8aaa80f07c40fa8e4b17432644919dc", 22669, "Save Island, Part 1" },
- { "2add0f28d9b236c866890cdf8d86ee60", 21169, "Savage Island, Part 2" },
- { "675126bd0477e8ed9230ad3db5afc45f", 21401, "The Golden Voyage" },
- { "0ef0def798d895ed766041fa99dd28a0", 22346, "Adventure 13" },
- { "0bf1bcc649422798332a38c88588fdff", 22087, "Adventure 14" },
- { "a0a5423967287dae9cbeb9abe8324479", 21038, "Buckaroo Banzai" },
- { nullptr, 0, nullptr }
+ { "ae541fc1085da2f7d561b72ed20a6bc1", "adventureland", 18003, "Adventureland" },
+ { "cbd47ab4fcfe00231ffd71d52378d410", "pirateadventure", 18482, "Pirate Adventure" },
+ { "9251ab2c64e63559d8a6e9e6246760a5", "missionimpossible", 17227, "Mission Impossible" },
+ { "be849c5747c7fc3b201984afb4403b8e", "voodoocastle", 18140, "Voodoo Castle" },
+ { "85b75b6079b5ee572b5259b29a0e5d21", "thecount", 19999, "The Count" },
+ { "c423cae841ac1927b5b2e503607b21bc", "strangeodyssey", 20115, "Strange Odyssey" },
+ { "326b98b991d401605074e64d474ce566", "mysteryfunhouse", 19700, "Mystery Fun House" },
+ { "8ef9010399f055da9adb15ce7745a11c", "pyramidofdoom", 20320, "Pyramid Of Doom" },
+ { "fcdcca8b2acf76ba2d0006cefa3630a1", "ghosttown", 20687, "Ghost Town" },
+ { "c8aaa80f07c40fa8e4b17432644919dc", "savageisland1", 22669, "Savage Island, Part 1" },
+ { "2add0f28d9b236c866890cdf8d86ee60", "savageisland2", 21169, "Savage Island, Part 2" },
+ { "675126bd0477e8ed9230ad3db5afc45f", "goldenvoyage", 21401, "The Golden Voyage" },
+ { "0ef0def798d895ed766041fa99dd28a0", "adventure13", 22346, "Adventure 13" },
+ { "0bf1bcc649422798332a38c88588fdff", "adventure14", 22087, "Adventure 14" },
+ { "a0a5423967287dae9cbeb9abe8324479", "buckaroobonzai", 21038, "Buckaroo Banzai" },
+ { nullptr, nullptr, 0, nullptr }
};
void ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
@@ -71,7 +72,7 @@ void ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
if (p->_filesize) {
// Found a match
- DetectedGame gd("scott", p->_desc, Common::EN_ANY, Common::kPlatformUnknown, "Scott");
+ DetectedGame gd(p->_gameId, p->_desc, Common::EN_ANY, Common::kPlatformUnknown);
gd.addExtraEntry("filename", file->getName());
gameList.push_back(gd);
Commit: d2554a73fb586166c774b7197f8e05d4c85387a2
https://github.com/scummvm/scummvm/commit/d2554a73fb586166c774b7197f8e05d4c85387a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix refreshing grid windows when text is changed
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
engines/gargoyle/windows.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 8c0580a..04218b1 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -128,8 +128,7 @@ bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
(f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportThumbnail);
+ (f == kSavesSupportMetaInfo);
}
bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index d5eccfe..40888b1 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -32,17 +32,19 @@ Events::Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false),
_priorFrameTime(0), _frameCounter(0) {
}
-bool Events::checkForNextFrameCounter() {
+void Events::checkForNextFrameCounter() {
// Check for next game frame
uint32 milli = g_system->getMillis();
if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
++_frameCounter;
_priorFrameTime = milli;
- return true;
+ if (_redraw)
+ g_vm->_windows->redraw();
+ _redraw = false;
+ g_vm->_screen->update();
+ return;
}
-
- return false;
}
void Events::getEvent(event_t *event, bool polled) {
@@ -106,11 +108,7 @@ void Events::dispatchEvent(Event &ev, bool polled) {
void Events::pollEvents() {
Common::Event event;
-
- if (checkForNextFrameCounter()) {
- // Update the screen
- g_vm->_screen->update();
- }
+ checkForNextFrameCounter();
do {
g_system->getEventManager()->pollEvent(event);
@@ -232,11 +230,7 @@ void Events::waitForPress() {
do {
g_system->getEventManager()->pollEvent(e);
g_system->delayMillis(10);
-
- if (checkForNextFrameCounter()) {
- // Update the screen
- g_vm->_screen->update();
- }
+ checkForNextFrameCounter();
} while (!g_vm->shouldQuit() && e.type != Common::EVENT_KEYDOWN &&
e.type != Common::EVENT_LBUTTONDOWN && e.type != Common::EVENT_RBUTTONDOWN &&
e.type != Common::EVENT_MBUTTONDOWN);
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 70e7af4..1347200 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -153,11 +153,12 @@ private:
bool _timeouts; ///< Timer timeouts flag
uint32 _priorFrameTime; ///< Time of prior game frame
uint32 _frameCounter; ///< Frame counter
+ bool _redraw; ///< Screen needed redrawing
private:
/**
* Checks for whether it's time for the next game frame
*/
- bool checkForNextFrameCounter();
+ void checkForNextFrameCounter();
/**
* Dispatches an event
@@ -225,6 +226,11 @@ public:
* Set the total number of frames played
*/
void Events::setTotalPlayTicks(uint frames) { _frameCounter = frames; }
+
+ /**
+ * Flags the screen for redrawing
+ */
+ void redraw() { _redraw = true; }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 2f0f0b4..53c9093 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -279,16 +279,21 @@ winid_t Glk::glk_window_get_sibling(winid_t win) {
void Glk::glk_window_clear(winid_t win) {
if (!win) {
warning("window_clear: invalid ref");
- } else if (win->_lineRequest || win->_lineRequestUni) {
- if (g_conf->_safeClicks && _events->_forceClick) {
- glk_cancel_line_event(win, nullptr);
- _events->_forceClick = false;
-
- win->clear();
- } else {
- warning("window_clear: window has pending line request");
- return;
+ } else {
+ if (win->_lineRequest || win->_lineRequestUni) {
+ if (g_conf->_safeClicks && _events->_forceClick) {
+ glk_cancel_line_event(win, nullptr);
+ _events->_forceClick = false;
+
+ win->clear();
+ } else {
+ warning("window_clear: window has pending line request");
+ return;
+ }
}
+
+ // Clear the window
+ win->clear();
}
}
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index b0f1cd7..5bf2b3e 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -420,7 +420,7 @@ void Windows::redrawRect(const Rect &r) {
}
void Windows::repaint(const Rect &box) {
- // No implementation
+ g_vm->_events->redraw();
}
byte *Windows::rgbShift(byte *rgb) {
Commit: 0ea7f92b67a8ba18c2b0420390db50d0352995b2
https://github.com/scummvm/scummvm/commit/0ea7f92b67a8ba18c2b0420390db50d0352995b2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Added saveGameState and loadGameState
Changed paths:
engines/gargoyle/gargoyle.h
engines/gargoyle/scott/scott.cpp
engines/gargoyle/scott/scott.h
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 5ec804e..373bf4c 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -127,6 +127,16 @@ public:
virtual ~GargoyleEngine();
/**
+ * Returns true if a savegame can be loaded
+ */
+ virtual bool canLoadGameStateCurrently() override { return true; }
+
+ /**
+ * Returns true if the game can be saved
+ */
+ virtual bool canSaveGameStateCurrently() override { return true; }
+
+ /**
* Returns the bitset of game features
*/
uint32 getFeatures() const;
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index a19fb00..6f1b9ef 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -526,19 +526,29 @@ void Scott::lineInput(char *buf, size_t n) {
}
void Scott::saveGame(void) {
- strid_t file;
- frefid_t ref;
- int ct;
- Common::String msg;
-
- ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame, filemode_Write, 0);
- if (ref == nullptr) return;
+ frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
+ filemode_Write, 0);
+ if (ref == nullptr)
+ return;
- file = glk_stream_open_file(ref, filemode_Write, 0);
+ int slot = ref->_slotNumber;
+ Common::String desc = ref->_description;
glk_fileref_destroy(ref);
- if (file == nullptr) return;
- for (ct = 0; ct < 16; ct++) {
+ saveGameState(slot, desc);
+}
+
+Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
+ Common::String msg;
+ FileReference ref;
+ ref._slotNumber = slot;
+ ref._description = desc;
+
+ strid_t file = glk_stream_open_file(&ref, filemode_Write, 0);
+ if (file == nullptr)
+ return Common::kWritingFailed;
+
+ for (int ct = 0; ct < 16; ct++) {
msg = Common::String::format("%d %d\n", Counters[ct], RoomSaved[ct]);
glk_put_string_stream(file, msg.c_str());
}
@@ -548,29 +558,42 @@ void Scott::saveGame(void) {
MyLoc, CurrentCounter, SavedRoom, GameHeader.LightTime);
glk_put_string_stream(file, msg.c_str());
- for (ct = 0; ct <= GameHeader.NumItems; ct++) {
+ for (int ct = 0; ct <= GameHeader.NumItems; ct++) {
msg = Common::String::format("%hd\n", (short)Items[ct].Location);
glk_put_string_stream(file, msg.c_str());
}
glk_stream_close(file, nullptr);
output("Saved.\n");
+
+ return Common::kNoError;
}
void Scott::loadGame(void) {
+ frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
+ filemode_Read, 0);
+ if (ref == nullptr)
+ return;
+
+ int slotNumber = ref->_slotNumber;
+ glk_fileref_destroy(ref);
+
+ loadGameState(slotNumber);
+}
+
+Common::Error Scott::loadGameState(int slot) {
strid_t file;
- frefid_t ref;
char buf[128];
int ct = 0;
short lo;
- short DarkFlag;
+ short darkFlag;
- ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame, filemode_Read, 0);
- if (ref == nullptr) return;
+ FileReference ref;
+ ref._slotNumber = slot;
- file = glk_stream_open_file(ref, filemode_Read, 0);
- glk_fileref_destroy(ref);
- if (file == nullptr) return;
+ file = glk_stream_open_file(&ref, filemode_Read, 0);
+ if (file == nullptr)
+ return Common::kReadingFailed;
for (ct = 0; ct<16; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
@@ -579,17 +602,19 @@ void Scott::loadGame(void) {
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%ld %hd %d %d %d %d\n",
- &BitFlags, &DarkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
+ &BitFlags, &darkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
&GameHeader.LightTime);
- /* Backward compatibility */
- if (DarkFlag)
+ // Backward compatibility
+ if (darkFlag)
BitFlags |= (1 << 15);
for (ct = 0; ct <= GameHeader.NumItems; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%hd\n", &lo);
Items[ct].Location = (unsigned char)lo;
}
+
+ return Common::kNoError;
}
int Scott::getInput(int *vb, int *no) {
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index f2fe769..81847cc 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -172,6 +172,16 @@ public:
* Execute the game
*/
virtual void runGame(Common::SeekableReadStream *gameFile) override;
+
+ /**
+ * Load a savegame
+ */
+ virtual Common::Error loadGameState(int slot) override;
+
+ /**
+ * Save the game
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
};
} // End of namespace Scott
Commit: 2e1192367779901e130bd3181ae3061b81116dee
https://github.com/scummvm/scummvm/commit/2e1192367779901e130bd3181ae3061b81116dee
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Added startup savegame loading
Changed paths:
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 6f1b9ef..f92754f 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -68,6 +68,13 @@ Release 1.14, (c) 1993,1994,1995 Swansea University Computer Society.\n\
Distributed under the GNU software license\n\n");
loadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
+ // Check for savegame
+ if (ConfMan.hasKey("save_slot")) {
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0)
+ loadGameState(saveSlot);
+ }
+
while (!shouldQuit()) {
glk_tick();
Commit: 77a4e99c31c6058217b8a55ba5d5d048dc1dea52
https://github.com/scummvm/scummvm/commit/77a4e99c31c6058217b8a55ba5d5d048dc1dea52
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add savegame listing
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/scott/detection.h
engines/gargoyle/streams.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 04218b1..7ccb2f6 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -154,7 +154,33 @@ bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD
}
SaveStateList GargoyleMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String saveDesc;
+ Common::String pattern = Common::String::format("%s.0##", target);
+ Gargoyle::SavegameHeader header;
+
+ filenames = saveFileMan->listSavefiles(pattern);
+
SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ const char *ext = strrchr(file->c_str(), '.');
+ int slot = ext ? atoi(ext + 1) : -1;
+
+ if (slot >= 0 && slot <= MAX_SAVES) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+ if (in) {
+ if (Gargoyle::FileStream::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+
+ delete in;
+ }
+ }
+ }
+
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 373bf4c..0b8bca7 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -72,15 +72,6 @@ enum GargoyleDebugChannels {
struct GargoyleGameDescription;
-struct GargoyleSavegameHeader {
- uint8 _version;
- Common::String _saveName;
- Graphics::Surface *_thumbnail;
- int _year, _month, _day;
- int _hour, _minute;
- int _totalFrames;
-};
-
/**
* Base class for the different interpreters
*/
diff --git a/engines/gargoyle/scott/detection.h b/engines/gargoyle/scott/detection.h
index 07f1476..e2aa93e 100644
--- a/engines/gargoyle/scott/detection.h
+++ b/engines/gargoyle/scott/detection.h
@@ -31,6 +31,9 @@ namespace Scott {
class ScottMetaEngine {
public:
+ /**
+ * Detect Scott Adams games
+ */
static void detectGames(const Common::FSList &fslist, DetectedGames &gameList);
};
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index a8c85a1..0dc82ed 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -536,6 +536,9 @@ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 roc
SavegameHeader header;
if (!readSavegameHeader(_inStream, header))
error("Invalid savegame");
+ if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
+ || header._md5 != g_vm->getGameMD5())
+ error("Savegame is for a different game");
g_vm->_events->setTotalPlayTicks(header._totalFrames);
}
@@ -989,10 +992,6 @@ bool FileStream::readSavegameHeader(Common::SeekableReadStream *stream, Savegame
header._language = stream->readByte();
header._md5 = readString(stream);
- if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
- || header._md5 != g_vm->getGameMD5())
- return false;
-
// Read in name
header._saveName = readString(stream);
Commit: 9bd7bc87b6bc33321298ddeba6fa490c8a34d527
https://github.com/scummvm/scummvm/commit/9bd7bc87b6bc33321298ddeba6fa490c8a34d527
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added savegame meta info retrieval
Changed paths:
engines/gargoyle/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 7ccb2f6..295e50b 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -125,10 +125,13 @@ public:
bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
return
- (f == kSupportsListSaves) ||
+ (f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
(f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo);
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
+ (f == kSimpleSavesNames);
}
bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
@@ -192,6 +195,23 @@ void GargoyleMetaEngine::removeSaveState(const char *target, int slot) const {
}
SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename);
+
+ if (in) {
+ Gargoyle::SavegameHeader header;
+ if (Gargoyle::FileStream::readSavegameHeader(in, header)) {
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header._saveName);
+ desc.setSaveDate(header._year, header._month, header._day);
+ desc.setSaveTime(header._hour, header._minute);
+ desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
+
+ delete in;
+ return desc;
+ }
+ }
+
return SaveStateDescriptor();
}
Commit: db61f4e0500c96503fbb69a78d7e7aafb2d71300
https://github.com/scummvm/scummvm/commit/db61f4e0500c96503fbb69a78d7e7aafb2d71300
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add miscellaneous stream methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 53c9093..43b6d0a 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -184,35 +184,35 @@ winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 w
}
void Glk::glk_window_close(winid_t win, stream_result_t *result) {
- if (!win) {
- warning("glk_window_close: invalid ref");
- } else {
+ if (win) {
_windows->windowClose(win, result);
+ } else {
+ warning("glk_window_close: invalid ref");
}
}
void Glk::glk_window_get_size(winid_t win, glui32 *width, glui32 *height) {
- if (!win) {
- warning("window_get_size: invalid ref");
- } else {
+ if (win) {
win->getSize(width, height);
+ } else {
+ warning("window_get_size: invalid ref");
}
}
void Glk::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keywin) {
- if (!win) {
- warning("window_set_arrangement: invalid ref");
- } else {
+ if (win) {
win->setArrangement(method, size, keywin);
+ } else {
+ warning("window_set_arrangement: invalid ref");
}
}
void Glk::glk_window_get_arrangement(winid_t win, glui32 *method,
glui32 *size, winid_t *keyWin) {
- if (!win) {
- warning("window_get_arrangement: invalid ref");
- } else {
+ if (win) {
win->getArrangement(method, size, keyWin);
+ } else {
+ warning("window_get_arrangement: invalid ref");
}
}
@@ -232,21 +232,21 @@ winid_t Glk::glk_window_iterate(winid_t win, glui32 *rock) {
}
glui32 Glk::glk_window_get_rock(winid_t win) {
- if (!win) {
+ if (win) {
+ return win->_rock;
+ } else {
warning("window_get_rock: invalid ref.");
return 0;
}
-
- return win->_rock;
}
glui32 Glk::glk_window_get_type(winid_t win) {
- if (!win) {
+ if (win) {
+ return win->_type;
+ } else {
warning("window_get_parent: invalid ref");
return 0;
}
-
- return win->_type;
}
winid_t Glk::glk_window_get_parent(winid_t win) {
@@ -298,27 +298,27 @@ void Glk::glk_window_clear(winid_t win) {
}
void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
- if (!win) {
- warning("window_move_cursor: invalid ref");
- } else {
+ if (win) {
win->moveCursor(Point(xpos, ypos));
+ } else {
+ warning("window_move_cursor: invalid ref");
}
}
strid_t Glk::glk_window_get_stream(winid_t win) {
- if (!win) {
+ if (win) {
+ return win->_stream;
+ } else {
warning("window_get_stream: invalid ref");
return nullptr;
}
-
- return win->_stream;
}
void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
- if (!win) {
- warning("window_set_echo_stream: invalid window id");
- } else {
+ if (win) {
win->_echoStream = str;
+ } else {
+ warning("window_set_echo_stream: invalid window id");
}
}
@@ -361,19 +361,19 @@ glui32 Glk::glk_stream_get_rock(strid_t str) const {
}
void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekMode) {
- if (!str) {
- warning("stream_set_position: invalid ref");
- } else {
+ if (str) {
str->setPosition(pos, seekMode);
+ } else {
+ warning("stream_set_position: invalid ref");
}
}
glui32 Glk::glk_stream_get_position(strid_t str) const {
- if (!str) {
+ if (str) {
+ return str->getPosition();
+ } else {
warning("stream_get_position: invalid ref");
return 0;
- } else {
- return str->getPosition();
}
}
@@ -427,21 +427,29 @@ void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
glsi32 Glk::glk_get_char_stream(strid_t str) {
if (str) {
+ return str->getChar();
+ } else {
warning("get_char_stream: invalid ref");
return -1;
- } else {
- return str->getChar();
}
}
glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
- // TODO
- return 0;
+ if (str) {
+ return str->getLine(buf, len);
+ } else {
+ warning("get_line_stream: invalid ref");
+ return 0;
+ }
}
glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
- // TODO
- return 0;
+ if (str) {
+ return str->getBuffer(buf, len);
+ } else {
+ warning("get_line_stream: invalid ref");
+ return 0;
+ }
}
void Glk::glk_stylehint_set(glui32 wintype, glui32 style, glui32 hint, glsi32 val) {
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 0dc82ed..24917c5 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -400,6 +400,63 @@ glsi32 MemoryStream::getCharUni() {
}
}
+glui32 MemoryStream::getBuffer(char *buf, glui32 len) {
+ if (!_readable)
+ return 0;
+
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if (!_unicode) {
+ unsigned char *bp = (unsigned char *)_bufPtr;
+ if (bp + len > (unsigned char *)_bufEnd) {
+ glui32 lx;
+ lx = (bp + len) - (unsigned char *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+
+ if (len) {
+ memcpy(buf, bp, len);
+ bp += len;
+ if (bp >(unsigned char *)_bufEof)
+ _bufEof = bp;
+ }
+
+ _readCount += len;
+ _bufPtr = bp;
+ } else {
+ glui32 *bp = (glui32 *)_bufPtr;
+ if (bp + len > (glui32 *)_bufEnd) {
+ glui32 lx;
+ lx = (bp + len) - (glui32 *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ if (len) {
+ glui32 i;
+ for (i = 0; i < len; i++) {
+ glui32 ch = *bp++;
+ if (ch > 0xff)
+ ch = '?';
+ *buf++ = (char)ch;
+ }
+ if (bp > (glui32 *)_bufEof)
+ _bufEof = bp;
+ }
+
+ _readCount += len;
+ _bufPtr = bp;
+ }
+ }
+
+ return len;
+}
+
glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
if (!_readable)
return 0;
@@ -452,6 +509,66 @@ glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
return len;
}
+glui32 MemoryStream::getLine(char *buf, glui32 len) {
+ glui32 lx;
+ bool gotNewline;
+
+ if (len == 0)
+ return 0;
+
+ len -= 1; /* for the terminal null */
+ if (!_unicode) {
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if ((char *)_bufPtr + len > (char *)_bufEnd) {
+ lx = ((char *)_bufPtr + len) - (char *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ }
+
+ gotNewline = false;
+ for (lx = 0; lx < len && !gotNewline; lx++) {
+ buf[lx] = ((char *)_bufPtr)[lx];
+ gotNewline = (buf[lx] == '\n');
+ }
+
+ buf[lx] = '\0';
+ _bufPtr = ((char *)_bufPtr) + lx;
+ } else {
+ if (_bufPtr >= _bufEnd) {
+ len = 0;
+ } else {
+ if ((char *)_bufPtr + len > (char *)_bufEnd) {
+ lx = ((char *)_bufPtr + len) - (char *)_bufEnd;
+ if (lx < len)
+ len -= lx;
+ else
+ len = 0;
+ }
+ }
+
+ gotNewline = false;
+ for (lx = 0; lx < len && !gotNewline; lx++) {
+ glui32 ch;
+ ch = ((glui32 *)_bufPtr)[lx];
+ if (ch >= 0x100)
+ ch = '?';
+ buf[lx] = (char)ch;
+ gotNewline = (ch == '\n');
+ }
+
+ buf[lx] = '\0';
+ _bufPtr = ((glui32 *)_bufPtr) + lx;
+ }
+
+ _readCount += lx;
+ return lx;
+}
+
glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) {
bool gotNewline;
int lx;
@@ -509,8 +626,8 @@ glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) {
/*--------------------------------------------------------------------------*/
FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode) :
- Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false),
- _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) {
+ Stream(streams, fmode == filemode_Read, fmode != filemode_Read, rock, unicode), _lastOp(0),
+ _textFile(fref->_textMode), _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) {
Common::String fname = fref->_slotNumber == -1 ? fref->_filename : fref->getSaveName();
if (fmode == filemode_Write || fmode == filemode_ReadWrite || fmode == filemode_WriteAppend) {
@@ -839,6 +956,56 @@ glsi32 FileStream::getCharUni() {
}
}
+glui32 FileStream::getBuffer(char *buf, glui32 len) {
+ ensureOp(filemode_Read);
+ if (!_unicode) {
+ glui32 res;
+ res = _inStream->read(buf, len);
+ _readCount += res;
+ return res;
+ } else if (_textFile) {
+ glui32 lx;
+ for (lx = 0; lx<len; lx++) {
+ glui32 ch;
+ ch = getCharUtf8();
+ if (ch == -1)
+ break;
+ _readCount++;
+ if (ch >= 0x100)
+ ch = '?';
+ buf[lx] = (char)ch;
+ }
+ return lx;
+ } else {
+ glui32 lx;
+ for (lx = 0; lx < len; lx++) {
+ int res;
+ glui32 ch;
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (res & 0xFF);
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ _readCount++;
+ if (ch >= 0x100)
+ ch = '?';
+ buf[lx] = (char)ch;
+ }
+ return lx;
+ }
+}
+
glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
if (!_readable)
return 0;
@@ -897,6 +1064,76 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
}
}
+glui32 FileStream::getLine(char *buf, glui32 len) {
+ glui32 lx;
+ bool gotNewline;
+
+ if (len == 0)
+ return 0;
+
+ ensureOp(filemode_Read);
+ if (!_unicode) {
+ char *res = buf;
+ for (; len > 0; ++res, --len) {
+ *res = _inStream->readByte();
+ if (*res == '\n')
+ break;
+ }
+ *res = '\0';
+
+ lx = strlen(buf);
+ _readCount += lx;
+ return lx;
+ } else if (_textFile) {
+ len -= 1; // for the terminal null
+ gotNewline = false;
+ for (lx = 0; lx < len && !gotNewline; lx++) {
+ glui32 ch;
+ ch = getCharUtf8();
+ if (ch == -1)
+ break;
+ _readCount++;
+ if (ch >= 0x100)
+ ch = '?';
+ buf[lx] = (char)ch;
+ gotNewline = (ch == '\n');
+ }
+ buf[lx] = '\0';
+ return lx;
+ } else {
+ len -= 1; // for the terminal null
+ gotNewline = false;
+ for (lx = 0; lx < len && !gotNewline; lx++) {
+ int res;
+ glui32 ch;
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (res & 0xFF);
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ res = _inStream->readByte();
+ if (res == -1)
+ break;
+ ch = (ch << 8) | (res & 0xFF);
+ _readCount++;
+ if (ch >= 0x100)
+ ch = '?';
+ buf[lx] = (char)ch;
+ gotNewline = (ch == '\n');
+ }
+
+ buf[lx] = '\0';
+ return lx;
+ }
+}
+
glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
bool gotNewline;
int lx;
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index dad6781..16f63db 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -101,6 +101,13 @@ struct FileReference {
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;
@@ -217,11 +224,21 @@ public:
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; }
@@ -330,11 +347,21 @@ public:
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;
@@ -422,11 +449,21 @@ public:
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;
Commit: 75f1ac769ba8158ff73f724a91e9544b29943905
https://github.com/scummvm/scummvm/commit/75f1ac769ba8158ff73f724a91e9544b29943905
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Fix loading and saving games
Changed paths:
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index f92754f..b0c3444 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -37,6 +37,7 @@ Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst,
void Scott::runGame(Common::SeekableReadStream *gameFile) {
int vb, no;
+ int saveSlot;
initialize();
Bottom = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
@@ -62,24 +63,26 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
Top = Bottom;
}
+ // Check for savegame
+ saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
+
output("\
Scott Free, A Scott Adams game driver in C.\n\
Release 1.14, (c) 1993,1994,1995 Swansea University Computer Society.\n\
Distributed under the GNU software license\n\n");
loadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
- // Check for savegame
- if (ConfMan.hasKey("save_slot")) {
- int saveSlot = ConfMan.getInt("save_slot");
- if (saveSlot >= 0)
- loadGameState(saveSlot);
- }
-
while (!shouldQuit()) {
glk_tick();
performActions(0, 0);
+ if (saveSlot >= 0) {
+ // Load any savegame during startup
+ loadGameState(saveSlot);
+ saveSlot = -1;
+ }
+
look();
if (getInput(&vb, &no) == -1)
@@ -547,9 +550,7 @@ void Scott::saveGame(void) {
Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
Common::String msg;
- FileReference ref;
- ref._slotNumber = slot;
- ref._description = desc;
+ FileReference ref(slot, desc, fileusage_TextMode | fileusage_SavedGame);
strid_t file = glk_stream_open_file(&ref, filemode_Write, 0);
if (file == nullptr)
@@ -595,8 +596,7 @@ Common::Error Scott::loadGameState(int slot) {
short lo;
short darkFlag;
- FileReference ref;
- ref._slotNumber = slot;
+ FileReference ref(slot, "", fileusage_SavedGame | fileusage_TextMode);
file = glk_stream_open_file(&ref, filemode_Read, 0);
if (file == nullptr)
Commit: 6b39263dab79ab20118bc2bb17677a0c5b14e84c
https://github.com/scummvm/scummvm/commit/6b39263dab79ab20118bc2bb17677a0c5b14e84c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Workaround to show caret for second line entry onwards
Not sure how original GLK code properly re-renders the caret,
since the line isn't marked as dirty once input starts.
This workaround marks the line as dirty when a line request is
done, which allows the line to be redrawn with the caret
Changed paths:
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 61cf92a..9b32393 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -637,6 +637,9 @@ void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen
putText(buf, initlen, _inCurs, 0);
}
+ // WORKAROUND: Mark bottom line as dirty so caret will be drawn
+ _lines[0]._dirty = true;
+
_echoLineInput = _echoLineInputBase;
if (_lineTerminatorsBase && _termCt) {
@@ -690,6 +693,9 @@ void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 in
putTextUni(buf, initlen, _inCurs, 0);
}
+ // WORKAROUND: Mark bottom line as dirty so caret will be drawn
+ _lines[0]._dirty = true;
+
_echoLineInput = _echoLineInputBase;
if (_lineTerminatorsBase && _termCt) {
Commit: 135c3adc94fdb29241b8bf6b4828a68136ca4a40
https://github.com/scummvm/scummvm/commit/135c3adc94fdb29241b8bf6b4828a68136ca4a40
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: In progress adding mouse cursors
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 40888b1..db5d8a6 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -22,14 +22,75 @@
#include "gargoyle/events.h"
#include "gargoyle/clipboard.h"
+#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/screen.h"
#include "gargoyle/windows.h"
+#include "graphics/cursorman.h"
namespace Gargoyle {
+const byte ARROW[] = {
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0, 2, 0xF7, 5,
+ 0, 3, 0xF7, 0xF7, 5,
+ 0, 3, 0xF7, 0xF7, 5,
+ 0, 4, 0xF7, 0xF7, 0xF7, 5,
+ 0, 4, 0xF7, 0xF7, 0xF7, 5,
+ 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 2, 3, 0xF7, 0xF7, 5,
+ 3, 3, 0xF7, 0xF7, 5,
+ 3, 3, 0xF7, 0xF7, 5,
+ 4, 2, 0xF7, 5
+};
+
Events::Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false),
- _priorFrameTime(0), _frameCounter(0) {
+ _priorFrameTime(0), _frameCounter(0), _cursorId(CURSOR_NONE) {
+ initializeCursors();
+}
+
+Events::~Events() {
+ for (int idx = 1; idx < 3; ++idx)
+ _cursors[idx].free();
+}
+
+void Events::initializeCursors() {
+ const Graphics::PixelFormat format = g_system->getScreenFormat();
+ const int WHITE = format.RGBToColor(0xff, 0xff, 0xff);
+ const int BLACK = 0;
+ const int TRANSPARENT = format.RGBToColor(0x80, 0x80, 0x80);
+
+ // Setup arrow cursor
+ Surface &arr = _cursors[CURSOR_ARROW];
+ arr.create(8, 16, g_system->getScreenFormat());
+ arr.fillRect(Common::Rect(0, 0, 8, 16), TRANSPARENT);
+
+ const byte *p = ARROW;
+ for (int y = 0; y < 16; ++y) {
+ int offset = *p++;
+ int len = *p++;
+
+ for (int x = offset; x < (offset + len); ++x, ++p) {
+ arr.hLine(x, y, x, (*p == 0xf7) ? WHITE : BLACK);
+ }
+ }
+
+ // Setup selection cusor sized to the vertical line size
+ Surface &sel = _cursors[CURSOR_SELECTION];
+ sel.create(5, g_conf->_leading, g_system->getScreenFormat());
+ sel.fillRect(Common::Rect(0, 0, sel.w, sel.h), TRANSPARENT);
+ sel.hLine(0, 0, 4, 0);
+ sel.hLine(0, sel.h - 1, 4, 0);
+ sel.vLine(2, 1, sel.h - 1, 0);
+ sel._hotspot = Common::Point(2, sel.h - 1);
}
void Events::checkForNextFrameCounter() {
@@ -115,14 +176,25 @@ void Events::pollEvents() {
switch (event.type) {
case Common::EVENT_KEYDOWN:
+ setCursor(CURSOR_NONE);
handleKeyDown(event.kbd);
return;
+
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+ // TODO
+ return;
+
case Common::EVENT_WHEELUP:
case Common::EVENT_WHEELDOWN:
+ setCursor(CURSOR_NONE);
handleScroll(event.type == Common::EVENT_WHEELUP);
return;
- case Common::EVENT_LBUTTONDOWN:
- case Common::EVENT_RBUTTONDOWN:
+
+ case Common::EVENT_MOUSEMOVE:
+ if (_cursorId == CURSOR_NONE)
+ setCursor(CURSOR_ARROW);
+ break;
default:
break;
@@ -236,4 +308,22 @@ void Events::waitForPress() {
e.type != Common::EVENT_MBUTTONDOWN);
}
+void Events::setCursor(CursorId cursorId) {
+ if (cursorId != _cursorId) {
+ if (cursorId == CURSOR_NONE) {
+ CursorMan.showMouse(false);
+ } else {
+ if (!CursorMan.isVisible())
+ CursorMan.showMouse(true);
+
+ const Surface &s = _cursors[cursorId];
+ const int TRANSPARENT = s.format.RGBToColor(0x80, 0x80, 0x80);
+
+ CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s._hotspot.x, s._hotspot.y, TRANSPARENT, true, &s.format);
+ }
+
+ _cursorId = cursorId;
+ }
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 1347200..5406e3c 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -24,6 +24,7 @@
#define GARGOYLE_EVENTS_H
#include "common/events.h"
+#include "graphics/surface.h"
#include "gargoyle/utils.h"
namespace Gargoyle {
@@ -93,6 +94,12 @@ enum Keycode {
keycode_MAXVAL = 28U
};
+enum CursorId {
+ CURSOR_NONE = 0,
+ CURSOR_ARROW = 1,
+ CURSOR_SELECTION = 2
+};
+
/**
* Event structure
*/
@@ -146,6 +153,9 @@ public:
* Events manager
*/
class Events {
+ struct Surface : public Graphics::Surface {
+ Common::Point _hotspot;
+ };
private:
EventQueue _eventsPolled; ///< User generated events
EventQueue _eventsLogged; ///< Custom events generated by game code
@@ -154,8 +164,15 @@ private:
uint32 _priorFrameTime; ///< Time of prior game frame
uint32 _frameCounter; ///< Frame counter
bool _redraw; ///< Screen needed redrawing
+ CursorId _cursorId; ///< Current cursor Id
+ Surface _cursors[3]; ///< Cursor pixel data
private:
/**
+ * Initialize the cursor graphics
+ */
+ void initializeCursors();
+
+ /**
* Checks for whether it's time for the next game frame
*/
void checkForNextFrameCounter();
@@ -203,6 +220,11 @@ public:
Events();
/**
+ * Destructor
+ */
+ ~Events();
+
+ /**
* Get any pending event
*/
void getEvent(event_t *event, bool polled);
@@ -231,6 +253,11 @@ public:
* Flags the screen for redrawing
*/
void redraw() { _redraw = true; }
+
+ /**
+ * Sets the current cursor
+ */
+ void setCursor(CursorId cursorId);
};
} // End of namespace Gargoyle
Commit: c5234c9f727a23c435f03c0cbab85e0fd88e5a94
https://github.com/scummvm/scummvm/commit/c5234c9f727a23c435f03c0cbab85e0fd88e5a94
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix display of mouse cursor
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index db5d8a6..4c5fb10 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -34,22 +34,23 @@ const byte ARROW[] = {
// byte 1: number of skipped pixels
// byte 2: number of plotted pixels
// then, pixels
- 0, 2, 0xF7, 5,
- 0, 3, 0xF7, 0xF7, 5,
- 0, 3, 0xF7, 0xF7, 5,
- 0, 4, 0xF7, 0xF7, 0xF7, 5,
- 0, 4, 0xF7, 0xF7, 0xF7, 5,
- 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 2, 3, 0xF7, 0xF7, 5,
- 3, 3, 0xF7, 0xF7, 5,
- 3, 3, 0xF7, 0xF7, 5,
- 4, 2, 0xF7, 5
+ 0, 1, 5,
+ 0, 2, 5, 5,
+ 0, 3, 5, 0xF7, 5,
+ 0, 3, 5, 0xF7, 5,
+ 0, 4, 5, 0xF7, 0xF7, 5,
+ 0, 4, 5, 0xF7, 0xF7, 5,
+ 0, 5, 5, 0xF7, 0xF7, 0xF7, 5,
+ 0, 5, 5, 0xF7, 0xF7, 0xF7, 5,
+ 0, 6, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 6, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 7, 5, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 6, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 0, 5, 5, 0xF7, 0xF7, 0xF7, 5,
+ 2, 3, 5, 0xF7, 5,
+ 3, 3, 5, 0xF7, 5,
+ 3, 3, 5, 0xF7, 5,
+ 4, 2, 5, 5
};
Events::Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false),
@@ -84,13 +85,15 @@ void Events::initializeCursors() {
}
// Setup selection cusor sized to the vertical line size
- Surface &sel = _cursors[CURSOR_SELECTION];
+ Surface &sel = _cursors[CURSOR_IBEAM];
sel.create(5, g_conf->_leading, g_system->getScreenFormat());
sel.fillRect(Common::Rect(0, 0, sel.w, sel.h), TRANSPARENT);
sel.hLine(0, 0, 4, 0);
sel.hLine(0, sel.h - 1, 4, 0);
sel.vLine(2, 1, sel.h - 1, 0);
sel._hotspot = Common::Point(2, sel.h - 1);
+
+ // TODO: Hyperlink hand cursor
}
void Events::checkForNextFrameCounter() {
@@ -169,9 +172,9 @@ void Events::dispatchEvent(Event &ev, bool polled) {
void Events::pollEvents() {
Common::Event event;
- checkForNextFrameCounter();
do {
+ checkForNextFrameCounter();
g_system->getEventManager()->pollEvent(event);
switch (event.type) {
@@ -192,8 +195,7 @@ void Events::pollEvents() {
return;
case Common::EVENT_MOUSEMOVE:
- if (_cursorId == CURSOR_NONE)
- setCursor(CURSOR_ARROW);
+ handleMouseMove(event.mouse);
break;
default:
@@ -267,6 +269,9 @@ void Events::handleScroll(bool wheelUp) {
}
void Events::handleMouseMove(const Point &pos) {
+ if (_cursorId == CURSOR_NONE)
+ setCursor(CURSOR_ARROW);
+
// hyperlinks and selection
// TODO: Properly handle commented out lines
if (g_vm->_copySelect) {
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 5406e3c..5da4e53 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -94,10 +94,14 @@ enum Keycode {
keycode_MAXVAL = 28U
};
+/**
+ * List of cursors
+ */
enum CursorId {
CURSOR_NONE = 0,
CURSOR_ARROW = 1,
- CURSOR_SELECTION = 2
+ CURSOR_IBEAM = 2,
+ CURSOR_HAND = 3
};
/**
@@ -165,7 +169,7 @@ private:
uint32 _frameCounter; ///< Frame counter
bool _redraw; ///< Screen needed redrawing
CursorId _cursorId; ///< Current cursor Id
- Surface _cursors[3]; ///< Cursor pixel data
+ Surface _cursors[4]; ///< Cursor pixel data
private:
/**
* Initialize the cursor graphics
Commit: 8e1be3a95c7395c83271e54f505ca10cc4c4c531
https://github.com/scummvm/scummvm/commit/8e1be3a95c7395c83271e54f505ca10cc4c4c531
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Text selection highlighting is now working
Changed paths:
engines/gargoyle/clipboard.h
engines/gargoyle/events.cpp
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_mask.cpp
engines/gargoyle/window_mask.h
engines/gargoyle/window_pair.cpp
engines/gargoyle/window_pair.h
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/clipboard.h b/engines/gargoyle/clipboard.h
index 23e7aaf..18519c7 100644
--- a/engines/gargoyle/clipboard.h
+++ b/engines/gargoyle/clipboard.h
@@ -29,6 +29,9 @@ namespace Gargoyle {
enum ClipSource { PRIMARY = 0, CLIPBOARD = 1 };
+/**
+ * Handles selection of text, and copying to and from the clipboard
+ */
class Clipboard {
private:
Common::Array<uint32> _text;
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 4c5fb10..7d6bf39 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -185,9 +185,13 @@ void Events::pollEvents() {
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
- // TODO
+ handleButtonDown(event.type == Common::EVENT_LBUTTONDOWN, event.mouse);
return;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ handleButtonUp(event.type == Common::EVENT_LBUTTONUP, event.mouse);
+
case Common::EVENT_WHEELUP:
case Common::EVENT_WHEELDOWN:
setCursor(CURSOR_NONE);
@@ -287,16 +291,18 @@ void Events::handleMouseMove(const Point &pos) {
}
void Events::handleButtonDown(bool isLeft, const Point &pos) {
- if (isLeft)
+ if (isLeft) {
+ setCursor(CURSOR_IBEAM);
g_vm->_windows->inputHandleClick(pos);
- else
+ } else {
g_vm->_clipboard->receive(PRIMARY);
+ }
}
void Events::handleButtonUp(bool isLeft, const Point &pos) {
if (isLeft) {
+ setCursor(CURSOR_ARROW);
g_vm->_copySelect = false;
- //gdk_window_set_cursor((GTK_WIDGET(widget)->window), nullptr);
g_vm->_clipboard->send(PRIMARY);
}
}
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index b31d620..3286876 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/window_graphics.h"
+#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/screen.h"
@@ -247,4 +248,25 @@ void GraphicsWindow::setBackgroundColor(glui32 color) {
_bgnd[2] = (color >> 0) & 0xff;
}
+void GraphicsWindow::click(const Point &newPos) {
+ Point diff = newPos - Point(_bbox.left, _bbox.top);
+
+ if (_mouseRequest) {
+ g_vm->_events->store(evtype_MouseInput, this, diff.x, diff.y);
+ _mouseRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+
+ if (_hyperRequest) {
+ glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
+ if (linkval) {
+ g_vm->_events->store(evtype_Hyperlink, this, linkval, 0);
+ _hyperRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = 1;
+ }
+ }
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
index f271444..ebcf45b 100644
--- a/engines/gargoyle/window_graphics.h
+++ b/engines/gargoyle/window_graphics.h
@@ -68,6 +68,11 @@ public:
}
/**
+ * Click the window
+ */
+ virtual void click(const Point &newPos) override;
+
+ /**
* Cancel a mouse event
*/
virtual void cancelMouseEvent() override { _mouseRequest = false; }
diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp
index 6c85789..495abc6 100644
--- a/engines/gargoyle/window_mask.cpp
+++ b/engines/gargoyle/window_mask.cpp
@@ -28,11 +28,8 @@
namespace Gargoyle {
-int WindowMask::_lastX;
-int WindowMask::_lastY;
-
WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) {
- _lastX = _lastY = 0;
+ _last.x = _last.y = 0;
resize(g_system->getWidth(), g_system->getHeight());
}
@@ -96,15 +93,13 @@ void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1
}
}
-glui32 WindowMask::getHyperlink(const Point &pos) {
+glui32 WindowMask::getHyperlink(const Point &pos) const {
if (!_hor || !_ver) {
warning("getHyperlink: struct not initialized");
return 0;
}
- if (pos.x >= (int16)_hor
- || pos.y >= (int16)_ver
- || !_links[pos.x]) {
+ if (pos.x >= (int16)_hor || pos.y >= (int16)_ver || !_links[pos.x]) {
warning("getHyperlink: invalid range given");
return 0;
}
@@ -123,8 +118,8 @@ void WindowMask::startSelection(const Point &pos) {
tx = MIN(pos.x, (int16)_hor);
ty = MIN(pos.y, (int16)_ver);
- _select.left = _lastX = tx;
- _select.top = _lastY = ty;
+ _select.left = _last.x = tx;
+ _select.top = _last.y = ty;
_select.right = 0;
_select.bottom = 0;
@@ -134,7 +129,7 @@ void WindowMask::startSelection(const Point &pos) {
void WindowMask::moveSelection(const Point &pos) {
int tx, ty;
- if (ABS(pos.x - _lastX) < 5 && abs(pos.y - _lastY) < 5)
+ if (ABS(pos.x - _last.x) < 5 && ABS(pos.y - _last.y) < 5)
return;
if (!_hor || !_ver) {
@@ -145,70 +140,35 @@ void WindowMask::moveSelection(const Point &pos) {
tx = MIN(pos.x, (int16)_hor);
ty = MIN(pos.y, (int16)_ver);
- _select.right = _lastX = tx;
- _select.bottom = _lastY = ty;
+ _select.right = _last.x = tx;
+ _select.bottom = _last.y = ty;
g_vm->_windows->selectionChanged();
}
void WindowMask::clearSelection() {
- if (_select.left || _select.right
- || _select.top || _select.bottom)
+ if (!_select.isEmpty())
Windows::_forceRedraw = true;
- _select.left = 0;
- _select.top = 0;
- _select.right = 0;
- _select.bottom = 0;
+ _select = Rect();
g_vm->_windows->clearClaimSelect();
}
-int WindowMask::checkSelection(uint x0, uint y0, uint x1, uint y1) {
- uint cx0, cx1, cy0, cy1;
-
- cx0 = _select.left < _select.right
- ? _select.left
- : _select.right;
-
- cx1 = _select.left < _select.right
- ? _select.right
- : _select.left;
-
- cy0 = _select.top < _select.bottom
- ? _select.top
- : _select.bottom;
-
- cy1 = _select.top < _select.bottom
- ? _select.bottom
- : _select.top;
-
- if (!cx0 || !cx1 || !cy0 || !cy1)
+bool WindowMask::checkSelection(const Rect &r) const {
+ Rect select(MIN(_select.left, _select.right), MAX(_select.left, _select.right),
+ MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom));
+ if (select.isEmpty())
return false;
- if (cx0 >= x0 && cx0 <= x1
- && cy0 >= y0 && cy0 <= y1)
- return true;
-
- if (cx0 >= x0 && cx0 <= x1
- && cy1 >= y0 && cy1 <= y1)
- return true;
-
- if (cx1 >= x0 && cx1 <= x1
- && cy0 >= y0 && cy0 <= y1)
- return true;
-
- if (cx1 >= x0 && cx1 <= x1
- && cy1 >= y0 && cy1 <= y1)
- return true;
-
- return false;
+ return select.intersects(r);
}
-int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *rx1) {
+bool WindowMask::getSelection(const Rect &r, int *rx0, int *rx1) const {
uint row, upper, lower, above, below;
- int row_selected, found_left, found_right;
+ bool row_selected, found_left, found_right;
int from_right, from_below, is_above, is_below;
uint cx0, cx1, cy0, cy1;
+ uint x0 = r.left, y0 = r.top, x1 = r.right, y1 = r.bottom;
row = (y0 + y1) / 2;
upper = row - (row - y0) / 2;
@@ -216,21 +176,10 @@ int WindowMask::getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *
above = upper - (g_conf->_leading) / 2;
below = lower + (g_conf->_leading) / 2;
- cx0 = _select.left < _select.right
- ? _select.left
- : _select.right;
-
- cx1 = _select.left < _select.right
- ? _select.right
- : _select.left;
-
- cy0 = _select.top < _select.bottom
- ? _select.top
- : _select.bottom;
-
- cy1 = _select.top < _select.bottom
- ? _select.bottom
- : _select.top;
+ cx0 = MIN(_select.left, _select.right);
+ cx1 = MAX(_select.left, _select.right);
+ cy0 = MIN(_select.top, _select.bottom);
+ cy1 = MAX(_select.top, _select.bottom);
row_selected = false;
diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h
index e9030a2..67d68dc 100644
--- a/engines/gargoyle/window_mask.h
+++ b/engines/gargoyle/window_mask.h
@@ -36,8 +36,7 @@ public:
size_t _hor, _ver;
glui32 **_links;
Rect _select;
-
- static int _lastX, _lastY;
+ Point _last;
public:
/**
* Constructor
@@ -51,17 +50,28 @@ public:
void putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1);
- glui32 getHyperlink(const Point &pos);
+ glui32 getHyperlink(const Point &pos) const;
+ /**
+ * Start selecting an area of the screen
+ * @param pos Position to start selection area at
+ */
void startSelection(const Point &pos);
+ /**
+ * Move the end point of the selection area
+ * @param pos Position to end selection area at
+ */
void moveSelection(const Point &pos);
void clearSelection();
- int checkSelection(uint x0, uint y0, uint x1, uint y1);
+ /**
+ * Checks whether the passed area intersects the selection area
+ */
+ bool checkSelection(const Rect &r) const;
- int getSelection(uint x0, uint y0, uint x1, uint y1, int *rx0, int *rx1);
+ bool getSelection(const Rect &r, int *rx0, int *rx1) const;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
index 26903cd..33914c5 100644
--- a/engines/gargoyle/window_pair.cpp
+++ b/engines/gargoyle/window_pair.cpp
@@ -225,4 +225,12 @@ void PairWindow::setArrangement(glui32 method, glui32 size, Window *keyWin) {
_windows->rearrange();
}
+void PairWindow::click(const Point &newPos) {
+ if (_child1->_bbox.contains(newPos))
+ _child1->click(newPos);
+
+ if (_child2->_bbox.contains(newPos))
+ _child2->click(newPos);
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
index a28f7fd0..a5b9081 100644
--- a/engines/gargoyle/window_pair.h
+++ b/engines/gargoyle/window_pair.h
@@ -61,6 +61,11 @@ public:
virtual void getArrangement(glui32 *method, glui32 *size, Window **keyWin) override;
virtual void setArrangement(glui32 method, glui32 size, Window *keyWin) override;
+
+ /**
+ * Click the window
+ */
+ virtual void click(const Point &newPos) override;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index 9b32393..a8ac85e 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -793,7 +793,8 @@ void TextBufferWindow::redraw() {
unsigned char *color;
int i;
int hx0, hx1, hy0, hy1;
- int selbuf, selrow, selchar, sx0, sx1, selleft, selright;
+ int selrow, selchar, sx0, sx1, selleft, selright;
+ bool selBuf;
int tx, tsc, tsw, lsc, rsc;
Screen &screen = *g_vm->_screen;
@@ -814,17 +815,16 @@ void TextBufferWindow::redraw() {
pw = x1 - x0 - 2 * GLI_SUBPIX;
// check if any part of buffer is selected
- selbuf = g_vm->_windowMask->checkSelection(x0/GLI_SUBPIX,y0,x1/GLI_SUBPIX,y1);
+ selBuf = g_vm->_windowMask->checkSelection(Rect(x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1));
for (i = _scrollPos + _height - 1; i >= _scrollPos; i--) {
// top of line
y = y0 + (_height - (i - _scrollPos) - 1) * g_conf->_leading;
// check if part of line is selected
- if (selbuf) {
- selrow = g_vm->_windowMask->getSelection(x0/GLI_SUBPIX, y,
- x1/GLI_SUBPIX, y + g_conf->_leading,
- &sx0, &sx1);
+ if (selBuf) {
+ selrow = g_vm->_windowMask->getSelection(Rect(x0 / GLI_SUBPIX, y,
+ x1 / GLI_SUBPIX, y + g_conf->_leading), &sx0, &sx1);
selleft = (sx0 == x0/GLI_SUBPIX);
selright = (sx1 == x1/GLI_SUBPIX);
} else {
@@ -1141,7 +1141,7 @@ void TextBufferWindow::redraw() {
}
// send selected text to clipboard
- if (selbuf && _copyPos) {
+ if (selBuf && _copyPos) {
Windows::_claimSelect = true;
g_vm->_clipboard->store(_copyBuf, _copyPos);
Commit: 88315e7349a011d8168dc3e4c562f40e6e51c1c1
https://github.com/scummvm/scummvm/commit/88315e7349a011d8168dc3e4c562f40e6e51c1c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix selection area getting removed when mouse button was released
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/window_mask.h
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 7d6bf39..4618df4 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -191,6 +191,7 @@ void Events::pollEvents() {
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
handleButtonUp(event.type == Common::EVENT_LBUTTONUP, event.mouse);
+ return;
case Common::EVENT_WHEELUP:
case Common::EVENT_WHEELDOWN:
diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h
index 67d68dc..502ed49 100644
--- a/engines/gargoyle/window_mask.h
+++ b/engines/gargoyle/window_mask.h
@@ -64,6 +64,9 @@ public:
*/
void moveSelection(const Point &pos);
+ /**
+ * Remove any previously selected area
+ */
void clearSelection();
/**
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index a8ac85e..c6dde5b 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -365,9 +365,9 @@ void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldle
void TextBufferWindow::touch(int line) {
_lines[line]._dirty = true;
g_vm->_windowMask->clearSelection();
- //int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
- //_windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
- redraw();
+
+ int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
+ _windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
}
glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
Commit: 596a36aef02e3bdd41f15c1b2f142acbd49f50f0
https://github.com/scummvm/scummvm/commit/596a36aef02e3bdd41f15c1b2f142acbd49f50f0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Allow video mode to be specified in the configuration
Changed paths:
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 3135fcb..1a817c6 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -68,7 +68,7 @@ void GargoyleEngine::initialize() {
DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
- initGraphics(640, 480, false);
+ initGraphicsMode();
_conf = new Conf();
_screen = new Screen();
@@ -80,6 +80,22 @@ void GargoyleEngine::initialize() {
_windowMask = new WindowMask();
}
+void GargoyleEngine::initGraphicsMode() {
+ uint width = ConfMan.hasKey("width") ? ConfMan.getInt("width") : 640;
+ uint height = ConfMan.hasKey("height") ? ConfMan.getInt("height") : 480;
+ Common::List<Graphics::PixelFormat> formats = g_system->getSupportedFormats();
+ Graphics::PixelFormat format = formats.front();
+
+ for (Common::List<Graphics::PixelFormat>::iterator i = formats.begin(); i != formats.end(); ++i) {
+ if ((*i).bytesPerPixel > 1) {
+ format = *i;
+ break;
+ }
+ }
+
+ initGraphics(width, height, &format);
+}
+
Common::Error GargoyleEngine::run() {
initialize();
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 0b8bca7..728dc0f 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -81,6 +81,11 @@ private:
* Handles basic initialization
*/
void initialize();
+
+ /**
+ * Setup the video mode
+ */
+ void initGraphicsMode();
protected:
const GargoyleGameDescription *_gameDescription;
Common::RandomSource _random;
Commit: 65167bd202f20e345bc9cdb2f0fe36c5abe28fe3
https://github.com/scummvm/scummvm/commit/65167bd202f20e345bc9cdb2f0fe36c5abe28fe3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added a fonts.dat Zip archive containing the fonts
Changed paths:
A dists/engine-data/fonts.dat
dists/scummvm.rc
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
diff --git a/dists/engine-data/fonts.dat b/dists/engine-data/fonts.dat
new file mode 100644
index 0000000..b7dde60
Binary files /dev/null and b/dists/engine-data/fonts.dat differ
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 65e7f00..6d7782a 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -34,6 +34,9 @@ cryo.dat FILE "dists/engine-data/cryo.dat"
#if ENABLE_DRASCULA == STATIC_PLUGIN
drascula.dat FILE "dists/engine-data/drascula.dat"
#endif
+#if ENABLE_GARGOYLE == STATIC_PLUGIN
+fonts.dat FILE "dists/engine-data/fonts.dat"
+#endif
#if ENABLE_HUGO == STATIC_PLUGIN
hugo.dat FILE "dists/engine-data/hugo.dat"
#endif
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 8172c78..857ef15 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -23,36 +23,20 @@
#include "gargoyle/fonts.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/conf.h"
-#include "common/file.h"
+#include "gargoyle/gargoyle.h"
+#include "common/memstream.h"
+#include "common/unzip.h"
#include "graphics/fonts/ttf.h"
+#include "graphics/fontman.h"
namespace Gargoyle {
-const char *gli_conf_propr = "NotoSerif-Regular";
-const char *gli_conf_propb = "NotoSerif-Bold";
-const char *gli_conf_propi = "NotoSerif-Italic";
-const char *gli_conf_propz = "NotoSerif-BoldItalic";
+#define FONTS_VERSION 1.0
+#define FONTS_FILENAME "fonts.dat"
-const char *gli_conf_monor = "GoMono-Regular";
-const char *gli_conf_monob = "GoMono-Bold";
-const char *gli_conf_monoi = "GoMono-Italic";
-const char *gli_conf_monoz = "GoMono-BoldItalic";
-
-Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface) {
- double monoAspect = g_conf->_monoAspect;
- double propAspect = g_conf->_propAspect;
- double monoSize = g_conf->_monoSize;
- double propSize = g_conf->_propSize;
-
- _fontTable[0] = loadFont(MONOR, monoSize, monoAspect, FONTR);
- _fontTable[1] = loadFont(MONOB, monoSize, monoAspect, FONTB);
- _fontTable[2] = loadFont(MONOI, monoSize, monoAspect, FONTI);
- _fontTable[3] = loadFont(MONOZ, monoSize, monoAspect, FONTZ);
-
- _fontTable[4] = loadFont(PROPR, propSize, propAspect, FONTR);
- _fontTable[5] = loadFont(PROPB, propSize, propAspect, FONTB);
- _fontTable[6] = loadFont(PROPI, propSize, propAspect, FONTI);
- _fontTable[7] = loadFont(PROPZ, propSize, propAspect, FONTZ);
+Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface), _fontsMissing(false) {
+ if (!loadFonts())
+ error("Could not load data file");
if (!g_conf->_leading)
g_conf->_leading = g_conf->_propSize + 2;
@@ -68,6 +52,63 @@ Fonts::~Fonts() {
delete _fontTable[idx];
}
+bool Fonts::loadFonts() {
+ Common::Archive *archive = nullptr;
+
+ if (!Common::File::exists(FONTS_FILENAME) || (archive = Common::makeZipArchive(FONTS_FILENAME)) == nullptr)
+ return false;
+
+ // Open the version.txt file within it to validate the version
+ Common::File f;
+ if (!f.open("version.txt", *archive)) {
+ delete archive;
+ return false;
+ }
+
+ // Validate the version
+ char buffer[4];
+ f.read(buffer, 3);
+ buffer[3] = '\0';
+
+ if (Common::String(buffer) != "1.0") {
+ delete archive;
+ return false;
+ }
+
+ // R ead in the fonts
+ double monoAspect = g_conf->_monoAspect;
+ double propAspect = g_conf->_propAspect;
+ double monoSize = g_conf->_monoSize;
+ double propSize = g_conf->_propSize;
+
+ _fontTable[0] = loadFont(MONOR, archive, monoSize, monoAspect, FONTR);
+ _fontTable[1] = loadFont(MONOB, archive, monoSize, monoAspect, FONTB);
+ _fontTable[2] = loadFont(MONOI, archive, monoSize, monoAspect, FONTI);
+ _fontTable[3] = loadFont(MONOZ, archive, monoSize, monoAspect, FONTZ);
+
+ _fontTable[4] = loadFont(PROPR, archive, propSize, propAspect, FONTR);
+ _fontTable[5] = loadFont(PROPB, archive, propSize, propAspect, FONTB);
+ _fontTable[6] = loadFont(PROPI, archive, propSize, propAspect, FONTI);
+ _fontTable[7] = loadFont(PROPZ, archive, propSize, propAspect, FONTZ);
+
+ delete archive;
+ return true;
+}
+
+const Graphics::Font *Fonts::loadFont(FACES face, Common::Archive *archive, double size, double aspect, int
+ style) {
+ const char *const FILENAMES[8] = {
+ "GoMono-Regular.ttf", "GoMono-Bold.ttf", "GoMono-Italic.ttf", "GoMono-Bold-Italic.ttf",
+ "NotoSerif-Regular.ttf", "NotoSerif-Bold.ttf", "NotoSerif-Italic.ttf", "NotoSerif-Bold-Italic.ttf"
+ };
+
+ Common::File f;
+ if (!f.open(FILENAMES[face], *archive))
+ error("Could not load font");
+
+ return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
+}
+
FACES Fonts::getId(const Common::String &name) {
if (name == "monor") return MONOR;
if (name == "monob") return MONOB;
@@ -80,28 +121,9 @@ FACES Fonts::getId(const Common::String &name) {
return MONOR;
}
-Graphics::Font *Fonts::loadFont(FACES face, double size, double aspect, int style) {
- static const char *const MAP[8] = {
- "Go-Mono-Regular",
- "Go-Mono-Bold",
- "Go-Mono-Italic",
- "Go-Mono-BoldItalic",
- "NotoSerif-Regular",
- "NotoSerif-Bold",
- "NotoSerif-Italic",
- "NotoSerif-BoldItalic"
- };
-
- Common::File f;
- if (!f.open(Common::String::format("%s.ttf", MAP[face])))
- return nullptr;
-
- return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
-}
-
int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
- Graphics::Font *font = _fontTable[fontIdx];
+ const Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
@@ -111,7 +133,7 @@ int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Comm
int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
- Graphics::Font *font = _fontTable[fontIdx];
+ const Graphics::Font *font = _fontTable[fontIdx];
const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
@@ -121,13 +143,13 @@ int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const C
size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
// TODO: Handle spw
- Graphics::Font *font = _fontTable[fontIdx];
+ const Graphics::Font *font = _fontTable[fontIdx];
return font->getStringWidth(text) * GLI_SUBPIX;
}
size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
// TODO: Handle spw
- Graphics::Font *font = _fontTable[fontIdx];
+ const Graphics::Font *font = _fontTable[fontIdx];
return font->getStringWidth(text) * GLI_SUBPIX;
}
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index dc0bfd8..2f2cb41 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -25,6 +25,9 @@
#include "gargoyle/glk_types.h"
#include "gargoyle/utils.h"
+#include "common/archive.h"
+#include "common/array.h"
+#include "common/file.h"
#include "common/str.h"
#include "common/ustr.h"
#include "graphics/font.h"
@@ -37,12 +40,24 @@ enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
enum TYPES { MONOF, PROPF };
enum STYLES { FONTR, FONTB, FONTI, FONTZ };
+/**
+ * Fonts manager
+ */
class Fonts {
private:
Graphics::ManagedSurface *_surface;
- Graphics::Font *_fontTable[FONTS_TOTAL];
+ const Graphics::Font *_fontTable[FONTS_TOTAL];
+ bool _fontsMissing;
private:
- Graphics::Font *loadFont(FACES face, double size, double aspect, int style);
+ /**
+ * Load all the fonts
+ */
+ bool loadFonts();
+
+ /**
+ * Load a single font
+ */
+ const Graphics::Font *loadFont(FACES face, Common::Archive *archive, double size, double aspect, int style);
public:
/**
* Get the index/id of a font by name
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 1a817c6..59a39b4 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -106,4 +106,16 @@ Common::Error GargoyleEngine::run() {
return Common::kNoError;
}
+void GargoyleEngine::GUIError(const char *msg, ...) {
+ char buffer[STRINGBUFLEN];
+ va_list va;
+
+ // Generate the full error message
+ va_start(va, msg);
+ vsnprintf(buffer, STRINGBUFLEN, msg, va);
+ va_end(va);
+
+ GUIErrorMessage(buffer);
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 728dc0f..f65ce94 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -166,6 +166,11 @@ public:
* Return the game engine's target name
*/
const Common::String &getTargetName() const { return _targetName; }
+
+ /**
+ * Display a message in a GUI dialog
+ */
+ void GUIError(const char *msg, ...);
};
extern GargoyleEngine *g_vm;
Commit: d6538380d7afe31b571945bf642496a08af09dfc
https://github.com/scummvm/scummvm/commit/d6538380d7afe31b571945bf642496a08af09dfc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Implemented pasting from clipboard
Changed paths:
engines/gargoyle/clipboard.cpp
diff --git a/engines/gargoyle/clipboard.cpp b/engines/gargoyle/clipboard.cpp
index 69ef8f8..81ef12f 100644
--- a/engines/gargoyle/clipboard.cpp
+++ b/engines/gargoyle/clipboard.cpp
@@ -21,6 +21,9 @@
*/
#include "gargoyle/clipboard.h"
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/windows.h"
+#include "common/system.h"
namespace Gargoyle {
@@ -33,7 +36,16 @@ void Clipboard::send(ClipSource source) {
}
void Clipboard::receive(ClipSource source) {
- // TODO
+ Windows &windows = *g_vm->_windows;
+
+ if (g_system->hasTextInClipboard()) {
+ Common::String text = g_system->getTextFromClipboard();
+ for (uint idx = 0; idx < text.size(); ++idx) {
+ uint c = text[idx];
+ if (c != '\r' && c != '\n' && c != '\b' && c != '\t')
+ windows.inputHandleKey(c);
+ }
+ }
}
} // End of namespace Gargoyle
Commit: c4bcb0882f6e8f7fba5c89b9a561bb91fb662f1a
https://github.com/scummvm/scummvm/commit/c4bcb0882f6e8f7fba5c89b9a561bb91fb662f1a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Merge Clipboard and WindowMask into a new Selection class
Changed paths:
A engines/gargoyle/selection.cpp
A engines/gargoyle/selection.h
R engines/gargoyle/clipboard.cpp
R engines/gargoyle/clipboard.h
R engines/gargoyle/window_mask.cpp
R engines/gargoyle/window_mask.h
engines/gargoyle/events.cpp
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/module.mk
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/clipboard.cpp b/engines/gargoyle/clipboard.cpp
deleted file mode 100644
index 81ef12f..0000000
--- a/engines/gargoyle/clipboard.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/clipboard.h"
-#include "gargoyle/gargoyle.h"
-#include "gargoyle/windows.h"
-#include "common/system.h"
-
-namespace Gargoyle {
-
-void Clipboard::store(const uint32 *text, size_t len) {
- // TODO
-}
-
-void Clipboard::send(ClipSource source) {
- // TODO
-}
-
-void Clipboard::receive(ClipSource source) {
- Windows &windows = *g_vm->_windows;
-
- if (g_system->hasTextInClipboard()) {
- Common::String text = g_system->getTextFromClipboard();
- for (uint idx = 0; idx < text.size(); ++idx) {
- uint c = text[idx];
- if (c != '\r' && c != '\n' && c != '\b' && c != '\t')
- windows.inputHandleKey(c);
- }
- }
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/clipboard.h b/engines/gargoyle/clipboard.h
deleted file mode 100644
index 18519c7..0000000
--- a/engines/gargoyle/clipboard.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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 GARGOYLE_CLIPBOARD_H
-#define GARGOYLE_CLIPBOARD_H
-
-#include "common/array.h"
-
-namespace Gargoyle {
-
-enum ClipSource { PRIMARY = 0, CLIPBOARD = 1 };
-
-/**
- * Handles selection of text, and copying to and from the clipboard
- */
-class Clipboard {
-private:
- Common::Array<uint32> _text;
-public:
- void store(const uint32 *text, size_t len);
-
- void send(ClipSource source);
-
- void receive(ClipSource source);
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 4618df4..bc56407 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -21,10 +21,10 @@
*/
#include "gargoyle/events.h"
-#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/screen.h"
+#include "gargoyle/selection.h"
#include "gargoyle/windows.h"
#include "graphics/cursorman.h"
@@ -217,15 +217,15 @@ void Events::handleKeyDown(const Common::KeyState &ks) {
if (ks.keycode == Common::KEYCODE_a)
windows.inputHandleKey(keycode_Home);
else if (ks.keycode == Common::KEYCODE_c)
- clipboard.send(CLIPBOARD);
+ clipboard.clipboardSend(CLIPBOARD);
else if (ks.keycode == Common::KEYCODE_e)
windows.inputHandleKey(keycode_End);
else if (ks.keycode == Common::KEYCODE_u)
windows.inputHandleKey(keycode_Escape);
else if (ks.keycode == Common::KEYCODE_v)
- clipboard.receive(CLIPBOARD);
+ clipboard.clipboardReceive(CLIPBOARD);
else if (ks.keycode == Common::KEYCODE_x)
- clipboard.send(CLIPBOARD);
+ clipboard.clipboardSend(CLIPBOARD);
else if (ks.keycode == Common::KEYCODE_LEFT || ks.keycode == Common::KEYCODE_KP4)
windows.inputHandleKey(keycode_SkipWordLeft);
else if (ks.keycode == Common::KEYCODE_RIGHT || ks.keycode == Common::KEYCODE_KP6)
@@ -281,9 +281,9 @@ void Events::handleMouseMove(const Point &pos) {
// TODO: Properly handle commented out lines
if (g_vm->_copySelect) {
//gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_ibeam);
- g_vm->_windowMask->moveSelection(pos);
+ g_vm->_selection->moveSelection(pos);
} else {
- if (g_vm->_windowMask->getHyperlink(pos)) {
+ if (g_vm->_selection->getHyperlink(pos)) {
//gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_hand);
} else {
//gdk_window_set_cursor((GTK_WIDGET(widget)->window), nullptr);
@@ -296,7 +296,7 @@ void Events::handleButtonDown(bool isLeft, const Point &pos) {
setCursor(CURSOR_IBEAM);
g_vm->_windows->inputHandleClick(pos);
} else {
- g_vm->_clipboard->receive(PRIMARY);
+ g_vm->_clipboard->clipboardReceive(PRIMARY);
}
}
@@ -304,7 +304,7 @@ void Events::handleButtonUp(bool isLeft, const Point &pos) {
if (isLeft) {
setCursor(CURSOR_ARROW);
g_vm->_copySelect = false;
- g_vm->_clipboard->send(PRIMARY);
+ g_vm->_clipboard->clipboardSend(PRIMARY);
}
}
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 59a39b4..9c00937 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -29,14 +29,13 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
-#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/events.h"
#include "gargoyle/picture.h"
#include "gargoyle/screen.h"
+#include "gargoyle/selection.h"
#include "gargoyle/streams.h"
#include "gargoyle/windows.h"
-#include "gargoyle/window_mask.h"
namespace Gargoyle {
@@ -44,8 +43,8 @@ GargoyleEngine *g_vm;
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _clipboard(nullptr),
- _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr), _windows(nullptr),
- _windowMask(nullptr), _copySelect(false), _terminated(false),
+ _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
+ _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
}
@@ -56,9 +55,9 @@ GargoyleEngine::~GargoyleEngine() {
delete _events;
delete _picList;
delete _screen;
+ delete _selection;
delete _streams;
delete _windows;
- delete _windowMask;
}
void GargoyleEngine::initialize() {
@@ -75,9 +74,9 @@ void GargoyleEngine::initialize() {
_clipboard = new Clipboard();
_events = new Events();
_picList = new PicList();
+ _selection = new Selection();
_streams = new Streams();
_windows = new Windows(_screen);
- _windowMask = new WindowMask();
}
void GargoyleEngine::initGraphicsMode() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index f65ce94..793a353 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -38,9 +38,9 @@ class Conf;
class Events;
class PicList;
class Screen;
+class Selection;
class Streams;
class Windows;
-class WindowMask;
enum InterpreterType {
INTERPRETER_ADVSYS = 0,
@@ -109,9 +109,9 @@ public:
Events *_events;
PicList *_picList;
Screen *_screen;
+ Selection *_selection;
Streams *_streams;
Windows *_windows;
- WindowMask *_windowMask;
bool _copySelect;
bool _terminated;
void (*gli_unregister_obj)(void *obj, glui32 objclass, gidispatch_rock_t objrock);
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index f4422b0..bf4138a 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -1,7 +1,6 @@
MODULE := engines/gargoyle
MODULE_OBJS := \
- clipboard.o \
conf.o \
detection.o \
events.o \
@@ -10,6 +9,7 @@ MODULE_OBJS := \
glk.o \
picture.o \
screen.o \
+ selection.o \
streams.o \
time.o \
unicode.o \
diff --git a/engines/gargoyle/selection.cpp b/engines/gargoyle/selection.cpp
new file mode 100644
index 0000000..2b72c1e
--- /dev/null
+++ b/engines/gargoyle/selection.cpp
@@ -0,0 +1,312 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/selection.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+#include "gargoyle/windows.h"
+#include "common/system.h"
+
+namespace Gargoyle {
+
+void Clipboard::clipboardStore(const uint32 *text, size_t len) {
+ // TODO
+}
+
+void Clipboard::clipboardSend(ClipSource source) {
+ // TODO
+}
+
+void Clipboard::clipboardReceive(ClipSource source) {
+ Windows &windows = *g_vm->_windows;
+
+ if (g_system->hasTextInClipboard()) {
+ Common::String text = g_system->getTextFromClipboard();
+ for (uint idx = 0; idx < text.size(); ++idx) {
+ uint c = text[idx];
+ if (c != '\r' && c != '\n' && c != '\b' && c != '\t')
+ windows.inputHandleKey(c);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) {
+ _last.x = _last.y = 0;
+ resize(g_system->getWidth(), g_system->getHeight());
+}
+
+void WindowMask::resize(size_t x, size_t y) {
+ // Deallocate old storage
+ for (size_t i = 0; i < _hor; i++) {
+ if (_links[i])
+ delete _links[i];
+ }
+
+ delete _links;
+
+ _hor = x + 1;
+ _ver = y + 1;
+
+ // allocate new storage
+ _links = new glui32 *[_hor];
+ if (!_links) {
+ warning("resize_mask: out of memory");
+ _hor = _ver = 0;
+ return;
+ }
+
+ for (size_t i = 0; i < _hor; i++) {
+ _links[i] = new glui32[_ver];
+ if (!_links[i]) {
+ warning("resize_mask: could not allocate new memory");
+ return;
+ }
+ }
+
+ _select.left = 0;
+ _select.top = 0;
+ _select.right = 0;
+ _select.bottom = 0;
+}
+
+void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1) {
+ uint i, k;
+ size_t tx0 = x0 < x1 ? x0 : x1;
+ size_t tx1 = x0 < x1 ? x1 : x0;
+ size_t ty0 = y0 < y1 ? y0 : y1;
+ size_t ty1 = y0 < y1 ? y1 : y0;
+
+ if (!_hor || !_ver) {
+ warning("putHyperlink: struct not initialized");
+ return;
+ }
+
+ if (tx0 >= _hor
+ || tx1 >= _hor
+ || ty0 >= _ver || ty1 >= _ver
+ || !_links[tx0] || !_links[tx1]) {
+ warning("putHyperlink: invalid range given");
+ return;
+ }
+
+ for (i = tx0; i < tx1; i++) {
+ for (k = ty0; k < ty1; k++)
+ _links[i][k] = linkval;
+ }
+}
+
+glui32 WindowMask::getHyperlink(const Point &pos) const {
+ if (!_hor || !_ver) {
+ warning("getHyperlink: struct not initialized");
+ return 0;
+ }
+
+ if (pos.x >= (int16)_hor || pos.y >= (int16)_ver || !_links[pos.x]) {
+ warning("getHyperlink: invalid range given");
+ return 0;
+ }
+
+ return _links[pos.x][pos.y];
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Selection::startSelection(const Point &pos) {
+ int tx, ty;
+
+ if (!_hor || !_ver) {
+ warning("startSelection: mask not initialized");
+ return;
+ }
+
+ tx = MIN(pos.x, (int16)_hor);
+ ty = MIN(pos.y, (int16)_ver);
+
+ _select.left = _last.x = tx;
+ _select.top = _last.y = ty;
+ _select.right = 0;
+ _select.bottom = 0;
+
+ g_vm->_windows->selectionChanged();
+}
+
+void Selection::moveSelection(const Point &pos) {
+ int tx, ty;
+
+ if (ABS(pos.x - _last.x) < 5 && ABS(pos.y - _last.y) < 5)
+ return;
+
+ if (!_hor || !_ver) {
+ warning("moveSelection: mask not initialized");
+ return;
+ }
+
+ tx = MIN(pos.x, (int16)_hor);
+ ty = MIN(pos.y, (int16)_ver);
+
+ _select.right = _last.x = tx;
+ _select.bottom = _last.y = ty;
+
+ g_vm->_windows->selectionChanged();
+}
+
+void Selection::clearSelection() {
+ if (!_select.isEmpty())
+ Windows::_forceRedraw = true;
+
+ _select = Rect();
+ g_vm->_windows->clearClaimSelect();
+}
+
+bool Selection::checkSelection(const Rect &r) const {
+ Rect select(MIN(_select.left, _select.right), MAX(_select.left, _select.right),
+ MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom));
+ if (select.isEmpty())
+ return false;
+
+ return select.intersects(r);
+}
+
+bool Selection::getSelection(const Rect &r, int *rx0, int *rx1) const {
+ uint row, upper, lower, above, below;
+ bool row_selected, found_left, found_right;
+ int from_right, from_below, is_above, is_below;
+ uint cx0, cx1, cy0, cy1;
+ uint x0 = r.left, y0 = r.top, x1 = r.right, y1 = r.bottom;
+
+ row = (y0 + y1) / 2;
+ upper = row - (row - y0) / 2;
+ lower = row + (y1 - row) / 2;
+ above = upper - (g_conf->_leading) / 2;
+ below = lower + (g_conf->_leading) / 2;
+
+ cx0 = MIN(_select.left, _select.right);
+ cx1 = MAX(_select.left, _select.right);
+ cy0 = MIN(_select.top, _select.bottom);
+ cy1 = MAX(_select.top, _select.bottom);
+
+ row_selected = false;
+
+ if ((cy0 >= upper && cy0 <= lower)
+ || (cy1 >= upper && cy1 <= lower))
+ row_selected = true;
+
+ if (row >= cy0 && row <= cy1)
+ row_selected = true;
+
+ if (!row_selected)
+ return false;
+
+ from_right = (_select.left != (int16)cx0);
+ from_below = (_select.top != (int16)cy0);
+ is_above = (above >= cy0 && above <= cy1);
+ is_below = (below >= cy0 && below <= cy1);
+
+ *rx0 = 0;
+ *rx1 = 0;
+
+ found_left = false;
+ found_right = false;
+
+ if (is_above && is_below) {
+ *rx0 = x0;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ } else if (!is_above && is_below) {
+ if (from_below) {
+ if (from_right) {
+ *rx0 = cx0;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx0 = cx1;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ }
+ } else {
+ if (from_right) {
+ *rx0 = cx1;
+ *rx1 = x1;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx1 = x1;
+ found_right = true;
+ }
+ }
+ } else if (is_above && !is_below) {
+ if (from_below) {
+ if (from_right) {
+ *rx0 = x0;
+ *rx1 = cx1;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx0 = x0;
+ *rx1 = cx0;
+ found_left = true;
+ found_right = true;
+ }
+ } else {
+ if (from_right) {
+ if (x0 > cx0)
+ return false;
+ *rx0 = x0;
+ *rx1 = cx0;
+ found_left = true;
+ found_right = true;
+ } else {
+ *rx0 = x0;
+ found_left = true;
+ }
+ }
+ }
+
+ if (found_left && found_right)
+ return true;
+
+ for (uint i = x0; i <= x1; i++) {
+ if (i >= cx0 && i <= cx1) {
+ if (!found_left) {
+ *rx0 = i;
+ found_left = true;
+ if (found_right)
+ return true;
+ } else {
+ if (!found_right)
+ *rx1 = i;
+ }
+ }
+ }
+
+ if (rx0 && !rx1)
+ *rx1 = x1;
+
+ return (rx0 && rx1);
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/selection.h b/engines/gargoyle/selection.h
new file mode 100644
index 0000000..bc56319
--- /dev/null
+++ b/engines/gargoyle/selection.h
@@ -0,0 +1,119 @@
+/* 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 GARGOYLE_SELECTION_H
+#define GARGOYLE_SELECTION_H
+
+#include "gargoyle/glk_types.h"
+#include "gargoyle/utils.h"
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace Gargoyle {
+
+enum ClipSource { PRIMARY = 0, CLIPBOARD = 1 };
+
+class Window;
+
+/**
+ * Acts as interface to and from the system's clipboard storage
+ */
+class Clipboard {
+private:
+ Common::Array<uint32> _text;
+public:
+ /**
+ * Makes a copy of selected text in preparation for the user copying it
+ * to the clpboard
+ */
+ void clipboardStore(const uint32 *text, size_t len);
+
+ /**
+ * Send previously designated text to the clipboard
+ */
+ void clipboardSend(ClipSource source);
+
+ /**
+ * Receive text from the clipboard, and paste it into the current window
+ */
+ void clipboardReceive(ClipSource source);
+};
+
+/**
+ * Manages hyperlinks for the screen
+ */
+class WindowMask {
+public:
+ size_t _hor, _ver;
+ glui32 **_links;
+ Rect _select;
+ Point _last;
+public:
+ /**
+ * Constructor
+ */
+ WindowMask();
+
+ /**
+ * Resize the links array
+ */
+ void resize(size_t x, size_t y);
+
+ void putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1);
+
+ glui32 getHyperlink(const Point &pos) const;
+};
+
+/**
+ * Overall manager for selecting areas on the screen, copying to/from the clipboard,
+ * and managing hyperlinks
+ */
+class Selection : public Clipboard, public WindowMask {
+public:
+ /**
+ * Start selecting an area of the screen
+ * @param pos Position to start selection area at
+ */
+ void startSelection(const Point &pos);
+
+ /**
+ * Move the end point of the selection area
+ * @param pos Position to end selection area at
+ */
+ void moveSelection(const Point &pos);
+
+ /**
+ * Remove any previously selected area
+ */
+ void clearSelection();
+
+ /**
+ * Checks whether the passed area intersects the selection area
+ */
+ bool checkSelection(const Rect &r) const;
+
+ bool getSelection(const Rect &r, int *rx0, int *rx1) const;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
index 3286876..a0d8b6d 100644
--- a/engines/gargoyle/window_graphics.cpp
+++ b/engines/gargoyle/window_graphics.cpp
@@ -147,7 +147,7 @@ void GraphicsWindow::eraseRect(bool whole, const Rect &box) {
hy1 = _bbox.top + y1;
/* zero out hyperlinks for these coordinates */
- g_vm->_windowMask->putHyperlink(0, hx0, hy0, hx1, hy1);
+ g_vm->_selection->putHyperlink(0, hx0, hy0, hx1, hy1);
_surface->fillRect(Rect(x0, y0, x1, y1), MKTAG(_bgnd[0], _bgnd[1], _bgnd[2], 0));
touch();
@@ -177,7 +177,7 @@ void GraphicsWindow::fillRect(glui32 color, const Rect &box) {
hy1 = _bbox.top + y1;
/* zero out hyperlinks for these coordinates */
- g_vm->_windowMask->putHyperlink(0, hx0, hy0, hx1, hy1);
+ g_vm->_selection->putHyperlink(0, hx0, hy0, hx1, hy1);
_surface->fillRect(Rect(x0, y0, x1, y1), MKTAG(col[0], col[1], col[2], 0));
touch();
@@ -229,7 +229,7 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
hy1 = _bbox.top + y1;
/* zero out or set hyperlink for these coordinates */
- g_vm->_windowMask->putHyperlink(linkval, hx0, hy0, hx1, hy1);
+ g_vm->_selection->putHyperlink(linkval, hx0, hy0, hx1, hy1);
w = sx1 - sx0;
h = sy1 - sy0;
@@ -259,7 +259,7 @@ void GraphicsWindow::click(const Point &newPos) {
}
if (_hyperRequest) {
- glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
+ glui32 linkval = g_vm->_selection->getHyperlink(newPos);
if (linkval) {
g_vm->_events->store(evtype_Hyperlink, this, linkval, 0);
_hyperRequest = false;
diff --git a/engines/gargoyle/window_mask.cpp b/engines/gargoyle/window_mask.cpp
deleted file mode 100644
index 495abc6..0000000
--- a/engines/gargoyle/window_mask.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/window_mask.h"
-#include "gargoyle/conf.h"
-#include "gargoyle/gargoyle.h"
-#include "gargoyle/windows.h"
-#include "common/system.h"
-
-namespace Gargoyle {
-
-WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) {
- _last.x = _last.y = 0;
- resize(g_system->getWidth(), g_system->getHeight());
-}
-
-void WindowMask::resize(size_t x, size_t y) {
- // Deallocate old storage
- for (size_t i = 0; i < _hor; i++) {
- if (_links[i])
- delete _links[i];
- }
-
- delete _links;
-
- _hor = x + 1;
- _ver = y + 1;
-
- // allocate new storage
- _links = new glui32 *[_hor];
- if (!_links) {
- warning("resize_mask: out of memory");
- _hor = _ver = 0;
- return;
- }
-
- for (size_t i = 0; i < _hor; i++) {
- _links[i] = new glui32[_ver];
- if (!_links[i]) {
- warning("resize_mask: could not allocate new memory");
- return;
- }
- }
-
- _select.left = 0;
- _select.top = 0;
- _select.right = 0;
- _select.bottom = 0;
-}
-
-void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1) {
- uint i, k;
- size_t tx0 = x0 < x1 ? x0 : x1;
- size_t tx1 = x0 < x1 ? x1 : x0;
- size_t ty0 = y0 < y1 ? y0 : y1;
- size_t ty1 = y0 < y1 ? y1 : y0;
-
- if (!_hor || !_ver) {
- warning("putHyperlink: struct not initialized");
- return;
- }
-
- if (tx0 >= _hor
- || tx1 >= _hor
- || ty0 >= _ver || ty1 >= _ver
- || !_links[tx0] || !_links[tx1]) {
- warning("putHyperlink: invalid range given");
- return;
- }
-
- for (i = tx0; i < tx1; i++) {
- for (k = ty0; k < ty1; k++)
- _links[i][k] = linkval;
- }
-}
-
-glui32 WindowMask::getHyperlink(const Point &pos) const {
- if (!_hor || !_ver) {
- warning("getHyperlink: struct not initialized");
- return 0;
- }
-
- if (pos.x >= (int16)_hor || pos.y >= (int16)_ver || !_links[pos.x]) {
- warning("getHyperlink: invalid range given");
- return 0;
- }
-
- return _links[pos.x][pos.y];
-}
-
-void WindowMask::startSelection(const Point &pos) {
- int tx, ty;
-
- if (!_hor || !_ver) {
- warning("startSelection: mask not initialized");
- return;
- }
-
- tx = MIN(pos.x, (int16)_hor);
- ty = MIN(pos.y, (int16)_ver);
-
- _select.left = _last.x = tx;
- _select.top = _last.y = ty;
- _select.right = 0;
- _select.bottom = 0;
-
- g_vm->_windows->selectionChanged();
-}
-
-void WindowMask::moveSelection(const Point &pos) {
- int tx, ty;
-
- if (ABS(pos.x - _last.x) < 5 && ABS(pos.y - _last.y) < 5)
- return;
-
- if (!_hor || !_ver) {
- warning("moveSelection: mask not initialized");
- return;
- }
-
- tx = MIN(pos.x, (int16)_hor);
- ty = MIN(pos.y, (int16)_ver);
-
- _select.right = _last.x = tx;
- _select.bottom = _last.y = ty;
-
- g_vm->_windows->selectionChanged();
-}
-
-void WindowMask::clearSelection() {
- if (!_select.isEmpty())
- Windows::_forceRedraw = true;
-
- _select = Rect();
- g_vm->_windows->clearClaimSelect();
-}
-
-bool WindowMask::checkSelection(const Rect &r) const {
- Rect select(MIN(_select.left, _select.right), MAX(_select.left, _select.right),
- MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom));
- if (select.isEmpty())
- return false;
-
- return select.intersects(r);
-}
-
-bool WindowMask::getSelection(const Rect &r, int *rx0, int *rx1) const {
- uint row, upper, lower, above, below;
- bool row_selected, found_left, found_right;
- int from_right, from_below, is_above, is_below;
- uint cx0, cx1, cy0, cy1;
- uint x0 = r.left, y0 = r.top, x1 = r.right, y1 = r.bottom;
-
- row = (y0 + y1) / 2;
- upper = row - (row - y0) / 2;
- lower = row + (y1 - row) / 2;
- above = upper - (g_conf->_leading) / 2;
- below = lower + (g_conf->_leading) / 2;
-
- cx0 = MIN(_select.left, _select.right);
- cx1 = MAX(_select.left, _select.right);
- cy0 = MIN(_select.top, _select.bottom);
- cy1 = MAX(_select.top, _select.bottom);
-
- row_selected = false;
-
- if ((cy0 >= upper && cy0 <= lower)
- || (cy1 >= upper && cy1 <= lower))
- row_selected = true;
-
- if (row >= cy0 && row <= cy1)
- row_selected = true;
-
- if (!row_selected)
- return false;
-
- from_right = (_select.left != (int16)cx0);
- from_below = (_select.top != (int16)cy0);
- is_above = (above >= cy0 && above <= cy1);
- is_below = (below >= cy0 && below <= cy1);
-
- *rx0 = 0;
- *rx1 = 0;
-
- found_left = false;
- found_right = false;
-
- if (is_above && is_below) {
- *rx0 = x0;
- *rx1 = x1;
- found_left = true;
- found_right = true;
- } else if (!is_above && is_below) {
- if (from_below) {
- if (from_right) {
- *rx0 = cx0;
- *rx1 = x1;
- found_left = true;
- found_right = true;
- } else {
- *rx0 = cx1;
- *rx1 = x1;
- found_left = true;
- found_right = true;
- }
- } else {
- if (from_right) {
- *rx0 = cx1;
- *rx1 = x1;
- found_left = true;
- found_right = true;
- } else {
- *rx1 = x1;
- found_right = true;
- }
- }
- } else if (is_above && !is_below) {
- if (from_below) {
- if (from_right) {
- *rx0 = x0;
- *rx1 = cx1;
- found_left = true;
- found_right = true;
- } else {
- *rx0 = x0;
- *rx1 = cx0;
- found_left = true;
- found_right = true;
- }
- } else {
- if (from_right) {
- if (x0 > cx0)
- return false;
- *rx0 = x0;
- *rx1 = cx0;
- found_left = true;
- found_right = true;
- } else {
- *rx0 = x0;
- found_left = true;
- }
- }
- }
-
- if (found_left && found_right)
- return true;
-
- for (uint i = x0; i <= x1; i++) {
- if (i >= cx0 && i <= cx1) {
- if (!found_left) {
- *rx0 = i;
- found_left = true;
- if (found_right)
- return true;
- } else {
- if (!found_right)
- *rx1 = i;
- }
- }
- }
-
- if (rx0 && !rx1)
- *rx1 = x1;
-
- return (rx0 && rx1);
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_mask.h b/engines/gargoyle/window_mask.h
deleted file mode 100644
index 502ed49..0000000
--- a/engines/gargoyle/window_mask.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* 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 GARGOYLE_WINDOW_MASK_H
-#define GARGOYLE_WINDOW_MASK_H
-
-#include "common/rect.h"
-#include "gargoyle/glk_types.h"
-#include "gargoyle/utils.h"
-
-namespace Gargoyle {
-
-class Window;
-
-class WindowMask {
-public:
- size_t _hor, _ver;
- glui32 **_links;
- Rect _select;
- Point _last;
-public:
- /**
- * Constructor
- */
- WindowMask();
-
- /**
- * Resize the links array
- */
- void resize(size_t x, size_t y);
-
- void putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1);
-
- glui32 getHyperlink(const Point &pos) const;
-
- /**
- * Start selecting an area of the screen
- * @param pos Position to start selection area at
- */
- void startSelection(const Point &pos);
-
- /**
- * Move the end point of the selection area
- * @param pos Position to end selection area at
- */
- void moveSelection(const Point &pos);
-
- /**
- * Remove any previously selected area
- */
- void clearSelection();
-
- /**
- * Checks whether the passed area intersects the selection area
- */
- bool checkSelection(const Rect &r) const;
-
- bool getSelection(const Rect &r, int *rx0, int *rx1) const;
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index c6dde5b..a7e5365 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -21,10 +21,10 @@
*/
#include "gargoyle/window_text_buffer.h"
-#include "gargoyle/clipboard.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/screen.h"
+#include "gargoyle/selection.h"
#include "gargoyle/unicode.h"
namespace Gargoyle {
@@ -232,7 +232,7 @@ void TextBufferWindow::reflow() {
}
void TextBufferWindow::touchScroll() {
- g_vm->_windowMask->clearSelection();
+ g_vm->_selection->clearSelection();
_windows->repaint(_bbox);
for (int i = 0; i < _scrollMax; i++)
@@ -364,7 +364,7 @@ void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldle
void TextBufferWindow::touch(int line) {
_lines[line]._dirty = true;
- g_vm->_windowMask->clearSelection();
+ g_vm->_selection->clearSelection();
int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
_windows->repaint(Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
@@ -572,7 +572,7 @@ void TextBufferWindow::click(const Point &newPos) {
_windows->setFocus(this);
if (_hyperRequest) {
- glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
+ glui32 linkval = g_vm->_selection->getHyperlink(newPos);
if (linkval) {
g_vm->_events->store(evtype_Hyperlink, this, linkval, 0);
_hyperRequest = false;
@@ -596,7 +596,7 @@ void TextBufferWindow::click(const Point &newPos) {
if (!gh && !gs) {
g_vm->_copySelect = true;
- g_vm->_windowMask->startSelection(newPos);
+ g_vm->_selection->startSelection(newPos);
}
}
@@ -815,7 +815,7 @@ void TextBufferWindow::redraw() {
pw = x1 - x0 - 2 * GLI_SUBPIX;
// check if any part of buffer is selected
- selBuf = g_vm->_windowMask->checkSelection(Rect(x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1));
+ selBuf = g_vm->_selection->checkSelection(Rect(x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1));
for (i = _scrollPos + _height - 1; i >= _scrollPos; i--) {
// top of line
@@ -823,7 +823,7 @@ void TextBufferWindow::redraw() {
// check if part of line is selected
if (selBuf) {
- selrow = g_vm->_windowMask->getSelection(Rect(x0 / GLI_SUBPIX, y,
+ selrow = g_vm->_selection->getSelection(Rect(x0 / GLI_SUBPIX, y,
x1 / GLI_SUBPIX, y + g_conf->_leading), &sx0, &sx1);
selleft = (sx0 == x0/GLI_SUBPIX);
selright = (sx1 == x1/GLI_SUBPIX);
@@ -947,7 +947,7 @@ void TextBufferWindow::redraw() {
}
// clear any stored hyperlink coordinates
- g_vm->_windowMask->putHyperlink(0, x0/GLI_SUBPIX, y,
+ g_vm->_selection->putHyperlink(0, x0/GLI_SUBPIX, y,
x1/GLI_SUBPIX, y + g_conf->_leading);
/*
@@ -970,7 +970,7 @@ void TextBufferWindow::redraw() {
if (link) {
screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
w / GLI_SUBPIX + 1, g_conf->_linkStyle), g_conf->_linkColor);
- g_vm->_windowMask->putHyperlink(link, x/GLI_SUBPIX, y,
+ g_vm->_selection->putHyperlink(link, x/GLI_SUBPIX, y,
x/GLI_SUBPIX + w/GLI_SUBPIX,
y + g_conf->_leading);
}
@@ -986,7 +986,7 @@ void TextBufferWindow::redraw() {
if (link) {
screen.fillRect(Rect::fromXYWH(x / GLI_SUBPIX + 1, y + g_conf->_baseLine + 1,
w/GLI_SUBPIX + 1, g_conf->_linkStyle), g_conf->_linkColor);
- g_vm->_windowMask->putHyperlink(link, x / GLI_SUBPIX, y,
+ g_vm->_selection->putHyperlink(link, x / GLI_SUBPIX, y,
x / GLI_SUBPIX + w / GLI_SUBPIX,
y + g_conf->_leading);
}
@@ -1034,7 +1034,7 @@ void TextBufferWindow::redraw() {
x = x0 + SLOP;
y = y0 + (_height - 1) * g_conf->_leading;
- g_vm->_windowMask->putHyperlink(0, x0/GLI_SUBPIX, y,
+ g_vm->_selection->putHyperlink(0, x0/GLI_SUBPIX, y,
x1/GLI_SUBPIX, y + g_conf->_leading);
color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
@@ -1080,7 +1080,7 @@ void TextBufferWindow::redraw() {
hx1 = x0/GLI_SUBPIX + ln->_lPic->w < x1/GLI_SUBPIX
? x0/GLI_SUBPIX + ln->_lPic->w
: x1/GLI_SUBPIX;
- g_vm->_windowMask->putHyperlink(link, hx0, hy0, hx1, hy1);
+ g_vm->_selection->putHyperlink(link, hx0, hy0, hx1, hy1);
}
}
@@ -1095,7 +1095,7 @@ void TextBufferWindow::redraw() {
? x1/GLI_SUBPIX - ln->_rPic->w
: x0/GLI_SUBPIX;
hx1 = x1/GLI_SUBPIX;
- g_vm->_windowMask->putHyperlink(link, hx0, hy0, hx1, hy1);
+ g_vm->_selection->putHyperlink(link, hx0, hy0, hx1, hy1);
}
}
}
@@ -1114,7 +1114,7 @@ void TextBufferWindow::redraw() {
y0 = _bbox.top + g_conf->_tMarginY;
y1 = _bbox.bottom - g_conf->_tMarginY;
- g_vm->_windowMask->putHyperlink(0, x0, y0, x1, y1);
+ g_vm->_selection->putHyperlink(0, x0, y0, x1, y1);
y0 += g_conf->_scrollWidth / 2;
y1 -= g_conf->_scrollWidth / 2;
@@ -1144,7 +1144,7 @@ void TextBufferWindow::redraw() {
if (selBuf && _copyPos) {
Windows::_claimSelect = true;
- g_vm->_clipboard->store(_copyBuf, _copyPos);
+ g_vm->_clipboard->clipboardStore(_copyBuf, _copyPos);
for (i = 0; i < _copyPos; i++)
_copyBuf[i] = 0;
_copyPos = 0;
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
index 351d9fb..1e5e41d 100644
--- a/engines/gargoyle/window_text_grid.cpp
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -23,8 +23,8 @@
#include "gargoyle/window_text_grid.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/selection.h"
#include "gargoyle/screen.h"
-#include "gargoyle/window_mask.h"
namespace Gargoyle {
@@ -204,7 +204,7 @@ void TextGridWindow::click(const Point &newPos) {
}
if (_hyperRequest) {
- glui32 linkval = g_vm->_windowMask->getHyperlink(newPos);
+ glui32 linkval = g_vm->_selection->getHyperlink(newPos);
if (linkval)
{
g_vm->_events->store(evtype_Hyperlink, this, linkval, 0);
@@ -592,7 +592,7 @@ void TextGridWindow::redraw() {
y = y0 + i * g_conf->_leading;
// clear any stored hyperlink coordinates
- g_vm->_windowMask->putHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
+ g_vm->_selection->putHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
a = 0;
for (b = 0; b < _width; b++) {
@@ -612,7 +612,7 @@ void TextGridWindow::redraw() {
if (link) {
screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w,
g_conf->_linkStyle), g_conf->_linkColor);
- g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ g_vm->_selection->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
x += w;
@@ -634,7 +634,7 @@ void TextGridWindow::redraw() {
if (link) {
screen.fillRect(Rect::fromXYWH(x, y + g_conf->_baseLine + 1, w, g_conf->_linkStyle),
g_conf->_linkColor);
- g_vm->_windowMask->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ g_vm->_selection->putHyperlink(link, x, y, x + w, y + g_conf->_leading);
}
}
}
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 5830c7c..0e4020b 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -30,8 +30,8 @@
#include "gargoyle/events.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
+#include "gargoyle/selection.h"
#include "gargoyle/streams.h"
-#include "gargoyle/window_mask.h"
namespace Gargoyle {
Commit: 3c2fd3e74f9a205109ab9b57c5af893011560452
https://github.com/scummvm/scummvm/commit/3c2fd3e74f9a205109ab9b57c5af893011560452
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add copying to clipboard
Changed paths:
engines/gargoyle/selection.cpp
engines/gargoyle/selection.h
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/selection.cpp b/engines/gargoyle/selection.cpp
index 2b72c1e..8ad3b76 100644
--- a/engines/gargoyle/selection.cpp
+++ b/engines/gargoyle/selection.cpp
@@ -28,23 +28,32 @@
namespace Gargoyle {
-void Clipboard::clipboardStore(const uint32 *text, size_t len) {
- // TODO
+void Clipboard::clipboardStore(const Common::U32String &text) {
+ _text = text;
}
void Clipboard::clipboardSend(ClipSource source) {
- // TODO
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) {
+ // Convert unicode string to standard string, since that's all ScummVM supports
+ Common::String text;
+ for (uint idx = 0; idx < _text.size(); ++idx)
+ text += (_text[idx] <= 0x7f) ? (char)_text[idx] : '?';
+
+ g_system->setTextInClipboard(text);
+ }
}
void Clipboard::clipboardReceive(ClipSource source) {
- Windows &windows = *g_vm->_windows;
-
- if (g_system->hasTextInClipboard()) {
- Common::String text = g_system->getTextFromClipboard();
- for (uint idx = 0; idx < text.size(); ++idx) {
- uint c = text[idx];
- if (c != '\r' && c != '\n' && c != '\b' && c != '\t')
- windows.inputHandleKey(c);
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) {
+ Windows &windows = *g_vm->_windows;
+
+ if (g_system->hasTextInClipboard()) {
+ Common::String text = g_system->getTextFromClipboard();
+ for (uint idx = 0; idx < text.size(); ++idx) {
+ uint c = text[idx];
+ if (c != '\r' && c != '\n' && c != '\b' && c != '\t')
+ windows.inputHandleKey(c);
+ }
}
}
}
diff --git a/engines/gargoyle/selection.h b/engines/gargoyle/selection.h
index bc56319..2d3a208 100644
--- a/engines/gargoyle/selection.h
+++ b/engines/gargoyle/selection.h
@@ -27,6 +27,7 @@
#include "gargoyle/utils.h"
#include "common/array.h"
#include "common/rect.h"
+#include "common/ustr.h"
namespace Gargoyle {
@@ -39,13 +40,13 @@ class Window;
*/
class Clipboard {
private:
- Common::Array<uint32> _text;
+ Common::U32String _text;
public:
/**
* Makes a copy of selected text in preparation for the user copying it
* to the clpboard
*/
- void clipboardStore(const uint32 *text, size_t len);
+ void clipboardStore(const Common::U32String &text);
/**
* Send previously designated text to the clipboard
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index a7e5365..7e65059 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -1140,11 +1140,11 @@ void TextBufferWindow::redraw() {
}
}
- // send selected text to clipboard
+ // Keep track of selected text to be ready when user copies it to the clipboard
if (selBuf && _copyPos) {
Windows::_claimSelect = true;
- g_vm->_clipboard->clipboardStore(_copyBuf, _copyPos);
+ g_vm->_clipboard->clipboardStore(Common::U32String(_copyBuf, _copyPos));
for (i = 0; i < _copyPos; i++)
_copyBuf[i] = 0;
_copyPos = 0;
Commit: 7cba554fc5ea46c3a6bbe23e073de16914d7895f
https://github.com/scummvm/scummvm/commit/7cba554fc5ea46c3a6bbe23e073de16914d7895f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Don't leading & baseline for fonts go below minimum size
Changed paths:
engines/gargoyle/fonts.cpp
engines/gargoyle/fonts.h
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
index 857ef15..9c07412 100644
--- a/engines/gargoyle/fonts.cpp
+++ b/engines/gargoyle/fonts.cpp
@@ -38,11 +38,14 @@ Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface), _fontsMissi
if (!loadFonts())
error("Could not load data file");
- if (!g_conf->_leading)
- g_conf->_leading = g_conf->_propSize + 2;
- if (!g_conf->_baseLine)
- g_conf->_baseLine = g_conf->_propSize + 0.5;
-
+ // TODO: See if there's any better way for getting the leading and baseline
+ Common::Rect r1 = _fontTable[7]->getBoundingBox('o');
+ Common::Rect r2 = _fontTable[7]->getBoundingBox('y');
+ double baseLine = (double)r1.bottom;
+ double leading = (double)r2.bottom + 2;
+
+ g_conf->_leading = MAX((double)g_conf->_leading, leading);
+ g_conf->_baseLine = MAX((double)g_conf->_baseLine, baseLine);
g_conf->_cellW = _fontTable[0]->getStringWidth("0");
g_conf->_cellH = g_conf->_leading;
}
@@ -142,13 +145,11 @@ int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const C
}
size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
- // TODO: Handle spw
const Graphics::Font *font = _fontTable[fontIdx];
return font->getStringWidth(text) * GLI_SUBPIX;
}
size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
- // TODO: Handle spw
const Graphics::Font *font = _fontTable[fontIdx];
return font->getStringWidth(text) * GLI_SUBPIX;
}
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index 2f2cb41..1437bd8 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -98,19 +98,19 @@ public:
* Get the width in pixels of a string
* @param fontIdx Which font to use
* @param text Text to get the width of
- * @param spw ???
+ * @param spw Delta X
* @returns Width of string multiplied by GLI_SUBPIX
*/
- size_t stringWidth(int fontIdx, const Common::String &text, int spw = -1);
+ size_t stringWidth(int fontIdx, const Common::String &text, int spw = 0);
/**
* Get the width in pixels of a unicode string
* @param fontIdx Which font to use
* @param text Text to get the width of
- * @param spw ???
+ * @param spw Delta X
* @returns Width of string multiplied by GLI_SUBPIX
*/
- size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = -1);
+ size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = 0);
};
} // End of namespace Gargoyle
Commit: e208e147960ef820f73999026ab692db25fe2bcd
https://github.com/scummvm/scummvm/commit/e208e147960ef820f73999026ab692db25fe2bcd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Get proper baseline and leading from loaded fonts
Changed paths:
engines/gargoyle/conf.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index ae67a8a..21f245a 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -79,7 +79,7 @@ Conf::Conf() {
get("morealign", _moreAlign);
get("monoaspect", _monoAspect, 1.0);
get("propaspect", _propAspect, 1.0);
- get("monosize", _monoSize, 8);
+ get("monosize", _monoSize, 11);
get("monor", _monoR);
get("monob", _monoR);
get("monoi", _monoI);
Commit: f73d56f6bab4ca2642790cb8429b9fee3d5d2006
https://github.com/scummvm/scummvm/commit/f73d56f6bab4ca2642790cb8429b9fee3d5d2006
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Setup default font colors to match garglk defaults
Changed paths:
engines/gargoyle/conf.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 21f245a..98af236 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -43,23 +43,23 @@ WindowStyle T_STYLES[style_NUMSTYLES] = {
{ PROPZ,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
{ PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
{ PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
+ { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x60,0x00 }, 0 }, ///< Input
{ MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User1
{ MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User2
};
WindowStyle G_STYLES[style_NUMSTYLES] = {
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
- { MONOI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
- { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
- { MONOB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Input
- { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User1
- { MONOR,{ 0x60,0x60,0x60 },{ 0xff,0xff,0xff }, 0 }, ///< User2
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Normal
+ { MONOI,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Emphasized
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Preformatted
+ { MONOB,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Header
+ { MONOB,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Subheader
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Alert
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Note
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< BlockQuote
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Input
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< User1
+ { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< User2
};
Conf *g_conf;
Commit: 671321c45fb52163022b51e4e128a02ec66dc28d
https://github.com/scummvm/scummvm/commit/671321c45fb52163022b51e4e128a02ec66dc28d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix loading of font colors and styles from configuration
Changed paths:
engines/gargoyle/conf.cpp
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 98af236..7add133 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -156,47 +156,44 @@ Conf::Conf() {
Common::copy(G_STYLES, G_STYLES + style_NUMSTYLES, _gStyles);
char buffer[255];
- const char *const TG_COLOR[2] = { "tcolor", "gcolor" };
- for (int idx = 0; idx < 2; ++idx) {
- if (!ConfMan.hasKey(TG_COLOR[idx]))
- continue;
-
- strncpy(buffer, ConfMan.get(TG_COLOR[idx]).c_str(), 254);
- buffer[255] = '\0';
- char *style = strtok(buffer, "\r\n\t ");
- char *fg = strtok(nullptr, "\r\n\t ");
- char *bg = strtok(nullptr, "\r\n\t ");
-
- int i = atoi(style);
- if (i < 0 || i >= style_NUMSTYLES)
- continue;
-
- if (idx == 0) {
- parseColor(fg, _tStyles[i].fg);
- parseColor(bg, _tStyles[i].bg);
- } else {
- parseColor(fg, _gStyles[i].fg);
- parseColor(bg, _gStyles[i].bg);
+ const char *const TG_COLOR[2] = { "tcolor_%d", "gcolor_%d" };
+ for (int tg = 0; tg < 2; ++tg) {
+ for (int style = 0; style <= 10; ++style) {
+ Common::String key = Common::String::format(TG_COLOR[tg], style);
+ if (!ConfMan.hasKey(key))
+ continue;
+
+ strncpy(buffer, ConfMan.get(key).c_str(), 254);
+ buffer[255] = '\0';
+ char *fg = strtok(buffer, "\r\n\t ");
+ char *bg = strtok(nullptr, "\r\n\t ");
+
+ if (tg == 0) {
+ parseColor(fg, _tStyles[style].fg);
+ parseColor(bg, _tStyles[style].bg);
+ } else {
+ parseColor(fg, _gStyles[style].fg);
+ parseColor(bg, _gStyles[style].bg);
+ }
}
}
- const char *const TG_FONT[2] = { "tfont", "gfont" };
- for (int idx = 0; idx < 2; ++idx) {
- if (!ConfMan.hasKey(TG_FONT[idx]))
- continue;
-
- strncpy(buffer, ConfMan.get(TG_FONT[idx]).c_str(), 254);
- buffer[255] = '\0';
- char *style = strtok(buffer, "\r\n\t ");
- char *font = strtok(nullptr, "\r\n\t ");
- int i = atoi(style);
- if (i < 0 || i >= style_NUMSTYLES)
- continue;
-
- if (idx == 0)
- _tStyles[i].font = Fonts::getId(font);
- else
- _gStyles[i].font = Fonts::getId(font);
+ const char *const TG_FONT[2] = { "tfont_%d", "gfont_%d" };
+ for (int tg = 0; tg < 2; ++tg) {
+ for (int style = 0; style <= 10; ++style) {
+ Common::String key = Common::String::format(TG_FONT[tg], style);
+ if (!ConfMan.hasKey(key))
+ continue;
+
+ strncpy(buffer, ConfMan.get(key).c_str(), 254);
+ buffer[255] = '\0';
+ char *font = strtok(buffer, "\r\n\t ");
+
+ if (tg == 0)
+ _tStyles[style].font = Fonts::getId(font);
+ else
+ _gStyles[style].font = Fonts::getId(font);
+ }
}
Common::copy(_tStyles, _tStyles + style_NUMSTYLES, _tStylesDefault);
Commit: 43bee7a72783cd60b86249997bfdaf7af5e5d740
https://github.com/scummvm/scummvm/commit/43bee7a72783cd60b86249997bfdaf7af5e5d740
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add GUI options to default detection entry
Changed paths:
engines/gargoyle/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 295e50b..af7cfc6 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -243,6 +243,7 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
gameDescription._desc.gameId = gameId;
gameDescription._desc.language = gd.language;
gameDescription._desc.platform = gd.platform;
+ gameDescription._desc.guiOptions = GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES);
gameDescription._filename = filename;
gameDescription._md5 = Common::computeStreamMD5AsString(f, 5000);
Commit: 601e1d486b038f121323e78ed68a154d6763c9f1
https://github.com/scummvm/scummvm/commit/601e1d486b038f121323e78ed68a154d6763c9f1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add GLK timer intervals
Changed paths:
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/glk.cpp
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index bc56407..520b6f2 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -53,8 +53,8 @@ const byte ARROW[] = {
4, 2, 5, 5
};
-Events::Events() : _forceClick(false), _currentEvent(nullptr), _timeouts(false),
- _priorFrameTime(0), _frameCounter(0), _cursorId(CURSOR_NONE) {
+Events::Events() : _forceClick(false), _currentEvent(nullptr), _cursorId(CURSOR_NONE),
+ _timerMilli(0), _timerTimeExpiry(0), _priorFrameTime(0), _frameCounter(0) {
initializeCursors();
}
@@ -118,7 +118,7 @@ void Events::getEvent(event_t *event, bool polled) {
dispatchEvent(*_currentEvent, polled);
if (!polled) {
- while (!g_vm->shouldQuit() && _currentEvent->type == evtype_None && !_timeouts) {
+ while (!g_vm->shouldQuit() && _currentEvent->type == evtype_None && !isTimerExpired()) {
pollEvents();
g_system->delayMillis(10);
@@ -129,10 +129,11 @@ void Events::getEvent(event_t *event, bool polled) {
_currentEvent->type = evtype_Quit;
}
- if (_currentEvent->type == evtype_None && _timeouts) {
+ if (_currentEvent->type == evtype_None && isTimerExpired()) {
store(evtype_Timer, nullptr, 0, 0);
dispatchEvent(*_currentEvent, polled);
- _timeouts = false;
+
+ _timerTimeExpiry = g_system->getMillis() + _timerMilli;
}
_currentEvent = nullptr;
@@ -338,4 +339,13 @@ void Events::setCursor(CursorId cursorId) {
}
}
+void Events::setTimerInterval(uint milli) {
+ _timerMilli = milli;
+ _timerTimeExpiry = g_system->getMillis() + milli;
+}
+
+bool Events::isTimerExpired() const {
+ return _timerMilli && g_system->getMillis() >= _timerTimeExpiry;
+}
+
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index 5da4e53..f91c91b 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -164,12 +164,13 @@ private:
EventQueue _eventsPolled; ///< User generated events
EventQueue _eventsLogged; ///< Custom events generated by game code
Event *_currentEvent; ///< Event pointer passed during event retrieval
- bool _timeouts; ///< Timer timeouts flag
uint32 _priorFrameTime; ///< Time of prior game frame
uint32 _frameCounter; ///< Frame counter
bool _redraw; ///< Screen needed redrawing
CursorId _cursorId; ///< Current cursor Id
Surface _cursors[4]; ///< Cursor pixel data
+ uint _timerMilli; ///< Time in milliseconds between timer events
+ uint _timerTimeExpiry; ///< When to trigger next timer event
private:
/**
* Initialize the cursor graphics
@@ -262,6 +263,17 @@ public:
* Sets the current cursor
*/
void setCursor(CursorId cursorId);
+
+ /**
+ * Set a timer interval
+ * @param milli Time in millieseconds for intervals, or 0 for off
+ */
+ void setTimerInterval(uint milli);
+
+ /**
+ * Returns true if it's time for a timer event
+ */
+ bool isTimerExpired() const;
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 43b6d0a..fe82edc 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -709,7 +709,7 @@ void Glk::glk_select_poll(event_t *event) {
}
void Glk::glk_request_timer_events(glui32 millisecs) {
- // TODO
+ _events->setTimerInterval(millisecs);
}
void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
Commit: 4bd3a4a9c692fcbc13a13eb86ec44c51a715d325
https://github.com/scummvm/scummvm/commit/4bd3a4a9c692fcbc13a13eb86ec44c51a715d325
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Cleanup of glk_gestalt_ext switch
Changed paths:
engines/gargoyle/glk.cpp
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index fe82edc..d815242 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -116,9 +116,6 @@ glui32 Glk::glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen) {
return true;
return false;
- case gestalt_Timer:
- return true;
-
case gestalt_Graphics:
case gestalt_GraphicsTransparency:
return g_conf->_graphics;
@@ -136,32 +133,21 @@ glui32 Glk::glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen) {
case gestalt_SoundNotify:
return g_conf->_sound;
- case gestalt_Sound2:
- return false;
+ case gestalt_LineTerminatorKey:
+ return Window::checkTerminator(val);
+ case gestalt_Timer:
case gestalt_Unicode:
- return true;
case gestalt_UnicodeNorm:
- return true;
-
case gestalt_Hyperlinks:
- return true;
case gestalt_HyperlinkInput:
- return true;
-
case gestalt_LineInputEcho:
- return true;
case gestalt_LineTerminators:
- return true;
- case gestalt_LineTerminatorKey:
- return Window::checkTerminator(val);
-
case gestalt_DateTime:
- return true;
-
case gestalt_GarglkText:
return true;
+ case gestalt_Sound2:
default:
return false;
}
Commit: c524c5859e7b92b189a6ee0475f0856a71441c3a
https://github.com/scummvm/scummvm/commit/c524c5859e7b92b189a6ee0475f0856a71441c3a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add garglk_unput_string methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index d815242..8beca88 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -1115,39 +1115,36 @@ glsi32 Glk::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor)
/* XXX non-official Glk functions that may or may not exist */
-char *garglk_fileref_get_name(frefid_t fref) {
- // TODO
- return nullptr;
+const char *Glk::garglk_fileref_get_name(frefid_t fref) const {
+ return fref->_filename.c_str();
}
void Glk::garglk_set_program_name(const char *name) {
- // TODO
+ // Program name isn't displayed
}
void Glk::garglk_set_program_info(const char *info) {
- // TODO
+ // Program info isn't displayed
}
void Glk::garglk_set_story_name(const char *name) {
- // TODO
+ // Story name isn't displayed
}
void Glk::garglk_set_story_title(const char *title) {
- // TODO
+ // Story title isn't displayed
}
void Glk::garglk_set_config(const char *name) {
- // TODO
+ // No implementation
}
-/* garglk_unput_string - removes the specified string from the end of the output buffer, if
-* indeed it is there. */
-void Glk::garglk_unput_string(char *str) {
- // TODO
+void Glk::garglk_unput_string(const char *str) {
+ _streams->getCurrent()->unputBuffer(str, strlen(str));
}
-void Glk::garglk_unput_string_uni(glui32 *str) {
- // TODO
+void Glk::garglk_unput_string_uni(const glui32 *str) {
+ _streams->getCurrent()->unputBufferUni(str, strlen_uni(str));
}
void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 7312a35..eb3e68d 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -260,7 +260,7 @@ public:
/* XXX non-official Glk functions that may or may not exist */
#define GARGLK 1
- char* garglk_fileref_get_name(frefid_t fref);
+ const char *garglk_fileref_get_name(frefid_t fref) const;
void garglk_set_program_name(const char *name);
void garglk_set_program_info(const char *info);
@@ -268,10 +268,17 @@ public:
void garglk_set_story_title(const char *title);
void garglk_set_config(const char *name);
- /* garglk_unput_string - removes the specified string from the end of the output buffer, if
- * indeed it is there. */
- void garglk_unput_string(char *str);
- void garglk_unput_string_uni(glui32 *str);
+ /**
+ * Removes the specified string from the end of the output buffer, if
+ * indeed it is there.
+ */
+ void garglk_unput_string(const char *str);
+
+ /**
+ * Removes the specified string from the end of the output buffer, if
+ * indeed it is there.
+ */
+ void garglk_unput_string_uni(const glui32 *str);
void garglk_set_zcolors(glui32 fg, glui32 bg);
void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 24917c5..0f95984 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -147,6 +147,59 @@ void WindowStream::putBufferUni(const uint32 *buf, size_t len) {
_window->_echoStream->putBufferUni(buf, len);
}
+void WindowStream::unputBuffer(const char *buf, size_t len) {
+ glui32 lx;
+ const char *cx;
+
+ if (!_writable)
+ return;
+
+ if (_window->_lineRequest || _window->_lineRequestUni) {
+ if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
+ _window->cancelLineEvent(nullptr);
+ g_vm->_events->_forceClick = false;
+ } else {
+ warning("unput_buffer: window has pending line request");
+ return;
+ }
+ }
+
+ for (lx = 0, cx = buf + len - 1; lx<len; lx++, cx--) {
+ if (!_window->unputCharUni(*cx))
+ break;
+ _writeCount--;
+ }
+ if (_window->_echoStream)
+ _window->_echoStream->unputBuffer(buf, len);
+}
+
+void WindowStream::unputBufferUni(const glui32 *buf, size_t len) {
+ glui32 lx;
+ const glui32 *cx;
+
+ if (!_writable)
+ return;
+
+ if (_window->_lineRequest || _window->_lineRequestUni) {
+ if (g_conf->_safeClicks && g_vm->_events->_forceClick) {
+ _window->cancelLineEvent(nullptr);
+ g_vm->_events->_forceClick = false;
+ } else {
+ warning("unput_buffer: window has pending line request");
+ return;
+ }
+ }
+
+ for (lx = 0, cx = buf + len - 1; lx<len; lx++, cx--) {
+ if (!_window->unputCharUni(*cx))
+ break;
+ _writeCount--;
+ }
+
+ if (_window->_echoStream)
+ _window->_echoStream->unputBufferUni(buf, len);
+}
+
void WindowStream::setStyle(glui32 val) {
if (!_writable)
return;
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 16f63db..02e2f3b 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -192,6 +192,16 @@ public:
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) {
@@ -288,6 +298,16 @@ public:
*/
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;
/**
Commit: df8dec156efa70bb5bda1f6ef6d255c22688d952
https://github.com/scummvm/scummvm/commit/df8dec156efa70bb5bda1f6ef6d255c22688d952
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add garglk_set_zcolors methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/glk_types.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 8beca88..6022a86 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -1148,11 +1148,15 @@ void Glk::garglk_unput_string_uni(const glui32 *str) {
}
void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
- // TODO
+ _streams->getCurrent()->setZColors(fg, bg);
}
void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
- // TODO
+ if (str) {
+ str->setZColors(fg, bg);
+ } else {
+ warning("set_style_stream: Invalid ref");
+ }
}
void Glk::garglk_set_reversevideo(glui32 reverse) {
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 6ea4408..6dd8504 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -179,6 +179,13 @@ enum giDisp {
gidisp_Class_Schannel = 3,
};
+enum zcolor {
+ zcolor_Transparent = (uint32)-4,
+ zcolor_Cursor = (uint32)-3,
+ zcolor_Current = (uint32)-2,
+ zcolor_Default = (uint32)-1
+};
+
#ifdef GLK_MODULE_IMAGE
enum ImageAlign {
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 0f95984..9d257f2 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -63,6 +63,11 @@ void Stream::close(StreamResult *result) {
delete this;
}
+void Stream::setZColors(glui32 fg, glui32 bg) {
+ if (_writable && g_conf->_styleHint)
+ Windows::_forceRedraw = true;
+}
+
/*--------------------------------------------------------------------------*/
void WindowStream::close(StreamResult *result) {
@@ -217,6 +222,67 @@ void WindowStream::setHyperlink(glui32 linkVal) {
_window->_attr.hyper = linkVal;
}
+void WindowStream::setZColors(glui32 fg, glui32 bg) {
+ if (!_writable || !g_conf->_styleHint)
+ return;
+
+ byte fore[3], back[3];
+ fore[0] = (fg >> 16) & 0xff;
+ fore[1] = (fg >> 8) & 0xff;
+ fore[2] = (fg) & 0xff;
+ back[0] = (bg >> 16) & 0xff;
+ back[1] = (bg >> 8) & 0xff;
+ back[2] = (bg) & 0xff;
+
+ if (fg != zcolor_Transparent && fg != zcolor_Cursor) {
+ if (fg == zcolor_Default) {
+ _window->_attr.fgset = 0;
+ _window->_attr.fgcolor = 0;
+ Windows::_overrideFgSet = false;
+ Windows::_overrideFgVal = 0;
+
+ Common::copy(g_conf->_moreSave, g_conf->_moreSave + 3, g_conf->_moreColor);
+ Common::copy(g_conf->_caretSave, g_conf->_caretSave + 3, g_conf->_caretColor);
+ Common::copy(g_conf->_linkSave, g_conf->_linkSave + 3, g_conf->_linkColor);
+ } else if (fg != zcolor_Current) {
+ _window->_attr.fgset = 1;
+ _window->_attr.fgcolor = fg;
+ Windows::_overrideFgSet = true;
+ Windows::_overrideFgVal = fg;
+
+ Common::copy(fore, fore + 3, g_conf->_moreColor);
+ Common::copy(fore, fore + 3, g_conf->_caretColor);
+ Common::copy(fore, fore + 3, g_conf->_linkColor);
+ }
+ }
+
+ if (bg != zcolor_Transparent && bg != zcolor_Cursor) {
+ if (bg == zcolor_Default) {
+ _window->_attr.bgset = 0;
+ _window->_attr.bgcolor = 0;
+ Windows::_overrideBgSet = false;
+ Windows::_overrideBgVal = 0;
+
+ Common::copy(g_conf->_windowSave, g_conf->_windowSave + 3, g_conf->_windowColor);
+ Common::copy(g_conf->_borderSave, g_conf->_borderSave + 3, g_conf->_borderColor);
+ } else if (bg != zcolor_Current) {
+ _window->_attr.bgset = 1;
+ _window->_attr.bgcolor = bg;
+ Windows::_overrideBgSet = true;
+ Windows::_overrideBgVal = bg;
+
+ Common::copy(back, back + 3, g_conf->_windowColor);
+ Common::copy(back, back + 3, g_conf->_borderColor);
+ }
+ }
+
+ Windows::_overrideReverse = !(fg == zcolor_Default && bg == zcolor_Default);
+ Windows::_forceRedraw = true;
+
+ if (_window->_echoStream)
+ _window->_echoStream->setZColors(fg, bg);
+}
+
/*--------------------------------------------------------------------------*/
MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 02e2f3b..ac25032 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -257,6 +257,11 @@ public:
* Set a hyperlink
*/
virtual void setHyperlink(glui32 linkVal) {}
+
+ /**
+ * Set the style colors
+ */
+ virtual void setZColors(glui32 fg, glui32 bg);
};
typedef Stream *strid_t;
@@ -314,6 +319,11 @@ public:
* Set a hyperlink
*/
virtual void setHyperlink(glui32 linkVal) override;
+
+ /**
+ * Set the style colors
+ */
+ virtual void setZColors(glui32 fg, glui32 bg) override;
};
/**
Commit: 7cb69167de7a024f4d79df5f967397a0737bd574
https://github.com/scummvm/scummvm/commit/7cb69167de7a024f4d79df5f967397a0737bd574
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add the garglk_set_reversevideo methods
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 6022a86..dc91d4c 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -1160,11 +1160,15 @@ void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
}
void Glk::garglk_set_reversevideo(glui32 reverse) {
- // TODO
+ _streams->getCurrent()->setReverseVideo(reverse != 0);
}
void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
- // TODO
+ if (str) {
+ str->setReverseVideo(reverse != 0);
+ } else {
+ warning("set_reversevideo: Invalid ref");
+ }
}
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 9d257f2..b301272 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -68,6 +68,11 @@ void Stream::setZColors(glui32 fg, glui32 bg) {
Windows::_forceRedraw = true;
}
+void Stream::setReverseVideo(bool reverse) {
+ if (_writable && g_conf->_styleHint)
+ Windows::_forceRedraw = true;
+}
+
/*--------------------------------------------------------------------------*/
void WindowStream::close(StreamResult *result) {
@@ -283,6 +288,17 @@ void WindowStream::setZColors(glui32 fg, glui32 bg) {
_window->_echoStream->setZColors(fg, bg);
}
+void WindowStream::setReverseVideo(bool reverse) {
+ if (!_writable || !g_conf->_styleHint)
+ return;
+
+ _window->_attr.reverse = reverse;
+ if (_window->_echoStream)
+ _window->_echoStream->setReverseVideo(reverse);
+
+ Windows::_forceRedraw = true;
+}
+
/*--------------------------------------------------------------------------*/
MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index ac25032..c8b6963 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -262,6 +262,11 @@ public:
* Set the style colors
*/
virtual void setZColors(glui32 fg, glui32 bg);
+
+ /**
+ * Set the reverse video style
+ */
+ virtual void setReverseVideo(bool reverse);
};
typedef Stream *strid_t;
@@ -324,6 +329,11 @@ public:
* Set the style colors
*/
virtual void setZColors(glui32 fg, glui32 bg) override;
+
+ /**
+ * Set the reverse video style
+ */
+ virtual void setReverseVideo(bool reverse) override;
};
/**
Commit: 5ddf55da6cb9ba283229d2a06014ab5b88f6bfb4
https://github.com/scummvm/scummvm/commit/5ddf55da6cb9ba283229d2a06014ab5b88f6bfb4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Convert comments to single line veresions
Changed paths:
engines/gargoyle/glk.cpp
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index dc91d4c..25ce3cc 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -1090,7 +1090,7 @@ void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *d
}
void Glk::glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time) {
- // TODO: timezones aren't currently supported
+ // WORKAROUND: timezones aren't currently supported
*time = TimeAndDate(*date);
}
@@ -1099,7 +1099,7 @@ void Glk::glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time) {
}
glsi32 Glk::glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor) {
- // TODO: timezones aren't currently supported
+ // WORKAROUND: timezones aren't currently supported
assert(factor);
TimeSeconds ts = TimeAndDate(*date);
return ts / factor;
@@ -1113,7 +1113,7 @@ glsi32 Glk::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor)
/*--------------------------------------------------------------------------*/
-/* XXX non-official Glk functions that may or may not exist */
+/* XXX non-official Glk functions */
const char *Glk::garglk_fileref_get_name(frefid_t fref) const {
return fref->_filename.c_str();
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index b0c3444..8728cdb 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -101,7 +101,7 @@ Distributed under the GNU software license\n\n");
break;
}
- /* Brian Howarth games seem to use -1 for forever */
+ // Brian Howarth games seem to use -1 for forever
if (Items[LIGHT_SOURCE].Location/*==-1*/ != DESTROYED && GameHeader.LightTime != -1) {
GameHeader.LightTime--;
if (GameHeader.LightTime < 1) {
@@ -208,7 +208,7 @@ int Scott::countCarried(void) {
const char *Scott::mapSynonym(const char *word) {
int n = 1;
const char *tp;
- static char lastword[16]; /* Last non synonym */
+ static char lastword[16]; // Last non synonym
while (n <= GameHeader.NumWords) {
tp = Nouns[n];
if (*tp == '*')
@@ -264,20 +264,16 @@ char *Scott::readString(Common::SeekableReadStream *f) {
}
}
if (c == '`')
- c = '"'; /* pdd */
+ c = '"'; // pdd
- /* Ensure a valid Glk newline is sent. */
+ // Ensure a valid Glk newline is sent.
if (c == '\n')
tmp[ct++] = 10;
- /* Special case: assume CR is part of CRLF in a
- * DOS-formatted file, and ignore it.
- */
+ // Special case: assume CR is part of CRLF in a DOS-formatted file, and ignore it.
else if (c == 13)
;
- /* Pass only ASCII to Glk; the other reasonable option
- * would be to pass Latin-1, but it's probably safe to
- * assume that Scott Adams games are ASCII only.
- */
+ // Pass only ASCII to Glk; the other reasonable option would be to pass Latin-1,
+ // but it's probably safe to assume that Scott Adams games are ASCII only.
else if ((c >= 32 && c <= 126))
tmp[ct++] = c;
else
@@ -297,8 +293,8 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
Action *ap;
Room *rp;
Item *ip;
- /* Load the header */
-
+
+ // Load the header
readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
GameHeader.NumItems = ni;
@@ -320,8 +316,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
Messages = (const char **)memAlloc(sizeof(char *)*(mn + 1));
GameHeader.TreasureRoom = trm;
- /* Load the actions */
-
+ // Load the actions
ct = 0;
ap = Actions;
if (loud)
@@ -377,7 +372,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
while (ct < ni + 1) {
ip->Text = readString(f);
ip->AutoGet = strchr(ip->Text, '/');
- /* Some games use // to mean no auto get/drop word! */
+ // Some games use // to mean no auto get/drop word!
if (ip->AutoGet && strcmp(ip->AutoGet, "//") && strcmp(ip->AutoGet, "/*")) {
char *t;
*ip->AutoGet++ = 0;
@@ -393,7 +388,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
ct++;
}
ct = 0;
- /* Discard Comment Strings */
+ // Discard Comment Strings
while (ct<na + 1) {
free(readString(f));
ct++;
@@ -654,12 +649,12 @@ int Scott::getInput(int *vb, int *no) {
case 'w':strcpy(verb, "WEST"); break;
case 'u':strcpy(verb, "UP"); break;
case 'd':strcpy(verb, "DOWN"); break;
- /* Brian Howarth interpreter also supports this */
+ // Brian Howarth interpreter also supports this
case 'i':strcpy(verb, "INVENTORY"); break;
}
}
nc = whichWord(verb, Nouns);
- /* The Scott Adams system has a hack to avoid typing 'go' */
+ // The Scott Adams system has a hack to avoid typing 'go'
if (nc >= 1 && nc <= 6) {
vc = 1;
} else {
@@ -673,7 +668,7 @@ int Scott::getInput(int *vb, int *no) {
}
} while (vc == -1);
- strcpy(NounText, noun); /* Needed by GET/DROP hack */
+ strcpy(NounText, noun); // Needed by GET/DROP hack
return 0;
}
@@ -765,14 +760,16 @@ int Scott::performLine(int ct) {
if (Items[dv].Location == Items[dv].InitialLoc)
return 0;
break;
- case 19:/* Only seen in Brian Howarth games so far */
+ case 19:
+ // Only seen in Brian Howarth games so far
if (CurrentCounter != dv)
return 0;
break;
}
cc++;
}
- /* Actions */
+
+ // Actions
act[0] = Actions[ct].action[0];
act[2] = Actions[ct].action[1];
act[1] = act[0] % 150;
@@ -789,15 +786,13 @@ int Scott::performLine(int ct) {
} else if (act[cc] > 101) {
output(Messages[act[cc] - 50]);
output("\n");
- }
- else {
+ } else {
switch (act[cc]) {
- case 0:/* NOP */
+ case 0:// NOP
break;
case 52:
- if (countCarried() == GameHeader.MaxCarry)
- {
- if (Options&YOUARE)
+ if (countCarried() == GameHeader.MaxCarry) {
+ if (Options & YOUARE)
output("You are carrying too much. ");
else
output("I've too much to carry! ");
@@ -835,27 +830,25 @@ int Scott::performLine(int ct) {
else
output("I am dead.\n");
BitFlags &= ~(1 << DARKBIT);
- MyLoc = GameHeader.NumRooms;/* It seems to be what the code says! */
+ MyLoc = GameHeader.NumRooms;// It seems to be what the code says!
break;
- case 62:
- {
- /* Bug fix for some systems - before it could get parameters wrong */
+ case 62: {
+ // Bug fix for some systems - before it could get parameters wrong */
int i = param[pptr++];
Items[i].Location = param[pptr++];
break;
}
case 63:
- doneit: output("The game is now over.\n");
- glk_exit();
- break;
+doneit:
+ output("The game is now over.\n");
+ glk_exit();
+ break;
case 64:
break;
- case 65:
- {
+ case 65: {
int i = 0;
int n = 0;
- while (i <= GameHeader.NumItems)
- {
+ while (i <= GameHeader.NumItems) {
if (Items[i].Location == GameHeader.TreasureRoom &&
*Items[i].Text == '*')
n++;
@@ -869,27 +862,22 @@ int Scott::performLine(int ct) {
output(" treasures. On a scale of 0 to 100, that rates ");
outputNumber((n * 100) / GameHeader.Treasures);
output(".\n");
- if (n == GameHeader.Treasures)
- {
+ if (n == GameHeader.Treasures) {
output("Well done.\n");
goto doneit;
}
break;
}
- case 66:
- {
+ case 66: {
int i = 0;
int f = 0;
if (Options&YOUARE)
output("You are carrying:\n");
else
output("I'm carrying:\n");
- while (i <= GameHeader.NumItems)
- {
- if (Items[i].Location == CARRIED)
- {
- if (f == 1)
- {
+ while (i <= GameHeader.NumItems) {
+ if (Items[i].Location == CARRIED) {
+ if (f == 1) {
if (Options & TRS80_STYLE)
output(". ");
else
@@ -917,13 +905,12 @@ int Scott::performLine(int ct) {
BitFlags &= ~(1 << LIGHTOUTBIT);
break;
case 70:
- clearScreen(); /* pdd. */
+ clearScreen(); // pdd.
break;
case 71:
saveGame();
break;
- case 72:
- {
+ case 72: {
int i1 = param[pptr++];
int i2 = param[pptr++];
int t = Items[i1].Location;
@@ -937,15 +924,15 @@ int Scott::performLine(int ct) {
case 74:
Items[param[pptr++]].Location = CARRIED;
break;
- case 75:
- {
+ case 75: {
int i1, i2;
i1 = param[pptr++];
i2 = param[pptr++];
Items[i1].Location = Items[i2].Location;
break;
}
- case 76: /* Looking at adventure .. */
+ case 76:
+ // Looking at adventure ..
break;
case 77:
if (CurrentCounter >= 0)
@@ -957,19 +944,16 @@ int Scott::performLine(int ct) {
case 79:
CurrentCounter = param[pptr++];
break;
- case 80:
- {
+ case 80: {
int t = MyLoc;
MyLoc = SavedRoom;
SavedRoom = t;
break;
}
- case 81:
- {
- /* This is somewhat guessed. Claymorgue always
- seems to do select counter n, thing, select counter n,
- but uses one value that always seems to exist. Trying
- a few options I found this gave sane results on ageing */
+ case 81: {
+ // This is somewhat guessed. Claymorgue always seems to do
+ // select counter n, thing, select counter n, but uses one value that always
+ // seems to exist. Trying a few options I found this gave sane results on ageing
int t = param[pptr++];
int c1 = CurrentCounter;
CurrentCounter = Counters[t];
@@ -983,8 +967,8 @@ int Scott::performLine(int ct) {
CurrentCounter -= param[pptr++];
if (CurrentCounter < -1)
CurrentCounter = -1;
- /* Note: This seems to be needed. I don't yet
- know if there is a maximum value to limit too */
+ // Note: This seems to be needed. I don't yet know if there
+ // is a maximum value to limit too
break;
case 84:
output(NounText);
@@ -996,10 +980,8 @@ int Scott::performLine(int ct) {
case 86:
output("\n");
break;
- case 87:
- {
- /* Changed this to swap location<->roomflag[x]
- not roomflag 0 and x */
+ case 87: {
+ // Changed this to swap location<->roomflag[x] not roomflag 0 and x
int p = param[pptr++];
int sr = MyLoc;
MyLoc = RoomSaved[p];
@@ -1011,9 +993,9 @@ int Scott::performLine(int ct) {
break;
case 89:
pptr++;
- /* SAGA draw picture n */
- /* Spectrum Seas of Blood - start combat ? */
- /* Poking this into older spectrum games causes a crash */
+ // SAGA draw picture n
+ // Spectrum Seas of Blood - start combat ?
+ // Poking this into older spectrum games causes a crash
break;
default:
error("Unknown action %d [Param begins %d %d]\n",
@@ -1029,7 +1011,7 @@ int Scott::performLine(int ct) {
}
int Scott::performActions(int vb, int no) {
- static int disable_sysfunc = 0; /* Recursion lock */
+ static int disable_sysfunc = 0; // Recursion lock
int d = BitFlags&(1 << DARKBIT);
int ct = 0;
@@ -1069,11 +1051,11 @@ int Scott::performActions(int vb, int no) {
while (ct <= GameHeader.NumActions) {
int vv, nv;
vv = Actions[ct].Vocab;
- /* Think this is now right. If a line we run has an action73
- run all following lines with vocab of 0,0 */
+ // Think this is now right. If a line we run has an action73
+ // run all following lines with vocab of 0,0
if (vb != 0 && (doagain&&vv != 0))
break;
- /* Oops.. added this minor cockup fix 1.11 */
+ // Oops.. added this minor cockup fix 1.11
if (vb != 0 && !doagain && fl == 0)
break;
nv = vv % 150;
@@ -1085,7 +1067,7 @@ int Scott::performActions(int vb, int no) {
if (fl == -1)
fl = -2;
if ((f2 = performLine(ct)) > 0) {
- /* ahah finally figured it out ! */
+ // ahah finally figured it out !
fl = 0;
if (f2 == 2)
doagain = 1;
@@ -1096,13 +1078,10 @@ int Scott::performActions(int vb, int no) {
}
ct++;
- /* Previously this did not check ct against
- * GameHeader.NumActions and would read past the end of
- * Actions. I don't know what should happen on the last
- * action, but doing nothing is better than reading one
- * past the end.
- * --Chris
- */
+ // Previously this did not check ct against GameHeader.NumActions and would read
+ // past the end of Actions. I don't know what should happen on the last action,
+ // but doing nothing is better than reading one past the end.
+ // --Chris
if (ct <= GameHeader.NumActions && Actions[ct].Vocab != 0)
doagain = 0;
}
@@ -1112,7 +1091,7 @@ int Scott::performActions(int vb, int no) {
Items[LIGHT_SOURCE].Location == CARRIED)
d = 0;
if (vb == 10 || vb == 18) {
- /* Yes they really _are_ hardcoded values */
+ // Yes they really _are_ hardcoded values
if (vb == 10) {
if (xstrcasecmp(NounText, "ALL") == 0) {
int i = 0;
@@ -1125,8 +1104,8 @@ int Scott::performActions(int vb, int no) {
while (i <= GameHeader.NumItems) {
if (Items[i].Location == MyLoc && Items[i].AutoGet != nullptr && Items[i].AutoGet[0] != '*') {
no = whichWord(Items[i].AutoGet, Nouns);
- disable_sysfunc = 1; /* Don't recurse into auto get ! */
- performActions(vb, no); /* Recursively check each items table code */
+ disable_sysfunc = 1; // Don't recurse into auto get !
+ performActions(vb, no); // Recursively check each items table code
disable_sysfunc = 0;
if (countCarried() == GameHeader.MaxCarry) {
if (Options&YOUARE)
@@ -1146,13 +1125,11 @@ int Scott::performActions(int vb, int no) {
output("Nothing taken.");
return 0;
}
- if (no == -1)
- {
+ if (no == -1) {
output("What ? ");
return 0;
}
- if (countCarried() == GameHeader.MaxCarry)
- {
+ if (countCarried() == GameHeader.MaxCarry) {
if (Options&YOUARE)
output("You are carrying too much. ");
else
@@ -1160,8 +1137,7 @@ int Scott::performActions(int vb, int no) {
return 0;
}
item = matchUpItem(NounText, MyLoc);
- if (item == -1)
- {
+ if (item == -1) {
if (Options&YOUARE)
output("It is beyond your power to do that. ");
else
Commit: a8e656a5de01e18697fa4f0086215d11d9143197
https://github.com/scummvm/scummvm/commit/a8e656a5de01e18697fa4f0086215d11d9143197
Author: dreammaster (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: astyle formatting
Changed paths:
engines/gargoyle/conf.cpp
engines/gargoyle/detection.cpp
engines/gargoyle/detection_tables.h
engines/gargoyle/events.cpp
engines/gargoyle/events.h
engines/gargoyle/fonts.h
engines/gargoyle/gargoyle.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/glk.cpp
engines/gargoyle/glk.h
engines/gargoyle/glk_types.h
engines/gargoyle/scott/scott.cpp
engines/gargoyle/scott/scott.h
engines/gargoyle/screen.h
engines/gargoyle/selection.cpp
engines/gargoyle/selection.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
engines/gargoyle/unicode.cpp
engines/gargoyle/unicode.h
engines/gargoyle/unicode_gen.cpp
engines/gargoyle/unicode_gen.h
engines/gargoyle/window_graphics.cpp
engines/gargoyle/window_graphics.h
engines/gargoyle/window_pair.cpp
engines/gargoyle/window_text_buffer.cpp
engines/gargoyle/window_text_buffer.h
engines/gargoyle/window_text_grid.cpp
engines/gargoyle/window_text_grid.h
engines/gargoyle/windows.cpp
engines/gargoyle/windows.h
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
index 7add133..9a0d648 100644
--- a/engines/gargoyle/conf.cpp
+++ b/engines/gargoyle/conf.cpp
@@ -35,31 +35,31 @@ const byte SCROLL_BG[3] = { 0xb0, 0xb0, 0xb0 };
const byte SCROLL_FG[3] = { 0x80, 0x80, 0x80 };
WindowStyle T_STYLES[style_NUMSTYLES] = {
- { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Normal
- { PROPI,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Emphasized
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Preformatted
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Header
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Subheader
- { PROPZ,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Alert
- { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< Note
- { PROPR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< BlockQuote
- { PROPB,{ 0xff,0xff,0xff },{ 0x00,0x60,0x00 }, 0 }, ///< Input
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User1
- { MONOR,{ 0xff,0xff,0xff },{ 0x00,0x00,0x00 }, 0 }, ///< User2
+ { PROPR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Normal
+ { PROPI, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Emphasized
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Preformatted
+ { PROPB, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Header
+ { PROPB, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Subheader
+ { PROPZ, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Alert
+ { PROPR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Note
+ { PROPR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< BlockQuote
+ { PROPB, { 0xff, 0xff, 0xff }, { 0x00, 0x60, 0x00 }, 0 }, ///< Input
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< User1
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< User2
};
WindowStyle G_STYLES[style_NUMSTYLES] = {
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Normal
- { MONOI,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Emphasized
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Preformatted
- { MONOB,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Header
- { MONOB,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Subheader
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Alert
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Note
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< BlockQuote
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< Input
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< User1
- { MONOR,{ 0xff,0xff,0xff },{ 0x60,0x60,0x60 }, 0 }, ///< User2
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Normal
+ { MONOI, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Emphasized
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Preformatted
+ { MONOB, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Header
+ { MONOB, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Subheader
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Alert
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Note
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< BlockQuote
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Input
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< User1
+ { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< User2
};
Conf *g_conf;
@@ -122,7 +122,7 @@ Conf::Conf() {
get("tmarginx", _tMarginX, 7);
get("tmarginy", _tMarginY, 7);
get("gamma", _gamma, 1.0);
-
+
get("caretcolor", _caretColor);
get("caretcolor", _caretSave);
get("linkcolor", _linkColor, BLUE);
@@ -235,9 +235,15 @@ void Conf::parseColor(const Common::String &str, byte *color) {
char r[3], g[3], b[3];
if (str.size() == 6) {
- r[0] = str[0]; r[1] = str[1]; r[2] = 0;
- g[0] = str[2]; g[1] = str[3]; g[2] = 0;
- b[0] = str[4]; b[1] = str[5]; b[2] = 0;
+ r[0] = str[0];
+ r[1] = str[1];
+ r[2] = 0;
+ g[0] = str[2];
+ g[1] = str[3];
+ g[2] = 0;
+ b[0] = str[4];
+ b[1] = str[5];
+ b[2] = 0;
color[0] = strtol(r, nullptr, 16);
color[1] = strtol(g, nullptr, 16);
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index af7cfc6..4363c46 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -125,20 +125,20 @@ public:
bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
return
- (f == kSupportsListSaves) ||
- (f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportCreationDate) ||
- (f == kSavesSupportPlayTime) ||
- (f == kSimpleSavesNames);
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
+ (f == kSimpleSavesNames);
}
bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
return
- (f == kSupportsRTL) ||
- (f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
}
bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
@@ -255,7 +255,7 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
}
#if PLUGIN_ENABLED_DYNAMIC(GARGOYLE)
- REGISTER_PLUGIN_DYNAMIC(Gargoyle, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
+REGISTER_PLUGIN_DYNAMIC(Gargoyle, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
#else
- REGISTER_PLUGIN_STATIC(GARGOYLE, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
+REGISTER_PLUGIN_STATIC(GARGOYLE, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
#endif
diff --git a/engines/gargoyle/detection_tables.h b/engines/gargoyle/detection_tables.h
index 780cfe2..777d4db 100644
--- a/engines/gargoyle/detection_tables.h
+++ b/engines/gargoyle/detection_tables.h
@@ -21,7 +21,7 @@
*/
namespace Gargoyle {
-
+
static const GargoyleGameDescription gameDescriptions[] = {
{
{
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
index 520b6f2..6c0cd71 100644
--- a/engines/gargoyle/events.cpp
+++ b/engines/gargoyle/events.cpp
@@ -54,7 +54,7 @@ const byte ARROW[] = {
};
Events::Events() : _forceClick(false), _currentEvent(nullptr), _cursorId(CURSOR_NONE),
- _timerMilli(0), _timerTimeExpiry(0), _priorFrameTime(0), _frameCounter(0) {
+ _timerMilli(0), _timerTimeExpiry(0), _priorFrameTime(0), _frameCounter(0) {
initializeCursors();
}
@@ -239,34 +239,85 @@ void Events::handleKeyDown(const Common::KeyState &ks) {
return;
switch (ks.keycode) {
- case Common::KEYCODE_RETURN: windows.inputHandleKey(keycode_Return); break;
- case Common::KEYCODE_BACKSPACE: windows.inputHandleKey(keycode_Delete); break;
- case Common::KEYCODE_DELETE: windows.inputHandleKey(keycode_Erase); break;
- case Common::KEYCODE_TAB: windows.inputHandleKey(keycode_Tab); break;
- case Common::KEYCODE_PAGEUP: windows.inputHandleKey(keycode_PageUp); break;
- case Common::KEYCODE_PAGEDOWN: windows.inputHandleKey(keycode_PageDown); break;
- case Common::KEYCODE_HOME: windows.inputHandleKey(keycode_Home); break;
- case Common::KEYCODE_END: windows.inputHandleKey(keycode_End); break;
- case Common::KEYCODE_LEFT: windows.inputHandleKey(keycode_Left); break;
- case Common::KEYCODE_RIGHT: windows.inputHandleKey(keycode_Right); break;
- case Common::KEYCODE_UP: windows.inputHandleKey(keycode_Up); break;
- case Common::KEYCODE_DOWN: windows.inputHandleKey(keycode_Down); break;
- case Common::KEYCODE_ESCAPE: windows.inputHandleKey(keycode_Escape); break;
- case Common::KEYCODE_F1: windows.inputHandleKey(keycode_Func1); break;
- case Common::KEYCODE_F2: windows.inputHandleKey(keycode_Func2); break;
- case Common::KEYCODE_F3: windows.inputHandleKey(keycode_Func3); break;
- case Common::KEYCODE_F4: windows.inputHandleKey(keycode_Func4); break;
- case Common::KEYCODE_F5: windows.inputHandleKey(keycode_Func5); break;
- case Common::KEYCODE_F6: windows.inputHandleKey(keycode_Func6); break;
- case Common::KEYCODE_F7: windows.inputHandleKey(keycode_Func7); break;
- case Common::KEYCODE_F8: windows.inputHandleKey(keycode_Func8); break;
- case Common::KEYCODE_F9: windows.inputHandleKey(keycode_Func9); break;
- case Common::KEYCODE_F10: windows.inputHandleKey(keycode_Func10); break;
- case Common::KEYCODE_F11: windows.inputHandleKey(keycode_Func11); break;
- case Common::KEYCODE_F12: windows.inputHandleKey(keycode_Func12); break;
+ case Common::KEYCODE_RETURN:
+ windows.inputHandleKey(keycode_Return);
+ break;
+ case Common::KEYCODE_BACKSPACE:
+ windows.inputHandleKey(keycode_Delete);
+ break;
+ case Common::KEYCODE_DELETE:
+ windows.inputHandleKey(keycode_Erase);
+ break;
+ case Common::KEYCODE_TAB:
+ windows.inputHandleKey(keycode_Tab);
+ break;
+ case Common::KEYCODE_PAGEUP:
+ windows.inputHandleKey(keycode_PageUp);
+ break;
+ case Common::KEYCODE_PAGEDOWN:
+ windows.inputHandleKey(keycode_PageDown);
+ break;
+ case Common::KEYCODE_HOME:
+ windows.inputHandleKey(keycode_Home);
+ break;
+ case Common::KEYCODE_END:
+ windows.inputHandleKey(keycode_End);
+ break;
+ case Common::KEYCODE_LEFT:
+ windows.inputHandleKey(keycode_Left);
+ break;
+ case Common::KEYCODE_RIGHT:
+ windows.inputHandleKey(keycode_Right);
+ break;
+ case Common::KEYCODE_UP:
+ windows.inputHandleKey(keycode_Up);
+ break;
+ case Common::KEYCODE_DOWN:
+ windows.inputHandleKey(keycode_Down);
+ break;
+ case Common::KEYCODE_ESCAPE:
+ windows.inputHandleKey(keycode_Escape);
+ break;
+ case Common::KEYCODE_F1:
+ windows.inputHandleKey(keycode_Func1);
+ break;
+ case Common::KEYCODE_F2:
+ windows.inputHandleKey(keycode_Func2);
+ break;
+ case Common::KEYCODE_F3:
+ windows.inputHandleKey(keycode_Func3);
+ break;
+ case Common::KEYCODE_F4:
+ windows.inputHandleKey(keycode_Func4);
+ break;
+ case Common::KEYCODE_F5:
+ windows.inputHandleKey(keycode_Func5);
+ break;
+ case Common::KEYCODE_F6:
+ windows.inputHandleKey(keycode_Func6);
+ break;
+ case Common::KEYCODE_F7:
+ windows.inputHandleKey(keycode_Func7);
+ break;
+ case Common::KEYCODE_F8:
+ windows.inputHandleKey(keycode_Func8);
+ break;
+ case Common::KEYCODE_F9:
+ windows.inputHandleKey(keycode_Func9);
+ break;
+ case Common::KEYCODE_F10:
+ windows.inputHandleKey(keycode_Func10);
+ break;
+ case Common::KEYCODE_F11:
+ windows.inputHandleKey(keycode_Func11);
+ break;
+ case Common::KEYCODE_F12:
+ windows.inputHandleKey(keycode_Func12);
+ break;
default:
- windows.inputHandleKey(ks.ascii); break;
- break;
+ windows.inputHandleKey(ks.ascii);
+ break;
+ break;
}
}
@@ -317,8 +368,8 @@ void Events::waitForPress() {
g_system->delayMillis(10);
checkForNextFrameCounter();
} while (!g_vm->shouldQuit() && e.type != Common::EVENT_KEYDOWN &&
- e.type != Common::EVENT_LBUTTONDOWN && e.type != Common::EVENT_RBUTTONDOWN &&
- e.type != Common::EVENT_MBUTTONDOWN);
+ e.type != Common::EVENT_LBUTTONDOWN && e.type != Common::EVENT_RBUTTONDOWN &&
+ e.type != Common::EVENT_MBUTTONDOWN);
}
void Events::setCursor(CursorId cursorId) {
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index f91c91b..b69cd04 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -50,7 +50,7 @@ enum EvType {
evtype_VolumeNotify = 9,
// ScummVM custom events
- evtype_Quit = 99
+ evtype_Quit = 99
};
/**
@@ -115,7 +115,9 @@ struct Event {
/**
* Constructor
*/
- Event() { clear(); }
+ Event() {
+ clear();
+ }
/**
* Constructor
@@ -139,7 +141,9 @@ struct Event {
/**
* Boolean cast to allow checking whether event is filled out
*/
- operator bool() const { return type != evtype_None; }
+ operator bool() const {
+ return type != evtype_None;
+ }
};
typedef Event event_t;
@@ -161,16 +165,16 @@ class Events {
Common::Point _hotspot;
};
private:
- EventQueue _eventsPolled; ///< User generated events
- EventQueue _eventsLogged; ///< Custom events generated by game code
- Event *_currentEvent; ///< Event pointer passed during event retrieval
- uint32 _priorFrameTime; ///< Time of prior game frame
- uint32 _frameCounter; ///< Frame counter
- bool _redraw; ///< Screen needed redrawing
- CursorId _cursorId; ///< Current cursor Id
- Surface _cursors[4]; ///< Cursor pixel data
- uint _timerMilli; ///< Time in milliseconds between timer events
- uint _timerTimeExpiry; ///< When to trigger next timer event
+ EventQueue _eventsPolled; ///< User generated events
+ EventQueue _eventsLogged; ///< Custom events generated by game code
+ Event *_currentEvent; ///< Event pointer passed during event retrieval
+ uint32 _priorFrameTime; ///< Time of prior game frame
+ uint32 _frameCounter; ///< Frame counter
+ bool _redraw; ///< Screen needed redrawing
+ CursorId _cursorId; ///< Current cursor Id
+ Surface _cursors[4]; ///< Cursor pixel data
+ uint _timerMilli; ///< Time in milliseconds between timer events
+ uint _timerTimeExpiry; ///< When to trigger next timer event
private:
/**
* Initialize the cursor graphics
@@ -247,17 +251,23 @@ public:
/**
* Get the total number of frames played
*/
- uint32 getTotalPlayTicks() const { return _frameCounter; }
+ uint32 getTotalPlayTicks() const {
+ return _frameCounter;
+ }
/**
* Set the total number of frames played
*/
- void Events::setTotalPlayTicks(uint frames) { _frameCounter = frames; }
+ void Events::setTotalPlayTicks(uint frames) {
+ _frameCounter = frames;
+ }
/**
* Flags the screen for redrawing
*/
- void redraw() { _redraw = true; }
+ void redraw() {
+ _redraw = true;
+ }
/**
* Sets the current cursor
@@ -266,7 +276,7 @@ public:
/**
* Set a timer interval
- * @param milli Time in millieseconds for intervals, or 0 for off
+ * @param milli Time in millieseconds for intervals, or 0 for off
*/
void setTimerInterval(uint milli);
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
index 1437bd8..737618e 100644
--- a/engines/gargoyle/fonts.h
+++ b/engines/gargoyle/fonts.h
@@ -76,39 +76,39 @@ public:
/**
* Draws a string using the specified font at the given co-ordinates
- * @param pos Position for the bottom-left corner the text will be drawn with
- * @param fontIdx Which font to use
- * @param rgb RGB tuplet specifying the text color
- * @param text The text to draw
- * @param spw ??
+ * @param pos Position for the bottom-left corner the text will be drawn with
+ * @param fontIdx Which font to use
+ * @param rgb RGB tuplet specifying the text color
+ * @param text The text to draw
+ * @param spw ??
*/
int drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
/**
* Draws a unicode string using the specified font at the given co-ordinates
- * @param pos Position for the bottom-left corner the text will be drawn with
- * @param fontIdx Which font to use
- * @param rgb RGB tuplet specifying the text color
- * @param text The text to draw
- * @param spw ??
+ * @param pos Position for the bottom-left corner the text will be drawn with
+ * @param fontIdx Which font to use
+ * @param rgb RGB tuplet specifying the text color
+ * @param text The text to draw
+ * @param spw ??
*/
int drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
/**
* Get the width in pixels of a string
* @param fontIdx Which font to use
- * @param text Text to get the width of
- * @param spw Delta X
- * @returns Width of string multiplied by GLI_SUBPIX
+ * @param text Text to get the width of
+ * @param spw Delta X
+ * @returns Width of string multiplied by GLI_SUBPIX
*/
size_t stringWidth(int fontIdx, const Common::String &text, int spw = 0);
/**
* Get the width in pixels of a unicode string
* @param fontIdx Which font to use
- * @param text Text to get the width of
- * @param spw Delta X
- * @returns Width of string multiplied by GLI_SUBPIX
+ * @param text Text to get the width of
+ * @param spw Delta X
+ * @returns Width of string multiplied by GLI_SUBPIX
*/
size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = 0);
};
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 9c00937..021323c 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -42,10 +42,10 @@ namespace Gargoyle {
GargoyleEngine *g_vm;
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _clipboard(nullptr),
- _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
- _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
- gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
+ _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _clipboard(nullptr),
+ _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
+ _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
+ gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 793a353..e131be1 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -62,8 +62,8 @@ enum InterpreterType {
enum GargoyleDebugChannels {
kDebugCore = 1 << 0,
- kDebugScripts = 1 << 1,
- kDebugGraphics = 1 << 2,
+ kDebugScripts = 1 << 1,
+ kDebugGraphics = 1 << 2,
kDebugSound = 1 << 3
};
@@ -125,12 +125,16 @@ public:
/**
* Returns true if a savegame can be loaded
*/
- virtual bool canLoadGameStateCurrently() override { return true; }
+ virtual bool canLoadGameStateCurrently() override {
+ return true;
+ }
/**
* Returns true if the game can be saved
*/
- virtual bool canSaveGameStateCurrently() override { return true; }
+ virtual bool canSaveGameStateCurrently() override {
+ return true;
+ }
/**
* Returns the bitset of game features
@@ -165,7 +169,9 @@ public:
/**
* Return the game engine's target name
*/
- const Common::String &getTargetName() const { return _targetName; }
+ const Common::String &getTargetName() const {
+ return _targetName;
+ }
/**
* Display a message in a GUI dialog
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 25ce3cc..58293f7 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -34,8 +34,8 @@
namespace Gargoyle {
-Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GargoyleEngine(syst, gameDesc), _gliFirstEvent(false) {
+Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+ GargoyleEngine(syst, gameDesc), _gliFirstEvent(false) {
// Set uppercase/lowercase tables
int ix, res;
for (ix = 0; ix < 256; ix++) {
@@ -59,7 +59,7 @@ Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
}
void Glk::glk_exit(void) {
- glk_put_string("[ press any key to exit ]");
+ glk_put_string("[ press any key to exit ]");
_events->waitForPress();
quitGame();
@@ -194,7 +194,7 @@ void Glk::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, wi
}
void Glk::glk_window_get_arrangement(winid_t win, glui32 *method,
- glui32 *size, winid_t *keyWin) {
+ glui32 *size, winid_t *keyWin) {
if (win) {
win->getArrangement(method, size, keyWin);
} else {
@@ -586,30 +586,30 @@ bool Glk::glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *resu
case stylehint_Weight:
*result =
- (styles[style].font == PROPB || styles[style].font == PROPZ ||
- styles[style].font == MONOB || styles[style].font == MONOZ);
+ (styles[style].font == PROPB || styles[style].font == PROPZ ||
+ styles[style].font == MONOB || styles[style].font == MONOZ);
break;
case stylehint_Oblique:
*result =
- (styles[style].font == PROPI || styles[style].font == PROPZ ||
- styles[style].font == MONOI || styles[style].font == MONOZ);
+ (styles[style].font == PROPI || styles[style].font == PROPZ ||
+ styles[style].font == MONOI || styles[style].font == MONOZ);
break;
case stylehint_Proportional:
*result =
- (styles[style].font == PROPR || styles[style].font == PROPI ||
- styles[style].font == PROPB || styles[style].font == PROPZ);
+ (styles[style].font == PROPR || styles[style].font == PROPI ||
+ styles[style].font == PROPB || styles[style].font == PROPZ);
break;
case stylehint_TextColor:
*result =
- (styles[style].fg[0] << 16) | (styles[style].fg[1] << 8) | (styles[style].fg[2]);
+ (styles[style].fg[0] << 16) | (styles[style].fg[1] << 8) | (styles[style].fg[2]);
break;
case stylehint_BackColor:
*result =
- (styles[style].bg[0] << 16) | (styles[style].bg[1] << 8) | (styles[style].bg[2]);
+ (styles[style].bg[0] << 16) | (styles[style].bg[1] << 8) | (styles[style].bg[2]);
break;
case stylehint_ReverseColor:
@@ -681,7 +681,7 @@ void Glk::glk_select(event_t *event) {
_windows->inputGuessFocus();
_gliFirstEvent = true;
}
-
+
_events->getEvent(event, false);
}
@@ -702,7 +702,7 @@ void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 i
if (!win) {
warning("request_line_event: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
+ || win->_lineRequestUni) {
warning("request_line_event: window already has keyboard request");
} else {
win->requestLineEvent(buf, maxlen, initlen);
@@ -713,7 +713,7 @@ void Glk::glk_request_char_event(winid_t win) {
if (!win) {
warning("request_char_event: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
+ || win->_lineRequestUni) {
warning("request_char_event: window already has keyboard request");
} else {
win->requestCharEvent();
@@ -777,7 +777,7 @@ glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchar
}
glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest) {
+ glui32 numchars, glui32 lowerrest) {
return bufferChangeCase(buf, len, numchars, CASE_TITLE, COND_LINESTART, lowerrest);
}
@@ -840,7 +840,7 @@ glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
return str->getLineUni(buf, len);
} else {
warning("get_line_stream_uni: invalid ref");
- return (glui32 )-1;
+ return (glui32) - 1;
}
}
@@ -856,7 +856,7 @@ void Glk::glk_request_char_event_uni(winid_t win) {
if (!win) {
warning("request_char_event_uni: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
+ || win->_lineRequestUni) {
warning("request_char_event_uni: window already has keyboard request");
} else {
win->requestCharEvent();
@@ -867,7 +867,7 @@ void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, gl
if (!win) {
warning("request_line_event_uni: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
+ || win->_lineRequestUni) {
warning("request_line_event_uni: window already has keyboard request");
} else {
win->requestLineEventUni(buf, maxlen, initlen);
@@ -875,7 +875,7 @@ void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, gl
}
glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars) {
+ glui32 numchars) {
// TODO
return 0;
}
@@ -901,7 +901,7 @@ glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2)
}
glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2,
- glui32 width, glui32 height) {
+ glui32 width, glui32 height) {
if (!win) {
warning("image_draw_scaled: invalid ref");
} else if (g_conf->_graphics) {
@@ -950,7 +950,7 @@ void Glk::glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 wid
}
void Glk::glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top,
- glui32 width, glui32 height) {
+ glui32 width, glui32 height) {
if (!win) {
warning("window_fill_rect: invalid ref");
} else {
@@ -1013,7 +1013,7 @@ schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
}
glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify) {
+ glui32 *sndarray, glui32 soundcount, glui32 notify) {
// TODO
return 0;
}
@@ -1027,7 +1027,7 @@ void Glk::glk_schannel_unpause(schanid_t chan) {
}
void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify) {
+ glui32 duration, glui32 notify) {
// TODO
}
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index eb3e68d..b14546c 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -63,14 +63,14 @@ public:
* Open a new window
*/
winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock = 0) const;
+ glui32 wintype, glui32 rock = 0) const;
void glk_window_close(winid_t win, stream_result_t *result);
void glk_window_get_size(winid_t win, glui32 *width, glui32 *height);
void glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keyWin);
+ glui32 size, winid_t keyWin);
void glk_window_get_arrangement(winid_t win, glui32 *method,
- glui32 *size, winid_t *keyWin);
+ glui32 *size, winid_t *keyWin);
winid_t glk_window_iterate(winid_t win, glui32 *rock);
glui32 glk_window_get_rock(winid_t win);
glui32 glk_window_get_type(winid_t win);
@@ -108,7 +108,7 @@ public:
glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
- glsi32 val);
+ glsi32 val);
void glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint);
glui32 glk_style_distinguish(winid_t win, glui32 style1, glui32 style2);
bool glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result);
@@ -129,7 +129,7 @@ public:
void glk_request_timer_events(glui32 millisecs);
void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
- glui32 initlen);
+ glui32 initlen);
void glk_request_char_event(winid_t win);
void glk_request_mouse_event(winid_t win);
@@ -143,19 +143,19 @@ public:
#ifdef GLK_MODULE_LINE_TERMINATORS
void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
- glui32 count);
+ glui32 count);
#endif /* GLK_MODULE_LINE_TERMINATORS */
- /** \addtogroup Unicode
+ /** \addtogroup Unicode
* @{
*/
glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
+ glui32 numchars);
glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
+ glui32 numchars);
glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest);
+ glui32 numchars, glui32 lowerrest);
void glk_put_char_uni(glui32 ch);
void glk_put_string_uni(glui32 *s);
@@ -173,16 +173,16 @@ public:
void glk_request_char_event_uni(winid_t win);
void glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen);
+ glui32 maxlen, glui32 initlen);
/** @}*/
#ifdef GLK_MODULE_UNICODE_NORM
glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars);
+ glui32 numchars);
glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
- glui32 numchars);
+ glui32 numchars);
#endif /* GLK_MODULE_UNICODE_NORM */
@@ -190,15 +190,15 @@ public:
glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
glui32 glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height);
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height);
glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
void glk_window_flow_break(winid_t win);
void glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
void glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
void glk_window_set_background_color(winid_t win, glui32 color);
#endif /* GLK_MODULE_IMAGE */
@@ -212,7 +212,7 @@ public:
glui32 glk_schannel_play(schanid_t chan, glui32 snd);
glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
- glui32 notify);
+ glui32 notify);
void glk_schannel_stop(schanid_t chan);
void glk_schannel_set_volume(schanid_t chan, glui32 vol);
@@ -224,11 +224,11 @@ public:
schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify);
+ glui32 *sndarray, glui32 soundcount, glui32 notify);
void glk_schannel_pause(schanid_t chan);
void glk_schannel_unpause(schanid_t chan);
void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify);
+ glui32 duration, glui32 notify);
#endif /* GLK_MODULE_SOUND2 */
#endif /* GLK_MODULE_SOUND */
@@ -258,7 +258,7 @@ public:
#endif /* GLK_MODULE_DATETIME */
/* XXX non-official Glk functions that may or may not exist */
- #define GARGLK 1
+#define GARGLK 1
const char *garglk_fileref_get_name(frefid_t fref) const;
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 6dd8504..7258e69 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -169,7 +169,7 @@ enum StyleHint {
* These constants define the classes of opaque objects. It's a bit ugly to put
* them in this header file, since more classes may be added in the future.
* But if you find yourself stuck with an obsolete version of this file,
- * adding new class definitions will be easy enough -- they will be numbered
+ * adding new class definitions will be easy enough -- they will be numbered
* sequentially, and the numeric constants can be found in the Glk specification.
*/
enum giDisp {
@@ -180,10 +180,10 @@ enum giDisp {
};
enum zcolor {
- zcolor_Transparent = (uint32)-4,
- zcolor_Cursor = (uint32)-3,
- zcolor_Current = (uint32)-2,
- zcolor_Default = (uint32)-1
+ zcolor_Transparent = (uint32) - 4,
+ zcolor_Cursor = (uint32) - 3,
+ zcolor_Current = (uint32) - 2,
+ zcolor_Default = (uint32) - 1
};
#ifdef GLK_MODULE_IMAGE
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 8728cdb..329cfb3 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -27,9 +27,9 @@ namespace Gargoyle {
namespace Scott {
Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
- Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
- Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
- split_screen(true), Bottom(0), Top(0), BitFlags(0) {
+ Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
+ Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
+ split_screen(true), Bottom(0), Top(0), BitFlags(0) {
Common::fill(&NounText[0], &NounText[16], '\0');
Common::fill(&Counters[0], &Counters[16], 0);
Common::fill(&RoomSaved[0], &RoomSaved[16], 0);
@@ -107,19 +107,19 @@ Distributed under the GNU software license\n\n");
if (GameHeader.LightTime < 1) {
BitFlags |= (1 << LIGHTOUTBIT);
if (Items[LIGHT_SOURCE].Location == CARRIED ||
- Items[LIGHT_SOURCE].Location == MyLoc) {
- if (Options&SCOTTLIGHT)
+ Items[LIGHT_SOURCE].Location == MyLoc) {
+ if (Options & SCOTTLIGHT)
output("Light has run out! ");
else
output("Your light has run out. ");
}
- if (Options&PREHISTORIC_LAMP)
+ if (Options & PREHISTORIC_LAMP)
Items[LIGHT_SOURCE].Location = DESTROYED;
} else if (GameHeader.LightTime < 25) {
if (Items[LIGHT_SOURCE].Location == CARRIED ||
- Items[LIGHT_SOURCE].Location == MyLoc) {
+ Items[LIGHT_SOURCE].Location == MyLoc) {
- if (Options&SCOTTLIGHT) {
+ if (Options & SCOTTLIGHT) {
output("Light runs out in ");
outputNumber(GameHeader.LightTime);
output(" turns. ");
@@ -208,7 +208,7 @@ int Scott::countCarried(void) {
const char *Scott::mapSynonym(const char *word) {
int n = 1;
const char *tp;
- static char lastword[16]; // Last non synonym
+ static char lastword[16]; // Last non synonym
while (n <= GameHeader.NumWords) {
tp = Nouns[n];
if (*tp == '*')
@@ -231,7 +231,7 @@ int Scott::matchUpItem(const char *text, int loc) {
while (ct <= GameHeader.NumItems) {
if (Items[ct].AutoGet && Items[ct].Location == loc &&
- xstrncasecmp(Items[ct].AutoGet, word, GameHeader.WordLength) == 0)
+ xstrncasecmp(Items[ct].AutoGet, word, GameHeader.WordLength) == 0)
return ct;
ct++;
}
@@ -293,27 +293,27 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
Action *ap;
Room *rp;
Item *ip;
-
+
// Load the header
readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
GameHeader.NumItems = ni;
- Items = (Item *)memAlloc(sizeof(Item)*(ni + 1));
+ Items = (Item *)memAlloc(sizeof(Item) * (ni + 1));
GameHeader.NumActions = na;
- Actions = (Action *)memAlloc(sizeof(Action)*(na + 1));
+ Actions = (Action *)memAlloc(sizeof(Action) * (na + 1));
GameHeader.NumWords = nw;
GameHeader.WordLength = wl;
- Verbs = (const char **)memAlloc(sizeof(char *)*(nw + 1));
- Nouns = (const char **)memAlloc(sizeof(char *)*(nw + 1));
+ Verbs = (const char **)memAlloc(sizeof(char *) * (nw + 1));
+ Nouns = (const char **)memAlloc(sizeof(char *) * (nw + 1));
GameHeader.NumRooms = nr;
- Rooms = (Room *)memAlloc(sizeof(Room)*(nr + 1));
+ Rooms = (Room *)memAlloc(sizeof(Room) * (nr + 1));
GameHeader.MaxCarry = mc;
GameHeader.PlayerRoom = pr;
GameHeader.Treasures = tr;
GameHeader.LightTime = lt;
LightRefill = lt;
GameHeader.NumMessages = mn;
- Messages = (const char **)memAlloc(sizeof(char *)*(mn + 1));
+ Messages = (const char **)memAlloc(sizeof(char *) * (mn + 1));
GameHeader.TreasureRoom = trm;
// Load the actions
@@ -323,14 +323,14 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
debug("Reading %d actions.", na);
while (ct < na + 1) {
readInts(f, 8,
- &ap->Vocab,
- &ap->Condition[0],
- &ap->Condition[1],
- &ap->Condition[2],
- &ap->Condition[3],
- &ap->Condition[4],
- &ap->action[0],
- &ap->action[1]);
+ &ap->Vocab,
+ &ap->Condition[0],
+ &ap->Condition[1],
+ &ap->Condition[2],
+ &ap->Condition[3],
+ &ap->Condition[4],
+ &ap->action[0],
+ &ap->action[1]);
ap++;
ct++;
}
@@ -338,7 +338,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
ct = 0;
if (loud)
debug("Reading %d word pairs.", nw);
- while (ct<nw + 1) {
+ while (ct < nw + 1) {
Verbs[ct] = readString(f);
Nouns[ct] = readString(f);
ct++;
@@ -347,11 +347,11 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
rp = Rooms;
if (loud)
debug("Reading %d rooms.", nr);
- while (ct<nr + 1) {
+ while (ct < nr + 1) {
readInts(f, 6,
- &rp->Exits[0], &rp->Exits[1], &rp->Exits[2],
- &rp->Exits[3], &rp->Exits[4], &rp->Exits[5]);
-
+ &rp->Exits[0], &rp->Exits[1], &rp->Exits[2],
+ &rp->Exits[3], &rp->Exits[4], &rp->Exits[5]);
+
rp->Text = readString(f);
ct++;
rp++;
@@ -360,7 +360,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
ct = 0;
if (loud)
debug("Reading %d messages.", mn);
- while (ct<mn + 1) {
+ while (ct < mn + 1) {
Messages[ct] = readString(f);
ct++;
}
@@ -389,7 +389,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
}
ct = 0;
// Discard Comment Strings
- while (ct<na + 1) {
+ while (ct < na + 1) {
free(readString(f));
ct++;
}
@@ -420,9 +420,9 @@ void Scott::look(void) {
if (split_screen)
glk_window_clear(Top);
- if ((BitFlags&(1 << DARKBIT)) && Items[LIGHT_SOURCE].Location != CARRIED
- && Items[LIGHT_SOURCE].Location != MyLoc) {
- if (Options&YOUARE)
+ if ((BitFlags & (1 << DARKBIT)) && Items[LIGHT_SOURCE].Location != CARRIED
+ && Items[LIGHT_SOURCE].Location != MyLoc) {
+ if (Options & YOUARE)
display(Top, "You can't see. It is too dark!\n");
else
display(Top, "I can't see. It is too dark!\n");
@@ -434,7 +434,7 @@ void Scott::look(void) {
if (*r->Text == '*')
display(Top, "%s\n", r->Text + 1);
else {
- if (Options&YOUARE)
+ if (Options & YOUARE)
display(Top, "You are in a %s\n", r->Text);
else
display(Top, "I'm in a %s\n", r->Text);
@@ -443,9 +443,8 @@ void Scott::look(void) {
ct = 0;
f = 0;
display(Top, "\nObvious exits: ");
- while (ct<6) {
- if (r->Exits[ct] != 0)
- {
+ while (ct < 6) {
+ if (r->Exits[ct] != 0) {
if (f == 0)
f = 1;
else
@@ -532,7 +531,7 @@ void Scott::lineInput(char *buf, size_t n) {
void Scott::saveGame(void) {
frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
- filemode_Write, 0);
+ filemode_Write, 0);
if (ref == nullptr)
return;
@@ -557,8 +556,8 @@ Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
}
msg = Common::String::format("%lu %d %hd %d %d %hd\n",
- BitFlags, (BitFlags&(1 << DARKBIT)) ? 1 : 0,
- MyLoc, CurrentCounter, SavedRoom, GameHeader.LightTime);
+ BitFlags, (BitFlags & (1 << DARKBIT)) ? 1 : 0,
+ MyLoc, CurrentCounter, SavedRoom, GameHeader.LightTime);
glk_put_string_stream(file, msg.c_str());
for (int ct = 0; ct <= GameHeader.NumItems; ct++) {
@@ -574,7 +573,7 @@ Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
void Scott::loadGame(void) {
frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
- filemode_Read, 0);
+ filemode_Read, 0);
if (ref == nullptr)
return;
@@ -597,15 +596,15 @@ Common::Error Scott::loadGameState(int slot) {
if (file == nullptr)
return Common::kReadingFailed;
- for (ct = 0; ct<16; ct++) {
+ for (ct = 0; ct < 16; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%d %d", &Counters[ct], &RoomSaved[ct]);
}
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%ld %hd %d %d %d %d\n",
- &BitFlags, &darkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
- &GameHeader.LightTime);
+ &BitFlags, &darkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
+ &GameHeader.LightTime);
// Backward compatibility
if (darkFlag)
@@ -634,7 +633,7 @@ int Scott::getInput(int *vb, int *no) {
num = sscanf(buf, "%9s %9s", verb, noun);
} while (num == 0 || *buf == '\n');
-
+
if (xstrcasecmp(verb, "restore") == 0) {
loadGame();
return -1;
@@ -643,14 +642,28 @@ int Scott::getInput(int *vb, int *no) {
*noun = 0;
if (*noun == 0 && strlen(verb) == 1) {
switch (Common::isUpper((unsigned char)*verb) ? tolower((unsigned char)*verb) : *verb) {
- case 'n':strcpy(verb, "NORTH"); break;
- case 'e':strcpy(verb, "EAST"); break;
- case 's':strcpy(verb, "SOUTH"); break;
- case 'w':strcpy(verb, "WEST"); break;
- case 'u':strcpy(verb, "UP"); break;
- case 'd':strcpy(verb, "DOWN"); break;
+ case 'n':
+ strcpy(verb, "NORTH");
+ break;
+ case 'e':
+ strcpy(verb, "EAST");
+ break;
+ case 's':
+ strcpy(verb, "SOUTH");
+ break;
+ case 'w':
+ strcpy(verb, "WEST");
+ break;
+ case 'u':
+ strcpy(verb, "UP");
+ break;
+ case 'd':
+ strcpy(verb, "DOWN");
+ break;
// Brian Howarth interpreter also supports this
- case 'i':strcpy(verb, "INVENTORY"); break;
+ case 'i':
+ strcpy(verb, "INVENTORY");
+ break;
}
}
nc = whichWord(verb, Nouns);
@@ -668,7 +681,7 @@ int Scott::getInput(int *vb, int *no) {
}
} while (vc == -1);
- strcpy(NounText, noun); // Needed by GET/DROP hack
+ strcpy(NounText, noun); // Needed by GET/DROP hack
return 0;
}
@@ -678,7 +691,7 @@ int Scott::performLine(int ct) {
int act[4];
int cc = 0;
- while (cc<5) {
+ while (cc < 5) {
int cv, dv;
cv = Actions[ct].Condition[cc];
dv = cv / 20;
@@ -696,8 +709,8 @@ int Scott::performLine(int ct) {
return 0;
break;
case 3:
- if (Items[dv].Location != CARRIED&&
- Items[dv].Location != MyLoc)
+ if (Items[dv].Location != CARRIED &&
+ Items[dv].Location != MyLoc)
return 0;
break;
case 4:
@@ -717,11 +730,11 @@ int Scott::performLine(int ct) {
return 0;
break;
case 8:
- if ((BitFlags&(1 << dv)) == 0)
+ if ((BitFlags & (1 << dv)) == 0)
return 0;
break;
case 9:
- if (BitFlags&(1 << dv))
+ if (BitFlags & (1 << dv))
return 0;
break;
case 10:
@@ -745,7 +758,7 @@ int Scott::performLine(int ct) {
return 0;
break;
case 15:
- if (CurrentCounter>dv)
+ if (CurrentCounter > dv)
return 0;
break;
case 16:
@@ -778,8 +791,7 @@ int Scott::performLine(int ct) {
act[2] /= 150;
cc = 0;
pptr = 0;
- while (cc<4)
- {
+ while (cc < 4) {
if (act[cc] >= 1 && act[cc] < 52) {
output(Messages[act[cc]]);
output("\n");
@@ -825,7 +837,7 @@ int Scott::performLine(int ct) {
BitFlags &= ~(1 << param[pptr++]);
break;
case 61:
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You are dead.\n");
else
output("I am dead.\n");
@@ -850,11 +862,11 @@ doneit:
int n = 0;
while (i <= GameHeader.NumItems) {
if (Items[i].Location == GameHeader.TreasureRoom &&
- *Items[i].Text == '*')
+ *Items[i].Text == '*')
n++;
i++;
}
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You have stored ");
else
output("I've stored ");
@@ -871,7 +883,7 @@ doneit:
case 66: {
int i = 0;
int f = 0;
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You are carrying:\n");
else
output("I'm carrying:\n");
@@ -999,7 +1011,7 @@ doneit:
break;
default:
error("Unknown action %d [Param begins %d %d]\n",
- act[cc], param[pptr], param[pptr + 1]);
+ act[cc], param[pptr], param[pptr + 1]);
break;
}
}
@@ -1011,8 +1023,8 @@ doneit:
}
int Scott::performActions(int vb, int no) {
- static int disable_sysfunc = 0; // Recursion lock
- int d = BitFlags&(1 << DARKBIT);
+ static int disable_sysfunc = 0; // Recursion lock
+ int d = BitFlags & (1 << DARKBIT);
int ct = 0;
int fl;
@@ -1024,7 +1036,7 @@ int Scott::performActions(int vb, int no) {
if (vb == 1 && no >= 1 && no <= 6) {
int nl;
if (Items[LIGHT_SOURCE].Location == MyLoc ||
- Items[LIGHT_SOURCE].Location == CARRIED)
+ Items[LIGHT_SOURCE].Location == CARRIED)
d = 0;
if (d)
output("Dangerous to move in the dark! ");
@@ -1034,13 +1046,13 @@ int Scott::performActions(int vb, int no) {
return 0;
}
if (d) {
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You fell down and broke your neck. ");
else
output("I fell down and broke my neck. ");
glk_exit();
}
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You can't go in that direction. ");
else
output("I can't go in that direction. ");
@@ -1053,16 +1065,16 @@ int Scott::performActions(int vb, int no) {
vv = Actions[ct].Vocab;
// Think this is now right. If a line we run has an action73
// run all following lines with vocab of 0,0
- if (vb != 0 && (doagain&&vv != 0))
+ if (vb != 0 && (doagain && vv != 0))
break;
// Oops.. added this minor cockup fix 1.11
if (vb != 0 && !doagain && fl == 0)
break;
nv = vv % 150;
vv /= 150;
- if ((vv == vb) || (doagain&&Actions[ct].Vocab == 0)) {
+ if ((vv == vb) || (doagain && Actions[ct].Vocab == 0)) {
if ((vv == 0 && randomPercent(nv)) || doagain ||
- (vv != 0 && (nv == no || nv == 0))) {
+ (vv != 0 && (nv == no || nv == 0))) {
int f2;
if (fl == -1)
fl = -2;
@@ -1088,7 +1100,7 @@ int Scott::performActions(int vb, int no) {
if (fl != 0 && disable_sysfunc == 0) {
int item;
if (Items[LIGHT_SOURCE].Location == MyLoc ||
- Items[LIGHT_SOURCE].Location == CARRIED)
+ Items[LIGHT_SOURCE].Location == CARRIED)
d = 0;
if (vb == 10 || vb == 18) {
// Yes they really _are_ hardcoded values
@@ -1104,11 +1116,11 @@ int Scott::performActions(int vb, int no) {
while (i <= GameHeader.NumItems) {
if (Items[i].Location == MyLoc && Items[i].AutoGet != nullptr && Items[i].AutoGet[0] != '*') {
no = whichWord(Items[i].AutoGet, Nouns);
- disable_sysfunc = 1; // Don't recurse into auto get !
- performActions(vb, no); // Recursively check each items table code
+ disable_sysfunc = 1; // Don't recurse into auto get !
+ performActions(vb, no); // Recursively check each items table code
disable_sysfunc = 0;
if (countCarried() == GameHeader.MaxCarry) {
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You are carrying too much. ");
else
output("I've too much to carry. ");
@@ -1130,7 +1142,7 @@ int Scott::performActions(int vb, int no) {
return 0;
}
if (countCarried() == GameHeader.MaxCarry) {
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("You are carrying too much. ");
else
output("I've too much to carry. ");
@@ -1138,7 +1150,7 @@ int Scott::performActions(int vb, int no) {
}
item = matchUpItem(NounText, MyLoc);
if (item == -1) {
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("It is beyond your power to do that. ");
else
output("It's beyond my power to do that. ");
@@ -1175,7 +1187,7 @@ int Scott::performActions(int vb, int no) {
}
item = matchUpItem(NounText, CARRIED);
if (item == -1) {
- if (Options&YOUARE)
+ if (Options & YOUARE)
output("It's beyond your power to do that.\n");
else
output("It's beyond my power to do that.\n");
@@ -1193,8 +1205,8 @@ int Scott::performActions(int vb, int no) {
int Scott::xstrcasecmp(const char *s1, const char *s2) {
const unsigned char
- *us1 = (const unsigned char *)s1,
- *us2 = (const unsigned char *)s2;
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
while (tolower(*us1) == tolower(*us2++))
if (*us1++ == '\0')
@@ -1205,8 +1217,8 @@ int Scott::xstrcasecmp(const char *s1, const char *s2) {
int Scott::xstrncasecmp(const char *s1, const char *s2, size_t n) {
if (n != 0) {
const unsigned char
- *us1 = (const unsigned char *)s1,
- *us2 = (const unsigned char *)s2;
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
do {
if (tolower(*us1) != tolower(*us2++))
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index 81847cc..0ff8d33 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -24,7 +24,7 @@
#define GARGOYLE_SCOTT
/*
- * Controlling block
+ * Controlling block
*/
#include "common/scummsys.h"
@@ -33,28 +33,28 @@
namespace Gargoyle {
namespace Scott {
-#define LIGHT_SOURCE 9 // Always 9 how odd
-#define CARRIED 255 // Carried
-#define DESTROYED 0 // Destroyed
-#define DARKBIT 15
-#define LIGHTOUTBIT 16 // Light gone out
+#define LIGHT_SOURCE 9 // Always 9 how odd
+#define CARRIED 255 // Carried
+#define DESTROYED 0 // Destroyed
+#define DARKBIT 15
+#define LIGHTOUTBIT 16 // Light gone out
enum GameOption {
- YOUARE = 1, ///< You are not I am
- SCOTTLIGHT = 2, ///< Authentic Scott Adams light messages
- DEBUGGING = 4, ///< Info from database load
- TRS80_STYLE = 8, ///< Display in style used on TRS-80
- PREHISTORIC_LAMP = 16 ///< Destroy the lamp (very old databases)
+ YOUARE = 1, ///< You are not I am
+ SCOTTLIGHT = 2, ///< Authentic Scott Adams light messages
+ DEBUGGING = 4, ///< Info from database load
+ TRS80_STYLE = 8, ///< Display in style used on TRS-80
+ PREHISTORIC_LAMP = 16 ///< Destroy the lamp (very old databases)
};
-#define TRS80_LINE "\n<------------------------------------------------------------>\n"
-#define MyLoc (GameHeader.PlayerRoom)
+#define TRS80_LINE "\n<------------------------------------------------------------>\n"
+#define MyLoc (GameHeader.PlayerRoom)
struct Header {
- int Unknown;
+ int Unknown;
int NumItems;
int NumActions;
- int NumWords; ///< Smaller of verb/noun is padded to same size
+ int NumWords; ///< Smaller of verb/noun is padded to same size
int NumRooms;
int MaxCarry;
int PlayerRoom;
@@ -90,7 +90,7 @@ struct Room {
};
struct Item {
- char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
+ char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
byte Location;
byte InitialLoc;
char *AutoGet;
@@ -125,7 +125,7 @@ private:
int SavedRoom;
int RoomSaved[16]; ///< Range unknown
int Options; ///< Option flags set
- int Width; ///< Terminal width
+ int Width; ///< Terminal width
int TopHeight; ///< Height of top window
bool split_screen;
diff --git a/engines/gargoyle/screen.h b/engines/gargoyle/screen.h
index d7631ef..aa43b1b 100644
--- a/engines/gargoyle/screen.h
+++ b/engines/gargoyle/screen.h
@@ -54,8 +54,8 @@ public:
/**
* Draws the text input caret at the given position
- * @remarks The position specifies the caret's bottom-left corner,
- * and the X position is in multiples of GLI_SUBPIX
+ * @remarks The position specifies the caret's bottom-left corner,
+ * and the X position is in multiples of GLI_SUBPIX
*/
void drawCaret(const Point &pos);
};
diff --git a/engines/gargoyle/selection.cpp b/engines/gargoyle/selection.cpp
index 8ad3b76..27cfbe7 100644
--- a/engines/gargoyle/selection.cpp
+++ b/engines/gargoyle/selection.cpp
@@ -112,9 +112,9 @@ void WindowMask::putHyperlink(glui32 linkval, uint x0, uint y0, uint x1, uint y1
}
if (tx0 >= _hor
- || tx1 >= _hor
- || ty0 >= _ver || ty1 >= _ver
- || !_links[tx0] || !_links[tx1]) {
+ || tx1 >= _hor
+ || ty0 >= _ver || ty1 >= _ver
+ || !_links[tx0] || !_links[tx1]) {
warning("putHyperlink: invalid range given");
return;
}
@@ -190,7 +190,7 @@ void Selection::clearSelection() {
bool Selection::checkSelection(const Rect &r) const {
Rect select(MIN(_select.left, _select.right), MAX(_select.left, _select.right),
- MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom));
+ MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom));
if (select.isEmpty())
return false;
@@ -218,7 +218,7 @@ bool Selection::getSelection(const Rect &r, int *rx0, int *rx1) const {
row_selected = false;
if ((cy0 >= upper && cy0 <= lower)
- || (cy1 >= upper && cy1 <= lower))
+ || (cy1 >= upper && cy1 <= lower))
row_selected = true;
if (row >= cy0 && row <= cy1)
diff --git a/engines/gargoyle/selection.h b/engines/gargoyle/selection.h
index 2d3a208..a82af6d 100644
--- a/engines/gargoyle/selection.h
+++ b/engines/gargoyle/selection.h
@@ -92,13 +92,13 @@ class Selection : public Clipboard, public WindowMask {
public:
/**
* Start selecting an area of the screen
- * @param pos Position to start selection area at
+ * @param pos Position to start selection area at
*/
void startSelection(const Point &pos);
/**
* Move the end point of the selection area
- * @param pos Position to end selection area at
+ * @param pos Position to end selection area at
*/
void moveSelection(const Point &pos);
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index b301272..75fb205 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -33,8 +33,8 @@
namespace Gargoyle {
Stream::Stream(Streams *streams, bool readable, bool writable, uint32 rock, bool unicode) :
- _streams(streams), _readable(readable), _writable(writable), _readCount(0),
- _writeCount(0), _prev(nullptr), _next(nullptr), _rock(0) {
+ _streams(streams), _readable(readable), _writable(writable), _readCount(0),
+ _writeCount(0), _prev(nullptr), _next(nullptr), _rock(0) {
}
Stream::~Stream() {
@@ -174,7 +174,7 @@ void WindowStream::unputBuffer(const char *buf, size_t len) {
}
}
- for (lx = 0, cx = buf + len - 1; lx<len; lx++, cx--) {
+ for (lx = 0, cx = buf + len - 1; lx < len; lx++, cx--) {
if (!_window->unputCharUni(*cx))
break;
_writeCount--;
@@ -200,7 +200,7 @@ void WindowStream::unputBufferUni(const glui32 *buf, size_t len) {
}
}
- for (lx = 0, cx = buf + len - 1; lx<len; lx++, cx--) {
+ for (lx = 0, cx = buf + len - 1; lx < len; lx++, cx--) {
if (!_window->unputCharUni(*cx))
break;
_writeCount--;
@@ -245,7 +245,7 @@ void WindowStream::setZColors(glui32 fg, glui32 bg) {
_window->_attr.fgcolor = 0;
Windows::_overrideFgSet = false;
Windows::_overrideFgVal = 0;
-
+
Common::copy(g_conf->_moreSave, g_conf->_moreSave + 3, g_conf->_moreColor);
Common::copy(g_conf->_caretSave, g_conf->_caretSave + 3, g_conf->_caretColor);
Common::copy(g_conf->_linkSave, g_conf->_linkSave + 3, g_conf->_linkColor);
@@ -254,7 +254,7 @@ void WindowStream::setZColors(glui32 fg, glui32 bg) {
_window->_attr.fgcolor = fg;
Windows::_overrideFgSet = true;
Windows::_overrideFgVal = fg;
-
+
Common::copy(fore, fore + 3, g_conf->_moreColor);
Common::copy(fore, fore + 3, g_conf->_caretColor);
Common::copy(fore, fore + 3, g_conf->_linkColor);
@@ -302,8 +302,8 @@ void WindowStream::setReverseVideo(bool reverse) {
/*--------------------------------------------------------------------------*/
MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) :
- Stream(streams, mode != filemode_Write, mode != filemode_Read, rock, unicode),
- _buf(buf), _bufLen(buflen), _bufPtr(buf) {
+ Stream(streams, 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);
@@ -363,8 +363,7 @@ void MemoryStream::putBuffer(const char *buf, size_t len) {
} else {
if (!_unicode) {
unsigned char *bp = (unsigned char *)_bufPtr;
- if (bp + len > (unsigned char *)_bufEnd)
- {
+ if (bp + len > (unsigned char *)_bufEnd) {
lx = (bp + len) - (unsigned char *)_bufEnd;
if (lx < len)
len -= lx;
@@ -374,7 +373,7 @@ void MemoryStream::putBuffer(const char *buf, size_t len) {
if (len) {
memmove(bp, buf, len);
bp += len;
- if (bp >(unsigned char *)_bufEof)
+ if (bp > (unsigned char *)_bufEof)
_bufEof = bp;
}
_bufPtr = bp;
@@ -392,7 +391,7 @@ void MemoryStream::putBuffer(const char *buf, size_t len) {
for (i = 0; i < len; i++)
bp[i] = buf[i];
bp += len;
- if (bp >(glui32 *)_bufEof)
+ if (bp > (glui32 *)_bufEof)
_bufEof = bp;
}
_bufPtr = bp;
@@ -444,7 +443,7 @@ void MemoryStream::putBufferUni(const uint32 *buf, size_t len) {
if (len) {
memmove(bp, buf, len * 4);
bp += len;
- if (bp >(glui32 *)_bufEof)
+ if (bp > (glui32 *)_bufEof)
_bufEof = bp;
}
_bufPtr = bp;
@@ -460,8 +459,7 @@ glui32 MemoryStream::getPosition() const {
}
void MemoryStream::setPosition(glui32 pos, glui32 seekMode) {
- if (!_unicode)
- {
+ if (!_unicode) {
if (seekMode == seekmode_Current)
pos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + pos;
else if (seekMode == seekmode_End)
@@ -556,7 +554,7 @@ glui32 MemoryStream::getBuffer(char *buf, glui32 len) {
if (len) {
memcpy(buf, bp, len);
bp += len;
- if (bp >(unsigned char *)_bufEof)
+ if (bp > (unsigned char *)_bufEof)
_bufEof = bp;
}
@@ -601,8 +599,7 @@ glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
} else {
if (!_unicode) {
unsigned char *bp = (unsigned char *)_bufPtr;
- if (bp + len > (unsigned char *)_bufEnd)
- {
+ if (bp + len > (unsigned char *)_bufEnd) {
glui32 lx;
lx = (bp + len) - (unsigned char *)_bufEnd;
if (lx < len)
@@ -615,7 +612,7 @@ glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
for (i = 0; i < len; i++)
buf[i] = bp[i];
bp += len;
- if (bp >(unsigned char *)_bufEof)
+ if (bp > (unsigned char *)_bufEof)
_bufEof = bp;
}
_readCount += len;
@@ -633,7 +630,7 @@ glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) {
if (len) {
memcpy(buf, bp, len * 4);
bp += len;
- if (bp >(glui32 *)_bufEof)
+ if (bp > (glui32 *)_bufEof)
_bufEof = bp;
}
_readCount += len;
@@ -761,8 +758,8 @@ glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) {
/*--------------------------------------------------------------------------*/
FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode) :
- Stream(streams, fmode == filemode_Read, fmode != filemode_Read, rock, unicode), _lastOp(0),
- _textFile(fref->_textMode), _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) {
+ Stream(streams, fmode == filemode_Read, fmode != filemode_Read, rock, unicode), _lastOp(0),
+ _textFile(fref->_textMode), _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) {
Common::String fname = fref->_slotNumber == -1 ? fref->_filename : fref->getSaveName();
if (fmode == filemode_Write || fmode == filemode_ReadWrite || fmode == filemode_WriteAppend) {
@@ -789,7 +786,7 @@ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 roc
if (!readSavegameHeader(_inStream, header))
error("Invalid savegame");
if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
- || header._md5 != g_vm->getGameMD5())
+ || header._md5 != g_vm->getGameMD5())
error("Savegame is for a different game");
g_vm->_events->setTotalPlayTicks(header._totalFrames);
@@ -873,7 +870,7 @@ void FileStream::putBufferUni(const uint32 *buf, size_t len) {
ensureOp(filemode_Write);
- for (size_t lx = 0; lx<len; lx++) {
+ for (size_t lx = 0; lx < len; lx++) {
glui32 ch = buf[lx];
if (!_unicode) {
if (ch >= 0x100)
@@ -1005,7 +1002,7 @@ void FileStream::setPosition(glui32 pos, glui32 seekMode) {
_lastOp = 0;
if (_unicode)
pos *= 4;
-
+
if (_inStream) {
_inStream->seek(pos, SEEK_SET);
} else {
@@ -1100,7 +1097,7 @@ glui32 FileStream::getBuffer(char *buf, glui32 len) {
return res;
} else if (_textFile) {
glui32 lx;
- for (lx = 0; lx<len; lx++) {
+ for (lx = 0; lx < len; lx++) {
glui32 ch;
ch = getCharUtf8();
if (ch == -1)
@@ -1148,7 +1145,7 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
ensureOp(filemode_Read);
if (!_unicode) {
glui32 lx;
- for (lx = 0; lx<len; lx++) {
+ for (lx = 0; lx < len; lx++) {
int res;
glui32 ch;
res = _inStream->readByte();
@@ -1161,7 +1158,7 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
return lx;
} else if (_textFile) {
glui32 lx;
- for (lx = 0; lx<len; lx++) {
+ for (lx = 0; lx < len; lx++) {
glui32 ch;
ch = getCharUtf8();
if (ch == -1)
@@ -1172,8 +1169,7 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
return lx;
} else {
glui32 lx;
- for (lx = 0; lx<len; lx++)
- {
+ for (lx = 0; lx < len; lx++) {
int res;
glui32 ch;
res = _inStream->readByte();
@@ -1477,8 +1473,7 @@ frefid_t Streams::createByPrompt(glui32 usage, FileMode fmode, glui32 rock) {
Common::String desc = dialog->getResultString();
return createRef(slot, desc, usage, rock);
}
- }
- else if (fmode == filemode_Read) {
+ } else if (fmode == filemode_Read) {
// Load a savegame slot
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
@@ -1486,8 +1481,7 @@ frefid_t Streams::createByPrompt(glui32 usage, FileMode fmode, glui32 rock) {
if (slot >= 0) {
return createRef(slot, "", usage, rock);
}
- }
- else {
+ } else {
error("Unsupport file mode");
}
break;
@@ -1527,7 +1521,7 @@ frefid_t Streams::createRef(const Common::String &filename, glui32 usage, glui32
frefid_t Streams::createTemp(glui32 usage, glui32 rock) {
return createRef(Common::String::format("%s.tmp", g_vm->getTargetName().c_str()),
- usage, rock);
+ usage, rock);
}
frefid_t Streams::createFromRef(frefid_t fref, glui32 usage, glui32 rock) {
@@ -1579,8 +1573,7 @@ bool FileReference::exists() const {
if (Common::File::exists(_filename))
return true;
filename = _filename;
- }
- else {
+ } else {
filename = getSaveName();
}
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index c8b6963..8a497e0 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -159,7 +159,9 @@ public:
/**
* Get the rock value for the stream
*/
- uint32 getRock() const { return _rock; }
+ uint32 getRock() const {
+ return _rock;
+ }
/**
* Fill out the total amount read and/or written
@@ -217,7 +219,9 @@ public:
putCharUni('\n');
}
- virtual glui32 getPosition() const { return 0; }
+ virtual glui32 getPosition() const {
+ return 0;
+ }
virtual void setPosition(glui32 pos, glui32 seekMode) {}
@@ -226,32 +230,44 @@ public:
/**
* Get a character from the stream
*/
- virtual glsi32 getChar() { return -1; }
+ virtual glsi32 getChar() {
+ return -1;
+ }
/**
* Get a unicode character from the stream
*/
- virtual glsi32 getCharUni() { return -1; }
+ virtual glsi32 getCharUni() {
+ return -1;
+ }
/**
* Get a buffer
*/
- virtual glui32 getBuffer(char *buf, glui32 len) { return 0; }
+ virtual glui32 getBuffer(char *buf, glui32 len) {
+ return 0;
+ }
/**
* Get a unicode buffer
*/
- virtual glui32 getBufferUni(glui32 *buf, glui32 len) { return 0; }
+ virtual glui32 getBufferUni(glui32 *buf, glui32 len) {
+ return 0;
+ }
/**
* Get a line
*/
- virtual glui32 getLine(char *buf, glui32 len) { return 0; }
+ virtual glui32 getLine(char *buf, glui32 len) {
+ return 0;
+ }
/**
* Get a unicode line
*/
- virtual glui32 getLineUni(glui32 *ubuf, glui32 len) { return 0; }
+ virtual glui32 getLineUni(glui32 *ubuf, glui32 len) {
+ return 0;
+ }
/**
* Set a hyperlink
@@ -341,11 +357,11 @@ public:
*/
class MemoryStream : public Stream {
private:
- void *_buf; ///< unsigned char* for latin1, glui32* for unicode
+ 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
+ size_t _bufLen; ///< # of bytes for latin1, # of 4-byte words for unicode
public:
/**
* Constructor
@@ -416,7 +432,7 @@ private:
Common::OutSaveFile *_outFile;
Common::InSaveFile *_inFile;
Common::SeekableReadStream *_inStream;
- uint32 _lastOp; ///< 0, filemode_Write, or filemode_Read
+ uint32 _lastOp; ///< 0, filemode_Write, or filemode_Read
bool _textFile;
private:
/**
@@ -577,7 +593,9 @@ public:
/**
* Gets the current output stream
*/
- Stream *getCurrent() const { return _currentStream; }
+ Stream *getCurrent() const {
+ return _currentStream;
+ }
/**
* Prompt for a savegame to load or save, and populate a file reference from the result
diff --git a/engines/gargoyle/unicode.cpp b/engines/gargoyle/unicode.cpp
index c783915..f32093b 100644
--- a/engines/gargoyle/unicode.cpp
+++ b/engines/gargoyle/unicode.cpp
@@ -34,7 +34,7 @@ size_t strlen_uni(const uint32 *s) {
}
glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCase destcase,
- BufferChangeCond cond, int changerest) {
+ BufferChangeCond cond, int changerest) {
glui32 ix, jx;
glui32 *outbuf;
glui32 *newoutbuf;
@@ -92,8 +92,7 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
res = block[ch & 0xFF][target];
}
- if (res != 0xFFFFFFFF || res == ch)
- {
+ if (res != 0xFFFFFFFF || res == ch) {
/* simple case */
if (outcount < len)
outbuf[outcount] = res;
@@ -130,7 +129,7 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
outbuf = newoutbuf;
}
- for (jx = 0; jx<speccount; jx++) {
+ for (jx = 0; jx < speccount; jx++) {
if (outcount < len)
outbuf[outcount] = ptr[jx];
outcount++;
diff --git a/engines/gargoyle/unicode.h b/engines/gargoyle/unicode.h
index 2392c1a..e9fa928 100644
--- a/engines/gargoyle/unicode.h
+++ b/engines/gargoyle/unicode.h
@@ -44,7 +44,7 @@ size_t strlen_uni(const uint32 *s);
*converted string should have contained.
*/
extern glui32 bufferChangeCase(glui32 *buf, glui32 len,
- glui32 numchars, BufferChangeCase destcase, BufferChangeCond cond, int changerest);
+ glui32 numchars, BufferChangeCase destcase, BufferChangeCond cond, int changerest);
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/unicode_gen.cpp b/engines/gargoyle/unicode_gen.cpp
index c9ad570..56e44c3 100644
--- a/engines/gargoyle/unicode_gen.cpp
+++ b/engines/gargoyle/unicode_gen.cpp
@@ -3861,3325 +3861,3325 @@ gli_case_special_t unigen_special_0xfb16 = { 857, 860, 862 };
gli_case_special_t unigen_special_0xfb17 = { 865, 868, 870 };
#define RETURN_COMBINING_CLASS(ch) \
-switch ((glui32)(ch) >> 8) { \
-case 3: \
-switch (ch) { \
- case 820: \
- case 821: \
- case 822: \
- case 823: \
- case 824: \
- return 1; \
- case 801: \
- case 802: \
- case 807: \
- case 808: \
- return 202; \
- case 795: \
- return 216; \
- case 790: \
- case 791: \
- case 792: \
- case 793: \
- case 796: \
- case 797: \
- case 798: \
- case 799: \
- case 800: \
- case 803: \
- case 804: \
- case 805: \
- case 806: \
- case 809: \
- case 810: \
- case 811: \
- case 812: \
- case 813: \
- case 814: \
- case 815: \
- case 816: \
- case 817: \
- case 818: \
- case 819: \
- case 825: \
- case 826: \
- case 827: \
- case 828: \
- case 839: \
- case 840: \
- case 841: \
- case 845: \
- case 846: \
- case 851: \
- case 852: \
- case 853: \
- case 854: \
- return 220; \
- case 768: \
- case 769: \
- case 770: \
- case 771: \
- case 772: \
- case 773: \
- case 774: \
- case 775: \
- case 776: \
- case 777: \
- case 778: \
- case 779: \
- case 780: \
- case 781: \
- case 782: \
- case 783: \
- case 784: \
- case 785: \
- case 786: \
- case 787: \
- case 788: \
- case 829: \
- case 830: \
- case 831: \
- case 832: \
- case 833: \
- case 834: \
- case 835: \
- case 836: \
- case 838: \
- case 842: \
- case 843: \
- case 844: \
- case 848: \
- case 849: \
- case 850: \
- case 855: \
- case 867: \
- case 868: \
- case 869: \
- case 870: \
- case 871: \
- case 872: \
- case 873: \
- case 874: \
- case 875: \
- case 876: \
- case 877: \
- case 878: \
- case 879: \
- return 230; \
- case 789: \
- case 794: \
- return 232; \
- case 863: \
- case 866: \
- return 233; \
- case 861: \
- case 862: \
- case 864: \
- case 865: \
- return 234; \
- case 837: \
- return 240; \
-} \
-return 0; \
-case 4: \
-switch (ch) { \
- case 1155: \
- case 1156: \
- case 1157: \
- case 1158: \
- return 230; \
-} \
-return 0; \
-case 5: \
-switch (ch) { \
- case 1456: \
- return 10; \
- case 1457: \
- return 11; \
- case 1458: \
- return 12; \
- case 1459: \
- return 13; \
- case 1460: \
- return 14; \
- case 1461: \
- return 15; \
- case 1462: \
- return 16; \
- case 1463: \
- return 17; \
- case 1464: \
- return 18; \
- case 1465: \
- return 19; \
- case 1467: \
- return 20; \
- case 1468: \
- return 21; \
- case 1469: \
- return 22; \
- case 1471: \
- return 23; \
- case 1473: \
- return 24; \
- case 1474: \
- return 25; \
- case 1425: \
- case 1430: \
- case 1435: \
- case 1443: \
- case 1444: \
- case 1445: \
- case 1446: \
- case 1447: \
- case 1450: \
- return 220; \
- case 1434: \
- case 1453: \
- return 222; \
- case 1454: \
- return 228; \
- case 1426: \
- case 1427: \
- case 1428: \
- case 1429: \
- case 1431: \
- case 1432: \
- case 1433: \
- case 1436: \
- case 1437: \
- case 1438: \
- case 1439: \
- case 1440: \
- case 1441: \
- case 1448: \
- case 1449: \
- case 1451: \
- case 1452: \
- case 1455: \
- case 1476: \
- return 230; \
-} \
-return 0; \
-case 6: \
-switch (ch) { \
- case 1611: \
- return 27; \
- case 1612: \
- return 28; \
- case 1613: \
- return 29; \
- case 1614: \
- return 30; \
- case 1615: \
- return 31; \
- case 1616: \
- return 32; \
- case 1617: \
- return 33; \
- case 1618: \
- return 34; \
- case 1648: \
- return 35; \
- case 1621: \
- case 1622: \
- case 1763: \
- case 1770: \
- case 1773: \
- return 220; \
- case 1552: \
- case 1553: \
- case 1554: \
- case 1555: \
- case 1556: \
- case 1557: \
- case 1619: \
- case 1620: \
- case 1623: \
- case 1624: \
- case 1750: \
- case 1751: \
- case 1752: \
- case 1753: \
- case 1754: \
- case 1755: \
- case 1756: \
- case 1759: \
- case 1760: \
- case 1761: \
- case 1762: \
- case 1764: \
- case 1767: \
- case 1768: \
- case 1771: \
- case 1772: \
- return 230; \
-} \
-return 0; \
-case 7: \
-switch (ch) { \
- case 1809: \
- return 36; \
- case 1841: \
- case 1844: \
- case 1847: \
- case 1848: \
- case 1849: \
- case 1851: \
- case 1852: \
- case 1854: \
- case 1858: \
- case 1860: \
- case 1862: \
- case 1864: \
- return 220; \
- case 1840: \
- case 1842: \
- case 1843: \
- case 1845: \
- case 1846: \
- case 1850: \
- case 1853: \
- case 1855: \
- case 1856: \
- case 1857: \
- case 1859: \
- case 1861: \
- case 1863: \
- case 1865: \
- case 1866: \
- return 230; \
-} \
-return 0; \
-case 9: \
-switch (ch) { \
- case 2364: \
- case 2492: \
- return 7; \
- case 2381: \
- case 2509: \
- return 9; \
- case 2386: \
- return 220; \
- case 2385: \
- case 2387: \
- case 2388: \
- return 230; \
-} \
-return 0; \
-case 10: \
-switch (ch) { \
- case 2620: \
- case 2748: \
- return 7; \
- case 2637: \
- case 2765: \
- return 9; \
-} \
-return 0; \
-case 11: \
-switch (ch) { \
- case 2876: \
- return 7; \
- case 2893: \
- case 3021: \
- return 9; \
-} \
-return 0; \
-case 12: \
-switch (ch) { \
- case 3260: \
- return 7; \
- case 3149: \
- case 3277: \
- return 9; \
- case 3157: \
- return 84; \
- case 3158: \
- return 91; \
-} \
-return 0; \
-case 13: \
-switch (ch) { \
- case 3405: \
- case 3530: \
- return 9; \
-} \
-return 0; \
-case 14: \
-switch (ch) { \
- case 3642: \
- return 9; \
- case 3640: \
- case 3641: \
- return 103; \
- case 3656: \
- case 3657: \
- case 3658: \
- case 3659: \
- return 107; \
- case 3768: \
- case 3769: \
- return 118; \
- case 3784: \
- case 3785: \
- case 3786: \
- case 3787: \
- return 122; \
-} \
-return 0; \
-case 15: \
-switch (ch) { \
- case 3972: \
- return 9; \
- case 3953: \
- return 129; \
- case 3954: \
- case 3962: \
- case 3963: \
- case 3964: \
- case 3965: \
- case 3968: \
- return 130; \
- case 3956: \
- return 132; \
- case 3897: \
- return 216; \
- case 3864: \
- case 3865: \
- case 3893: \
- case 3895: \
- case 4038: \
- return 220; \
- case 3970: \
- case 3971: \
- case 3974: \
- case 3975: \
- return 230; \
-} \
-return 0; \
-case 16: \
-switch (ch) { \
- case 4151: \
- return 7; \
- case 4153: \
- return 9; \
-} \
-return 0; \
-case 23: \
-switch (ch) { \
- case 5908: \
- case 5940: \
- case 6098: \
- return 9; \
- case 6109: \
- return 230; \
-} \
-return 0; \
-case 24: \
-switch (ch) { \
- case 6313: \
- return 228; \
-} \
-return 0; \
-case 25: \
-switch (ch) { \
- case 6459: \
- return 220; \
- case 6457: \
- return 222; \
- case 6458: \
- return 230; \
-} \
-return 0; \
-case 32: \
-switch (ch) { \
- case 8402: \
- case 8403: \
- case 8408: \
- case 8409: \
- case 8410: \
- case 8421: \
- case 8422: \
- case 8426: \
- return 1; \
- case 8424: \
- return 220; \
- case 8400: \
- case 8401: \
- case 8404: \
- case 8405: \
- case 8406: \
- case 8407: \
- case 8411: \
- case 8412: \
- case 8417: \
- case 8423: \
- case 8425: \
- return 230; \
-} \
-return 0; \
-case 48: \
-switch (ch) { \
- case 12441: \
- case 12442: \
- return 8; \
- case 12330: \
- return 218; \
- case 12333: \
- return 222; \
- case 12334: \
- case 12335: \
- return 224; \
- case 12331: \
- return 228; \
- case 12332: \
- return 232; \
-} \
-return 0; \
-case 251: \
-switch (ch) { \
- case 64286: \
- return 26; \
-} \
-return 0; \
-case 254: \
-switch (ch) { \
- case 65056: \
- case 65057: \
- case 65058: \
- case 65059: \
- return 230; \
-} \
-return 0; \
-case 465: \
-switch (ch) { \
- case 119143: \
- case 119144: \
- case 119145: \
- return 1; \
- case 119141: \
- case 119142: \
- case 119150: \
- case 119151: \
- case 119152: \
- case 119153: \
- case 119154: \
- return 216; \
- case 119163: \
- case 119164: \
- case 119165: \
- case 119166: \
- case 119167: \
- case 119168: \
- case 119169: \
- case 119170: \
- case 119178: \
- case 119179: \
- return 220; \
- case 119149: \
- return 226; \
- case 119173: \
- case 119174: \
- case 119175: \
- case 119176: \
- case 119177: \
- case 119210: \
- case 119211: \
- case 119212: \
- case 119213: \
- return 230; \
-} \
-return 0; \
-} \
-return 0;
+ switch ((glui32)(ch) >> 8) { \
+ case 3: \
+ switch (ch) { \
+ case 820: \
+ case 821: \
+ case 822: \
+ case 823: \
+ case 824: \
+ return 1; \
+ case 801: \
+ case 802: \
+ case 807: \
+ case 808: \
+ return 202; \
+ case 795: \
+ return 216; \
+ case 790: \
+ case 791: \
+ case 792: \
+ case 793: \
+ case 796: \
+ case 797: \
+ case 798: \
+ case 799: \
+ case 800: \
+ case 803: \
+ case 804: \
+ case 805: \
+ case 806: \
+ case 809: \
+ case 810: \
+ case 811: \
+ case 812: \
+ case 813: \
+ case 814: \
+ case 815: \
+ case 816: \
+ case 817: \
+ case 818: \
+ case 819: \
+ case 825: \
+ case 826: \
+ case 827: \
+ case 828: \
+ case 839: \
+ case 840: \
+ case 841: \
+ case 845: \
+ case 846: \
+ case 851: \
+ case 852: \
+ case 853: \
+ case 854: \
+ return 220; \
+ case 768: \
+ case 769: \
+ case 770: \
+ case 771: \
+ case 772: \
+ case 773: \
+ case 774: \
+ case 775: \
+ case 776: \
+ case 777: \
+ case 778: \
+ case 779: \
+ case 780: \
+ case 781: \
+ case 782: \
+ case 783: \
+ case 784: \
+ case 785: \
+ case 786: \
+ case 787: \
+ case 788: \
+ case 829: \
+ case 830: \
+ case 831: \
+ case 832: \
+ case 833: \
+ case 834: \
+ case 835: \
+ case 836: \
+ case 838: \
+ case 842: \
+ case 843: \
+ case 844: \
+ case 848: \
+ case 849: \
+ case 850: \
+ case 855: \
+ case 867: \
+ case 868: \
+ case 869: \
+ case 870: \
+ case 871: \
+ case 872: \
+ case 873: \
+ case 874: \
+ case 875: \
+ case 876: \
+ case 877: \
+ case 878: \
+ case 879: \
+ return 230; \
+ case 789: \
+ case 794: \
+ return 232; \
+ case 863: \
+ case 866: \
+ return 233; \
+ case 861: \
+ case 862: \
+ case 864: \
+ case 865: \
+ return 234; \
+ case 837: \
+ return 240; \
+ } \
+ return 0; \
+ case 4: \
+ switch (ch) { \
+ case 1155: \
+ case 1156: \
+ case 1157: \
+ case 1158: \
+ return 230; \
+ } \
+ return 0; \
+ case 5: \
+ switch (ch) { \
+ case 1456: \
+ return 10; \
+ case 1457: \
+ return 11; \
+ case 1458: \
+ return 12; \
+ case 1459: \
+ return 13; \
+ case 1460: \
+ return 14; \
+ case 1461: \
+ return 15; \
+ case 1462: \
+ return 16; \
+ case 1463: \
+ return 17; \
+ case 1464: \
+ return 18; \
+ case 1465: \
+ return 19; \
+ case 1467: \
+ return 20; \
+ case 1468: \
+ return 21; \
+ case 1469: \
+ return 22; \
+ case 1471: \
+ return 23; \
+ case 1473: \
+ return 24; \
+ case 1474: \
+ return 25; \
+ case 1425: \
+ case 1430: \
+ case 1435: \
+ case 1443: \
+ case 1444: \
+ case 1445: \
+ case 1446: \
+ case 1447: \
+ case 1450: \
+ return 220; \
+ case 1434: \
+ case 1453: \
+ return 222; \
+ case 1454: \
+ return 228; \
+ case 1426: \
+ case 1427: \
+ case 1428: \
+ case 1429: \
+ case 1431: \
+ case 1432: \
+ case 1433: \
+ case 1436: \
+ case 1437: \
+ case 1438: \
+ case 1439: \
+ case 1440: \
+ case 1441: \
+ case 1448: \
+ case 1449: \
+ case 1451: \
+ case 1452: \
+ case 1455: \
+ case 1476: \
+ return 230; \
+ } \
+ return 0; \
+ case 6: \
+ switch (ch) { \
+ case 1611: \
+ return 27; \
+ case 1612: \
+ return 28; \
+ case 1613: \
+ return 29; \
+ case 1614: \
+ return 30; \
+ case 1615: \
+ return 31; \
+ case 1616: \
+ return 32; \
+ case 1617: \
+ return 33; \
+ case 1618: \
+ return 34; \
+ case 1648: \
+ return 35; \
+ case 1621: \
+ case 1622: \
+ case 1763: \
+ case 1770: \
+ case 1773: \
+ return 220; \
+ case 1552: \
+ case 1553: \
+ case 1554: \
+ case 1555: \
+ case 1556: \
+ case 1557: \
+ case 1619: \
+ case 1620: \
+ case 1623: \
+ case 1624: \
+ case 1750: \
+ case 1751: \
+ case 1752: \
+ case 1753: \
+ case 1754: \
+ case 1755: \
+ case 1756: \
+ case 1759: \
+ case 1760: \
+ case 1761: \
+ case 1762: \
+ case 1764: \
+ case 1767: \
+ case 1768: \
+ case 1771: \
+ case 1772: \
+ return 230; \
+ } \
+ return 0; \
+ case 7: \
+ switch (ch) { \
+ case 1809: \
+ return 36; \
+ case 1841: \
+ case 1844: \
+ case 1847: \
+ case 1848: \
+ case 1849: \
+ case 1851: \
+ case 1852: \
+ case 1854: \
+ case 1858: \
+ case 1860: \
+ case 1862: \
+ case 1864: \
+ return 220; \
+ case 1840: \
+ case 1842: \
+ case 1843: \
+ case 1845: \
+ case 1846: \
+ case 1850: \
+ case 1853: \
+ case 1855: \
+ case 1856: \
+ case 1857: \
+ case 1859: \
+ case 1861: \
+ case 1863: \
+ case 1865: \
+ case 1866: \
+ return 230; \
+ } \
+ return 0; \
+ case 9: \
+ switch (ch) { \
+ case 2364: \
+ case 2492: \
+ return 7; \
+ case 2381: \
+ case 2509: \
+ return 9; \
+ case 2386: \
+ return 220; \
+ case 2385: \
+ case 2387: \
+ case 2388: \
+ return 230; \
+ } \
+ return 0; \
+ case 10: \
+ switch (ch) { \
+ case 2620: \
+ case 2748: \
+ return 7; \
+ case 2637: \
+ case 2765: \
+ return 9; \
+ } \
+ return 0; \
+ case 11: \
+ switch (ch) { \
+ case 2876: \
+ return 7; \
+ case 2893: \
+ case 3021: \
+ return 9; \
+ } \
+ return 0; \
+ case 12: \
+ switch (ch) { \
+ case 3260: \
+ return 7; \
+ case 3149: \
+ case 3277: \
+ return 9; \
+ case 3157: \
+ return 84; \
+ case 3158: \
+ return 91; \
+ } \
+ return 0; \
+ case 13: \
+ switch (ch) { \
+ case 3405: \
+ case 3530: \
+ return 9; \
+ } \
+ return 0; \
+ case 14: \
+ switch (ch) { \
+ case 3642: \
+ return 9; \
+ case 3640: \
+ case 3641: \
+ return 103; \
+ case 3656: \
+ case 3657: \
+ case 3658: \
+ case 3659: \
+ return 107; \
+ case 3768: \
+ case 3769: \
+ return 118; \
+ case 3784: \
+ case 3785: \
+ case 3786: \
+ case 3787: \
+ return 122; \
+ } \
+ return 0; \
+ case 15: \
+ switch (ch) { \
+ case 3972: \
+ return 9; \
+ case 3953: \
+ return 129; \
+ case 3954: \
+ case 3962: \
+ case 3963: \
+ case 3964: \
+ case 3965: \
+ case 3968: \
+ return 130; \
+ case 3956: \
+ return 132; \
+ case 3897: \
+ return 216; \
+ case 3864: \
+ case 3865: \
+ case 3893: \
+ case 3895: \
+ case 4038: \
+ return 220; \
+ case 3970: \
+ case 3971: \
+ case 3974: \
+ case 3975: \
+ return 230; \
+ } \
+ return 0; \
+ case 16: \
+ switch (ch) { \
+ case 4151: \
+ return 7; \
+ case 4153: \
+ return 9; \
+ } \
+ return 0; \
+ case 23: \
+ switch (ch) { \
+ case 5908: \
+ case 5940: \
+ case 6098: \
+ return 9; \
+ case 6109: \
+ return 230; \
+ } \
+ return 0; \
+ case 24: \
+ switch (ch) { \
+ case 6313: \
+ return 228; \
+ } \
+ return 0; \
+ case 25: \
+ switch (ch) { \
+ case 6459: \
+ return 220; \
+ case 6457: \
+ return 222; \
+ case 6458: \
+ return 230; \
+ } \
+ return 0; \
+ case 32: \
+ switch (ch) { \
+ case 8402: \
+ case 8403: \
+ case 8408: \
+ case 8409: \
+ case 8410: \
+ case 8421: \
+ case 8422: \
+ case 8426: \
+ return 1; \
+ case 8424: \
+ return 220; \
+ case 8400: \
+ case 8401: \
+ case 8404: \
+ case 8405: \
+ case 8406: \
+ case 8407: \
+ case 8411: \
+ case 8412: \
+ case 8417: \
+ case 8423: \
+ case 8425: \
+ return 230; \
+ } \
+ return 0; \
+ case 48: \
+ switch (ch) { \
+ case 12441: \
+ case 12442: \
+ return 8; \
+ case 12330: \
+ return 218; \
+ case 12333: \
+ return 222; \
+ case 12334: \
+ case 12335: \
+ return 224; \
+ case 12331: \
+ return 228; \
+ case 12332: \
+ return 232; \
+ } \
+ return 0; \
+ case 251: \
+ switch (ch) { \
+ case 64286: \
+ return 26; \
+ } \
+ return 0; \
+ case 254: \
+ switch (ch) { \
+ case 65056: \
+ case 65057: \
+ case 65058: \
+ case 65059: \
+ return 230; \
+ } \
+ return 0; \
+ case 465: \
+ switch (ch) { \
+ case 119143: \
+ case 119144: \
+ case 119145: \
+ return 1; \
+ case 119141: \
+ case 119142: \
+ case 119150: \
+ case 119151: \
+ case 119152: \
+ case 119153: \
+ case 119154: \
+ return 216; \
+ case 119163: \
+ case 119164: \
+ case 119165: \
+ case 119166: \
+ case 119167: \
+ case 119168: \
+ case 119169: \
+ case 119170: \
+ case 119178: \
+ case 119179: \
+ return 220; \
+ case 119149: \
+ return 226; \
+ case 119173: \
+ case 119174: \
+ case 119175: \
+ case 119176: \
+ case 119177: \
+ case 119210: \
+ case 119211: \
+ case 119212: \
+ case 119213: \
+ return 230; \
+ } \
+ return 0; \
+ } \
+ return 0;
#define RETURN_COMPOSITION(ch1, ch2) \
-switch ((glui32)(ch1) >> 8) { \
-case 0: \
-switch (ch1) { \
- case 60: \
- switch (ch2) { \
- case 824: return 8814; \
- } \
- return 0; \
- case 61: \
- switch (ch2) { \
- case 824: return 8800; \
- } \
- return 0; \
- case 62: \
- switch (ch2) { \
- case 824: return 8815; \
- } \
- return 0; \
- case 65: \
- switch (ch2) { \
- case 768: return 192; \
- case 769: return 193; \
- case 770: return 194; \
- case 771: return 195; \
- case 772: return 256; \
- case 774: return 258; \
- case 775: return 550; \
- case 776: return 196; \
- case 777: return 7842; \
- case 778: return 197; \
- case 780: return 461; \
- case 783: return 512; \
- case 785: return 514; \
- case 803: return 7840; \
- case 805: return 7680; \
- case 808: return 260; \
- } \
- return 0; \
- case 66: \
- switch (ch2) { \
- case 775: return 7682; \
- case 803: return 7684; \
- case 817: return 7686; \
- } \
- return 0; \
- case 67: \
- switch (ch2) { \
- case 769: return 262; \
- case 770: return 264; \
- case 775: return 266; \
- case 780: return 268; \
- case 807: return 199; \
- } \
- return 0; \
- case 68: \
- switch (ch2) { \
- case 775: return 7690; \
- case 780: return 270; \
- case 803: return 7692; \
- case 807: return 7696; \
- case 813: return 7698; \
- case 817: return 7694; \
- } \
- return 0; \
- case 69: \
- switch (ch2) { \
- case 768: return 200; \
- case 769: return 201; \
- case 770: return 202; \
- case 771: return 7868; \
- case 772: return 274; \
- case 774: return 276; \
- case 775: return 278; \
- case 776: return 203; \
- case 777: return 7866; \
- case 780: return 282; \
- case 783: return 516; \
- case 785: return 518; \
- case 803: return 7864; \
- case 807: return 552; \
- case 808: return 280; \
- case 813: return 7704; \
- case 816: return 7706; \
- } \
- return 0; \
- case 70: \
- switch (ch2) { \
- case 775: return 7710; \
- } \
- return 0; \
- case 71: \
- switch (ch2) { \
- case 769: return 500; \
- case 770: return 284; \
- case 772: return 7712; \
- case 774: return 286; \
- case 775: return 288; \
- case 780: return 486; \
- case 807: return 290; \
- } \
- return 0; \
- case 72: \
- switch (ch2) { \
- case 770: return 292; \
- case 775: return 7714; \
- case 776: return 7718; \
- case 780: return 542; \
- case 803: return 7716; \
- case 807: return 7720; \
- case 814: return 7722; \
- } \
- return 0; \
- case 73: \
- switch (ch2) { \
- case 768: return 204; \
- case 769: return 205; \
- case 770: return 206; \
- case 771: return 296; \
- case 772: return 298; \
- case 774: return 300; \
- case 775: return 304; \
- case 776: return 207; \
- case 777: return 7880; \
- case 780: return 463; \
- case 783: return 520; \
- case 785: return 522; \
- case 803: return 7882; \
- case 808: return 302; \
- case 816: return 7724; \
- } \
- return 0; \
- case 74: \
- switch (ch2) { \
- case 770: return 308; \
- } \
- return 0; \
- case 75: \
- switch (ch2) { \
- case 769: return 7728; \
- case 780: return 488; \
- case 803: return 7730; \
- case 807: return 310; \
- case 817: return 7732; \
- } \
- return 0; \
- case 76: \
- switch (ch2) { \
- case 769: return 313; \
- case 780: return 317; \
- case 803: return 7734; \
- case 807: return 315; \
- case 813: return 7740; \
- case 817: return 7738; \
- } \
- return 0; \
- case 77: \
- switch (ch2) { \
- case 769: return 7742; \
- case 775: return 7744; \
- case 803: return 7746; \
- } \
- return 0; \
- case 78: \
- switch (ch2) { \
- case 768: return 504; \
- case 769: return 323; \
- case 771: return 209; \
- case 775: return 7748; \
- case 780: return 327; \
- case 803: return 7750; \
- case 807: return 325; \
- case 813: return 7754; \
- case 817: return 7752; \
- } \
- return 0; \
- case 79: \
- switch (ch2) { \
- case 768: return 210; \
- case 769: return 211; \
- case 770: return 212; \
- case 771: return 213; \
- case 772: return 332; \
- case 774: return 334; \
- case 775: return 558; \
- case 776: return 214; \
- case 777: return 7886; \
- case 779: return 336; \
- case 780: return 465; \
- case 783: return 524; \
- case 785: return 526; \
- case 795: return 416; \
- case 803: return 7884; \
- case 808: return 490; \
- } \
- return 0; \
- case 80: \
- switch (ch2) { \
- case 769: return 7764; \
- case 775: return 7766; \
- } \
- return 0; \
- case 82: \
- switch (ch2) { \
- case 769: return 340; \
- case 775: return 7768; \
- case 780: return 344; \
- case 783: return 528; \
- case 785: return 530; \
- case 803: return 7770; \
- case 807: return 342; \
- case 817: return 7774; \
- } \
- return 0; \
- case 83: \
- switch (ch2) { \
- case 769: return 346; \
- case 770: return 348; \
- case 775: return 7776; \
- case 780: return 352; \
- case 803: return 7778; \
- case 806: return 536; \
- case 807: return 350; \
- } \
- return 0; \
- case 84: \
- switch (ch2) { \
- case 775: return 7786; \
- case 780: return 356; \
- case 803: return 7788; \
- case 806: return 538; \
- case 807: return 354; \
- case 813: return 7792; \
- case 817: return 7790; \
- } \
- return 0; \
- case 85: \
- switch (ch2) { \
- case 768: return 217; \
- case 769: return 218; \
- case 770: return 219; \
- case 771: return 360; \
- case 772: return 362; \
- case 774: return 364; \
- case 776: return 220; \
- case 777: return 7910; \
- case 778: return 366; \
- case 779: return 368; \
- case 780: return 467; \
- case 783: return 532; \
- case 785: return 534; \
- case 795: return 431; \
- case 803: return 7908; \
- case 804: return 7794; \
- case 808: return 370; \
- case 813: return 7798; \
- case 816: return 7796; \
- } \
- return 0; \
- case 86: \
- switch (ch2) { \
- case 771: return 7804; \
- case 803: return 7806; \
- } \
- return 0; \
- case 87: \
- switch (ch2) { \
- case 768: return 7808; \
- case 769: return 7810; \
- case 770: return 372; \
- case 775: return 7814; \
- case 776: return 7812; \
- case 803: return 7816; \
- } \
- return 0; \
- case 88: \
- switch (ch2) { \
- case 775: return 7818; \
- case 776: return 7820; \
- } \
- return 0; \
- case 89: \
- switch (ch2) { \
- case 768: return 7922; \
- case 769: return 221; \
- case 770: return 374; \
- case 771: return 7928; \
- case 772: return 562; \
- case 775: return 7822; \
- case 776: return 376; \
- case 777: return 7926; \
- case 803: return 7924; \
- } \
- return 0; \
- case 90: \
- switch (ch2) { \
- case 769: return 377; \
- case 770: return 7824; \
- case 775: return 379; \
- case 780: return 381; \
- case 803: return 7826; \
- case 817: return 7828; \
- } \
- return 0; \
- case 97: \
- switch (ch2) { \
- case 768: return 224; \
- case 769: return 225; \
- case 770: return 226; \
- case 771: return 227; \
- case 772: return 257; \
- case 774: return 259; \
- case 775: return 551; \
- case 776: return 228; \
- case 777: return 7843; \
- case 778: return 229; \
- case 780: return 462; \
- case 783: return 513; \
- case 785: return 515; \
- case 803: return 7841; \
- case 805: return 7681; \
- case 808: return 261; \
- } \
- return 0; \
- case 98: \
- switch (ch2) { \
- case 775: return 7683; \
- case 803: return 7685; \
- case 817: return 7687; \
- } \
- return 0; \
- case 99: \
- switch (ch2) { \
- case 769: return 263; \
- case 770: return 265; \
- case 775: return 267; \
- case 780: return 269; \
- case 807: return 231; \
- } \
- return 0; \
- case 100: \
- switch (ch2) { \
- case 775: return 7691; \
- case 780: return 271; \
- case 803: return 7693; \
- case 807: return 7697; \
- case 813: return 7699; \
- case 817: return 7695; \
- } \
- return 0; \
- case 101: \
- switch (ch2) { \
- case 768: return 232; \
- case 769: return 233; \
- case 770: return 234; \
- case 771: return 7869; \
- case 772: return 275; \
- case 774: return 277; \
- case 775: return 279; \
- case 776: return 235; \
- case 777: return 7867; \
- case 780: return 283; \
- case 783: return 517; \
- case 785: return 519; \
- case 803: return 7865; \
- case 807: return 553; \
- case 808: return 281; \
- case 813: return 7705; \
- case 816: return 7707; \
- } \
- return 0; \
- case 102: \
- switch (ch2) { \
- case 775: return 7711; \
- } \
- return 0; \
- case 103: \
- switch (ch2) { \
- case 769: return 501; \
- case 770: return 285; \
- case 772: return 7713; \
- case 774: return 287; \
- case 775: return 289; \
- case 780: return 487; \
- case 807: return 291; \
- } \
- return 0; \
- case 104: \
- switch (ch2) { \
- case 770: return 293; \
- case 775: return 7715; \
- case 776: return 7719; \
- case 780: return 543; \
- case 803: return 7717; \
- case 807: return 7721; \
- case 814: return 7723; \
- case 817: return 7830; \
- } \
- return 0; \
- case 105: \
- switch (ch2) { \
- case 768: return 236; \
- case 769: return 237; \
- case 770: return 238; \
- case 771: return 297; \
- case 772: return 299; \
- case 774: return 301; \
- case 776: return 239; \
- case 777: return 7881; \
- case 780: return 464; \
- case 783: return 521; \
- case 785: return 523; \
- case 803: return 7883; \
- case 808: return 303; \
- case 816: return 7725; \
- } \
- return 0; \
- case 106: \
- switch (ch2) { \
- case 770: return 309; \
- case 780: return 496; \
- } \
- return 0; \
- case 107: \
- switch (ch2) { \
- case 769: return 7729; \
- case 780: return 489; \
- case 803: return 7731; \
- case 807: return 311; \
- case 817: return 7733; \
- } \
- return 0; \
- case 108: \
- switch (ch2) { \
- case 769: return 314; \
- case 780: return 318; \
- case 803: return 7735; \
- case 807: return 316; \
- case 813: return 7741; \
- case 817: return 7739; \
- } \
- return 0; \
- case 109: \
- switch (ch2) { \
- case 769: return 7743; \
- case 775: return 7745; \
- case 803: return 7747; \
- } \
- return 0; \
- case 110: \
- switch (ch2) { \
- case 768: return 505; \
- case 769: return 324; \
- case 771: return 241; \
- case 775: return 7749; \
- case 780: return 328; \
- case 803: return 7751; \
- case 807: return 326; \
- case 813: return 7755; \
- case 817: return 7753; \
- } \
- return 0; \
- case 111: \
- switch (ch2) { \
- case 768: return 242; \
- case 769: return 243; \
- case 770: return 244; \
- case 771: return 245; \
- case 772: return 333; \
- case 774: return 335; \
- case 775: return 559; \
- case 776: return 246; \
- case 777: return 7887; \
- case 779: return 337; \
- case 780: return 466; \
- case 783: return 525; \
- case 785: return 527; \
- case 795: return 417; \
- case 803: return 7885; \
- case 808: return 491; \
- } \
- return 0; \
- case 112: \
- switch (ch2) { \
- case 769: return 7765; \
- case 775: return 7767; \
- } \
- return 0; \
- case 114: \
- switch (ch2) { \
- case 769: return 341; \
- case 775: return 7769; \
- case 780: return 345; \
- case 783: return 529; \
- case 785: return 531; \
- case 803: return 7771; \
- case 807: return 343; \
- case 817: return 7775; \
- } \
- return 0; \
- case 115: \
- switch (ch2) { \
- case 769: return 347; \
- case 770: return 349; \
- case 775: return 7777; \
- case 780: return 353; \
- case 803: return 7779; \
- case 806: return 537; \
- case 807: return 351; \
- } \
- return 0; \
- case 116: \
- switch (ch2) { \
- case 775: return 7787; \
- case 776: return 7831; \
- case 780: return 357; \
- case 803: return 7789; \
- case 806: return 539; \
- case 807: return 355; \
- case 813: return 7793; \
- case 817: return 7791; \
- } \
- return 0; \
- case 117: \
- switch (ch2) { \
- case 768: return 249; \
- case 769: return 250; \
- case 770: return 251; \
- case 771: return 361; \
- case 772: return 363; \
- case 774: return 365; \
- case 776: return 252; \
- case 777: return 7911; \
- case 778: return 367; \
- case 779: return 369; \
- case 780: return 468; \
- case 783: return 533; \
- case 785: return 535; \
- case 795: return 432; \
- case 803: return 7909; \
- case 804: return 7795; \
- case 808: return 371; \
- case 813: return 7799; \
- case 816: return 7797; \
- } \
- return 0; \
- case 118: \
- switch (ch2) { \
- case 771: return 7805; \
- case 803: return 7807; \
- } \
- return 0; \
- case 119: \
- switch (ch2) { \
- case 768: return 7809; \
- case 769: return 7811; \
- case 770: return 373; \
- case 775: return 7815; \
- case 776: return 7813; \
- case 778: return 7832; \
- case 803: return 7817; \
- } \
- return 0; \
- case 120: \
- switch (ch2) { \
- case 775: return 7819; \
- case 776: return 7821; \
- } \
- return 0; \
- case 121: \
- switch (ch2) { \
- case 768: return 7923; \
- case 769: return 253; \
- case 770: return 375; \
- case 771: return 7929; \
- case 772: return 563; \
- case 775: return 7823; \
- case 776: return 255; \
- case 777: return 7927; \
- case 778: return 7833; \
- case 803: return 7925; \
- } \
- return 0; \
- case 122: \
- switch (ch2) { \
- case 769: return 378; \
- case 770: return 7825; \
- case 775: return 380; \
- case 780: return 382; \
- case 803: return 7827; \
- case 817: return 7829; \
- } \
- return 0; \
- case 168: \
- switch (ch2) { \
- case 768: return 8173; \
- case 769: return 901; \
- case 834: return 8129; \
- } \
- return 0; \
- case 194: \
- switch (ch2) { \
- case 768: return 7846; \
- case 769: return 7844; \
- case 771: return 7850; \
- case 777: return 7848; \
- } \
- return 0; \
- case 196: \
- switch (ch2) { \
- case 772: return 478; \
- } \
- return 0; \
- case 197: \
- switch (ch2) { \
- case 769: return 506; \
- } \
- return 0; \
- case 198: \
- switch (ch2) { \
- case 769: return 508; \
- case 772: return 482; \
- } \
- return 0; \
- case 199: \
- switch (ch2) { \
- case 769: return 7688; \
- } \
- return 0; \
- case 202: \
- switch (ch2) { \
- case 768: return 7872; \
- case 769: return 7870; \
- case 771: return 7876; \
- case 777: return 7874; \
- } \
- return 0; \
- case 207: \
- switch (ch2) { \
- case 769: return 7726; \
- } \
- return 0; \
- case 212: \
- switch (ch2) { \
- case 768: return 7890; \
- case 769: return 7888; \
- case 771: return 7894; \
- case 777: return 7892; \
- } \
- return 0; \
- case 213: \
- switch (ch2) { \
- case 769: return 7756; \
- case 772: return 556; \
- case 776: return 7758; \
- } \
- return 0; \
- case 214: \
- switch (ch2) { \
- case 772: return 554; \
- } \
- return 0; \
- case 216: \
- switch (ch2) { \
- case 769: return 510; \
- } \
- return 0; \
- case 220: \
- switch (ch2) { \
- case 768: return 475; \
- case 769: return 471; \
- case 772: return 469; \
- case 780: return 473; \
- } \
- return 0; \
- case 226: \
- switch (ch2) { \
- case 768: return 7847; \
- case 769: return 7845; \
- case 771: return 7851; \
- case 777: return 7849; \
- } \
- return 0; \
- case 228: \
- switch (ch2) { \
- case 772: return 479; \
- } \
- return 0; \
- case 229: \
- switch (ch2) { \
- case 769: return 507; \
- } \
- return 0; \
- case 230: \
- switch (ch2) { \
- case 769: return 509; \
- case 772: return 483; \
- } \
- return 0; \
- case 231: \
- switch (ch2) { \
- case 769: return 7689; \
- } \
- return 0; \
- case 234: \
- switch (ch2) { \
- case 768: return 7873; \
- case 769: return 7871; \
- case 771: return 7877; \
- case 777: return 7875; \
- } \
- return 0; \
- case 239: \
- switch (ch2) { \
- case 769: return 7727; \
- } \
- return 0; \
- case 244: \
- switch (ch2) { \
- case 768: return 7891; \
- case 769: return 7889; \
- case 771: return 7895; \
- case 777: return 7893; \
- } \
- return 0; \
- case 245: \
- switch (ch2) { \
- case 769: return 7757; \
- case 772: return 557; \
- case 776: return 7759; \
- } \
- return 0; \
- case 246: \
- switch (ch2) { \
- case 772: return 555; \
- } \
- return 0; \
- case 248: \
- switch (ch2) { \
- case 769: return 511; \
- } \
- return 0; \
- case 252: \
- switch (ch2) { \
- case 768: return 476; \
- case 769: return 472; \
- case 772: return 470; \
- case 780: return 474; \
- } \
- return 0; \
-} \
-return 0; \
-case 1: \
-switch (ch1) { \
- case 258: \
- switch (ch2) { \
- case 768: return 7856; \
- case 769: return 7854; \
- case 771: return 7860; \
- case 777: return 7858; \
- } \
- return 0; \
- case 259: \
- switch (ch2) { \
- case 768: return 7857; \
- case 769: return 7855; \
- case 771: return 7861; \
- case 777: return 7859; \
- } \
- return 0; \
- case 274: \
- switch (ch2) { \
- case 768: return 7700; \
- case 769: return 7702; \
- } \
- return 0; \
- case 275: \
- switch (ch2) { \
- case 768: return 7701; \
- case 769: return 7703; \
- } \
- return 0; \
- case 332: \
- switch (ch2) { \
- case 768: return 7760; \
- case 769: return 7762; \
- } \
- return 0; \
- case 333: \
- switch (ch2) { \
- case 768: return 7761; \
- case 769: return 7763; \
- } \
- return 0; \
- case 346: \
- switch (ch2) { \
- case 775: return 7780; \
- } \
- return 0; \
- case 347: \
- switch (ch2) { \
- case 775: return 7781; \
- } \
- return 0; \
- case 352: \
- switch (ch2) { \
- case 775: return 7782; \
- } \
- return 0; \
- case 353: \
- switch (ch2) { \
- case 775: return 7783; \
- } \
- return 0; \
- case 360: \
- switch (ch2) { \
- case 769: return 7800; \
- } \
- return 0; \
- case 361: \
- switch (ch2) { \
- case 769: return 7801; \
- } \
- return 0; \
- case 362: \
- switch (ch2) { \
- case 776: return 7802; \
- } \
- return 0; \
- case 363: \
- switch (ch2) { \
- case 776: return 7803; \
- } \
- return 0; \
- case 383: \
- switch (ch2) { \
- case 775: return 7835; \
- } \
- return 0; \
- case 416: \
- switch (ch2) { \
- case 768: return 7900; \
- case 769: return 7898; \
- case 771: return 7904; \
- case 777: return 7902; \
- case 803: return 7906; \
- } \
- return 0; \
- case 417: \
- switch (ch2) { \
- case 768: return 7901; \
- case 769: return 7899; \
- case 771: return 7905; \
- case 777: return 7903; \
- case 803: return 7907; \
- } \
- return 0; \
- case 431: \
- switch (ch2) { \
- case 768: return 7914; \
- case 769: return 7912; \
- case 771: return 7918; \
- case 777: return 7916; \
- case 803: return 7920; \
- } \
- return 0; \
- case 432: \
- switch (ch2) { \
- case 768: return 7915; \
- case 769: return 7913; \
- case 771: return 7919; \
- case 777: return 7917; \
- case 803: return 7921; \
- } \
- return 0; \
- case 439: \
- switch (ch2) { \
- case 780: return 494; \
- } \
- return 0; \
- case 490: \
- switch (ch2) { \
- case 772: return 492; \
- } \
- return 0; \
- case 491: \
- switch (ch2) { \
- case 772: return 493; \
- } \
- return 0; \
-} \
-return 0; \
-case 2: \
-switch (ch1) { \
- case 550: \
- switch (ch2) { \
- case 772: return 480; \
- } \
- return 0; \
- case 551: \
- switch (ch2) { \
- case 772: return 481; \
- } \
- return 0; \
- case 552: \
- switch (ch2) { \
- case 774: return 7708; \
- } \
- return 0; \
- case 553: \
- switch (ch2) { \
- case 774: return 7709; \
- } \
- return 0; \
- case 558: \
- switch (ch2) { \
- case 772: return 560; \
- } \
- return 0; \
- case 559: \
- switch (ch2) { \
- case 772: return 561; \
- } \
- return 0; \
- case 658: \
- switch (ch2) { \
- case 780: return 495; \
- } \
- return 0; \
-} \
-return 0; \
-case 3: \
-switch (ch1) { \
- case 776: \
- switch (ch2) { \
- case 769: return 836; \
- } \
- return 0; \
- case 913: \
- switch (ch2) { \
- case 768: return 8122; \
- case 769: return 902; \
- case 772: return 8121; \
- case 774: return 8120; \
- case 787: return 7944; \
- case 788: return 7945; \
- case 837: return 8124; \
- } \
- return 0; \
- case 917: \
- switch (ch2) { \
- case 768: return 8136; \
- case 769: return 904; \
- case 787: return 7960; \
- case 788: return 7961; \
- } \
- return 0; \
- case 919: \
- switch (ch2) { \
- case 768: return 8138; \
- case 769: return 905; \
- case 787: return 7976; \
- case 788: return 7977; \
- case 837: return 8140; \
- } \
- return 0; \
- case 921: \
- switch (ch2) { \
- case 768: return 8154; \
- case 769: return 906; \
- case 772: return 8153; \
- case 774: return 8152; \
- case 776: return 938; \
- case 787: return 7992; \
- case 788: return 7993; \
- } \
- return 0; \
- case 927: \
- switch (ch2) { \
- case 768: return 8184; \
- case 769: return 908; \
- case 787: return 8008; \
- case 788: return 8009; \
- } \
- return 0; \
- case 929: \
- switch (ch2) { \
- case 788: return 8172; \
- } \
- return 0; \
- case 933: \
- switch (ch2) { \
- case 768: return 8170; \
- case 769: return 910; \
- case 772: return 8169; \
- case 774: return 8168; \
- case 776: return 939; \
- case 788: return 8025; \
- } \
- return 0; \
- case 937: \
- switch (ch2) { \
- case 768: return 8186; \
- case 769: return 911; \
- case 787: return 8040; \
- case 788: return 8041; \
- case 837: return 8188; \
- } \
- return 0; \
- case 940: \
- switch (ch2) { \
- case 837: return 8116; \
- } \
- return 0; \
- case 942: \
- switch (ch2) { \
- case 837: return 8132; \
- } \
- return 0; \
- case 945: \
- switch (ch2) { \
- case 768: return 8048; \
- case 769: return 940; \
- case 772: return 8113; \
- case 774: return 8112; \
- case 787: return 7936; \
- case 788: return 7937; \
- case 834: return 8118; \
- case 837: return 8115; \
- } \
- return 0; \
- case 949: \
- switch (ch2) { \
- case 768: return 8050; \
- case 769: return 941; \
- case 787: return 7952; \
- case 788: return 7953; \
- } \
- return 0; \
- case 951: \
- switch (ch2) { \
- case 768: return 8052; \
- case 769: return 942; \
- case 787: return 7968; \
- case 788: return 7969; \
- case 834: return 8134; \
- case 837: return 8131; \
- } \
- return 0; \
- case 953: \
- switch (ch2) { \
- case 768: return 8054; \
- case 769: return 943; \
- case 772: return 8145; \
- case 774: return 8144; \
- case 776: return 970; \
- case 787: return 7984; \
- case 788: return 7985; \
- case 834: return 8150; \
- } \
- return 0; \
- case 959: \
- switch (ch2) { \
- case 768: return 8056; \
- case 769: return 972; \
- case 787: return 8000; \
- case 788: return 8001; \
- } \
- return 0; \
- case 961: \
- switch (ch2) { \
- case 787: return 8164; \
- case 788: return 8165; \
- } \
- return 0; \
- case 965: \
- switch (ch2) { \
- case 768: return 8058; \
- case 769: return 973; \
- case 772: return 8161; \
- case 774: return 8160; \
- case 776: return 971; \
- case 787: return 8016; \
- case 788: return 8017; \
- case 834: return 8166; \
- } \
- return 0; \
- case 969: \
- switch (ch2) { \
- case 768: return 8060; \
- case 769: return 974; \
- case 787: return 8032; \
- case 788: return 8033; \
- case 834: return 8182; \
- case 837: return 8179; \
- } \
- return 0; \
- case 970: \
- switch (ch2) { \
- case 768: return 8146; \
- case 769: return 912; \
- case 834: return 8151; \
- } \
- return 0; \
- case 971: \
- switch (ch2) { \
- case 768: return 8162; \
- case 769: return 944; \
- case 834: return 8167; \
- } \
- return 0; \
- case 974: \
- switch (ch2) { \
- case 837: return 8180; \
- } \
- return 0; \
- case 978: \
- switch (ch2) { \
- case 769: return 979; \
- case 776: return 980; \
- } \
- return 0; \
-} \
-return 0; \
-case 4: \
-switch (ch1) { \
- case 1030: \
- switch (ch2) { \
- case 776: return 1031; \
- } \
- return 0; \
- case 1040: \
- switch (ch2) { \
- case 774: return 1232; \
- case 776: return 1234; \
- } \
- return 0; \
- case 1043: \
- switch (ch2) { \
- case 769: return 1027; \
- } \
- return 0; \
- case 1045: \
- switch (ch2) { \
- case 768: return 1024; \
- case 774: return 1238; \
- case 776: return 1025; \
- } \
- return 0; \
- case 1046: \
- switch (ch2) { \
- case 774: return 1217; \
- case 776: return 1244; \
- } \
- return 0; \
- case 1047: \
- switch (ch2) { \
- case 776: return 1246; \
- } \
- return 0; \
- case 1048: \
- switch (ch2) { \
- case 768: return 1037; \
- case 772: return 1250; \
- case 774: return 1049; \
- case 776: return 1252; \
- } \
- return 0; \
- case 1050: \
- switch (ch2) { \
- case 769: return 1036; \
- } \
- return 0; \
- case 1054: \
- switch (ch2) { \
- case 776: return 1254; \
- } \
- return 0; \
- case 1059: \
- switch (ch2) { \
- case 772: return 1262; \
- case 774: return 1038; \
- case 776: return 1264; \
- case 779: return 1266; \
- } \
- return 0; \
- case 1063: \
- switch (ch2) { \
- case 776: return 1268; \
- } \
- return 0; \
- case 1067: \
- switch (ch2) { \
- case 776: return 1272; \
- } \
- return 0; \
- case 1069: \
- switch (ch2) { \
- case 776: return 1260; \
- } \
- return 0; \
- case 1072: \
- switch (ch2) { \
- case 774: return 1233; \
- case 776: return 1235; \
- } \
- return 0; \
- case 1075: \
- switch (ch2) { \
- case 769: return 1107; \
- } \
- return 0; \
- case 1077: \
- switch (ch2) { \
- case 768: return 1104; \
- case 774: return 1239; \
- case 776: return 1105; \
- } \
- return 0; \
- case 1078: \
- switch (ch2) { \
- case 774: return 1218; \
- case 776: return 1245; \
- } \
- return 0; \
- case 1079: \
- switch (ch2) { \
- case 776: return 1247; \
- } \
- return 0; \
- case 1080: \
- switch (ch2) { \
- case 768: return 1117; \
- case 772: return 1251; \
- case 774: return 1081; \
- case 776: return 1253; \
- } \
- return 0; \
- case 1082: \
- switch (ch2) { \
- case 769: return 1116; \
- } \
- return 0; \
- case 1086: \
- switch (ch2) { \
- case 776: return 1255; \
- } \
- return 0; \
- case 1091: \
- switch (ch2) { \
- case 772: return 1263; \
- case 774: return 1118; \
- case 776: return 1265; \
- case 779: return 1267; \
- } \
- return 0; \
- case 1095: \
- switch (ch2) { \
- case 776: return 1269; \
- } \
- return 0; \
- case 1099: \
- switch (ch2) { \
- case 776: return 1273; \
- } \
- return 0; \
- case 1101: \
- switch (ch2) { \
- case 776: return 1261; \
- } \
- return 0; \
- case 1110: \
- switch (ch2) { \
- case 776: return 1111; \
- } \
- return 0; \
- case 1140: \
- switch (ch2) { \
- case 783: return 1142; \
- } \
- return 0; \
- case 1141: \
- switch (ch2) { \
- case 783: return 1143; \
- } \
- return 0; \
- case 1240: \
- switch (ch2) { \
- case 776: return 1242; \
- } \
- return 0; \
- case 1241: \
- switch (ch2) { \
- case 776: return 1243; \
- } \
- return 0; \
- case 1256: \
- switch (ch2) { \
- case 776: return 1258; \
- } \
- return 0; \
- case 1257: \
- switch (ch2) { \
- case 776: return 1259; \
- } \
- return 0; \
-} \
-return 0; \
-case 5: \
-switch (ch1) { \
- case 1488: \
- switch (ch2) { \
- case 1463: return 64302; \
- case 1464: return 64303; \
- case 1468: return 64304; \
- } \
- return 0; \
- case 1489: \
- switch (ch2) { \
- case 1468: return 64305; \
- case 1471: return 64332; \
- } \
- return 0; \
- case 1490: \
- switch (ch2) { \
- case 1468: return 64306; \
- } \
- return 0; \
- case 1491: \
- switch (ch2) { \
- case 1468: return 64307; \
- } \
- return 0; \
- case 1492: \
- switch (ch2) { \
- case 1468: return 64308; \
- } \
- return 0; \
- case 1493: \
- switch (ch2) { \
- case 1465: return 64331; \
- case 1468: return 64309; \
- } \
- return 0; \
- case 1494: \
- switch (ch2) { \
- case 1468: return 64310; \
- } \
- return 0; \
- case 1496: \
- switch (ch2) { \
- case 1468: return 64312; \
- } \
- return 0; \
- case 1497: \
- switch (ch2) { \
- case 1460: return 64285; \
- case 1468: return 64313; \
- } \
- return 0; \
- case 1498: \
- switch (ch2) { \
- case 1468: return 64314; \
- } \
- return 0; \
- case 1499: \
- switch (ch2) { \
- case 1468: return 64315; \
- case 1471: return 64333; \
- } \
- return 0; \
- case 1500: \
- switch (ch2) { \
- case 1468: return 64316; \
- } \
- return 0; \
- case 1502: \
- switch (ch2) { \
- case 1468: return 64318; \
- } \
- return 0; \
- case 1504: \
- switch (ch2) { \
- case 1468: return 64320; \
- } \
- return 0; \
- case 1505: \
- switch (ch2) { \
- case 1468: return 64321; \
- } \
- return 0; \
- case 1507: \
- switch (ch2) { \
- case 1468: return 64323; \
- } \
- return 0; \
- case 1508: \
- switch (ch2) { \
- case 1468: return 64324; \
- case 1471: return 64334; \
- } \
- return 0; \
- case 1510: \
- switch (ch2) { \
- case 1468: return 64326; \
- } \
- return 0; \
- case 1511: \
- switch (ch2) { \
- case 1468: return 64327; \
- } \
- return 0; \
- case 1512: \
- switch (ch2) { \
- case 1468: return 64328; \
- } \
- return 0; \
- case 1513: \
- switch (ch2) { \
- case 1468: return 64329; \
- case 1473: return 64298; \
- case 1474: return 64299; \
- } \
- return 0; \
- case 1514: \
- switch (ch2) { \
- case 1468: return 64330; \
- } \
- return 0; \
- case 1522: \
- switch (ch2) { \
- case 1463: return 64287; \
- } \
- return 0; \
-} \
-return 0; \
-case 6: \
-switch (ch1) { \
- case 1575: \
- switch (ch2) { \
- case 1619: return 1570; \
- case 1620: return 1571; \
- case 1621: return 1573; \
- } \
- return 0; \
- case 1608: \
- switch (ch2) { \
- case 1620: return 1572; \
- } \
- return 0; \
- case 1610: \
- switch (ch2) { \
- case 1620: return 1574; \
- } \
- return 0; \
- case 1729: \
- switch (ch2) { \
- case 1620: return 1730; \
- } \
- return 0; \
- case 1746: \
- switch (ch2) { \
- case 1620: return 1747; \
- } \
- return 0; \
- case 1749: \
- switch (ch2) { \
- case 1620: return 1728; \
- } \
- return 0; \
-} \
-return 0; \
-case 9: \
-switch (ch1) { \
- case 2325: \
- switch (ch2) { \
- case 2364: return 2392; \
- } \
- return 0; \
- case 2326: \
- switch (ch2) { \
- case 2364: return 2393; \
- } \
- return 0; \
- case 2327: \
- switch (ch2) { \
- case 2364: return 2394; \
- } \
- return 0; \
- case 2332: \
- switch (ch2) { \
- case 2364: return 2395; \
- } \
- return 0; \
- case 2337: \
- switch (ch2) { \
- case 2364: return 2396; \
- } \
- return 0; \
- case 2338: \
- switch (ch2) { \
- case 2364: return 2397; \
- } \
- return 0; \
- case 2344: \
- switch (ch2) { \
- case 2364: return 2345; \
- } \
- return 0; \
- case 2347: \
- switch (ch2) { \
- case 2364: return 2398; \
- } \
- return 0; \
- case 2351: \
- switch (ch2) { \
- case 2364: return 2399; \
- } \
- return 0; \
- case 2352: \
- switch (ch2) { \
- case 2364: return 2353; \
- } \
- return 0; \
- case 2355: \
- switch (ch2) { \
- case 2364: return 2356; \
- } \
- return 0; \
- case 2465: \
- switch (ch2) { \
- case 2492: return 2524; \
- } \
- return 0; \
- case 2466: \
- switch (ch2) { \
- case 2492: return 2525; \
- } \
- return 0; \
- case 2479: \
- switch (ch2) { \
- case 2492: return 2527; \
- } \
- return 0; \
- case 2503: \
- switch (ch2) { \
- case 2494: return 2507; \
- case 2519: return 2508; \
- } \
- return 0; \
-} \
-return 0; \
-case 10: \
-switch (ch1) { \
- case 2582: \
- switch (ch2) { \
- case 2620: return 2649; \
- } \
- return 0; \
- case 2583: \
- switch (ch2) { \
- case 2620: return 2650; \
- } \
- return 0; \
- case 2588: \
- switch (ch2) { \
- case 2620: return 2651; \
- } \
- return 0; \
- case 2603: \
- switch (ch2) { \
- case 2620: return 2654; \
- } \
- return 0; \
- case 2610: \
- switch (ch2) { \
- case 2620: return 2611; \
- } \
- return 0; \
- case 2616: \
- switch (ch2) { \
- case 2620: return 2614; \
- } \
- return 0; \
-} \
-return 0; \
-case 11: \
-switch (ch1) { \
- case 2849: \
- switch (ch2) { \
- case 2876: return 2908; \
- } \
- return 0; \
- case 2850: \
- switch (ch2) { \
- case 2876: return 2909; \
- } \
- return 0; \
- case 2887: \
- switch (ch2) { \
- case 2878: return 2891; \
- case 2902: return 2888; \
- case 2903: return 2892; \
- } \
- return 0; \
- case 2962: \
- switch (ch2) { \
- case 3031: return 2964; \
- } \
- return 0; \
- case 3014: \
- switch (ch2) { \
- case 3006: return 3018; \
- case 3031: return 3020; \
- } \
- return 0; \
- case 3015: \
- switch (ch2) { \
- case 3006: return 3019; \
- } \
- return 0; \
-} \
-return 0; \
-case 12: \
-switch (ch1) { \
- case 3142: \
- switch (ch2) { \
- case 3158: return 3144; \
- } \
- return 0; \
- case 3263: \
- switch (ch2) { \
- case 3285: return 3264; \
- } \
- return 0; \
- case 3270: \
- switch (ch2) { \
- case 3266: return 3274; \
- case 3285: return 3271; \
- case 3286: return 3272; \
- } \
- return 0; \
- case 3274: \
- switch (ch2) { \
- case 3285: return 3275; \
- } \
- return 0; \
-} \
-return 0; \
-case 13: \
-switch (ch1) { \
- case 3398: \
- switch (ch2) { \
- case 3390: return 3402; \
- case 3415: return 3404; \
- } \
- return 0; \
- case 3399: \
- switch (ch2) { \
- case 3390: return 3403; \
- } \
- return 0; \
- case 3545: \
- switch (ch2) { \
- case 3530: return 3546; \
- case 3535: return 3548; \
- case 3551: return 3550; \
- } \
- return 0; \
- case 3548: \
- switch (ch2) { \
- case 3530: return 3549; \
- } \
- return 0; \
-} \
-return 0; \
-case 15: \
-switch (ch1) { \
- case 3904: \
- switch (ch2) { \
- case 4021: return 3945; \
- } \
- return 0; \
- case 3906: \
- switch (ch2) { \
- case 4023: return 3907; \
- } \
- return 0; \
- case 3916: \
- switch (ch2) { \
- case 4023: return 3917; \
- } \
- return 0; \
- case 3921: \
- switch (ch2) { \
- case 4023: return 3922; \
- } \
- return 0; \
- case 3926: \
- switch (ch2) { \
- case 4023: return 3927; \
- } \
- return 0; \
- case 3931: \
- switch (ch2) { \
- case 4023: return 3932; \
- } \
- return 0; \
- case 3953: \
- switch (ch2) { \
- case 3954: return 3955; \
- case 3956: return 3957; \
- case 3968: return 3969; \
- } \
- return 0; \
- case 3984: \
- switch (ch2) { \
- case 4021: return 4025; \
- } \
- return 0; \
- case 3986: \
- switch (ch2) { \
- case 4023: return 3987; \
- } \
- return 0; \
- case 3996: \
- switch (ch2) { \
- case 4023: return 3997; \
- } \
- return 0; \
- case 4001: \
- switch (ch2) { \
- case 4023: return 4002; \
- } \
- return 0; \
- case 4006: \
- switch (ch2) { \
- case 4023: return 4007; \
- } \
- return 0; \
- case 4011: \
- switch (ch2) { \
- case 4023: return 4012; \
- } \
- return 0; \
- case 4018: \
- switch (ch2) { \
- case 3968: return 3958; \
- } \
- return 0; \
- case 4019: \
- switch (ch2) { \
- case 3968: return 3960; \
- } \
- return 0; \
-} \
-return 0; \
-case 16: \
-switch (ch1) { \
- case 4133: \
- switch (ch2) { \
- case 4142: return 4134; \
- } \
- return 0; \
-} \
-return 0; \
-case 30: \
-switch (ch1) { \
- case 7734: \
- switch (ch2) { \
- case 772: return 7736; \
- } \
- return 0; \
- case 7735: \
- switch (ch2) { \
- case 772: return 7737; \
- } \
- return 0; \
- case 7770: \
- switch (ch2) { \
- case 772: return 7772; \
- } \
- return 0; \
- case 7771: \
- switch (ch2) { \
- case 772: return 7773; \
- } \
- return 0; \
- case 7778: \
- switch (ch2) { \
- case 775: return 7784; \
- } \
- return 0; \
- case 7779: \
- switch (ch2) { \
- case 775: return 7785; \
- } \
- return 0; \
- case 7840: \
- switch (ch2) { \
- case 770: return 7852; \
- case 774: return 7862; \
- } \
- return 0; \
- case 7841: \
- switch (ch2) { \
- case 770: return 7853; \
- case 774: return 7863; \
- } \
- return 0; \
- case 7864: \
- switch (ch2) { \
- case 770: return 7878; \
- } \
- return 0; \
- case 7865: \
- switch (ch2) { \
- case 770: return 7879; \
- } \
- return 0; \
- case 7884: \
- switch (ch2) { \
- case 770: return 7896; \
- } \
- return 0; \
- case 7885: \
- switch (ch2) { \
- case 770: return 7897; \
- } \
- return 0; \
-} \
-return 0; \
-case 31: \
-switch (ch1) { \
- case 7936: \
- switch (ch2) { \
- case 768: return 7938; \
- case 769: return 7940; \
- case 834: return 7942; \
- case 837: return 8064; \
- } \
- return 0; \
- case 7937: \
- switch (ch2) { \
- case 768: return 7939; \
- case 769: return 7941; \
- case 834: return 7943; \
- case 837: return 8065; \
- } \
- return 0; \
- case 7938: \
- switch (ch2) { \
- case 837: return 8066; \
- } \
- return 0; \
- case 7939: \
- switch (ch2) { \
- case 837: return 8067; \
- } \
- return 0; \
- case 7940: \
- switch (ch2) { \
- case 837: return 8068; \
- } \
- return 0; \
- case 7941: \
- switch (ch2) { \
- case 837: return 8069; \
- } \
- return 0; \
- case 7942: \
- switch (ch2) { \
- case 837: return 8070; \
- } \
- return 0; \
- case 7943: \
- switch (ch2) { \
- case 837: return 8071; \
- } \
- return 0; \
- case 7944: \
- switch (ch2) { \
- case 768: return 7946; \
- case 769: return 7948; \
- case 834: return 7950; \
- case 837: return 8072; \
- } \
- return 0; \
- case 7945: \
- switch (ch2) { \
- case 768: return 7947; \
- case 769: return 7949; \
- case 834: return 7951; \
- case 837: return 8073; \
- } \
- return 0; \
- case 7946: \
- switch (ch2) { \
- case 837: return 8074; \
- } \
- return 0; \
- case 7947: \
- switch (ch2) { \
- case 837: return 8075; \
- } \
- return 0; \
- case 7948: \
- switch (ch2) { \
- case 837: return 8076; \
- } \
- return 0; \
- case 7949: \
- switch (ch2) { \
- case 837: return 8077; \
- } \
- return 0; \
- case 7950: \
- switch (ch2) { \
- case 837: return 8078; \
- } \
- return 0; \
- case 7951: \
- switch (ch2) { \
- case 837: return 8079; \
- } \
- return 0; \
- case 7952: \
- switch (ch2) { \
- case 768: return 7954; \
- case 769: return 7956; \
- } \
- return 0; \
- case 7953: \
- switch (ch2) { \
- case 768: return 7955; \
- case 769: return 7957; \
- } \
- return 0; \
- case 7960: \
- switch (ch2) { \
- case 768: return 7962; \
- case 769: return 7964; \
- } \
- return 0; \
- case 7961: \
- switch (ch2) { \
- case 768: return 7963; \
- case 769: return 7965; \
- } \
- return 0; \
- case 7968: \
- switch (ch2) { \
- case 768: return 7970; \
- case 769: return 7972; \
- case 834: return 7974; \
- case 837: return 8080; \
- } \
- return 0; \
- case 7969: \
- switch (ch2) { \
- case 768: return 7971; \
- case 769: return 7973; \
- case 834: return 7975; \
- case 837: return 8081; \
- } \
- return 0; \
- case 7970: \
- switch (ch2) { \
- case 837: return 8082; \
- } \
- return 0; \
- case 7971: \
- switch (ch2) { \
- case 837: return 8083; \
- } \
- return 0; \
- case 7972: \
- switch (ch2) { \
- case 837: return 8084; \
- } \
- return 0; \
- case 7973: \
- switch (ch2) { \
- case 837: return 8085; \
- } \
- return 0; \
- case 7974: \
- switch (ch2) { \
- case 837: return 8086; \
- } \
- return 0; \
- case 7975: \
- switch (ch2) { \
- case 837: return 8087; \
- } \
- return 0; \
- case 7976: \
- switch (ch2) { \
- case 768: return 7978; \
- case 769: return 7980; \
- case 834: return 7982; \
- case 837: return 8088; \
- } \
- return 0; \
- case 7977: \
- switch (ch2) { \
- case 768: return 7979; \
- case 769: return 7981; \
- case 834: return 7983; \
- case 837: return 8089; \
- } \
- return 0; \
- case 7978: \
- switch (ch2) { \
- case 837: return 8090; \
- } \
- return 0; \
- case 7979: \
- switch (ch2) { \
- case 837: return 8091; \
- } \
- return 0; \
- case 7980: \
- switch (ch2) { \
- case 837: return 8092; \
- } \
- return 0; \
- case 7981: \
- switch (ch2) { \
- case 837: return 8093; \
- } \
- return 0; \
- case 7982: \
- switch (ch2) { \
- case 837: return 8094; \
- } \
- return 0; \
- case 7983: \
- switch (ch2) { \
- case 837: return 8095; \
- } \
- return 0; \
- case 7984: \
- switch (ch2) { \
- case 768: return 7986; \
- case 769: return 7988; \
- case 834: return 7990; \
- } \
- return 0; \
- case 7985: \
- switch (ch2) { \
- case 768: return 7987; \
- case 769: return 7989; \
- case 834: return 7991; \
- } \
- return 0; \
- case 7992: \
- switch (ch2) { \
- case 768: return 7994; \
- case 769: return 7996; \
- case 834: return 7998; \
- } \
- return 0; \
- case 7993: \
- switch (ch2) { \
- case 768: return 7995; \
- case 769: return 7997; \
- case 834: return 7999; \
- } \
- return 0; \
- case 8000: \
- switch (ch2) { \
- case 768: return 8002; \
- case 769: return 8004; \
- } \
- return 0; \
- case 8001: \
- switch (ch2) { \
- case 768: return 8003; \
- case 769: return 8005; \
- } \
- return 0; \
- case 8008: \
- switch (ch2) { \
- case 768: return 8010; \
- case 769: return 8012; \
- } \
- return 0; \
- case 8009: \
- switch (ch2) { \
- case 768: return 8011; \
- case 769: return 8013; \
- } \
- return 0; \
- case 8016: \
- switch (ch2) { \
- case 768: return 8018; \
- case 769: return 8020; \
- case 834: return 8022; \
- } \
- return 0; \
- case 8017: \
- switch (ch2) { \
- case 768: return 8019; \
- case 769: return 8021; \
- case 834: return 8023; \
- } \
- return 0; \
- case 8025: \
- switch (ch2) { \
- case 768: return 8027; \
- case 769: return 8029; \
- case 834: return 8031; \
- } \
- return 0; \
- case 8032: \
- switch (ch2) { \
- case 768: return 8034; \
- case 769: return 8036; \
- case 834: return 8038; \
- case 837: return 8096; \
- } \
- return 0; \
- case 8033: \
- switch (ch2) { \
- case 768: return 8035; \
- case 769: return 8037; \
- case 834: return 8039; \
- case 837: return 8097; \
- } \
- return 0; \
- case 8034: \
- switch (ch2) { \
- case 837: return 8098; \
- } \
- return 0; \
- case 8035: \
- switch (ch2) { \
- case 837: return 8099; \
- } \
- return 0; \
- case 8036: \
- switch (ch2) { \
- case 837: return 8100; \
- } \
- return 0; \
- case 8037: \
- switch (ch2) { \
- case 837: return 8101; \
- } \
- return 0; \
- case 8038: \
- switch (ch2) { \
- case 837: return 8102; \
- } \
- return 0; \
- case 8039: \
- switch (ch2) { \
- case 837: return 8103; \
- } \
- return 0; \
- case 8040: \
- switch (ch2) { \
- case 768: return 8042; \
- case 769: return 8044; \
- case 834: return 8046; \
- case 837: return 8104; \
- } \
- return 0; \
- case 8041: \
- switch (ch2) { \
- case 768: return 8043; \
- case 769: return 8045; \
- case 834: return 8047; \
- case 837: return 8105; \
- } \
- return 0; \
- case 8042: \
- switch (ch2) { \
- case 837: return 8106; \
- } \
- return 0; \
- case 8043: \
- switch (ch2) { \
- case 837: return 8107; \
- } \
- return 0; \
- case 8044: \
- switch (ch2) { \
- case 837: return 8108; \
- } \
- return 0; \
- case 8045: \
- switch (ch2) { \
- case 837: return 8109; \
- } \
- return 0; \
- case 8046: \
- switch (ch2) { \
- case 837: return 8110; \
- } \
- return 0; \
- case 8047: \
- switch (ch2) { \
- case 837: return 8111; \
- } \
- return 0; \
- case 8048: \
- switch (ch2) { \
- case 837: return 8114; \
- } \
- return 0; \
- case 8052: \
- switch (ch2) { \
- case 837: return 8130; \
- } \
- return 0; \
- case 8060: \
- switch (ch2) { \
- case 837: return 8178; \
- } \
- return 0; \
- case 8118: \
- switch (ch2) { \
- case 837: return 8119; \
- } \
- return 0; \
- case 8127: \
- switch (ch2) { \
- case 768: return 8141; \
- case 769: return 8142; \
- case 834: return 8143; \
- } \
- return 0; \
- case 8134: \
- switch (ch2) { \
- case 837: return 8135; \
- } \
- return 0; \
- case 8182: \
- switch (ch2) { \
- case 837: return 8183; \
- } \
- return 0; \
- case 8190: \
- switch (ch2) { \
- case 768: return 8157; \
- case 769: return 8158; \
- case 834: return 8159; \
- } \
- return 0; \
-} \
-return 0; \
-case 33: \
-switch (ch1) { \
- case 8592: \
- switch (ch2) { \
- case 824: return 8602; \
- } \
- return 0; \
- case 8594: \
- switch (ch2) { \
- case 824: return 8603; \
- } \
- return 0; \
- case 8596: \
- switch (ch2) { \
- case 824: return 8622; \
- } \
- return 0; \
- case 8656: \
- switch (ch2) { \
- case 824: return 8653; \
- } \
- return 0; \
- case 8658: \
- switch (ch2) { \
- case 824: return 8655; \
- } \
- return 0; \
- case 8660: \
- switch (ch2) { \
- case 824: return 8654; \
- } \
- return 0; \
-} \
-return 0; \
-case 34: \
-switch (ch1) { \
- case 8707: \
- switch (ch2) { \
- case 824: return 8708; \
- } \
- return 0; \
- case 8712: \
- switch (ch2) { \
- case 824: return 8713; \
- } \
- return 0; \
- case 8715: \
- switch (ch2) { \
- case 824: return 8716; \
- } \
- return 0; \
- case 8739: \
- switch (ch2) { \
- case 824: return 8740; \
- } \
- return 0; \
- case 8741: \
- switch (ch2) { \
- case 824: return 8742; \
- } \
- return 0; \
- case 8764: \
- switch (ch2) { \
- case 824: return 8769; \
- } \
- return 0; \
- case 8771: \
- switch (ch2) { \
- case 824: return 8772; \
- } \
- return 0; \
- case 8773: \
- switch (ch2) { \
- case 824: return 8775; \
- } \
- return 0; \
- case 8776: \
- switch (ch2) { \
- case 824: return 8777; \
- } \
- return 0; \
- case 8781: \
- switch (ch2) { \
- case 824: return 8813; \
- } \
- return 0; \
- case 8801: \
- switch (ch2) { \
- case 824: return 8802; \
- } \
- return 0; \
- case 8804: \
- switch (ch2) { \
- case 824: return 8816; \
- } \
- return 0; \
- case 8805: \
- switch (ch2) { \
- case 824: return 8817; \
- } \
- return 0; \
- case 8818: \
- switch (ch2) { \
- case 824: return 8820; \
- } \
- return 0; \
- case 8819: \
- switch (ch2) { \
- case 824: return 8821; \
- } \
- return 0; \
- case 8822: \
- switch (ch2) { \
- case 824: return 8824; \
- } \
- return 0; \
- case 8823: \
- switch (ch2) { \
- case 824: return 8825; \
- } \
- return 0; \
- case 8826: \
- switch (ch2) { \
- case 824: return 8832; \
- } \
- return 0; \
- case 8827: \
- switch (ch2) { \
- case 824: return 8833; \
- } \
- return 0; \
- case 8828: \
- switch (ch2) { \
- case 824: return 8928; \
- } \
- return 0; \
- case 8829: \
- switch (ch2) { \
- case 824: return 8929; \
- } \
- return 0; \
- case 8834: \
- switch (ch2) { \
- case 824: return 8836; \
- } \
- return 0; \
- case 8835: \
- switch (ch2) { \
- case 824: return 8837; \
- } \
- return 0; \
- case 8838: \
- switch (ch2) { \
- case 824: return 8840; \
- } \
- return 0; \
- case 8839: \
- switch (ch2) { \
- case 824: return 8841; \
- } \
- return 0; \
- case 8849: \
- switch (ch2) { \
- case 824: return 8930; \
- } \
- return 0; \
- case 8850: \
- switch (ch2) { \
- case 824: return 8931; \
- } \
- return 0; \
- case 8866: \
- switch (ch2) { \
- case 824: return 8876; \
- } \
- return 0; \
- case 8872: \
- switch (ch2) { \
- case 824: return 8877; \
- } \
- return 0; \
- case 8873: \
- switch (ch2) { \
- case 824: return 8878; \
- } \
- return 0; \
- case 8875: \
- switch (ch2) { \
- case 824: return 8879; \
- } \
- return 0; \
- case 8882: \
- switch (ch2) { \
- case 824: return 8938; \
- } \
- return 0; \
- case 8883: \
- switch (ch2) { \
- case 824: return 8939; \
- } \
- return 0; \
- case 8884: \
- switch (ch2) { \
- case 824: return 8940; \
- } \
- return 0; \
- case 8885: \
- switch (ch2) { \
- case 824: return 8941; \
- } \
- return 0; \
-} \
-return 0; \
-case 42: \
-switch (ch1) { \
- case 10973: \
- switch (ch2) { \
- case 824: return 10972; \
- } \
- return 0; \
-} \
-return 0; \
-case 48: \
-switch (ch1) { \
- case 12358: \
- switch (ch2) { \
- case 12441: return 12436; \
- } \
- return 0; \
- case 12363: \
- switch (ch2) { \
- case 12441: return 12364; \
- } \
- return 0; \
- case 12365: \
- switch (ch2) { \
- case 12441: return 12366; \
- } \
- return 0; \
- case 12367: \
- switch (ch2) { \
- case 12441: return 12368; \
- } \
- return 0; \
- case 12369: \
- switch (ch2) { \
- case 12441: return 12370; \
- } \
- return 0; \
- case 12371: \
- switch (ch2) { \
- case 12441: return 12372; \
- } \
- return 0; \
- case 12373: \
- switch (ch2) { \
- case 12441: return 12374; \
- } \
- return 0; \
- case 12375: \
- switch (ch2) { \
- case 12441: return 12376; \
- } \
- return 0; \
- case 12377: \
- switch (ch2) { \
- case 12441: return 12378; \
- } \
- return 0; \
- case 12379: \
- switch (ch2) { \
- case 12441: return 12380; \
- } \
- return 0; \
- case 12381: \
- switch (ch2) { \
- case 12441: return 12382; \
- } \
- return 0; \
- case 12383: \
- switch (ch2) { \
- case 12441: return 12384; \
- } \
- return 0; \
- case 12385: \
- switch (ch2) { \
- case 12441: return 12386; \
- } \
- return 0; \
- case 12388: \
- switch (ch2) { \
- case 12441: return 12389; \
- } \
- return 0; \
- case 12390: \
- switch (ch2) { \
- case 12441: return 12391; \
- } \
- return 0; \
- case 12392: \
- switch (ch2) { \
- case 12441: return 12393; \
- } \
- return 0; \
- case 12399: \
- switch (ch2) { \
- case 12441: return 12400; \
- case 12442: return 12401; \
- } \
- return 0; \
- case 12402: \
- switch (ch2) { \
- case 12441: return 12403; \
- case 12442: return 12404; \
- } \
- return 0; \
- case 12405: \
- switch (ch2) { \
- case 12441: return 12406; \
- case 12442: return 12407; \
- } \
- return 0; \
- case 12408: \
- switch (ch2) { \
- case 12441: return 12409; \
- case 12442: return 12410; \
- } \
- return 0; \
- case 12411: \
- switch (ch2) { \
- case 12441: return 12412; \
- case 12442: return 12413; \
- } \
- return 0; \
- case 12445: \
- switch (ch2) { \
- case 12441: return 12446; \
- } \
- return 0; \
- case 12454: \
- switch (ch2) { \
- case 12441: return 12532; \
- } \
- return 0; \
- case 12459: \
- switch (ch2) { \
- case 12441: return 12460; \
- } \
- return 0; \
- case 12461: \
- switch (ch2) { \
- case 12441: return 12462; \
- } \
- return 0; \
- case 12463: \
- switch (ch2) { \
- case 12441: return 12464; \
- } \
- return 0; \
- case 12465: \
- switch (ch2) { \
- case 12441: return 12466; \
- } \
- return 0; \
- case 12467: \
- switch (ch2) { \
- case 12441: return 12468; \
- } \
- return 0; \
- case 12469: \
- switch (ch2) { \
- case 12441: return 12470; \
- } \
- return 0; \
- case 12471: \
- switch (ch2) { \
- case 12441: return 12472; \
- } \
- return 0; \
- case 12473: \
- switch (ch2) { \
- case 12441: return 12474; \
- } \
- return 0; \
- case 12475: \
- switch (ch2) { \
- case 12441: return 12476; \
- } \
- return 0; \
- case 12477: \
- switch (ch2) { \
- case 12441: return 12478; \
- } \
- return 0; \
- case 12479: \
- switch (ch2) { \
- case 12441: return 12480; \
- } \
- return 0; \
- case 12481: \
- switch (ch2) { \
- case 12441: return 12482; \
- } \
- return 0; \
- case 12484: \
- switch (ch2) { \
- case 12441: return 12485; \
- } \
- return 0; \
- case 12486: \
- switch (ch2) { \
- case 12441: return 12487; \
- } \
- return 0; \
- case 12488: \
- switch (ch2) { \
- case 12441: return 12489; \
- } \
- return 0; \
- case 12495: \
- switch (ch2) { \
- case 12441: return 12496; \
- case 12442: return 12497; \
- } \
- return 0; \
- case 12498: \
- switch (ch2) { \
- case 12441: return 12499; \
- case 12442: return 12500; \
- } \
- return 0; \
- case 12501: \
- switch (ch2) { \
- case 12441: return 12502; \
- case 12442: return 12503; \
- } \
- return 0; \
- case 12504: \
- switch (ch2) { \
- case 12441: return 12505; \
- case 12442: return 12506; \
- } \
- return 0; \
- case 12507: \
- switch (ch2) { \
- case 12441: return 12508; \
- case 12442: return 12509; \
- } \
- return 0; \
- case 12527: \
- switch (ch2) { \
- case 12441: return 12535; \
- } \
- return 0; \
- case 12528: \
- switch (ch2) { \
- case 12441: return 12536; \
- } \
- return 0; \
- case 12529: \
- switch (ch2) { \
- case 12441: return 12537; \
- } \
- return 0; \
- case 12530: \
- switch (ch2) { \
- case 12441: return 12538; \
- } \
- return 0; \
- case 12541: \
- switch (ch2) { \
- case 12441: return 12542; \
- } \
- return 0; \
-} \
-return 0; \
-case 251: \
-switch (ch1) { \
- case 64329: \
- switch (ch2) { \
- case 1473: return 64300; \
- case 1474: return 64301; \
- } \
- return 0; \
-} \
-return 0; \
-case 465: \
-switch (ch1) { \
- case 119127: \
- switch (ch2) { \
- case 119141: return 119134; \
- } \
- return 0; \
- case 119128: \
- switch (ch2) { \
- case 119141: return 119135; \
- } \
- return 0; \
- case 119135: \
- switch (ch2) { \
- case 119150: return 119136; \
- case 119151: return 119137; \
- case 119152: return 119138; \
- case 119153: return 119139; \
- case 119154: return 119140; \
- } \
- return 0; \
- case 119225: \
- switch (ch2) { \
- case 119141: return 119227; \
- } \
- return 0; \
- case 119226: \
- switch (ch2) { \
- case 119141: return 119228; \
- } \
- return 0; \
- case 119227: \
- switch (ch2) { \
- case 119150: return 119229; \
- case 119151: return 119231; \
- } \
- return 0; \
- case 119228: \
- switch (ch2) { \
- case 119150: return 119230; \
- case 119151: return 119232; \
- } \
- return 0; \
-} \
-return 0; \
-} \
-return 0;
+ switch ((glui32)(ch1) >> 8) { \
+ case 0: \
+ switch (ch1) { \
+ case 60: \
+ switch (ch2) { \
+ case 824: return 8814; \
+ } \
+ return 0; \
+ case 61: \
+ switch (ch2) { \
+ case 824: return 8800; \
+ } \
+ return 0; \
+ case 62: \
+ switch (ch2) { \
+ case 824: return 8815; \
+ } \
+ return 0; \
+ case 65: \
+ switch (ch2) { \
+ case 768: return 192; \
+ case 769: return 193; \
+ case 770: return 194; \
+ case 771: return 195; \
+ case 772: return 256; \
+ case 774: return 258; \
+ case 775: return 550; \
+ case 776: return 196; \
+ case 777: return 7842; \
+ case 778: return 197; \
+ case 780: return 461; \
+ case 783: return 512; \
+ case 785: return 514; \
+ case 803: return 7840; \
+ case 805: return 7680; \
+ case 808: return 260; \
+ } \
+ return 0; \
+ case 66: \
+ switch (ch2) { \
+ case 775: return 7682; \
+ case 803: return 7684; \
+ case 817: return 7686; \
+ } \
+ return 0; \
+ case 67: \
+ switch (ch2) { \
+ case 769: return 262; \
+ case 770: return 264; \
+ case 775: return 266; \
+ case 780: return 268; \
+ case 807: return 199; \
+ } \
+ return 0; \
+ case 68: \
+ switch (ch2) { \
+ case 775: return 7690; \
+ case 780: return 270; \
+ case 803: return 7692; \
+ case 807: return 7696; \
+ case 813: return 7698; \
+ case 817: return 7694; \
+ } \
+ return 0; \
+ case 69: \
+ switch (ch2) { \
+ case 768: return 200; \
+ case 769: return 201; \
+ case 770: return 202; \
+ case 771: return 7868; \
+ case 772: return 274; \
+ case 774: return 276; \
+ case 775: return 278; \
+ case 776: return 203; \
+ case 777: return 7866; \
+ case 780: return 282; \
+ case 783: return 516; \
+ case 785: return 518; \
+ case 803: return 7864; \
+ case 807: return 552; \
+ case 808: return 280; \
+ case 813: return 7704; \
+ case 816: return 7706; \
+ } \
+ return 0; \
+ case 70: \
+ switch (ch2) { \
+ case 775: return 7710; \
+ } \
+ return 0; \
+ case 71: \
+ switch (ch2) { \
+ case 769: return 500; \
+ case 770: return 284; \
+ case 772: return 7712; \
+ case 774: return 286; \
+ case 775: return 288; \
+ case 780: return 486; \
+ case 807: return 290; \
+ } \
+ return 0; \
+ case 72: \
+ switch (ch2) { \
+ case 770: return 292; \
+ case 775: return 7714; \
+ case 776: return 7718; \
+ case 780: return 542; \
+ case 803: return 7716; \
+ case 807: return 7720; \
+ case 814: return 7722; \
+ } \
+ return 0; \
+ case 73: \
+ switch (ch2) { \
+ case 768: return 204; \
+ case 769: return 205; \
+ case 770: return 206; \
+ case 771: return 296; \
+ case 772: return 298; \
+ case 774: return 300; \
+ case 775: return 304; \
+ case 776: return 207; \
+ case 777: return 7880; \
+ case 780: return 463; \
+ case 783: return 520; \
+ case 785: return 522; \
+ case 803: return 7882; \
+ case 808: return 302; \
+ case 816: return 7724; \
+ } \
+ return 0; \
+ case 74: \
+ switch (ch2) { \
+ case 770: return 308; \
+ } \
+ return 0; \
+ case 75: \
+ switch (ch2) { \
+ case 769: return 7728; \
+ case 780: return 488; \
+ case 803: return 7730; \
+ case 807: return 310; \
+ case 817: return 7732; \
+ } \
+ return 0; \
+ case 76: \
+ switch (ch2) { \
+ case 769: return 313; \
+ case 780: return 317; \
+ case 803: return 7734; \
+ case 807: return 315; \
+ case 813: return 7740; \
+ case 817: return 7738; \
+ } \
+ return 0; \
+ case 77: \
+ switch (ch2) { \
+ case 769: return 7742; \
+ case 775: return 7744; \
+ case 803: return 7746; \
+ } \
+ return 0; \
+ case 78: \
+ switch (ch2) { \
+ case 768: return 504; \
+ case 769: return 323; \
+ case 771: return 209; \
+ case 775: return 7748; \
+ case 780: return 327; \
+ case 803: return 7750; \
+ case 807: return 325; \
+ case 813: return 7754; \
+ case 817: return 7752; \
+ } \
+ return 0; \
+ case 79: \
+ switch (ch2) { \
+ case 768: return 210; \
+ case 769: return 211; \
+ case 770: return 212; \
+ case 771: return 213; \
+ case 772: return 332; \
+ case 774: return 334; \
+ case 775: return 558; \
+ case 776: return 214; \
+ case 777: return 7886; \
+ case 779: return 336; \
+ case 780: return 465; \
+ case 783: return 524; \
+ case 785: return 526; \
+ case 795: return 416; \
+ case 803: return 7884; \
+ case 808: return 490; \
+ } \
+ return 0; \
+ case 80: \
+ switch (ch2) { \
+ case 769: return 7764; \
+ case 775: return 7766; \
+ } \
+ return 0; \
+ case 82: \
+ switch (ch2) { \
+ case 769: return 340; \
+ case 775: return 7768; \
+ case 780: return 344; \
+ case 783: return 528; \
+ case 785: return 530; \
+ case 803: return 7770; \
+ case 807: return 342; \
+ case 817: return 7774; \
+ } \
+ return 0; \
+ case 83: \
+ switch (ch2) { \
+ case 769: return 346; \
+ case 770: return 348; \
+ case 775: return 7776; \
+ case 780: return 352; \
+ case 803: return 7778; \
+ case 806: return 536; \
+ case 807: return 350; \
+ } \
+ return 0; \
+ case 84: \
+ switch (ch2) { \
+ case 775: return 7786; \
+ case 780: return 356; \
+ case 803: return 7788; \
+ case 806: return 538; \
+ case 807: return 354; \
+ case 813: return 7792; \
+ case 817: return 7790; \
+ } \
+ return 0; \
+ case 85: \
+ switch (ch2) { \
+ case 768: return 217; \
+ case 769: return 218; \
+ case 770: return 219; \
+ case 771: return 360; \
+ case 772: return 362; \
+ case 774: return 364; \
+ case 776: return 220; \
+ case 777: return 7910; \
+ case 778: return 366; \
+ case 779: return 368; \
+ case 780: return 467; \
+ case 783: return 532; \
+ case 785: return 534; \
+ case 795: return 431; \
+ case 803: return 7908; \
+ case 804: return 7794; \
+ case 808: return 370; \
+ case 813: return 7798; \
+ case 816: return 7796; \
+ } \
+ return 0; \
+ case 86: \
+ switch (ch2) { \
+ case 771: return 7804; \
+ case 803: return 7806; \
+ } \
+ return 0; \
+ case 87: \
+ switch (ch2) { \
+ case 768: return 7808; \
+ case 769: return 7810; \
+ case 770: return 372; \
+ case 775: return 7814; \
+ case 776: return 7812; \
+ case 803: return 7816; \
+ } \
+ return 0; \
+ case 88: \
+ switch (ch2) { \
+ case 775: return 7818; \
+ case 776: return 7820; \
+ } \
+ return 0; \
+ case 89: \
+ switch (ch2) { \
+ case 768: return 7922; \
+ case 769: return 221; \
+ case 770: return 374; \
+ case 771: return 7928; \
+ case 772: return 562; \
+ case 775: return 7822; \
+ case 776: return 376; \
+ case 777: return 7926; \
+ case 803: return 7924; \
+ } \
+ return 0; \
+ case 90: \
+ switch (ch2) { \
+ case 769: return 377; \
+ case 770: return 7824; \
+ case 775: return 379; \
+ case 780: return 381; \
+ case 803: return 7826; \
+ case 817: return 7828; \
+ } \
+ return 0; \
+ case 97: \
+ switch (ch2) { \
+ case 768: return 224; \
+ case 769: return 225; \
+ case 770: return 226; \
+ case 771: return 227; \
+ case 772: return 257; \
+ case 774: return 259; \
+ case 775: return 551; \
+ case 776: return 228; \
+ case 777: return 7843; \
+ case 778: return 229; \
+ case 780: return 462; \
+ case 783: return 513; \
+ case 785: return 515; \
+ case 803: return 7841; \
+ case 805: return 7681; \
+ case 808: return 261; \
+ } \
+ return 0; \
+ case 98: \
+ switch (ch2) { \
+ case 775: return 7683; \
+ case 803: return 7685; \
+ case 817: return 7687; \
+ } \
+ return 0; \
+ case 99: \
+ switch (ch2) { \
+ case 769: return 263; \
+ case 770: return 265; \
+ case 775: return 267; \
+ case 780: return 269; \
+ case 807: return 231; \
+ } \
+ return 0; \
+ case 100: \
+ switch (ch2) { \
+ case 775: return 7691; \
+ case 780: return 271; \
+ case 803: return 7693; \
+ case 807: return 7697; \
+ case 813: return 7699; \
+ case 817: return 7695; \
+ } \
+ return 0; \
+ case 101: \
+ switch (ch2) { \
+ case 768: return 232; \
+ case 769: return 233; \
+ case 770: return 234; \
+ case 771: return 7869; \
+ case 772: return 275; \
+ case 774: return 277; \
+ case 775: return 279; \
+ case 776: return 235; \
+ case 777: return 7867; \
+ case 780: return 283; \
+ case 783: return 517; \
+ case 785: return 519; \
+ case 803: return 7865; \
+ case 807: return 553; \
+ case 808: return 281; \
+ case 813: return 7705; \
+ case 816: return 7707; \
+ } \
+ return 0; \
+ case 102: \
+ switch (ch2) { \
+ case 775: return 7711; \
+ } \
+ return 0; \
+ case 103: \
+ switch (ch2) { \
+ case 769: return 501; \
+ case 770: return 285; \
+ case 772: return 7713; \
+ case 774: return 287; \
+ case 775: return 289; \
+ case 780: return 487; \
+ case 807: return 291; \
+ } \
+ return 0; \
+ case 104: \
+ switch (ch2) { \
+ case 770: return 293; \
+ case 775: return 7715; \
+ case 776: return 7719; \
+ case 780: return 543; \
+ case 803: return 7717; \
+ case 807: return 7721; \
+ case 814: return 7723; \
+ case 817: return 7830; \
+ } \
+ return 0; \
+ case 105: \
+ switch (ch2) { \
+ case 768: return 236; \
+ case 769: return 237; \
+ case 770: return 238; \
+ case 771: return 297; \
+ case 772: return 299; \
+ case 774: return 301; \
+ case 776: return 239; \
+ case 777: return 7881; \
+ case 780: return 464; \
+ case 783: return 521; \
+ case 785: return 523; \
+ case 803: return 7883; \
+ case 808: return 303; \
+ case 816: return 7725; \
+ } \
+ return 0; \
+ case 106: \
+ switch (ch2) { \
+ case 770: return 309; \
+ case 780: return 496; \
+ } \
+ return 0; \
+ case 107: \
+ switch (ch2) { \
+ case 769: return 7729; \
+ case 780: return 489; \
+ case 803: return 7731; \
+ case 807: return 311; \
+ case 817: return 7733; \
+ } \
+ return 0; \
+ case 108: \
+ switch (ch2) { \
+ case 769: return 314; \
+ case 780: return 318; \
+ case 803: return 7735; \
+ case 807: return 316; \
+ case 813: return 7741; \
+ case 817: return 7739; \
+ } \
+ return 0; \
+ case 109: \
+ switch (ch2) { \
+ case 769: return 7743; \
+ case 775: return 7745; \
+ case 803: return 7747; \
+ } \
+ return 0; \
+ case 110: \
+ switch (ch2) { \
+ case 768: return 505; \
+ case 769: return 324; \
+ case 771: return 241; \
+ case 775: return 7749; \
+ case 780: return 328; \
+ case 803: return 7751; \
+ case 807: return 326; \
+ case 813: return 7755; \
+ case 817: return 7753; \
+ } \
+ return 0; \
+ case 111: \
+ switch (ch2) { \
+ case 768: return 242; \
+ case 769: return 243; \
+ case 770: return 244; \
+ case 771: return 245; \
+ case 772: return 333; \
+ case 774: return 335; \
+ case 775: return 559; \
+ case 776: return 246; \
+ case 777: return 7887; \
+ case 779: return 337; \
+ case 780: return 466; \
+ case 783: return 525; \
+ case 785: return 527; \
+ case 795: return 417; \
+ case 803: return 7885; \
+ case 808: return 491; \
+ } \
+ return 0; \
+ case 112: \
+ switch (ch2) { \
+ case 769: return 7765; \
+ case 775: return 7767; \
+ } \
+ return 0; \
+ case 114: \
+ switch (ch2) { \
+ case 769: return 341; \
+ case 775: return 7769; \
+ case 780: return 345; \
+ case 783: return 529; \
+ case 785: return 531; \
+ case 803: return 7771; \
+ case 807: return 343; \
+ case 817: return 7775; \
+ } \
+ return 0; \
+ case 115: \
+ switch (ch2) { \
+ case 769: return 347; \
+ case 770: return 349; \
+ case 775: return 7777; \
+ case 780: return 353; \
+ case 803: return 7779; \
+ case 806: return 537; \
+ case 807: return 351; \
+ } \
+ return 0; \
+ case 116: \
+ switch (ch2) { \
+ case 775: return 7787; \
+ case 776: return 7831; \
+ case 780: return 357; \
+ case 803: return 7789; \
+ case 806: return 539; \
+ case 807: return 355; \
+ case 813: return 7793; \
+ case 817: return 7791; \
+ } \
+ return 0; \
+ case 117: \
+ switch (ch2) { \
+ case 768: return 249; \
+ case 769: return 250; \
+ case 770: return 251; \
+ case 771: return 361; \
+ case 772: return 363; \
+ case 774: return 365; \
+ case 776: return 252; \
+ case 777: return 7911; \
+ case 778: return 367; \
+ case 779: return 369; \
+ case 780: return 468; \
+ case 783: return 533; \
+ case 785: return 535; \
+ case 795: return 432; \
+ case 803: return 7909; \
+ case 804: return 7795; \
+ case 808: return 371; \
+ case 813: return 7799; \
+ case 816: return 7797; \
+ } \
+ return 0; \
+ case 118: \
+ switch (ch2) { \
+ case 771: return 7805; \
+ case 803: return 7807; \
+ } \
+ return 0; \
+ case 119: \
+ switch (ch2) { \
+ case 768: return 7809; \
+ case 769: return 7811; \
+ case 770: return 373; \
+ case 775: return 7815; \
+ case 776: return 7813; \
+ case 778: return 7832; \
+ case 803: return 7817; \
+ } \
+ return 0; \
+ case 120: \
+ switch (ch2) { \
+ case 775: return 7819; \
+ case 776: return 7821; \
+ } \
+ return 0; \
+ case 121: \
+ switch (ch2) { \
+ case 768: return 7923; \
+ case 769: return 253; \
+ case 770: return 375; \
+ case 771: return 7929; \
+ case 772: return 563; \
+ case 775: return 7823; \
+ case 776: return 255; \
+ case 777: return 7927; \
+ case 778: return 7833; \
+ case 803: return 7925; \
+ } \
+ return 0; \
+ case 122: \
+ switch (ch2) { \
+ case 769: return 378; \
+ case 770: return 7825; \
+ case 775: return 380; \
+ case 780: return 382; \
+ case 803: return 7827; \
+ case 817: return 7829; \
+ } \
+ return 0; \
+ case 168: \
+ switch (ch2) { \
+ case 768: return 8173; \
+ case 769: return 901; \
+ case 834: return 8129; \
+ } \
+ return 0; \
+ case 194: \
+ switch (ch2) { \
+ case 768: return 7846; \
+ case 769: return 7844; \
+ case 771: return 7850; \
+ case 777: return 7848; \
+ } \
+ return 0; \
+ case 196: \
+ switch (ch2) { \
+ case 772: return 478; \
+ } \
+ return 0; \
+ case 197: \
+ switch (ch2) { \
+ case 769: return 506; \
+ } \
+ return 0; \
+ case 198: \
+ switch (ch2) { \
+ case 769: return 508; \
+ case 772: return 482; \
+ } \
+ return 0; \
+ case 199: \
+ switch (ch2) { \
+ case 769: return 7688; \
+ } \
+ return 0; \
+ case 202: \
+ switch (ch2) { \
+ case 768: return 7872; \
+ case 769: return 7870; \
+ case 771: return 7876; \
+ case 777: return 7874; \
+ } \
+ return 0; \
+ case 207: \
+ switch (ch2) { \
+ case 769: return 7726; \
+ } \
+ return 0; \
+ case 212: \
+ switch (ch2) { \
+ case 768: return 7890; \
+ case 769: return 7888; \
+ case 771: return 7894; \
+ case 777: return 7892; \
+ } \
+ return 0; \
+ case 213: \
+ switch (ch2) { \
+ case 769: return 7756; \
+ case 772: return 556; \
+ case 776: return 7758; \
+ } \
+ return 0; \
+ case 214: \
+ switch (ch2) { \
+ case 772: return 554; \
+ } \
+ return 0; \
+ case 216: \
+ switch (ch2) { \
+ case 769: return 510; \
+ } \
+ return 0; \
+ case 220: \
+ switch (ch2) { \
+ case 768: return 475; \
+ case 769: return 471; \
+ case 772: return 469; \
+ case 780: return 473; \
+ } \
+ return 0; \
+ case 226: \
+ switch (ch2) { \
+ case 768: return 7847; \
+ case 769: return 7845; \
+ case 771: return 7851; \
+ case 777: return 7849; \
+ } \
+ return 0; \
+ case 228: \
+ switch (ch2) { \
+ case 772: return 479; \
+ } \
+ return 0; \
+ case 229: \
+ switch (ch2) { \
+ case 769: return 507; \
+ } \
+ return 0; \
+ case 230: \
+ switch (ch2) { \
+ case 769: return 509; \
+ case 772: return 483; \
+ } \
+ return 0; \
+ case 231: \
+ switch (ch2) { \
+ case 769: return 7689; \
+ } \
+ return 0; \
+ case 234: \
+ switch (ch2) { \
+ case 768: return 7873; \
+ case 769: return 7871; \
+ case 771: return 7877; \
+ case 777: return 7875; \
+ } \
+ return 0; \
+ case 239: \
+ switch (ch2) { \
+ case 769: return 7727; \
+ } \
+ return 0; \
+ case 244: \
+ switch (ch2) { \
+ case 768: return 7891; \
+ case 769: return 7889; \
+ case 771: return 7895; \
+ case 777: return 7893; \
+ } \
+ return 0; \
+ case 245: \
+ switch (ch2) { \
+ case 769: return 7757; \
+ case 772: return 557; \
+ case 776: return 7759; \
+ } \
+ return 0; \
+ case 246: \
+ switch (ch2) { \
+ case 772: return 555; \
+ } \
+ return 0; \
+ case 248: \
+ switch (ch2) { \
+ case 769: return 511; \
+ } \
+ return 0; \
+ case 252: \
+ switch (ch2) { \
+ case 768: return 476; \
+ case 769: return 472; \
+ case 772: return 470; \
+ case 780: return 474; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 1: \
+ switch (ch1) { \
+ case 258: \
+ switch (ch2) { \
+ case 768: return 7856; \
+ case 769: return 7854; \
+ case 771: return 7860; \
+ case 777: return 7858; \
+ } \
+ return 0; \
+ case 259: \
+ switch (ch2) { \
+ case 768: return 7857; \
+ case 769: return 7855; \
+ case 771: return 7861; \
+ case 777: return 7859; \
+ } \
+ return 0; \
+ case 274: \
+ switch (ch2) { \
+ case 768: return 7700; \
+ case 769: return 7702; \
+ } \
+ return 0; \
+ case 275: \
+ switch (ch2) { \
+ case 768: return 7701; \
+ case 769: return 7703; \
+ } \
+ return 0; \
+ case 332: \
+ switch (ch2) { \
+ case 768: return 7760; \
+ case 769: return 7762; \
+ } \
+ return 0; \
+ case 333: \
+ switch (ch2) { \
+ case 768: return 7761; \
+ case 769: return 7763; \
+ } \
+ return 0; \
+ case 346: \
+ switch (ch2) { \
+ case 775: return 7780; \
+ } \
+ return 0; \
+ case 347: \
+ switch (ch2) { \
+ case 775: return 7781; \
+ } \
+ return 0; \
+ case 352: \
+ switch (ch2) { \
+ case 775: return 7782; \
+ } \
+ return 0; \
+ case 353: \
+ switch (ch2) { \
+ case 775: return 7783; \
+ } \
+ return 0; \
+ case 360: \
+ switch (ch2) { \
+ case 769: return 7800; \
+ } \
+ return 0; \
+ case 361: \
+ switch (ch2) { \
+ case 769: return 7801; \
+ } \
+ return 0; \
+ case 362: \
+ switch (ch2) { \
+ case 776: return 7802; \
+ } \
+ return 0; \
+ case 363: \
+ switch (ch2) { \
+ case 776: return 7803; \
+ } \
+ return 0; \
+ case 383: \
+ switch (ch2) { \
+ case 775: return 7835; \
+ } \
+ return 0; \
+ case 416: \
+ switch (ch2) { \
+ case 768: return 7900; \
+ case 769: return 7898; \
+ case 771: return 7904; \
+ case 777: return 7902; \
+ case 803: return 7906; \
+ } \
+ return 0; \
+ case 417: \
+ switch (ch2) { \
+ case 768: return 7901; \
+ case 769: return 7899; \
+ case 771: return 7905; \
+ case 777: return 7903; \
+ case 803: return 7907; \
+ } \
+ return 0; \
+ case 431: \
+ switch (ch2) { \
+ case 768: return 7914; \
+ case 769: return 7912; \
+ case 771: return 7918; \
+ case 777: return 7916; \
+ case 803: return 7920; \
+ } \
+ return 0; \
+ case 432: \
+ switch (ch2) { \
+ case 768: return 7915; \
+ case 769: return 7913; \
+ case 771: return 7919; \
+ case 777: return 7917; \
+ case 803: return 7921; \
+ } \
+ return 0; \
+ case 439: \
+ switch (ch2) { \
+ case 780: return 494; \
+ } \
+ return 0; \
+ case 490: \
+ switch (ch2) { \
+ case 772: return 492; \
+ } \
+ return 0; \
+ case 491: \
+ switch (ch2) { \
+ case 772: return 493; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 2: \
+ switch (ch1) { \
+ case 550: \
+ switch (ch2) { \
+ case 772: return 480; \
+ } \
+ return 0; \
+ case 551: \
+ switch (ch2) { \
+ case 772: return 481; \
+ } \
+ return 0; \
+ case 552: \
+ switch (ch2) { \
+ case 774: return 7708; \
+ } \
+ return 0; \
+ case 553: \
+ switch (ch2) { \
+ case 774: return 7709; \
+ } \
+ return 0; \
+ case 558: \
+ switch (ch2) { \
+ case 772: return 560; \
+ } \
+ return 0; \
+ case 559: \
+ switch (ch2) { \
+ case 772: return 561; \
+ } \
+ return 0; \
+ case 658: \
+ switch (ch2) { \
+ case 780: return 495; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 3: \
+ switch (ch1) { \
+ case 776: \
+ switch (ch2) { \
+ case 769: return 836; \
+ } \
+ return 0; \
+ case 913: \
+ switch (ch2) { \
+ case 768: return 8122; \
+ case 769: return 902; \
+ case 772: return 8121; \
+ case 774: return 8120; \
+ case 787: return 7944; \
+ case 788: return 7945; \
+ case 837: return 8124; \
+ } \
+ return 0; \
+ case 917: \
+ switch (ch2) { \
+ case 768: return 8136; \
+ case 769: return 904; \
+ case 787: return 7960; \
+ case 788: return 7961; \
+ } \
+ return 0; \
+ case 919: \
+ switch (ch2) { \
+ case 768: return 8138; \
+ case 769: return 905; \
+ case 787: return 7976; \
+ case 788: return 7977; \
+ case 837: return 8140; \
+ } \
+ return 0; \
+ case 921: \
+ switch (ch2) { \
+ case 768: return 8154; \
+ case 769: return 906; \
+ case 772: return 8153; \
+ case 774: return 8152; \
+ case 776: return 938; \
+ case 787: return 7992; \
+ case 788: return 7993; \
+ } \
+ return 0; \
+ case 927: \
+ switch (ch2) { \
+ case 768: return 8184; \
+ case 769: return 908; \
+ case 787: return 8008; \
+ case 788: return 8009; \
+ } \
+ return 0; \
+ case 929: \
+ switch (ch2) { \
+ case 788: return 8172; \
+ } \
+ return 0; \
+ case 933: \
+ switch (ch2) { \
+ case 768: return 8170; \
+ case 769: return 910; \
+ case 772: return 8169; \
+ case 774: return 8168; \
+ case 776: return 939; \
+ case 788: return 8025; \
+ } \
+ return 0; \
+ case 937: \
+ switch (ch2) { \
+ case 768: return 8186; \
+ case 769: return 911; \
+ case 787: return 8040; \
+ case 788: return 8041; \
+ case 837: return 8188; \
+ } \
+ return 0; \
+ case 940: \
+ switch (ch2) { \
+ case 837: return 8116; \
+ } \
+ return 0; \
+ case 942: \
+ switch (ch2) { \
+ case 837: return 8132; \
+ } \
+ return 0; \
+ case 945: \
+ switch (ch2) { \
+ case 768: return 8048; \
+ case 769: return 940; \
+ case 772: return 8113; \
+ case 774: return 8112; \
+ case 787: return 7936; \
+ case 788: return 7937; \
+ case 834: return 8118; \
+ case 837: return 8115; \
+ } \
+ return 0; \
+ case 949: \
+ switch (ch2) { \
+ case 768: return 8050; \
+ case 769: return 941; \
+ case 787: return 7952; \
+ case 788: return 7953; \
+ } \
+ return 0; \
+ case 951: \
+ switch (ch2) { \
+ case 768: return 8052; \
+ case 769: return 942; \
+ case 787: return 7968; \
+ case 788: return 7969; \
+ case 834: return 8134; \
+ case 837: return 8131; \
+ } \
+ return 0; \
+ case 953: \
+ switch (ch2) { \
+ case 768: return 8054; \
+ case 769: return 943; \
+ case 772: return 8145; \
+ case 774: return 8144; \
+ case 776: return 970; \
+ case 787: return 7984; \
+ case 788: return 7985; \
+ case 834: return 8150; \
+ } \
+ return 0; \
+ case 959: \
+ switch (ch2) { \
+ case 768: return 8056; \
+ case 769: return 972; \
+ case 787: return 8000; \
+ case 788: return 8001; \
+ } \
+ return 0; \
+ case 961: \
+ switch (ch2) { \
+ case 787: return 8164; \
+ case 788: return 8165; \
+ } \
+ return 0; \
+ case 965: \
+ switch (ch2) { \
+ case 768: return 8058; \
+ case 769: return 973; \
+ case 772: return 8161; \
+ case 774: return 8160; \
+ case 776: return 971; \
+ case 787: return 8016; \
+ case 788: return 8017; \
+ case 834: return 8166; \
+ } \
+ return 0; \
+ case 969: \
+ switch (ch2) { \
+ case 768: return 8060; \
+ case 769: return 974; \
+ case 787: return 8032; \
+ case 788: return 8033; \
+ case 834: return 8182; \
+ case 837: return 8179; \
+ } \
+ return 0; \
+ case 970: \
+ switch (ch2) { \
+ case 768: return 8146; \
+ case 769: return 912; \
+ case 834: return 8151; \
+ } \
+ return 0; \
+ case 971: \
+ switch (ch2) { \
+ case 768: return 8162; \
+ case 769: return 944; \
+ case 834: return 8167; \
+ } \
+ return 0; \
+ case 974: \
+ switch (ch2) { \
+ case 837: return 8180; \
+ } \
+ return 0; \
+ case 978: \
+ switch (ch2) { \
+ case 769: return 979; \
+ case 776: return 980; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 4: \
+ switch (ch1) { \
+ case 1030: \
+ switch (ch2) { \
+ case 776: return 1031; \
+ } \
+ return 0; \
+ case 1040: \
+ switch (ch2) { \
+ case 774: return 1232; \
+ case 776: return 1234; \
+ } \
+ return 0; \
+ case 1043: \
+ switch (ch2) { \
+ case 769: return 1027; \
+ } \
+ return 0; \
+ case 1045: \
+ switch (ch2) { \
+ case 768: return 1024; \
+ case 774: return 1238; \
+ case 776: return 1025; \
+ } \
+ return 0; \
+ case 1046: \
+ switch (ch2) { \
+ case 774: return 1217; \
+ case 776: return 1244; \
+ } \
+ return 0; \
+ case 1047: \
+ switch (ch2) { \
+ case 776: return 1246; \
+ } \
+ return 0; \
+ case 1048: \
+ switch (ch2) { \
+ case 768: return 1037; \
+ case 772: return 1250; \
+ case 774: return 1049; \
+ case 776: return 1252; \
+ } \
+ return 0; \
+ case 1050: \
+ switch (ch2) { \
+ case 769: return 1036; \
+ } \
+ return 0; \
+ case 1054: \
+ switch (ch2) { \
+ case 776: return 1254; \
+ } \
+ return 0; \
+ case 1059: \
+ switch (ch2) { \
+ case 772: return 1262; \
+ case 774: return 1038; \
+ case 776: return 1264; \
+ case 779: return 1266; \
+ } \
+ return 0; \
+ case 1063: \
+ switch (ch2) { \
+ case 776: return 1268; \
+ } \
+ return 0; \
+ case 1067: \
+ switch (ch2) { \
+ case 776: return 1272; \
+ } \
+ return 0; \
+ case 1069: \
+ switch (ch2) { \
+ case 776: return 1260; \
+ } \
+ return 0; \
+ case 1072: \
+ switch (ch2) { \
+ case 774: return 1233; \
+ case 776: return 1235; \
+ } \
+ return 0; \
+ case 1075: \
+ switch (ch2) { \
+ case 769: return 1107; \
+ } \
+ return 0; \
+ case 1077: \
+ switch (ch2) { \
+ case 768: return 1104; \
+ case 774: return 1239; \
+ case 776: return 1105; \
+ } \
+ return 0; \
+ case 1078: \
+ switch (ch2) { \
+ case 774: return 1218; \
+ case 776: return 1245; \
+ } \
+ return 0; \
+ case 1079: \
+ switch (ch2) { \
+ case 776: return 1247; \
+ } \
+ return 0; \
+ case 1080: \
+ switch (ch2) { \
+ case 768: return 1117; \
+ case 772: return 1251; \
+ case 774: return 1081; \
+ case 776: return 1253; \
+ } \
+ return 0; \
+ case 1082: \
+ switch (ch2) { \
+ case 769: return 1116; \
+ } \
+ return 0; \
+ case 1086: \
+ switch (ch2) { \
+ case 776: return 1255; \
+ } \
+ return 0; \
+ case 1091: \
+ switch (ch2) { \
+ case 772: return 1263; \
+ case 774: return 1118; \
+ case 776: return 1265; \
+ case 779: return 1267; \
+ } \
+ return 0; \
+ case 1095: \
+ switch (ch2) { \
+ case 776: return 1269; \
+ } \
+ return 0; \
+ case 1099: \
+ switch (ch2) { \
+ case 776: return 1273; \
+ } \
+ return 0; \
+ case 1101: \
+ switch (ch2) { \
+ case 776: return 1261; \
+ } \
+ return 0; \
+ case 1110: \
+ switch (ch2) { \
+ case 776: return 1111; \
+ } \
+ return 0; \
+ case 1140: \
+ switch (ch2) { \
+ case 783: return 1142; \
+ } \
+ return 0; \
+ case 1141: \
+ switch (ch2) { \
+ case 783: return 1143; \
+ } \
+ return 0; \
+ case 1240: \
+ switch (ch2) { \
+ case 776: return 1242; \
+ } \
+ return 0; \
+ case 1241: \
+ switch (ch2) { \
+ case 776: return 1243; \
+ } \
+ return 0; \
+ case 1256: \
+ switch (ch2) { \
+ case 776: return 1258; \
+ } \
+ return 0; \
+ case 1257: \
+ switch (ch2) { \
+ case 776: return 1259; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 5: \
+ switch (ch1) { \
+ case 1488: \
+ switch (ch2) { \
+ case 1463: return 64302; \
+ case 1464: return 64303; \
+ case 1468: return 64304; \
+ } \
+ return 0; \
+ case 1489: \
+ switch (ch2) { \
+ case 1468: return 64305; \
+ case 1471: return 64332; \
+ } \
+ return 0; \
+ case 1490: \
+ switch (ch2) { \
+ case 1468: return 64306; \
+ } \
+ return 0; \
+ case 1491: \
+ switch (ch2) { \
+ case 1468: return 64307; \
+ } \
+ return 0; \
+ case 1492: \
+ switch (ch2) { \
+ case 1468: return 64308; \
+ } \
+ return 0; \
+ case 1493: \
+ switch (ch2) { \
+ case 1465: return 64331; \
+ case 1468: return 64309; \
+ } \
+ return 0; \
+ case 1494: \
+ switch (ch2) { \
+ case 1468: return 64310; \
+ } \
+ return 0; \
+ case 1496: \
+ switch (ch2) { \
+ case 1468: return 64312; \
+ } \
+ return 0; \
+ case 1497: \
+ switch (ch2) { \
+ case 1460: return 64285; \
+ case 1468: return 64313; \
+ } \
+ return 0; \
+ case 1498: \
+ switch (ch2) { \
+ case 1468: return 64314; \
+ } \
+ return 0; \
+ case 1499: \
+ switch (ch2) { \
+ case 1468: return 64315; \
+ case 1471: return 64333; \
+ } \
+ return 0; \
+ case 1500: \
+ switch (ch2) { \
+ case 1468: return 64316; \
+ } \
+ return 0; \
+ case 1502: \
+ switch (ch2) { \
+ case 1468: return 64318; \
+ } \
+ return 0; \
+ case 1504: \
+ switch (ch2) { \
+ case 1468: return 64320; \
+ } \
+ return 0; \
+ case 1505: \
+ switch (ch2) { \
+ case 1468: return 64321; \
+ } \
+ return 0; \
+ case 1507: \
+ switch (ch2) { \
+ case 1468: return 64323; \
+ } \
+ return 0; \
+ case 1508: \
+ switch (ch2) { \
+ case 1468: return 64324; \
+ case 1471: return 64334; \
+ } \
+ return 0; \
+ case 1510: \
+ switch (ch2) { \
+ case 1468: return 64326; \
+ } \
+ return 0; \
+ case 1511: \
+ switch (ch2) { \
+ case 1468: return 64327; \
+ } \
+ return 0; \
+ case 1512: \
+ switch (ch2) { \
+ case 1468: return 64328; \
+ } \
+ return 0; \
+ case 1513: \
+ switch (ch2) { \
+ case 1468: return 64329; \
+ case 1473: return 64298; \
+ case 1474: return 64299; \
+ } \
+ return 0; \
+ case 1514: \
+ switch (ch2) { \
+ case 1468: return 64330; \
+ } \
+ return 0; \
+ case 1522: \
+ switch (ch2) { \
+ case 1463: return 64287; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 6: \
+ switch (ch1) { \
+ case 1575: \
+ switch (ch2) { \
+ case 1619: return 1570; \
+ case 1620: return 1571; \
+ case 1621: return 1573; \
+ } \
+ return 0; \
+ case 1608: \
+ switch (ch2) { \
+ case 1620: return 1572; \
+ } \
+ return 0; \
+ case 1610: \
+ switch (ch2) { \
+ case 1620: return 1574; \
+ } \
+ return 0; \
+ case 1729: \
+ switch (ch2) { \
+ case 1620: return 1730; \
+ } \
+ return 0; \
+ case 1746: \
+ switch (ch2) { \
+ case 1620: return 1747; \
+ } \
+ return 0; \
+ case 1749: \
+ switch (ch2) { \
+ case 1620: return 1728; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 9: \
+ switch (ch1) { \
+ case 2325: \
+ switch (ch2) { \
+ case 2364: return 2392; \
+ } \
+ return 0; \
+ case 2326: \
+ switch (ch2) { \
+ case 2364: return 2393; \
+ } \
+ return 0; \
+ case 2327: \
+ switch (ch2) { \
+ case 2364: return 2394; \
+ } \
+ return 0; \
+ case 2332: \
+ switch (ch2) { \
+ case 2364: return 2395; \
+ } \
+ return 0; \
+ case 2337: \
+ switch (ch2) { \
+ case 2364: return 2396; \
+ } \
+ return 0; \
+ case 2338: \
+ switch (ch2) { \
+ case 2364: return 2397; \
+ } \
+ return 0; \
+ case 2344: \
+ switch (ch2) { \
+ case 2364: return 2345; \
+ } \
+ return 0; \
+ case 2347: \
+ switch (ch2) { \
+ case 2364: return 2398; \
+ } \
+ return 0; \
+ case 2351: \
+ switch (ch2) { \
+ case 2364: return 2399; \
+ } \
+ return 0; \
+ case 2352: \
+ switch (ch2) { \
+ case 2364: return 2353; \
+ } \
+ return 0; \
+ case 2355: \
+ switch (ch2) { \
+ case 2364: return 2356; \
+ } \
+ return 0; \
+ case 2465: \
+ switch (ch2) { \
+ case 2492: return 2524; \
+ } \
+ return 0; \
+ case 2466: \
+ switch (ch2) { \
+ case 2492: return 2525; \
+ } \
+ return 0; \
+ case 2479: \
+ switch (ch2) { \
+ case 2492: return 2527; \
+ } \
+ return 0; \
+ case 2503: \
+ switch (ch2) { \
+ case 2494: return 2507; \
+ case 2519: return 2508; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 10: \
+ switch (ch1) { \
+ case 2582: \
+ switch (ch2) { \
+ case 2620: return 2649; \
+ } \
+ return 0; \
+ case 2583: \
+ switch (ch2) { \
+ case 2620: return 2650; \
+ } \
+ return 0; \
+ case 2588: \
+ switch (ch2) { \
+ case 2620: return 2651; \
+ } \
+ return 0; \
+ case 2603: \
+ switch (ch2) { \
+ case 2620: return 2654; \
+ } \
+ return 0; \
+ case 2610: \
+ switch (ch2) { \
+ case 2620: return 2611; \
+ } \
+ return 0; \
+ case 2616: \
+ switch (ch2) { \
+ case 2620: return 2614; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 11: \
+ switch (ch1) { \
+ case 2849: \
+ switch (ch2) { \
+ case 2876: return 2908; \
+ } \
+ return 0; \
+ case 2850: \
+ switch (ch2) { \
+ case 2876: return 2909; \
+ } \
+ return 0; \
+ case 2887: \
+ switch (ch2) { \
+ case 2878: return 2891; \
+ case 2902: return 2888; \
+ case 2903: return 2892; \
+ } \
+ return 0; \
+ case 2962: \
+ switch (ch2) { \
+ case 3031: return 2964; \
+ } \
+ return 0; \
+ case 3014: \
+ switch (ch2) { \
+ case 3006: return 3018; \
+ case 3031: return 3020; \
+ } \
+ return 0; \
+ case 3015: \
+ switch (ch2) { \
+ case 3006: return 3019; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 12: \
+ switch (ch1) { \
+ case 3142: \
+ switch (ch2) { \
+ case 3158: return 3144; \
+ } \
+ return 0; \
+ case 3263: \
+ switch (ch2) { \
+ case 3285: return 3264; \
+ } \
+ return 0; \
+ case 3270: \
+ switch (ch2) { \
+ case 3266: return 3274; \
+ case 3285: return 3271; \
+ case 3286: return 3272; \
+ } \
+ return 0; \
+ case 3274: \
+ switch (ch2) { \
+ case 3285: return 3275; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 13: \
+ switch (ch1) { \
+ case 3398: \
+ switch (ch2) { \
+ case 3390: return 3402; \
+ case 3415: return 3404; \
+ } \
+ return 0; \
+ case 3399: \
+ switch (ch2) { \
+ case 3390: return 3403; \
+ } \
+ return 0; \
+ case 3545: \
+ switch (ch2) { \
+ case 3530: return 3546; \
+ case 3535: return 3548; \
+ case 3551: return 3550; \
+ } \
+ return 0; \
+ case 3548: \
+ switch (ch2) { \
+ case 3530: return 3549; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 15: \
+ switch (ch1) { \
+ case 3904: \
+ switch (ch2) { \
+ case 4021: return 3945; \
+ } \
+ return 0; \
+ case 3906: \
+ switch (ch2) { \
+ case 4023: return 3907; \
+ } \
+ return 0; \
+ case 3916: \
+ switch (ch2) { \
+ case 4023: return 3917; \
+ } \
+ return 0; \
+ case 3921: \
+ switch (ch2) { \
+ case 4023: return 3922; \
+ } \
+ return 0; \
+ case 3926: \
+ switch (ch2) { \
+ case 4023: return 3927; \
+ } \
+ return 0; \
+ case 3931: \
+ switch (ch2) { \
+ case 4023: return 3932; \
+ } \
+ return 0; \
+ case 3953: \
+ switch (ch2) { \
+ case 3954: return 3955; \
+ case 3956: return 3957; \
+ case 3968: return 3969; \
+ } \
+ return 0; \
+ case 3984: \
+ switch (ch2) { \
+ case 4021: return 4025; \
+ } \
+ return 0; \
+ case 3986: \
+ switch (ch2) { \
+ case 4023: return 3987; \
+ } \
+ return 0; \
+ case 3996: \
+ switch (ch2) { \
+ case 4023: return 3997; \
+ } \
+ return 0; \
+ case 4001: \
+ switch (ch2) { \
+ case 4023: return 4002; \
+ } \
+ return 0; \
+ case 4006: \
+ switch (ch2) { \
+ case 4023: return 4007; \
+ } \
+ return 0; \
+ case 4011: \
+ switch (ch2) { \
+ case 4023: return 4012; \
+ } \
+ return 0; \
+ case 4018: \
+ switch (ch2) { \
+ case 3968: return 3958; \
+ } \
+ return 0; \
+ case 4019: \
+ switch (ch2) { \
+ case 3968: return 3960; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 16: \
+ switch (ch1) { \
+ case 4133: \
+ switch (ch2) { \
+ case 4142: return 4134; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 30: \
+ switch (ch1) { \
+ case 7734: \
+ switch (ch2) { \
+ case 772: return 7736; \
+ } \
+ return 0; \
+ case 7735: \
+ switch (ch2) { \
+ case 772: return 7737; \
+ } \
+ return 0; \
+ case 7770: \
+ switch (ch2) { \
+ case 772: return 7772; \
+ } \
+ return 0; \
+ case 7771: \
+ switch (ch2) { \
+ case 772: return 7773; \
+ } \
+ return 0; \
+ case 7778: \
+ switch (ch2) { \
+ case 775: return 7784; \
+ } \
+ return 0; \
+ case 7779: \
+ switch (ch2) { \
+ case 775: return 7785; \
+ } \
+ return 0; \
+ case 7840: \
+ switch (ch2) { \
+ case 770: return 7852; \
+ case 774: return 7862; \
+ } \
+ return 0; \
+ case 7841: \
+ switch (ch2) { \
+ case 770: return 7853; \
+ case 774: return 7863; \
+ } \
+ return 0; \
+ case 7864: \
+ switch (ch2) { \
+ case 770: return 7878; \
+ } \
+ return 0; \
+ case 7865: \
+ switch (ch2) { \
+ case 770: return 7879; \
+ } \
+ return 0; \
+ case 7884: \
+ switch (ch2) { \
+ case 770: return 7896; \
+ } \
+ return 0; \
+ case 7885: \
+ switch (ch2) { \
+ case 770: return 7897; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 31: \
+ switch (ch1) { \
+ case 7936: \
+ switch (ch2) { \
+ case 768: return 7938; \
+ case 769: return 7940; \
+ case 834: return 7942; \
+ case 837: return 8064; \
+ } \
+ return 0; \
+ case 7937: \
+ switch (ch2) { \
+ case 768: return 7939; \
+ case 769: return 7941; \
+ case 834: return 7943; \
+ case 837: return 8065; \
+ } \
+ return 0; \
+ case 7938: \
+ switch (ch2) { \
+ case 837: return 8066; \
+ } \
+ return 0; \
+ case 7939: \
+ switch (ch2) { \
+ case 837: return 8067; \
+ } \
+ return 0; \
+ case 7940: \
+ switch (ch2) { \
+ case 837: return 8068; \
+ } \
+ return 0; \
+ case 7941: \
+ switch (ch2) { \
+ case 837: return 8069; \
+ } \
+ return 0; \
+ case 7942: \
+ switch (ch2) { \
+ case 837: return 8070; \
+ } \
+ return 0; \
+ case 7943: \
+ switch (ch2) { \
+ case 837: return 8071; \
+ } \
+ return 0; \
+ case 7944: \
+ switch (ch2) { \
+ case 768: return 7946; \
+ case 769: return 7948; \
+ case 834: return 7950; \
+ case 837: return 8072; \
+ } \
+ return 0; \
+ case 7945: \
+ switch (ch2) { \
+ case 768: return 7947; \
+ case 769: return 7949; \
+ case 834: return 7951; \
+ case 837: return 8073; \
+ } \
+ return 0; \
+ case 7946: \
+ switch (ch2) { \
+ case 837: return 8074; \
+ } \
+ return 0; \
+ case 7947: \
+ switch (ch2) { \
+ case 837: return 8075; \
+ } \
+ return 0; \
+ case 7948: \
+ switch (ch2) { \
+ case 837: return 8076; \
+ } \
+ return 0; \
+ case 7949: \
+ switch (ch2) { \
+ case 837: return 8077; \
+ } \
+ return 0; \
+ case 7950: \
+ switch (ch2) { \
+ case 837: return 8078; \
+ } \
+ return 0; \
+ case 7951: \
+ switch (ch2) { \
+ case 837: return 8079; \
+ } \
+ return 0; \
+ case 7952: \
+ switch (ch2) { \
+ case 768: return 7954; \
+ case 769: return 7956; \
+ } \
+ return 0; \
+ case 7953: \
+ switch (ch2) { \
+ case 768: return 7955; \
+ case 769: return 7957; \
+ } \
+ return 0; \
+ case 7960: \
+ switch (ch2) { \
+ case 768: return 7962; \
+ case 769: return 7964; \
+ } \
+ return 0; \
+ case 7961: \
+ switch (ch2) { \
+ case 768: return 7963; \
+ case 769: return 7965; \
+ } \
+ return 0; \
+ case 7968: \
+ switch (ch2) { \
+ case 768: return 7970; \
+ case 769: return 7972; \
+ case 834: return 7974; \
+ case 837: return 8080; \
+ } \
+ return 0; \
+ case 7969: \
+ switch (ch2) { \
+ case 768: return 7971; \
+ case 769: return 7973; \
+ case 834: return 7975; \
+ case 837: return 8081; \
+ } \
+ return 0; \
+ case 7970: \
+ switch (ch2) { \
+ case 837: return 8082; \
+ } \
+ return 0; \
+ case 7971: \
+ switch (ch2) { \
+ case 837: return 8083; \
+ } \
+ return 0; \
+ case 7972: \
+ switch (ch2) { \
+ case 837: return 8084; \
+ } \
+ return 0; \
+ case 7973: \
+ switch (ch2) { \
+ case 837: return 8085; \
+ } \
+ return 0; \
+ case 7974: \
+ switch (ch2) { \
+ case 837: return 8086; \
+ } \
+ return 0; \
+ case 7975: \
+ switch (ch2) { \
+ case 837: return 8087; \
+ } \
+ return 0; \
+ case 7976: \
+ switch (ch2) { \
+ case 768: return 7978; \
+ case 769: return 7980; \
+ case 834: return 7982; \
+ case 837: return 8088; \
+ } \
+ return 0; \
+ case 7977: \
+ switch (ch2) { \
+ case 768: return 7979; \
+ case 769: return 7981; \
+ case 834: return 7983; \
+ case 837: return 8089; \
+ } \
+ return 0; \
+ case 7978: \
+ switch (ch2) { \
+ case 837: return 8090; \
+ } \
+ return 0; \
+ case 7979: \
+ switch (ch2) { \
+ case 837: return 8091; \
+ } \
+ return 0; \
+ case 7980: \
+ switch (ch2) { \
+ case 837: return 8092; \
+ } \
+ return 0; \
+ case 7981: \
+ switch (ch2) { \
+ case 837: return 8093; \
+ } \
+ return 0; \
+ case 7982: \
+ switch (ch2) { \
+ case 837: return 8094; \
+ } \
+ return 0; \
+ case 7983: \
+ switch (ch2) { \
+ case 837: return 8095; \
+ } \
+ return 0; \
+ case 7984: \
+ switch (ch2) { \
+ case 768: return 7986; \
+ case 769: return 7988; \
+ case 834: return 7990; \
+ } \
+ return 0; \
+ case 7985: \
+ switch (ch2) { \
+ case 768: return 7987; \
+ case 769: return 7989; \
+ case 834: return 7991; \
+ } \
+ return 0; \
+ case 7992: \
+ switch (ch2) { \
+ case 768: return 7994; \
+ case 769: return 7996; \
+ case 834: return 7998; \
+ } \
+ return 0; \
+ case 7993: \
+ switch (ch2) { \
+ case 768: return 7995; \
+ case 769: return 7997; \
+ case 834: return 7999; \
+ } \
+ return 0; \
+ case 8000: \
+ switch (ch2) { \
+ case 768: return 8002; \
+ case 769: return 8004; \
+ } \
+ return 0; \
+ case 8001: \
+ switch (ch2) { \
+ case 768: return 8003; \
+ case 769: return 8005; \
+ } \
+ return 0; \
+ case 8008: \
+ switch (ch2) { \
+ case 768: return 8010; \
+ case 769: return 8012; \
+ } \
+ return 0; \
+ case 8009: \
+ switch (ch2) { \
+ case 768: return 8011; \
+ case 769: return 8013; \
+ } \
+ return 0; \
+ case 8016: \
+ switch (ch2) { \
+ case 768: return 8018; \
+ case 769: return 8020; \
+ case 834: return 8022; \
+ } \
+ return 0; \
+ case 8017: \
+ switch (ch2) { \
+ case 768: return 8019; \
+ case 769: return 8021; \
+ case 834: return 8023; \
+ } \
+ return 0; \
+ case 8025: \
+ switch (ch2) { \
+ case 768: return 8027; \
+ case 769: return 8029; \
+ case 834: return 8031; \
+ } \
+ return 0; \
+ case 8032: \
+ switch (ch2) { \
+ case 768: return 8034; \
+ case 769: return 8036; \
+ case 834: return 8038; \
+ case 837: return 8096; \
+ } \
+ return 0; \
+ case 8033: \
+ switch (ch2) { \
+ case 768: return 8035; \
+ case 769: return 8037; \
+ case 834: return 8039; \
+ case 837: return 8097; \
+ } \
+ return 0; \
+ case 8034: \
+ switch (ch2) { \
+ case 837: return 8098; \
+ } \
+ return 0; \
+ case 8035: \
+ switch (ch2) { \
+ case 837: return 8099; \
+ } \
+ return 0; \
+ case 8036: \
+ switch (ch2) { \
+ case 837: return 8100; \
+ } \
+ return 0; \
+ case 8037: \
+ switch (ch2) { \
+ case 837: return 8101; \
+ } \
+ return 0; \
+ case 8038: \
+ switch (ch2) { \
+ case 837: return 8102; \
+ } \
+ return 0; \
+ case 8039: \
+ switch (ch2) { \
+ case 837: return 8103; \
+ } \
+ return 0; \
+ case 8040: \
+ switch (ch2) { \
+ case 768: return 8042; \
+ case 769: return 8044; \
+ case 834: return 8046; \
+ case 837: return 8104; \
+ } \
+ return 0; \
+ case 8041: \
+ switch (ch2) { \
+ case 768: return 8043; \
+ case 769: return 8045; \
+ case 834: return 8047; \
+ case 837: return 8105; \
+ } \
+ return 0; \
+ case 8042: \
+ switch (ch2) { \
+ case 837: return 8106; \
+ } \
+ return 0; \
+ case 8043: \
+ switch (ch2) { \
+ case 837: return 8107; \
+ } \
+ return 0; \
+ case 8044: \
+ switch (ch2) { \
+ case 837: return 8108; \
+ } \
+ return 0; \
+ case 8045: \
+ switch (ch2) { \
+ case 837: return 8109; \
+ } \
+ return 0; \
+ case 8046: \
+ switch (ch2) { \
+ case 837: return 8110; \
+ } \
+ return 0; \
+ case 8047: \
+ switch (ch2) { \
+ case 837: return 8111; \
+ } \
+ return 0; \
+ case 8048: \
+ switch (ch2) { \
+ case 837: return 8114; \
+ } \
+ return 0; \
+ case 8052: \
+ switch (ch2) { \
+ case 837: return 8130; \
+ } \
+ return 0; \
+ case 8060: \
+ switch (ch2) { \
+ case 837: return 8178; \
+ } \
+ return 0; \
+ case 8118: \
+ switch (ch2) { \
+ case 837: return 8119; \
+ } \
+ return 0; \
+ case 8127: \
+ switch (ch2) { \
+ case 768: return 8141; \
+ case 769: return 8142; \
+ case 834: return 8143; \
+ } \
+ return 0; \
+ case 8134: \
+ switch (ch2) { \
+ case 837: return 8135; \
+ } \
+ return 0; \
+ case 8182: \
+ switch (ch2) { \
+ case 837: return 8183; \
+ } \
+ return 0; \
+ case 8190: \
+ switch (ch2) { \
+ case 768: return 8157; \
+ case 769: return 8158; \
+ case 834: return 8159; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 33: \
+ switch (ch1) { \
+ case 8592: \
+ switch (ch2) { \
+ case 824: return 8602; \
+ } \
+ return 0; \
+ case 8594: \
+ switch (ch2) { \
+ case 824: return 8603; \
+ } \
+ return 0; \
+ case 8596: \
+ switch (ch2) { \
+ case 824: return 8622; \
+ } \
+ return 0; \
+ case 8656: \
+ switch (ch2) { \
+ case 824: return 8653; \
+ } \
+ return 0; \
+ case 8658: \
+ switch (ch2) { \
+ case 824: return 8655; \
+ } \
+ return 0; \
+ case 8660: \
+ switch (ch2) { \
+ case 824: return 8654; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 34: \
+ switch (ch1) { \
+ case 8707: \
+ switch (ch2) { \
+ case 824: return 8708; \
+ } \
+ return 0; \
+ case 8712: \
+ switch (ch2) { \
+ case 824: return 8713; \
+ } \
+ return 0; \
+ case 8715: \
+ switch (ch2) { \
+ case 824: return 8716; \
+ } \
+ return 0; \
+ case 8739: \
+ switch (ch2) { \
+ case 824: return 8740; \
+ } \
+ return 0; \
+ case 8741: \
+ switch (ch2) { \
+ case 824: return 8742; \
+ } \
+ return 0; \
+ case 8764: \
+ switch (ch2) { \
+ case 824: return 8769; \
+ } \
+ return 0; \
+ case 8771: \
+ switch (ch2) { \
+ case 824: return 8772; \
+ } \
+ return 0; \
+ case 8773: \
+ switch (ch2) { \
+ case 824: return 8775; \
+ } \
+ return 0; \
+ case 8776: \
+ switch (ch2) { \
+ case 824: return 8777; \
+ } \
+ return 0; \
+ case 8781: \
+ switch (ch2) { \
+ case 824: return 8813; \
+ } \
+ return 0; \
+ case 8801: \
+ switch (ch2) { \
+ case 824: return 8802; \
+ } \
+ return 0; \
+ case 8804: \
+ switch (ch2) { \
+ case 824: return 8816; \
+ } \
+ return 0; \
+ case 8805: \
+ switch (ch2) { \
+ case 824: return 8817; \
+ } \
+ return 0; \
+ case 8818: \
+ switch (ch2) { \
+ case 824: return 8820; \
+ } \
+ return 0; \
+ case 8819: \
+ switch (ch2) { \
+ case 824: return 8821; \
+ } \
+ return 0; \
+ case 8822: \
+ switch (ch2) { \
+ case 824: return 8824; \
+ } \
+ return 0; \
+ case 8823: \
+ switch (ch2) { \
+ case 824: return 8825; \
+ } \
+ return 0; \
+ case 8826: \
+ switch (ch2) { \
+ case 824: return 8832; \
+ } \
+ return 0; \
+ case 8827: \
+ switch (ch2) { \
+ case 824: return 8833; \
+ } \
+ return 0; \
+ case 8828: \
+ switch (ch2) { \
+ case 824: return 8928; \
+ } \
+ return 0; \
+ case 8829: \
+ switch (ch2) { \
+ case 824: return 8929; \
+ } \
+ return 0; \
+ case 8834: \
+ switch (ch2) { \
+ case 824: return 8836; \
+ } \
+ return 0; \
+ case 8835: \
+ switch (ch2) { \
+ case 824: return 8837; \
+ } \
+ return 0; \
+ case 8838: \
+ switch (ch2) { \
+ case 824: return 8840; \
+ } \
+ return 0; \
+ case 8839: \
+ switch (ch2) { \
+ case 824: return 8841; \
+ } \
+ return 0; \
+ case 8849: \
+ switch (ch2) { \
+ case 824: return 8930; \
+ } \
+ return 0; \
+ case 8850: \
+ switch (ch2) { \
+ case 824: return 8931; \
+ } \
+ return 0; \
+ case 8866: \
+ switch (ch2) { \
+ case 824: return 8876; \
+ } \
+ return 0; \
+ case 8872: \
+ switch (ch2) { \
+ case 824: return 8877; \
+ } \
+ return 0; \
+ case 8873: \
+ switch (ch2) { \
+ case 824: return 8878; \
+ } \
+ return 0; \
+ case 8875: \
+ switch (ch2) { \
+ case 824: return 8879; \
+ } \
+ return 0; \
+ case 8882: \
+ switch (ch2) { \
+ case 824: return 8938; \
+ } \
+ return 0; \
+ case 8883: \
+ switch (ch2) { \
+ case 824: return 8939; \
+ } \
+ return 0; \
+ case 8884: \
+ switch (ch2) { \
+ case 824: return 8940; \
+ } \
+ return 0; \
+ case 8885: \
+ switch (ch2) { \
+ case 824: return 8941; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 42: \
+ switch (ch1) { \
+ case 10973: \
+ switch (ch2) { \
+ case 824: return 10972; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 48: \
+ switch (ch1) { \
+ case 12358: \
+ switch (ch2) { \
+ case 12441: return 12436; \
+ } \
+ return 0; \
+ case 12363: \
+ switch (ch2) { \
+ case 12441: return 12364; \
+ } \
+ return 0; \
+ case 12365: \
+ switch (ch2) { \
+ case 12441: return 12366; \
+ } \
+ return 0; \
+ case 12367: \
+ switch (ch2) { \
+ case 12441: return 12368; \
+ } \
+ return 0; \
+ case 12369: \
+ switch (ch2) { \
+ case 12441: return 12370; \
+ } \
+ return 0; \
+ case 12371: \
+ switch (ch2) { \
+ case 12441: return 12372; \
+ } \
+ return 0; \
+ case 12373: \
+ switch (ch2) { \
+ case 12441: return 12374; \
+ } \
+ return 0; \
+ case 12375: \
+ switch (ch2) { \
+ case 12441: return 12376; \
+ } \
+ return 0; \
+ case 12377: \
+ switch (ch2) { \
+ case 12441: return 12378; \
+ } \
+ return 0; \
+ case 12379: \
+ switch (ch2) { \
+ case 12441: return 12380; \
+ } \
+ return 0; \
+ case 12381: \
+ switch (ch2) { \
+ case 12441: return 12382; \
+ } \
+ return 0; \
+ case 12383: \
+ switch (ch2) { \
+ case 12441: return 12384; \
+ } \
+ return 0; \
+ case 12385: \
+ switch (ch2) { \
+ case 12441: return 12386; \
+ } \
+ return 0; \
+ case 12388: \
+ switch (ch2) { \
+ case 12441: return 12389; \
+ } \
+ return 0; \
+ case 12390: \
+ switch (ch2) { \
+ case 12441: return 12391; \
+ } \
+ return 0; \
+ case 12392: \
+ switch (ch2) { \
+ case 12441: return 12393; \
+ } \
+ return 0; \
+ case 12399: \
+ switch (ch2) { \
+ case 12441: return 12400; \
+ case 12442: return 12401; \
+ } \
+ return 0; \
+ case 12402: \
+ switch (ch2) { \
+ case 12441: return 12403; \
+ case 12442: return 12404; \
+ } \
+ return 0; \
+ case 12405: \
+ switch (ch2) { \
+ case 12441: return 12406; \
+ case 12442: return 12407; \
+ } \
+ return 0; \
+ case 12408: \
+ switch (ch2) { \
+ case 12441: return 12409; \
+ case 12442: return 12410; \
+ } \
+ return 0; \
+ case 12411: \
+ switch (ch2) { \
+ case 12441: return 12412; \
+ case 12442: return 12413; \
+ } \
+ return 0; \
+ case 12445: \
+ switch (ch2) { \
+ case 12441: return 12446; \
+ } \
+ return 0; \
+ case 12454: \
+ switch (ch2) { \
+ case 12441: return 12532; \
+ } \
+ return 0; \
+ case 12459: \
+ switch (ch2) { \
+ case 12441: return 12460; \
+ } \
+ return 0; \
+ case 12461: \
+ switch (ch2) { \
+ case 12441: return 12462; \
+ } \
+ return 0; \
+ case 12463: \
+ switch (ch2) { \
+ case 12441: return 12464; \
+ } \
+ return 0; \
+ case 12465: \
+ switch (ch2) { \
+ case 12441: return 12466; \
+ } \
+ return 0; \
+ case 12467: \
+ switch (ch2) { \
+ case 12441: return 12468; \
+ } \
+ return 0; \
+ case 12469: \
+ switch (ch2) { \
+ case 12441: return 12470; \
+ } \
+ return 0; \
+ case 12471: \
+ switch (ch2) { \
+ case 12441: return 12472; \
+ } \
+ return 0; \
+ case 12473: \
+ switch (ch2) { \
+ case 12441: return 12474; \
+ } \
+ return 0; \
+ case 12475: \
+ switch (ch2) { \
+ case 12441: return 12476; \
+ } \
+ return 0; \
+ case 12477: \
+ switch (ch2) { \
+ case 12441: return 12478; \
+ } \
+ return 0; \
+ case 12479: \
+ switch (ch2) { \
+ case 12441: return 12480; \
+ } \
+ return 0; \
+ case 12481: \
+ switch (ch2) { \
+ case 12441: return 12482; \
+ } \
+ return 0; \
+ case 12484: \
+ switch (ch2) { \
+ case 12441: return 12485; \
+ } \
+ return 0; \
+ case 12486: \
+ switch (ch2) { \
+ case 12441: return 12487; \
+ } \
+ return 0; \
+ case 12488: \
+ switch (ch2) { \
+ case 12441: return 12489; \
+ } \
+ return 0; \
+ case 12495: \
+ switch (ch2) { \
+ case 12441: return 12496; \
+ case 12442: return 12497; \
+ } \
+ return 0; \
+ case 12498: \
+ switch (ch2) { \
+ case 12441: return 12499; \
+ case 12442: return 12500; \
+ } \
+ return 0; \
+ case 12501: \
+ switch (ch2) { \
+ case 12441: return 12502; \
+ case 12442: return 12503; \
+ } \
+ return 0; \
+ case 12504: \
+ switch (ch2) { \
+ case 12441: return 12505; \
+ case 12442: return 12506; \
+ } \
+ return 0; \
+ case 12507: \
+ switch (ch2) { \
+ case 12441: return 12508; \
+ case 12442: return 12509; \
+ } \
+ return 0; \
+ case 12527: \
+ switch (ch2) { \
+ case 12441: return 12535; \
+ } \
+ return 0; \
+ case 12528: \
+ switch (ch2) { \
+ case 12441: return 12536; \
+ } \
+ return 0; \
+ case 12529: \
+ switch (ch2) { \
+ case 12441: return 12537; \
+ } \
+ return 0; \
+ case 12530: \
+ switch (ch2) { \
+ case 12441: return 12538; \
+ } \
+ return 0; \
+ case 12541: \
+ switch (ch2) { \
+ case 12441: return 12542; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 251: \
+ switch (ch1) { \
+ case 64329: \
+ switch (ch2) { \
+ case 1473: return 64300; \
+ case 1474: return 64301; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ case 465: \
+ switch (ch1) { \
+ case 119127: \
+ switch (ch2) { \
+ case 119141: return 119134; \
+ } \
+ return 0; \
+ case 119128: \
+ switch (ch2) { \
+ case 119141: return 119135; \
+ } \
+ return 0; \
+ case 119135: \
+ switch (ch2) { \
+ case 119150: return 119136; \
+ case 119151: return 119137; \
+ case 119152: return 119138; \
+ case 119153: return 119139; \
+ case 119154: return 119140; \
+ } \
+ return 0; \
+ case 119225: \
+ switch (ch2) { \
+ case 119141: return 119227; \
+ } \
+ return 0; \
+ case 119226: \
+ switch (ch2) { \
+ case 119141: return 119228; \
+ } \
+ return 0; \
+ case 119227: \
+ switch (ch2) { \
+ case 119150: return 119229; \
+ case 119151: return 119231; \
+ } \
+ return 0; \
+ case 119228: \
+ switch (ch2) { \
+ case 119150: return 119230; \
+ case 119151: return 119232; \
+ } \
+ return 0; \
+ } \
+ return 0; \
+ } \
+ return 0;
glui32 unigen_decomp_data[3247] = {
0x41, 0x300, 0x41, 0x301, 0x41, 0x302, 0x41, 0x303,
@@ -7587,7 +7587,8 @@ glui32 unigen_decomp_data[3247] = {
0x980b, 0x9829, 0x295b6, 0x98e2, 0x4b33, 0x9929, 0x99a7, 0x99c2,
0x99fe, 0x4bce, 0x29b30, 0x9b12, 0x9c40, 0x9cfd, 0x4cce, 0x4ced,
0x9d67, 0x2a0ce, 0x4cf8, 0x2a105, 0x2a20e, 0x2a291, 0x9ebb, 0x4d56,
- 0x9ef9, 0x9efe, 0x9f05, 0x9f0f, 0x9f16, 0x9f3b, 0x2a600, };
+ 0x9ef9, 0x9efe, 0x9f05, 0x9f0f, 0x9f16, 0x9f3b, 0x2a600,
+};
gli_decomp_block_t unigen_decomp_block_0x0[256] = {
{ 0, 0 },
@@ -11475,351 +11476,351 @@ gli_decomp_block_t unigen_decomp_block_0x2fa[256] = {
};
#define GET_DECOMP_BLOCK(ch, blockptr) \
-switch ((glui32)(ch) >> 8) { \
- case 0x0: \
- *blockptr = unigen_decomp_block_0x0; \
- break; \
- case 0x1: \
- *blockptr = unigen_decomp_block_0x1; \
- break; \
- case 0x2: \
- *blockptr = unigen_decomp_block_0x2; \
- break; \
- case 0x3: \
- *blockptr = unigen_decomp_block_0x3; \
- break; \
- case 0x4: \
- *blockptr = unigen_decomp_block_0x4; \
- break; \
- case 0x1e: \
- *blockptr = unigen_decomp_block_0x1e; \
- break; \
- case 0x1f: \
- *blockptr = unigen_decomp_block_0x1f; \
- break; \
- case 0x22: \
- *blockptr = unigen_decomp_block_0x22; \
- break; \
- case 0x30: \
- *blockptr = unigen_decomp_block_0x30; \
- break; \
- case 0xf9: \
- *blockptr = unigen_decomp_block_0xf9; \
- break; \
- case 0xfa: \
- *blockptr = unigen_decomp_block_0xfa; \
- break; \
- case 0xfb: \
- *blockptr = unigen_decomp_block_0xfb; \
- break; \
- case 0x2f8: \
- *blockptr = unigen_decomp_block_0x2f8; \
- break; \
- case 0x2f9: \
- *blockptr = unigen_decomp_block_0x2f9; \
- break; \
- case 0x2fa: \
- *blockptr = unigen_decomp_block_0x2fa; \
- break; \
- default: \
- *blockptr = nullptr; \
-}
+ switch ((glui32)(ch) >> 8) { \
+ case 0x0: \
+ *blockptr = unigen_decomp_block_0x0; \
+ break; \
+ case 0x1: \
+ *blockptr = unigen_decomp_block_0x1; \
+ break; \
+ case 0x2: \
+ *blockptr = unigen_decomp_block_0x2; \
+ break; \
+ case 0x3: \
+ *blockptr = unigen_decomp_block_0x3; \
+ break; \
+ case 0x4: \
+ *blockptr = unigen_decomp_block_0x4; \
+ break; \
+ case 0x1e: \
+ *blockptr = unigen_decomp_block_0x1e; \
+ break; \
+ case 0x1f: \
+ *blockptr = unigen_decomp_block_0x1f; \
+ break; \
+ case 0x22: \
+ *blockptr = unigen_decomp_block_0x22; \
+ break; \
+ case 0x30: \
+ *blockptr = unigen_decomp_block_0x30; \
+ break; \
+ case 0xf9: \
+ *blockptr = unigen_decomp_block_0xf9; \
+ break; \
+ case 0xfa: \
+ *blockptr = unigen_decomp_block_0xfa; \
+ break; \
+ case 0xfb: \
+ *blockptr = unigen_decomp_block_0xfb; \
+ break; \
+ case 0x2f8: \
+ *blockptr = unigen_decomp_block_0x2f8; \
+ break; \
+ case 0x2f9: \
+ *blockptr = unigen_decomp_block_0x2f9; \
+ break; \
+ case 0x2fa: \
+ *blockptr = unigen_decomp_block_0x2fa; \
+ break; \
+ default: \
+ *blockptr = nullptr; \
+ }
#define GET_DECOMP_SPECIAL(ch, countptr, posptr) \
-switch (ch) { \
- case 0x622: \
- *countptr = 2; *posptr = 686; \
- break; \
- case 0x623: \
- *countptr = 2; *posptr = 688; \
- break; \
- case 0x624: \
- *countptr = 2; *posptr = 690; \
- break; \
- case 0x625: \
- *countptr = 2; *posptr = 692; \
- break; \
- case 0x626: \
- *countptr = 2; *posptr = 694; \
- break; \
- case 0x6c0: \
- *countptr = 2; *posptr = 696; \
- break; \
- case 0x6c2: \
- *countptr = 2; *posptr = 698; \
- break; \
- case 0x6d3: \
- *countptr = 2; *posptr = 700; \
- break; \
- case 0x929: \
- *countptr = 2; *posptr = 702; \
- break; \
- case 0x931: \
- *countptr = 2; *posptr = 704; \
- break; \
- case 0x934: \
- *countptr = 2; *posptr = 706; \
- break; \
- case 0x958: \
- *countptr = 2; *posptr = 708; \
- break; \
- case 0x959: \
- *countptr = 2; *posptr = 710; \
- break; \
- case 0x95a: \
- *countptr = 2; *posptr = 712; \
- break; \
- case 0x95b: \
- *countptr = 2; *posptr = 714; \
- break; \
- case 0x95c: \
- *countptr = 2; *posptr = 716; \
- break; \
- case 0x95d: \
- *countptr = 2; *posptr = 718; \
- break; \
- case 0x95e: \
- *countptr = 2; *posptr = 720; \
- break; \
- case 0x95f: \
- *countptr = 2; *posptr = 722; \
- break; \
- case 0x9cb: \
- *countptr = 2; *posptr = 724; \
- break; \
- case 0x9cc: \
- *countptr = 2; *posptr = 726; \
- break; \
- case 0x9dc: \
- *countptr = 2; *posptr = 728; \
- break; \
- case 0x9dd: \
- *countptr = 2; *posptr = 730; \
- break; \
- case 0x9df: \
- *countptr = 2; *posptr = 732; \
- break; \
- case 0xa33: \
- *countptr = 2; *posptr = 734; \
- break; \
- case 0xa36: \
- *countptr = 2; *posptr = 736; \
- break; \
- case 0xa59: \
- *countptr = 2; *posptr = 738; \
- break; \
- case 0xa5a: \
- *countptr = 2; *posptr = 740; \
- break; \
- case 0xa5b: \
- *countptr = 2; *posptr = 742; \
- break; \
- case 0xa5e: \
- *countptr = 2; *posptr = 744; \
- break; \
- case 0xb48: \
- *countptr = 2; *posptr = 746; \
- break; \
- case 0xb4b: \
- *countptr = 2; *posptr = 748; \
- break; \
- case 0xb4c: \
- *countptr = 2; *posptr = 750; \
- break; \
- case 0xb5c: \
- *countptr = 2; *posptr = 752; \
- break; \
- case 0xb5d: \
- *countptr = 2; *posptr = 754; \
- break; \
- case 0xb94: \
- *countptr = 2; *posptr = 756; \
- break; \
- case 0xbca: \
- *countptr = 2; *posptr = 758; \
- break; \
- case 0xbcb: \
- *countptr = 2; *posptr = 760; \
- break; \
- case 0xbcc: \
- *countptr = 2; *posptr = 762; \
- break; \
- case 0xc48: \
- *countptr = 2; *posptr = 764; \
- break; \
- case 0xcc0: \
- *countptr = 2; *posptr = 766; \
- break; \
- case 0xcc7: \
- *countptr = 2; *posptr = 768; \
- break; \
- case 0xcc8: \
- *countptr = 2; *posptr = 770; \
- break; \
- case 0xcca: \
- *countptr = 2; *posptr = 772; \
- break; \
- case 0xccb: \
- *countptr = 3; *posptr = 774; \
- break; \
- case 0xd4a: \
- *countptr = 2; *posptr = 777; \
- break; \
- case 0xd4b: \
- *countptr = 2; *posptr = 779; \
- break; \
- case 0xd4c: \
- *countptr = 2; *posptr = 781; \
- break; \
- case 0xdda: \
- *countptr = 2; *posptr = 783; \
- break; \
- case 0xddc: \
- *countptr = 2; *posptr = 785; \
- break; \
- case 0xddd: \
- *countptr = 3; *posptr = 787; \
- break; \
- case 0xdde: \
- *countptr = 2; *posptr = 790; \
- break; \
- case 0xf43: \
- *countptr = 2; *posptr = 792; \
- break; \
- case 0xf4d: \
- *countptr = 2; *posptr = 794; \
- break; \
- case 0xf52: \
- *countptr = 2; *posptr = 796; \
- break; \
- case 0xf57: \
- *countptr = 2; *posptr = 798; \
- break; \
- case 0xf5c: \
- *countptr = 2; *posptr = 800; \
- break; \
- case 0xf69: \
- *countptr = 2; *posptr = 802; \
- break; \
- case 0xf73: \
- *countptr = 2; *posptr = 804; \
- break; \
- case 0xf75: \
- *countptr = 2; *posptr = 806; \
- break; \
- case 0xf76: \
- *countptr = 2; *posptr = 808; \
- break; \
- case 0xf78: \
- *countptr = 2; *posptr = 810; \
- break; \
- case 0xf81: \
- *countptr = 2; *posptr = 812; \
- break; \
- case 0xf93: \
- *countptr = 2; *posptr = 814; \
- break; \
- case 0xf9d: \
- *countptr = 2; *posptr = 816; \
- break; \
- case 0xfa2: \
- *countptr = 2; *posptr = 818; \
- break; \
- case 0xfa7: \
- *countptr = 2; *posptr = 820; \
- break; \
- case 0xfac: \
- *countptr = 2; *posptr = 822; \
- break; \
- case 0xfb9: \
- *countptr = 2; *posptr = 824; \
- break; \
- case 0x1026: \
- *countptr = 2; *posptr = 826; \
- break; \
- case 0x2000: \
- *countptr = 1; *posptr = 2037; \
- break; \
- case 0x2001: \
- *countptr = 1; *posptr = 2038; \
- break; \
- case 0x2126: \
- *countptr = 1; *posptr = 2039; \
- break; \
- case 0x212a: \
- *countptr = 1; *posptr = 2040; \
- break; \
- case 0x212b: \
- *countptr = 2; *posptr = 2041; \
- break; \
- case 0x219a: \
- *countptr = 2; *posptr = 2043; \
- break; \
- case 0x219b: \
- *countptr = 2; *posptr = 2045; \
- break; \
- case 0x21ae: \
- *countptr = 2; *posptr = 2047; \
- break; \
- case 0x21cd: \
- *countptr = 2; *posptr = 2049; \
- break; \
- case 0x21ce: \
- *countptr = 2; *posptr = 2051; \
- break; \
- case 0x21cf: \
- *countptr = 2; *posptr = 2053; \
- break; \
- case 0x2329: \
- *countptr = 1; *posptr = 2131; \
- break; \
- case 0x232a: \
- *countptr = 1; *posptr = 2132; \
- break; \
- case 0x2adc: \
- *countptr = 2; *posptr = 2133; \
- break; \
- case 0x1d15e: \
- *countptr = 2; *posptr = 2670; \
- break; \
- case 0x1d15f: \
- *countptr = 2; *posptr = 2672; \
- break; \
- case 0x1d160: \
- *countptr = 3; *posptr = 2674; \
- break; \
- case 0x1d161: \
- *countptr = 3; *posptr = 2677; \
- break; \
- case 0x1d162: \
- *countptr = 3; *posptr = 2680; \
- break; \
- case 0x1d163: \
- *countptr = 3; *posptr = 2683; \
- break; \
- case 0x1d164: \
- *countptr = 3; *posptr = 2686; \
- break; \
- case 0x1d1bb: \
- *countptr = 2; *posptr = 2689; \
- break; \
- case 0x1d1bc: \
- *countptr = 2; *posptr = 2691; \
- break; \
- case 0x1d1bd: \
- *countptr = 3; *posptr = 2693; \
- break; \
- case 0x1d1be: \
- *countptr = 3; *posptr = 2696; \
- break; \
- case 0x1d1bf: \
- *countptr = 3; *posptr = 2699; \
- break; \
- case 0x1d1c0: \
- *countptr = 3; *posptr = 2702; \
- break; \
- default: \
- *countptr = 0; \
-}
+ switch (ch) { \
+ case 0x622: \
+ *countptr = 2; *posptr = 686; \
+ break; \
+ case 0x623: \
+ *countptr = 2; *posptr = 688; \
+ break; \
+ case 0x624: \
+ *countptr = 2; *posptr = 690; \
+ break; \
+ case 0x625: \
+ *countptr = 2; *posptr = 692; \
+ break; \
+ case 0x626: \
+ *countptr = 2; *posptr = 694; \
+ break; \
+ case 0x6c0: \
+ *countptr = 2; *posptr = 696; \
+ break; \
+ case 0x6c2: \
+ *countptr = 2; *posptr = 698; \
+ break; \
+ case 0x6d3: \
+ *countptr = 2; *posptr = 700; \
+ break; \
+ case 0x929: \
+ *countptr = 2; *posptr = 702; \
+ break; \
+ case 0x931: \
+ *countptr = 2; *posptr = 704; \
+ break; \
+ case 0x934: \
+ *countptr = 2; *posptr = 706; \
+ break; \
+ case 0x958: \
+ *countptr = 2; *posptr = 708; \
+ break; \
+ case 0x959: \
+ *countptr = 2; *posptr = 710; \
+ break; \
+ case 0x95a: \
+ *countptr = 2; *posptr = 712; \
+ break; \
+ case 0x95b: \
+ *countptr = 2; *posptr = 714; \
+ break; \
+ case 0x95c: \
+ *countptr = 2; *posptr = 716; \
+ break; \
+ case 0x95d: \
+ *countptr = 2; *posptr = 718; \
+ break; \
+ case 0x95e: \
+ *countptr = 2; *posptr = 720; \
+ break; \
+ case 0x95f: \
+ *countptr = 2; *posptr = 722; \
+ break; \
+ case 0x9cb: \
+ *countptr = 2; *posptr = 724; \
+ break; \
+ case 0x9cc: \
+ *countptr = 2; *posptr = 726; \
+ break; \
+ case 0x9dc: \
+ *countptr = 2; *posptr = 728; \
+ break; \
+ case 0x9dd: \
+ *countptr = 2; *posptr = 730; \
+ break; \
+ case 0x9df: \
+ *countptr = 2; *posptr = 732; \
+ break; \
+ case 0xa33: \
+ *countptr = 2; *posptr = 734; \
+ break; \
+ case 0xa36: \
+ *countptr = 2; *posptr = 736; \
+ break; \
+ case 0xa59: \
+ *countptr = 2; *posptr = 738; \
+ break; \
+ case 0xa5a: \
+ *countptr = 2; *posptr = 740; \
+ break; \
+ case 0xa5b: \
+ *countptr = 2; *posptr = 742; \
+ break; \
+ case 0xa5e: \
+ *countptr = 2; *posptr = 744; \
+ break; \
+ case 0xb48: \
+ *countptr = 2; *posptr = 746; \
+ break; \
+ case 0xb4b: \
+ *countptr = 2; *posptr = 748; \
+ break; \
+ case 0xb4c: \
+ *countptr = 2; *posptr = 750; \
+ break; \
+ case 0xb5c: \
+ *countptr = 2; *posptr = 752; \
+ break; \
+ case 0xb5d: \
+ *countptr = 2; *posptr = 754; \
+ break; \
+ case 0xb94: \
+ *countptr = 2; *posptr = 756; \
+ break; \
+ case 0xbca: \
+ *countptr = 2; *posptr = 758; \
+ break; \
+ case 0xbcb: \
+ *countptr = 2; *posptr = 760; \
+ break; \
+ case 0xbcc: \
+ *countptr = 2; *posptr = 762; \
+ break; \
+ case 0xc48: \
+ *countptr = 2; *posptr = 764; \
+ break; \
+ case 0xcc0: \
+ *countptr = 2; *posptr = 766; \
+ break; \
+ case 0xcc7: \
+ *countptr = 2; *posptr = 768; \
+ break; \
+ case 0xcc8: \
+ *countptr = 2; *posptr = 770; \
+ break; \
+ case 0xcca: \
+ *countptr = 2; *posptr = 772; \
+ break; \
+ case 0xccb: \
+ *countptr = 3; *posptr = 774; \
+ break; \
+ case 0xd4a: \
+ *countptr = 2; *posptr = 777; \
+ break; \
+ case 0xd4b: \
+ *countptr = 2; *posptr = 779; \
+ break; \
+ case 0xd4c: \
+ *countptr = 2; *posptr = 781; \
+ break; \
+ case 0xdda: \
+ *countptr = 2; *posptr = 783; \
+ break; \
+ case 0xddc: \
+ *countptr = 2; *posptr = 785; \
+ break; \
+ case 0xddd: \
+ *countptr = 3; *posptr = 787; \
+ break; \
+ case 0xdde: \
+ *countptr = 2; *posptr = 790; \
+ break; \
+ case 0xf43: \
+ *countptr = 2; *posptr = 792; \
+ break; \
+ case 0xf4d: \
+ *countptr = 2; *posptr = 794; \
+ break; \
+ case 0xf52: \
+ *countptr = 2; *posptr = 796; \
+ break; \
+ case 0xf57: \
+ *countptr = 2; *posptr = 798; \
+ break; \
+ case 0xf5c: \
+ *countptr = 2; *posptr = 800; \
+ break; \
+ case 0xf69: \
+ *countptr = 2; *posptr = 802; \
+ break; \
+ case 0xf73: \
+ *countptr = 2; *posptr = 804; \
+ break; \
+ case 0xf75: \
+ *countptr = 2; *posptr = 806; \
+ break; \
+ case 0xf76: \
+ *countptr = 2; *posptr = 808; \
+ break; \
+ case 0xf78: \
+ *countptr = 2; *posptr = 810; \
+ break; \
+ case 0xf81: \
+ *countptr = 2; *posptr = 812; \
+ break; \
+ case 0xf93: \
+ *countptr = 2; *posptr = 814; \
+ break; \
+ case 0xf9d: \
+ *countptr = 2; *posptr = 816; \
+ break; \
+ case 0xfa2: \
+ *countptr = 2; *posptr = 818; \
+ break; \
+ case 0xfa7: \
+ *countptr = 2; *posptr = 820; \
+ break; \
+ case 0xfac: \
+ *countptr = 2; *posptr = 822; \
+ break; \
+ case 0xfb9: \
+ *countptr = 2; *posptr = 824; \
+ break; \
+ case 0x1026: \
+ *countptr = 2; *posptr = 826; \
+ break; \
+ case 0x2000: \
+ *countptr = 1; *posptr = 2037; \
+ break; \
+ case 0x2001: \
+ *countptr = 1; *posptr = 2038; \
+ break; \
+ case 0x2126: \
+ *countptr = 1; *posptr = 2039; \
+ break; \
+ case 0x212a: \
+ *countptr = 1; *posptr = 2040; \
+ break; \
+ case 0x212b: \
+ *countptr = 2; *posptr = 2041; \
+ break; \
+ case 0x219a: \
+ *countptr = 2; *posptr = 2043; \
+ break; \
+ case 0x219b: \
+ *countptr = 2; *posptr = 2045; \
+ break; \
+ case 0x21ae: \
+ *countptr = 2; *posptr = 2047; \
+ break; \
+ case 0x21cd: \
+ *countptr = 2; *posptr = 2049; \
+ break; \
+ case 0x21ce: \
+ *countptr = 2; *posptr = 2051; \
+ break; \
+ case 0x21cf: \
+ *countptr = 2; *posptr = 2053; \
+ break; \
+ case 0x2329: \
+ *countptr = 1; *posptr = 2131; \
+ break; \
+ case 0x232a: \
+ *countptr = 1; *posptr = 2132; \
+ break; \
+ case 0x2adc: \
+ *countptr = 2; *posptr = 2133; \
+ break; \
+ case 0x1d15e: \
+ *countptr = 2; *posptr = 2670; \
+ break; \
+ case 0x1d15f: \
+ *countptr = 2; *posptr = 2672; \
+ break; \
+ case 0x1d160: \
+ *countptr = 3; *posptr = 2674; \
+ break; \
+ case 0x1d161: \
+ *countptr = 3; *posptr = 2677; \
+ break; \
+ case 0x1d162: \
+ *countptr = 3; *posptr = 2680; \
+ break; \
+ case 0x1d163: \
+ *countptr = 3; *posptr = 2683; \
+ break; \
+ case 0x1d164: \
+ *countptr = 3; *posptr = 2686; \
+ break; \
+ case 0x1d1bb: \
+ *countptr = 2; *posptr = 2689; \
+ break; \
+ case 0x1d1bc: \
+ *countptr = 2; *posptr = 2691; \
+ break; \
+ case 0x1d1bd: \
+ *countptr = 3; *posptr = 2693; \
+ break; \
+ case 0x1d1be: \
+ *countptr = 3; *posptr = 2696; \
+ break; \
+ case 0x1d1bf: \
+ *countptr = 3; *posptr = 2699; \
+ break; \
+ case 0x1d1c0: \
+ *countptr = 3; *posptr = 2702; \
+ break; \
+ default: \
+ *countptr = 0; \
+ }
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/unicode_gen.h b/engines/gargoyle/unicode_gen.h
index 1539ec4..7c86e9b 100644
--- a/engines/gargoyle/unicode_gen.h
+++ b/engines/gargoyle/unicode_gen.h
@@ -28,400 +28,400 @@
namespace Gargoyle {
#define GET_CASE_BLOCK(ch, blockptr) \
-switch ((glui32)(ch) >> 8) { \
-case 0x0: \
- *blockptr = unigen_case_block_0x0; \
- break; \
-case 0x1: \
- *blockptr = unigen_case_block_0x1; \
- break; \
-case 0x2: \
- *blockptr = unigen_case_block_0x2; \
- break; \
-case 0x3: \
- *blockptr = unigen_case_block_0x3; \
- break; \
-case 0x4: \
- *blockptr = unigen_case_block_0x4; \
- break; \
-case 0x5: \
- *blockptr = unigen_case_block_0x5; \
- break; \
-case 0x1e: \
- *blockptr = unigen_case_block_0x1e; \
- break; \
-case 0x1f: \
- *blockptr = unigen_case_block_0x1f; \
- break; \
-case 0x21: \
- *blockptr = unigen_case_block_0x21; \
- break; \
-case 0x24: \
- *blockptr = unigen_case_block_0x24; \
- break; \
-case 0xfb: \
- *blockptr = unigen_case_block_0xfb; \
- break; \
-case 0xff: \
- *blockptr = unigen_case_block_0xff; \
- break; \
-case 0x104: \
- *blockptr = unigen_case_block_0x104; \
- break; \
-default: \
- *blockptr = nullptr; \
-}
+ switch ((glui32)(ch) >> 8) { \
+ case 0x0: \
+ *blockptr = unigen_case_block_0x0; \
+ break; \
+ case 0x1: \
+ *blockptr = unigen_case_block_0x1; \
+ break; \
+ case 0x2: \
+ *blockptr = unigen_case_block_0x2; \
+ break; \
+ case 0x3: \
+ *blockptr = unigen_case_block_0x3; \
+ break; \
+ case 0x4: \
+ *blockptr = unigen_case_block_0x4; \
+ break; \
+ case 0x5: \
+ *blockptr = unigen_case_block_0x5; \
+ break; \
+ case 0x1e: \
+ *blockptr = unigen_case_block_0x1e; \
+ break; \
+ case 0x1f: \
+ *blockptr = unigen_case_block_0x1f; \
+ break; \
+ case 0x21: \
+ *blockptr = unigen_case_block_0x21; \
+ break; \
+ case 0x24: \
+ *blockptr = unigen_case_block_0x24; \
+ break; \
+ case 0xfb: \
+ *blockptr = unigen_case_block_0xfb; \
+ break; \
+ case 0xff: \
+ *blockptr = unigen_case_block_0xff; \
+ break; \
+ case 0x104: \
+ *blockptr = unigen_case_block_0x104; \
+ break; \
+ default: \
+ *blockptr = nullptr; \
+ }
#define GET_CASE_SPECIAL(ch, specptr) \
-switch (ch) { \
-case 0xdf: \
- *specptr = unigen_special_0xdf; \
- break; \
-case 0x130: \
- *specptr = unigen_special_0x130; \
- break; \
-case 0x149: \
- *specptr = unigen_special_0x149; \
- break; \
-case 0x1c4: \
- *specptr = unigen_special_0x1c4; \
- break; \
-case 0x1c5: \
- *specptr = unigen_special_0x1c5; \
- break; \
-case 0x1c6: \
- *specptr = unigen_special_0x1c6; \
- break; \
-case 0x1c7: \
- *specptr = unigen_special_0x1c7; \
- break; \
-case 0x1c8: \
- *specptr = unigen_special_0x1c8; \
- break; \
-case 0x1c9: \
- *specptr = unigen_special_0x1c9; \
- break; \
-case 0x1ca: \
- *specptr = unigen_special_0x1ca; \
- break; \
-case 0x1cb: \
- *specptr = unigen_special_0x1cb; \
- break; \
-case 0x1cc: \
- *specptr = unigen_special_0x1cc; \
- break; \
-case 0x1f0: \
- *specptr = unigen_special_0x1f0; \
- break; \
-case 0x1f1: \
- *specptr = unigen_special_0x1f1; \
- break; \
-case 0x1f2: \
- *specptr = unigen_special_0x1f2; \
- break; \
-case 0x1f3: \
- *specptr = unigen_special_0x1f3; \
- break; \
-case 0x390: \
- *specptr = unigen_special_0x390; \
- break; \
-case 0x3b0: \
- *specptr = unigen_special_0x3b0; \
- break; \
-case 0x587: \
- *specptr = unigen_special_0x587; \
- break; \
-case 0x1e96: \
- *specptr = unigen_special_0x1e96; \
- break; \
-case 0x1e97: \
- *specptr = unigen_special_0x1e97; \
- break; \
-case 0x1e98: \
- *specptr = unigen_special_0x1e98; \
- break; \
-case 0x1e99: \
- *specptr = unigen_special_0x1e99; \
- break; \
-case 0x1e9a: \
- *specptr = unigen_special_0x1e9a; \
- break; \
-case 0x1f50: \
- *specptr = unigen_special_0x1f50; \
- break; \
-case 0x1f52: \
- *specptr = unigen_special_0x1f52; \
- break; \
-case 0x1f54: \
- *specptr = unigen_special_0x1f54; \
- break; \
-case 0x1f56: \
- *specptr = unigen_special_0x1f56; \
- break; \
-case 0x1f80: \
- *specptr = unigen_special_0x1f80; \
- break; \
-case 0x1f81: \
- *specptr = unigen_special_0x1f81; \
- break; \
-case 0x1f82: \
- *specptr = unigen_special_0x1f82; \
- break; \
-case 0x1f83: \
- *specptr = unigen_special_0x1f83; \
- break; \
-case 0x1f84: \
- *specptr = unigen_special_0x1f84; \
- break; \
-case 0x1f85: \
- *specptr = unigen_special_0x1f85; \
- break; \
-case 0x1f86: \
- *specptr = unigen_special_0x1f86; \
- break; \
-case 0x1f87: \
- *specptr = unigen_special_0x1f87; \
- break; \
-case 0x1f88: \
- *specptr = unigen_special_0x1f88; \
- break; \
-case 0x1f89: \
- *specptr = unigen_special_0x1f89; \
- break; \
-case 0x1f8a: \
- *specptr = unigen_special_0x1f8a; \
- break; \
-case 0x1f8b: \
- *specptr = unigen_special_0x1f8b; \
- break; \
-case 0x1f8c: \
- *specptr = unigen_special_0x1f8c; \
- break; \
-case 0x1f8d: \
- *specptr = unigen_special_0x1f8d; \
- break; \
-case 0x1f8e: \
- *specptr = unigen_special_0x1f8e; \
- break; \
-case 0x1f8f: \
- *specptr = unigen_special_0x1f8f; \
- break; \
-case 0x1f90: \
- *specptr = unigen_special_0x1f90; \
- break; \
-case 0x1f91: \
- *specptr = unigen_special_0x1f91; \
- break; \
-case 0x1f92: \
- *specptr = unigen_special_0x1f92; \
- break; \
-case 0x1f93: \
- *specptr = unigen_special_0x1f93; \
- break; \
-case 0x1f94: \
- *specptr = unigen_special_0x1f94; \
- break; \
-case 0x1f95: \
- *specptr = unigen_special_0x1f95; \
- break; \
-case 0x1f96: \
- *specptr = unigen_special_0x1f96; \
- break; \
-case 0x1f97: \
- *specptr = unigen_special_0x1f97; \
- break; \
-case 0x1f98: \
- *specptr = unigen_special_0x1f98; \
- break; \
-case 0x1f99: \
- *specptr = unigen_special_0x1f99; \
- break; \
-case 0x1f9a: \
- *specptr = unigen_special_0x1f9a; \
- break; \
-case 0x1f9b: \
- *specptr = unigen_special_0x1f9b; \
- break; \
-case 0x1f9c: \
- *specptr = unigen_special_0x1f9c; \
- break; \
-case 0x1f9d: \
- *specptr = unigen_special_0x1f9d; \
- break; \
-case 0x1f9e: \
- *specptr = unigen_special_0x1f9e; \
- break; \
-case 0x1f9f: \
- *specptr = unigen_special_0x1f9f; \
- break; \
-case 0x1fa0: \
- *specptr = unigen_special_0x1fa0; \
- break; \
-case 0x1fa1: \
- *specptr = unigen_special_0x1fa1; \
- break; \
-case 0x1fa2: \
- *specptr = unigen_special_0x1fa2; \
- break; \
-case 0x1fa3: \
- *specptr = unigen_special_0x1fa3; \
- break; \
-case 0x1fa4: \
- *specptr = unigen_special_0x1fa4; \
- break; \
-case 0x1fa5: \
- *specptr = unigen_special_0x1fa5; \
- break; \
-case 0x1fa6: \
- *specptr = unigen_special_0x1fa6; \
- break; \
-case 0x1fa7: \
- *specptr = unigen_special_0x1fa7; \
- break; \
-case 0x1fa8: \
- *specptr = unigen_special_0x1fa8; \
- break; \
-case 0x1fa9: \
- *specptr = unigen_special_0x1fa9; \
- break; \
-case 0x1faa: \
- *specptr = unigen_special_0x1faa; \
- break; \
-case 0x1fab: \
- *specptr = unigen_special_0x1fab; \
- break; \
-case 0x1fac: \
- *specptr = unigen_special_0x1fac; \
- break; \
-case 0x1fad: \
- *specptr = unigen_special_0x1fad; \
- break; \
-case 0x1fae: \
- *specptr = unigen_special_0x1fae; \
- break; \
-case 0x1faf: \
- *specptr = unigen_special_0x1faf; \
- break; \
-case 0x1fb2: \
- *specptr = unigen_special_0x1fb2; \
- break; \
-case 0x1fb3: \
- *specptr = unigen_special_0x1fb3; \
- break; \
-case 0x1fb4: \
- *specptr = unigen_special_0x1fb4; \
- break; \
-case 0x1fb6: \
- *specptr = unigen_special_0x1fb6; \
- break; \
-case 0x1fb7: \
- *specptr = unigen_special_0x1fb7; \
- break; \
-case 0x1fbc: \
- *specptr = unigen_special_0x1fbc; \
- break; \
-case 0x1fc2: \
- *specptr = unigen_special_0x1fc2; \
- break; \
-case 0x1fc3: \
- *specptr = unigen_special_0x1fc3; \
- break; \
-case 0x1fc4: \
- *specptr = unigen_special_0x1fc4; \
- break; \
-case 0x1fc6: \
- *specptr = unigen_special_0x1fc6; \
- break; \
-case 0x1fc7: \
- *specptr = unigen_special_0x1fc7; \
- break; \
-case 0x1fcc: \
- *specptr = unigen_special_0x1fcc; \
- break; \
-case 0x1fd2: \
- *specptr = unigen_special_0x1fd2; \
- break; \
-case 0x1fd3: \
- *specptr = unigen_special_0x1fd3; \
- break; \
-case 0x1fd6: \
- *specptr = unigen_special_0x1fd6; \
- break; \
-case 0x1fd7: \
- *specptr = unigen_special_0x1fd7; \
- break; \
-case 0x1fe2: \
- *specptr = unigen_special_0x1fe2; \
- break; \
-case 0x1fe3: \
- *specptr = unigen_special_0x1fe3; \
- break; \
-case 0x1fe4: \
- *specptr = unigen_special_0x1fe4; \
- break; \
-case 0x1fe6: \
- *specptr = unigen_special_0x1fe6; \
- break; \
-case 0x1fe7: \
- *specptr = unigen_special_0x1fe7; \
- break; \
-case 0x1ff2: \
- *specptr = unigen_special_0x1ff2; \
- break; \
-case 0x1ff3: \
- *specptr = unigen_special_0x1ff3; \
- break; \
-case 0x1ff4: \
- *specptr = unigen_special_0x1ff4; \
- break; \
-case 0x1ff6: \
- *specptr = unigen_special_0x1ff6; \
- break; \
-case 0x1ff7: \
- *specptr = unigen_special_0x1ff7; \
- break; \
-case 0x1ffc: \
- *specptr = unigen_special_0x1ffc; \
- break; \
-case 0xfb00: \
- *specptr = unigen_special_0xfb00; \
- break; \
-case 0xfb01: \
- *specptr = unigen_special_0xfb01; \
- break; \
-case 0xfb02: \
- *specptr = unigen_special_0xfb02; \
- break; \
-case 0xfb03: \
- *specptr = unigen_special_0xfb03; \
- break; \
-case 0xfb04: \
- *specptr = unigen_special_0xfb04; \
- break; \
-case 0xfb05: \
- *specptr = unigen_special_0xfb05; \
- break; \
-case 0xfb06: \
- *specptr = unigen_special_0xfb06; \
- break; \
-case 0xfb13: \
- *specptr = unigen_special_0xfb13; \
- break; \
-case 0xfb14: \
- *specptr = unigen_special_0xfb14; \
- break; \
-case 0xfb15: \
- *specptr = unigen_special_0xfb15; \
- break; \
-case 0xfb16: \
- *specptr = unigen_special_0xfb16; \
- break; \
-case 0xfb17: \
- *specptr = unigen_special_0xfb17; \
- break; \
-default: \
- *specptr = nullptr; \
-}
+ switch (ch) { \
+ case 0xdf: \
+ *specptr = unigen_special_0xdf; \
+ break; \
+ case 0x130: \
+ *specptr = unigen_special_0x130; \
+ break; \
+ case 0x149: \
+ *specptr = unigen_special_0x149; \
+ break; \
+ case 0x1c4: \
+ *specptr = unigen_special_0x1c4; \
+ break; \
+ case 0x1c5: \
+ *specptr = unigen_special_0x1c5; \
+ break; \
+ case 0x1c6: \
+ *specptr = unigen_special_0x1c6; \
+ break; \
+ case 0x1c7: \
+ *specptr = unigen_special_0x1c7; \
+ break; \
+ case 0x1c8: \
+ *specptr = unigen_special_0x1c8; \
+ break; \
+ case 0x1c9: \
+ *specptr = unigen_special_0x1c9; \
+ break; \
+ case 0x1ca: \
+ *specptr = unigen_special_0x1ca; \
+ break; \
+ case 0x1cb: \
+ *specptr = unigen_special_0x1cb; \
+ break; \
+ case 0x1cc: \
+ *specptr = unigen_special_0x1cc; \
+ break; \
+ case 0x1f0: \
+ *specptr = unigen_special_0x1f0; \
+ break; \
+ case 0x1f1: \
+ *specptr = unigen_special_0x1f1; \
+ break; \
+ case 0x1f2: \
+ *specptr = unigen_special_0x1f2; \
+ break; \
+ case 0x1f3: \
+ *specptr = unigen_special_0x1f3; \
+ break; \
+ case 0x390: \
+ *specptr = unigen_special_0x390; \
+ break; \
+ case 0x3b0: \
+ *specptr = unigen_special_0x3b0; \
+ break; \
+ case 0x587: \
+ *specptr = unigen_special_0x587; \
+ break; \
+ case 0x1e96: \
+ *specptr = unigen_special_0x1e96; \
+ break; \
+ case 0x1e97: \
+ *specptr = unigen_special_0x1e97; \
+ break; \
+ case 0x1e98: \
+ *specptr = unigen_special_0x1e98; \
+ break; \
+ case 0x1e99: \
+ *specptr = unigen_special_0x1e99; \
+ break; \
+ case 0x1e9a: \
+ *specptr = unigen_special_0x1e9a; \
+ break; \
+ case 0x1f50: \
+ *specptr = unigen_special_0x1f50; \
+ break; \
+ case 0x1f52: \
+ *specptr = unigen_special_0x1f52; \
+ break; \
+ case 0x1f54: \
+ *specptr = unigen_special_0x1f54; \
+ break; \
+ case 0x1f56: \
+ *specptr = unigen_special_0x1f56; \
+ break; \
+ case 0x1f80: \
+ *specptr = unigen_special_0x1f80; \
+ break; \
+ case 0x1f81: \
+ *specptr = unigen_special_0x1f81; \
+ break; \
+ case 0x1f82: \
+ *specptr = unigen_special_0x1f82; \
+ break; \
+ case 0x1f83: \
+ *specptr = unigen_special_0x1f83; \
+ break; \
+ case 0x1f84: \
+ *specptr = unigen_special_0x1f84; \
+ break; \
+ case 0x1f85: \
+ *specptr = unigen_special_0x1f85; \
+ break; \
+ case 0x1f86: \
+ *specptr = unigen_special_0x1f86; \
+ break; \
+ case 0x1f87: \
+ *specptr = unigen_special_0x1f87; \
+ break; \
+ case 0x1f88: \
+ *specptr = unigen_special_0x1f88; \
+ break; \
+ case 0x1f89: \
+ *specptr = unigen_special_0x1f89; \
+ break; \
+ case 0x1f8a: \
+ *specptr = unigen_special_0x1f8a; \
+ break; \
+ case 0x1f8b: \
+ *specptr = unigen_special_0x1f8b; \
+ break; \
+ case 0x1f8c: \
+ *specptr = unigen_special_0x1f8c; \
+ break; \
+ case 0x1f8d: \
+ *specptr = unigen_special_0x1f8d; \
+ break; \
+ case 0x1f8e: \
+ *specptr = unigen_special_0x1f8e; \
+ break; \
+ case 0x1f8f: \
+ *specptr = unigen_special_0x1f8f; \
+ break; \
+ case 0x1f90: \
+ *specptr = unigen_special_0x1f90; \
+ break; \
+ case 0x1f91: \
+ *specptr = unigen_special_0x1f91; \
+ break; \
+ case 0x1f92: \
+ *specptr = unigen_special_0x1f92; \
+ break; \
+ case 0x1f93: \
+ *specptr = unigen_special_0x1f93; \
+ break; \
+ case 0x1f94: \
+ *specptr = unigen_special_0x1f94; \
+ break; \
+ case 0x1f95: \
+ *specptr = unigen_special_0x1f95; \
+ break; \
+ case 0x1f96: \
+ *specptr = unigen_special_0x1f96; \
+ break; \
+ case 0x1f97: \
+ *specptr = unigen_special_0x1f97; \
+ break; \
+ case 0x1f98: \
+ *specptr = unigen_special_0x1f98; \
+ break; \
+ case 0x1f99: \
+ *specptr = unigen_special_0x1f99; \
+ break; \
+ case 0x1f9a: \
+ *specptr = unigen_special_0x1f9a; \
+ break; \
+ case 0x1f9b: \
+ *specptr = unigen_special_0x1f9b; \
+ break; \
+ case 0x1f9c: \
+ *specptr = unigen_special_0x1f9c; \
+ break; \
+ case 0x1f9d: \
+ *specptr = unigen_special_0x1f9d; \
+ break; \
+ case 0x1f9e: \
+ *specptr = unigen_special_0x1f9e; \
+ break; \
+ case 0x1f9f: \
+ *specptr = unigen_special_0x1f9f; \
+ break; \
+ case 0x1fa0: \
+ *specptr = unigen_special_0x1fa0; \
+ break; \
+ case 0x1fa1: \
+ *specptr = unigen_special_0x1fa1; \
+ break; \
+ case 0x1fa2: \
+ *specptr = unigen_special_0x1fa2; \
+ break; \
+ case 0x1fa3: \
+ *specptr = unigen_special_0x1fa3; \
+ break; \
+ case 0x1fa4: \
+ *specptr = unigen_special_0x1fa4; \
+ break; \
+ case 0x1fa5: \
+ *specptr = unigen_special_0x1fa5; \
+ break; \
+ case 0x1fa6: \
+ *specptr = unigen_special_0x1fa6; \
+ break; \
+ case 0x1fa7: \
+ *specptr = unigen_special_0x1fa7; \
+ break; \
+ case 0x1fa8: \
+ *specptr = unigen_special_0x1fa8; \
+ break; \
+ case 0x1fa9: \
+ *specptr = unigen_special_0x1fa9; \
+ break; \
+ case 0x1faa: \
+ *specptr = unigen_special_0x1faa; \
+ break; \
+ case 0x1fab: \
+ *specptr = unigen_special_0x1fab; \
+ break; \
+ case 0x1fac: \
+ *specptr = unigen_special_0x1fac; \
+ break; \
+ case 0x1fad: \
+ *specptr = unigen_special_0x1fad; \
+ break; \
+ case 0x1fae: \
+ *specptr = unigen_special_0x1fae; \
+ break; \
+ case 0x1faf: \
+ *specptr = unigen_special_0x1faf; \
+ break; \
+ case 0x1fb2: \
+ *specptr = unigen_special_0x1fb2; \
+ break; \
+ case 0x1fb3: \
+ *specptr = unigen_special_0x1fb3; \
+ break; \
+ case 0x1fb4: \
+ *specptr = unigen_special_0x1fb4; \
+ break; \
+ case 0x1fb6: \
+ *specptr = unigen_special_0x1fb6; \
+ break; \
+ case 0x1fb7: \
+ *specptr = unigen_special_0x1fb7; \
+ break; \
+ case 0x1fbc: \
+ *specptr = unigen_special_0x1fbc; \
+ break; \
+ case 0x1fc2: \
+ *specptr = unigen_special_0x1fc2; \
+ break; \
+ case 0x1fc3: \
+ *specptr = unigen_special_0x1fc3; \
+ break; \
+ case 0x1fc4: \
+ *specptr = unigen_special_0x1fc4; \
+ break; \
+ case 0x1fc6: \
+ *specptr = unigen_special_0x1fc6; \
+ break; \
+ case 0x1fc7: \
+ *specptr = unigen_special_0x1fc7; \
+ break; \
+ case 0x1fcc: \
+ *specptr = unigen_special_0x1fcc; \
+ break; \
+ case 0x1fd2: \
+ *specptr = unigen_special_0x1fd2; \
+ break; \
+ case 0x1fd3: \
+ *specptr = unigen_special_0x1fd3; \
+ break; \
+ case 0x1fd6: \
+ *specptr = unigen_special_0x1fd6; \
+ break; \
+ case 0x1fd7: \
Commit: a698756c24c50059b84b6ca8833530b5f8cfef59
https://github.com/scummvm/scummvm/commit/a698756c24c50059b84b6ca8833530b5f8cfef59
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Don't show intro text when loading savegame from launcher
Changed paths:
engines/gargoyle/scott/scott.cpp
engines/gargoyle/scott/scott.h
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 329cfb3..001eff5 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -29,7 +29,7 @@ namespace Scott {
Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
- split_screen(true), Bottom(0), Top(0), BitFlags(0) {
+ split_screen(true), Bottom(0), Top(0), BitFlags(0), _saveSlot(-1) {
Common::fill(&NounText[0], &NounText[16], '\0');
Common::fill(&Counters[0], &Counters[16], 0);
Common::fill(&RoomSaved[0], &RoomSaved[16], 0);
@@ -37,7 +37,6 @@ Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst,
void Scott::runGame(Common::SeekableReadStream *gameFile) {
int vb, no;
- int saveSlot;
initialize();
Bottom = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
@@ -63,24 +62,24 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
Top = Bottom;
}
+ output("ScummVM support adapted from Scott Free, A Scott Adams game driver in C.\n\n");
+
// Check for savegame
- saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
+ _saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
- output("\
-Scott Free, A Scott Adams game driver in C.\n\
-Release 1.14, (c) 1993,1994,1995 Swansea University Computer Society.\n\
-Distributed under the GNU software license\n\n");
+ // Load the game
loadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
+ // Main game loop
while (!shouldQuit()) {
glk_tick();
performActions(0, 0);
- if (saveSlot >= 0) {
+ if (_saveSlot >= 0) {
// Load any savegame during startup
- loadGameState(saveSlot);
- saveSlot = -1;
+ loadGameState(_saveSlot);
+ _saveSlot = -1;
}
look();
@@ -404,7 +403,8 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
}
void Scott::output(const char *a) {
- display(Bottom, "%s", a);
+ if (_saveSlot == -1)
+ display(Bottom, "%s", a);
}
void Scott::outputNumber(int a) {
diff --git a/engines/gargoyle/scott/scott.h b/engines/gargoyle/scott/scott.h
index 0ff8d33..168476c 100644
--- a/engines/gargoyle/scott/scott.h
+++ b/engines/gargoyle/scott/scott.h
@@ -131,6 +131,7 @@ private:
bool split_screen;
winid_t Bottom, Top;
uint32 BitFlags; ///< Might be >32 flags - I haven't seen >32 yet
+ int _saveSlot; ///< Save slot when loading savegame from launcher
private:
/**
* Initialization code
Commit: fbed3ed7a3ab37cedf05d551e9c904db44a35b88
https://github.com/scummvm/scummvm/commit/fbed3ed7a3ab37cedf05d551e9c904db44a35b88
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Handle negative values in readInts
Changed paths:
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 001eff5..9f3a87d 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -1243,10 +1243,17 @@ void Scott::readInts(Common::SeekableReadStream *f, size_t count, ...) {
// Get the next value
int *val = (int *)va_arg(va, int);
*val = 0;
+
+ int factor = c == '-' ? -1 : 1;
+ if (factor == -1)
+ c = f->readByte();
+
while (Common::isDigit(c)) {
*val = (*val * 10) + (c - '0');
c = f->readByte();
}
+
+ *val *= factor; // Handle negatives
}
va_end(va);
Commit: 62315b969d851166c94c6fb73a3da7ac4ab44a73
https://github.com/scummvm/scummvm/commit/62315b969d851166c94c6fb73a3da7ac4ab44a73
Author: dreammaster (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: gcc compilation fixes
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/detection_tables.h
engines/gargoyle/events.h
engines/gargoyle/gargoyle.h
engines/gargoyle/glk_types.h
engines/gargoyle/module.mk
engines/gargoyle/scott/scott.cpp
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
engines/gargoyle/window_text_buffer.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 4363c46..245790a 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -142,8 +142,7 @@ bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
}
bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- Gargoyle::GargoyleGameDescription *gd = (Gargoyle::GargoyleGameDescription *)desc;
- gd->_filename = ConfMan.get("filename");
+ const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
switch (gd->_interpType) {
case Gargoyle::INTERPRETER_SCOTT:
diff --git a/engines/gargoyle/detection_tables.h b/engines/gargoyle/detection_tables.h
index 777d4db..30491f6 100644
--- a/engines/gargoyle/detection_tables.h
+++ b/engines/gargoyle/detection_tables.h
@@ -23,19 +23,7 @@
namespace Gargoyle {
static const GargoyleGameDescription gameDescriptions[] = {
- {
- {
- "Gargoyle",
- 0,
- AD_ENTRY1s("dummy", "0", 0),
- Common::EN_ANY,
- Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- },
-
- { AD_TABLE_END_MARKER }
+ { AD_TABLE_END_MARKER, "", (InterpreterType)0, "" }
};
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
index b69cd04..745f1ae 100644
--- a/engines/gargoyle/events.h
+++ b/engines/gargoyle/events.h
@@ -258,7 +258,7 @@ public:
/**
* Set the total number of frames played
*/
- void Events::setTotalPlayTicks(uint frames) {
+ void setTotalPlayTicks(uint frames) {
_frameCounter = frames;
}
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index e131be1..aeaa0c0 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -164,7 +164,7 @@ public:
/**
* Returns the primary filename for the game
*/
- const Common::String &GargoyleEngine::getFilename() const;
+ const Common::String &getFilename() const;
/**
* Return the game engine's target name
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index 7258e69..21a8b75 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -103,7 +103,7 @@ enum Gestalt {
gestalt_LineTerminatorKey = 19,
gestalt_DateTime = 20,
gestalt_Sound2 = 21,
- gestalt_GarglkText = 0x1100,
+ gestalt_GarglkText = 0x1100
};
enum Style {
@@ -118,7 +118,7 @@ enum Style {
style_Input = 8,
style_User1 = 9,
style_User2 = 10,
- style_NUMSTYLES = 11,
+ style_NUMSTYLES = 11
};
enum WinType {
@@ -127,7 +127,7 @@ enum WinType {
wintype_Blank = 2,
wintype_TextBuffer = 3,
wintype_TextGrid = 4,
- wintype_Graphics = 5,
+ wintype_Graphics = 5
};
enum WinMethod {
@@ -143,7 +143,7 @@ enum WinMethod {
winmethod_Border = 0x000,
winmethod_NoBorder = 0x100,
- winmethod_BorderMask = 0x100,
+ winmethod_BorderMask = 0x100
};
enum StyleHint {
@@ -162,7 +162,7 @@ enum StyleHint {
stylehint_just_LeftFlush = 0,
stylehint_just_LeftRight = 1,
stylehint_just_Centered = 2,
- stylehint_just_RightFlush = 3,
+ stylehint_just_RightFlush = 3
};
/**
@@ -176,7 +176,7 @@ enum giDisp {
gidisp_Class_Window = 0,
gidisp_Class_Stream = 1,
gidisp_Class_Fileref = 2,
- gidisp_Class_Schannel = 3,
+ gidisp_Class_Schannel = 3
};
enum zcolor {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index bf4138a..d24a041 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -16,7 +16,6 @@ MODULE_OBJS := \
unicode_gen.o \
utils.o \
windows.o \
- window_mask.o \
window_graphics.o \
window_pair.o \
window_text_buffer.o \
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 9f3a87d..3316995 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -175,7 +175,7 @@ void Scott::delay(int seconds) {
}
void Scott::fatal(const char *x) {
- error(x);
+ error("%s", x);
}
void Scott::clearScreen(void) {
@@ -412,7 +412,7 @@ void Scott::outputNumber(int a) {
}
void Scott::look(void) {
- static char *ExitNames[6] = { "North", "South", "East", "West", "Up", "Down" };
+ const char *const ExitNames[6] = { "North", "South", "East", "West", "Up", "Down" };
Room *r;
int ct, f;
int pos;
@@ -555,7 +555,7 @@ Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
glk_put_string_stream(file, msg.c_str());
}
- msg = Common::String::format("%lu %d %hd %d %d %hd\n",
+ msg = Common::String::format("%u %d %hd %d %d %hd\n",
BitFlags, (BitFlags & (1 << DARKBIT)) ? 1 : 0,
MyLoc, CurrentCounter, SavedRoom, GameHeader.LightTime);
glk_put_string_stream(file, msg.c_str());
@@ -602,7 +602,7 @@ Common::Error Scott::loadGameState(int slot) {
}
glk_get_line_stream(file, buf, sizeof buf);
- sscanf(buf, "%ld %hd %d %d %d %d\n",
+ sscanf(buf, "%u %hd %d %d %d %d\n",
&BitFlags, &darkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
&GameHeader.LightTime);
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 75fb205..659fcd0 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -850,7 +850,7 @@ void FileStream::putBuffer(const char *buf, size_t len) {
ensureOp(filemode_Write);
for (size_t lx = 0; lx < len; lx++) {
- unsigned char ch = ((unsigned char *)buf)[lx];
+ unsigned char ch = ((const unsigned char *)buf)[lx];
if (!_unicode) {
_outFile->writeByte(ch);
} else if (_textFile) {
@@ -1100,7 +1100,7 @@ glui32 FileStream::getBuffer(char *buf, glui32 len) {
for (lx = 0; lx < len; lx++) {
glui32 ch;
ch = getCharUtf8();
- if (ch == -1)
+ if (ch == (glui32)-1)
break;
_readCount++;
if (ch >= 0x100)
@@ -1161,7 +1161,7 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) {
for (lx = 0; lx < len; lx++) {
glui32 ch;
ch = getCharUtf8();
- if (ch == -1)
+ if (ch == (glui32)-1)
break;
_readCount++;
buf[lx] = ch;
@@ -1221,7 +1221,7 @@ glui32 FileStream::getLine(char *buf, glui32 len) {
for (lx = 0; lx < len && !gotNewline; lx++) {
glui32 ch;
ch = getCharUtf8();
- if (ch == -1)
+ if (ch == (glui32)-1)
break;
_readCount++;
if (ch >= 0x100)
@@ -1295,7 +1295,7 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
for (lx = 0; lx < (int)len && !gotNewline; lx++) {
glui32 ch;
ch = getCharUtf8();
- if (ch == -1)
+ if (ch == (glui32)-1)
break;
_readCount++;
ubuf[lx] = ch;
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 8a497e0..772b021 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -44,20 +44,20 @@ enum FileUsage {
fileusage_TypeMask = 0x0f,
fileusage_TextMode = 0x100,
- fileusage_BinaryMode = 0x000,
+ fileusage_BinaryMode = 0x000
};
enum FileMode {
filemode_Write = 0x01,
filemode_Read = 0x02,
filemode_ReadWrite = 0x03,
- filemode_WriteAppend = 0x05,
+ filemode_WriteAppend = 0x05
};
enum SeekMode {
seekmode_Start = 0,
seekmode_Current = 1,
- seekmode_End = 2,
+ seekmode_End = 2
};
struct StreamResult {
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
index ca89167..5cf8f34 100644
--- a/engines/gargoyle/window_text_buffer.cpp
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -43,7 +43,7 @@ TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windo
_radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
_spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
_type = wintype_TextBuffer;
- Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
+ Common::fill(&_history[0], &_history[HISTORYLEN], (glui32 *)nullptr);
_lines.resize(SCROLLBACK);
_chars = _lines[0]._chars;
@@ -908,7 +908,7 @@ void TextBufferWindow::redraw() {
for (tsc = 0; tsc < linelen; tsc++) {
tsw = calcWidth(ln->_chars, ln->_attrs, 0, tsc, spw) / GLI_SUBPIX;
if (tsw + tx >= sx0 ||
- tsw + tx + GLI_SUBPIX >= sx0 && ln->_chars[tsc] != ' ') {
+ ((tsw + tx + GLI_SUBPIX) >= sx0 && ln->_chars[tsc] != ' ')) {
lsc = tsc;
selchar = true;
break;
Commit: cde50e00edea1c0cc0235aa814501038e6a1792c
https://github.com/scummvm/scummvm/commit/cde50e00edea1c0cc0235aa814501038e6a1792c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix handling of negative file offsets in MemoryStream::setPosition
Changed paths:
engines/gargoyle/streams.cpp
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 659fcd0..41f3caf 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -459,29 +459,31 @@ glui32 MemoryStream::getPosition() const {
}
void MemoryStream::setPosition(glui32 pos, glui32 seekMode) {
+ glsi32 newPos = pos;
+
if (!_unicode) {
if (seekMode == seekmode_Current)
- pos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + pos;
+ newPos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + newPos;
else if (seekMode == seekmode_End)
- pos = ((unsigned char *)_bufEof - (unsigned char *)_buf) + pos;
+ newPos = ((unsigned char *)_bufEof - (unsigned char *)_buf) + newPos;
else
- /* pos = pos */;
- if (pos < 0)
- pos = 0;
- if (pos > (glui32)((unsigned char *)_bufEof - (unsigned char *)_buf))
- pos = ((unsigned char *)_bufEof - (unsigned char *)_buf);
- _bufPtr = (unsigned char *)_buf + pos;
+ /* newPos = newPos */;
+ if (newPos < 0)
+ newPos = 0;
+ if (newPos > ((unsigned char *)_bufEof - (unsigned char *)_buf))
+ newPos = ((unsigned char *)_bufEof - (unsigned char *)_buf);
+ _bufPtr = (unsigned char *)_buf + newPos;
} else {
if (seekMode == seekmode_Current)
- pos = ((glui32 *)_bufPtr - (glui32 *)_buf) + pos;
+ newPos = ((glui32 *)_bufPtr - (glui32 *)_buf) + newPos;
else if (seekMode == seekmode_End)
- pos = ((glui32 *)_bufEof - (glui32 *)_buf) + pos;
+ newPos = ((glui32 *)_bufEof - (glui32 *)_buf) + newPos;
- if (pos < 0)
- pos = 0;
- if (pos > (glui32)((glui32 *)_bufEof - (glui32 *)_buf))
- pos = ((glui32 *)_bufEof - (glui32 *)_buf);
- _bufPtr = (glui32 *)_buf + pos;
+ if (newPos < 0)
+ newPos = 0;
+ if (newPos > ((glui32 *)_bufEof - (glui32 *)_buf))
+ newPos = ((glui32 *)_bufEof - (glui32 *)_buf);
+ _bufPtr = (glui32 *)_buf + newPos;
}
}
Commit: 43cee5fb0f4fee9669098c21777ac9b41865bee1
https://github.com/scummvm/scummvm/commit/43cee5fb0f4fee9669098c21777ac9b41865bee1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix setTime converting seconds to a date/time structure
Changed paths:
engines/gargoyle/time.cpp
diff --git a/engines/gargoyle/time.cpp b/engines/gargoyle/time.cpp
index 9a99d3b..39c3b7c 100644
--- a/engines/gargoyle/time.cpp
+++ b/engines/gargoyle/time.cpp
@@ -63,15 +63,17 @@ TimeAndDate::operator Timestamp() const {
void TimeAndDate::setTime(const TimeSeconds &ts) {
TimeSeconds total = ts;
- int daysInYear, secsInYear;
+ int daysInYear = 0, secsInYear = 0;
// Figure out the year
this->year = 1969;
do {
++this->year;
- daysInYear = ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 365 : 365;
+ total -= secsInYear;
+
+ daysInYear = ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 366 : 365;
secsInYear = daysInYear * 24 * 60 * 60;
- } while (total >= daysInYear);
+ } while (total >= secsInYear);
// Figure out month and day
int dayInYear = total / (24 * 60 * 60);
Commit: c589b807e2b4ae67928cfadb0a5b2e18cef38ff3
https://github.com/scummvm/scummvm/commit/c589b807e2b4ae67928cfadb0a5b2e18cef38ff3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Skeleton sub-engine for Frotz interpreter
Changed paths:
A engines/gargoyle/frotz/detection.cpp
A engines/gargoyle/frotz/detection.h
A engines/gargoyle/frotz/frotz.cpp
A engines/gargoyle/frotz/frotz.h
A engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/detection.cpp
engines/gargoyle/module.mk
engines/gargoyle/scott/detection.cpp
engines/gargoyle/scott/detection.h
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 245790a..f3b7ca0 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -69,6 +69,7 @@ const Common::String &GargoyleEngine::getGameMD5() const {
} // End of namespace Gargoyle
static const PlainGameDescriptor gargoyleGames[] = {
+ {"zcode", "Zcode Games" },
{"scottadams", "Scott Adams Games"},
// Scott Adams games
@@ -94,6 +95,8 @@ static const PlainGameDescriptor gargoyleGames[] = {
#include "common/config-manager.h"
#include "common/file.h"
#include "gargoyle/detection_tables.h"
+#include "gargoyle/frotz/detection.h"
+#include "gargoyle/frotz/frotz.h"
#include "gargoyle/scott/detection.h"
#include "gargoyle/scott/scott.h"
@@ -145,6 +148,9 @@ bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD
const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
switch (gd->_interpType) {
+ case Gargoyle::INTERPRETER_FROTZ:
+ *engine = new Gargoyle::Frotz::Frotz(syst, gd);
+ break;
case Gargoyle::INTERPRETER_SCOTT:
*engine = new Gargoyle::Scott::Scott(syst, gd);
break;
@@ -216,6 +222,7 @@ SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, i
DetectedGames GargoyleMetaEngine::detectGames(const Common::FSList &fslist) const {
DetectedGames detectedGames;
+ Gargoyle::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
return detectedGames;
@@ -234,11 +241,19 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
ADDetectedGames results;
Common::File f;
- Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
- if (detectedGames.size() > 0 && f.open(parent.getChild(filename))) {
+ // Check each sub-engine for any detected games
+ if (Gargoyle::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames))
+ gameDescription._interpType = Gargoyle::INTERPRETER_FROTZ;
+ else if (Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames))
+ gameDescription._interpType = Gargoyle::INTERPRETER_SCOTT;
+ else
+ // No match found, so return no results
+ return results;
+
+ // Set up the game description and return it
+ if (f.open(parent.getChild(filename))) {
DetectedGame gd = detectedGames.front();
- gameDescription._interpType = Gargoyle::INTERPRETER_SCOTT;
gameDescription._desc.gameId = gameId;
gameDescription._desc.language = gd.language;
gameDescription._desc.platform = gd.platform;
diff --git a/engines/gargoyle/frotz/detection.cpp b/engines/gargoyle/frotz/detection.cpp
new file mode 100644
index 0000000..6760777
--- /dev/null
+++ b/engines/gargoyle/frotz/detection.cpp
@@ -0,0 +1,83 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/detection.h"
+#include "common/file.h"
+#include "common/md5.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+struct FrotzGame {
+ const char *_md5;
+ const char *_gameId;
+ int32 _filesize;
+ const char *_desc;
+};
+
+const FrotzGame FROTZ_GAMES[] = {
+ { nullptr, nullptr, 0, nullptr }
+};
+
+bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
+ Common::File gameFile;
+ Common::String md5;
+ const char *const EXTENSIONS[9] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
+
+ // Loop through the files of the folder
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ // Check for a recognised filename
+ if (file->isDirectory())
+ continue;
+ Common::String filename = file->getName();
+ bool hasExt = false;
+ for (int idx = 0; idx < 9 && !hasExt; ++idx)
+ hasExt = filename.hasSuffixIgnoreCase(EXTENSIONS[idx]);
+ if (!hasExt)
+ continue;
+
+ // Check for known game
+ if (gameFile.open(*file)) {
+ md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+
+ // Scan through the game list for a match
+ const FrotzGame *p = FROTZ_GAMES;
+ while (p->_md5 && p->_filesize != gameFile.size() && md5 != p->_md5)
+ ++p;
+
+ if (p->_filesize) {
+ // Found a match
+ DetectedGame gd(p->_gameId, p->_desc, Common::EN_ANY, Common::kPlatformUnknown);
+ gd.addExtraEntry("filename", file->getName());
+
+ gameList.push_back(gd);
+ }
+
+ gameFile.close();
+ }
+ }
+
+ return !gameList.empty();
+}
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/detection.h b/engines/gargoyle/frotz/detection.h
new file mode 100644
index 0000000..2e70d7c
--- /dev/null
+++ b/engines/gargoyle/frotz/detection.h
@@ -0,0 +1,43 @@
+/* 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 GARGOYLE_FROTZ_DETECTION
+#define GARGOYLE_FROTZ_DETECTION
+
+#include "common/fs.h"
+#include "engines/game.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+class FrotzMetaEngine {
+public:
+ /**
+ * Detect supported games
+ */
+ static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
new file mode 100644
index 0000000..c13f5b2
--- /dev/null
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -0,0 +1,45 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/frotz.h"
+#include "gargoyle/frotz/frotz_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc) {
+}
+
+void Frotz::runGame(Common::SeekableReadStream *gameFile) {
+ // TODO
+}
+
+Common::Error Frotz::loadGameState(int slot) {
+ return Common::kNoError;
+}
+
+Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
+ return Common::kNoError;
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
new file mode 100644
index 0000000..8aa2ce7
--- /dev/null
+++ b/engines/gargoyle/frotz/frotz.h
@@ -0,0 +1,65 @@
+/* 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 GARGOYLE_FROTZ_FROTZ
+#define GARGOYLE_FROTZ_FROTZ
+
+#include "gargoyle/glk.h"
+#include "gargoyle/frotz/frotz_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+/**
+ * Frotz interpreter for Z-code games
+ */
+class Frotz : public Glk {
+private:
+ /**
+ *
+ */
+public:
+ /**
+ * Constructor
+ */
+ Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc);
+
+ /**
+ * Execute the game
+ */
+ virtual void runGame(Common::SeekableReadStream *gameFile) override;
+
+ /**
+ * Load a savegame
+ */
+ virtual Common::Error loadGameState(int slot) override;
+
+ /**
+ * Save the game
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
new file mode 100644
index 0000000..d4a6d8c
--- /dev/null
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -0,0 +1,37 @@
+/* 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 GARGOYLE_FROTZ_FROTZ_TYPES
+#define GARGOYLE_FROTZ_FROTZ_TYPES
+
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+typedef byte zbyte;
+typedef uint16 zword;
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index d24a041..135b39c 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -20,6 +20,8 @@ MODULE_OBJS := \
window_pair.o \
window_text_buffer.o \
window_text_grid.o \
+ frotz/detection.o \
+ frotz/frotz.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/scott/detection.cpp b/engines/gargoyle/scott/detection.cpp
index 04d4f83..1b8041a 100644
--- a/engines/gargoyle/scott/detection.cpp
+++ b/engines/gargoyle/scott/detection.cpp
@@ -53,7 +53,7 @@ const ScottGame SCOTT_GAMES[] = {
{ nullptr, nullptr, 0, nullptr }
};
-void ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
+bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
Common::File gameFile;
Common::String md5;
@@ -81,6 +81,8 @@ void ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
gameFile.close();
}
}
+
+ return !gameList.empty();
}
} // End of namespace Scott
diff --git a/engines/gargoyle/scott/detection.h b/engines/gargoyle/scott/detection.h
index e2aa93e..01e1ffe 100644
--- a/engines/gargoyle/scott/detection.h
+++ b/engines/gargoyle/scott/detection.h
@@ -32,9 +32,9 @@ namespace Scott {
class ScottMetaEngine {
public:
/**
- * Detect Scott Adams games
+ * Detect supported games
*/
- static void detectGames(const Common::FSList &fslist, DetectedGames &gameList);
+ static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
};
} // End of namespace Scott
Commit: 1aaf2fd145e30937e8cd4c6736bee448f2b05a2c
https://github.com/scummvm/scummvm/commit/1aaf2fd145e30937e8cd4c6736bee448f2b05a2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fleshing out detection logic and added some entries
Changed paths:
A engines/gargoyle/frotz/detection_tables.cpp
A engines/gargoyle/frotz/detection_tables.h
engines/gargoyle/detection.cpp
engines/gargoyle/frotz/detection.cpp
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index f3b7ca0..2836e04 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -68,10 +68,55 @@ const Common::String &GargoyleEngine::getGameMD5() const {
} // End of namespace Gargoyle
+#include "gargoyle/frotz/detection_tables.h"
+#define ZCODE(ID, NAME) { ID, Gargoyle::Frotz::NAME }
+
static const PlainGameDescriptor gargoyleGames[] = {
{"zcode", "Zcode Games" },
{"scottadams", "Scott Adams Games"},
+ // Infocom/Z-code games
+ ZCODE("amfv", AMFV),
+ ZCODE("arthur", ARTHUR),
+ ZCODE("ballyhoo", BALLYHOO),
+ ZCODE("beyondzork", BEYONDZORK),
+ ZCODE("borderzone", BORDERZONE),
+ ZCODE("bureaucracy", BUREAUCRACY),
+ ZCODE("cutthroats", CUTTHROATS),
+ ZCODE("deadline", DEADLINE),
+ ZCODE("enchanter", ENCHANTER),
+ ZCODE("hhgttg", HHGTTG),
+ ZCODE("hijinx", HIJINX),
+ ZCODE("infidel", INFIDEL),
+ ZCODE("journey", JOURNEY),
+ ZCODE("lgop", LGOP),
+ ZCODE("lgop2", LGOP2),
+ ZCODE("lurking", LURKING),
+ ZCODE("minizork1", MINIZORK1),
+ ZCODE("moonmist", MOONMIST),
+ ZCODE("nordbert", NORDBERT),
+ ZCODE("planetfall", PLANETFALL),
+ ZCODE("plundered", PLUNDERED),
+ ZCODE("sampler1", SAMPLER1),
+ ZCODE("sampler2", SAMPLER2),
+ ZCODE("seastalker", SEASTALKER),
+ ZCODE("sherlockriddle", SHERLOCKRIDDLE),
+ ZCODE("shogun", SHOGUN),
+ ZCODE("sorcerer", SORCERER),
+ ZCODE("spellbreaker", SPELLBREAKER),
+ ZCODE("starcross", STARCROSS),
+ ZCODE("stationfall", STATIONFALL),
+ ZCODE("suspect", SUSPECT),
+ ZCODE("suspended", SUSPENDED),
+ ZCODE("trinity", TRINITY),
+ ZCODE("wishbringer", WISHBRINGER),
+ ZCODE("witness", WITNESS),
+ ZCODE("zork0", ZORK0),
+ ZCODE("zork1", ZORK1),
+ ZCODE("zork2", ZORK2),
+ ZCODE("zork3", ZORK3),
+ ZCODE("ztuu", ZTUU),
+
// Scott Adams games
{ "adventureland", "Adventureland" },
{ "pirateadventure", "Pirate Adventure" },
diff --git a/engines/gargoyle/frotz/detection.cpp b/engines/gargoyle/frotz/detection.cpp
index 6760777..fff8005 100644
--- a/engines/gargoyle/frotz/detection.cpp
+++ b/engines/gargoyle/frotz/detection.cpp
@@ -24,23 +24,12 @@
#include "common/file.h"
#include "common/md5.h"
+#include "gargoyle/frotz/detection_tables.h"
+
namespace Gargoyle {
namespace Frotz {
-struct FrotzGame {
- const char *_md5;
- const char *_gameId;
- int32 _filesize;
- const char *_desc;
-};
-
-const FrotzGame FROTZ_GAMES[] = {
- { nullptr, nullptr, 0, nullptr }
-};
-
bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
- Common::File gameFile;
- Common::String md5;
const char *const EXTENSIONS[9] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
// Loop through the files of the folder
@@ -55,25 +44,33 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
if (!hasExt)
continue;
- // Check for known game
- if (gameFile.open(*file)) {
- md5 = Common::computeStreamMD5AsString(gameFile, 5000);
-
- // Scan through the game list for a match
- const FrotzGame *p = FROTZ_GAMES;
- while (p->_md5 && p->_filesize != gameFile.size() && md5 != p->_md5)
- ++p;
+ // Open up the file and calculate the md5
+ Common::File gameFile;
+ if (!gameFile.open(*file))
+ continue;
+ Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+ size_t filesize = gameFile.size();
+ gameFile.close();
- if (p->_filesize) {
- // Found a match
- DetectedGame gd(p->_gameId, p->_desc, Common::EN_ANY, Common::kPlatformUnknown);
- gd.addExtraEntry("filename", file->getName());
+ // Check for known game
+ const FrotzGameDescription *p = FROTZ_GAMES;
+ while (p->_gameId && p->_md5 && (md5 != p->_md5 || filesize != p->_filesize))
+ ++p;
- gameList.push_back(gd);
- }
+ DetectedGame gd;
+ if (!p->_gameId) {
+ // Generic .dat files don't get reported as matches unless they have a known md5
+ if (filename.hasSuffixIgnoreCase(".dat"))
+ continue;
- gameFile.close();
+ warning("Uknown zcode game %s - %s %d", filename.c_str(), md5.c_str(), filesize);
+ gd = DetectedGame("zcode", "Unrecognised zcode game", Common::UNK_LANG, Common::kPlatformUnknown);
+ } else {
+ gd = DetectedGame(p->_gameId, p->_description, p->_language, Common::kPlatformUnknown, p->_extra);
}
+
+ gd.addExtraEntry("filename", filename);
+ gameList.push_back(gd);
}
return !gameList.empty();
diff --git a/engines/gargoyle/frotz/detection_tables.cpp b/engines/gargoyle/frotz/detection_tables.cpp
new file mode 100644
index 0000000..f8d3f42
--- /dev/null
+++ b/engines/gargoyle/frotz/detection_tables.cpp
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/detection_tables.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+const char *const AMFV = "A Mind Forever Voyaging";
+const char *const ARTHUR = "Arthur: The Quest for Excalibur";
+const char *const BALLYHOO = "Ballyhoo";
+const char *const BEYONDZORK = "Beyond Zork";
+const char *const BORDERZONE = "Border Zone";
+const char *const BUREAUCRACY = "Bureaucracy";
+const char *const CUTTHROATS = "Cutthroats";
+const char *const DEADLINE = "Deadline";
+const char *const ENCHANTER = "Enchanter";
+const char *const HHGTTG = "The Hitchhiker's Guide to the Galaxy";
+const char *const HIJINX = "Hollywood Hijinx";
+const char *const INFIDEL = "Infidel";
+const char *const JOURNEY = "Journey";
+const char *const LGOP = "Leather Goddesses of Phobos";
+const char *const LGOP2 = "Leather Goddesses of Phobos 2";
+const char *const LURKING = "The Lurking Horror";
+const char *const MINIZORK1 = "Mini Zork I: The Great Underground Empire";
+const char *const MOONMIST = "Moonmist";
+const char *const NORDBERT = "Nord and Bert Couldn't Make Head or Tail of It";
+const char *const PLANETFALL = "Planetfall";
+const char *const PLUNDERED = "Plundered Hearts";
+const char *const SAMPLER1 = "Infocom Sampler 1";
+const char *const SAMPLER2 = "Infocom Sampler 2";
+const char *const SEASTALKER = "Seastalker";
+const char *const SHERLOCKRIDDLE = "Sherlock: The Riddle of the Crown Jewels";
+const char *const SHOGUN = "James Clavell's Shogun";
+const char *const SORCERER = "Sorcerer";
+const char *const SPELLBREAKER = "Spellbreaker";
+const char *const STARCROSS = "Starcross";
+const char *const STATIONFALL = "Stationfall";
+const char *const SUSPECT = "Suspect";
+const char *const SUSPENDED = "Suspended";
+const char *const TRINITY = "Trinity";
+const char *const WISHBRINGER = "Wishbringer";
+const char *const WITNESS = "The Witness";
+const char *const ZORK0 = "Zork Zero: The Revenge of Megaboz";
+const char *const ZORK1 = "Zork I: The Great Underground Empire";
+const char *const ZORK2 = "Zork II: The Wizard of Frobozz";
+const char *const ZORK3 = "Zork III: The Dungeon Master";
+const char *const ZTUU = "Zork: The Undiscovered Underground";
+
+#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
+#define ENTRY0(ID, DESC, VERSION, MD5, FILESIZE) { ID, DESC, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
+#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
+
+const FrotzGameDescription FROTZ_GAMES[] = {
+ ENTRY0("hhgttg", HHGTTG, "v31 Solid Gold", "379022bcd4ec74b90274c6100c33f579", 158412),
+ ENTRY0("hhgttg", HHGTTG, "v47", "fdda8f4239819402c62db866bb61a648", 112622),
+ ENTRY0("hhgttg", HHGTTG, "v56", "a214fcb42bc9f554d07d983a12f6a062", 113444),
+ ENTRY0("hhgttg", HHGTTG, "v58", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
+ ENTRY0("hhgttg", HHGTTG, "v59", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
+
+ FROTZ_TABLE_END_MARKER
+};
+
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/detection_tables.h b/engines/gargoyle/frotz/detection_tables.h
new file mode 100644
index 0000000..1a9e4ee
--- /dev/null
+++ b/engines/gargoyle/frotz/detection_tables.h
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ */
+
+#include "engines/advancedDetector.h"
+#include "common/language.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+/**
+ * Game descriptor for ZCode games
+ */
+struct FrotzGameDescription {
+ const char *const _gameId;
+ const char *const _description;
+ const char *const _extra;
+ const char *const _md5;
+ size_t _filesize;
+ Common::Language _language;
+ const char *const _guiOptions;
+};
+
+extern const FrotzGameDescription FROTZ_GAMES[];
+extern const char *const AMFV;
+extern const char *const ARTHUR;
+extern const char *const BALLYHOO;
+extern const char *const BEYONDZORK;
+extern const char *const BORDERZONE;
+extern const char *const BUREAUCRACY;
+extern const char *const CUTTHROATS;
+extern const char *const DEADLINE;
+extern const char *const ENCHANTER;
+extern const char *const HHGTTG;
+extern const char *const HIJINX;
+extern const char *const INFIDEL;
+extern const char *const JOURNEY;
+extern const char *const LGOP;
+extern const char *const LGOP2;
+extern const char *const LURKING;
+extern const char *const MINIZORK1;
+extern const char *const MOONMIST;
+extern const char *const NORDBERT;
+extern const char *const PLANETFALL;
+extern const char *const PLUNDERED;
+extern const char *const SAMPLER1;
+extern const char *const SAMPLER2;
+extern const char *const SEASTALKER;
+extern const char *const SHERLOCKRIDDLE;
+extern const char *const SHOGUN;
+extern const char *const SORCERER;
+extern const char *const SPELLBREAKER;
+extern const char *const STARCROSS;
+extern const char *const STATIONFALL;
+extern const char *const SUSPECT;
+extern const char *const SUSPENDED;
+extern const char *const TRINITY;
+extern const char *const WISHBRINGER;
+extern const char *const WITNESS;
+extern const char *const ZORK0;
+extern const char *const ZORK1;
+extern const char *const ZORK2;
+extern const char *const ZORK3;
+extern const char *const ZTUU;
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 135b39c..8e16bfe 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -21,6 +21,7 @@ MODULE_OBJS := \
window_text_buffer.o \
window_text_grid.o \
frotz/detection.o \
+ frotz/detection_tables.o \
frotz/frotz.o \
scott/detection.o \
scott/scott.o
Commit: 8316c1a5b28f0a185df32d8bbafd08374a0aed32
https://github.com/scummvm/scummvm/commit/8316c1a5b28f0a185df32d8bbafd08374a0aed32
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Beginnings of initialization
Changed paths:
A engines/gargoyle/frotz/buffer.cpp
A engines/gargoyle/frotz/buffer.h
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/frotz/buffer.cpp b/engines/gargoyle/frotz/buffer.cpp
new file mode 100644
index 0000000..15ec771
--- /dev/null
+++ b/engines/gargoyle/frotz/buffer.cpp
@@ -0,0 +1,104 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/buffer.h"
+#include "gargoyle/frotz/frotz.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Replace these method stubs with correct calls
+void stream_char(zchar) {}
+void stream_word(const zchar *) {}
+void stream_new_line(void) {}
+
+Buffer::Buffer() : _bufPos(0), _locked(false), _prevC('\0') {
+ Common::fill(&_buffer[0], &_buffer[TEXT_BUFFER_SIZE], '\0');
+}
+
+void Buffer::flush() {
+ /* Make sure we stop when flush_buffer is called from flush_buffer.
+ * Note that this is difficult to avoid as we might print a newline
+ * during flush_buffer, which might cause a newline interrupt, that
+ * might execute any arbitrary opcode, which might flush the buffer.
+ */
+ if (_locked || empty())
+ return;
+
+ // Send the buffer to the output streams
+ _buffer[_bufPos] = '\0';
+
+ _locked = true;
+ stream_word(_buffer);
+ _locked = false;
+
+ // Reset the buffer
+ _bufPos = 0;
+ _prevC = '\0';
+}
+
+void Buffer::printChar(zchar c) {
+ static bool flag = false;
+
+ if (g_vm->_message || g_vm->_ostream_memory || g_vm->_enableBuffering) {
+ if (!flag) {
+ // Characters 0 and ZC_RETURN are special cases
+ if (c == ZC_RETURN) {
+ newLine();
+ return;
+ }
+ if (c == 0)
+ return;
+
+ // Flush the buffer before a whitespace or after a hyphen
+ if (c == ' ' || c == ZC_INDENT || c == ZC_GAP || (_prevC == '-' && c != '-'))
+ flush();
+
+ // Set the flag if this is part one of a style or font change
+ if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE)
+ flag = true;
+
+ // Remember the current character code
+ _prevC = c;
+ } else {
+ flag = false;
+ }
+
+ // Insert the character into the buffer
+ _buffer[_bufPos++] = c;
+
+ if (_bufPos == TEXT_BUFFER_SIZE)
+ error("Text buffer overflow");
+ } else {
+ stream_char(c);
+ }
+}
+
+void Buffer::newLine() {
+ flush();
+ stream_new_line();
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/buffer.h b/engines/gargoyle/frotz/buffer.h
new file mode 100644
index 0000000..608e087
--- /dev/null
+++ b/engines/gargoyle/frotz/buffer.h
@@ -0,0 +1,72 @@
+/* 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 GARGOYLE_FROTZ_BUFFER
+#define GARGOYLE_FROTZ_BUFFER
+
+#include "gargoyle/frotz/frotz_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+#define TEXT_BUFFER_SIZE 200
+
+/**
+ * Text buffer class
+ */
+class Buffer {
+public:
+ zchar _buffer[TEXT_BUFFER_SIZE];
+ size_t _bufPos;
+ bool _locked;
+ zchar _prevC;
+public:
+ /**
+ * Constructor
+ */
+ Buffer();
+
+ /**
+ * Copy the contents of the text buffer to the output streams.
+ */
+ void flush();
+
+ /**
+ * High level output function.
+ */
+ void printChar(zchar c);
+
+ /**
+ * High level newline function.
+ */
+ void newLine();
+
+ /**
+ * Returns true if the buffer is empty
+ */
+ bool empty() const { return !_bufPos; }
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index c13f5b2..e7c6972 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -26,7 +26,17 @@
namespace Gargoyle {
namespace Frotz {
-Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc) {
+Frotz *g_vm;
+
+Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
+ _storyId(STORY_UNKNOWN), _storySize(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
+ _ostream_screen(true), _ostream_script(false), _ostream_memory(false),
+ _ostream_record(false), _istream_replay(false), _message(false),
+ _cwin(0), _mwin(0), _mouse_x(0), _mouse_y(0), _menu_selected(0),
+ _enableWrapping(false), _enableScripting(true), _enableScrolling(false),
+ _enableBuffering(false), _reserveMem(0) {
+ g_vm = this;
+ Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
}
void Frotz::runGame(Common::SeekableReadStream *gameFile) {
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index 8aa2ce7..6ed226a 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -33,10 +33,44 @@ namespace Frotz {
* Frotz interpreter for Z-code games
*/
class Frotz : public Glk {
-private:
- /**
- *
- */
+public:
+ UserOptions _options;
+ Header _header;
+
+ // Story file name, id number and size
+ Common::String _storyName;
+ Story _storyId;
+ size_t _storySize;
+
+ // Stack data
+ zword _stack[STACK_SIZE];
+ zword *_sp;
+ zword *_fp;
+ zword _frameCount;
+
+ // IO streams
+ bool _ostream_screen;
+ bool _ostream_script;
+ bool _ostream_memory;
+ bool _ostream_record;
+ bool _istream_replay;
+ bool _message;
+
+ // Current window and mouse data
+ int _cwin;
+ int _mwin;
+ int _mouse_y;
+ int _mouse_x;
+ int _menu_selected;
+
+ // Window attributes
+ bool _enableWrapping;
+ bool _enableScripting;
+ bool _enableScrolling;
+ bool _enableBuffering;
+
+ // Size of memory to reserve (in bytes)
+ size_t _reserveMem;
public:
/**
* Constructor
@@ -59,6 +93,8 @@ public:
virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
};
+extern Frotz *g_vm;
+
} // End of namespace Frotz
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index d4a6d8c..6fee562 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -24,13 +24,177 @@
#define GARGOYLE_FROTZ_FROTZ_TYPES
#include "gargoyle/glk_types.h"
+#include "common/algorithm.h"
namespace Gargoyle {
namespace Frotz {
+#define MAX_UNDO_SLOTS 500
+#define STACK_SIZE 20
+
+/* There are four error reporting modes: never report errors;
+ * report only the first time a given error type occurs;
+ * report every time an error occurs;
+ * or treat all errors as fatal errors, killing the interpreter.
+ * I strongly recommend "report once" as the default. But you can compile in a
+ * different default by changing the definition of ERR_DEFAULT_REPORT_MODE.
+ */
+enum ErrorReport {
+ ERR_REPORT_NEVER = 0,
+ ERR_REPORT_ONCE = 1,
+ ERR_REPORT_ALWAYS = 2,
+ ERR_REPORT_FATAL = 3,
+
+ ERR_DEFAULT_REPORT_MODE = ERR_REPORT_NEVER
+};
+
+/**
+ * Character codes
+ */
+enum ZCode {
+ ZC_TIME_OUT = 0x00,
+ ZC_NEW_STYLE = 0x01,
+ ZC_NEW_FONT = 0x02,
+ ZC_BACKSPACE = 0x08,
+ ZC_INDENT = 0x09,
+ ZC_GAP = 0x0b,
+ ZC_RETURN = 0x0d,
+ ZC_HKEY_MIN = 0x0e,
+ ZC_HKEY_RECORD = 0x0e,
+ ZC_HKEY_PLAYBACK = 0x0f,
+ ZC_HKEY_SEED = 0x10,
+ ZC_HKEY_UNDO = 0x11,
+ ZC_HKEY_RESTART = 0x12,
+ ZC_HKEY_QUIT = 0x13,
+ ZC_HKEY_DEBUG = 0x14,
+ ZC_HKEY_HELP = 0x15,
+ ZC_HKEY_MAX = 0x15,
+ ZC_ESCAPE = 0x1b,
+ ZC_ASCII_MIN = 0x20,
+ ZC_ASCII_MAX = 0x7e,
+ ZC_BAD = 0x7f,
+ ZC_ARROW_MIN = 0x81,
+ ZC_ARROW_UP = 0x81,
+ ZC_ARROW_DOWN = 0x82,
+ ZC_ARROW_LEFT = 0x83,
+ ZC_ARROW_RIGHT = 0x84,
+ ZC_ARROW_MAX = 0x84,
+ ZC_FKEY_MIN = 0x85,
+ ZC_FKEY_MAX = 0x90,
+ ZC_NUMPAD_MIN = 0x91,
+ ZC_NUMPAD_MAX = 0x9a,
+ ZC_SINGLE_CLICK = 0x9b,
+ ZC_DOUBLE_CLICK = 0x9c,
+ ZC_MENU_CLICK = 0x9d,
+ ZC_LATIN1_MIN = 0xa0,
+ ZC_LATIN1_MAX = 0xff
+};
+
+enum Story {
+ STORY_BEYOND_ZORK,
+ STORY_SHERLOCK,
+ STORY_ZORK_ZERO,
+ STORY_SHOGUN,
+ STORY_ARTHUR,
+ STORY_JOURNEY,
+ STORY_LURKING_HORROR,
+ STORY_UNKNOWN
+};
+
typedef byte zbyte;
+typedef char zchar;
typedef uint16 zword;
+/**
+ * User options
+ */
+struct UserOptions {
+ int _attribute_assignment;
+ int _attribute_testing;
+ int _context_lines;
+ int _object_locating;
+ int _object_movement;
+ int _left_margin;
+ int _right_margin;
+ bool _ignore_errors;
+ bool _piracy;
+ int _undo_slots;
+ int _expand_abbreviations;
+ int _script_cols;
+ bool _save_quetzal;
+ int _err_report_mode;
+ bool _sound;
+
+ UserOptions() : _attribute_assignment(0), _attribute_testing(0),
+ _context_lines(0), _object_locating(0), _object_movement(0),
+ _left_margin(0), _right_margin(0), _ignore_errors(false), _piracy(false),
+ _undo_slots(MAX_UNDO_SLOTS), _expand_abbreviations(0), _script_cols(80),
+ _save_quetzal(true),
+ _err_report_mode(ERR_DEFAULT_REPORT_MODE), _sound(true) {
+ }
+};
+
+/**
+ * Story file header data
+ */
+struct Header {
+ zbyte _version;
+ zbyte _config;
+ zword _release;
+ zword _resident_size;
+ zword _start_pc;
+ zword _dictionary;
+ zword _objects;
+ zword _globals;
+ zword _dynamic_size;
+ zword _flags;
+ zbyte _serial[6];
+ zword _abbreviations;
+ zword _file_size;
+ zword _checksum;
+ zbyte _interpreter_number;
+ zbyte _interpreter_version;
+ zbyte _screen_rows;
+ zbyte _screen_cols;
+ zword _screen_width;
+ zword _screen_height;
+ zbyte _font_height = 1;
+ zbyte _font_width = 1;
+ zword _functions_offset;
+ zword _strings_offset;
+ zbyte _default_background;
+ zbyte _default_foreground;
+ zword _terminating_keys;
+ zword _line_width;
+ zbyte _standard_high;
+ zbyte _standard_low;
+ zword _alphabet;
+ zword _extension_table;
+ zbyte _user_name[8];
+
+ zword _hx_table_size;
+ zword _hx_mouse_x;
+ zword _hx_mouse_y;
+ zword _hx_unicode_table;
+ zword _hx_flags;
+ zword _hx_fore_colour;
+ zword _hx_back_colour;
+
+ Header() : _version(0), _config(0), _release(0), _resident_size(0), _start_pc(0),
+ _dictionary(0), _objects(0), _globals(0), _dynamic_size(0), _flags(0),
+ _abbreviations(0), _file_size(0), _checksum(0), _interpreter_number(0),
+ _interpreter_version(0), _screen_rows(0), _screen_cols(0), _screen_width(0),
+ _screen_height(0), _font_height(1), _font_width(1), _functions_offset(0),
+ _strings_offset(0), _default_background(0), _default_foreground(0),
+ _terminating_keys(0), _line_width(0), _standard_high(1), _standard_low(1),
+ _alphabet(0), _extension_table(0),
+ _hx_table_size(0), _hx_mouse_x(0), _hx_mouse_y(0), _hx_unicode_table(0),
+ _hx_flags(0), _hx_fore_colour(0), _hx_back_colour(0) {
+ Common::fill(&_serial[0], &_serial[6], '\0');
+ Common::fill(&_user_name[0], &_user_name[8], '\0');
+ }
+};
+
} // End of namespace Frotz
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 8e16bfe..85bd055 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -20,6 +20,7 @@ MODULE_OBJS := \
window_pair.o \
window_text_buffer.o \
window_text_grid.o \
+ frotz/buffer.o \
frotz/detection.o \
frotz/detection_tables.o \
frotz/frotz.o \
Commit: 7d20a3552bd26d10e220261c97a8f65f2d3add54
https://github.com/scummvm/scummvm/commit/7d20a3552bd26d10e220261c97a8f65f2d3add54
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added error handling
Changed paths:
A engines/gargoyle/frotz/err.cpp
A engines/gargoyle/frotz/err.h
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/frotz/err.cpp b/engines/gargoyle/frotz/err.cpp
new file mode 100644
index 0000000..b25b75c
--- /dev/null
+++ b/engines/gargoyle/frotz/err.cpp
@@ -0,0 +1,131 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/err.h"
+#include "gargoyle/frotz/frotz.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+const char *const Errors::ERR_MESSAGES[ERR_NUM_ERRORS] = {
+ "Text buffer overflow",
+ "Store out of dynamic memory",
+ "Division by zero",
+ "Illegal object",
+ "Illegal attribute",
+ "No such property",
+ "Stack overflow",
+ "Call to illegal address",
+ "Call to non-routine",
+ "Stack underflow",
+ "Illegal opcode",
+ "Bad stack frame",
+ "Jump to illegal address",
+ "Can't save while in interrupt",
+ "Nesting stream #3 too deep",
+ "Illegal window",
+ "Illegal window property",
+ "Print at illegal address",
+ "Illegal dictionary word length",
+ "@jin called with object 0",
+ "@get_child called with object 0",
+ "@get_parent called with object 0",
+ "@get_sibling called with object 0",
+ "@get_prop_addr called with object 0",
+ "@get_prop called with object 0",
+ "@put_prop called with object 0",
+ "@clear_attr called with object 0",
+ "@set_attr called with object 0",
+ "@test_attr called with object 0",
+ "@move_object called moving object 0",
+ "@move_object called moving into object 0",
+ "@remove_object called with object 0",
+ "@get_next_prop called with object 0"
+};
+
+Errors::Errors() {
+ Common::fill(&_count[0], &_count[ERR_NUM_ERRORS], 0);
+}
+
+void Errors::runtimeError(int errNum) {
+ int wasfirst;
+
+ if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
+ return;
+
+ if (g_vm->_options._err_report_mode == ERR_REPORT_FATAL
+ || (!g_vm->_options._ignore_errors && errNum <= ERR_MAX_FATAL)) {
+ g_vm->_buffer.flush();
+ error(ERR_MESSAGES[errNum - 1]);
+ return;
+ }
+
+ wasfirst = (_count[errNum - 1] == 0);
+ _count[errNum - 1]++;
+
+ if ((g_vm->_options._err_report_mode == ERR_REPORT_ALWAYS)
+ || (g_vm->_options._err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
+ long pc = g_vm->getPC();
+ printString("Warning: ");
+ printString(ERR_MESSAGES[errNum - 1]);
+ printString(" (PC = ");
+ printLong(pc, 16);
+ printChar(')');
+
+ if (g_vm->_options._err_report_mode == ERR_REPORT_ONCE) {
+ printString(" (will ignore further occurrences)");
+ } else {
+ printString(" (occurence ");
+ printLong(_count[errNum - 1], 10);
+ printChar(')');
+ }
+
+ newLine();
+ }
+}
+
+void Errors::printLong(uint value, int base) {
+ unsigned long i;
+ char c;
+
+ for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base)
+ if (value >= i || i == 1) {
+ c = (value / i) % base;
+ printChar(c + (c <= 9 ? '0' : 'a' - 10));
+ }
+}
+
+void Errors::printChar(const char c) {
+ // TODO
+}
+
+void Errors::printString(const char *str) {
+ // TODO
+}
+
+void Errors::newLine() {
+ // TODO
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/err.h b/engines/gargoyle/frotz/err.h
new file mode 100644
index 0000000..f61d726
--- /dev/null
+++ b/engines/gargoyle/frotz/err.h
@@ -0,0 +1,75 @@
+/* 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 GARGOYLE_FROTZ_ERR
+#define GARGOYLE_FROTZ_ERR
+
+#include "gargoyle/frotz/frotz_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+#define ERR_NUM_ERRORS 33
+#define ERR_MAX_FATAL 19
+
+class Errors {
+private:
+ static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
+ int _count[ERR_NUM_ERRORS];
+public:
+ /**
+ * Constructor
+ */
+ Errors();
+
+ /**
+ * An error has occurred. Ignore it, pass it to os_fatal or report
+ * it according to err_report_mode.
+ * @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
+ */
+ void runtimeError(int errNum);
+
+ /**
+ * Print an unsigned 32bit number in decimal or hex.
+ */
+ void printLong(uint value, int base);
+
+ /**
+ * Print a character
+ */
+ void printChar(const char c);
+
+ /**
+ * Print a string
+ */
+ void printString(const char *str);
+
+ /**
+ * Add a newline
+ */
+ void newLine();
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index e7c6972..2a7bcd0 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -51,5 +51,10 @@ Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
return Common::kNoError;
}
+uint Frotz::getPC() const {
+ // TODO
+ return 0;
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index 6ed226a..b0a7e1d 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -25,6 +25,8 @@
#include "gargoyle/glk.h"
#include "gargoyle/frotz/frotz_types.h"
+#include "gargoyle/frotz/buffer.h"
+#include "gargoyle/frotz/err.h"
namespace Gargoyle {
namespace Frotz {
@@ -36,6 +38,7 @@ class Frotz : public Glk {
public:
UserOptions _options;
Header _header;
+ Buffer _buffer;
// Story file name, id number and size
Common::String _storyName;
@@ -91,6 +94,11 @@ public:
* Save the game
*/
virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+
+ /**
+ * Get the current PC
+ */
+ uint getPC() const;
};
extern Frotz *g_vm;
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 85bd055..8fdf82a 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -23,6 +23,7 @@ MODULE_OBJS := \
frotz/buffer.o \
frotz/detection.o \
frotz/detection_tables.o \
+ frotz/err.o \
frotz/frotz.o \
scott/detection.o \
scott/scott.o
Commit: 4497a55a860a5ec5de47075e11cf69deffd2031d
https://github.com/scummvm/scummvm/commit/4497a55a860a5ec5de47075e11cf69deffd2031d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Beginnings of Mem class
Changed paths:
A engines/gargoyle/frotz/mem.cpp
A engines/gargoyle/frotz/mem.h
engines/gargoyle/detection.cpp
engines/gargoyle/frotz/detection_tables.cpp
engines/gargoyle/frotz/detection_tables.h
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 2836e04..4238e64 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -69,7 +69,7 @@ const Common::String &GargoyleEngine::getGameMD5() const {
} // End of namespace Gargoyle
#include "gargoyle/frotz/detection_tables.h"
-#define ZCODE(ID, NAME) { ID, Gargoyle::Frotz::NAME }
+#define ZCODE(ID, NAME) { ID, Gargoyle::Frotz::NAME##_DESC }
static const PlainGameDescriptor gargoyleGames[] = {
{"zcode", "Zcode Games" },
diff --git a/engines/gargoyle/frotz/detection_tables.cpp b/engines/gargoyle/frotz/detection_tables.cpp
index f8d3f42..af856ed 100644
--- a/engines/gargoyle/frotz/detection_tables.cpp
+++ b/engines/gargoyle/frotz/detection_tables.cpp
@@ -25,49 +25,49 @@
namespace Gargoyle {
namespace Frotz {
-const char *const AMFV = "A Mind Forever Voyaging";
-const char *const ARTHUR = "Arthur: The Quest for Excalibur";
-const char *const BALLYHOO = "Ballyhoo";
-const char *const BEYONDZORK = "Beyond Zork";
-const char *const BORDERZONE = "Border Zone";
-const char *const BUREAUCRACY = "Bureaucracy";
-const char *const CUTTHROATS = "Cutthroats";
-const char *const DEADLINE = "Deadline";
-const char *const ENCHANTER = "Enchanter";
-const char *const HHGTTG = "The Hitchhiker's Guide to the Galaxy";
-const char *const HIJINX = "Hollywood Hijinx";
-const char *const INFIDEL = "Infidel";
-const char *const JOURNEY = "Journey";
-const char *const LGOP = "Leather Goddesses of Phobos";
-const char *const LGOP2 = "Leather Goddesses of Phobos 2";
-const char *const LURKING = "The Lurking Horror";
-const char *const MINIZORK1 = "Mini Zork I: The Great Underground Empire";
-const char *const MOONMIST = "Moonmist";
-const char *const NORDBERT = "Nord and Bert Couldn't Make Head or Tail of It";
-const char *const PLANETFALL = "Planetfall";
-const char *const PLUNDERED = "Plundered Hearts";
-const char *const SAMPLER1 = "Infocom Sampler 1";
-const char *const SAMPLER2 = "Infocom Sampler 2";
-const char *const SEASTALKER = "Seastalker";
-const char *const SHERLOCKRIDDLE = "Sherlock: The Riddle of the Crown Jewels";
-const char *const SHOGUN = "James Clavell's Shogun";
-const char *const SORCERER = "Sorcerer";
-const char *const SPELLBREAKER = "Spellbreaker";
-const char *const STARCROSS = "Starcross";
-const char *const STATIONFALL = "Stationfall";
-const char *const SUSPECT = "Suspect";
-const char *const SUSPENDED = "Suspended";
-const char *const TRINITY = "Trinity";
-const char *const WISHBRINGER = "Wishbringer";
-const char *const WITNESS = "The Witness";
-const char *const ZORK0 = "Zork Zero: The Revenge of Megaboz";
-const char *const ZORK1 = "Zork I: The Great Underground Empire";
-const char *const ZORK2 = "Zork II: The Wizard of Frobozz";
-const char *const ZORK3 = "Zork III: The Dungeon Master";
-const char *const ZTUU = "Zork: The Undiscovered Underground";
+const char *const AMFV_DESC = "A Mind Forever Voyaging";
+const char *const ARTHUR_DESC = "Arthur: The Quest for Excalibur";
+const char *const BALLYHOO_DESC = "Ballyhoo";
+const char *const BEYONDZORK_DESC = "Beyond Zork";
+const char *const BORDERZONE_DESC = "Border Zone";
+const char *const BUREAUCRACY_DESC = "Bureaucracy";
+const char *const CUTTHROATS_DESC = "Cutthroats";
+const char *const DEADLINE_DESC = "Deadline";
+const char *const ENCHANTER_DESC = "Enchanter";
+const char *const HHGTTG_DESC = "The Hitchhiker's Guide to the Galaxy";
+const char *const HIJINX_DESC = "Hollywood Hijinx";
+const char *const INFIDEL_DESC = "Infidel";
+const char *const JOURNEY_DESC = "Journey";
+const char *const LGOP_DESC = "Leather Goddesses of Phobos";
+const char *const LGOP2_DESC = "Leather Goddesses of Phobos 2";
+const char *const LURKING_DESC = "The Lurking Horror";
+const char *const MINIZORK1_DESC = "Mini Zork I: The Great Underground Empire";
+const char *const MOONMIST_DESC = "Moonmist";
+const char *const NORDBERT_DESC = "Nord and Bert Couldn't Make Head or Tail of It";
+const char *const PLANETFALL_DESC = "Planetfall";
+const char *const PLUNDERED_DESC = "Plundered Hearts";
+const char *const SAMPLER1_DESC = "Infocom Sampler 1";
+const char *const SAMPLER2_DESC = "Infocom Sampler 2";
+const char *const SEASTALKER_DESC = "Seastalker";
+const char *const SHERLOCKRIDDLE_DESC = "Sherlock: The Riddle of the Crown Jewels";
+const char *const SHOGUN_DESC = "James Clavell's Shogun";
+const char *const SORCERER_DESC = "Sorcerer";
+const char *const SPELLBREAKER_DESC = "Spellbreaker";
+const char *const STARCROSS_DESC = "Starcross";
+const char *const STATIONFALL_DESC = "Stationfall";
+const char *const SUSPECT_DESC = "Suspect";
+const char *const SUSPENDED_DESC = "Suspended";
+const char *const TRINITY_DESC = "Trinity";
+const char *const WISHBRINGER_DESC = "Wishbringer";
+const char *const WITNESS_DESC = "The Witness";
+const char *const ZORK0_DESC = "Zork Zero: The Revenge of Megaboz";
+const char *const ZORK1_DESC = "Zork I: The Great Underground Empire";
+const char *const ZORK2_DESC = "Zork II: The Wizard of Frobozz";
+const char *const ZORK3_DESC = "Zork III: The Dungeon Master";
+const char *const ZTUU_DESC = "Zork: The Undiscovered Underground";
#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
-#define ENTRY0(ID, DESC, VERSION, MD5, FILESIZE) { ID, DESC, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
+#define ENTRY0(ID, DESCRIPTION, VERSION, MD5, FILESIZE) { ID, DESCRIPTION##_DESC, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
const FrotzGameDescription FROTZ_GAMES[] = {
diff --git a/engines/gargoyle/frotz/detection_tables.h b/engines/gargoyle/frotz/detection_tables.h
index 1a9e4ee..48e0eb0 100644
--- a/engines/gargoyle/frotz/detection_tables.h
+++ b/engines/gargoyle/frotz/detection_tables.h
@@ -40,46 +40,46 @@ struct FrotzGameDescription {
};
extern const FrotzGameDescription FROTZ_GAMES[];
-extern const char *const AMFV;
-extern const char *const ARTHUR;
-extern const char *const BALLYHOO;
-extern const char *const BEYONDZORK;
-extern const char *const BORDERZONE;
-extern const char *const BUREAUCRACY;
-extern const char *const CUTTHROATS;
-extern const char *const DEADLINE;
-extern const char *const ENCHANTER;
-extern const char *const HHGTTG;
-extern const char *const HIJINX;
-extern const char *const INFIDEL;
-extern const char *const JOURNEY;
-extern const char *const LGOP;
-extern const char *const LGOP2;
-extern const char *const LURKING;
-extern const char *const MINIZORK1;
-extern const char *const MOONMIST;
-extern const char *const NORDBERT;
-extern const char *const PLANETFALL;
-extern const char *const PLUNDERED;
-extern const char *const SAMPLER1;
-extern const char *const SAMPLER2;
-extern const char *const SEASTALKER;
-extern const char *const SHERLOCKRIDDLE;
-extern const char *const SHOGUN;
-extern const char *const SORCERER;
-extern const char *const SPELLBREAKER;
-extern const char *const STARCROSS;
-extern const char *const STATIONFALL;
-extern const char *const SUSPECT;
-extern const char *const SUSPENDED;
-extern const char *const TRINITY;
-extern const char *const WISHBRINGER;
-extern const char *const WITNESS;
-extern const char *const ZORK0;
-extern const char *const ZORK1;
-extern const char *const ZORK2;
-extern const char *const ZORK3;
-extern const char *const ZTUU;
+extern const char *const AMFV_DESC;
+extern const char *const ARTHUR_DESC;
+extern const char *const BALLYHOO_DESC;
+extern const char *const BEYONDZORK_DESC;
+extern const char *const BORDERZONE_DESC;
+extern const char *const BUREAUCRACY_DESC;
+extern const char *const CUTTHROATS_DESC;
+extern const char *const DEADLINE_DESC;
+extern const char *const ENCHANTER_DESC;
+extern const char *const HHGTTG_DESC;
+extern const char *const HIJINX_DESC;
+extern const char *const INFIDEL_DESC;
+extern const char *const JOURNEY_DESC;
+extern const char *const LGOP_DESC;
+extern const char *const LGOP2_DESC;
+extern const char *const LURKING_DESC;
+extern const char *const MINIZORK1_DESC;
+extern const char *const MOONMIST_DESC;
+extern const char *const NORDBERT_DESC;
+extern const char *const PLANETFALL_DESC;
+extern const char *const PLUNDERED_DESC;
+extern const char *const SAMPLER1_DESC;
+extern const char *const SAMPLER2_DESC;
+extern const char *const SEASTALKER_DESC;
+extern const char *const SHERLOCKRIDDLE_DESC;
+extern const char *const SHOGUN_DESC;
+extern const char *const SORCERER_DESC;
+extern const char *const SPELLBREAKER_DESC;
+extern const char *const STARCROSS_DESC;
+extern const char *const STATIONFALL_DESC;
+extern const char *const SUSPECT_DESC;
+extern const char *const SUSPENDED_DESC;
+extern const char *const TRINITY_DESC;
+extern const char *const WISHBRINGER_DESC;
+extern const char *const WITNESS_DESC;
+extern const char *const ZORK0_DESC;
+extern const char *const ZORK1_DESC;
+extern const char *const ZORK2_DESC;
+extern const char *const ZORK3_DESC;
+extern const char *const ZTUU_DESC;
} // End of namespace Frotz
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index 2a7bcd0..77c3303 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -29,7 +29,7 @@ namespace Frotz {
Frotz *g_vm;
Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
- _storyId(STORY_UNKNOWN), _storySize(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
+ _storyId(UNKNOWN), _storySize(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
_ostream_screen(true), _ostream_script(false), _ostream_memory(false),
_ostream_record(false), _istream_replay(false), _message(false),
_cwin(0), _mwin(0), _mouse_x(0), _mouse_y(0), _menu_selected(0),
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index b0a7e1d..e1f3d9f 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -27,6 +27,7 @@
#include "gargoyle/frotz/frotz_types.h"
#include "gargoyle/frotz/buffer.h"
#include "gargoyle/frotz/err.h"
+#include "gargoyle/frotz/mem.h"
namespace Gargoyle {
namespace Frotz {
@@ -39,6 +40,7 @@ public:
UserOptions _options;
Header _header;
Buffer _buffer;
+ Mem _mem;
// Story file name, id number and size
Common::String _storyName;
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 6fee562..505d656 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -91,18 +91,18 @@ enum ZCode {
};
enum Story {
- STORY_BEYOND_ZORK,
- STORY_SHERLOCK,
- STORY_ZORK_ZERO,
- STORY_SHOGUN,
- STORY_ARTHUR,
- STORY_JOURNEY,
- STORY_LURKING_HORROR,
- STORY_UNKNOWN
+ BEYOND_ZORK,
+ SHERLOCK,
+ ZORK_ZERO,
+ SHOGUN,
+ ARTHUR,
+ JOURNEY,
+ LURKING_HORROR,
+ UNKNOWN
};
typedef byte zbyte;
-typedef char zchar;
+typedef uint zchar;
typedef uint16 zword;
/**
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
new file mode 100644
index 0000000..4bd2324
--- /dev/null
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -0,0 +1,59 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/mem.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+const Mem::StoryEntry Mem::RECORDS[25] = {
+ { SHERLOCK, 21, "871214" },
+ { SHERLOCK, 26, "880127" },
+ { BEYOND_ZORK, 47, "870915" },
+ { BEYOND_ZORK, 49, "870917" },
+ { BEYOND_ZORK, 51, "870923" },
+ { BEYOND_ZORK, 57, "871221" },
+ { ZORK_ZERO, 296, "881019" },
+ { ZORK_ZERO, 366, "890323" },
+ { ZORK_ZERO, 383, "890602" },
+ { ZORK_ZERO, 393, "890714" },
+ { SHOGUN, 292, "890314" },
+ { SHOGUN, 295, "890321" },
+ { SHOGUN, 311, "890510" },
+ { SHOGUN, 322, "890706" },
+ { ARTHUR, 54, "890606" },
+ { ARTHUR, 63, "890622" },
+ { ARTHUR, 74, "890714" },
+ { JOURNEY, 26, "890316" },
+ { JOURNEY, 30, "890322" },
+ { JOURNEY, 77, "890616" },
+ { JOURNEY, 83, "890706" },
+ { LURKING_HORROR, 203, "870506" },
+ { LURKING_HORROR, 219, "870912" },
+ { LURKING_HORROR, 221, "870918" },
+ { UNKNOWN, 0, "------" }
+};
+
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
new file mode 100644
index 0000000..4abe464
--- /dev/null
+++ b/engines/gargoyle/frotz/mem.h
@@ -0,0 +1,43 @@
+/* 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 GARGOYLE_FROTZ_MEM
+#define GARGOYLE_FROTZ_MEM
+
+#include "gargoyle/frotz/frotz_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+class Mem {
+ struct StoryEntry {
+ Story _storyId;
+ zword _release;
+ char _serial[7];
+ };
+ static const StoryEntry RECORDS[25];
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 8fdf82a..f40a79a 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
frotz/detection_tables.o \
frotz/err.o \
frotz/frotz.o \
+ frotz/mem.o \
scott/detection.o \
scott/scott.o
Commit: b8fcb62dd242db6d50a252ec7cfabe97fe5c9b6c
https://github.com/scummvm/scummvm/commit/b8fcb62dd242db6d50a252ec7cfabe97fe5c9b6c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added Blorb container file handling
Changed paths:
A engines/gargoyle/blorb.cpp
A engines/gargoyle/blorb.h
engines/gargoyle/glk.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/blorb.cpp b/engines/gargoyle/blorb.cpp
new file mode 100644
index 0000000..064f9c4
--- /dev/null
+++ b/engines/gargoyle/blorb.cpp
@@ -0,0 +1,543 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/blorb.h"
+
+namespace Gargoyle {
+
+#define giblorb_Inited_Magic 0xB7012BEDU
+
+/**
+ * Describes one chunk of the Blorb file.
+ */
+struct giblorb_chunkdesc_struct {
+ glui32 type;
+ glui32 len;
+ glui32 startpos; ///< start of chunk header
+ glui32 datpos; ///< start of data (either startpos or startpos+8)
+
+ void *ptr; ///< pointer to malloc'd data, if loaded
+ int auxdatnum; ///< entry in the auxsound/auxpict array; -1 if none. This only applies to chunks that represent resources;
+};
+typedef giblorb_chunkdesc_struct giblorb_chunkdesc_t;
+
+/**
+ * Describes one resource in the Blorb file.
+ */
+struct giblorb_resdesc_struct {
+ glui32 usage;
+ glui32 resnum;
+ glui32 chunknum;
+};
+
+/**
+ * Holds the complete description of an open Blorb file.
+ */
+struct giblorb_map_struct {
+ glui32 inited; ///< holds giblorb_Inited_Magic if the map structure is valid
+ Common::SeekableReadStream *file;
+
+ uint numchunks;
+ giblorb_chunkdesc_t *chunks; ///< list of chunk descriptors
+
+ int numresources;
+ giblorb_resdesc_t *resources; ///< list of resource descriptors
+ giblorb_resdesc_t **ressorted; ///< list of pointers to descriptors in map->resources -- sorted by usage and resource number.
+};
+
+/*--------------------------------------------------------------------------*/
+
+giblorb_err_t Blorb::giblorb_initialize() {
+ _file = nullptr;
+ _map = nullptr;
+ return giblorb_err_None;
+}
+
+giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap) {
+ giblorb_err_t err;
+ giblorb_map_t *map;
+ glui32 readlen;
+ glui32 nextpos, totallength;
+ giblorb_chunkdesc_t *chunks;
+ int chunks_size, numchunks;
+ char buffer[16];
+
+ *newmap = nullptr;
+
+ if (!_libInited) {
+ err = giblorb_initialize();
+ if (err)
+ return err;
+ _libInited = true;
+ }
+
+ /* First, chew through the file and index the chunks. */
+ file->seek(0);
+
+ readlen = file->read(buffer, 12);
+ if (readlen != 12)
+ return giblorb_err_Read;
+
+ if (READ_BE_INT32(buffer + 0) != giblorb_ID_FORM)
+ return giblorb_err_Format;
+ if (READ_BE_INT32(buffer + 8) != giblorb_ID_IFRS)
+ return giblorb_err_Format;
+
+ totallength = READ_BE_INT32(buffer + 4) + 8;
+ nextpos = 12;
+
+ chunks_size = 8;
+ numchunks = 0;
+ chunks = new giblorb_chunkdesc_t[chunks_size];
+
+ while (nextpos < totallength) {
+ glui32 type, len;
+ int chunum;
+ giblorb_chunkdesc_t *chu;
+
+ file->seek(nextpos);
+
+ readlen = file->read(buffer, 8);
+ if (readlen != 8) {
+ delete[] chunks;
+ return giblorb_err_Read;
+ }
+
+ type = READ_BE_INT32(buffer + 0);
+ len = READ_BE_INT32(buffer + 4);
+
+ if (numchunks >= chunks_size) {
+ chunks_size *= 2;
+ chunks = new giblorb_chunkdesc_t[chunks_size];
+ }
+
+ chunum = numchunks;
+ chu = &(chunks[chunum]);
+ numchunks++;
+
+ chu->type = type;
+ chu->startpos = nextpos;
+ if (type == giblorb_ID_FORM) {
+ chu->datpos = nextpos;
+ chu->len = len + 8;
+ } else {
+ chu->datpos = nextpos + 8;
+ chu->len = len;
+ }
+ chu->ptr = nullptr;
+ chu->auxdatnum = -1;
+
+ nextpos = nextpos + len + 8;
+ if (nextpos & 1)
+ nextpos++;
+
+ if (nextpos > totallength) {
+ delete[] chunks;
+ return giblorb_err_Format;
+ }
+ }
+
+ // The basic IFF structure seems to be ok, and we have a list of chunks.
+ // Now we allocate the map structure itself.
+ map = new giblorb_map_t();
+ if (!map) {
+ delete[] chunks;
+ return giblorb_err_Alloc;
+ }
+
+ map->inited = giblorb_Inited_Magic;
+ map->file = file;
+ map->chunks = chunks;
+ map->numchunks = numchunks;
+ map->resources = nullptr;
+ map->ressorted = nullptr;
+ map->numresources = 0;
+
+ // Now we do everything else involved in loading the Blorb file,
+ // such as building resource lists.
+ err = giblorb_initialize_map(map);
+ if (err) {
+ giblorb_destroy_map(map);
+ return err;
+ }
+
+ *newmap = map;
+ return giblorb_err_None;
+}
+
+
+giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
+ // It is important that the map structure be kept valid during this function.
+ // If this returns an error, giblorb_destroy_map() will be called.
+ uint ix, jx;
+ giblorb_result_t chunkres;
+ giblorb_err_t err;
+ char *ptr;
+ glui32 len;
+ glui32 numres;
+ int gotindex = false;
+
+ for (ix = 0; ix<map->numchunks; ix++) {
+ giblorb_chunkdesc_t *chu = &map->chunks[ix];
+
+ switch (chu->type) {
+ case giblorb_ID_RIdx:
+ // Resource index chunk: build the resource list and sort it.
+
+ if (gotindex)
+ return giblorb_err_Format; // duplicate index chunk
+ err = giblorb_load_chunk_by_number(map, giblorb_method_Memory, &chunkres, ix);
+ if (err)
+ return err;
+
+ ptr = (char *)chunkres.data.ptr;
+ len = chunkres.length;
+ numres = READ_BE_INT32(ptr + 0);
+
+ if (numres) {
+ uint ix2;
+ giblorb_resdesc_t *resources;
+ giblorb_resdesc_t **ressorted;
+
+ if (len != numres * 12 + 4)
+ return giblorb_err_Format; // bad length field
+
+ resources = new giblorb_resdesc_t[numres];
+ ressorted = new giblorb_resdesc_t *[numres];
+ if (!ressorted || !resources) {
+ delete[] resources;
+ delete[] ressorted;
+ return giblorb_err_Alloc;
+ }
+
+ ix2 = 0;
+ for (jx = 0; jx < numres; jx++) {
+ giblorb_resdesc_t *res = &(resources[jx]);
+ glui32 respos;
+
+ res->usage = READ_BE_INT32(ptr + jx * 12 + 4);
+ res->resnum = READ_BE_INT32(ptr + jx * 12 + 8);
+ respos = READ_BE_INT32(ptr + jx * 12 + 12);
+
+ while (ix2 < map->numchunks
+ && map->chunks[ix2].startpos < respos)
+ ix2++;
+
+ if (ix2 >= map->numchunks
+ || map->chunks[ix2].startpos != respos) {
+ delete[] resources;
+ delete[] ressorted;
+ return giblorb_err_Format; // start pos does not match a real chunk
+ }
+
+ res->chunknum = ix2;
+
+ ressorted[jx] = res;
+ }
+
+ // Sort a resource list (actually a list of pointers to structures in map->resources.)
+ // This makes it easy to find resources by usage and resource number.
+ giblorb_qsort(ressorted, numres);
+
+ map->numresources = numres;
+ map->resources = resources;
+ map->ressorted = ressorted;
+ }
+
+ giblorb_unload_chunk(map, ix);
+ gotindex = true;
+ break;
+ }
+ }
+
+ return giblorb_err_None;
+}
+
+void Blorb::giblorb_qsort(giblorb_resdesc_t **list, size_t len) {
+ int ix, jx, res;
+ giblorb_resdesc_t *tmpptr, *pivot;
+
+ if (len < 6) {
+ // The list is short enough for a bubble-sort.
+ for (jx = len - 1; jx>0; jx--) {
+ for (ix = 0; ix<jx; ix++) {
+ res = sortsplot(list[ix], list[ix + 1]);
+ if (res > 0) {
+ tmpptr = list[ix];
+ list[ix] = list[ix + 1];
+ list[ix + 1] = tmpptr;
+ }
+ }
+ }
+ } else {
+ // Split the list.
+ pivot = list[len / 2];
+ ix = 0;
+ jx = len;
+ for (;;) {
+ while (ix < jx - 1 && sortsplot(list[ix], pivot) < 0)
+ ix++;
+ while (ix < jx - 1 && sortsplot(list[jx - 1], pivot) > 0)
+ jx--;
+ if (ix >= jx - 1)
+ break;
+ tmpptr = list[ix];
+ list[ix] = list[jx - 1];
+ list[jx - 1] = tmpptr;
+ }
+ ix++;
+ // Sort the halves.
+ giblorb_qsort(list + 0, ix);
+ giblorb_qsort(list + ix, len - ix);
+ }
+}
+
+giblorb_resdesc_t *Blorb::giblorb_bsearch(giblorb_resdesc_t *sample,
+ giblorb_resdesc_t **list, int len) {
+ int top, bot, val, res;
+
+ bot = 0;
+ top = len;
+
+ while (bot < top) {
+ val = (top + bot) / 2;
+ res = sortsplot(list[val], sample);
+ if (res == 0)
+ return list[val];
+ if (res < 0) {
+ bot = val + 1;
+ } else {
+ top = val;
+ }
+ }
+
+ return nullptr;
+}
+
+int Blorb::sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2) {
+ if (v1->usage < v2->usage)
+ return -1;
+ if (v1->usage > v2->usage)
+ return 1;
+ if (v1->resnum < v2->resnum)
+ return -1;
+ if (v1->resnum > v2->resnum)
+ return 1;
+ return 0;
+}
+
+giblorb_err_t Blorb::giblorb_destroy_map(giblorb_map_t *map) {
+ if (!map || !map->chunks || map->inited != giblorb_Inited_Magic)
+ return giblorb_err_NotAMap;
+
+ for (uint ix = 0; ix<map->numchunks; ix++) {
+ giblorb_chunkdesc_t *chu = &(map->chunks[ix]);
+ if (chu->ptr) {
+ delete chu->ptr;
+ chu->ptr = nullptr;
+ }
+ }
+
+ if (map->chunks) {
+ delete[] map->chunks;
+ map->chunks = nullptr;
+ }
+
+ map->numchunks = 0;
+
+ if (map->resources) {
+ delete[] map->resources;
+ map->resources = nullptr;
+ }
+
+ if (map->ressorted) {
+ delete[] map->ressorted;
+ map->ressorted = nullptr;
+ }
+
+ map->numresources = 0;
+ map->file = nullptr;
+ map->inited = 0;
+
+ delete map;
+
+ return giblorb_err_None;
+}
+
+giblorb_err_t Blorb::giblorb_load_chunk_by_type(giblorb_map_t *map,
+ glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
+ uint ix;
+
+ for (ix = 0; ix < map->numchunks; ix++) {
+ if (map->chunks[ix].type == chunktype) {
+ if (count == 0)
+ break;
+ count--;
+ }
+ }
+
+ if (ix >= map->numchunks) {
+ return giblorb_err_NotFound;
+ }
+
+ return giblorb_load_chunk_by_number(map, method, res, ix);
+}
+
+giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
+ glui32 method, giblorb_result_t *res, glui32 chunknum) {
+ giblorb_chunkdesc_t *chu;
+
+ if (chunknum < 0 || chunknum >= map->numchunks)
+ return giblorb_err_NotFound;
+
+ chu = &(map->chunks[chunknum]);
+
+ switch (method) {
+ case giblorb_method_DontLoad:
+ // do nothing
+ break;
+
+ case giblorb_method_FilePos:
+ res->data.startpos = chu->datpos;
+ break;
+
+ case giblorb_method_Memory:
+ if (!chu->ptr) {
+ glui32 readlen;
+ byte *dat = new byte[chu->len];
+
+ if (!dat)
+ return giblorb_err_Alloc;
+
+ map->file->seek(chu->datpos);
+
+ readlen = map->file->read(dat, chu->len);
+ if (readlen != chu->len)
+ return giblorb_err_Read;
+
+ chu->ptr = dat;
+ }
+
+ res->data.ptr = chu->ptr;
+ break;
+ }
+
+ res->chunknum = chunknum;
+ res->length = chu->len;
+ res->chunktype = chu->type;
+
+ return giblorb_err_None;
+}
+
+giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
+ giblorb_chunkdesc_t *chu;
+
+ if (chunknum < 0 || chunknum >= map->numchunks)
+ return giblorb_err_NotFound;
+
+ chu = &(map->chunks[chunknum]);
+
+ if (chu->ptr) {
+ delete chu->ptr;
+ chu->ptr = nullptr;
+ }
+
+ return giblorb_err_None;
+}
+
+giblorb_err_t Blorb::giblorb_load_resource(giblorb_map_t *map, glui32 method,
+ giblorb_result_t *res, glui32 usage, glui32 resnum) {
+ giblorb_resdesc_t sample;
+ giblorb_resdesc_t *found;
+
+ sample.usage = usage;
+ sample.resnum = resnum;
+
+ found = giblorb_bsearch(&sample, map->ressorted, map->numresources);
+
+ if (!found)
+ return giblorb_err_NotFound;
+
+ return giblorb_load_chunk_by_number(map, method, res, found->chunknum);
+}
+
+giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
+ glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
+ int ix;
+ int count;
+ glui32 val;
+ glui32 minval, maxval;
+
+ count = 0;
+ minval = 0;
+ maxval = 0;
+
+ for (ix = 0; ix<map->numresources; ix++) {
+ if (map->resources[ix].usage == usage) {
+ val = map->resources[ix].resnum;
+ if (count == 0) {
+ count++;
+ minval = val;
+ maxval = val;
+ }
+ else {
+ count++;
+ if (val < minval)
+ minval = val;
+ if (val > maxval)
+ maxval = val;
+ }
+ }
+ }
+
+ if (num)
+ *num = count;
+ if (min)
+ *min = minval;
+ if (max)
+ *max = maxval;
+
+ return giblorb_err_None;
+}
+
+giblorb_err_t Blorb::giblorb_set_resource_map(Common::SeekableReadStream *file) {
+ giblorb_err_t err;
+
+ err = giblorb_create_map(file, &_map);
+ if (err) {
+ _map = nullptr;
+ return err;
+ }
+
+ _file = file;
+ return giblorb_err_None;
+}
+
+giblorb_map_t *Blorb::giblorb_get_resource_map(void) {
+ return _map;
+}
+
+bool Blorb::giblorb_is_resource_map(void) const {
+ return _map != nullptr;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/blorb.h b/engines/gargoyle/blorb.h
new file mode 100644
index 0000000..9de1947
--- /dev/null
+++ b/engines/gargoyle/blorb.h
@@ -0,0 +1,146 @@
+/* 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 GARGOYLE_BLORB_H
+#define GARGOYLE_BLORB_H
+
+#include "gargoyle/glk_types.h"
+#include "gargoyle/streams.h"
+
+namespace Gargoyle {
+
+
+/**
+ * Error type
+ */
+typedef glui32 giblorb_err_t;
+
+/**
+ * Error codes
+ */
+enum giblorbError {
+ giblorb_err_None = 0,
+ giblorb_err_CompileTime = 1,
+ giblorb_err_Alloc = 2,
+ giblorb_err_Read = 3,
+ giblorb_err_NotAMap = 4,
+ giblorb_err_Format = 5,
+ giblorb_err_NotFound = 6
+};
+
+/**
+ * Methods for loading a chunk
+ */
+enum giblorbMethod {
+ giblorb_method_DontLoad = 0,
+ giblorb_method_Memory = 1,
+ giblorb_method_FilePos = 2
+};
+
+enum {
+ giblorb_ID_Snd = MKTAG('S', 'n', 'd', ' '),
+ giblorb_ID_Exec = MKTAG('E', 'x', 'e', 'c'),
+ giblorb_ID_Pict = MKTAG('P', 'i', 'c', 't'),
+ giblorb_ID_Copyright = MKTAG('(', 'c', ')', ' '),
+ giblorb_ID_AUTH = MKTAG('A', 'U', 'T', 'H'),
+ giblorb_ID_ANNO = MKTAG('A', 'N', 'N', 'O')
+};
+
+
+enum {
+ giblorb_ID_MOD = MKTAG('M', 'O', 'D', ' '),
+ giblorb_ID_FORM = MKTAG('F', 'O', 'R', 'M'),
+ giblorb_ID_IFRS = MKTAG('I', 'F', 'R', 'S'),
+ giblorb_ID_RIdx = MKTAG('R', 'I', 'd', 'x'),
+ giblorb_ID_OGG = MKTAG('O', 'G', 'G', 'V'),
+
+ // non-standard types
+ giblorb_ID_MIDI = MKTAG('M', 'I', 'D', 'I'),
+ giblorb_ID_MP3 = MKTAG('M', 'P', '3', ' '),
+ giblorb_ID_WAVE = MKTAG('W', 'A', 'V', 'E')
+};
+
+/**
+ * Holds the complete description of an open Blorb file.
+ * This type is opaque for normal interpreter use.
+ */
+typedef struct giblorb_map_struct giblorb_map_t;
+
+/* giblorb_result_t: Result when you try to load a chunk. */
+typedef struct giblorb_result_struct {
+ glui32 chunknum; // The chunk number (for use in giblorb_unload_chunk(), etc.)
+ union {
+ void *ptr; ///< A pointer to the data (if you used giblorb_method_Memory)
+ glui32 startpos; ///< The position in the file (if you used giblorb_method_FilePos)
+ } data;
+
+ glui32 length; ///< The length of the data
+ glui32 chunktype; ///< The type of the chunk.
+} giblorb_result_t;
+
+typedef struct giblorb_resdesc_struct giblorb_resdesc_t;
+
+class Blorb {
+private:
+ bool _libInited;
+ Common::SeekableReadStream *_file;
+ giblorb_map_t *_map;
+private:
+ /**
+ * Initializes Blorb
+ */
+ giblorb_err_t giblorb_initialize();
+
+ giblorb_err_t giblorb_initialize_map(giblorb_map_t *map);
+ void giblorb_qsort(giblorb_resdesc_t **list, size_t len);
+ giblorb_resdesc_t *giblorb_bsearch(giblorb_resdesc_t *sample,
+ giblorb_resdesc_t **list, int len);
+ int sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2);
+public:
+ /**
+ * Constructor
+ */
+ Blorb() : _libInited(false), _file(nullptr), _map(nullptr) {}
+
+ giblorb_err_t giblorb_set_resource_map(Common::SeekableReadStream *file);
+ giblorb_map_t *giblorb_get_resource_map(void);
+ bool giblorb_is_resource_map(void) const;
+
+
+ giblorb_err_t giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap);
+ giblorb_err_t giblorb_destroy_map(giblorb_map_t *map);
+
+ giblorb_err_t giblorb_load_chunk_by_type(giblorb_map_t *map,
+ glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
+ giblorb_err_t giblorb_load_chunk_by_number(giblorb_map_t *map,
+ glui32 method, giblorb_result_t *res, glui32 chunknum);
+ giblorb_err_t giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum);
+
+ giblorb_err_t giblorb_load_resource(giblorb_map_t *map, glui32 method,
+ giblorb_result_t *res, glui32 usage, glui32 resnum);
+ giblorb_err_t giblorb_count_resources(giblorb_map_t *map,
+ glui32 usage, glui32 *num, glui32 *min, glui32 *max);
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index b14546c..9dc7f97 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -25,6 +25,7 @@
#include "gargoyle/gargoyle.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/blorb.h"
#include "gargoyle/time.h"
#include "gargoyle/windows.h"
@@ -33,7 +34,7 @@ namespace Gargoyle {
/**
* Implements the GLK interface
*/
-class Glk : public GargoyleEngine {
+class Glk : public GargoyleEngine, public Blorb {
private:
bool _gliFirstEvent;
unsigned char _charTolowerTable[256];
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index f40a79a..d359429 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/gargoyle
MODULE_OBJS := \
+ blorb.o \
conf.o \
detection.o \
events.o \
Commit: fc4c3293d10ae25c6792cff8c5648ff4d4369697
https://github.com/scummvm/scummvm/commit/fc4c3293d10ae25c6792cff8c5648ff4d4369697
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add parsing if game file is a Blorb container
Changed paths:
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
engines/gargoyle/frotz/mem.cpp
engines/gargoyle/frotz/mem.h
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index 77c3303..d5cdaf3 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -40,9 +40,15 @@ Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst,
}
void Frotz::runGame(Common::SeekableReadStream *gameFile) {
+ initialize();
+
// TODO
}
+void Frotz::initialize() {
+ _mem.initialize();
+}
+
Common::Error Frotz::loadGameState(int slot) {
return Common::kNoError;
}
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index e1f3d9f..e1fb36c 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -36,6 +36,11 @@ namespace Frotz {
* Frotz interpreter for Z-code games
*/
class Frotz : public Glk {
+private:
+ /**
+ * Perform any initialization
+ */
+ void initialize();
public:
UserOptions _options;
Header _header;
@@ -43,7 +48,7 @@ public:
Mem _mem;
// Story file name, id number and size
- Common::String _storyName;
+ Common::SeekableReadStream *_gameFile;
Story _storyId;
size_t _storySize;
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
index 4bd2324..1b43e93 100644
--- a/engines/gargoyle/frotz/mem.cpp
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/frotz/mem.h"
+#include "gargoyle/frotz/frotz.h"
#include "common/textconsole.h"
namespace Gargoyle {
@@ -54,6 +55,51 @@ const Mem::StoryEntry Mem::RECORDS[25] = {
{ UNKNOWN, 0, "------" }
};
+Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0) {
+}
+
+void Mem::initialize() {
+/*
+ long size;
+ zword addr;
+ unsigned n;
+ int i, j;
+ */
+ initializeStoryFile();
+
+ // TODO: More stuff
+}
+
+void Mem::initializeStoryFile() {
+ Common::SeekableReadStream *f = g_vm->_gameFile;
+ giblorb_map_t *map;
+ giblorb_result_t res;
+ uint32 magic;
+
+ story_fp = f;
+ magic = f->readUint32BE();
+
+ if (magic == MKTAG('F', 'O', 'R', 'M')) {
+ if (g_vm->giblorb_set_resource_map(f))
+ error("This Blorb file seems to be invalid.");
+
+ map = g_vm->giblorb_get_resource_map();
+
+ if (g_vm->giblorb_load_resource(map, giblorb_method_FilePos, &res, giblorb_ID_Exec, 0))
+ error("This Blorb file does not contain an executable chunk.");
+ if (res.chunktype != MKTAG('Z', 'C', 'O', 'D'))
+ error("This Blorb file contains an executable chunk, but it is not a Z-code file.");
+
+ blorb_ofs = res.data.startpos;
+ blorb_len = res.length;
+ } else {
+ blorb_ofs = 0;
+ blorb_len = f->size();
+ }
+
+ if (blorb_len < 64)
+ error("This file is too small to be a Z-code file.");
+}
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index 4abe464..8882a58 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -35,6 +35,24 @@ class Mem {
char _serial[7];
};
static const StoryEntry RECORDS[25];
+private:
+ Common::SeekableReadStream *story_fp;
+ uint blorb_ofs, blorb_len;
+private:
+ /**
+ * Handles setting the story file, parsing it if it's a Blorb file
+ */
+ void initializeStoryFile();
+public:
+ /**
+ * Constructor
+ */
+ Mem();
+
+ /**
+ * Initialize
+ */
+ void initialize();
};
} // End of namespace Frotz
Commit: f19f92e396e348e095e51becc902cdb5ef62618b
https://github.com/scummvm/scummvm/commit/f19f92e396e348e095e51becc902cdb5ef62618b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Move Header to be an ancestor class to Mem
Changed paths:
engines/gargoyle/frotz/err.cpp
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/frotz/mem.h
diff --git a/engines/gargoyle/frotz/err.cpp b/engines/gargoyle/frotz/err.cpp
index b25b75c..f9a3ce9 100644
--- a/engines/gargoyle/frotz/err.cpp
+++ b/engines/gargoyle/frotz/err.cpp
@@ -85,7 +85,8 @@ void Errors::runtimeError(int errNum) {
if ((g_vm->_options._err_report_mode == ERR_REPORT_ALWAYS)
|| (g_vm->_options._err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
- long pc = g_vm->getPC();
+ long pc;
+ GET_PC(pc);
printString("Warning: ");
printString(ERR_MESSAGES[errNum - 1]);
printString(" (PC = ");
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index d5cdaf3..64b9f54 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -57,10 +57,5 @@ Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
return Common::kNoError;
}
-uint Frotz::getPC() const {
- // TODO
- return 0;
-}
-
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index e1fb36c..4dd5834 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -101,11 +101,6 @@ public:
* Save the game
*/
virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
-
- /**
- * Get the current PC
- */
- uint getPC() const;
};
extern Frotz *g_vm;
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 505d656..3c7312c 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -32,6 +32,18 @@ namespace Frotz {
#define MAX_UNDO_SLOTS 500
#define STACK_SIZE 20
+#define lo(v) (v & 0xff)
+#define hi(v) (v >> 8)
+
+#define SET_WORD(addr,v) WRITE_BE_UINT16(addr,v)
+#define LOW_WORD(addr,v) READ_BE_UINT16(addr,v)
+#define HIGH_WORD(addr,v) READ_BE_UINT16(addr,v)
+#define HIGH_LONG(addr,v) READ_BE_UINT32(addr,v)
+#define CODE_WORD(v) v = g_vm->_mem.readWord()
+#define CODE_IDX_WORD(v,i) v = g_vm->_mem.readWord(i)
+#define GET_PC(v) v = g_vm->_mem.getPC()
+#define SET_PC(v) g_vm->_mem.setPC(v);
+
/* There are four error reporting modes: never report errors;
* report only the first time a given error type occurs;
* report every time an error occurs;
@@ -134,67 +146,6 @@ struct UserOptions {
}
};
-/**
- * Story file header data
- */
-struct Header {
- zbyte _version;
- zbyte _config;
- zword _release;
- zword _resident_size;
- zword _start_pc;
- zword _dictionary;
- zword _objects;
- zword _globals;
- zword _dynamic_size;
- zword _flags;
- zbyte _serial[6];
- zword _abbreviations;
- zword _file_size;
- zword _checksum;
- zbyte _interpreter_number;
- zbyte _interpreter_version;
- zbyte _screen_rows;
- zbyte _screen_cols;
- zword _screen_width;
- zword _screen_height;
- zbyte _font_height = 1;
- zbyte _font_width = 1;
- zword _functions_offset;
- zword _strings_offset;
- zbyte _default_background;
- zbyte _default_foreground;
- zword _terminating_keys;
- zword _line_width;
- zbyte _standard_high;
- zbyte _standard_low;
- zword _alphabet;
- zword _extension_table;
- zbyte _user_name[8];
-
- zword _hx_table_size;
- zword _hx_mouse_x;
- zword _hx_mouse_y;
- zword _hx_unicode_table;
- zword _hx_flags;
- zword _hx_fore_colour;
- zword _hx_back_colour;
-
- Header() : _version(0), _config(0), _release(0), _resident_size(0), _start_pc(0),
- _dictionary(0), _objects(0), _globals(0), _dynamic_size(0), _flags(0),
- _abbreviations(0), _file_size(0), _checksum(0), _interpreter_number(0),
- _interpreter_version(0), _screen_rows(0), _screen_cols(0), _screen_width(0),
- _screen_height(0), _font_height(1), _font_width(1), _functions_offset(0),
- _strings_offset(0), _default_background(0), _default_foreground(0),
- _terminating_keys(0), _line_width(0), _standard_high(1), _standard_low(1),
- _alphabet(0), _extension_table(0),
- _hx_table_size(0), _hx_mouse_x(0), _hx_mouse_y(0), _hx_unicode_table(0),
- _hx_flags(0), _hx_fore_colour(0), _hx_back_colour(0) {
- Common::fill(&_serial[0], &_serial[6], '\0');
- Common::fill(&_user_name[0], &_user_name[8], '\0');
- }
-};
-
} // End of namespace Frotz
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index 8882a58..68c7b85 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -28,7 +28,69 @@
namespace Gargoyle {
namespace Frotz {
-class Mem {
+
+/**
+ * Story file header data
+ */
+struct Header {
+ zbyte h_version;
+ zbyte h_config;
+ zword h_release;
+ zword h_resident_size;
+ zword h_start_pc;
+ zword h_dictionary;
+ zword h_objects;
+ zword h_globals;
+ zword h_dynamic_size;
+ zword h_flags;
+ zbyte h_serial[6];
+ zword h_abbreviations;
+ zword h_file_size;
+ zword h_checksum;
+ zbyte h_interpreter_number;
+ zbyte h_interpreter_version;
+ zbyte h_screen_rows;
+ zbyte h_screen_cols;
+ zword h_screen_width;
+ zword h_screen_height;
+ zbyte h_font_height = 1;
+ zbyte h_font_width = 1;
+ zword h_functions_offset;
+ zword h_strings_offset;
+ zbyte h_default_background;
+ zbyte h_default_foreground;
+ zword h_terminating_keys;
+ zword h_line_width;
+ zbyte h_standard_high;
+ zbyte h_standard_low;
+ zword h_alphabet;
+ zword h_extension_table;
+ zbyte h_user_name[8];
+
+ zword hx_table_size;
+ zword hx_mouse_x;
+ zword hx_mouse_y;
+ zword hx_unicode_table;
+ zword hx_flags;
+ zword hx_fore_colour;
+ zword hx_back_colour;
+
+ Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
+ h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
+ h_abbreviations(0), h_file_size(0), h_checksum(0), h_interpreter_number(0),
+ h_interpreter_version(0), h_screen_rows(0), h_screen_cols(0), h_screen_width(0),
+ h_screen_height(0), h_font_height(1), h_font_width(1), h_functions_offset(0),
+ h_strings_offset(0), h_default_background(0), h_default_foreground(0),
+ h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
+ h_alphabet(0), h_extension_table(0),
+ hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
+ hx_flags(0), hx_fore_colour(0), hx_back_colour(0) {
+ Common::fill(&h_serial[0], &h_serial[6], '\0');
+ Common::fill(&h_user_name[0], &h_user_name[8], '\0');
+ }
+};
+
+class Mem : public Header {
struct StoryEntry {
Story _storyId;
zword _release;
@@ -38,6 +100,8 @@ class Mem {
private:
Common::SeekableReadStream *story_fp;
uint blorb_ofs, blorb_len;
+ byte *pcp;
+ byte *zmp;
private:
/**
* Handles setting the story file, parsing it if it's a Blorb file
@@ -53,6 +117,31 @@ public:
* Initialize
*/
void initialize();
+
+ /**
+ * Read a word
+ */
+ zword readWord() {
+ pcp += 2;
+ return READ_BE_UINT16(pcp - 2);
+ }
+
+ /**
+ * Read a word at a given index relative to pcp
+ */
+ zword readWord(size_t ofs) {
+ return READ_BE_UINT16(pcp + ofs);
+ }
+
+ /**
+ * Get the PC
+ */
+ uint getPC() const { return pcp - zmp; }
+
+ /**
+ * Set the PC
+ */
+ void setPC(uint ofs) { pcp = zmp + ofs; }
};
} // End of namespace Frotz
Commit: cc9b52e5ac9c0e08e86f07c94713c3ebc54dc680
https://github.com/scummvm/scummvm/commit/cc9b52e5ac9c0e08e86f07c94713c3ebc54dc680
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Implement the removeSaveState method
Changed paths:
engines/gargoyle/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 4238e64..5ff0cc7 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -242,6 +242,8 @@ int GargoyleMetaEngine::getMaximumSaveSlot() const {
}
void GargoyleMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
}
SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Commit: 38a458139aef488acf48abfcf61233c529984cb1
https://github.com/scummvm/scummvm/commit/38a458139aef488acf48abfcf61233c529984cb1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add Gargoyle engine to credits.pl
Changed paths:
devtools/credits.pl
diff --git a/devtools/credits.pl b/devtools/credits.pl
index ad011b7..3cfa7b7 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -623,6 +623,13 @@ begin_credits("Credits");
begin_section("Fullpipe");
add_person("Eugene Sandulenko", "sev", "");
end_section();
+
+ begin_section("Gargoyle");
+ add_person("Paul Gilbert", "dreammaster", "");
+ add_person("Tor Andersson", "", "GLK library");
+ add_person("Stefan Jokisch", "", "Frotz interpreter");
+ add_person("Alan Cox", "", "ScottFree interpreter");
+ end_section();
begin_section("Gnap");
add_person("Arnaud Boutonné", "Strangerke", "");
Commit: a083eb3d5ca682a0b465d383413f62ff38b8e814
https://github.com/scummvm/scummvm/commit/a083eb3d5ca682a0b465d383413f62ff38b8e814
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added bulk of game processor
Changed paths:
A engines/gargoyle/frotz/glk_interface.cpp
A engines/gargoyle/frotz/glk_interface.h
A engines/gargoyle/frotz/processor.cpp
A engines/gargoyle/frotz/processor.h
A engines/gargoyle/frotz/processor_input.cpp
A engines/gargoyle/frotz/processor_maths.cpp
A engines/gargoyle/frotz/processor_objects.cpp
A engines/gargoyle/frotz/processor_screen.cpp
A engines/gargoyle/frotz/processor_streams.cpp
A engines/gargoyle/frotz/processor_table.cpp
A engines/gargoyle/frotz/processor_text.cpp
A engines/gargoyle/frotz/processor_variables.cpp
engines/gargoyle/frotz/buffer.cpp
engines/gargoyle/frotz/err.cpp
engines/gargoyle/frotz/err.h
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/frotz/mem.cpp
engines/gargoyle/frotz/mem.h
engines/gargoyle/glk.h
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/frotz/buffer.cpp b/engines/gargoyle/frotz/buffer.cpp
index 15ec771..7d9e644 100644
--- a/engines/gargoyle/frotz/buffer.cpp
+++ b/engines/gargoyle/frotz/buffer.cpp
@@ -61,7 +61,7 @@ void Buffer::flush() {
void Buffer::printChar(zchar c) {
static bool flag = false;
- if (g_vm->_message || g_vm->_ostream_memory || g_vm->_enableBuffering) {
+ if (g_vm->message || g_vm->ostream_memory || g_vm->enable_buffering) {
if (!flag) {
// Characters 0 and ZC_RETURN are special cases
if (c == ZC_RETURN) {
diff --git a/engines/gargoyle/frotz/err.cpp b/engines/gargoyle/frotz/err.cpp
index f9a3ce9..f75b764 100644
--- a/engines/gargoyle/frotz/err.cpp
+++ b/engines/gargoyle/frotz/err.cpp
@@ -67,14 +67,15 @@ Errors::Errors() {
Common::fill(&_count[0], &_count[ERR_NUM_ERRORS], 0);
}
-void Errors::runtimeError(int errNum) {
- int wasfirst;
+void Errors::runtimeError(ErrorCode errNum) {
+#ifdef TODO
+ int wasfirst;
if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
return;
- if (g_vm->_options._err_report_mode == ERR_REPORT_FATAL
- || (!g_vm->_options._ignore_errors && errNum <= ERR_MAX_FATAL)) {
+ if (g_vm->_err_report_mode == ERR_REPORT_FATAL
+ || (!g_vm->_ignore_errors && errNum <= ERR_MAX_FATAL)) {
g_vm->_buffer.flush();
error(ERR_MESSAGES[errNum - 1]);
return;
@@ -83,9 +84,9 @@ void Errors::runtimeError(int errNum) {
wasfirst = (_count[errNum - 1] == 0);
_count[errNum - 1]++;
- if ((g_vm->_options._err_report_mode == ERR_REPORT_ALWAYS)
- || (g_vm->_options._err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
- long pc;
+ if ((g_vm->_err_report_mode == ERR_REPORT_ALWAYS)
+ || (_err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
+ long pc = g_vm->_processor
GET_PC(pc);
printString("Warning: ");
printString(ERR_MESSAGES[errNum - 1]);
@@ -93,7 +94,7 @@ void Errors::runtimeError(int errNum) {
printLong(pc, 16);
printChar(')');
- if (g_vm->_options._err_report_mode == ERR_REPORT_ONCE) {
+ if (_err_report_mode == ERR_REPORT_ONCE) {
printString(" (will ignore further occurrences)");
} else {
printString(" (occurence ");
@@ -103,6 +104,7 @@ void Errors::runtimeError(int errNum) {
newLine();
}
+#endif
}
void Errors::printLong(uint value, int base) {
diff --git a/engines/gargoyle/frotz/err.h b/engines/gargoyle/frotz/err.h
index f61d726..e71c988 100644
--- a/engines/gargoyle/frotz/err.h
+++ b/engines/gargoyle/frotz/err.h
@@ -28,26 +28,51 @@
namespace Gargoyle {
namespace Frotz {
-#define ERR_NUM_ERRORS 33
-#define ERR_MAX_FATAL 19
+enum ErrorCode {
+ ERR_TEXT_BUF_OVF = 1, ///< Text buffer overflow
+ ERR_STORE_RANGE = 2, ///< Store out of dynamic memory
+ ERR_DIV_ZERO = 3, ///< Division by zero
+ ERR_ILL_OBJ = 4, ///< Illegal object
+ ERR_ILL_ATTR = 5, ///< Illegal attribute
+ ERR_NO_PROP = 6, ///< No such property
+ ERR_STK_OVF = 7, ///< Stack overflow
+ ERR_ILL_CALL_ADDR = 8, ///< Call to illegal address
+ ERR_CALL_NON_RTN = 9, ///< Call to non-routine
+ ERR_STK_UNDF = 10, ///< Stack underflow
+ ERR_ILL_OPCODE = 11, ///< Illegal opcode
+ ERR_BAD_FRAME = 12, ///< Bad stack frame
+ ERR_ILL_JUMP_ADDR = 13, ///< Jump to illegal address
+ ERR_SAVE_IN_INTER = 14, ///< Can't save while in interrupt
+ ERR_STR3_NESTING = 15, ///< Nesting stream #3 too deep
+ ERR_ILL_WIN = 16, ///< Illegal window
+ ERR_ILL_WIN_PROP = 17, ///< Illegal window property
+ ERR_ILL_PRINT_ADDR = 18, ///< Print at illegal address
+ ERR_DICT_LEN = 19, ///< Illegal dictionary word length
+ ERR_MAX_FATAL = 19,
+
+ // Less serious errors
+ ERR_JIN_0 = 20, ///< @jin called with object 0
+ ERR_GET_CHILD_0 = 21, ///< @get_child called with object 0
+ ERR_GET_PARENT_0 = 22, ///< @get_parent called with object 0
+ ERR_GET_SIBLING_0 = 23, ///< @get_sibling called with object 0
+ ERR_GET_PROP_ADDR_0 = 24, ///< @get_prop_addr called with object 0
+ ERR_GET_PROP_0 = 25, ///< @get_prop called with object 0
+ ERR_PUT_PROP_0 = 26, ///< @put_prop called with object 0
+ ERR_CLEAR_ATTR_0 = 27, ///< @clear_attr called with object 0
+ ERR_SET_ATTR_0 = 28, ///< @set_attr called with object 0
+ ERR_TEST_ATTR_0 = 29, ///< @test_attr called with object 0
+ ERR_MOVE_OBJECT_0 = 30, ///< @move_object called moving object 0
+ ERR_MOVE_OBJECT_TO_0 = 31, ///< @move_object called moving into object 0
+ ERR_REMOVE_OBJECT_0 = 32, ///< @remove_object called with object 0
+ ERR_GET_NEXT_PROP_0 = 33, ///< @get_next_prop called with object 0
+ ERR_NUM_ERRORS = 33
+};
class Errors {
private:
static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
int _count[ERR_NUM_ERRORS];
-public:
- /**
- * Constructor
- */
- Errors();
-
- /**
- * An error has occurred. Ignore it, pass it to os_fatal or report
- * it according to err_report_mode.
- * @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
- */
- void runtimeError(int errNum);
-
+private:
/**
* Print an unsigned 32bit number in decimal or hex.
*/
@@ -67,6 +92,23 @@ public:
* Add a newline
*/
void newLine();
+protected:
+ /**
+ * Get the PC. Is implemented by the Processor class, which derives from Errors
+ */
+ virtual zword getPC() const = 0;
+public:
+ /**
+ * Constructor
+ */
+ Errors();
+
+ /**
+ * An error has occurred. Ignore it, pass it to os_fatal or report
+ * it according to err_report_mode.
+ * @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
+ */
+ void runtimeError(ErrorCode errNum);
};
} // End of namespace Frotz
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index 64b9f54..c0a9442 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -28,27 +28,18 @@ namespace Frotz {
Frotz *g_vm;
-Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
- _storyId(UNKNOWN), _storySize(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
- _ostream_screen(true), _ostream_script(false), _ostream_memory(false),
- _ostream_record(false), _istream_replay(false), _message(false),
- _cwin(0), _mwin(0), _mouse_x(0), _mouse_y(0), _menu_selected(0),
- _enableWrapping(false), _enableScripting(true), _enableScrolling(false),
- _enableBuffering(false), _reserveMem(0) {
+Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+ Processor(syst, gameDesc) {
g_vm = this;
- Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
}
void Frotz::runGame(Common::SeekableReadStream *gameFile) {
+ story_fp = gameFile;
initialize();
// TODO
}
-void Frotz::initialize() {
- _mem.initialize();
-}
-
Common::Error Frotz::loadGameState(int slot) {
return Common::kNoError;
}
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index 4dd5834..c032265 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -23,11 +23,7 @@
#ifndef GARGOYLE_FROTZ_FROTZ
#define GARGOYLE_FROTZ_FROTZ
-#include "gargoyle/glk.h"
-#include "gargoyle/frotz/frotz_types.h"
-#include "gargoyle/frotz/buffer.h"
-#include "gargoyle/frotz/err.h"
-#include "gargoyle/frotz/mem.h"
+#include "gargoyle/frotz/processor.h"
namespace Gargoyle {
namespace Frotz {
@@ -35,52 +31,7 @@ namespace Frotz {
/**
* Frotz interpreter for Z-code games
*/
-class Frotz : public Glk {
-private:
- /**
- * Perform any initialization
- */
- void initialize();
-public:
- UserOptions _options;
- Header _header;
- Buffer _buffer;
- Mem _mem;
-
- // Story file name, id number and size
- Common::SeekableReadStream *_gameFile;
- Story _storyId;
- size_t _storySize;
-
- // Stack data
- zword _stack[STACK_SIZE];
- zword *_sp;
- zword *_fp;
- zword _frameCount;
-
- // IO streams
- bool _ostream_screen;
- bool _ostream_script;
- bool _ostream_memory;
- bool _ostream_record;
- bool _istream_replay;
- bool _message;
-
- // Current window and mouse data
- int _cwin;
- int _mwin;
- int _mouse_y;
- int _mouse_x;
- int _menu_selected;
-
- // Window attributes
- bool _enableWrapping;
- bool _enableScripting;
- bool _enableScrolling;
- bool _enableBuffering;
-
- // Size of memory to reserve (in bytes)
- size_t _reserveMem;
+class Frotz : public Processor {
public:
/**
* Constructor
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 3c7312c..c4f4298 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -35,15 +35,6 @@ namespace Frotz {
#define lo(v) (v & 0xff)
#define hi(v) (v >> 8)
-#define SET_WORD(addr,v) WRITE_BE_UINT16(addr,v)
-#define LOW_WORD(addr,v) READ_BE_UINT16(addr,v)
-#define HIGH_WORD(addr,v) READ_BE_UINT16(addr,v)
-#define HIGH_LONG(addr,v) READ_BE_UINT32(addr,v)
-#define CODE_WORD(v) v = g_vm->_mem.readWord()
-#define CODE_IDX_WORD(v,i) v = g_vm->_mem.readWord(i)
-#define GET_PC(v) v = g_vm->_mem.getPC()
-#define SET_PC(v) g_vm->_mem.setPC(v);
-
/* There are four error reporting modes: never report errors;
* report only the first time a given error type occurs;
* report every time an error occurs;
@@ -113,6 +104,113 @@ enum Story {
UNKNOWN
};
+enum Version {
+ V1 = 1,
+ V2 = 2,
+ V3 = 3,
+ V4 = 4,
+ V5 = 5,
+ V6 = 6,
+ V7 = 7,
+ V8 = 8,
+ V9 = 9
+};
+
+enum ConfigFlag {
+ CONFIG_BYTE_SWAPPED = 0x01, ///< Story file is byte swapped - V3
+ CONFIG_TIME = 0x02, ///< Status line displays time - V3
+ CONFIG_TWODISKS = 0x04, ///< Story file occupied two disks - V3
+ CONFIG_TANDY = 0x08, ///< Tandy licensed game - V3
+ CONFIG_NOSTATUSLINE = 0x10, ///< Interpr can't support status lines - V3
+ CONFIG_SPLITSCREEN = 0x20, ///< Interpr supports split screen mode - V3
+ CONFIG_PROPORTIONAL = 0x40, ///< Interpr uses proportional font - V3
+
+ CONFIG_COLOUR = 0x01, ///< Interpr supports colour - V5+
+ CONFIG_PICTURES = 0x02, ///< Interpr supports pictures - V6
+ CONFIG_BOLDFACE = 0x04, ///< Interpr supports boldface style - V4+
+ CONFIG_EMPHASIS = 0x08, ///< Interpr supports emphasis style - V4+
+ CONFIG_FIXED = 0x10, ///< Interpr supports fixed width style - V4+
+ CONFIG_SOUND = 0x20, ///< Interpr supports sound - V6
+ CONFIG_TIMEDINPUT = 0x80, ///< Interpr supports timed input - V4+
+
+ SCRIPTING_FLAG = 0x0001, ///< Outputting to transscription file - V1+
+ FIXED_FONT_FLAG = 0x0002, ///< Use fixed width font - V3+
+ REFRESH_FLAG = 0x0004, ///< Refresh the screen - V6
+ GRAPHICS_FLAG = 0x0008, ///< Game wants to use graphics - V5+
+ OLD_SOUND_FLAG = 0x0010, ///< Game wants to use sound effects - V3
+ UNDO_FLAG = 0x0010, ///< Game wants to use UNDO feature - V5+
+ MOUSE_FLAG = 0x0020, ///< Game wants to use a mouse - V5+
+ COLOUR_FLAG = 0x0040, ///< Game wants to use colours - V5+
+ SOUND_FLAG = 0x0080, ///< Game wants to use sound effects - V5+
+ MENU_FLAG = 0x0100 ///< Game wants to use menus - V6
+};
+
+enum {
+ TRANSPARENT_FLAG = 0x0001 ///< Game wants to use transparency - V6
+};
+
+enum FrotzInterp {
+#define INTERP_DEFAULT 0
+#define INTERP_DEC_20 1
+#define INTERP_APPLE_IIE 2
+#define INTERP_MACINTOSH 3
+#define INTERP_AMIGA 4
+#define INTERP_ATARI_ST 5
+#define INTERP_MSDOS 6
+#define INTERP_CBM_128 7
+#define INTERP_CBM_64 8
+#define INTERP_APPLE_IIC 9
+#define INTERP_APPLE_IIGS 10
+#define INTERP_TANDY 11
+};
+
+enum Colour {
+ BLACK_COLOUR = 2,
+ RED_COLOUR = 3,
+ GREEN_COLOUR = 4,
+ YELLOW_COLOUR = 5,
+ BLUE_COLOUR = 6,
+ MAGENTA_COLOUR = 7,
+ CYAN_COLOUR = 8,
+ WHITE_COLOUR = 9,
+ GREY_COLOUR = 10, ///< INTERP_MSDOS only
+ LIGHTGREY_COLOUR = 10, ///< INTERP_AMIGA only
+ MEDIUMGREY_COLOUR = 11, ///< INTERP_AMIGA only
+ DARKGREY_COLOUR = 12, ///< INTERP_AMIGA only
+ TRANSPARENT_COLOUR = 15 ///< ZSpec 1.1
+};
+
+enum Style {
+ REVERSE_STYLE = 1,
+ BOLDFACE_STYLE = 2,
+ EMPHASIS_STYLE = 4,
+ FIXED_WIDTH_STYLE = 8
+};
+
+enum FontStyle {
+ TEXT_FONT = 1,
+ PICTURE_FONT = 2,
+ GRAPHICS_FONT = 3,
+ FIXED_WIDTH_FONT = 4
+};
+
+/*** Constants for os_beep */
+
+#define BEEP_HIGH 1
+#define BEEP_LOW 2
+
+/*** Constants for os_restart_game */
+
+#define RESTART_BEGIN 0
+#define RESTART_WPROP_SET 1
+#define RESTART_END 2
+
+/*** Constants for os_menu */
+
+#define MENU_NEW 0
+#define MENU_ADD 1
+#define MENU_REMOVE 2
+
typedef byte zbyte;
typedef uint zchar;
typedef uint16 zword;
diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp
new file mode 100644
index 0000000..e1311fb
--- /dev/null
+++ b/engines/gargoyle/frotz/glk_interface.cpp
@@ -0,0 +1,272 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/glk_interface.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+ Glk(syst, gameDesc),
+ oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
+ curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
+ curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
+ gos_lower(nullptr), gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr),
+ gos_linewin(nullptr), gos_channel(nullptr), cwin(0), mwin(0), mouse_x(0), mouse_y(0),
+ menu_selected(0), ostream_screen(false), ostream_script(false), ostream_memory(false),
+ ostream_record(false), istream_replay(false), message(false),
+ enable_wrapping(false), enable_scripting(false), enable_scrolling(false),
+ enable_buffering(false), next_sample(0), next_volume(0),
+ _soundLocked(false), _soundPlaying(false) {
+ Common::fill(&statusline[0], &statusline[256], '\0');
+}
+
+int GlkInterface::os_char_width(zchar z) {
+ return 1;
+}
+
+int GlkInterface::os_string_width(const zchar *s) {
+ int width = 0;
+ zchar c;
+ while ((c = *s++) != 0)
+ if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT)
+ s++;
+ else
+ width += os_char_width(c);
+ return width;
+}
+
+int GlkInterface::os_string_length(zchar *s) {
+ int length = 0;
+ while (*s++) length++;
+ return length;
+}
+
+void GlkInterface::os_prepare_sample(int a) {
+ glk_sound_load_hint(a, 1);
+}
+
+void GlkInterface::os_finish_with_sample(int a) {
+ glk_sound_load_hint(a, 0);
+}
+
+void GlkInterface::os_start_sample(int number, int volume, int repeats, zword eos) {
+ int vol;
+
+ if (!gos_channel) {
+ gos_channel = glk_schannel_create(0);
+ if (!gos_channel)
+ return;
+ }
+
+ switch (volume) {
+ case 1: vol = 0x02000; break;
+ case 2: vol = 0x04000; break;
+ case 3: vol = 0x06000; break;
+ case 4: vol = 0x08000; break;
+ case 5: vol = 0x0a000; break;
+ case 6: vol = 0x0c000; break;
+ case 7: vol = 0x0e000; break;
+ case 8: vol = 0x10000; break;
+ default: vol = 0x20000; break;
+ }
+
+ // we dont do repeating or eos-callback for now...
+ glk_schannel_play_ext(gos_channel, number, 1, 0);
+ glk_schannel_set_volume(gos_channel, vol);
+}
+
+void GlkInterface::os_stop_sample(int a) {
+ if (!gos_channel)
+ return;
+ glk_schannel_stop(gos_channel);
+}
+
+void GlkInterface::os_beep(int volume) {
+}
+
+void GlkInterface::start_sample(int number, int volume, int repeats, zword eos) {
+ // TODO
+}
+
+void GlkInterface::start_next_sample() {
+ // TODO
+}
+
+void GlkInterface::gos_update_width() {
+ glui32 width;
+ if (gos_upper) {
+ glk_window_get_size(gos_upper, &width, nullptr);
+ h_screen_cols = width;
+ SET_BYTE(H_SCREEN_COLS, width);
+ if (curx > width) {
+ glk_window_move_cursor(gos_upper, 0, cury - 1);
+ curx = 1;
+ }
+ }
+}
+
+void GlkInterface::gos_update_height() {
+ glui32 height_upper;
+ glui32 height_lower;
+ if (gos_curwin) {
+ glk_window_get_size(gos_upper, nullptr, &height_upper);
+ glk_window_get_size(gos_lower, nullptr, &height_lower);
+ h_screen_rows = height_upper + height_lower + 1;
+ SET_BYTE(H_SCREEN_ROWS, h_screen_rows);
+ }
+}
+
+void GlkInterface::reset_status_ht() {
+ glui32 height;
+ if (gos_upper) {
+ glk_window_get_size(gos_upper, nullptr, &height);
+ if (mach_status_ht != height) {
+ glk_window_set_arrangement(
+ glk_window_get_parent(gos_upper),
+ winmethod_Above | winmethod_Fixed,
+ mach_status_ht, nullptr);
+ }
+ }
+}
+
+void GlkInterface::erase_window(zword w) {
+ if (w == 0)
+ glk_window_clear(gos_lower);
+ else if (gos_upper) {
+#ifdef GARGLK
+ garglk_set_reversevideo_stream(
+ glk_window_get_stream(gos_upper),
+ true);
+#endif /* GARGLK */
+
+ memset(statusline, ' ', sizeof statusline);
+ glk_window_clear(gos_upper);
+ reset_status_ht();
+ curr_status_ht = 0;
+ }
+}
+
+void GlkInterface::split_window(zword lines) {
+ if (!gos_upper)
+ return;
+
+ // The top line is always set for V1 to V3 games
+ if (h_version < V4)
+ lines++;
+
+ if (!lines || lines > curr_status_ht) {
+ glui32 height;
+
+ glk_window_get_size(gos_upper, nullptr, &height);
+ if (lines != height)
+ glk_window_set_arrangement(
+ glk_window_get_parent(gos_upper),
+ winmethod_Above | winmethod_Fixed,
+ lines, nullptr);
+ curr_status_ht = lines;
+ }
+ mach_status_ht = lines;
+ if (cury > lines)
+ {
+ glk_window_move_cursor(gos_upper, 0, 0);
+ curx = cury = 1;
+ }
+ gos_update_width();
+
+ if (h_version == V3)
+ glk_window_clear(gos_upper);
+}
+
+void GlkInterface::restart_screen() {
+ erase_window(0);
+ erase_window(1);
+ split_window(0);
+}
+
+void GlkInterface::packspaces(zchar *src, zchar *dst) {
+ int killing = 0;
+ while (*src) {
+ if (*src == 0x20202020)
+ *src = ' ';
+ if (*src == ' ')
+ killing++;
+ else
+ killing = 0;
+ if (killing > 2)
+ src++;
+ else
+ *dst++ = *src++;
+ }
+
+ *dst = 0;
+}
+
+void GlkInterface::smartstatusline() {
+ zchar packed[256];
+ zchar buf[256];
+ zchar *a, *b, *c, *d;
+ int roomlen, scorelen, scoreofs;
+ int len, tmp;
+
+ packspaces(statusline, packed);
+ len = os_string_length(packed);
+
+ a = packed;
+ while (a[0] == ' ')
+ a++;
+
+ b = a;
+ while (b[0] != 0 && !(b[0] == ' ' && b[1] == ' '))
+ b++;
+
+ c = b;
+ while (c[0] == ' ')
+ c++;
+
+ d = packed + len - 1;
+ while (d[0] == ' ' && d > c)
+ d--;
+ if (d[0] != ' ' && d[0] != 0)
+ d++;
+ if (d < c)
+ d = c;
+
+ roomlen = b - a;
+ scorelen = d - c;
+ scoreofs = h_screen_cols - scorelen - 2;
+ if (scoreofs <= roomlen)
+ scoreofs = roomlen + 2;
+
+ for (tmp = 0; tmp < h_screen_cols; tmp++)
+ buf[tmp] = ' ';
+
+ memcpy(buf + 1 + scoreofs, c, scorelen * sizeof(zchar));
+ memcpy(buf + 1, a, roomlen * sizeof(zchar));
+
+ glk_window_move_cursor(gos_upper, 0, 0);
+ glk_put_buffer_uni(buf, h_screen_cols);
+ glk_window_move_cursor(gos_upper, cury - 1, curx - 1);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
new file mode 100644
index 0000000..ea3f60c
--- /dev/null
+++ b/engines/gargoyle/frotz/glk_interface.h
@@ -0,0 +1,147 @@
+/* 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 GARGOYLE_FROTZ_GLK_INTERFACE
+#define GARGOYLE_FROTZ_GLK_INTERFACE
+
+#include "gargoyle/glk.h"
+#include "gargoyle/frotz/mem.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+enum SoundEffect {
+ EFFECT_PREPARE = 1,
+ EFFECT_PLAY = 2,
+ EFFECT_STOP = 3,
+ EFFECT_FINISH_WITH = 4
+};
+
+/**
+ * Implements an intermediate interface on top of the GLK layer, providing screen
+ * and sound effect handling
+ */
+class GlkInterface : public Glk, public virtual Mem {
+public:
+ zchar statusline[256];
+ int oldstyle;
+ int curstyle;
+ int cury;
+ int curx;
+ int fixforced;
+
+ int curr_fg;
+ int curr_bg;
+ int curr_font;
+ int prev_font;
+ int temp_font;
+
+ int curr_status_ht;
+ int mach_status_ht;
+
+ winid_t gos_status;
+ winid_t gos_upper;
+ winid_t gos_lower;
+ winid_t gos_curwin;
+ int gos_linepending;
+ zchar *gos_linebuf;
+ winid_t gos_linewin;
+ schanid_t gos_channel;
+
+ // Current window and mouse data
+ int cwin;
+ int mwin;
+ int mouse_y;
+ int mouse_x;
+ int menu_selected;
+
+ // IO streams
+ bool ostream_screen;
+ bool ostream_script;
+ bool ostream_memory;
+ bool ostream_record;
+ bool istream_replay;
+ bool message;
+
+ // Window attributes
+ bool enable_wrapping;
+ bool enable_scripting;
+ bool enable_scrolling;
+ bool enable_buffering;
+
+ // Sound fields
+ int next_sample;
+ int next_volume;
+
+ bool _soundLocked;
+ bool _soundPlaying;
+protected:
+ int os_char_width(zchar z);
+ int os_string_width(const zchar *s);
+ int os_string_length(zchar *s);
+ void os_prepare_sample(int a);
+ void os_finish_with_sample(int a);
+
+ /**
+ * Play the given sample at the given volume (ranging from 1 to 8 and
+ * 255 meaning a default volume). The sound is played once or several
+ * times in the background (255 meaning forever). In Z-code 3 the
+ * repeats value is always 0 and the number of repeats is taken from
+ * the sound file itself. The end_of_sound function is called as soon
+ * as the sound finishes.
+ */
+ void os_start_sample(int number, int volume, int repeats, zword eos);
+
+ void os_stop_sample(int a);
+ void os_beep(int volume);
+
+ /**
+ * Call the IO interface to play a sample.
+ */
+ void start_sample(int number, int volume, int repeats, zword eos);
+
+ void start_next_sample();
+ void gos_update_width();
+ void gos_update_height();
+ void reset_status_ht();
+ void erase_window(zword w);
+ void split_window(zword lines);
+ void restart_screen();
+
+ /**
+ * statusline overflowed the window size ... bad game!
+ * so ... split status text into regions, reformat and print anew.
+ */
+ void packspaces(zchar *src, zchar *dst);
+
+ void smartstatusline();
+public:
+ /**
+ * Constructor
+ */
+ GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc);
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
index 1b43e93..cb5a73b 100644
--- a/engines/gargoyle/frotz/mem.cpp
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -22,12 +22,13 @@
#include "gargoyle/frotz/mem.h"
#include "gargoyle/frotz/frotz.h"
+#include "common/memstream.h"
#include "common/textconsole.h"
namespace Gargoyle {
namespace Frotz {
-const Mem::StoryEntry Mem::RECORDS[25] = {
+const Header::StoryEntry Header::RECORDS[25] = {
{ SHERLOCK, 21, "871214" },
{ SHERLOCK, 26, "880127" },
{ BEYOND_ZORK, 47, "870915" },
@@ -55,28 +56,99 @@ const Mem::StoryEntry Mem::RECORDS[25] = {
{ UNKNOWN, 0, "------" }
};
-Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0) {
+void Header::loadHeader(Common::SeekableReadStream &f) {
+ h_version = f.readByte();
+ h_config = f.readByte();
+
+ if (h_version < V1 || h_version > V8)
+ error("Unknown Z-code version");
+
+ if (h_version == V6)
+ error("Cannot play Z-code version 6");
+
+ if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
+ error("Byte swapped story file");
+
+ h_release = f.readUint16BE();
+ h_resident_size = f.readUint16BE();
+ h_start_pc = f.readUint16BE();
+ h_dictionary = f.readUint16BE();
+ h_objects = f.readUint16BE();
+ h_globals = f.readUint16BE();
+ h_dynamic_size = f.readUint16BE();
+ h_flags = f.readUint16BE();
+ f.read(h_serial, 6);
+
+ /* Auto-detect buggy story files that need special fixes */
+ _storyId = UNKNOWN;
+
+ for (int i = 0; RECORDS[i]._storyId != UNKNOWN; ++i) {
+ if (h_release == RECORDS[i]._release) {
+ if (!strncmp((const char *)h_serial, RECORDS[i]._serial, 6)) {
+ _storyId = RECORDS[i]._storyId;
+ break;
+ }
+ }
+ }
+
+ h_abbreviations = f.readUint16BE();
+ h_file_size = f.readUint16BE();
+ h_checksum = f.readUint16BE();
+
+ f.seek(H_FUNCTIONS_OFFSET);
+ h_functions_offset = f.readUint16BE();
+ h_strings_offset = f.readUint16BE();
+ f.seek(H_TERMINATING_KEYS);
+ h_terminating_keys = f.readUint16BE();
+ f.seek(H_ALPHABET);
+ h_alphabet = f.readUint16BE();
+ h_extension_table = f.readUint16BE();
+
+
+ // Zork Zero Macintosh doesn't have the graphics flag set
+ if (_storyId == ZORK_ZERO && h_release == 296)
+ h_flags |= GRAPHICS_FLAG;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0) {
}
void Mem::initialize() {
-/*
- long size;
- zword addr;
- unsigned n;
- int i, j;
- */
initializeStoryFile();
+ loadGameHeader();
+
+ // Allocate memory for story data
+ if ((zmp = (zbyte *)realloc(zmp, story_size)) == nullptr)
+ error("Out of memory");
+
+ // Load story file in chunks of 32KB
+ uint n = 0x8000;
+
+ for (uint size = 64; size < story_size; size += n) {
+ if (story_size - size < 0x8000)
+ n = story_size - size;
+
+ setPC(size);
- // TODO: More stuff
+ if (story_fp->read(pcp, n) != n)
+ error("Story file read error");
+
+ }
+
+ // Read header extension table
+ hx_table_size = get_header_extension(HX_TABLE_SIZE);
+ hx_unicode_table = get_header_extension(HX_UNICODE_TABLE);
+ hx_flags = get_header_extension(HX_FLAGS);
}
void Mem::initializeStoryFile() {
- Common::SeekableReadStream *f = g_vm->_gameFile;
+ Common::SeekableReadStream *f = story_fp;
giblorb_map_t *map;
giblorb_result_t res;
uint32 magic;
- story_fp = f;
magic = f->readUint32BE();
if (magic == MKTAG('F', 'O', 'R', 'M')) {
@@ -101,5 +173,41 @@ void Mem::initializeStoryFile() {
error("This file is too small to be a Z-code file.");
}
+void Mem::loadGameHeader() {
+ // Load header
+ zmp = new byte[64];
+ story_fp->seek(blorb_ofs);
+ story_fp->read(zmp, 64);
+
+ Common::MemoryReadStream h(zmp, 64);
+ loadHeader(h);
+
+ // Calculate story file size in bytes
+ if (h_file_size != 0) {
+ story_size = (long)2 * h_file_size;
+
+ if (h_version >= V4)
+ story_size *= 2;
+ if (h_version >= V6)
+ story_size *= 2;
+ } else {
+ // Some old games lack the file size entry
+ story_size = blorb_len;
+ }
+}
+
+zword Mem::get_header_extension(int entry) {
+ zword addr;
+ zword val;
+
+ if (h_extension_table == 0 || entry > hx_table_size)
+ return 0;
+
+ addr = h_extension_table + 2 * entry;
+ LOW_WORD(addr, val);
+
+ return val;
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index 68c7b85..d37cdd3 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -28,11 +28,71 @@
namespace Gargoyle {
namespace Frotz {
+#define SET_WORD(addr,v) zmp[addr] = hi(v); zmp[addr+1] = lo(v)
+#define LOW_WORD(addr,v) v = READ_BE_UINT16(&zmp[addr])
+#define HIGH_WORD(addr,v) v = READ_BE_UINT16(&zmp[addr])
+#define HIGH_LONG(addr,v) v = READ_BE_UINT32(&zmp[addr])
+#define SET_BYTE(addr,v) zmp[addr] = v
+#define LOW_BYTE(addr,v) v = zmp[addr]
+
+enum HeaderByte {
+ H_VERSION = 0,
+ H_CONFIG = 1,
+ H_RELEASE = 2,
+ H_RESIDENT_SIZE = 4,
+ H_START_PC = 6,
+ H_DICTIONARY = 8,
+ H_OBJECTS = 10,
+ H_GLOBALS = 12,
+ H_DYNAMIC_SIZE = 14,
+ H_FLAGS = 16,
+ H_SERIAL = 18,
+ H_ABBREVIATIONS = 24,
+ H_FILE_SIZE = 26,
+ H_CHECKSUM = 28,
+ H_INTERPRETER_NUMBER = 30,
+ H_INTERPRETER_VERSION = 31,
+ H_SCREEN_ROWS = 32,
+ H_SCREEN_COLS = 33,
+ H_SCREEN_WIDTH = 34,
+ H_SCREEN_HEIGHT = 36,
+ H_FONT_HEIGHT = 38, ///< this is the font width in V5
+ H_FONT_WIDTH = 39, ///< this is the font height in V5
+ H_FUNCTIONS_OFFSET = 40,
+ H_STRINGS_OFFSET = 42,
+ H_DEFAULT_BACKGROUND = 44,
+ H_DEFAULT_FOREGROUND = 45,
+ H_TERMINATING_KEYS = 46,
+ H_LINE_WIDTH = 48,
+ H_STANDARD_HIGH = 50,
+ H_STANDARD_LOW = 51,
+ H_ALPHABET = 52,
+ H_EXTENSION_TABLE = 54,
+ H_USER_NAME = 56
+};
+
+enum {
+ HX_TABLE_SIZE = 0,
+ HX_MOUSE_X = 1,
+ HX_MOUSE_Y = 2,
+ HX_UNICODE_TABLE = 3,
+ HX_FLAGS = 4,
+ HX_FORE_COLOUR = 5,
+ HX_BACK_COLOUR = 6
+};
/**
* Story file header data
*/
struct Header {
+private:
+ struct StoryEntry {
+ Story _storyId;
+ zword _release;
+ char _serial[7];
+ };
+ static const StoryEntry RECORDS[25];
+public:
zbyte h_version;
zbyte h_config;
zword h_release;
@@ -75,6 +135,11 @@ struct Header {
zword hx_fore_colour;
zword hx_back_colour;
+ Story _storyId;
+
+ /**
+ * Constructor
+ */
Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
h_abbreviations(0), h_file_size(0), h_checksum(0), h_interpreter_number(0),
@@ -84,22 +149,22 @@ struct Header {
h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
h_alphabet(0), h_extension_table(0),
hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
- hx_flags(0), hx_fore_colour(0), hx_back_colour(0) {
+ hx_flags(0), hx_fore_colour(0), hx_back_colour(0), _storyId(UNKNOWN) {
Common::fill(&h_serial[0], &h_serial[6], '\0');
Common::fill(&h_user_name[0], &h_user_name[8], '\0');
}
+
+ /**
+ * Load the header
+ */
+ void loadHeader(Common::SeekableReadStream &f);
};
class Mem : public Header {
- struct StoryEntry {
- Story _storyId;
- zword _release;
- char _serial[7];
- };
- static const StoryEntry RECORDS[25];
-private:
+protected:
Common::SeekableReadStream *story_fp;
uint blorb_ofs, blorb_len;
+ uint story_size;
byte *pcp;
byte *zmp;
private:
@@ -107,6 +172,11 @@ private:
* Handles setting the story file, parsing it if it's a Blorb file
*/
void initializeStoryFile();
+
+ /**
+ * Handles loading the game header
+ */
+ void loadGameHeader();
public:
/**
* Constructor
@@ -116,7 +186,7 @@ public:
/**
* Initialize
*/
- void initialize();
+ virtual void initialize();
/**
* Read a word
@@ -142,6 +212,11 @@ public:
* Set the PC
*/
void setPC(uint ofs) { pcp = zmp + ofs; }
+
+ /**
+ * Read a value from the header extension (former mouse table).
+ */
+ zword get_header_extension(int entry);
};
} // End of namespace Frotz
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
new file mode 100644
index 0000000..1a31898
--- /dev/null
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -0,0 +1,659 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+#include "gargoyle/frotz/frotz.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Stubs to replace with actual code
+zword save_undo() { return 0; }
+zword restore_undo() { return 0; }
+
+
+Opcode Processor::var_opcodes[64] = {
+ &Processor::__illegal__,
+ &Processor::z_je,
+ &Processor::z_jl,
+ &Processor::z_jg,
+ &Processor::z_dec_chk,
+ &Processor::z_inc_chk,
+ &Processor::z_jin,
+ &Processor::z_test,
+ &Processor::z_or,
+ &Processor::z_and,
+ &Processor::z_test_attr,
+ &Processor::z_set_attr,
+ &Processor::z_clear_attr,
+ &Processor::z_store,
+ &Processor::z_insert_obj,
+ &Processor::z_loadw,
+ &Processor::z_loadb,
+ &Processor::z_get_prop,
+ &Processor::z_get_prop_addr,
+ &Processor::z_get_next_prop,
+ &Processor::z_add,
+ &Processor::z_sub,
+ &Processor::z_mul,
+ &Processor::z_div,
+ &Processor::z_mod,
+ &Processor::z_call_s,
+ &Processor::z_call_n,
+ &Processor::z_set_colour,
+ &Processor::z_throw,
+ &Processor::__illegal__,
+ &Processor::__illegal__,
+ &Processor::__illegal__,
+ &Processor::z_call_s,
+ &Processor::z_storew,
+ &Processor::z_storeb,
+ &Processor::z_put_prop,
+ &Processor::z_read,
+ &Processor::z_print_char,
+ &Processor::z_print_num,
+ &Processor::z_random,
+ &Processor::z_push,
+ &Processor::z_pull,
+ &Processor::z_split_window,
+ &Processor::z_set_window,
+ &Processor::z_call_s,
+ &Processor::z_erase_window,
+ &Processor::z_erase_line,
+ &Processor::z_set_cursor,
+ &Processor::z_get_cursor,
+ &Processor::z_set_text_style,
+ &Processor::z_buffer_mode,
+ &Processor::z_output_stream,
+ &Processor::z_input_stream,
+ &Processor::z_sound_effect,
+ &Processor::z_read_char,
+ &Processor::z_scan_table,
+ &Processor::z_not,
+ &Processor::z_call_n,
+ &Processor::z_call_n,
+ &Processor::z_tokenise,
+ &Processor::z_encode_text,
+ &Processor::z_copy_table,
+ &Processor::z_print_table,
+ &Processor::z_check_arg_count
+};
+
+Opcode Processor::ext_opcodes[64] = {
+ &Processor::z_save,
+ &Processor::z_restore,
+ &Processor::z_log_shift,
+ &Processor::z_art_shift,
+ &Processor::z_set_font,
+ &Processor::__illegal__, // glkify - Processor::z_draw_picture,
+ &Processor::__illegal__, // glkify - Processor::z_picture_data,
+ &Processor::__illegal__, // glkify - Processor::z_erase_picture,
+ &Processor::__illegal__, // glkify - Processor::z_set_margins,
+ &Processor::z_save_undo,
+ &Processor::z_restore_undo,
+ &Processor::z_print_unicode,
+ &Processor::z_check_unicode,
+ &Processor::z_set_true_colour, // spec 1.1
+ &Processor::__illegal__,
+ &Processor::__illegal__,
+ &Processor::__illegal__, // glkify - Processor::z_move_window,
+ &Processor::__illegal__, // glkify - Processor::z_window_size,
+ &Processor::__illegal__, // glkify - Processor::z_window_style,
+ &Processor::__illegal__, // glkify - Processor::z_get_wind_prop,
+ &Processor::__illegal__, // glkify - Processor::z_scroll_window,
+ &Processor::z_pop_stack,
+ &Processor::__illegal__, // glkify - Processor::z_read_mouse,
+ &Processor::__illegal__, // glkify - Processor::z_mouse_window,
+ &Processor::z_push_stack,
+ &Processor::__illegal__, // glkify - Processor::z_put_wind_prop,
+ &Processor::z_print_form,
+ &Processor::z_make_menu,
+ &Processor::__illegal__, // glkify - Processor::z_picture_table
+ &Processor::z_buffer_screen, // spec 1.1
+};
+
+Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+ GlkInterface(syst, gameDesc), Mem(), Errors(), UserOptions(),
+ _finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
+ zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
+ _randomInterval(0), _randomCtr(0), first_restart(true) {
+ static const Opcode OP0_OPCODES[16] = {
+ &Processor::z_rtrue,
+ &Processor::z_rfalse,
+ &Processor::z_print,
+ &Processor::z_print_ret,
+ &Processor::z_nop,
+ &Processor::z_save,
+ &Processor::z_restore,
+ &Processor::z_restart,
+ &Processor::z_ret_popped,
+ &Processor::z_catch,
+ &Processor::z_quit,
+ &Processor::z_new_line,
+ &Processor::z_show_status,
+ &Processor::z_verify,
+ &Processor::__extended__,
+ &Processor::z_piracy
+ };
+ static const Opcode OP1_OPCODES[16] = {
+ &Processor::z_jz,
+ &Processor::z_get_sibling,
+ &Processor::z_get_child,
+ &Processor::z_get_parent,
+ &Processor::z_get_prop_len,
+ &Processor::z_inc,
+ &Processor::z_dec,
+ &Processor::z_print_addr,
+ &Processor::z_call_s,
+ &Processor::z_remove_obj,
+ &Processor::z_print_obj,
+ &Processor::z_ret,
+ &Processor::z_jump,
+ &Processor::z_print_paddr,
+ &Processor::z_load,
+ &Processor::z_call_n
+ };
+
+ Common::copy(&OP0_OPCODES[0], &OP0_OPCODES[16], op0_opcodes);
+ Common::copy(&OP1_OPCODES[0], &OP1_OPCODES[16], op1_opcodes);
+ Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
+ Common::fill(&zargs[0], &zargs[8], 0);
+}
+
+void Processor::initialize() {
+ Mem::initialize();
+
+ if (h_version <= V4) {
+ op0_opcodes[9] = &Processor::z_pop;
+ op1_opcodes[15] = &Processor::z_not;
+ } else {
+ op0_opcodes[9] = &Processor::z_catch;
+ op1_opcodes[15] = &Processor::z_call_n;
+ }
+}
+
+void Processor::load_operand(zbyte type) {
+ zword value;
+
+ if (type & 2) {
+ // variable
+ zbyte variable;
+
+ CODE_BYTE(variable);
+
+ if (variable == 0)
+ value = *_sp++;
+ else if (variable < 16)
+ value = *(_fp - variable);
+ else {
+ zword addr = h_globals + 2 * (variable - 16);
+ LOW_WORD(addr, value);
+ }
+ } else if (type & 1) {
+ // small constant
+ zbyte bvalue;
+
+ CODE_BYTE(bvalue);
+ value = bvalue;
+
+ } else {
+ // large constant
+ CODE_WORD(value);
+ }
+
+ zargs[zargc++] = value;
+}
+
+void Processor::load_all_operands(zbyte specifier) {
+ for (int i = 6; i >= 0; i -= 2) {
+ zbyte type = (specifier >> i) & 0x03;
+
+ if (type == 3)
+ break;
+
+ load_operand(type);
+ }
+}
+
+void Processor::interpret() {
+ do {
+ zbyte opcode;
+ CODE_BYTE(opcode);
+ zargc = 0;
+
+ if (opcode < 0x80) {
+ // 2OP opcodes
+ load_operand((zbyte)(opcode & 0x40) ? 2 : 1);
+ load_operand((zbyte)(opcode & 0x20) ? 2 : 1);
+
+ (*this.*var_opcodes[opcode & 0x1f])();
+
+ } else if (opcode < 0xb0) {
+ // 1OP opcodes
+ load_operand((zbyte)(opcode >> 4));
+
+ (*this.*op1_opcodes[opcode & 0x0f])();
+
+ } else if (opcode < 0xc0) {
+ // 0OP opcodes
+ (*this.*op0_opcodes[opcode - 0xb0])();
+
+ } else {
+ // VAR opcodes
+ zbyte specifier1;
+ zbyte specifier2;
+
+ if (opcode == 0xec || opcode == 0xfa) { // opcodes 0xec
+ CODE_BYTE(specifier1); // and 0xfa are
+ CODE_BYTE(specifier2); // call opcodes
+ load_all_operands(specifier1); // with up to 8
+ load_all_operands(specifier2); // arguments
+ } else {
+ CODE_BYTE(specifier1);
+ load_all_operands(specifier1);
+ }
+
+ (*this.*var_opcodes[opcode - 0xc0])();
+ }
+
+#if defined(DJGPP) && defined(SOUND_SUPPORT)
+ if (end_of_sound_flag)
+ end_of_sound();
+#endif
+ } while (!_finished);
+
+ _finished--;
+}
+
+void Processor::call(zword routine, int argc, zword *args, int ct) {
+ long pc;
+ zword value;
+ zbyte count;
+ int i;
+
+ if (_sp - _stack < 4)
+ runtimeError(ERR_STK_OVF);
+
+ GET_PC(pc);
+
+ *--_sp = (zword)(pc >> 9);
+ *--_sp = (zword)(pc & 0x1ff);
+ *--_sp = (zword)(_fp - _stack - 1);
+ *--_sp = (zword)(argc | (ct << (_save_quetzal ? 12 : 8)));
+
+ _fp = _sp;
+ _frameCount++;
+
+ // Calculate byte address of routine
+ if (h_version <= V3)
+ pc = (long)routine << 1;
+ else if (h_version <= V5)
+ pc = (long)routine << 2;
+ else if (h_version <= V7)
+ pc = ((long)routine << 2) + ((long)h_functions_offset << 3);
+ else if (h_version <= V8)
+ pc = (long)routine << 3;
+ else {
+ // h_version == V9
+ long indirect = (long)routine << 2;
+ HIGH_LONG(indirect, pc);
+ }
+
+ if ((uint)pc >= story_size)
+ runtimeError(ERR_ILL_CALL_ADDR);
+
+ SET_PC(pc);
+
+ // Initialise local variables
+ CODE_BYTE(count);
+
+ if (count > 15)
+ runtimeError(ERR_CALL_NON_RTN);
+ if (_sp - _stack < count)
+ runtimeError(ERR_STK_OVF);
+
+ if (_save_quetzal)
+ _fp[0] |= (zword)count << 8; // Save local var count for Quetzal.
+
+ value = 0;
+
+ for (i = 0; i < count; i++) {
+ if (h_version <= V4) // V1 to V4 games provide default
+ CODE_WORD(value); // values for all local variables
+
+ *--_sp = (zword)((argc-- > 0) ? args[i] : value);
+ }
+
+ // Start main loop for direct calls
+ if (ct == 2)
+ interpret();
+}
+
+void Processor::ret(zword value) {
+ long pc;
+ int ct;
+
+ if (_sp > _fp)
+ runtimeError(ERR_STK_UNDF);
+
+ _sp = _fp;
+
+ ct = *_sp++ >> (_save_quetzal ? 12 : 8);
+ _frameCount--;
+ _fp = _stack + 1 + *_sp++;
+ pc = *_sp++;
+ pc = ((long)*_sp++ << 9) | pc;
+
+ SET_PC(pc);
+
+ // Handle resulting value
+ if (ct == 0)
+ store(value);
+ if (ct == 2)
+ *--_sp = value;
+
+ // Stop main loop for direct calls
+ if (ct == 2)
+ _finished++;
+}
+
+void Processor::branch(bool flag) {
+ long pc;
+ zword offset;
+ zbyte specifier;
+ zbyte off1;
+ zbyte off2;
+
+ CODE_BYTE(specifier);
+ off1 = specifier & 0x3f;
+
+ if (!flag)
+ specifier ^= 0x80;
+
+ if (!(specifier & 0x40)) {
+ // it's a long branch
+ if (off1 & 0x20) // propagate sign bit
+ off1 |= 0xc0;
+
+ CODE_BYTE(off2);
+ offset = (off1 << 8) | off2;
+ } else {
+ // It's a short branch
+ offset = off1;
+ }
+
+ if (specifier & 0x80) {
+ if (offset > 1) {
+ // normal branch
+ GET_PC(pc);
+ pc += (short)offset - 2;
+ SET_PC(pc);
+ } else {
+ // special case, return 0 or 1
+ ret(offset);
+ }
+ }
+}
+
+void Processor::store(zword value) {
+ zbyte variable;
+
+ CODE_BYTE(variable);
+
+ if (variable == 0)
+ *--_sp = value;
+ else if (variable < 16)
+ *(_fp - variable) = value;
+ else {
+ zword addr = h_globals + 2 * (variable - 16);
+ SET_WORD(addr, value);
+ }
+}
+
+int Processor::direct_call(zword addr) {
+ zword saved_zargs[8];
+ int saved_zargc;
+ int i;
+
+ // Calls to address 0 return false
+ if (addr == 0)
+ return 0;
+
+ // Save operands and operand count
+ for (i = 0; i < 8; i++)
+ saved_zargs[i] = zargs[i];
+
+ saved_zargc = zargc;
+
+ // Call routine directly
+ call(addr, 0, 0, 2);
+
+ // Restore operands and operand count
+ for (i = 0; i < 8; i++)
+ zargs[i] = saved_zargs[i];
+
+ zargc = saved_zargc;
+
+ // Resulting value lies on top of the stack
+ return (short)*_sp++;
+}
+
+void Processor::seed_random(int value) {
+ if (value == 0) {
+ // Now using random values
+ _randomInterval = 0;
+ } else if (value < 1000) {
+ // special seed value
+ _randomCtr = 0;
+ _randomInterval = value;
+ } else {
+ // standard seed value
+ _random.setSeed(value);
+ _randomInterval = 0;
+ }
+}
+
+void Processor::__extended__() {
+ zbyte opcode;
+ zbyte specifier;
+
+ CODE_BYTE(opcode);
+ CODE_BYTE(specifier);
+
+ load_all_operands(specifier);
+
+ if (opcode < 0x1e) // extended opcodes from 0x1e on
+ (*this.*ext_opcodes[opcode])(); // are reserved for future spec'
+}
+
+void Processor::__illegal__() {
+ runtimeError(ERR_ILL_OPCODE);
+}
+
+void Processor::z_catch() {
+ store(_save_quetzal ? _frameCount : (zword)(_fp - _stack));
+}
+
+void Processor::z_throw() {
+ if (_save_quetzal) {
+ if (zargs[1] > _frameCount)
+ runtimeError(ERR_BAD_FRAME);
+
+ // Unwind the stack a frame at a time.
+ for (; _frameCount > zargs[1]; --_frameCount)
+ _fp = _stack + 1 + _fp[1];
+ } else {
+ if (zargs[1] > STACK_SIZE)
+ runtimeError(ERR_BAD_FRAME);
+
+ _fp = _stack + zargs[1];
+ }
+
+ ret(zargs[0]);
+}
+
+void Processor::z_call_n() {
+ if (zargs[0] != 0)
+ call(zargs[0], zargc - 1, zargs + 1, 1);
+}
+
+void Processor::z_call_s() {
+ if (zargs[0] != 0)
+ call(zargs[0], zargc - 1, zargs + 1, 0);
+ else
+ store(0);
+}
+
+void Processor::z_check_arg_count() {
+ if (_fp == _stack + STACK_SIZE)
+ branch(zargs[0] == 0);
+ else
+ branch(zargs[0] <= (*_fp & 0xff));
+}
+
+void Processor::z_jump() {
+ long pc;
+ GET_PC(pc);
+
+ pc += (short)zargs[0] - 2;
+
+ if ((uint)pc >= story_size)
+ runtimeError(ERR_ILL_JUMP_ADDR);
+
+ SET_PC(pc);
+}
+
+void Processor::z_nop() {
+ // Do nothing
+}
+
+void Processor::z_quit() {
+ _finished = 9999;
+}
+
+void Processor::z_ret() {
+ ret(zargs[0]);
+}
+
+void Processor::z_ret_popped() {
+ ret(*_sp++);
+}
+
+void Processor::z_rfalse() {
+ ret(0);
+}
+
+void Processor::z_rtrue() {
+ ret(1);
+}
+
+void Processor::z_random() {
+ if ((short) zargs[0] <= 0) {
+ // set random seed
+ seed_random(- (short) zargs[0]);
+ store(0);
+
+ } else {
+ // generate random number
+ zword result;
+ if (_randomInterval != 0) {
+ // ...in special mode
+ result = _randomCtr++;
+ if (_randomCtr == _randomInterval)
+ _randomCtr = 0;
+ } else {
+ // ...in standard mode
+ result = _random.getRandomNumber(0xffff);
+ }
+
+ store((zword)(result % zargs[0] + 1));
+ }
+}
+
+void Processor::z_sound_effect() {
+ zword number = zargs[0];
+ zword effect = zargs[1];
+ zword volume = zargs[2];
+
+ if (zargc < 1)
+ number = 0;
+ if (zargc < 2)
+ effect = EFFECT_PLAY;
+ if (zargc < 3)
+ volume = 8;
+
+ if (number >= 3 || number == 0) {
+ _soundLocked = true;
+
+ if (_storyId == LURKING_HORROR && (number == 9 || number == 16)) {
+ if (effect == EFFECT_PLAY) {
+ next_sample = number;
+ next_volume = volume;
+
+ _soundLocked = false;
+
+ if (!_soundPlaying)
+ start_next_sample();
+ } else {
+ _soundLocked = false;
+ }
+ return;
+ }
+
+ _soundPlaying = false;
+
+ switch (effect) {
+
+ case EFFECT_PREPARE:
+ os_prepare_sample (number);
+ break;
+ case EFFECT_PLAY:
+ start_sample(number, lo (volume), hi (volume), (zargc == 4) ? zargs[3] : 0);
+ break;
+ case EFFECT_STOP:
+ os_stop_sample (number);
+ break;
+ case EFFECT_FINISH_WITH:
+ os_finish_with_sample (number);
+ break;
+ }
+
+ _soundLocked = false;
+ } else {
+ os_beep(number);
+ }
+}
+
+void Processor::z_piracy() {
+ branch(!_piracy);
+}
+
+void Processor::z_save_undo(void) {
+ store((zword)save_undo());
+}
+
+void Processor::z_restore_undo(void) {
+ store((zword)restore_undo());
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
new file mode 100644
index 0000000..074100a
--- /dev/null
+++ b/engines/gargoyle/frotz/processor.h
@@ -0,0 +1,1322 @@
+/* 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 GARGOYLE_FROTZ_PROCESSOR
+#define GARGOYLE_FROTZ_PROCESSOR
+
+#include "gargoyle/frotz/buffer.h"
+#include "gargoyle/frotz/err.h"
+#include "gargoyle/frotz/mem.h"
+#include "gargoyle/frotz/glk_interface.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+#define CODE_BYTE(v) v = *pcp++
+#define CODE_WORD(v) v = READ_BE_UINT16(pcp += 2)
+#define CODE_IDX_WORD(v,i) v = READ_BE_UINT16(pcp + i)
+#define GET_PC(v) v = pcp - zmp
+#define SET_PC(v) pcp = zmp + v
+
+
+enum string_type {
+ LOW_STRING, ABBREVIATION, HIGH_STRING, EMBEDDED_STRING, VOCABULARY
+};
+
+class Processor;
+typedef void (Processor::*Opcode)();
+
+/**
+ * Zcode processor
+ */
+class Processor : public virtual Mem, public Errors, public GlkInterface, public UserOptions {
+private:
+ Opcode op0_opcodes[16];
+ Opcode op1_opcodes[16];
+ static Opcode var_opcodes[64];
+ static Opcode ext_opcodes[64];
+ int _finished;
+ zword zargs[8];
+ int zargc;
+ uint _randomInterval;
+ uint _randomCtr;
+ bool first_restart;
+
+ // Stack data
+ zword _stack[STACK_SIZE];
+ zword *_sp;
+ zword *_fp;
+ zword _frameCount;
+
+ // Text related fields
+ static zchar ZSCII_TO_LATIN1[];
+ zchar *_decoded, *_encoded;
+ int _resolution;
+private:
+ /**
+ * \defgroup General support methods
+ * @{
+ */
+
+ /**
+ * Load an operand, either a variable or a constant.
+ */
+ void load_operand(zbyte type);
+
+ /**
+ * Given the operand specifier byte, load all (up to four) operands
+ * for a VAR or EXT opcode.
+ */
+ void load_all_operands(zbyte specifier);
+
+ /**
+ * Call a subroutine. Save PC and FP then load new PC and initialise
+ * new stack frame. Note that the caller may legally provide less or
+ * more arguments than the function actually has. The call type "ct"
+ * can be 0 (z_call_s), 1 (z_call_n) or 2 (direct call).
+ */
+ void call(zword routine, int argc, zword *args, int ct);
+
+ /**
+ * Return from the current subroutine and restore the previous _stack
+ * frame. The result may be stored (0), thrown away (1) or pushed on
+ * the stack (2). In the latter case a direct call has been finished
+ * and we must exit the interpreter loop.
+ */
+ void ret(zword value);
+
+ /**
+ * Take a jump after an instruction based on the flag, either true or
+ * false. The branch can be short or long; it is encoded in one or two
+ * bytes respectively. When bit 7 of the first byte is set, the jump
+ * takes place if the flag is true; otherwise it is taken if the flag
+ * is false. When bit 6 of the first byte is set, the branch is short;
+ * otherwise it is long. The offset occupies the bottom 6 bits of the
+ * first byte plus all the bits in the second byte for long branches.
+ * Uniquely, an offset of 0 means return false, and an offset of 1 is
+ * return true.
+ */
+ void branch(bool flag);
+
+ /**
+ * Store an operand, either as a variable or pushed on the stack.
+ */
+ void store(zword value);
+
+ /*
+ * Call the interpreter loop directly. This is necessary when
+ *
+ * - a sound effect has been finished
+ * - a read instruction has timed out
+ * - a newline countdown has hit zero
+ *
+ * The interpreter returns the result value on the stack.
+ */
+ int direct_call(zword addr);
+
+ /**
+ * Set the seed value for the random number generator.
+ */
+ void seed_random(int value);
+
+ /**@}*/
+
+ /**
+ * \defgroup Input support methods
+ * @{
+ */
+
+ /**
+ * Check if the given key is an input terminator.
+ */
+ bool is_terminator(zchar key);
+
+ /**
+ * Ask the user a question; return true if the answer is yes.
+ */
+ bool read_yes_or_no(const char *s);
+
+ /**
+ * Read a string from the current input stream.
+ */
+ void read_string(int max, zchar *buffer);
+
+ /**
+ * Ask the user to type in a number and return it.
+ */
+ int read_number();
+
+ /**@}*/
+
+ /**
+ * \defgroup Object support methods
+ * @{
+ */
+
+ /**
+ * Calculate the address of an object.
+ */
+ zword object_address(zword obj);
+
+ /**
+ * Return the address of the given object's name.
+ */
+ zword object_name(zword object);
+
+ /**
+ * Calculate the start address of the property list associated with an object.
+ */
+ zword first_property(zword obj);
+
+ /**
+ * Calculate the address of the next property in a property list.
+ */
+ zword next_property(zword prop_addr);
+
+ /**
+ * Unlink an object from its parent and siblings.
+ */
+ void unlink_object(zword object);
+
+ /**@}*/
+
+ /**
+ * \defgroup Screen support methods
+ * @{
+ */
+
+ void screen_char(zchar c);
+ void screen_new_line();
+ void screen_word(const zchar *s);
+ void screen_mssg_on();
+ void screen_mssg_off();
+
+ /**@}*/
+
+ /**
+ * \defgroup Stream support methods
+ * @{
+ */
+
+ /**
+ * Write a single character to the scrollback buffer.
+ *
+ */
+ void scrollback_char(zchar c);
+
+ /**
+ * Write a string to the scrollback buffer.
+ */
+ void scrollback_word(const zchar *s);
+
+ /**
+ * Send an input line to the scrollback buffer.
+ */
+ void scrollback_write_input(const zchar *buf, zchar key);
+
+ /**
+ * Remove an input line from the scrollback buffer.
+ */
+ void scrollback_erase_input(const zchar *buf);
+
+ /**
+ * Start printing a "debugging" message.
+ */
+ void stream_mssg_on();
+
+ /**
+ * Stop printing a "debugging" message.
+ */
+ void stream_mssg_off();
+
+ /**
+ * Send a single character to the output stream.
+ */
+ void stream_char(zchar c);
+
+ /**
+ * Send a string of characters to the output streams.
+ */
+ void stream_word(const zchar *s);
+
+ /**
+ * Send a newline to the output streams.
+ */
+ void stream_new_line();
+
+ /**
+ * Read a single keystroke from the current input stream.
+ */
+ zchar stream_read_key(zword timeout, zword routine, bool hot_keys);
+
+ /**
+ * Read a line of input from the current input stream.
+ */
+ zchar stream_read_input(int max, zchar *buf, zword timeout, zword routine,
+ bool hot_keys, bool no_scripting);
+
+ /**@}*/
+
+ /**
+ * \defgroup Text support methods
+ * @{
+ */
+
+ /**
+ * Map a ZSCII character into Unicode.
+ */
+ zchar translate_from_zscii(zbyte c);
+
+ /**
+ * Convert a Unicode character to ZSCII, returning 0 on failure.
+ */
+ zbyte unicode_to_zscii(zchar c);
+
+ /**
+ * Map a Unicode character onto the ZSCII alphabet.
+ *
+ */
+ zbyte translate_to_zscii(zchar c);
+
+ /**
+ * Return a character from one of the three character sets.
+ */
+ zchar alphabet(int set, int index);
+
+ /**
+ * Find the number of bytes used for dictionary resolution.
+ */
+ void find_resolution();
+
+ /**
+ * Copy a ZSCII string from the memory to the global "decoded" string.
+ */
+ void load_string(zword addr, zword length);
+
+ /**
+ * Encode the Unicode text in the global "decoded" string then write
+ * the result to the global "encoded" array. (This is used to look up
+ * words in the dictionary.) Up to V3 the vocabulary resolution is
+ * two, from V4 it is three, and from V9 it is any number of words.
+ * Because each word contains three Z-characters, that makes six or
+ * nine Z-characters respectively. Longer words are chopped to the
+ * proper size, shorter words are are padded out with 5's. For word
+ * completion we pad with 0s and 31s, the minimum and maximum
+ * Z-characters.
+ */
+ void encode_text(int padding);
+
+ /**
+ * Convert _encoded text to Unicode. The _encoded text consists of 16bit
+ * words. Every word holds 3 Z-characters (5 bits each) plus a spare
+ * bit to mark the last word. The Z-characters translate to ZSCII by
+ * looking at the current current character set. Some select another
+ * character set, others refer to abbreviations.
+ *
+ * There are several different string types:
+ *
+ * LOW_STRING - from the lower 64KB (byte address)
+ * ABBREVIATION - from the abbreviations table (word address)
+ * HIGH_STRING - from the end of the memory map (packed address)
+ * EMBEDDED_STRING - from the instruction stream (at PC)
+ * VOCABULARY - from the dictionary (byte address)
+ *
+ * The last type is only used for word completion.
+ */
+ void decode_text(string_type st, zword addr);
+
+ /**
+ * Print a signed 16bit number.
+ */
+ void print_num(zword value);
+
+ /**
+ * print_object
+ *
+ * Print an object description.
+ *
+ */
+ void print_object(zword object);
+
+ /**
+ * Scan a dictionary searching for the given word. The first argument
+ * can be
+ *
+ * 0x00 - find the first word which is >= the given one
+ * 0x05 - find the word which exactly matches the given one
+ * 0x1f - find the last word which is <= the given one
+ *
+ * The return value is 0 if the search fails.
+ */
+ zword lookup_text(int padding, zword dct);
+
+ /**
+ * tokenise_text
+ *
+ * Translate a single word to a token and append it to the token
+ * buffer. Every token consists of the address of the dictionary
+ * entry, the length of the word and the offset of the word from
+ * the start of the text buffer. Unknown words cause empty slots
+ * if the flag is set (such that the text can be scanned several
+ * times with different dictionaries); otherwise they are zero.
+ *
+ */
+ void tokenise_text(zword text, zword length, zword from, zword parse, zword dct, bool flag);
+
+ /**
+ * Split an input line into words and translate the words to tokens.
+ */
+ void tokenise_line(zword text, zword token, zword dct, bool flag);
+
+ /**
+ * Scan the vocabulary to complete the last word on the input line
+ * (similar to "tcsh" under Unix). The return value is
+ *
+ * 2 ==> completion is impossible
+ * 1 ==> completion is ambiguous
+ * 0 ==> completion is successful
+ *
+ * The function also returns a string in its second argument. In case
+ * of 2, the string is empty; in case of 1, the string is the longest
+ * extension of the last word on the input line that is common to all
+ * possible completions (for instance, if the last word on the input
+ * is "fo" and its only possible completions are "follow" and "folly"
+ * then the string is "ll"); in case of 0, the string is an extension
+ * to the last word that results in the only possible completion.
+ */
+ int completion(const zchar *buffer, zchar *result);
+
+ /**
+ * Convert a Unicode character to lowercase.
+ * Taken from Zip2000 by Kevin Bracey.
+ */
+ zchar unicode_tolower(zchar c);
+
+ /**@}*/
+private:
+ /**
+ * \defgroup General Opcode methods
+ * @{
+ */
+
+ /*
+ * Load and execute an extended opcode.
+ */
+ void __extended__();
+
+ /*
+ * Exit game because an unknown opcode has been hit.
+ */
+ void __illegal__();
+
+ /*
+ * Store the current _stack frame for later use with z_throw.
+ *
+ * no zargs used
+ */
+ void z_catch();
+
+ /**
+ * Go back to the given _stack frame and return the given value.
+ *
+ * zargs[0] = value to return
+ * zargs[1] = _stack frame
+ */
+ void z_throw();
+
+ /*
+ * Call a subroutine and discard its result.
+ *
+ * zargs[0] = packed address of subroutine
+ * zargs[1] = first argument (optional)
+ * ...
+ * zargs[7] = seventh argument (optional)
+ */
+ void z_call_n();
+
+ /**
+ * Call a subroutine and store its result.
+ *
+ * zargs[0] = packed address of subroutine
+ * zargs[1] = first argument (optional)
+ * ...
+ * zargs[7] = seventh argument (optional)
+ */
+ void z_call_s();
+
+ /**
+ * Branch if subroutine was called with >= n arg's.
+ *
+ * zargs[0] = number of arguments
+ */
+ void z_check_arg_count();
+
+ /**
+ * Jump unconditionally to the given address.
+ *
+ * zargs[0] = PC relative address
+ */
+ void z_jump();
+
+ /*
+ * No operation.
+ *
+ * no zargs used
+ */
+ void z_nop();
+
+ /*
+ * Stop game and exit interpreter.
+ *
+ * no zargs used
+ */
+ void z_quit();
+
+ /*
+ * Return from a subroutine with the given value.
+ *
+ * zargs[0] = value to return
+ */
+ void z_ret();
+
+ /*
+ * Return from a subroutine with a value popped off the stack.
+ *
+ * no zargs used
+ */
+ void z_ret_popped();
+
+ /*
+ * Return from a subroutine with false (0).
+ *
+ * no zargs used
+ */
+ void z_rfalse();
+
+ /*
+ * Return from a subroutine with true (1).
+ *
+ * no zargs used
+ */
+ void z_rtrue();
+
+ /**
+ * Store a random number or set the random number seed.
+ *
+ * zargs[0] = range (positive) or seed value (negative)
+ */
+ void z_random();
+
+ /**
+ * Load / play / stop / discard a sound effect.
+ *
+ * zargs[0] = number of bleep (1 or 2) or sample
+ * zargs[1] = operation to perform (samples only)
+ * zargs[2] = repeats and volume (play sample only)
+ * zargs[3] = end-of-sound routine (play sample only, optional)
+ *
+ * Note: Volumes range from 1 to 8, volume 255 is the default volume.
+ * Repeats are stored in the high byte, 255 is infinite loop.
+ *
+ */
+ void z_sound_effect();
+
+ /**
+ * Branch if the story file is a legal copy
+ */
+ void z_piracy();
+
+ /**
+ * Save the current Z-machine state for a future undo.
+ *
+ * no zargs used
+ */
+ void z_save_undo();
+
+ /**
+ * Restore a Z-machine state from memory.
+ *
+ * no zargs used
+ */
+ void z_restore_undo();
+
+ /**@}*/
+
+ /**
+ * \defgroup Input Opcode methods
+ * @{
+ */
+
+ /**
+ * Add or remove a menu and branch if successful.
+ *
+ * zargs[0] = number of menu
+ * zargs[1] = table of menu entries or 0 to remove menu
+ */
+ void z_make_menu();
+
+ /**
+ * Read a line of input and (in V5+) store the terminating key.
+ *
+ * zargs[0] = address of text buffer
+ * zargs[1] = address of token buffer
+ * zargs[2] = timeout in tenths of a second (optional)
+ * zargs[3] = packed address of routine to be called on timeout
+ */
+ void z_read();
+
+ /**
+ * Read and store a key.
+ *
+ * zargs[0] = input device (must be 1)
+ * zargs[1] = timeout in tenths of a second (optional)
+ * zargs[2] = packed address of routine to be called on timeout
+ */
+ void z_read_char();
+
+ /**
+ * z_read_mouse, write the current mouse status into a table.
+ *
+ * zargs[0] = address of table
+ */
+ void z_read_mouse();
+
+ /**@}*/
+
+ /**
+ * \defgroup Math Opcode methods
+ * @{
+ */
+
+ /**
+ * 16 bit addition.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_add();
+
+ /**
+ * Bitwise AND operation.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_and();
+
+ /**
+ * Arithmetic SHIFT operation.
+ *
+ * zargs[0] = value
+ * zargs[1] = #positions to shift left (positive) or right
+ */
+ void z_art_shift();
+
+ /**
+ * Signed 16bit division.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_div();
+
+ /**
+ * B ranch if the first value equals any of the following.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value (optional)
+ * ...
+ * zargs[3] = fourth value (optional)
+ */
+ void z_je();
+
+ /**
+ * Branch if the first value is greater than the second.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_jg();
+
+ /**
+ * Branch if the first value is less than the second.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_jl();
+
+ /**
+ * Branch if value is zero.
+ *
+ * zargs[0] = value
+ */
+ void z_jz();
+
+ /**
+ * Logical SHIFT operation.
+ *
+ * zargs[0] = value
+ * zargs[1] = #positions to shift left (positive) or right (negative)
+ */
+ void z_log_shift();
+
+ /*
+ * Remainder after signed 16bit division.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_mod();
+
+ /**
+ * 16 bit multiplication.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_mul();
+
+ /**
+ * Bitwise NOT operation.
+ *
+ * zargs[0] = value
+ */
+ void z_not();
+
+ /**
+ * Bitwise OR operation.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_or();
+
+ /**
+ * 16 bit substraction.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_sub();
+
+ /**
+ * Branch if all the flags of a bit mask are set in a value.
+ *
+ * zargs[0] = value to be examined
+ * zargs[1] = bit mask
+ */
+ void z_test();
+
+ /**@}*/
+
+ /**
+ * \defgroup Object Opcode methods
+ * @{
+ */
+
+ /**
+ * Branch if the first object is inside the second.
+ *
+ * zargs[0] = first object
+ * zargs[1] = second object
+ */
+ void z_jin();
+
+ /**
+ * Store the child of an object.
+ *
+ * zargs[0] = object
+ */
+ void z_get_child();
+
+ /**
+ * Store the number of the first or next property.
+ *
+ * zargs[0] = object
+ * zargs[1] = address of current property (0 gets the first property)
+ */
+ void z_get_next_prop();
+
+ /**
+ * Store the parent of an object.
+ *
+ * zargs[0] = object
+ */
+ void z_get_parent();
+
+ /**
+ * Store the value of an object property.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of property to be examined
+ */
+ void z_get_prop();
+
+ /**
+ * Store the address of an object property.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of property to be examined
+ */
+ void z_get_prop_addr();
+
+ /**
+ * Store the length of an object property.
+ *
+ * zargs[0] = address of property to be examined
+ */
+ void z_get_prop_len();
+
+ /**
+ * Store the sibling of an object.
+ *
+ * zargs[0] = object
+ */
+ void z_get_sibling();
+
+ /**
+ * Make an object the first child of another object.
+ *
+ * zargs[0] = object to be moved
+ * zargs[1] = destination object
+ */
+ void z_insert_obj();
+
+ /**
+ * Set the value of an object property.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of property to set
+ * zargs[2] = value to set property to
+ */
+ void z_put_prop();
+
+ /**
+ * Unlink an object from its parent and siblings.
+ *
+ * zargs[0] = object
+ */
+ void z_remove_obj();
+
+ /**
+ * Set an object attribute.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of attribute to set
+ */
+ void z_set_attr();
+
+ /**
+ * Branch if an object attribute is set.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of attribute to test
+ */
+ void z_test_attr();
+
+ /**
+ * Clear an object attribute.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of attribute to be cleared
+ */
+ void z_clear_attr();
+
+ /**@}*/
+
+ /**
+ * \defgroup Screen Opcode methods
+ * @{
+ */
+
+ /**
+ * Turn text buffering on/off.
+ *
+ * zargs[0] = new text buffering flag (0 or 1)
+ */
+ void z_buffer_mode();
+
+ /**
+ * Set the screen buffering mode.
+ *
+ * zargs[0] = mode
+ */
+ void z_buffer_screen();
+
+ /**
+ * Erase the line starting at the cursor position.
+ *
+ * zargs[0] = 1 + #units to erase (1 clears to the end of the line)
+ */
+ void z_erase_line();
+
+ /**
+ * Erase a window or the screen to background colour.
+ *
+ * zargs[0] = window (-3 current, -2 screen, -1 screen & unsplit)
+ */
+ void z_erase_window();
+
+ /**
+ * Write the cursor coordinates into a table.
+ *
+ * zargs[0] = address to write information to
+ */
+ void z_get_cursor();
+
+ /**
+ * Print ASCII text in a rectangular area.
+ *
+ * zargs[0] = address of text to be printed
+ * zargs[1] = width of rectangular area
+ * zargs[2] = height of rectangular area (optional)
+ * zargs[3] = number of char's to skip between lines (optional)
+ */
+ void z_print_table();
+
+ /**
+ * Set the foreground and background colours
+ * to specific RGB colour values.
+ *
+ * zargs[0] = foreground colour
+ * zargs[1] = background colour
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_true_colour();
+
+ /**
+ * Set the foreground and background colours.
+ *
+ * zargs[0] = foreground colour
+ * zargs[1] = background colour
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_colour();
+
+ /**
+ * Set the font for text output and store the previous font.
+ *
+ * zargs[0] = number of font or 0 to keep current font
+ */
+ void z_set_font();
+
+ /**
+ * Set the cursor position or turn the cursor on/off.
+ *
+ * zargs[0] = y-coordinate or -2/-1 for cursor on/off
+ * zargs[1] = x-coordinate
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_cursor();
+
+ /**
+ * z_set_text_style, set the style for text output.
+ *
+ * zargs[0] = style flags to set or 0 to reset text style
+ */
+ void z_set_text_style();
+
+ /**
+ * Select the current window.
+ *
+ * zargs[0] = window to be selected (-3 is the current one)
+ */
+ void z_set_window();
+
+ /**
+ * Display the status line for V1 to V3 games.
+ *
+ * no zargs used
+ */
+ void pad_status_line(int column);
+
+ /**
+ * Display the status line for V1 to V3 games.
+ *
+ * no zargs used
+ */
+ void z_show_status();
+
+ /**
+ * Split the screen into an upper (1) and lower (0) window.
+ *
+ * zargs[0] = height of upper window in screen units (V6) or #lines
+ */
+ void z_split_window();
+
+ /**@}*/
+
+ /**
+ * \defgroup Stream Opcode methods
+ * @{
+ */
+
+ /**
+ * Select an input stream.
+ *
+ * zargs[0] = input stream to be selected
+ */
+ void z_input_stream();
+
+ /**
+ * Open or close an output stream.
+ *
+ * zargs[0] = stream to open (positive) or close (negative)
+ * zargs[1] = address to redirect output to (stream 3 only)
+ * zargs[2] = width of redirected output (stream 3 only, optional)
+ */
+ void z_output_stream();
+
+ /**
+ * Re-load dynamic area, clear the stack and set the PC.
+ *
+ * no zargs used
+ */
+ void z_restart();
+
+ /**
+ * Save [a part of] the Z-machine state to disk.
+ *
+ * zargs[0] = address of memory area to save (optional)
+ * zargs[1] = number of bytes to save
+ * zargs[2] = address of suggested file name
+ */
+ void z_save();
+
+ /**
+ * Restore [a part of] a Z-machine state from disk
+ *
+ * zargs[0] = address of area to restore (optional)
+ * zargs[1] = number of bytes to restore
+ * zargs[2] = address of suggested file name
+ */
+ void z_restore();
+
+ /**
+ * Check the story file integrity.
+ *
+ * no zargs used
+ */
+ void z_verify();
+
+ /**@}*/
+
+ /**
+ * \defgroup Table Opcode methods
+ * @{
+ */
+
+ /**
+ * Copy a table or fill it with zeroes.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = destination address or 0 for fill
+ * zargs[2] = size of table
+ *
+ * Note: Copying is safe even when source and destination overlap; but
+ * if zargs[1] is negative the table _must_ be copied forwards.
+ */
+ void z_copy_table();
+
+ /**
+ * Store a value from a table of bytes.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry to store
+ */
+ void z_loadb();
+
+ /**
+ * Store a value from a table of words.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry to store
+ */
+ void z_loadw();
+
+ /**
+ * Find and store the address of a target within a table.
+ *
+ * zargs[0] = target value to be searched for
+ * zargs[1] = address of table
+ * zargs[2] = number of table entries to check value against
+ * zargs[3] = type of table (optional, defaults to 0x82)
+ *
+ * Note: The table is a word array if bit 7 of zargs[3] is set; otherwise
+ * it's a byte array. The lower bits hold the address step.
+ */
+ void z_scan_table();
+
+ /**
+ * Write a byte into a table of bytes.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry
+ * zargs[2] = value to be written
+ */
+ void z_storeb();
+
+ /**
+ * Write a word into a table of words.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry
+ * zargs[2] = value to be written
+ */
+ void z_storew();
+
+ /**@}*/
+
+ /**
+ * \defgroup Text Opcode methods
+ * @{
+ */
+
+ /**
+ * Test if a unicode character can be printed (bit 0) and read (bit 1).
+ *
+ * zargs[0] = Unicode
+ */
+ void z_check_unicode();
+
+ /**
+ * Encode a ZSCII string for use in a dictionary.
+ *
+ * zargs[0] = address of text buffer
+ * zargs[1] = length of ASCII string
+ * zargs[2] = offset of ASCII string within the text buffer
+ * zargs[3] = address to store encoded text in
+ *
+ * This is a V5+ opcode and therefore the dictionary resolution must be
+ * three 16bit words.
+ */
+ void z_encode_text();
+
+ /**
+ * Print a new line.
+ *
+ * no zargs used
+ *
+ */
+ void z_new_line();
+
+ /**
+ * Print a string embedded in the instruction stream.
+ *
+ * no zargs used
+ */
+ void z_print();
+
+ /**
+ * Print a string from the lower 64KB.
+ *
+ * zargs[0] = address of string to print
+ */
+ void z_print_addr();
+
+ /**
+ * Print a single ZSCII character.
+ *
+ * zargs[0] = ZSCII character to be printed
+ */
+ void z_print_char();
+
+ /**
+ * Print a formatted table.
+ *
+ * zargs[0] = address of formatted table to be printed
+ */
+ void z_print_form();
+
+ /**
+ * Print a signed number.
+ *
+ * zargs[0] = number to print
+ */
+ void z_print_num();
+
+ /**
+ * Print an object description.
+ *
+ * zargs[0] = number of object to be printed
+ */
+ void z_print_obj();
+
+ /**
+ * Print the string at the given packed address.
+ *
+ * zargs[0] = packed address of string to be printed
+ */
+ void z_print_paddr();
+
+ /*
+ * Print the string at PC, print newline then return true.
+ *
+ * no zargs used
+ */
+ void z_print_ret();
+
+ /**
+ * Print a string of ASCII characters.
+ */
+ void print_string(const char *s);
+
+ /**
+ * Print unicode character
+ *
+ * zargs[0] = Unicode
+ */
+ void z_print_unicode();
+
+ /**
+ * Make a lexical analysis of a ZSCII string.
+ *
+ * zargs[0] = address of string to analyze
+ * zargs[1] = address of token buffer
+ * zargs[2] = address of dictionary (optional)
+ * zargs[3] = set when unknown words cause empty slots (optional)
+ */
+ void z_tokenise();
+
+ /**@}*/
+
+ /**
+ * \defgroup Variable Opcode methods
+ * @{
+ */
+
+ /**
+ * Decrement a variable.
+ *
+ * zargs[0] = variable to decrement
+ */
+ void z_dec();
+
+ /**
+ * Decrement a variable and branch if now less than value.
+ *
+ * zargs[0] = variable to decrement
+ * zargs[1] = value to check variable against
+ */
+ void z_dec_chk();
+
+ /**
+ * Increment a variable.
+ *
+ * zargs[0] = variable to increment
+ */
+ void z_inc();
+
+ /**
+ * Increment a variable and branch if now greater than value.
+ *
+ * zargs[0] = variable to increment
+ * zargs[1] = value to check variable against
+ */
+ void z_inc_chk();
+
+ /**
+ * Store the value of a variable.
+ *
+ * zargs[0] = variable to store
+ */
+ void z_load();
+
+ /**
+ * Pop a value off the game stack and discard it.
+ *
+ * no zargs used
+ */
+ void z_pop();
+
+ /**
+ * Pop n values off the game or user stack and discard them.
+ *
+ * zargs[0] = number of values to discard
+ * zargs[1] = address of user stack (optional)
+ */
+ void z_pop_stack();
+
+ /**
+ * Pop a value off...
+ *
+ * a) ...the game or a user stack and store it (V6)
+ *
+ * zargs[0] = address of user stack (optional)
+ *
+ * b) ...the game stack and write it to a variable (other than V6)
+ *
+ * zargs[0] = variable to write value to
+ */
+ void z_pull();
+
+ /**
+ * Push a value onto the game stack.
+ *
+ * zargs[0] = value to push onto the stack
+ */
+ void z_push();
+
+ /**
+ * Push a value onto a user stack then branch if successful.
+ *
+ * zargs[0] = value to push onto the stack
+ * zargs[1] = address of user stack
+ */
+ void z_push_stack();
+
+ /**
+ * Write a value to a variable.
+ *
+ * zargs[0] = variable to be written to
+ * zargs[1] = value to write
+ */
+ void z_store();
+
+ /**@}*/
+protected:
+ /**
+ * Get the PC. Is implemented by the Processor class, which derives from Errors
+ */
+ virtual zword getPC() const { return pcp - zmp; }
+public:
+ /**
+ * Constructor
+ */
+ Processor(OSystem *syst, const GargoyleGameDescription *gameDesc);
+
+ /**
+ * Initialization
+ */
+ virtual void initialize() override;
+
+ /**
+ * Z-code interpreter main loop
+ */
+ void interpret();
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
new file mode 100644
index 0000000..e7f92ab
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -0,0 +1,207 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Implement method stubs
+static zchar stream_read_key(zword, zword, bool) { return 0; }
+static zchar stream_read_input(int, zchar *, zword, zword, bool, bool) { return 0;}
+static void storeb(zword, zchar) {}
+static void storew(zword, zword) {}
+static void save_undo() {}
+static zword os_read_mouse() { return 0; }
+
+
+#define INPUT_BUFFER_SIZE 200
+
+void Processor::z_make_menu() {
+ // This opcode was only used for the Macintosh version of Journey.
+ // It controls menus with numbers greater than 2 (menus 0, 1 and 2
+ // are system menus).
+ branch (false);
+}
+
+bool Processor::read_yes_or_no(const char *s) {
+ zchar key;
+
+ print_string(s);
+ print_string("? (y/n) >");
+
+ key = stream_read_key(0, 0, false);
+
+ if (key == 'y' || key == 'Y') {
+ print_string("y\n");
+ return true;
+ } else {
+ print_string("n\n");
+ return false;
+ }
+}
+
+void Processor::read_string(int max, zchar *buffer) {
+ zchar key;
+
+ buffer[0] = 0;
+
+ do {
+ key = stream_read_input(max, buffer, 0, 0, false, false);
+ } while (key != ZC_RETURN);
+}
+
+int Processor::read_number() {
+ zchar buffer[6];
+ int value = 0;
+ int i;
+
+ read_string(5, buffer);
+
+ for (i = 0; buffer[i] != 0; i++)
+ if (buffer[i] >= '0' && buffer[i] <= '9')
+ value = 10 * value + buffer[i] - '0';
+
+ return value;
+
+}
+
+void Processor::z_read() {
+ zchar buffer[INPUT_BUFFER_SIZE];
+ zword addr;
+ zchar key;
+ zbyte max, size;
+ zbyte c;
+ int i;
+
+ // Supply default arguments
+ if (zargc < 3)
+ zargs[2] = 0;
+
+ // Get maximum input size
+ addr = zargs[0];
+
+ LOW_BYTE(addr, max);
+
+ if (h_version <= V4)
+ max--;
+
+ if (max >= INPUT_BUFFER_SIZE)
+ max = INPUT_BUFFER_SIZE - 1;
+
+ // Get initial input size
+ if (h_version >= V5) {
+ addr++;
+ LOW_BYTE(addr, size);
+ } else {
+ size = 0;
+ }
+
+ // Copy initial input to local buffer
+ for (i = 0; i < size; i++) {
+ addr++;
+ LOW_BYTE(addr, c);
+ buffer[i] = translate_from_zscii(c);
+ }
+ buffer[i] = 0;
+
+ // Draw status line for V1 to V3 games
+ if (h_version <= V3)
+ z_show_status();
+
+ // Read input from current input stream
+ key = stream_read_input(
+ max, buffer, // buffer and size
+ zargs[2], // timeout value
+ zargs[3], // timeout routine
+ false, // enable hot keys
+ h_version == V6 // no script in V6
+ );
+
+ if (key == ZC_BAD)
+ return;
+
+ // Perform save_undo for V1 to V4 games
+ if (h_version <= V4)
+ save_undo();
+
+ // Copy local buffer back to dynamic memory
+ for (i = 0; buffer[i] != 0; i++) {
+ if (key == ZC_RETURN) {
+ buffer[i] = unicode_tolower (buffer[i]);
+ }
+
+ storeb((zword) (zargs[0] + ((h_version <= V4) ? 1 : 2) + i), translate_to_zscii (buffer[i]));
+ }
+
+ // Add null character (V1-V4) or write input length into 2nd byte
+ if (h_version <= V4)
+ storeb((zword) (zargs[0] + 1 + i), 0);
+ else
+ storeb((zword) (zargs[0] + 1), i);
+
+ // Tokenise line if a token buffer is present
+ if (key == ZC_RETURN && zargs[1] != 0)
+ tokenise_line (zargs[0], zargs[1], 0, false);
+
+ // Store key
+ if (h_version >= V5)
+ store(translate_to_zscii(key));
+}
+
+void Processor::z_read_char() {
+ zchar key;
+
+ // Supply default arguments
+ if (zargc < 2)
+ zargs[1] = 0;
+
+ // Read input from the current input stream
+ key = stream_read_key(
+ zargs[1], // timeout value
+ zargs[2], // timeout routine
+ false // enable hot keys
+ );
+
+ if (key == ZC_BAD)
+ return;
+
+ // Store key
+ store (translate_to_zscii (key));
+}
+
+void Processor::z_read_mouse(){
+ zword btn;
+
+ // Read the mouse position, the last menu click and which buttons are down
+ btn = os_read_mouse();
+ hx_mouse_y = mouse_y;
+ hx_mouse_x = mouse_x;
+
+ storew((zword) (zargs[0] + 0), hx_mouse_y);
+ storew((zword) (zargs[0] + 2), hx_mouse_x);
+ storew((zword) (zargs[0] + 4), btn); // mouse button bits
+ storew((zword) (zargs[0] + 6), menu_selected); // menu selection
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_maths.cpp b/engines/gargoyle/frotz/processor_maths.cpp
new file mode 100644
index 0000000..e64dd55
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_maths.cpp
@@ -0,0 +1,105 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+void Processor::z_add() {
+ store((zword)((short)zargs[0] + (short)zargs[1]));
+}
+
+void Processor::z_and() {
+ store((zword)(zargs[0] & zargs[1]));
+}
+
+void Processor::z_art_shift() {
+ if ((short)zargs[1] > 0)
+ store((zword)((short)zargs[0] << (short)zargs[1]));
+ else
+ store((zword)((short)zargs[0] >> - (short)zargs[1]));
+}
+
+void Processor::z_div() {
+ if (zargs[1] == 0)
+ runtimeError(ERR_DIV_ZERO);
+
+ store((zword)((short)zargs[0] / (short)zargs[1]));
+}
+
+void Processor::z_je() {
+ branch(
+ zargc > 1 && (zargs[0] == zargs[1] || (
+ zargc > 2 && (zargs[0] == zargs[2] || (
+ zargc > 3 && (zargs[0] == zargs[3])))))
+ );
+}
+
+void Processor::z_jg() {
+ branch((short)zargs[0] > (short)zargs[1]);
+}
+
+void Processor::z_jl() {
+ branch((short)zargs[0] < (short)zargs[1]);
+}
+
+void Processor::z_jz() {
+ branch((short)zargs[0] == 0);
+}
+
+void Processor::z_log_shift() {
+ if ((short)zargs[1] > 0)
+ store((zword)(zargs[0] << (short)zargs[1]));
+ else
+ store((zword)(zargs[0] >> - (short)zargs[1]));
+}
+
+void Processor::z_mod() {
+ if (zargs[1] == 0)
+ runtimeError(ERR_DIV_ZERO);
+
+ store((zword)((short)zargs[0] % (short)zargs[1]));
+}
+
+void Processor::z_mul() {
+ store((zword)((short)zargs[0] * (short)zargs[1]));
+}
+
+void Processor::z_not() {
+ store((zword)~zargs[0]);
+}
+
+void Processor::z_or() {
+ store((zword)(zargs[0] | zargs[1]));
+}
+
+void Processor::z_sub() {
+ store((zword)((short)zargs[0] - (short)zargs[1]));
+}
+
+void Processor::z_test() {
+ branch((zargs[0] & zargs[1]) == zargs[1]);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_objects.cpp b/engines/gargoyle/frotz/processor_objects.cpp
new file mode 100644
index 0000000..3d2b171
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_objects.cpp
@@ -0,0 +1,735 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Method stubs to implement
+static void new_line() {}
+
+#define MAX_OBJECT 2000
+
+enum O1 {
+ O1_PARENT = 4,
+ O1_SIBLING = 5,
+ O1_CHILD = 6,
+ O1_PROPERTY_OFFSET = 7,
+ O1_SIZE = 9
+};
+
+enum O4 {
+ O4_PARENT = 6,
+ O4_SIBLING = 8,
+ O4_CHILD = 10,
+ O4_PROPERTY_OFFSET = 12,
+ O4_SIZE = 14
+};
+
+zword Processor::object_address(zword obj) {
+ // Check object number
+ if (obj > ((h_version <= V3) ? 255 : MAX_OBJECT)) {
+ print_string("@Attempt to address illegal object ");
+ print_num(obj);
+ print_string(". This is normally fatal.");
+ new_line();
+ runtimeError(ERR_ILL_OBJ);
+ }
+
+ // Return object address
+ if (h_version <= V3)
+ return h_objects + ((obj - 1) * O1_SIZE + 62);
+ else
+ return h_objects + ((obj - 1) * O4_SIZE + 126);
+}
+
+zword Processor::object_name(zword object) {
+ zword obj_addr;
+ zword name_addr;
+
+ obj_addr = object_address(object);
+
+ // The object name address is found at the start of the properties
+ if (h_version <= V3)
+ obj_addr += O1_PROPERTY_OFFSET;
+ else
+ obj_addr += O4_PROPERTY_OFFSET;
+
+ LOW_WORD(obj_addr, name_addr);
+
+ return name_addr;
+}
+
+zword Processor::first_property(zword obj) {
+ zword prop_addr;
+ zbyte size;
+
+ // Fetch address of object name
+ prop_addr = object_name (obj);
+
+ // Get length of object name
+ LOW_BYTE(prop_addr, size);
+
+ // Add name length to pointer
+ return prop_addr + 1 + 2 * size;
+}
+
+zword Processor::next_property(zword prop_addr) {
+ zbyte value;
+
+ // Load the current property id
+ LOW_BYTE(prop_addr, value);
+ prop_addr++;
+
+ // Calculate the length of this property
+ if (h_version <= V3)
+ value >>= 5;
+ else if (!(value & 0x80))
+ value >>= 6;
+ else {
+ LOW_BYTE(prop_addr, value);
+ value &= 0x3f;
+
+ if (value == 0)
+ // demanded by Spec 1.0
+ value = 64;
+ }
+
+ // Add property length to current property pointer
+ return prop_addr + value + 1;
+}
+
+void Processor::unlink_object(zword object) {
+ zword obj_addr;
+ zword parent_addr;
+ zword sibling_addr;
+
+ if (object == 0) {
+ runtimeError(ERR_REMOVE_OBJECT_0);
+ return;
+ }
+
+ obj_addr = object_address(object);
+
+ if (h_version <= V3) {
+
+ zbyte parent;
+ zbyte younger_sibling;
+ zbyte older_sibling;
+ zbyte zero = 0;
+
+ // Get parent of object, and return if no parent
+ obj_addr += O1_PARENT;
+ LOW_BYTE(obj_addr, parent);
+ if (!parent)
+ return;
+
+ // Get (older) sibling of object and set both parent and sibling pointers to 0
+ SET_BYTE(obj_addr, zero);
+ obj_addr += O1_SIBLING - O1_PARENT;
+ LOW_BYTE(obj_addr, older_sibling);
+ SET_BYTE(obj_addr, zero);
+
+ // Get first child of parent (the youngest sibling of the object)
+ parent_addr = object_address(parent) + O1_CHILD;
+ LOW_BYTE(parent_addr, younger_sibling);
+
+ // Remove object from the list of siblings
+ if (younger_sibling == object)
+ SET_BYTE(parent_addr, older_sibling);
+ else {
+ do {
+ sibling_addr = object_address(younger_sibling) + O1_SIBLING;
+ LOW_BYTE(sibling_addr, younger_sibling);
+ } while (younger_sibling != object);
+ SET_BYTE(sibling_addr, older_sibling);
+ }
+ } else {
+ zword parent;
+ zword younger_sibling;
+ zword older_sibling;
+ zword zero = 0;
+
+ // Get parent of object, and return if no parent
+ obj_addr += O4_PARENT;
+ LOW_WORD(obj_addr, parent);
+ if (!parent)
+ return;
+
+ // Get (older) sibling of object and set both parent and sibling pointers to 0
+ SET_WORD(obj_addr, zero);
+ obj_addr += O4_SIBLING - O4_PARENT;
+ LOW_WORD(obj_addr, older_sibling);
+ SET_WORD(obj_addr, zero);
+
+ // Get first child of parent (the youngest sibling of the object)
+ parent_addr = object_address(parent) + O4_CHILD;
+ LOW_WORD(parent_addr, younger_sibling);
+
+ // Remove object from the list of siblings
+ if (younger_sibling == object) {
+ SET_WORD(parent_addr, older_sibling);
+ } else {
+ do {
+ sibling_addr = object_address(younger_sibling) + O4_SIBLING;
+ LOW_WORD(sibling_addr, younger_sibling);
+ } while (younger_sibling != object);
+ SET_WORD(sibling_addr, older_sibling);
+ }
+ }
+}
+
+void Processor::z_clear_attr() {
+ zword obj_addr;
+ zbyte value;
+
+ if (_storyId == SHERLOCK)
+ if (zargs[1] == 48)
+ return;
+
+ if (zargs[1] > ((h_version <= V3) ? 31 : 47))
+ runtimeError(ERR_ILL_ATTR);
+
+ // If we are monitoring attribute assignment display a short note
+ if (_attribute_assignment) {
+ stream_mssg_on();
+ print_string("@clear_attr ");
+ print_object(zargs[0]);
+ print_string(" ");
+ print_num(zargs[1]);
+ stream_mssg_off();
+ }
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_CLEAR_ATTR_0);
+ return;
+ }
+
+ // Get attribute address
+ obj_addr = object_address(zargs[0]) + zargs[1] / 8;
+
+ // Clear attribute bit
+ LOW_BYTE(obj_addr, value);
+ value &= ~(0x80 >> (zargs[1] & 7));
+ SET_BYTE(obj_addr, value);
+}
+
+void Processor::z_jin() {
+ zword obj_addr;
+
+ // If we are monitoring object locating display a short note
+ if (_object_locating) {
+ stream_mssg_on();
+ print_string("@jin ");
+ print_object(zargs[0]);
+ print_string(" ");
+ print_object(zargs[1]);
+ stream_mssg_off();
+ }
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_JIN_0);
+ branch(0 == zargs[1]);
+ return;
+ }
+
+ obj_addr = object_address(zargs[0]);
+
+ if (h_version <= V3) {
+ zbyte parent;
+
+ // Get parent id from object
+ obj_addr += O1_PARENT;
+ LOW_BYTE(obj_addr, parent);
+
+ // Branch if the parent is obj2
+ branch(parent == zargs[1]);
+
+ } else {
+ zword parent;
+
+ // Get parent id from object
+ obj_addr += O4_PARENT;
+ LOW_WORD(obj_addr, parent);
+
+ // Branch if the parent is obj2
+ branch(parent == zargs[1]);
+ }
+}
+
+void Processor::z_get_child() {
+ zword obj_addr;
+
+ // If we are monitoring object locating display a short note
+ if (_object_locating) {
+ stream_mssg_on();
+ print_string("@get_child ");
+ print_object(zargs[0]);
+ stream_mssg_off();
+ }
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_GET_CHILD_0);
+ store(0);
+ branch(false);
+ return;
+ }
+
+ obj_addr = object_address(zargs[0]);
+
+ if (h_version <= V3) {
+ zbyte child;
+
+ // Get child id from object
+ obj_addr += O1_CHILD;
+ LOW_BYTE(obj_addr, child);
+
+ // Store child id and branch
+ store(child);
+ branch(child);
+ } else {
+ zword child;
+
+ // Get child id from object
+ obj_addr += O4_CHILD;
+ LOW_WORD(obj_addr, child);
+
+ // Store child id and branch
+ store(child);
+ branch(child);
+ }
+}
+
+void Processor::z_get_next_prop() {
+ zword prop_addr;
+ zbyte value;
+ zbyte mask;
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_GET_NEXT_PROP_0);
+ store(0);
+ return;
+ }
+
+ // Property id is in bottom five (six) bits
+ mask = (h_version <= V3) ? 0x1f : 0x3f;
+
+ // Load address of first property
+ prop_addr = first_property(zargs[0]);
+
+ if (zargs[1] != 0) {
+ // Scan down the property list
+ do {
+ LOW_BYTE(prop_addr, value);
+ prop_addr = next_property(prop_addr);
+ } while ((value & mask) > zargs[1]);
+
+ // Exit if the property does not exist
+ if ((value & mask) != zargs[1])
+ runtimeError(ERR_NO_PROP);
+ }
+
+ // Return the property id
+ LOW_BYTE(prop_addr, value);
+ store((zword) (value & mask));
+}
+
+void Processor::z_get_parent() {
+ zword obj_addr;
+
+ // If we are monitoring object locating display a short note
+ if (_object_locating) {
+ stream_mssg_on();
+ print_string("@get_parent ");
+ print_object(zargs[0]);
+ stream_mssg_off();
+ }
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_GET_PARENT_0);
+ store(0);
+ return;
+ }
+
+ obj_addr = object_address(zargs[0]);
+
+ if (h_version <= V3) {
+ zbyte parent;
+
+ // Get parent id from object
+ obj_addr += O1_PARENT;
+ LOW_BYTE(obj_addr, parent);
+
+ // Store parent
+ store(parent);
+
+ } else {
+ zword parent;
+
+ // Get parent id from object
+ obj_addr += O4_PARENT;
+ LOW_WORD(obj_addr, parent);
+
+ // Store parent
+ store(parent);
+ }
+}
+
+void Processor::z_get_prop() {
+ zword prop_addr;
+ zword wprop_val;
+ zbyte bprop_val;
+ zbyte value;
+ zbyte mask;
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_GET_PROP_0);
+ store(0);
+ return;
+ }
+
+ // Property id is in bottom five (six) bits
+ mask = (h_version <= V3) ? 0x1f : 0x3f;
+
+ // Load address of first property
+ prop_addr = first_property(zargs[0]);
+
+ // Scan down the property list
+ for (;;) {
+ LOW_BYTE(prop_addr, value);
+ if ((value & mask) <= zargs[1])
+ break;
+ prop_addr = next_property(prop_addr);
+ }
+
+ if ((value & mask) == zargs[1]) {
+ // property found
+
+ // Load property(byte or word sized)
+ prop_addr++;
+
+ if ((h_version <= V3 && !(value & 0xe0)) || (h_version >= V4 && !(value & 0xc0))) {
+ LOW_BYTE(prop_addr, bprop_val);
+ wprop_val = bprop_val;
+ } else {
+ LOW_WORD(prop_addr, wprop_val);
+ }
+ } else {
+ // property not found
+
+ // Load default value
+ prop_addr = h_objects + 2 * (zargs[1] - 1);
+ LOW_WORD(prop_addr, wprop_val);
+ }
+
+ // Store the property value
+ store(wprop_val);
+}
+
+void Processor::z_get_prop_addr() {
+ zword prop_addr;
+ zbyte value;
+ zbyte mask;
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_GET_PROP_ADDR_0);
+ store(0);
+ return;
+ }
+
+ if (_storyId == BEYOND_ZORK)
+ if (zargs[0] > MAX_OBJECT)
+ { store(0); return; }
+
+ // Property id is in bottom five (six) bits
+ mask = (h_version <= V3) ? 0x1f : 0x3f;
+
+ // Load address of first property
+ prop_addr = first_property(zargs[0]);
+
+ // Scan down the property list
+ for (;;) {
+ LOW_BYTE(prop_addr, value);
+ if ((value & mask) <= zargs[1])
+ break;
+ prop_addr = next_property(prop_addr);
+ }
+
+ // Calculate the property address or return zero
+ if ((value & mask) == zargs[1]) {
+
+ if (h_version >= V4 && (value & 0x80))
+ prop_addr++;
+ store((zword) (prop_addr + 1));
+
+ } else {
+ store(0);
+ }
+}
+
+void Processor::z_get_prop_len() {
+ zword addr;
+ zbyte value;
+
+ // Back up the property pointer to the property id
+ addr = zargs[0] - 1;
+ LOW_BYTE(addr, value);
+
+ // Calculate length of property
+ if (h_version <= V3)
+ value = (value >> 5) + 1;
+ else if (!(value & 0x80))
+ value = (value >> 6) + 1;
+ else {
+ value &= 0x3f;
+
+ if (value == 0)
+ value = 64; // demanded by Spec 1.0
+ }
+
+ // Store length of property
+ store(value);
+}
+
+void Processor::z_get_sibling() {
+ zword obj_addr;
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_GET_SIBLING_0);
+ store(0);
+ branch(false);
+ return;
+ }
+
+ obj_addr = object_address(zargs[0]);
+
+ if (h_version <= V3) {
+ zbyte sibling;
+
+ // Get sibling id from object
+ obj_addr += O1_SIBLING;
+ LOW_BYTE(obj_addr, sibling);
+
+ // Store sibling and branch
+ store(sibling);
+ branch(sibling);
+
+ } else {
+ zword sibling;
+
+ // Get sibling id from object
+ obj_addr += O4_SIBLING;
+ LOW_WORD(obj_addr, sibling);
+
+ // Store sibling and branch
+ store(sibling);
+ branch(sibling);
+ }
+}
+
+void Processor::z_insert_obj() {
+ zword obj1 = zargs[0];
+ zword obj2 = zargs[1];
+ zword obj1_addr;
+ zword obj2_addr;
+
+ // If we are monitoring object movements display a short note
+ if (_object_movement) {
+ stream_mssg_on();
+ print_string("@move_obj ");
+ print_object(obj1);
+ print_string(" ");
+ print_object(obj2);
+ stream_mssg_off();
+ }
+
+ if (obj1 == 0) {
+ runtimeError(ERR_MOVE_OBJECT_0);
+ return;
+ }
+
+ if (obj2 == 0) {
+ runtimeError(ERR_MOVE_OBJECT_TO_0);
+ return;
+ }
+
+ // Get addresses of both objects
+ obj1_addr = object_address(obj1);
+ obj2_addr = object_address(obj2);
+
+ // Remove object 1 from current parent
+ unlink_object(obj1);
+
+ // Make object 1 first child of object 2
+ if (h_version <= V3) {
+ zbyte child;
+
+ obj1_addr += O1_PARENT;
+ SET_BYTE(obj1_addr, obj2);
+ obj2_addr += O1_CHILD;
+ LOW_BYTE(obj2_addr, child);
+ SET_BYTE(obj2_addr, obj1);
+ obj1_addr += O1_SIBLING - O1_PARENT;
+ SET_BYTE(obj1_addr, child);
+
+ } else {
+ zword child;
+
+ obj1_addr += O4_PARENT;
+ SET_WORD(obj1_addr, obj2);
+ obj2_addr += O4_CHILD;
+ LOW_WORD(obj2_addr, child);
+ SET_WORD(obj2_addr, obj1);
+ obj1_addr += O4_SIBLING - O4_PARENT;
+ SET_WORD(obj1_addr, child);
+ }
+}
+
+void Processor::z_put_prop() {
+ zword prop_addr;
+ zword value;
+ zbyte mask;
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_PUT_PROP_0);
+ return;
+ }
+
+ // Property id is in bottom five or six bits
+ mask = (h_version <= V3) ? 0x1f : 0x3f;
+
+ // Load address of first property
+ prop_addr = first_property(zargs[0]);
+
+ // Scan down the property list
+ for (;;) {
+ LOW_BYTE(prop_addr, value);
+ if ((value & mask) <= zargs[1])
+ break;
+
+ prop_addr = next_property(prop_addr);
+ }
+
+ // Exit if the property does not exist
+ if ((value & mask) != zargs[1])
+ runtimeError(ERR_NO_PROP);
+
+ // Store the new property value (byte or word sized)
+ prop_addr++;
+
+ if ((h_version <= V3 && !(value & 0xe0)) || (h_version >= V4 && !(value & 0xc0))) {
+ zbyte v = zargs[2];
+ SET_BYTE(prop_addr, v);
+ } else {
+ zword v = zargs[2];
+ SET_WORD(prop_addr, v);
+ }
+}
+
+void Processor::z_remove_obj() {
+ // If we are monitoring object movements display a short note
+ if (_object_movement) {
+ stream_mssg_on();
+ print_string("@remove_obj ");
+ print_object(zargs[0]);
+ stream_mssg_off();
+ }
+
+ // Call unlink_object to do the job
+ unlink_object(zargs[0]);
+}
+
+void Processor::z_set_attr() {
+ zword obj_addr;
+ zbyte value;
+
+ if (_storyId == SHERLOCK)
+ if (zargs[1] == 48)
+ return;
+
+ if (zargs[1] > ((h_version <= V3) ? 31 : 47))
+ runtimeError(ERR_ILL_ATTR);
+
+ // If we are monitoring attribute assignment display a short note
+ if (_attribute_assignment) {
+ stream_mssg_on();
+ print_string("@set_attr ");
+ print_object(zargs[0]);
+ print_string(" ");
+ print_num(zargs[1]);
+ stream_mssg_off();
+ }
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_SET_ATTR_0);
+ return;
+ }
+
+ // Get attribute address
+ obj_addr = object_address(zargs[0]) + zargs[1] / 8;
+
+ // Load attribute byte
+ LOW_BYTE(obj_addr, value);
+
+ // Set attribute bit
+ value |= 0x80 >> (zargs[1] & 7);
+
+ // Store attribute byte
+ SET_BYTE(obj_addr, value);
+}
+
+void Processor::z_test_attr() {
+ zword obj_addr;
+ zbyte value;
+
+ if (zargs[1] > ((h_version <= V3) ? 31 : 47))
+ runtimeError(ERR_ILL_ATTR);
+
+ // If we are monitoring attribute testing display a short note
+ if (_attribute_testing) {
+ stream_mssg_on();
+ print_string("@test_attr ");
+ print_object(zargs[0]);
+ print_string(" ");
+ print_num(zargs[1]);
+ stream_mssg_off();
+ }
+
+ if (zargs[0] == 0) {
+ runtimeError(ERR_TEST_ATTR_0);
+ branch(false);
+ return;
+ }
+
+ // Get attribute address
+ obj_addr = object_address(zargs[0]) + zargs[1] / 8;
+
+ // Load attribute byte
+ LOW_BYTE(obj_addr, value);
+
+ // Test attribute
+ branch(value & (0x80 >> (zargs[1] & 7)));
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_screen.cpp b/engines/gargoyle/frotz/processor_screen.cpp
new file mode 100644
index 0000000..5b3b8cb
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_screen.cpp
@@ -0,0 +1,455 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Method stubs to implement
+static void storew(zword, zword) {}
+static void print_char(zchar) {}
+
+
+void Processor::screen_char(zchar c) {
+ // TODO
+}
+
+void Processor::screen_new_line() {
+ // TODO
+}
+
+void Processor::screen_word(const zchar *s) {
+ // TODO
+}
+
+void Processor::screen_mssg_on() {
+ // TODO
+}
+
+void Processor::screen_mssg_off() {
+ // TODO
+}
+
+
+void Processor::z_buffer_mode() {
+}
+
+void Processor::z_buffer_screen() {
+ store(0);
+}
+
+void Processor::z_erase_line() {
+ int i;
+
+ if (gos_upper && gos_curwin == gos_upper) {
+ for (i = 0; i < h_screen_cols + 1 - curx; i++)
+ glk_put_char(' ');
+ glk_window_move_cursor(gos_curwin, curx - 1, cury - 1);
+ }
+}
+
+void Processor::z_erase_window() {
+ short w = zargs[0];
+ if (w == -2)
+ {
+ if (gos_upper) {
+ glk_set_window(gos_upper);
+#ifdef GARGLK
+ garglk_set_zcolors(curr_fg, curr_bg);
+#endif /* GARGLK */
+ glk_window_clear(gos_upper);
+ glk_set_window(gos_curwin);
+ }
+ glk_window_clear(gos_lower);
+ }
+ if (w == -1)
+ {
+ if (gos_upper) {
+ glk_set_window(gos_upper);
+#ifdef GARGLK
+ garglk_set_zcolors(curr_fg, curr_bg);
+#endif /* GARGLK */
+ glk_window_clear(gos_upper);
+ }
+ glk_window_clear(gos_lower);
+ split_window(0);
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+ }
+ if (w == 0)
+ glk_window_clear(gos_lower);
+ if (w == 1 && gos_upper)
+ glk_window_clear(gos_upper);
+}
+
+void Processor::z_get_cursor() {
+ storew((zword) (zargs[0] + 0), cury);
+ storew((zword) (zargs[0] + 2), curx);
+}
+
+void Processor::z_print_table() {
+ zword addr = zargs[0];
+ zword x;
+ int i, j;
+
+ // Supply default arguments
+ if (zargc < 3)
+ zargs[2] = 1;
+ if (zargc < 4)
+ zargs[3] = 0;
+
+ // Write text in width x height rectangle
+ x = curx;
+
+ for (i = 0; i < zargs[2]; i++) {
+ if (i != 0) {
+ cury += 1;
+ curx = x;
+ }
+
+ for (j = 0; j < zargs[1]; j++) {
+
+ zbyte c;
+
+ LOW_BYTE(addr, c);
+ addr++;
+
+ print_char(c);
+ }
+
+ addr += zargs[3];
+ }
+}
+
+#define zB(i) ((((i >> 10) & 0x1F) << 3) | (((i >> 10) & 0x1F) >> 2))
+#define zG(i) ((((i >> 5) & 0x1F) << 3) | (((i >> 5) & 0x1F) >> 2))
+#define zR(i) ((((i ) & 0x1F) << 3) | (((i ) & 0x1F) >> 2))
+
+#define zRGB(i) (zR(i) << 16 | zG(i) << 8 | zB(i))
+
+void Processor::z_set_true_colour() {
+ int zfore = zargs[0];
+ int zback = zargs[1];
+
+ if (!(zfore < 0))
+ zfore = zRGB(zargs[0]);
+
+ if (!(zback < 0))
+ zback = zRGB(zargs[1]);
+
+#ifdef GARGLK
+ garglk_set_zcolors(zfore, zback);
+#endif /* GARGLK */
+
+ curr_fg = zfore;
+ curr_bg = zback;
+}
+
+static const int zcolor_map[] = {
+ -2, ///< 0 = current
+ -1, ///< 1 = default
+ 0x0000, ///< 2 = black
+ 0x001D, ///< 3 = red
+ 0x0340, ///< 4 = green
+ 0x03BD, ///< 5 = yellow
+ 0x59A0, ///< 6 = blue
+ 0x7C1F, ///< 7 = magenta
+ 0x77A0, ///< 8 = cyan
+ 0x7FFF, ///< 9 = white
+ 0x5AD6, ///< 10 = light grey
+ 0x4631, ///< 11 = medium grey
+ 0x2D6B, ///< 12 = dark grey
+};
+
+#define zcolor_NUMCOLORS (13)
+
+void Processor::z_set_colour() {
+ int zfore = zargs[0];
+ int zback = zargs[1];
+
+ switch (zfore) {
+ case -1:
+ zfore = -3;
+ break;
+
+ case 0:
+ case 1:
+ zfore = zcolor_map[zfore];
+ break;
+
+ default:
+ if (zfore < zcolor_NUMCOLORS)
+ zfore = zRGB(zcolor_map[zfore]);
+ break;
+ }
+
+ switch (zback) {
+ case -1:
+ zback = -3;
+
+ case 0:
+ case 1:
+ zback = zcolor_map[zback];
+ break;
+
+ default:
+ if (zback < zcolor_NUMCOLORS)
+ zback = zRGB(zcolor_map[zback]);
+ break;
+ }
+
+#ifdef GARGLK
+ garglk_set_zcolors(zfore, zback);
+#endif /* GARGLK */
+
+ curr_fg = zfore;
+ curr_bg = zback;
+}
+
+void Processor::z_set_font() {
+ zword font = zargs[0];
+
+ switch (font) {
+ case 0:
+ // previous font
+ temp_font = curr_font;
+ curr_font = prev_font;
+ prev_font = temp_font;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store (curr_font);
+ break;
+
+ case 1: /* normal font */
+ prev_font = curr_font;
+ curr_font = 1;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store (prev_font);
+ break;
+
+ case 4: /* fixed-pitch font*/
+ prev_font = curr_font;
+ curr_font = 4;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store (prev_font);
+ break;
+
+ case 2: // picture font, undefined per 1.1
+ case 3: // character graphics font
+ default: // unavailable
+ store (0);
+ break;
+ }
+}
+
+void Processor::z_set_cursor() {
+ cury = zargs[0];
+ curx = zargs[1];
+
+ if (gos_upper) {
+ if (cury > mach_status_ht) {
+ mach_status_ht = cury;
+ reset_status_ht();
+ }
+
+ glk_window_move_cursor(gos_upper, curx - 1, cury - 1);
+ }
+}
+
+void Processor::z_set_text_style() {
+ int style;
+
+ if (zargs[0] == 0)
+ curstyle = 0;
+ else if (zargs[0] != 0xf000) /* not tickle time */
+ curstyle |= zargs[0];
+
+ if (h_flags & FIXED_FONT_FLAG || curr_font == 4)
+ style = curstyle | FIXED_WIDTH_STYLE;
+ else
+ style = curstyle;
+
+ if (gos_linepending && gos_curwin == gos_linewin)
+ return;
+
+ if (style & REVERSE_STYLE) {
+#ifdef GARGLK
+ garglk_set_reversevideo(true);
+#endif /* GARGLK */
+ }
+
+ if (style & FIXED_WIDTH_STYLE) {
+ if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+ glk_set_style(style_BlockQuote); // monoz
+ else if (style & EMPHASIS_STYLE)
+ glk_set_style(style_Alert); // monoi
+ else if (style & BOLDFACE_STYLE)
+ glk_set_style(style_Subheader); // monob
+ else
+ glk_set_style(style_Preformatted); // monor
+ } else {
+ if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+ glk_set_style(style_Note); // propz
+ else if (style & EMPHASIS_STYLE)
+ glk_set_style(style_Emphasized); // propi
+ else if (style & BOLDFACE_STYLE)
+ glk_set_style(style_Header); // propb
+ else
+ glk_set_style(style_Normal); // propr
+ }
+
+ if (curstyle == 0) {
+#ifdef GARGLK
+ garglk_set_reversevideo(false);
+#endif /* GARGLK */
+ }
+}
+
+void Processor::z_set_window() {
+ int win = zargs[0];
+
+ if (win == 0) {
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+ } else {
+ if (gos_upper)
+ glk_set_window(gos_upper);
+ gos_curwin = gos_upper;
+ }
+
+ if (win == 0)
+ enable_scripting = true;
+ else
+ enable_scripting = false;
+
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+}
+
+void Processor::pad_status_line(int column) {
+ int spaces;
+ spaces = (h_screen_cols + 1 - curx) - column;
+ while (spaces-- > 0)
+ print_char(' ');
+}
+
+void Processor::z_show_status() {
+ zword global0;
+ zword global1;
+ zword global2;
+ zword addr;
+
+ bool brief = false;
+
+ if (!gos_upper)
+ return;
+
+ // One V5 game (Wishbringer Solid Gold) contains this opcode by accident,
+ // so just return if the version number does not fit
+ if (h_version >= V4)
+ return;
+
+ // Read all relevant global variables from the memory of the Z-machine
+ // into local variables
+
+ addr = h_globals;
+ LOW_WORD(addr, global0);
+ addr += 2;
+ LOW_WORD(addr, global1);
+ addr += 2;
+ LOW_WORD(addr, global2);
+
+ // Move to top of the status window, and print in reverse style.
+ glk_set_window(gos_upper);
+ gos_curwin = gos_upper;
+
+#ifdef GARGLK
+ garglk_set_reversevideo(true);
+#endif /* GARGLK */
+
+ curx = cury = 1;
+ glk_window_move_cursor(gos_upper, 0, 0);
+
+ // If the screen width is below 55 characters then we have to use
+ // the brief status line format
+ if (h_screen_cols < 55)
+ brief = true;
+
+ // Print the object description for the global variable 0
+ print_char (' ');
+ print_object (global0);
+
+ // A header flag tells us whether we have to display the current
+ // time or the score/moves information
+ if (h_config & CONFIG_TIME) {
+ // print hours and minutes
+ zword hours = (global1 + 11) % 12 + 1;
+
+ pad_status_line (brief ? 15 : 20);
+
+ print_string ("Time: ");
+
+ if (hours < 10)
+ print_char (' ');
+ print_num (hours);
+
+ print_char (':');
+
+ if (global2 < 10)
+ print_char ('0');
+ print_num (global2);
+
+ print_char (' ');
+
+ print_char ((global1 >= 12) ? 'p' : 'a');
+ print_char ('m');
+
+ } else {
+ // print score and moves
+ pad_status_line (brief ? 15 : 30);
+
+ print_string (brief ? "S: " : "Score: ");
+ print_num (global1);
+
+ pad_status_line (brief ? 8 : 14);
+
+ print_string (brief ? "M: " : "Moves: ");
+ print_num (global2);
+ }
+
+ // Pad the end of the status line with spaces
+ pad_status_line (0);
+
+ // Return to the lower window
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+}
+
+void Processor::z_split_window() {
+ split_window(zargs[0]);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
new file mode 100644
index 0000000..5fe526f
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -0,0 +1,533 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Implement method stubs
+static void os_scrollback_char(zchar) {}
+static void os_scrollback_erase(zword) {}
+static void flush_buffer() {}
+static void script_open() {}
+static void script_close() {}
+static void script_mssg_on() {}
+static void script_mssg_off() {}
+static void script_char(zchar) {}
+static void script_word(const zchar *) {}
+static void script_new_line() {}
+static void script_erase_input(const zchar *) {}
+static void script_write_input(zchar *, char) {}
+static void memory_open(zword, zword, bool) {}
+static void memory_close() {}
+static void memory_word(const zchar *) {}
+static void memory_new_line() {}
+static void replay_open() {}
+static void replay_close() {}
+static zchar replay_read_key() { return 0; }
+static zchar replay_read_input(zchar *) { return 0; }
+static zchar console_read_key(zword) { return 0; }
+static zchar console_read_input(uint, zchar *, uint, bool) { return 0; }
+static void record_open() {}
+static void record_close() {}
+static void record_write_key(zchar) {}
+static void record_write_input(zchar *, zchar) {}
+static void os_restart_game(zword) {}
+static void restart_header() {}
+
+
+void Processor::scrollback_char (zchar c) {
+ if (c == ZC_INDENT)
+ { scrollback_char (' '); scrollback_char (' '); scrollback_char (' '); return; }
+ if (c == ZC_GAP)
+ { scrollback_char (' '); scrollback_char (' '); return; }
+
+ os_scrollback_char(c);
+}
+
+void Processor::scrollback_word(const zchar *s) {
+ int i;
+
+ for (i = 0; s[i] != 0; i++) {
+ if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
+ i++;
+ else
+ scrollback_char(s[i]);
+ }
+}
+
+void Processor::scrollback_write_input(const zchar *buf, zchar key) {
+ int i;
+
+ for (i = 0; buf[i] != 0; i++)
+ scrollback_char (buf[i]);
+
+ if (key == ZC_RETURN)
+ scrollback_char ('\n');
+}
+
+void Processor::scrollback_erase_input(const zchar *buf) {
+ int width;
+ int i;
+
+ for (i = 0, width = 0; buf[i] != 0; i++)
+ width++;
+
+ os_scrollback_erase(width);
+
+}
+
+void Processor::stream_mssg_on() {
+ flush_buffer();
+
+ if (ostream_screen)
+ screen_mssg_on();
+ if (ostream_script && enable_scripting)
+ script_mssg_on();
+
+ message = true;
+}
+
+void Processor::stream_mssg_off() {
+ flush_buffer();
+
+ if (ostream_screen)
+ screen_mssg_off();
+ if (ostream_script && enable_scripting)
+ script_mssg_off();
+
+ message = false;
+}
+
+void Processor::stream_char(zchar c) {
+ if (ostream_screen)
+ screen_char(c);
+ if (ostream_script && enable_scripting)
+ script_char(c);
+ if (enable_scripting)
+ scrollback_char(c);
+}
+
+void Processor::stream_word(const zchar *s) {
+ if (ostream_memory && !message)
+ memory_word(s);
+ else {
+ if (ostream_screen)
+ screen_word(s);
+ if (ostream_script && enable_scripting)
+ script_word(s);
+ if (enable_scripting)
+ scrollback_word(s);
+ }
+}
+
+void Processor::stream_new_line() {
+ if (ostream_memory && !message)
+ memory_new_line();
+ else {
+ if (ostream_screen)
+ screen_new_line();
+ if (ostream_script && enable_scripting)
+ script_new_line();
+ if (enable_scripting)
+ os_scrollback_char ('\n');
+ }
+}
+
+zchar Processor::stream_read_key(zword timeout, zword routine, bool hot_keys) {
+ zchar key = ZC_BAD;
+
+ flush_buffer();
+
+ // Read key from current input stream
+continue_input:
+
+ do {
+ if (istream_replay)
+ key = replay_read_key();
+ else
+ key = console_read_key(timeout);
+ } while (key == ZC_BAD);
+
+ // Copy key to the command file
+ if (ostream_record && !istream_replay)
+ record_write_key(key);
+
+ // Handle timeouts
+ if (key == ZC_TIME_OUT)
+ if (direct_call (routine) == 0)
+ goto continue_input;
+
+ // Return key
+ return key;
+}
+
+zchar Processor::stream_read_input(int max, zchar *buf, zword timeout, zword routine,
+ bool hot_keys, bool no_scripting) {
+ zchar key = ZC_BAD;
+ bool no_scrollback = no_scripting;
+
+ if (h_version == V6 && _storyId == UNKNOWN && !ostream_script)
+ no_scrollback = false;
+
+ flush_buffer();
+
+ // Remove initial input from the transscript file or from the screen
+ if (ostream_script && enable_scripting && !no_scripting)
+ script_erase_input(buf);
+
+ // Read input line from current input stream
+continue_input:
+
+ do {
+ if (istream_replay)
+ key = replay_read_input(buf);
+ else
+ key = console_read_input(max, buf, timeout, key != ZC_BAD);
+ } while (key == ZC_BAD);
+
+ // Copy input line to the command file
+ if (ostream_record && !istream_replay)
+ record_write_input(buf, key);
+
+ // Handle timeouts
+ if (key == ZC_TIME_OUT)
+ if (direct_call(routine) == 0)
+ goto continue_input;
+
+ // Copy input line to transscript file or to the screen
+ if (ostream_script && enable_scripting && !no_scripting)
+ script_write_input(buf, key);
+
+ // Return terminating key
+ return key;
+}
+
+void Processor::z_input_stream() {
+ flush_buffer();
+
+ if (zargs[0] == 0 && istream_replay)
+ replay_close();
+ if (zargs[0] == 1 && !istream_replay)
+ replay_open();
+}
+
+void Processor::z_output_stream() {
+ flush_buffer();
+
+ switch ((short) zargs[0]) {
+ case 1: ostream_screen = true;
+ break;
+ case -1: ostream_screen = false;
+ break;
+ case 2: if (!ostream_script) script_open();
+ break;
+ case -2: if (ostream_script) script_close();
+ break;
+ case 3: memory_open(zargs[1], zargs[2], zargc >= 3);
+ break;
+ case -3: memory_close();
+ break;
+ case 4: if (!ostream_record) record_open();
+ break;
+ case -4: if (ostream_record) record_close();
+ break;
+ default:
+ break;
+ }
+}
+
+void Processor::z_restart(void) {
+ flush_buffer();
+
+ os_restart_game(RESTART_BEGIN);
+
+ seed_random(0);
+
+ if (!first_restart) {
+ story_fp->seek(blorb_ofs);
+
+ if (story_fp->read(zmp, h_dynamic_size) != h_dynamic_size)
+ error("Story file read error");
+
+ } else {
+ first_restart = false;
+ }
+
+ restart_header();
+ restart_screen();
+
+ _sp = _fp = _stack + STACK_SIZE;
+ _frameCount = 0;
+
+ if (h_version != V6 && h_version != V9) {
+ long pc = (long)h_start_pc;
+ SET_PC(pc);
+ } else {
+ call(h_start_pc, 0, nullptr, 0);
+ }
+
+ os_restart_game(RESTART_END);
+}
+
+
+void Processor::z_save(void) {
+#ifdef TODO
+ bool success = false;
+
+ if (zargc != 0) {
+ // Open auxilary file
+ frefid_t ref = glk_fileref_create_by_prompt(fileusage_Data | fileusage_BinaryMode,
+ filemode_Write, 0);
+ if (ref == nullptr)
+ goto finished;
+
+ // Write data
+ strid_t f = glk_stream_open_file(ref, filemode_Write);
+
+ glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
+
+ stream_result_t result;
+ glk_stream_close(f, &result);
+
+ } else {
+ long pc;
+ zword addr;
+ zword nsp, nfp;
+ int skip;
+ int i;
+
+ /* Open game file */
+
+ if ((gfp = frotzopenprompt (FILE_SAVE)) == nullptr)
+ goto finished;
+
+ if (option_save_quetzal) {
+ success = save_quetzal (gfp, story_fp, blorb_ofs);
+ } else {
+ /* Write game file */
+
+ fputc ((int) hi (h_release), gfp);
+ fputc ((int) lo (h_release), gfp);
+ fputc ((int) hi (h_checksum), gfp);
+ fputc ((int) lo (h_checksum), gfp);
+
+ GET_PC (pc)
+
+ fputc ((int) (pc >> 16) & 0xff, gfp);
+ fputc ((int) (pc >> 8) & 0xff, gfp);
+ fputc ((int) (pc) & 0xff, gfp);
+
+ nsp = (int) (_sp - _stack);
+ nfp = (int) (_fp - _stack);
+
+ fputc ((int) hi (nsp), gfp);
+ fputc ((int) lo (nsp), gfp);
+ fputc ((int) hi (nfp), gfp);
+ fputc ((int) lo (nfp), gfp);
+
+ for (i = nsp; i < STACK_SIZE; i++) {
+ fputc ((int) hi (_stack[i]), gfp);
+ fputc ((int) lo (_stack[i]), gfp);
+ }
+
+ fseek (story_fp, blorb_ofs, SEEK_SET);
+
+ for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
+ if (zmp[addr] != fgetc (story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
+ fputc (skip, gfp);
+ fputc (zmp[addr], gfp);
+ skip = 0;
+ } else skip++;
+ }
+
+ /* Close game file and check for errors */
+
+ if (fclose (gfp) == EOF || ferror (story_fp)) {
+ print_string ("Error writing save file\n");
+ goto finished;
+ }
+
+ /* Success */
+
+ success = 1;
+
+ }
+
+finished:
+
+ if (h_version <= V3)
+ branch (success);
+ else
+ store (success);
+#endif
+}
+
+void Processor::z_restore() {
+#ifdef TODO
+ FILE *gfp;
+
+ zword success = 0;
+
+ if (zargc != 0) {
+
+ /* Get the file name */
+
+ /* Open auxilary file */
+
+ if ((gfp = frotzopenprompt(FILE_LOAD_AUX)) == nullptr)
+ goto finished;
+
+ /* Load auxilary file */
+
+ success = fread (zmp + zargs[0], 1, zargs[1], gfp);
+
+ /* Close auxilary file */
+
+ fclose (gfp);
+
+ } else {
+
+ long pc;
+ zword release;
+ zword addr;
+ int i;
+
+ /* Open game file */
+
+ if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
+ goto finished;
+
+ if (option_save_quetzal) {
+ success = restore_quetzal (gfp, story_fp, blorb_ofs);
+
+ } else {
+ /* Load game file */
+
+ release = (unsigned) fgetc (gfp) << 8;
+ release |= fgetc (gfp);
+
+ (void) fgetc (gfp);
+ (void) fgetc (gfp);
+
+ /* Check the release number */
+
+ if (release == h_release) {
+
+ pc = (long) fgetc (gfp) << 16;
+ pc |= (unsigned) fgetc (gfp) << 8;
+ pc |= fgetc (gfp);
+
+ SET_PC (pc);
+
+ _sp = _stack + (fgetc (gfp) << 8);
+ _sp += fgetc (gfp);
+ _fp = _stack + (fgetc (gfp) << 8);
+ _fp += fgetc (gfp);
+
+ for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
+ _stack[i] = (unsigned) fgetc (gfp) << 8;
+ _stack[i] |= fgetc (gfp);
+ }
+
+ fseek (story_fp, blorb_ofs, SEEK_SET);
+
+ for (addr = 0; addr < h_dynamic_size; addr++) {
+ int skip = fgetc (gfp);
+ for (i = 0; i < skip; i++)
+ zmp[addr++] = fgetc (story_fp);
+ zmp[addr] = fgetc (gfp);
+ (void) fgetc (story_fp);
+ }
+
+ /* Check for errors */
+
+ if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
+ success = -1;
+ else
+
+ /* Success */
+
+ success = 2;
+
+ } else print_string ("Invalid save file\n");
+ }
+
+ if ((short) success >= 0) {
+
+ /* Close game file */
+
+ fclose (gfp);
+
+ if ((short) success > 0) {
+ zbyte old_screen_rows;
+ zbyte old_screen_cols;
+
+ /* In V3, reset the upper window. */
+ if (h_version == V3)
+ split_window (0);
+
+ LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
+ LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
+
+ /* Reload cached header fields. */
+ restart_header ();
+
+ /*
+ * Since QUETZAL files may be saved on many different machines,
+ * the screen sizes may vary a lot. Erasing the status window
+ * seems to cover up most of the resulting badness.
+ */
+ if (h_version > V3 && h_version != V6
+ && (h_screen_rows != old_screen_rows
+ || h_screen_cols != old_screen_cols))
+ erase_window (1);
+ }
+ } else
+ os_fatal ("Error reading save file");
+ }
+
+finished:
+
+ if (h_version <= V3)
+ branch (success);
+ else
+ store (success);
+#endif
+}
+
+void Processor::z_verify(void) {
+ zword checksum = 0;
+
+ // Sum all bytes in story file except header bytes
+ story_fp->seek(blorb_ofs + 64);
+
+ for (uint i = 64; i < story_size; i++)
+ checksum += story_fp->readByte();
+
+ // Branch if the checksums are equal
+ branch(checksum == h_checksum);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_table.cpp b/engines/gargoyle/frotz/processor_table.cpp
new file mode 100644
index 0000000..4e660ca
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_table.cpp
@@ -0,0 +1,125 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Method stubs to implement
+static void storeb(zword, zbyte) {}
+static void storew(zword, zword) {}
+
+
+void Processor::z_copy_table() {
+ zword addr;
+ zword size = zargs[2];
+ zbyte value;
+ int i;
+
+ if (zargs[1] == 0) /* zero table */
+
+ for (i = 0; i < size; i++)
+ storeb((zword) (zargs[0] + i), 0);
+
+ else if ((short) size < 0 || zargs[0] > zargs[1]) /* copy forwards */
+
+ for (i = 0; i < (((short) size < 0) ? - (short) size : size); i++) {
+ addr = zargs[0] + i;
+ LOW_BYTE(addr, value);
+ storeb((zword) (zargs[1] + i), value);
+ } else {
+ // copy backwards
+ for (i = size - 1; i >= 0; i--) {
+ addr = zargs[0] + i;
+ LOW_BYTE(addr, value);
+ storeb((zword) (zargs[1] + i), value);
+ }
+ }
+}
+
+void Processor::z_loadb() {
+ zword addr = zargs[0] + zargs[1];
+ zbyte value;
+
+ LOW_BYTE(addr, value);
+
+ store(value);
+}
+
+void Processor::z_loadw() {
+ zword addr = zargs[0] + 2 * zargs[1];
+ zword value;
+
+ LOW_WORD(addr, value);
+
+ store(value);
+}
+
+void Processor::z_scan_table() {
+ zword addr = zargs[1];
+ int i;
+
+ // Supply default arguments
+ if (zargc < 4)
+ zargs[3] = 0x82;
+
+ // Scan byte or word array
+ for (i = 0; i < zargs[2]; i++) {
+ if (zargs[3] & 0x80) {
+ // scan word array
+ zword wvalue;
+
+ LOW_WORD(addr, wvalue);
+
+ if (wvalue == zargs[0])
+ goto finished;
+ } else {
+ // scan byte array
+ zbyte bvalue;
+
+ LOW_BYTE(addr, bvalue);
+
+ if (bvalue == zargs[0])
+ goto finished;
+ }
+
+ addr += zargs[3] & 0x7f;
+ }
+
+ addr = 0;
+
+finished:
+ store(addr);
+ branch(addr);
+}
+
+void Processor::z_storeb() {
+ storeb((zword) (zargs[0] + zargs[1]), zargs[2]);
+}
+
+void Processor::z_storew() {
+ storew((zword)(zargs[0] + 2 * zargs[1]), zargs[2]);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_text.cpp b/engines/gargoyle/frotz/processor_text.cpp
new file mode 100644
index 0000000..e660ac1
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_text.cpp
@@ -0,0 +1,904 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Replace method stubs
+static void new_line() {}
+static void print_char(zchar) {}
+static void storeb(zword, zchar) {}
+static void storew(zword, zword) {}
+
+
+zchar Processor::ZSCII_TO_LATIN1[] = {
+ 0x0e4, 0x0f6, 0x0fc, 0x0c4, 0x0d6, 0x0dc, 0x0df, 0x0bb,
+ 0x0ab, 0x0eb, 0x0ef, 0x0ff, 0x0cb, 0x0cf, 0x0e1, 0x0e9,
+ 0x0ed, 0x0f3, 0x0fa, 0x0fd, 0x0c1, 0x0c9, 0x0cd, 0x0d3,
+ 0x0da, 0x0dd, 0x0e0, 0x0e8, 0x0ec, 0x0f2, 0x0f9, 0x0c0,
+ 0x0c8, 0x0cc, 0x0d2, 0x0d9, 0x0e2, 0x0ea, 0x0ee, 0x0f4,
+ 0x0fb, 0x0c2, 0x0ca, 0x0ce, 0x0d4, 0x0db, 0x0e5, 0x0c5,
+ 0x0f8, 0x0d8, 0x0e3, 0x0f1, 0x0f5, 0x0c3, 0x0d1, 0x0d5,
+ 0x0e6, 0x0c6, 0x0e7, 0x0c7, 0x0fe, 0x0f0, 0x0de, 0x0d0,
+ 0x0a3, 0x153, 0x152, 0x0a1, 0x0bf
+};
+
+zchar Processor::translate_from_zscii(zbyte c) {
+ if (c == 0xfc)
+ return ZC_MENU_CLICK;
+ if (c == 0xfd)
+ return ZC_DOUBLE_CLICK;
+ if (c == 0xfe)
+ return ZC_SINGLE_CLICK;
+
+ if (c >= 0x9b && _storyId != BEYOND_ZORK) {
+ if (hx_unicode_table != 0) {
+ // game has its own Unicode table
+ zbyte N;
+ LOW_BYTE(hx_unicode_table, N);
+
+ if (c - 0x9b < N) {
+ zword addr = hx_unicode_table + 1 + 2 * (c - 0x9b);
+ zword unicode;
+
+ LOW_WORD(addr, unicode);
+
+ if (unicode < 0x20)
+ return '?';
+
+ return unicode;
+ } else {
+ return '?';
+ }
+ } else {
+ // game uses standard set
+ if (c <= 0xdf) {
+ return ZSCII_TO_LATIN1[c - 0x9b];
+ } else {
+ return '?';
+ }
+ }
+ }
+
+ return (zchar)c;
+}
+
+zbyte Processor::unicode_to_zscii(zchar c) {
+ int i;
+
+ if (c >= ZC_LATIN1_MIN) {
+ if (hx_unicode_table != 0) {
+ // game has its own Unicode table
+ zbyte N;
+ LOW_BYTE(hx_unicode_table, N);
+
+ for (i = 0x9b; i < 0x9b + N; i++) {
+ zword addr = hx_unicode_table + 1 + 2 * (i - 0x9b);
+ zword unicode;
+
+ LOW_WORD(addr, unicode);
+
+ if (c == unicode)
+ return (zbyte) i;
+ }
+
+ return 0;
+ } else {
+ // game uses standard set
+ for (i = 0x9b; i <= 0xdf; i++)
+ if (c == ZSCII_TO_LATIN1[i - 0x9b])
+ return (zbyte) i;
+
+ return 0;
+ }
+ }
+
+ return (zbyte)c;
+}
+
+zbyte Processor::translate_to_zscii(zchar c) {
+ if (c == ZC_SINGLE_CLICK)
+ return 0xfe;
+ if (c == ZC_DOUBLE_CLICK)
+ return 0xfd;
+ if (c == ZC_MENU_CLICK)
+ return 0xfc;
+ if (c == 0)
+ return 0;
+
+ c = unicode_to_zscii (c);
+ if (c == 0)
+ c = '?';
+
+ return (zbyte)c;
+}
+
+zchar Processor::alphabet(int set, int index) {
+ if (h_version > V1 && set == 2 && index == 1)
+ // always newline
+ return '\r';
+
+ if (h_alphabet != 0) {
+ // game uses its own alphabet
+ zbyte c;
+
+ zword addr = h_alphabet + 26 * set + index;
+ LOW_BYTE(addr, c);
+
+ return translate_from_zscii(c);
+ } else {
+ // game uses default alphabet
+ if (set == 0)
+ return 'a' + index;
+ else if (set == 1)
+ return 'A' + index;
+ else if (h_version == V1)
+ return " 0123456789.,!?_#'\"/\\<-:()"[index];
+ else
+ return " ^0123456789.,!?_#'\"/\\-:()"[index];
+ }
+}
+
+void Processor::find_resolution() {
+ zword dct = h_dictionary;
+ zword entry_count;
+ zbyte sep_count;
+ zbyte entry_len;
+
+ LOW_BYTE(dct, sep_count);
+ dct += 1 + sep_count; // skip word separators
+ LOW_BYTE(dct, entry_len);
+ dct += 1; // skip entry length
+ LOW_WORD(dct, entry_count);
+ dct += 2; // get number of entries
+
+ if (h_version < V9) {
+ _resolution = (h_version <= V3) ? 2 : 3;
+ } else {
+ zword addr = dct;
+ zword code;
+
+ if (entry_count == 0)
+ runtimeError(ERR_DICT_LEN);
+
+ // check the first word in the dictionary
+ do {
+ LOW_WORD(addr, code);
+ addr += 2;
+ } while (!(code & 0x8000) && (addr - dct < entry_len + 1));
+
+ _resolution = (addr - dct) / 2;
+ }
+
+ if (2 * _resolution > entry_len) {
+ runtimeError(ERR_DICT_LEN);
+ }
+
+ _decoded = (zchar *)malloc (sizeof (zchar) * (3 * _resolution) + 1);
+ _encoded = (zchar *)malloc (sizeof (zchar) * _resolution);
+}
+
+void Processor::load_string (zword addr, zword length) {
+ int i = 0;
+
+ if (_resolution == 0)
+ find_resolution();
+
+ while (i < 3 * _resolution) {
+ if (i < length) {
+ zbyte c;
+ LOW_BYTE(addr, c);
+ addr++;
+
+ _decoded[i++] = translate_from_zscii(c);
+ } else {
+ _decoded[i++] = 0;
+ }
+ }
+}
+
+void Processor::encode_text(int padding) {
+ static const zchar again[] = { 'a', 'g', 'a', 'i', 'n', 0, 0, 0, 0 };
+ static const zchar examine[] = { 'e', 'x', 'a', 'm', 'i', 'n', 'e', 0, 0 };
+ static const zchar wait[] = { 'w', 'a', 'i', 't', 0, 0, 0, 0, 0 };
+
+ zbyte *zchars;
+ const zchar *ptr;
+ zchar c;
+ int i = 0;
+
+ if (_resolution == 0) find_resolution();
+
+ zchars = new byte[3 * (_resolution + 1)];
+ ptr = _decoded;
+
+ // Expand abbreviations that some old Infocom games lack
+ if (_expand_abbreviations && (h_version <= V8)) {
+ if (padding == 0x05 && _decoded[1] == 0) {
+ switch (_decoded[0]) {
+ case 'g': ptr = again; break;
+ case 'x': ptr = examine; break;
+ case 'z': ptr = wait; break;
+ default: break;
+ }
+ }
+ }
+
+ // Translate string to a sequence of Z-characters
+ while (i < 3 * _resolution) {
+ if ((c = *ptr++) != 0) {
+ int index, set;
+ zbyte c2;
+
+ if (c == ' ') {
+ zchars[i++] = 0;
+ continue;
+ }
+
+ // Search character in the alphabet
+ for (set = 0; set < 3; set++)
+ for (index = 0; index < 26; index++)
+ if (c == alphabet (set, index))
+ goto letter_found;
+
+ // Character not found, store its ZSCII value
+ c2 = translate_to_zscii (c);
+
+ zchars[i++] = 5;
+ zchars[i++] = 6;
+ zchars[i++] = c2 >> 5;
+ zchars[i++] = c2 & 0x1f;
+ continue;
+
+ letter_found:
+ // Character found, store its index
+ if (set != 0)
+ zchars[i++] = ((h_version <= V2) ? 1 : 3) + set;
+
+ zchars[i++] = index + 6;
+ } else {
+ zchars[i++] = padding;
+ }
+ }
+
+ // Three Z-characters make a 16bit word
+ for (i = 0; i < _resolution; i++)
+ _encoded[i] =
+ (zchars[3 * i + 0] << 10) |
+ (zchars[3 * i + 1] << 5) |
+ (zchars[3 * i + 2]);
+
+ _encoded[_resolution - 1] |= 0x8000;
+ delete[] zchars;
+}
+
+#define outchar(c) if (st == VOCABULARY) *ptr++=c; else print_char(c)
+
+void Processor::decode_text(enum string_type st, zword addr) {
+ zchar *ptr = nullptr;
+ long byte_addr = 0;
+ zchar c2;
+ zword code;
+ zbyte c, prev_c = 0;
+ int shift_state = 0;
+ int shift_lock = 0;
+ int status = 0;
+
+ if (_resolution == 0)
+ find_resolution();
+
+ // Calculate the byte address if necessary
+ if (st == ABBREVIATION)
+ byte_addr = (long)addr << 1;
+
+ else if (st == HIGH_STRING) {
+ if (h_version <= V3)
+ byte_addr = (long)addr << 1;
+ else if (h_version <= V5)
+ byte_addr = (long)addr << 2;
+ else if (h_version <= V7)
+ byte_addr = ((long)addr << 2) + ((long)h_strings_offset << 3);
+ else if (h_version <= V8)
+ byte_addr = (long)addr << 3;
+ else {
+ // h_version == V9
+ long indirect = (long)addr << 2;
+ HIGH_LONG(indirect, byte_addr);
+ }
+
+ if ((uint)byte_addr >= story_size)
+ runtimeError(ERR_ILL_PRINT_ADDR);
+ }
+
+ // Loop until a 16bit word has the highest bit set
+ if (st == VOCABULARY)
+ ptr = _decoded;
+
+ do {
+ int i;
+
+ // Fetch the next 16bit word
+ if (st == LOW_STRING || st == VOCABULARY) {
+ LOW_WORD(addr, code);
+ addr += 2;
+ } else if (st == HIGH_STRING || st == ABBREVIATION) {
+ HIGH_WORD(byte_addr, code);
+ byte_addr += 2;
+ } else {
+ CODE_WORD(code);
+ }
+
+ // Read its three Z-characters
+ for (i = 10; i >= 0; i -= 5) {
+ zword abbr_addr;
+ zword ptr_addr;
+ zchar zc;
+
+ c = (code >> i) & 0x1f;
+
+ switch (status) {
+ case 0:
+ // normal operation
+ if (shift_state == 2 && c == 6)
+ status = 2;
+
+ else if (h_version == V1 && c == 1)
+ new_line();
+
+ else if (h_version >= V2 && shift_state == 2 && c == 7)
+ new_line();
+
+ else if (c >= 6)
+ outchar(alphabet(shift_state, c - 6));
+
+ else if (c == 0)
+ outchar(' ');
+
+ else if (h_version >= V2 && c == 1)
+ status = 1;
+
+ else if (h_version >= V3 && c <= 3)
+ status = 1;
+
+ else {
+ shift_state = (shift_lock + (c & 1) + 1) % 3;
+
+ if (h_version <= V2 && c >= 4)
+ shift_lock = shift_state;
+
+ break;
+ }
+
+ shift_state = shift_lock;
+ break;
+
+ case 1:
+ // abbreviation
+ ptr_addr = h_abbreviations + 64 * (prev_c - 1) + 2 * c;
+
+ LOW_WORD(ptr_addr, abbr_addr);
+ decode_text(ABBREVIATION, abbr_addr);
+
+ status = 0;
+ break;
+
+ case 2:
+ // ZSCII character - first part
+ status = 3;
+ break;
+
+ case 3:
+ // ZSCII character - second part
+ zc = (prev_c << 5) | c;
+
+ if (zc > 767) {
+ // Unicode escape
+ while (zc-- > 767) {
+ if (st == LOW_STRING || st == VOCABULARY) {
+ LOW_WORD(addr, c2);
+ addr += 2;
+ } else if (st == HIGH_STRING || st == ABBREVIATION) {
+ HIGH_WORD(byte_addr, c2);
+ byte_addr += 2;
+ } else
+ CODE_WORD(c2);
+
+ outchar(c2 ^ 0xFFFF);
+ }
+ } else {
+ c2 = translate_from_zscii(zc);
+ outchar(c2);
+ }
+
+ status = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ prev_c = c;
+ }
+ } while (!(code & 0x8000));
+
+ if (st == VOCABULARY)
+ *ptr = 0;
+}
+
+#undef outchar
+
+void Processor::print_num(zword value) {
+ int i;
+
+ /* Print sign */
+
+ if ((short)value < 0) {
+ print_char('-');
+ value = -(short)value;
+ }
+
+ /* Print absolute value */
+
+ for (i = 10000; i != 0; i /= 10)
+ if (value >= i || i == 1)
+ print_char('0' + (value / i) % 10);
+
+}
+
+void Processor::print_object(zword object) {
+ zword addr = object_name(object);
+ zword code = 0x94a5;
+ zbyte length;
+
+ LOW_BYTE(addr, length);
+ addr++;
+
+ if (length != 0)
+ LOW_WORD(addr, code);
+
+ if (code == 0x94a5) {
+ // _encoded text 0x94a5 == empty string
+ print_string("object#"); // supply a generic name
+ print_num(object); // for anonymous objects
+ } else {
+ decode_text(LOW_STRING, addr);
+ }
+}
+
+void Processor::print_string(const char *s) {
+ char c;
+
+ while ((c = *s++) != 0) {
+ if (c == '\n')
+ new_line();
+ else
+ print_char(c);
+ }
+}
+
+zword Processor::lookup_text(int padding, zword dct) {
+ zword entry_addr;
+ zword entry_count;
+ zword entry;
+ zword addr;
+ zbyte entry_len;
+ zbyte sep_count;
+ int entry_number;
+ int lower, upper;
+ int i;
+ bool sorted;
+
+ if (_resolution == 0)
+ find_resolution();
+
+ encode_text(padding);
+
+ LOW_BYTE(dct, sep_count); // skip word separators
+ dct += 1 + sep_count;
+ LOW_BYTE(dct, entry_len); // get length of entries
+ dct += 1;
+ LOW_WORD(dct, entry_count); // get number of entries
+ dct += 2;
+
+ if ((short)entry_count < 0) {
+ // bad luck, entries aren't sorted
+ entry_count = -(short)entry_count;
+ sorted = false;
+
+ } else {
+ sorted = true; // entries are sorted
+ }
+
+ lower = 0;
+ upper = entry_count - 1;
+
+ while (lower <= upper) {
+ if (sorted)
+ // binary search
+ entry_number = (lower + upper) / 2;
+ else
+ // linear search
+ entry_number = lower;
+
+ entry_addr = dct + entry_number * entry_len;
+
+ // Compare word to dictionary entry
+ addr = entry_addr;
+
+ for (i = 0; i < _resolution; i++) {
+ LOW_WORD(addr, entry);
+ if (_encoded[i] != entry)
+ goto continuing;
+ addr += 2;
+ }
+
+ return entry_addr; // exact match found, return now
+
+ continuing:
+ if (sorted) {
+ // binary search
+ if (_encoded[i] > entry)
+ lower = entry_number + 1;
+ else
+ upper = entry_number - 1;
+ } else {
+ // linear search
+ lower++;
+ }
+ }
+
+ // No exact match has been found
+ if (padding == 0x05)
+ return 0;
+
+ entry_number = (padding == 0x00) ? lower : upper;
+
+ if (entry_number == -1 || entry_number == entry_count)
+ return 0;
+
+ return dct + entry_number * entry_len;
+}
+
+void Processor::tokenise_text(zword text, zword length, zword from, zword parse, zword dct, bool flag) {
+ zword addr;
+ zbyte token_max, token_count;
+
+ LOW_BYTE(parse, token_max);
+ parse++;
+ LOW_BYTE(parse, token_count);
+
+ if (token_count < token_max) {
+ // sufficient space left for token?
+ storeb(parse++, token_count + 1);
+
+ load_string((zword)(text + from), length);
+
+ addr = lookup_text(0x05, dct);
+
+ if (addr != 0 || !flag) {
+
+ parse += 4 * token_count;
+
+ storew((zword)(parse + 0), addr);
+ storeb((zword)(parse + 2), length);
+ storeb((zword)(parse + 3), from);
+ }
+ }
+}
+
+void Processor::tokenise_line(zword text, zword token, zword dct, bool flag) {
+ zword addr1;
+ zword addr2;
+ zbyte length = 0;
+ zbyte c;
+
+ // Use standard dictionary if the given dictionary is zero
+ if (dct == 0)
+ dct = h_dictionary;
+
+ // Remove all tokens before inserting new ones
+ storeb((zword)(token + 1), 0);
+
+ // Move the first pointer across the text buffer searching for the beginning
+ // of a word. If this succeeds, store the position in a second pointer.
+ // Move the first pointer searching for the end of the word. When it is found,
+ // "tokenise" the word. Continue until the end of the buffer is reached.
+ addr1 = text;
+ addr2 = 0;
+
+ if (h_version >= V5) {
+ addr1++;
+ LOW_BYTE(addr1, length);
+ }
+
+ do {
+ zword sep_addr;
+ zbyte sep_count;
+ zbyte separator;
+
+ // Fetch next ZSCII character
+ addr1++;
+
+ if (h_version >= V5 && addr1 == text + 2 + length)
+ c = 0;
+ else
+ LOW_BYTE(addr1, c);
+
+ // Check for separator
+ sep_addr = dct;
+
+ LOW_BYTE(sep_addr, sep_count);
+ sep_addr++;
+
+ do {
+ LOW_BYTE(sep_addr, separator);
+ sep_addr++;
+ } while (c != separator && --sep_count != 0);
+
+ // This could be the start or the end of a word
+ if (sep_count == 0 && c != ' ' && c != 0) {
+ if (addr2 == 0)
+ addr2 = addr1;
+ } else if (addr2 != 0) {
+ tokenise_text(text, (zword)(addr1 - addr2), (zword)(addr2 - text),
+ token, dct, flag);
+
+ addr2 = 0;
+ }
+
+ // Translate separator (which is a word in its own right)
+ if (sep_count != 0)
+ tokenise_text(text, (zword)(1), (zword)(addr1 - text), token, dct, flag);
+
+ } while (c != 0);
+}
+
+int Processor::completion(const zchar *buffer, zchar *result) {
+ zword minaddr;
+ zword maxaddr;
+ zchar *ptr;
+ zchar c;
+ int len;
+ int i;
+
+ *result = 0;
+
+ if (_resolution == 0)
+ find_resolution();
+
+ // Copy last word to "_decoded" string
+ len = 0;
+
+ while ((c = *buffer++) != 0)
+ if (c != ' ') {
+ if (len < 3 * _resolution)
+ _decoded[len++] = c;
+ } else {
+ len = 0;
+ }
+
+ _decoded[len] = 0;
+
+ // Search the dictionary for first and last possible extensions
+ minaddr = lookup_text(0x00, h_dictionary);
+ maxaddr = lookup_text(0x1f, h_dictionary);
+
+ if (minaddr == 0 || maxaddr == 0 || minaddr > maxaddr)
+ return 2;
+
+ // Copy first extension to "result" string
+ decode_text(VOCABULARY, minaddr);
+
+ ptr = result;
+
+ for (i = len; (c = _decoded[i]) != 0; i++)
+ *ptr++ = c;
+ *ptr = 0;
+
+ // Merge second extension with "result" string
+ decode_text(VOCABULARY, maxaddr);
+
+ for (i = len, ptr = result; (c = _decoded[i]) != 0; i++, ptr++) {
+ if (*ptr != c)
+ break;
+ }
+ *ptr = 0;
+
+ // Search was ambiguous or successful
+ return (minaddr == maxaddr) ? 0 : 1;
+}
+
+zchar Processor::unicode_tolower(zchar c) {
+ static const byte tolower_basic_latin[0x100] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
+ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xD7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xDF,
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+ };
+ static const byte tolower_latin_extended_a[0x80] = {
+ 0x01,0x01,0x03,0x03,0x05,0x05,0x07,0x07,0x09,0x09,0x0B,0x0B,0x0D,0x0D,0x0F,0x0F,
+ 0x11,0x11,0x13,0x13,0x15,0x15,0x17,0x17,0x19,0x19,0x1B,0x1B,0x1D,0x1D,0x1F,0x1F,
+ 0x21,0x21,0x23,0x23,0x25,0x25,0x27,0x27,0x29,0x29,0x2B,0x2B,0x2D,0x2D,0x2F,0x2F,
+ 0x00,0x31,0x33,0x33,0x35,0x35,0x37,0x37,0x38,0x3A,0x3A,0x3C,0x3C,0x3E,0x3E,0x40,
+ 0x40,0x42,0x42,0x44,0x44,0x46,0x46,0x48,0x48,0x49,0x4B,0x4B,0x4D,0x4D,0x4F,0x4F,
+ 0x51,0x51,0x53,0x53,0x55,0x55,0x57,0x57,0x59,0x59,0x5B,0x5B,0x5D,0x5D,0x5F,0x5F,
+ 0x61,0x61,0x63,0x63,0x65,0x65,0x67,0x67,0x69,0x69,0x6B,0x6B,0x6D,0x6D,0x6F,0x6F,
+ 0x71,0x71,0x73,0x73,0x75,0x75,0x77,0x77,0x00,0x7A,0x7A,0x7C,0x7C,0x7E,0x7E,0x7F
+ };
+ static const byte tolower_greek[0x50] = {
+ 0x80,0x81,0x82,0x83,0x84,0x85,0xAC,0x87,0xAD,0xAE,0xAF,0x8B,0xCC,0x8D,0xCD,0xCE,
+ 0x90,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xC0,0xC1,0xA2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xAC,0xAD,0xAE,0xAF,
+ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF
+ };
+ static const byte tolower_cyrillic[0x60] = {
+ 0x00,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F
+ };
+
+ if (c < 0x0100)
+ c = tolower_basic_latin[c];
+ else if (c == 0x0130)
+ c = 0x0069; // Capital I with dot -> lower case i
+ else if (c == 0x0178)
+ c = 0x00FF; // Capital Y diaeresis -> lower case y diaeresis
+ else if (c < 0x0180)
+ c = tolower_latin_extended_a[c - 0x100] + 0x100;
+ else if (c >= 0x380 && c < 0x3D0)
+ c = tolower_greek[c - 0x380] + 0x300;
+ else if (c >= 0x400 && c < 0x460)
+ c = tolower_cyrillic[c - 0x400] + 0x400;
+
+ return c;
+}
+
+
+void Processor::z_check_unicode() {
+ zword c = zargs[0];
+ zword result = 0;
+
+ if (c <= 0x1f) {
+ if ((c == 0x08) || (c == 0x0d) || (c == 0x1b))
+ result = 2;
+ } else if (c <= 0x7e) {
+ result = 3;
+ } else {
+ // we support unicode
+ result = 1;
+ }
+
+ store (result);
+}
+
+void Processor::z_encode_text() {
+ int i;
+
+ load_string((zword) (zargs[0] + zargs[2]), zargs[1]);
+
+ encode_text(0x05);
+
+ for (i = 0; i < _resolution; i++)
+ storew((zword) (zargs[3] + 2 * i), _encoded[i]);
+
+}
+
+void Processor::z_new_line() {
+ new_line ();
+}
+
+void Processor::z_print () {
+ decode_text(EMBEDDED_STRING, 0);
+}
+
+void Processor::z_print_addr() {
+ decode_text(LOW_STRING, zargs[0]);
+}
+
+void Processor::z_print_char() {
+ print_char (translate_from_zscii(zargs[0]));
+}
+
+void Processor::z_print_form() {
+ zword count;
+ zword addr = zargs[0];
+ bool first = true;
+
+ for (;;) {
+ LOW_WORD(addr, count);
+ addr += 2;
+
+ if (count == 0)
+ break;
+
+ if (!first)
+ new_line ();
+
+ while (count--) {
+ zbyte c;
+
+ LOW_BYTE(addr, c);
+ addr++;
+
+ print_char(translate_from_zscii (c));
+ }
+
+ first = false;
+ }
+}
+
+void Processor::z_print_num() {
+ print_num (zargs[0]);
+}
+
+void Processor::z_print_obj() {
+ print_object(zargs[0]);
+}
+
+void Processor::z_print_paddr() {
+ decode_text (HIGH_STRING, zargs[0]);
+}
+
+void Processor::z_print_ret() {
+ decode_text(EMBEDDED_STRING, 0);
+ new_line();
+ ret(1);
+}
+
+void Processor::z_print_unicode() {
+ if (zargs[0] < 0x20)
+ print_char('?');
+ else
+ print_char(zargs[0]);
+}
+
+void Processor::z_tokenise() {
+ // Supply default arguments
+ if (zargc < 3)
+ zargs[2] = 0;
+ if (zargc < 4)
+ zargs[3] = 0;
+
+ // Call tokenise_line to do the real work
+ tokenise_line(zargs[0], zargs[1], zargs[2], zargs[3] != 0);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_variables.cpp b/engines/gargoyle/frotz/processor_variables.cpp
new file mode 100644
index 0000000..24bbd28
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_variables.cpp
@@ -0,0 +1,203 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Replace method stubs
+static void storew(zword, zword) {}
+
+
+void Processor::z_dec() {
+ zword value;
+
+ if (zargs[0] == 0)
+ (*_sp)--;
+ else if (zargs[0] < 16)
+ (*(_fp - zargs[0]))--;
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ LOW_WORD(addr, value);
+ value--;
+ SET_WORD(addr, value);
+ }
+}
+
+void Processor::z_dec_chk() {
+ zword value;
+
+ if (zargs[0] == 0)
+ value = --(*_sp);
+ else if (zargs[0] < 16)
+ value = --(*(_fp - zargs[0]));
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ LOW_WORD(addr, value);
+ value--;
+ SET_WORD(addr, value);
+ }
+
+ branch((short)value < (short)zargs[1]);
+}
+
+void Processor::z_inc() {
+ zword value;
+
+ if (zargs[0] == 0)
+ (*_sp)++;
+ else if (zargs[0] < 16)
+ (*(_fp - zargs[0]))++;
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ LOW_WORD(addr, value);
+ value++;
+ SET_WORD(addr, value);
+ }
+}
+
+void Processor::z_inc_chk() {
+ zword value;
+
+ if (zargs[0] == 0)
+ value = ++(*_sp);
+ else if (zargs[0] < 16)
+ value = ++(*(_fp - zargs[0]));
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ LOW_WORD(addr, value);
+ value++;
+ SET_WORD(addr, value);
+ }
+
+ branch((short)value > (short)zargs[1]);
+}
+
+void Processor::z_load() {
+ zword value;
+
+ if (zargs[0] == 0)
+ value = *_sp;
+ else if (zargs[0] < 16)
+ value = *(_fp - zargs[0]);
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ LOW_WORD(addr, value);
+ }
+
+ store(value);
+}
+
+void Processor::z_pop() {
+ _sp++;
+}
+
+void Processor::z_pop_stack() {
+ if (zargc == 2) {
+ // it's a user stack
+ zword size;
+ zword addr = zargs[1];
+
+ LOW_WORD(addr, size);
+
+ size += zargs[0];
+ storew(addr, size);
+ } else {
+ // it's the game stack
+ _sp += zargs[0];
+ }
+}
+
+void Processor::z_pull() {
+ zword value;
+
+ if (h_version != V6) {
+ // not a V6 game, pop stack and write
+ value = *_sp++;
+
+ if (zargs[0] == 0)
+ *_sp = value;
+ else if (zargs[0] < 16)
+ *(_fp - zargs[0]) = value;
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ SET_WORD(addr, value);
+ }
+ } else {
+ // it's V6, but is there a user stack?
+ if (zargc == 1) {
+ // it's a user stack
+ zword size;
+ zword addr = zargs[0];
+
+ LOW_WORD(addr, size);
+
+ size++;
+ storew(addr, size);
+
+ addr += 2 * size;
+ LOW_WORD(addr, value);
+ } else {
+ // it's the game stack
+ value = *_sp++;
+ }
+
+ store(value);
+ }
+}
+
+void Processor::z_push() {
+ *--_sp = zargs[0];
+}
+
+void Processor::z_push_stack() {
+ zword size;
+ zword addr = zargs[1];
+
+ LOW_WORD(addr, size);
+
+ if (size != 0) {
+ storew((zword)(addr + 2 * size), zargs[0]);
+
+ size--;
+ storew(addr, size);
+ }
+
+ branch(size);
+}
+
+void Processor::z_store() {
+ zword value = zargs[1];
+
+ if (zargs[0] == 0)
+ *_sp = value;
+ else if (zargs[0] < 16)
+ *(_fp - zargs[0]) = value;
+ else {
+ zword addr = h_globals + 2 * (zargs[0] - 16);
+ SET_WORD(addr, value);
+ }
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 9dc7f97..a7a1198 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -72,7 +72,7 @@ public:
glui32 size, winid_t keyWin);
void glk_window_get_arrangement(winid_t win, glui32 *method,
glui32 *size, winid_t *keyWin);
- winid_t glk_window_iterate(winid_t win, glui32 *rock);
+ winid_t glk_window_iterate(winid_t win, glui32 *rock = 0);
glui32 glk_window_get_rock(winid_t win);
glui32 glk_window_get_type(winid_t win);
winid_t glk_window_get_parent(winid_t win);
@@ -85,8 +85,8 @@ 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, FileMode fmode, glui32 rock);
- strid_t glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock);
+ strid_t glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock = 0);
+ strid_t glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
void glk_stream_close(strid_t str, stream_result_t *result);
strid_t glk_stream_iterate(strid_t str, glui32 *rockptr) const;
glui32 glk_stream_get_rock(strid_t str) const;
@@ -114,10 +114,10 @@ public:
glui32 glk_style_distinguish(winid_t win, glui32 style1, glui32 style2);
bool glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result);
- frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock);
- frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock);
- 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);
+ frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock = 0);
+ frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock = 0);
+ frefid_t glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock = 0);
+ frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock = 0);
void glk_fileref_destroy(frefid_t fref);
frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
glui32 glk_fileref_get_rock(frefid_t fref);
@@ -169,8 +169,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, FileMode fmode, glui32 rock);
- strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock);
+ strid_t glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock = 0);
+ strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
void glk_request_char_event_uni(winid_t win);
void glk_request_line_event_uni(winid_t win, glui32 *buf,
@@ -206,7 +206,7 @@ public:
#ifdef GLK_MODULE_SOUND
- schanid_t glk_schannel_create(glui32 rock);
+ schanid_t glk_schannel_create(glui32 rock = 0);
void glk_schannel_destroy(schanid_t chan);
schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
glui32 glk_schannel_get_rock(schanid_t chan);
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index d359429..9a1b4c4 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -26,7 +26,17 @@ MODULE_OBJS := \
frotz/detection_tables.o \
frotz/err.o \
frotz/frotz.o \
+ frotz/glk_interface.o \
frotz/mem.o \
+ frotz/processor.o \
+ frotz/processor_input.o \
+ frotz/processor_maths.o \
+ frotz/processor_objects.o \
+ frotz/processor_screen.o \
+ frotz/processor_streams.o \
+ frotz/processor_table.o \
+ frotz/processor_text.o \
+ frotz/processor_variables.o \
scott/detection.o \
scott/scott.o
Commit: 9fadd84b37ff4e9fa76cb2efc3464d5b958a7ed3
https://github.com/scummvm/scummvm/commit/9fadd84b37ff4e9fa76cb2efc3464d5b958a7ed3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add GlkInterface initialize method
Changed paths:
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/frotz/glk_interface.cpp
engines/gargoyle/frotz/glk_interface.h
engines/gargoyle/frotz/mem.h
engines/gargoyle/frotz/processor.cpp
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_input.cpp
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index c4f4298..302cc43 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -234,13 +234,14 @@ struct UserOptions {
bool _save_quetzal;
int _err_report_mode;
bool _sound;
+ bool _user_tandy_bit;
UserOptions() : _attribute_assignment(0), _attribute_testing(0),
_context_lines(0), _object_locating(0), _object_movement(0),
_left_margin(0), _right_margin(0), _ignore_errors(false), _piracy(false),
_undo_slots(MAX_UNDO_SLOTS), _expand_abbreviations(0), _script_cols(80),
- _save_quetzal(true),
- _err_report_mode(ERR_DEFAULT_REPORT_MODE), _sound(true) {
+ _save_quetzal(true), _err_report_mode(ERR_DEFAULT_REPORT_MODE), _sound(true),
+ _user_tandy_bit(false) {
}
};
diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp
index e1311fb..f60ecc5 100644
--- a/engines/gargoyle/frotz/glk_interface.cpp
+++ b/engines/gargoyle/frotz/glk_interface.cpp
@@ -26,7 +26,7 @@ namespace Gargoyle {
namespace Frotz {
GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- Glk(syst, gameDesc),
+ Glk(syst, gameDesc), UserOptions(),
oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
@@ -40,6 +40,135 @@ GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDes
Common::fill(&statusline[0], &statusline[256], '\0');
}
+void GlkInterface::initialize() {
+ uint width, height;
+
+ /*
+ * Init glk stuff
+ */
+
+ // monor
+ glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Oblique, 0);
+
+ // monob
+ glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Oblique, 0);
+
+ // monoi
+ glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Oblique, 1);
+
+ // monoz
+ glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Oblique, 1);
+
+ // propr
+ glk_stylehint_set(wintype_TextBuffer, style_Normal, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Normal, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Oblique, 0);
+
+ // propb
+ glk_stylehint_set(wintype_TextBuffer, style_Header, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Header, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Oblique, 0);
+
+ // propi
+ glk_stylehint_set(wintype_TextBuffer, style_Emphasized, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Emphasized, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Oblique, 1);
+
+ // propi
+ glk_stylehint_set(wintype_TextBuffer, style_Note, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Note, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Oblique, 1);
+
+ gos_lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
+ if (!gos_lower)
+ gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
+ glk_window_get_size(gos_lower, &width, &height);
+ glk_window_close(gos_lower, NULL);
+
+ gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
+ gos_upper = glk_window_open(gos_lower,
+ winmethod_Above | winmethod_Fixed,
+ 0,
+ wintype_TextGrid, 0);
+
+ gos_channel = NULL;
+
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+
+ /*
+ * Icky magic bit setting
+ */
+
+ if (h_version == V3 && _user_tandy_bit)
+ h_config |= CONFIG_TANDY;
+
+ if (h_version == V3 && gos_upper)
+ h_config |= CONFIG_SPLITSCREEN;
+
+ if (h_version == V3 && !gos_upper)
+ h_config |= CONFIG_NOSTATUSLINE;
+
+ if (h_version >= V4)
+ h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS |
+ CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR;
+
+ if (h_version >= V5)
+ h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG);
+
+ if ((h_version >= 5) && (h_flags & SOUND_FLAG))
+ h_flags |= SOUND_FLAG;
+
+ if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG))
+ h_flags |= OLD_SOUND_FLAG;
+
+ if ((h_version == 6) && (_sound != 0))
+ h_config |= CONFIG_SOUND;
+
+ if (h_version >= V5 && (h_flags & UNDO_FLAG))
+ if (_undo_slots == 0)
+ h_flags &= ~UNDO_FLAG;
+
+ h_screen_cols = width;
+ h_screen_rows = height;
+
+ h_screen_height = h_screen_rows;
+ h_screen_width = h_screen_cols;
+
+ h_font_width = 1;
+ h_font_height = 1;
+
+ /* Must be after screen dimensions are computed. */
+ if (h_version == V6) {
+ h_flags &= ~GRAPHICS_FLAG;
+ }
+
+ // Use the ms-dos interpreter number for v6, because that's the
+ // kind of graphics files we understand. Otherwise, use DEC.
+ h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_DEC_20;
+ h_interpreter_version = 'F';
+
+ {
+ // Set these per spec 8.3.2.
+ h_default_foreground = WHITE_COLOUR;
+ h_default_background = BLACK_COLOUR;
+ if (h_flags & COLOUR_FLAG)
+ h_flags &= ~COLOUR_FLAG;
+ }
+}
+
int GlkInterface::os_char_width(zchar z) {
return 1;
}
@@ -118,7 +247,7 @@ void GlkInterface::gos_update_width() {
glk_window_get_size(gos_upper, &width, nullptr);
h_screen_cols = width;
SET_BYTE(H_SCREEN_COLS, width);
- if (curx > width) {
+ if ((uint)curx > width) {
glk_window_move_cursor(gos_upper, 0, cury - 1);
curx = 1;
}
@@ -140,7 +269,7 @@ void GlkInterface::reset_status_ht() {
glui32 height;
if (gos_upper) {
glk_window_get_size(gos_upper, nullptr, &height);
- if (mach_status_ht != height) {
+ if ((uint)mach_status_ht != height) {
glk_window_set_arrangement(
glk_window_get_parent(gos_upper),
winmethod_Above | winmethod_Fixed,
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
index ea3f60c..1d30364 100644
--- a/engines/gargoyle/frotz/glk_interface.h
+++ b/engines/gargoyle/frotz/glk_interface.h
@@ -40,7 +40,7 @@ enum SoundEffect {
* Implements an intermediate interface on top of the GLK layer, providing screen
* and sound effect handling
*/
-class GlkInterface : public Glk, public virtual Mem {
+class GlkInterface : public Glk, public UserOptions, public virtual Mem {
public:
zchar statusline[256];
int oldstyle;
@@ -139,6 +139,11 @@ public:
* Constructor
*/
GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc);
+
+ /**
+ * Initialization
+ */
+ void initialize();
};
} // End of namespace Frotz
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index d37cdd3..55cc4dc 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -186,7 +186,7 @@ public:
/**
* Initialize
*/
- virtual void initialize();
+ void initialize();
/**
* Read a word
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
index 1a31898..20fb387 100644
--- a/engines/gargoyle/frotz/processor.cpp
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -132,7 +132,7 @@ Opcode Processor::ext_opcodes[64] = {
};
Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GlkInterface(syst, gameDesc), Mem(), Errors(), UserOptions(),
+ GlkInterface(syst, gameDesc), Mem(), Errors(),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
_randomInterval(0), _randomCtr(0), first_restart(true) {
@@ -181,6 +181,7 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
void Processor::initialize() {
Mem::initialize();
+ GlkInterface::initialize();
if (h_version <= V4) {
op0_opcodes[9] = &Processor::z_pop;
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 074100a..a11fa1b 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -48,7 +48,7 @@ typedef void (Processor::*Opcode)();
/**
* Zcode processor
*/
-class Processor : public virtual Mem, public Errors, public GlkInterface, public UserOptions {
+class Processor : public virtual Mem, public Errors, public GlkInterface {
private:
Opcode op0_opcodes[16];
Opcode op1_opcodes[16];
@@ -1308,7 +1308,7 @@ public:
/**
* Initialization
*/
- virtual void initialize() override;
+ void initialize();
/**
* Z-code interpreter main loop
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
index e7f92ab..86a8abc 100644
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -26,8 +26,6 @@ namespace Gargoyle {
namespace Frotz {
// TODO: Implement method stubs
-static zchar stream_read_key(zword, zword, bool) { return 0; }
-static zchar stream_read_input(int, zchar *, zword, zword, bool, bool) { return 0;}
static void storeb(zword, zchar) {}
static void storew(zword, zword) {}
static void save_undo() {}
Commit: ad95130e4f3ad9b0eb0f1ab976dd157a0e7a2dbf
https://github.com/scummvm/scummvm/commit/ad95130e4f3ad9b0eb0f1ab976dd157a0e7a2dbf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added user options initialization from configuration
Changed paths:
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index c0a9442..df6d736 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -22,6 +22,7 @@
#include "gargoyle/frotz/frotz.h"
#include "gargoyle/frotz/frotz_types.h"
+#include "common/config-manager.h"
namespace Gargoyle {
namespace Frotz {
@@ -40,11 +41,48 @@ void Frotz::runGame(Common::SeekableReadStream *gameFile) {
// TODO
}
+void Frotz::initialize() {
+ if (ConfMan.hasKey("attribute_assignment") && ConfMan.getBool("attribute_assignment"))
+ _attribute_assignment = true;
+ if (ConfMan.hasKey("attribute_testing") && ConfMan.getBool("attribute_testing"))
+ _attribute_testing = true;
+ if (ConfMan.hasKey("ignore_errors") && ConfMan.getBool("ignore_errors"))
+ _ignore_errors = true;
+ if (ConfMan.hasKey("object_movement") && ConfMan.getBool("object_movement"))
+ _object_movement = true;
+ if (ConfMan.hasKey("object_locating") && ConfMan.getBool("object_locating"))
+ _object_locating = true;
+ if (ConfMan.hasKey("piracy") && ConfMan.getBool("piracy"))
+ _piracy = true;
+ if (ConfMan.hasKey("save_quetzal") && ConfMan.getBool("save_quetzal"))
+ _save_quetzal = true;
+ if (ConfMan.hasKey("random_seed"))
+ _random.setSeed(ConfMan.getInt("random_seed"));
+ if (ConfMan.hasKey("script_cols"))
+ _script_cols = ConfMan.getInt("script_cols");
+ if (ConfMan.hasKey("tandy_bit") && ConfMan.getBool("tandy_bit"))
+ _user_tandy_bit = true;
+ if (ConfMan.hasKey("undo_slots"))
+ _undo_slots = ConfMan.getInt("undo_slots");
+ if (ConfMan.hasKey("expand_abbreviations") && ConfMan.getBool("expand_abbreviations"))
+ _expand_abbreviations = true;
+ if (ConfMan.hasKey("err_report_mode")) {
+ _err_report_mode = ConfMan.getInt("err_report_mode");
+ if ((_err_report_mode < ERR_REPORT_NEVER) || (_err_report_mode > ERR_REPORT_FATAL))
+ _err_report_mode = ERR_DEFAULT_REPORT_MODE;
+ }
+
+ // Call process initialization
+ Processor::initialize();
+}
+
Common::Error Frotz::loadGameState(int slot) {
+ // TODO
return Common::kNoError;
}
Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
+ // TODO
return Common::kNoError;
}
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index c032265..78272f0 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -39,6 +39,11 @@ public:
Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc);
/**
+ * Initialization
+ */
+ void initialize();
+
+ /**
* Execute the game
*/
virtual void runGame(Common::SeekableReadStream *gameFile) override;
Commit: 7a3dd94de1e5343f00316d69674e46d129f56914
https://github.com/scummvm/scummvm/commit/7a3dd94de1e5343f00316d69674e46d129f56914
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add undo data initialization
Changed paths:
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/glk_interface.cpp
engines/gargoyle/frotz/glk_interface.h
engines/gargoyle/frotz/mem.cpp
engines/gargoyle/frotz/mem.h
engines/gargoyle/frotz/processor.cpp
engines/gargoyle/frotz/processor.h
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index df6d736..5c86189 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -74,6 +74,9 @@ void Frotz::initialize() {
// Call process initialization
Processor::initialize();
+
+ // Restart the game
+ z_restart();
}
Common::Error Frotz::loadGameState(int slot) {
diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp
index f60ecc5..13d0a56 100644
--- a/engines/gargoyle/frotz/glk_interface.cpp
+++ b/engines/gargoyle/frotz/glk_interface.cpp
@@ -26,7 +26,7 @@ namespace Gargoyle {
namespace Frotz {
GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- Glk(syst, gameDesc), UserOptions(),
+ Glk(syst, gameDesc),
oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
index 1d30364..f02fa0d 100644
--- a/engines/gargoyle/frotz/glk_interface.h
+++ b/engines/gargoyle/frotz/glk_interface.h
@@ -40,7 +40,7 @@ enum SoundEffect {
* Implements an intermediate interface on top of the GLK layer, providing screen
* and sound effect handling
*/
-class GlkInterface : public Glk, public UserOptions, public virtual Mem {
+class GlkInterface : public Glk, public virtual UserOptions, public virtual Mem {
public:
zchar statusline[256];
int oldstyle;
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
index cb5a73b..d9ff53d 100644
--- a/engines/gargoyle/frotz/mem.cpp
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -112,11 +112,15 @@ void Header::loadHeader(Common::SeekableReadStream &f) {
/*--------------------------------------------------------------------------*/
-Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0) {
+Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0),
+ first_undo(nullptr), last_undo(nullptr), curr_undo(nullptr),
+ undo_mem(nullptr), prev_zmp(nullptr), undo_diff(nullptr),
+ undo_count(0), reserve_mem(0) {
}
void Mem::initialize() {
initializeStoryFile();
+ initializeUndo();
loadGameHeader();
// Allocate memory for story data
@@ -173,6 +177,29 @@ void Mem::initializeStoryFile() {
error("This file is too small to be a Z-code file.");
}
+void Mem::initializeUndo() {
+ void *reserved = nullptr;
+
+ if (reserve_mem != 0) {
+ if ((reserved = malloc(reserve_mem)) == NULL)
+ return;
+ }
+
+ // Allocate h_dynamic_size bytes for previous dynamic zmp state
+ // + 1.5 h_dynamic_size for Quetzal diff + 2.
+ undo_mem = new zbyte[(h_dynamic_size * 5) / 2 + 2];
+ if (undo_mem != nullptr) {
+ prev_zmp = undo_mem;
+ undo_diff = undo_mem + h_dynamic_size;
+ memcpy(prev_zmp, zmp, h_dynamic_size);
+ } else {
+ _undo_slots = 0;
+ }
+
+ if (reserve_mem != 0)
+ delete reserved;
+}
+
void Mem::loadGameHeader() {
// Load header
zmp = new byte[64];
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index 55cc4dc..e12c062 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -82,6 +82,21 @@ enum {
};
/**
+ * Stores undo information
+ */
+struct undo_struct {
+ undo_struct *next;
+ undo_struct *prev;
+ long pc;
+ long diff_size;
+ zword frame_count;
+ zword stack_size;
+ zword frame_offset;
+ // undo diff and stack data follow
+};
+typedef undo_struct undo_t;
+
+/**
* Story file header data
*/
struct Header {
@@ -160,13 +175,18 @@ public:
void loadHeader(Common::SeekableReadStream &f);
};
-class Mem : public Header {
+class Mem : public Header, public virtual UserOptions {
protected:
Common::SeekableReadStream *story_fp;
uint blorb_ofs, blorb_len;
uint story_size;
byte *pcp;
byte *zmp;
+
+ undo_t *first_undo, *last_undo, *curr_undo;
+ zbyte *undo_mem, *prev_zmp, *undo_diff;
+ int undo_count;
+ int reserve_mem;
private:
/**
* Handles setting the story file, parsing it if it's a Blorb file
@@ -174,6 +194,11 @@ private:
void initializeStoryFile();
/**
+ * Setup undo data
+ */
+ void initializeUndo();
+
+ /**
* Handles loading the game header
*/
void loadGameHeader();
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
index 20fb387..721f64b 100644
--- a/engines/gargoyle/frotz/processor.cpp
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -132,7 +132,7 @@ Opcode Processor::ext_opcodes[64] = {
};
Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GlkInterface(syst, gameDesc), Mem(), Errors(),
+ GlkInterface(syst, gameDesc), Errors(),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
_randomInterval(0), _randomCtr(0), first_restart(true) {
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index a11fa1b..77192b4 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -412,7 +412,7 @@ private:
zchar unicode_tolower(zchar c);
/**@}*/
-private:
+protected:
/**
* \defgroup General Opcode methods
* @{
Commit: fbe7fb7e1a6223070bd0d0c9929b372391756c8c
https://github.com/scummvm/scummvm/commit/fbe7fb7e1a6223070bd0d0c9929b372391756c8c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Merge Buffer class into Processor
Changed paths:
A engines/gargoyle/frotz/processor_buffer.cpp
R engines/gargoyle/frotz/buffer.cpp
R engines/gargoyle/frotz/buffer.h
engines/gargoyle/frotz/processor.cpp
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_streams.cpp
engines/gargoyle/frotz/processor_text.cpp
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/frotz/buffer.cpp b/engines/gargoyle/frotz/buffer.cpp
deleted file mode 100644
index 7d9e644..0000000
--- a/engines/gargoyle/frotz/buffer.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/buffer.h"
-#include "gargoyle/frotz/frotz.h"
-#include "common/algorithm.h"
-#include "common/textconsole.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-// TODO: Replace these method stubs with correct calls
-void stream_char(zchar) {}
-void stream_word(const zchar *) {}
-void stream_new_line(void) {}
-
-Buffer::Buffer() : _bufPos(0), _locked(false), _prevC('\0') {
- Common::fill(&_buffer[0], &_buffer[TEXT_BUFFER_SIZE], '\0');
-}
-
-void Buffer::flush() {
- /* Make sure we stop when flush_buffer is called from flush_buffer.
- * Note that this is difficult to avoid as we might print a newline
- * during flush_buffer, which might cause a newline interrupt, that
- * might execute any arbitrary opcode, which might flush the buffer.
- */
- if (_locked || empty())
- return;
-
- // Send the buffer to the output streams
- _buffer[_bufPos] = '\0';
-
- _locked = true;
- stream_word(_buffer);
- _locked = false;
-
- // Reset the buffer
- _bufPos = 0;
- _prevC = '\0';
-}
-
-void Buffer::printChar(zchar c) {
- static bool flag = false;
-
- if (g_vm->message || g_vm->ostream_memory || g_vm->enable_buffering) {
- if (!flag) {
- // Characters 0 and ZC_RETURN are special cases
- if (c == ZC_RETURN) {
- newLine();
- return;
- }
- if (c == 0)
- return;
-
- // Flush the buffer before a whitespace or after a hyphen
- if (c == ' ' || c == ZC_INDENT || c == ZC_GAP || (_prevC == '-' && c != '-'))
- flush();
-
- // Set the flag if this is part one of a style or font change
- if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE)
- flag = true;
-
- // Remember the current character code
- _prevC = c;
- } else {
- flag = false;
- }
-
- // Insert the character into the buffer
- _buffer[_bufPos++] = c;
-
- if (_bufPos == TEXT_BUFFER_SIZE)
- error("Text buffer overflow");
- } else {
- stream_char(c);
- }
-}
-
-void Buffer::newLine() {
- flush();
- stream_new_line();
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/buffer.h b/engines/gargoyle/frotz/buffer.h
deleted file mode 100644
index 608e087..0000000
--- a/engines/gargoyle/frotz/buffer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* 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 GARGOYLE_FROTZ_BUFFER
-#define GARGOYLE_FROTZ_BUFFER
-
-#include "gargoyle/frotz/frotz_types.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-#define TEXT_BUFFER_SIZE 200
-
-/**
- * Text buffer class
- */
-class Buffer {
-public:
- zchar _buffer[TEXT_BUFFER_SIZE];
- size_t _bufPos;
- bool _locked;
- zchar _prevC;
-public:
- /**
- * Constructor
- */
- Buffer();
-
- /**
- * Copy the contents of the text buffer to the output streams.
- */
- void flush();
-
- /**
- * High level output function.
- */
- void printChar(zchar c);
-
- /**
- * High level newline function.
- */
- void newLine();
-
- /**
- * Returns true if the buffer is empty
- */
- bool empty() const { return !_bufPos; }
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
index 721f64b..85a539b 100644
--- a/engines/gargoyle/frotz/processor.cpp
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -135,7 +135,8 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
GlkInterface(syst, gameDesc), Errors(),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
- _randomInterval(0), _randomCtr(0), first_restart(true) {
+ _randomInterval(0), _randomCtr(0), first_restart(true), _bufPos(0),
+ _locked(false), _prevC('\0') {
static const Opcode OP0_OPCODES[16] = {
&Processor::z_rtrue,
&Processor::z_rfalse,
@@ -177,6 +178,7 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
Common::copy(&OP1_OPCODES[0], &OP1_OPCODES[16], op1_opcodes);
Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
Common::fill(&zargs[0], &zargs[8], 0);
+ Common::fill(&_buffer[0], &_buffer[TEXT_BUFFER_SIZE], '\0');
}
void Processor::initialize() {
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 77192b4..d754b1f 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -23,7 +23,6 @@
#ifndef GARGOYLE_FROTZ_PROCESSOR
#define GARGOYLE_FROTZ_PROCESSOR
-#include "gargoyle/frotz/buffer.h"
#include "gargoyle/frotz/err.h"
#include "gargoyle/frotz/mem.h"
#include "gargoyle/frotz/glk_interface.h"
@@ -37,6 +36,7 @@ namespace Frotz {
#define GET_PC(v) v = pcp - zmp
#define SET_PC(v) pcp = zmp + v
+#define TEXT_BUFFER_SIZE 200
enum string_type {
LOW_STRING, ABBREVIATION, HIGH_STRING, EMBEDDED_STRING, VOCABULARY
@@ -48,12 +48,8 @@ typedef void (Processor::*Opcode)();
/**
* Zcode processor
*/
-class Processor : public virtual Mem, public Errors, public GlkInterface {
+class Processor : public Errors, public GlkInterface, public virtual Mem {
private:
- Opcode op0_opcodes[16];
- Opcode op1_opcodes[16];
- static Opcode var_opcodes[64];
- static Opcode ext_opcodes[64];
int _finished;
zword zargs[8];
int zargc;
@@ -71,6 +67,17 @@ private:
static zchar ZSCII_TO_LATIN1[];
zchar *_decoded, *_encoded;
int _resolution;
+
+ // Buffer related fields
+ zchar _buffer[TEXT_BUFFER_SIZE];
+ size_t _bufPos;
+ bool _locked;
+ zchar _prevC;
+
+ Opcode op0_opcodes[16];
+ Opcode op1_opcodes[16];
+ static Opcode var_opcodes[64];
+ static Opcode ext_opcodes[64];
private:
/**
* \defgroup General support methods
@@ -146,6 +153,33 @@ private:
*/
/**
+ * Copy the contents of the text buffer to the output streams.
+ */
+ void flush_buffer();
+
+ /**
+ * High level output function.
+ */
+ void print_char(zchar c);
+
+ /**
+ * High level newline function.
+ */
+ void new_line();
+
+ /**
+ * Returns true if the buffer is empty
+ */
+ bool bufferEmpty() const { return !_bufPos; }
+
+ /**@}*/
+
+ /**
+ * \defgroup Input support methods
+ * @{
+ */
+
+ /**
* Check if the given key is an input terminator.
*/
bool is_terminator(zchar key);
diff --git a/engines/gargoyle/frotz/processor_buffer.cpp b/engines/gargoyle/frotz/processor_buffer.cpp
new file mode 100644
index 0000000..be30bfe
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_buffer.cpp
@@ -0,0 +1,99 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+// TODO: Replace these method stubs with correct calls
+void stream_char(zchar) {}
+void stream_word(const zchar *) {}
+void stream_new_line(void) {}
+
+void Processor::flush_buffer() {
+ /* Make sure we stop when flush_buffer is called from flush_buffer.
+ * Note that this is difficult to avoid as we might print a newline
+ * during flush_buffer, which might cause a newline interrupt, that
+ * might execute any arbitrary opcode, which might flush the buffer.
+ */
+ if (_locked || bufferEmpty())
+ return;
+
+ // Send the buffer to the output streams
+ _buffer[_bufPos] = '\0';
+
+ _locked = true;
+ stream_word(_buffer);
+ _locked = false;
+
+ // Reset the buffer
+ _bufPos = 0;
+ _prevC = '\0';
+}
+
+void Processor::print_char(zchar c) {
+ static bool flag = false;
+
+ if (message || ostream_memory || enable_buffering) {
+ if (!flag) {
+ // Characters 0 and ZC_RETURN are special cases
+ if (c == ZC_RETURN) {
+ new_line();
+ return;
+ }
+ if (c == 0)
+ return;
+
+ // Flush the buffer before a whitespace or after a hyphen
+ if (c == ' ' || c == ZC_INDENT || c == ZC_GAP || (_prevC == '-' && c != '-'))
+ flush_buffer();
+
+ // Set the flag if this is part one of a style or font change
+ if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE)
+ flag = true;
+
+ // Remember the current character code
+ _prevC = c;
+ } else {
+ flag = false;
+ }
+
+ // Insert the character into the buffer
+ _buffer[_bufPos++] = c;
+
+ if (_bufPos == TEXT_BUFFER_SIZE)
+ error("Text buffer overflow");
+ } else {
+ stream_char(c);
+ }
+}
+
+void Processor::new_line() {
+ flush_buffer();
+ stream_new_line();
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index 5fe526f..ae4dbaa 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -28,7 +28,6 @@ namespace Frotz {
// TODO: Implement method stubs
static void os_scrollback_char(zchar) {}
static void os_scrollback_erase(zword) {}
-static void flush_buffer() {}
static void script_open() {}
static void script_close() {}
static void script_mssg_on() {}
diff --git a/engines/gargoyle/frotz/processor_text.cpp b/engines/gargoyle/frotz/processor_text.cpp
index e660ac1..f6a82fb 100644
--- a/engines/gargoyle/frotz/processor_text.cpp
+++ b/engines/gargoyle/frotz/processor_text.cpp
@@ -26,8 +26,6 @@ namespace Gargoyle {
namespace Frotz {
// TODO: Replace method stubs
-static void new_line() {}
-static void print_char(zchar) {}
static void storeb(zword, zchar) {}
static void storew(zword, zword) {}
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 9a1b4c4..78bde80 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -21,7 +21,6 @@ MODULE_OBJS := \
window_pair.o \
window_text_buffer.o \
window_text_grid.o \
- frotz/buffer.o \
frotz/detection.o \
frotz/detection_tables.o \
frotz/err.o \
@@ -29,6 +28,7 @@ MODULE_OBJS := \
frotz/glk_interface.o \
frotz/mem.o \
frotz/processor.o \
+ frotz/processor_buffer.o \
frotz/processor_input.o \
frotz/processor_maths.o \
frotz/processor_objects.o \
Commit: 53612fa6f72cc2167f9b5a65bc09eb351248b718
https://github.com/scummvm/scummvm/commit/53612fa6f72cc2167f9b5a65bc09eb351248b718
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added storeb and storew methods
Changed paths:
engines/gargoyle/frotz/processor.cpp
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_input.cpp
engines/gargoyle/frotz/processor_streams.cpp
engines/gargoyle/frotz/processor_table.cpp
engines/gargoyle/frotz/processor_text.cpp
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
index 85a539b..9341013 100644
--- a/engines/gargoyle/frotz/processor.cpp
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -135,8 +135,8 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
GlkInterface(syst, gameDesc), Errors(),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
- _randomInterval(0), _randomCtr(0), first_restart(true), _bufPos(0),
- _locked(false), _prevC('\0') {
+ _randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false),
+ _bufPos(0), _locked(false), _prevC('\0') {
static const Opcode OP0_OPCODES[16] = {
&Processor::z_rtrue,
&Processor::z_rfalse,
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index d754b1f..1554265 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -56,6 +56,7 @@ private:
uint _randomInterval;
uint _randomCtr;
bool first_restart;
+ bool script_valid;
// Stack data
zword _stack[STACK_SIZE];
@@ -202,6 +203,21 @@ private:
/**@}*/
/**
+ * \defgroup Memory support methods
+ * @{
+ */
+
+ /**
+ * Write a byte value to the dynamic Z-machine memory.
+ */
+ void storeb(zword addr, zbyte value);
+
+ /**
+ * Write a word value to the dynamic Z-machine memory.
+ */
+ void storew(zword addr, zword value);
+
+ /**
* \defgroup Object support methods
* @{
*/
@@ -308,6 +324,26 @@ private:
zchar stream_read_input(int max, zchar *buf, zword timeout, zword routine,
bool hot_keys, bool no_scripting);
+ /*
+ * script_open
+ *
+ * Open the transscript file. 'AMFV' makes this more complicated as it
+ * turns transscription on/off several times to exclude some text from
+ * the transscription file. This wasn't a problem for the original V4
+ * interpreters which always sent transscription to the printer, but it
+ * means a problem to modern interpreters that offer to open a new file
+ * every time transscription is turned on. Our solution is to append to
+ * the old transscription file in V1 to V4, and to ask for a new file
+ * name in V5+.
+ *
+ */
+ void script_open();
+
+ /*
+ * Stop transscription.
+ */
+ void script_close();
+
/**@}*/
/**
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
index 86a8abc..43f0aaf 100644
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -26,8 +26,6 @@ namespace Gargoyle {
namespace Frotz {
// TODO: Implement method stubs
-static void storeb(zword, zchar) {}
-static void storew(zword, zword) {}
static void save_undo() {}
static zword os_read_mouse() { return 0; }
@@ -80,7 +78,35 @@ int Processor::read_number() {
value = 10 * value + buffer[i] - '0';
return value;
+}
+
+void Processor::storeb(zword addr, zbyte value) {
+ if (addr >= h_dynamic_size)
+ runtimeError(ERR_STORE_RANGE);
+
+ if (addr == H_FLAGS + 1) { /* flags register is modified */
+
+ h_flags &= ~(SCRIPTING_FLAG | FIXED_FONT_FLAG);
+ h_flags |= value & (SCRIPTING_FLAG | FIXED_FONT_FLAG);
+
+ if (value & SCRIPTING_FLAG) {
+ if (!ostream_script)
+ script_open();
+ } else {
+ if (ostream_script)
+ script_close();
+ }
+
+ // TOR - glkified / refresh_text_style ();
+ }
+
+ SET_BYTE(addr, value);
+
+}
+void Processor::storew(zword addr, zword value) {
+ storeb((zword)(addr + 0), hi(value));
+ storeb((zword)(addr + 1), lo(value));
}
void Processor::z_read() {
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index ae4dbaa..a536095 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -222,6 +222,14 @@ continue_input:
return key;
}
+void Processor::script_open() {
+ // TODO
+}
+
+void Processor::script_close() {
+ // TODO
+}
+
void Processor::z_input_stream() {
flush_buffer();
diff --git a/engines/gargoyle/frotz/processor_table.cpp b/engines/gargoyle/frotz/processor_table.cpp
index 4e660ca..d449062 100644
--- a/engines/gargoyle/frotz/processor_table.cpp
+++ b/engines/gargoyle/frotz/processor_table.cpp
@@ -25,11 +25,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Method stubs to implement
-static void storeb(zword, zbyte) {}
-static void storew(zword, zword) {}
-
-
void Processor::z_copy_table() {
zword addr;
zword size = zargs[2];
diff --git a/engines/gargoyle/frotz/processor_text.cpp b/engines/gargoyle/frotz/processor_text.cpp
index f6a82fb..630bd50 100644
--- a/engines/gargoyle/frotz/processor_text.cpp
+++ b/engines/gargoyle/frotz/processor_text.cpp
@@ -25,11 +25,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Replace method stubs
-static void storeb(zword, zchar) {}
-static void storew(zword, zword) {}
-
-
zchar Processor::ZSCII_TO_LATIN1[] = {
0x0e4, 0x0f6, 0x0fc, 0x0c4, 0x0d6, 0x0dc, 0x0df, 0x0bb,
0x0ab, 0x0eb, 0x0ef, 0x0ff, 0x0cb, 0x0cf, 0x0e1, 0x0e9,
Commit: 1b4791f92328e4dc28e697cd9f12383c7f10b932
https://github.com/scummvm/scummvm/commit/1b4791f92328e4dc28e697cd9f12383c7f10b932
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Removal of method stubs that are now implemented
Changed paths:
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/frotz/glk_interface.h
engines/gargoyle/frotz/processor_objects.cpp
engines/gargoyle/frotz/processor_screen.cpp
engines/gargoyle/frotz/processor_streams.cpp
engines/gargoyle/frotz/processor_variables.cpp
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 302cc43..2b33fbd 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -199,12 +199,6 @@ enum FontStyle {
#define BEEP_HIGH 1
#define BEEP_LOW 2
-/*** Constants for os_restart_game */
-
-#define RESTART_BEGIN 0
-#define RESTART_WPROP_SET 1
-#define RESTART_END 2
-
/*** Constants for os_menu */
#define MENU_NEW 0
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
index f02fa0d..161a1f3 100644
--- a/engines/gargoyle/frotz/glk_interface.h
+++ b/engines/gargoyle/frotz/glk_interface.h
@@ -36,6 +36,13 @@ enum SoundEffect {
EFFECT_FINISH_WITH = 4
};
+enum RestartAction {
+ RESTART_BEGIN = 0,
+ RESTART_WPROP_SET = 1,
+ RESTART_END = 2
+};
+
+
/**
* Implements an intermediate interface on top of the GLK layer, providing screen
* and sound effect handling
@@ -134,6 +141,11 @@ protected:
void packspaces(zchar *src, zchar *dst);
void smartstatusline();
+
+ /**
+ * Called during game restarts
+ */
+ void os_restart_game(RestartAction) {}
public:
/**
* Constructor
diff --git a/engines/gargoyle/frotz/processor_objects.cpp b/engines/gargoyle/frotz/processor_objects.cpp
index 3d2b171..986bf87 100644
--- a/engines/gargoyle/frotz/processor_objects.cpp
+++ b/engines/gargoyle/frotz/processor_objects.cpp
@@ -25,9 +25,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Method stubs to implement
-static void new_line() {}
-
#define MAX_OBJECT 2000
enum O1 {
diff --git a/engines/gargoyle/frotz/processor_screen.cpp b/engines/gargoyle/frotz/processor_screen.cpp
index 5b3b8cb..27d3cda 100644
--- a/engines/gargoyle/frotz/processor_screen.cpp
+++ b/engines/gargoyle/frotz/processor_screen.cpp
@@ -25,11 +25,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Method stubs to implement
-static void storew(zword, zword) {}
-static void print_char(zchar) {}
-
-
void Processor::screen_char(zchar c) {
// TODO
}
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index a536095..3f35c1f 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -28,8 +28,6 @@ namespace Frotz {
// TODO: Implement method stubs
static void os_scrollback_char(zchar) {}
static void os_scrollback_erase(zword) {}
-static void script_open() {}
-static void script_close() {}
static void script_mssg_on() {}
static void script_mssg_off() {}
static void script_char(zchar) {}
@@ -51,7 +49,6 @@ static void record_open() {}
static void record_close() {}
static void record_write_key(zchar) {}
static void record_write_input(zchar *, zchar) {}
-static void os_restart_game(zword) {}
static void restart_header() {}
diff --git a/engines/gargoyle/frotz/processor_variables.cpp b/engines/gargoyle/frotz/processor_variables.cpp
index 24bbd28..19a40b9 100644
--- a/engines/gargoyle/frotz/processor_variables.cpp
+++ b/engines/gargoyle/frotz/processor_variables.cpp
@@ -25,10 +25,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Replace method stubs
-static void storew(zword, zword) {}
-
-
void Processor::z_dec() {
zword value;
Commit: 1ca59e74c38c397d9631c0779bf102136be83f1d
https://github.com/scummvm/scummvm/commit/1ca59e74c38c397d9631c0779bf102136be83f1d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added storeb & storew into the Mem class
Changed paths:
A engines/gargoyle/frotz/processor_mem.cpp
engines/gargoyle/frotz/mem.cpp
engines/gargoyle/frotz/mem.h
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_input.cpp
engines/gargoyle/frotz/processor_streams.cpp
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
index d9ff53d..57b2825 100644
--- a/engines/gargoyle/frotz/mem.cpp
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -134,11 +134,10 @@ void Mem::initialize() {
if (story_size - size < 0x8000)
n = story_size - size;
- setPC(size);
+ SET_PC(size);
if (story_fp->read(pcp, n) != n)
error("Story file read error");
-
}
// Read header extension table
@@ -236,5 +235,91 @@ zword Mem::get_header_extension(int entry) {
return val;
}
+void Mem::set_header_extension(int entry, zword val) {
+ zword addr;
+
+ if (h_extension_table == 0 || entry > hx_table_size)
+ return;
+
+ addr = h_extension_table + 2 * entry;
+ SET_WORD(addr, val);
+}
+
+void Mem::restart_header(void) {
+ zword screen_x_size;
+ zword screen_y_size;
+ zbyte font_x_size;
+ zbyte font_y_size;
+
+ int i;
+
+ SET_BYTE(H_CONFIG, h_config);
+ SET_WORD(H_FLAGS, h_flags);
+
+ if (h_version >= V4) {
+ SET_BYTE(H_INTERPRETER_NUMBER, h_interpreter_number);
+ SET_BYTE(H_INTERPRETER_VERSION, h_interpreter_version);
+ SET_BYTE(H_SCREEN_ROWS, h_screen_rows);
+ SET_BYTE(H_SCREEN_COLS, h_screen_cols);
+ }
+
+ /* It's less trouble to use font size 1x1 for V5 games, especially
+ because of a bug in the unreleased German version of "Zork 1" */
+
+ if (h_version != V6) {
+ screen_x_size = (zword)h_screen_cols;
+ screen_y_size = (zword)h_screen_rows;
+ font_x_size = 1;
+ font_y_size = 1;
+ } else {
+ screen_x_size = h_screen_width;
+ screen_y_size = h_screen_height;
+ font_x_size = h_font_width;
+ font_y_size = h_font_height;
+ }
+
+ if (h_version >= V5) {
+ SET_WORD(H_SCREEN_WIDTH, screen_x_size);
+ SET_WORD(H_SCREEN_HEIGHT, screen_y_size);
+ SET_BYTE(H_FONT_HEIGHT, font_y_size);
+ SET_BYTE(H_FONT_WIDTH, font_x_size);
+ SET_BYTE(H_DEFAULT_BACKGROUND, h_default_background);
+ SET_BYTE(H_DEFAULT_FOREGROUND, h_default_foreground);
+ }
+
+ if (h_version == V6)
+ for (i = 0; i < 8; i++)
+ storeb((zword)(H_USER_NAME + i), h_user_name[i]);
+
+ SET_BYTE(H_STANDARD_HIGH, h_standard_high);
+ SET_BYTE(H_STANDARD_LOW, h_standard_low);
+
+ set_header_extension(HX_FLAGS, hx_flags);
+ set_header_extension(HX_FORE_COLOUR, hx_fore_colour);
+ set_header_extension(HX_BACK_COLOUR, hx_back_colour);
+}
+
+void Mem::storeb(zword addr, zbyte value) {
+ if (addr >= h_dynamic_size)
+ runtimeError(ERR_STORE_RANGE);
+
+ if (addr == H_FLAGS + 1) {
+ // flags register is modified
+
+ h_flags &= ~(SCRIPTING_FLAG | FIXED_FONT_FLAG);
+ h_flags |= value & (SCRIPTING_FLAG | FIXED_FONT_FLAG);
+
+ flagsChanged(value);
+ }
+
+ SET_BYTE(addr, value);
+}
+
+void Mem::storew(zword addr, zword value) {
+ storeb((zword)(addr + 0), hi(value));
+ storeb((zword)(addr + 1), lo(value));
+}
+
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index e12c062..c128994 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -24,6 +24,7 @@
#define GARGOYLE_FROTZ_MEM
#include "gargoyle/frotz/frotz_types.h"
+#include "gargoyle/frotz/err.h"
namespace Gargoyle {
namespace Frotz {
@@ -202,46 +203,51 @@ private:
* Handles loading the game header
*/
void loadGameHeader();
-public:
+protected:
/**
- * Constructor
+ * Read a value from the header extension (former mouse table).
*/
- Mem();
+ zword get_header_extension(int entry);
/**
- * Initialize
+ * Set an entry in the header extension (former mouse table).
*/
- void initialize();
+ void set_header_extension(int entry, zword val);
/**
- * Read a word
+ * Set all header fields which hold information about the interpreter.
*/
- zword readWord() {
- pcp += 2;
- return READ_BE_UINT16(pcp - 2);
- }
+ void restart_header();
/**
- * Read a word at a given index relative to pcp
+ * Write a byte value to the dynamic Z-machine memory.
*/
- zword readWord(size_t ofs) {
- return READ_BE_UINT16(pcp + ofs);
- }
+ void storeb(zword addr, zbyte value);
/**
- * Get the PC
+ * Write a word value to the dynamic Z-machine memory.
*/
- uint getPC() const { return pcp - zmp; }
+ void storew(zword addr, zword value);
/**
- * Set the PC
+ * Generates a runtime error
*/
- void setPC(uint ofs) { pcp = zmp + ofs; }
+ virtual void runtimeError(ErrorCode errNum) = 0;
/**
- * Read a value from the header extension (former mouse table).
+ * Called when the flags are changed
*/
- zword get_header_extension(int entry);
+ virtual void flagsChanged(zbyte value) = 0;
+public:
+ /**
+ * Constructor
+ */
+ Mem();
+
+ /**
+ * Initialize
+ */
+ void initialize();
};
} // End of namespace Frotz
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 1554265..b70bf44 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -208,14 +208,16 @@ private:
*/
/**
- * Write a byte value to the dynamic Z-machine memory.
+ * Generates a runtime error
*/
- void storeb(zword addr, zbyte value);
+ virtual void runtimeError(ErrorCode errNum) override {
+ Errors::runtimeError(errNum);
+ }
/**
- * Write a word value to the dynamic Z-machine memory.
+ * Called when the H_FLAGS field of the header has changed
*/
- void storew(zword addr, zword value);
+ virtual void flagsChanged(zbyte value) override;
/**
* \defgroup Object support methods
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
index 43f0aaf..b9c9604 100644
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -80,35 +80,6 @@ int Processor::read_number() {
return value;
}
-void Processor::storeb(zword addr, zbyte value) {
- if (addr >= h_dynamic_size)
- runtimeError(ERR_STORE_RANGE);
-
- if (addr == H_FLAGS + 1) { /* flags register is modified */
-
- h_flags &= ~(SCRIPTING_FLAG | FIXED_FONT_FLAG);
- h_flags |= value & (SCRIPTING_FLAG | FIXED_FONT_FLAG);
-
- if (value & SCRIPTING_FLAG) {
- if (!ostream_script)
- script_open();
- } else {
- if (ostream_script)
- script_close();
- }
-
- // TOR - glkified / refresh_text_style ();
- }
-
- SET_BYTE(addr, value);
-
-}
-
-void Processor::storew(zword addr, zword value) {
- storeb((zword)(addr + 0), hi(value));
- storeb((zword)(addr + 1), lo(value));
-}
-
void Processor::z_read() {
zchar buffer[INPUT_BUFFER_SIZE];
zword addr;
diff --git a/engines/gargoyle/frotz/processor_mem.cpp b/engines/gargoyle/frotz/processor_mem.cpp
new file mode 100644
index 0000000..1f3944e
--- /dev/null
+++ b/engines/gargoyle/frotz/processor_mem.cpp
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+void Processor::flagsChanged(zbyte value) {
+ if (value & SCRIPTING_FLAG) {
+ if (!ostream_script)
+ script_open();
+ } else {
+ if (ostream_script)
+ script_close();
+ }
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index 3f35c1f..4406275 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -49,7 +49,6 @@ static void record_open() {}
static void record_close() {}
static void record_write_key(zchar) {}
static void record_write_input(zchar *, zchar) {}
-static void restart_header() {}
void Processor::scrollback_char (zchar c) {
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 78bde80..14cc048 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -31,6 +31,7 @@ MODULE_OBJS := \
frotz/processor_buffer.o \
frotz/processor_input.o \
frotz/processor_maths.o \
+ frotz/processor_mem.o \
frotz/processor_objects.o \
frotz/processor_screen.o \
frotz/processor_streams.o \
Commit: 5507242395a0b183b8f445ca5a56284d974687f2
https://github.com/scummvm/scummvm/commit/5507242395a0b183b8f445ca5a56284d974687f2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix casting of vardiac retrieval
Thanks to bgK for identifying the bad cast
Changed paths:
engines/gargoyle/scott/scott.cpp
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 3316995..698a2ea 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -1241,7 +1241,7 @@ void Scott::readInts(Common::SeekableReadStream *f, size_t count, ...) {
c = f->readByte();
// Get the next value
- int *val = (int *)va_arg(va, int);
+ int *val = va_arg(va, int *);
*val = 0;
int factor = c == '-' ? -1 : 1;
Commit: e1de76b491e5145b837b55f7313b8fff07986572
https://github.com/scummvm/scummvm/commit/e1de76b491e5145b837b55f7313b8fff07986572
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added remaining memory methods
Changed paths:
engines/gargoyle/frotz/mem.cpp
engines/gargoyle/frotz/mem.h
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_input.cpp
engines/gargoyle/frotz/processor_mem.cpp
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
index 57b2825..ad60b89 100644
--- a/engines/gargoyle/frotz/mem.cpp
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -320,6 +320,103 @@ void Mem::storew(zword addr, zword value) {
storeb((zword)(addr + 1), lo(value));
}
+void Mem::free_undo(int count) {
+ undo_t *p;
+
+ if (count > undo_count)
+ count = undo_count;
+ while (count--) {
+ p = first_undo;
+ if (curr_undo == first_undo)
+ curr_undo = curr_undo->next;
+ first_undo = first_undo->next;
+ free(p);
+ undo_count--;
+ }
+ if (first_undo)
+ first_undo->prev = NULL;
+ else
+ last_undo = NULL;
+}
+
+void Mem::reset_memory() {
+ story_fp = nullptr;
+ blorb_ofs = 0;
+ blorb_len = 0;
+
+ if (undo_mem) {
+ free_undo(undo_count);
+ delete undo_mem;
+ }
+
+ undo_mem = nullptr;
+ undo_count = 0;
+ delete[] zmp;
+ zmp = nullptr;
+}
+
+long Mem::mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff) {
+ unsigned size = mem_size;
+ zbyte *p = diff;
+ unsigned j;
+ zbyte c = 0;
+
+ for (;;) {
+ for (j = 0; size > 0 && (c = *a++ ^ *b++) == 0; j++)
+ size--;
+ if (size == 0) break;
+ size--;
+ if (j > 0x8000) {
+ *p++ = 0;
+ *p++ = 0xff;
+ *p++ = 0xff;
+ j -= 0x8000;
+ }
+ if (j > 0) {
+ *p++ = 0;
+ j--;
+ if (j <= 0x7f) {
+ *p++ = j;
+ } else {
+ *p++ = (j & 0x7f) | 0x80;
+ *p++ = (j & 0x7f80) >> 7;
+ }
+ }
+
+ *p++ = c;
+ *(b - 1) ^= c;
+ }
+
+ return p - diff;
+}
+
+void Mem::mem_undiff(zbyte *diff, long diff_length, zbyte *dest) {
+ zbyte c;
+
+ while (diff_length) {
+ c = *diff++;
+ diff_length--;
+ if (c == 0) {
+ unsigned runlen;
+
+ if (!diff_length)
+ return; // Incomplete run
+ runlen = *diff++;
+ diff_length--;
+ if (runlen & 0x80) {
+ if (!diff_length)
+ return; // Incomplete extended run
+ c = *diff++;
+ diff_length--;
+ runlen = (runlen & 0x7f) | (((unsigned)c) << 7);
+ }
+
+ dest += runlen + 1;
+ } else {
+ *dest++ ^= c;
+ }
+ }
+}
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index c128994..a45eec5 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -230,6 +230,11 @@ protected:
void storew(zword addr, zword value);
/**
+ * Free count undo blocks from the beginning of the undo list
+ */
+ void free_undo(int count);
+
+ /**
* Generates a runtime error
*/
virtual void runtimeError(ErrorCode errNum) = 0;
@@ -238,6 +243,26 @@ protected:
* Called when the flags are changed
*/
virtual void flagsChanged(zbyte value) = 0;
+
+ /**
+ * Close the story file and deallocate memory.
+ */
+ void reset_memory();
+
+ /**
+ * Set diff to a Quetzal-like difference between a and b,
+ * copying a to b as we go. It is assumed that diff points to a
+ * buffer which is large enough to hold the diff.
+ * mem_size is the number of bytes to compare.
+ * Returns the number of bytes copied to diff.
+ *
+ */
+ long mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff);
+
+ /**
+ * Applies a quetzal-like diff to dest
+ */
+ void mem_undiff(zbyte *diff, long diff_length, zbyte *dest);
public:
/**
* Constructor
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index b70bf44..f9352ec 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -220,6 +220,18 @@ private:
virtual void flagsChanged(zbyte value) override;
/**
+ * This function does the dirty work for z_save_undo.
+ */
+ int save_undo();
+
+ /**
+ * This function does the dirty work for z_restore_undo.
+ */
+ int restore_undo();
+
+ /**@}*/
+
+ /**
* \defgroup Object support methods
* @{
*/
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
index b9c9604..48951d2 100644
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -26,7 +26,6 @@ namespace Gargoyle {
namespace Frotz {
// TODO: Implement method stubs
-static void save_undo() {}
static zword os_read_mouse() { return 0; }
diff --git a/engines/gargoyle/frotz/processor_mem.cpp b/engines/gargoyle/frotz/processor_mem.cpp
index 1f3944e..71abe77 100644
--- a/engines/gargoyle/frotz/processor_mem.cpp
+++ b/engines/gargoyle/frotz/processor_mem.cpp
@@ -35,5 +35,88 @@ void Processor::flagsChanged(zbyte value) {
}
}
+int Processor::save_undo() {
+ long diff_size;
+ zword stack_size;
+ undo_t *p;
+
+ if (_undo_slots == 0)
+ // undo feature unavailable
+ return -1;
+
+ // save undo possible
+ while (last_undo != curr_undo) {
+ p = last_undo;
+ last_undo = last_undo->prev;
+ delete p;
+ undo_count--;
+ }
+ if (last_undo)
+ last_undo->next = nullptr;
+ else
+ first_undo = nullptr;
+
+ if (undo_count == _undo_slots)
+ free_undo(1);
+
+ diff_size = mem_diff(zmp, prev_zmp, h_dynamic_size, undo_diff);
+ stack_size = _stack + STACK_SIZE - _sp;
+ do {
+ p = (undo_t *) malloc(sizeof(undo_t) + diff_size + stack_size * sizeof(*_sp));
+ if (p == nullptr)
+ free_undo(1);
+ } while (!p && undo_count);
+ if (p == nullptr)
+ return -1;
+
+ GET_PC(p->pc);
+ p->frame_count = _frameCount;
+ p->diff_size = diff_size;
+ p->stack_size = stack_size;
+ p->frame_offset = _fp - _stack;
+ memcpy(p + 1, undo_diff, diff_size);
+ memcpy((zbyte *)(p + 1) + diff_size, _sp, stack_size * sizeof(*_sp));
+
+ if (!first_undo) {
+ p->prev = nullptr;
+ first_undo = p;
+ } else {
+ last_undo->next = p;
+ p->prev = last_undo;
+ }
+
+ p->next = nullptr;
+ curr_undo = last_undo = p;
+ undo_count++;
+
+ return 1;
+}
+
+int Processor::restore_undo(void) {
+ if (_undo_slots == 0)
+ // undo feature unavailable
+ return -1;
+
+ if (curr_undo == nullptr)
+ // no saved game state
+ return 0;
+
+ // undo possible
+ memcpy(zmp, prev_zmp, h_dynamic_size);
+ SET_PC(curr_undo->pc);
+ _sp = _stack + STACK_SIZE - curr_undo->stack_size;
+ _fp = _stack + curr_undo->frame_offset;
+ _frameCount = curr_undo->frame_count;
+ mem_undiff((zbyte *)(curr_undo + 1), curr_undo->diff_size, prev_zmp);
+ memcpy(_sp, (zbyte *)(curr_undo + 1) + curr_undo->diff_size,
+ curr_undo->stack_size * sizeof(*_sp));
+
+ curr_undo = curr_undo->prev;
+
+ restart_header();
+
+ return 2;
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
Commit: 2c37a949136e4bd6a38daf420eb4638ce8d5f4ae
https://github.com/scummvm/scummvm/commit/2c37a949136e4bd6a38daf420eb4638ce8d5f4ae
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Fix detecting .dat gamefiles, added Windows game versions detections
Changed paths:
engines/gargoyle/detection.cpp
engines/gargoyle/scott/detection.cpp
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
index 5ff0cc7..61cf201 100644
--- a/engines/gargoyle/detection.cpp
+++ b/engines/gargoyle/detection.cpp
@@ -133,7 +133,8 @@ static const PlainGameDescriptor gargoyleGames[] = {
{ "adventure13", "Adventure 13" },
{ "adventure14", "Adventure 14" },
{ "buckaroobonzai", "Buckaroo Banzai" },
-
+ { "marveladventure", "Marvel Adventure #1" },
+ { "scottsampler", "Adventure International's Mini-Adventure Sampler" },
{0, 0}
};
diff --git a/engines/gargoyle/scott/detection.cpp b/engines/gargoyle/scott/detection.cpp
index 1b8041a..e4047a5 100644
--- a/engines/gargoyle/scott/detection.cpp
+++ b/engines/gargoyle/scott/detection.cpp
@@ -35,6 +35,25 @@ struct ScottGame {
};
const ScottGame SCOTT_GAMES[] = {
+ // PC game versions
+ { "7c6f495d757a54e73d259efc718d8024", "adventureland", 15896, "Adventureland" },
+ { "ea535fa7684508410151b4561de1f323", "pirateadventure", 16325, "Pirate Adventure" },
+ { "379c77a9a483886366b3b5c425e56410", "missionimpossible", 15275, "Mission Impossible" },
+ { "a530a6857d1092eaa177eee575c94c71", "voodoocastle", 15852, "Voodoo Castle" },
+ { "5ebb4ade985670bb2eac54f8fa202214", "thecount", 17476, "The Count" },
+ { "c57bb6df04dc77a2b232bc5bcab6e417", "strangeodyssey", 17489, "Strange Odyssey" },
+ { "ce2931ac3d5cbc270a5cb7be9e614f6e", "mysteryfunhouse", 17165, "Mystery Fun House" },
+ { "4e6127fad6b5d75eccd3f3b101f8c9c8", "pyramidofdoom", 17673, "Pyramid Of Doom" },
+ { "2c08327ab06d5490bd9e367ddaeca627", "ghosttown", 17831, "Ghost Town" },
+ { "8feb77f11d32e9567ce2fc7d435eaf44", "savageisland1", 19533, "Savage Island, Part 1" },
+ { "20c40a349f7a214ac515fb1d63c30a87", "savageisland2", 18367, "Savage Island, Part 2" },
+ { "e2a8f956ab215012d1495550c4c11ee8", "goldenvoyage", 18513, "The Golden Voyage" },
+ { "f986d7e1ee074f65b6c1d00461c9b3c3", "adventure13", 19232, "Adventure 13" },
+ { "6d98f422cc986d959a3c74351785aea3", "adventure14", 19013, "Adventure 14" },
+ { "aadcc04e6b37eb9d30a58b5bc775842e", "marveladventure", 18876, "Marvel Adventure #1" },
+ { "d569a769f304dc02b3062d97458ddd01", "scottsampler", 13854, "Adventure International's Mini-Adventure Sampler" },
+
+ // PDA game versions
{ "ae541fc1085da2f7d561b72ed20a6bc1", "adventureland", 18003, "Adventureland" },
{ "cbd47ab4fcfe00231ffd71d52378d410", "pirateadventure", 18482, "Pirate Adventure" },
{ "9251ab2c64e63559d8a6e9e6246760a5", "missionimpossible", 17227, "Mission Impossible" },
@@ -59,7 +78,8 @@ bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory() || !file->getName().hasSuffix(".saga"))
+ if (file->isDirectory() || !(file->getName().hasSuffixIgnoreCase(".saga")
+ || file->getName().hasSuffixIgnoreCase(".dat")))
continue;
if (gameFile.open(*file)) {
Commit: 7a52f21c0bb267d6851ede650298b1d084493ef6
https://github.com/scummvm/scummvm/commit/7a52f21c0bb267d6851ede650298b1d084493ef6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added script/record/transcript/replay methods
Changed paths:
engines/gargoyle/frotz/processor.cpp
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_input.cpp
engines/gargoyle/frotz/processor_streams.cpp
engines/gargoyle/glk.h
engines/gargoyle/streams.cpp
engines/gargoyle/streams.h
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
index 9341013..ac18a23 100644
--- a/engines/gargoyle/frotz/processor.cpp
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -136,7 +136,8 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
_randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false),
- _bufPos(0), _locked(false), _prevC('\0') {
+ _bufPos(0), _locked(false), _prevC('\0'), script_width(0),
+ sfp(nullptr), rfp(nullptr), pfp(nullptr) {
static const Opcode OP0_OPCODES[16] = {
&Processor::z_rtrue,
&Processor::z_rfalse,
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index f9352ec..50c951a 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -79,6 +79,10 @@ private:
Opcode op1_opcodes[16];
static Opcode var_opcodes[64];
static Opcode ext_opcodes[64];
+
+ // Stream related fields
+ int script_width;
+ strid_t sfp, rfp, pfp;
private:
/**
* \defgroup General support methods
@@ -358,7 +362,102 @@ private:
*/
void script_close();
- /**@}*/
+ /**
+ * Write a newline to the transscript file.
+ */
+ void script_new_line();
+
+ /**
+ * Write a single character to the transscript file.
+ */
+ void script_char(zchar c);
+
+ /**
+ * Write a string to the transscript file.
+ */
+ void script_word(const zchar *s);
+
+ /**
+ * Send an input line to the transscript file.
+ */
+ void script_write_input(const zchar *buf, zchar key);
+
+ /**
+ * Remove an input line from the transscript file.
+ */
+ void script_erase_input(const zchar *buf);
+
+ /**
+ * Start sending a "debugging" message to the transscript file.
+ */
+ void script_mssg_on();
+
+ /**
+ * Stop writing a "debugging" message.
+ */
+ void script_mssg_off();
+
+ /**
+ * Open a file to record the player's input.
+ */
+ void record_open();
+
+ /**
+ * Stop recording the player's input.
+ */
+ void record_close();
+
+ /**
+ * Helper function for record_char.
+ */
+ void record_code(int c, bool force_encoding);
+
+ /**
+ * Write a character to the command file.
+ */
+ void record_char(zchar c);
+
+ /**
+ * Copy a keystroke to the command file.
+ */
+ void record_write_key(zchar key);
+
+ /**
+ * Copy a line of input to a command file.
+ */
+ void record_write_input(const zchar *buf, zchar key);
+
+ /**
+ * Open a file of commands for playback.
+ */
+ void replay_open();
+
+ /**
+ * Stop playback of commands.
+ */
+ void replay_close();
+
+ /*
+ * Helper function for replay_key and replay_line.
+ */
+ int replay_code();
+
+ /**
+ * Read a character from the command file.
+ */
+ zchar replay_char();
+
+ /**
+ * Read a keystroke from a command file.
+ */
+ zchar replay_read_key();
+
+ /*
+ * Read a line of input from a command file.
+ */
+ zchar replay_read_input(zchar *buf);
+
+ /**@}*/
/**
* \defgroup Text support methods
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
index 48951d2..89aa188 100644
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -31,13 +31,6 @@ static zword os_read_mouse() { return 0; }
#define INPUT_BUFFER_SIZE 200
-void Processor::z_make_menu() {
- // This opcode was only used for the Macintosh version of Journey.
- // It controls menus with numbers greater than 2 (menus 0, 1 and 2
- // are system menus).
- branch (false);
-}
-
bool Processor::read_yes_or_no(const char *s) {
zchar key;
@@ -65,6 +58,39 @@ void Processor::read_string(int max, zchar *buffer) {
} while (key != ZC_RETURN);
}
+bool Processor::is_terminator(zchar key) {
+ if (key == ZC_TIME_OUT)
+ return true;
+ if (key == ZC_RETURN)
+ return true;
+ if (key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX)
+ return true;
+
+ if (h_terminating_keys != 0) {
+ if (key >= ZC_ARROW_MIN && key <= ZC_MENU_CLICK) {
+
+ zword addr = h_terminating_keys;
+ zbyte c;
+
+ do {
+ LOW_BYTE(addr, c);
+ if (c == 255 || key == translate_from_zscii(c))
+ return true;
+ addr++;
+ } while (c != 0);
+ }
+ }
+
+ return false;
+}
+
+void Processor::z_make_menu() {
+ // This opcode was only used for the Macintosh version of Journey.
+ // It controls menus with numbers greater than 2 (menus 0, 1 and 2
+ // are system menus).
+ branch(false);
+}
+
int Processor::read_number() {
zchar buffer[6];
int value = 0;
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index 4406275..95205a5 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -28,30 +28,15 @@ namespace Frotz {
// TODO: Implement method stubs
static void os_scrollback_char(zchar) {}
static void os_scrollback_erase(zword) {}
-static void script_mssg_on() {}
-static void script_mssg_off() {}
-static void script_char(zchar) {}
-static void script_word(const zchar *) {}
-static void script_new_line() {}
-static void script_erase_input(const zchar *) {}
-static void script_write_input(zchar *, char) {}
static void memory_open(zword, zword, bool) {}
static void memory_close() {}
static void memory_word(const zchar *) {}
static void memory_new_line() {}
-static void replay_open() {}
-static void replay_close() {}
-static zchar replay_read_key() { return 0; }
-static zchar replay_read_input(zchar *) { return 0; }
static zchar console_read_key(zword) { return 0; }
static zchar console_read_input(uint, zchar *, uint, bool) { return 0; }
-static void record_open() {}
-static void record_close() {}
-static void record_write_key(zchar) {}
-static void record_write_input(zchar *, zchar) {}
-void Processor::scrollback_char (zchar c) {
+void Processor::scrollback_char(zchar c) {
if (c == ZC_INDENT)
{ scrollback_char (' '); scrollback_char (' '); scrollback_char (' '); return; }
if (c == ZC_GAP)
@@ -219,13 +204,282 @@ continue_input:
}
void Processor::script_open() {
- // TODO
+ h_flags &= ~SCRIPTING_FLAG;
+
+ frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript,
+ filemode_WriteAppend);
+ sfp = glk_stream_open_file(fref, filemode_WriteAppend);
+
+ if (sfp != nullptr) {
+ sfp->setPosition(0, seekmode_End);
+
+ h_flags |= SCRIPTING_FLAG;
+
+ script_valid = true;
+ ostream_script = true;
+
+ script_width = 0;
+ } else {
+ print_string("Cannot open file\n");
+ }
+
+ SET_WORD(H_FLAGS, h_flags);
}
void Processor::script_close() {
- // TODO
+ h_flags &= ~SCRIPTING_FLAG;
+ SET_WORD(H_FLAGS, h_flags);
+
+ glk_stream_close(sfp);
+ ostream_script = false;
+}
+
+void Processor::script_new_line() {
+ script_char('\n');
+ script_width = 0;
+}
+
+void Processor::script_char(zchar c) {
+ if (c == ZC_INDENT && script_width != 0)
+ c = ' ';
+
+ if (c == ZC_INDENT) {
+ script_char(' ');
+ script_char(' ');
+ script_char(' ');
+ return;
+ }
+ if (c == ZC_GAP) {
+ script_char(' ');
+ script_char(' ');
+ return;
+ }
+
+ sfp->putCharUni(c);
+ script_width++;
+}
+
+void Processor::script_word(const zchar *s) {
+ int width;
+ int i;
+
+ if (*s == ZC_INDENT && script_width != 0)
+ script_char(*s++);
+
+ for (i = 0, width = 0; s[i] != 0; i++) {
+ if (s[i] == ZC_NEW_STYLE || s[i] == ZC_NEW_FONT)
+ i++;
+ else if (s[i] == ZC_GAP)
+ width += 3;
+ else if (s[i] == ZC_INDENT)
+ width += 2;
+ else
+ width += 1;
+ }
+
+ if (_script_cols != 0 && script_width + width > _script_cols) {
+ if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
+ s++;
+
+ script_new_line();
+ }
+
+ for (i = 0; s[i] != 0; i++) {
+ if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
+ i++;
+ else
+ script_char(s[i]);
+ }
+}
+
+void Processor::script_write_input(const zchar *buf, zchar key) {
+ int width;
+ int i;
+
+ for (i = 0, width = 0; buf[i] != 0; i++)
+ width++;
+
+ if (_script_cols != 0 && script_width + width > _script_cols)
+ script_new_line();
+
+ for (i = 0; buf[i] != 0; i++)
+ script_char(buf[i]);
+
+ if (key == ZC_RETURN)
+ script_new_line();
+}
+
+void Processor::script_erase_input(const zchar *buf) {
+ int width;
+ int i;
+
+ for (i = 0, width = 0; buf[i] != 0; i++)
+ width++;
+
+ sfp->setPosition(-width, seekmode_Current);
+ script_width -= width;
+}
+
+void Processor::script_mssg_on() {
+ if (script_width != 0)
+ script_new_line();
+
+ script_char(ZC_INDENT);
+}
+
+void Processor::script_mssg_off() {
+ script_new_line();
+}
+
+void Processor::record_open() {
+ frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, filemode_Write);
+ if ((rfp = glk_stream_open_file(fref, filemode_Write)) != nullptr)
+ ostream_record = true;
+ else
+ print_string("Cannot open file\n");
+}
+
+void Processor::record_close() {
+ glk_stream_close(rfp);
+ ostream_record = false;
+}
+
+void Processor::record_code(int c, bool force_encoding) {
+ if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) {
+ int i;
+
+ rfp->putChar('[');
+
+ for (i = 10000; i != 0; i /= 10)
+ if (c >= i || i == 1)
+ rfp->putChar('0' + (c / i) % 10);
+
+ rfp->putChar(']');
+ } else {
+ rfp->putChar(c);
+ }
+}
+
+void Processor::record_char(zchar c) {
+ if (c != ZC_RETURN) {
+ if (c < ZC_HKEY_MIN || c > ZC_HKEY_MAX) {
+ record_code(translate_to_zscii(c), false);
+ if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
+ record_code(mouse_x, true);
+ record_code(mouse_y, true);
+ }
+ } else {
+ record_code(1000 + c - ZC_HKEY_MIN, true);
+ }
+ }
+}
+
+void Processor::record_write_key(zchar key) {
+ record_char(key);
+ rfp->putChar('\n');
+}
+
+void Processor::record_write_input(const zchar *buf, zchar key) {
+ zchar c;
+
+ while ((c = *buf++) != 0)
+ record_char(c);
+
+ record_write_key(key);
+}
+
+void Processor::replay_open() {
+ frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, filemode_Read);
+ if ((pfp = glk_stream_open_file(fref, filemode_Read)) != nullptr)
+ istream_replay = true;
+ else
+ print_string("Cannot open file\n");
+}
+
+void Processor::replay_close() {
+ glk_stream_close(pfp);
+ istream_replay = false;
}
+int Processor::replay_code() {
+ int c;
+
+ if ((c = pfp->getChar()) == '[') {
+ int c2;
+
+ c = 0;
+
+ while ((c2 = pfp->getChar()) != EOF && c2 >= '0' && c2 <= '9')
+ c = 10 * c + c2 - '0';
+
+ return (c2 == ']') ? c : EOF;
+ } else {
+ return c;
+ }
+}
+
+zchar Processor::replay_char() {
+ int c;
+
+ if ((c = replay_code()) != EOF) {
+ if (c != '\n') {
+ if (c < 1000) {
+
+ c = translate_from_zscii(c);
+
+ if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
+ mouse_x = replay_code();
+ mouse_y = replay_code();
+ }
+
+ return c;
+ } else {
+ return ZC_HKEY_MIN + c - 1000;
+ }
+ }
+
+ pfp->unputBuffer("\n", 1);
+ return ZC_RETURN;
+
+ } else {
+ return ZC_BAD;
+ }
+}
+
+zchar Processor::replay_read_key() {
+ zchar key = replay_char();
+
+ if (pfp->getChar() != '\n') {
+ replay_close();
+ return ZC_BAD;
+ } else {
+ return key;
+ }
+}
+
+zchar Processor::replay_read_input(zchar *buf) {
+ zchar c;
+
+ for (;;) {
+ c = replay_char();
+
+ if (c == ZC_BAD || is_terminator(c))
+ break;
+
+ *buf++ = c;
+ }
+
+ *buf = 0;
+
+ if (pfp->getChar() != '\n') {
+ replay_close();
+ return ZC_BAD;
+ } else {
+ return c;
+ }
+}
+
+
void Processor::z_input_stream() {
flush_buffer();
@@ -260,7 +514,7 @@ void Processor::z_output_stream() {
}
}
-void Processor::z_restart(void) {
+void Processor::z_restart() {
flush_buffer();
os_restart_game(RESTART_BEGIN);
@@ -293,8 +547,7 @@ void Processor::z_restart(void) {
os_restart_game(RESTART_END);
}
-
-void Processor::z_save(void) {
+void Processor::z_save() {
#ifdef TODO
bool success = false;
@@ -310,8 +563,7 @@ void Processor::z_save(void) {
glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
- stream_result_t result;
- glk_stream_close(f, &result);
+ glk_stream_close(f);
} else {
long pc;
@@ -430,8 +682,8 @@ void Processor::z_restore() {
release = (unsigned) fgetc (gfp) << 8;
release |= fgetc (gfp);
- (void) fgetc (gfp);
- (void) fgetc (gfp);
+ () fgetc (gfp);
+ () fgetc (gfp);
/* Check the release number */
@@ -460,7 +712,7 @@ void Processor::z_restore() {
for (i = 0; i < skip; i++)
zmp[addr++] = fgetc (story_fp);
zmp[addr] = fgetc (gfp);
- (void) fgetc (story_fp);
+ () fgetc (story_fp);
}
/* Check for errors */
@@ -519,7 +771,7 @@ finished:
#endif
}
-void Processor::z_verify(void) {
+void Processor::z_verify() {
zword checksum = 0;
// Sum all bytes in story file except header bytes
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index a7a1198..2f3620f 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -66,7 +66,7 @@ public:
winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
glui32 wintype, glui32 rock = 0) const;
- void glk_window_close(winid_t win, stream_result_t *result);
+ void glk_window_close(winid_t win, stream_result_t *result = nullptr);
void glk_window_get_size(winid_t win, glui32 *width, glui32 *height);
void glk_window_set_arrangement(winid_t win, glui32 method,
glui32 size, winid_t keyWin);
@@ -87,7 +87,7 @@ public:
strid_t glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock = 0);
strid_t glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
- void glk_stream_close(strid_t str, stream_result_t *result);
+ void glk_stream_close(strid_t str, stream_result_t *result = nullptr);
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);
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index 41f3caf..d5671f1 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -458,32 +458,30 @@ glui32 MemoryStream::getPosition() const {
return ((unsigned char *)_bufPtr - (unsigned char *)_buf);
}
-void MemoryStream::setPosition(glui32 pos, glui32 seekMode) {
- glsi32 newPos = pos;
-
+void MemoryStream::setPosition(glsi32 pos, glui32 seekMode) {
if (!_unicode) {
if (seekMode == seekmode_Current)
- newPos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + newPos;
+ pos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + pos;
else if (seekMode == seekmode_End)
- newPos = ((unsigned char *)_bufEof - (unsigned char *)_buf) + newPos;
+ pos = ((unsigned char *)_bufEof - (unsigned char *)_buf) + pos;
else
- /* newPos = newPos */;
- if (newPos < 0)
- newPos = 0;
- if (newPos > ((unsigned char *)_bufEof - (unsigned char *)_buf))
- newPos = ((unsigned char *)_bufEof - (unsigned char *)_buf);
- _bufPtr = (unsigned char *)_buf + newPos;
+ /* pos = pos */;
+ if (pos < 0)
+ pos = 0;
+ if (pos > ((unsigned char *)_bufEof - (unsigned char *)_buf))
+ pos = ((unsigned char *)_bufEof - (unsigned char *)_buf);
+ _bufPtr = (unsigned char *)_buf + pos;
} else {
if (seekMode == seekmode_Current)
- newPos = ((glui32 *)_bufPtr - (glui32 *)_buf) + newPos;
+ pos = ((glui32 *)_bufPtr - (glui32 *)_buf) + pos;
else if (seekMode == seekmode_End)
- newPos = ((glui32 *)_bufEof - (glui32 *)_buf) + newPos;
+ pos = ((glui32 *)_bufEof - (glui32 *)_buf) + pos;
- if (newPos < 0)
- newPos = 0;
- if (newPos > ((glui32 *)_bufEof - (glui32 *)_buf))
- newPos = ((glui32 *)_bufEof - (glui32 *)_buf);
- _bufPtr = (glui32 *)_buf + newPos;
+ if (pos < 0)
+ pos = 0;
+ if (pos > ((glui32 *)_bufEof - (glui32 *)_buf))
+ pos = ((glui32 *)_bufEof - (glui32 *)_buf);
+ _bufPtr = (glui32 *)_buf + pos;
}
}
@@ -1000,7 +998,7 @@ glui32 FileStream::getPosition() const {
return _outFile ? _outFile->pos() : _inStream->pos();
}
-void FileStream::setPosition(glui32 pos, glui32 seekMode) {
+void FileStream::setPosition(glsi32 pos, glui32 seekMode) {
_lastOp = 0;
if (_unicode)
pos *= 4;
diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h
index 772b021..ea9c651 100644
--- a/engines/gargoyle/streams.h
+++ b/engines/gargoyle/streams.h
@@ -223,7 +223,7 @@ public:
return 0;
}
- virtual void setPosition(glui32 pos, glui32 seekMode) {}
+ virtual void setPosition(glsi32 pos, glui32 seekMode) {}
virtual void setStyle(glui32 val) {}
@@ -390,7 +390,7 @@ public:
virtual glui32 getPosition() const override;
- virtual void setPosition(glui32 pos, glui32 seekMode) override;
+ virtual void setPosition(glsi32 pos, glui32 seekMode) override;
/**
* Get a character from the stream
@@ -492,7 +492,7 @@ public:
virtual glui32 getPosition() const override;
- virtual void setPosition(glui32 pos, glui32 seekMode) override;
+ virtual void setPosition(glsi32 pos, glui32 seekMode) override;
/**
* Get a character from the stream
Commit: aab1dfeff8002a8b8f69d4d5f24110a7a01c263d
https://github.com/scummvm/scummvm/commit/aab1dfeff8002a8b8f69d4d5f24110a7a01c263d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added memory redirect methods
Changed paths:
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_mem.cpp
engines/gargoyle/frotz/processor_streams.cpp
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 2b33fbd..3ccaa45 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -239,6 +239,18 @@ struct UserOptions {
}
};
+#define MAX_NESTING 16
+struct Redirect {
+ zword _xSize;
+ zword _table;
+ zword _width;
+ zword _total;
+
+ Redirect() : _xSize(0), _table(0), _width(0), _total(0) {}
+ Redirect(zword xSize, zword table, zword width = 0, zword total = 0) :
+ _xSize(xSize), _table(table), _width(width), _total(total) {}
+};
+
} // End of namespace Frotz
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 50c951a..0a9d0ef 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -26,6 +26,8 @@
#include "gargoyle/frotz/err.h"
#include "gargoyle/frotz/mem.h"
#include "gargoyle/frotz/glk_interface.h"
+#include "gargoyle/frotz/frotz_types.h"
+#include "common/stack.h"
namespace Gargoyle {
namespace Frotz {
@@ -83,6 +85,7 @@ private:
// Stream related fields
int script_width;
strid_t sfp, rfp, pfp;
+ Common::FixedStack<Redirect, MAX_NESTING> _redirect;
private:
/**
* \defgroup General support methods
@@ -233,6 +236,26 @@ private:
*/
int restore_undo();
+ /**
+ * Begin output redirection to the memory of the Z-machine.
+ */
+ void memory_open(zword table, zword xsize, bool buffering);
+
+ /**
+ * End of output redirection.
+ */
+ void memory_close();
+
+ /**
+ * Redirect a newline to the memory of the Z-machine.
+ */
+ void memory_new_line();
+
+ /**
+ * Redirect a string of characters to the memory of the Z-machine.
+ */
+ void memory_word(const zchar *s);
+
/**@}*/
/**
diff --git a/engines/gargoyle/frotz/processor_mem.cpp b/engines/gargoyle/frotz/processor_mem.cpp
index 71abe77..d46402c 100644
--- a/engines/gargoyle/frotz/processor_mem.cpp
+++ b/engines/gargoyle/frotz/processor_mem.cpp
@@ -118,5 +118,101 @@ int Processor::restore_undo(void) {
return 2;
}
+/**
+ * TOR: glkify -- this is for V6 only
+ */
+static zword get_max_width(zword win) { return 80; }
+
+void Processor::memory_open(zword table, zword xsize, bool buffering) {
+ if (_redirect.size() < MAX_NESTING) {
+ if (!buffering)
+ xsize = 0xffff;
+ if (buffering && (short)xsize <= 0)
+ xsize = get_max_width((zword)(-(short)xsize));
+
+ storew(table, 0);
+
+ _redirect.push(Redirect(xsize, table));
+ ostream_memory = true;
+ } else {
+ runtimeError(ERR_STR3_NESTING);
+ }
+}
+
+void Processor::memory_new_line() {
+ zword size;
+ zword addr;
+
+ Redirect &r = _redirect.top();
+ r._total += r._width;
+ r._width = 0;
+
+ addr = r._table;
+
+ LOW_WORD(addr, size);
+ addr += 2;
+
+ if (r._xSize != 0xffff) {
+ r._table = addr + size;
+ size = 0;
+ } else {
+ storeb((zword)(addr + (size++)), 13);
+ }
+
+ storew(r._table, size);
+}
+
+void Processor::memory_word(const zchar *s) {
+ zword size;
+ zword addr;
+ zchar c;
+
+ Redirect &r = _redirect.top();
+ if (h_version == V6) {
+ int width = os_string_width(s);
+
+ if (r._xSize != 0xffff) {
+ if (r._width + width > r._xSize) {
+
+ if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
+ width = os_string_width(++s);
+
+ memory_new_line();
+ }
+ }
+
+ r._width += width;
+ }
+
+ addr = r._table;
+
+ LOW_WORD(addr, size);
+ addr += 2;
+
+ while ((c = *s++) != 0)
+ storeb((zword)(addr + (size++)), translate_to_zscii(c));
+
+ storew(r._table, size);
+}
+
+void Processor::memory_close(void) {
+ if (!_redirect.empty()) {
+ Redirect &r = _redirect.top();
+
+ if (r._xSize != 0xffff)
+ memory_new_line();
+
+ if (h_version == V6) {
+ h_line_width = (r._xSize != 0xffff) ? r._total : r._width;
+
+ SET_WORD(H_LINE_WIDTH, h_line_width);
+ }
+
+ _redirect.pop();
+ if (_redirect.empty())
+ ostream_memory = false;
+ }
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index 95205a5..97784c8 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -28,10 +28,6 @@ namespace Frotz {
// TODO: Implement method stubs
static void os_scrollback_char(zchar) {}
static void os_scrollback_erase(zword) {}
-static void memory_open(zword, zword, bool) {}
-static void memory_close() {}
-static void memory_word(const zchar *) {}
-static void memory_new_line() {}
static zchar console_read_key(zword) { return 0; }
static zchar console_read_input(uint, zchar *, uint, bool) { return 0; }
Commit: 7d2406870e733258c7d59d54a7b490fbf52c2109
https://github.com/scummvm/scummvm/commit/7d2406870e733258c7d59d54a7b490fbf52c2109
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add screen message methods
Changed paths:
engines/gargoyle/frotz/glk_interface.cpp
engines/gargoyle/frotz/glk_interface.h
engines/gargoyle/frotz/processor_buffer.cpp
engines/gargoyle/frotz/processor_input.cpp
engines/gargoyle/frotz/processor_screen.cpp
diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp
index 13d0a56..c536a48 100644
--- a/engines/gargoyle/frotz/glk_interface.cpp
+++ b/engines/gargoyle/frotz/glk_interface.cpp
@@ -397,5 +397,12 @@ void GlkInterface::smartstatusline() {
glk_window_move_cursor(gos_upper, cury - 1, curx - 1);
}
+void GlkInterface::gos_cancel_pending_line() {
+ event_t ev;
+ glk_cancel_line_event(gos_linewin, &ev);
+ gos_linebuf[ev.val1] = '\0';
+ gos_linepending = 0;
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
index 161a1f3..aeb33a8 100644
--- a/engines/gargoyle/frotz/glk_interface.h
+++ b/engines/gargoyle/frotz/glk_interface.h
@@ -143,9 +143,22 @@ protected:
void smartstatusline();
/**
+ * Cancels any pending line
+ */
+ void gos_cancel_pending_line();
+
+ /**
* Called during game restarts
*/
void os_restart_game(RestartAction) {}
+
+ /**
+ * Reads the mouse buttons
+ */
+ zword os_read_mouse() {
+ // Not implemented
+ return 0;
+ }
public:
/**
* Constructor
diff --git a/engines/gargoyle/frotz/processor_buffer.cpp b/engines/gargoyle/frotz/processor_buffer.cpp
index be30bfe..b2b6ccd 100644
--- a/engines/gargoyle/frotz/processor_buffer.cpp
+++ b/engines/gargoyle/frotz/processor_buffer.cpp
@@ -27,11 +27,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Replace these method stubs with correct calls
-void stream_char(zchar) {}
-void stream_word(const zchar *) {}
-void stream_new_line(void) {}
-
void Processor::flush_buffer() {
/* Make sure we stop when flush_buffer is called from flush_buffer.
* Note that this is difficult to avoid as we might print a newline
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
index 89aa188..fa9da21 100644
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ b/engines/gargoyle/frotz/processor_input.cpp
@@ -25,10 +25,6 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Implement method stubs
-static zword os_read_mouse() { return 0; }
-
-
#define INPUT_BUFFER_SIZE 200
bool Processor::read_yes_or_no(const char *s) {
diff --git a/engines/gargoyle/frotz/processor_screen.cpp b/engines/gargoyle/frotz/processor_screen.cpp
index 27d3cda..77e2e94 100644
--- a/engines/gargoyle/frotz/processor_screen.cpp
+++ b/engines/gargoyle/frotz/processor_screen.cpp
@@ -25,28 +25,106 @@
namespace Gargoyle {
namespace Frotz {
-void Processor::screen_char(zchar c) {
- // TODO
+void Processor::screen_mssg_on() {
+ if (gos_curwin == gos_lower) {
+ oldstyle = curstyle;
+ glk_set_style(style_Preformatted);
+ glk_put_string("\n ");
+ }
}
-void Processor::screen_new_line() {
- // TODO
+void Processor::screen_mssg_off() {
+ if (gos_curwin == gos_lower) {
+ glk_put_char('\n');
+ zargs[0] = 0;
+ z_set_text_style();
+ zargs[0] = oldstyle;
+ z_set_text_style();
+ }
}
-void Processor::screen_word(const zchar *s) {
- // TODO
+void Processor::screen_char(zchar c) {
+ if (gos_linepending && (gos_curwin == gos_linewin)) {
+ gos_cancel_pending_line();
+ if (gos_curwin == gos_upper) {
+ curx = 1;
+ cury ++;
+ }
+ if (c == '\n')
+ return;
+ }
+
+ // check fixed flag in header, game can change it at whim
+ int forcefix = ((h_flags & FIXED_FONT_FLAG) != 0);
+ int curfix = ((curstyle & FIXED_WIDTH_STYLE) != 0);
+ if (forcefix && !curfix) {
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ fixforced = true;
+ } else if (!forcefix && fixforced) {
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ fixforced = false;
+ }
+
+ if (gos_upper && gos_curwin == gos_upper) {
+ if (c == '\n' || c == ZC_RETURN) {
+ glk_put_char('\n');
+ curx = 1;
+ cury ++;
+ } else {
+ if (cury == 1) {
+ if (curx <= ((sizeof statusline / sizeof(zchar)) - 1)) {
+ statusline[curx - 1] = c;
+ statusline[curx] = 0;
+ }
+ if (curx < h_screen_cols) {
+ glk_put_char_uni(c);
+ } else if (curx == h_screen_cols) {
+ glk_put_char_uni(c);
+ glk_window_move_cursor(gos_curwin, curx-1, cury-1);
+ } else {
+ smartstatusline();
+ }
+
+ curx++;
+ } else {
+ if (curx < h_screen_cols) {
+ glk_put_char_uni(c);
+ } else if (curx == (h_screen_cols)) {
+ glk_put_char_uni(c);
+ glk_window_move_cursor(gos_curwin, curx-1, cury-1);
+ }
+
+ curx++;
+ }
+ }
+ } else if (gos_curwin == gos_lower) {
+ if (c == ZC_RETURN)
+ glk_put_char('\n');
+ else glk_put_char_uni(c);
+ }
}
-void Processor::screen_mssg_on() {
- // TODO
+void Processor::screen_new_line() {
+ screen_char('\n');
}
-void Processor::screen_mssg_off() {
- // TODO
+void Processor::screen_word(const zchar *s) {
+ zchar c;
+ while ((c = *s++) != 0) {
+ if (c == ZC_NEW_FONT)
+ s++;
+ else if (c == ZC_NEW_STYLE)
+ s++;
+ else
+ screen_char(c);
+ }
}
void Processor::z_buffer_mode() {
+ // No implementation
}
void Processor::z_buffer_screen() {
Commit: ce7113b34a808ef8136114881f9d19ce857d13bc
https://github.com/scummvm/scummvm/commit/ce7113b34a808ef8136114881f9d19ce857d13bc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added OS read line and character methods
Changed paths:
engines/gargoyle/frotz/glk_interface.cpp
engines/gargoyle/frotz/glk_interface.h
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_streams.cpp
diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp
index c536a48..c376dc0 100644
--- a/engines/gargoyle/frotz/glk_interface.cpp
+++ b/engines/gargoyle/frotz/glk_interface.cpp
@@ -404,5 +404,95 @@ void GlkInterface::gos_cancel_pending_line() {
gos_linepending = 0;
}
+zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
+ event_t ev;
+ winid_t win = gos_curwin ? gos_curwin : gos_lower;
+
+ if (gos_linepending)
+ gos_cancel_pending_line();
+
+ glk_request_char_event_uni(win);
+ if (timeout != 0)
+ glk_request_timer_events(timeout * 100);
+
+ while (!shouldQuit()) {
+ glk_select(&ev);
+ if (ev.type == evtype_Arrange) {
+ gos_update_height();
+ gos_update_width();
+ } else if (ev.type == evtype_Timer) {
+ glk_cancel_char_event(win);
+ glk_request_timer_events(0);
+ return ZC_TIME_OUT;
+ } else if (ev.type == evtype_CharInput)
+ break;
+ }
+ if (shouldQuit())
+ return 0;
+
+ glk_request_timer_events(0);
+
+ if (gos_upper && mach_status_ht < curr_status_ht)
+ reset_status_ht();
+ curr_status_ht = 0;
+
+ switch (ev.val1) {
+ case keycode_Escape: return ZC_ESCAPE;
+ case keycode_PageUp: return ZC_ARROW_MIN;
+ case keycode_PageDown: return ZC_ARROW_MAX;
+ case keycode_Left: return ZC_ARROW_LEFT;
+ case keycode_Right: return ZC_ARROW_RIGHT;
+ case keycode_Up: return ZC_ARROW_UP;
+ case keycode_Down: return ZC_ARROW_DOWN;
+ case keycode_Return: return ZC_RETURN;
+ case keycode_Delete: return ZC_BACKSPACE;
+ case keycode_Tab: return ZC_INDENT;
+ default:
+ return ev.val1;
+ }
+}
+
+zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, int continued) {
+ event_t ev;
+ winid_t win = gos_curwin ? gos_curwin : gos_lower;
+
+ if (!continued && gos_linepending)
+ gos_cancel_pending_line();
+
+ if (!continued || !gos_linepending) {
+ glk_request_line_event_uni(win, buf, max, os_string_length(buf));
+ if (timeout != 0)
+ glk_request_timer_events(timeout * 100);
+ }
+
+ gos_linepending = 0;
+
+ while (!shouldQuit()) {
+ glk_select(&ev);
+ if (ev.type == evtype_Arrange) {
+ gos_update_height();
+ gos_update_width();
+ } else if (ev.type == evtype_Timer) {
+ gos_linewin = win;
+ gos_linepending = 1;
+ gos_linebuf = buf;
+ return ZC_TIME_OUT;
+ } else if (ev.type == evtype_LineInput) {
+ break;
+ }
+ }
+ if (shouldQuit())
+ return 0;
+
+ glk_request_timer_events(0);
+ buf[ev.val1] = '\0';
+
+ if (gos_upper && mach_status_ht < curr_status_ht)
+ reset_status_ht();
+ curr_status_ht = 0;
+
+ return ZC_RETURN;
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
index aeb33a8..5393c5d 100644
--- a/engines/gargoyle/frotz/glk_interface.h
+++ b/engines/gargoyle/frotz/glk_interface.h
@@ -159,6 +159,24 @@ protected:
// Not implemented
return 0;
}
+
+ void os_scrollback_char(zchar z) {
+ // Not implemented
+ }
+
+ void os_scrollback_erase(int amount) {
+ // Not implemented
+ }
+
+ /**
+ * Waits for a keypress
+ */
+ zchar os_read_key(int timeout, bool show_cursor);
+
+ /**
+ * Waits for the user to type an input line
+ */
+ zchar os_read_line(int max, zchar *buf, int timeout, int width, int continued);
public:
/**
* Constructor
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 0a9d0ef..6a28121 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -309,6 +309,16 @@ private:
*/
/**
+ * Waits for the user to type an input line
+ */
+ zchar console_read_input(int max, zchar *buf, zword timeout, bool continued);
+
+ /**
+ * Waits for a keypress
+ */
+ zchar console_read_key(zword timeout);
+
+ /**
* Write a single character to the scrollback buffer.
*
*/
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index 97784c8..d75819e 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -25,12 +25,13 @@
namespace Gargoyle {
namespace Frotz {
-// TODO: Implement method stubs
-static void os_scrollback_char(zchar) {}
-static void os_scrollback_erase(zword) {}
-static zchar console_read_key(zword) { return 0; }
-static zchar console_read_input(uint, zchar *, uint, bool) { return 0; }
+zchar Processor::console_read_input(int max, zchar *buf, zword timeout, bool continued) {
+ return os_read_line(max, buf, timeout, max, continued);
+}
+zchar Processor::console_read_key(zword timeout) {
+ return os_read_key(timeout, 0);
+}
void Processor::scrollback_char(zchar c) {
if (c == ZC_INDENT)
Commit: c19d40fa781a414560341a1d357b64875791f17f
https://github.com/scummvm/scummvm/commit/c19d40fa781a414560341a1d357b64875791f17f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Implemented Quetzal class for savegames
Changed paths:
A engines/gargoyle/frotz/quetzal.cpp
A engines/gargoyle/frotz/quetzal.h
engines/gargoyle/frotz/err.h
engines/gargoyle/frotz/mem.cpp
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_streams.cpp
engines/gargoyle/gargoyle.h
engines/gargoyle/module.mk
engines/gargoyle/streams.cpp
diff --git a/engines/gargoyle/frotz/err.h b/engines/gargoyle/frotz/err.h
index e71c988..090ce3f 100644
--- a/engines/gargoyle/frotz/err.h
+++ b/engines/gargoyle/frotz/err.h
@@ -96,7 +96,7 @@ protected:
/**
* Get the PC. Is implemented by the Processor class, which derives from Errors
*/
- virtual zword getPC() const = 0;
+ virtual uint getPC() const = 0;
public:
/**
* Constructor
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
index ad60b89..e327fba 100644
--- a/engines/gargoyle/frotz/mem.cpp
+++ b/engines/gargoyle/frotz/mem.cpp
@@ -129,14 +129,11 @@ void Mem::initialize() {
// Load story file in chunks of 32KB
uint n = 0x8000;
-
for (uint size = 64; size < story_size; size += n) {
if (story_size - size < 0x8000)
n = story_size - size;
- SET_PC(size);
-
- if (story_fp->read(pcp, n) != n)
+ if (story_fp->read(zmp + size, n) != n)
error("Story file read error");
}
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 6a28121..0f7ecc0 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -32,25 +32,27 @@
namespace Gargoyle {
namespace Frotz {
-#define CODE_BYTE(v) v = *pcp++
-#define CODE_WORD(v) v = READ_BE_UINT16(pcp += 2)
-#define CODE_IDX_WORD(v,i) v = READ_BE_UINT16(pcp + i)
-#define GET_PC(v) v = pcp - zmp
-#define SET_PC(v) pcp = zmp + v
-
#define TEXT_BUFFER_SIZE 200
+#define CODE_BYTE(v) v = codeByte()
+#define CODE_WORD(v) v = codeWord()
+#define CODE_IDX_WORD(v,i) v = codeWordIdx(i)
+#define GET_PC(v) v = getPC()
+#define SET_PC(v) setPC(v)
+
enum string_type {
LOW_STRING, ABBREVIATION, HIGH_STRING, EMBEDDED_STRING, VOCABULARY
};
class Processor;
+class Quetzal;
typedef void (Processor::*Opcode)();
/**
* Zcode processor
*/
class Processor : public Errors, public GlkInterface, public virtual Mem {
+ friend class Quetzal;
private:
int _finished;
zword zargs[8];
@@ -1510,11 +1512,6 @@ protected:
void z_store();
/**@}*/
-protected:
- /**
- * Get the PC. Is implemented by the Processor class, which derives from Errors
- */
- virtual zword getPC() const { return pcp - zmp; }
public:
/**
* Constructor
@@ -1530,6 +1527,50 @@ public:
* Z-code interpreter main loop
*/
void interpret();
+
+ /**
+ * \defgroup Memory access methods
+ * @{
+ */
+
+ /**
+ * Square brackets operator
+ */
+ zbyte &operator[](uint addr) { return zmp[addr]; }
+
+ /**
+ * Read a code byte
+ */
+ zbyte codeByte() { return *pcp++; }
+
+ /**
+ * Read a code word
+ */
+ zword codeWord() {
+ zword v = READ_BE_UINT16(pcp);
+ pcp += 2;
+ return v;
+ }
+
+ /**
+ * Return a code word at a given address
+ */
+ zword codeWordIdx(uint addr) const {
+ return READ_BE_UINT16(pcp + addr);
+ }
+
+ /**
+ * Return the current program execution offset
+ * @remarks This virtual as a convenient way for the ancestor Err class to access
+ */
+ virtual uint getPC() const override { return pcp - zmp; }
+
+ /**
+ * Set the program execution offset
+ */
+ void setPC(uint addr) { pcp = zmp + addr; }
+
+ /**@}*/
};
} // End of namespace Frotz
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
index d75819e..50d6425 100644
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ b/engines/gargoyle/frotz/processor_streams.cpp
@@ -21,6 +21,7 @@
*/
#include "gargoyle/frotz/processor.h"
+#include "gargoyle/frotz/quetzal.h"
namespace Gargoyle {
namespace Frotz {
@@ -574,7 +575,7 @@ void Processor::z_save() {
if ((gfp = frotzopenprompt (FILE_SAVE)) == nullptr)
goto finished;
- if (option_save_quetzal) {
+ if (_save_quetzal) {
success = save_quetzal (gfp, story_fp, blorb_ofs);
} else {
/* Write game file */
@@ -670,7 +671,7 @@ void Processor::z_restore() {
if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
goto finished;
- if (option_save_quetzal) {
+ if (_save_quetzal) {
success = restore_quetzal (gfp, story_fp, blorb_ofs);
} else {
diff --git a/engines/gargoyle/frotz/quetzal.cpp b/engines/gargoyle/frotz/quetzal.cpp
new file mode 100644
index 0000000..183217a
--- /dev/null
+++ b/engines/gargoyle/frotz/quetzal.cpp
@@ -0,0 +1,485 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/frotz/quetzal.h"
+#include "gargoyle/frotz/processor.h"
+#include "common/memstream.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+/**
+ * Various parsing states within restoration.
+ */
+enum ParseState {
+ GOT_HEADER = 0x01,
+ GOT_STACK = 0x02,
+ GOT_MEMORY = 0x04,
+ GOT_NONE = 0x00,
+ GOT_ALL = 0x07,
+ GOT_ERROR = 0x80
+};
+
+
+bool Quetzal::read_word(Common::ReadStream *f, zword *result) {
+ *result = f->readUint16BE();
+ return true;
+}
+
+bool Quetzal::read_long(Common::ReadStream *f, uint *result) {
+ *result = f->readUint32BE();
+ return true;
+}
+
+bool Quetzal::save(Common::WriteStream *svf, Processor *proc) {
+ Processor &p = *proc;
+ uint ifzslen = 0, cmemlen = 0, stkslen = 0;
+ uint pc;
+ zword i, j, n;
+ zword nvars, nargs, nstk;
+ zbyte var;
+ long cmempos, stkspos;
+ int c;
+
+ // Set a temporary memory stream for writing out the data. This is needed, since we need to
+ // do some seeking within it at the end to fill out totals before properly writing it all out
+ Common::MemoryWriteStreamDynamic saveData(DisposeAfterUse::YES);
+ _out = &saveData;
+
+ // Write `IFZS' header.
+ write_chnk(ID_FORM, 0);
+ write_long(ID_IFZS);
+
+ // Write `IFhd' chunk
+ pc = p.getPC();
+ write_chnk(ID_IFhd, 13);
+ write_word(p.h_release);
+ for (i = H_SERIAL; i<H_SERIAL + 6; ++i)
+ write_byte(p[i]);
+
+ write_word(p.h_checksum);
+ write_long(pc << 8); // Includes pad
+
+ // Write `CMem' chunk.
+ cmempos = svf->pos();
+ write_chnk(ID_CMem, 0);
+ _storyFile->seek(_blorbOffset);
+
+ // j holds current run length.
+ for (i = 0, j = 0, cmemlen = 0; i < p.h_dynamic_size; ++i) {
+ c = _storyFile->readByte();
+ c ^= p[i];
+
+ if (c == 0) {
+ // It's a run of equal bytes
+ ++j;
+ } else {
+ // Write out any run there may be.
+ if (j > 0) {
+ for (; j > 0x100; j -= 0x100) {
+ write_run(0xFF);
+ cmemlen += 2;
+ }
+ write_run(j - 1);
+ cmemlen += 2;
+ j = 0;
+ }
+
+ // Any runs are now written. Write this (nonzero) byte
+ write_byte((zbyte)c);
+ ++cmemlen;
+ }
+ }
+
+ // Reached end of dynamic memory. We ignore any unwritten run there may be at this point.
+ if (cmemlen & 1)
+ // Chunk length must be even.
+ write_byte(0);
+
+ // Write `Stks' chunk. You are not expected to understand this. ;)
+ stkspos = _storyFile->pos();
+ write_chnk(ID_Stks, 0);
+
+ // We construct a list of frame indices, most recent first, in `frames'.
+ // These indices are the offsets into the `stack' array of the word before
+ // the first word pushed in each frame.
+ frames[0] = p._sp - p._stack; // The frame we'd get by doing a call now.
+ for (i = p._fp - p._stack + 4, n = 0; i < STACK_SIZE + 4; i = p._stack[i - 3] + 5)
+ frames[++n] = i;
+
+ // All versions other than V6 can use evaluation stack outside a function
+ // context. We write a faked stack frame (most fields zero) to cater for this.
+ if (p.h_version != V6) {
+ for (i = 0; i < 6; ++i)
+ write_byte(0);
+ nstk = STACK_SIZE - frames[n];
+ write_word(nstk);
+ for (j = STACK_SIZE - 1; j >= frames[n]; --j)
+ write_word(p._stack[j]);
+ stkslen = 8 + 2 * nstk;
+ }
+
+ // Write out the rest of the stack frames.
+ for (i = n; i > 0; --i) {
+ zword *pf = p._stack + frames[i] - 4; // Points to call frame
+ nvars = (pf[0] & 0x0F00) >> 8;
+ nargs = pf[0] & 0x00FF;
+ nstk = frames[i] - frames[i - 1] - nvars - 4;
+ pc = ((uint)pf[3] << 9) | pf[2];
+
+ // Check type of call
+ switch (pf[0] & 0xF000) {
+ case 0x0000:
+ // Function
+ var = p[pc];
+ pc = ((pc + 1) << 8) | nvars;
+ break;
+
+ case 0x1000:
+ // Procedure
+ var = 0;
+ pc = (pc << 8) | 0x10 | nvars; // Set procedure flag
+ break;
+
+ default:
+ p.runtimeError(ERR_SAVE_IN_INTER);
+ return 0;
+ }
+ if (nargs != 0)
+ nargs = (1 << nargs) - 1; // Make args into bitmap
+
+ // Write the main part of the frame...
+ write_long(pc);
+ write_byte(var);
+ write_byte(nargs);
+ write_word(nstk);
+
+ // Write the variables and eval stack
+ for (j = 0, --pf; j<nvars + nstk; ++j, --pf)
+ write_word(*pf);
+
+ // Calculate length written thus far
+ stkslen += 8 + 2 * (nvars + nstk);
+ }
+
+ // Fill in variable chunk lengths
+ ifzslen = 3 * 8 + 4 + 14 + cmemlen + stkslen;
+ if (cmemlen & 1)
+ ++ifzslen;
+
+ saveData.seek(4);
+ saveData.writeUint32BE(ifzslen);
+ saveData.seek(cmempos + 4);
+ saveData.writeUint32BE(cmemlen);
+ saveData.seek(stkspos + 4);
+ saveData.writeUint32BE(stkslen);
+
+ // Write the save data out
+ svf->write(saveData.getData(), saveData.size());
+
+ // After all that, still nothing went wrong!
+ return true;
+}
+
+
+int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
+ Processor &p = *proc;
+ uint ifzslen, currlen, tmpl;
+ uint pc;
+ zword i, tmpw;
+ int fatal = 0; // Set to -1 when errors must be fatal.
+ zbyte skip, progress = GOT_NONE;
+ int x, y;
+
+ // Check it's really an `IFZS' file.
+ tmpl = svf->readUint32BE();
+ ifzslen = svf->readUint32BE();
+ currlen = svf->readUint32BE();
+ if (tmpl != ID_FORM || currlen != ID_IFZS) {
+ p.print_string("This is not a saved game file!\n");
+ return 0;
+ }
+ if ((ifzslen & 1) || ifzslen<4)
+ // Sanity checks
+ return 0;
+ ifzslen -= 4;
+
+ // Read each chunk and process it
+ while (ifzslen > 0) {
+ // Read chunk header
+ if (ifzslen < 8)
+ // Couldn't contain a chunk
+ return 0;
+
+ tmpl = svf->readUint32BE();
+ currlen = svf->readUint32BE();
+ ifzslen -= 8; // Reduce remaining by size of header
+
+ // Handle chunk body
+ if (ifzslen < currlen)
+ // Chunk goes past EOF?!
+ return 0;
+ skip = currlen & 1;
+ ifzslen -= currlen + (uint)skip;
+
+ switch (tmpl) {
+ // `IFhd' header chunk; must be first in file
+ case ID_IFhd:
+ if (progress & GOT_HEADER) {
+ p.print_string("Save file has two IFZS chunks!\n");
+ return fatal;
+ }
+ progress |= GOT_HEADER;
+ if (currlen < 13)
+ return fatal;
+
+ tmpw = svf->readUint16BE();
+ if (tmpw != p.h_release)
+ progress = GOT_ERROR;
+
+ for (i = H_SERIAL; i < H_SERIAL + 6; ++i) {
+ x = svf->readByte();
+ if (x != p[i])
+ progress = GOT_ERROR;
+ }
+
+ tmpw = svf->readUint16BE();
+ if (tmpw != p.h_checksum)
+ progress = GOT_ERROR;
+
+ if (progress & GOT_ERROR) {
+ p.print_string("File was not saved from this story!\n");
+ return fatal;
+ }
+
+ x = svf->readByte();
+ pc = (uint)x << 16;
+ x = svf->readByte();
+ pc |= (uint)x << 8;
+ x = svf->readByte();
+ pc |= (uint)x;
+
+ fatal = -1; // Setting PC means errors must be fatal
+ p.setPC(pc);
+
+ svf->skip(13); // Skip rest of chunk
+ break;
+
+ // `Stks' stacks chunk; restoring this is quite complex. ;)
+ case ID_Stks:
+ if (progress & GOT_STACK) {
+ p.print_string("File contains two stack chunks!\n");
+ break;
+ }
+ progress |= GOT_STACK;
+
+ fatal = -1; // Setting SP means errors must be fatal
+ p._sp = p._stack + STACK_SIZE;
+
+ // All versions other than V6 may use evaluation stack outside any function context.
+ // As a result a faked function context will be present in the file here. We skip
+ // this context, but load the associated stack onto the stack proper...
+ if (p.h_version != V6) {
+ if (currlen < 8)
+ return fatal;
+
+ svf->skip(6);
+ tmpw = svf->readUint16BE();
+
+ if (tmpw > STACK_SIZE) {
+ p.print_string("Save-file has too much stack (and I can't cope).\n");
+ return fatal;
+ }
+
+ currlen -= 8;
+ if (currlen < (uint)tmpw * 2)
+ return fatal;
+ for (i = 0; i < tmpw; ++i)
+ *--p._sp = svf->readUint16BE();
+ currlen -= tmpw * 2;
+ }
+
+ // We now proceed to load the main block of stack frames
+ for (p._fp = p._stack + STACK_SIZE, p._frameCount = 0;
+ currlen > 0; currlen -= 8, ++p._frameCount) {
+ if (currlen < 8) return fatal;
+ if (p._sp - p._stack < 4) {
+ // No space for frame
+ p.print_string("Save-file has too much stack (and I can't cope).\n");
+ return fatal;
+ }
+
+ // Read PC, procedure flag and formal param count
+ tmpl = svf->readUint32BE();
+ y = (int)(tmpl & 0x0F); // Number of formals
+ tmpw = y << 8;
+
+ // Read result variable
+ x = svf->readByte();
+
+ // Check the procedure flag...
+ if (tmpl & 0x10) {
+ tmpw |= 0x1000; // It's a procedure
+ tmpl >>= 8; // Shift to get PC value
+ } else {
+ // Functions have type 0, so no need to or anything
+ tmpl >>= 8; // Shift to get PC value
+ --tmpl; // Point at result byte. */
+
+ // Sanity check on result variable...
+ if (p[tmpl] != (zbyte)x) {
+ p.print_string("Save-file has wrong variable number on stack (possibly wrong game version?)\n");
+ return fatal;
+ }
+ }
+
+ *--p._sp = (zword)(tmpl >> 9); // High part of PC
+ *--p._sp = (zword)(tmpl & 0x1FF); // Low part of PC
+ *--p._sp = (zword)(p._fp - p._stack - 1); // FP
+
+ // Read and process argument mask
+ x = svf->readByte();
+ ++x; // Should now be a power of 2
+ for (i = 0; i<8; ++i)
+ if (x & (1 << i))
+ break;
+ if (x ^ (1 << i)) {
+ // Not a power of 2
+ p.print_string("Save-file uses incomplete argument lists (which I can't handle)\n");
+ return fatal;
+ }
+
+ *--p._sp = tmpw | i;
+ p._fp = p._sp; // FP for next frame
+
+ // Read amount of eval stack used
+ tmpw = svf->readUint16BE();
+
+ tmpw += y; // Amount of stack + number of locals
+ if (p._sp - p._stack <= tmpw) {
+ p.print_string("Save-file has too much stack (and I can't cope).\n");
+ return fatal;
+ }
+ if (currlen < (uint)tmpw * 2)
+ return fatal;
+
+ for (i = 0; i < tmpw; ++i)
+ --*p._sp = svf->readUint16BE();
+ currlen -= tmpw * 2;
+ }
+
+ // End of `Stks' processing...
+ break;
+
+ // Any more special chunk types must go in HERE or ABOVE
+ // `CMem' compressed memory chunk; uncompress it
+ case ID_CMem:
+ if (!(progress & GOT_MEMORY)) {
+ // Don't complain if two
+ _storyFile->seek(_blorbOffset);
+
+ i = 0; // Bytes written to data area
+ for (; currlen > 0; --currlen) {
+ x = svf->readByte();
+ if (x == 0) {
+ // Start of run
+ // Check for bogus run
+ if (currlen < 2) {
+ p.print_string("File contains bogus `CMem' chunk.\n");
+ svf->skip(currlen);
+
+ currlen = 1;
+ i = 0xFFFF;
+ break; // Keep going; may be a `UMem' too
+ }
+
+ // Copy story file to memory during the run
+ --currlen;
+ x = svf->readByte();
+ for (; x >= 0 && i < p.h_dynamic_size; --x, ++i)
+ p[i] = svf->readByte();
+ } else {
+ // Not a run
+ y = svf->readByte();
+ p[i] = (zbyte)(x ^ y);
+ ++i;
+ }
+
+ // Make sure we don't load too much
+ if (i > p.h_dynamic_size) {
+ p.print_string("warning: `CMem' chunk too long!\n");
+ svf->skip(currlen);
+ break; // Keep going; there may be a `UMem' too
+ }
+ }
+
+ // If chunk is short, assume a run
+ for (; i < p.h_dynamic_size; ++i)
+ p[i] = svf->readByte();
+
+ if (currlen == 0)
+ progress |= GOT_MEMORY; // Only if succeeded
+ break;
+ }
+
+ // Intentional fall-through
+
+ case ID_UMem:
+ if (!(progress & GOT_MEMORY)) {
+ // Must be exactly the right size
+ if (currlen == p.h_dynamic_size) {
+ if (svf->read(p.zmp, currlen) == currlen) {
+ progress |= GOT_MEMORY; // Only on success
+ break;
+ }
+ } else {
+ p.print_string("`UMem' chunk wrong size!\n");
+ }
+
+ // Fall into default action (skip chunk) on errors
+ }
+
+ // Intentional fall-through
+
+ default:
+ svf->seek(currlen, SEEK_CUR); // Skip chunk
+ break;
+ }
+
+ if (skip)
+ svf->skip(1); // Skip pad byte
+ }
+
+ // We've reached the end of the file. For the restoration to have been a
+ // success, we must have had one of each of the required chunks.
+ if (!(progress & GOT_HEADER))
+ p.print_string("error: no valid header (`IFhd') chunk in file.\n");
+ if (!(progress & GOT_STACK))
+ p.print_string("error: no valid stack (`Stks') chunk in file.\n");
+ if (!(progress & GOT_MEMORY))
+ p.print_string("error: no valid memory (`CMem' or `UMem') chunk in file.\n");
+
+ return (progress == GOT_ALL ? 2 : fatal);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/quetzal.h b/engines/gargoyle/frotz/quetzal.h
new file mode 100644
index 0000000..6975155
--- /dev/null
+++ b/engines/gargoyle/frotz/quetzal.h
@@ -0,0 +1,97 @@
+/* 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 GARGOYLE_FROTZ_QUETZAL
+#define GARGOYLE_FROTZ_QUETZAL
+
+#include "gargoyle/glk_types.h"
+#include "gargoyle/frotz/frotz_types.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+enum QueztalTag {
+ ID_FORM = MKTAG('F', 'O', 'R', 'M'),
+ ID_IFZS = MKTAG('I', 'F', 'Z', 'S'),
+ ID_IFhd = MKTAG('I', 'F', 'h', 'd'),
+ ID_UMem = MKTAG('U', 'M', 'e', 'm'),
+ ID_CMem = MKTAG('C', 'M', 'e', 'm'),
+ ID_Stks = MKTAG('S', 't', 'k', 's'),
+ ID_ANNO = MKTAG('A', 'N', 'N', 'O')
+};
+
+class Processor;
+
+class Quetzal {
+private:
+ Common::SeekableReadStream *_storyFile;
+ Common::WriteStream *_out;
+ size_t _blorbOffset;
+ int _slot;
+ zword frames[STACK_SIZE / 4 + 1];
+private:
+ /**
+ * Read a 16-bit value from the file
+ */
+ bool read_word(Common::ReadStream *f, zword *result);
+
+ /**
+ * Read 32-bit value from the file
+ */
+ bool read_long(Common::ReadStream *f, uint *result);
+
+ void write_byte(zbyte b) { _out->writeByte(b); }
+ void write_bytx(zword b) { _out->writeByte(b & 0xFF); }
+ void write_word(zword w) { _out->writeUint16BE(w); }
+ void write_long(uint l) { _out->writeUint32BE(l); }
+ void write_run(zword run) { _out->writeUint16LE(run); }
+ void write_chnk(QueztalTag id, zword len) {
+ _out->writeUint32BE(id);
+ _out->writeUint32BE(len);
+ }
+public:
+ /**
+ * Constructor
+ */
+ Quetzal(Common::SeekableReadStream *storyFile, size_t blorbOffset, int slot) :
+ _storyFile(storyFile), _blorbOffset(blorbOffset), _slot(slot) {}
+
+ /*
+ * Save a game using Quetzal format.
+ * @param svf Savegame file
+ * @returns Returns true if OK, false if failed
+ */
+ bool save(Common::WriteStream *svf, Processor *proc);
+
+ /**
+ * Restore a saved game using Quetzal format
+ * @param svf Savegame file
+ * @returns Return 2 if OK, 0 if an error occurred before any damage was done,
+ * -1 on a fatal error
+ */
+ int restore(Common::SeekableReadStream *svf, Processor *proc);
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index aeaa0c0..676708f 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -174,6 +174,13 @@ public:
}
/**
+ * Return the filename for a given save slot
+ */
+ Common::String getSaveName(uint slot) const {
+ return Common::String::format("%s.%.3u", getTargetName().c_str(), slot);
+ }
+
+ /**
* Display a message in a GUI dialog
*/
void GUIError(const char *msg, ...);
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 14cc048..4694449 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -38,6 +38,7 @@ MODULE_OBJS := \
frotz/processor_table.o \
frotz/processor_text.o \
frotz/processor_variables.o \
+ frotz/quetzal.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp
index d5671f1..6a87084 100644
--- a/engines/gargoyle/streams.cpp
+++ b/engines/gargoyle/streams.cpp
@@ -1563,7 +1563,7 @@ frefid_t Streams::iterate(frefid_t fref, glui32 *rock) {
const Common::String FileReference::getSaveName() const {
assert(_slotNumber != -1);
- return Common::String::format("%s.%.3d", g_vm->getTargetName().c_str(), _slotNumber);
+ return g_vm->getSaveName(_slotNumber);
}
bool FileReference::exists() const {
Commit: 6b23a72e517bce458246b33b6ead2a9d90afc258
https://github.com/scummvm/scummvm/commit/6b23a72e517bce458246b33b6ead2a9d90afc258
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Merge Err class into Processor
Changed paths:
R engines/gargoyle/frotz/err.cpp
R engines/gargoyle/frotz/err.h
engines/gargoyle/frotz/frotz_types.h
engines/gargoyle/frotz/mem.h
engines/gargoyle/frotz/processor.cpp
engines/gargoyle/frotz/processor.h
engines/gargoyle/frotz/processor_buffer.cpp
engines/gargoyle/frotz/processor_text.cpp
engines/gargoyle/module.mk
diff --git a/engines/gargoyle/frotz/err.cpp b/engines/gargoyle/frotz/err.cpp
deleted file mode 100644
index f75b764..0000000
--- a/engines/gargoyle/frotz/err.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/err.h"
-#include "gargoyle/frotz/frotz.h"
-#include "common/textconsole.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-const char *const Errors::ERR_MESSAGES[ERR_NUM_ERRORS] = {
- "Text buffer overflow",
- "Store out of dynamic memory",
- "Division by zero",
- "Illegal object",
- "Illegal attribute",
- "No such property",
- "Stack overflow",
- "Call to illegal address",
- "Call to non-routine",
- "Stack underflow",
- "Illegal opcode",
- "Bad stack frame",
- "Jump to illegal address",
- "Can't save while in interrupt",
- "Nesting stream #3 too deep",
- "Illegal window",
- "Illegal window property",
- "Print at illegal address",
- "Illegal dictionary word length",
- "@jin called with object 0",
- "@get_child called with object 0",
- "@get_parent called with object 0",
- "@get_sibling called with object 0",
- "@get_prop_addr called with object 0",
- "@get_prop called with object 0",
- "@put_prop called with object 0",
- "@clear_attr called with object 0",
- "@set_attr called with object 0",
- "@test_attr called with object 0",
- "@move_object called moving object 0",
- "@move_object called moving into object 0",
- "@remove_object called with object 0",
- "@get_next_prop called with object 0"
-};
-
-Errors::Errors() {
- Common::fill(&_count[0], &_count[ERR_NUM_ERRORS], 0);
-}
-
-void Errors::runtimeError(ErrorCode errNum) {
-#ifdef TODO
- int wasfirst;
-
- if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
- return;
-
- if (g_vm->_err_report_mode == ERR_REPORT_FATAL
- || (!g_vm->_ignore_errors && errNum <= ERR_MAX_FATAL)) {
- g_vm->_buffer.flush();
- error(ERR_MESSAGES[errNum - 1]);
- return;
- }
-
- wasfirst = (_count[errNum - 1] == 0);
- _count[errNum - 1]++;
-
- if ((g_vm->_err_report_mode == ERR_REPORT_ALWAYS)
- || (_err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
- long pc = g_vm->_processor
- GET_PC(pc);
- printString("Warning: ");
- printString(ERR_MESSAGES[errNum - 1]);
- printString(" (PC = ");
- printLong(pc, 16);
- printChar(')');
-
- if (_err_report_mode == ERR_REPORT_ONCE) {
- printString(" (will ignore further occurrences)");
- } else {
- printString(" (occurence ");
- printLong(_count[errNum - 1], 10);
- printChar(')');
- }
-
- newLine();
- }
-#endif
-}
-
-void Errors::printLong(uint value, int base) {
- unsigned long i;
- char c;
-
- for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base)
- if (value >= i || i == 1) {
- c = (value / i) % base;
- printChar(c + (c <= 9 ? '0' : 'a' - 10));
- }
-}
-
-void Errors::printChar(const char c) {
- // TODO
-}
-
-void Errors::printString(const char *str) {
- // TODO
-}
-
-void Errors::newLine() {
- // TODO
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/err.h b/engines/gargoyle/frotz/err.h
deleted file mode 100644
index 090ce3f..0000000
--- a/engines/gargoyle/frotz/err.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* 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 GARGOYLE_FROTZ_ERR
-#define GARGOYLE_FROTZ_ERR
-
-#include "gargoyle/frotz/frotz_types.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-enum ErrorCode {
- ERR_TEXT_BUF_OVF = 1, ///< Text buffer overflow
- ERR_STORE_RANGE = 2, ///< Store out of dynamic memory
- ERR_DIV_ZERO = 3, ///< Division by zero
- ERR_ILL_OBJ = 4, ///< Illegal object
- ERR_ILL_ATTR = 5, ///< Illegal attribute
- ERR_NO_PROP = 6, ///< No such property
- ERR_STK_OVF = 7, ///< Stack overflow
- ERR_ILL_CALL_ADDR = 8, ///< Call to illegal address
- ERR_CALL_NON_RTN = 9, ///< Call to non-routine
- ERR_STK_UNDF = 10, ///< Stack underflow
- ERR_ILL_OPCODE = 11, ///< Illegal opcode
- ERR_BAD_FRAME = 12, ///< Bad stack frame
- ERR_ILL_JUMP_ADDR = 13, ///< Jump to illegal address
- ERR_SAVE_IN_INTER = 14, ///< Can't save while in interrupt
- ERR_STR3_NESTING = 15, ///< Nesting stream #3 too deep
- ERR_ILL_WIN = 16, ///< Illegal window
- ERR_ILL_WIN_PROP = 17, ///< Illegal window property
- ERR_ILL_PRINT_ADDR = 18, ///< Print at illegal address
- ERR_DICT_LEN = 19, ///< Illegal dictionary word length
- ERR_MAX_FATAL = 19,
-
- // Less serious errors
- ERR_JIN_0 = 20, ///< @jin called with object 0
- ERR_GET_CHILD_0 = 21, ///< @get_child called with object 0
- ERR_GET_PARENT_0 = 22, ///< @get_parent called with object 0
- ERR_GET_SIBLING_0 = 23, ///< @get_sibling called with object 0
- ERR_GET_PROP_ADDR_0 = 24, ///< @get_prop_addr called with object 0
- ERR_GET_PROP_0 = 25, ///< @get_prop called with object 0
- ERR_PUT_PROP_0 = 26, ///< @put_prop called with object 0
- ERR_CLEAR_ATTR_0 = 27, ///< @clear_attr called with object 0
- ERR_SET_ATTR_0 = 28, ///< @set_attr called with object 0
- ERR_TEST_ATTR_0 = 29, ///< @test_attr called with object 0
- ERR_MOVE_OBJECT_0 = 30, ///< @move_object called moving object 0
- ERR_MOVE_OBJECT_TO_0 = 31, ///< @move_object called moving into object 0
- ERR_REMOVE_OBJECT_0 = 32, ///< @remove_object called with object 0
- ERR_GET_NEXT_PROP_0 = 33, ///< @get_next_prop called with object 0
- ERR_NUM_ERRORS = 33
-};
-
-class Errors {
-private:
- static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
- int _count[ERR_NUM_ERRORS];
-private:
- /**
- * Print an unsigned 32bit number in decimal or hex.
- */
- void printLong(uint value, int base);
-
- /**
- * Print a character
- */
- void printChar(const char c);
-
- /**
- * Print a string
- */
- void printString(const char *str);
-
- /**
- * Add a newline
- */
- void newLine();
-protected:
- /**
- * Get the PC. Is implemented by the Processor class, which derives from Errors
- */
- virtual uint getPC() const = 0;
-public:
- /**
- * Constructor
- */
- Errors();
-
- /**
- * An error has occurred. Ignore it, pass it to os_fatal or report
- * it according to err_report_mode.
- * @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
- */
- void runtimeError(ErrorCode errNum);
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 3ccaa45..6efd0fc 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -149,19 +149,59 @@ enum {
TRANSPARENT_FLAG = 0x0001 ///< Game wants to use transparency - V6
};
+enum ErrorCode {
+ ERR_TEXT_BUF_OVF = 1, ///< Text buffer overflow
+ ERR_STORE_RANGE = 2, ///< Store out of dynamic memory
+ ERR_DIV_ZERO = 3, ///< Division by zero
+ ERR_ILL_OBJ = 4, ///< Illegal object
+ ERR_ILL_ATTR = 5, ///< Illegal attribute
+ ERR_NO_PROP = 6, ///< No such property
+ ERR_STK_OVF = 7, ///< Stack overflow
+ ERR_ILL_CALL_ADDR = 8, ///< Call to illegal address
+ ERR_CALL_NON_RTN = 9, ///< Call to non-routine
+ ERR_STK_UNDF = 10, ///< Stack underflow
+ ERR_ILL_OPCODE = 11, ///< Illegal opcode
+ ERR_BAD_FRAME = 12, ///< Bad stack frame
+ ERR_ILL_JUMP_ADDR = 13, ///< Jump to illegal address
+ ERR_SAVE_IN_INTER = 14, ///< Can't save while in interrupt
+ ERR_STR3_NESTING = 15, ///< Nesting stream #3 too deep
+ ERR_ILL_WIN = 16, ///< Illegal window
+ ERR_ILL_WIN_PROP = 17, ///< Illegal window property
+ ERR_ILL_PRINT_ADDR = 18, ///< Print at illegal address
+ ERR_DICT_LEN = 19, ///< Illegal dictionary word length
+ ERR_MAX_FATAL = 19,
+
+ // Less serious errors
+ ERR_JIN_0 = 20, ///< @jin called with object 0
+ ERR_GET_CHILD_0 = 21, ///< @get_child called with object 0
+ ERR_GET_PARENT_0 = 22, ///< @get_parent called with object 0
+ ERR_GET_SIBLING_0 = 23, ///< @get_sibling called with object 0
+ ERR_GET_PROP_ADDR_0 = 24, ///< @get_prop_addr called with object 0
+ ERR_GET_PROP_0 = 25, ///< @get_prop called with object 0
+ ERR_PUT_PROP_0 = 26, ///< @put_prop called with object 0
+ ERR_CLEAR_ATTR_0 = 27, ///< @clear_attr called with object 0
+ ERR_SET_ATTR_0 = 28, ///< @set_attr called with object 0
+ ERR_TEST_ATTR_0 = 29, ///< @test_attr called with object 0
+ ERR_MOVE_OBJECT_0 = 30, ///< @move_object called moving object 0
+ ERR_MOVE_OBJECT_TO_0 = 31, ///< @move_object called moving into object 0
+ ERR_REMOVE_OBJECT_0 = 32, ///< @remove_object called with object 0
+ ERR_GET_NEXT_PROP_0 = 33, ///< @get_next_prop called with object 0
+ ERR_NUM_ERRORS = 33
+};
+
enum FrotzInterp {
-#define INTERP_DEFAULT 0
-#define INTERP_DEC_20 1
-#define INTERP_APPLE_IIE 2
-#define INTERP_MACINTOSH 3
-#define INTERP_AMIGA 4
-#define INTERP_ATARI_ST 5
-#define INTERP_MSDOS 6
-#define INTERP_CBM_128 7
-#define INTERP_CBM_64 8
-#define INTERP_APPLE_IIC 9
-#define INTERP_APPLE_IIGS 10
-#define INTERP_TANDY 11
+ INTERP_DEFAULT = 0,
+ INTERP_DEC_20 = 1,
+ INTERP_APPLE_IIE = 2,
+ INTERP_MACINTOSH = 3,
+ INTERP_AMIGA = 4,
+ INTERP_ATARI_ST = 5,
+ INTERP_MSDOS = 6,
+ INTERP_CBM_128 = 7,
+ INTERP_CBM_64 = 8,
+ INTERP_APPLE_IIC = 9,
+ INTERP_APPLE_IIGS = 10,
+ INTERP_TANDY = 11
};
enum Colour {
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
index a45eec5..a2e0e34 100644
--- a/engines/gargoyle/frotz/mem.h
+++ b/engines/gargoyle/frotz/mem.h
@@ -24,7 +24,6 @@
#define GARGOYLE_FROTZ_MEM
#include "gargoyle/frotz/frotz_types.h"
-#include "gargoyle/frotz/err.h"
namespace Gargoyle {
namespace Frotz {
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
index ac18a23..3336aae 100644
--- a/engines/gargoyle/frotz/processor.cpp
+++ b/engines/gargoyle/frotz/processor.cpp
@@ -132,7 +132,7 @@ Opcode Processor::ext_opcodes[64] = {
};
Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GlkInterface(syst, gameDesc), Errors(),
+ GlkInterface(syst, gameDesc),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
_randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false),
@@ -180,6 +180,7 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
Common::fill(&zargs[0], &zargs[8], 0);
Common::fill(&_buffer[0], &_buffer[TEXT_BUFFER_SIZE], '\0');
+ Common::fill(&_errorCount[0], &_errorCount[ERR_NUM_ERRORS], 0);
}
void Processor::initialize() {
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
index 0f7ecc0..3ead900 100644
--- a/engines/gargoyle/frotz/processor.h
+++ b/engines/gargoyle/frotz/processor.h
@@ -23,7 +23,6 @@
#ifndef GARGOYLE_FROTZ_PROCESSOR
#define GARGOYLE_FROTZ_PROCESSOR
-#include "gargoyle/frotz/err.h"
#include "gargoyle/frotz/mem.h"
#include "gargoyle/frotz/glk_interface.h"
#include "gargoyle/frotz/frotz_types.h"
@@ -51,9 +50,15 @@ typedef void (Processor::*Opcode)();
/**
* Zcode processor
*/
-class Processor : public Errors, public GlkInterface, public virtual Mem {
+class Processor : public GlkInterface, public virtual Mem {
friend class Quetzal;
private:
+ Opcode op0_opcodes[16];
+ Opcode op1_opcodes[16];
+ static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
+ static Opcode var_opcodes[64];
+ static Opcode ext_opcodes[64];
+
int _finished;
zword zargs[8];
int zargc;
@@ -72,17 +77,13 @@ private:
static zchar ZSCII_TO_LATIN1[];
zchar *_decoded, *_encoded;
int _resolution;
+ int _errorCount[ERR_NUM_ERRORS];
// Buffer related fields
- zchar _buffer[TEXT_BUFFER_SIZE];
- size_t _bufPos;
bool _locked;
zchar _prevC;
-
- Opcode op0_opcodes[16];
- Opcode op1_opcodes[16];
- static Opcode var_opcodes[64];
- static Opcode ext_opcodes[64];
+ zchar _buffer[TEXT_BUFFER_SIZE];
+ size_t _bufPos;
// Stream related fields
int script_width;
@@ -172,6 +173,16 @@ private:
*/
void print_char(zchar c);
+ /**
+ * Print a string of ASCII characters.
+ */
+ void print_string(const char *s);
+
+ /**
+ * Print an unsigned 32bit number in decimal or hex.
+ */
+ void print_long(uint value, int base);
+
/**
* High level newline function.
*/
@@ -182,6 +193,13 @@ private:
*/
bool bufferEmpty() const { return !_bufPos; }
+ /**
+ * An error has occurred. Ignore it, pass it to os_fatal or report
+ * it according to err_report_mode.
+ * @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
+ */
+ void runtimeError(ErrorCode errNum);
+
/**@}*/
/**
@@ -217,13 +235,6 @@ private:
*/
/**
- * Generates a runtime error
- */
- virtual void runtimeError(ErrorCode errNum) override {
- Errors::runtimeError(errNum);
- }
-
- /**
* Called when the H_FLAGS field of the header has changed
*/
virtual void flagsChanged(zbyte value) override;
@@ -1395,11 +1406,6 @@ protected:
void z_print_ret();
/**
- * Print a string of ASCII characters.
- */
- void print_string(const char *s);
-
- /**
* Print unicode character
*
* zargs[0] = Unicode
@@ -1561,9 +1567,8 @@ public:
/**
* Return the current program execution offset
- * @remarks This virtual as a convenient way for the ancestor Err class to access
*/
- virtual uint getPC() const override { return pcp - zmp; }
+ uint getPC() const { return pcp - zmp; }
/**
* Set the program execution offset
diff --git a/engines/gargoyle/frotz/processor_buffer.cpp b/engines/gargoyle/frotz/processor_buffer.cpp
index b2b6ccd..62980fb 100644
--- a/engines/gargoyle/frotz/processor_buffer.cpp
+++ b/engines/gargoyle/frotz/processor_buffer.cpp
@@ -27,6 +27,42 @@
namespace Gargoyle {
namespace Frotz {
+const char *const Processor::ERR_MESSAGES[ERR_NUM_ERRORS] = {
+ "Text buffer overflow",
+ "Store out of dynamic memory",
+ "Division by zero",
+ "Illegal object",
+ "Illegal attribute",
+ "No such property",
+ "Stack overflow",
+ "Call to illegal address",
+ "Call to non-routine",
+ "Stack underflow",
+ "Illegal opcode",
+ "Bad stack frame",
+ "Jump to illegal address",
+ "Can't save while in interrupt",
+ "Nesting stream #3 too deep",
+ "Illegal window",
+ "Illegal window property",
+ "Print at illegal address",
+ "Illegal dictionary word length",
+ "@jin called with object 0",
+ "@get_child called with object 0",
+ "@get_parent called with object 0",
+ "@get_sibling called with object 0",
+ "@get_prop_addr called with object 0",
+ "@get_prop called with object 0",
+ "@put_prop called with object 0",
+ "@clear_attr called with object 0",
+ "@set_attr called with object 0",
+ "@test_attr called with object 0",
+ "@move_object called moving object 0",
+ "@move_object called moving into object 0",
+ "@remove_object called with object 0",
+ "@get_next_prop called with object 0"
+};
+
void Processor::flush_buffer() {
/* Make sure we stop when flush_buffer is called from flush_buffer.
* Note that this is difficult to avoid as we might print a newline
@@ -85,10 +121,72 @@ void Processor::print_char(zchar c) {
}
}
+void Processor::print_string(const char *s) {
+ char c;
+
+ while ((c = *s++) != 0) {
+ if (c == '\n')
+ new_line();
+ else
+ print_char(c);
+ }
+}
+
+void Processor::print_long(uint value, int base) {
+ unsigned long i;
+ char c;
+
+ for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base) {
+ if (value >= i || i == 1) {
+ c = (value / i) % base;
+ print_char(c + (c <= 9 ? '0' : 'a' - 10));
+ }
+ }
+}
+
void Processor::new_line() {
flush_buffer();
stream_new_line();
}
+void Processor::runtimeError(ErrorCode errNum) {
+ int wasfirst;
+
+ if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
+ return;
+
+ if (_err_report_mode == ERR_REPORT_FATAL
+ || (!_ignore_errors && errNum <= ERR_MAX_FATAL)) {
+ flush_buffer();
+ error(ERR_MESSAGES[errNum - 1]);
+ return;
+ }
+
+ wasfirst = (_errorCount[errNum - 1] == 0);
+ _errorCount[errNum - 1]++;
+
+ if ((_err_report_mode == ERR_REPORT_ALWAYS)
+ || (_err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
+ long pc;
+ GET_PC(pc);
+ print_string("Warning: ");
+ print_string(ERR_MESSAGES[errNum - 1]);
+ print_string(" (PC = ");
+ print_long(pc, 16);
+ print_char(')');
+
+ if (_err_report_mode == ERR_REPORT_ONCE) {
+ print_string(" (will ignore further occurrences)");
+ }
+ else {
+ print_string(" (occurence ");
+ print_long(_errorCount[errNum - 1], 10);
+ print_char(')');
+ }
+
+ new_line();
+ }
+}
+
} // End of namespace Scott
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_text.cpp b/engines/gargoyle/frotz/processor_text.cpp
index 630bd50..0852dc4 100644
--- a/engines/gargoyle/frotz/processor_text.cpp
+++ b/engines/gargoyle/frotz/processor_text.cpp
@@ -479,17 +479,6 @@ void Processor::print_object(zword object) {
}
}
-void Processor::print_string(const char *s) {
- char c;
-
- while ((c = *s++) != 0) {
- if (c == '\n')
- new_line();
- else
- print_char(c);
- }
-}
-
zword Processor::lookup_text(int padding, zword dct) {
zword entry_addr;
zword entry_count;
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 4694449..3c09b32 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -23,7 +23,6 @@ MODULE_OBJS := \
window_text_grid.o \
frotz/detection.o \
frotz/detection_tables.o \
- frotz/err.o \
frotz/frotz.o \
frotz/glk_interface.o \
frotz/mem.o \
Commit: 7b90a2b60ed09fdba081dd752b4167e0b0e1fd27
https://github.com/scummvm/scummvm/commit/7b90a2b60ed09fdba081dd752b4167e0b0e1fd27
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Hook up processor execution to main runGame method
Changed paths:
engines/gargoyle/frotz/frotz.cpp
engines/gargoyle/frotz/frotz.h
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
index 5c86189..3a7b913 100644
--- a/engines/gargoyle/frotz/frotz.cpp
+++ b/engines/gargoyle/frotz/frotz.cpp
@@ -34,11 +34,16 @@ Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) :
g_vm = this;
}
+Frotz::~Frotz() {
+ reset_memory();
+}
+
void Frotz::runGame(Common::SeekableReadStream *gameFile) {
story_fp = gameFile;
initialize();
- // TODO
+ // Game loop
+ interpret();
}
void Frotz::initialize() {
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
index 78272f0..f7211f7 100644
--- a/engines/gargoyle/frotz/frotz.h
+++ b/engines/gargoyle/frotz/frotz.h
@@ -39,6 +39,11 @@ public:
Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc);
/**
+ * Destructor
+ */
+ virtual ~Frotz();
+
+ /**
* Initialization
*/
void initialize();
Commit: 7d670ff157fbc3df45f70f9e7a5b537b3d13152b
https://github.com/scummvm/scummvm/commit/7d670ff157fbc3df45f70f9e7a5b537b3d13152b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix stack size
Changed paths:
engines/gargoyle/frotz/frotz_types.h
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
index 6efd0fc..6b4fe67 100644
--- a/engines/gargoyle/frotz/frotz_types.h
+++ b/engines/gargoyle/frotz/frotz_types.h
@@ -30,7 +30,7 @@ namespace Gargoyle {
namespace Frotz {
#define MAX_UNDO_SLOTS 500
-#define STACK_SIZE 20
+#define STACK_SIZE 32768
#define lo(v) (v & 0xff)
#define hi(v) (v >> 8)
Commit: 1fb931fbd950324754536ee0b33ed0b91f68c9a2
https://github.com/scummvm/scummvm/commit/1fb931fbd950324754536ee0b33ed0b91f68c9a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Changing gargoyle folder to glk
Changed paths:
A engines/glk/blorb.cpp
A engines/glk/blorb.h
A engines/glk/conf.cpp
A engines/glk/conf.h
A engines/glk/configure.engine
A engines/glk/detection.cpp
A engines/glk/detection_tables.h
A engines/glk/events.cpp
A engines/glk/events.h
A engines/glk/fonts.cpp
A engines/glk/fonts.h
A engines/glk/frotz/detection.cpp
A engines/glk/frotz/detection.h
A engines/glk/frotz/detection_tables.cpp
A engines/glk/frotz/detection_tables.h
A engines/glk/frotz/frotz.cpp
A engines/glk/frotz/frotz.h
A engines/glk/frotz/frotz_types.h
A engines/glk/frotz/glk_interface.cpp
A engines/glk/frotz/glk_interface.h
A engines/glk/frotz/mem.cpp
A engines/glk/frotz/mem.h
A engines/glk/frotz/processor.cpp
A engines/glk/frotz/processor.h
A engines/glk/frotz/processor_buffer.cpp
A engines/glk/frotz/processor_input.cpp
A engines/glk/frotz/processor_maths.cpp
A engines/glk/frotz/processor_mem.cpp
A engines/glk/frotz/processor_objects.cpp
A engines/glk/frotz/processor_screen.cpp
A engines/glk/frotz/processor_streams.cpp
A engines/glk/frotz/processor_table.cpp
A engines/glk/frotz/processor_text.cpp
A engines/glk/frotz/processor_variables.cpp
A engines/glk/frotz/quetzal.cpp
A engines/glk/frotz/quetzal.h
A engines/glk/gargoyle.cpp
A engines/glk/gargoyle.h
A engines/glk/glk.cpp
A engines/glk/glk.h
A engines/glk/glk_types.h
A engines/glk/module.mk
A engines/glk/picture.cpp
A engines/glk/picture.h
A engines/glk/scott/detection.cpp
A engines/glk/scott/detection.h
A engines/glk/scott/scott.cpp
A engines/glk/scott/scott.h
A engines/glk/screen.cpp
A engines/glk/screen.h
A engines/glk/selection.cpp
A engines/glk/selection.h
A engines/glk/speech.h
A engines/glk/streams.cpp
A engines/glk/streams.h
A engines/glk/time.cpp
A engines/glk/time.h
A engines/glk/unicode.cpp
A engines/glk/unicode.h
A engines/glk/unicode_gen.cpp
A engines/glk/unicode_gen.h
A engines/glk/utils.cpp
A engines/glk/utils.h
A engines/glk/window_graphics.cpp
A engines/glk/window_graphics.h
A engines/glk/window_pair.cpp
A engines/glk/window_pair.h
A engines/glk/window_text_buffer.cpp
A engines/glk/window_text_buffer.h
A engines/glk/window_text_grid.cpp
A engines/glk/window_text_grid.h
A engines/glk/windows.cpp
A engines/glk/windows.h
R engines/gargoyle/blorb.cpp
R engines/gargoyle/blorb.h
R engines/gargoyle/conf.cpp
R engines/gargoyle/conf.h
R engines/gargoyle/configure.engine
R engines/gargoyle/detection.cpp
R engines/gargoyle/detection_tables.h
R engines/gargoyle/events.cpp
R engines/gargoyle/events.h
R engines/gargoyle/fonts.cpp
R engines/gargoyle/fonts.h
R engines/gargoyle/frotz/detection.cpp
R engines/gargoyle/frotz/detection.h
R engines/gargoyle/frotz/detection_tables.cpp
R engines/gargoyle/frotz/detection_tables.h
R engines/gargoyle/frotz/frotz.cpp
R engines/gargoyle/frotz/frotz.h
R engines/gargoyle/frotz/frotz_types.h
R engines/gargoyle/frotz/glk_interface.cpp
R engines/gargoyle/frotz/glk_interface.h
R engines/gargoyle/frotz/mem.cpp
R engines/gargoyle/frotz/mem.h
R engines/gargoyle/frotz/processor.cpp
R engines/gargoyle/frotz/processor.h
R engines/gargoyle/frotz/processor_buffer.cpp
R engines/gargoyle/frotz/processor_input.cpp
R engines/gargoyle/frotz/processor_maths.cpp
R engines/gargoyle/frotz/processor_mem.cpp
R engines/gargoyle/frotz/processor_objects.cpp
R engines/gargoyle/frotz/processor_screen.cpp
R engines/gargoyle/frotz/processor_streams.cpp
R engines/gargoyle/frotz/processor_table.cpp
R engines/gargoyle/frotz/processor_text.cpp
R engines/gargoyle/frotz/processor_variables.cpp
R engines/gargoyle/frotz/quetzal.cpp
R engines/gargoyle/frotz/quetzal.h
R engines/gargoyle/gargoyle.cpp
R engines/gargoyle/gargoyle.h
R engines/gargoyle/glk.cpp
R engines/gargoyle/glk.h
R engines/gargoyle/glk_types.h
R engines/gargoyle/module.mk
R engines/gargoyle/picture.cpp
R engines/gargoyle/picture.h
R engines/gargoyle/scott/detection.cpp
R engines/gargoyle/scott/detection.h
R engines/gargoyle/scott/scott.cpp
R engines/gargoyle/scott/scott.h
R engines/gargoyle/screen.cpp
R engines/gargoyle/screen.h
R engines/gargoyle/selection.cpp
R engines/gargoyle/selection.h
R engines/gargoyle/speech.h
R engines/gargoyle/streams.cpp
R engines/gargoyle/streams.h
R engines/gargoyle/time.cpp
R engines/gargoyle/time.h
R engines/gargoyle/unicode.cpp
R engines/gargoyle/unicode.h
R engines/gargoyle/unicode_gen.cpp
R engines/gargoyle/unicode_gen.h
R engines/gargoyle/utils.cpp
R engines/gargoyle/utils.h
R engines/gargoyle/window_graphics.cpp
R engines/gargoyle/window_graphics.h
R engines/gargoyle/window_pair.cpp
R engines/gargoyle/window_pair.h
R engines/gargoyle/window_text_buffer.cpp
R engines/gargoyle/window_text_buffer.h
R engines/gargoyle/window_text_grid.cpp
R engines/gargoyle/window_text_grid.h
R engines/gargoyle/windows.cpp
R engines/gargoyle/windows.h
diff --git a/engines/gargoyle/blorb.cpp b/engines/gargoyle/blorb.cpp
deleted file mode 100644
index 064f9c4..0000000
--- a/engines/gargoyle/blorb.cpp
+++ /dev/null
@@ -1,543 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/blorb.h"
-
-namespace Gargoyle {
-
-#define giblorb_Inited_Magic 0xB7012BEDU
-
-/**
- * Describes one chunk of the Blorb file.
- */
-struct giblorb_chunkdesc_struct {
- glui32 type;
- glui32 len;
- glui32 startpos; ///< start of chunk header
- glui32 datpos; ///< start of data (either startpos or startpos+8)
-
- void *ptr; ///< pointer to malloc'd data, if loaded
- int auxdatnum; ///< entry in the auxsound/auxpict array; -1 if none. This only applies to chunks that represent resources;
-};
-typedef giblorb_chunkdesc_struct giblorb_chunkdesc_t;
-
-/**
- * Describes one resource in the Blorb file.
- */
-struct giblorb_resdesc_struct {
- glui32 usage;
- glui32 resnum;
- glui32 chunknum;
-};
-
-/**
- * Holds the complete description of an open Blorb file.
- */
-struct giblorb_map_struct {
- glui32 inited; ///< holds giblorb_Inited_Magic if the map structure is valid
- Common::SeekableReadStream *file;
-
- uint numchunks;
- giblorb_chunkdesc_t *chunks; ///< list of chunk descriptors
-
- int numresources;
- giblorb_resdesc_t *resources; ///< list of resource descriptors
- giblorb_resdesc_t **ressorted; ///< list of pointers to descriptors in map->resources -- sorted by usage and resource number.
-};
-
-/*--------------------------------------------------------------------------*/
-
-giblorb_err_t Blorb::giblorb_initialize() {
- _file = nullptr;
- _map = nullptr;
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap) {
- giblorb_err_t err;
- giblorb_map_t *map;
- glui32 readlen;
- glui32 nextpos, totallength;
- giblorb_chunkdesc_t *chunks;
- int chunks_size, numchunks;
- char buffer[16];
-
- *newmap = nullptr;
-
- if (!_libInited) {
- err = giblorb_initialize();
- if (err)
- return err;
- _libInited = true;
- }
-
- /* First, chew through the file and index the chunks. */
- file->seek(0);
-
- readlen = file->read(buffer, 12);
- if (readlen != 12)
- return giblorb_err_Read;
-
- if (READ_BE_INT32(buffer + 0) != giblorb_ID_FORM)
- return giblorb_err_Format;
- if (READ_BE_INT32(buffer + 8) != giblorb_ID_IFRS)
- return giblorb_err_Format;
-
- totallength = READ_BE_INT32(buffer + 4) + 8;
- nextpos = 12;
-
- chunks_size = 8;
- numchunks = 0;
- chunks = new giblorb_chunkdesc_t[chunks_size];
-
- while (nextpos < totallength) {
- glui32 type, len;
- int chunum;
- giblorb_chunkdesc_t *chu;
-
- file->seek(nextpos);
-
- readlen = file->read(buffer, 8);
- if (readlen != 8) {
- delete[] chunks;
- return giblorb_err_Read;
- }
-
- type = READ_BE_INT32(buffer + 0);
- len = READ_BE_INT32(buffer + 4);
-
- if (numchunks >= chunks_size) {
- chunks_size *= 2;
- chunks = new giblorb_chunkdesc_t[chunks_size];
- }
-
- chunum = numchunks;
- chu = &(chunks[chunum]);
- numchunks++;
-
- chu->type = type;
- chu->startpos = nextpos;
- if (type == giblorb_ID_FORM) {
- chu->datpos = nextpos;
- chu->len = len + 8;
- } else {
- chu->datpos = nextpos + 8;
- chu->len = len;
- }
- chu->ptr = nullptr;
- chu->auxdatnum = -1;
-
- nextpos = nextpos + len + 8;
- if (nextpos & 1)
- nextpos++;
-
- if (nextpos > totallength) {
- delete[] chunks;
- return giblorb_err_Format;
- }
- }
-
- // The basic IFF structure seems to be ok, and we have a list of chunks.
- // Now we allocate the map structure itself.
- map = new giblorb_map_t();
- if (!map) {
- delete[] chunks;
- return giblorb_err_Alloc;
- }
-
- map->inited = giblorb_Inited_Magic;
- map->file = file;
- map->chunks = chunks;
- map->numchunks = numchunks;
- map->resources = nullptr;
- map->ressorted = nullptr;
- map->numresources = 0;
-
- // Now we do everything else involved in loading the Blorb file,
- // such as building resource lists.
- err = giblorb_initialize_map(map);
- if (err) {
- giblorb_destroy_map(map);
- return err;
- }
-
- *newmap = map;
- return giblorb_err_None;
-}
-
-
-giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
- // It is important that the map structure be kept valid during this function.
- // If this returns an error, giblorb_destroy_map() will be called.
- uint ix, jx;
- giblorb_result_t chunkres;
- giblorb_err_t err;
- char *ptr;
- glui32 len;
- glui32 numres;
- int gotindex = false;
-
- for (ix = 0; ix<map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &map->chunks[ix];
-
- switch (chu->type) {
- case giblorb_ID_RIdx:
- // Resource index chunk: build the resource list and sort it.
-
- if (gotindex)
- return giblorb_err_Format; // duplicate index chunk
- err = giblorb_load_chunk_by_number(map, giblorb_method_Memory, &chunkres, ix);
- if (err)
- return err;
-
- ptr = (char *)chunkres.data.ptr;
- len = chunkres.length;
- numres = READ_BE_INT32(ptr + 0);
-
- if (numres) {
- uint ix2;
- giblorb_resdesc_t *resources;
- giblorb_resdesc_t **ressorted;
-
- if (len != numres * 12 + 4)
- return giblorb_err_Format; // bad length field
-
- resources = new giblorb_resdesc_t[numres];
- ressorted = new giblorb_resdesc_t *[numres];
- if (!ressorted || !resources) {
- delete[] resources;
- delete[] ressorted;
- return giblorb_err_Alloc;
- }
-
- ix2 = 0;
- for (jx = 0; jx < numres; jx++) {
- giblorb_resdesc_t *res = &(resources[jx]);
- glui32 respos;
-
- res->usage = READ_BE_INT32(ptr + jx * 12 + 4);
- res->resnum = READ_BE_INT32(ptr + jx * 12 + 8);
- respos = READ_BE_INT32(ptr + jx * 12 + 12);
-
- while (ix2 < map->numchunks
- && map->chunks[ix2].startpos < respos)
- ix2++;
-
- if (ix2 >= map->numchunks
- || map->chunks[ix2].startpos != respos) {
- delete[] resources;
- delete[] ressorted;
- return giblorb_err_Format; // start pos does not match a real chunk
- }
-
- res->chunknum = ix2;
-
- ressorted[jx] = res;
- }
-
- // Sort a resource list (actually a list of pointers to structures in map->resources.)
- // This makes it easy to find resources by usage and resource number.
- giblorb_qsort(ressorted, numres);
-
- map->numresources = numres;
- map->resources = resources;
- map->ressorted = ressorted;
- }
-
- giblorb_unload_chunk(map, ix);
- gotindex = true;
- break;
- }
- }
-
- return giblorb_err_None;
-}
-
-void Blorb::giblorb_qsort(giblorb_resdesc_t **list, size_t len) {
- int ix, jx, res;
- giblorb_resdesc_t *tmpptr, *pivot;
-
- if (len < 6) {
- // The list is short enough for a bubble-sort.
- for (jx = len - 1; jx>0; jx--) {
- for (ix = 0; ix<jx; ix++) {
- res = sortsplot(list[ix], list[ix + 1]);
- if (res > 0) {
- tmpptr = list[ix];
- list[ix] = list[ix + 1];
- list[ix + 1] = tmpptr;
- }
- }
- }
- } else {
- // Split the list.
- pivot = list[len / 2];
- ix = 0;
- jx = len;
- for (;;) {
- while (ix < jx - 1 && sortsplot(list[ix], pivot) < 0)
- ix++;
- while (ix < jx - 1 && sortsplot(list[jx - 1], pivot) > 0)
- jx--;
- if (ix >= jx - 1)
- break;
- tmpptr = list[ix];
- list[ix] = list[jx - 1];
- list[jx - 1] = tmpptr;
- }
- ix++;
- // Sort the halves.
- giblorb_qsort(list + 0, ix);
- giblorb_qsort(list + ix, len - ix);
- }
-}
-
-giblorb_resdesc_t *Blorb::giblorb_bsearch(giblorb_resdesc_t *sample,
- giblorb_resdesc_t **list, int len) {
- int top, bot, val, res;
-
- bot = 0;
- top = len;
-
- while (bot < top) {
- val = (top + bot) / 2;
- res = sortsplot(list[val], sample);
- if (res == 0)
- return list[val];
- if (res < 0) {
- bot = val + 1;
- } else {
- top = val;
- }
- }
-
- return nullptr;
-}
-
-int Blorb::sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2) {
- if (v1->usage < v2->usage)
- return -1;
- if (v1->usage > v2->usage)
- return 1;
- if (v1->resnum < v2->resnum)
- return -1;
- if (v1->resnum > v2->resnum)
- return 1;
- return 0;
-}
-
-giblorb_err_t Blorb::giblorb_destroy_map(giblorb_map_t *map) {
- if (!map || !map->chunks || map->inited != giblorb_Inited_Magic)
- return giblorb_err_NotAMap;
-
- for (uint ix = 0; ix<map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &(map->chunks[ix]);
- if (chu->ptr) {
- delete chu->ptr;
- chu->ptr = nullptr;
- }
- }
-
- if (map->chunks) {
- delete[] map->chunks;
- map->chunks = nullptr;
- }
-
- map->numchunks = 0;
-
- if (map->resources) {
- delete[] map->resources;
- map->resources = nullptr;
- }
-
- if (map->ressorted) {
- delete[] map->ressorted;
- map->ressorted = nullptr;
- }
-
- map->numresources = 0;
- map->file = nullptr;
- map->inited = 0;
-
- delete map;
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_load_chunk_by_type(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
- uint ix;
-
- for (ix = 0; ix < map->numchunks; ix++) {
- if (map->chunks[ix].type == chunktype) {
- if (count == 0)
- break;
- count--;
- }
- }
-
- if (ix >= map->numchunks) {
- return giblorb_err_NotFound;
- }
-
- return giblorb_load_chunk_by_number(map, method, res, ix);
-}
-
-giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunknum) {
- giblorb_chunkdesc_t *chu;
-
- if (chunknum < 0 || chunknum >= map->numchunks)
- return giblorb_err_NotFound;
-
- chu = &(map->chunks[chunknum]);
-
- switch (method) {
- case giblorb_method_DontLoad:
- // do nothing
- break;
-
- case giblorb_method_FilePos:
- res->data.startpos = chu->datpos;
- break;
-
- case giblorb_method_Memory:
- if (!chu->ptr) {
- glui32 readlen;
- byte *dat = new byte[chu->len];
-
- if (!dat)
- return giblorb_err_Alloc;
-
- map->file->seek(chu->datpos);
-
- readlen = map->file->read(dat, chu->len);
- if (readlen != chu->len)
- return giblorb_err_Read;
-
- chu->ptr = dat;
- }
-
- res->data.ptr = chu->ptr;
- break;
- }
-
- res->chunknum = chunknum;
- res->length = chu->len;
- res->chunktype = chu->type;
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
- giblorb_chunkdesc_t *chu;
-
- if (chunknum < 0 || chunknum >= map->numchunks)
- return giblorb_err_NotFound;
-
- chu = &(map->chunks[chunknum]);
-
- if (chu->ptr) {
- delete chu->ptr;
- chu->ptr = nullptr;
- }
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_load_resource(giblorb_map_t *map, glui32 method,
- giblorb_result_t *res, glui32 usage, glui32 resnum) {
- giblorb_resdesc_t sample;
- giblorb_resdesc_t *found;
-
- sample.usage = usage;
- sample.resnum = resnum;
-
- found = giblorb_bsearch(&sample, map->ressorted, map->numresources);
-
- if (!found)
- return giblorb_err_NotFound;
-
- return giblorb_load_chunk_by_number(map, method, res, found->chunknum);
-}
-
-giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
- glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
- int ix;
- int count;
- glui32 val;
- glui32 minval, maxval;
-
- count = 0;
- minval = 0;
- maxval = 0;
-
- for (ix = 0; ix<map->numresources; ix++) {
- if (map->resources[ix].usage == usage) {
- val = map->resources[ix].resnum;
- if (count == 0) {
- count++;
- minval = val;
- maxval = val;
- }
- else {
- count++;
- if (val < minval)
- minval = val;
- if (val > maxval)
- maxval = val;
- }
- }
- }
-
- if (num)
- *num = count;
- if (min)
- *min = minval;
- if (max)
- *max = maxval;
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_set_resource_map(Common::SeekableReadStream *file) {
- giblorb_err_t err;
-
- err = giblorb_create_map(file, &_map);
- if (err) {
- _map = nullptr;
- return err;
- }
-
- _file = file;
- return giblorb_err_None;
-}
-
-giblorb_map_t *Blorb::giblorb_get_resource_map(void) {
- return _map;
-}
-
-bool Blorb::giblorb_is_resource_map(void) const {
- return _map != nullptr;
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/blorb.h b/engines/gargoyle/blorb.h
deleted file mode 100644
index 9de1947..0000000
--- a/engines/gargoyle/blorb.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* 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 GARGOYLE_BLORB_H
-#define GARGOYLE_BLORB_H
-
-#include "gargoyle/glk_types.h"
-#include "gargoyle/streams.h"
-
-namespace Gargoyle {
-
-
-/**
- * Error type
- */
-typedef glui32 giblorb_err_t;
-
-/**
- * Error codes
- */
-enum giblorbError {
- giblorb_err_None = 0,
- giblorb_err_CompileTime = 1,
- giblorb_err_Alloc = 2,
- giblorb_err_Read = 3,
- giblorb_err_NotAMap = 4,
- giblorb_err_Format = 5,
- giblorb_err_NotFound = 6
-};
-
-/**
- * Methods for loading a chunk
- */
-enum giblorbMethod {
- giblorb_method_DontLoad = 0,
- giblorb_method_Memory = 1,
- giblorb_method_FilePos = 2
-};
-
-enum {
- giblorb_ID_Snd = MKTAG('S', 'n', 'd', ' '),
- giblorb_ID_Exec = MKTAG('E', 'x', 'e', 'c'),
- giblorb_ID_Pict = MKTAG('P', 'i', 'c', 't'),
- giblorb_ID_Copyright = MKTAG('(', 'c', ')', ' '),
- giblorb_ID_AUTH = MKTAG('A', 'U', 'T', 'H'),
- giblorb_ID_ANNO = MKTAG('A', 'N', 'N', 'O')
-};
-
-
-enum {
- giblorb_ID_MOD = MKTAG('M', 'O', 'D', ' '),
- giblorb_ID_FORM = MKTAG('F', 'O', 'R', 'M'),
- giblorb_ID_IFRS = MKTAG('I', 'F', 'R', 'S'),
- giblorb_ID_RIdx = MKTAG('R', 'I', 'd', 'x'),
- giblorb_ID_OGG = MKTAG('O', 'G', 'G', 'V'),
-
- // non-standard types
- giblorb_ID_MIDI = MKTAG('M', 'I', 'D', 'I'),
- giblorb_ID_MP3 = MKTAG('M', 'P', '3', ' '),
- giblorb_ID_WAVE = MKTAG('W', 'A', 'V', 'E')
-};
-
-/**
- * Holds the complete description of an open Blorb file.
- * This type is opaque for normal interpreter use.
- */
-typedef struct giblorb_map_struct giblorb_map_t;
-
-/* giblorb_result_t: Result when you try to load a chunk. */
-typedef struct giblorb_result_struct {
- glui32 chunknum; // The chunk number (for use in giblorb_unload_chunk(), etc.)
- union {
- void *ptr; ///< A pointer to the data (if you used giblorb_method_Memory)
- glui32 startpos; ///< The position in the file (if you used giblorb_method_FilePos)
- } data;
-
- glui32 length; ///< The length of the data
- glui32 chunktype; ///< The type of the chunk.
-} giblorb_result_t;
-
-typedef struct giblorb_resdesc_struct giblorb_resdesc_t;
-
-class Blorb {
-private:
- bool _libInited;
- Common::SeekableReadStream *_file;
- giblorb_map_t *_map;
-private:
- /**
- * Initializes Blorb
- */
- giblorb_err_t giblorb_initialize();
-
- giblorb_err_t giblorb_initialize_map(giblorb_map_t *map);
- void giblorb_qsort(giblorb_resdesc_t **list, size_t len);
- giblorb_resdesc_t *giblorb_bsearch(giblorb_resdesc_t *sample,
- giblorb_resdesc_t **list, int len);
- int sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2);
-public:
- /**
- * Constructor
- */
- Blorb() : _libInited(false), _file(nullptr), _map(nullptr) {}
-
- giblorb_err_t giblorb_set_resource_map(Common::SeekableReadStream *file);
- giblorb_map_t *giblorb_get_resource_map(void);
- bool giblorb_is_resource_map(void) const;
-
-
- giblorb_err_t giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap);
- giblorb_err_t giblorb_destroy_map(giblorb_map_t *map);
-
- giblorb_err_t giblorb_load_chunk_by_type(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
- giblorb_err_t giblorb_load_chunk_by_number(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunknum);
- giblorb_err_t giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum);
-
- giblorb_err_t giblorb_load_resource(giblorb_map_t *map, glui32 method,
- giblorb_result_t *res, glui32 usage, glui32 resnum);
- giblorb_err_t giblorb_count_resources(giblorb_map_t *map,
- glui32 usage, glui32 *num, glui32 *min, glui32 *max);
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/conf.cpp b/engines/gargoyle/conf.cpp
deleted file mode 100644
index 9a0d648..0000000
--- a/engines/gargoyle/conf.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/conf.h"
-#include "gargoyle/fonts.h"
-#include "gargoyle/utils.h"
-#include "gargoyle/windows.h"
-#include "common/config-manager.h"
-#include "common/system.h"
-
-namespace Gargoyle {
-
-const byte WHITE[3] = { 0xff, 0xff, 0xff };
-const byte BLUE[3] = { 0x00, 0x00, 0x60 };
-const byte SCROLL_BG[3] = { 0xb0, 0xb0, 0xb0 };
-const byte SCROLL_FG[3] = { 0x80, 0x80, 0x80 };
-
-WindowStyle T_STYLES[style_NUMSTYLES] = {
- { PROPR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Normal
- { PROPI, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Emphasized
- { MONOR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Preformatted
- { PROPB, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Header
- { PROPB, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Subheader
- { PROPZ, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Alert
- { PROPR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< Note
- { PROPR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< BlockQuote
- { PROPB, { 0xff, 0xff, 0xff }, { 0x00, 0x60, 0x00 }, 0 }, ///< Input
- { MONOR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< User1
- { MONOR, { 0xff, 0xff, 0xff }, { 0x00, 0x00, 0x00 }, 0 }, ///< User2
-};
-
-WindowStyle G_STYLES[style_NUMSTYLES] = {
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Normal
- { MONOI, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Emphasized
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Preformatted
- { MONOB, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Header
- { MONOB, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Subheader
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Alert
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Note
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< BlockQuote
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< Input
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< User1
- { MONOR, { 0xff, 0xff, 0xff }, { 0x60, 0x60, 0x60 }, 0 }, ///< User2
-};
-
-Conf *g_conf;
-
-Conf::Conf() {
- g_conf = this;
- _imageW = g_system->getWidth();
- _imageH = g_system->getHeight();
- _cellW = _cellH = 8;
- _leading = 0;
- _baseLine = 0;
-
- get("moreprompt", _morePrompt, "\207 more \207");
- get("morecolor", _moreColor);
- get("morecolor", _moreSave);
- get("morefont", _moreFont, PROPB);
- get("morealign", _moreAlign);
- get("monoaspect", _monoAspect, 1.0);
- get("propaspect", _propAspect, 1.0);
- get("monosize", _monoSize, 11);
- get("monor", _monoR);
- get("monob", _monoR);
- get("monoi", _monoI);
- get("monoz", _monoZ);
- get("monofont", _monoFont, "Liberation Mono");
- get("propsize", _propSize, 12);
- get("propr", _propR);
- get("propb", _propR);
- get("propi", _propI);
- get("propz", _propZ);
- get("propfont", _propFont, "Linux Libertine O");
- get("rows", _rows, 25);
- get("cols", _cols, 60);
-
- if (ConfMan.hasKey("leading"))
- _leading = atof(ConfMan.get("leading").c_str()) + 0.5;
- if (ConfMan.hasKey("baseline"))
- _baseLine = atof(ConfMan.get("baseline").c_str()) + 0.5;
-
- if (ConfMan.hasKey("minrows"))
- _rows = MAX(_rows, strToInt(ConfMan.get("minrows").c_str()));
- if (ConfMan.hasKey("maxrows"))
- _rows = MIN(_rows, strToInt(ConfMan.get("maxrows").c_str()));
- if (ConfMan.hasKey("mincols"))
- _cols = MAX(_cols, strToInt(ConfMan.get("mincols").c_str()));
- if (ConfMan.hasKey("maxcols"))
- _cols = MIN(_cols, strToInt(ConfMan.get("maxcols").c_str()));
-
- get("lockrows", _lockRows);
- get("lockcols", _lockCols);
- get("wmarginx", _wMarginX, 15);
- get("wmarginy", _wMarginY, 15);
- _wMarginSaveX = _wMarginX;
- _wMarginSaveY = _wMarginY;
-
- get("wpaddingx", _wPaddingX);
- get("wpaddingy", _wPaddingY);
- get("wborderx", _wBorderX);
- get("wbordery", _wBorderY);
- get("tmarginx", _tMarginX, 7);
- get("tmarginy", _tMarginY, 7);
- get("gamma", _gamma, 1.0);
-
- get("caretcolor", _caretColor);
- get("caretcolor", _caretSave);
- get("linkcolor", _linkColor, BLUE);
- get("linkcolor", _linkSave, BLUE);
- get("bordercolor", _borderColor);
- get("bordercolor", _borderSave);
- get("windowcolor", _windowColor, WHITE);
- get("windowcolor", _windowSave, WHITE);
- get("lcd", _lcd, 1);
- get("caretshape", _caretShape, 2);
-
- _linkStyle = ConfMan.hasKey("linkstyle") && !strToInt(ConfMan.get("linkstyle").c_str()) ? 0 : 1;
-
- get("scrollwidth", _scrollWidth);
- get("scrollbg", _scrollBg, SCROLL_BG);
- get("scrollfg", _scrollFg, SCROLL_FG);
- get("justify", _justify);
- get("quotes", _quotes, 1);
- get("dashes", _dashes, 1);
- get("spaces", _spaces);
- get("caps", _caps);
- get("graphics", _graphics, true);
- get("sound", _sound, true);
- get("speak", _speak);
- get("speak_input", _speakInput);
- get("speak_language", _speakLanguage);
- get("stylehint", _styleHint, 1);
- get("safeclicks", _safeClicks);
-
- Common::copy(T_STYLES, T_STYLES + style_NUMSTYLES, _tStyles);
- Common::copy(G_STYLES, G_STYLES + style_NUMSTYLES, _gStyles);
-
- char buffer[255];
- const char *const TG_COLOR[2] = { "tcolor_%d", "gcolor_%d" };
- for (int tg = 0; tg < 2; ++tg) {
- for (int style = 0; style <= 10; ++style) {
- Common::String key = Common::String::format(TG_COLOR[tg], style);
- if (!ConfMan.hasKey(key))
- continue;
-
- strncpy(buffer, ConfMan.get(key).c_str(), 254);
- buffer[255] = '\0';
- char *fg = strtok(buffer, "\r\n\t ");
- char *bg = strtok(nullptr, "\r\n\t ");
-
- if (tg == 0) {
- parseColor(fg, _tStyles[style].fg);
- parseColor(bg, _tStyles[style].bg);
- } else {
- parseColor(fg, _gStyles[style].fg);
- parseColor(bg, _gStyles[style].bg);
- }
- }
- }
-
- const char *const TG_FONT[2] = { "tfont_%d", "gfont_%d" };
- for (int tg = 0; tg < 2; ++tg) {
- for (int style = 0; style <= 10; ++style) {
- Common::String key = Common::String::format(TG_FONT[tg], style);
- if (!ConfMan.hasKey(key))
- continue;
-
- strncpy(buffer, ConfMan.get(key).c_str(), 254);
- buffer[255] = '\0';
- char *font = strtok(buffer, "\r\n\t ");
-
- if (tg == 0)
- _tStyles[style].font = Fonts::getId(font);
- else
- _gStyles[style].font = Fonts::getId(font);
- }
- }
-
- Common::copy(_tStyles, _tStyles + style_NUMSTYLES, _tStylesDefault);
- Common::copy(_gStyles, _gStyles + style_NUMSTYLES, _gStylesDefault);
-}
-
-void Conf::get(const Common::String &key, Common::String &field, const char *defaultVal) {
- field = ConfMan.hasKey(key) ? ConfMan.get(key) : defaultVal;
- field.trim();
-}
-
-void Conf::get(const Common::String &key, byte *color, const byte *defaultColor) {
- if (ConfMan.hasKey(key)) {
- parseColor(ConfMan.get(key), color);
- } else if (defaultColor) {
- Common::copy(defaultColor, defaultColor + 3, color);
- } else {
- Common::fill(color, color + 3, 0);
- }
-}
-
-void Conf::get(const Common::String &key, int &field, int defaultVal) {
- field = ConfMan.hasKey(key) ? strToInt(ConfMan.get(key).c_str()) : defaultVal;
-}
-
-void Conf::get(const Common::String &key, bool &field, bool defaultVal) {
- field = ConfMan.hasKey(key) ? strToInt(ConfMan.get(key).c_str()) != 0 : defaultVal;
-}
-
-void Conf::get(const Common::String &key, FACES &field, FACES defaultFont) {
- field = ConfMan.hasKey(key) ? Fonts::getId(ConfMan.get(key)) : defaultFont;
-}
-
-void Conf::get(const Common::String &key, double &field, double defaultVal) {
- field = ConfMan.hasKey(key) ? atof(ConfMan.get(key).c_str()) : defaultVal;
-}
-
-void Conf::parseColor(const Common::String &str, byte *color) {
- char r[3], g[3], b[3];
-
- if (str.size() == 6) {
- r[0] = str[0];
- r[1] = str[1];
- r[2] = 0;
- g[0] = str[2];
- g[1] = str[3];
- g[2] = 0;
- b[0] = str[4];
- b[1] = str[5];
- b[2] = 0;
-
- color[0] = strtol(r, nullptr, 16);
- color[1] = strtol(g, nullptr, 16);
- color[2] = strtol(b, nullptr, 16);
- }
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/conf.h b/engines/gargoyle/conf.h
deleted file mode 100644
index 05dc6c9..0000000
--- a/engines/gargoyle/conf.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* 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 GARGOYLE_CONF_H
-#define GARGOYLE_CONF_H
-
-#include "gargoyle/glk_types.h"
-#include "gargoyle/fonts.h"
-#include "gargoyle/windows.h"
-
-namespace Gargoyle {
-
-class Conf {
-private:
- /**
- * Get a string
- */
- void get(const Common::String &key, Common::String &field, const char *defaultVal = nullptr);
-
- /**
- * Get a color
- */
- void get(const Common::String &key, byte *color, const byte *defaultColor = nullptr);
-
- /**
- * Get a font name into a font Id
- */
- void get(const Common::String &key, FACES &field, FACES defaultFont);
-
- /**
- * Get a numeric value
- */
- void get(const Common::String &key, int &field, int defaultVal = 0);
-
- /**
- * Get a numeric value
- */
- void get(const Common::String &key, bool &field, bool defaultVal = false);
-
- /**
- * Get a double
- */
- void get(const Common::String &key, double &field, double defaultVal = 0.0);
-
- /**
- * Parse a color
- */
- void parseColor(const Common::String &str, byte *color);
-public:
- Common::String _morePrompt;
- byte _moreColor[3], _moreSave[3];
- FACES _moreFont;
- int _moreAlign;
- double _monoAspect;
- double _propAspect;
- double _monoSize;
- Common::String _monoR;
- Common::String _monoB;
- Common::String _monoI;
- Common::String _monoZ;
- Common::String _monoFont;
- double _propSize;
- Common::String _propR;
- Common::String _propB;
- Common::String _propI;
- Common::String _propZ;
- Common::String _propFont;
- int _leading;
- int _baseLine;
- int _cols, _rows;
- int _lockCols, _lockRows;
- int _wMarginX, _wMarginY;
- int _wMarginSaveX, _wMarginSaveY;
- int _wPaddingX, _wPaddingY;
- int _wBorderX, _wBorderY;
- int _tMarginX, _tMarginY;
- double _gamma;
- byte _caretColor[3], _caretSave[3];
- byte _linkColor[3], _linkSave[3];
- byte _borderColor[3], _borderSave[3];
- byte _windowColor[3], _windowSave[3];
- int _lcd;
- int _caretShape;
- int _linkStyle;
- int _scrollWidth;
- byte _scrollBg[3], _scrollFg[3];
- int _justify;
- int _quotes;
- int _dashes;
- int _spaces;
- int _caps;
- bool _graphics;
- bool _sound;
- bool _speak;
- bool _speakInput;
- Common::String _speakLanguage;
- int _styleHint;
- bool _safeClicks;
- WindowStyle _tStyles[style_NUMSTYLES];
- WindowStyle _gStyles[style_NUMSTYLES];
- WindowStyle _tStylesDefault[style_NUMSTYLES];
- WindowStyle _gStylesDefault[style_NUMSTYLES];
-
- int _imageW, _imageH;
- int _cellW, _cellH;
-public:
- /**
- * Constructor
- */
- Conf();
-};
-
-extern Conf *g_conf;
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/configure.engine b/engines/gargoyle/configure.engine
deleted file mode 100644
index 3569297..0000000
--- a/engines/gargoyle/configure.engine
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file is included from the main "configure" script
-# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine gargoyle "Interactive Fiction games" no "" "" "freetype2"
diff --git a/engines/gargoyle/detection.cpp b/engines/gargoyle/detection.cpp
deleted file mode 100644
index 61cf201..0000000
--- a/engines/gargoyle/detection.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/gargoyle.h"
-
-#include "base/plugins.h"
-#include "common/md5.h"
-#include "common/memstream.h"
-#include "common/savefile.h"
-#include "common/str-array.h"
-#include "common/system.h"
-#include "engines/advancedDetector.h"
-#include "graphics/colormasks.h"
-#include "graphics/surface.h"
-
-#define MAX_SAVES 99
-
-namespace Gargoyle {
-
-struct GargoyleGameDescription {
- ADGameDescription _desc;
- Common::String _filename;
- InterpreterType _interpType;
- Common::String _md5;
-};
-
-const Common::String &GargoyleEngine::getFilename() const {
- return _gameDescription->_filename;
-}
-uint32 GargoyleEngine::getFeatures() const {
- return _gameDescription->_desc.flags;
-}
-
-bool GargoyleEngine::isDemo() const {
- return (bool)(_gameDescription->_desc.flags & ADGF_DEMO);
-}
-
-Common::Language GargoyleEngine::getLanguage() const {
- return _gameDescription->_desc.language;
-}
-
-InterpreterType GargoyleEngine::getInterpreterType() const {
- return _gameDescription->_interpType;
-}
-
-const Common::String &GargoyleEngine::getGameMD5() const {
- return _gameDescription->_md5;
-}
-
-} // End of namespace Gargoyle
-
-#include "gargoyle/frotz/detection_tables.h"
-#define ZCODE(ID, NAME) { ID, Gargoyle::Frotz::NAME##_DESC }
-
-static const PlainGameDescriptor gargoyleGames[] = {
- {"zcode", "Zcode Games" },
- {"scottadams", "Scott Adams Games"},
-
- // Infocom/Z-code games
- ZCODE("amfv", AMFV),
- ZCODE("arthur", ARTHUR),
- ZCODE("ballyhoo", BALLYHOO),
- ZCODE("beyondzork", BEYONDZORK),
- ZCODE("borderzone", BORDERZONE),
- ZCODE("bureaucracy", BUREAUCRACY),
- ZCODE("cutthroats", CUTTHROATS),
- ZCODE("deadline", DEADLINE),
- ZCODE("enchanter", ENCHANTER),
- ZCODE("hhgttg", HHGTTG),
- ZCODE("hijinx", HIJINX),
- ZCODE("infidel", INFIDEL),
- ZCODE("journey", JOURNEY),
- ZCODE("lgop", LGOP),
- ZCODE("lgop2", LGOP2),
- ZCODE("lurking", LURKING),
- ZCODE("minizork1", MINIZORK1),
- ZCODE("moonmist", MOONMIST),
- ZCODE("nordbert", NORDBERT),
- ZCODE("planetfall", PLANETFALL),
- ZCODE("plundered", PLUNDERED),
- ZCODE("sampler1", SAMPLER1),
- ZCODE("sampler2", SAMPLER2),
- ZCODE("seastalker", SEASTALKER),
- ZCODE("sherlockriddle", SHERLOCKRIDDLE),
- ZCODE("shogun", SHOGUN),
- ZCODE("sorcerer", SORCERER),
- ZCODE("spellbreaker", SPELLBREAKER),
- ZCODE("starcross", STARCROSS),
- ZCODE("stationfall", STATIONFALL),
- ZCODE("suspect", SUSPECT),
- ZCODE("suspended", SUSPENDED),
- ZCODE("trinity", TRINITY),
- ZCODE("wishbringer", WISHBRINGER),
- ZCODE("witness", WITNESS),
- ZCODE("zork0", ZORK0),
- ZCODE("zork1", ZORK1),
- ZCODE("zork2", ZORK2),
- ZCODE("zork3", ZORK3),
- ZCODE("ztuu", ZTUU),
-
- // Scott Adams games
- { "adventureland", "Adventureland" },
- { "pirateadventure", "Pirate Adventure" },
- { "missionimpossible", "Mission Impossible" },
- { "voodoocastle", "Voodoo Castle" },
- { "thecount", "The Count" },
- { "strangeodyssey", "Strange Odyssey" },
- { "mysteryfunhouse", "Mystery Fun House" },
- { "pyramidofdoom", "Pyramid Of Doom" },
- { "ghosttown", "Ghost Town" },
- { "savageisland1", "Savage Island, Part 1" },
- { "savageisland2", "Savage Island, Part 2" },
- { "goldenvoyage", "The Golden Voyage" },
- { "adventure13", "Adventure 13" },
- { "adventure14", "Adventure 14" },
- { "buckaroobonzai", "Buckaroo Banzai" },
- { "marveladventure", "Marvel Adventure #1" },
- { "scottsampler", "Adventure International's Mini-Adventure Sampler" },
- {0, 0}
-};
-
-#include "common/config-manager.h"
-#include "common/file.h"
-#include "gargoyle/detection_tables.h"
-#include "gargoyle/frotz/detection.h"
-#include "gargoyle/frotz/frotz.h"
-#include "gargoyle/scott/detection.h"
-#include "gargoyle/scott/scott.h"
-
-class GargoyleMetaEngine : public AdvancedMetaEngine {
-public:
- GargoyleMetaEngine() : AdvancedMetaEngine(Gargoyle::gameDescriptions, sizeof(Gargoyle::GargoyleGameDescription), gargoyleGames) {
- _maxScanDepth = 3;
- }
-
- virtual const char *getName() const {
- return "Gargoyle Engine";
- }
-
- virtual const char *getOriginalCopyright() const {
- return "Gargoyle Engine (c) 2018";
- }
-
- virtual bool hasFeature(MetaEngineFeature f) const override;
- virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
- virtual SaveStateList listSaves(const char *target) const;
- virtual int getMaximumSaveSlot() const;
- virtual void removeSaveState(const char *target, int slot) const;
- SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
-
- virtual DetectedGames detectGames(const Common::FSList &fslist) const override;
-
- virtual ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override;
-};
-
-bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
- return
- (f == kSupportsListSaves) ||
- (f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportCreationDate) ||
- (f == kSavesSupportPlayTime) ||
- (f == kSimpleSavesNames);
-}
-
-bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
- return
- (f == kSupportsRTL) ||
- (f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
-}
-
-bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
-
- switch (gd->_interpType) {
- case Gargoyle::INTERPRETER_FROTZ:
- *engine = new Gargoyle::Frotz::Frotz(syst, gd);
- break;
- case Gargoyle::INTERPRETER_SCOTT:
- *engine = new Gargoyle::Scott::Scott(syst, gd);
- break;
- default:
- error("Unknown interpreter");
- }
-
- return gd != 0;
-}
-
-SaveStateList GargoyleMetaEngine::listSaves(const char *target) const {
- Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- Common::StringArray filenames;
- Common::String saveDesc;
- Common::String pattern = Common::String::format("%s.0##", target);
- Gargoyle::SavegameHeader header;
-
- filenames = saveFileMan->listSavefiles(pattern);
-
- SaveStateList saveList;
- for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
- const char *ext = strrchr(file->c_str(), '.');
- int slot = ext ? atoi(ext + 1) : -1;
-
- if (slot >= 0 && slot <= MAX_SAVES) {
- Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
-
- if (in) {
- if (Gargoyle::FileStream::readSavegameHeader(in, header))
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
-
- delete in;
- }
- }
- }
-
- // Sort saves based on slot number.
- Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
- return saveList;
-}
-
-int GargoyleMetaEngine::getMaximumSaveSlot() const {
- return MAX_SAVES;
-}
-
-void GargoyleMetaEngine::removeSaveState(const char *target, int slot) const {
- Common::String filename = Common::String::format("%s.%03d", target, slot);
- g_system->getSavefileManager()->removeSavefile(filename);
-}
-
-SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
- Common::String filename = Common::String::format("%s.%03d", target, slot);
- Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename);
-
- if (in) {
- Gargoyle::SavegameHeader header;
- if (Gargoyle::FileStream::readSavegameHeader(in, header)) {
- // Create the return descriptor
- SaveStateDescriptor desc(slot, header._saveName);
- desc.setSaveDate(header._year, header._month, header._day);
- desc.setSaveTime(header._hour, header._minute);
- desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
-
- delete in;
- return desc;
- }
- }
-
- return SaveStateDescriptor();
-}
-
-DetectedGames GargoyleMetaEngine::detectGames(const Common::FSList &fslist) const {
- DetectedGames detectedGames;
- Gargoyle::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
- Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
-
- return detectedGames;
-}
-
-static Gargoyle::GargoyleGameDescription gameDescription;
-
-ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
- static char gameId[100];
- strcpy(gameId, ConfMan.get("gameid").c_str());
- Common::String filename = ConfMan.get("filename");
-
- Common::FSList fslist;
- DetectedGames detectedGames;
- fslist.push_back(parent.getChild(filename));
- ADDetectedGames results;
- Common::File f;
-
- // Check each sub-engine for any detected games
- if (Gargoyle::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames))
- gameDescription._interpType = Gargoyle::INTERPRETER_FROTZ;
- else if (Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames))
- gameDescription._interpType = Gargoyle::INTERPRETER_SCOTT;
- else
- // No match found, so return no results
- return results;
-
- // Set up the game description and return it
- if (f.open(parent.getChild(filename))) {
- DetectedGame gd = detectedGames.front();
-
- gameDescription._desc.gameId = gameId;
- gameDescription._desc.language = gd.language;
- gameDescription._desc.platform = gd.platform;
- gameDescription._desc.guiOptions = GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES);
- gameDescription._filename = filename;
- gameDescription._md5 = Common::computeStreamMD5AsString(f, 5000);
-
- ADDetectedGame dg((ADGameDescription *)&gameDescription);
- results.push_back(dg);
- }
-
- return results;
-}
-
-#if PLUGIN_ENABLED_DYNAMIC(GARGOYLE)
-REGISTER_PLUGIN_DYNAMIC(Gargoyle, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
-#else
-REGISTER_PLUGIN_STATIC(GARGOYLE, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
-#endif
diff --git a/engines/gargoyle/detection_tables.h b/engines/gargoyle/detection_tables.h
deleted file mode 100644
index 30491f6..0000000
--- a/engines/gargoyle/detection_tables.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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.
- *
- */
-
-namespace Gargoyle {
-
-static const GargoyleGameDescription gameDescriptions[] = {
- { AD_TABLE_END_MARKER, "", (InterpreterType)0, "" }
-};
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.cpp b/engines/gargoyle/events.cpp
deleted file mode 100644
index 6c0cd71..0000000
--- a/engines/gargoyle/events.cpp
+++ /dev/null
@@ -1,402 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/events.h"
-#include "gargoyle/conf.h"
-#include "gargoyle/gargoyle.h"
-#include "gargoyle/screen.h"
-#include "gargoyle/selection.h"
-#include "gargoyle/windows.h"
-#include "graphics/cursorman.h"
-
-namespace Gargoyle {
-
-const byte ARROW[] = {
- // byte 1: number of skipped pixels
- // byte 2: number of plotted pixels
- // then, pixels
- 0, 1, 5,
- 0, 2, 5, 5,
- 0, 3, 5, 0xF7, 5,
- 0, 3, 5, 0xF7, 5,
- 0, 4, 5, 0xF7, 0xF7, 5,
- 0, 4, 5, 0xF7, 0xF7, 5,
- 0, 5, 5, 0xF7, 0xF7, 0xF7, 5,
- 0, 5, 5, 0xF7, 0xF7, 0xF7, 5,
- 0, 6, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 6, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 7, 5, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 6, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
- 0, 5, 5, 0xF7, 0xF7, 0xF7, 5,
- 2, 3, 5, 0xF7, 5,
- 3, 3, 5, 0xF7, 5,
- 3, 3, 5, 0xF7, 5,
- 4, 2, 5, 5
-};
-
-Events::Events() : _forceClick(false), _currentEvent(nullptr), _cursorId(CURSOR_NONE),
- _timerMilli(0), _timerTimeExpiry(0), _priorFrameTime(0), _frameCounter(0) {
- initializeCursors();
-}
-
-Events::~Events() {
- for (int idx = 1; idx < 3; ++idx)
- _cursors[idx].free();
-}
-
-void Events::initializeCursors() {
- const Graphics::PixelFormat format = g_system->getScreenFormat();
- const int WHITE = format.RGBToColor(0xff, 0xff, 0xff);
- const int BLACK = 0;
- const int TRANSPARENT = format.RGBToColor(0x80, 0x80, 0x80);
-
- // Setup arrow cursor
- Surface &arr = _cursors[CURSOR_ARROW];
- arr.create(8, 16, g_system->getScreenFormat());
- arr.fillRect(Common::Rect(0, 0, 8, 16), TRANSPARENT);
-
- const byte *p = ARROW;
- for (int y = 0; y < 16; ++y) {
- int offset = *p++;
- int len = *p++;
-
- for (int x = offset; x < (offset + len); ++x, ++p) {
- arr.hLine(x, y, x, (*p == 0xf7) ? WHITE : BLACK);
- }
- }
-
- // Setup selection cusor sized to the vertical line size
- Surface &sel = _cursors[CURSOR_IBEAM];
- sel.create(5, g_conf->_leading, g_system->getScreenFormat());
- sel.fillRect(Common::Rect(0, 0, sel.w, sel.h), TRANSPARENT);
- sel.hLine(0, 0, 4, 0);
- sel.hLine(0, sel.h - 1, 4, 0);
- sel.vLine(2, 1, sel.h - 1, 0);
- sel._hotspot = Common::Point(2, sel.h - 1);
-
- // TODO: Hyperlink hand cursor
-}
-
-void Events::checkForNextFrameCounter() {
- // Check for next game frame
- uint32 milli = g_system->getMillis();
- if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
- ++_frameCounter;
- _priorFrameTime = milli;
-
- if (_redraw)
- g_vm->_windows->redraw();
- _redraw = false;
- g_vm->_screen->update();
- return;
- }
-}
-
-void Events::getEvent(event_t *event, bool polled) {
- _currentEvent = event;
- event->clear();
-
- dispatchEvent(*_currentEvent, polled);
-
- if (!polled) {
- while (!g_vm->shouldQuit() && _currentEvent->type == evtype_None && !isTimerExpired()) {
- pollEvents();
- g_system->delayMillis(10);
-
- dispatchEvent(*_currentEvent, polled);
- }
-
- if (g_vm->shouldQuit())
- _currentEvent->type = evtype_Quit;
- }
-
- if (_currentEvent->type == evtype_None && isTimerExpired()) {
- store(evtype_Timer, nullptr, 0, 0);
- dispatchEvent(*_currentEvent, polled);
-
- _timerTimeExpiry = g_system->getMillis() + _timerMilli;
- }
-
- _currentEvent = nullptr;
-}
-
-void Events::store(EvType type, Window *win, uint32 val1, uint32 val2) {
- Event ev(type, win, val1, val2);
-
- switch (type) {
- case evtype_Arrange:
- case evtype_Redraw:
- case evtype_SoundNotify:
- case evtype_Timer:
- _eventsPolled.push(ev);
- break;
-
- default:
- _eventsLogged.push(ev);
- break;
- }
-}
-
-void Events::dispatchEvent(Event &ev, bool polled) {
- Event dispatch;
-
- if (!polled) {
- dispatch = _eventsLogged.retrieve();
- if (!dispatch)
- dispatch = _eventsPolled.retrieve();
- } else {
- dispatch = _eventsPolled.retrieve();
- }
-
- if (dispatch)
- ev = dispatch;
-}
-
-void Events::pollEvents() {
- Common::Event event;
-
- do {
- checkForNextFrameCounter();
- g_system->getEventManager()->pollEvent(event);
-
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- setCursor(CURSOR_NONE);
- handleKeyDown(event.kbd);
- return;
-
- case Common::EVENT_LBUTTONDOWN:
- case Common::EVENT_RBUTTONDOWN:
- handleButtonDown(event.type == Common::EVENT_LBUTTONDOWN, event.mouse);
- return;
-
- case Common::EVENT_LBUTTONUP:
- case Common::EVENT_RBUTTONUP:
- handleButtonUp(event.type == Common::EVENT_LBUTTONUP, event.mouse);
- return;
-
- case Common::EVENT_WHEELUP:
- case Common::EVENT_WHEELDOWN:
- setCursor(CURSOR_NONE);
- handleScroll(event.type == Common::EVENT_WHEELUP);
- return;
-
- case Common::EVENT_MOUSEMOVE:
- handleMouseMove(event.mouse);
- break;
-
- default:
- break;
- }
- } while (event.type == Common::EVENT_MOUSEMOVE);
-}
-
-void Events::handleKeyDown(const Common::KeyState &ks) {
- Clipboard &clipboard = *g_vm->_clipboard;
- Windows &windows = *g_vm->_windows;
-
- if (ks.flags & Common::KBD_CTRL) {
- if (ks.keycode == Common::KEYCODE_a)
- windows.inputHandleKey(keycode_Home);
- else if (ks.keycode == Common::KEYCODE_c)
- clipboard.clipboardSend(CLIPBOARD);
- else if (ks.keycode == Common::KEYCODE_e)
- windows.inputHandleKey(keycode_End);
- else if (ks.keycode == Common::KEYCODE_u)
- windows.inputHandleKey(keycode_Escape);
- else if (ks.keycode == Common::KEYCODE_v)
- clipboard.clipboardReceive(CLIPBOARD);
- else if (ks.keycode == Common::KEYCODE_x)
- clipboard.clipboardSend(CLIPBOARD);
- else if (ks.keycode == Common::KEYCODE_LEFT || ks.keycode == Common::KEYCODE_KP4)
- windows.inputHandleKey(keycode_SkipWordLeft);
- else if (ks.keycode == Common::KEYCODE_RIGHT || ks.keycode == Common::KEYCODE_KP6)
- windows.inputHandleKey(keycode_SkipWordRight);
-
- return;
- }
-
- if (ks.flags & Common::KBD_ALT)
- return;
-
- switch (ks.keycode) {
- case Common::KEYCODE_RETURN:
- windows.inputHandleKey(keycode_Return);
- break;
- case Common::KEYCODE_BACKSPACE:
- windows.inputHandleKey(keycode_Delete);
- break;
- case Common::KEYCODE_DELETE:
- windows.inputHandleKey(keycode_Erase);
- break;
- case Common::KEYCODE_TAB:
- windows.inputHandleKey(keycode_Tab);
- break;
- case Common::KEYCODE_PAGEUP:
- windows.inputHandleKey(keycode_PageUp);
- break;
- case Common::KEYCODE_PAGEDOWN:
- windows.inputHandleKey(keycode_PageDown);
- break;
- case Common::KEYCODE_HOME:
- windows.inputHandleKey(keycode_Home);
- break;
- case Common::KEYCODE_END:
- windows.inputHandleKey(keycode_End);
- break;
- case Common::KEYCODE_LEFT:
- windows.inputHandleKey(keycode_Left);
- break;
- case Common::KEYCODE_RIGHT:
- windows.inputHandleKey(keycode_Right);
- break;
- case Common::KEYCODE_UP:
- windows.inputHandleKey(keycode_Up);
- break;
- case Common::KEYCODE_DOWN:
- windows.inputHandleKey(keycode_Down);
- break;
- case Common::KEYCODE_ESCAPE:
- windows.inputHandleKey(keycode_Escape);
- break;
- case Common::KEYCODE_F1:
- windows.inputHandleKey(keycode_Func1);
- break;
- case Common::KEYCODE_F2:
- windows.inputHandleKey(keycode_Func2);
- break;
- case Common::KEYCODE_F3:
- windows.inputHandleKey(keycode_Func3);
- break;
- case Common::KEYCODE_F4:
- windows.inputHandleKey(keycode_Func4);
- break;
- case Common::KEYCODE_F5:
- windows.inputHandleKey(keycode_Func5);
- break;
- case Common::KEYCODE_F6:
- windows.inputHandleKey(keycode_Func6);
- break;
- case Common::KEYCODE_F7:
- windows.inputHandleKey(keycode_Func7);
- break;
- case Common::KEYCODE_F8:
- windows.inputHandleKey(keycode_Func8);
- break;
- case Common::KEYCODE_F9:
- windows.inputHandleKey(keycode_Func9);
- break;
- case Common::KEYCODE_F10:
- windows.inputHandleKey(keycode_Func10);
- break;
- case Common::KEYCODE_F11:
- windows.inputHandleKey(keycode_Func11);
- break;
- case Common::KEYCODE_F12:
- windows.inputHandleKey(keycode_Func12);
- break;
- default:
- windows.inputHandleKey(ks.ascii);
- break;
- break;
- }
-}
-
-void Events::handleScroll(bool wheelUp) {
- g_vm->_windows->inputHandleKey(wheelUp ? keycode_MouseWheelUp : keycode_MouseWheelDown);
-}
-
-void Events::handleMouseMove(const Point &pos) {
- if (_cursorId == CURSOR_NONE)
- setCursor(CURSOR_ARROW);
-
- // hyperlinks and selection
- // TODO: Properly handle commented out lines
- if (g_vm->_copySelect) {
- //gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_ibeam);
- g_vm->_selection->moveSelection(pos);
- } else {
- if (g_vm->_selection->getHyperlink(pos)) {
- //gdk_window_set_cursor((GTK_WIDGET(widget)->window), gdk_hand);
- } else {
- //gdk_window_set_cursor((GTK_WIDGET(widget)->window), nullptr);
- }
- }
-}
-
-void Events::handleButtonDown(bool isLeft, const Point &pos) {
- if (isLeft) {
- setCursor(CURSOR_IBEAM);
- g_vm->_windows->inputHandleClick(pos);
- } else {
- g_vm->_clipboard->clipboardReceive(PRIMARY);
- }
-}
-
-void Events::handleButtonUp(bool isLeft, const Point &pos) {
- if (isLeft) {
- setCursor(CURSOR_ARROW);
- g_vm->_copySelect = false;
- g_vm->_clipboard->clipboardSend(PRIMARY);
- }
-}
-
-void Events::waitForPress() {
- Common::Event e;
-
- do {
- g_system->getEventManager()->pollEvent(e);
- g_system->delayMillis(10);
- checkForNextFrameCounter();
- } while (!g_vm->shouldQuit() && e.type != Common::EVENT_KEYDOWN &&
- e.type != Common::EVENT_LBUTTONDOWN && e.type != Common::EVENT_RBUTTONDOWN &&
- e.type != Common::EVENT_MBUTTONDOWN);
-}
-
-void Events::setCursor(CursorId cursorId) {
- if (cursorId != _cursorId) {
- if (cursorId == CURSOR_NONE) {
- CursorMan.showMouse(false);
- } else {
- if (!CursorMan.isVisible())
- CursorMan.showMouse(true);
-
- const Surface &s = _cursors[cursorId];
- const int TRANSPARENT = s.format.RGBToColor(0x80, 0x80, 0x80);
-
- CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s._hotspot.x, s._hotspot.y, TRANSPARENT, true, &s.format);
- }
-
- _cursorId = cursorId;
- }
-}
-
-void Events::setTimerInterval(uint milli) {
- _timerMilli = milli;
- _timerTimeExpiry = g_system->getMillis() + milli;
-}
-
-bool Events::isTimerExpired() const {
- return _timerMilli && g_system->getMillis() >= _timerTimeExpiry;
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/events.h b/engines/gargoyle/events.h
deleted file mode 100644
index 745f1ae..0000000
--- a/engines/gargoyle/events.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/* 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 GARGOYLE_EVENTS_H
-#define GARGOYLE_EVENTS_H
-
-#include "common/events.h"
-#include "graphics/surface.h"
-#include "gargoyle/utils.h"
-
-namespace Gargoyle {
-
-#define GAME_FRAME_RATE 100
-#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
-
-class Window;
-
-/**
- * Event types
- */
-enum EvType {
- evtype_None = 0,
- evtype_Timer = 1,
- evtype_CharInput = 2,
- evtype_LineInput = 3,
- evtype_MouseInput = 4,
- evtype_Arrange = 5,
- evtype_Redraw = 6,
- evtype_SoundNotify = 7,
- evtype_Hyperlink = 8,
- evtype_VolumeNotify = 9,
-
- // ScummVM custom events
- evtype_Quit = 99
-};
-
-/**
- * Keycodes
- */
-enum Keycode {
- keycode_Unknown = 0xffffffffU,
- keycode_Left = 0xfffffffeU,
- keycode_Right = 0xfffffffdU,
- keycode_Up = 0xfffffffcU,
- keycode_Down = 0xfffffffbU,
- keycode_Return = 0xfffffffaU,
- keycode_Delete = 0xfffffff9U,
- keycode_Escape = 0xfffffff8U,
- keycode_Tab = 0xfffffff7U,
- keycode_PageUp = 0xfffffff6U,
- keycode_PageDown = 0xfffffff5U,
- keycode_Home = 0xfffffff4U,
- keycode_End = 0xfffffff3U,
- keycode_Func1 = 0xffffffefU,
- keycode_Func2 = 0xffffffeeU,
- keycode_Func3 = 0xffffffedU,
- keycode_Func4 = 0xffffffecU,
- keycode_Func5 = 0xffffffebU,
- keycode_Func6 = 0xffffffeaU,
- keycode_Func7 = 0xffffffe9U,
- keycode_Func8 = 0xffffffe8U,
- keycode_Func9 = 0xffffffe7U,
- keycode_Func10 = 0xffffffe6U,
- keycode_Func11 = 0xffffffe5U,
- keycode_Func12 = 0xffffffe4U,
-
- // non standard keycodes
- keycode_Erase = 0xffffef7fU,
- keycode_MouseWheelUp = 0xffffeffeU,
- keycode_MouseWheelDown = 0xffffefffU,
- keycode_SkipWordLeft = 0xfffff000U,
- keycode_SkipWordRight = 0xfffff001U,
-
- // The last keycode is always = 0x100000000 - keycode_MAXVAL)
- keycode_MAXVAL = 28U
-};
-
-/**
- * List of cursors
- */
-enum CursorId {
- CURSOR_NONE = 0,
- CURSOR_ARROW = 1,
- CURSOR_IBEAM = 2,
- CURSOR_HAND = 3
-};
-
-/**
- * Event structure
- */
-struct Event {
- EvType type;
- Window *window;
- uint32 val1, val2;
-
- /**
- * Constructor
- */
- Event() {
- clear();
- }
-
- /**
- * Constructor
- */
- Event(EvType evType, Window *evWindow, uint32 evVal1, uint32 evVal2) {
- type = evType;
- window = evWindow;
- val1 = evVal1;
- val2 = evVal2;
- }
-
- /**
- * Clear
- */
- void clear() {
- type = evtype_None;
- window = nullptr;
- val1 = val2 = 0;
- }
-
- /**
- * Boolean cast to allow checking whether event is filled out
- */
- operator bool() const {
- return type != evtype_None;
- }
-};
-typedef Event event_t;
-
-class EventQueue : public Common::Queue<Event> {
-public:
- /**
- * Retrieve a pending event, if any
- */
- Event retrieve() {
- return empty() ? Event() : pop();
- }
-};
-
-/**
- * Events manager
- */
-class Events {
- struct Surface : public Graphics::Surface {
- Common::Point _hotspot;
- };
-private:
- EventQueue _eventsPolled; ///< User generated events
- EventQueue _eventsLogged; ///< Custom events generated by game code
- Event *_currentEvent; ///< Event pointer passed during event retrieval
- uint32 _priorFrameTime; ///< Time of prior game frame
- uint32 _frameCounter; ///< Frame counter
- bool _redraw; ///< Screen needed redrawing
- CursorId _cursorId; ///< Current cursor Id
- Surface _cursors[4]; ///< Cursor pixel data
- uint _timerMilli; ///< Time in milliseconds between timer events
- uint _timerTimeExpiry; ///< When to trigger next timer event
-private:
- /**
- * Initialize the cursor graphics
- */
- void initializeCursors();
-
- /**
- * Checks for whether it's time for the next game frame
- */
- void checkForNextFrameCounter();
-
- /**
- * Dispatches an event
- */
- void dispatchEvent(Event &ev, bool polled);
-
- /**
- * Poll for user events
- */
- void pollEvents();
-
- /**
- * Handle a key down event
- */
- void handleKeyDown(const Common::KeyState &ks);
-
- /**
- * Handle scroll events
- */
- void handleScroll(bool wheelUp);
-
- /**
- * Handle mouse move events
- */
- void handleMouseMove(const Point &pos);
-
- /**
- * Handle mouse down events
- */
- void handleButtonDown(bool isLeft, const Point &pos);
-
- /**
- * Handle mouse up events
- */
- void handleButtonUp(bool isLeft, const Point &pos);
-public:
- bool _forceClick;
-public:
- /**
- * Constructor
- */
- Events();
-
- /**
- * Destructor
- */
- ~Events();
-
- /**
- * Get any pending event
- */
- void getEvent(event_t *event, bool polled);
-
- /**
- * Store an event for retrieval
- */
- void store(EvType type, Window *win, uint32 val1 = 0, uint32 val2 = 0);
-
- /**
- * Wait for a keyboard or mouse press
- */
- void waitForPress();
-
- /**
- * Get the total number of frames played
- */
- uint32 getTotalPlayTicks() const {
- return _frameCounter;
- }
-
- /**
- * Set the total number of frames played
- */
- void setTotalPlayTicks(uint frames) {
- _frameCounter = frames;
- }
-
- /**
- * Flags the screen for redrawing
- */
- void redraw() {
- _redraw = true;
- }
-
- /**
- * Sets the current cursor
- */
- void setCursor(CursorId cursorId);
-
- /**
- * Set a timer interval
- * @param milli Time in millieseconds for intervals, or 0 for off
- */
- void setTimerInterval(uint milli);
-
- /**
- * Returns true if it's time for a timer event
- */
- bool isTimerExpired() const;
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/fonts.cpp b/engines/gargoyle/fonts.cpp
deleted file mode 100644
index 9c07412..0000000
--- a/engines/gargoyle/fonts.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/fonts.h"
-#include "gargoyle/glk_types.h"
-#include "gargoyle/conf.h"
-#include "gargoyle/gargoyle.h"
-#include "common/memstream.h"
-#include "common/unzip.h"
-#include "graphics/fonts/ttf.h"
-#include "graphics/fontman.h"
-
-namespace Gargoyle {
-
-#define FONTS_VERSION 1.0
-#define FONTS_FILENAME "fonts.dat"
-
-Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface), _fontsMissing(false) {
- if (!loadFonts())
- error("Could not load data file");
-
- // TODO: See if there's any better way for getting the leading and baseline
- Common::Rect r1 = _fontTable[7]->getBoundingBox('o');
- Common::Rect r2 = _fontTable[7]->getBoundingBox('y');
- double baseLine = (double)r1.bottom;
- double leading = (double)r2.bottom + 2;
-
- g_conf->_leading = MAX((double)g_conf->_leading, leading);
- g_conf->_baseLine = MAX((double)g_conf->_baseLine, baseLine);
- g_conf->_cellW = _fontTable[0]->getStringWidth("0");
- g_conf->_cellH = g_conf->_leading;
-}
-
-Fonts::~Fonts() {
- for (int idx = 0; idx < FONTS_TOTAL; ++idx)
- delete _fontTable[idx];
-}
-
-bool Fonts::loadFonts() {
- Common::Archive *archive = nullptr;
-
- if (!Common::File::exists(FONTS_FILENAME) || (archive = Common::makeZipArchive(FONTS_FILENAME)) == nullptr)
- return false;
-
- // Open the version.txt file within it to validate the version
- Common::File f;
- if (!f.open("version.txt", *archive)) {
- delete archive;
- return false;
- }
-
- // Validate the version
- char buffer[4];
- f.read(buffer, 3);
- buffer[3] = '\0';
-
- if (Common::String(buffer) != "1.0") {
- delete archive;
- return false;
- }
-
- // R ead in the fonts
- double monoAspect = g_conf->_monoAspect;
- double propAspect = g_conf->_propAspect;
- double monoSize = g_conf->_monoSize;
- double propSize = g_conf->_propSize;
-
- _fontTable[0] = loadFont(MONOR, archive, monoSize, monoAspect, FONTR);
- _fontTable[1] = loadFont(MONOB, archive, monoSize, monoAspect, FONTB);
- _fontTable[2] = loadFont(MONOI, archive, monoSize, monoAspect, FONTI);
- _fontTable[3] = loadFont(MONOZ, archive, monoSize, monoAspect, FONTZ);
-
- _fontTable[4] = loadFont(PROPR, archive, propSize, propAspect, FONTR);
- _fontTable[5] = loadFont(PROPB, archive, propSize, propAspect, FONTB);
- _fontTable[6] = loadFont(PROPI, archive, propSize, propAspect, FONTI);
- _fontTable[7] = loadFont(PROPZ, archive, propSize, propAspect, FONTZ);
-
- delete archive;
- return true;
-}
-
-const Graphics::Font *Fonts::loadFont(FACES face, Common::Archive *archive, double size, double aspect, int
- style) {
- const char *const FILENAMES[8] = {
- "GoMono-Regular.ttf", "GoMono-Bold.ttf", "GoMono-Italic.ttf", "GoMono-Bold-Italic.ttf",
- "NotoSerif-Regular.ttf", "NotoSerif-Bold.ttf", "NotoSerif-Italic.ttf", "NotoSerif-Bold-Italic.ttf"
- };
-
- Common::File f;
- if (!f.open(FILENAMES[face], *archive))
- error("Could not load font");
-
- return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
-}
-
-FACES Fonts::getId(const Common::String &name) {
- if (name == "monor") return MONOR;
- if (name == "monob") return MONOB;
- if (name == "monoi") return MONOI;
- if (name == "monoz") return MONOZ;
- if (name == "propr") return PROPR;
- if (name == "propb") return PROPB;
- if (name == "propi") return PROPI;
- if (name == "propz") return PROPZ;
- return MONOR;
-}
-
-int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
- Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
- const Graphics::Font *font = _fontTable[fontIdx];
- const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
-
- pt.x += font->getStringWidth(text);
- return MIN((int)pt.x, (int)_surface->w) * GLI_SUBPIX;
-}
-
-int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
- Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
- const Graphics::Font *font = _fontTable[fontIdx];
- const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
-
- pt.x += font->getStringWidth(text);
- return MIN((int)pt.x, (int)_surface->w) * GLI_SUBPIX;
-}
-
-size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
- const Graphics::Font *font = _fontTable[fontIdx];
- return font->getStringWidth(text) * GLI_SUBPIX;
-}
-
-size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
- const Graphics::Font *font = _fontTable[fontIdx];
- return font->getStringWidth(text) * GLI_SUBPIX;
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/fonts.h b/engines/gargoyle/fonts.h
deleted file mode 100644
index 737618e..0000000
--- a/engines/gargoyle/fonts.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* 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 GARGOYLE_FONTS_H
-#define GARGOYLE_FONTS_H
-
-#include "gargoyle/glk_types.h"
-#include "gargoyle/utils.h"
-#include "common/archive.h"
-#include "common/array.h"
-#include "common/file.h"
-#include "common/str.h"
-#include "common/ustr.h"
-#include "graphics/font.h"
-
-namespace Gargoyle {
-
-#define FONTS_TOTAL 8
-
-enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
-enum TYPES { MONOF, PROPF };
-enum STYLES { FONTR, FONTB, FONTI, FONTZ };
-
-/**
- * Fonts manager
- */
-class Fonts {
-private:
- Graphics::ManagedSurface *_surface;
- const Graphics::Font *_fontTable[FONTS_TOTAL];
- bool _fontsMissing;
-private:
- /**
- * Load all the fonts
- */
- bool loadFonts();
-
- /**
- * Load a single font
- */
- const Graphics::Font *loadFont(FACES face, Common::Archive *archive, double size, double aspect, int style);
-public:
- /**
- * Get the index/id of a font by name
- */
- static FACES getId(const Common::String &name);
-public:
- /**
- * Constructor
- */
- Fonts(Graphics::ManagedSurface *surface);
-
- /**
- * Destructor
- */
- virtual ~Fonts();
-
- /**
- * Draws a string using the specified font at the given co-ordinates
- * @param pos Position for the bottom-left corner the text will be drawn with
- * @param fontIdx Which font to use
- * @param rgb RGB tuplet specifying the text color
- * @param text The text to draw
- * @param spw ??
- */
- int drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
-
- /**
- * Draws a unicode string using the specified font at the given co-ordinates
- * @param pos Position for the bottom-left corner the text will be drawn with
- * @param fontIdx Which font to use
- * @param rgb RGB tuplet specifying the text color
- * @param text The text to draw
- * @param spw ??
- */
- int drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
-
- /**
- * Get the width in pixels of a string
- * @param fontIdx Which font to use
- * @param text Text to get the width of
- * @param spw Delta X
- * @returns Width of string multiplied by GLI_SUBPIX
- */
- size_t stringWidth(int fontIdx, const Common::String &text, int spw = 0);
-
- /**
- * Get the width in pixels of a unicode string
- * @param fontIdx Which font to use
- * @param text Text to get the width of
- * @param spw Delta X
- * @returns Width of string multiplied by GLI_SUBPIX
- */
- size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = 0);
-};
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/detection.cpp b/engines/gargoyle/frotz/detection.cpp
deleted file mode 100644
index fff8005..0000000
--- a/engines/gargoyle/frotz/detection.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/detection.h"
-#include "common/file.h"
-#include "common/md5.h"
-
-#include "gargoyle/frotz/detection_tables.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
- const char *const EXTENSIONS[9] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
-
- // Loop through the files of the folder
- for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- // Check for a recognised filename
- if (file->isDirectory())
- continue;
- Common::String filename = file->getName();
- bool hasExt = false;
- for (int idx = 0; idx < 9 && !hasExt; ++idx)
- hasExt = filename.hasSuffixIgnoreCase(EXTENSIONS[idx]);
- if (!hasExt)
- continue;
-
- // Open up the file and calculate the md5
- Common::File gameFile;
- if (!gameFile.open(*file))
- continue;
- Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
- size_t filesize = gameFile.size();
- gameFile.close();
-
- // Check for known game
- const FrotzGameDescription *p = FROTZ_GAMES;
- while (p->_gameId && p->_md5 && (md5 != p->_md5 || filesize != p->_filesize))
- ++p;
-
- DetectedGame gd;
- if (!p->_gameId) {
- // Generic .dat files don't get reported as matches unless they have a known md5
- if (filename.hasSuffixIgnoreCase(".dat"))
- continue;
-
- warning("Uknown zcode game %s - %s %d", filename.c_str(), md5.c_str(), filesize);
- gd = DetectedGame("zcode", "Unrecognised zcode game", Common::UNK_LANG, Common::kPlatformUnknown);
- } else {
- gd = DetectedGame(p->_gameId, p->_description, p->_language, Common::kPlatformUnknown, p->_extra);
- }
-
- gd.addExtraEntry("filename", filename);
- gameList.push_back(gd);
- }
-
- return !gameList.empty();
-}
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/detection.h b/engines/gargoyle/frotz/detection.h
deleted file mode 100644
index 2e70d7c..0000000
--- a/engines/gargoyle/frotz/detection.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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 GARGOYLE_FROTZ_DETECTION
-#define GARGOYLE_FROTZ_DETECTION
-
-#include "common/fs.h"
-#include "engines/game.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-class FrotzMetaEngine {
-public:
- /**
- * Detect supported games
- */
- static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/detection_tables.cpp b/engines/gargoyle/frotz/detection_tables.cpp
deleted file mode 100644
index af856ed..0000000
--- a/engines/gargoyle/frotz/detection_tables.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/detection_tables.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-const char *const AMFV_DESC = "A Mind Forever Voyaging";
-const char *const ARTHUR_DESC = "Arthur: The Quest for Excalibur";
-const char *const BALLYHOO_DESC = "Ballyhoo";
-const char *const BEYONDZORK_DESC = "Beyond Zork";
-const char *const BORDERZONE_DESC = "Border Zone";
-const char *const BUREAUCRACY_DESC = "Bureaucracy";
-const char *const CUTTHROATS_DESC = "Cutthroats";
-const char *const DEADLINE_DESC = "Deadline";
-const char *const ENCHANTER_DESC = "Enchanter";
-const char *const HHGTTG_DESC = "The Hitchhiker's Guide to the Galaxy";
-const char *const HIJINX_DESC = "Hollywood Hijinx";
-const char *const INFIDEL_DESC = "Infidel";
-const char *const JOURNEY_DESC = "Journey";
-const char *const LGOP_DESC = "Leather Goddesses of Phobos";
-const char *const LGOP2_DESC = "Leather Goddesses of Phobos 2";
-const char *const LURKING_DESC = "The Lurking Horror";
-const char *const MINIZORK1_DESC = "Mini Zork I: The Great Underground Empire";
-const char *const MOONMIST_DESC = "Moonmist";
-const char *const NORDBERT_DESC = "Nord and Bert Couldn't Make Head or Tail of It";
-const char *const PLANETFALL_DESC = "Planetfall";
-const char *const PLUNDERED_DESC = "Plundered Hearts";
-const char *const SAMPLER1_DESC = "Infocom Sampler 1";
-const char *const SAMPLER2_DESC = "Infocom Sampler 2";
-const char *const SEASTALKER_DESC = "Seastalker";
-const char *const SHERLOCKRIDDLE_DESC = "Sherlock: The Riddle of the Crown Jewels";
-const char *const SHOGUN_DESC = "James Clavell's Shogun";
-const char *const SORCERER_DESC = "Sorcerer";
-const char *const SPELLBREAKER_DESC = "Spellbreaker";
-const char *const STARCROSS_DESC = "Starcross";
-const char *const STATIONFALL_DESC = "Stationfall";
-const char *const SUSPECT_DESC = "Suspect";
-const char *const SUSPENDED_DESC = "Suspended";
-const char *const TRINITY_DESC = "Trinity";
-const char *const WISHBRINGER_DESC = "Wishbringer";
-const char *const WITNESS_DESC = "The Witness";
-const char *const ZORK0_DESC = "Zork Zero: The Revenge of Megaboz";
-const char *const ZORK1_DESC = "Zork I: The Great Underground Empire";
-const char *const ZORK2_DESC = "Zork II: The Wizard of Frobozz";
-const char *const ZORK3_DESC = "Zork III: The Dungeon Master";
-const char *const ZTUU_DESC = "Zork: The Undiscovered Underground";
-
-#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
-#define ENTRY0(ID, DESCRIPTION, VERSION, MD5, FILESIZE) { ID, DESCRIPTION##_DESC, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
-#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
-
-const FrotzGameDescription FROTZ_GAMES[] = {
- ENTRY0("hhgttg", HHGTTG, "v31 Solid Gold", "379022bcd4ec74b90274c6100c33f579", 158412),
- ENTRY0("hhgttg", HHGTTG, "v47", "fdda8f4239819402c62db866bb61a648", 112622),
- ENTRY0("hhgttg", HHGTTG, "v56", "a214fcb42bc9f554d07d983a12f6a062", 113444),
- ENTRY0("hhgttg", HHGTTG, "v58", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
- ENTRY0("hhgttg", HHGTTG, "v59", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
-
- FROTZ_TABLE_END_MARKER
-};
-
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/detection_tables.h b/engines/gargoyle/frotz/detection_tables.h
deleted file mode 100644
index 48e0eb0..0000000
--- a/engines/gargoyle/frotz/detection_tables.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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.
- *
- */
-
-#include "engines/advancedDetector.h"
-#include "common/language.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-/**
- * Game descriptor for ZCode games
- */
-struct FrotzGameDescription {
- const char *const _gameId;
- const char *const _description;
- const char *const _extra;
- const char *const _md5;
- size_t _filesize;
- Common::Language _language;
- const char *const _guiOptions;
-};
-
-extern const FrotzGameDescription FROTZ_GAMES[];
-extern const char *const AMFV_DESC;
-extern const char *const ARTHUR_DESC;
-extern const char *const BALLYHOO_DESC;
-extern const char *const BEYONDZORK_DESC;
-extern const char *const BORDERZONE_DESC;
-extern const char *const BUREAUCRACY_DESC;
-extern const char *const CUTTHROATS_DESC;
-extern const char *const DEADLINE_DESC;
-extern const char *const ENCHANTER_DESC;
-extern const char *const HHGTTG_DESC;
-extern const char *const HIJINX_DESC;
-extern const char *const INFIDEL_DESC;
-extern const char *const JOURNEY_DESC;
-extern const char *const LGOP_DESC;
-extern const char *const LGOP2_DESC;
-extern const char *const LURKING_DESC;
-extern const char *const MINIZORK1_DESC;
-extern const char *const MOONMIST_DESC;
-extern const char *const NORDBERT_DESC;
-extern const char *const PLANETFALL_DESC;
-extern const char *const PLUNDERED_DESC;
-extern const char *const SAMPLER1_DESC;
-extern const char *const SAMPLER2_DESC;
-extern const char *const SEASTALKER_DESC;
-extern const char *const SHERLOCKRIDDLE_DESC;
-extern const char *const SHOGUN_DESC;
-extern const char *const SORCERER_DESC;
-extern const char *const SPELLBREAKER_DESC;
-extern const char *const STARCROSS_DESC;
-extern const char *const STATIONFALL_DESC;
-extern const char *const SUSPECT_DESC;
-extern const char *const SUSPENDED_DESC;
-extern const char *const TRINITY_DESC;
-extern const char *const WISHBRINGER_DESC;
-extern const char *const WITNESS_DESC;
-extern const char *const ZORK0_DESC;
-extern const char *const ZORK1_DESC;
-extern const char *const ZORK2_DESC;
-extern const char *const ZORK3_DESC;
-extern const char *const ZTUU_DESC;
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp
deleted file mode 100644
index 3a7b913..0000000
--- a/engines/gargoyle/frotz/frotz.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/frotz.h"
-#include "gargoyle/frotz/frotz_types.h"
-#include "common/config-manager.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-Frotz *g_vm;
-
-Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- Processor(syst, gameDesc) {
- g_vm = this;
-}
-
-Frotz::~Frotz() {
- reset_memory();
-}
-
-void Frotz::runGame(Common::SeekableReadStream *gameFile) {
- story_fp = gameFile;
- initialize();
-
- // Game loop
- interpret();
-}
-
-void Frotz::initialize() {
- if (ConfMan.hasKey("attribute_assignment") && ConfMan.getBool("attribute_assignment"))
- _attribute_assignment = true;
- if (ConfMan.hasKey("attribute_testing") && ConfMan.getBool("attribute_testing"))
- _attribute_testing = true;
- if (ConfMan.hasKey("ignore_errors") && ConfMan.getBool("ignore_errors"))
- _ignore_errors = true;
- if (ConfMan.hasKey("object_movement") && ConfMan.getBool("object_movement"))
- _object_movement = true;
- if (ConfMan.hasKey("object_locating") && ConfMan.getBool("object_locating"))
- _object_locating = true;
- if (ConfMan.hasKey("piracy") && ConfMan.getBool("piracy"))
- _piracy = true;
- if (ConfMan.hasKey("save_quetzal") && ConfMan.getBool("save_quetzal"))
- _save_quetzal = true;
- if (ConfMan.hasKey("random_seed"))
- _random.setSeed(ConfMan.getInt("random_seed"));
- if (ConfMan.hasKey("script_cols"))
- _script_cols = ConfMan.getInt("script_cols");
- if (ConfMan.hasKey("tandy_bit") && ConfMan.getBool("tandy_bit"))
- _user_tandy_bit = true;
- if (ConfMan.hasKey("undo_slots"))
- _undo_slots = ConfMan.getInt("undo_slots");
- if (ConfMan.hasKey("expand_abbreviations") && ConfMan.getBool("expand_abbreviations"))
- _expand_abbreviations = true;
- if (ConfMan.hasKey("err_report_mode")) {
- _err_report_mode = ConfMan.getInt("err_report_mode");
- if ((_err_report_mode < ERR_REPORT_NEVER) || (_err_report_mode > ERR_REPORT_FATAL))
- _err_report_mode = ERR_DEFAULT_REPORT_MODE;
- }
-
- // Call process initialization
- Processor::initialize();
-
- // Restart the game
- z_restart();
-}
-
-Common::Error Frotz::loadGameState(int slot) {
- // TODO
- return Common::kNoError;
-}
-
-Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
- // TODO
- return Common::kNoError;
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/frotz.h b/engines/gargoyle/frotz/frotz.h
deleted file mode 100644
index f7211f7..0000000
--- a/engines/gargoyle/frotz/frotz.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* 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 GARGOYLE_FROTZ_FROTZ
-#define GARGOYLE_FROTZ_FROTZ
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-/**
- * Frotz interpreter for Z-code games
- */
-class Frotz : public Processor {
-public:
- /**
- * Constructor
- */
- Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc);
-
- /**
- * Destructor
- */
- virtual ~Frotz();
-
- /**
- * Initialization
- */
- void initialize();
-
- /**
- * Execute the game
- */
- virtual void runGame(Common::SeekableReadStream *gameFile) override;
-
- /**
- * Load a savegame
- */
- virtual Common::Error loadGameState(int slot) override;
-
- /**
- * Save the game
- */
- virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
-};
-
-extern Frotz *g_vm;
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/frotz_types.h b/engines/gargoyle/frotz/frotz_types.h
deleted file mode 100644
index 6b4fe67..0000000
--- a/engines/gargoyle/frotz/frotz_types.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/* 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 GARGOYLE_FROTZ_FROTZ_TYPES
-#define GARGOYLE_FROTZ_FROTZ_TYPES
-
-#include "gargoyle/glk_types.h"
-#include "common/algorithm.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-#define MAX_UNDO_SLOTS 500
-#define STACK_SIZE 32768
-
-#define lo(v) (v & 0xff)
-#define hi(v) (v >> 8)
-
-/* There are four error reporting modes: never report errors;
- * report only the first time a given error type occurs;
- * report every time an error occurs;
- * or treat all errors as fatal errors, killing the interpreter.
- * I strongly recommend "report once" as the default. But you can compile in a
- * different default by changing the definition of ERR_DEFAULT_REPORT_MODE.
- */
-enum ErrorReport {
- ERR_REPORT_NEVER = 0,
- ERR_REPORT_ONCE = 1,
- ERR_REPORT_ALWAYS = 2,
- ERR_REPORT_FATAL = 3,
-
- ERR_DEFAULT_REPORT_MODE = ERR_REPORT_NEVER
-};
-
-/**
- * Character codes
- */
-enum ZCode {
- ZC_TIME_OUT = 0x00,
- ZC_NEW_STYLE = 0x01,
- ZC_NEW_FONT = 0x02,
- ZC_BACKSPACE = 0x08,
- ZC_INDENT = 0x09,
- ZC_GAP = 0x0b,
- ZC_RETURN = 0x0d,
- ZC_HKEY_MIN = 0x0e,
- ZC_HKEY_RECORD = 0x0e,
- ZC_HKEY_PLAYBACK = 0x0f,
- ZC_HKEY_SEED = 0x10,
- ZC_HKEY_UNDO = 0x11,
- ZC_HKEY_RESTART = 0x12,
- ZC_HKEY_QUIT = 0x13,
- ZC_HKEY_DEBUG = 0x14,
- ZC_HKEY_HELP = 0x15,
- ZC_HKEY_MAX = 0x15,
- ZC_ESCAPE = 0x1b,
- ZC_ASCII_MIN = 0x20,
- ZC_ASCII_MAX = 0x7e,
- ZC_BAD = 0x7f,
- ZC_ARROW_MIN = 0x81,
- ZC_ARROW_UP = 0x81,
- ZC_ARROW_DOWN = 0x82,
- ZC_ARROW_LEFT = 0x83,
- ZC_ARROW_RIGHT = 0x84,
- ZC_ARROW_MAX = 0x84,
- ZC_FKEY_MIN = 0x85,
- ZC_FKEY_MAX = 0x90,
- ZC_NUMPAD_MIN = 0x91,
- ZC_NUMPAD_MAX = 0x9a,
- ZC_SINGLE_CLICK = 0x9b,
- ZC_DOUBLE_CLICK = 0x9c,
- ZC_MENU_CLICK = 0x9d,
- ZC_LATIN1_MIN = 0xa0,
- ZC_LATIN1_MAX = 0xff
-};
-
-enum Story {
- BEYOND_ZORK,
- SHERLOCK,
- ZORK_ZERO,
- SHOGUN,
- ARTHUR,
- JOURNEY,
- LURKING_HORROR,
- UNKNOWN
-};
-
-enum Version {
- V1 = 1,
- V2 = 2,
- V3 = 3,
- V4 = 4,
- V5 = 5,
- V6 = 6,
- V7 = 7,
- V8 = 8,
- V9 = 9
-};
-
-enum ConfigFlag {
- CONFIG_BYTE_SWAPPED = 0x01, ///< Story file is byte swapped - V3
- CONFIG_TIME = 0x02, ///< Status line displays time - V3
- CONFIG_TWODISKS = 0x04, ///< Story file occupied two disks - V3
- CONFIG_TANDY = 0x08, ///< Tandy licensed game - V3
- CONFIG_NOSTATUSLINE = 0x10, ///< Interpr can't support status lines - V3
- CONFIG_SPLITSCREEN = 0x20, ///< Interpr supports split screen mode - V3
- CONFIG_PROPORTIONAL = 0x40, ///< Interpr uses proportional font - V3
-
- CONFIG_COLOUR = 0x01, ///< Interpr supports colour - V5+
- CONFIG_PICTURES = 0x02, ///< Interpr supports pictures - V6
- CONFIG_BOLDFACE = 0x04, ///< Interpr supports boldface style - V4+
- CONFIG_EMPHASIS = 0x08, ///< Interpr supports emphasis style - V4+
- CONFIG_FIXED = 0x10, ///< Interpr supports fixed width style - V4+
- CONFIG_SOUND = 0x20, ///< Interpr supports sound - V6
- CONFIG_TIMEDINPUT = 0x80, ///< Interpr supports timed input - V4+
-
- SCRIPTING_FLAG = 0x0001, ///< Outputting to transscription file - V1+
- FIXED_FONT_FLAG = 0x0002, ///< Use fixed width font - V3+
- REFRESH_FLAG = 0x0004, ///< Refresh the screen - V6
- GRAPHICS_FLAG = 0x0008, ///< Game wants to use graphics - V5+
- OLD_SOUND_FLAG = 0x0010, ///< Game wants to use sound effects - V3
- UNDO_FLAG = 0x0010, ///< Game wants to use UNDO feature - V5+
- MOUSE_FLAG = 0x0020, ///< Game wants to use a mouse - V5+
- COLOUR_FLAG = 0x0040, ///< Game wants to use colours - V5+
- SOUND_FLAG = 0x0080, ///< Game wants to use sound effects - V5+
- MENU_FLAG = 0x0100 ///< Game wants to use menus - V6
-};
-
-enum {
- TRANSPARENT_FLAG = 0x0001 ///< Game wants to use transparency - V6
-};
-
-enum ErrorCode {
- ERR_TEXT_BUF_OVF = 1, ///< Text buffer overflow
- ERR_STORE_RANGE = 2, ///< Store out of dynamic memory
- ERR_DIV_ZERO = 3, ///< Division by zero
- ERR_ILL_OBJ = 4, ///< Illegal object
- ERR_ILL_ATTR = 5, ///< Illegal attribute
- ERR_NO_PROP = 6, ///< No such property
- ERR_STK_OVF = 7, ///< Stack overflow
- ERR_ILL_CALL_ADDR = 8, ///< Call to illegal address
- ERR_CALL_NON_RTN = 9, ///< Call to non-routine
- ERR_STK_UNDF = 10, ///< Stack underflow
- ERR_ILL_OPCODE = 11, ///< Illegal opcode
- ERR_BAD_FRAME = 12, ///< Bad stack frame
- ERR_ILL_JUMP_ADDR = 13, ///< Jump to illegal address
- ERR_SAVE_IN_INTER = 14, ///< Can't save while in interrupt
- ERR_STR3_NESTING = 15, ///< Nesting stream #3 too deep
- ERR_ILL_WIN = 16, ///< Illegal window
- ERR_ILL_WIN_PROP = 17, ///< Illegal window property
- ERR_ILL_PRINT_ADDR = 18, ///< Print at illegal address
- ERR_DICT_LEN = 19, ///< Illegal dictionary word length
- ERR_MAX_FATAL = 19,
-
- // Less serious errors
- ERR_JIN_0 = 20, ///< @jin called with object 0
- ERR_GET_CHILD_0 = 21, ///< @get_child called with object 0
- ERR_GET_PARENT_0 = 22, ///< @get_parent called with object 0
- ERR_GET_SIBLING_0 = 23, ///< @get_sibling called with object 0
- ERR_GET_PROP_ADDR_0 = 24, ///< @get_prop_addr called with object 0
- ERR_GET_PROP_0 = 25, ///< @get_prop called with object 0
- ERR_PUT_PROP_0 = 26, ///< @put_prop called with object 0
- ERR_CLEAR_ATTR_0 = 27, ///< @clear_attr called with object 0
- ERR_SET_ATTR_0 = 28, ///< @set_attr called with object 0
- ERR_TEST_ATTR_0 = 29, ///< @test_attr called with object 0
- ERR_MOVE_OBJECT_0 = 30, ///< @move_object called moving object 0
- ERR_MOVE_OBJECT_TO_0 = 31, ///< @move_object called moving into object 0
- ERR_REMOVE_OBJECT_0 = 32, ///< @remove_object called with object 0
- ERR_GET_NEXT_PROP_0 = 33, ///< @get_next_prop called with object 0
- ERR_NUM_ERRORS = 33
-};
-
-enum FrotzInterp {
- INTERP_DEFAULT = 0,
- INTERP_DEC_20 = 1,
- INTERP_APPLE_IIE = 2,
- INTERP_MACINTOSH = 3,
- INTERP_AMIGA = 4,
- INTERP_ATARI_ST = 5,
- INTERP_MSDOS = 6,
- INTERP_CBM_128 = 7,
- INTERP_CBM_64 = 8,
- INTERP_APPLE_IIC = 9,
- INTERP_APPLE_IIGS = 10,
- INTERP_TANDY = 11
-};
-
-enum Colour {
- BLACK_COLOUR = 2,
- RED_COLOUR = 3,
- GREEN_COLOUR = 4,
- YELLOW_COLOUR = 5,
- BLUE_COLOUR = 6,
- MAGENTA_COLOUR = 7,
- CYAN_COLOUR = 8,
- WHITE_COLOUR = 9,
- GREY_COLOUR = 10, ///< INTERP_MSDOS only
- LIGHTGREY_COLOUR = 10, ///< INTERP_AMIGA only
- MEDIUMGREY_COLOUR = 11, ///< INTERP_AMIGA only
- DARKGREY_COLOUR = 12, ///< INTERP_AMIGA only
- TRANSPARENT_COLOUR = 15 ///< ZSpec 1.1
-};
-
-enum Style {
- REVERSE_STYLE = 1,
- BOLDFACE_STYLE = 2,
- EMPHASIS_STYLE = 4,
- FIXED_WIDTH_STYLE = 8
-};
-
-enum FontStyle {
- TEXT_FONT = 1,
- PICTURE_FONT = 2,
- GRAPHICS_FONT = 3,
- FIXED_WIDTH_FONT = 4
-};
-
-/*** Constants for os_beep */
-
-#define BEEP_HIGH 1
-#define BEEP_LOW 2
-
-/*** Constants for os_menu */
-
-#define MENU_NEW 0
-#define MENU_ADD 1
-#define MENU_REMOVE 2
-
-typedef byte zbyte;
-typedef uint zchar;
-typedef uint16 zword;
-
-/**
- * User options
- */
-struct UserOptions {
- int _attribute_assignment;
- int _attribute_testing;
- int _context_lines;
- int _object_locating;
- int _object_movement;
- int _left_margin;
- int _right_margin;
- bool _ignore_errors;
- bool _piracy;
- int _undo_slots;
- int _expand_abbreviations;
- int _script_cols;
- bool _save_quetzal;
- int _err_report_mode;
- bool _sound;
- bool _user_tandy_bit;
-
- UserOptions() : _attribute_assignment(0), _attribute_testing(0),
- _context_lines(0), _object_locating(0), _object_movement(0),
- _left_margin(0), _right_margin(0), _ignore_errors(false), _piracy(false),
- _undo_slots(MAX_UNDO_SLOTS), _expand_abbreviations(0), _script_cols(80),
- _save_quetzal(true), _err_report_mode(ERR_DEFAULT_REPORT_MODE), _sound(true),
- _user_tandy_bit(false) {
- }
-};
-
-#define MAX_NESTING 16
-struct Redirect {
- zword _xSize;
- zword _table;
- zword _width;
- zword _total;
-
- Redirect() : _xSize(0), _table(0), _width(0), _total(0) {}
- Redirect(zword xSize, zword table, zword width = 0, zword total = 0) :
- _xSize(xSize), _table(table), _width(width), _total(total) {}
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp
deleted file mode 100644
index c376dc0..0000000
--- a/engines/gargoyle/frotz/glk_interface.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/glk_interface.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- Glk(syst, gameDesc),
- oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
- curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
- curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
- gos_lower(nullptr), gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr),
- gos_linewin(nullptr), gos_channel(nullptr), cwin(0), mwin(0), mouse_x(0), mouse_y(0),
- menu_selected(0), ostream_screen(false), ostream_script(false), ostream_memory(false),
- ostream_record(false), istream_replay(false), message(false),
- enable_wrapping(false), enable_scripting(false), enable_scrolling(false),
- enable_buffering(false), next_sample(0), next_volume(0),
- _soundLocked(false), _soundPlaying(false) {
- Common::fill(&statusline[0], &statusline[256], '\0');
-}
-
-void GlkInterface::initialize() {
- uint width, height;
-
- /*
- * Init glk stuff
- */
-
- // monor
- glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Oblique, 0);
-
- // monob
- glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Oblique, 0);
-
- // monoi
- glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Oblique, 1);
-
- // monoz
- glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Oblique, 1);
-
- // propr
- glk_stylehint_set(wintype_TextBuffer, style_Normal, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Normal, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Oblique, 0);
-
- // propb
- glk_stylehint_set(wintype_TextBuffer, style_Header, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Header, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Oblique, 0);
-
- // propi
- glk_stylehint_set(wintype_TextBuffer, style_Emphasized, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Emphasized, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Oblique, 1);
-
- // propi
- glk_stylehint_set(wintype_TextBuffer, style_Note, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Note, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Oblique, 1);
-
- gos_lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
- if (!gos_lower)
- gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
- glk_window_get_size(gos_lower, &width, &height);
- glk_window_close(gos_lower, NULL);
-
- gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
- gos_upper = glk_window_open(gos_lower,
- winmethod_Above | winmethod_Fixed,
- 0,
- wintype_TextGrid, 0);
-
- gos_channel = NULL;
-
- glk_set_window(gos_lower);
- gos_curwin = gos_lower;
-
- /*
- * Icky magic bit setting
- */
-
- if (h_version == V3 && _user_tandy_bit)
- h_config |= CONFIG_TANDY;
-
- if (h_version == V3 && gos_upper)
- h_config |= CONFIG_SPLITSCREEN;
-
- if (h_version == V3 && !gos_upper)
- h_config |= CONFIG_NOSTATUSLINE;
-
- if (h_version >= V4)
- h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS |
- CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR;
-
- if (h_version >= V5)
- h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG);
-
- if ((h_version >= 5) && (h_flags & SOUND_FLAG))
- h_flags |= SOUND_FLAG;
-
- if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG))
- h_flags |= OLD_SOUND_FLAG;
-
- if ((h_version == 6) && (_sound != 0))
- h_config |= CONFIG_SOUND;
-
- if (h_version >= V5 && (h_flags & UNDO_FLAG))
- if (_undo_slots == 0)
- h_flags &= ~UNDO_FLAG;
-
- h_screen_cols = width;
- h_screen_rows = height;
-
- h_screen_height = h_screen_rows;
- h_screen_width = h_screen_cols;
-
- h_font_width = 1;
- h_font_height = 1;
-
- /* Must be after screen dimensions are computed. */
- if (h_version == V6) {
- h_flags &= ~GRAPHICS_FLAG;
- }
-
- // Use the ms-dos interpreter number for v6, because that's the
- // kind of graphics files we understand. Otherwise, use DEC.
- h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_DEC_20;
- h_interpreter_version = 'F';
-
- {
- // Set these per spec 8.3.2.
- h_default_foreground = WHITE_COLOUR;
- h_default_background = BLACK_COLOUR;
- if (h_flags & COLOUR_FLAG)
- h_flags &= ~COLOUR_FLAG;
- }
-}
-
-int GlkInterface::os_char_width(zchar z) {
- return 1;
-}
-
-int GlkInterface::os_string_width(const zchar *s) {
- int width = 0;
- zchar c;
- while ((c = *s++) != 0)
- if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT)
- s++;
- else
- width += os_char_width(c);
- return width;
-}
-
-int GlkInterface::os_string_length(zchar *s) {
- int length = 0;
- while (*s++) length++;
- return length;
-}
-
-void GlkInterface::os_prepare_sample(int a) {
- glk_sound_load_hint(a, 1);
-}
-
-void GlkInterface::os_finish_with_sample(int a) {
- glk_sound_load_hint(a, 0);
-}
-
-void GlkInterface::os_start_sample(int number, int volume, int repeats, zword eos) {
- int vol;
-
- if (!gos_channel) {
- gos_channel = glk_schannel_create(0);
- if (!gos_channel)
- return;
- }
-
- switch (volume) {
- case 1: vol = 0x02000; break;
- case 2: vol = 0x04000; break;
- case 3: vol = 0x06000; break;
- case 4: vol = 0x08000; break;
- case 5: vol = 0x0a000; break;
- case 6: vol = 0x0c000; break;
- case 7: vol = 0x0e000; break;
- case 8: vol = 0x10000; break;
- default: vol = 0x20000; break;
- }
-
- // we dont do repeating or eos-callback for now...
- glk_schannel_play_ext(gos_channel, number, 1, 0);
- glk_schannel_set_volume(gos_channel, vol);
-}
-
-void GlkInterface::os_stop_sample(int a) {
- if (!gos_channel)
- return;
- glk_schannel_stop(gos_channel);
-}
-
-void GlkInterface::os_beep(int volume) {
-}
-
-void GlkInterface::start_sample(int number, int volume, int repeats, zword eos) {
- // TODO
-}
-
-void GlkInterface::start_next_sample() {
- // TODO
-}
-
-void GlkInterface::gos_update_width() {
- glui32 width;
- if (gos_upper) {
- glk_window_get_size(gos_upper, &width, nullptr);
- h_screen_cols = width;
- SET_BYTE(H_SCREEN_COLS, width);
- if ((uint)curx > width) {
- glk_window_move_cursor(gos_upper, 0, cury - 1);
- curx = 1;
- }
- }
-}
-
-void GlkInterface::gos_update_height() {
- glui32 height_upper;
- glui32 height_lower;
- if (gos_curwin) {
- glk_window_get_size(gos_upper, nullptr, &height_upper);
- glk_window_get_size(gos_lower, nullptr, &height_lower);
- h_screen_rows = height_upper + height_lower + 1;
- SET_BYTE(H_SCREEN_ROWS, h_screen_rows);
- }
-}
-
-void GlkInterface::reset_status_ht() {
- glui32 height;
- if (gos_upper) {
- glk_window_get_size(gos_upper, nullptr, &height);
- if ((uint)mach_status_ht != height) {
- glk_window_set_arrangement(
- glk_window_get_parent(gos_upper),
- winmethod_Above | winmethod_Fixed,
- mach_status_ht, nullptr);
- }
- }
-}
-
-void GlkInterface::erase_window(zword w) {
- if (w == 0)
- glk_window_clear(gos_lower);
- else if (gos_upper) {
-#ifdef GARGLK
- garglk_set_reversevideo_stream(
- glk_window_get_stream(gos_upper),
- true);
-#endif /* GARGLK */
-
- memset(statusline, ' ', sizeof statusline);
- glk_window_clear(gos_upper);
- reset_status_ht();
- curr_status_ht = 0;
- }
-}
-
-void GlkInterface::split_window(zword lines) {
- if (!gos_upper)
- return;
-
- // The top line is always set for V1 to V3 games
- if (h_version < V4)
- lines++;
-
- if (!lines || lines > curr_status_ht) {
- glui32 height;
-
- glk_window_get_size(gos_upper, nullptr, &height);
- if (lines != height)
- glk_window_set_arrangement(
- glk_window_get_parent(gos_upper),
- winmethod_Above | winmethod_Fixed,
- lines, nullptr);
- curr_status_ht = lines;
- }
- mach_status_ht = lines;
- if (cury > lines)
- {
- glk_window_move_cursor(gos_upper, 0, 0);
- curx = cury = 1;
- }
- gos_update_width();
-
- if (h_version == V3)
- glk_window_clear(gos_upper);
-}
-
-void GlkInterface::restart_screen() {
- erase_window(0);
- erase_window(1);
- split_window(0);
-}
-
-void GlkInterface::packspaces(zchar *src, zchar *dst) {
- int killing = 0;
- while (*src) {
- if (*src == 0x20202020)
- *src = ' ';
- if (*src == ' ')
- killing++;
- else
- killing = 0;
- if (killing > 2)
- src++;
- else
- *dst++ = *src++;
- }
-
- *dst = 0;
-}
-
-void GlkInterface::smartstatusline() {
- zchar packed[256];
- zchar buf[256];
- zchar *a, *b, *c, *d;
- int roomlen, scorelen, scoreofs;
- int len, tmp;
-
- packspaces(statusline, packed);
- len = os_string_length(packed);
-
- a = packed;
- while (a[0] == ' ')
- a++;
-
- b = a;
- while (b[0] != 0 && !(b[0] == ' ' && b[1] == ' '))
- b++;
-
- c = b;
- while (c[0] == ' ')
- c++;
-
- d = packed + len - 1;
- while (d[0] == ' ' && d > c)
- d--;
- if (d[0] != ' ' && d[0] != 0)
- d++;
- if (d < c)
- d = c;
-
- roomlen = b - a;
- scorelen = d - c;
- scoreofs = h_screen_cols - scorelen - 2;
- if (scoreofs <= roomlen)
- scoreofs = roomlen + 2;
-
- for (tmp = 0; tmp < h_screen_cols; tmp++)
- buf[tmp] = ' ';
-
- memcpy(buf + 1 + scoreofs, c, scorelen * sizeof(zchar));
- memcpy(buf + 1, a, roomlen * sizeof(zchar));
-
- glk_window_move_cursor(gos_upper, 0, 0);
- glk_put_buffer_uni(buf, h_screen_cols);
- glk_window_move_cursor(gos_upper, cury - 1, curx - 1);
-}
-
-void GlkInterface::gos_cancel_pending_line() {
- event_t ev;
- glk_cancel_line_event(gos_linewin, &ev);
- gos_linebuf[ev.val1] = '\0';
- gos_linepending = 0;
-}
-
-zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
- event_t ev;
- winid_t win = gos_curwin ? gos_curwin : gos_lower;
-
- if (gos_linepending)
- gos_cancel_pending_line();
-
- glk_request_char_event_uni(win);
- if (timeout != 0)
- glk_request_timer_events(timeout * 100);
-
- while (!shouldQuit()) {
- glk_select(&ev);
- if (ev.type == evtype_Arrange) {
- gos_update_height();
- gos_update_width();
- } else if (ev.type == evtype_Timer) {
- glk_cancel_char_event(win);
- glk_request_timer_events(0);
- return ZC_TIME_OUT;
- } else if (ev.type == evtype_CharInput)
- break;
- }
- if (shouldQuit())
- return 0;
-
- glk_request_timer_events(0);
-
- if (gos_upper && mach_status_ht < curr_status_ht)
- reset_status_ht();
- curr_status_ht = 0;
-
- switch (ev.val1) {
- case keycode_Escape: return ZC_ESCAPE;
- case keycode_PageUp: return ZC_ARROW_MIN;
- case keycode_PageDown: return ZC_ARROW_MAX;
- case keycode_Left: return ZC_ARROW_LEFT;
- case keycode_Right: return ZC_ARROW_RIGHT;
- case keycode_Up: return ZC_ARROW_UP;
- case keycode_Down: return ZC_ARROW_DOWN;
- case keycode_Return: return ZC_RETURN;
- case keycode_Delete: return ZC_BACKSPACE;
- case keycode_Tab: return ZC_INDENT;
- default:
- return ev.val1;
- }
-}
-
-zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, int continued) {
- event_t ev;
- winid_t win = gos_curwin ? gos_curwin : gos_lower;
-
- if (!continued && gos_linepending)
- gos_cancel_pending_line();
-
- if (!continued || !gos_linepending) {
- glk_request_line_event_uni(win, buf, max, os_string_length(buf));
- if (timeout != 0)
- glk_request_timer_events(timeout * 100);
- }
-
- gos_linepending = 0;
-
- while (!shouldQuit()) {
- glk_select(&ev);
- if (ev.type == evtype_Arrange) {
- gos_update_height();
- gos_update_width();
- } else if (ev.type == evtype_Timer) {
- gos_linewin = win;
- gos_linepending = 1;
- gos_linebuf = buf;
- return ZC_TIME_OUT;
- } else if (ev.type == evtype_LineInput) {
- break;
- }
- }
- if (shouldQuit())
- return 0;
-
- glk_request_timer_events(0);
- buf[ev.val1] = '\0';
-
- if (gos_upper && mach_status_ht < curr_status_ht)
- reset_status_ht();
- curr_status_ht = 0;
-
- return ZC_RETURN;
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h
deleted file mode 100644
index 5393c5d..0000000
--- a/engines/gargoyle/frotz/glk_interface.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* 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 GARGOYLE_FROTZ_GLK_INTERFACE
-#define GARGOYLE_FROTZ_GLK_INTERFACE
-
-#include "gargoyle/glk.h"
-#include "gargoyle/frotz/mem.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-enum SoundEffect {
- EFFECT_PREPARE = 1,
- EFFECT_PLAY = 2,
- EFFECT_STOP = 3,
- EFFECT_FINISH_WITH = 4
-};
-
-enum RestartAction {
- RESTART_BEGIN = 0,
- RESTART_WPROP_SET = 1,
- RESTART_END = 2
-};
-
-
-/**
- * Implements an intermediate interface on top of the GLK layer, providing screen
- * and sound effect handling
- */
-class GlkInterface : public Glk, public virtual UserOptions, public virtual Mem {
-public:
- zchar statusline[256];
- int oldstyle;
- int curstyle;
- int cury;
- int curx;
- int fixforced;
-
- int curr_fg;
- int curr_bg;
- int curr_font;
- int prev_font;
- int temp_font;
-
- int curr_status_ht;
- int mach_status_ht;
-
- winid_t gos_status;
- winid_t gos_upper;
- winid_t gos_lower;
- winid_t gos_curwin;
- int gos_linepending;
- zchar *gos_linebuf;
- winid_t gos_linewin;
- schanid_t gos_channel;
-
- // Current window and mouse data
- int cwin;
- int mwin;
- int mouse_y;
- int mouse_x;
- int menu_selected;
-
- // IO streams
- bool ostream_screen;
- bool ostream_script;
- bool ostream_memory;
- bool ostream_record;
- bool istream_replay;
- bool message;
-
- // Window attributes
- bool enable_wrapping;
- bool enable_scripting;
- bool enable_scrolling;
- bool enable_buffering;
-
- // Sound fields
- int next_sample;
- int next_volume;
-
- bool _soundLocked;
- bool _soundPlaying;
-protected:
- int os_char_width(zchar z);
- int os_string_width(const zchar *s);
- int os_string_length(zchar *s);
- void os_prepare_sample(int a);
- void os_finish_with_sample(int a);
-
- /**
- * Play the given sample at the given volume (ranging from 1 to 8 and
- * 255 meaning a default volume). The sound is played once or several
- * times in the background (255 meaning forever). In Z-code 3 the
- * repeats value is always 0 and the number of repeats is taken from
- * the sound file itself. The end_of_sound function is called as soon
- * as the sound finishes.
- */
- void os_start_sample(int number, int volume, int repeats, zword eos);
-
- void os_stop_sample(int a);
- void os_beep(int volume);
-
- /**
- * Call the IO interface to play a sample.
- */
- void start_sample(int number, int volume, int repeats, zword eos);
-
- void start_next_sample();
- void gos_update_width();
- void gos_update_height();
- void reset_status_ht();
- void erase_window(zword w);
- void split_window(zword lines);
- void restart_screen();
-
- /**
- * statusline overflowed the window size ... bad game!
- * so ... split status text into regions, reformat and print anew.
- */
- void packspaces(zchar *src, zchar *dst);
-
- void smartstatusline();
-
- /**
- * Cancels any pending line
- */
- void gos_cancel_pending_line();
-
- /**
- * Called during game restarts
- */
- void os_restart_game(RestartAction) {}
-
- /**
- * Reads the mouse buttons
- */
- zword os_read_mouse() {
- // Not implemented
- return 0;
- }
-
- void os_scrollback_char(zchar z) {
- // Not implemented
- }
-
- void os_scrollback_erase(int amount) {
- // Not implemented
- }
-
- /**
- * Waits for a keypress
- */
- zchar os_read_key(int timeout, bool show_cursor);
-
- /**
- * Waits for the user to type an input line
- */
- zchar os_read_line(int max, zchar *buf, int timeout, int width, int continued);
-public:
- /**
- * Constructor
- */
- GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc);
-
- /**
- * Initialization
- */
- void initialize();
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp
deleted file mode 100644
index e327fba..0000000
--- a/engines/gargoyle/frotz/mem.cpp
+++ /dev/null
@@ -1,419 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/mem.h"
-#include "gargoyle/frotz/frotz.h"
-#include "common/memstream.h"
-#include "common/textconsole.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-const Header::StoryEntry Header::RECORDS[25] = {
- { SHERLOCK, 21, "871214" },
- { SHERLOCK, 26, "880127" },
- { BEYOND_ZORK, 47, "870915" },
- { BEYOND_ZORK, 49, "870917" },
- { BEYOND_ZORK, 51, "870923" },
- { BEYOND_ZORK, 57, "871221" },
- { ZORK_ZERO, 296, "881019" },
- { ZORK_ZERO, 366, "890323" },
- { ZORK_ZERO, 383, "890602" },
- { ZORK_ZERO, 393, "890714" },
- { SHOGUN, 292, "890314" },
- { SHOGUN, 295, "890321" },
- { SHOGUN, 311, "890510" },
- { SHOGUN, 322, "890706" },
- { ARTHUR, 54, "890606" },
- { ARTHUR, 63, "890622" },
- { ARTHUR, 74, "890714" },
- { JOURNEY, 26, "890316" },
- { JOURNEY, 30, "890322" },
- { JOURNEY, 77, "890616" },
- { JOURNEY, 83, "890706" },
- { LURKING_HORROR, 203, "870506" },
- { LURKING_HORROR, 219, "870912" },
- { LURKING_HORROR, 221, "870918" },
- { UNKNOWN, 0, "------" }
-};
-
-void Header::loadHeader(Common::SeekableReadStream &f) {
- h_version = f.readByte();
- h_config = f.readByte();
-
- if (h_version < V1 || h_version > V8)
- error("Unknown Z-code version");
-
- if (h_version == V6)
- error("Cannot play Z-code version 6");
-
- if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
- error("Byte swapped story file");
-
- h_release = f.readUint16BE();
- h_resident_size = f.readUint16BE();
- h_start_pc = f.readUint16BE();
- h_dictionary = f.readUint16BE();
- h_objects = f.readUint16BE();
- h_globals = f.readUint16BE();
- h_dynamic_size = f.readUint16BE();
- h_flags = f.readUint16BE();
- f.read(h_serial, 6);
-
- /* Auto-detect buggy story files that need special fixes */
- _storyId = UNKNOWN;
-
- for (int i = 0; RECORDS[i]._storyId != UNKNOWN; ++i) {
- if (h_release == RECORDS[i]._release) {
- if (!strncmp((const char *)h_serial, RECORDS[i]._serial, 6)) {
- _storyId = RECORDS[i]._storyId;
- break;
- }
- }
- }
-
- h_abbreviations = f.readUint16BE();
- h_file_size = f.readUint16BE();
- h_checksum = f.readUint16BE();
-
- f.seek(H_FUNCTIONS_OFFSET);
- h_functions_offset = f.readUint16BE();
- h_strings_offset = f.readUint16BE();
- f.seek(H_TERMINATING_KEYS);
- h_terminating_keys = f.readUint16BE();
- f.seek(H_ALPHABET);
- h_alphabet = f.readUint16BE();
- h_extension_table = f.readUint16BE();
-
-
- // Zork Zero Macintosh doesn't have the graphics flag set
- if (_storyId == ZORK_ZERO && h_release == 296)
- h_flags |= GRAPHICS_FLAG;
-}
-
-/*--------------------------------------------------------------------------*/
-
-Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0),
- first_undo(nullptr), last_undo(nullptr), curr_undo(nullptr),
- undo_mem(nullptr), prev_zmp(nullptr), undo_diff(nullptr),
- undo_count(0), reserve_mem(0) {
-}
-
-void Mem::initialize() {
- initializeStoryFile();
- initializeUndo();
- loadGameHeader();
-
- // Allocate memory for story data
- if ((zmp = (zbyte *)realloc(zmp, story_size)) == nullptr)
- error("Out of memory");
-
- // Load story file in chunks of 32KB
- uint n = 0x8000;
- for (uint size = 64; size < story_size; size += n) {
- if (story_size - size < 0x8000)
- n = story_size - size;
-
- if (story_fp->read(zmp + size, n) != n)
- error("Story file read error");
- }
-
- // Read header extension table
- hx_table_size = get_header_extension(HX_TABLE_SIZE);
- hx_unicode_table = get_header_extension(HX_UNICODE_TABLE);
- hx_flags = get_header_extension(HX_FLAGS);
-}
-
-void Mem::initializeStoryFile() {
- Common::SeekableReadStream *f = story_fp;
- giblorb_map_t *map;
- giblorb_result_t res;
- uint32 magic;
-
- magic = f->readUint32BE();
-
- if (magic == MKTAG('F', 'O', 'R', 'M')) {
- if (g_vm->giblorb_set_resource_map(f))
- error("This Blorb file seems to be invalid.");
-
- map = g_vm->giblorb_get_resource_map();
-
- if (g_vm->giblorb_load_resource(map, giblorb_method_FilePos, &res, giblorb_ID_Exec, 0))
- error("This Blorb file does not contain an executable chunk.");
- if (res.chunktype != MKTAG('Z', 'C', 'O', 'D'))
- error("This Blorb file contains an executable chunk, but it is not a Z-code file.");
-
- blorb_ofs = res.data.startpos;
- blorb_len = res.length;
- } else {
- blorb_ofs = 0;
- blorb_len = f->size();
- }
-
- if (blorb_len < 64)
- error("This file is too small to be a Z-code file.");
-}
-
-void Mem::initializeUndo() {
- void *reserved = nullptr;
-
- if (reserve_mem != 0) {
- if ((reserved = malloc(reserve_mem)) == NULL)
- return;
- }
-
- // Allocate h_dynamic_size bytes for previous dynamic zmp state
- // + 1.5 h_dynamic_size for Quetzal diff + 2.
- undo_mem = new zbyte[(h_dynamic_size * 5) / 2 + 2];
- if (undo_mem != nullptr) {
- prev_zmp = undo_mem;
- undo_diff = undo_mem + h_dynamic_size;
- memcpy(prev_zmp, zmp, h_dynamic_size);
- } else {
- _undo_slots = 0;
- }
-
- if (reserve_mem != 0)
- delete reserved;
-}
-
-void Mem::loadGameHeader() {
- // Load header
- zmp = new byte[64];
- story_fp->seek(blorb_ofs);
- story_fp->read(zmp, 64);
-
- Common::MemoryReadStream h(zmp, 64);
- loadHeader(h);
-
- // Calculate story file size in bytes
- if (h_file_size != 0) {
- story_size = (long)2 * h_file_size;
-
- if (h_version >= V4)
- story_size *= 2;
- if (h_version >= V6)
- story_size *= 2;
- } else {
- // Some old games lack the file size entry
- story_size = blorb_len;
- }
-}
-
-zword Mem::get_header_extension(int entry) {
- zword addr;
- zword val;
-
- if (h_extension_table == 0 || entry > hx_table_size)
- return 0;
-
- addr = h_extension_table + 2 * entry;
- LOW_WORD(addr, val);
-
- return val;
-}
-
-void Mem::set_header_extension(int entry, zword val) {
- zword addr;
-
- if (h_extension_table == 0 || entry > hx_table_size)
- return;
-
- addr = h_extension_table + 2 * entry;
- SET_WORD(addr, val);
-}
-
-void Mem::restart_header(void) {
- zword screen_x_size;
- zword screen_y_size;
- zbyte font_x_size;
- zbyte font_y_size;
-
- int i;
-
- SET_BYTE(H_CONFIG, h_config);
- SET_WORD(H_FLAGS, h_flags);
-
- if (h_version >= V4) {
- SET_BYTE(H_INTERPRETER_NUMBER, h_interpreter_number);
- SET_BYTE(H_INTERPRETER_VERSION, h_interpreter_version);
- SET_BYTE(H_SCREEN_ROWS, h_screen_rows);
- SET_BYTE(H_SCREEN_COLS, h_screen_cols);
- }
-
- /* It's less trouble to use font size 1x1 for V5 games, especially
- because of a bug in the unreleased German version of "Zork 1" */
-
- if (h_version != V6) {
- screen_x_size = (zword)h_screen_cols;
- screen_y_size = (zword)h_screen_rows;
- font_x_size = 1;
- font_y_size = 1;
- } else {
- screen_x_size = h_screen_width;
- screen_y_size = h_screen_height;
- font_x_size = h_font_width;
- font_y_size = h_font_height;
- }
-
- if (h_version >= V5) {
- SET_WORD(H_SCREEN_WIDTH, screen_x_size);
- SET_WORD(H_SCREEN_HEIGHT, screen_y_size);
- SET_BYTE(H_FONT_HEIGHT, font_y_size);
- SET_BYTE(H_FONT_WIDTH, font_x_size);
- SET_BYTE(H_DEFAULT_BACKGROUND, h_default_background);
- SET_BYTE(H_DEFAULT_FOREGROUND, h_default_foreground);
- }
-
- if (h_version == V6)
- for (i = 0; i < 8; i++)
- storeb((zword)(H_USER_NAME + i), h_user_name[i]);
-
- SET_BYTE(H_STANDARD_HIGH, h_standard_high);
- SET_BYTE(H_STANDARD_LOW, h_standard_low);
-
- set_header_extension(HX_FLAGS, hx_flags);
- set_header_extension(HX_FORE_COLOUR, hx_fore_colour);
- set_header_extension(HX_BACK_COLOUR, hx_back_colour);
-}
-
-void Mem::storeb(zword addr, zbyte value) {
- if (addr >= h_dynamic_size)
- runtimeError(ERR_STORE_RANGE);
-
- if (addr == H_FLAGS + 1) {
- // flags register is modified
-
- h_flags &= ~(SCRIPTING_FLAG | FIXED_FONT_FLAG);
- h_flags |= value & (SCRIPTING_FLAG | FIXED_FONT_FLAG);
-
- flagsChanged(value);
- }
-
- SET_BYTE(addr, value);
-}
-
-void Mem::storew(zword addr, zword value) {
- storeb((zword)(addr + 0), hi(value));
- storeb((zword)(addr + 1), lo(value));
-}
-
-void Mem::free_undo(int count) {
- undo_t *p;
-
- if (count > undo_count)
- count = undo_count;
- while (count--) {
- p = first_undo;
- if (curr_undo == first_undo)
- curr_undo = curr_undo->next;
- first_undo = first_undo->next;
- free(p);
- undo_count--;
- }
- if (first_undo)
- first_undo->prev = NULL;
- else
- last_undo = NULL;
-}
-
-void Mem::reset_memory() {
- story_fp = nullptr;
- blorb_ofs = 0;
- blorb_len = 0;
-
- if (undo_mem) {
- free_undo(undo_count);
- delete undo_mem;
- }
-
- undo_mem = nullptr;
- undo_count = 0;
- delete[] zmp;
- zmp = nullptr;
-}
-
-long Mem::mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff) {
- unsigned size = mem_size;
- zbyte *p = diff;
- unsigned j;
- zbyte c = 0;
-
- for (;;) {
- for (j = 0; size > 0 && (c = *a++ ^ *b++) == 0; j++)
- size--;
- if (size == 0) break;
- size--;
- if (j > 0x8000) {
- *p++ = 0;
- *p++ = 0xff;
- *p++ = 0xff;
- j -= 0x8000;
- }
- if (j > 0) {
- *p++ = 0;
- j--;
- if (j <= 0x7f) {
- *p++ = j;
- } else {
- *p++ = (j & 0x7f) | 0x80;
- *p++ = (j & 0x7f80) >> 7;
- }
- }
-
- *p++ = c;
- *(b - 1) ^= c;
- }
-
- return p - diff;
-}
-
-void Mem::mem_undiff(zbyte *diff, long diff_length, zbyte *dest) {
- zbyte c;
-
- while (diff_length) {
- c = *diff++;
- diff_length--;
- if (c == 0) {
- unsigned runlen;
-
- if (!diff_length)
- return; // Incomplete run
- runlen = *diff++;
- diff_length--;
- if (runlen & 0x80) {
- if (!diff_length)
- return; // Incomplete extended run
- c = *diff++;
- diff_length--;
- runlen = (runlen & 0x7f) | (((unsigned)c) << 7);
- }
-
- dest += runlen + 1;
- } else {
- *dest++ ^= c;
- }
- }
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h
deleted file mode 100644
index a2e0e34..0000000
--- a/engines/gargoyle/frotz/mem.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/* 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 GARGOYLE_FROTZ_MEM
-#define GARGOYLE_FROTZ_MEM
-
-#include "gargoyle/frotz/frotz_types.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-#define SET_WORD(addr,v) zmp[addr] = hi(v); zmp[addr+1] = lo(v)
-#define LOW_WORD(addr,v) v = READ_BE_UINT16(&zmp[addr])
-#define HIGH_WORD(addr,v) v = READ_BE_UINT16(&zmp[addr])
-#define HIGH_LONG(addr,v) v = READ_BE_UINT32(&zmp[addr])
-#define SET_BYTE(addr,v) zmp[addr] = v
-#define LOW_BYTE(addr,v) v = zmp[addr]
-
-enum HeaderByte {
- H_VERSION = 0,
- H_CONFIG = 1,
- H_RELEASE = 2,
- H_RESIDENT_SIZE = 4,
- H_START_PC = 6,
- H_DICTIONARY = 8,
- H_OBJECTS = 10,
- H_GLOBALS = 12,
- H_DYNAMIC_SIZE = 14,
- H_FLAGS = 16,
- H_SERIAL = 18,
- H_ABBREVIATIONS = 24,
- H_FILE_SIZE = 26,
- H_CHECKSUM = 28,
- H_INTERPRETER_NUMBER = 30,
- H_INTERPRETER_VERSION = 31,
- H_SCREEN_ROWS = 32,
- H_SCREEN_COLS = 33,
- H_SCREEN_WIDTH = 34,
- H_SCREEN_HEIGHT = 36,
- H_FONT_HEIGHT = 38, ///< this is the font width in V5
- H_FONT_WIDTH = 39, ///< this is the font height in V5
- H_FUNCTIONS_OFFSET = 40,
- H_STRINGS_OFFSET = 42,
- H_DEFAULT_BACKGROUND = 44,
- H_DEFAULT_FOREGROUND = 45,
- H_TERMINATING_KEYS = 46,
- H_LINE_WIDTH = 48,
- H_STANDARD_HIGH = 50,
- H_STANDARD_LOW = 51,
- H_ALPHABET = 52,
- H_EXTENSION_TABLE = 54,
- H_USER_NAME = 56
-};
-
-enum {
- HX_TABLE_SIZE = 0,
- HX_MOUSE_X = 1,
- HX_MOUSE_Y = 2,
- HX_UNICODE_TABLE = 3,
- HX_FLAGS = 4,
- HX_FORE_COLOUR = 5,
- HX_BACK_COLOUR = 6
-};
-
-/**
- * Stores undo information
- */
-struct undo_struct {
- undo_struct *next;
- undo_struct *prev;
- long pc;
- long diff_size;
- zword frame_count;
- zword stack_size;
- zword frame_offset;
- // undo diff and stack data follow
-};
-typedef undo_struct undo_t;
-
-/**
- * Story file header data
- */
-struct Header {
-private:
- struct StoryEntry {
- Story _storyId;
- zword _release;
- char _serial[7];
- };
- static const StoryEntry RECORDS[25];
-public:
- zbyte h_version;
- zbyte h_config;
- zword h_release;
- zword h_resident_size;
- zword h_start_pc;
- zword h_dictionary;
- zword h_objects;
- zword h_globals;
- zword h_dynamic_size;
- zword h_flags;
- zbyte h_serial[6];
- zword h_abbreviations;
- zword h_file_size;
- zword h_checksum;
- zbyte h_interpreter_number;
- zbyte h_interpreter_version;
- zbyte h_screen_rows;
- zbyte h_screen_cols;
- zword h_screen_width;
- zword h_screen_height;
- zbyte h_font_height = 1;
- zbyte h_font_width = 1;
- zword h_functions_offset;
- zword h_strings_offset;
- zbyte h_default_background;
- zbyte h_default_foreground;
- zword h_terminating_keys;
- zword h_line_width;
- zbyte h_standard_high;
- zbyte h_standard_low;
- zword h_alphabet;
- zword h_extension_table;
- zbyte h_user_name[8];
-
- zword hx_table_size;
- zword hx_mouse_x;
- zword hx_mouse_y;
- zword hx_unicode_table;
- zword hx_flags;
- zword hx_fore_colour;
- zword hx_back_colour;
-
- Story _storyId;
-
- /**
- * Constructor
- */
- Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
- h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
- h_abbreviations(0), h_file_size(0), h_checksum(0), h_interpreter_number(0),
- h_interpreter_version(0), h_screen_rows(0), h_screen_cols(0), h_screen_width(0),
- h_screen_height(0), h_font_height(1), h_font_width(1), h_functions_offset(0),
- h_strings_offset(0), h_default_background(0), h_default_foreground(0),
- h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
- h_alphabet(0), h_extension_table(0),
- hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
- hx_flags(0), hx_fore_colour(0), hx_back_colour(0), _storyId(UNKNOWN) {
- Common::fill(&h_serial[0], &h_serial[6], '\0');
- Common::fill(&h_user_name[0], &h_user_name[8], '\0');
- }
-
- /**
- * Load the header
- */
- void loadHeader(Common::SeekableReadStream &f);
-};
-
-class Mem : public Header, public virtual UserOptions {
-protected:
- Common::SeekableReadStream *story_fp;
- uint blorb_ofs, blorb_len;
- uint story_size;
- byte *pcp;
- byte *zmp;
-
- undo_t *first_undo, *last_undo, *curr_undo;
- zbyte *undo_mem, *prev_zmp, *undo_diff;
- int undo_count;
- int reserve_mem;
-private:
- /**
- * Handles setting the story file, parsing it if it's a Blorb file
- */
- void initializeStoryFile();
-
- /**
- * Setup undo data
- */
- void initializeUndo();
-
- /**
- * Handles loading the game header
- */
- void loadGameHeader();
-protected:
- /**
- * Read a value from the header extension (former mouse table).
- */
- zword get_header_extension(int entry);
-
- /**
- * Set an entry in the header extension (former mouse table).
- */
- void set_header_extension(int entry, zword val);
-
- /**
- * Set all header fields which hold information about the interpreter.
- */
- void restart_header();
-
- /**
- * Write a byte value to the dynamic Z-machine memory.
- */
- void storeb(zword addr, zbyte value);
-
- /**
- * Write a word value to the dynamic Z-machine memory.
- */
- void storew(zword addr, zword value);
-
- /**
- * Free count undo blocks from the beginning of the undo list
- */
- void free_undo(int count);
-
- /**
- * Generates a runtime error
- */
- virtual void runtimeError(ErrorCode errNum) = 0;
-
- /**
- * Called when the flags are changed
- */
- virtual void flagsChanged(zbyte value) = 0;
-
- /**
- * Close the story file and deallocate memory.
- */
- void reset_memory();
-
- /**
- * Set diff to a Quetzal-like difference between a and b,
- * copying a to b as we go. It is assumed that diff points to a
- * buffer which is large enough to hold the diff.
- * mem_size is the number of bytes to compare.
- * Returns the number of bytes copied to diff.
- *
- */
- long mem_diff(zbyte *a, zbyte *b, zword mem_size, zbyte *diff);
-
- /**
- * Applies a quetzal-like diff to dest
- */
- void mem_undiff(zbyte *diff, long diff_length, zbyte *dest);
-public:
- /**
- * Constructor
- */
- Mem();
-
- /**
- * Initialize
- */
- void initialize();
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp
deleted file mode 100644
index 3336aae..0000000
--- a/engines/gargoyle/frotz/processor.cpp
+++ /dev/null
@@ -1,664 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-#include "gargoyle/frotz/frotz.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-// TODO: Stubs to replace with actual code
-zword save_undo() { return 0; }
-zword restore_undo() { return 0; }
-
-
-Opcode Processor::var_opcodes[64] = {
- &Processor::__illegal__,
- &Processor::z_je,
- &Processor::z_jl,
- &Processor::z_jg,
- &Processor::z_dec_chk,
- &Processor::z_inc_chk,
- &Processor::z_jin,
- &Processor::z_test,
- &Processor::z_or,
- &Processor::z_and,
- &Processor::z_test_attr,
- &Processor::z_set_attr,
- &Processor::z_clear_attr,
- &Processor::z_store,
- &Processor::z_insert_obj,
- &Processor::z_loadw,
- &Processor::z_loadb,
- &Processor::z_get_prop,
- &Processor::z_get_prop_addr,
- &Processor::z_get_next_prop,
- &Processor::z_add,
- &Processor::z_sub,
- &Processor::z_mul,
- &Processor::z_div,
- &Processor::z_mod,
- &Processor::z_call_s,
- &Processor::z_call_n,
- &Processor::z_set_colour,
- &Processor::z_throw,
- &Processor::__illegal__,
- &Processor::__illegal__,
- &Processor::__illegal__,
- &Processor::z_call_s,
- &Processor::z_storew,
- &Processor::z_storeb,
- &Processor::z_put_prop,
- &Processor::z_read,
- &Processor::z_print_char,
- &Processor::z_print_num,
- &Processor::z_random,
- &Processor::z_push,
- &Processor::z_pull,
- &Processor::z_split_window,
- &Processor::z_set_window,
- &Processor::z_call_s,
- &Processor::z_erase_window,
- &Processor::z_erase_line,
- &Processor::z_set_cursor,
- &Processor::z_get_cursor,
- &Processor::z_set_text_style,
- &Processor::z_buffer_mode,
- &Processor::z_output_stream,
- &Processor::z_input_stream,
- &Processor::z_sound_effect,
- &Processor::z_read_char,
- &Processor::z_scan_table,
- &Processor::z_not,
- &Processor::z_call_n,
- &Processor::z_call_n,
- &Processor::z_tokenise,
- &Processor::z_encode_text,
- &Processor::z_copy_table,
- &Processor::z_print_table,
- &Processor::z_check_arg_count
-};
-
-Opcode Processor::ext_opcodes[64] = {
- &Processor::z_save,
- &Processor::z_restore,
- &Processor::z_log_shift,
- &Processor::z_art_shift,
- &Processor::z_set_font,
- &Processor::__illegal__, // glkify - Processor::z_draw_picture,
- &Processor::__illegal__, // glkify - Processor::z_picture_data,
- &Processor::__illegal__, // glkify - Processor::z_erase_picture,
- &Processor::__illegal__, // glkify - Processor::z_set_margins,
- &Processor::z_save_undo,
- &Processor::z_restore_undo,
- &Processor::z_print_unicode,
- &Processor::z_check_unicode,
- &Processor::z_set_true_colour, // spec 1.1
- &Processor::__illegal__,
- &Processor::__illegal__,
- &Processor::__illegal__, // glkify - Processor::z_move_window,
- &Processor::__illegal__, // glkify - Processor::z_window_size,
- &Processor::__illegal__, // glkify - Processor::z_window_style,
- &Processor::__illegal__, // glkify - Processor::z_get_wind_prop,
- &Processor::__illegal__, // glkify - Processor::z_scroll_window,
- &Processor::z_pop_stack,
- &Processor::__illegal__, // glkify - Processor::z_read_mouse,
- &Processor::__illegal__, // glkify - Processor::z_mouse_window,
- &Processor::z_push_stack,
- &Processor::__illegal__, // glkify - Processor::z_put_wind_prop,
- &Processor::z_print_form,
- &Processor::z_make_menu,
- &Processor::__illegal__, // glkify - Processor::z_picture_table
- &Processor::z_buffer_screen, // spec 1.1
-};
-
-Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GlkInterface(syst, gameDesc),
- _finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
- zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
- _randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false),
- _bufPos(0), _locked(false), _prevC('\0'), script_width(0),
- sfp(nullptr), rfp(nullptr), pfp(nullptr) {
- static const Opcode OP0_OPCODES[16] = {
- &Processor::z_rtrue,
- &Processor::z_rfalse,
- &Processor::z_print,
- &Processor::z_print_ret,
- &Processor::z_nop,
- &Processor::z_save,
- &Processor::z_restore,
- &Processor::z_restart,
- &Processor::z_ret_popped,
- &Processor::z_catch,
- &Processor::z_quit,
- &Processor::z_new_line,
- &Processor::z_show_status,
- &Processor::z_verify,
- &Processor::__extended__,
- &Processor::z_piracy
- };
- static const Opcode OP1_OPCODES[16] = {
- &Processor::z_jz,
- &Processor::z_get_sibling,
- &Processor::z_get_child,
- &Processor::z_get_parent,
- &Processor::z_get_prop_len,
- &Processor::z_inc,
- &Processor::z_dec,
- &Processor::z_print_addr,
- &Processor::z_call_s,
- &Processor::z_remove_obj,
- &Processor::z_print_obj,
- &Processor::z_ret,
- &Processor::z_jump,
- &Processor::z_print_paddr,
- &Processor::z_load,
- &Processor::z_call_n
- };
-
- Common::copy(&OP0_OPCODES[0], &OP0_OPCODES[16], op0_opcodes);
- Common::copy(&OP1_OPCODES[0], &OP1_OPCODES[16], op1_opcodes);
- Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
- Common::fill(&zargs[0], &zargs[8], 0);
- Common::fill(&_buffer[0], &_buffer[TEXT_BUFFER_SIZE], '\0');
- Common::fill(&_errorCount[0], &_errorCount[ERR_NUM_ERRORS], 0);
-}
-
-void Processor::initialize() {
- Mem::initialize();
- GlkInterface::initialize();
-
- if (h_version <= V4) {
- op0_opcodes[9] = &Processor::z_pop;
- op1_opcodes[15] = &Processor::z_not;
- } else {
- op0_opcodes[9] = &Processor::z_catch;
- op1_opcodes[15] = &Processor::z_call_n;
- }
-}
-
-void Processor::load_operand(zbyte type) {
- zword value;
-
- if (type & 2) {
- // variable
- zbyte variable;
-
- CODE_BYTE(variable);
-
- if (variable == 0)
- value = *_sp++;
- else if (variable < 16)
- value = *(_fp - variable);
- else {
- zword addr = h_globals + 2 * (variable - 16);
- LOW_WORD(addr, value);
- }
- } else if (type & 1) {
- // small constant
- zbyte bvalue;
-
- CODE_BYTE(bvalue);
- value = bvalue;
-
- } else {
- // large constant
- CODE_WORD(value);
- }
-
- zargs[zargc++] = value;
-}
-
-void Processor::load_all_operands(zbyte specifier) {
- for (int i = 6; i >= 0; i -= 2) {
- zbyte type = (specifier >> i) & 0x03;
-
- if (type == 3)
- break;
-
- load_operand(type);
- }
-}
-
-void Processor::interpret() {
- do {
- zbyte opcode;
- CODE_BYTE(opcode);
- zargc = 0;
-
- if (opcode < 0x80) {
- // 2OP opcodes
- load_operand((zbyte)(opcode & 0x40) ? 2 : 1);
- load_operand((zbyte)(opcode & 0x20) ? 2 : 1);
-
- (*this.*var_opcodes[opcode & 0x1f])();
-
- } else if (opcode < 0xb0) {
- // 1OP opcodes
- load_operand((zbyte)(opcode >> 4));
-
- (*this.*op1_opcodes[opcode & 0x0f])();
-
- } else if (opcode < 0xc0) {
- // 0OP opcodes
- (*this.*op0_opcodes[opcode - 0xb0])();
-
- } else {
- // VAR opcodes
- zbyte specifier1;
- zbyte specifier2;
-
- if (opcode == 0xec || opcode == 0xfa) { // opcodes 0xec
- CODE_BYTE(specifier1); // and 0xfa are
- CODE_BYTE(specifier2); // call opcodes
- load_all_operands(specifier1); // with up to 8
- load_all_operands(specifier2); // arguments
- } else {
- CODE_BYTE(specifier1);
- load_all_operands(specifier1);
- }
-
- (*this.*var_opcodes[opcode - 0xc0])();
- }
-
-#if defined(DJGPP) && defined(SOUND_SUPPORT)
- if (end_of_sound_flag)
- end_of_sound();
-#endif
- } while (!_finished);
-
- _finished--;
-}
-
-void Processor::call(zword routine, int argc, zword *args, int ct) {
- long pc;
- zword value;
- zbyte count;
- int i;
-
- if (_sp - _stack < 4)
- runtimeError(ERR_STK_OVF);
-
- GET_PC(pc);
-
- *--_sp = (zword)(pc >> 9);
- *--_sp = (zword)(pc & 0x1ff);
- *--_sp = (zword)(_fp - _stack - 1);
- *--_sp = (zword)(argc | (ct << (_save_quetzal ? 12 : 8)));
-
- _fp = _sp;
- _frameCount++;
-
- // Calculate byte address of routine
- if (h_version <= V3)
- pc = (long)routine << 1;
- else if (h_version <= V5)
- pc = (long)routine << 2;
- else if (h_version <= V7)
- pc = ((long)routine << 2) + ((long)h_functions_offset << 3);
- else if (h_version <= V8)
- pc = (long)routine << 3;
- else {
- // h_version == V9
- long indirect = (long)routine << 2;
- HIGH_LONG(indirect, pc);
- }
-
- if ((uint)pc >= story_size)
- runtimeError(ERR_ILL_CALL_ADDR);
-
- SET_PC(pc);
-
- // Initialise local variables
- CODE_BYTE(count);
-
- if (count > 15)
- runtimeError(ERR_CALL_NON_RTN);
- if (_sp - _stack < count)
- runtimeError(ERR_STK_OVF);
-
- if (_save_quetzal)
- _fp[0] |= (zword)count << 8; // Save local var count for Quetzal.
-
- value = 0;
-
- for (i = 0; i < count; i++) {
- if (h_version <= V4) // V1 to V4 games provide default
- CODE_WORD(value); // values for all local variables
-
- *--_sp = (zword)((argc-- > 0) ? args[i] : value);
- }
-
- // Start main loop for direct calls
- if (ct == 2)
- interpret();
-}
-
-void Processor::ret(zword value) {
- long pc;
- int ct;
-
- if (_sp > _fp)
- runtimeError(ERR_STK_UNDF);
-
- _sp = _fp;
-
- ct = *_sp++ >> (_save_quetzal ? 12 : 8);
- _frameCount--;
- _fp = _stack + 1 + *_sp++;
- pc = *_sp++;
- pc = ((long)*_sp++ << 9) | pc;
-
- SET_PC(pc);
-
- // Handle resulting value
- if (ct == 0)
- store(value);
- if (ct == 2)
- *--_sp = value;
-
- // Stop main loop for direct calls
- if (ct == 2)
- _finished++;
-}
-
-void Processor::branch(bool flag) {
- long pc;
- zword offset;
- zbyte specifier;
- zbyte off1;
- zbyte off2;
-
- CODE_BYTE(specifier);
- off1 = specifier & 0x3f;
-
- if (!flag)
- specifier ^= 0x80;
-
- if (!(specifier & 0x40)) {
- // it's a long branch
- if (off1 & 0x20) // propagate sign bit
- off1 |= 0xc0;
-
- CODE_BYTE(off2);
- offset = (off1 << 8) | off2;
- } else {
- // It's a short branch
- offset = off1;
- }
-
- if (specifier & 0x80) {
- if (offset > 1) {
- // normal branch
- GET_PC(pc);
- pc += (short)offset - 2;
- SET_PC(pc);
- } else {
- // special case, return 0 or 1
- ret(offset);
- }
- }
-}
-
-void Processor::store(zword value) {
- zbyte variable;
-
- CODE_BYTE(variable);
-
- if (variable == 0)
- *--_sp = value;
- else if (variable < 16)
- *(_fp - variable) = value;
- else {
- zword addr = h_globals + 2 * (variable - 16);
- SET_WORD(addr, value);
- }
-}
-
-int Processor::direct_call(zword addr) {
- zword saved_zargs[8];
- int saved_zargc;
- int i;
-
- // Calls to address 0 return false
- if (addr == 0)
- return 0;
-
- // Save operands and operand count
- for (i = 0; i < 8; i++)
- saved_zargs[i] = zargs[i];
-
- saved_zargc = zargc;
-
- // Call routine directly
- call(addr, 0, 0, 2);
-
- // Restore operands and operand count
- for (i = 0; i < 8; i++)
- zargs[i] = saved_zargs[i];
-
- zargc = saved_zargc;
-
- // Resulting value lies on top of the stack
- return (short)*_sp++;
-}
-
-void Processor::seed_random(int value) {
- if (value == 0) {
- // Now using random values
- _randomInterval = 0;
- } else if (value < 1000) {
- // special seed value
- _randomCtr = 0;
- _randomInterval = value;
- } else {
- // standard seed value
- _random.setSeed(value);
- _randomInterval = 0;
- }
-}
-
-void Processor::__extended__() {
- zbyte opcode;
- zbyte specifier;
-
- CODE_BYTE(opcode);
- CODE_BYTE(specifier);
-
- load_all_operands(specifier);
-
- if (opcode < 0x1e) // extended opcodes from 0x1e on
- (*this.*ext_opcodes[opcode])(); // are reserved for future spec'
-}
-
-void Processor::__illegal__() {
- runtimeError(ERR_ILL_OPCODE);
-}
-
-void Processor::z_catch() {
- store(_save_quetzal ? _frameCount : (zword)(_fp - _stack));
-}
-
-void Processor::z_throw() {
- if (_save_quetzal) {
- if (zargs[1] > _frameCount)
- runtimeError(ERR_BAD_FRAME);
-
- // Unwind the stack a frame at a time.
- for (; _frameCount > zargs[1]; --_frameCount)
- _fp = _stack + 1 + _fp[1];
- } else {
- if (zargs[1] > STACK_SIZE)
- runtimeError(ERR_BAD_FRAME);
-
- _fp = _stack + zargs[1];
- }
-
- ret(zargs[0]);
-}
-
-void Processor::z_call_n() {
- if (zargs[0] != 0)
- call(zargs[0], zargc - 1, zargs + 1, 1);
-}
-
-void Processor::z_call_s() {
- if (zargs[0] != 0)
- call(zargs[0], zargc - 1, zargs + 1, 0);
- else
- store(0);
-}
-
-void Processor::z_check_arg_count() {
- if (_fp == _stack + STACK_SIZE)
- branch(zargs[0] == 0);
- else
- branch(zargs[0] <= (*_fp & 0xff));
-}
-
-void Processor::z_jump() {
- long pc;
- GET_PC(pc);
-
- pc += (short)zargs[0] - 2;
-
- if ((uint)pc >= story_size)
- runtimeError(ERR_ILL_JUMP_ADDR);
-
- SET_PC(pc);
-}
-
-void Processor::z_nop() {
- // Do nothing
-}
-
-void Processor::z_quit() {
- _finished = 9999;
-}
-
-void Processor::z_ret() {
- ret(zargs[0]);
-}
-
-void Processor::z_ret_popped() {
- ret(*_sp++);
-}
-
-void Processor::z_rfalse() {
- ret(0);
-}
-
-void Processor::z_rtrue() {
- ret(1);
-}
-
-void Processor::z_random() {
- if ((short) zargs[0] <= 0) {
- // set random seed
- seed_random(- (short) zargs[0]);
- store(0);
-
- } else {
- // generate random number
- zword result;
- if (_randomInterval != 0) {
- // ...in special mode
- result = _randomCtr++;
- if (_randomCtr == _randomInterval)
- _randomCtr = 0;
- } else {
- // ...in standard mode
- result = _random.getRandomNumber(0xffff);
- }
-
- store((zword)(result % zargs[0] + 1));
- }
-}
-
-void Processor::z_sound_effect() {
- zword number = zargs[0];
- zword effect = zargs[1];
- zword volume = zargs[2];
-
- if (zargc < 1)
- number = 0;
- if (zargc < 2)
- effect = EFFECT_PLAY;
- if (zargc < 3)
- volume = 8;
-
- if (number >= 3 || number == 0) {
- _soundLocked = true;
-
- if (_storyId == LURKING_HORROR && (number == 9 || number == 16)) {
- if (effect == EFFECT_PLAY) {
- next_sample = number;
- next_volume = volume;
-
- _soundLocked = false;
-
- if (!_soundPlaying)
- start_next_sample();
- } else {
- _soundLocked = false;
- }
- return;
- }
-
- _soundPlaying = false;
-
- switch (effect) {
-
- case EFFECT_PREPARE:
- os_prepare_sample (number);
- break;
- case EFFECT_PLAY:
- start_sample(number, lo (volume), hi (volume), (zargc == 4) ? zargs[3] : 0);
- break;
- case EFFECT_STOP:
- os_stop_sample (number);
- break;
- case EFFECT_FINISH_WITH:
- os_finish_with_sample (number);
- break;
- }
-
- _soundLocked = false;
- } else {
- os_beep(number);
- }
-}
-
-void Processor::z_piracy() {
- branch(!_piracy);
-}
-
-void Processor::z_save_undo(void) {
- store((zword)save_undo());
-}
-
-void Processor::z_restore_undo(void) {
- store((zword)restore_undo());
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h
deleted file mode 100644
index 3ead900..0000000
--- a/engines/gargoyle/frotz/processor.h
+++ /dev/null
@@ -1,1584 +0,0 @@
-/* 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 GARGOYLE_FROTZ_PROCESSOR
-#define GARGOYLE_FROTZ_PROCESSOR
-
-#include "gargoyle/frotz/mem.h"
-#include "gargoyle/frotz/glk_interface.h"
-#include "gargoyle/frotz/frotz_types.h"
-#include "common/stack.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-#define TEXT_BUFFER_SIZE 200
-
-#define CODE_BYTE(v) v = codeByte()
-#define CODE_WORD(v) v = codeWord()
-#define CODE_IDX_WORD(v,i) v = codeWordIdx(i)
-#define GET_PC(v) v = getPC()
-#define SET_PC(v) setPC(v)
-
-enum string_type {
- LOW_STRING, ABBREVIATION, HIGH_STRING, EMBEDDED_STRING, VOCABULARY
-};
-
-class Processor;
-class Quetzal;
-typedef void (Processor::*Opcode)();
-
-/**
- * Zcode processor
- */
-class Processor : public GlkInterface, public virtual Mem {
- friend class Quetzal;
-private:
- Opcode op0_opcodes[16];
- Opcode op1_opcodes[16];
- static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
- static Opcode var_opcodes[64];
- static Opcode ext_opcodes[64];
-
- int _finished;
- zword zargs[8];
- int zargc;
- uint _randomInterval;
- uint _randomCtr;
- bool first_restart;
- bool script_valid;
-
- // Stack data
- zword _stack[STACK_SIZE];
- zword *_sp;
- zword *_fp;
- zword _frameCount;
-
- // Text related fields
- static zchar ZSCII_TO_LATIN1[];
- zchar *_decoded, *_encoded;
- int _resolution;
- int _errorCount[ERR_NUM_ERRORS];
-
- // Buffer related fields
- bool _locked;
- zchar _prevC;
- zchar _buffer[TEXT_BUFFER_SIZE];
- size_t _bufPos;
-
- // Stream related fields
- int script_width;
- strid_t sfp, rfp, pfp;
- Common::FixedStack<Redirect, MAX_NESTING> _redirect;
-private:
- /**
- * \defgroup General support methods
- * @{
- */
-
- /**
- * Load an operand, either a variable or a constant.
- */
- void load_operand(zbyte type);
-
- /**
- * Given the operand specifier byte, load all (up to four) operands
- * for a VAR or EXT opcode.
- */
- void load_all_operands(zbyte specifier);
-
- /**
- * Call a subroutine. Save PC and FP then load new PC and initialise
- * new stack frame. Note that the caller may legally provide less or
- * more arguments than the function actually has. The call type "ct"
- * can be 0 (z_call_s), 1 (z_call_n) or 2 (direct call).
- */
- void call(zword routine, int argc, zword *args, int ct);
-
- /**
- * Return from the current subroutine and restore the previous _stack
- * frame. The result may be stored (0), thrown away (1) or pushed on
- * the stack (2). In the latter case a direct call has been finished
- * and we must exit the interpreter loop.
- */
- void ret(zword value);
-
- /**
- * Take a jump after an instruction based on the flag, either true or
- * false. The branch can be short or long; it is encoded in one or two
- * bytes respectively. When bit 7 of the first byte is set, the jump
- * takes place if the flag is true; otherwise it is taken if the flag
- * is false. When bit 6 of the first byte is set, the branch is short;
- * otherwise it is long. The offset occupies the bottom 6 bits of the
- * first byte plus all the bits in the second byte for long branches.
- * Uniquely, an offset of 0 means return false, and an offset of 1 is
- * return true.
- */
- void branch(bool flag);
-
- /**
- * Store an operand, either as a variable or pushed on the stack.
- */
- void store(zword value);
-
- /*
- * Call the interpreter loop directly. This is necessary when
- *
- * - a sound effect has been finished
- * - a read instruction has timed out
- * - a newline countdown has hit zero
- *
- * The interpreter returns the result value on the stack.
- */
- int direct_call(zword addr);
-
- /**
- * Set the seed value for the random number generator.
- */
- void seed_random(int value);
-
- /**@}*/
-
- /**
- * \defgroup Input support methods
- * @{
- */
-
- /**
- * Copy the contents of the text buffer to the output streams.
- */
- void flush_buffer();
-
- /**
- * High level output function.
- */
- void print_char(zchar c);
-
- /**
- * Print a string of ASCII characters.
- */
- void print_string(const char *s);
-
- /**
- * Print an unsigned 32bit number in decimal or hex.
- */
- void print_long(uint value, int base);
-
- /**
- * High level newline function.
- */
- void new_line();
-
- /**
- * Returns true if the buffer is empty
- */
- bool bufferEmpty() const { return !_bufPos; }
-
- /**
- * An error has occurred. Ignore it, pass it to os_fatal or report
- * it according to err_report_mode.
- * @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
- */
- void runtimeError(ErrorCode errNum);
-
- /**@}*/
-
- /**
- * \defgroup Input support methods
- * @{
- */
-
- /**
- * Check if the given key is an input terminator.
- */
- bool is_terminator(zchar key);
-
- /**
- * Ask the user a question; return true if the answer is yes.
- */
- bool read_yes_or_no(const char *s);
-
- /**
- * Read a string from the current input stream.
- */
- void read_string(int max, zchar *buffer);
-
- /**
- * Ask the user to type in a number and return it.
- */
- int read_number();
-
- /**@}*/
-
- /**
- * \defgroup Memory support methods
- * @{
- */
-
- /**
- * Called when the H_FLAGS field of the header has changed
- */
- virtual void flagsChanged(zbyte value) override;
-
- /**
- * This function does the dirty work for z_save_undo.
- */
- int save_undo();
-
- /**
- * This function does the dirty work for z_restore_undo.
- */
- int restore_undo();
-
- /**
- * Begin output redirection to the memory of the Z-machine.
- */
- void memory_open(zword table, zword xsize, bool buffering);
-
- /**
- * End of output redirection.
- */
- void memory_close();
-
- /**
- * Redirect a newline to the memory of the Z-machine.
- */
- void memory_new_line();
-
- /**
- * Redirect a string of characters to the memory of the Z-machine.
- */
- void memory_word(const zchar *s);
-
- /**@}*/
-
- /**
- * \defgroup Object support methods
- * @{
- */
-
- /**
- * Calculate the address of an object.
- */
- zword object_address(zword obj);
-
- /**
- * Return the address of the given object's name.
- */
- zword object_name(zword object);
-
- /**
- * Calculate the start address of the property list associated with an object.
- */
- zword first_property(zword obj);
-
- /**
- * Calculate the address of the next property in a property list.
- */
- zword next_property(zword prop_addr);
-
- /**
- * Unlink an object from its parent and siblings.
- */
- void unlink_object(zword object);
-
- /**@}*/
-
- /**
- * \defgroup Screen support methods
- * @{
- */
-
- void screen_char(zchar c);
- void screen_new_line();
- void screen_word(const zchar *s);
- void screen_mssg_on();
- void screen_mssg_off();
-
- /**@}*/
-
- /**
- * \defgroup Stream support methods
- * @{
- */
-
- /**
- * Waits for the user to type an input line
- */
- zchar console_read_input(int max, zchar *buf, zword timeout, bool continued);
-
- /**
- * Waits for a keypress
- */
- zchar console_read_key(zword timeout);
-
- /**
- * Write a single character to the scrollback buffer.
- *
- */
- void scrollback_char(zchar c);
-
- /**
- * Write a string to the scrollback buffer.
- */
- void scrollback_word(const zchar *s);
-
- /**
- * Send an input line to the scrollback buffer.
- */
- void scrollback_write_input(const zchar *buf, zchar key);
-
- /**
- * Remove an input line from the scrollback buffer.
- */
- void scrollback_erase_input(const zchar *buf);
-
- /**
- * Start printing a "debugging" message.
- */
- void stream_mssg_on();
-
- /**
- * Stop printing a "debugging" message.
- */
- void stream_mssg_off();
-
- /**
- * Send a single character to the output stream.
- */
- void stream_char(zchar c);
-
- /**
- * Send a string of characters to the output streams.
- */
- void stream_word(const zchar *s);
-
- /**
- * Send a newline to the output streams.
- */
- void stream_new_line();
-
- /**
- * Read a single keystroke from the current input stream.
- */
- zchar stream_read_key(zword timeout, zword routine, bool hot_keys);
-
- /**
- * Read a line of input from the current input stream.
- */
- zchar stream_read_input(int max, zchar *buf, zword timeout, zword routine,
- bool hot_keys, bool no_scripting);
-
- /*
- * script_open
- *
- * Open the transscript file. 'AMFV' makes this more complicated as it
- * turns transscription on/off several times to exclude some text from
- * the transscription file. This wasn't a problem for the original V4
- * interpreters which always sent transscription to the printer, but it
- * means a problem to modern interpreters that offer to open a new file
- * every time transscription is turned on. Our solution is to append to
- * the old transscription file in V1 to V4, and to ask for a new file
- * name in V5+.
- *
- */
- void script_open();
-
- /*
- * Stop transscription.
- */
- void script_close();
-
- /**
- * Write a newline to the transscript file.
- */
- void script_new_line();
-
- /**
- * Write a single character to the transscript file.
- */
- void script_char(zchar c);
-
- /**
- * Write a string to the transscript file.
- */
- void script_word(const zchar *s);
-
- /**
- * Send an input line to the transscript file.
- */
- void script_write_input(const zchar *buf, zchar key);
-
- /**
- * Remove an input line from the transscript file.
- */
- void script_erase_input(const zchar *buf);
-
- /**
- * Start sending a "debugging" message to the transscript file.
- */
- void script_mssg_on();
-
- /**
- * Stop writing a "debugging" message.
- */
- void script_mssg_off();
-
- /**
- * Open a file to record the player's input.
- */
- void record_open();
-
- /**
- * Stop recording the player's input.
- */
- void record_close();
-
- /**
- * Helper function for record_char.
- */
- void record_code(int c, bool force_encoding);
-
- /**
- * Write a character to the command file.
- */
- void record_char(zchar c);
-
- /**
- * Copy a keystroke to the command file.
- */
- void record_write_key(zchar key);
-
- /**
- * Copy a line of input to a command file.
- */
- void record_write_input(const zchar *buf, zchar key);
-
- /**
- * Open a file of commands for playback.
- */
- void replay_open();
-
- /**
- * Stop playback of commands.
- */
- void replay_close();
-
- /*
- * Helper function for replay_key and replay_line.
- */
- int replay_code();
-
- /**
- * Read a character from the command file.
- */
- zchar replay_char();
-
- /**
- * Read a keystroke from a command file.
- */
- zchar replay_read_key();
-
- /*
- * Read a line of input from a command file.
- */
- zchar replay_read_input(zchar *buf);
-
- /**@}*/
-
- /**
- * \defgroup Text support methods
- * @{
- */
-
- /**
- * Map a ZSCII character into Unicode.
- */
- zchar translate_from_zscii(zbyte c);
-
- /**
- * Convert a Unicode character to ZSCII, returning 0 on failure.
- */
- zbyte unicode_to_zscii(zchar c);
-
- /**
- * Map a Unicode character onto the ZSCII alphabet.
- *
- */
- zbyte translate_to_zscii(zchar c);
-
- /**
- * Return a character from one of the three character sets.
- */
- zchar alphabet(int set, int index);
-
- /**
- * Find the number of bytes used for dictionary resolution.
- */
- void find_resolution();
-
- /**
- * Copy a ZSCII string from the memory to the global "decoded" string.
- */
- void load_string(zword addr, zword length);
-
- /**
- * Encode the Unicode text in the global "decoded" string then write
- * the result to the global "encoded" array. (This is used to look up
- * words in the dictionary.) Up to V3 the vocabulary resolution is
- * two, from V4 it is three, and from V9 it is any number of words.
- * Because each word contains three Z-characters, that makes six or
- * nine Z-characters respectively. Longer words are chopped to the
- * proper size, shorter words are are padded out with 5's. For word
- * completion we pad with 0s and 31s, the minimum and maximum
- * Z-characters.
- */
- void encode_text(int padding);
-
- /**
- * Convert _encoded text to Unicode. The _encoded text consists of 16bit
- * words. Every word holds 3 Z-characters (5 bits each) plus a spare
- * bit to mark the last word. The Z-characters translate to ZSCII by
- * looking at the current current character set. Some select another
- * character set, others refer to abbreviations.
- *
- * There are several different string types:
- *
- * LOW_STRING - from the lower 64KB (byte address)
- * ABBREVIATION - from the abbreviations table (word address)
- * HIGH_STRING - from the end of the memory map (packed address)
- * EMBEDDED_STRING - from the instruction stream (at PC)
- * VOCABULARY - from the dictionary (byte address)
- *
- * The last type is only used for word completion.
- */
- void decode_text(string_type st, zword addr);
-
- /**
- * Print a signed 16bit number.
- */
- void print_num(zword value);
-
- /**
- * print_object
- *
- * Print an object description.
- *
- */
- void print_object(zword object);
-
- /**
- * Scan a dictionary searching for the given word. The first argument
- * can be
- *
- * 0x00 - find the first word which is >= the given one
- * 0x05 - find the word which exactly matches the given one
- * 0x1f - find the last word which is <= the given one
- *
- * The return value is 0 if the search fails.
- */
- zword lookup_text(int padding, zword dct);
-
- /**
- * tokenise_text
- *
- * Translate a single word to a token and append it to the token
- * buffer. Every token consists of the address of the dictionary
- * entry, the length of the word and the offset of the word from
- * the start of the text buffer. Unknown words cause empty slots
- * if the flag is set (such that the text can be scanned several
- * times with different dictionaries); otherwise they are zero.
- *
- */
- void tokenise_text(zword text, zword length, zword from, zword parse, zword dct, bool flag);
-
- /**
- * Split an input line into words and translate the words to tokens.
- */
- void tokenise_line(zword text, zword token, zword dct, bool flag);
-
- /**
- * Scan the vocabulary to complete the last word on the input line
- * (similar to "tcsh" under Unix). The return value is
- *
- * 2 ==> completion is impossible
- * 1 ==> completion is ambiguous
- * 0 ==> completion is successful
- *
- * The function also returns a string in its second argument. In case
- * of 2, the string is empty; in case of 1, the string is the longest
- * extension of the last word on the input line that is common to all
- * possible completions (for instance, if the last word on the input
- * is "fo" and its only possible completions are "follow" and "folly"
- * then the string is "ll"); in case of 0, the string is an extension
- * to the last word that results in the only possible completion.
- */
- int completion(const zchar *buffer, zchar *result);
-
- /**
- * Convert a Unicode character to lowercase.
- * Taken from Zip2000 by Kevin Bracey.
- */
- zchar unicode_tolower(zchar c);
-
- /**@}*/
-protected:
- /**
- * \defgroup General Opcode methods
- * @{
- */
-
- /*
- * Load and execute an extended opcode.
- */
- void __extended__();
-
- /*
- * Exit game because an unknown opcode has been hit.
- */
- void __illegal__();
-
- /*
- * Store the current _stack frame for later use with z_throw.
- *
- * no zargs used
- */
- void z_catch();
-
- /**
- * Go back to the given _stack frame and return the given value.
- *
- * zargs[0] = value to return
- * zargs[1] = _stack frame
- */
- void z_throw();
-
- /*
- * Call a subroutine and discard its result.
- *
- * zargs[0] = packed address of subroutine
- * zargs[1] = first argument (optional)
- * ...
- * zargs[7] = seventh argument (optional)
- */
- void z_call_n();
-
- /**
- * Call a subroutine and store its result.
- *
- * zargs[0] = packed address of subroutine
- * zargs[1] = first argument (optional)
- * ...
- * zargs[7] = seventh argument (optional)
- */
- void z_call_s();
-
- /**
- * Branch if subroutine was called with >= n arg's.
- *
- * zargs[0] = number of arguments
- */
- void z_check_arg_count();
-
- /**
- * Jump unconditionally to the given address.
- *
- * zargs[0] = PC relative address
- */
- void z_jump();
-
- /*
- * No operation.
- *
- * no zargs used
- */
- void z_nop();
-
- /*
- * Stop game and exit interpreter.
- *
- * no zargs used
- */
- void z_quit();
-
- /*
- * Return from a subroutine with the given value.
- *
- * zargs[0] = value to return
- */
- void z_ret();
-
- /*
- * Return from a subroutine with a value popped off the stack.
- *
- * no zargs used
- */
- void z_ret_popped();
-
- /*
- * Return from a subroutine with false (0).
- *
- * no zargs used
- */
- void z_rfalse();
-
- /*
- * Return from a subroutine with true (1).
- *
- * no zargs used
- */
- void z_rtrue();
-
- /**
- * Store a random number or set the random number seed.
- *
- * zargs[0] = range (positive) or seed value (negative)
- */
- void z_random();
-
- /**
- * Load / play / stop / discard a sound effect.
- *
- * zargs[0] = number of bleep (1 or 2) or sample
- * zargs[1] = operation to perform (samples only)
- * zargs[2] = repeats and volume (play sample only)
- * zargs[3] = end-of-sound routine (play sample only, optional)
- *
- * Note: Volumes range from 1 to 8, volume 255 is the default volume.
- * Repeats are stored in the high byte, 255 is infinite loop.
- *
- */
- void z_sound_effect();
-
- /**
- * Branch if the story file is a legal copy
- */
- void z_piracy();
-
- /**
- * Save the current Z-machine state for a future undo.
- *
- * no zargs used
- */
- void z_save_undo();
-
- /**
- * Restore a Z-machine state from memory.
- *
- * no zargs used
- */
- void z_restore_undo();
-
- /**@}*/
-
- /**
- * \defgroup Input Opcode methods
- * @{
- */
-
- /**
- * Add or remove a menu and branch if successful.
- *
- * zargs[0] = number of menu
- * zargs[1] = table of menu entries or 0 to remove menu
- */
- void z_make_menu();
-
- /**
- * Read a line of input and (in V5+) store the terminating key.
- *
- * zargs[0] = address of text buffer
- * zargs[1] = address of token buffer
- * zargs[2] = timeout in tenths of a second (optional)
- * zargs[3] = packed address of routine to be called on timeout
- */
- void z_read();
-
- /**
- * Read and store a key.
- *
- * zargs[0] = input device (must be 1)
- * zargs[1] = timeout in tenths of a second (optional)
- * zargs[2] = packed address of routine to be called on timeout
- */
- void z_read_char();
-
- /**
- * z_read_mouse, write the current mouse status into a table.
- *
- * zargs[0] = address of table
- */
- void z_read_mouse();
-
- /**@}*/
-
- /**
- * \defgroup Math Opcode methods
- * @{
- */
-
- /**
- * 16 bit addition.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_add();
-
- /**
- * Bitwise AND operation.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_and();
-
- /**
- * Arithmetic SHIFT operation.
- *
- * zargs[0] = value
- * zargs[1] = #positions to shift left (positive) or right
- */
- void z_art_shift();
-
- /**
- * Signed 16bit division.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_div();
-
- /**
- * B ranch if the first value equals any of the following.
- *
- * zargs[0] = first value
- * zargs[1] = second value (optional)
- * ...
- * zargs[3] = fourth value (optional)
- */
- void z_je();
-
- /**
- * Branch if the first value is greater than the second.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_jg();
-
- /**
- * Branch if the first value is less than the second.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_jl();
-
- /**
- * Branch if value is zero.
- *
- * zargs[0] = value
- */
- void z_jz();
-
- /**
- * Logical SHIFT operation.
- *
- * zargs[0] = value
- * zargs[1] = #positions to shift left (positive) or right (negative)
- */
- void z_log_shift();
-
- /*
- * Remainder after signed 16bit division.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_mod();
-
- /**
- * 16 bit multiplication.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_mul();
-
- /**
- * Bitwise NOT operation.
- *
- * zargs[0] = value
- */
- void z_not();
-
- /**
- * Bitwise OR operation.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_or();
-
- /**
- * 16 bit substraction.
- *
- * zargs[0] = first value
- * zargs[1] = second value
- */
- void z_sub();
-
- /**
- * Branch if all the flags of a bit mask are set in a value.
- *
- * zargs[0] = value to be examined
- * zargs[1] = bit mask
- */
- void z_test();
-
- /**@}*/
-
- /**
- * \defgroup Object Opcode methods
- * @{
- */
-
- /**
- * Branch if the first object is inside the second.
- *
- * zargs[0] = first object
- * zargs[1] = second object
- */
- void z_jin();
-
- /**
- * Store the child of an object.
- *
- * zargs[0] = object
- */
- void z_get_child();
-
- /**
- * Store the number of the first or next property.
- *
- * zargs[0] = object
- * zargs[1] = address of current property (0 gets the first property)
- */
- void z_get_next_prop();
-
- /**
- * Store the parent of an object.
- *
- * zargs[0] = object
- */
- void z_get_parent();
-
- /**
- * Store the value of an object property.
- *
- * zargs[0] = object
- * zargs[1] = number of property to be examined
- */
- void z_get_prop();
-
- /**
- * Store the address of an object property.
- *
- * zargs[0] = object
- * zargs[1] = number of property to be examined
- */
- void z_get_prop_addr();
-
- /**
- * Store the length of an object property.
- *
- * zargs[0] = address of property to be examined
- */
- void z_get_prop_len();
-
- /**
- * Store the sibling of an object.
- *
- * zargs[0] = object
- */
- void z_get_sibling();
-
- /**
- * Make an object the first child of another object.
- *
- * zargs[0] = object to be moved
- * zargs[1] = destination object
- */
- void z_insert_obj();
-
- /**
- * Set the value of an object property.
- *
- * zargs[0] = object
- * zargs[1] = number of property to set
- * zargs[2] = value to set property to
- */
- void z_put_prop();
-
- /**
- * Unlink an object from its parent and siblings.
- *
- * zargs[0] = object
- */
- void z_remove_obj();
-
- /**
- * Set an object attribute.
- *
- * zargs[0] = object
- * zargs[1] = number of attribute to set
- */
- void z_set_attr();
-
- /**
- * Branch if an object attribute is set.
- *
- * zargs[0] = object
- * zargs[1] = number of attribute to test
- */
- void z_test_attr();
-
- /**
- * Clear an object attribute.
- *
- * zargs[0] = object
- * zargs[1] = number of attribute to be cleared
- */
- void z_clear_attr();
-
- /**@}*/
-
- /**
- * \defgroup Screen Opcode methods
- * @{
- */
-
- /**
- * Turn text buffering on/off.
- *
- * zargs[0] = new text buffering flag (0 or 1)
- */
- void z_buffer_mode();
-
- /**
- * Set the screen buffering mode.
- *
- * zargs[0] = mode
- */
- void z_buffer_screen();
-
- /**
- * Erase the line starting at the cursor position.
- *
- * zargs[0] = 1 + #units to erase (1 clears to the end of the line)
- */
- void z_erase_line();
-
- /**
- * Erase a window or the screen to background colour.
- *
- * zargs[0] = window (-3 current, -2 screen, -1 screen & unsplit)
- */
- void z_erase_window();
-
- /**
- * Write the cursor coordinates into a table.
- *
- * zargs[0] = address to write information to
- */
- void z_get_cursor();
-
- /**
- * Print ASCII text in a rectangular area.
- *
- * zargs[0] = address of text to be printed
- * zargs[1] = width of rectangular area
- * zargs[2] = height of rectangular area (optional)
- * zargs[3] = number of char's to skip between lines (optional)
- */
- void z_print_table();
-
- /**
- * Set the foreground and background colours
- * to specific RGB colour values.
- *
- * zargs[0] = foreground colour
- * zargs[1] = background colour
- * zargs[2] = window (-3 is the current one, optional)
- */
- void z_set_true_colour();
-
- /**
- * Set the foreground and background colours.
- *
- * zargs[0] = foreground colour
- * zargs[1] = background colour
- * zargs[2] = window (-3 is the current one, optional)
- */
- void z_set_colour();
-
- /**
- * Set the font for text output and store the previous font.
- *
- * zargs[0] = number of font or 0 to keep current font
- */
- void z_set_font();
-
- /**
- * Set the cursor position or turn the cursor on/off.
- *
- * zargs[0] = y-coordinate or -2/-1 for cursor on/off
- * zargs[1] = x-coordinate
- * zargs[2] = window (-3 is the current one, optional)
- */
- void z_set_cursor();
-
- /**
- * z_set_text_style, set the style for text output.
- *
- * zargs[0] = style flags to set or 0 to reset text style
- */
- void z_set_text_style();
-
- /**
- * Select the current window.
- *
- * zargs[0] = window to be selected (-3 is the current one)
- */
- void z_set_window();
-
- /**
- * Display the status line for V1 to V3 games.
- *
- * no zargs used
- */
- void pad_status_line(int column);
-
- /**
- * Display the status line for V1 to V3 games.
- *
- * no zargs used
- */
- void z_show_status();
-
- /**
- * Split the screen into an upper (1) and lower (0) window.
- *
- * zargs[0] = height of upper window in screen units (V6) or #lines
- */
- void z_split_window();
-
- /**@}*/
-
- /**
- * \defgroup Stream Opcode methods
- * @{
- */
-
- /**
- * Select an input stream.
- *
- * zargs[0] = input stream to be selected
- */
- void z_input_stream();
-
- /**
- * Open or close an output stream.
- *
- * zargs[0] = stream to open (positive) or close (negative)
- * zargs[1] = address to redirect output to (stream 3 only)
- * zargs[2] = width of redirected output (stream 3 only, optional)
- */
- void z_output_stream();
-
- /**
- * Re-load dynamic area, clear the stack and set the PC.
- *
- * no zargs used
- */
- void z_restart();
-
- /**
- * Save [a part of] the Z-machine state to disk.
- *
- * zargs[0] = address of memory area to save (optional)
- * zargs[1] = number of bytes to save
- * zargs[2] = address of suggested file name
- */
- void z_save();
-
- /**
- * Restore [a part of] a Z-machine state from disk
- *
- * zargs[0] = address of area to restore (optional)
- * zargs[1] = number of bytes to restore
- * zargs[2] = address of suggested file name
- */
- void z_restore();
-
- /**
- * Check the story file integrity.
- *
- * no zargs used
- */
- void z_verify();
-
- /**@}*/
-
- /**
- * \defgroup Table Opcode methods
- * @{
- */
-
- /**
- * Copy a table or fill it with zeroes.
- *
- * zargs[0] = address of table
- * zargs[1] = destination address or 0 for fill
- * zargs[2] = size of table
- *
- * Note: Copying is safe even when source and destination overlap; but
- * if zargs[1] is negative the table _must_ be copied forwards.
- */
- void z_copy_table();
-
- /**
- * Store a value from a table of bytes.
- *
- * zargs[0] = address of table
- * zargs[1] = index of table entry to store
- */
- void z_loadb();
-
- /**
- * Store a value from a table of words.
- *
- * zargs[0] = address of table
- * zargs[1] = index of table entry to store
- */
- void z_loadw();
-
- /**
- * Find and store the address of a target within a table.
- *
- * zargs[0] = target value to be searched for
- * zargs[1] = address of table
- * zargs[2] = number of table entries to check value against
- * zargs[3] = type of table (optional, defaults to 0x82)
- *
- * Note: The table is a word array if bit 7 of zargs[3] is set; otherwise
- * it's a byte array. The lower bits hold the address step.
- */
- void z_scan_table();
-
- /**
- * Write a byte into a table of bytes.
- *
- * zargs[0] = address of table
- * zargs[1] = index of table entry
- * zargs[2] = value to be written
- */
- void z_storeb();
-
- /**
- * Write a word into a table of words.
- *
- * zargs[0] = address of table
- * zargs[1] = index of table entry
- * zargs[2] = value to be written
- */
- void z_storew();
-
- /**@}*/
-
- /**
- * \defgroup Text Opcode methods
- * @{
- */
-
- /**
- * Test if a unicode character can be printed (bit 0) and read (bit 1).
- *
- * zargs[0] = Unicode
- */
- void z_check_unicode();
-
- /**
- * Encode a ZSCII string for use in a dictionary.
- *
- * zargs[0] = address of text buffer
- * zargs[1] = length of ASCII string
- * zargs[2] = offset of ASCII string within the text buffer
- * zargs[3] = address to store encoded text in
- *
- * This is a V5+ opcode and therefore the dictionary resolution must be
- * three 16bit words.
- */
- void z_encode_text();
-
- /**
- * Print a new line.
- *
- * no zargs used
- *
- */
- void z_new_line();
-
- /**
- * Print a string embedded in the instruction stream.
- *
- * no zargs used
- */
- void z_print();
-
- /**
- * Print a string from the lower 64KB.
- *
- * zargs[0] = address of string to print
- */
- void z_print_addr();
-
- /**
- * Print a single ZSCII character.
- *
- * zargs[0] = ZSCII character to be printed
- */
- void z_print_char();
-
- /**
- * Print a formatted table.
- *
- * zargs[0] = address of formatted table to be printed
- */
- void z_print_form();
-
- /**
- * Print a signed number.
- *
- * zargs[0] = number to print
- */
- void z_print_num();
-
- /**
- * Print an object description.
- *
- * zargs[0] = number of object to be printed
- */
- void z_print_obj();
-
- /**
- * Print the string at the given packed address.
- *
- * zargs[0] = packed address of string to be printed
- */
- void z_print_paddr();
-
- /*
- * Print the string at PC, print newline then return true.
- *
- * no zargs used
- */
- void z_print_ret();
-
- /**
- * Print unicode character
- *
- * zargs[0] = Unicode
- */
- void z_print_unicode();
-
- /**
- * Make a lexical analysis of a ZSCII string.
- *
- * zargs[0] = address of string to analyze
- * zargs[1] = address of token buffer
- * zargs[2] = address of dictionary (optional)
- * zargs[3] = set when unknown words cause empty slots (optional)
- */
- void z_tokenise();
-
- /**@}*/
-
- /**
- * \defgroup Variable Opcode methods
- * @{
- */
-
- /**
- * Decrement a variable.
- *
- * zargs[0] = variable to decrement
- */
- void z_dec();
-
- /**
- * Decrement a variable and branch if now less than value.
- *
- * zargs[0] = variable to decrement
- * zargs[1] = value to check variable against
- */
- void z_dec_chk();
-
- /**
- * Increment a variable.
- *
- * zargs[0] = variable to increment
- */
- void z_inc();
-
- /**
- * Increment a variable and branch if now greater than value.
- *
- * zargs[0] = variable to increment
- * zargs[1] = value to check variable against
- */
- void z_inc_chk();
-
- /**
- * Store the value of a variable.
- *
- * zargs[0] = variable to store
- */
- void z_load();
-
- /**
- * Pop a value off the game stack and discard it.
- *
- * no zargs used
- */
- void z_pop();
-
- /**
- * Pop n values off the game or user stack and discard them.
- *
- * zargs[0] = number of values to discard
- * zargs[1] = address of user stack (optional)
- */
- void z_pop_stack();
-
- /**
- * Pop a value off...
- *
- * a) ...the game or a user stack and store it (V6)
- *
- * zargs[0] = address of user stack (optional)
- *
- * b) ...the game stack and write it to a variable (other than V6)
- *
- * zargs[0] = variable to write value to
- */
- void z_pull();
-
- /**
- * Push a value onto the game stack.
- *
- * zargs[0] = value to push onto the stack
- */
- void z_push();
-
- /**
- * Push a value onto a user stack then branch if successful.
- *
- * zargs[0] = value to push onto the stack
- * zargs[1] = address of user stack
- */
- void z_push_stack();
-
- /**
- * Write a value to a variable.
- *
- * zargs[0] = variable to be written to
- * zargs[1] = value to write
- */
- void z_store();
-
- /**@}*/
-public:
- /**
- * Constructor
- */
- Processor(OSystem *syst, const GargoyleGameDescription *gameDesc);
-
- /**
- * Initialization
- */
- void initialize();
-
- /**
- * Z-code interpreter main loop
- */
- void interpret();
-
- /**
- * \defgroup Memory access methods
- * @{
- */
-
- /**
- * Square brackets operator
- */
- zbyte &operator[](uint addr) { return zmp[addr]; }
-
- /**
- * Read a code byte
- */
- zbyte codeByte() { return *pcp++; }
-
- /**
- * Read a code word
- */
- zword codeWord() {
- zword v = READ_BE_UINT16(pcp);
- pcp += 2;
- return v;
- }
-
- /**
- * Return a code word at a given address
- */
- zword codeWordIdx(uint addr) const {
- return READ_BE_UINT16(pcp + addr);
- }
-
- /**
- * Return the current program execution offset
- */
- uint getPC() const { return pcp - zmp; }
-
- /**
- * Set the program execution offset
- */
- void setPC(uint addr) { pcp = zmp + addr; }
-
- /**@}*/
-};
-
-} // End of namespace Frotz
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/gargoyle/frotz/processor_buffer.cpp b/engines/gargoyle/frotz/processor_buffer.cpp
deleted file mode 100644
index 62980fb..0000000
--- a/engines/gargoyle/frotz/processor_buffer.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-#include "common/algorithm.h"
-#include "common/textconsole.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-const char *const Processor::ERR_MESSAGES[ERR_NUM_ERRORS] = {
- "Text buffer overflow",
- "Store out of dynamic memory",
- "Division by zero",
- "Illegal object",
- "Illegal attribute",
- "No such property",
- "Stack overflow",
- "Call to illegal address",
- "Call to non-routine",
- "Stack underflow",
- "Illegal opcode",
- "Bad stack frame",
- "Jump to illegal address",
- "Can't save while in interrupt",
- "Nesting stream #3 too deep",
- "Illegal window",
- "Illegal window property",
- "Print at illegal address",
- "Illegal dictionary word length",
- "@jin called with object 0",
- "@get_child called with object 0",
- "@get_parent called with object 0",
- "@get_sibling called with object 0",
- "@get_prop_addr called with object 0",
- "@get_prop called with object 0",
- "@put_prop called with object 0",
- "@clear_attr called with object 0",
- "@set_attr called with object 0",
- "@test_attr called with object 0",
- "@move_object called moving object 0",
- "@move_object called moving into object 0",
- "@remove_object called with object 0",
- "@get_next_prop called with object 0"
-};
-
-void Processor::flush_buffer() {
- /* Make sure we stop when flush_buffer is called from flush_buffer.
- * Note that this is difficult to avoid as we might print a newline
- * during flush_buffer, which might cause a newline interrupt, that
- * might execute any arbitrary opcode, which might flush the buffer.
- */
- if (_locked || bufferEmpty())
- return;
-
- // Send the buffer to the output streams
- _buffer[_bufPos] = '\0';
-
- _locked = true;
- stream_word(_buffer);
- _locked = false;
-
- // Reset the buffer
- _bufPos = 0;
- _prevC = '\0';
-}
-
-void Processor::print_char(zchar c) {
- static bool flag = false;
-
- if (message || ostream_memory || enable_buffering) {
- if (!flag) {
- // Characters 0 and ZC_RETURN are special cases
- if (c == ZC_RETURN) {
- new_line();
- return;
- }
- if (c == 0)
- return;
-
- // Flush the buffer before a whitespace or after a hyphen
- if (c == ' ' || c == ZC_INDENT || c == ZC_GAP || (_prevC == '-' && c != '-'))
- flush_buffer();
-
- // Set the flag if this is part one of a style or font change
- if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE)
- flag = true;
-
- // Remember the current character code
- _prevC = c;
- } else {
- flag = false;
- }
-
- // Insert the character into the buffer
- _buffer[_bufPos++] = c;
-
- if (_bufPos == TEXT_BUFFER_SIZE)
- error("Text buffer overflow");
- } else {
- stream_char(c);
- }
-}
-
-void Processor::print_string(const char *s) {
- char c;
-
- while ((c = *s++) != 0) {
- if (c == '\n')
- new_line();
- else
- print_char(c);
- }
-}
-
-void Processor::print_long(uint value, int base) {
- unsigned long i;
- char c;
-
- for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base) {
- if (value >= i || i == 1) {
- c = (value / i) % base;
- print_char(c + (c <= 9 ? '0' : 'a' - 10));
- }
- }
-}
-
-void Processor::new_line() {
- flush_buffer();
- stream_new_line();
-}
-
-void Processor::runtimeError(ErrorCode errNum) {
- int wasfirst;
-
- if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
- return;
-
- if (_err_report_mode == ERR_REPORT_FATAL
- || (!_ignore_errors && errNum <= ERR_MAX_FATAL)) {
- flush_buffer();
- error(ERR_MESSAGES[errNum - 1]);
- return;
- }
-
- wasfirst = (_errorCount[errNum - 1] == 0);
- _errorCount[errNum - 1]++;
-
- if ((_err_report_mode == ERR_REPORT_ALWAYS)
- || (_err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
- long pc;
- GET_PC(pc);
- print_string("Warning: ");
- print_string(ERR_MESSAGES[errNum - 1]);
- print_string(" (PC = ");
- print_long(pc, 16);
- print_char(')');
-
- if (_err_report_mode == ERR_REPORT_ONCE) {
- print_string(" (will ignore further occurrences)");
- }
- else {
- print_string(" (occurence ");
- print_long(_errorCount[errNum - 1], 10);
- print_char(')');
- }
-
- new_line();
- }
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp
deleted file mode 100644
index fa9da21..0000000
--- a/engines/gargoyle/frotz/processor_input.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-#define INPUT_BUFFER_SIZE 200
-
-bool Processor::read_yes_or_no(const char *s) {
- zchar key;
-
- print_string(s);
- print_string("? (y/n) >");
-
- key = stream_read_key(0, 0, false);
-
- if (key == 'y' || key == 'Y') {
- print_string("y\n");
- return true;
- } else {
- print_string("n\n");
- return false;
- }
-}
-
-void Processor::read_string(int max, zchar *buffer) {
- zchar key;
-
- buffer[0] = 0;
-
- do {
- key = stream_read_input(max, buffer, 0, 0, false, false);
- } while (key != ZC_RETURN);
-}
-
-bool Processor::is_terminator(zchar key) {
- if (key == ZC_TIME_OUT)
- return true;
- if (key == ZC_RETURN)
- return true;
- if (key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX)
- return true;
-
- if (h_terminating_keys != 0) {
- if (key >= ZC_ARROW_MIN && key <= ZC_MENU_CLICK) {
-
- zword addr = h_terminating_keys;
- zbyte c;
-
- do {
- LOW_BYTE(addr, c);
- if (c == 255 || key == translate_from_zscii(c))
- return true;
- addr++;
- } while (c != 0);
- }
- }
-
- return false;
-}
-
-void Processor::z_make_menu() {
- // This opcode was only used for the Macintosh version of Journey.
- // It controls menus with numbers greater than 2 (menus 0, 1 and 2
- // are system menus).
- branch(false);
-}
-
-int Processor::read_number() {
- zchar buffer[6];
- int value = 0;
- int i;
-
- read_string(5, buffer);
-
- for (i = 0; buffer[i] != 0; i++)
- if (buffer[i] >= '0' && buffer[i] <= '9')
- value = 10 * value + buffer[i] - '0';
-
- return value;
-}
-
-void Processor::z_read() {
- zchar buffer[INPUT_BUFFER_SIZE];
- zword addr;
- zchar key;
- zbyte max, size;
- zbyte c;
- int i;
-
- // Supply default arguments
- if (zargc < 3)
- zargs[2] = 0;
-
- // Get maximum input size
- addr = zargs[0];
-
- LOW_BYTE(addr, max);
-
- if (h_version <= V4)
- max--;
-
- if (max >= INPUT_BUFFER_SIZE)
- max = INPUT_BUFFER_SIZE - 1;
-
- // Get initial input size
- if (h_version >= V5) {
- addr++;
- LOW_BYTE(addr, size);
- } else {
- size = 0;
- }
-
- // Copy initial input to local buffer
- for (i = 0; i < size; i++) {
- addr++;
- LOW_BYTE(addr, c);
- buffer[i] = translate_from_zscii(c);
- }
- buffer[i] = 0;
-
- // Draw status line for V1 to V3 games
- if (h_version <= V3)
- z_show_status();
-
- // Read input from current input stream
- key = stream_read_input(
- max, buffer, // buffer and size
- zargs[2], // timeout value
- zargs[3], // timeout routine
- false, // enable hot keys
- h_version == V6 // no script in V6
- );
-
- if (key == ZC_BAD)
- return;
-
- // Perform save_undo for V1 to V4 games
- if (h_version <= V4)
- save_undo();
-
- // Copy local buffer back to dynamic memory
- for (i = 0; buffer[i] != 0; i++) {
- if (key == ZC_RETURN) {
- buffer[i] = unicode_tolower (buffer[i]);
- }
-
- storeb((zword) (zargs[0] + ((h_version <= V4) ? 1 : 2) + i), translate_to_zscii (buffer[i]));
- }
-
- // Add null character (V1-V4) or write input length into 2nd byte
- if (h_version <= V4)
- storeb((zword) (zargs[0] + 1 + i), 0);
- else
- storeb((zword) (zargs[0] + 1), i);
-
- // Tokenise line if a token buffer is present
- if (key == ZC_RETURN && zargs[1] != 0)
- tokenise_line (zargs[0], zargs[1], 0, false);
-
- // Store key
- if (h_version >= V5)
- store(translate_to_zscii(key));
-}
-
-void Processor::z_read_char() {
- zchar key;
-
- // Supply default arguments
- if (zargc < 2)
- zargs[1] = 0;
-
- // Read input from the current input stream
- key = stream_read_key(
- zargs[1], // timeout value
- zargs[2], // timeout routine
- false // enable hot keys
- );
-
- if (key == ZC_BAD)
- return;
-
- // Store key
- store (translate_to_zscii (key));
-}
-
-void Processor::z_read_mouse(){
- zword btn;
-
- // Read the mouse position, the last menu click and which buttons are down
- btn = os_read_mouse();
- hx_mouse_y = mouse_y;
- hx_mouse_x = mouse_x;
-
- storew((zword) (zargs[0] + 0), hx_mouse_y);
- storew((zword) (zargs[0] + 2), hx_mouse_x);
- storew((zword) (zargs[0] + 4), btn); // mouse button bits
- storew((zword) (zargs[0] + 6), menu_selected); // menu selection
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_maths.cpp b/engines/gargoyle/frotz/processor_maths.cpp
deleted file mode 100644
index e64dd55..0000000
--- a/engines/gargoyle/frotz/processor_maths.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-void Processor::z_add() {
- store((zword)((short)zargs[0] + (short)zargs[1]));
-}
-
-void Processor::z_and() {
- store((zword)(zargs[0] & zargs[1]));
-}
-
-void Processor::z_art_shift() {
- if ((short)zargs[1] > 0)
- store((zword)((short)zargs[0] << (short)zargs[1]));
- else
- store((zword)((short)zargs[0] >> - (short)zargs[1]));
-}
-
-void Processor::z_div() {
- if (zargs[1] == 0)
- runtimeError(ERR_DIV_ZERO);
-
- store((zword)((short)zargs[0] / (short)zargs[1]));
-}
-
-void Processor::z_je() {
- branch(
- zargc > 1 && (zargs[0] == zargs[1] || (
- zargc > 2 && (zargs[0] == zargs[2] || (
- zargc > 3 && (zargs[0] == zargs[3])))))
- );
-}
-
-void Processor::z_jg() {
- branch((short)zargs[0] > (short)zargs[1]);
-}
-
-void Processor::z_jl() {
- branch((short)zargs[0] < (short)zargs[1]);
-}
-
-void Processor::z_jz() {
- branch((short)zargs[0] == 0);
-}
-
-void Processor::z_log_shift() {
- if ((short)zargs[1] > 0)
- store((zword)(zargs[0] << (short)zargs[1]));
- else
- store((zword)(zargs[0] >> - (short)zargs[1]));
-}
-
-void Processor::z_mod() {
- if (zargs[1] == 0)
- runtimeError(ERR_DIV_ZERO);
-
- store((zword)((short)zargs[0] % (short)zargs[1]));
-}
-
-void Processor::z_mul() {
- store((zword)((short)zargs[0] * (short)zargs[1]));
-}
-
-void Processor::z_not() {
- store((zword)~zargs[0]);
-}
-
-void Processor::z_or() {
- store((zword)(zargs[0] | zargs[1]));
-}
-
-void Processor::z_sub() {
- store((zword)((short)zargs[0] - (short)zargs[1]));
-}
-
-void Processor::z_test() {
- branch((zargs[0] & zargs[1]) == zargs[1]);
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_mem.cpp b/engines/gargoyle/frotz/processor_mem.cpp
deleted file mode 100644
index d46402c..0000000
--- a/engines/gargoyle/frotz/processor_mem.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-void Processor::flagsChanged(zbyte value) {
- if (value & SCRIPTING_FLAG) {
- if (!ostream_script)
- script_open();
- } else {
- if (ostream_script)
- script_close();
- }
-}
-
-int Processor::save_undo() {
- long diff_size;
- zword stack_size;
- undo_t *p;
-
- if (_undo_slots == 0)
- // undo feature unavailable
- return -1;
-
- // save undo possible
- while (last_undo != curr_undo) {
- p = last_undo;
- last_undo = last_undo->prev;
- delete p;
- undo_count--;
- }
- if (last_undo)
- last_undo->next = nullptr;
- else
- first_undo = nullptr;
-
- if (undo_count == _undo_slots)
- free_undo(1);
-
- diff_size = mem_diff(zmp, prev_zmp, h_dynamic_size, undo_diff);
- stack_size = _stack + STACK_SIZE - _sp;
- do {
- p = (undo_t *) malloc(sizeof(undo_t) + diff_size + stack_size * sizeof(*_sp));
- if (p == nullptr)
- free_undo(1);
- } while (!p && undo_count);
- if (p == nullptr)
- return -1;
-
- GET_PC(p->pc);
- p->frame_count = _frameCount;
- p->diff_size = diff_size;
- p->stack_size = stack_size;
- p->frame_offset = _fp - _stack;
- memcpy(p + 1, undo_diff, diff_size);
- memcpy((zbyte *)(p + 1) + diff_size, _sp, stack_size * sizeof(*_sp));
-
- if (!first_undo) {
- p->prev = nullptr;
- first_undo = p;
- } else {
- last_undo->next = p;
- p->prev = last_undo;
- }
-
- p->next = nullptr;
- curr_undo = last_undo = p;
- undo_count++;
-
- return 1;
-}
-
-int Processor::restore_undo(void) {
- if (_undo_slots == 0)
- // undo feature unavailable
- return -1;
-
- if (curr_undo == nullptr)
- // no saved game state
- return 0;
-
- // undo possible
- memcpy(zmp, prev_zmp, h_dynamic_size);
- SET_PC(curr_undo->pc);
- _sp = _stack + STACK_SIZE - curr_undo->stack_size;
- _fp = _stack + curr_undo->frame_offset;
- _frameCount = curr_undo->frame_count;
- mem_undiff((zbyte *)(curr_undo + 1), curr_undo->diff_size, prev_zmp);
- memcpy(_sp, (zbyte *)(curr_undo + 1) + curr_undo->diff_size,
- curr_undo->stack_size * sizeof(*_sp));
-
- curr_undo = curr_undo->prev;
-
- restart_header();
-
- return 2;
-}
-
-/**
- * TOR: glkify -- this is for V6 only
- */
-static zword get_max_width(zword win) { return 80; }
-
-void Processor::memory_open(zword table, zword xsize, bool buffering) {
- if (_redirect.size() < MAX_NESTING) {
- if (!buffering)
- xsize = 0xffff;
- if (buffering && (short)xsize <= 0)
- xsize = get_max_width((zword)(-(short)xsize));
-
- storew(table, 0);
-
- _redirect.push(Redirect(xsize, table));
- ostream_memory = true;
- } else {
- runtimeError(ERR_STR3_NESTING);
- }
-}
-
-void Processor::memory_new_line() {
- zword size;
- zword addr;
-
- Redirect &r = _redirect.top();
- r._total += r._width;
- r._width = 0;
-
- addr = r._table;
-
- LOW_WORD(addr, size);
- addr += 2;
-
- if (r._xSize != 0xffff) {
- r._table = addr + size;
- size = 0;
- } else {
- storeb((zword)(addr + (size++)), 13);
- }
-
- storew(r._table, size);
-}
-
-void Processor::memory_word(const zchar *s) {
- zword size;
- zword addr;
- zchar c;
-
- Redirect &r = _redirect.top();
- if (h_version == V6) {
- int width = os_string_width(s);
-
- if (r._xSize != 0xffff) {
- if (r._width + width > r._xSize) {
-
- if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
- width = os_string_width(++s);
-
- memory_new_line();
- }
- }
-
- r._width += width;
- }
-
- addr = r._table;
-
- LOW_WORD(addr, size);
- addr += 2;
-
- while ((c = *s++) != 0)
- storeb((zword)(addr + (size++)), translate_to_zscii(c));
-
- storew(r._table, size);
-}
-
-void Processor::memory_close(void) {
- if (!_redirect.empty()) {
- Redirect &r = _redirect.top();
-
- if (r._xSize != 0xffff)
- memory_new_line();
-
- if (h_version == V6) {
- h_line_width = (r._xSize != 0xffff) ? r._total : r._width;
-
- SET_WORD(H_LINE_WIDTH, h_line_width);
- }
-
- _redirect.pop();
- if (_redirect.empty())
- ostream_memory = false;
- }
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_objects.cpp b/engines/gargoyle/frotz/processor_objects.cpp
deleted file mode 100644
index 986bf87..0000000
--- a/engines/gargoyle/frotz/processor_objects.cpp
+++ /dev/null
@@ -1,732 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-#define MAX_OBJECT 2000
-
-enum O1 {
- O1_PARENT = 4,
- O1_SIBLING = 5,
- O1_CHILD = 6,
- O1_PROPERTY_OFFSET = 7,
- O1_SIZE = 9
-};
-
-enum O4 {
- O4_PARENT = 6,
- O4_SIBLING = 8,
- O4_CHILD = 10,
- O4_PROPERTY_OFFSET = 12,
- O4_SIZE = 14
-};
-
-zword Processor::object_address(zword obj) {
- // Check object number
- if (obj > ((h_version <= V3) ? 255 : MAX_OBJECT)) {
- print_string("@Attempt to address illegal object ");
- print_num(obj);
- print_string(". This is normally fatal.");
- new_line();
- runtimeError(ERR_ILL_OBJ);
- }
-
- // Return object address
- if (h_version <= V3)
- return h_objects + ((obj - 1) * O1_SIZE + 62);
- else
- return h_objects + ((obj - 1) * O4_SIZE + 126);
-}
-
-zword Processor::object_name(zword object) {
- zword obj_addr;
- zword name_addr;
-
- obj_addr = object_address(object);
-
- // The object name address is found at the start of the properties
- if (h_version <= V3)
- obj_addr += O1_PROPERTY_OFFSET;
- else
- obj_addr += O4_PROPERTY_OFFSET;
-
- LOW_WORD(obj_addr, name_addr);
-
- return name_addr;
-}
-
-zword Processor::first_property(zword obj) {
- zword prop_addr;
- zbyte size;
-
- // Fetch address of object name
- prop_addr = object_name (obj);
-
- // Get length of object name
- LOW_BYTE(prop_addr, size);
-
- // Add name length to pointer
- return prop_addr + 1 + 2 * size;
-}
-
-zword Processor::next_property(zword prop_addr) {
- zbyte value;
-
- // Load the current property id
- LOW_BYTE(prop_addr, value);
- prop_addr++;
-
- // Calculate the length of this property
- if (h_version <= V3)
- value >>= 5;
- else if (!(value & 0x80))
- value >>= 6;
- else {
- LOW_BYTE(prop_addr, value);
- value &= 0x3f;
-
- if (value == 0)
- // demanded by Spec 1.0
- value = 64;
- }
-
- // Add property length to current property pointer
- return prop_addr + value + 1;
-}
-
-void Processor::unlink_object(zword object) {
- zword obj_addr;
- zword parent_addr;
- zword sibling_addr;
-
- if (object == 0) {
- runtimeError(ERR_REMOVE_OBJECT_0);
- return;
- }
-
- obj_addr = object_address(object);
-
- if (h_version <= V3) {
-
- zbyte parent;
- zbyte younger_sibling;
- zbyte older_sibling;
- zbyte zero = 0;
-
- // Get parent of object, and return if no parent
- obj_addr += O1_PARENT;
- LOW_BYTE(obj_addr, parent);
- if (!parent)
- return;
-
- // Get (older) sibling of object and set both parent and sibling pointers to 0
- SET_BYTE(obj_addr, zero);
- obj_addr += O1_SIBLING - O1_PARENT;
- LOW_BYTE(obj_addr, older_sibling);
- SET_BYTE(obj_addr, zero);
-
- // Get first child of parent (the youngest sibling of the object)
- parent_addr = object_address(parent) + O1_CHILD;
- LOW_BYTE(parent_addr, younger_sibling);
-
- // Remove object from the list of siblings
- if (younger_sibling == object)
- SET_BYTE(parent_addr, older_sibling);
- else {
- do {
- sibling_addr = object_address(younger_sibling) + O1_SIBLING;
- LOW_BYTE(sibling_addr, younger_sibling);
- } while (younger_sibling != object);
- SET_BYTE(sibling_addr, older_sibling);
- }
- } else {
- zword parent;
- zword younger_sibling;
- zword older_sibling;
- zword zero = 0;
-
- // Get parent of object, and return if no parent
- obj_addr += O4_PARENT;
- LOW_WORD(obj_addr, parent);
- if (!parent)
- return;
-
- // Get (older) sibling of object and set both parent and sibling pointers to 0
- SET_WORD(obj_addr, zero);
- obj_addr += O4_SIBLING - O4_PARENT;
- LOW_WORD(obj_addr, older_sibling);
- SET_WORD(obj_addr, zero);
-
- // Get first child of parent (the youngest sibling of the object)
- parent_addr = object_address(parent) + O4_CHILD;
- LOW_WORD(parent_addr, younger_sibling);
-
- // Remove object from the list of siblings
- if (younger_sibling == object) {
- SET_WORD(parent_addr, older_sibling);
- } else {
- do {
- sibling_addr = object_address(younger_sibling) + O4_SIBLING;
- LOW_WORD(sibling_addr, younger_sibling);
- } while (younger_sibling != object);
- SET_WORD(sibling_addr, older_sibling);
- }
- }
-}
-
-void Processor::z_clear_attr() {
- zword obj_addr;
- zbyte value;
-
- if (_storyId == SHERLOCK)
- if (zargs[1] == 48)
- return;
-
- if (zargs[1] > ((h_version <= V3) ? 31 : 47))
- runtimeError(ERR_ILL_ATTR);
-
- // If we are monitoring attribute assignment display a short note
- if (_attribute_assignment) {
- stream_mssg_on();
- print_string("@clear_attr ");
- print_object(zargs[0]);
- print_string(" ");
- print_num(zargs[1]);
- stream_mssg_off();
- }
-
- if (zargs[0] == 0) {
- runtimeError(ERR_CLEAR_ATTR_0);
- return;
- }
-
- // Get attribute address
- obj_addr = object_address(zargs[0]) + zargs[1] / 8;
-
- // Clear attribute bit
- LOW_BYTE(obj_addr, value);
- value &= ~(0x80 >> (zargs[1] & 7));
- SET_BYTE(obj_addr, value);
-}
-
-void Processor::z_jin() {
- zword obj_addr;
-
- // If we are monitoring object locating display a short note
- if (_object_locating) {
- stream_mssg_on();
- print_string("@jin ");
- print_object(zargs[0]);
- print_string(" ");
- print_object(zargs[1]);
- stream_mssg_off();
- }
-
- if (zargs[0] == 0) {
- runtimeError(ERR_JIN_0);
- branch(0 == zargs[1]);
- return;
- }
-
- obj_addr = object_address(zargs[0]);
-
- if (h_version <= V3) {
- zbyte parent;
-
- // Get parent id from object
- obj_addr += O1_PARENT;
- LOW_BYTE(obj_addr, parent);
-
- // Branch if the parent is obj2
- branch(parent == zargs[1]);
-
- } else {
- zword parent;
-
- // Get parent id from object
- obj_addr += O4_PARENT;
- LOW_WORD(obj_addr, parent);
-
- // Branch if the parent is obj2
- branch(parent == zargs[1]);
- }
-}
-
-void Processor::z_get_child() {
- zword obj_addr;
-
- // If we are monitoring object locating display a short note
- if (_object_locating) {
- stream_mssg_on();
- print_string("@get_child ");
- print_object(zargs[0]);
- stream_mssg_off();
- }
-
- if (zargs[0] == 0) {
- runtimeError(ERR_GET_CHILD_0);
- store(0);
- branch(false);
- return;
- }
-
- obj_addr = object_address(zargs[0]);
-
- if (h_version <= V3) {
- zbyte child;
-
- // Get child id from object
- obj_addr += O1_CHILD;
- LOW_BYTE(obj_addr, child);
-
- // Store child id and branch
- store(child);
- branch(child);
- } else {
- zword child;
-
- // Get child id from object
- obj_addr += O4_CHILD;
- LOW_WORD(obj_addr, child);
-
- // Store child id and branch
- store(child);
- branch(child);
- }
-}
-
-void Processor::z_get_next_prop() {
- zword prop_addr;
- zbyte value;
- zbyte mask;
-
- if (zargs[0] == 0) {
- runtimeError(ERR_GET_NEXT_PROP_0);
- store(0);
- return;
- }
-
- // Property id is in bottom five (six) bits
- mask = (h_version <= V3) ? 0x1f : 0x3f;
-
- // Load address of first property
- prop_addr = first_property(zargs[0]);
-
- if (zargs[1] != 0) {
- // Scan down the property list
- do {
- LOW_BYTE(prop_addr, value);
- prop_addr = next_property(prop_addr);
- } while ((value & mask) > zargs[1]);
-
- // Exit if the property does not exist
- if ((value & mask) != zargs[1])
- runtimeError(ERR_NO_PROP);
- }
-
- // Return the property id
- LOW_BYTE(prop_addr, value);
- store((zword) (value & mask));
-}
-
-void Processor::z_get_parent() {
- zword obj_addr;
-
- // If we are monitoring object locating display a short note
- if (_object_locating) {
- stream_mssg_on();
- print_string("@get_parent ");
- print_object(zargs[0]);
- stream_mssg_off();
- }
-
- if (zargs[0] == 0) {
- runtimeError(ERR_GET_PARENT_0);
- store(0);
- return;
- }
-
- obj_addr = object_address(zargs[0]);
-
- if (h_version <= V3) {
- zbyte parent;
-
- // Get parent id from object
- obj_addr += O1_PARENT;
- LOW_BYTE(obj_addr, parent);
-
- // Store parent
- store(parent);
-
- } else {
- zword parent;
-
- // Get parent id from object
- obj_addr += O4_PARENT;
- LOW_WORD(obj_addr, parent);
-
- // Store parent
- store(parent);
- }
-}
-
-void Processor::z_get_prop() {
- zword prop_addr;
- zword wprop_val;
- zbyte bprop_val;
- zbyte value;
- zbyte mask;
-
- if (zargs[0] == 0) {
- runtimeError(ERR_GET_PROP_0);
- store(0);
- return;
- }
-
- // Property id is in bottom five (six) bits
- mask = (h_version <= V3) ? 0x1f : 0x3f;
-
- // Load address of first property
- prop_addr = first_property(zargs[0]);
-
- // Scan down the property list
- for (;;) {
- LOW_BYTE(prop_addr, value);
- if ((value & mask) <= zargs[1])
- break;
- prop_addr = next_property(prop_addr);
- }
-
- if ((value & mask) == zargs[1]) {
- // property found
-
- // Load property(byte or word sized)
- prop_addr++;
-
- if ((h_version <= V3 && !(value & 0xe0)) || (h_version >= V4 && !(value & 0xc0))) {
- LOW_BYTE(prop_addr, bprop_val);
- wprop_val = bprop_val;
- } else {
- LOW_WORD(prop_addr, wprop_val);
- }
- } else {
- // property not found
-
- // Load default value
- prop_addr = h_objects + 2 * (zargs[1] - 1);
- LOW_WORD(prop_addr, wprop_val);
- }
-
- // Store the property value
- store(wprop_val);
-}
-
-void Processor::z_get_prop_addr() {
- zword prop_addr;
- zbyte value;
- zbyte mask;
-
- if (zargs[0] == 0) {
- runtimeError(ERR_GET_PROP_ADDR_0);
- store(0);
- return;
- }
-
- if (_storyId == BEYOND_ZORK)
- if (zargs[0] > MAX_OBJECT)
- { store(0); return; }
-
- // Property id is in bottom five (six) bits
- mask = (h_version <= V3) ? 0x1f : 0x3f;
-
- // Load address of first property
- prop_addr = first_property(zargs[0]);
-
- // Scan down the property list
- for (;;) {
- LOW_BYTE(prop_addr, value);
- if ((value & mask) <= zargs[1])
- break;
- prop_addr = next_property(prop_addr);
- }
-
- // Calculate the property address or return zero
- if ((value & mask) == zargs[1]) {
-
- if (h_version >= V4 && (value & 0x80))
- prop_addr++;
- store((zword) (prop_addr + 1));
-
- } else {
- store(0);
- }
-}
-
-void Processor::z_get_prop_len() {
- zword addr;
- zbyte value;
-
- // Back up the property pointer to the property id
- addr = zargs[0] - 1;
- LOW_BYTE(addr, value);
-
- // Calculate length of property
- if (h_version <= V3)
- value = (value >> 5) + 1;
- else if (!(value & 0x80))
- value = (value >> 6) + 1;
- else {
- value &= 0x3f;
-
- if (value == 0)
- value = 64; // demanded by Spec 1.0
- }
-
- // Store length of property
- store(value);
-}
-
-void Processor::z_get_sibling() {
- zword obj_addr;
-
- if (zargs[0] == 0) {
- runtimeError(ERR_GET_SIBLING_0);
- store(0);
- branch(false);
- return;
- }
-
- obj_addr = object_address(zargs[0]);
-
- if (h_version <= V3) {
- zbyte sibling;
-
- // Get sibling id from object
- obj_addr += O1_SIBLING;
- LOW_BYTE(obj_addr, sibling);
-
- // Store sibling and branch
- store(sibling);
- branch(sibling);
-
- } else {
- zword sibling;
-
- // Get sibling id from object
- obj_addr += O4_SIBLING;
- LOW_WORD(obj_addr, sibling);
-
- // Store sibling and branch
- store(sibling);
- branch(sibling);
- }
-}
-
-void Processor::z_insert_obj() {
- zword obj1 = zargs[0];
- zword obj2 = zargs[1];
- zword obj1_addr;
- zword obj2_addr;
-
- // If we are monitoring object movements display a short note
- if (_object_movement) {
- stream_mssg_on();
- print_string("@move_obj ");
- print_object(obj1);
- print_string(" ");
- print_object(obj2);
- stream_mssg_off();
- }
-
- if (obj1 == 0) {
- runtimeError(ERR_MOVE_OBJECT_0);
- return;
- }
-
- if (obj2 == 0) {
- runtimeError(ERR_MOVE_OBJECT_TO_0);
- return;
- }
-
- // Get addresses of both objects
- obj1_addr = object_address(obj1);
- obj2_addr = object_address(obj2);
-
- // Remove object 1 from current parent
- unlink_object(obj1);
-
- // Make object 1 first child of object 2
- if (h_version <= V3) {
- zbyte child;
-
- obj1_addr += O1_PARENT;
- SET_BYTE(obj1_addr, obj2);
- obj2_addr += O1_CHILD;
- LOW_BYTE(obj2_addr, child);
- SET_BYTE(obj2_addr, obj1);
- obj1_addr += O1_SIBLING - O1_PARENT;
- SET_BYTE(obj1_addr, child);
-
- } else {
- zword child;
-
- obj1_addr += O4_PARENT;
- SET_WORD(obj1_addr, obj2);
- obj2_addr += O4_CHILD;
- LOW_WORD(obj2_addr, child);
- SET_WORD(obj2_addr, obj1);
- obj1_addr += O4_SIBLING - O4_PARENT;
- SET_WORD(obj1_addr, child);
- }
-}
-
-void Processor::z_put_prop() {
- zword prop_addr;
- zword value;
- zbyte mask;
-
- if (zargs[0] == 0) {
- runtimeError(ERR_PUT_PROP_0);
- return;
- }
-
- // Property id is in bottom five or six bits
- mask = (h_version <= V3) ? 0x1f : 0x3f;
-
- // Load address of first property
- prop_addr = first_property(zargs[0]);
-
- // Scan down the property list
- for (;;) {
- LOW_BYTE(prop_addr, value);
- if ((value & mask) <= zargs[1])
- break;
-
- prop_addr = next_property(prop_addr);
- }
-
- // Exit if the property does not exist
- if ((value & mask) != zargs[1])
- runtimeError(ERR_NO_PROP);
-
- // Store the new property value (byte or word sized)
- prop_addr++;
-
- if ((h_version <= V3 && !(value & 0xe0)) || (h_version >= V4 && !(value & 0xc0))) {
- zbyte v = zargs[2];
- SET_BYTE(prop_addr, v);
- } else {
- zword v = zargs[2];
- SET_WORD(prop_addr, v);
- }
-}
-
-void Processor::z_remove_obj() {
- // If we are monitoring object movements display a short note
- if (_object_movement) {
- stream_mssg_on();
- print_string("@remove_obj ");
- print_object(zargs[0]);
- stream_mssg_off();
- }
-
- // Call unlink_object to do the job
- unlink_object(zargs[0]);
-}
-
-void Processor::z_set_attr() {
- zword obj_addr;
- zbyte value;
-
- if (_storyId == SHERLOCK)
- if (zargs[1] == 48)
- return;
-
- if (zargs[1] > ((h_version <= V3) ? 31 : 47))
- runtimeError(ERR_ILL_ATTR);
-
- // If we are monitoring attribute assignment display a short note
- if (_attribute_assignment) {
- stream_mssg_on();
- print_string("@set_attr ");
- print_object(zargs[0]);
- print_string(" ");
- print_num(zargs[1]);
- stream_mssg_off();
- }
-
- if (zargs[0] == 0) {
- runtimeError(ERR_SET_ATTR_0);
- return;
- }
-
- // Get attribute address
- obj_addr = object_address(zargs[0]) + zargs[1] / 8;
-
- // Load attribute byte
- LOW_BYTE(obj_addr, value);
-
- // Set attribute bit
- value |= 0x80 >> (zargs[1] & 7);
-
- // Store attribute byte
- SET_BYTE(obj_addr, value);
-}
-
-void Processor::z_test_attr() {
- zword obj_addr;
- zbyte value;
-
- if (zargs[1] > ((h_version <= V3) ? 31 : 47))
- runtimeError(ERR_ILL_ATTR);
-
- // If we are monitoring attribute testing display a short note
- if (_attribute_testing) {
- stream_mssg_on();
- print_string("@test_attr ");
- print_object(zargs[0]);
- print_string(" ");
- print_num(zargs[1]);
- stream_mssg_off();
- }
-
- if (zargs[0] == 0) {
- runtimeError(ERR_TEST_ATTR_0);
- branch(false);
- return;
- }
-
- // Get attribute address
- obj_addr = object_address(zargs[0]) + zargs[1] / 8;
-
- // Load attribute byte
- LOW_BYTE(obj_addr, value);
-
- // Test attribute
- branch(value & (0x80 >> (zargs[1] & 7)));
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_screen.cpp b/engines/gargoyle/frotz/processor_screen.cpp
deleted file mode 100644
index 77e2e94..0000000
--- a/engines/gargoyle/frotz/processor_screen.cpp
+++ /dev/null
@@ -1,528 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-void Processor::screen_mssg_on() {
- if (gos_curwin == gos_lower) {
- oldstyle = curstyle;
- glk_set_style(style_Preformatted);
- glk_put_string("\n ");
- }
-}
-
-void Processor::screen_mssg_off() {
- if (gos_curwin == gos_lower) {
- glk_put_char('\n');
- zargs[0] = 0;
- z_set_text_style();
- zargs[0] = oldstyle;
- z_set_text_style();
- }
-}
-
-void Processor::screen_char(zchar c) {
- if (gos_linepending && (gos_curwin == gos_linewin)) {
- gos_cancel_pending_line();
- if (gos_curwin == gos_upper) {
- curx = 1;
- cury ++;
- }
- if (c == '\n')
- return;
- }
-
- // check fixed flag in header, game can change it at whim
- int forcefix = ((h_flags & FIXED_FONT_FLAG) != 0);
- int curfix = ((curstyle & FIXED_WIDTH_STYLE) != 0);
- if (forcefix && !curfix) {
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- fixforced = true;
- } else if (!forcefix && fixforced) {
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- fixforced = false;
- }
-
- if (gos_upper && gos_curwin == gos_upper) {
- if (c == '\n' || c == ZC_RETURN) {
- glk_put_char('\n');
- curx = 1;
- cury ++;
- } else {
- if (cury == 1) {
- if (curx <= ((sizeof statusline / sizeof(zchar)) - 1)) {
- statusline[curx - 1] = c;
- statusline[curx] = 0;
- }
- if (curx < h_screen_cols) {
- glk_put_char_uni(c);
- } else if (curx == h_screen_cols) {
- glk_put_char_uni(c);
- glk_window_move_cursor(gos_curwin, curx-1, cury-1);
- } else {
- smartstatusline();
- }
-
- curx++;
- } else {
- if (curx < h_screen_cols) {
- glk_put_char_uni(c);
- } else if (curx == (h_screen_cols)) {
- glk_put_char_uni(c);
- glk_window_move_cursor(gos_curwin, curx-1, cury-1);
- }
-
- curx++;
- }
- }
- } else if (gos_curwin == gos_lower) {
- if (c == ZC_RETURN)
- glk_put_char('\n');
- else glk_put_char_uni(c);
- }
-}
-
-void Processor::screen_new_line() {
- screen_char('\n');
-}
-
-void Processor::screen_word(const zchar *s) {
- zchar c;
- while ((c = *s++) != 0) {
- if (c == ZC_NEW_FONT)
- s++;
- else if (c == ZC_NEW_STYLE)
- s++;
- else
- screen_char(c);
- }
-}
-
-
-void Processor::z_buffer_mode() {
- // No implementation
-}
-
-void Processor::z_buffer_screen() {
- store(0);
-}
-
-void Processor::z_erase_line() {
- int i;
-
- if (gos_upper && gos_curwin == gos_upper) {
- for (i = 0; i < h_screen_cols + 1 - curx; i++)
- glk_put_char(' ');
- glk_window_move_cursor(gos_curwin, curx - 1, cury - 1);
- }
-}
-
-void Processor::z_erase_window() {
- short w = zargs[0];
- if (w == -2)
- {
- if (gos_upper) {
- glk_set_window(gos_upper);
-#ifdef GARGLK
- garglk_set_zcolors(curr_fg, curr_bg);
-#endif /* GARGLK */
- glk_window_clear(gos_upper);
- glk_set_window(gos_curwin);
- }
- glk_window_clear(gos_lower);
- }
- if (w == -1)
- {
- if (gos_upper) {
- glk_set_window(gos_upper);
-#ifdef GARGLK
- garglk_set_zcolors(curr_fg, curr_bg);
-#endif /* GARGLK */
- glk_window_clear(gos_upper);
- }
- glk_window_clear(gos_lower);
- split_window(0);
- glk_set_window(gos_lower);
- gos_curwin = gos_lower;
- }
- if (w == 0)
- glk_window_clear(gos_lower);
- if (w == 1 && gos_upper)
- glk_window_clear(gos_upper);
-}
-
-void Processor::z_get_cursor() {
- storew((zword) (zargs[0] + 0), cury);
- storew((zword) (zargs[0] + 2), curx);
-}
-
-void Processor::z_print_table() {
- zword addr = zargs[0];
- zword x;
- int i, j;
-
- // Supply default arguments
- if (zargc < 3)
- zargs[2] = 1;
- if (zargc < 4)
- zargs[3] = 0;
-
- // Write text in width x height rectangle
- x = curx;
-
- for (i = 0; i < zargs[2]; i++) {
- if (i != 0) {
- cury += 1;
- curx = x;
- }
-
- for (j = 0; j < zargs[1]; j++) {
-
- zbyte c;
-
- LOW_BYTE(addr, c);
- addr++;
-
- print_char(c);
- }
-
- addr += zargs[3];
- }
-}
-
-#define zB(i) ((((i >> 10) & 0x1F) << 3) | (((i >> 10) & 0x1F) >> 2))
-#define zG(i) ((((i >> 5) & 0x1F) << 3) | (((i >> 5) & 0x1F) >> 2))
-#define zR(i) ((((i ) & 0x1F) << 3) | (((i ) & 0x1F) >> 2))
-
-#define zRGB(i) (zR(i) << 16 | zG(i) << 8 | zB(i))
-
-void Processor::z_set_true_colour() {
- int zfore = zargs[0];
- int zback = zargs[1];
-
- if (!(zfore < 0))
- zfore = zRGB(zargs[0]);
-
- if (!(zback < 0))
- zback = zRGB(zargs[1]);
-
-#ifdef GARGLK
- garglk_set_zcolors(zfore, zback);
-#endif /* GARGLK */
-
- curr_fg = zfore;
- curr_bg = zback;
-}
-
-static const int zcolor_map[] = {
- -2, ///< 0 = current
- -1, ///< 1 = default
- 0x0000, ///< 2 = black
- 0x001D, ///< 3 = red
- 0x0340, ///< 4 = green
- 0x03BD, ///< 5 = yellow
- 0x59A0, ///< 6 = blue
- 0x7C1F, ///< 7 = magenta
- 0x77A0, ///< 8 = cyan
- 0x7FFF, ///< 9 = white
- 0x5AD6, ///< 10 = light grey
- 0x4631, ///< 11 = medium grey
- 0x2D6B, ///< 12 = dark grey
-};
-
-#define zcolor_NUMCOLORS (13)
-
-void Processor::z_set_colour() {
- int zfore = zargs[0];
- int zback = zargs[1];
-
- switch (zfore) {
- case -1:
- zfore = -3;
- break;
-
- case 0:
- case 1:
- zfore = zcolor_map[zfore];
- break;
-
- default:
- if (zfore < zcolor_NUMCOLORS)
- zfore = zRGB(zcolor_map[zfore]);
- break;
- }
-
- switch (zback) {
- case -1:
- zback = -3;
-
- case 0:
- case 1:
- zback = zcolor_map[zback];
- break;
-
- default:
- if (zback < zcolor_NUMCOLORS)
- zback = zRGB(zcolor_map[zback]);
- break;
- }
-
-#ifdef GARGLK
- garglk_set_zcolors(zfore, zback);
-#endif /* GARGLK */
-
- curr_fg = zfore;
- curr_bg = zback;
-}
-
-void Processor::z_set_font() {
- zword font = zargs[0];
-
- switch (font) {
- case 0:
- // previous font
- temp_font = curr_font;
- curr_font = prev_font;
- prev_font = temp_font;
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- store (curr_font);
- break;
-
- case 1: /* normal font */
- prev_font = curr_font;
- curr_font = 1;
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- store (prev_font);
- break;
-
- case 4: /* fixed-pitch font*/
- prev_font = curr_font;
- curr_font = 4;
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- store (prev_font);
- break;
-
- case 2: // picture font, undefined per 1.1
- case 3: // character graphics font
- default: // unavailable
- store (0);
- break;
- }
-}
-
-void Processor::z_set_cursor() {
- cury = zargs[0];
- curx = zargs[1];
-
- if (gos_upper) {
- if (cury > mach_status_ht) {
- mach_status_ht = cury;
- reset_status_ht();
- }
-
- glk_window_move_cursor(gos_upper, curx - 1, cury - 1);
- }
-}
-
-void Processor::z_set_text_style() {
- int style;
-
- if (zargs[0] == 0)
- curstyle = 0;
- else if (zargs[0] != 0xf000) /* not tickle time */
- curstyle |= zargs[0];
-
- if (h_flags & FIXED_FONT_FLAG || curr_font == 4)
- style = curstyle | FIXED_WIDTH_STYLE;
- else
- style = curstyle;
-
- if (gos_linepending && gos_curwin == gos_linewin)
- return;
-
- if (style & REVERSE_STYLE) {
-#ifdef GARGLK
- garglk_set_reversevideo(true);
-#endif /* GARGLK */
- }
-
- if (style & FIXED_WIDTH_STYLE) {
- if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
- glk_set_style(style_BlockQuote); // monoz
- else if (style & EMPHASIS_STYLE)
- glk_set_style(style_Alert); // monoi
- else if (style & BOLDFACE_STYLE)
- glk_set_style(style_Subheader); // monob
- else
- glk_set_style(style_Preformatted); // monor
- } else {
- if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
- glk_set_style(style_Note); // propz
- else if (style & EMPHASIS_STYLE)
- glk_set_style(style_Emphasized); // propi
- else if (style & BOLDFACE_STYLE)
- glk_set_style(style_Header); // propb
- else
- glk_set_style(style_Normal); // propr
- }
-
- if (curstyle == 0) {
-#ifdef GARGLK
- garglk_set_reversevideo(false);
-#endif /* GARGLK */
- }
-}
-
-void Processor::z_set_window() {
- int win = zargs[0];
-
- if (win == 0) {
- glk_set_window(gos_lower);
- gos_curwin = gos_lower;
- } else {
- if (gos_upper)
- glk_set_window(gos_upper);
- gos_curwin = gos_upper;
- }
-
- if (win == 0)
- enable_scripting = true;
- else
- enable_scripting = false;
-
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
-}
-
-void Processor::pad_status_line(int column) {
- int spaces;
- spaces = (h_screen_cols + 1 - curx) - column;
- while (spaces-- > 0)
- print_char(' ');
-}
-
-void Processor::z_show_status() {
- zword global0;
- zword global1;
- zword global2;
- zword addr;
-
- bool brief = false;
-
- if (!gos_upper)
- return;
-
- // One V5 game (Wishbringer Solid Gold) contains this opcode by accident,
- // so just return if the version number does not fit
- if (h_version >= V4)
- return;
-
- // Read all relevant global variables from the memory of the Z-machine
- // into local variables
-
- addr = h_globals;
- LOW_WORD(addr, global0);
- addr += 2;
- LOW_WORD(addr, global1);
- addr += 2;
- LOW_WORD(addr, global2);
-
- // Move to top of the status window, and print in reverse style.
- glk_set_window(gos_upper);
- gos_curwin = gos_upper;
-
-#ifdef GARGLK
- garglk_set_reversevideo(true);
-#endif /* GARGLK */
-
- curx = cury = 1;
- glk_window_move_cursor(gos_upper, 0, 0);
-
- // If the screen width is below 55 characters then we have to use
- // the brief status line format
- if (h_screen_cols < 55)
- brief = true;
-
- // Print the object description for the global variable 0
- print_char (' ');
- print_object (global0);
-
- // A header flag tells us whether we have to display the current
- // time or the score/moves information
- if (h_config & CONFIG_TIME) {
- // print hours and minutes
- zword hours = (global1 + 11) % 12 + 1;
-
- pad_status_line (brief ? 15 : 20);
-
- print_string ("Time: ");
-
- if (hours < 10)
- print_char (' ');
- print_num (hours);
-
- print_char (':');
-
- if (global2 < 10)
- print_char ('0');
- print_num (global2);
-
- print_char (' ');
-
- print_char ((global1 >= 12) ? 'p' : 'a');
- print_char ('m');
-
- } else {
- // print score and moves
- pad_status_line (brief ? 15 : 30);
-
- print_string (brief ? "S: " : "Score: ");
- print_num (global1);
-
- pad_status_line (brief ? 8 : 14);
-
- print_string (brief ? "M: " : "Moves: ");
- print_num (global2);
- }
-
- // Pad the end of the status line with spaces
- pad_status_line (0);
-
- // Return to the lower window
- glk_set_window(gos_lower);
- gos_curwin = gos_lower;
-}
-
-void Processor::z_split_window() {
- split_window(zargs[0]);
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp
deleted file mode 100644
index 50d6425..0000000
--- a/engines/gargoyle/frotz/processor_streams.cpp
+++ /dev/null
@@ -1,786 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-#include "gargoyle/frotz/quetzal.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-zchar Processor::console_read_input(int max, zchar *buf, zword timeout, bool continued) {
- return os_read_line(max, buf, timeout, max, continued);
-}
-
-zchar Processor::console_read_key(zword timeout) {
- return os_read_key(timeout, 0);
-}
-
-void Processor::scrollback_char(zchar c) {
- if (c == ZC_INDENT)
- { scrollback_char (' '); scrollback_char (' '); scrollback_char (' '); return; }
- if (c == ZC_GAP)
- { scrollback_char (' '); scrollback_char (' '); return; }
-
- os_scrollback_char(c);
-}
-
-void Processor::scrollback_word(const zchar *s) {
- int i;
-
- for (i = 0; s[i] != 0; i++) {
- if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
- i++;
- else
- scrollback_char(s[i]);
- }
-}
-
-void Processor::scrollback_write_input(const zchar *buf, zchar key) {
- int i;
-
- for (i = 0; buf[i] != 0; i++)
- scrollback_char (buf[i]);
-
- if (key == ZC_RETURN)
- scrollback_char ('\n');
-}
-
-void Processor::scrollback_erase_input(const zchar *buf) {
- int width;
- int i;
-
- for (i = 0, width = 0; buf[i] != 0; i++)
- width++;
-
- os_scrollback_erase(width);
-
-}
-
-void Processor::stream_mssg_on() {
- flush_buffer();
-
- if (ostream_screen)
- screen_mssg_on();
- if (ostream_script && enable_scripting)
- script_mssg_on();
-
- message = true;
-}
-
-void Processor::stream_mssg_off() {
- flush_buffer();
-
- if (ostream_screen)
- screen_mssg_off();
- if (ostream_script && enable_scripting)
- script_mssg_off();
-
- message = false;
-}
-
-void Processor::stream_char(zchar c) {
- if (ostream_screen)
- screen_char(c);
- if (ostream_script && enable_scripting)
- script_char(c);
- if (enable_scripting)
- scrollback_char(c);
-}
-
-void Processor::stream_word(const zchar *s) {
- if (ostream_memory && !message)
- memory_word(s);
- else {
- if (ostream_screen)
- screen_word(s);
- if (ostream_script && enable_scripting)
- script_word(s);
- if (enable_scripting)
- scrollback_word(s);
- }
-}
-
-void Processor::stream_new_line() {
- if (ostream_memory && !message)
- memory_new_line();
- else {
- if (ostream_screen)
- screen_new_line();
- if (ostream_script && enable_scripting)
- script_new_line();
- if (enable_scripting)
- os_scrollback_char ('\n');
- }
-}
-
-zchar Processor::stream_read_key(zword timeout, zword routine, bool hot_keys) {
- zchar key = ZC_BAD;
-
- flush_buffer();
-
- // Read key from current input stream
-continue_input:
-
- do {
- if (istream_replay)
- key = replay_read_key();
- else
- key = console_read_key(timeout);
- } while (key == ZC_BAD);
-
- // Copy key to the command file
- if (ostream_record && !istream_replay)
- record_write_key(key);
-
- // Handle timeouts
- if (key == ZC_TIME_OUT)
- if (direct_call (routine) == 0)
- goto continue_input;
-
- // Return key
- return key;
-}
-
-zchar Processor::stream_read_input(int max, zchar *buf, zword timeout, zword routine,
- bool hot_keys, bool no_scripting) {
- zchar key = ZC_BAD;
- bool no_scrollback = no_scripting;
-
- if (h_version == V6 && _storyId == UNKNOWN && !ostream_script)
- no_scrollback = false;
-
- flush_buffer();
-
- // Remove initial input from the transscript file or from the screen
- if (ostream_script && enable_scripting && !no_scripting)
- script_erase_input(buf);
-
- // Read input line from current input stream
-continue_input:
-
- do {
- if (istream_replay)
- key = replay_read_input(buf);
- else
- key = console_read_input(max, buf, timeout, key != ZC_BAD);
- } while (key == ZC_BAD);
-
- // Copy input line to the command file
- if (ostream_record && !istream_replay)
- record_write_input(buf, key);
-
- // Handle timeouts
- if (key == ZC_TIME_OUT)
- if (direct_call(routine) == 0)
- goto continue_input;
-
- // Copy input line to transscript file or to the screen
- if (ostream_script && enable_scripting && !no_scripting)
- script_write_input(buf, key);
-
- // Return terminating key
- return key;
-}
-
-void Processor::script_open() {
- h_flags &= ~SCRIPTING_FLAG;
-
- frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript,
- filemode_WriteAppend);
- sfp = glk_stream_open_file(fref, filemode_WriteAppend);
-
- if (sfp != nullptr) {
- sfp->setPosition(0, seekmode_End);
-
- h_flags |= SCRIPTING_FLAG;
-
- script_valid = true;
- ostream_script = true;
-
- script_width = 0;
- } else {
- print_string("Cannot open file\n");
- }
-
- SET_WORD(H_FLAGS, h_flags);
-}
-
-void Processor::script_close() {
- h_flags &= ~SCRIPTING_FLAG;
- SET_WORD(H_FLAGS, h_flags);
-
- glk_stream_close(sfp);
- ostream_script = false;
-}
-
-void Processor::script_new_line() {
- script_char('\n');
- script_width = 0;
-}
-
-void Processor::script_char(zchar c) {
- if (c == ZC_INDENT && script_width != 0)
- c = ' ';
-
- if (c == ZC_INDENT) {
- script_char(' ');
- script_char(' ');
- script_char(' ');
- return;
- }
- if (c == ZC_GAP) {
- script_char(' ');
- script_char(' ');
- return;
- }
-
- sfp->putCharUni(c);
- script_width++;
-}
-
-void Processor::script_word(const zchar *s) {
- int width;
- int i;
-
- if (*s == ZC_INDENT && script_width != 0)
- script_char(*s++);
-
- for (i = 0, width = 0; s[i] != 0; i++) {
- if (s[i] == ZC_NEW_STYLE || s[i] == ZC_NEW_FONT)
- i++;
- else if (s[i] == ZC_GAP)
- width += 3;
- else if (s[i] == ZC_INDENT)
- width += 2;
- else
- width += 1;
- }
-
- if (_script_cols != 0 && script_width + width > _script_cols) {
- if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
- s++;
-
- script_new_line();
- }
-
- for (i = 0; s[i] != 0; i++) {
- if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE)
- i++;
- else
- script_char(s[i]);
- }
-}
-
-void Processor::script_write_input(const zchar *buf, zchar key) {
- int width;
- int i;
-
- for (i = 0, width = 0; buf[i] != 0; i++)
- width++;
-
- if (_script_cols != 0 && script_width + width > _script_cols)
- script_new_line();
-
- for (i = 0; buf[i] != 0; i++)
- script_char(buf[i]);
-
- if (key == ZC_RETURN)
- script_new_line();
-}
-
-void Processor::script_erase_input(const zchar *buf) {
- int width;
- int i;
-
- for (i = 0, width = 0; buf[i] != 0; i++)
- width++;
-
- sfp->setPosition(-width, seekmode_Current);
- script_width -= width;
-}
-
-void Processor::script_mssg_on() {
- if (script_width != 0)
- script_new_line();
-
- script_char(ZC_INDENT);
-}
-
-void Processor::script_mssg_off() {
- script_new_line();
-}
-
-void Processor::record_open() {
- frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, filemode_Write);
- if ((rfp = glk_stream_open_file(fref, filemode_Write)) != nullptr)
- ostream_record = true;
- else
- print_string("Cannot open file\n");
-}
-
-void Processor::record_close() {
- glk_stream_close(rfp);
- ostream_record = false;
-}
-
-void Processor::record_code(int c, bool force_encoding) {
- if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) {
- int i;
-
- rfp->putChar('[');
-
- for (i = 10000; i != 0; i /= 10)
- if (c >= i || i == 1)
- rfp->putChar('0' + (c / i) % 10);
-
- rfp->putChar(']');
- } else {
- rfp->putChar(c);
- }
-}
-
-void Processor::record_char(zchar c) {
- if (c != ZC_RETURN) {
- if (c < ZC_HKEY_MIN || c > ZC_HKEY_MAX) {
- record_code(translate_to_zscii(c), false);
- if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
- record_code(mouse_x, true);
- record_code(mouse_y, true);
- }
- } else {
- record_code(1000 + c - ZC_HKEY_MIN, true);
- }
- }
-}
-
-void Processor::record_write_key(zchar key) {
- record_char(key);
- rfp->putChar('\n');
-}
-
-void Processor::record_write_input(const zchar *buf, zchar key) {
- zchar c;
-
- while ((c = *buf++) != 0)
- record_char(c);
-
- record_write_key(key);
-}
-
-void Processor::replay_open() {
- frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, filemode_Read);
- if ((pfp = glk_stream_open_file(fref, filemode_Read)) != nullptr)
- istream_replay = true;
- else
- print_string("Cannot open file\n");
-}
-
-void Processor::replay_close() {
- glk_stream_close(pfp);
- istream_replay = false;
-}
-
-int Processor::replay_code() {
- int c;
-
- if ((c = pfp->getChar()) == '[') {
- int c2;
-
- c = 0;
-
- while ((c2 = pfp->getChar()) != EOF && c2 >= '0' && c2 <= '9')
- c = 10 * c + c2 - '0';
-
- return (c2 == ']') ? c : EOF;
- } else {
- return c;
- }
-}
-
-zchar Processor::replay_char() {
- int c;
-
- if ((c = replay_code()) != EOF) {
- if (c != '\n') {
- if (c < 1000) {
-
- c = translate_from_zscii(c);
-
- if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) {
- mouse_x = replay_code();
- mouse_y = replay_code();
- }
-
- return c;
- } else {
- return ZC_HKEY_MIN + c - 1000;
- }
- }
-
- pfp->unputBuffer("\n", 1);
- return ZC_RETURN;
-
- } else {
- return ZC_BAD;
- }
-}
-
-zchar Processor::replay_read_key() {
- zchar key = replay_char();
-
- if (pfp->getChar() != '\n') {
- replay_close();
- return ZC_BAD;
- } else {
- return key;
- }
-}
-
-zchar Processor::replay_read_input(zchar *buf) {
- zchar c;
-
- for (;;) {
- c = replay_char();
-
- if (c == ZC_BAD || is_terminator(c))
- break;
-
- *buf++ = c;
- }
-
- *buf = 0;
-
- if (pfp->getChar() != '\n') {
- replay_close();
- return ZC_BAD;
- } else {
- return c;
- }
-}
-
-
-void Processor::z_input_stream() {
- flush_buffer();
-
- if (zargs[0] == 0 && istream_replay)
- replay_close();
- if (zargs[0] == 1 && !istream_replay)
- replay_open();
-}
-
-void Processor::z_output_stream() {
- flush_buffer();
-
- switch ((short) zargs[0]) {
- case 1: ostream_screen = true;
- break;
- case -1: ostream_screen = false;
- break;
- case 2: if (!ostream_script) script_open();
- break;
- case -2: if (ostream_script) script_close();
- break;
- case 3: memory_open(zargs[1], zargs[2], zargc >= 3);
- break;
- case -3: memory_close();
- break;
- case 4: if (!ostream_record) record_open();
- break;
- case -4: if (ostream_record) record_close();
- break;
- default:
- break;
- }
-}
-
-void Processor::z_restart() {
- flush_buffer();
-
- os_restart_game(RESTART_BEGIN);
-
- seed_random(0);
-
- if (!first_restart) {
- story_fp->seek(blorb_ofs);
-
- if (story_fp->read(zmp, h_dynamic_size) != h_dynamic_size)
- error("Story file read error");
-
- } else {
- first_restart = false;
- }
-
- restart_header();
- restart_screen();
-
- _sp = _fp = _stack + STACK_SIZE;
- _frameCount = 0;
-
- if (h_version != V6 && h_version != V9) {
- long pc = (long)h_start_pc;
- SET_PC(pc);
- } else {
- call(h_start_pc, 0, nullptr, 0);
- }
-
- os_restart_game(RESTART_END);
-}
-
-void Processor::z_save() {
-#ifdef TODO
- bool success = false;
-
- if (zargc != 0) {
- // Open auxilary file
- frefid_t ref = glk_fileref_create_by_prompt(fileusage_Data | fileusage_BinaryMode,
- filemode_Write, 0);
- if (ref == nullptr)
- goto finished;
-
- // Write data
- strid_t f = glk_stream_open_file(ref, filemode_Write);
-
- glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
-
- glk_stream_close(f);
-
- } else {
- long pc;
- zword addr;
- zword nsp, nfp;
- int skip;
- int i;
-
- /* Open game file */
-
- if ((gfp = frotzopenprompt (FILE_SAVE)) == nullptr)
- goto finished;
-
- if (_save_quetzal) {
- success = save_quetzal (gfp, story_fp, blorb_ofs);
- } else {
- /* Write game file */
-
- fputc ((int) hi (h_release), gfp);
- fputc ((int) lo (h_release), gfp);
- fputc ((int) hi (h_checksum), gfp);
- fputc ((int) lo (h_checksum), gfp);
-
- GET_PC (pc)
-
- fputc ((int) (pc >> 16) & 0xff, gfp);
- fputc ((int) (pc >> 8) & 0xff, gfp);
- fputc ((int) (pc) & 0xff, gfp);
-
- nsp = (int) (_sp - _stack);
- nfp = (int) (_fp - _stack);
-
- fputc ((int) hi (nsp), gfp);
- fputc ((int) lo (nsp), gfp);
- fputc ((int) hi (nfp), gfp);
- fputc ((int) lo (nfp), gfp);
-
- for (i = nsp; i < STACK_SIZE; i++) {
- fputc ((int) hi (_stack[i]), gfp);
- fputc ((int) lo (_stack[i]), gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
- if (zmp[addr] != fgetc (story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
- fputc (skip, gfp);
- fputc (zmp[addr], gfp);
- skip = 0;
- } else skip++;
- }
-
- /* Close game file and check for errors */
-
- if (fclose (gfp) == EOF || ferror (story_fp)) {
- print_string ("Error writing save file\n");
- goto finished;
- }
-
- /* Success */
-
- success = 1;
-
- }
-
-finished:
-
- if (h_version <= V3)
- branch (success);
- else
- store (success);
-#endif
-}
-
-void Processor::z_restore() {
-#ifdef TODO
- FILE *gfp;
-
- zword success = 0;
-
- if (zargc != 0) {
-
- /* Get the file name */
-
- /* Open auxilary file */
-
- if ((gfp = frotzopenprompt(FILE_LOAD_AUX)) == nullptr)
- goto finished;
-
- /* Load auxilary file */
-
- success = fread (zmp + zargs[0], 1, zargs[1], gfp);
-
- /* Close auxilary file */
-
- fclose (gfp);
-
- } else {
-
- long pc;
- zword release;
- zword addr;
- int i;
-
- /* Open game file */
-
- if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
- goto finished;
-
- if (_save_quetzal) {
- success = restore_quetzal (gfp, story_fp, blorb_ofs);
-
- } else {
- /* Load game file */
-
- release = (unsigned) fgetc (gfp) << 8;
- release |= fgetc (gfp);
-
- () fgetc (gfp);
- () fgetc (gfp);
-
- /* Check the release number */
-
- if (release == h_release) {
-
- pc = (long) fgetc (gfp) << 16;
- pc |= (unsigned) fgetc (gfp) << 8;
- pc |= fgetc (gfp);
-
- SET_PC (pc);
-
- _sp = _stack + (fgetc (gfp) << 8);
- _sp += fgetc (gfp);
- _fp = _stack + (fgetc (gfp) << 8);
- _fp += fgetc (gfp);
-
- for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
- _stack[i] = (unsigned) fgetc (gfp) << 8;
- _stack[i] |= fgetc (gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0; addr < h_dynamic_size; addr++) {
- int skip = fgetc (gfp);
- for (i = 0; i < skip; i++)
- zmp[addr++] = fgetc (story_fp);
- zmp[addr] = fgetc (gfp);
- () fgetc (story_fp);
- }
-
- /* Check for errors */
-
- if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
- success = -1;
- else
-
- /* Success */
-
- success = 2;
-
- } else print_string ("Invalid save file\n");
- }
-
- if ((short) success >= 0) {
-
- /* Close game file */
-
- fclose (gfp);
-
- if ((short) success > 0) {
- zbyte old_screen_rows;
- zbyte old_screen_cols;
-
- /* In V3, reset the upper window. */
- if (h_version == V3)
- split_window (0);
-
- LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
- LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
-
- /* Reload cached header fields. */
- restart_header ();
-
- /*
- * Since QUETZAL files may be saved on many different machines,
- * the screen sizes may vary a lot. Erasing the status window
- * seems to cover up most of the resulting badness.
- */
- if (h_version > V3 && h_version != V6
- && (h_screen_rows != old_screen_rows
- || h_screen_cols != old_screen_cols))
- erase_window (1);
- }
- } else
- os_fatal ("Error reading save file");
- }
-
-finished:
-
- if (h_version <= V3)
- branch (success);
- else
- store (success);
-#endif
-}
-
-void Processor::z_verify() {
- zword checksum = 0;
-
- // Sum all bytes in story file except header bytes
- story_fp->seek(blorb_ofs + 64);
-
- for (uint i = 64; i < story_size; i++)
- checksum += story_fp->readByte();
-
- // Branch if the checksums are equal
- branch(checksum == h_checksum);
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_table.cpp b/engines/gargoyle/frotz/processor_table.cpp
deleted file mode 100644
index d449062..0000000
--- a/engines/gargoyle/frotz/processor_table.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-void Processor::z_copy_table() {
- zword addr;
- zword size = zargs[2];
- zbyte value;
- int i;
-
- if (zargs[1] == 0) /* zero table */
-
- for (i = 0; i < size; i++)
- storeb((zword) (zargs[0] + i), 0);
-
- else if ((short) size < 0 || zargs[0] > zargs[1]) /* copy forwards */
-
- for (i = 0; i < (((short) size < 0) ? - (short) size : size); i++) {
- addr = zargs[0] + i;
- LOW_BYTE(addr, value);
- storeb((zword) (zargs[1] + i), value);
- } else {
- // copy backwards
- for (i = size - 1; i >= 0; i--) {
- addr = zargs[0] + i;
- LOW_BYTE(addr, value);
- storeb((zword) (zargs[1] + i), value);
- }
- }
-}
-
-void Processor::z_loadb() {
- zword addr = zargs[0] + zargs[1];
- zbyte value;
-
- LOW_BYTE(addr, value);
-
- store(value);
-}
-
-void Processor::z_loadw() {
- zword addr = zargs[0] + 2 * zargs[1];
- zword value;
-
- LOW_WORD(addr, value);
-
- store(value);
-}
-
-void Processor::z_scan_table() {
- zword addr = zargs[1];
- int i;
-
- // Supply default arguments
- if (zargc < 4)
- zargs[3] = 0x82;
-
- // Scan byte or word array
- for (i = 0; i < zargs[2]; i++) {
- if (zargs[3] & 0x80) {
- // scan word array
- zword wvalue;
-
- LOW_WORD(addr, wvalue);
-
- if (wvalue == zargs[0])
- goto finished;
- } else {
- // scan byte array
- zbyte bvalue;
-
- LOW_BYTE(addr, bvalue);
-
- if (bvalue == zargs[0])
- goto finished;
- }
-
- addr += zargs[3] & 0x7f;
- }
-
- addr = 0;
-
-finished:
- store(addr);
- branch(addr);
-}
-
-void Processor::z_storeb() {
- storeb((zword) (zargs[0] + zargs[1]), zargs[2]);
-}
-
-void Processor::z_storew() {
- storew((zword)(zargs[0] + 2 * zargs[1]), zargs[2]);
-}
-
-} // End of namespace Scott
-} // End of namespace Gargoyle
diff --git a/engines/gargoyle/frotz/processor_text.cpp b/engines/gargoyle/frotz/processor_text.cpp
deleted file mode 100644
index 0852dc4..0000000
--- a/engines/gargoyle/frotz/processor_text.cpp
+++ /dev/null
@@ -1,886 +0,0 @@
-/* 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.
- *
- */
-
-#include "gargoyle/frotz/processor.h"
-
-namespace Gargoyle {
-namespace Frotz {
-
-zchar Processor::ZSCII_TO_LATIN1[] = {
- 0x0e4, 0x0f6, 0x0fc, 0x0c4, 0x0d6, 0x0dc, 0x0df, 0x0bb,
- 0x0ab, 0x0eb, 0x0ef, 0x0ff, 0x0cb, 0x0cf, 0x0e1, 0x0e9,
- 0x0ed, 0x0f3, 0x0fa, 0x0fd, 0x0c1, 0x0c9, 0x0cd, 0x0d3,
- 0x0da, 0x0dd, 0x0e0, 0x0e8, 0x0ec, 0x0f2, 0x0f9, 0x0c0,
- 0x0c8, 0x0cc, 0x0d2, 0x0d9, 0x0e2, 0x0ea, 0x0ee, 0x0f4,
- 0x0fb, 0x0c2, 0x0ca, 0x0ce, 0x0d4, 0x0db, 0x0e5, 0x0c5,
- 0x0f8, 0x0d8, 0x0e3, 0x0f1, 0x0f5, 0x0c3, 0x0d1, 0x0d5,
- 0x0e6, 0x0c6, 0x0e7, 0x0c7, 0x0fe, 0x0f0, 0x0de, 0x0d0,
- 0x0a3, 0x153, 0x152, 0x0a1, 0x0bf
-};
-
-zchar Processor::translate_from_zscii(zbyte c) {
- if (c == 0xfc)
- return ZC_MENU_CLICK;
- if (c == 0xfd)
- return ZC_DOUBLE_CLICK;
- if (c == 0xfe)
- return ZC_SINGLE_CLICK;
-
- if (c >= 0x9b && _storyId != BEYOND_ZORK) {
- if (hx_unicode_table != 0) {
- // game has its own Unicode table
- zbyte N;
- LOW_BYTE(hx_unicode_table, N);
-
- if (c - 0x9b < N) {
- zword addr = hx_unicode_table + 1 + 2 * (c - 0x9b);
- zword unicode;
-
- LOW_WORD(addr, unicode);
-
- if (unicode < 0x20)
- return '?';
-
- return unicode;
- } else {
- return '?';
- }
- } else {
- // game uses standard set
- if (c <= 0xdf) {
- return ZSCII_TO_LATIN1[c - 0x9b];
- } else {
- return '?';
- }
- }
- }
-
- return (zchar)c;
-}
-
-zbyte Processor::unicode_to_zscii(zchar c) {
- int i;
-
- if (c >= ZC_LATIN1_MIN) {
- if (hx_unicode_table != 0) {
- // game has its own Unicode table
- zbyte N;
- LOW_BYTE(hx_unicode_table, N);
-
- for (i = 0x9b; i < 0x9b + N; i++) {
- zword addr = hx_unicode_table + 1 + 2 * (i - 0x9b);
- zword unicode;
-
- LOW_WORD(addr, unicode);
-
- if (c == unicode)
- return (zbyte) i;
Commit: a2104deb4cefdcf0cd6bb3a66ef09bb46cba3f66
https://github.com/scummvm/scummvm/commit/a2104deb4cefdcf0cd6bb3a66ef09bb46cba3f66
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Changing class and namespaces from Gargoyle to Glk
Changed paths:
A engines/glk/glk_api.cpp
A engines/glk/glk_api.h
R engines/glk/gargoyle.cpp
R engines/glk/gargoyle.h
engines/glk/blorb.cpp
engines/glk/blorb.h
engines/glk/conf.cpp
engines/glk/conf.h
engines/glk/detection.cpp
engines/glk/detection_tables.h
engines/glk/events.cpp
engines/glk/events.h
engines/glk/fonts.cpp
engines/glk/fonts.h
engines/glk/frotz/detection.cpp
engines/glk/frotz/detection.h
engines/glk/frotz/detection_tables.cpp
engines/glk/frotz/detection_tables.h
engines/glk/frotz/frotz.cpp
engines/glk/frotz/frotz.h
engines/glk/frotz/frotz_types.h
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/frotz/mem.cpp
engines/glk/frotz/mem.h
engines/glk/frotz/processor.cpp
engines/glk/frotz/processor.h
engines/glk/frotz/processor_buffer.cpp
engines/glk/frotz/processor_input.cpp
engines/glk/frotz/processor_maths.cpp
engines/glk/frotz/processor_mem.cpp
engines/glk/frotz/processor_objects.cpp
engines/glk/frotz/processor_screen.cpp
engines/glk/frotz/processor_streams.cpp
engines/glk/frotz/processor_table.cpp
engines/glk/frotz/processor_text.cpp
engines/glk/frotz/processor_variables.cpp
engines/glk/frotz/quetzal.cpp
engines/glk/frotz/quetzal.h
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/glk_types.h
engines/glk/module.mk
engines/glk/picture.cpp
engines/glk/picture.h
engines/glk/scott/detection.cpp
engines/glk/scott/detection.h
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
engines/glk/screen.cpp
engines/glk/screen.h
engines/glk/selection.cpp
engines/glk/selection.h
engines/glk/speech.h
engines/glk/streams.cpp
engines/glk/streams.h
engines/glk/time.cpp
engines/glk/time.h
engines/glk/unicode.cpp
engines/glk/unicode.h
engines/glk/unicode_gen.cpp
engines/glk/unicode_gen.h
engines/glk/utils.cpp
engines/glk/utils.h
engines/glk/window_graphics.cpp
engines/glk/window_graphics.h
engines/glk/window_pair.cpp
engines/glk/window_pair.h
engines/glk/window_text_buffer.cpp
engines/glk/window_text_buffer.h
engines/glk/window_text_grid.cpp
engines/glk/window_text_grid.h
engines/glk/windows.cpp
engines/glk/windows.h
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 24340fa..e298e1c 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -22,7 +22,7 @@
#include "glk/blorb.h"
-namespace Gargoyle {
+namespace Glk {
#define giblorb_Inited_Magic 0xB7012BEDU
@@ -540,4 +540,4 @@ bool Blorb::giblorb_is_resource_map(void) const {
return _map != nullptr;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/blorb.h b/engines/glk/blorb.h
index 75f811c..352d01a 100644
--- a/engines/glk/blorb.h
+++ b/engines/glk/blorb.h
@@ -26,7 +26,7 @@
#include "glk/glk_types.h"
#include "glk/streams.h"
-namespace Gargoyle {
+namespace Glk {
/**
@@ -141,6 +141,6 @@ public:
glui32 usage, glui32 *num, glui32 *min, glui32 *max);
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/conf.cpp b/engines/glk/conf.cpp
index 45d6168..ae99e6b 100644
--- a/engines/glk/conf.cpp
+++ b/engines/glk/conf.cpp
@@ -27,7 +27,7 @@
#include "common/config-manager.h"
#include "common/system.h"
-namespace Gargoyle {
+namespace Glk {
const byte WHITE[3] = { 0xff, 0xff, 0xff };
const byte BLUE[3] = { 0x00, 0x00, 0x60 };
@@ -251,4 +251,4 @@ void Conf::parseColor(const Common::String &str, byte *color) {
}
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/conf.h b/engines/glk/conf.h
index 6c9dbf9..fb68427 100644
--- a/engines/glk/conf.h
+++ b/engines/glk/conf.h
@@ -27,7 +27,7 @@
#include "glk/fonts.h"
#include "glk/windows.h"
-namespace Gargoyle {
+namespace Glk {
class Conf {
private:
@@ -131,6 +131,6 @@ public:
extern Conf *g_conf;
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index 9266825..893ed87 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "base/plugins.h"
#include "common/md5.h"
@@ -34,44 +34,44 @@
#define MAX_SAVES 99
-namespace Gargoyle {
+namespace Glk {
-struct GargoyleGameDescription {
+struct GlkGameDescription {
ADGameDescription _desc;
Common::String _filename;
InterpreterType _interpType;
Common::String _md5;
};
-const Common::String &GargoyleEngine::getFilename() const {
+const Common::String &GlkEngine::getFilename() const {
return _gameDescription->_filename;
}
-uint32 GargoyleEngine::getFeatures() const {
+uint32 GlkEngine::getFeatures() const {
return _gameDescription->_desc.flags;
}
-bool GargoyleEngine::isDemo() const {
+bool GlkEngine::isDemo() const {
return (bool)(_gameDescription->_desc.flags & ADGF_DEMO);
}
-Common::Language GargoyleEngine::getLanguage() const {
+Common::Language GlkEngine::getLanguage() const {
return _gameDescription->_desc.language;
}
-InterpreterType GargoyleEngine::getInterpreterType() const {
+InterpreterType GlkEngine::getInterpreterType() const {
return _gameDescription->_interpType;
}
-const Common::String &GargoyleEngine::getGameMD5() const {
+const Common::String &GlkEngine::getGameMD5() const {
return _gameDescription->_md5;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
#include "glk/frotz/detection_tables.h"
-#define ZCODE(ID, NAME) { ID, Gargoyle::Frotz::NAME##_DESC }
+#define ZCODE(ID, NAME) { ID, Glk::Frotz::NAME##_DESC }
-static const PlainGameDescriptor gargoyleGames[] = {
+static const PlainGameDescriptor glkGames[] = {
{"zcode", "Zcode Games" },
{"scottadams", "Scott Adams Games"},
@@ -146,9 +146,9 @@ static const PlainGameDescriptor gargoyleGames[] = {
#include "glk/scott/detection.h"
#include "glk/scott/scott.h"
-class GargoyleMetaEngine : public AdvancedMetaEngine {
+class GlkMetaEngine : public AdvancedMetaEngine {
public:
- GargoyleMetaEngine() : AdvancedMetaEngine(Gargoyle::gameDescriptions, sizeof(Gargoyle::GargoyleGameDescription), gargoyleGames) {
+ GlkMetaEngine() : AdvancedMetaEngine(Glk::gameDescriptions, sizeof(Glk::GlkGameDescription), glkGames) {
_maxScanDepth = 3;
}
@@ -172,7 +172,7 @@ public:
virtual ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override;
};
-bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
+bool GlkMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
@@ -183,22 +183,22 @@ bool GargoyleMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSimpleSavesNames);
}
-bool Gargoyle::GargoyleEngine::hasFeature(EngineFeature f) const {
+bool Glk::GlkEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsRTL) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
-bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- const Gargoyle::GargoyleGameDescription *gd = (const Gargoyle::GargoyleGameDescription *)desc;
+bool GlkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Glk::GlkGameDescription *gd = (const Glk::GlkGameDescription *)desc;
switch (gd->_interpType) {
- case Gargoyle::INTERPRETER_FROTZ:
- *engine = new Gargoyle::Frotz::Frotz(syst, gd);
+ case Glk::INTERPRETER_FROTZ:
+ *engine = new Glk::Frotz::Frotz(syst, gd);
break;
- case Gargoyle::INTERPRETER_SCOTT:
- *engine = new Gargoyle::Scott::Scott(syst, gd);
+ case Glk::INTERPRETER_SCOTT:
+ *engine = new Glk::Scott::Scott(syst, gd);
break;
default:
error("Unknown interpreter");
@@ -207,12 +207,12 @@ bool GargoyleMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD
return gd != 0;
}
-SaveStateList GargoyleMetaEngine::listSaves(const char *target) const {
+SaveStateList GlkMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
Common::String saveDesc;
Common::String pattern = Common::String::format("%s.0##", target);
- Gargoyle::SavegameHeader header;
+ Glk::SavegameHeader header;
filenames = saveFileMan->listSavefiles(pattern);
@@ -225,7 +225,7 @@ SaveStateList GargoyleMetaEngine::listSaves(const char *target) const {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- if (Gargoyle::FileStream::readSavegameHeader(in, header))
+ if (Glk::FileStream::readSavegameHeader(in, header))
saveList.push_back(SaveStateDescriptor(slot, header._saveName));
delete in;
@@ -238,22 +238,22 @@ SaveStateList GargoyleMetaEngine::listSaves(const char *target) const {
return saveList;
}
-int GargoyleMetaEngine::getMaximumSaveSlot() const {
+int GlkMetaEngine::getMaximumSaveSlot() const {
return MAX_SAVES;
}
-void GargoyleMetaEngine::removeSaveState(const char *target, int slot) const {
+void GlkMetaEngine::removeSaveState(const char *target, int slot) const {
Common::String filename = Common::String::format("%s.%03d", target, slot);
g_system->getSavefileManager()->removeSavefile(filename);
}
-SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+SaveStateDescriptor GlkMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::String filename = Common::String::format("%s.%03d", target, slot);
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename);
if (in) {
- Gargoyle::SavegameHeader header;
- if (Gargoyle::FileStream::readSavegameHeader(in, header)) {
+ Glk::SavegameHeader header;
+ if (Glk::FileStream::readSavegameHeader(in, header)) {
// Create the return descriptor
SaveStateDescriptor desc(slot, header._saveName);
desc.setSaveDate(header._year, header._month, header._day);
@@ -268,17 +268,17 @@ SaveStateDescriptor GargoyleMetaEngine::querySaveMetaInfos(const char *target, i
return SaveStateDescriptor();
}
-DetectedGames GargoyleMetaEngine::detectGames(const Common::FSList &fslist) const {
+DetectedGames GlkMetaEngine::detectGames(const Common::FSList &fslist) const {
DetectedGames detectedGames;
- Gargoyle::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
- Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
+ Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
+ Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
return detectedGames;
}
-static Gargoyle::GargoyleGameDescription gameDescription;
+static Glk::GlkGameDescription gameDescription;
-ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
+ADDetectedGames GlkMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
static char gameId[100];
strcpy(gameId, ConfMan.get("gameid").c_str());
Common::String filename = ConfMan.get("filename");
@@ -290,10 +290,10 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
Common::File f;
// Check each sub-engine for any detected games
- if (Gargoyle::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames))
- gameDescription._interpType = Gargoyle::INTERPRETER_FROTZ;
- else if (Gargoyle::Scott::ScottMetaEngine::detectGames(fslist, detectedGames))
- gameDescription._interpType = Gargoyle::INTERPRETER_SCOTT;
+ if (Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames))
+ gameDescription._interpType = Glk::INTERPRETER_FROTZ;
+ else if (Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames))
+ gameDescription._interpType = Glk::INTERPRETER_SCOTT;
else
// No match found, so return no results
return results;
@@ -317,7 +317,7 @@ ADDetectedGames GargoyleMetaEngine::detectGame(const Common::FSNode &parent, con
}
#if PLUGIN_ENABLED_DYNAMIC(GLK)
-REGISTER_PLUGIN_DYNAMIC(GLK, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
+REGISTER_PLUGIN_DYNAMIC(GLK, PLUGIN_TYPE_ENGINE, GlkMetaEngine);
#else
-REGISTER_PLUGIN_STATIC(GLK, PLUGIN_TYPE_ENGINE, GargoyleMetaEngine);
+REGISTER_PLUGIN_STATIC(GLK, PLUGIN_TYPE_ENGINE, GlkMetaEngine);
#endif
diff --git a/engines/glk/detection_tables.h b/engines/glk/detection_tables.h
index 30491f6..47a761e 100644
--- a/engines/glk/detection_tables.h
+++ b/engines/glk/detection_tables.h
@@ -20,10 +20,10 @@
*
*/
-namespace Gargoyle {
+namespace Glk {
-static const GargoyleGameDescription gameDescriptions[] = {
+static const GlkGameDescription gameDescriptions[] = {
{ AD_TABLE_END_MARKER, "", (InterpreterType)0, "" }
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/events.cpp b/engines/glk/events.cpp
index 74a108e..8f3d5ef 100644
--- a/engines/glk/events.cpp
+++ b/engines/glk/events.cpp
@@ -22,13 +22,13 @@
#include "glk/events.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/screen.h"
#include "glk/selection.h"
#include "glk/windows.h"
#include "graphics/cursorman.h"
-namespace Gargoyle {
+namespace Glk {
const byte ARROW[] = {
// byte 1: number of skipped pixels
@@ -399,4 +399,4 @@ bool Events::isTimerExpired() const {
return _timerMilli && g_system->getMillis() >= _timerTimeExpiry;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/events.h b/engines/glk/events.h
index 537813f..f68fca9 100644
--- a/engines/glk/events.h
+++ b/engines/glk/events.h
@@ -27,7 +27,7 @@
#include "graphics/surface.h"
#include "glk/utils.h"
-namespace Gargoyle {
+namespace Glk {
#define GAME_FRAME_RATE 100
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
@@ -286,6 +286,6 @@ public:
bool isTimerExpired() const;
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/fonts.cpp b/engines/glk/fonts.cpp
index ee958b0..bc699af 100644
--- a/engines/glk/fonts.cpp
+++ b/engines/glk/fonts.cpp
@@ -23,13 +23,13 @@
#include "glk/fonts.h"
#include "glk/glk_types.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "common/memstream.h"
#include "common/unzip.h"
#include "graphics/fonts/ttf.h"
#include "graphics/fontman.h"
-namespace Gargoyle {
+namespace Glk {
#define FONTS_VERSION 1.0
#define FONTS_FILENAME "fonts.dat"
@@ -154,4 +154,4 @@ size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw
return font->getStringWidth(text) * GLI_SUBPIX;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/fonts.h b/engines/glk/fonts.h
index db547aa..364b023 100644
--- a/engines/glk/fonts.h
+++ b/engines/glk/fonts.h
@@ -32,7 +32,7 @@
#include "common/ustr.h"
#include "graphics/font.h"
-namespace Gargoyle {
+namespace Glk {
#define FONTS_TOTAL 8
@@ -113,6 +113,6 @@ public:
size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = 0);
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 57965c8..36303d4 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -26,7 +26,7 @@
#include "glk/frotz/detection_tables.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
@@ -77,4 +77,4 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
}
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/detection.h b/engines/glk/frotz/detection.h
index 7630cb3..9cd9373 100644
--- a/engines/glk/frotz/detection.h
+++ b/engines/glk/frotz/detection.h
@@ -26,7 +26,7 @@
#include "common/fs.h"
#include "engines/game.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
class FrotzMetaEngine {
@@ -38,6 +38,6 @@ public:
};
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/detection_tables.cpp b/engines/glk/frotz/detection_tables.cpp
index 3f619a5..f52b099 100644
--- a/engines/glk/frotz/detection_tables.cpp
+++ b/engines/glk/frotz/detection_tables.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/detection_tables.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
const char *const AMFV_DESC = "A Mind Forever Voyaging";
@@ -82,4 +82,4 @@ const FrotzGameDescription FROTZ_GAMES[] = {
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index 48e0eb0..51994ed 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -23,7 +23,7 @@
#include "engines/advancedDetector.h"
#include "common/language.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
/**
@@ -82,4 +82,4 @@ extern const char *const ZORK3_DESC;
extern const char *const ZTUU_DESC;
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 0e516f0..f30acd0 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -24,12 +24,12 @@
#include "glk/frotz/frotz_types.h"
#include "common/config-manager.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
Frotz *g_vm;
-Frotz::Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+Frotz::Frotz(OSystem *syst, const GlkGameDescription *gameDesc) :
Processor(syst, gameDesc) {
g_vm = this;
}
@@ -95,4 +95,4 @@ Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index c1fe5dc..cecd886 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -25,7 +25,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
/**
@@ -36,7 +36,7 @@ public:
/**
* Constructor
*/
- Frotz(OSystem *syst, const GargoyleGameDescription *gameDesc);
+ Frotz(OSystem *syst, const GlkGameDescription *gameDesc);
/**
* Destructor
@@ -67,6 +67,6 @@ public:
extern Frotz *g_vm;
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/frotz_types.h b/engines/glk/frotz/frotz_types.h
index 5aae3d0..e68f55e 100644
--- a/engines/glk/frotz/frotz_types.h
+++ b/engines/glk/frotz/frotz_types.h
@@ -26,7 +26,7 @@
#include "glk/glk_types.h"
#include "common/algorithm.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
#define MAX_UNDO_SLOTS 500
@@ -292,6 +292,6 @@ struct Redirect {
};
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index b253438..da27382 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -22,11 +22,11 @@
#include "glk/frotz/glk_interface.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
-GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- Glk(syst, gameDesc),
+GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription *gameDesc) :
+ GlkAPI(syst, gameDesc),
oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
@@ -495,4 +495,4 @@ zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, in
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index e3fa2c9..d78d49f 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -23,10 +23,10 @@
#ifndef GLK_FROTZ_GLK_INTERFACE
#define GLK_FROTZ_GLK_INTERFACE
-#include "glk/glk.h"
+#include "glk/glk_api.h"
#include "glk/frotz/mem.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
enum SoundEffect {
@@ -47,7 +47,7 @@ enum RestartAction {
* Implements an intermediate interface on top of the GLK layer, providing screen
* and sound effect handling
*/
-class GlkInterface : public Glk, public virtual UserOptions, public virtual Mem {
+class GlkInterface : public GlkAPI, public virtual UserOptions, public virtual Mem {
public:
zchar statusline[256];
int oldstyle;
@@ -181,7 +181,7 @@ public:
/**
* Constructor
*/
- GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc);
+ GlkInterface(OSystem *syst, const GlkGameDescription *gameDesc);
/**
* Initialization
@@ -190,6 +190,6 @@ public:
};
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index a7747f5..378e496 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -25,7 +25,7 @@
#include "common/memstream.h"
#include "common/textconsole.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
const Header::StoryEntry Header::RECORDS[25] = {
@@ -416,4 +416,4 @@ void Mem::mem_undiff(zbyte *diff, long diff_length, zbyte *dest) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/mem.h b/engines/glk/frotz/mem.h
index de22006..43b2727 100644
--- a/engines/glk/frotz/mem.h
+++ b/engines/glk/frotz/mem.h
@@ -25,7 +25,7 @@
#include "glk/frotz/frotz_types.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
#define SET_WORD(addr,v) zmp[addr] = hi(v); zmp[addr+1] = lo(v)
@@ -275,6 +275,6 @@ public:
};
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index 1cdc67a..a7cbad0 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -23,7 +23,7 @@
#include "glk/frotz/processor.h"
#include "glk/frotz/frotz.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
// TODO: Stubs to replace with actual code
@@ -131,7 +131,7 @@ Opcode Processor::ext_opcodes[64] = {
&Processor::z_buffer_screen, // spec 1.1
};
-Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
+Processor::Processor(OSystem *syst, const GlkGameDescription *gameDesc) :
GlkInterface(syst, gameDesc),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
@@ -661,4 +661,4 @@ void Processor::z_restore_undo(void) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index b5c113d..4bd9d2c 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -28,7 +28,7 @@
#include "glk/frotz/frotz_types.h"
#include "common/stack.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
#define TEXT_BUFFER_SIZE 200
@@ -1522,7 +1522,7 @@ public:
/**
* Constructor
*/
- Processor(OSystem *syst, const GargoyleGameDescription *gameDesc);
+ Processor(OSystem *syst, const GlkGameDescription *gameDesc);
/**
* Initialization
@@ -1579,6 +1579,6 @@ public:
};
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/frotz/processor_buffer.cpp b/engines/glk/frotz/processor_buffer.cpp
index faec6ef..c4eaeaa 100644
--- a/engines/glk/frotz/processor_buffer.cpp
+++ b/engines/glk/frotz/processor_buffer.cpp
@@ -24,7 +24,7 @@
#include "common/algorithm.h"
#include "common/textconsole.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
const char *const Processor::ERR_MESSAGES[ERR_NUM_ERRORS] = {
@@ -189,4 +189,4 @@ void Processor::runtimeError(ErrorCode errNum) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_input.cpp b/engines/glk/frotz/processor_input.cpp
index 6dda853..af5c7dc 100644
--- a/engines/glk/frotz/processor_input.cpp
+++ b/engines/glk/frotz/processor_input.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
#define INPUT_BUFFER_SIZE 200
@@ -220,4 +220,4 @@ void Processor::z_read_mouse(){
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_maths.cpp b/engines/glk/frotz/processor_maths.cpp
index 90e09ca..5a2a522 100644
--- a/engines/glk/frotz/processor_maths.cpp
+++ b/engines/glk/frotz/processor_maths.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
void Processor::z_add() {
@@ -102,4 +102,4 @@ void Processor::z_test() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_mem.cpp b/engines/glk/frotz/processor_mem.cpp
index 7c7af0d..dec7520 100644
--- a/engines/glk/frotz/processor_mem.cpp
+++ b/engines/glk/frotz/processor_mem.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
void Processor::flagsChanged(zbyte value) {
@@ -215,4 +215,4 @@ void Processor::memory_close(void) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_objects.cpp b/engines/glk/frotz/processor_objects.cpp
index 7e1fe6d..13e8a11 100644
--- a/engines/glk/frotz/processor_objects.cpp
+++ b/engines/glk/frotz/processor_objects.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
#define MAX_OBJECT 2000
@@ -729,4 +729,4 @@ void Processor::z_test_attr() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 87c190f..6c25ef9 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
void Processor::screen_mssg_on() {
@@ -525,4 +525,4 @@ void Processor::z_split_window() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index b7b23b2..8413f4b 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -23,7 +23,7 @@
#include "glk/frotz/processor.h"
#include "glk/frotz/quetzal.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
zchar Processor::console_read_input(int max, zchar *buf, zword timeout, bool continued) {
@@ -783,4 +783,4 @@ void Processor::z_verify() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_table.cpp b/engines/glk/frotz/processor_table.cpp
index bb16389..c586355 100644
--- a/engines/glk/frotz/processor_table.cpp
+++ b/engines/glk/frotz/processor_table.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
void Processor::z_copy_table() {
@@ -117,4 +117,4 @@ void Processor::z_storew() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_text.cpp b/engines/glk/frotz/processor_text.cpp
index e058793..3cfe50b 100644
--- a/engines/glk/frotz/processor_text.cpp
+++ b/engines/glk/frotz/processor_text.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
zchar Processor::ZSCII_TO_LATIN1[] = {
@@ -883,4 +883,4 @@ void Processor::z_tokenise() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/processor_variables.cpp b/engines/glk/frotz/processor_variables.cpp
index 0162f84..6e6a191 100644
--- a/engines/glk/frotz/processor_variables.cpp
+++ b/engines/glk/frotz/processor_variables.cpp
@@ -22,7 +22,7 @@
#include "glk/frotz/processor.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
void Processor::z_dec() {
@@ -196,4 +196,4 @@ void Processor::z_store() {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/quetzal.cpp b/engines/glk/frotz/quetzal.cpp
index a7b48fc..9ff33ab 100644
--- a/engines/glk/frotz/quetzal.cpp
+++ b/engines/glk/frotz/quetzal.cpp
@@ -24,7 +24,7 @@
#include "glk/frotz/processor.h"
#include "common/memstream.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
/**
@@ -482,4 +482,4 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/frotz/quetzal.h b/engines/glk/frotz/quetzal.h
index bbd4496..9d382ab 100644
--- a/engines/glk/frotz/quetzal.h
+++ b/engines/glk/frotz/quetzal.h
@@ -26,7 +26,7 @@
#include "glk/glk_types.h"
#include "glk/frotz/frotz_types.h"
-namespace Gargoyle {
+namespace Glk {
namespace Frotz {
enum QueztalTag {
@@ -92,6 +92,6 @@ public:
};
} // End of namespace Frotz
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/gargoyle.cpp b/engines/glk/gargoyle.cpp
deleted file mode 100644
index 702efe7..0000000
--- a/engines/glk/gargoyle.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* 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.
- *
- */
-
-#include "common/scummsys.h"
-#include "common/config-manager.h"
-#include "common/debug-channels.h"
-#include "common/events.h"
-#include "common/file.h"
-#include "engines/util.h"
-#include "graphics/scaler.h"
-#include "graphics/thumbnail.h"
-#include "glk/gargoyle.h"
-#include "glk/conf.h"
-#include "glk/events.h"
-#include "glk/picture.h"
-#include "glk/screen.h"
-#include "glk/selection.h"
-#include "glk/streams.h"
-#include "glk/windows.h"
-
-namespace Gargoyle {
-
-GargoyleEngine *g_vm;
-
-GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"), _clipboard(nullptr),
- _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
- _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
- gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
- g_vm = this;
-}
-
-GargoyleEngine::~GargoyleEngine() {
- delete _clipboard;
- delete _conf;
- delete _events;
- delete _picList;
- delete _screen;
- delete _selection;
- delete _streams;
- delete _windows;
-}
-
-void GargoyleEngine::initialize() {
- // Set up debug channels
- DebugMan.addDebugChannel(kDebugCore, "core", "Core engine debug level");
- DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
- DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
- DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
-
- initGraphicsMode();
- _conf = new Conf();
- _screen = new Screen();
-
- _clipboard = new Clipboard();
- _events = new Events();
- _picList = new PicList();
- _selection = new Selection();
- _streams = new Streams();
- _windows = new Windows(_screen);
-}
-
-void GargoyleEngine::initGraphicsMode() {
- uint width = ConfMan.hasKey("width") ? ConfMan.getInt("width") : 640;
- uint height = ConfMan.hasKey("height") ? ConfMan.getInt("height") : 480;
- Common::List<Graphics::PixelFormat> formats = g_system->getSupportedFormats();
- Graphics::PixelFormat format = formats.front();
-
- for (Common::List<Graphics::PixelFormat>::iterator i = formats.begin(); i != formats.end(); ++i) {
- if ((*i).bytesPerPixel > 1) {
- format = *i;
- break;
- }
- }
-
- initGraphics(width, height, &format);
-}
-
-Common::Error GargoyleEngine::run() {
- initialize();
-
- Common::File f;
- if (f.open(getFilename()))
- runGame(&f);
-
- return Common::kNoError;
-}
-
-void GargoyleEngine::GUIError(const char *msg, ...) {
- char buffer[STRINGBUFLEN];
- va_list va;
-
- // Generate the full error message
- va_start(va, msg);
- vsnprintf(buffer, STRINGBUFLEN, msg, va);
- va_end(va);
-
- GUIErrorMessage(buffer);
-}
-
-} // End of namespace Gargoyle
diff --git a/engines/glk/gargoyle.h b/engines/glk/gargoyle.h
deleted file mode 100644
index d3019ca..0000000
--- a/engines/glk/gargoyle.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/* 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_GARGOLE_H
-#define GLK_GARGOLE_H
-
-#include "common/scummsys.h"
-#include "common/random.h"
-#include "common/system.h"
-#include "common/serializer.h"
-#include "engines/advancedDetector.h"
-#include "engines/engine.h"
-#include "glk/glk_types.h"
-
-namespace Gargoyle {
-
-class Clipboard;
-class Conf;
-class Events;
-class PicList;
-class Screen;
-class Selection;
-class Streams;
-class Windows;
-
-enum InterpreterType {
- INTERPRETER_ADVSYS = 0,
- INTERPRETER_AGILITY = 1,
- INTERPRETER_ALAN2 = 2,
- INTERPRETER_ALAN3 = 3,
- INTERPRETER_BOCFEL = 4,
- INTERPRETER_FROTZ = 5,
- INTERPRETER_GEAS = 6,
- INTERPRETER_HUGO = 7,
- INTERPRETER_JACL = 8,
- INTERPRETER_LEVEL9 = 9,
- INTERPRETER_MAGNETIC = 10,
- INTERPRETER_NITFOL = 11,
- INTERPRETER_SCARE = 12,
- INTERPRETER_SCOTT = 13,
- INTERPRETER_TADS = 14
-};
-
-enum GargoyleDebugChannels {
- kDebugCore = 1 << 0,
- kDebugScripts = 1 << 1,
- kDebugGraphics = 1 << 2,
- kDebugSound = 1 << 3
-};
-
-
-#define GLK_SAVEGAME_VERSION 1
-
-struct GargoyleGameDescription;
-
-/**
- * Base class for the different interpreters
- */
-class GargoyleEngine : public Engine {
-private:
- /**
- * Handles basic initialization
- */
- void initialize();
-
- /**
- * Setup the video mode
- */
- void initGraphicsMode();
-protected:
- const GargoyleGameDescription *_gameDescription;
- Common::RandomSource _random;
- int _loadSaveSlot;
-
- // Engine APIs
- virtual Common::Error run();
-
- /**
- * Returns true whether a given feature is supported by the engine
- */
- virtual bool hasFeature(EngineFeature f) const;
-
- /**
- * Main game loop for the individual interpreters
- */
- virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
-public:
- Clipboard *_clipboard;
- Conf *_conf;
- Events *_events;
- PicList *_picList;
- Screen *_screen;
- Selection *_selection;
- Streams *_streams;
- Windows *_windows;
- bool _copySelect;
- bool _terminated;
- void (*gli_unregister_obj)(void *obj, glui32 objclass, gidispatch_rock_t objrock);
- gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, const char *typecode);
- void (*gli_unregister_arr)(void *array, glui32 len, const char *typecode, gidispatch_rock_t objrock);
-
-public:
- GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc);
- virtual ~GargoyleEngine();
-
- /**
- * Returns true if a savegame can be loaded
- */
- virtual bool canLoadGameStateCurrently() override {
- return true;
- }
-
- /**
- * Returns true if the game can be saved
- */
- virtual bool canSaveGameStateCurrently() override {
- return true;
- }
-
- /**
- * Returns the bitset of game features
- */
- uint32 getFeatures() const;
-
- /**
- * Returns whether the game is a demo
- */
- bool isDemo() const;
-
- /**
- * Returns the language
- */
- Common::Language getLanguage() const;
-
- /**
- * Returns the running interpreter type
- */
- InterpreterType getInterpreterType() const;
-
- /**
- * Returns the game's md5
- */
- const Common::String &getGameMD5() const;
-
- /**
- * Returns the primary filename for the game
- */
- const Common::String &getFilename() const;
-
- /**
- * Return the game engine's target name
- */
- const Common::String &getTargetName() const {
- return _targetName;
- }
-
- /**
- * Return the filename for a given save slot
- */
- Common::String getSaveName(uint slot) const {
- return Common::String::format("%s.%.3u", getTargetName().c_str(), slot);
- }
-
- /**
- * Display a message in a GUI dialog
- */
- void GUIError(const char *msg, ...);
-};
-
-extern GargoyleEngine *g_vm;
-
-} // End of namespace Gargoyle
-
-#endif
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 77fb242..a35f242 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -4,1171 +4,117 @@
* 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
+ * 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
+ * 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
+ * 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
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "engines/util.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
#include "glk/glk.h"
#include "glk/conf.h"
#include "glk/events.h"
#include "glk/picture.h"
+#include "glk/screen.h"
+#include "glk/selection.h"
#include "glk/streams.h"
-#include "glk/unicode.h"
#include "glk/windows.h"
-#include "glk/window_graphics.h"
-#include "glk/window_text_buffer.h"
-#include "glk/window_pair.h"
-
-namespace Gargoyle {
-
-Glk::Glk(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- GargoyleEngine(syst, gameDesc), _gliFirstEvent(false) {
- // Set uppercase/lowercase tables
- int ix, res;
- for (ix = 0; ix < 256; ix++) {
- _charToupperTable[ix] = ix;
- _charTolowerTable[ix] = ix;
- }
-
- for (ix = 0; ix < 256; ix++) {
- if (ix >= 'A' && ix <= 'Z')
- res = ix + ('a' - 'A');
- else if (ix >= 0xC0 && ix <= 0xDE && ix != 0xD7)
- res = ix + 0x20;
- else
- res = 0;
-
- if (res) {
- _charTolowerTable[ix] = res;
- _charToupperTable[res] = ix;
+namespace Glk {
+
+GlkEngine *g_vm;
+
+GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription *gameDesc) :
+ _gameDescription(gameDesc), Engine(syst), _random("Glk"), _clipboard(nullptr),
+ _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
+ _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
+ gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
+ g_vm = this;
+}
+
+GlkEngine::~GlkEngine() {
+ delete _clipboard;
+ delete _conf;
+ delete _events;
+ delete _picList;
+ delete _screen;
+ delete _selection;
+ delete _streams;
+ delete _windows;
+}
+
+void GlkEngine::initialize() {
+ // Set up debug channels
+ DebugMan.addDebugChannel(kDebugCore, "core", "Core engine debug level");
+ DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
+ DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
+ DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
+
+ initGraphicsMode();
+ _conf = new Conf();
+ _screen = new Screen();
+
+ _clipboard = new Clipboard();
+ _events = new Events();
+ _picList = new PicList();
+ _selection = new Selection();
+ _streams = new Streams();
+ _windows = new Windows(_screen);
+}
+
+void GlkEngine::initGraphicsMode() {
+ uint width = ConfMan.hasKey("width") ? ConfMan.getInt("width") : 640;
+ uint height = ConfMan.hasKey("height") ? ConfMan.getInt("height") : 480;
+ Common::List<Graphics::PixelFormat> formats = g_system->getSupportedFormats();
+ Graphics::PixelFormat format = formats.front();
+
+ for (Common::List<Graphics::PixelFormat>::iterator i = formats.begin(); i != formats.end(); ++i) {
+ if ((*i).bytesPerPixel > 1) {
+ format = *i;
+ break;
}
}
-}
-
-void Glk::glk_exit(void) {
- glk_put_string("[ press any key to exit ]");
- _events->waitForPress();
-
- quitGame();
-}
-
-void Glk::glk_set_interrupt_handler(void(*func)(void)) {
- // This library doesn't handle interrupts.
-}
-
-void Glk::glk_tick(void) {
- // Nothing needed
-}
-
-glui32 Glk::glk_gestalt(glui32 id, glui32 val) {
- return glk_gestalt_ext(id, val, nullptr, 0);
-}
-
-glui32 Glk::glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen) {
- switch (id) {
- case gestalt_Version:
- return 0x00000703;
-
- case gestalt_LineInput:
- if (val >= 32 && val < 0x10ffff)
- return true;
- else
- return false;
-
- case gestalt_CharInput:
- if (val >= 32 && val < 0x10ffff)
- return true;
- else if (val == keycode_Return)
- return true;
- else
- return false;
-
- case gestalt_CharOutput:
- if (val >= 32 && val < 0x10ffff) {
- if (arr && arrlen >= 1)
- arr[0] = 1;
- return gestalt_CharOutput_ExactPrint;
- } else {
- // cheaply, we don't do any translation of printed characters,
- // so the output is always one character even if it's wrong.
- if (arr && arrlen >= 1)
- arr[0] = 1;
- return gestalt_CharOutput_CannotPrint;
- }
-
- case gestalt_MouseInput:
- if (val == wintype_TextGrid)
- return true;
- if (val == wintype_Graphics)
- return true;
- return false;
-
- case gestalt_Graphics:
- case gestalt_GraphicsTransparency:
- return g_conf->_graphics;
-
- case gestalt_DrawImage:
- if (val == wintype_TextBuffer)
- return g_conf->_graphics;
- if (val == wintype_Graphics)
- return g_conf->_graphics;
- return false;
-
- case gestalt_Sound:
- case gestalt_SoundVolume:
- case gestalt_SoundMusic:
- case gestalt_SoundNotify:
- return g_conf->_sound;
-
- case gestalt_LineTerminatorKey:
- return Window::checkTerminator(val);
-
- case gestalt_Timer:
- case gestalt_Unicode:
- case gestalt_UnicodeNorm:
- case gestalt_Hyperlinks:
- case gestalt_HyperlinkInput:
- case gestalt_LineInputEcho:
- case gestalt_LineTerminators:
- case gestalt_DateTime:
- case gestalt_GarglkText:
- return true;
-
- case gestalt_Sound2:
- default:
- return false;
- }
-}
-unsigned char Glk::glk_char_to_lower(unsigned char ch) {
- return _charTolowerTable[ch];
+ initGraphics(width, height, &format);
}
-unsigned char Glk::glk_char_to_upper(unsigned char ch) {
- return _charToupperTable[ch];
-}
+Common::Error GlkEngine::run() {
+ initialize();
-winid_t Glk::glk_window_get_root(void) const {
- return _windows->getRoot();
-}
+ Common::File f;
+ if (f.open(getFilename()))
+ runGame(&f);
-winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, glui32 rock) const {
- return _windows->windowOpen(split, method, size, wintype, rock);
+ return Common::kNoError;
}
-void Glk::glk_window_close(winid_t win, stream_result_t *result) {
- if (win) {
- _windows->windowClose(win, result);
- } else {
- warning("glk_window_close: invalid ref");
- }
-}
-
-void Glk::glk_window_get_size(winid_t win, glui32 *width, glui32 *height) {
- if (win) {
- win->getSize(width, height);
- } else {
- warning("window_get_size: invalid ref");
- }
-}
+void GlkEngine::GUIError(const char *msg, ...) {
+ char buffer[STRINGBUFLEN];
+ va_list va;
-void Glk::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keywin) {
- if (win) {
- win->setArrangement(method, size, keywin);
- } else {
- warning("window_set_arrangement: invalid ref");
- }
-}
-
-void Glk::glk_window_get_arrangement(winid_t win, glui32 *method,
- glui32 *size, winid_t *keyWin) {
- if (win) {
- win->getArrangement(method, size, keyWin);
- } else {
- warning("window_get_arrangement: invalid ref");
- }
-}
-
-winid_t Glk::glk_window_iterate(winid_t win, glui32 *rock) {
- win = win ? win->_next : _windows->getRoot();
-
- if (win) {
- if (rock)
- *rock = win->_rock;
- return win;
- }
-
- if (rock)
- *rock = 0;
-
- return nullptr;
-}
-
-glui32 Glk::glk_window_get_rock(winid_t win) {
- if (win) {
- return win->_rock;
- } else {
- warning("window_get_rock: invalid ref.");
- return 0;
- }
-}
-
-glui32 Glk::glk_window_get_type(winid_t win) {
- if (win) {
- return win->_type;
- } else {
- warning("window_get_parent: invalid ref");
- return 0;
- }
-}
-
-winid_t Glk::glk_window_get_parent(winid_t win) {
- if (!win) {
- warning("window_get_parent: invalid ref");
- return 0;
- }
-
- return win->_parent;
-}
-
-winid_t Glk::glk_window_get_sibling(winid_t win) {
- if (!win) {
- warning("window_get_sibling: invalid ref");
- return nullptr;
- }
-
- PairWindow *parentWin = dynamic_cast<PairWindow *>(win->_parent);
- if (!parentWin)
- return nullptr;
-
- if (parentWin->_child1 == win)
- return parentWin->_child2;
- else if (parentWin->_child2 == win)
- return parentWin->_child1;
-
- return nullptr;
-}
-
-void Glk::glk_window_clear(winid_t win) {
- if (!win) {
- warning("window_clear: invalid ref");
- } else {
- if (win->_lineRequest || win->_lineRequestUni) {
- if (g_conf->_safeClicks && _events->_forceClick) {
- glk_cancel_line_event(win, nullptr);
- _events->_forceClick = false;
-
- win->clear();
- } else {
- warning("window_clear: window has pending line request");
- return;
- }
- }
-
- // Clear the window
- win->clear();
- }
-}
-
-void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
- if (win) {
- win->moveCursor(Point(xpos, ypos));
- } else {
- warning("window_move_cursor: invalid ref");
- }
-}
-
-strid_t Glk::glk_window_get_stream(winid_t win) {
- if (win) {
- return win->_stream;
- } else {
- warning("window_get_stream: invalid ref");
- return nullptr;
- }
-}
-
-void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) {
- if (win) {
- win->_echoStream = str;
- } else {
- warning("window_set_echo_stream: invalid window id");
- }
-}
-
-strid_t Glk::glk_window_get_echo_stream(winid_t win) {
- if (!win) {
- warning("window_get_echo_stream: invalid ref");
- return nullptr;
- }
-
- return win->_echoStream;
-}
-
-void Glk::glk_set_window(winid_t win) {
- _streams->setCurrent(win ? win->_stream : nullptr);
-}
-
-strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock) {
- return _streams->openFileStream(fileref, fmode, rock, false);
-}
-
-strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock) {
- return _streams->openMemoryStream(buf, buflen, fmode, rock, false);
-}
-
-void Glk::glk_stream_close(strid_t str, stream_result_t *result) {
- str->close(result);
-}
-
-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) 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) {
- if (str) {
- str->setPosition(pos, seekMode);
- } else {
- warning("stream_set_position: invalid ref");
- }
-}
+ // Generate the full error message
+ va_start(va, msg);
+ vsnprintf(buffer, STRINGBUFLEN, msg, va);
+ va_end(va);
-glui32 Glk::glk_stream_get_position(strid_t str) const {
- if (str) {
- return str->getPosition();
- } else {
- warning("stream_get_position: invalid ref");
- return 0;
- }
-}
-
-void Glk::glk_stream_set_current(strid_t str) {
- _streams->setCurrent(str);
-}
-
-strid_t Glk::glk_stream_get_current(void) {
- return _streams->getCurrent();
-}
-
-void Glk::glk_put_char(unsigned char ch) {
- _streams->getCurrent()->putChar(ch);
-}
-
-void Glk::glk_put_char_stream(strid_t str, unsigned char ch) {
- if (str) {
- str->putChar(ch);
- } else {
- warning("put_char_stream: invalid ref");
- }
-}
-
-void Glk::glk_put_string(const char *s) {
- _streams->getCurrent()->putBuffer(s, strlen(s));
-}
-
-void Glk::glk_put_string_stream(strid_t str, const char *s) {
- str->putBuffer(s, strlen(s));
-}
-
-void Glk::glk_put_buffer(char *buf, glui32 len) {
- _streams->getCurrent()->putBuffer(buf, len);
-}
-
-void Glk::glk_put_buffer_stream(strid_t str, const char *buf, glui32 len) {
- str->putBuffer(buf, len);
-}
-
-void Glk::glk_set_style(glui32 styl) {
- _streams->getCurrent()->setStyle(styl);
-}
-
-void Glk::glk_set_style_stream(strid_t str, glui32 styl) {
- if (str) {
- str->setStyle(styl);
- } else {
- warning("set_style_stream: invalid ref");
- }
-}
-
-glsi32 Glk::glk_get_char_stream(strid_t str) {
- if (str) {
- return str->getChar();
- } else {
- warning("get_char_stream: invalid ref");
- return -1;
- }
-}
-
-glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
- if (str) {
- return str->getLine(buf, len);
- } else {
- warning("get_line_stream: invalid ref");
- return 0;
- }
-}
-
-glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
- if (str) {
- return str->getBuffer(buf, len);
- } else {
- warning("get_line_stream: invalid ref");
- return 0;
- }
-}
-
-void Glk::glk_stylehint_set(glui32 wintype, glui32 style, glui32 hint, glsi32 val) {
- WindowStyle *styles;
- bool p, b, i;
-
- if (wintype == wintype_AllTypes) {
- glk_stylehint_set(wintype_TextGrid, style, hint, val);
- glk_stylehint_set(wintype_TextBuffer, style, hint, val);
- return;
- }
-
- if (wintype == wintype_TextGrid)
- styles = g_conf->_gStyles;
- else if (wintype == wintype_TextBuffer)
- styles = g_conf->_tStyles;
- else
- return;
-
- if (!g_conf->_styleHint)
- return;
-
- switch (hint) {
- case stylehint_TextColor:
- styles[style].fg[0] = (val >> 16) & 0xff;
- styles[style].fg[1] = (val >> 8) & 0xff;
- styles[style].fg[2] = (val) & 0xff;
- break;
-
- case stylehint_BackColor:
- styles[style].bg[0] = (val >> 16) & 0xff;
- styles[style].bg[1] = (val >> 8) & 0xff;
- styles[style].bg[2] = (val) & 0xff;
- break;
-
- case stylehint_ReverseColor:
- styles[style].reverse = (val != 0);
- break;
-
- case stylehint_Proportional:
- if (wintype == wintype_TextBuffer) {
- p = val > 0;
- b = styles[style].isBold();
- i = styles[style].isItalic();
- styles[style].font = WindowStyle::makeFont(p, b, i);
- }
- break;
-
- case stylehint_Weight:
- p = styles[style].isProp();
- b = val > 0;
- i = styles[style].isItalic();
- styles[style].font = WindowStyle::makeFont(p, b, i);
- break;
-
- case stylehint_Oblique:
- p = styles[style].isProp();
- b = styles[style].isBold();
- i = val > 0;
- styles[style].font = WindowStyle::makeFont(p, b, i);
- break;
- }
-
- if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_BackColor) {
- memcpy(g_conf->_windowColor, styles[style].bg, 3);
- }
-
- if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_TextColor) {
- memcpy(g_conf->_moreColor, styles[style].fg, 3);
- memcpy(g_conf->_caretColor, styles[style].fg, 3);
- }
-}
-
-void Glk::glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint) {
- WindowStyle *styles;
- const WindowStyle *defaults;
-
- if (wintype == wintype_AllTypes) {
- glk_stylehint_clear(wintype_TextGrid, style, hint);
- glk_stylehint_clear(wintype_TextBuffer, style, hint);
- return;
- }
-
- if (wintype == wintype_TextGrid) {
- styles = g_conf->_gStyles;
- defaults = g_conf->_gStylesDefault;
- } else if (wintype == wintype_TextBuffer) {
- styles = g_conf->_tStyles;
- defaults = g_conf->_tStylesDefault;
- } else {
- return;
- }
-
- if (!g_conf->_styleHint)
- return;
-
- switch (hint) {
- case stylehint_TextColor:
- styles[style].fg[0] = defaults[style].fg[0];
- styles[style].fg[1] = defaults[style].fg[1];
- styles[style].fg[2] = defaults[style].fg[2];
- break;
-
- case stylehint_BackColor:
- styles[style].bg[0] = defaults[style].bg[0];
- styles[style].bg[1] = defaults[style].bg[1];
- styles[style].bg[2] = defaults[style].bg[2];
- break;
-
- case stylehint_ReverseColor:
- styles[style].reverse = defaults[style].reverse;
- break;
-
- case stylehint_Proportional:
- case stylehint_Weight:
- case stylehint_Oblique:
- styles[style].font = defaults[style].font;
- break;
- }
-}
-
-glui32 Glk::glk_style_distinguish(winid_t win, glui32 style1, glui32 style2) {
- const WindowStyle *styles = win->getStyles();
- if (!styles)
- return false;
-
- return styles[style1] == styles[style2] ? 0 : 1;
-}
-
-bool Glk::glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result) {
- const WindowStyle *styles = win->getStyles();
- if (!styles)
- return false;
-
- switch (hint) {
- case stylehint_Indentation:
- case stylehint_ParaIndentation:
- *result = 0;
- break;
-
- case stylehint_Justification:
- *result = stylehint_just_LeftFlush;
- break;
-
- case stylehint_Size:
- *result = 1;
- break;
-
- case stylehint_Weight:
- *result =
- (styles[style].font == PROPB || styles[style].font == PROPZ ||
- styles[style].font == MONOB || styles[style].font == MONOZ);
- break;
-
- case stylehint_Oblique:
- *result =
- (styles[style].font == PROPI || styles[style].font == PROPZ ||
- styles[style].font == MONOI || styles[style].font == MONOZ);
- break;
-
- case stylehint_Proportional:
- *result =
- (styles[style].font == PROPR || styles[style].font == PROPI ||
- styles[style].font == PROPB || styles[style].font == PROPZ);
- break;
-
- case stylehint_TextColor:
- *result =
- (styles[style].fg[0] << 16) | (styles[style].fg[1] << 8) | (styles[style].fg[2]);
- break;
-
- case stylehint_BackColor:
- *result =
- (styles[style].bg[0] << 16) | (styles[style].bg[1] << 8) | (styles[style].bg[2]);
- break;
-
- case stylehint_ReverseColor:
- *result = styles[style].reverse;
- break;
-
- default:
- return false;
- }
-
- return true;
-}
-
-frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) {
- return _streams->createTemp(usage, rock);
-}
-
-frefid_t Glk::glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock) {
- // Take out all dangerous characters
- Common::String tempName(name);
- for (uint idx = 0; idx < tempName.size(); ++idx) {
- if (tempName[idx] == '/' || tempName[idx] == '\\' || tempName[idx] == ':')
- tempName.setChar(idx, '-');
- }
-
- return _streams->createRef(tempName, usage, rock);
-}
-
-frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock) {
- return _streams->createByPrompt(usage, fmode, rock);
-}
-
-frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
- if (!fref) {
- warning("fileref_create_from_fileref: invalid ref");
- return nullptr;
- } else {
- return _streams->createFromRef(fref, usage, rock);
- }
-}
-
-void Glk::glk_fileref_destroy(frefid_t fref) {
- _streams->deleteRef(fref);
-}
-
-frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
- return _streams->iterate(fref, rockptr);
-}
-
-glui32 Glk::glk_fileref_get_rock(frefid_t fref) {
- if (!fref) {
- warning("fileref_get_rock: invalid ref.");
- return 0;
- } else {
- return fref->_rock;
- }
-}
-
-void Glk::glk_fileref_delete_file(frefid_t fref) {
- fref->deleteFile();
-}
-
-glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) {
- return fref->exists();
-}
-
-void Glk::glk_select(event_t *event) {
- if (!_gliFirstEvent) {
- _windows->inputGuessFocus();
- _gliFirstEvent = true;
- }
-
- _events->getEvent(event, false);
-}
-
-void Glk::glk_select_poll(event_t *event) {
- if (!_gliFirstEvent) {
- _windows->inputGuessFocus();
- _gliFirstEvent = true;
- }
-
- _events->getEvent(event, true);
-}
-
-void Glk::glk_request_timer_events(glui32 millisecs) {
- _events->setTimerInterval(millisecs);
-}
-
-void Glk::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
- if (!win) {
- warning("request_line_event: invalid ref");
- } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
- warning("request_line_event: window already has keyboard request");
- } else {
- win->requestLineEvent(buf, maxlen, initlen);
- }
-}
-
-void Glk::glk_request_char_event(winid_t win) {
- if (!win) {
- warning("request_char_event: invalid ref");
- } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
- warning("request_char_event: window already has keyboard request");
- } else {
- win->requestCharEvent();
- }
-}
-
-void Glk::glk_request_mouse_event(winid_t win) {
- if (!win) {
- warning("request_mouse_event: invalid ref");
- } else {
- win->requestMouseEvent();
- }
-}
-
-void Glk::glk_cancel_line_event(winid_t win, event_t *event) {
- if (!win) {
- warning("cancel_line_event: invalid ref");
- } else {
- win->cancelLineEvent(event);
- }
-}
-
-void Glk::glk_cancel_char_event(winid_t win) {
- if (!win) {
- warning("glk_cancel_char_event: invalid ref");
- } else {
- win->cancelCharEvent();
- }
-}
-
-void Glk::glk_cancel_mouse_event(winid_t win) {
- if (!win) {
- warning("cancel_mouse_event: invalid ref");
- } else {
- win->cancelMouseEvent();
- }
-}
-
-void Glk::glk_set_echo_line_event(winid_t win, glui32 val) {
- if (!win) {
- warning("set_echo_line_event: invalid ref");
- } else {
- win->setEchoLineEvent(val);
- }
-}
-
-void Glk::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
- if (!win) {
- warning("set_terminators_line_event: invalid ref");
- } else {
- win->setTerminatorsLineEvent(keycodes, count);
- }
-}
-
-glui32 Glk::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return bufferChangeCase(buf, len, numchars, CASE_LOWER, COND_ALL, true);
-}
-
-glui32 Glk::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return bufferChangeCase(buf, len, numchars, CASE_UPPER, COND_ALL, true);
-}
-
-glui32 Glk::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest) {
- return bufferChangeCase(buf, len, numchars, CASE_TITLE, COND_LINESTART, lowerrest);
-}
-
-void Glk::glk_put_char_uni(glui32 ch) {
- _streams->getCurrent()->putCharUni(ch);
-}
-
-void Glk::glk_put_string_uni(glui32 *s) {
- _streams->getCurrent()->putBufferUni(s, strlen_uni(s));
-}
-
-void Glk::glk_put_buffer_uni(glui32 *buf, glui32 len) {
- _streams->getCurrent()->putBufferUni(buf, len);
-}
-
-void Glk::glk_put_char_stream_uni(strid_t str, glui32 ch) {
- if (str) {
- str->putCharUni(ch);
- } else {
- warning("put_char_stream_uni: invalid ref");
- }
-}
-
-void Glk::glk_put_string_stream_uni(strid_t str, const glui32 *s) {
- if (str) {
- str->putBufferUni(s, strlen_uni(s));
- } else {
- warning("put_string_stream_uni: invalid ref");
- }
-}
-
-void Glk::glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len) {
- if (str) {
- str->putBufferUni(buf, len);
- } else {
- warning("put_buffer_stream_uni: invalid ref");
- }
-}
-
-glsi32 Glk::glk_get_char_stream_uni(strid_t str) {
- if (str) {
- return str->getCharUni();
- } else {
- warning("get_char_stream_uni: invalid ref");
- return -1;
- }
-}
-
-glui32 Glk::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- if (str) {
- return str->getBufferUni(buf, len);
- } else {
- warning("get_buffer_stream_uni: invalid ref");
- return 0;
- }
-}
-
-glui32 Glk::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
- if (str) {
- return str->getLineUni(buf, len);
- } else {
- warning("get_line_stream_uni: invalid ref");
- return (glui32) - 1;
- }
-}
-
-strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock) {
- return _streams->openFileStream(fileref, fmode, rock, true);
-}
-
-strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock) {
- return _streams->openMemoryStream(buf, buflen, fmode, rock, true);
-}
-
-void Glk::glk_request_char_event_uni(winid_t win) {
- if (!win) {
- warning("request_char_event_uni: invalid ref");
- } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
- warning("request_char_event_uni: window already has keyboard request");
- } else {
- win->requestCharEvent();
- }
-}
-
-void Glk::glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initlen) {
- if (!win) {
- warning("request_line_event_uni: invalid ref");
- } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
- || win->_lineRequestUni) {
- warning("request_line_event_uni: window already has keyboard request");
- } else {
- win->requestLineEventUni(buf, maxlen, initlen);
- }
-}
-
-glui32 Glk::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
- return 0;
-}
-
-glui32 Glk::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
- if (!win) {
- warning("image_draw: invalid ref");
- } else if (g_conf->_graphics) {
- TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
- GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
-
- if (textWin)
- textWin->drawPicture(image, val1, false, 0, 0);
- else if (gfxWin)
- gfxWin->drawPicture(image, val1, val2, false, 0, 0);
- }
-
- return false;
-}
-
-glui32 Glk::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2,
- glui32 width, glui32 height) {
- if (!win) {
- warning("image_draw_scaled: invalid ref");
- } else if (g_conf->_graphics) {
- TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
- GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
-
- if (textWin)
- textWin->drawPicture(image, val1, true, width, height);
- else if (gfxWin)
- gfxWin->drawPicture(image, val1, val2, true, width, height);
- }
-
- return false;
-}
-
-glui32 Glk::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
- if (!g_conf->_graphics)
- return false;
-
- Picture *pic = Picture::load(image);
- if (!pic)
- return false;
-
- if (width)
- *width = pic->w;
- if (height)
- *height = pic->h;
-
- return true;
-}
-
-void Glk::glk_window_flow_break(winid_t win) {
- if (!win) {
- warning("window_erase_rect: invalid ref");
- } else {
- win->flowBreak();
- }
-}
-
-void Glk::glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 height) {
- if (!win) {
- warning("window_erase_rect: invalid ref");
- } else {
- win->eraseRect(false, Rect(left, top, left + width, top + height));
- }
-}
-
-void Glk::glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top,
- glui32 width, glui32 height) {
- if (!win) {
- warning("window_fill_rect: invalid ref");
- } else {
- win->eraseRect(color, Rect(left, top, left + width, top + height));
- }
-}
-
-void Glk::glk_window_set_background_color(winid_t win, glui32 color) {
- if (!win) {
- warning("window_set_background_color: invalid ref");
- } else {
- win->setBackgroundColor(color);
- }
-}
-
-schanid_t Glk::glk_schannel_create(glui32 rock) {
- // TODO
- return nullptr;
-}
-
-void Glk::glk_schannel_destroy(schanid_t chan) {
- // TODO
-}
-
-schanid_t Glk::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
- // TODO
- return nullptr;
-}
-
-glui32 Glk::glk_schannel_get_rock(schanid_t chan) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_schannel_play(schanid_t chan, glui32 snd) {
- // TODO
- return 0;
-}
-
-glui32 Glk::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
- // TODO
- return 0;
-}
-
-void Glk::glk_schannel_stop(schanid_t chan) {
- // TODO
-}
-
-void Glk::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
- // TODO
-}
-
-void Glk::glk_sound_load_hint(glui32 snd, glui32 flag) {
- // TODO
-}
-
-schanid_t Glk::glk_schannel_create_ext(glui32 rock, glui32 volume) {
- // TODO
- return nullptr;
-}
-
-glui32 Glk::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify) {
- // TODO
- return 0;
-}
-
-void Glk::glk_schannel_pause(schanid_t chan) {
- // TODO
-}
-
-void Glk::glk_schannel_unpause(schanid_t chan) {
- // TODO
-}
-
-void Glk::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify) {
- // TODO
-}
-
-void Glk::glk_set_hyperlink(glui32 linkval) {
- _streams->getCurrent()->setHyperlink(linkval);
-}
-
-void Glk::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
- if (str)
- str->setHyperlink(linkval);
-}
-
-void Glk::glk_request_hyperlink_event(winid_t win) {
- if (!win) {
- warning("request_hyperlink_event: invalid ref");
- } else {
- win->requestHyperlinkEvent();
- }
-}
-
-void Glk::glk_cancel_hyperlink_event(winid_t win) {
- if (win) {
- win->cancelHyperlinkEvent();
- } else {
- warning("cancel_hyperlink_event: invalid ref");
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-void Glk::glk_current_time(glktimeval_t *time) {
- TimeAndDate td;
- *time = td;
-}
-
-glsi32 Glk::glk_current_simple_time(glui32 factor) {
- assert(factor);
- TimeAndDate td;
-
- return td / factor;
-}
-
-void Glk::glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date) {
- // TODO: timezones aren't currently supported
- *date = TimeAndDate(*time);
-}
-
-void Glk::glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date) {
- *date = TimeAndDate(*time);
-}
-
-void Glk::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
- TimeSeconds secs = (int64)time * factor;
- *date = TimeAndDate(secs);
-}
-
-void Glk::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
- TimeSeconds secs = (int64)time * factor;
- *date = TimeAndDate(secs);
-}
-
-void Glk::glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time) {
- // WORKAROUND: timezones aren't currently supported
- *time = TimeAndDate(*date);
-}
-
-void Glk::glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time) {
- *time = TimeAndDate(*date);
-}
-
-glsi32 Glk::glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor) {
- // WORKAROUND: timezones aren't currently supported
- assert(factor);
- TimeSeconds ts = TimeAndDate(*date);
- return ts / factor;
-}
-
-glsi32 Glk::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor) {
- assert(factor);
- TimeSeconds ts = TimeAndDate(*date);
- return ts / factor;
-}
-
-/*--------------------------------------------------------------------------*/
-
-/* XXX non-official Glk functions */
-
-const char *Glk::garglk_fileref_get_name(frefid_t fref) const {
- return fref->_filename.c_str();
-}
-
-void Glk::garglk_set_program_name(const char *name) {
- // Program name isn't displayed
-}
-
-void Glk::garglk_set_program_info(const char *info) {
- // Program info isn't displayed
-}
-
-void Glk::garglk_set_story_name(const char *name) {
- // Story name isn't displayed
-}
-
-void Glk::garglk_set_story_title(const char *title) {
- // Story title isn't displayed
-}
-
-void Glk::garglk_set_config(const char *name) {
- // No implementation
-}
-
-void Glk::garglk_unput_string(const char *str) {
- _streams->getCurrent()->unputBuffer(str, strlen(str));
-}
-
-void Glk::garglk_unput_string_uni(const glui32 *str) {
- _streams->getCurrent()->unputBufferUni(str, strlen_uni(str));
-}
-
-void Glk::garglk_set_zcolors(glui32 fg, glui32 bg) {
- _streams->getCurrent()->setZColors(fg, bg);
-}
-
-void Glk::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
- if (str) {
- str->setZColors(fg, bg);
- } else {
- warning("set_style_stream: Invalid ref");
- }
-}
-
-void Glk::garglk_set_reversevideo(glui32 reverse) {
- _streams->getCurrent()->setReverseVideo(reverse != 0);
-}
-
-void Glk::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
- if (str) {
- str->setReverseVideo(reverse != 0);
- } else {
- warning("set_reversevideo: Invalid ref");
- }
+ GUIErrorMessage(buffer);
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index f71ad76..92ea2ab 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -23,270 +23,171 @@
#ifndef GLK_GLK_H
#define GLK_GLK_H
-#include "glk/gargoyle.h"
+#include "common/scummsys.h"
+#include "common/random.h"
+#include "common/system.h"
+#include "common/serializer.h"
+#include "engines/advancedDetector.h"
+#include "engines/engine.h"
#include "glk/glk_types.h"
-#include "glk/blorb.h"
-#include "glk/time.h"
-#include "glk/windows.h"
-namespace Gargoyle {
+namespace Glk {
+
+class Clipboard;
+class Conf;
+class Events;
+class PicList;
+class Screen;
+class Selection;
+class Streams;
+class Windows;
+
+enum InterpreterType {
+ INTERPRETER_ADVSYS = 0,
+ INTERPRETER_AGILITY = 1,
+ INTERPRETER_ALAN2 = 2,
+ INTERPRETER_ALAN3 = 3,
+ INTERPRETER_BOCFEL = 4,
+ INTERPRETER_FROTZ = 5,
+ INTERPRETER_GEAS = 6,
+ INTERPRETER_HUGO = 7,
+ INTERPRETER_JACL = 8,
+ INTERPRETER_LEVEL9 = 9,
+ INTERPRETER_MAGNETIC = 10,
+ INTERPRETER_NITFOL = 11,
+ INTERPRETER_SCARE = 12,
+ INTERPRETER_SCOTT = 13,
+ INTERPRETER_TADS = 14
+};
-/**
- * Implements the GLK interface
- */
-class Glk : public GargoyleEngine, public Blorb {
-private:
- bool _gliFirstEvent;
- unsigned char _charTolowerTable[256];
- unsigned char _charToupperTable[256];
-public:
- /**
- * Constructor
- */
- Glk(OSystem *syst, const GargoyleGameDescription *gameDesc);
+enum GlkDebugChannels {
+ kDebugCore = 1 << 0,
+ kDebugScripts = 1 << 1,
+ kDebugGraphics = 1 << 2,
+ kDebugSound = 1 << 3
+};
- void glk_exit(void);
- void glk_set_interrupt_handler(void(*func)(void));
- void glk_tick(void);
- glui32 glk_gestalt(glui32 id, glui32 val);
- glui32 glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen);
+#define GLK_SAVEGAME_VERSION 1
- unsigned char glk_char_to_lower(unsigned char ch);
- unsigned char glk_char_to_upper(unsigned char ch);
+struct GlkGameDescription;
+/**
+ * Base class for the different interpreters
+ */
+class GlkEngine : public Engine {
+private:
/**
- * Get the root window of the window hierarchy
+ * Handles basic initialization
*/
- winid_t glk_window_get_root(void) const;
+ void initialize();
/**
- * Open a new window
+ * Setup the video mode
*/
- winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock = 0) const;
-
- void glk_window_close(winid_t win, stream_result_t *result = nullptr);
- void glk_window_get_size(winid_t win, glui32 *width, glui32 *height);
- void glk_window_set_arrangement(winid_t win, glui32 method,
- glui32 size, winid_t keyWin);
- void glk_window_get_arrangement(winid_t win, glui32 *method,
- glui32 *size, winid_t *keyWin);
- winid_t glk_window_iterate(winid_t win, glui32 *rock = 0);
- glui32 glk_window_get_rock(winid_t win);
- glui32 glk_window_get_type(winid_t win);
- winid_t glk_window_get_parent(winid_t win);
- winid_t glk_window_get_sibling(winid_t win);
- void glk_window_clear(winid_t win);
- void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
-
- strid_t glk_window_get_stream(winid_t win);
- void glk_window_set_echo_stream(winid_t win, strid_t str);
- 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, FileMode fmode, glui32 rock = 0);
- strid_t glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
- void glk_stream_close(strid_t str, stream_result_t *result = nullptr);
- 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) const;
- void glk_stream_set_current(strid_t str);
- strid_t glk_stream_get_current(void);
-
- void glk_put_char(unsigned char ch);
- void glk_put_char_stream(strid_t str, unsigned char ch);
- void glk_put_string(const char *s);
- void glk_put_string_stream(strid_t str, const char *s);
- void glk_put_buffer(char *buf, glui32 len);
- void glk_put_buffer_stream(strid_t str, const char *buf, glui32 len);
- void glk_set_style(glui32 styl);
- void glk_set_style_stream(strid_t str, glui32 styl);
-
- glsi32 glk_get_char_stream(strid_t str);
- glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
- glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
-
- void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
- glsi32 val);
- void glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint);
- glui32 glk_style_distinguish(winid_t win, glui32 style1, glui32 style2);
- bool glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result);
+ void initGraphicsMode();
+protected:
+ const GlkGameDescription *_gameDescription;
+ Common::RandomSource _random;
+ int _loadSaveSlot;
- frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock = 0);
- frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock = 0);
- frefid_t glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock = 0);
- frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock = 0);
- void glk_fileref_destroy(frefid_t fref);
- frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
- glui32 glk_fileref_get_rock(frefid_t fref);
- void glk_fileref_delete_file(frefid_t fref);
- glui32 glk_fileref_does_file_exist(frefid_t fref);
+ // Engine APIs
+ virtual Common::Error run();
- void glk_select(event_t *event);
- void glk_select_poll(event_t *event);
-
- void glk_request_timer_events(glui32 millisecs);
-
- void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
- glui32 initlen);
- void glk_request_char_event(winid_t win);
- void glk_request_mouse_event(winid_t win);
-
- void glk_cancel_line_event(winid_t win, event_t *event);
- void glk_cancel_char_event(winid_t win);
- void glk_cancel_mouse_event(winid_t win);
-
-#ifdef GLK_MODULE_LINE_ECHO
- void glk_set_echo_line_event(winid_t win, glui32 val);
-#endif /* GLK_MODULE_LINE_ECHO */
-
-#ifdef GLK_MODULE_LINE_TERMINATORS
- void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
- glui32 count);
-#endif /* GLK_MODULE_LINE_TERMINATORS */
+ /**
+ * Returns true whether a given feature is supported by the engine
+ */
+ virtual bool hasFeature(EngineFeature f) const;
- /** \addtogroup Unicode
- * @{
+ /**
+ * Main game loop for the individual interpreters
*/
+ virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
+public:
+ Clipboard *_clipboard;
+ Conf *_conf;
+ Events *_events;
+ PicList *_picList;
+ Screen *_screen;
+ Selection *_selection;
+ Streams *_streams;
+ Windows *_windows;
+ bool _copySelect;
+ bool _terminated;
+ void (*gli_unregister_obj)(void *obj, glui32 objclass, gidispatch_rock_t objrock);
+ gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, const char *typecode);
+ void (*gli_unregister_arr)(void *array, glui32 len, const char *typecode, gidispatch_rock_t objrock);
- glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
- glui32 numchars, glui32 lowerrest);
-
- void glk_put_char_uni(glui32 ch);
- void glk_put_string_uni(glui32 *s);
- void glk_put_buffer_uni(glui32 *buf, glui32 len);
- void glk_put_char_stream_uni(strid_t str, glui32 ch);
- void glk_put_string_stream_uni(strid_t str, const glui32 *s);
- void glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len);
-
- glsi32 glk_get_char_stream_uni(strid_t str);
- 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, FileMode fmode, glui32 rock = 0);
- strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
-
- void glk_request_char_event_uni(winid_t win);
- void glk_request_line_event_uni(winid_t win, glui32 *buf,
- glui32 maxlen, glui32 initlen);
-
- /** @}*/
-
-#ifdef GLK_MODULE_UNICODE_NORM
-
- glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
- glui32 numchars);
- glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
- glui32 numchars);
-
-#endif /* GLK_MODULE_UNICODE_NORM */
-
-#ifdef GLK_MODULE_IMAGE
-
- glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
- glui32 glk_image_draw_scaled(winid_t win, glui32 image,
- glsi32 val1, glsi32 val2, glui32 width, glui32 height);
- glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
-
- void glk_window_flow_break(winid_t win);
-
- void glk_window_erase_rect(winid_t win,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
- void glk_window_fill_rect(winid_t win, glui32 color,
- glsi32 left, glsi32 top, glui32 width, glui32 height);
- void glk_window_set_background_color(winid_t win, glui32 color);
-
-#endif /* GLK_MODULE_IMAGE */
-
-#ifdef GLK_MODULE_SOUND
-
- schanid_t glk_schannel_create(glui32 rock = 0);
- void glk_schannel_destroy(schanid_t chan);
- schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
- glui32 glk_schannel_get_rock(schanid_t chan);
-
- glui32 glk_schannel_play(schanid_t chan, glui32 snd);
- glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
- glui32 notify);
- void glk_schannel_stop(schanid_t chan);
- void glk_schannel_set_volume(schanid_t chan, glui32 vol);
-
- void glk_sound_load_hint(glui32 snd, glui32 flag);
-
-#ifdef GLK_MODULE_SOUND2
- /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
- GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
-
- schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
- glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
- glui32 *sndarray, glui32 soundcount, glui32 notify);
- void glk_schannel_pause(schanid_t chan);
- void glk_schannel_unpause(schanid_t chan);
- void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
- glui32 duration, glui32 notify);
-
-#endif /* GLK_MODULE_SOUND2 */
-#endif /* GLK_MODULE_SOUND */
-
-#ifdef GLK_MODULE_HYPERLINKS
+public:
+ GlkEngine(OSystem *syst, const GlkGameDescription *gameDesc);
+ virtual ~GlkEngine();
- void glk_set_hyperlink(glui32 linkval);
- void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
- void glk_request_hyperlink_event(winid_t win);
- void glk_cancel_hyperlink_event(winid_t win);
+ /**
+ * Returns true if a savegame can be loaded
+ */
+ virtual bool canLoadGameStateCurrently() override {
+ return true;
+ }
-#endif /* GLK_MODULE_HYPERLINKS */
+ /**
+ * Returns true if the game can be saved
+ */
+ virtual bool canSaveGameStateCurrently() override {
+ return true;
+ }
-#ifdef GLK_MODULE_DATETIME
+ /**
+ * Returns the bitset of game features
+ */
+ uint32 getFeatures() const;
- void glk_current_time(glktimeval_t *time);
- glsi32 glk_current_simple_time(glui32 factor);
- void glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date);
- void glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date);
- void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date);
- void glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date);
- void glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time);
- void glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time);
- glsi32 glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor);
- glsi32 glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor);
+ /**
+ * Returns whether the game is a demo
+ */
+ bool isDemo() const;
-#endif /* GLK_MODULE_DATETIME */
+ /**
+ * Returns the language
+ */
+ Common::Language getLanguage() const;
- /* XXX non-official Glk functions that may or may not exist */
-#define GARGLK 1
+ /**
+ * Returns the running interpreter type
+ */
+ InterpreterType getInterpreterType() const;
- const char *garglk_fileref_get_name(frefid_t fref) const;
+ /**
+ * Returns the game's md5
+ */
+ const Common::String &getGameMD5() const;
- void garglk_set_program_name(const char *name);
- void garglk_set_program_info(const char *info);
- void garglk_set_story_name(const char *name);
- void garglk_set_story_title(const char *title);
- void garglk_set_config(const char *name);
+ /**
+ * Returns the primary filename for the game
+ */
+ const Common::String &getFilename() const;
/**
- * Removes the specified string from the end of the output buffer, if
- * indeed it is there.
+ * Return the game engine's target name
*/
- void garglk_unput_string(const char *str);
+ const Common::String &getTargetName() const {
+ return _targetName;
+ }
/**
- * Removes the specified string from the end of the output buffer, if
- * indeed it is there.
+ * Return the filename for a given save slot
*/
- void garglk_unput_string_uni(const glui32 *str);
+ Common::String getSaveName(uint slot) const {
+ return Common::String::format("%s.%.3u", getTargetName().c_str(), slot);
+ }
- void garglk_set_zcolors(glui32 fg, glui32 bg);
- void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
- void garglk_set_reversevideo(glui32 reverse);
- void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
+ /**
+ * Display a message in a GUI dialog
+ */
+ void GUIError(const char *msg, ...);
};
-} // End of namespace Gargoyle
+extern GlkEngine *g_vm;
+
+} // End of namespace Glk
#endif
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
new file mode 100644
index 0000000..c219cd1
--- /dev/null
+++ b/engines/glk/glk_api.cpp
@@ -0,0 +1,1174 @@
+/* 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.
+ *
+ */
+
+#include "glk/glk_api.h"
+#include "glk/conf.h"
+#include "glk/events.h"
+#include "glk/picture.h"
+#include "glk/streams.h"
+#include "glk/unicode.h"
+#include "glk/windows.h"
+#include "glk/window_graphics.h"
+#include "glk/window_text_buffer.h"
+#include "glk/window_pair.h"
+
+
+namespace Glk {
+
+GlkAPI::GlkAPI(OSystem *syst, const GlkGameDescription *gameDesc) :
+ GlkEngine(syst, gameDesc), _gliFirstEvent(false) {
+ // Set uppercase/lowercase tables
+ int ix, res;
+ for (ix = 0; ix < 256; ix++) {
+ _charToupperTable[ix] = ix;
+ _charTolowerTable[ix] = ix;
+ }
+
+ for (ix = 0; ix < 256; ix++) {
+ if (ix >= 'A' && ix <= 'Z')
+ res = ix + ('a' - 'A');
+ else if (ix >= 0xC0 && ix <= 0xDE && ix != 0xD7)
+ res = ix + 0x20;
+ else
+ res = 0;
+
+ if (res) {
+ _charTolowerTable[ix] = res;
+ _charToupperTable[res] = ix;
+ }
+ }
+}
+
+void GlkAPI::glk_exit(void) {
+ glk_put_string("[ press any key to exit ]");
+ _events->waitForPress();
+
+ quitGame();
+}
+
+void GlkAPI::glk_set_interrupt_handler(void(*func)(void)) {
+ // This library doesn't handle interrupts.
+}
+
+void GlkAPI::glk_tick(void) {
+ // Nothing needed
+}
+
+glui32 GlkAPI::glk_gestalt(glui32 id, glui32 val) {
+ return glk_gestalt_ext(id, val, nullptr, 0);
+}
+
+glui32 GlkAPI::glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen) {
+ switch (id) {
+ case gestalt_Version:
+ return 0x00000703;
+
+ case gestalt_LineInput:
+ if (val >= 32 && val < 0x10ffff)
+ return true;
+ else
+ return false;
+
+ case gestalt_CharInput:
+ if (val >= 32 && val < 0x10ffff)
+ return true;
+ else if (val == keycode_Return)
+ return true;
+ else
+ return false;
+
+ case gestalt_CharOutput:
+ if (val >= 32 && val < 0x10ffff) {
+ if (arr && arrlen >= 1)
+ arr[0] = 1;
+ return gestalt_CharOutput_ExactPrint;
+ } else {
+ // cheaply, we don't do any translation of printed characters,
+ // so the output is always one character even if it's wrong.
+ if (arr && arrlen >= 1)
+ arr[0] = 1;
+ return gestalt_CharOutput_CannotPrint;
+ }
+
+ case gestalt_MouseInput:
+ if (val == wintype_TextGrid)
+ return true;
+ if (val == wintype_Graphics)
+ return true;
+ return false;
+
+ case gestalt_Graphics:
+ case gestalt_GraphicsTransparency:
+ return g_conf->_graphics;
+
+ case gestalt_DrawImage:
+ if (val == wintype_TextBuffer)
+ return g_conf->_graphics;
+ if (val == wintype_Graphics)
+ return g_conf->_graphics;
+ return false;
+
+ case gestalt_Sound:
+ case gestalt_SoundVolume:
+ case gestalt_SoundMusic:
+ case gestalt_SoundNotify:
+ return g_conf->_sound;
+
+ case gestalt_LineTerminatorKey:
+ return Window::checkTerminator(val);
+
+ case gestalt_Timer:
+ case gestalt_Unicode:
+ case gestalt_UnicodeNorm:
+ case gestalt_Hyperlinks:
+ case gestalt_HyperlinkInput:
+ case gestalt_LineInputEcho:
+ case gestalt_LineTerminators:
+ case gestalt_DateTime:
+ case gestalt_GarglkText:
+ return true;
+
+ case gestalt_Sound2:
+ default:
+ return false;
+ }
+}
+
+unsigned char GlkAPI::glk_char_to_lower(unsigned char ch) {
+ return _charTolowerTable[ch];
+}
+
+unsigned char GlkAPI::glk_char_to_upper(unsigned char ch) {
+ return _charToupperTable[ch];
+}
+
+winid_t GlkAPI::glk_window_get_root(void) const {
+ return _windows->getRoot();
+}
+
+winid_t GlkAPI::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, glui32 rock) const {
+ return _windows->windowOpen(split, method, size, wintype, rock);
+}
+
+void GlkAPI::glk_window_close(winid_t win, stream_result_t *result) {
+ if (win) {
+ _windows->windowClose(win, result);
+ } else {
+ warning("glk_window_close: invalid ref");
+ }
+}
+
+void GlkAPI::glk_window_get_size(winid_t win, glui32 *width, glui32 *height) {
+ if (win) {
+ win->getSize(width, height);
+ } else {
+ warning("window_get_size: invalid ref");
+ }
+}
+
+void GlkAPI::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keywin) {
+ if (win) {
+ win->setArrangement(method, size, keywin);
+ } else {
+ warning("window_set_arrangement: invalid ref");
+ }
+}
+
+void GlkAPI::glk_window_get_arrangement(winid_t win, glui32 *method,
+ glui32 *size, winid_t *keyWin) {
+ if (win) {
+ win->getArrangement(method, size, keyWin);
+ } else {
+ warning("window_get_arrangement: invalid ref");
+ }
+}
+
+winid_t GlkAPI::glk_window_iterate(winid_t win, glui32 *rock) {
+ win = win ? win->_next : _windows->getRoot();
+
+ if (win) {
+ if (rock)
+ *rock = win->_rock;
+ return win;
+ }
+
+ if (rock)
+ *rock = 0;
+
+ return nullptr;
+}
+
+glui32 GlkAPI::glk_window_get_rock(winid_t win) {
+ if (win) {
+ return win->_rock;
+ } else {
+ warning("window_get_rock: invalid ref.");
+ return 0;
+ }
+}
+
+glui32 GlkAPI::glk_window_get_type(winid_t win) {
+ if (win) {
+ return win->_type;
+ } else {
+ warning("window_get_parent: invalid ref");
+ return 0;
+ }
+}
+
+winid_t GlkAPI::glk_window_get_parent(winid_t win) {
+ if (!win) {
+ warning("window_get_parent: invalid ref");
+ return 0;
+ }
+
+ return win->_parent;
+}
+
+winid_t GlkAPI::glk_window_get_sibling(winid_t win) {
+ if (!win) {
+ warning("window_get_sibling: invalid ref");
+ return nullptr;
+ }
+
+ PairWindow *parentWin = dynamic_cast<PairWindow *>(win->_parent);
+ if (!parentWin)
+ return nullptr;
+
+ if (parentWin->_child1 == win)
+ return parentWin->_child2;
+ else if (parentWin->_child2 == win)
+ return parentWin->_child1;
+
+ return nullptr;
+}
+
+void GlkAPI::glk_window_clear(winid_t win) {
+ if (!win) {
+ warning("window_clear: invalid ref");
+ } else {
+ if (win->_lineRequest || win->_lineRequestUni) {
+ if (g_conf->_safeClicks && _events->_forceClick) {
+ glk_cancel_line_event(win, nullptr);
+ _events->_forceClick = false;
+
+ win->clear();
+ } else {
+ warning("window_clear: window has pending line request");
+ return;
+ }
+ }
+
+ // Clear the window
+ win->clear();
+ }
+}
+
+void GlkAPI::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) {
+ if (win) {
+ win->moveCursor(Point(xpos, ypos));
+ } else {
+ warning("window_move_cursor: invalid ref");
+ }
+}
+
+strid_t GlkAPI::glk_window_get_stream(winid_t win) {
+ if (win) {
+ return win->_stream;
+ } else {
+ warning("window_get_stream: invalid ref");
+ return nullptr;
+ }
+}
+
+void GlkAPI::glk_window_set_echo_stream(winid_t win, strid_t str) {
+ if (win) {
+ win->_echoStream = str;
+ } else {
+ warning("window_set_echo_stream: invalid window id");
+ }
+}
+
+strid_t GlkAPI::glk_window_get_echo_stream(winid_t win) {
+ if (!win) {
+ warning("window_get_echo_stream: invalid ref");
+ return nullptr;
+ }
+
+ return win->_echoStream;
+}
+
+void GlkAPI::glk_set_window(winid_t win) {
+ _streams->setCurrent(win ? win->_stream : nullptr);
+}
+
+strid_t GlkAPI::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock) {
+ return _streams->openFileStream(fileref, fmode, rock, false);
+}
+
+strid_t GlkAPI::glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock) {
+ return _streams->openMemoryStream(buf, buflen, fmode, rock, false);
+}
+
+void GlkAPI::glk_stream_close(strid_t str, stream_result_t *result) {
+ str->close(result);
+}
+
+strid_t GlkAPI::glk_stream_iterate(strid_t str, glui32 *rockptr) const {
+ return str ? str->getNext(rockptr) : _streams->getFirst(rockptr);
+}
+
+glui32 GlkAPI::glk_stream_get_rock(strid_t str) const {
+ if (!str) {
+ warning("stream_get_rock: invalid ref");
+ return 0;
+ }
+
+ return str->getRock();
+}
+
+void GlkAPI::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekMode) {
+ if (str) {
+ str->setPosition(pos, seekMode);
+ } else {
+ warning("stream_set_position: invalid ref");
+ }
+}
+
+glui32 GlkAPI::glk_stream_get_position(strid_t str) const {
+ if (str) {
+ return str->getPosition();
+ } else {
+ warning("stream_get_position: invalid ref");
+ return 0;
+ }
+}
+
+void GlkAPI::glk_stream_set_current(strid_t str) {
+ _streams->setCurrent(str);
+}
+
+strid_t GlkAPI::glk_stream_get_current(void) {
+ return _streams->getCurrent();
+}
+
+void GlkAPI::glk_put_char(unsigned char ch) {
+ _streams->getCurrent()->putChar(ch);
+}
+
+void GlkAPI::glk_put_char_stream(strid_t str, unsigned char ch) {
+ if (str) {
+ str->putChar(ch);
+ } else {
+ warning("put_char_stream: invalid ref");
+ }
+}
+
+void GlkAPI::glk_put_string(const char *s) {
+ _streams->getCurrent()->putBuffer(s, strlen(s));
+}
+
+void GlkAPI::glk_put_string_stream(strid_t str, const char *s) {
+ str->putBuffer(s, strlen(s));
+}
+
+void GlkAPI::glk_put_buffer(char *buf, glui32 len) {
+ _streams->getCurrent()->putBuffer(buf, len);
+}
+
+void GlkAPI::glk_put_buffer_stream(strid_t str, const char *buf, glui32 len) {
+ str->putBuffer(buf, len);
+}
+
+void GlkAPI::glk_set_style(glui32 styl) {
+ _streams->getCurrent()->setStyle(styl);
+}
+
+void GlkAPI::glk_set_style_stream(strid_t str, glui32 styl) {
+ if (str) {
+ str->setStyle(styl);
+ } else {
+ warning("set_style_stream: invalid ref");
+ }
+}
+
+glsi32 GlkAPI::glk_get_char_stream(strid_t str) {
+ if (str) {
+ return str->getChar();
+ } else {
+ warning("get_char_stream: invalid ref");
+ return -1;
+ }
+}
+
+glui32 GlkAPI::glk_get_line_stream(strid_t str, char *buf, glui32 len) {
+ if (str) {
+ return str->getLine(buf, len);
+ } else {
+ warning("get_line_stream: invalid ref");
+ return 0;
+ }
+}
+
+glui32 GlkAPI::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) {
+ if (str) {
+ return str->getBuffer(buf, len);
+ } else {
+ warning("get_line_stream: invalid ref");
+ return 0;
+ }
+}
+
+void GlkAPI::glk_stylehint_set(glui32 wintype, glui32 style, glui32 hint, glsi32 val) {
+ WindowStyle *styles;
+ bool p, b, i;
+
+ if (wintype == wintype_AllTypes) {
+ glk_stylehint_set(wintype_TextGrid, style, hint, val);
+ glk_stylehint_set(wintype_TextBuffer, style, hint, val);
+ return;
+ }
+
+ if (wintype == wintype_TextGrid)
+ styles = g_conf->_gStyles;
+ else if (wintype == wintype_TextBuffer)
+ styles = g_conf->_tStyles;
+ else
+ return;
+
+ if (!g_conf->_styleHint)
+ return;
+
+ switch (hint) {
+ case stylehint_TextColor:
+ styles[style].fg[0] = (val >> 16) & 0xff;
+ styles[style].fg[1] = (val >> 8) & 0xff;
+ styles[style].fg[2] = (val) & 0xff;
+ break;
+
+ case stylehint_BackColor:
+ styles[style].bg[0] = (val >> 16) & 0xff;
+ styles[style].bg[1] = (val >> 8) & 0xff;
+ styles[style].bg[2] = (val) & 0xff;
+ break;
+
+ case stylehint_ReverseColor:
+ styles[style].reverse = (val != 0);
+ break;
+
+ case stylehint_Proportional:
+ if (wintype == wintype_TextBuffer) {
+ p = val > 0;
+ b = styles[style].isBold();
+ i = styles[style].isItalic();
+ styles[style].font = WindowStyle::makeFont(p, b, i);
+ }
+ break;
+
+ case stylehint_Weight:
+ p = styles[style].isProp();
+ b = val > 0;
+ i = styles[style].isItalic();
+ styles[style].font = WindowStyle::makeFont(p, b, i);
+ break;
+
+ case stylehint_Oblique:
+ p = styles[style].isProp();
+ b = styles[style].isBold();
+ i = val > 0;
+ styles[style].font = WindowStyle::makeFont(p, b, i);
+ break;
+ }
+
+ if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_BackColor) {
+ memcpy(g_conf->_windowColor, styles[style].bg, 3);
+ }
+
+ if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_TextColor) {
+ memcpy(g_conf->_moreColor, styles[style].fg, 3);
+ memcpy(g_conf->_caretColor, styles[style].fg, 3);
+ }
+}
+
+void GlkAPI::glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint) {
+ WindowStyle *styles;
+ const WindowStyle *defaults;
+
+ if (wintype == wintype_AllTypes) {
+ glk_stylehint_clear(wintype_TextGrid, style, hint);
+ glk_stylehint_clear(wintype_TextBuffer, style, hint);
+ return;
+ }
+
+ if (wintype == wintype_TextGrid) {
+ styles = g_conf->_gStyles;
+ defaults = g_conf->_gStylesDefault;
+ } else if (wintype == wintype_TextBuffer) {
+ styles = g_conf->_tStyles;
+ defaults = g_conf->_tStylesDefault;
+ } else {
+ return;
+ }
+
+ if (!g_conf->_styleHint)
+ return;
+
+ switch (hint) {
+ case stylehint_TextColor:
+ styles[style].fg[0] = defaults[style].fg[0];
+ styles[style].fg[1] = defaults[style].fg[1];
+ styles[style].fg[2] = defaults[style].fg[2];
+ break;
+
+ case stylehint_BackColor:
+ styles[style].bg[0] = defaults[style].bg[0];
+ styles[style].bg[1] = defaults[style].bg[1];
+ styles[style].bg[2] = defaults[style].bg[2];
+ break;
+
+ case stylehint_ReverseColor:
+ styles[style].reverse = defaults[style].reverse;
+ break;
+
+ case stylehint_Proportional:
+ case stylehint_Weight:
+ case stylehint_Oblique:
+ styles[style].font = defaults[style].font;
+ break;
+ }
+}
+
+glui32 GlkAPI::glk_style_distinguish(winid_t win, glui32 style1, glui32 style2) {
+ const WindowStyle *styles = win->getStyles();
+ if (!styles)
+ return false;
+
+ return styles[style1] == styles[style2] ? 0 : 1;
+}
+
+bool GlkAPI::glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result) {
+ const WindowStyle *styles = win->getStyles();
+ if (!styles)
+ return false;
+
+ switch (hint) {
+ case stylehint_Indentation:
+ case stylehint_ParaIndentation:
+ *result = 0;
+ break;
+
+ case stylehint_Justification:
+ *result = stylehint_just_LeftFlush;
+ break;
+
+ case stylehint_Size:
+ *result = 1;
+ break;
+
+ case stylehint_Weight:
+ *result =
+ (styles[style].font == PROPB || styles[style].font == PROPZ ||
+ styles[style].font == MONOB || styles[style].font == MONOZ);
+ break;
+
+ case stylehint_Oblique:
+ *result =
+ (styles[style].font == PROPI || styles[style].font == PROPZ ||
+ styles[style].font == MONOI || styles[style].font == MONOZ);
+ break;
+
+ case stylehint_Proportional:
+ *result =
+ (styles[style].font == PROPR || styles[style].font == PROPI ||
+ styles[style].font == PROPB || styles[style].font == PROPZ);
+ break;
+
+ case stylehint_TextColor:
+ *result =
+ (styles[style].fg[0] << 16) | (styles[style].fg[1] << 8) | (styles[style].fg[2]);
+ break;
+
+ case stylehint_BackColor:
+ *result =
+ (styles[style].bg[0] << 16) | (styles[style].bg[1] << 8) | (styles[style].bg[2]);
+ break;
+
+ case stylehint_ReverseColor:
+ *result = styles[style].reverse;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+frefid_t GlkAPI::glk_fileref_create_temp(glui32 usage, glui32 rock) {
+ return _streams->createTemp(usage, rock);
+}
+
+frefid_t GlkAPI::glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock) {
+ // Take out all dangerous characters
+ Common::String tempName(name);
+ for (uint idx = 0; idx < tempName.size(); ++idx) {
+ if (tempName[idx] == '/' || tempName[idx] == '\\' || tempName[idx] == ':')
+ tempName.setChar(idx, '-');
+ }
+
+ return _streams->createRef(tempName, usage, rock);
+}
+
+frefid_t GlkAPI::glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock) {
+ return _streams->createByPrompt(usage, fmode, rock);
+}
+
+frefid_t GlkAPI::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) {
+ if (!fref) {
+ warning("fileref_create_from_fileref: invalid ref");
+ return nullptr;
+ } else {
+ return _streams->createFromRef(fref, usage, rock);
+ }
+}
+
+void GlkAPI::glk_fileref_destroy(frefid_t fref) {
+ _streams->deleteRef(fref);
+}
+
+frefid_t GlkAPI::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) {
+ return _streams->iterate(fref, rockptr);
+}
+
+glui32 GlkAPI::glk_fileref_get_rock(frefid_t fref) {
+ if (!fref) {
+ warning("fileref_get_rock: invalid ref.");
+ return 0;
+ } else {
+ return fref->_rock;
+ }
+}
+
+void GlkAPI::glk_fileref_delete_file(frefid_t fref) {
+ fref->deleteFile();
+}
+
+glui32 GlkAPI::glk_fileref_does_file_exist(frefid_t fref) {
+ return fref->exists();
+}
+
+void GlkAPI::glk_select(event_t *event) {
+ if (!_gliFirstEvent) {
+ _windows->inputGuessFocus();
+ _gliFirstEvent = true;
+ }
+
+ _events->getEvent(event, false);
+}
+
+void GlkAPI::glk_select_poll(event_t *event) {
+ if (!_gliFirstEvent) {
+ _windows->inputGuessFocus();
+ _gliFirstEvent = true;
+ }
+
+ _events->getEvent(event, true);
+}
+
+void GlkAPI::glk_request_timer_events(glui32 millisecs) {
+ _events->setTimerInterval(millisecs);
+}
+
+void GlkAPI::glk_request_line_event(winid_t win, char *buf, glui32 maxlen, glui32 initlen) {
+ if (!win) {
+ warning("request_line_event: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_line_event: window already has keyboard request");
+ } else {
+ win->requestLineEvent(buf, maxlen, initlen);
+ }
+}
+
+void GlkAPI::glk_request_char_event(winid_t win) {
+ if (!win) {
+ warning("request_char_event: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_char_event: window already has keyboard request");
+ } else {
+ win->requestCharEvent();
+ }
+}
+
+void GlkAPI::glk_request_mouse_event(winid_t win) {
+ if (!win) {
+ warning("request_mouse_event: invalid ref");
+ } else {
+ win->requestMouseEvent();
+ }
+}
+
+void GlkAPI::glk_cancel_line_event(winid_t win, event_t *event) {
+ if (!win) {
+ warning("cancel_line_event: invalid ref");
+ } else {
+ win->cancelLineEvent(event);
+ }
+}
+
+void GlkAPI::glk_cancel_char_event(winid_t win) {
+ if (!win) {
+ warning("glk_cancel_char_event: invalid ref");
+ } else {
+ win->cancelCharEvent();
+ }
+}
+
+void GlkAPI::glk_cancel_mouse_event(winid_t win) {
+ if (!win) {
+ warning("cancel_mouse_event: invalid ref");
+ } else {
+ win->cancelMouseEvent();
+ }
+}
+
+void GlkAPI::glk_set_echo_line_event(winid_t win, glui32 val) {
+ if (!win) {
+ warning("set_echo_line_event: invalid ref");
+ } else {
+ win->setEchoLineEvent(val);
+ }
+}
+
+void GlkAPI::glk_set_terminators_line_event(winid_t win, glui32 *keycodes, glui32 count) {
+ if (!win) {
+ warning("set_terminators_line_event: invalid ref");
+ } else {
+ win->setTerminatorsLineEvent(keycodes, count);
+ }
+}
+
+glui32 GlkAPI::glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return bufferChangeCase(buf, len, numchars, CASE_LOWER, COND_ALL, true);
+}
+
+glui32 GlkAPI::glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return bufferChangeCase(buf, len, numchars, CASE_UPPER, COND_ALL, true);
+}
+
+glui32 GlkAPI::glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest) {
+ return bufferChangeCase(buf, len, numchars, CASE_TITLE, COND_LINESTART, lowerrest);
+}
+
+void GlkAPI::glk_put_char_uni(glui32 ch) {
+ _streams->getCurrent()->putCharUni(ch);
+}
+
+void GlkAPI::glk_put_string_uni(glui32 *s) {
+ _streams->getCurrent()->putBufferUni(s, strlen_uni(s));
+}
+
+void GlkAPI::glk_put_buffer_uni(glui32 *buf, glui32 len) {
+ _streams->getCurrent()->putBufferUni(buf, len);
+}
+
+void GlkAPI::glk_put_char_stream_uni(strid_t str, glui32 ch) {
+ if (str) {
+ str->putCharUni(ch);
+ } else {
+ warning("put_char_stream_uni: invalid ref");
+ }
+}
+
+void GlkAPI::glk_put_string_stream_uni(strid_t str, const glui32 *s) {
+ if (str) {
+ str->putBufferUni(s, strlen_uni(s));
+ } else {
+ warning("put_string_stream_uni: invalid ref");
+ }
+}
+
+void GlkAPI::glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len) {
+ if (str) {
+ str->putBufferUni(buf, len);
+ } else {
+ warning("put_buffer_stream_uni: invalid ref");
+ }
+}
+
+glsi32 GlkAPI::glk_get_char_stream_uni(strid_t str) {
+ if (str) {
+ return str->getCharUni();
+ } else {
+ warning("get_char_stream_uni: invalid ref");
+ return -1;
+ }
+}
+
+glui32 GlkAPI::glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ if (str) {
+ return str->getBufferUni(buf, len);
+ } else {
+ warning("get_buffer_stream_uni: invalid ref");
+ return 0;
+ }
+}
+
+glui32 GlkAPI::glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) {
+ if (str) {
+ return str->getLineUni(buf, len);
+ } else {
+ warning("get_line_stream_uni: invalid ref");
+ return (glui32) - 1;
+ }
+}
+
+strid_t GlkAPI::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 rock) {
+ return _streams->openFileStream(fileref, fmode, rock, true);
+}
+
+strid_t GlkAPI::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock) {
+ return _streams->openMemoryStream(buf, buflen, fmode, rock, true);
+}
+
+void GlkAPI::glk_request_char_event_uni(winid_t win) {
+ if (!win) {
+ warning("request_char_event_uni: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_char_event_uni: window already has keyboard request");
+ } else {
+ win->requestCharEvent();
+ }
+}
+
+void GlkAPI::glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (!win) {
+ warning("request_line_event_uni: invalid ref");
+ } else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
+ || win->_lineRequestUni) {
+ warning("request_line_event_uni: window already has keyboard request");
+ } else {
+ win->requestLineEventUni(buf, maxlen, initlen);
+ }
+}
+
+glui32 GlkAPI::glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars) {
+ // TODO
+ return 0;
+}
+
+glui32 GlkAPI::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 numchars) {
+ return 0;
+}
+
+glui32 GlkAPI::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
+ if (!win) {
+ warning("image_draw: invalid ref");
+ } else if (g_conf->_graphics) {
+ TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
+ GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
+
+ if (textWin)
+ textWin->drawPicture(image, val1, false, 0, 0);
+ else if (gfxWin)
+ gfxWin->drawPicture(image, val1, val2, false, 0, 0);
+ }
+
+ return false;
+}
+
+glui32 GlkAPI::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2,
+ glui32 width, glui32 height) {
+ if (!win) {
+ warning("image_draw_scaled: invalid ref");
+ } else if (g_conf->_graphics) {
+ TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
+ GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
+
+ if (textWin)
+ textWin->drawPicture(image, val1, true, width, height);
+ else if (gfxWin)
+ gfxWin->drawPicture(image, val1, val2, true, width, height);
+ }
+
+ return false;
+}
+
+glui32 GlkAPI::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
+ if (!g_conf->_graphics)
+ return false;
+
+ Picture *pic = Picture::load(image);
+ if (!pic)
+ return false;
+
+ if (width)
+ *width = pic->w;
+ if (height)
+ *height = pic->h;
+
+ return true;
+}
+
+void GlkAPI::glk_window_flow_break(winid_t win) {
+ if (!win) {
+ warning("window_erase_rect: invalid ref");
+ } else {
+ win->flowBreak();
+ }
+}
+
+void GlkAPI::glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 height) {
+ if (!win) {
+ warning("window_erase_rect: invalid ref");
+ } else {
+ win->eraseRect(false, Rect(left, top, left + width, top + height));
+ }
+}
+
+void GlkAPI::glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top,
+ glui32 width, glui32 height) {
+ if (!win) {
+ warning("window_fill_rect: invalid ref");
+ } else {
+ win->eraseRect(color, Rect(left, top, left + width, top + height));
+ }
+}
+
+void GlkAPI::glk_window_set_background_color(winid_t win, glui32 color) {
+ if (!win) {
+ warning("window_set_background_color: invalid ref");
+ } else {
+ win->setBackgroundColor(color);
+ }
+}
+
+schanid_t GlkAPI::glk_schannel_create(glui32 rock) {
+ // TODO
+ return nullptr;
+}
+
+void GlkAPI::glk_schannel_destroy(schanid_t chan) {
+ // TODO
+}
+
+schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
+ // TODO
+ return nullptr;
+}
+
+glui32 GlkAPI::glk_schannel_get_rock(schanid_t chan) {
+ // TODO
+ return 0;
+}
+
+glui32 GlkAPI::glk_schannel_play(schanid_t chan, glui32 snd) {
+ // TODO
+ return 0;
+}
+
+glui32 GlkAPI::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
+ // TODO
+ return 0;
+}
+
+void GlkAPI::glk_schannel_stop(schanid_t chan) {
+ // TODO
+}
+
+void GlkAPI::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
+ // TODO
+}
+
+void GlkAPI::glk_sound_load_hint(glui32 snd, glui32 flag) {
+ // TODO
+}
+
+schanid_t GlkAPI::glk_schannel_create_ext(glui32 rock, glui32 volume) {
+ // TODO
+ return nullptr;
+}
+
+glui32 GlkAPI::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify) {
+ // TODO
+ return 0;
+}
+
+void GlkAPI::glk_schannel_pause(schanid_t chan) {
+ // TODO
+}
+
+void GlkAPI::glk_schannel_unpause(schanid_t chan) {
+ // TODO
+}
+
+void GlkAPI::glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify) {
+ // TODO
+}
+
+void GlkAPI::glk_set_hyperlink(glui32 linkval) {
+ _streams->getCurrent()->setHyperlink(linkval);
+}
+
+void GlkAPI::glk_set_hyperlink_stream(strid_t str, glui32 linkval) {
+ if (str)
+ str->setHyperlink(linkval);
+}
+
+void GlkAPI::glk_request_hyperlink_event(winid_t win) {
+ if (!win) {
+ warning("request_hyperlink_event: invalid ref");
+ } else {
+ win->requestHyperlinkEvent();
+ }
+}
+
+void GlkAPI::glk_cancel_hyperlink_event(winid_t win) {
+ if (win) {
+ win->cancelHyperlinkEvent();
+ } else {
+ warning("cancel_hyperlink_event: invalid ref");
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void GlkAPI::glk_current_time(glktimeval_t *time) {
+ TimeAndDate td;
+ *time = td;
+}
+
+glsi32 GlkAPI::glk_current_simple_time(glui32 factor) {
+ assert(factor);
+ TimeAndDate td;
+
+ return td / factor;
+}
+
+void GlkAPI::glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date) {
+ // TODO: timezones aren't currently supported
+ *date = TimeAndDate(*time);
+}
+
+void GlkAPI::glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date) {
+ *date = TimeAndDate(*time);
+}
+
+void GlkAPI::glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date) {
+ TimeSeconds secs = (int64)time * factor;
+ *date = TimeAndDate(secs);
+}
+
+void GlkAPI::glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date) {
+ TimeSeconds secs = (int64)time * factor;
+ *date = TimeAndDate(secs);
+}
+
+void GlkAPI::glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time) {
+ // WORKAROUND: timezones aren't currently supported
+ *time = TimeAndDate(*date);
+}
+
+void GlkAPI::glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time) {
+ *time = TimeAndDate(*date);
+}
+
+glsi32 GlkAPI::glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor) {
+ // WORKAROUND: timezones aren't currently supported
+ assert(factor);
+ TimeSeconds ts = TimeAndDate(*date);
+ return ts / factor;
+}
+
+glsi32 GlkAPI::glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor) {
+ assert(factor);
+ TimeSeconds ts = TimeAndDate(*date);
+ return ts / factor;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* XXX non-official Glk functions */
+
+const char *GlkAPI::garglk_fileref_get_name(frefid_t fref) const {
+ return fref->_filename.c_str();
+}
+
+void GlkAPI::garglk_set_program_name(const char *name) {
+ // Program name isn't displayed
+}
+
+void GlkAPI::garglk_set_program_info(const char *info) {
+ // Program info isn't displayed
+}
+
+void GlkAPI::garglk_set_story_name(const char *name) {
+ // Story name isn't displayed
+}
+
+void GlkAPI::garglk_set_story_title(const char *title) {
+ // Story title isn't displayed
+}
+
+void GlkAPI::garglk_set_config(const char *name) {
+ // No implementation
+}
+
+void GlkAPI::garglk_unput_string(const char *str) {
+ _streams->getCurrent()->unputBuffer(str, strlen(str));
+}
+
+void GlkAPI::garglk_unput_string_uni(const glui32 *str) {
+ _streams->getCurrent()->unputBufferUni(str, strlen_uni(str));
+}
+
+void GlkAPI::garglk_set_zcolors(glui32 fg, glui32 bg) {
+ _streams->getCurrent()->setZColors(fg, bg);
+}
+
+void GlkAPI::garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg) {
+ if (str) {
+ str->setZColors(fg, bg);
+ } else {
+ warning("set_style_stream: Invalid ref");
+ }
+}
+
+void GlkAPI::garglk_set_reversevideo(glui32 reverse) {
+ _streams->getCurrent()->setReverseVideo(reverse != 0);
+}
+
+void GlkAPI::garglk_set_reversevideo_stream(strid_t str, glui32 reverse) {
+ if (str) {
+ str->setReverseVideo(reverse != 0);
+ } else {
+ warning("set_reversevideo: Invalid ref");
+ }
+}
+
+} // End of namespace Glk
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
new file mode 100644
index 0000000..f864ac9
--- /dev/null
+++ b/engines/glk/glk_api.h
@@ -0,0 +1,292 @@
+/* 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_GLK_API_H
+#define GLK_GLK_API_H
+
+#include "glk/glk.h"
+#include "glk/glk_types.h"
+#include "glk/blorb.h"
+#include "glk/time.h"
+#include "glk/windows.h"
+
+namespace Glk {
+
+/**
+ * Implements the GLK interface
+ */
+class GlkAPI : public GlkEngine, public Blorb {
+private:
+ bool _gliFirstEvent;
+ unsigned char _charTolowerTable[256];
+ unsigned char _charToupperTable[256];
+public:
+ /**
+ * Constructor
+ */
+ GlkAPI(OSystem *syst, const GlkGameDescription *gameDesc);
+
+ void glk_exit(void);
+ void glk_set_interrupt_handler(void(*func)(void));
+ void glk_tick(void);
+
+ glui32 glk_gestalt(glui32 id, glui32 val);
+ glui32 glk_gestalt_ext(glui32 id, glui32 val, glui32 *arr, glui32 arrlen);
+
+ unsigned char glk_char_to_lower(unsigned char ch);
+ unsigned char glk_char_to_upper(unsigned char ch);
+
+ /**
+ * Get the root window of the window hierarchy
+ */
+ winid_t glk_window_get_root(void) const;
+
+ /**
+ * Open a new window
+ */
+ winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock = 0) const;
+
+ void glk_window_close(winid_t win, stream_result_t *result = nullptr);
+ void glk_window_get_size(winid_t win, glui32 *width, glui32 *height);
+ void glk_window_set_arrangement(winid_t win, glui32 method,
+ glui32 size, winid_t keyWin);
+ void glk_window_get_arrangement(winid_t win, glui32 *method,
+ glui32 *size, winid_t *keyWin);
+ winid_t glk_window_iterate(winid_t win, glui32 *rock = 0);
+ glui32 glk_window_get_rock(winid_t win);
+ glui32 glk_window_get_type(winid_t win);
+ winid_t glk_window_get_parent(winid_t win);
+ winid_t glk_window_get_sibling(winid_t win);
+ void glk_window_clear(winid_t win);
+ void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos);
+
+ strid_t glk_window_get_stream(winid_t win);
+ void glk_window_set_echo_stream(winid_t win, strid_t str);
+ 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, FileMode fmode, glui32 rock = 0);
+ strid_t glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
+ void glk_stream_close(strid_t str, stream_result_t *result = nullptr);
+ 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) const;
+ void glk_stream_set_current(strid_t str);
+ strid_t glk_stream_get_current(void);
+
+ void glk_put_char(unsigned char ch);
+ void glk_put_char_stream(strid_t str, unsigned char ch);
+ void glk_put_string(const char *s);
+ void glk_put_string_stream(strid_t str, const char *s);
+ void glk_put_buffer(char *buf, glui32 len);
+ void glk_put_buffer_stream(strid_t str, const char *buf, glui32 len);
+ void glk_set_style(glui32 styl);
+ void glk_set_style_stream(strid_t str, glui32 styl);
+
+ glsi32 glk_get_char_stream(strid_t str);
+ glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len);
+ glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len);
+
+ void glk_stylehint_set(glui32 wintype, glui32 styl, glui32 hint,
+ glsi32 val);
+ void glk_stylehint_clear(glui32 wintype, glui32 style, glui32 hint);
+ glui32 glk_style_distinguish(winid_t win, glui32 style1, glui32 style2);
+ bool glk_style_measure(winid_t win, glui32 style, glui32 hint, glui32 *result);
+
+ frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock = 0);
+ frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock = 0);
+ frefid_t glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock = 0);
+ frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock = 0);
+ void glk_fileref_destroy(frefid_t fref);
+ frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr);
+ glui32 glk_fileref_get_rock(frefid_t fref);
+ void glk_fileref_delete_file(frefid_t fref);
+ glui32 glk_fileref_does_file_exist(frefid_t fref);
+
+ void glk_select(event_t *event);
+ void glk_select_poll(event_t *event);
+
+ void glk_request_timer_events(glui32 millisecs);
+
+ void glk_request_line_event(winid_t win, char *buf, glui32 maxlen,
+ glui32 initlen);
+ void glk_request_char_event(winid_t win);
+ void glk_request_mouse_event(winid_t win);
+
+ void glk_cancel_line_event(winid_t win, event_t *event);
+ void glk_cancel_char_event(winid_t win);
+ void glk_cancel_mouse_event(winid_t win);
+
+#ifdef GLK_MODULE_LINE_ECHO
+ void glk_set_echo_line_event(winid_t win, glui32 val);
+#endif /* GLK_MODULE_LINE_ECHO */
+
+#ifdef GLK_MODULE_LINE_TERMINATORS
+ void glk_set_terminators_line_event(winid_t win, glui32 *keycodes,
+ glui32 count);
+#endif /* GLK_MODULE_LINE_TERMINATORS */
+
+ /** \addtogroup Unicode
+ * @{
+ */
+
+ glui32 glk_buffer_to_lower_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_upper_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_to_title_case_uni(glui32 *buf, glui32 len,
+ glui32 numchars, glui32 lowerrest);
+
+ void glk_put_char_uni(glui32 ch);
+ void glk_put_string_uni(glui32 *s);
+ void glk_put_buffer_uni(glui32 *buf, glui32 len);
+ void glk_put_char_stream_uni(strid_t str, glui32 ch);
+ void glk_put_string_stream_uni(strid_t str, const glui32 *s);
+ void glk_put_buffer_stream_uni(strid_t str, const glui32 *buf, glui32 len);
+
+ glsi32 glk_get_char_stream_uni(strid_t str);
+ 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, FileMode fmode, glui32 rock = 0);
+ strid_t glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock = 0);
+
+ void glk_request_char_event_uni(winid_t win);
+ void glk_request_line_event_uni(winid_t win, glui32 *buf,
+ glui32 maxlen, glui32 initlen);
+
+ /** @}*/
+
+#ifdef GLK_MODULE_UNICODE_NORM
+
+ glui32 glk_buffer_canon_decompose_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+ glui32 glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len,
+ glui32 numchars);
+
+#endif /* GLK_MODULE_UNICODE_NORM */
+
+#ifdef GLK_MODULE_IMAGE
+
+ glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
+ glui32 glk_image_draw_scaled(winid_t win, glui32 image,
+ glsi32 val1, glsi32 val2, glui32 width, glui32 height);
+ glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
+
+ void glk_window_flow_break(winid_t win);
+
+ void glk_window_erase_rect(winid_t win,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_fill_rect(winid_t win, glui32 color,
+ glsi32 left, glsi32 top, glui32 width, glui32 height);
+ void glk_window_set_background_color(winid_t win, glui32 color);
+
+#endif /* GLK_MODULE_IMAGE */
+
+#ifdef GLK_MODULE_SOUND
+
+ schanid_t glk_schannel_create(glui32 rock = 0);
+ void glk_schannel_destroy(schanid_t chan);
+ schanid_t glk_schannel_iterate(schanid_t chan, glui32 *rockptr);
+ glui32 glk_schannel_get_rock(schanid_t chan);
+
+ glui32 glk_schannel_play(schanid_t chan, glui32 snd);
+ glui32 glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats,
+ glui32 notify);
+ void glk_schannel_stop(schanid_t chan);
+ void glk_schannel_set_volume(schanid_t chan, glui32 vol);
+
+ void glk_sound_load_hint(glui32 snd, glui32 flag);
+
+#ifdef GLK_MODULE_SOUND2
+ /* Note that this section is nested inside the #ifdef GLK_MODULE_SOUND.
+ GLK_MODULE_SOUND must be defined if GLK_MODULE_SOUND2 is. */
+
+ schanid_t glk_schannel_create_ext(glui32 rock, glui32 volume);
+ glui32 glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
+ glui32 *sndarray, glui32 soundcount, glui32 notify);
+ void glk_schannel_pause(schanid_t chan);
+ void glk_schannel_unpause(schanid_t chan);
+ void glk_schannel_set_volume_ext(schanid_t chan, glui32 vol,
+ glui32 duration, glui32 notify);
+
+#endif /* GLK_MODULE_SOUND2 */
+#endif /* GLK_MODULE_SOUND */
+
+#ifdef GLK_MODULE_HYPERLINKS
+
+ void glk_set_hyperlink(glui32 linkval);
+ void glk_set_hyperlink_stream(strid_t str, glui32 linkval);
+ void glk_request_hyperlink_event(winid_t win);
+ void glk_cancel_hyperlink_event(winid_t win);
+
+#endif /* GLK_MODULE_HYPERLINKS */
+
+#ifdef GLK_MODULE_DATETIME
+
+ void glk_current_time(glktimeval_t *time);
+ glsi32 glk_current_simple_time(glui32 factor);
+ void glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date);
+ void glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date);
+ void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date);
+ void glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date);
+ void glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time);
+ void glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time);
+ glsi32 glk_date_to_simple_time_utc(const glkdate_t *date, glui32 factor);
+ glsi32 glk_date_to_simple_time_local(const glkdate_t *date, glui32 factor);
+
+#endif /* GLK_MODULE_DATETIME */
+
+ /* XXX non-official Glk functions that may or may not exist */
+#define GARGLK 1
+
+ const char *garglk_fileref_get_name(frefid_t fref) const;
+
+ void garglk_set_program_name(const char *name);
+ void garglk_set_program_info(const char *info);
+ void garglk_set_story_name(const char *name);
+ void garglk_set_story_title(const char *title);
+ void garglk_set_config(const char *name);
+
+ /**
+ * Removes the specified string from the end of the output buffer, if
+ * indeed it is there.
+ */
+ void garglk_unput_string(const char *str);
+
+ /**
+ * Removes the specified string from the end of the output buffer, if
+ * indeed it is there.
+ */
+ void garglk_unput_string_uni(const glui32 *str);
+
+ void garglk_set_zcolors(glui32 fg, glui32 bg);
+ void garglk_set_zcolors_stream(strid_t str, glui32 fg, glui32 bg);
+ void garglk_set_reversevideo(glui32 reverse);
+ void garglk_set_reversevideo_stream(strid_t str, glui32 reverse);
+};
+
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/glk_types.h b/engines/glk/glk_types.h
index 32b0968..1745178 100644
--- a/engines/glk/glk_types.h
+++ b/engines/glk/glk_types.h
@@ -26,7 +26,7 @@
#include "common/scummsys.h"
#include "common/stream.h"
-namespace Gargoyle {
+namespace Glk {
typedef uint32 glui32;
typedef int32 glsi32;
@@ -203,6 +203,6 @@ union gidispatch_rock_t {
void *ptr;
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index e3fa26b..3fd88ef 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -6,8 +6,8 @@ MODULE_OBJS := \
detection.o \
events.o \
fonts.o \
- gargoyle.o \
glk.o \
+ glk_api.o \
picture.o \
screen.o \
selection.o \
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 444589b..b87b129 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -22,7 +22,7 @@
#include "glk/picture.h"
-namespace Gargoyle {
+namespace Glk {
void PicList::increment() {
// TODO
@@ -60,4 +60,4 @@ void Picture::drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1) {
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/picture.h b/engines/glk/picture.h
index e29d420..3ca615b 100644
--- a/engines/glk/picture.h
+++ b/engines/glk/picture.h
@@ -25,7 +25,7 @@
#include "graphics/surface.h"
-namespace Gargoyle {
+namespace Glk {
class PicList {
public:
@@ -68,6 +68,6 @@ public:
void drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1);
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index 900f650..7afdf93 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -24,7 +24,7 @@
#include "common/file.h"
#include "common/md5.h"
-namespace Gargoyle {
+namespace Glk {
namespace Scott {
struct ScottGame {
@@ -106,4 +106,4 @@ bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/scott/detection.h b/engines/glk/scott/detection.h
index cd487bd..2c187cd 100644
--- a/engines/glk/scott/detection.h
+++ b/engines/glk/scott/detection.h
@@ -26,7 +26,7 @@
#include "common/fs.h"
#include "engines/game.h"
-namespace Gargoyle {
+namespace Glk {
namespace Scott {
class ScottMetaEngine {
@@ -38,6 +38,6 @@ public:
};
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index a5e8667..2def1a2 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -23,10 +23,10 @@
#include "glk/scott/scott.h"
#include "common/config-manager.h"
-namespace Gargoyle {
+namespace Glk {
namespace Scott {
-Scott::Scott(OSystem *syst, const GargoyleGameDescription *gameDesc) : Glk(syst, gameDesc),
+Scott::Scott(OSystem *syst, const GlkGameDescription *gameDesc) : GlkAPI(syst, gameDesc),
Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
split_screen(true), Bottom(0), Top(0), BitFlags(0), _saveSlot(-1) {
@@ -1260,4 +1260,4 @@ void Scott::readInts(Common::SeekableReadStream *f, size_t count, ...) {
}
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index ec6a860..6899485 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -28,9 +28,9 @@
*/
#include "common/scummsys.h"
-#include "glk/glk.h"
+#include "glk/glk_api.h"
-namespace Gargoyle {
+namespace Glk {
namespace Scott {
#define LIGHT_SOURCE 9 // Always 9 how odd
@@ -109,7 +109,7 @@ struct Tail {
/**
* Scott Adams game interpreter
*/
-class Scott : public Glk {
+class Scott : public GlkAPI {
private:
Header GameHeader;
Item *Items;
@@ -167,7 +167,7 @@ public:
/**
* Constructor
*/
- Scott(OSystem *syst, const GargoyleGameDescription *gameDesc);
+ Scott(OSystem *syst, const GlkGameDescription *gameDesc);
/**
* Execute the game
@@ -186,6 +186,6 @@ public:
};
} // End of namespace Scott
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/screen.cpp b/engines/glk/screen.cpp
index ff46f1b..1a76ac8 100644
--- a/engines/glk/screen.cpp
+++ b/engines/glk/screen.cpp
@@ -23,7 +23,7 @@
#include "glk/screen.h"
#include "glk/conf.h"
-namespace Gargoyle {
+namespace Glk {
void Screen::fill(const byte *rgb) {
uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
@@ -69,4 +69,4 @@ void Screen::drawCaret(const Point &pos) {
}
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/screen.h b/engines/glk/screen.h
index e81cf9f..0020d86 100644
--- a/engines/glk/screen.h
+++ b/engines/glk/screen.h
@@ -26,7 +26,7 @@
#include "graphics/screen.h"
#include "glk/fonts.h"
-namespace Gargoyle {
+namespace Glk {
enum CaretShape {
SMALL_DOT = 0, FAT_DOT = 1, THIN_LINE = 2, FAT_LINE = 3, BLOCK = 4
@@ -60,6 +60,6 @@ public:
void drawCaret(const Point &pos);
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/selection.cpp b/engines/glk/selection.cpp
index f1c5bb8..2bc4fb8 100644
--- a/engines/glk/selection.cpp
+++ b/engines/glk/selection.cpp
@@ -22,11 +22,11 @@
#include "glk/selection.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/windows.h"
#include "common/system.h"
-namespace Gargoyle {
+namespace Glk {
void Clipboard::clipboardStore(const Common::U32String &text) {
_text = text;
@@ -318,4 +318,4 @@ bool Selection::getSelection(const Rect &r, int *rx0, int *rx1) const {
return (rx0 && rx1);
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/selection.h b/engines/glk/selection.h
index aa44a1d..4497d68 100644
--- a/engines/glk/selection.h
+++ b/engines/glk/selection.h
@@ -29,7 +29,7 @@
#include "common/rect.h"
#include "common/ustr.h"
-namespace Gargoyle {
+namespace Glk {
enum ClipSource { PRIMARY = 0, CLIPBOARD = 1 };
@@ -115,6 +115,6 @@ public:
bool getSelection(const Rect &r, int *rx0, int *rx1) const;
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/speech.h b/engines/glk/speech.h
index 5f92555..df4a89e 100644
--- a/engines/glk/speech.h
+++ b/engines/glk/speech.h
@@ -26,7 +26,7 @@
#include "common/events.h"
#include "glk/glk_types.h"
-namespace Gargoyle {
+namespace Glk {
/**
* Currently not implemented
@@ -44,6 +44,6 @@ protected:
void gli_free_tts(void) {}
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index d53f5d7..801cd54 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -23,14 +23,14 @@
#include "glk/streams.h"
#include "glk/conf.h"
#include "glk/events.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/windows.h"
#include "gui/saveload.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/translation.h"
-namespace Gargoyle {
+namespace Glk {
Stream::Stream(Streams *streams, bool readable, bool writable, uint32 rock, bool unicode) :
_streams(streams), _readable(readable), _writable(writable), _readCount(0),
@@ -1589,4 +1589,4 @@ void FileReference::deleteFile() {
g_system->getSavefileManager()->removeSavefile(filename);
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/streams.h b/engines/glk/streams.h
index 24ecc68..32bde70 100644
--- a/engines/glk/streams.h
+++ b/engines/glk/streams.h
@@ -29,7 +29,7 @@
#include "common/str.h"
#include "glk/glk_types.h"
-namespace Gargoyle {
+namespace Glk {
#define SAVEGAME_VERSION 1
@@ -634,6 +634,6 @@ public:
frefid_t iterate(frefid_t fref, glui32 *rock);
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/time.cpp b/engines/glk/time.cpp
index 9442102..df09716 100644
--- a/engines/glk/time.cpp
+++ b/engines/glk/time.cpp
@@ -23,7 +23,7 @@
#include "glk/time.h"
#include "common/system.h"
-namespace Gargoyle {
+namespace Glk {
TimeAndDate::TimeAndDate() {
::TimeDate t;
@@ -117,4 +117,4 @@ TimeSeconds TimeAndDate::getTime() const {
return totalMinutes * 60 + second;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/time.h b/engines/glk/time.h
index 119fab7..8e68328 100644
--- a/engines/glk/time.h
+++ b/engines/glk/time.h
@@ -25,7 +25,7 @@
#include "glk/glk_types.h"
-namespace Gargoyle {
+namespace Glk {
typedef int64 TimeSeconds;
@@ -88,6 +88,6 @@ public:
};
typedef TimeAndDate glkdate_t;
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/unicode.cpp b/engines/glk/unicode.cpp
index dd88c95..d9f2ee1 100644
--- a/engines/glk/unicode.cpp
+++ b/engines/glk/unicode.cpp
@@ -24,7 +24,7 @@
#include "glk/unicode_gen.h"
#include "common/textconsole.h"
-namespace Gargoyle {
+namespace Glk {
size_t strlen_uni(const uint32 *s) {
size_t len = 0;
@@ -148,4 +148,4 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
return outcount;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/unicode.h b/engines/glk/unicode.h
index 249ab5d..3165d39 100644
--- a/engines/glk/unicode.h
+++ b/engines/glk/unicode.h
@@ -25,7 +25,7 @@
#include "glk/glk_types.h"
-namespace Gargoyle {
+namespace Glk {
typedef glui32 gli_case_block_t[2]; /* upper, lower */
enum BufferChangeCase { CASE_UPPER = 0, CASE_LOWER = 1, CASE_TITLE = 2, CASE_IDENT = 3 };
@@ -46,6 +46,6 @@ size_t strlen_uni(const uint32 *s);
extern glui32 bufferChangeCase(glui32 *buf, glui32 len,
glui32 numchars, BufferChangeCase destcase, BufferChangeCond cond, int changerest);
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/unicode_gen.cpp b/engines/glk/unicode_gen.cpp
index ac8a149..9c67859 100644
--- a/engines/glk/unicode_gen.cpp
+++ b/engines/glk/unicode_gen.cpp
@@ -27,7 +27,7 @@
#include "glk/unicode_gen.h"
-namespace Gargoyle {
+namespace Glk {
gli_case_block_t unigen_case_block_0x0[256] = {
{ 0x0, 0x0 },
@@ -11823,4 +11823,4 @@ gli_decomp_block_t unigen_decomp_block_0x2fa[256] = {
*countptr = 0; \
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/unicode_gen.h b/engines/glk/unicode_gen.h
index f601bf6..6822d69 100644
--- a/engines/glk/unicode_gen.h
+++ b/engines/glk/unicode_gen.h
@@ -25,7 +25,7 @@
#include "glk/glk_types.h"
-namespace Gargoyle {
+namespace Glk {
#define GET_CASE_BLOCK(ch, blockptr) \
switch ((glui32)(ch) >> 8) { \
@@ -558,6 +558,6 @@ extern gli_case_special_t unigen_special_0xfb16;
extern gli_case_special_t unigen_special_0xfb17;
extern glui32 unigen_special_array[];
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/utils.cpp b/engines/glk/utils.cpp
index 12f9e30..07c0a4d 100644
--- a/engines/glk/utils.cpp
+++ b/engines/glk/utils.cpp
@@ -23,7 +23,7 @@
#include "glk/utils.h"
#include "common/textconsole.h"
-namespace Gargoyle {
+namespace Glk {
int strToInt(const char *s) {
if (!*s)
@@ -41,4 +41,4 @@ int strToInt(const char *s) {
return (int)tmp;
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/utils.h b/engines/glk/utils.h
index 361c65f..3655f57 100644
--- a/engines/glk/utils.h
+++ b/engines/glk/utils.h
@@ -26,7 +26,7 @@
#include "common/rect.h"
#include "glk/glk_types.h"
-namespace Gargoyle {
+namespace Glk {
typedef Common::Point Point;
@@ -46,6 +46,6 @@ public:
*/
int strToInt(const char *s);
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/window_graphics.cpp b/engines/glk/window_graphics.cpp
index 4eea5c0..e80fc8e 100644
--- a/engines/glk/window_graphics.cpp
+++ b/engines/glk/window_graphics.cpp
@@ -22,10 +22,10 @@
#include "glk/window_graphics.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/screen.h"
-namespace Gargoyle {
+namespace Glk {
GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
_w(0), _h(0), _dirty(false), _surface(nullptr) {
@@ -269,4 +269,4 @@ void GraphicsWindow::click(const Point &newPos) {
}
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/window_graphics.h b/engines/glk/window_graphics.h
index 1ddc26c..c2f4a55 100644
--- a/engines/glk/window_graphics.h
+++ b/engines/glk/window_graphics.h
@@ -26,7 +26,7 @@
#include "glk/windows.h"
#include "glk/picture.h"
-namespace Gargoyle {
+namespace Glk {
/**
* Graphics window
@@ -108,6 +108,6 @@ public:
virtual void setBackgroundColor(glui32 color) override;
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/window_pair.cpp b/engines/glk/window_pair.cpp
index 56e5b45..a0fdbb4 100644
--- a/engines/glk/window_pair.cpp
+++ b/engines/glk/window_pair.cpp
@@ -22,10 +22,10 @@
#include "glk/window_pair.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/screen.h"
-namespace Gargoyle {
+namespace Glk {
PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size) :
Window(windows, 0),
@@ -233,4 +233,4 @@ void PairWindow::click(const Point &newPos) {
_child2->click(newPos);
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/window_pair.h b/engines/glk/window_pair.h
index 11b4e49..f77ae92 100644
--- a/engines/glk/window_pair.h
+++ b/engines/glk/window_pair.h
@@ -25,7 +25,7 @@
#include "glk/windows.h"
-namespace Gargoyle {
+namespace Glk {
/**
* Pair window
@@ -68,6 +68,6 @@ public:
virtual void click(const Point &newPos) override;
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/window_text_buffer.cpp b/engines/glk/window_text_buffer.cpp
index 1506f4e..36d8c6e 100644
--- a/engines/glk/window_text_buffer.cpp
+++ b/engines/glk/window_text_buffer.cpp
@@ -22,12 +22,12 @@
#include "glk/window_text_buffer.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/screen.h"
#include "glk/selection.h"
#include "glk/unicode.h"
-namespace Gargoyle {
+namespace Glk {
/**
*
@@ -1633,4 +1633,4 @@ TextBufferWindow::TextBufferRow::TextBufferRow() : _len(0), _newLine(0), _dirty(
Common::fill(&_chars[0], &_chars[TBLINELEN], 0);
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/window_text_buffer.h b/engines/glk/window_text_buffer.h
index a26a95b..4384986 100644
--- a/engines/glk/window_text_buffer.h
+++ b/engines/glk/window_text_buffer.h
@@ -27,7 +27,7 @@
#include "glk/picture.h"
#include "glk/speech.h"
-namespace Gargoyle {
+namespace Glk {
/**
* Text Buffer window
@@ -240,6 +240,6 @@ public:
}
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/window_text_grid.cpp b/engines/glk/window_text_grid.cpp
index 9630836..e16c9bd 100644
--- a/engines/glk/window_text_grid.cpp
+++ b/engines/glk/window_text_grid.cpp
@@ -22,11 +22,11 @@
#include "glk/window_text_grid.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/selection.h"
#include "glk/screen.h"
-namespace Gargoyle {
+namespace Glk {
TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
_type = wintype_TextGrid;
@@ -651,4 +651,4 @@ void TextGridWindow::TextGridRow::resize(size_t newSize) {
Common::fill(&_chars[0], &_chars[0] + newSize, ' ');
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/window_text_grid.h b/engines/glk/window_text_grid.h
index acfd366..30a0f79 100644
--- a/engines/glk/window_text_grid.h
+++ b/engines/glk/window_text_grid.h
@@ -25,7 +25,7 @@
#include "glk/windows.h"
-namespace Gargoyle {
+namespace Glk {
/**
* Text Grid window
@@ -190,6 +190,6 @@ public:
}
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
index d982f6c..02298ad 100644
--- a/engines/glk/windows.cpp
+++ b/engines/glk/windows.cpp
@@ -26,13 +26,13 @@
#include "glk/window_text_buffer.h"
#include "glk/window_text_grid.h"
#include "glk/conf.h"
-#include "glk/gargoyle.h"
+#include "glk/glk.h"
#include "glk/screen.h"
#include "glk/streams.h"
#include "common/algorithm.h"
#include "common/textconsole.h"
-namespace Gargoyle {
+namespace Glk {
bool Windows::_overrideReverse;
bool Windows::_overrideFgSet;
@@ -770,4 +770,4 @@ byte *Attributes::attrFg(WindowStyle *styles) {
}
}
-} // End of namespace Gargoyle
+} // End of namespace Glk
diff --git a/engines/glk/windows.h b/engines/glk/windows.h
index 5bf5f2a..98f0d2d 100644
--- a/engines/glk/windows.h
+++ b/engines/glk/windows.h
@@ -33,7 +33,7 @@
#include "glk/selection.h"
#include "glk/streams.h"
-namespace Gargoyle {
+namespace Glk {
class Window;
class PairWindow;
@@ -536,6 +536,6 @@ public:
BlankWindow(Windows *windows, uint32 rock);
};
-} // End of namespace Gargoyle
+} // End of namespace Glk
#endif
Commit: 454f92cc74e1357b96ce06e8c77ed6c32cb30ba9
https://github.com/scummvm/scummvm/commit/454f92cc74e1357b96ce06e8c77ed6c32cb30ba9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Centralize the set of game names
Changed paths:
A engines/glk/scott/detection_tables.cpp
A engines/glk/scott/detection_tables.h
engines/glk/detection.cpp
engines/glk/module.mk
engines/glk/scott/detection.cpp
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index 893ed87..c3b6865 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -68,7 +68,9 @@ const Common::String &GlkEngine::getGameMD5() const {
} // End of namespace Glk
+#include "glk/scott/detection_tables.h"
#include "glk/frotz/detection_tables.h"
+#define SCOTT(ID, NAME) { ID, Glk::Scott::NAME##_DESC }
#define ZCODE(ID, NAME) { ID, Glk::Frotz::NAME##_DESC }
static const PlainGameDescriptor glkGames[] = {
@@ -118,23 +120,23 @@ static const PlainGameDescriptor glkGames[] = {
ZCODE("ztuu", ZTUU),
// Scott Adams games
- { "adventureland", "Adventureland" },
- { "pirateadventure", "Pirate Adventure" },
- { "missionimpossible", "Mission Impossible" },
- { "voodoocastle", "Voodoo Castle" },
- { "thecount", "The Count" },
- { "strangeodyssey", "Strange Odyssey" },
- { "mysteryfunhouse", "Mystery Fun House" },
- { "pyramidofdoom", "Pyramid Of Doom" },
- { "ghosttown", "Ghost Town" },
- { "savageisland1", "Savage Island, Part 1" },
- { "savageisland2", "Savage Island, Part 2" },
- { "goldenvoyage", "The Golden Voyage" },
- { "adventure13", "Adventure 13" },
- { "adventure14", "Adventure 14" },
- { "buckaroobonzai", "Buckaroo Banzai" },
- { "marveladventure", "Marvel Adventure #1" },
- { "scottsampler", "Adventure International's Mini-Adventure Sampler" },
+ SCOTT("adventureland", ADVENTURELAND),
+ SCOTT("pirateadventure", PIRATE_ADVENTURE),
+ SCOTT("missionimpossible", MISSION_IMPOSSIBLE),
+ SCOTT("voodoocastle", VOODOO_CASTLE),
+ SCOTT("thecount", THE_COUNT),
+ SCOTT("strangeodyssey", STRANGE_ODYSSEY),
+ SCOTT("mysteryfunhouse", MYSTERY_FUN_HOUSE),
+ SCOTT("pyramidofdoom", PYRAMID_OF_DOOM),
+ SCOTT("ghosttown", GHOST_TOWN),
+ SCOTT("savageisland1", SAVAGE_ISLAND1),
+ SCOTT("savageisland2", SAVAGE_ISLAND2),
+ SCOTT("goldenvoyage", THE_GOLDEN_VOYAGE),
+ SCOTT("adventure13", ADVENTURE13),
+ SCOTT("adventure14", ADVENTURE14),
+ SCOTT("buckaroobanzai", BUCKAROO_BANZAI),
+ SCOTT("marveladventure", MARVEL_ADVENTURE),
+ SCOTT("scottsampler", MINI_SAMPLER),
{0, 0}
};
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 3fd88ef..0f79cd8 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -39,6 +39,7 @@ MODULE_OBJS := \
frotz/processor_variables.o \
frotz/quetzal.o \
scott/detection.o \
+ scott/detection_tables.o \
scott/scott.o
# This module can be built as a plugin
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index 7afdf93..523b02d 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -21,57 +21,13 @@
*/
#include "glk/scott/detection.h"
+#include "glk/scott/detection_tables.h"
#include "common/file.h"
#include "common/md5.h"
namespace Glk {
namespace Scott {
-struct ScottGame {
- const char *_md5;
- const char *_gameId;
- int32 _filesize;
- const char *_desc;
-};
-
-const ScottGame SCOTT_GAMES[] = {
- // PC game versions
- { "7c6f495d757a54e73d259efc718d8024", "adventureland", 15896, "Adventureland" },
- { "ea535fa7684508410151b4561de1f323", "pirateadventure", 16325, "Pirate Adventure" },
- { "379c77a9a483886366b3b5c425e56410", "missionimpossible", 15275, "Mission Impossible" },
- { "a530a6857d1092eaa177eee575c94c71", "voodoocastle", 15852, "Voodoo Castle" },
- { "5ebb4ade985670bb2eac54f8fa202214", "thecount", 17476, "The Count" },
- { "c57bb6df04dc77a2b232bc5bcab6e417", "strangeodyssey", 17489, "Strange Odyssey" },
- { "ce2931ac3d5cbc270a5cb7be9e614f6e", "mysteryfunhouse", 17165, "Mystery Fun House" },
- { "4e6127fad6b5d75eccd3f3b101f8c9c8", "pyramidofdoom", 17673, "Pyramid Of Doom" },
- { "2c08327ab06d5490bd9e367ddaeca627", "ghosttown", 17831, "Ghost Town" },
- { "8feb77f11d32e9567ce2fc7d435eaf44", "savageisland1", 19533, "Savage Island, Part 1" },
- { "20c40a349f7a214ac515fb1d63c30a87", "savageisland2", 18367, "Savage Island, Part 2" },
- { "e2a8f956ab215012d1495550c4c11ee8", "goldenvoyage", 18513, "The Golden Voyage" },
- { "f986d7e1ee074f65b6c1d00461c9b3c3", "adventure13", 19232, "Adventure 13" },
- { "6d98f422cc986d959a3c74351785aea3", "adventure14", 19013, "Adventure 14" },
- { "aadcc04e6b37eb9d30a58b5bc775842e", "marveladventure", 18876, "Marvel Adventure #1" },
- { "d569a769f304dc02b3062d97458ddd01", "scottsampler", 13854, "Adventure International's Mini-Adventure Sampler" },
-
- // PDA game versions
- { "ae541fc1085da2f7d561b72ed20a6bc1", "adventureland", 18003, "Adventureland" },
- { "cbd47ab4fcfe00231ffd71d52378d410", "pirateadventure", 18482, "Pirate Adventure" },
- { "9251ab2c64e63559d8a6e9e6246760a5", "missionimpossible", 17227, "Mission Impossible" },
- { "be849c5747c7fc3b201984afb4403b8e", "voodoocastle", 18140, "Voodoo Castle" },
- { "85b75b6079b5ee572b5259b29a0e5d21", "thecount", 19999, "The Count" },
- { "c423cae841ac1927b5b2e503607b21bc", "strangeodyssey", 20115, "Strange Odyssey" },
- { "326b98b991d401605074e64d474ce566", "mysteryfunhouse", 19700, "Mystery Fun House" },
- { "8ef9010399f055da9adb15ce7745a11c", "pyramidofdoom", 20320, "Pyramid Of Doom" },
- { "fcdcca8b2acf76ba2d0006cefa3630a1", "ghosttown", 20687, "Ghost Town" },
- { "c8aaa80f07c40fa8e4b17432644919dc", "savageisland1", 22669, "Savage Island, Part 1" },
- { "2add0f28d9b236c866890cdf8d86ee60", "savageisland2", 21169, "Savage Island, Part 2" },
- { "675126bd0477e8ed9230ad3db5afc45f", "goldenvoyage", 21401, "The Golden Voyage" },
- { "0ef0def798d895ed766041fa99dd28a0", "adventure13", 22346, "Adventure 13" },
- { "0bf1bcc649422798332a38c88588fdff", "adventure14", 22087, "Adventure 14" },
- { "a0a5423967287dae9cbeb9abe8324479", "buckaroobonzai", 21038, "Buckaroo Banzai" },
- { nullptr, nullptr, 0, nullptr }
-};
-
bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
Common::File gameFile;
Common::String md5;
diff --git a/engines/glk/scott/detection_tables.cpp b/engines/glk/scott/detection_tables.cpp
new file mode 100644
index 0000000..f9a2a6c
--- /dev/null
+++ b/engines/glk/scott/detection_tables.cpp
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ */
+
+#include "glk/scott/detection_tables.h"
+
+namespace Glk {
+namespace Scott {
+
+const char *const ADVENTURELAND_DESC = "Adventureland";
+const char *const PIRATE_ADVENTURE_DESC = "Pirate Adventure";
+const char *const MISSION_IMPOSSIBLE_DESC = "Mission Impossible";
+const char *const VOODOO_CASTLE_DESC = "Voodoo Castle";
+const char *const THE_COUNT_DESC = "The Count";
+const char *const STRANGE_ODYSSEY_DESC = "Strange Odyssey";
+const char *const MYSTERY_FUN_HOUSE_DESC = "Mystery Fun House";
+const char *const PYRAMID_OF_DOOM_DESC = "Pyramid Of Doom";
+const char *const GHOST_TOWN_DESC = "Ghost Town";
+const char *const SAVAGE_ISLAND1_DESC = "Savage Island, Part 1";
+const char *const SAVAGE_ISLAND2_DESC = "Savage Island, Part 2";
+const char *const THE_GOLDEN_VOYAGE_DESC = "The Golden Voyage";
+const char *const ADVENTURE13_DESC = "Adventure 13";
+const char *const ADVENTURE14_DESC = "Adventure 14";
+const char *const BUCKAROO_BANZAI_DESC = "Buckaroo Banzai";
+const char *const MARVEL_ADVENTURE_DESC = "Marvel Adventure #1";
+const char *const MINI_SAMPLER_DESC = "Adventure International's Mini-Adventure Sampler";
+
+const ScottGame SCOTT_GAMES[] = {
+ // PC game versions
+ { "7c6f495d757a54e73d259efc718d8024", "adventureland", 15896, ADVENTURELAND_DESC },
+ { "ea535fa7684508410151b4561de1f323", "pirateadventure", 16325, PIRATE_ADVENTURE_DESC },
+ { "379c77a9a483886366b3b5c425e56410", "missionimpossible", 15275, MISSION_IMPOSSIBLE_DESC },
+ { "a530a6857d1092eaa177eee575c94c71", "voodoocastle", 15852, VOODOO_CASTLE_DESC },
+ { "5ebb4ade985670bb2eac54f8fa202214", "thecount", 17476, THE_COUNT_DESC },
+ { "c57bb6df04dc77a2b232bc5bcab6e417", "strangeodyssey", 17489, STRANGE_ODYSSEY_DESC },
+ { "ce2931ac3d5cbc270a5cb7be9e614f6e", "mysteryfunhouse", 17165, MYSTERY_FUN_HOUSE_DESC },
+ { "4e6127fad6b5d75eccd3f3b101f8c9c8", "pyramidofdoom", 17673, PYRAMID_OF_DOOM_DESC },
+ { "2c08327ab06d5490bd9e367ddaeca627", "ghosttown", 17831, GHOST_TOWN_DESC },
+ { "8feb77f11d32e9567ce2fc7d435eaf44", "savageisland1", 19533, SAVAGE_ISLAND1_DESC },
+ { "20c40a349f7a214ac515fb1d63c30a87", "savageisland2", 18367, SAVAGE_ISLAND2_DESC },
+ { "e2a8f956ab215012d1495550c4c11ee8", "goldenvoyage", 18513, THE_GOLDEN_VOYAGE_DESC },
+ { "f986d7e1ee074f65b6c1d00461c9b3c3", "adventure13", 19232, ADVENTURE13_DESC },
+ { "6d98f422cc986d959a3c74351785aea3", "adventure14", 19013, ADVENTURE14_DESC },
+ { "aadcc04e6b37eb9d30a58b5bc775842e", "marveladventure", 18876, MARVEL_ADVENTURE_DESC },
+ { "d569a769f304dc02b3062d97458ddd01", "scottsampler", 13854, MINI_SAMPLER_DESC },
+
+ // PDA game versions
+ { "ae541fc1085da2f7d561b72ed20a6bc1", "adventureland", 18003, ADVENTURELAND_DESC },
+ { "cbd47ab4fcfe00231ffd71d52378d410", "pirateadventure", 18482, PIRATE_ADVENTURE_DESC },
+ { "9251ab2c64e63559d8a6e9e6246760a5", "missionimpossible", 17227, MISSION_IMPOSSIBLE_DESC },
+ { "be849c5747c7fc3b201984afb4403b8e", "voodoocastle", 18140, VOODOO_CASTLE_DESC },
+ { "85b75b6079b5ee572b5259b29a0e5d21", "thecount", 19999, THE_COUNT_DESC },
+ { "c423cae841ac1927b5b2e503607b21bc", "strangeodyssey", 20115, STRANGE_ODYSSEY_DESC },
+ { "326b98b991d401605074e64d474ce566", "mysteryfunhouse", 19700, MYSTERY_FUN_HOUSE_DESC },
+ { "8ef9010399f055da9adb15ce7745a11c", "pyramidofdoom", 20320, PYRAMID_OF_DOOM_DESC },
+ { "fcdcca8b2acf76ba2d0006cefa3630a1", "ghosttown", 20687, GHOST_TOWN_DESC },
+ { "c8aaa80f07c40fa8e4b17432644919dc", "savageisland1", 22669, SAVAGE_ISLAND1_DESC },
+ { "2add0f28d9b236c866890cdf8d86ee60", "savageisland2", 21169, SAVAGE_ISLAND2_DESC },
+ { "675126bd0477e8ed9230ad3db5afc45f", "goldenvoyage", 21401, THE_GOLDEN_VOYAGE_DESC },
+ { "0ef0def798d895ed766041fa99dd28a0", "adventure13", 22346, ADVENTURE13_DESC },
+ { "0bf1bcc649422798332a38c88588fdff", "adventure14", 22087, ADVENTURE14_DESC },
+ { "a0a5423967287dae9cbeb9abe8324479", "buckaroobanzai", 21038, BUCKAROO_BANZAI_DESC },
+ { nullptr, nullptr, 0, nullptr }
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
new file mode 100644
index 0000000..6365bde
--- /dev/null
+++ b/engines/glk/scott/detection_tables.h
@@ -0,0 +1,59 @@
+/* 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.
+ *
+ */
+
+#include "engines/advancedDetector.h"
+#include "common/language.h"
+
+namespace Glk {
+namespace Scott {
+
+/**
+ * Game descriptor for Scott Adams games
+ */
+struct ScottGame {
+ const char *_md5;
+ const char *_gameId;
+ int32 _filesize;
+ const char *_desc;
+};
+
+extern const ScottGame SCOTT_GAMES[];
+extern const char *const ADVENTURELAND_DESC;
+extern const char *const PIRATE_ADVENTURE_DESC;
+extern const char *const MISSION_IMPOSSIBLE_DESC;
+extern const char *const VOODOO_CASTLE_DESC;
+extern const char *const THE_COUNT_DESC;
+extern const char *const STRANGE_ODYSSEY_DESC;
+extern const char *const MYSTERY_FUN_HOUSE_DESC;
+extern const char *const PYRAMID_OF_DOOM_DESC;
+extern const char *const GHOST_TOWN_DESC;
+extern const char *const SAVAGE_ISLAND1_DESC;
+extern const char *const SAVAGE_ISLAND2_DESC;
+extern const char *const THE_GOLDEN_VOYAGE_DESC;
+extern const char *const ADVENTURE13_DESC;
+extern const char *const ADVENTURE14_DESC;
+extern const char *const BUCKAROO_BANZAI_DESC;
+extern const char *const MARVEL_ADVENTURE_DESC;
+extern const char *const MINI_SAMPLER_DESC;
+
+} // End of namespace Frotz
+} // End of namespace Glk
Commit: 67275924b5255d7503fe8bd15c853cfec197c569
https://github.com/scummvm/scummvm/commit/67275924b5255d7503fe8bd15c853cfec197c569
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Derive detection from MetaEngine rather than AdvancedMetaEngine
Changed paths:
R engines/glk/detection_tables.h
R engines/glk/frotz/detection_tables.cpp
R engines/glk/scott/detection_tables.cpp
engines/glk/detection.cpp
engines/glk/frotz/detection.cpp
engines/glk/frotz/detection.h
engines/glk/frotz/detection_tables.h
engines/glk/frotz/frotz.cpp
engines/glk/frotz/frotz.h
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/frotz/processor.cpp
engines/glk/frotz/processor.h
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/glk_api.cpp
engines/glk/glk_api.h
engines/glk/module.mk
engines/glk/scott/detection.cpp
engines/glk/scott/detection.h
engines/glk/scott/detection_tables.h
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index c3b6865..b3cbccc 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -21,6 +21,10 @@
*/
#include "glk/glk.h"
+#include "glk/frotz/detection.h"
+#include "glk/frotz/frotz.h"
+#include "glk/scott/detection.h"
+#include "glk/scott/scott.h"
#include "base/plugins.h"
#include "common/md5.h"
@@ -31,128 +35,14 @@
#include "engines/advancedDetector.h"
#include "graphics/colormasks.h"
#include "graphics/surface.h"
-
-#define MAX_SAVES 99
-
-namespace Glk {
-
-struct GlkGameDescription {
- ADGameDescription _desc;
- Common::String _filename;
- InterpreterType _interpType;
- Common::String _md5;
-};
-
-const Common::String &GlkEngine::getFilename() const {
- return _gameDescription->_filename;
-}
-uint32 GlkEngine::getFeatures() const {
- return _gameDescription->_desc.flags;
-}
-
-bool GlkEngine::isDemo() const {
- return (bool)(_gameDescription->_desc.flags & ADGF_DEMO);
-}
-
-Common::Language GlkEngine::getLanguage() const {
- return _gameDescription->_desc.language;
-}
-
-InterpreterType GlkEngine::getInterpreterType() const {
- return _gameDescription->_interpType;
-}
-
-const Common::String &GlkEngine::getGameMD5() const {
- return _gameDescription->_md5;
-}
-
-} // End of namespace Glk
-
-#include "glk/scott/detection_tables.h"
-#include "glk/frotz/detection_tables.h"
-#define SCOTT(ID, NAME) { ID, Glk::Scott::NAME##_DESC }
-#define ZCODE(ID, NAME) { ID, Glk::Frotz::NAME##_DESC }
-
-static const PlainGameDescriptor glkGames[] = {
- {"zcode", "Zcode Games" },
- {"scottadams", "Scott Adams Games"},
-
- // Infocom/Z-code games
- ZCODE("amfv", AMFV),
- ZCODE("arthur", ARTHUR),
- ZCODE("ballyhoo", BALLYHOO),
- ZCODE("beyondzork", BEYONDZORK),
- ZCODE("borderzone", BORDERZONE),
- ZCODE("bureaucracy", BUREAUCRACY),
- ZCODE("cutthroats", CUTTHROATS),
- ZCODE("deadline", DEADLINE),
- ZCODE("enchanter", ENCHANTER),
- ZCODE("hhgttg", HHGTTG),
- ZCODE("hijinx", HIJINX),
- ZCODE("infidel", INFIDEL),
- ZCODE("journey", JOURNEY),
- ZCODE("lgop", LGOP),
- ZCODE("lgop2", LGOP2),
- ZCODE("lurking", LURKING),
- ZCODE("minizork1", MINIZORK1),
- ZCODE("moonmist", MOONMIST),
- ZCODE("nordbert", NORDBERT),
- ZCODE("planetfall", PLANETFALL),
- ZCODE("plundered", PLUNDERED),
- ZCODE("sampler1", SAMPLER1),
- ZCODE("sampler2", SAMPLER2),
- ZCODE("seastalker", SEASTALKER),
- ZCODE("sherlockriddle", SHERLOCKRIDDLE),
- ZCODE("shogun", SHOGUN),
- ZCODE("sorcerer", SORCERER),
- ZCODE("spellbreaker", SPELLBREAKER),
- ZCODE("starcross", STARCROSS),
- ZCODE("stationfall", STATIONFALL),
- ZCODE("suspect", SUSPECT),
- ZCODE("suspended", SUSPENDED),
- ZCODE("trinity", TRINITY),
- ZCODE("wishbringer", WISHBRINGER),
- ZCODE("witness", WITNESS),
- ZCODE("zork0", ZORK0),
- ZCODE("zork1", ZORK1),
- ZCODE("zork2", ZORK2),
- ZCODE("zork3", ZORK3),
- ZCODE("ztuu", ZTUU),
-
- // Scott Adams games
- SCOTT("adventureland", ADVENTURELAND),
- SCOTT("pirateadventure", PIRATE_ADVENTURE),
- SCOTT("missionimpossible", MISSION_IMPOSSIBLE),
- SCOTT("voodoocastle", VOODOO_CASTLE),
- SCOTT("thecount", THE_COUNT),
- SCOTT("strangeodyssey", STRANGE_ODYSSEY),
- SCOTT("mysteryfunhouse", MYSTERY_FUN_HOUSE),
- SCOTT("pyramidofdoom", PYRAMID_OF_DOOM),
- SCOTT("ghosttown", GHOST_TOWN),
- SCOTT("savageisland1", SAVAGE_ISLAND1),
- SCOTT("savageisland2", SAVAGE_ISLAND2),
- SCOTT("goldenvoyage", THE_GOLDEN_VOYAGE),
- SCOTT("adventure13", ADVENTURE13),
- SCOTT("adventure14", ADVENTURE14),
- SCOTT("buckaroobanzai", BUCKAROO_BANZAI),
- SCOTT("marveladventure", MARVEL_ADVENTURE),
- SCOTT("scottsampler", MINI_SAMPLER),
- {0, 0}
-};
-
#include "common/config-manager.h"
#include "common/file.h"
-#include "glk/detection_tables.h"
-#include "glk/frotz/detection.h"
-#include "glk/frotz/frotz.h"
-#include "glk/scott/detection.h"
-#include "glk/scott/scott.h"
-class GlkMetaEngine : public AdvancedMetaEngine {
+#define MAX_SAVES 99
+
+class GlkMetaEngine : public MetaEngine {
public:
- GlkMetaEngine() : AdvancedMetaEngine(Glk::gameDescriptions, sizeof(Glk::GlkGameDescription), glkGames) {
- _maxScanDepth = 3;
- }
+ GlkMetaEngine() : MetaEngine() {}
virtual const char *getName() const {
return "ScummGlk Engine";
@@ -163,15 +53,28 @@ public:
}
virtual bool hasFeature(MetaEngineFeature f) const override;
- virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+ virtual Common::Error createInstance(OSystem *syst, Engine **engine) const override;
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
virtual void removeSaveState(const char *target, int slot) const;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+ /**
+ * Returns a list of games supported by this engine.
+ */
+ virtual PlainGameList getSupportedGames() const override;
+
+ /**
+ * Runs the engine's game detector on the given list of files, and returns a
+ * (possibly empty) list of games supported by the engine which it was able
+ * to detect amongst the given files.
+ */
virtual DetectedGames detectGames(const Common::FSList &fslist) const override;
- virtual ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override;
+ /**
+ * Query the engine for a PlainGameDescriptor for the specified gameid, if any.
+ */
+ virtual PlainGameDescriptor findGame(const char *gameId) const override;
};
bool GlkMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -192,21 +95,49 @@ bool Glk::GlkEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
-bool GlkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- const Glk::GlkGameDescription *gd = (const Glk::GlkGameDescription *)desc;
-
- switch (gd->_interpType) {
- case Glk::INTERPRETER_FROTZ:
- *engine = new Glk::Frotz::Frotz(syst, gd);
- break;
- case Glk::INTERPRETER_SCOTT:
- *engine = new Glk::Scott::Scott(syst, gd);
- break;
- default:
- error("Unknown interpreter");
- }
+Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
+ assert(engine);
- return gd != 0;
+ Glk::GlkGameDescription gameDesc;
+ gameDesc._gameId = ConfMan.get("gameid");
+ gameDesc._filename = ConfMan.get("filename");
+
+ if (Glk::Frotz::FrotzMetaEngine::findGame(gameDesc._gameId.c_str()).description)
+ *engine = new Glk::Frotz::Frotz(syst, gameDesc);
+ else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description)
+ *engine = new Glk::Scott::Scott(syst, gameDesc);
+ else
+ return Common::kNoGameDataFoundError;
+
+ return Common::kNoError;
+}
+
+PlainGameList GlkMetaEngine::getSupportedGames() const {
+ PlainGameList list;
+ Glk::Frotz::FrotzMetaEngine::getSupportedGames(list);
+ Glk::Scott::ScottMetaEngine::getSupportedGames(list);
+
+ return list;
+}
+
+PlainGameDescriptor GlkMetaEngine::findGame(const char *gameId) const {
+ PlainGameDescriptor gd;
+
+ gd = Glk::Frotz::FrotzMetaEngine::findGame(gameId);
+ if (gd.description) return gd;
+
+ gd = Glk::Scott::ScottMetaEngine::findGame(gameId);
+ if (gd.description) return gd;
+
+ return PlainGameDescriptor();
+}
+
+DetectedGames GlkMetaEngine::detectGames(const Common::FSList &fslist) const {
+ DetectedGames detectedGames;
+ Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
+ Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
+
+ return detectedGames;
}
SaveStateList GlkMetaEngine::listSaves(const char *target) const {
@@ -270,54 +201,6 @@ SaveStateDescriptor GlkMetaEngine::querySaveMetaInfos(const char *target, int sl
return SaveStateDescriptor();
}
-DetectedGames GlkMetaEngine::detectGames(const Common::FSList &fslist) const {
- DetectedGames detectedGames;
- Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
- Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
-
- return detectedGames;
-}
-
-static Glk::GlkGameDescription gameDescription;
-
-ADDetectedGames GlkMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
- static char gameId[100];
- strcpy(gameId, ConfMan.get("gameid").c_str());
- Common::String filename = ConfMan.get("filename");
-
- Common::FSList fslist;
- DetectedGames detectedGames;
- fslist.push_back(parent.getChild(filename));
- ADDetectedGames results;
- Common::File f;
-
- // Check each sub-engine for any detected games
- if (Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames))
- gameDescription._interpType = Glk::INTERPRETER_FROTZ;
- else if (Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames))
- gameDescription._interpType = Glk::INTERPRETER_SCOTT;
- else
- // No match found, so return no results
- return results;
-
- // Set up the game description and return it
- if (f.open(parent.getChild(filename))) {
- DetectedGame gd = detectedGames.front();
-
- gameDescription._desc.gameId = gameId;
- gameDescription._desc.language = gd.language;
- gameDescription._desc.platform = gd.platform;
- gameDescription._desc.guiOptions = GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES);
- gameDescription._filename = filename;
- gameDescription._md5 = Common::computeStreamMD5AsString(f, 5000);
-
- ADDetectedGame dg((ADGameDescription *)&gameDescription);
- results.push_back(dg);
- }
-
- return results;
-}
-
#if PLUGIN_ENABLED_DYNAMIC(GLK)
REGISTER_PLUGIN_DYNAMIC(GLK, PLUGIN_TYPE_ENGINE, GlkMetaEngine);
#else
diff --git a/engines/glk/detection_tables.h b/engines/glk/detection_tables.h
deleted file mode 100644
index 47a761e..0000000
--- a/engines/glk/detection_tables.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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.
- *
- */
-
-namespace Glk {
-
-static const GlkGameDescription gameDescriptions[] = {
- { AD_TABLE_END_MARKER, "", (InterpreterType)0, "" }
-};
-
-} // End of namespace Glk
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 36303d4..b77344d 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -21,14 +21,27 @@
*/
#include "glk/frotz/detection.h"
+#include "glk/frotz/detection_tables.h"
#include "common/file.h"
#include "common/md5.h"
-#include "glk/frotz/detection_tables.h"
-
namespace Glk {
namespace Frotz {
+void FrotzMetaEngine::getSupportedGames(PlainGameList &games) {
+ for (const PlainGameDescriptor *pd = FROTZ_GAME_LIST; pd->gameId; ++pd)
+ games.push_back(*pd);
+}
+
+PlainGameDescriptor FrotzMetaEngine::findGame(const char *gameId) {
+ for (const PlainGameDescriptor *pd = FROTZ_GAME_LIST; pd->gameId; ++pd) {
+ if (!strcmp(gameId, pd->gameId))
+ return *pd;
+ }
+
+ return PlainGameDescriptor();;
+}
+
bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
const char *const EXTENSIONS[9] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
@@ -66,7 +79,8 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
warning("Uknown zcode game %s - %s %d", filename.c_str(), md5.c_str(), filesize);
gd = DetectedGame("zcode", "Unrecognised zcode game", Common::UNK_LANG, Common::kPlatformUnknown);
} else {
- gd = DetectedGame(p->_gameId, p->_description, p->_language, Common::kPlatformUnknown, p->_extra);
+ PlainGameDescriptor gameDesc = findGame(p->_gameId);
+ gd = DetectedGame(p->_gameId, gameDesc.description, p->_language, Common::kPlatformUnknown, p->_extra);
}
gd.addExtraEntry("filename", filename);
diff --git a/engines/glk/frotz/detection.h b/engines/glk/frotz/detection.h
index 9cd9373..6c70f98 100644
--- a/engines/glk/frotz/detection.h
+++ b/engines/glk/frotz/detection.h
@@ -32,6 +32,17 @@ namespace Frotz {
class FrotzMetaEngine {
public:
/**
+ * Get a list of supported games
+ */
+ static void getSupportedGames(PlainGameList &games);
+
+
+ /**
+ * Returns a game description for the given game Id, if it's supported
+ */
+ static PlainGameDescriptor findGame(const char *gameId);
+
+ /**
* Detect supported games
*/
static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
diff --git a/engines/glk/frotz/detection_tables.cpp b/engines/glk/frotz/detection_tables.cpp
deleted file mode 100644
index f52b099..0000000
--- a/engines/glk/frotz/detection_tables.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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.
- *
- */
-
-#include "glk/frotz/detection_tables.h"
-
-namespace Glk {
-namespace Frotz {
-
-const char *const AMFV_DESC = "A Mind Forever Voyaging";
-const char *const ARTHUR_DESC = "Arthur: The Quest for Excalibur";
-const char *const BALLYHOO_DESC = "Ballyhoo";
-const char *const BEYONDZORK_DESC = "Beyond Zork";
-const char *const BORDERZONE_DESC = "Border Zone";
-const char *const BUREAUCRACY_DESC = "Bureaucracy";
-const char *const CUTTHROATS_DESC = "Cutthroats";
-const char *const DEADLINE_DESC = "Deadline";
-const char *const ENCHANTER_DESC = "Enchanter";
-const char *const HHGTTG_DESC = "The Hitchhiker's Guide to the Galaxy";
-const char *const HIJINX_DESC = "Hollywood Hijinx";
-const char *const INFIDEL_DESC = "Infidel";
-const char *const JOURNEY_DESC = "Journey";
-const char *const LGOP_DESC = "Leather Goddesses of Phobos";
-const char *const LGOP2_DESC = "Leather Goddesses of Phobos 2";
-const char *const LURKING_DESC = "The Lurking Horror";
-const char *const MINIZORK1_DESC = "Mini Zork I: The Great Underground Empire";
-const char *const MOONMIST_DESC = "Moonmist";
-const char *const NORDBERT_DESC = "Nord and Bert Couldn't Make Head or Tail of It";
-const char *const PLANETFALL_DESC = "Planetfall";
-const char *const PLUNDERED_DESC = "Plundered Hearts";
-const char *const SAMPLER1_DESC = "Infocom Sampler 1";
-const char *const SAMPLER2_DESC = "Infocom Sampler 2";
-const char *const SEASTALKER_DESC = "Seastalker";
-const char *const SHERLOCKRIDDLE_DESC = "Sherlock: The Riddle of the Crown Jewels";
-const char *const SHOGUN_DESC = "James Clavell's Shogun";
-const char *const SORCERER_DESC = "Sorcerer";
-const char *const SPELLBREAKER_DESC = "Spellbreaker";
-const char *const STARCROSS_DESC = "Starcross";
-const char *const STATIONFALL_DESC = "Stationfall";
-const char *const SUSPECT_DESC = "Suspect";
-const char *const SUSPENDED_DESC = "Suspended";
-const char *const TRINITY_DESC = "Trinity";
-const char *const WISHBRINGER_DESC = "Wishbringer";
-const char *const WITNESS_DESC = "The Witness";
-const char *const ZORK0_DESC = "Zork Zero: The Revenge of Megaboz";
-const char *const ZORK1_DESC = "Zork I: The Great Underground Empire";
-const char *const ZORK2_DESC = "Zork II: The Wizard of Frobozz";
-const char *const ZORK3_DESC = "Zork III: The Dungeon Master";
-const char *const ZTUU_DESC = "Zork: The Undiscovered Underground";
-
-#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
-#define ENTRY0(ID, DESCRIPTION, VERSION, MD5, FILESIZE) { ID, DESCRIPTION##_DESC, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
-#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
-
-const FrotzGameDescription FROTZ_GAMES[] = {
- ENTRY0("hhgttg", HHGTTG, "v31 Solid Gold", "379022bcd4ec74b90274c6100c33f579", 158412),
- ENTRY0("hhgttg", HHGTTG, "v47", "fdda8f4239819402c62db866bb61a648", 112622),
- ENTRY0("hhgttg", HHGTTG, "v56", "a214fcb42bc9f554d07d983a12f6a062", 113444),
- ENTRY0("hhgttg", HHGTTG, "v58", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
- ENTRY0("hhgttg", HHGTTG, "v59", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
-
- FROTZ_TABLE_END_MARKER
-};
-
-
-} // End of namespace Frotz
-} // End of namespace Glk
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index 51994ed..5eb310d 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -20,7 +20,8 @@
*
*/
-#include "engines/advancedDetector.h"
+#include "engines/game.h"
+#include "common/gui_options.h"
#include "common/language.h"
namespace Glk {
@@ -31,7 +32,6 @@ namespace Frotz {
*/
struct FrotzGameDescription {
const char *const _gameId;
- const char *const _description;
const char *const _extra;
const char *const _md5;
size_t _filesize;
@@ -39,47 +39,63 @@ struct FrotzGameDescription {
const char *const _guiOptions;
};
-extern const FrotzGameDescription FROTZ_GAMES[];
-extern const char *const AMFV_DESC;
-extern const char *const ARTHUR_DESC;
-extern const char *const BALLYHOO_DESC;
-extern const char *const BEYONDZORK_DESC;
-extern const char *const BORDERZONE_DESC;
-extern const char *const BUREAUCRACY_DESC;
-extern const char *const CUTTHROATS_DESC;
-extern const char *const DEADLINE_DESC;
-extern const char *const ENCHANTER_DESC;
-extern const char *const HHGTTG_DESC;
-extern const char *const HIJINX_DESC;
-extern const char *const INFIDEL_DESC;
-extern const char *const JOURNEY_DESC;
-extern const char *const LGOP_DESC;
-extern const char *const LGOP2_DESC;
-extern const char *const LURKING_DESC;
-extern const char *const MINIZORK1_DESC;
-extern const char *const MOONMIST_DESC;
-extern const char *const NORDBERT_DESC;
-extern const char *const PLANETFALL_DESC;
-extern const char *const PLUNDERED_DESC;
-extern const char *const SAMPLER1_DESC;
-extern const char *const SAMPLER2_DESC;
-extern const char *const SEASTALKER_DESC;
-extern const char *const SHERLOCKRIDDLE_DESC;
-extern const char *const SHOGUN_DESC;
-extern const char *const SORCERER_DESC;
-extern const char *const SPELLBREAKER_DESC;
-extern const char *const STARCROSS_DESC;
-extern const char *const STATIONFALL_DESC;
-extern const char *const SUSPECT_DESC;
-extern const char *const SUSPENDED_DESC;
-extern const char *const TRINITY_DESC;
-extern const char *const WISHBRINGER_DESC;
-extern const char *const WITNESS_DESC;
-extern const char *const ZORK0_DESC;
-extern const char *const ZORK1_DESC;
-extern const char *const ZORK2_DESC;
-extern const char *const ZORK3_DESC;
-extern const char *const ZTUU_DESC;
+const PlainGameDescriptor FROTZ_GAME_LIST[] = {
+ { "amfv", "A Mind Forever Voyaging" },
+ { "arthur", "Arthur: The Quest for Excalibur" },
+ { "ballyhoo", "Ballyhoo" },
+ { "beyondzork", "Beyond Zork" },
+ { "borderzone", "Border Zone" },
+ { "bureaucracy", "Bureaucracy" },
+ { "cutthroats", "Cutthroats" },
+ { "deadline", "Deadline" },
+ { "enchanter", "Enchanter" },
+ { "hhgttg", "The Hitchhiker's Guide to the Galaxy" },
+ { "hollywoodhijinx", "Hollywood Hijinx" },
+ { "infidel", "Infidel" },
+ { "journey", "Journey" },
+ { "lgop", "Leather Goddesses of Phobos" },
+ { "lgop2", "Leather Goddesses of Phobos 2" },
+ { "lurkinghorror", "The Lurking Horror" },
+ { "minizork", "Mini Zork I: The Great Underground Empire" },
+ { "moonmist", "Moonmist" },
+ { "nordbert", "Nord and Bert Couldn't Make Head or Tail of It" },
+ { "planetfall", "Planetfall" },
+ { "plunderedhearts", "Plundered Hearts" },
+ { "infocomsampler1", "Infocom Sampler 1" },
+ { "infocomsampler2", "Infocom Sampler 2" },
+ { "seastalker", "Seastalker" },
+ { "sherlockriddle", "Sherlock: The Riddle of the Crown Jewels" },
+ { "shogun", "James Clavell's Shogun" },
+ { "sorcerer", "Sorcerer" },
+ { "spellbreaker", "Spellbreaker" },
+ { "starcross", "Starcross" },
+ { "stationfall", "Stationfall" },
+ { "suspect", "Suspect" },
+ { "suspended", "Suspended" },
+ { "trinity", "Trinity" },
+ { "wishbringer", "Wishbringer" },
+ { "thewitness", "The Witness" },
+ { "zork0", "Zork Zero: The Revenge of Megaboz" },
+ { "zork1", "Zork I: The Great Underground Empire" },
+ { "zork2", "Zork II: The Wizard of Frobozz" },
+ { "zork3", "Zork III: The Dungeon Master" },
+ { "ztuu", "Zork: The Undiscovered Underground" },
+ { nullptr, nullptr }
+};
+
+#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
+#define ENTRY0(ID, VERSION, MD5, FILESIZE) { ID, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
+#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
+
+const FrotzGameDescription FROTZ_GAMES[] = {
+ ENTRY0("hhgttg", "v31 Solid Gold", "379022bcd4ec74b90274c6100c33f579", 158412),
+ ENTRY0("hhgttg", "v47", "fdda8f4239819402c62db866bb61a648", 112622),
+ ENTRY0("hhgttg", "v56", "a214fcb42bc9f554d07d983a12f6a062", 113444),
+ ENTRY0("hhgttg", "v58", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
+ ENTRY0("hhgttg", "v59", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
+
+ FROTZ_TABLE_END_MARKER
+};
} // End of namespace Frotz
} // End of namespace Glk
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index f30acd0..a6371b6 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -29,7 +29,7 @@ namespace Frotz {
Frotz *g_vm;
-Frotz::Frotz(OSystem *syst, const GlkGameDescription *gameDesc) :
+Frotz::Frotz(OSystem *syst, const GlkGameDescription &gameDesc) :
Processor(syst, gameDesc) {
g_vm = this;
}
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index cecd886..e45abc0 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -36,7 +36,7 @@ public:
/**
* Constructor
*/
- Frotz(OSystem *syst, const GlkGameDescription *gameDesc);
+ Frotz(OSystem *syst, const GlkGameDescription &gameDesc);
/**
* Destructor
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index da27382..b9652bc 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -25,7 +25,7 @@
namespace Glk {
namespace Frotz {
-GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription *gameDesc) :
+GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) :
GlkAPI(syst, gameDesc),
oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index d78d49f..8bbdb73 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -181,7 +181,7 @@ public:
/**
* Constructor
*/
- GlkInterface(OSystem *syst, const GlkGameDescription *gameDesc);
+ GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc);
/**
* Initialization
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index a7cbad0..442b007 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -131,7 +131,7 @@ Opcode Processor::ext_opcodes[64] = {
&Processor::z_buffer_screen, // spec 1.1
};
-Processor::Processor(OSystem *syst, const GlkGameDescription *gameDesc) :
+Processor::Processor(OSystem *syst, const GlkGameDescription &gameDesc) :
GlkInterface(syst, gameDesc),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index 4bd9d2c..ddb264c 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -1522,7 +1522,7 @@ public:
/**
* Constructor
*/
- Processor(OSystem *syst, const GlkGameDescription *gameDesc);
+ Processor(OSystem *syst, const GlkGameDescription &gameDesc);
/**
* Initialization
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index a35f242..987fbc8 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -41,7 +41,7 @@ namespace Glk {
GlkEngine *g_vm;
-GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription *gameDesc) :
+GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription &gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Glk"), _clipboard(nullptr),
_conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
_selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 92ea2ab..b48d4e6 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -70,7 +70,13 @@ enum GlkDebugChannels {
#define GLK_SAVEGAME_VERSION 1
-struct GlkGameDescription;
+struct GlkGameDescription {
+ Common::String _gameId;
+ Common::Language _language;
+ Common::String _filename;
+ InterpreterType _interpType;
+ Common::String _md5;
+};
/**
* Base class for the different interpreters
@@ -87,7 +93,7 @@ private:
*/
void initGraphicsMode();
protected:
- const GlkGameDescription *_gameDescription;
+ const GlkGameDescription _gameDescription;
Common::RandomSource _random;
int _loadSaveSlot;
@@ -119,7 +125,7 @@ public:
void (*gli_unregister_arr)(void *array, glui32 len, const char *typecode, gidispatch_rock_t objrock);
public:
- GlkEngine(OSystem *syst, const GlkGameDescription *gameDesc);
+ GlkEngine(OSystem *syst, const GlkGameDescription &gameDesc);
virtual ~GlkEngine();
/**
@@ -149,22 +155,22 @@ public:
/**
* Returns the language
*/
- Common::Language getLanguage() const;
+ Common::Language getLanguage() const { return _gameDescription._language; };
/**
* Returns the running interpreter type
*/
- InterpreterType getInterpreterType() const;
+ InterpreterType getInterpreterType() const { return _gameDescription._interpType; }
/**
* Returns the game's md5
*/
- const Common::String &getGameMD5() const;
+ const Common::String &getGameMD5() const { return _gameDescription._md5; }
/**
* Returns the primary filename for the game
*/
- const Common::String &getFilename() const;
+ const Common::String &getFilename() const { return _gameDescription._filename; }
/**
* Return the game engine's target name
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index c219cd1..6094015 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -34,7 +34,7 @@
namespace Glk {
-GlkAPI::GlkAPI(OSystem *syst, const GlkGameDescription *gameDesc) :
+GlkAPI::GlkAPI(OSystem *syst, const GlkGameDescription &gameDesc) :
GlkEngine(syst, gameDesc), _gliFirstEvent(false) {
// Set uppercase/lowercase tables
int ix, res;
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index f864ac9..8a37df1 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -43,7 +43,7 @@ public:
/**
* Constructor
*/
- GlkAPI(OSystem *syst, const GlkGameDescription *gameDesc);
+ GlkAPI(OSystem *syst, const GlkGameDescription &gameDesc);
void glk_exit(void);
void glk_set_interrupt_handler(void(*func)(void));
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 0f79cd8..b523034 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -22,7 +22,6 @@ MODULE_OBJS := \
window_text_buffer.o \
window_text_grid.o \
frotz/detection.o \
- frotz/detection_tables.o \
frotz/frotz.o \
frotz/glk_interface.o \
frotz/mem.o \
@@ -39,7 +38,6 @@ MODULE_OBJS := \
frotz/processor_variables.o \
frotz/quetzal.o \
scott/detection.o \
- scott/detection_tables.o \
scott/scott.o
# This module can be built as a plugin
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index 523b02d..a02e3c5 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -24,10 +24,25 @@
#include "glk/scott/detection_tables.h"
#include "common/file.h"
#include "common/md5.h"
+#include "engines/game.h"
namespace Glk {
namespace Scott {
+void ScottMetaEngine::getSupportedGames(PlainGameList &games) {
+ for (const PlainGameDescriptor *pd = SCOTT_GAME_LIST; pd->gameId; ++pd)
+ games.push_back(*pd);
+}
+
+PlainGameDescriptor ScottMetaEngine::findGame(const char *gameId) {
+ for (const PlainGameDescriptor *pd = SCOTT_GAME_LIST; pd->gameId; ++pd) {
+ if (!strcmp(gameId, pd->gameId))
+ return *pd;
+ }
+
+ return PlainGameDescriptor();;
+}
+
bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
Common::File gameFile;
Common::String md5;
@@ -48,7 +63,8 @@ bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
if (p->_filesize) {
// Found a match
- DetectedGame gd(p->_gameId, p->_desc, Common::EN_ANY, Common::kPlatformUnknown);
+ PlainGameDescriptor gameDesc = findGame(p->_gameId);
+ DetectedGame gd(p->_gameId, gameDesc.description, Common::EN_ANY, Common::kPlatformUnknown);
gd.addExtraEntry("filename", file->getName());
gameList.push_back(gd);
diff --git a/engines/glk/scott/detection.h b/engines/glk/scott/detection.h
index 2c187cd..384197c 100644
--- a/engines/glk/scott/detection.h
+++ b/engines/glk/scott/detection.h
@@ -32,6 +32,16 @@ namespace Scott {
class ScottMetaEngine {
public:
/**
+ * Get a list of supported games
+ */
+ static void getSupportedGames(PlainGameList &games);
+
+ /**
+ * Returns a game description for the given game Id, if it's supported
+ */
+ static PlainGameDescriptor findGame(const char *gameId);
+
+ /**
* Detect supported games
*/
static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
diff --git a/engines/glk/scott/detection_tables.cpp b/engines/glk/scott/detection_tables.cpp
deleted file mode 100644
index f9a2a6c..0000000
--- a/engines/glk/scott/detection_tables.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 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.
- *
- */
-
-#include "glk/scott/detection_tables.h"
-
-namespace Glk {
-namespace Scott {
-
-const char *const ADVENTURELAND_DESC = "Adventureland";
-const char *const PIRATE_ADVENTURE_DESC = "Pirate Adventure";
-const char *const MISSION_IMPOSSIBLE_DESC = "Mission Impossible";
-const char *const VOODOO_CASTLE_DESC = "Voodoo Castle";
-const char *const THE_COUNT_DESC = "The Count";
-const char *const STRANGE_ODYSSEY_DESC = "Strange Odyssey";
-const char *const MYSTERY_FUN_HOUSE_DESC = "Mystery Fun House";
-const char *const PYRAMID_OF_DOOM_DESC = "Pyramid Of Doom";
-const char *const GHOST_TOWN_DESC = "Ghost Town";
-const char *const SAVAGE_ISLAND1_DESC = "Savage Island, Part 1";
-const char *const SAVAGE_ISLAND2_DESC = "Savage Island, Part 2";
-const char *const THE_GOLDEN_VOYAGE_DESC = "The Golden Voyage";
-const char *const ADVENTURE13_DESC = "Adventure 13";
-const char *const ADVENTURE14_DESC = "Adventure 14";
-const char *const BUCKAROO_BANZAI_DESC = "Buckaroo Banzai";
-const char *const MARVEL_ADVENTURE_DESC = "Marvel Adventure #1";
-const char *const MINI_SAMPLER_DESC = "Adventure International's Mini-Adventure Sampler";
-
-const ScottGame SCOTT_GAMES[] = {
- // PC game versions
- { "7c6f495d757a54e73d259efc718d8024", "adventureland", 15896, ADVENTURELAND_DESC },
- { "ea535fa7684508410151b4561de1f323", "pirateadventure", 16325, PIRATE_ADVENTURE_DESC },
- { "379c77a9a483886366b3b5c425e56410", "missionimpossible", 15275, MISSION_IMPOSSIBLE_DESC },
- { "a530a6857d1092eaa177eee575c94c71", "voodoocastle", 15852, VOODOO_CASTLE_DESC },
- { "5ebb4ade985670bb2eac54f8fa202214", "thecount", 17476, THE_COUNT_DESC },
- { "c57bb6df04dc77a2b232bc5bcab6e417", "strangeodyssey", 17489, STRANGE_ODYSSEY_DESC },
- { "ce2931ac3d5cbc270a5cb7be9e614f6e", "mysteryfunhouse", 17165, MYSTERY_FUN_HOUSE_DESC },
- { "4e6127fad6b5d75eccd3f3b101f8c9c8", "pyramidofdoom", 17673, PYRAMID_OF_DOOM_DESC },
- { "2c08327ab06d5490bd9e367ddaeca627", "ghosttown", 17831, GHOST_TOWN_DESC },
- { "8feb77f11d32e9567ce2fc7d435eaf44", "savageisland1", 19533, SAVAGE_ISLAND1_DESC },
- { "20c40a349f7a214ac515fb1d63c30a87", "savageisland2", 18367, SAVAGE_ISLAND2_DESC },
- { "e2a8f956ab215012d1495550c4c11ee8", "goldenvoyage", 18513, THE_GOLDEN_VOYAGE_DESC },
- { "f986d7e1ee074f65b6c1d00461c9b3c3", "adventure13", 19232, ADVENTURE13_DESC },
- { "6d98f422cc986d959a3c74351785aea3", "adventure14", 19013, ADVENTURE14_DESC },
- { "aadcc04e6b37eb9d30a58b5bc775842e", "marveladventure", 18876, MARVEL_ADVENTURE_DESC },
- { "d569a769f304dc02b3062d97458ddd01", "scottsampler", 13854, MINI_SAMPLER_DESC },
-
- // PDA game versions
- { "ae541fc1085da2f7d561b72ed20a6bc1", "adventureland", 18003, ADVENTURELAND_DESC },
- { "cbd47ab4fcfe00231ffd71d52378d410", "pirateadventure", 18482, PIRATE_ADVENTURE_DESC },
- { "9251ab2c64e63559d8a6e9e6246760a5", "missionimpossible", 17227, MISSION_IMPOSSIBLE_DESC },
- { "be849c5747c7fc3b201984afb4403b8e", "voodoocastle", 18140, VOODOO_CASTLE_DESC },
- { "85b75b6079b5ee572b5259b29a0e5d21", "thecount", 19999, THE_COUNT_DESC },
- { "c423cae841ac1927b5b2e503607b21bc", "strangeodyssey", 20115, STRANGE_ODYSSEY_DESC },
- { "326b98b991d401605074e64d474ce566", "mysteryfunhouse", 19700, MYSTERY_FUN_HOUSE_DESC },
- { "8ef9010399f055da9adb15ce7745a11c", "pyramidofdoom", 20320, PYRAMID_OF_DOOM_DESC },
- { "fcdcca8b2acf76ba2d0006cefa3630a1", "ghosttown", 20687, GHOST_TOWN_DESC },
- { "c8aaa80f07c40fa8e4b17432644919dc", "savageisland1", 22669, SAVAGE_ISLAND1_DESC },
- { "2add0f28d9b236c866890cdf8d86ee60", "savageisland2", 21169, SAVAGE_ISLAND2_DESC },
- { "675126bd0477e8ed9230ad3db5afc45f", "goldenvoyage", 21401, THE_GOLDEN_VOYAGE_DESC },
- { "0ef0def798d895ed766041fa99dd28a0", "adventure13", 22346, ADVENTURE13_DESC },
- { "0bf1bcc649422798332a38c88588fdff", "adventure14", 22087, ADVENTURE14_DESC },
- { "a0a5423967287dae9cbeb9abe8324479", "buckaroobanzai", 21038, BUCKAROO_BANZAI_DESC },
- { nullptr, nullptr, 0, nullptr }
-};
-
-} // End of namespace Frotz
-} // End of namespace Glk
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 6365bde..37a0163 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -20,7 +20,8 @@
*
*/
-#include "engines/advancedDetector.h"
+#include "engines/game.h"
+#include "common/gui_options.h"
#include "common/language.h"
namespace Glk {
@@ -33,27 +34,66 @@ struct ScottGame {
const char *_md5;
const char *_gameId;
int32 _filesize;
- const char *_desc;
};
-extern const ScottGame SCOTT_GAMES[];
-extern const char *const ADVENTURELAND_DESC;
-extern const char *const PIRATE_ADVENTURE_DESC;
-extern const char *const MISSION_IMPOSSIBLE_DESC;
-extern const char *const VOODOO_CASTLE_DESC;
-extern const char *const THE_COUNT_DESC;
-extern const char *const STRANGE_ODYSSEY_DESC;
-extern const char *const MYSTERY_FUN_HOUSE_DESC;
-extern const char *const PYRAMID_OF_DOOM_DESC;
-extern const char *const GHOST_TOWN_DESC;
-extern const char *const SAVAGE_ISLAND1_DESC;
-extern const char *const SAVAGE_ISLAND2_DESC;
-extern const char *const THE_GOLDEN_VOYAGE_DESC;
-extern const char *const ADVENTURE13_DESC;
-extern const char *const ADVENTURE14_DESC;
-extern const char *const BUCKAROO_BANZAI_DESC;
-extern const char *const MARVEL_ADVENTURE_DESC;
-extern const char *const MINI_SAMPLER_DESC;
+const PlainGameDescriptor SCOTT_GAME_LIST[] = {
+ { "adventureland", "Adventureland" },
+ { "pirateadventure", "Pirate Adventure" },
+ { "missionimpossible", "Mission Impossible" },
+ { "voodoocastle", "Voodoo Castle" },
+ { "thecount", "The Count" },
+ { "strangeodyssey", "Strange Odyssey" },
+ { "mysteryfunhouse", "Mystery Fun House" },
+ { "pyramidofdoom", "Pyramid Of Doom" },
+ { "ghosttown", "Ghost Town" },
+ { "savageisland1", "Savage Island, Part 1" },
+ { "savageisland2", "Savage Island, Part 2" },
+ { "goldenvoyage", "The Golden Voyage" },
+ { "adventure13", "Adventure 13" },
+ { "adventure14", "Adventure 14" },
+ { "buckaroobanzai", "Buckaroo Banzai" },
+ { "marveladventure", "Marvel Adventure #1" },
+ { "scottsampler", "Adventure International's Mini-Adventure Sampler" },
+ { nullptr, nullptr }
+};
+
+const ScottGame SCOTT_GAMES[] = {
+ // PC game versions
+ { "7c6f495d757a54e73d259efc718d8024", "adventureland", 15896 },
+ { "ea535fa7684508410151b4561de1f323", "pirateadventure", 16325 },
+ { "379c77a9a483886366b3b5c425e56410", "missionimpossible", 15275 },
+ { "a530a6857d1092eaa177eee575c94c71", "voodoocastle", 15852 },
+ { "5ebb4ade985670bb2eac54f8fa202214", "thecount", 17476 },
+ { "c57bb6df04dc77a2b232bc5bcab6e417", "strangeodyssey", 17489 },
+ { "ce2931ac3d5cbc270a5cb7be9e614f6e", "mysteryfunhouse", 17165 },
+ { "4e6127fad6b5d75eccd3f3b101f8c9c8", "pyramidofdoom", 17673 },
+ { "2c08327ab06d5490bd9e367ddaeca627", "ghosttown", 17831 },
+ { "8feb77f11d32e9567ce2fc7d435eaf44", "savageisland1", 19533 },
+ { "20c40a349f7a214ac515fb1d63c30a87", "savageisland2", 18367 },
+ { "e2a8f956ab215012d1495550c4c11ee8", "goldenvoyage", 18513 },
+ { "f986d7e1ee074f65b6c1d00461c9b3c3", "adventure13", 19232 },
+ { "6d98f422cc986d959a3c74351785aea3", "adventure14", 19013 },
+ { "aadcc04e6b37eb9d30a58b5bc775842e", "marveladventure", 18876 },
+ { "d569a769f304dc02b3062d97458ddd01", "scottsampler", 13854 },
+
+ // PDA game versions
+ { "ae541fc1085da2f7d561b72ed20a6bc1", "adventureland", 18003 },
+ { "cbd47ab4fcfe00231ffd71d52378d410", "pirateadventure", 18482 },
+ { "9251ab2c64e63559d8a6e9e6246760a5", "missionimpossible", 17227 },
+ { "be849c5747c7fc3b201984afb4403b8e", "voodoocastle", 18140 },
+ { "85b75b6079b5ee572b5259b29a0e5d21", "thecount", 19999 },
+ { "c423cae841ac1927b5b2e503607b21bc", "strangeodyssey", 20115 },
+ { "326b98b991d401605074e64d474ce566", "mysteryfunhouse", 19700 },
+ { "8ef9010399f055da9adb15ce7745a11c", "pyramidofdoom", 20320 },
+ { "fcdcca8b2acf76ba2d0006cefa3630a1", "ghosttown", 20687 },
+ { "c8aaa80f07c40fa8e4b17432644919dc", "savageisland1", 22669 },
+ { "2add0f28d9b236c866890cdf8d86ee60", "savageisland2", 21169 },
+ { "675126bd0477e8ed9230ad3db5afc45f", "goldenvoyage", 21401 },
+ { "0ef0def798d895ed766041fa99dd28a0", "adventure13", 22346 },
+ { "0bf1bcc649422798332a38c88588fdff", "adventure14", 22087 },
+ { "a0a5423967287dae9cbeb9abe8324479", "buckaroobanzai", 21038 },
+ { nullptr, nullptr, 0 }
+};
} // End of namespace Frotz
} // End of namespace Glk
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 2def1a2..6fedab1 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -26,7 +26,7 @@
namespace Glk {
namespace Scott {
-Scott::Scott(OSystem *syst, const GlkGameDescription *gameDesc) : GlkAPI(syst, gameDesc),
+Scott::Scott(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
split_screen(true), Bottom(0), Top(0), BitFlags(0), _saveSlot(-1) {
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 6899485..cf5f7bd 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -167,7 +167,7 @@ public:
/**
* Constructor
*/
- Scott(OSystem *syst, const GlkGameDescription *gameDesc);
+ Scott(OSystem *syst, const GlkGameDescription &gameDesc);
/**
* Execute the game
Commit: eff0ac80ff312d4e20fdcafa8d15971ba2183ce2
https://github.com/scummvm/scummvm/commit/eff0ac80ff312d4e20fdcafa8d15971ba2183ce2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Handle starting the engine directly from the command line
Changed paths:
engines/glk/detection.cpp
engines/glk/glk.h
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index b3cbccc..e6a129f 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -41,6 +41,8 @@
#define MAX_SAVES 99
class GlkMetaEngine : public MetaEngine {
+private:
+ Common::String findFileByGameId(const Common::String &gameId) const;
public:
GlkMetaEngine() : MetaEngine() {}
@@ -98,10 +100,27 @@ bool Glk::GlkEngine::hasFeature(EngineFeature f) const {
Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(engine);
+ // Populate the game description
Glk::GlkGameDescription gameDesc;
gameDesc._gameId = ConfMan.get("gameid");
gameDesc._filename = ConfMan.get("filename");
+ gameDesc._language = Common::UNK_LANG;
+ gameDesc._platform = Common::kPlatformUnknown;
+ if (ConfMan.hasKey("language"))
+ gameDesc._language = Common::parseLanguage(ConfMan.get("language"));
+ if (ConfMan.hasKey("platform"))
+ gameDesc._platform = Common::parsePlatform(ConfMan.get("platform"));
+
+ // If the game description has no filename, the engine has been launched directly from
+ // the command line. Do a scan for supported games for that Id in the game folder
+ if (gameDesc._filename.empty()) {
+ gameDesc._filename = findFileByGameId(gameDesc._gameId);
+ if (gameDesc._filename.empty())
+ return Common::kNoGameDataFoundError;
+ }
+
+ // Correct the correct engine
if (Glk::Frotz::FrotzMetaEngine::findGame(gameDesc._gameId.c_str()).description)
*engine = new Glk::Frotz::Frotz(syst, gameDesc);
else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description)
@@ -112,6 +131,28 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
return Common::kNoError;
}
+Common::String GlkMetaEngine::findFileByGameId(const Common::String &gameId) const {
+ // Get the list of files in the folder and return detection against them
+ Common::FSNode folder = Common::FSNode(ConfMan.get("path"));
+ Common::FSList fslist;
+ folder.getChildren(fslist, Common::FSNode::kListFilesOnly);
+
+ // Iterate over the files
+ for (Common::FSList::iterator i = fslist.begin(); i != fslist.end(); ++i) {
+ // Run a detection on each file in the folder individually
+ Common::FSList singleList;
+ singleList.push_back(*i);
+ DetectedGames games = detectGames(singleList);
+
+ // If a detection was found with the correct game Id, we have a winner
+ if (!games.empty() && games.front().gameId == gameId)
+ return (*i).getName();
+ }
+
+ // No match found
+ return Common::String();
+}
+
PlainGameList GlkMetaEngine::getSupportedGames() const {
PlainGameList list;
Glk::Frotz::FrotzMetaEngine::getSupportedGames(list);
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index b48d4e6..8dce78f 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -73,6 +73,7 @@ enum GlkDebugChannels {
struct GlkGameDescription {
Common::String _gameId;
Common::Language _language;
+ Common::Platform _platform;
Common::String _filename;
InterpreterType _interpType;
Common::String _md5;
Commit: 7b1b3935b89e119d7a268521adbc39afc605e403
https://github.com/scummvm/scummvm/commit/7b1b3935b89e119d7a268521adbc39afc605e403
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix remaining Gargoyle references identified by digitall
Changed paths:
devtools/credits.pl
dists/scummvm.rc
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 3cfa7b7..25ef73c 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -624,9 +624,9 @@ begin_credits("Credits");
add_person("Eugene Sandulenko", "sev", "");
end_section();
- begin_section("Gargoyle");
+ begin_section("ScummGlk");
add_person("Paul Gilbert", "dreammaster", "");
- add_person("Tor Andersson", "", "GLK library");
+ add_person("Tor Andersson", "", "GarGlk library");
add_person("Stefan Jokisch", "", "Frotz interpreter");
add_person("Alan Cox", "", "ScottFree interpreter");
end_section();
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 6d7782a..fb45f42 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -34,7 +34,7 @@ cryo.dat FILE "dists/engine-data/cryo.dat"
#if ENABLE_DRASCULA == STATIC_PLUGIN
drascula.dat FILE "dists/engine-data/drascula.dat"
#endif
-#if ENABLE_GARGOYLE == STATIC_PLUGIN
+#if ENABLE_GLK == STATIC_PLUGIN
fonts.dat FILE "dists/engine-data/fonts.dat"
#endif
#if ENABLE_HUGO == STATIC_PLUGIN
Commit: a1d355d0be8dfe0e3c1227a8f17ada609041ece4
https://github.com/scummvm/scummvm/commit/a1d355d0be8dfe0e3c1227a8f17ada609041ece4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Move ostream_* flags from GlkInterface to Processor
Changed paths:
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/frotz/processor.cpp
engines/glk/frotz/processor.h
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index b9652bc..6a0d510 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -32,10 +32,8 @@ GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) :
curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
gos_lower(nullptr), gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr),
gos_linewin(nullptr), gos_channel(nullptr), cwin(0), mwin(0), mouse_x(0), mouse_y(0),
- menu_selected(0), ostream_screen(false), ostream_script(false), ostream_memory(false),
- ostream_record(false), istream_replay(false), message(false),
- enable_wrapping(false), enable_scripting(false), enable_scrolling(false),
- enable_buffering(false), next_sample(0), next_volume(0),
+ menu_selected(0), enable_wrapping(false), enable_scripting(false),
+ enable_scrolling(false), enable_buffering(false), next_sample(0), next_volume(0),
_soundLocked(false), _soundPlaying(false) {
Common::fill(&statusline[0], &statusline[256], '\0');
}
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index 8bbdb73..c18ebb8 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -81,14 +81,6 @@ public:
int mouse_x;
int menu_selected;
- // IO streams
- bool ostream_screen;
- bool ostream_script;
- bool ostream_memory;
- bool ostream_record;
- bool istream_replay;
- bool message;
-
// Window attributes
bool enable_wrapping;
bool enable_scripting;
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index 442b007..eaa7310 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -137,7 +137,8 @@ Processor::Processor(OSystem *syst, const GlkGameDescription &gameDesc) :
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
_randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false),
_bufPos(0), _locked(false), _prevC('\0'), script_width(0),
- sfp(nullptr), rfp(nullptr), pfp(nullptr) {
+ sfp(nullptr), rfp(nullptr), pfp(nullptr), ostream_screen(true), ostream_script(false),
+ ostream_memory(false), ostream_record(false), istream_replay(false), message(false) {
static const Opcode OP0_OPCODES[16] = {
&Processor::z_rtrue,
&Processor::z_rfalse,
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index ddb264c..1a1dfc5 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -88,6 +88,12 @@ private:
// Stream related fields
int script_width;
strid_t sfp, rfp, pfp;
+ bool ostream_screen;
+ bool ostream_script;
+ bool ostream_memory;
+ bool ostream_record;
+ bool istream_replay;
+ bool message;
Common::FixedStack<Redirect, MAX_NESTING> _redirect;
private:
/**
Commit: f29147ba22b994a8985a6831290aa899a262af0c
https://github.com/scummvm/scummvm/commit/f29147ba22b994a8985a6831290aa899a262af0c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix showing unicode input lines
Changed paths:
engines/glk/window_text_buffer.cpp
engines/glk/window_text_grid.cpp
diff --git a/engines/glk/window_text_buffer.cpp b/engines/glk/window_text_buffer.cpp
index 36d8c6e..21de0d9 100644
--- a/engines/glk/window_text_buffer.cpp
+++ b/engines/glk/window_text_buffer.cpp
@@ -663,6 +663,7 @@ void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 in
int pw;
+ _lineRequestUni = true;
gli_tts_flush();
// because '>' prompt is ugly without extra space
@@ -693,9 +694,6 @@ void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 in
putTextUni(buf, initlen, _inCurs, 0);
}
- // WORKAROUND: Mark bottom line as dirty so caret will be drawn
- _lines[0]._dirty = true;
-
_echoLineInput = _echoLineInputBase;
if (_lineTerminatorsBase && _termCt) {
diff --git a/engines/glk/window_text_grid.cpp b/engines/glk/window_text_grid.cpp
index e16c9bd..3ee8198 100644
--- a/engines/glk/window_text_grid.cpp
+++ b/engines/glk/window_text_grid.cpp
@@ -272,6 +272,8 @@ void TextGridWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 init
return;
}
+ _lineRequestUni = true;
+
if ((int)maxlen > (_width - _curX))
maxlen = (_width - _curX);
Commit: beddf3853e631c4b3bc5393ee9072c489d1679ea
https://github.com/scummvm/scummvm/commit/beddf3853e631c4b3bc5393ee9072c489d1679ea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fill out HHGTTG version serial numbers
Changed paths:
engines/glk/frotz/detection_tables.h
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index 5eb310d..be32aba 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -88,11 +88,11 @@ const PlainGameDescriptor FROTZ_GAME_LIST[] = {
#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
const FrotzGameDescription FROTZ_GAMES[] = {
- ENTRY0("hhgttg", "v31 Solid Gold", "379022bcd4ec74b90274c6100c33f579", 158412),
- ENTRY0("hhgttg", "v47", "fdda8f4239819402c62db866bb61a648", 112622),
- ENTRY0("hhgttg", "v56", "a214fcb42bc9f554d07d983a12f6a062", 113444),
- ENTRY0("hhgttg", "v58", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
- ENTRY0("hhgttg", "v59", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
+ ENTRY0("hhgttg", "R47-840914", "fdda8f4239819402c62db866bb61a648", 112622),
+ ENTRY0("hhgttg", "R56-841221", "a214fcb42bc9f554d07d983a12f6a062", 113444),
+ ENTRY0("hhgttg", "R58-851002", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
+ ENTRY0("hhgttg", "R59-851108", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
+ ENTRY0("hhgttg", "R31-871119", "379022bcd4ec74b90274c6100c33f579", 158412),
FROTZ_TABLE_END_MARKER
};
Commit: af081ad322649918c205e03e4dd29991547981e0
https://github.com/scummvm/scummvm/commit/af081ad322649918c205e03e4dd29991547981e0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Improve fallback detection of Z-code games
Changed paths:
engines/glk/frotz/detection.cpp
engines/glk/frotz/detection_tables.h
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index b77344d..9ac033b 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -77,7 +77,8 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
continue;
warning("Uknown zcode game %s - %s %d", filename.c_str(), md5.c_str(), filesize);
- gd = DetectedGame("zcode", "Unrecognised zcode game", Common::UNK_LANG, Common::kPlatformUnknown);
+ const PlainGameDescriptor &desc = FROTZ_GAME_LIST[0];
+ gd = DetectedGame(desc.gameId, desc.description, Common::UNK_LANG, Common::kPlatformUnknown);
} else {
PlainGameDescriptor gameDesc = findGame(p->_gameId);
gd = DetectedGame(p->_gameId, gameDesc.description, p->_language, Common::kPlatformUnknown, p->_extra);
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index be32aba..d4d6f7e 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -40,6 +40,9 @@ struct FrotzGameDescription {
};
const PlainGameDescriptor FROTZ_GAME_LIST[] = {
+ { "zcode", "Unknown Z-code game" },
+
+ // Infocom games
{ "amfv", "A Mind Forever Voyaging" },
{ "arthur", "Arthur: The Quest for Excalibur" },
{ "ballyhoo", "Ballyhoo" },
Commit: d9e7fca83c7025d2a91ac5341fb9082ea2b8a0fb
https://github.com/scummvm/scummvm/commit/d9e7fca83c7025d2a91ac5341fb9082ea2b8a0fb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix exiting when application is forcefully closed
Changed paths:
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/processor.cpp
engines/glk/frotz/processor_streams.cpp
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index 6a0d510..292409f 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -155,7 +155,7 @@ void GlkInterface::initialize() {
// Use the ms-dos interpreter number for v6, because that's the
// kind of graphics files we understand. Otherwise, use DEC.
- h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_DEC_20;
+ h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_AMIGA;
h_interpreter_version = 'F';
{
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index eaa7310..343299e 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -285,7 +285,7 @@ void Processor::interpret() {
if (end_of_sound_flag)
end_of_sound();
#endif
- } while (!_finished);
+ } while (!shouldQuit() && !_finished);
_finished--;
}
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index 8413f4b..581eb1e 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -182,6 +182,8 @@ continue_input:
key = replay_read_input(buf);
else
key = console_read_input(max, buf, timeout, key != ZC_BAD);
+ if (shouldQuit())
+ return ZC_BAD;
} while (key == ZC_BAD);
// Copy input line to the command file
Commit: 04f42acca06c705eeb49da50c58ff15f7611a7c1
https://github.com/scummvm/scummvm/commit/04f42acca06c705eeb49da50c58ff15f7611a7c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Allow exiting ScumMVM when waiting for a keypress
Changed paths:
engines/glk/frotz/processor_streams.cpp
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index 581eb1e..93b9c0b 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -145,6 +145,8 @@ continue_input:
key = replay_read_key();
else
key = console_read_key(timeout);
+ if (shouldQuit())
+ return ZC_BAD;
} while (key == ZC_BAD);
// Copy key to the command file
Commit: 625df27cfcbdffcec708692a6f182891ad6b9363
https://github.com/scummvm/scummvm/commit/625df27cfcbdffcec708692a6f182891ad6b9363
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Adding detection entries for Infocom games
Changed paths:
engines/glk/frotz/detection_tables.h
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index d4d6f7e..a1fdbdf 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -57,9 +57,8 @@ const PlainGameDescriptor FROTZ_GAME_LIST[] = {
{ "infidel", "Infidel" },
{ "journey", "Journey" },
{ "lgop", "Leather Goddesses of Phobos" },
- { "lgop2", "Leather Goddesses of Phobos 2" },
{ "lurkinghorror", "The Lurking Horror" },
- { "minizork", "Mini Zork I: The Great Underground Empire" },
+ { "minizork1", "Mini Zork I: The Great Underground Empire" },
{ "moonmist", "Moonmist" },
{ "nordbert", "Nord and Bert Couldn't Make Head or Tail of It" },
{ "planetfall", "Planetfall" },
@@ -91,11 +90,45 @@ const PlainGameDescriptor FROTZ_GAME_LIST[] = {
#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
const FrotzGameDescription FROTZ_GAMES[] = {
+ ENTRY0("amfv", "R77-850814", "b7ffaed0ca4a90450f92b34066133377", 262016),
+ ENTRY0("amfv", "R79-851122", "1e37dbcf7ccc9244dbfc3229796362f4", 262544),
+ ENTRY0("arthur", "R54-890606", "ced2c66d03a49de0e8190b468332f081", 271360),
+ ENTRY0("arthur", "R74-890714", "13d13f375f85a874c82a8ac7ad69dc41", 269200),
+ ENTRY0("ballyhoo", "R97-851218", "7944e832a7d7b34037c7b6791de43dbd", 128556),
+ ENTRY0("beyondzork", "R49-870917", "a5547795def620d0a75a064f9a37ab2d", 261900),
+ ENTRY0("beyondzork", "R51-870923", "73948f415596fa4d9afe442b2c19e61f", 261548),
+ ENTRY0("beyondzork", "R57-871221", "c56cac07a500e5864a994b19286bc07c", 261388),
+ ENTRY0("borderzone", "R9-871008", "189231ed0675f6be3be86856f49211af", 178372),
+ ENTRY0("bureaucracy", "R86-870212", "2bb00311d4c201082cfcd278ae5db921", 243144),
+ ENTRY0("bureaucracy", "R116-870602", "a8ae194257a989ed3d82648a507466f2", 243340),
+ ENTRY0("cutthroats", "R23-840809", "059801d9f90fffeb3645816c37c7eda2", 112558),
+ ENTRY0("deadline", "R22-820809", "1610e84ca2505885566e648c1c525976", 111782),
+ ENTRY0("deadline", "R26-821108", "e1ae6af1098067b86076c34865ae713c", 108372),
+ ENTRY0("deadline", "R27-831006", "166ffb7cabc6b85f210655f371c89c46", 108454),
+ ENTRY0("enchanter", "R10-830810", "7b41d915b4c2e31423d99925e9438aa4", 109126),
+ ENTRY0("enchanter", "R15-831107", "e70f21aad650dd196fa3601cab5e0fc5", 109230),
+ ENTRY0("enchanter", "R16-831118", "46187e0691f6f5ecdd5a336885db6aad", 109234),
+ ENTRY0("enchanter", "R29-860820", "f87cdafad3682ead25cfc473656ff713", 111126),
ENTRY0("hhgttg", "R47-840914", "fdda8f4239819402c62db866bb61a648", 112622),
ENTRY0("hhgttg", "R56-841221", "a214fcb42bc9f554d07d983a12f6a062", 113444),
ENTRY0("hhgttg", "R58-851002", "e867d49ad1fb9406ff4e0678a4ee2ac9", 113332),
ENTRY0("hhgttg", "R59-851108", "34f6abc1f2a42be127ef434fc475f0ee", 113334),
ENTRY0("hhgttg", "R31-871119", "379022bcd4ec74b90274c6100c33f579", 158412),
+ ENTRY0("hollywoodhijinx", "R37-861215", "7b52824057ae24e098c228c41460ef75", 109650),
+ ENTRY0("infidel", "R22-830916", "38f713e53af720624434529ea780040c", 93556),
+ ENTRY0("journey", "R30-890322", "c9893bc0399080bd3850d4db2120d110", 280472),
+ ENTRY0("journey", "R77-890616", "8a4ab56f62e1b7c918b837794182dbcd", 282176),
+ ENTRY0("journey", "R83-890706", "c33ea33ab8aec6c617734dcfe1211067", 282312),
+ ENTRY0("lgop", "R0", "69b3534570851b90d7f53ebe9d224a6a", 128998),
+ ENTRY0("lgop", "R4-880405", "6bdae7434df7c03f3589ece0bed3317d", 159928),
+ ENTRY0("lgop", "R59-860730", "e81237e220a612c5a93fbcc1fdf85a0a", 129022),
+ ENTRY0("lurkinghorror", "R203", "e2d2505510479fec0405727e3d0abc10", 128986),
+ ENTRY0("lurkinghorror", "R219", "83936d75c2cfd71fb64bf63c4696b9ac", 129704),
+ ENTRY0("lurkinghorror", "R221", "c60cd0bf3c6eda867241378c7cb5464a", 129944),
+ ENTRY0("minizork1", "R34-871124", "0d7700679e5e63dec97f712698610a46", 52216),
+
+
+
FROTZ_TABLE_END_MARKER
};
Commit: dee20ace65cb16a30c80c0790462d569f5da627d
https://github.com/scummvm/scummvm/commit/dee20ace65cb16a30c80c0790462d569f5da627d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added detection entries for more Infocom games
Changed paths:
engines/glk/frotz/detection_tables.h
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index a1fdbdf..8e6da37 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -126,7 +126,37 @@ const FrotzGameDescription FROTZ_GAMES[] = {
ENTRY0("lurkinghorror", "R219", "83936d75c2cfd71fb64bf63c4696b9ac", 129704),
ENTRY0("lurkinghorror", "R221", "c60cd0bf3c6eda867241378c7cb5464a", 129944),
ENTRY0("minizork1", "R34-871124", "0d7700679e5e63dec97f712698610a46", 52216),
-
+ ENTRY0("moonmist", "R4-860918", "284797c3025ffaf76aecfa5c2bbffa86", 129002),
+ ENTRY0("moonmist", "R9-861022", "698475de2769c66bc5a1eca600c71561", 128866),
+ ENTRY0("nordbert", "R19-870722", "da1e189e19e3b24b2e35bd41fc32d261", 170284),
+ ENTRY0("planetfall", "R20-830708", "15815c461a8548b7630d2aee46d07cc7", 107958),
+ ENTRY0("planetfall", "R26-831014", "cf6ce61eb2eff9d4f18d7bcba7c12cfb", 108674),
+ ENTRY0("planetfall", "R29-840118", "9facd8b974e658520fb762af4c4789dc", 109052),
+ ENTRY0("planetfall", "R37-851003", "01844816673414c97d21dc003304989b",109398),
+ ENTRY0("planetfall", "R10-880531", "34c69f1d24418fd4d2de195a1d7546c4", 136560),
+ ENTRY0("plunderedhearts", "R26-870730", "fe5b9eb91949d41838166364f1753b10", 128962),
+ ENTRY0("infocomsampler1", "R26-840731", "5483febc51abd55fb5e04c4c97a0b260", 112610),
+ ENTRY0("infocomsampler1", "R53-850407", "47b8b8394e25faec870a798145529688", 126708),
+ ENTRY0("infocomsampler1", "R55-850823", "05d9d1a1c3c73fce9e24ab695ece16c8", 126902),
+ ENTRY0("infocomsampler2", "R97-870601", "201fa230a942df5aa75bb5b5f609e8ce", 125314),
+ ENTRY0("seastalker", "R15-840501", "2f0220b0390deda695e01832a92b5493", 117738),
+ ENTRY0("seastalker", "R15-840522", "050961fa7788c309bbf40accbff2ffdf", 117728),
+ ENTRY0("seastalker", "R16-850515", "eb39dff7beb3589c8581dd2e3569eb78", 117752),
+ ENTRY0("seastalker", "R16-850603", "bccf194b1e823e37db2431b586662773", 117762),
+ ENTRY0("seastalker", "R86-840320", "64fb27e7b9fd682ff4f0d0ec6616a468", 116456),
+ ENTRY0("sherlockriddle", "R21-871214", "69862f7f07a4e977159ea4da7f2f2ba6", 188444),
+ ENTRY0("sherlockriddle", "R26-880127", "2cb2bda2e34eb7f9494cb585720e74cd", 190180),
+ ENTRY0("shogun", "R322-890706", "62cca41feb94082442026f44f3e48e19", 344816),
+ ENTRY0("sorcerer", "R4-840131", "d4a914fdfe90f5cd055a03b9aa24addd", 109734),
+ ENTRY0("sorcerer", "R6-840508", "7ee357c10a9e049fe7c641a4817ee575", 109482),
+ ENTRY0("sorcerer", "R13-851021", "7a076459806eaee72015b2b2882a89dc", 108692),
+ ENTRY0("sorcerer", "R15-851108", "cde88a011d2ba183ff69b47b0d8881c6", 108682),
+ ENTRY0("spellbreaker", "R63-850916", "b7b9eef231dee03fb40a9d98416fa0d5", 128480),
+ ENTRY0("spellbreaker", "R87-860904", "852286847f4cdd790075fa824260ff4e", 128916),
+ ENTRY0("starcross", "R15-820901", "fb2e6d9a0ad5822f3a8d4aec949e4e3c", 84984),
+ ENTRY0("starcross", "R17-821021", "ed1e62e1f0eb9d819be45c076c5729f7", 83792),
+ ENTRY0("stationfall", "R107-870430", "cfadfb66afabaa2971ec9b4ae65266ca", 128934),
+ ENTRY0("suspect", "R14-841005", "3d759ccb19233f51968fa79d7374b393", 118692),
Commit: 238022890edd256182d0bebd894af39a7f6cd79b
https://github.com/scummvm/scummvm/commit/238022890edd256182d0bebd894af39a7f6cd79b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Debug code to generate detection entries for unknown games
Used it to flesh out the list of Infocom game detection entries
Changed paths:
engines/glk/frotz/detection.cpp
engines/glk/frotz/detection_tables.h
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 9ac033b..61d9a14 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -22,6 +22,7 @@
#include "glk/frotz/detection.h"
#include "glk/frotz/detection_tables.h"
+#include "common/debug.h"
#include "common/file.h"
#include "common/md5.h"
@@ -63,6 +64,11 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
continue;
Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
size_t filesize = gameFile.size();
+ char serial[7] = "unkown";
+ if (!filename.hasSuffixIgnoreCase(".zblorb")) {
+ gameFile.seek(18);
+ gameFile.read(&serial[0], 6);
+ }
gameFile.close();
// Check for known game
@@ -76,7 +82,20 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
if (filename.hasSuffixIgnoreCase(".dat"))
continue;
- warning("Uknown zcode game %s - %s %d", filename.c_str(), md5.c_str(), filesize);
+ if (gDebugLevel > 0) {
+ // Print an entry suitable for putting into the detection_tables.h, using the
+ // name of the parent folder the game is in as the presumed game Id
+ Common::String folderName = file->getParent().getName();
+ if (folderName.hasSuffix("\\"))
+ folderName.deleteLastChar();
+ Common::String fname = filename;
+ const char *dot = strchr(fname.c_str(), '.');
+ if (dot)
+ fname = Common::String(fname.c_str(), dot);
+
+ debug("ENTRY0(\"%s\", \"%s-%s\", \"%s\", %u),",
+ folderName.c_str(), fname.c_str(), serial, md5.c_str(), filesize);
+ }
const PlainGameDescriptor &desc = FROTZ_GAME_LIST[0];
gd = DetectedGame(desc.gameId, desc.description, Common::UNK_LANG, Common::kPlatformUnknown);
} else {
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index 8e6da37..179067c 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -87,9 +87,11 @@ const PlainGameDescriptor FROTZ_GAME_LIST[] = {
#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
#define ENTRY0(ID, VERSION, MD5, FILESIZE) { ID, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
+#define ENTRY1(ID, VERSION, MD5, FILESIZE, LANG) { ID, VERSION, MD5, FILESIZE, LANG, NONE }
#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
const FrotzGameDescription FROTZ_GAMES[] = {
+ // Infocom Games - English
ENTRY0("amfv", "R77-850814", "b7ffaed0ca4a90450f92b34066133377", 262016),
ENTRY0("amfv", "R79-851122", "1e37dbcf7ccc9244dbfc3229796362f4", 262544),
ENTRY0("arthur", "R54-890606", "ced2c66d03a49de0e8190b468332f081", 271360),
@@ -157,8 +159,53 @@ const FrotzGameDescription FROTZ_GAMES[] = {
ENTRY0("starcross", "R17-821021", "ed1e62e1f0eb9d819be45c076c5729f7", 83792),
ENTRY0("stationfall", "R107-870430", "cfadfb66afabaa2971ec9b4ae65266ca", 128934),
ENTRY0("suspect", "R14-841005", "3d759ccb19233f51968fa79d7374b393", 118692),
+ ENTRY0("suspended", "v5-830222", "d898430e3cccdee9f9acfffcc9ef709c", 105418),
+ ENTRY0("suspended", "R7-830419", "65f0cc760a2500d110242fbf942f1028", 105500),
+ ENTRY0("suspended", "R8-830521", "b749d42462dfec21831b69635cd9c5e8", 105492),
+ ENTRY0("suspended", "R8_2-840521", "6088ad7cb553626b52875a9b8e801312", 105584),
+ ENTRY0("trinity", "R11-860509", "994ea591f8d401e11661c912b92ee05e", 262016),
+ ENTRY0("trinity", "R12-860926", "5377dc1ee39f1c8ed572944f89946eb2", 262064),
+ ENTRY0("wishbringer", "R23-880706", "bec823084c5622e88eca5a886278d2a5", 164712),
+ ENTRY0("wishbringer", "R68-850501", "898b9b157ce8e54a0953366d6317fbd5", 128952),
+ ENTRY0("wishbringer", "R69-850920", "e7c0412c4b3bda39de438a02cbae3816", 128904),
+ ENTRY0("thewitness", "R13-830524", "d2297ddfe2c1b976c1b0c381ab01e2b3", 102608),
+ ENTRY0("thewitness", "R18-830910", "a6e441b0b92a72537c830fed201267af", 103728),
+ ENTRY0("thewitness", "R22-840924", "1019b9b1e1aa2c6eda945d7d92c2073a", 104664),
+ ENTRY0("zork0", "R296-881019", "fca554c21542729c9d154c319af6307e", 295536),
+ ENTRY0("zork0", "R366-demo-890323", "b58c35dc2ba36d48fade99564922c7c3", 296376),
+ ENTRY0("zork0", "R366-890323", "e787b2cad2d6f29fd812e737f75646e8", 296376),
+ ENTRY0("zork0", "R383-890602", "32e3e7ec438dabe77df2351af6ece324", 299392),
+ ENTRY0("zork0", "R393-890714", "29fb0e090bbff7bc8e9661e55da69ae7", 299968),
+ ENTRY0("zork1", "R15-UG3AU5", "fa2d22304700898cb8de921f46ca4bc9", 78566),
+ ENTRY0("zork1", "R20", "b222bed4a0ab2650135cba7f4b1b1c67", 75734),
+ ENTRY0("zork1", "R23-820428", "6ad3d9ab2874beefcbc53630e9261118", 75780),
+ ENTRY0("zork1", "R25-820515", "287a1ce17f458fb2e776499a13796719", 75808),
+ ENTRY0("zork1", "R26-820803", "285f1d7c5deb1a2f23825f63823d0777", 75964),
+ ENTRY0("zork1", "R28-821013", "83bb70d73f3b4b5c4a32d8588b2d0707", 76018),
+ ENTRY0("zork1", "R30-830330", "d6d8b3ae49a683a6fce2383a8bab36a5", 76324),
+ ENTRY0("zork1", "R5", "dd5ba502b30189d03abfcfb9817dffe0", 82836),
+ ENTRY0("zork1", "R52-871125", "e56267fd041c71fc229f7deb6b6537c2", 105264),
+ ENTRY0("zork1", "R75-830929", "b35bca8dd18f6312c7e54dcd7958d7e5", 84868),
+ ENTRY0("zork1", "R76-840509", "50ebf3c0c959ac2571c23cb7f7907c70", 84874),
+ ENTRY0("zork1", "R88-840726", "d708b6751126f3b2b7612c760f080d41", 84876),
+ ENTRY0("zork2", "R15-820308", "4b6ecc8e40243ddbd4cc19ef82304c3b", 82110),
+ ENTRY0("zork2", "R17-820427", "386f2cd937e0ca316695d6ddca521c78", 82368),
+ ENTRY0("zork2", "R18-820512", "a019dd721134b57f5926ee2adf634b55", 82422),
+ ENTRY0("zork2", "R18_2-820517", "6cafa0e5239a74aa120bb8e2c33441be", 82422),
+ ENTRY0("zork2", "R19-820721", "a5236020509af26b47c737e51ce884aa", 82586),
+ ENTRY0("zork2", "R22-830331", "600264d62720731283454592261ec3fe", 82920),
+ ENTRY0("zork2", "R23-830411", "6c2e766b553c127bb07f7a0f8fe03ae2", 81876),
+ ENTRY0("zork2", "R48-840904", "a5064c9c3ce0bc02f16e01d745f39b67", 89912),
+ ENTRY0("zork2", "R7-UG3AU5", "8243ce12e7b3ce24b150f34cc2cb472c", 85260),
+ ENTRY0("zork3", "R10-820818", "ba4897f4d82ba08906295dd3aebf501a", 82334),
+ ENTRY0("zork3", "R15-830331", "2fb29e6f5eebb643f42714ca9086e145", 82558),
+ ENTRY0("zork3", "R15_2-840518", "672b54d8f457bd3be32e41fc9e069d71", 82642),
+ ENTRY0("zork3", "R16-830410", "4717f8ec2f08da7d438c05f1351d28bd", 81626),
+ ENTRY0("zork3", "R17-840727", "c5dc520f469771c59d193558d405341d", 82714),
+ ENTRY0("ztuu", "ztuu-970828", "3a55991be19943a13da58a91cd3615eb", 102524),
-
+ // Infocom Games - Foreign
+ ENTRY1("zork1", "R3-880113", "9f336c92c1fd392fc7e81288e5c9b6ab", 116216, Common::DE_DEU),
FROTZ_TABLE_END_MARKER
};
Commit: bd4bc0a43f5f90c6c4cead91df9f5296f3b82899
https://github.com/scummvm/scummvm/commit/bd4bc0a43f5f90c6c4cead91df9f5296f3b82899
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix crash clicking screen with mouse without dragging
Changed paths:
engines/glk/selection.cpp
diff --git a/engines/glk/selection.cpp b/engines/glk/selection.cpp
index 2bc4fb8..566ae65 100644
--- a/engines/glk/selection.cpp
+++ b/engines/glk/selection.cpp
@@ -152,10 +152,8 @@ void Selection::startSelection(const Point &pos) {
tx = MIN(pos.x, (int16)_hor);
ty = MIN(pos.y, (int16)_ver);
- _select.left = _last.x = tx;
- _select.top = _last.y = ty;
- _select.right = 0;
- _select.bottom = 0;
+ _select.left = _select.right = _last.x = tx;
+ _select.top = _select.bottom = _last.y = ty;
g_vm->_windows->selectionChanged();
}
@@ -189,8 +187,8 @@ void Selection::clearSelection() {
}
bool Selection::checkSelection(const Rect &r) const {
- Rect select(MIN(_select.left, _select.right), MAX(_select.left, _select.right),
- MIN(_select.top, _select.bottom), MAX(_select.top, _select.bottom));
+ Rect select(MIN(_select.left, _select.right), MIN(_select.top, _select.bottom),
+ MAX(_select.left, _select.right), MAX(_select.top, _select.bottom));
if (select.isEmpty())
return false;
Commit: 027240678e54f410fcce21b1a9f86d52fdcc07af
https://github.com/scummvm/scummvm/commit/027240678e54f410fcce21b1a9f86d52fdcc07af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Change engine to use ScummVM String and Arrays
Changed paths:
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 6fedab1..c895d2b 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -27,9 +27,8 @@ namespace Glk {
namespace Scott {
Scott::Scott(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
- Items(nullptr), Rooms(nullptr), Verbs(nullptr), Nouns(nullptr), Messages(nullptr),
- Actions(nullptr), CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0),
- split_screen(true), Bottom(0), Top(0), BitFlags(0), _saveSlot(-1) {
+ CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0), split_screen(true),
+ Bottom(0), Top(0), BitFlags(0), _saveSlot(-1) {
Common::fill(&NounText[0], &NounText[16], '\0');
Common::fill(&Counters[0], &Counters[16], 0);
Common::fill(&RoomSaved[0], &RoomSaved[16], 0);
@@ -182,13 +181,6 @@ void Scott::clearScreen(void) {
glk_window_clear(Bottom);
}
-void *Scott::memAlloc(int size) {
- void *t = (void *)malloc(size);
- if (t == nullptr)
- fatal("Out of memory");
- return t;
-}
-
bool Scott::randomPercent(uint n) {
return _random.getRandomNumber(99) < n;
}
@@ -209,7 +201,7 @@ const char *Scott::mapSynonym(const char *word) {
const char *tp;
static char lastword[16]; // Last non synonym
while (n <= GameHeader.NumWords) {
- tp = Nouns[n];
+ tp = Nouns[n].c_str();
if (*tp == '*')
tp++;
else
@@ -229,8 +221,8 @@ int Scott::matchUpItem(const char *text, int loc) {
word = text;
while (ct <= GameHeader.NumItems) {
- if (Items[ct].AutoGet && Items[ct].Location == loc &&
- xstrncasecmp(Items[ct].AutoGet, word, GameHeader.WordLength) == 0)
+ if (!Items[ct].AutoGet.empty() && Items[ct].Location == loc &&
+ xstrncasecmp(Items[ct].AutoGet.c_str(), word, GameHeader.WordLength) == 0)
return ct;
ct++;
}
@@ -238,9 +230,8 @@ int Scott::matchUpItem(const char *text, int loc) {
return -1;
}
-char *Scott::readString(Common::SeekableReadStream *f) {
+Common::String Scott::readString(Common::SeekableReadStream *f) {
char tmp[1024];
- char *t;
int c, nc;
int ct = 0;
do {
@@ -280,9 +271,7 @@ char *Scott::readString(Common::SeekableReadStream *f) {
}
tmp[ct] = 0;
- t = (char *)memAlloc(ct + 1);
- memcpy(t, tmp, ct + 1);
- return t;
+ return Common::String(tmp);
}
void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
@@ -297,27 +286,27 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
GameHeader.NumItems = ni;
- Items = (Item *)memAlloc(sizeof(Item) * (ni + 1));
+ Items.resize(ni + 1);
GameHeader.NumActions = na;
- Actions = (Action *)memAlloc(sizeof(Action) * (na + 1));
+ Actions.resize(na + 1);
GameHeader.NumWords = nw;
GameHeader.WordLength = wl;
- Verbs = (const char **)memAlloc(sizeof(char *) * (nw + 1));
- Nouns = (const char **)memAlloc(sizeof(char *) * (nw + 1));
+ Verbs.resize(nw + 1);
+ Nouns.resize(nw + 1);
GameHeader.NumRooms = nr;
- Rooms = (Room *)memAlloc(sizeof(Room) * (nr + 1));
+ Rooms.resize(nr + 1);
GameHeader.MaxCarry = mc;
GameHeader.PlayerRoom = pr;
GameHeader.Treasures = tr;
GameHeader.LightTime = lt;
LightRefill = lt;
GameHeader.NumMessages = mn;
- Messages = (const char **)memAlloc(sizeof(char *) * (mn + 1));
+ Messages.resize(mn + 1);
GameHeader.TreasureRoom = trm;
// Load the actions
ct = 0;
- ap = Actions;
+ ap = &Actions[0];
if (loud)
debug("Reading %d actions.", na);
while (ct < na + 1) {
@@ -343,7 +332,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
ct++;
}
ct = 0;
- rp = Rooms;
+ rp = &Rooms[0];
if (loud)
debug("Reading %d rooms.", nr);
while (ct < nr + 1) {
@@ -367,17 +356,23 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
ct = 0;
if (loud)
debug("Reading %d items.", ni);
- ip = Items;
+ ip = &Items[0];
while (ct < ni + 1) {
ip->Text = readString(f);
- ip->AutoGet = strchr(ip->Text, '/');
- // Some games use // to mean no auto get/drop word!
- if (ip->AutoGet && strcmp(ip->AutoGet, "//") && strcmp(ip->AutoGet, "/*")) {
- char *t;
- *ip->AutoGet++ = 0;
- t = strchr(ip->AutoGet, '/');
- if (t != nullptr)
- *t = 0;
+
+ const char *p = strchr(ip->Text.c_str(), '/');
+ if (p) {
+ ip->AutoGet = Common::String(p);
+
+ // Some games use // to mean no auto get/drop word!
+ if (!ip->AutoGet.hasPrefix("//") && !ip->AutoGet.hasPrefix("/*")) {
+ ip->Text = Common::String(ip->Text.c_str(), p);
+ ip->AutoGet.deleteChar(0);
+
+ const char *t = strchr(ip->AutoGet.c_str(), '/');
+ if (t)
+ ip->AutoGet = Common::String(ip->AutoGet.c_str(), t);
+ }
}
readInts(f, 1, &lo);
@@ -387,9 +382,10 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
ct++;
}
ct = 0;
- // Discard Comment Strings
+
+ // Skip Comment Strings
while (ct < na + 1) {
- free(readString(f));
+ readString(f);
ct++;
}
@@ -402,9 +398,9 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
debug("%d.\nLoad Complete.\n", ct);
}
-void Scott::output(const char *a) {
+void Scott::output(const Common::String &a) {
if (_saveSlot == -1)
- display(Bottom, "%s", a);
+ display(Bottom, "%s", a.c_str());
}
void Scott::outputNumber(int a) {
@@ -431,13 +427,13 @@ void Scott::look(void) {
return;
}
r = &Rooms[MyLoc];
- if (*r->Text == '*')
- display(Top, "%s\n", r->Text + 1);
+ if (r->Text.hasPrefix("*"))
+ display(Top, "%s\n", r->Text.c_str() + 1);
else {
if (Options & YOUARE)
- display(Top, "You are in a %s\n", r->Text);
+ display(Top, "You are in a %s\n", r->Text.c_str());
else
- display(Top, "I'm in a %s\n", r->Text);
+ display(Top, "I'm in a %s\n", r->Text.c_str());
}
ct = 0;
@@ -475,12 +471,12 @@ void Scott::look(void) {
display(Top, " - ");
pos += 3;
}
- if (pos + (int)strlen(Items[ct].Text) > (Width - 10)) {
+ if (pos + (int)Items[ct].Text.size() > (Width - 10)) {
pos = 0;
display(Top, "\n");
}
- display(Top, "%s", Items[ct].Text);
- pos += strlen(Items[ct].Text);
+ display(Top, "%s", Items[ct].Text.c_str());
+ pos += Items[ct].Text.size();
if (Options & TRS80_STYLE) {
display(Top, ". ");
pos += 2;
@@ -494,12 +490,12 @@ void Scott::look(void) {
display(Top, TRS80_LINE);
}
-int Scott::whichWord(const char *word, const char **list) {
+int Scott::whichWord(const char *word, const Common::StringArray &list) {
int n = 1;
int ne = 1;
const char *tp;
while (ne <= GameHeader.NumWords) {
- tp = list[ne];
+ tp = list[ne].c_str();
if (*tp == '*')
tp++;
else
@@ -862,7 +858,7 @@ doneit:
int n = 0;
while (i <= GameHeader.NumItems) {
if (Items[i].Location == GameHeader.TreasureRoom &&
- *Items[i].Text == '*')
+ Items[i].Text.hasPrefix("*"))
n++;
i++;
}
@@ -1115,7 +1111,7 @@ int Scott::performActions(int vb, int no) {
}
while (i <= GameHeader.NumItems) {
if (Items[i].Location == MyLoc && Items[i].AutoGet != nullptr && Items[i].AutoGet[0] != '*') {
- no = whichWord(Items[i].AutoGet, Nouns);
+ no = whichWord(Items[i].AutoGet.c_str(), Nouns);
disable_sysfunc = 1; // Don't recurse into auto get !
performActions(vb, no); // Recursively check each items table code
disable_sysfunc = 0;
@@ -1165,8 +1161,9 @@ int Scott::performActions(int vb, int no) {
int i = 0;
int f = 0;
while (i <= GameHeader.NumItems) {
- if (Items[i].Location == CARRIED && Items[i].AutoGet && Items[i].AutoGet[0] != '*') {
- no = whichWord(Items[i].AutoGet, Nouns);
+ if (Items[i].Location == CARRIED && !Items[i].AutoGet.empty()
+ && !Items[i].AutoGet.hasPrefix("*")) {
+ no = whichWord(Items[i].AutoGet.c_str(), Nouns);
disable_sysfunc = 1;
performActions(vb, no);
disable_sysfunc = 0;
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index cf5f7bd..188ddd7 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -81,21 +81,21 @@ struct Action {
};
struct Room {
- char *Text;
+ Common::String Text;
short Exits[6];
- Room() : Text(0) {
+ Room() {
Common::fill(&Exits[0], &Exits[6], 0);
}
};
struct Item {
- char *Text; // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
+ Common::String Text;
byte Location;
byte InitialLoc;
- char *AutoGet;
+ Common::String AutoGet;
- Item() : Text(nullptr), Location(0), InitialLoc(0), AutoGet(nullptr) {}
+ Item() : Location(0), InitialLoc(0) {}
};
struct Tail {
@@ -112,12 +112,12 @@ struct Tail {
class Scott : public GlkAPI {
private:
Header GameHeader;
- Item *Items;
- Room *Rooms;
- const char **Verbs;
- const char **Nouns;
- const char **Messages;
- Action *Actions;
+ Common::Array<Item> Items;
+ Common::Array<Room> Rooms;
+ Common::StringArray Verbs;
+ Common::StringArray Nouns;
+ Common::StringArray Messages;
+ Common::Array<Action> Actions;
int LightRefill;
char NounText[16];
int Counters[16]; ///< Range unknown
@@ -142,17 +142,16 @@ private:
void delay(int seconds);
void fatal(const char *x);
void clearScreen(void);
- void *memAlloc(int size);
bool randomPercent(uint n);
int countCarried(void);
const char *mapSynonym(const char *word);
int matchUpItem(const char *text, int loc);
- char *readString(Common::SeekableReadStream *f);
+ Common::String readString(Common::SeekableReadStream *f);
void loadDatabase(Common::SeekableReadStream *f, bool loud);
- void output(const char *a);
+ void output(const Common::String &a);
void outputNumber(int a);
void look(void);
- int whichWord(const char *word, const char **list);
+ int whichWord(const char *word, const Common::StringArray &list);
void lineInput(char *buf, size_t n);
void saveGame(void);
void loadGame(void);
Commit: 83646598c9afacb522cabe6bd7e3778a82d3459c
https://github.com/scummvm/scummvm/commit/83646598c9afacb522cabe6bd7e3778a82d3459c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Renaming of all fields to ScummVM convention
Changed paths:
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index c895d2b..ff014e7 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -27,38 +27,38 @@ namespace Glk {
namespace Scott {
Scott::Scott(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
- CurrentCounter(0), SavedRoom(0), Options(0), Width(0), TopHeight(0), split_screen(true),
- Bottom(0), Top(0), BitFlags(0), _saveSlot(-1) {
- Common::fill(&NounText[0], &NounText[16], '\0');
- Common::fill(&Counters[0], &Counters[16], 0);
- Common::fill(&RoomSaved[0], &RoomSaved[16], 0);
+ _currentCounter(0), _savedRoom(0), _options(0), _width(0), _topHeight(0), _splitScreen(true),
+ _bottomWindow(0), _topWindow(0), _bitFlags(0), _saveSlot(-1) {
+ Common::fill(&_nounText[0], &_nounText[16], '\0');
+ Common::fill(&_counters[0], &_counters[16], 0);
+ Common::fill(&_roomSaved[0], &_roomSaved[16], 0);
}
void Scott::runGame(Common::SeekableReadStream *gameFile) {
int vb, no;
initialize();
- Bottom = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
- if (Bottom == nullptr)
+ _bottomWindow = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
+ if (_bottomWindow == nullptr)
glk_exit();
- glk_set_window(Bottom);
+ glk_set_window(_bottomWindow);
- if (Options & TRS80_STYLE) {
- Width = 64;
- TopHeight = 11;
+ if (_options & TRS80_STYLE) {
+ _width = 64;
+ _topHeight = 11;
} else {
- Width = 80;
- TopHeight = 10;
+ _width = 80;
+ _topHeight = 10;
}
- if (split_screen) {
- Top = glk_window_open(Bottom, winmethod_Above | winmethod_Fixed, TopHeight, wintype_TextGrid, 0);
- if (Top == nullptr) {
- split_screen = 0;
- Top = Bottom;
+ if (_splitScreen) {
+ _topWindow = glk_window_open(_bottomWindow, winmethod_Above | winmethod_Fixed, _topHeight, wintype_TextGrid, 0);
+ if (_topWindow == nullptr) {
+ _splitScreen = 0;
+ _topWindow = _bottomWindow;
}
} else {
- Top = Bottom;
+ _topWindow = _bottomWindow;
}
output("ScummVM support adapted from Scott Free, A Scott Adams game driver in C.\n\n");
@@ -67,7 +67,7 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
_saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
// Load the game
- loadDatabase(gameFile, (Options & DEBUGGING) ? 1 : 0);
+ loadDatabase(gameFile, (_options & DEBUGGING) ? 1 : 0);
// Main game loop
while (!shouldQuit()) {
@@ -100,29 +100,29 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
}
// Brian Howarth games seem to use -1 for forever
- if (Items[LIGHT_SOURCE].Location/*==-1*/ != DESTROYED && GameHeader.LightTime != -1) {
- GameHeader.LightTime--;
- if (GameHeader.LightTime < 1) {
- BitFlags |= (1 << LIGHTOUTBIT);
- if (Items[LIGHT_SOURCE].Location == CARRIED ||
- Items[LIGHT_SOURCE].Location == MyLoc) {
- if (Options & SCOTTLIGHT)
+ if (_items[LIGHT_SOURCE]._location/*==-1*/ != DESTROYED && _gameHeader._lightTime != -1) {
+ _gameHeader._lightTime--;
+ if (_gameHeader._lightTime < 1) {
+ _bitFlags |= (1 << LIGHTOUTBIT);
+ if (_items[LIGHT_SOURCE]._location == CARRIED ||
+ _items[LIGHT_SOURCE]._location == MY_LOC) {
+ if (_options & SCOTTLIGHT)
output("Light has run out! ");
else
output("Your light has run out. ");
}
- if (Options & PREHISTORIC_LAMP)
- Items[LIGHT_SOURCE].Location = DESTROYED;
- } else if (GameHeader.LightTime < 25) {
- if (Items[LIGHT_SOURCE].Location == CARRIED ||
- Items[LIGHT_SOURCE].Location == MyLoc) {
+ if (_options & PREHISTORIC_LAMP)
+ _items[LIGHT_SOURCE]._location = DESTROYED;
+ } else if (_gameHeader._lightTime < 25) {
+ if (_items[LIGHT_SOURCE]._location == CARRIED ||
+ _items[LIGHT_SOURCE]._location == MY_LOC) {
- if (Options & SCOTTLIGHT) {
+ if (_options & SCOTTLIGHT) {
output("Light runs out in ");
- outputNumber(GameHeader.LightTime);
+ outputNumber(_gameHeader._lightTime);
output(" turns. ");
} else {
- if (GameHeader.LightTime % 5 == 0)
+ if (_gameHeader._lightTime % 5 == 0)
output("Your light is growing dim. ");
}
}
@@ -134,18 +134,18 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
void Scott::initialize() {
if (ConfMan.hasKey("YOUARE")) {
if (ConfMan.getBool("YOUARE"))
- Options |= YOUARE;
+ _options |= YOUARE;
else
- Options &= ~YOUARE;
+ _options &= ~YOUARE;
}
if (gDebugLevel > 0)
- Options |= DEBUGGING;
+ _options |= DEBUGGING;
if (ConfMan.hasKey("SCOTTLIGHT") && ConfMan.getBool("SCOTTLIGHT"))
- Options |= SCOTTLIGHT;
+ _options |= SCOTTLIGHT;
if (ConfMan.hasKey("TRS80_STYLE") && ConfMan.getBool("TRS80_STYLE"))
- Options |= TRS80_STYLE;
+ _options |= TRS80_STYLE;
if (ConfMan.hasKey("PREHISTORIC_LAMP") && ConfMan.getBool("PREHISTORIC_LAMP"))
- Options |= PREHISTORIC_LAMP;
+ _options |= PREHISTORIC_LAMP;
}
void Scott::display(winid_t w, const char *fmt, ...) {
@@ -178,7 +178,7 @@ void Scott::fatal(const char *x) {
}
void Scott::clearScreen(void) {
- glk_window_clear(Bottom);
+ glk_window_clear(_bottomWindow);
}
bool Scott::randomPercent(uint n) {
@@ -188,8 +188,8 @@ bool Scott::randomPercent(uint n) {
int Scott::countCarried(void) {
int ct = 0;
int n = 0;
- while (ct <= GameHeader.NumItems) {
- if (Items[ct].Location == CARRIED)
+ while (ct <= _gameHeader._numItems) {
+ if (_items[ct]._location == CARRIED)
n++;
ct++;
}
@@ -200,13 +200,13 @@ const char *Scott::mapSynonym(const char *word) {
int n = 1;
const char *tp;
static char lastword[16]; // Last non synonym
- while (n <= GameHeader.NumWords) {
- tp = Nouns[n].c_str();
+ while (n <= _gameHeader._numWords) {
+ tp = _nouns[n].c_str();
if (*tp == '*')
tp++;
else
strcpy(lastword, tp);
- if (xstrncasecmp(word, tp, GameHeader.WordLength) == 0)
+ if (xstrncasecmp(word, tp, _gameHeader._wordLength) == 0)
return lastword;
n++;
}
@@ -220,9 +220,9 @@ int Scott::matchUpItem(const char *text, int loc) {
if (word == nullptr)
word = text;
- while (ct <= GameHeader.NumItems) {
- if (!Items[ct].AutoGet.empty() && Items[ct].Location == loc &&
- xstrncasecmp(Items[ct].AutoGet.c_str(), word, GameHeader.WordLength) == 0)
+ while (ct <= _gameHeader._numItems) {
+ if (!_items[ct]._autoGet.empty() && _items[ct]._location == loc &&
+ xstrncasecmp(_items[ct]._autoGet.c_str(), word, _gameHeader._wordLength) == 0)
return ct;
ct++;
}
@@ -285,40 +285,40 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
// Load the header
readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
- GameHeader.NumItems = ni;
- Items.resize(ni + 1);
- GameHeader.NumActions = na;
- Actions.resize(na + 1);
- GameHeader.NumWords = nw;
- GameHeader.WordLength = wl;
- Verbs.resize(nw + 1);
- Nouns.resize(nw + 1);
- GameHeader.NumRooms = nr;
- Rooms.resize(nr + 1);
- GameHeader.MaxCarry = mc;
- GameHeader.PlayerRoom = pr;
- GameHeader.Treasures = tr;
- GameHeader.LightTime = lt;
- LightRefill = lt;
- GameHeader.NumMessages = mn;
- Messages.resize(mn + 1);
- GameHeader.TreasureRoom = trm;
+ _gameHeader._numItems = ni;
+ _items.resize(ni + 1);
+ _gameHeader._numActions = na;
+ _actions.resize(na + 1);
+ _gameHeader._numWords = nw;
+ _gameHeader._wordLength = wl;
+ _verbs.resize(nw + 1);
+ _nouns.resize(nw + 1);
+ _gameHeader._numRooms = nr;
+ _rooms.resize(nr + 1);
+ _gameHeader._maxCarry = mc;
+ _gameHeader._playerRoom = pr;
+ _gameHeader._treasures = tr;
+ _gameHeader._lightTime = lt;
+ _lightRefill = lt;
+ _gameHeader._numMessages = mn;
+ _messages.resize(mn + 1);
+ _gameHeader._treasureRoom = trm;
// Load the actions
ct = 0;
- ap = &Actions[0];
+ ap = &_actions[0];
if (loud)
debug("Reading %d actions.", na);
while (ct < na + 1) {
readInts(f, 8,
- &ap->Vocab,
- &ap->Condition[0],
- &ap->Condition[1],
- &ap->Condition[2],
- &ap->Condition[3],
- &ap->Condition[4],
- &ap->action[0],
- &ap->action[1]);
+ &ap->_vocab,
+ &ap->_condition[0],
+ &ap->_condition[1],
+ &ap->_condition[2],
+ &ap->_condition[3],
+ &ap->_condition[4],
+ &ap->_action[0],
+ &ap->_action[1]);
ap++;
ct++;
}
@@ -327,20 +327,20 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
if (loud)
debug("Reading %d word pairs.", nw);
while (ct < nw + 1) {
- Verbs[ct] = readString(f);
- Nouns[ct] = readString(f);
+ _verbs[ct] = readString(f);
+ _nouns[ct] = readString(f);
ct++;
}
ct = 0;
- rp = &Rooms[0];
+ rp = &_rooms[0];
if (loud)
debug("Reading %d rooms.", nr);
while (ct < nr + 1) {
readInts(f, 6,
- &rp->Exits[0], &rp->Exits[1], &rp->Exits[2],
- &rp->Exits[3], &rp->Exits[4], &rp->Exits[5]);
+ &rp->_exits[0], &rp->_exits[1], &rp->_exits[2],
+ &rp->_exits[3], &rp->_exits[4], &rp->_exits[5]);
- rp->Text = readString(f);
+ rp->_text = readString(f);
ct++;
rp++;
}
@@ -349,35 +349,35 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
if (loud)
debug("Reading %d messages.", mn);
while (ct < mn + 1) {
- Messages[ct] = readString(f);
+ _messages[ct] = readString(f);
ct++;
}
ct = 0;
if (loud)
debug("Reading %d items.", ni);
- ip = &Items[0];
+ ip = &_items[0];
while (ct < ni + 1) {
- ip->Text = readString(f);
+ ip->_text = readString(f);
- const char *p = strchr(ip->Text.c_str(), '/');
+ const char *p = strchr(ip->_text.c_str(), '/');
if (p) {
- ip->AutoGet = Common::String(p);
+ ip->_autoGet = Common::String(p);
// Some games use // to mean no auto get/drop word!
- if (!ip->AutoGet.hasPrefix("//") && !ip->AutoGet.hasPrefix("/*")) {
- ip->Text = Common::String(ip->Text.c_str(), p);
- ip->AutoGet.deleteChar(0);
+ if (!ip->_autoGet.hasPrefix("//") && !ip->_autoGet.hasPrefix("/*")) {
+ ip->_text = Common::String(ip->_text.c_str(), p);
+ ip->_autoGet.deleteChar(0);
- const char *t = strchr(ip->AutoGet.c_str(), '/');
+ const char *t = strchr(ip->_autoGet.c_str(), '/');
if (t)
- ip->AutoGet = Common::String(ip->AutoGet.c_str(), t);
+ ip->_autoGet = Common::String(ip->_autoGet.c_str(), t);
}
}
readInts(f, 1, &lo);
- ip->Location = (unsigned char)lo;
- ip->InitialLoc = ip->Location;
+ ip->_location = (unsigned char)lo;
+ ip->_initialLoc = ip->_location;
ip++;
ct++;
}
@@ -400,11 +400,11 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
void Scott::output(const Common::String &a) {
if (_saveSlot == -1)
- display(Bottom, "%s", a.c_str());
+ display(_bottomWindow, "%s", a.c_str());
}
void Scott::outputNumber(int a) {
- display(Bottom, "%d", a);
+ display(_bottomWindow, "%d", a);
}
void Scott::look(void) {
@@ -413,94 +413,94 @@ void Scott::look(void) {
int ct, f;
int pos;
- if (split_screen)
- glk_window_clear(Top);
+ if (_splitScreen)
+ glk_window_clear(_topWindow);
- if ((BitFlags & (1 << DARKBIT)) && Items[LIGHT_SOURCE].Location != CARRIED
- && Items[LIGHT_SOURCE].Location != MyLoc) {
- if (Options & YOUARE)
- display(Top, "You can't see. It is too dark!\n");
+ if ((_bitFlags & (1 << DARKBIT)) && _items[LIGHT_SOURCE]._location != CARRIED
+ && _items[LIGHT_SOURCE]._location != MY_LOC) {
+ if (_options & YOUARE)
+ display(_topWindow, "You can't see. It is too dark!\n");
else
- display(Top, "I can't see. It is too dark!\n");
- if (Options & TRS80_STYLE)
- display(Top, TRS80_LINE);
+ display(_topWindow, "I can't see. It is too dark!\n");
+ if (_options & TRS80_STYLE)
+ display(_topWindow, TRS80_LINE);
return;
}
- r = &Rooms[MyLoc];
- if (r->Text.hasPrefix("*"))
- display(Top, "%s\n", r->Text.c_str() + 1);
+ r = &_rooms[MY_LOC];
+ if (r->_text.hasPrefix("*"))
+ display(_topWindow, "%s\n", r->_text.c_str() + 1);
else {
- if (Options & YOUARE)
- display(Top, "You are in a %s\n", r->Text.c_str());
+ if (_options & YOUARE)
+ display(_topWindow, "You are in a %s\n", r->_text.c_str());
else
- display(Top, "I'm in a %s\n", r->Text.c_str());
+ display(_topWindow, "I'm in a %s\n", r->_text.c_str());
}
ct = 0;
f = 0;
- display(Top, "\nObvious exits: ");
+ display(_topWindow, "\nObvious exits: ");
while (ct < 6) {
- if (r->Exits[ct] != 0) {
+ if (r->_exits[ct] != 0) {
if (f == 0)
f = 1;
else
- display(Top, ", ");
- display(Top, "%s", ExitNames[ct]);
+ display(_topWindow, ", ");
+ display(_topWindow, "%s", ExitNames[ct]);
}
ct++;
}
if (f == 0)
- display(Top, "none");
- display(Top, ".\n");
+ display(_topWindow, "none");
+ display(_topWindow, ".\n");
ct = 0;
f = 0;
pos = 0;
- while (ct <= GameHeader.NumItems) {
- if (Items[ct].Location == MyLoc) {
+ while (ct <= _gameHeader._numItems) {
+ if (_items[ct]._location == MY_LOC) {
if (f == 0) {
- if (Options & YOUARE) {
- display(Top, "\nYou can also see: ");
+ if (_options & YOUARE) {
+ display(_topWindow, "\nYou can also see: ");
pos = 18;
} else {
- display(Top, "\nI can also see: ");
+ display(_topWindow, "\nI can also see: ");
pos = 16;
}
f++;
- } else if (!(Options & TRS80_STYLE)) {
- display(Top, " - ");
+ } else if (!(_options & TRS80_STYLE)) {
+ display(_topWindow, " - ");
pos += 3;
}
- if (pos + (int)Items[ct].Text.size() > (Width - 10)) {
+ if (pos + (int)_items[ct]._text.size() > (_width - 10)) {
pos = 0;
- display(Top, "\n");
+ display(_topWindow, "\n");
}
- display(Top, "%s", Items[ct].Text.c_str());
- pos += Items[ct].Text.size();
- if (Options & TRS80_STYLE) {
- display(Top, ". ");
+ display(_topWindow, "%s", _items[ct]._text.c_str());
+ pos += _items[ct]._text.size();
+ if (_options & TRS80_STYLE) {
+ display(_topWindow, ". ");
pos += 2;
}
}
ct++;
}
- display(Top, "\n");
- if (Options & TRS80_STYLE)
- display(Top, TRS80_LINE);
+ display(_topWindow, "\n");
+ if (_options & TRS80_STYLE)
+ display(_topWindow, TRS80_LINE);
}
int Scott::whichWord(const char *word, const Common::StringArray &list) {
int n = 1;
int ne = 1;
const char *tp;
- while (ne <= GameHeader.NumWords) {
+ while (ne <= _gameHeader._numWords) {
tp = list[ne].c_str();
if (*tp == '*')
tp++;
else
n = ne;
- if (xstrncasecmp(word, tp, GameHeader.WordLength) == 0)
+ if (xstrncasecmp(word, tp, _gameHeader._wordLength) == 0)
return n;
ne++;
}
@@ -510,7 +510,7 @@ int Scott::whichWord(const char *word, const Common::StringArray &list) {
void Scott::lineInput(char *buf, size_t n) {
event_t ev;
- glk_request_line_event(Bottom, buf, n - 1, 0);
+ glk_request_line_event(_bottomWindow, buf, n - 1, 0);
do {
glk_select(&ev);
@@ -518,7 +518,7 @@ void Scott::lineInput(char *buf, size_t n) {
return;
else if (ev.type == evtype_LineInput)
break;
- else if (ev.type == evtype_Arrange && split_screen)
+ else if (ev.type == evtype_Arrange && _splitScreen)
look();
} while (ev.type != evtype_Quit);
@@ -547,17 +547,17 @@ Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
return Common::kWritingFailed;
for (int ct = 0; ct < 16; ct++) {
- msg = Common::String::format("%d %d\n", Counters[ct], RoomSaved[ct]);
+ msg = Common::String::format("%d %d\n", _counters[ct], _roomSaved[ct]);
glk_put_string_stream(file, msg.c_str());
}
msg = Common::String::format("%u %d %hd %d %d %hd\n",
- BitFlags, (BitFlags & (1 << DARKBIT)) ? 1 : 0,
- MyLoc, CurrentCounter, SavedRoom, GameHeader.LightTime);
+ _bitFlags, (_bitFlags & (1 << DARKBIT)) ? 1 : 0,
+ MY_LOC, _currentCounter, _savedRoom, _gameHeader._lightTime);
glk_put_string_stream(file, msg.c_str());
- for (int ct = 0; ct <= GameHeader.NumItems; ct++) {
- msg = Common::String::format("%hd\n", (short)Items[ct].Location);
+ for (int ct = 0; ct <= _gameHeader._numItems; ct++) {
+ msg = Common::String::format("%hd\n", (short)_items[ct]._location);
glk_put_string_stream(file, msg.c_str());
}
@@ -594,21 +594,21 @@ Common::Error Scott::loadGameState(int slot) {
for (ct = 0; ct < 16; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
- sscanf(buf, "%d %d", &Counters[ct], &RoomSaved[ct]);
+ sscanf(buf, "%d %d", &_counters[ct], &_roomSaved[ct]);
}
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%u %hd %d %d %d %d\n",
- &BitFlags, &darkFlag, &MyLoc, &CurrentCounter, &SavedRoom,
- &GameHeader.LightTime);
+ &_bitFlags, &darkFlag, &MY_LOC, &_currentCounter, &_savedRoom,
+ &_gameHeader._lightTime);
// Backward compatibility
if (darkFlag)
- BitFlags |= (1 << 15);
- for (ct = 0; ct <= GameHeader.NumItems; ct++) {
+ _bitFlags |= (1 << 15);
+ for (ct = 0; ct <= _gameHeader._numItems; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%hd\n", &lo);
- Items[ct].Location = (unsigned char)lo;
+ _items[ct]._location = (unsigned char)lo;
}
return Common::kNoError;
@@ -662,13 +662,13 @@ int Scott::getInput(int *vb, int *no) {
break;
}
}
- nc = whichWord(verb, Nouns);
+ nc = whichWord(verb, _nouns);
// The Scott Adams system has a hack to avoid typing 'go'
if (nc >= 1 && nc <= 6) {
vc = 1;
} else {
- vc = whichWord(verb, Verbs);
- nc = whichWord(noun, Nouns);
+ vc = whichWord(verb, _verbs);
+ nc = whichWord(noun, _nouns);
}
*vb = vc;
*no = nc;
@@ -677,7 +677,7 @@ int Scott::getInput(int *vb, int *no) {
}
} while (vc == -1);
- strcpy(NounText, noun); // Needed by GET/DROP hack
+ strcpy(_nounText, noun); // Needed by GET/DROP hack
return 0;
}
@@ -689,7 +689,7 @@ int Scott::performLine(int ct) {
while (cc < 5) {
int cv, dv;
- cv = Actions[ct].Condition[cc];
+ cv = _actions[ct]._condition[cc];
dv = cv / 20;
cv %= 20;
switch (cv) {
@@ -697,40 +697,40 @@ int Scott::performLine(int ct) {
param[pptr++] = dv;
break;
case 1:
- if (Items[dv].Location != CARRIED)
+ if (_items[dv]._location != CARRIED)
return 0;
break;
case 2:
- if (Items[dv].Location != MyLoc)
+ if (_items[dv]._location != MY_LOC)
return 0;
break;
case 3:
- if (Items[dv].Location != CARRIED &&
- Items[dv].Location != MyLoc)
+ if (_items[dv]._location != CARRIED &&
+ _items[dv]._location != MY_LOC)
return 0;
break;
case 4:
- if (MyLoc != dv)
+ if (MY_LOC != dv)
return 0;
break;
case 5:
- if (Items[dv].Location == MyLoc)
+ if (_items[dv]._location == MY_LOC)
return 0;
break;
case 6:
- if (Items[dv].Location == CARRIED)
+ if (_items[dv]._location == CARRIED)
return 0;
break;
case 7:
- if (MyLoc == dv)
+ if (MY_LOC == dv)
return 0;
break;
case 8:
- if ((BitFlags & (1 << dv)) == 0)
+ if ((_bitFlags & (1 << dv)) == 0)
return 0;
break;
case 9:
- if (BitFlags & (1 << dv))
+ if (_bitFlags & (1 << dv))
return 0;
break;
case 10:
@@ -742,45 +742,45 @@ int Scott::performLine(int ct) {
return 0;
break;
case 12:
- if (Items[dv].Location == CARRIED || Items[dv].Location == MyLoc)
+ if (_items[dv]._location == CARRIED || _items[dv]._location == MY_LOC)
return 0;
break;
case 13:
- if (Items[dv].Location == 0)
+ if (_items[dv]._location == 0)
return 0;
break;
case 14:
- if (Items[dv].Location)
+ if (_items[dv]._location)
return 0;
break;
case 15:
- if (CurrentCounter > dv)
+ if (_currentCounter > dv)
return 0;
break;
case 16:
- if (CurrentCounter <= dv)
+ if (_currentCounter <= dv)
return 0;
break;
case 17:
- if (Items[dv].Location != Items[dv].InitialLoc)
+ if (_items[dv]._location != _items[dv]._initialLoc)
return 0;
break;
case 18:
- if (Items[dv].Location == Items[dv].InitialLoc)
+ if (_items[dv]._location == _items[dv]._initialLoc)
return 0;
break;
case 19:
// Only seen in Brian Howarth games so far
- if (CurrentCounter != dv)
+ if (_currentCounter != dv)
return 0;
break;
}
cc++;
}
- // Actions
- act[0] = Actions[ct].action[0];
- act[2] = Actions[ct].action[1];
+ // _actions
+ act[0] = _actions[ct]._action[0];
+ act[2] = _actions[ct]._action[1];
act[1] = act[0] % 150;
act[3] = act[2] % 150;
act[0] /= 150;
@@ -789,61 +789,61 @@ int Scott::performLine(int ct) {
pptr = 0;
while (cc < 4) {
if (act[cc] >= 1 && act[cc] < 52) {
- output(Messages[act[cc]]);
+ output(_messages[act[cc]]);
output("\n");
} else if (act[cc] > 101) {
- output(Messages[act[cc] - 50]);
+ output(_messages[act[cc] - 50]);
output("\n");
} else {
switch (act[cc]) {
case 0:// NOP
break;
case 52:
- if (countCarried() == GameHeader.MaxCarry) {
- if (Options & YOUARE)
+ if (countCarried() == _gameHeader._maxCarry) {
+ if (_options & YOUARE)
output("You are carrying too much. ");
else
output("I've too much to carry! ");
break;
}
- Items[param[pptr++]].Location = CARRIED;
+ _items[param[pptr++]]._location = CARRIED;
break;
case 53:
- Items[param[pptr++]].Location = MyLoc;
+ _items[param[pptr++]]._location = MY_LOC;
break;
case 54:
- MyLoc = param[pptr++];
+ MY_LOC = param[pptr++];
break;
case 55:
- Items[param[pptr++]].Location = 0;
+ _items[param[pptr++]]._location = 0;
break;
case 56:
- BitFlags |= 1 << DARKBIT;
+ _bitFlags |= 1 << DARKBIT;
break;
case 57:
- BitFlags &= ~(1 << DARKBIT);
+ _bitFlags &= ~(1 << DARKBIT);
break;
case 58:
- BitFlags |= (1 << param[pptr++]);
+ _bitFlags |= (1 << param[pptr++]);
break;
case 59:
- Items[param[pptr++]].Location = 0;
+ _items[param[pptr++]]._location = 0;
break;
case 60:
- BitFlags &= ~(1 << param[pptr++]);
+ _bitFlags &= ~(1 << param[pptr++]);
break;
case 61:
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("You are dead.\n");
else
output("I am dead.\n");
- BitFlags &= ~(1 << DARKBIT);
- MyLoc = GameHeader.NumRooms;// It seems to be what the code says!
+ _bitFlags &= ~(1 << DARKBIT);
+ MY_LOC = _gameHeader._numRooms;// It seems to be what the code says!
break;
case 62: {
// Bug fix for some systems - before it could get parameters wrong */
int i = param[pptr++];
- Items[i].Location = param[pptr++];
+ _items[i]._location = param[pptr++];
break;
}
case 63:
@@ -856,21 +856,21 @@ doneit:
case 65: {
int i = 0;
int n = 0;
- while (i <= GameHeader.NumItems) {
- if (Items[i].Location == GameHeader.TreasureRoom &&
- Items[i].Text.hasPrefix("*"))
+ while (i <= _gameHeader._numItems) {
+ if (_items[i]._location == _gameHeader._treasureRoom &&
+ _items[i]._text.hasPrefix("*"))
n++;
i++;
}
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("You have stored ");
else
output("I've stored ");
outputNumber(n);
output(" treasures. On a scale of 0 to 100, that rates ");
- outputNumber((n * 100) / GameHeader.Treasures);
+ outputNumber((n * 100) / _gameHeader._treasures);
output(".\n");
- if (n == GameHeader.Treasures) {
+ if (n == _gameHeader._treasures) {
output("Well done.\n");
goto doneit;
}
@@ -879,20 +879,20 @@ doneit:
case 66: {
int i = 0;
int f = 0;
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("You are carrying:\n");
else
output("I'm carrying:\n");
- while (i <= GameHeader.NumItems) {
- if (Items[i].Location == CARRIED) {
+ while (i <= _gameHeader._numItems) {
+ if (_items[i]._location == CARRIED) {
if (f == 1) {
- if (Options & TRS80_STYLE)
+ if (_options & TRS80_STYLE)
output(". ");
else
output(" - ");
}
f = 1;
- output(Items[i].Text);
+ output(_items[i]._text);
}
i++;
}
@@ -902,15 +902,15 @@ doneit:
break;
}
case 67:
- BitFlags |= (1 << 0);
+ _bitFlags |= (1 << 0);
break;
case 68:
- BitFlags &= ~(1 << 0);
+ _bitFlags &= ~(1 << 0);
break;
case 69:
- GameHeader.LightTime = LightRefill;
- Items[LIGHT_SOURCE].Location = CARRIED;
- BitFlags &= ~(1 << LIGHTOUTBIT);
+ _gameHeader._lightTime = _lightRefill;
+ _items[LIGHT_SOURCE]._location = CARRIED;
+ _bitFlags &= ~(1 << LIGHTOUTBIT);
break;
case 70:
clearScreen(); // pdd.
@@ -921,41 +921,41 @@ doneit:
case 72: {
int i1 = param[pptr++];
int i2 = param[pptr++];
- int t = Items[i1].Location;
- Items[i1].Location = Items[i2].Location;
- Items[i2].Location = t;
+ int t = _items[i1]._location;
+ _items[i1]._location = _items[i2]._location;
+ _items[i2]._location = t;
break;
}
case 73:
continuation = 1;
break;
case 74:
- Items[param[pptr++]].Location = CARRIED;
+ _items[param[pptr++]]._location = CARRIED;
break;
case 75: {
int i1, i2;
i1 = param[pptr++];
i2 = param[pptr++];
- Items[i1].Location = Items[i2].Location;
+ _items[i1]._location = _items[i2]._location;
break;
}
case 76:
// Looking at adventure ..
break;
case 77:
- if (CurrentCounter >= 0)
- CurrentCounter--;
+ if (_currentCounter >= 0)
+ _currentCounter--;
break;
case 78:
- outputNumber(CurrentCounter);
+ outputNumber(_currentCounter);
break;
case 79:
- CurrentCounter = param[pptr++];
+ _currentCounter = param[pptr++];
break;
case 80: {
- int t = MyLoc;
- MyLoc = SavedRoom;
- SavedRoom = t;
+ int t = MY_LOC;
+ MY_LOC = _savedRoom;
+ _savedRoom = t;
break;
}
case 81: {
@@ -963,26 +963,26 @@ doneit:
// select counter n, thing, select counter n, but uses one value that always
// seems to exist. Trying a few options I found this gave sane results on ageing
int t = param[pptr++];
- int c1 = CurrentCounter;
- CurrentCounter = Counters[t];
- Counters[t] = c1;
+ int c1 = _currentCounter;
+ _currentCounter = _counters[t];
+ _counters[t] = c1;
break;
}
case 82:
- CurrentCounter += param[pptr++];
+ _currentCounter += param[pptr++];
break;
case 83:
- CurrentCounter -= param[pptr++];
- if (CurrentCounter < -1)
- CurrentCounter = -1;
+ _currentCounter -= param[pptr++];
+ if (_currentCounter < -1)
+ _currentCounter = -1;
// Note: This seems to be needed. I don't yet know if there
// is a maximum value to limit too
break;
case 84:
- output(NounText);
+ output(_nounText);
break;
case 85:
- output(NounText);
+ output(_nounText);
output("\n");
break;
case 86:
@@ -991,9 +991,9 @@ doneit:
case 87: {
// Changed this to swap location<->roomflag[x] not roomflag 0 and x
int p = param[pptr++];
- int sr = MyLoc;
- MyLoc = RoomSaved[p];
- RoomSaved[p] = sr;
+ int sr = MY_LOC;
+ MY_LOC = _roomSaved[p];
+ _roomSaved[p] = sr;
break;
}
case 88:
@@ -1020,7 +1020,7 @@ doneit:
int Scott::performActions(int vb, int no) {
static int disable_sysfunc = 0; // Recursion lock
- int d = BitFlags & (1 << DARKBIT);
+ int d = _bitFlags & (1 << DARKBIT);
int ct = 0;
int fl;
@@ -1031,24 +1031,24 @@ int Scott::performActions(int vb, int no) {
}
if (vb == 1 && no >= 1 && no <= 6) {
int nl;
- if (Items[LIGHT_SOURCE].Location == MyLoc ||
- Items[LIGHT_SOURCE].Location == CARRIED)
+ if (_items[LIGHT_SOURCE]._location == MY_LOC ||
+ _items[LIGHT_SOURCE]._location == CARRIED)
d = 0;
if (d)
output("Dangerous to move in the dark! ");
- nl = Rooms[MyLoc].Exits[no - 1];
+ nl = _rooms[MY_LOC]._exits[no - 1];
if (nl != 0) {
- MyLoc = nl;
+ MY_LOC = nl;
return 0;
}
if (d) {
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("You fell down and broke your neck. ");
else
output("I fell down and broke my neck. ");
glk_exit();
}
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("You can't go in that direction. ");
else
output("I can't go in that direction. ");
@@ -1056,9 +1056,9 @@ int Scott::performActions(int vb, int no) {
}
fl = -1;
- while (ct <= GameHeader.NumActions) {
+ while (ct <= _gameHeader._numActions) {
int vv, nv;
- vv = Actions[ct].Vocab;
+ vv = _actions[ct]._vocab;
// Think this is now right. If a line we run has an action73
// run all following lines with vocab of 0,0
if (vb != 0 && (doagain && vv != 0))
@@ -1068,7 +1068,7 @@ int Scott::performActions(int vb, int no) {
break;
nv = vv % 150;
vv /= 150;
- if ((vv == vb) || (doagain && Actions[ct].Vocab == 0)) {
+ if ((vv == vb) || (doagain && _actions[ct]._vocab == 0)) {
if ((vv == 0 && randomPercent(nv)) || doagain ||
(vv != 0 && (nv == no || nv == 0))) {
int f2;
@@ -1086,22 +1086,22 @@ int Scott::performActions(int vb, int no) {
}
ct++;
- // Previously this did not check ct against GameHeader.NumActions and would read
- // past the end of Actions. I don't know what should happen on the last action,
+ // Previously this did not check ct against _gameHeader._numActions and would read
+ // past the end of _actions. I don't know what should happen on the last action,
// but doing nothing is better than reading one past the end.
// --Chris
- if (ct <= GameHeader.NumActions && Actions[ct].Vocab != 0)
+ if (ct <= _gameHeader._numActions && _actions[ct]._vocab != 0)
doagain = 0;
}
if (fl != 0 && disable_sysfunc == 0) {
int item;
- if (Items[LIGHT_SOURCE].Location == MyLoc ||
- Items[LIGHT_SOURCE].Location == CARRIED)
+ if (_items[LIGHT_SOURCE]._location == MY_LOC ||
+ _items[LIGHT_SOURCE]._location == CARRIED)
d = 0;
if (vb == 10 || vb == 18) {
// Yes they really _are_ hardcoded values
if (vb == 10) {
- if (xstrcasecmp(NounText, "ALL") == 0) {
+ if (xstrcasecmp(_nounText, "ALL") == 0) {
int i = 0;
int f = 0;
@@ -1109,21 +1109,21 @@ int Scott::performActions(int vb, int no) {
output("It is dark.\n");
return 0;
}
- while (i <= GameHeader.NumItems) {
- if (Items[i].Location == MyLoc && Items[i].AutoGet != nullptr && Items[i].AutoGet[0] != '*') {
- no = whichWord(Items[i].AutoGet.c_str(), Nouns);
+ while (i <= _gameHeader._numItems) {
+ if (_items[i]._location == MY_LOC && _items[i]._autoGet != nullptr && _items[i]._autoGet[0] != '*') {
+ no = whichWord(_items[i]._autoGet.c_str(), _nouns);
disable_sysfunc = 1; // Don't recurse into auto get !
performActions(vb, no); // Recursively check each items table code
disable_sysfunc = 0;
- if (countCarried() == GameHeader.MaxCarry) {
- if (Options & YOUARE)
+ if (countCarried() == _gameHeader._maxCarry) {
+ if (_options & YOUARE)
output("You are carrying too much. ");
else
output("I've too much to carry. ");
return 0;
}
- Items[i].Location = CARRIED;
- output(Items[i].Text);
+ _items[i]._location = CARRIED;
+ output(_items[i]._text);
output(": O.K.\n");
f = 1;
}
@@ -1137,38 +1137,38 @@ int Scott::performActions(int vb, int no) {
output("What ? ");
return 0;
}
- if (countCarried() == GameHeader.MaxCarry) {
- if (Options & YOUARE)
+ if (countCarried() == _gameHeader._maxCarry) {
+ if (_options & YOUARE)
output("You are carrying too much. ");
else
output("I've too much to carry. ");
return 0;
}
- item = matchUpItem(NounText, MyLoc);
+ item = matchUpItem(_nounText, MY_LOC);
if (item == -1) {
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("It is beyond your power to do that. ");
else
output("It's beyond my power to do that. ");
return 0;
}
- Items[item].Location = CARRIED;
+ _items[item]._location = CARRIED;
output("O.K. ");
return 0;
}
if (vb == 18) {
- if (xstrcasecmp(NounText, "ALL") == 0) {
+ if (xstrcasecmp(_nounText, "ALL") == 0) {
int i = 0;
int f = 0;
- while (i <= GameHeader.NumItems) {
- if (Items[i].Location == CARRIED && !Items[i].AutoGet.empty()
- && !Items[i].AutoGet.hasPrefix("*")) {
- no = whichWord(Items[i].AutoGet.c_str(), Nouns);
+ while (i <= _gameHeader._numItems) {
+ if (_items[i]._location == CARRIED && !_items[i]._autoGet.empty()
+ && !_items[i]._autoGet.hasPrefix("*")) {
+ no = whichWord(_items[i]._autoGet.c_str(), _nouns);
disable_sysfunc = 1;
performActions(vb, no);
disable_sysfunc = 0;
- Items[i].Location = MyLoc;
- output(Items[i].Text);
+ _items[i]._location = MY_LOC;
+ output(_items[i]._text);
output(": O.K.\n");
f = 1;
}
@@ -1182,15 +1182,15 @@ int Scott::performActions(int vb, int no) {
output("What ? ");
return 0;
}
- item = matchUpItem(NounText, CARRIED);
+ item = matchUpItem(_nounText, CARRIED);
if (item == -1) {
- if (Options & YOUARE)
+ if (_options & YOUARE)
output("It's beyond your power to do that.\n");
else
output("It's beyond my power to do that.\n");
return 0;
}
- Items[item].Location = MyLoc;
+ _items[item]._location = MY_LOC;
output("O.K. ");
return 0;
}
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 188ddd7..955ebb9 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -48,62 +48,62 @@ enum GameOption {
};
#define TRS80_LINE "\n<------------------------------------------------------------>\n"
-#define MyLoc (GameHeader.PlayerRoom)
+#define MY_LOC (_gameHeader._playerRoom)
struct Header {
- int Unknown;
- int NumItems;
- int NumActions;
- int NumWords; ///< Smaller of verb/noun is padded to same size
- int NumRooms;
- int MaxCarry;
- int PlayerRoom;
- int Treasures;
- int WordLength;
- int LightTime;
- int NumMessages;
- int TreasureRoom;
-
- Header() : Unknown(0), NumItems(0), NumActions(0), NumWords(0), NumRooms(0),
- MaxCarry(0), PlayerRoom(0), Treasures(0), WordLength(0), LightTime(0),
- NumMessages(0), TreasureRoom(0) {}
+ int _unknown;
+ int _numItems;
+ int _numActions;
+ int _numWords; ///< Smaller of verb/noun is padded to same size
+ int _numRooms;
+ int _maxCarry;
+ int _playerRoom;
+ int _treasures;
+ int _wordLength;
+ int _lightTime;
+ int _numMessages;
+ int _treasureRoom;
+
+ Header() : _unknown(0), _numItems(0), _numActions(0), _numWords(0), _numRooms(0),
+ _maxCarry(0), _playerRoom(0), _treasures(0), _wordLength(0), _lightTime(0),
+ _numMessages(0), _treasureRoom(0) {}
};
struct Action {
- uint Vocab;
- uint Condition[5];
- uint action[2];
+ uint _vocab;
+ uint _condition[5];
+ uint _action[2];
- Action() : Vocab(0) {
- Common::fill(&Condition[0], &Condition[5], 0);
- Common::fill(&action[0], &action[2], 0);
+ Action() : _vocab(0) {
+ Common::fill(&_condition[0], &_condition[5], 0);
+ Common::fill(&_action[0], &_action[2], 0);
}
};
struct Room {
- Common::String Text;
- short Exits[6];
+ Common::String _text;
+ short _exits[6];
Room() {
- Common::fill(&Exits[0], &Exits[6], 0);
+ Common::fill(&_exits[0], &_exits[6], 0);
}
};
struct Item {
- Common::String Text;
- byte Location;
- byte InitialLoc;
- Common::String AutoGet;
+ Common::String _text;
+ byte _location;
+ byte _initialLoc;
+ Common::String _autoGet;
- Item() : Location(0), InitialLoc(0) {}
+ Item() : _location(0), _initialLoc(0) {}
};
struct Tail {
- int Version;
- int AdventureNumber;
- int Unknown;
+ int _version;
+ int _adventureNumber;
+ int _unknown;
- Tail() : Version(0), AdventureNumber(0), Unknown(0) {}
+ Tail() : _version(0), _adventureNumber(0), _unknown(0) {}
};
/**
@@ -111,27 +111,27 @@ struct Tail {
*/
class Scott : public GlkAPI {
private:
- Header GameHeader;
- Common::Array<Item> Items;
- Common::Array<Room> Rooms;
- Common::StringArray Verbs;
- Common::StringArray Nouns;
- Common::StringArray Messages;
- Common::Array<Action> Actions;
- int LightRefill;
- char NounText[16];
- int Counters[16]; ///< Range unknown
- int CurrentCounter;
- int SavedRoom;
- int RoomSaved[16]; ///< Range unknown
- int Options; ///< Option flags set
- int Width; ///< Terminal width
- int TopHeight; ///< Height of top window
-
- bool split_screen;
- winid_t Bottom, Top;
- uint32 BitFlags; ///< Might be >32 flags - I haven't seen >32 yet
- int _saveSlot; ///< Save slot when loading savegame from launcher
+ Header _gameHeader;
+ Common::Array<Item> _items;
+ Common::Array<Room> _rooms;
+ Common::StringArray _verbs;
+ Common::StringArray _nouns;
+ Common::StringArray _messages;
+ Common::Array<Action> _actions;
+ int _lightRefill;
+ char _nounText[16];
+ int _counters[16]; ///< Range unknown
+ int _currentCounter;
+ int _savedRoom;
+ int _roomSaved[16]; ///< Range unknown
+ int _options; ///< Option flags set
+ int _width; ///< Terminal width
+ int _topHeight; ///< Height of top window
+
+ bool _splitScreen;
+ winid_t _bottomWindow, _topWindow;
+ uint32 _bitFlags; ///< Might be >32 flags - I haven't seen >32 yet
+ int _saveSlot; ///< Save slot when loading savegame from launcher
private:
/**
* Initialization code
Commit: fc2b1edd1fd6227e9495ada72840e9434f9095fa
https://github.com/scummvm/scummvm/commit/fc2b1edd1fd6227e9495ada72840e9434f9095fa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Extra returns/exits after glk_exit is called
Changed paths:
engines/glk/scott/scott.cpp
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index ff014e7..77fd9cc 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -39,8 +39,10 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
initialize();
_bottomWindow = glk_window_open(0, 0, 0, wintype_TextBuffer, 1);
- if (_bottomWindow == nullptr)
+ if (_bottomWindow == nullptr) {
glk_exit();
+ return;
+ }
glk_set_window(_bottomWindow);
if (_options & TRS80_STYLE) {
@@ -74,6 +76,8 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
glk_tick();
performActions(0, 0);
+ if (shouldQuit())
+ break;
if (_saveSlot >= 0) {
// Load any savegame during startup
@@ -1019,7 +1023,7 @@ doneit:
}
int Scott::performActions(int vb, int no) {
- static int disable_sysfunc = 0; // Recursion lock
+ static bool disableSysFunc = false; // Recursion lock
int d = _bitFlags & (1 << DARKBIT);
int ct = 0;
@@ -1047,6 +1051,7 @@ int Scott::performActions(int vb, int no) {
else
output("I fell down and broke my neck. ");
glk_exit();
+ return 0;
}
if (_options & YOUARE)
output("You can't go in that direction. ");
@@ -1093,7 +1098,7 @@ int Scott::performActions(int vb, int no) {
if (ct <= _gameHeader._numActions && _actions[ct]._vocab != 0)
doagain = 0;
}
- if (fl != 0 && disable_sysfunc == 0) {
+ if (fl != 0 && disableSysFunc == 0) {
int item;
if (_items[LIGHT_SOURCE]._location == MY_LOC ||
_items[LIGHT_SOURCE]._location == CARRIED)
@@ -1112,9 +1117,12 @@ int Scott::performActions(int vb, int no) {
while (i <= _gameHeader._numItems) {
if (_items[i]._location == MY_LOC && _items[i]._autoGet != nullptr && _items[i]._autoGet[0] != '*') {
no = whichWord(_items[i]._autoGet.c_str(), _nouns);
- disable_sysfunc = 1; // Don't recurse into auto get !
- performActions(vb, no); // Recursively check each items table code
- disable_sysfunc = 0;
+ disableSysFunc = true; // Don't recurse into auto get !
+ performActions(vb, no); // Recursively check each items table code
+ disableSysFunc = false;
+ if (shouldQuit())
+ return 0;
+
if (countCarried() == _gameHeader._maxCarry) {
if (_options & YOUARE)
output("You are carrying too much. ");
@@ -1164,9 +1172,12 @@ int Scott::performActions(int vb, int no) {
if (_items[i]._location == CARRIED && !_items[i]._autoGet.empty()
&& !_items[i]._autoGet.hasPrefix("*")) {
no = whichWord(_items[i]._autoGet.c_str(), _nouns);
- disable_sysfunc = 1;
+ disableSysFunc = true;
performActions(vb, no);
- disable_sysfunc = 0;
+ disableSysFunc = false;
+ if (shouldQuit())
+ return 0;
+
_items[i]._location = MY_LOC;
output(_items[i]._text);
output(": O.K.\n");
Commit: bc4df65bd7b81dc5cec98f6681e9d83f7c22dc8e
https://github.com/scummvm/scummvm/commit/bc4df65bd7b81dc5cec98f6681e9d83f7c22dc8e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix gcc compiler warnings
Changed paths:
engines/glk/blorb.cpp
engines/glk/frotz/detection.cpp
engines/glk/frotz/glk_interface.h
engines/glk/frotz/mem.h
engines/glk/frotz/processor.h
engines/glk/frotz/processor_screen.cpp
engines/glk/glk_api.h
engines/glk/window_graphics.cpp
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index e298e1c..ed730bf 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -35,7 +35,7 @@ struct giblorb_chunkdesc_struct {
glui32 startpos; ///< start of chunk header
glui32 datpos; ///< start of data (either startpos or startpos+8)
- void *ptr; ///< pointer to malloc'd data, if loaded
+ byte *ptr; ///< pointer to malloc'd data, if loaded
int auxdatnum; ///< entry in the auxsound/auxpict array; -1 if none. This only applies to chunks that represent resources;
};
typedef giblorb_chunkdesc_struct giblorb_chunkdesc_t;
@@ -406,7 +406,7 @@ giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
glui32 method, giblorb_result_t *res, glui32 chunknum) {
giblorb_chunkdesc_t *chu;
- if (chunknum < 0 || chunknum >= map->numchunks)
+ if (chunknum >= map->numchunks)
return giblorb_err_NotFound;
chu = &(map->chunks[chunknum]);
@@ -451,7 +451,7 @@ giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
giblorb_chunkdesc_t *chu;
- if (chunknum < 0 || chunknum >= map->numchunks)
+ if (chunknum >= map->numchunks)
return giblorb_err_NotFound;
chu = &(map->chunks[chunknum]);
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 61d9a14..29eb5d7 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -93,7 +93,7 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
if (dot)
fname = Common::String(fname.c_str(), dot);
- debug("ENTRY0(\"%s\", \"%s-%s\", \"%s\", %u),",
+ debug("ENTRY0(\"%s\", \"%s-%s\", \"%s\", %lu),",
folderName.c_str(), fname.c_str(), serial, md5.c_str(), filesize);
}
const PlainGameDescriptor &desc = FROTZ_GAME_LIST[0];
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index c18ebb8..0103f88 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -174,6 +174,7 @@ public:
* Constructor
*/
GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc);
+ virtual ~GlkInterface() {}
/**
* Initialization
diff --git a/engines/glk/frotz/mem.h b/engines/glk/frotz/mem.h
index 43b2727..372c7e7 100644
--- a/engines/glk/frotz/mem.h
+++ b/engines/glk/frotz/mem.h
@@ -128,8 +128,8 @@ public:
zbyte h_screen_cols;
zword h_screen_width;
zword h_screen_height;
- zbyte h_font_height = 1;
- zbyte h_font_width = 1;
+ zbyte h_font_height;
+ zbyte h_font_width;
zword h_functions_offset;
zword h_strings_offset;
zbyte h_default_background;
@@ -267,6 +267,7 @@ public:
* Constructor
*/
Mem();
+ virtual ~Mem() {}
/**
* Initialize
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index 1a1dfc5..7c8944f 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -1529,6 +1529,7 @@ public:
* Constructor
*/
Processor(OSystem *syst, const GlkGameDescription &gameDesc);
+ virtual ~Processor() {}
/**
* Initialization
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 6c25ef9..2e07b47 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -74,7 +74,7 @@ void Processor::screen_char(zchar c) {
cury ++;
} else {
if (cury == 1) {
- if (curx <= ((sizeof statusline / sizeof(zchar)) - 1)) {
+ if (curx <= (int)((sizeof statusline / sizeof(zchar)) - 1)) {
statusline[curx - 1] = c;
statusline[curx] = 0;
}
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index 8a37df1..400f3c0 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -44,6 +44,7 @@ public:
* Constructor
*/
GlkAPI(OSystem *syst, const GlkGameDescription &gameDesc);
+ virtual ~GlkAPI() {}
void glk_exit(void);
void glk_set_interrupt_handler(void(*func)(void));
diff --git a/engines/glk/window_graphics.cpp b/engines/glk/window_graphics.cpp
index e80fc8e..f81313e 100644
--- a/engines/glk/window_graphics.cpp
+++ b/engines/glk/window_graphics.cpp
@@ -40,15 +40,12 @@ GraphicsWindow::~GraphicsWindow() {
void GraphicsWindow::rearrange(const Rect &box) {
int newwid, newhgt;
int bothwid, bothhgt;
- int oldw, oldh;
Graphics::ManagedSurface *newSurface;
_bbox = box;
newwid = box.width();
newhgt = box.height();
- oldw = _w;
- oldh = _h;
if (newwid <= 0 || newhgt <= 0) {
_w = 0;
Commit: e344809eeac75e9dbfd943015c083001a2628440
https://github.com/scummvm/scummvm/commit/e344809eeac75e9dbfd943015c083001a2628440
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix gcc warnings, adding extra method comments
Changed paths:
engines/glk/frotz/glk_interface.h
engines/glk/frotz/mem.cpp
engines/glk/frotz/processor.h
engines/glk/frotz/processor_buffer.cpp
engines/glk/frotz/processor_screen.cpp
engines/glk/frotz/processor_streams.cpp
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index 0103f88..5e2fa62 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -94,10 +94,33 @@ public:
bool _soundLocked;
bool _soundPlaying;
protected:
+ /**
+ * Return the length of the character in screen units.
+ */
int os_char_width(zchar z);
+
+ /**
+ * Calculate the length of a word in screen units. Apart from letters,
+ * the word may contain special codes:
+ *
+ * ZC_NEW_STYLE - next character is a new text style
+ * ZC_NEW_FONT - next character is a new font
+ */
int os_string_width(const zchar *s);
+
+ /**
+ * Return the length of a string
+ */
int os_string_length(zchar *s);
+
+ /**
+ * Prepare a sample for playing
+ */
void os_prepare_sample(int a);
+
+ /**
+ * Signal that a given sample is finished with
+ */
void os_finish_with_sample(int a);
/**
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index 378e496..6ee6781 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -174,10 +174,10 @@ void Mem::initializeStoryFile() {
}
void Mem::initializeUndo() {
- void *reserved = nullptr;
+ byte *reserved = nullptr;
if (reserve_mem != 0) {
- if ((reserved = malloc(reserve_mem)) == NULL)
+ if ((reserved = new byte[reserve_mem]) == nullptr)
return;
}
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index 7c8944f..5f61a2e 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -314,11 +314,32 @@ private:
* @{
*/
+ /**
+ * Start printing a so-called debugging message. The contents of the
+ * message are passed to the message stream, a Frotz specific output
+ * stream with maximum priority.
+ */
+ void screen_mssg_on();
+
+ /**
+ * Stop printing a "debugging" message
+ */
+ void screen_mssg_off();
+
+ /**
+ * Display a single character on the screen.
+ */
void screen_char(zchar c);
+
+ /**
+ * Print a newline to the screen.
+ */
void screen_new_line();
+
+ /**
+ * Print a newline to the screen.
+ */
void screen_word(const zchar *s);
- void screen_mssg_on();
- void screen_mssg_off();
/**@}*/
diff --git a/engines/glk/frotz/processor_buffer.cpp b/engines/glk/frotz/processor_buffer.cpp
index c4eaeaa..b8b37ed 100644
--- a/engines/glk/frotz/processor_buffer.cpp
+++ b/engines/glk/frotz/processor_buffer.cpp
@@ -158,7 +158,7 @@ void Processor::runtimeError(ErrorCode errNum) {
if (_err_report_mode == ERR_REPORT_FATAL
|| (!_ignore_errors && errNum <= ERR_MAX_FATAL)) {
flush_buffer();
- error(ERR_MESSAGES[errNum - 1]);
+ error("%s", ERR_MESSAGES[errNum - 1]);
return;
}
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 2e07b47..c0d8ca1 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -122,7 +122,6 @@ void Processor::screen_word(const zchar *s) {
}
}
-
void Processor::z_buffer_mode() {
// No implementation
}
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index 93b9c0b..ebeb303 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -174,7 +174,7 @@ zchar Processor::stream_read_input(int max, zchar *buf, zword timeout, zword rou
// Remove initial input from the transscript file or from the screen
if (ostream_script && enable_scripting && !no_scripting)
- script_erase_input(buf);
+ script_erase_input(buf);
// Read input line from current input stream
continue_input:
Commit: 3d34cd151f9f56d24299eba4372e71e4a6b26131
https://github.com/scummvm/scummvm/commit/3d34cd151f9f56d24299eba4372e71e4a6b26131
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Remove unused local variable
Changed paths:
engines/glk/frotz/processor_streams.cpp
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index ebeb303..091165e 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -165,11 +165,6 @@ continue_input:
zchar Processor::stream_read_input(int max, zchar *buf, zword timeout, zword routine,
bool hot_keys, bool no_scripting) {
zchar key = ZC_BAD;
- bool no_scrollback = no_scripting;
-
- if (h_version == V6 && _storyId == UNKNOWN && !ostream_script)
- no_scrollback = false;
-
flush_buffer();
// Remove initial input from the transscript file or from the screen
Commit: 4b011b2f1cfdc3aac0468248f4feb9faea3501a2
https://github.com/scummvm/scummvm/commit/4b011b2f1cfdc3aac0468248f4feb9faea3501a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Freeing of data on exit
Changed paths:
engines/glk/selection.cpp
engines/glk/selection.h
engines/glk/windows.cpp
engines/glk/windows.h
diff --git a/engines/glk/selection.cpp b/engines/glk/selection.cpp
index 566ae65..f251171 100644
--- a/engines/glk/selection.cpp
+++ b/engines/glk/selection.cpp
@@ -65,14 +65,21 @@ WindowMask::WindowMask() : _hor(0), _ver(0), _links(nullptr) {
resize(g_system->getWidth(), g_system->getHeight());
}
-void WindowMask::resize(size_t x, size_t y) {
- // Deallocate old storage
+WindowMask::~WindowMask() {
+ clear();
+}
+
+void WindowMask::clear() {
for (size_t i = 0; i < _hor; i++) {
if (_links[i])
delete _links[i];
}
delete _links;
+}
+
+void WindowMask::resize(size_t x, size_t y) {
+ clear();
_hor = x + 1;
_ver = y + 1;
diff --git a/engines/glk/selection.h b/engines/glk/selection.h
index 4497d68..10d6d5c 100644
--- a/engines/glk/selection.h
+++ b/engines/glk/selection.h
@@ -63,6 +63,11 @@ public:
* Manages hyperlinks for the screen
*/
class WindowMask {
+private:
+ /**
+ * Clear the links data
+ */
+ void clear();
public:
size_t _hor, _ver;
glui32 **_links;
@@ -75,6 +80,11 @@ public:
WindowMask();
/**
+ * Destructor
+ */
+ ~WindowMask();
+
+ /**
* Resize the links array
*/
void resize(size_t x, size_t y);
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
index 02298ad..ce1929f 100644
--- a/engines/glk/windows.cpp
+++ b/engines/glk/windows.cpp
@@ -70,6 +70,10 @@ Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullpt
_zcolor_Bright[0] = _zcolor_Bright[1] = _zcolor_Bright[2] = 0;
}
+Windows::~Windows() {
+ delete _rootWin;
+}
+
Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
glui32 wintype, glui32 rock) {
Window *newwin, *oldparent;
diff --git a/engines/glk/windows.h b/engines/glk/windows.h
index 98f0d2d..7abb9e5 100644
--- a/engines/glk/windows.h
+++ b/engines/glk/windows.h
@@ -152,6 +152,11 @@ public:
Windows(Graphics::Screen *screen);
/**
+ * Destructor
+ */
+ ~Windows();
+
+ /**
* Open a new window
*/
Window *windowOpen(Window *splitwin, glui32 method, glui32 size,
Commit: 813918aaba8c2f86d55c4b256da7ee79c155b12f
https://github.com/scummvm/scummvm/commit/813918aaba8c2f86d55c4b256da7ee79c155b12f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Memory leak fixes
Changed paths:
engines/glk/selection.cpp
engines/glk/streams.cpp
engines/glk/streams.h
diff --git a/engines/glk/selection.cpp b/engines/glk/selection.cpp
index f251171..9109776 100644
--- a/engines/glk/selection.cpp
+++ b/engines/glk/selection.cpp
@@ -72,10 +72,10 @@ WindowMask::~WindowMask() {
void WindowMask::clear() {
for (size_t i = 0; i < _hor; i++) {
if (_links[i])
- delete _links[i];
+ delete[] _links[i];
}
- delete _links;
+ delete[] _links;
}
void WindowMask::resize(size_t x, size_t y) {
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index 801cd54..cd7130f 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -75,6 +75,10 @@ void Stream::setReverseVideo(bool reverse) {
/*--------------------------------------------------------------------------*/
+WindowStream::~WindowStream() {
+ _window->_stream = nullptr;
+}
+
void WindowStream::close(StreamResult *result) {
warning("cannot close window stream");
}
@@ -1407,8 +1411,10 @@ Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) {
}
Streams::~Streams() {
- while (_streamList)
- delete _streamList;
+ for (Stream *currStream = _streamList, *nextStream; currStream; currStream = nextStream) {
+ nextStream = currStream->_next;
+ delete currStream;
+ }
}
FileStream *Streams::openFileStream(frefid_t fref, glui32 fmode, glui32 rock, bool unicode) {
diff --git a/engines/glk/streams.h b/engines/glk/streams.h
index 32bde70..22a0a59 100644
--- a/engines/glk/streams.h
+++ b/engines/glk/streams.h
@@ -300,6 +300,11 @@ public:
Stream(streams, false, true, rock, unicode), _window(window) {}
/**
+ * Destructor
+ */
+ virtual ~WindowStream();
+
+ /**
* Close the stream
*/
virtual void close(StreamResult *result = nullptr);
Commit: 326f69136eb4fee72391a8175ad722a317f84ca6
https://github.com/scummvm/scummvm/commit/326f69136eb4fee72391a8175ad722a317f84ca6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Fix memory corruption loading game data
Changed paths:
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 77fd9cc..fed31f0 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -104,7 +104,7 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
}
// Brian Howarth games seem to use -1 for forever
- if (_items[LIGHT_SOURCE]._location/*==-1*/ != DESTROYED && _gameHeader._lightTime != -1) {
+ if (_items[LIGHT_SOURCE]._location != DESTROYED && _gameHeader._lightTime != -1) {
_gameHeader._lightTime--;
if (_gameHeader._lightTime < 1) {
_bitFlags |= (1 << LIGHTOUTBIT);
@@ -282,9 +282,6 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
int unused, ni, na, nw, nr, mc, pr, tr, wl, lt, mn, trm;
int ct;
int lo;
- Action *ap;
- Room *rp;
- Item *ip;
// Load the header
readInts(f, 12, &unused, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
@@ -309,89 +306,66 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
_gameHeader._treasureRoom = trm;
// Load the actions
- ct = 0;
- ap = &_actions[0];
if (loud)
debug("Reading %d actions.", na);
- while (ct < na + 1) {
+
+ for (uint idx = 0; idx < na + 1; ++idx) {
+ Action &a = _actions[idx];
readInts(f, 8,
- &ap->_vocab,
- &ap->_condition[0],
- &ap->_condition[1],
- &ap->_condition[2],
- &ap->_condition[3],
- &ap->_condition[4],
- &ap->_action[0],
- &ap->_action[1]);
- ap++;
- ct++;
+ &a._vocab, &a._condition[0], &a._condition[1], &a._condition[2],
+ &a._condition[3], &a._condition[4], &a._action[0], &a._action[1]);
}
- ct = 0;
if (loud)
debug("Reading %d word pairs.", nw);
- while (ct < nw + 1) {
- _verbs[ct] = readString(f);
- _nouns[ct] = readString(f);
- ct++;
+ for (int idx = 0; idx < nw + 1; ++idx) {
+ _verbs[idx] = readString(f);
+ _nouns[idx] = readString(f);
}
- ct = 0;
- rp = &_rooms[0];
+
if (loud)
debug("Reading %d rooms.", nr);
- while (ct < nr + 1) {
- readInts(f, 6,
- &rp->_exits[0], &rp->_exits[1], &rp->_exits[2],
- &rp->_exits[3], &rp->_exits[4], &rp->_exits[5]);
-
- rp->_text = readString(f);
- ct++;
- rp++;
+ for (int idx = 0; idx < nr + 1; ++idx) {
+ Room &r = _rooms[idx];
+ readInts(f, 6, &r._exits[0], &r._exits[1], &r._exits[2],
+ &r._exits[3], &r._exits[4], &r._exits[5]);
+ r._text = readString(f);
}
- ct = 0;
if (loud)
debug("Reading %d messages.", mn);
- while (ct < mn + 1) {
- _messages[ct] = readString(f);
- ct++;
- }
+ for (int idx = 0; idx < mn + 1; ++idx)
+ _messages[idx] = readString(f);
- ct = 0;
if (loud)
debug("Reading %d items.", ni);
- ip = &_items[0];
- while (ct < ni + 1) {
- ip->_text = readString(f);
+ for (int idx = 0; idx < ni + 1; ++idx) {
+ Item &i = _items[idx];
+ i._text = readString(f);
- const char *p = strchr(ip->_text.c_str(), '/');
+ const char *p = strchr(i._text.c_str(), '/');
if (p) {
- ip->_autoGet = Common::String(p);
+ i._autoGet = Common::String(p);
// Some games use // to mean no auto get/drop word!
- if (!ip->_autoGet.hasPrefix("//") && !ip->_autoGet.hasPrefix("/*")) {
- ip->_text = Common::String(ip->_text.c_str(), p);
- ip->_autoGet.deleteChar(0);
+ if (!i._autoGet.hasPrefix("//") && !i._autoGet.hasPrefix("/*")) {
+ i._text = Common::String(i._text.c_str(), p);
+ i._autoGet.deleteChar(0);
- const char *t = strchr(ip->_autoGet.c_str(), '/');
+ const char *t = strchr(i._autoGet.c_str(), '/');
if (t)
- ip->_autoGet = Common::String(ip->_autoGet.c_str(), t);
+ i._autoGet = Common::String(i._autoGet.c_str(), t);
}
}
readInts(f, 1, &lo);
- ip->_location = (unsigned char)lo;
- ip->_initialLoc = ip->_location;
- ip++;
- ct++;
+ i._location = (unsigned char)lo;
+ i._initialLoc = i._location;
}
- ct = 0;
// Skip Comment Strings
- while (ct < na + 1) {
+ for (int idx = 0; idx < na + 1; ++idx)
readString(f);
- ct++;
- }
readInts(f, 1, &ct);
if (loud)
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 955ebb9..4741892 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -70,9 +70,9 @@ struct Header {
};
struct Action {
- uint _vocab;
- uint _condition[5];
- uint _action[2];
+ int _vocab;
+ int _condition[5];
+ int _action[2];
Action() : _vocab(0) {
Common::fill(&_condition[0], &_condition[5], 0);
@@ -82,7 +82,7 @@ struct Action {
struct Room {
Common::String _text;
- short _exits[6];
+ int _exits[6];
Room() {
Common::fill(&_exits[0], &_exits[6], 0);
Commit: b05a16a0ad0dcc2881aeda81e0d1a84a752eccab
https://github.com/scummvm/scummvm/commit/b05a16a0ad0dcc2881aeda81e0d1a84a752eccab
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Centralizing more of the savegame code in GlkEngine
Changed paths:
engines/glk/frotz/frotz.cpp
engines/glk/frotz/frotz.h
engines/glk/frotz/processor_streams.cpp
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
engines/glk/streams.h
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index a6371b6..344aa92 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -84,13 +84,174 @@ void Frotz::initialize() {
z_restart();
}
-Common::Error Frotz::loadGameState(int slot) {
- // TODO
+Common::Error Frotz::saveGameData(strid_t file) {
+#ifdef TODO
+ long pc;
+ zword addr;
+ zword nsp, nfp;
+ int skip;
+ int i;
+
+ /* Open game file */
+
+ if ((gfp = frotzopenprompt(FILE_SAVE)) == nullptr)
+ goto finished;
+
+ if (_save_quetzal) {
+ success = save_quetzal(gfp, story_fp, blorb_ofs);
+ }
+ else {
+ /* Write game file */
+
+ fputc((int)hi(h_release), gfp);
+ fputc((int)lo(h_release), gfp);
+ fputc((int)hi(h_checksum), gfp);
+ fputc((int)lo(h_checksum), gfp);
+
+ GET_PC(pc)
+
+ fputc((int)(pc >> 16) & 0xff, gfp);
+ fputc((int)(pc >> 8) & 0xff, gfp);
+ fputc((int)(pc)& 0xff, gfp);
+
+ nsp = (int)(_sp - _stack);
+ nfp = (int)(_fp - _stack);
+
+ fputc((int)hi(nsp), gfp);
+ fputc((int)lo(nsp), gfp);
+ fputc((int)hi(nfp), gfp);
+ fputc((int)lo(nfp), gfp);
+
+ for (i = nsp; i < STACK_SIZE; i++) {
+ fputc((int)hi(_stack[i]), gfp);
+ fputc((int)lo(_stack[i]), gfp);
+ }
+
+ fseek(story_fp, blorb_ofs, SEEK_SET);
+
+ for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
+ if (zmp[addr] != fgetc(story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
+ fputc(skip, gfp);
+ fputc(zmp[addr], gfp);
+ skip = 0;
+ }
+ else skip++;
+ }
+
+ /* Close game file and check for errors */
+
+ if (fclose(gfp) == EOF || ferror(story_fp)) {
+ print_string("Error writing save file\n");
+ goto finished;
+ }
+
+ /* Success */
+
+ success = 1;
+#endif
return Common::kNoError;
}
-Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
- // TODO
+Common::Error Frotz::loadGameData(strid_t file) {
+#ifdef TODO
+ long pc;
+ zword release;
+ zword addr;
+ int i;
+
+ /* Open game file */
+
+ if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
+ goto finished;
+
+ if (_save_quetzal) {
+ success = restore_quetzal (gfp, story_fp, blorb_ofs);
+
+ } else {
+ /* Load game file */
+
+ release = (unsigned) fgetc (gfp) << 8;
+ release |= fgetc (gfp);
+
+ () fgetc (gfp);
+ () fgetc (gfp);
+
+ /* Check the release number */
+
+ if (release == h_release) {
+
+ pc = (long) fgetc (gfp) << 16;
+ pc |= (unsigned) fgetc (gfp) << 8;
+ pc |= fgetc (gfp);
+
+ SET_PC (pc);
+
+ _sp = _stack + (fgetc (gfp) << 8);
+ _sp += fgetc (gfp);
+ _fp = _stack + (fgetc (gfp) << 8);
+ _fp += fgetc (gfp);
+
+ for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
+ _stack[i] = (unsigned) fgetc (gfp) << 8;
+ _stack[i] |= fgetc (gfp);
+ }
+
+ fseek (story_fp, blorb_ofs, SEEK_SET);
+
+ for (addr = 0; addr < h_dynamic_size; addr++) {
+ int skip = fgetc (gfp);
+ for (i = 0; i < skip; i++)
+ zmp[addr++] = fgetc (story_fp);
+ zmp[addr] = fgetc (gfp);
+ () fgetc (story_fp);
+ }
+
+ /* Check for errors */
+
+ if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
+ success = -1;
+ else
+
+ /* Success */
+
+ success = 2;
+
+ } else print_string ("Invalid save file\n");
+ }
+
+ if ((short) success >= 0) {
+
+ /* Close game file */
+
+ fclose (gfp);
+
+ if ((short) success > 0) {
+ zbyte old_screen_rows;
+ zbyte old_screen_cols;
+
+ /* In V3, reset the upper window. */
+ if (h_version == V3)
+ split_window (0);
+
+ LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
+ LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
+
+ /* Reload cached header fields. */
+ restart_header ();
+
+ /*
+ * Since QUETZAL files may be saved on many different machines,
+ * the screen sizes may vary a lot. Erasing the status window
+ * seems to cover up most of the resulting badness.
+ */
+ if (h_version > V3 && h_version != V6
+ && (h_screen_rows != old_screen_rows
+ || h_screen_cols != old_screen_cols))
+ erase_window (1);
+ }
+ } else
+ os_fatal ("Error reading save file");
+#endif
return Common::kNoError;
}
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index e45abc0..00aeb59 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -54,14 +54,14 @@ public:
virtual void runGame(Common::SeekableReadStream *gameFile) override;
/**
- * Load a savegame
+ * Load a savegame from the passed stream
*/
- virtual Common::Error loadGameState(int slot) override;
+ virtual Common::Error loadGameData(strid_t file) override;
/**
- * Save the game
+ * Save the game to the passed stream
*/
- virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+ virtual Common::Error saveGameData(strid_t file) override;
};
extern Frotz *g_vm;
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index 091165e..cbef38a 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -545,227 +545,54 @@ void Processor::z_restart() {
}
void Processor::z_save() {
-#ifdef TODO
bool success = false;
if (zargc != 0) {
// Open auxilary file
frefid_t ref = glk_fileref_create_by_prompt(fileusage_Data | fileusage_BinaryMode,
filemode_Write, 0);
- if (ref == nullptr)
- goto finished;
+ if (ref != nullptr) {
+ // Write data
+ strid_t f = glk_stream_open_file(ref, filemode_Write);
- // Write data
- strid_t f = glk_stream_open_file(ref, filemode_Write);
+ glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
- glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
-
- glk_stream_close(f);
-
- } else {
- long pc;
- zword addr;
- zword nsp, nfp;
- int skip;
- int i;
-
- /* Open game file */
-
- if ((gfp = frotzopenprompt (FILE_SAVE)) == nullptr)
- goto finished;
-
- if (_save_quetzal) {
- success = save_quetzal (gfp, story_fp, blorb_ofs);
- } else {
- /* Write game file */
-
- fputc ((int) hi (h_release), gfp);
- fputc ((int) lo (h_release), gfp);
- fputc ((int) hi (h_checksum), gfp);
- fputc ((int) lo (h_checksum), gfp);
-
- GET_PC (pc)
-
- fputc ((int) (pc >> 16) & 0xff, gfp);
- fputc ((int) (pc >> 8) & 0xff, gfp);
- fputc ((int) (pc) & 0xff, gfp);
-
- nsp = (int) (_sp - _stack);
- nfp = (int) (_fp - _stack);
-
- fputc ((int) hi (nsp), gfp);
- fputc ((int) lo (nsp), gfp);
- fputc ((int) hi (nfp), gfp);
- fputc ((int) lo (nfp), gfp);
-
- for (i = nsp; i < STACK_SIZE; i++) {
- fputc ((int) hi (_stack[i]), gfp);
- fputc ((int) lo (_stack[i]), gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
- if (zmp[addr] != fgetc (story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
- fputc (skip, gfp);
- fputc (zmp[addr], gfp);
- skip = 0;
- } else skip++;
+ glk_stream_close(f);
+ success = true;
}
-
- /* Close game file and check for errors */
-
- if (fclose (gfp) == EOF || ferror (story_fp)) {
- print_string ("Error writing save file\n");
- goto finished;
- }
-
- /* Success */
-
- success = 1;
-
+ } else {
+ success = saveGame().getCode() == Common::kNoError;
}
-finished:
-
if (h_version <= V3)
branch (success);
else
store (success);
-#endif
}
void Processor::z_restore() {
-#ifdef TODO
- FILE *gfp;
-
- zword success = 0;
+ bool success = false;
if (zargc != 0) {
+ frefid_t ref = glk_fileref_create_by_prompt(fileusage_Data | fileusage_BinaryMode,
+ filemode_Read, 0);
+ if (ref != nullptr) {
+ // Write data
+ strid_t f = glk_stream_open_file(ref, filemode_Read);
- /* Get the file name */
-
- /* Open auxilary file */
-
- if ((gfp = frotzopenprompt(FILE_LOAD_AUX)) == nullptr)
- goto finished;
-
- /* Load auxilary file */
-
- success = fread (zmp + zargs[0], 1, zargs[1], gfp);
-
- /* Close auxilary file */
-
- fclose (gfp);
-
- } else {
-
- long pc;
- zword release;
- zword addr;
- int i;
-
- /* Open game file */
-
- if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
- goto finished;
-
- if (_save_quetzal) {
- success = restore_quetzal (gfp, story_fp, blorb_ofs);
-
- } else {
- /* Load game file */
-
- release = (unsigned) fgetc (gfp) << 8;
- release |= fgetc (gfp);
-
- () fgetc (gfp);
- () fgetc (gfp);
-
- /* Check the release number */
-
- if (release == h_release) {
-
- pc = (long) fgetc (gfp) << 16;
- pc |= (unsigned) fgetc (gfp) << 8;
- pc |= fgetc (gfp);
-
- SET_PC (pc);
-
- _sp = _stack + (fgetc (gfp) << 8);
- _sp += fgetc (gfp);
- _fp = _stack + (fgetc (gfp) << 8);
- _fp += fgetc (gfp);
-
- for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
- _stack[i] = (unsigned) fgetc (gfp) << 8;
- _stack[i] |= fgetc (gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0; addr < h_dynamic_size; addr++) {
- int skip = fgetc (gfp);
- for (i = 0; i < skip; i++)
- zmp[addr++] = fgetc (story_fp);
- zmp[addr] = fgetc (gfp);
- () fgetc (story_fp);
- }
-
- /* Check for errors */
-
- if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
- success = -1;
- else
-
- /* Success */
-
- success = 2;
+ glk_get_buffer_stream(f, (char *)zmp + zargs[0], zargs[1]);
- } else print_string ("Invalid save file\n");
+ glk_stream_close(f);
+ success = true;
}
-
- if ((short) success >= 0) {
-
- /* Close game file */
-
- fclose (gfp);
-
- if ((short) success > 0) {
- zbyte old_screen_rows;
- zbyte old_screen_cols;
-
- /* In V3, reset the upper window. */
- if (h_version == V3)
- split_window (0);
-
- LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
- LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
-
- /* Reload cached header fields. */
- restart_header ();
-
- /*
- * Since QUETZAL files may be saved on many different machines,
- * the screen sizes may vary a lot. Erasing the status window
- * seems to cover up most of the resulting badness.
- */
- if (h_version > V3 && h_version != V6
- && (h_screen_rows != old_screen_rows
- || h_screen_cols != old_screen_cols))
- erase_window (1);
- }
- } else
- os_fatal ("Error reading save file");
+ } else {
+ success = loadGame().getCode() == Common::kNoError;
}
-finished:
-
if (h_version <= V3)
branch (success);
else
store (success);
-#endif
}
void Processor::z_verify() {
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 987fbc8..a3cd167 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -117,4 +117,56 @@ void GlkEngine::GUIError(const char *msg, ...) {
GUIErrorMessage(buffer);
}
+Common::Error GlkEngine::loadGame() {
+ frefid_t ref = _streams->createByPrompt(fileusage_BinaryMode | fileusage_SavedGame,
+ filemode_Read, 0);
+ if (ref == nullptr)
+ return Common::kReadingFailed;
+
+ int slotNumber = ref->_slotNumber;
+ _streams->deleteRef(ref);
+
+ return loadGameState(slotNumber);
+}
+
+Common::Error GlkEngine::saveGame() {
+ frefid_t ref = _streams->createByPrompt(fileusage_BinaryMode | fileusage_SavedGame,
+ filemode_Write, 0);
+ if (ref == nullptr)
+ return Common::kWritingFailed;
+
+ int slot = ref->_slotNumber;
+ Common::String desc = ref->_description;
+ _streams->deleteRef(ref);
+
+ return saveGameState(slot, desc);
+}
+
+Common::Error GlkEngine::loadGameState(int slot) {
+ FileReference ref(slot, "", fileusage_SavedGame | fileusage_TextMode);
+
+ strid_t file = _streams->openFileStream(&ref, filemode_Read);
+ if (file == nullptr)
+ return Common::kReadingFailed;
+
+ Common::Error result = saveGameData(file);
+
+ file->close();
+ return result;
+}
+
+Common::Error GlkEngine::saveGameState(int slot, const Common::String &desc) {
+ Common::String msg;
+ FileReference ref(slot, desc, fileusage_BinaryMode | fileusage_SavedGame);
+
+ strid_t file = _streams->openFileStream(&ref, filemode_Write);
+ if (file == nullptr)
+ return Common::kWritingFailed;
+
+ Common::Error result = loadGameData(file);
+
+ file->close();
+ return result;
+}
+
} // End of namespace Glk
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 8dce78f..f925fd0 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -30,6 +30,7 @@
#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "glk/glk_types.h"
+#include "glk/streams.h"
namespace Glk {
@@ -181,6 +182,11 @@ public:
}
/**
+ * Display a message in a GUI dialog
+ */
+ void GUIError(const char *msg, ...);
+
+ /**
* Return the filename for a given save slot
*/
Common::String getSaveName(uint slot) const {
@@ -188,9 +194,34 @@ public:
}
/**
- * Display a message in a GUI dialog
+ * Prompt the user for a savegame to load, and then load it
*/
- void GUIError(const char *msg, ...);
+ Common::Error loadGame();
+
+ /**
+ * Prompt the user to save their game, and then save it
+ */
+ Common::Error saveGame();
+
+ /**
+ * Load a savegame from a given slot
+ */
+ virtual Common::Error loadGameState(int slot) override;
+
+ /**
+ * Save the game to a given slot
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+
+ /**
+ * Load a savegame from the passed file
+ */
+ virtual Common::Error loadGameData(strid_t file) = 0;
+
+ /**
+ * Save the game to the passed file
+ */
+ virtual Common::Error saveGameData(strid_t file) = 0;
};
extern GlkEngine *g_vm;
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index fed31f0..cbc5886 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -309,7 +309,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
if (loud)
debug("Reading %d actions.", na);
- for (uint idx = 0; idx < na + 1; ++idx) {
+ for (int idx = 0; idx < na + 1; ++idx) {
Action &a = _actions[idx];
readInts(f, 8,
&a._vocab, &a._condition[0], &a._condition[1], &a._condition[2],
@@ -503,26 +503,8 @@ void Scott::lineInput(char *buf, size_t n) {
buf[ev.val1] = 0;
}
-void Scott::saveGame(void) {
- frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
- filemode_Write, 0);
- if (ref == nullptr)
- return;
-
- int slot = ref->_slotNumber;
- Common::String desc = ref->_description;
- glk_fileref_destroy(ref);
-
- saveGameState(slot, desc);
-}
-
-Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
+Common::Error Scott::saveGameData(strid_t file) {
Common::String msg;
- FileReference ref(slot, desc, fileusage_TextMode | fileusage_SavedGame);
-
- strid_t file = glk_stream_open_file(&ref, filemode_Write, 0);
- if (file == nullptr)
- return Common::kWritingFailed;
for (int ct = 0; ct < 16; ct++) {
msg = Common::String::format("%d %d\n", _counters[ct], _roomSaved[ct]);
@@ -539,37 +521,16 @@ Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
glk_put_string_stream(file, msg.c_str());
}
- glk_stream_close(file, nullptr);
output("Saved.\n");
-
return Common::kNoError;
}
-void Scott::loadGame(void) {
- frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
- filemode_Read, 0);
- if (ref == nullptr)
- return;
-
- int slotNumber = ref->_slotNumber;
- glk_fileref_destroy(ref);
-
- loadGameState(slotNumber);
-}
-
-Common::Error Scott::loadGameState(int slot) {
- strid_t file;
+Common::Error Scott::loadGameData(strid_t file) {
char buf[128];
int ct = 0;
short lo;
short darkFlag;
- FileReference ref(slot, "", fileusage_SavedGame | fileusage_TextMode);
-
- file = glk_stream_open_file(&ref, filemode_Read, 0);
- if (file == nullptr)
- return Common::kReadingFailed;
-
for (ct = 0; ct < 16; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%d %d", &_counters[ct], &_roomSaved[ct]);
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 4741892..a22f88b 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -153,8 +153,6 @@ private:
void look(void);
int whichWord(const char *word, const Common::StringArray &list);
void lineInput(char *buf, size_t n);
- void saveGame(void);
- void loadGame(void);
int getInput(int *vb, int *no);
int performLine(int ct);
int performActions(int vb, int no);
@@ -174,14 +172,14 @@ public:
virtual void runGame(Common::SeekableReadStream *gameFile) override;
/**
- * Load a savegame
+ * Load a savegame from the passed stream
*/
- virtual Common::Error loadGameState(int slot) override;
+ virtual Common::Error loadGameData(strid_t file) override;
/**
- * Save the game
+ * Save the game to the passed stream
*/
- virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+ virtual Common::Error saveGameData(strid_t file) override;
};
} // End of namespace Scott
diff --git a/engines/glk/streams.h b/engines/glk/streams.h
index 22a0a59..3150ce9 100644
--- a/engines/glk/streams.h
+++ b/engines/glk/streams.h
@@ -563,7 +563,7 @@ public:
/**
* Open a file stream
*/
- FileStream *openFileStream(frefid_t fref, glui32 fmode, glui32 rock, bool unicode);
+ FileStream *openFileStream(frefid_t fref, glui32 fmode, glui32 rock = 0, bool unicode = false);
/**
* Open a window stream
Commit: 3b906cb2bb302d9256d07cb462f445af16c7d129
https://github.com/scummvm/scummvm/commit/3b906cb2bb302d9256d07cb462f445af16c7d129
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fixes for combined loading/saving code
Changed paths:
engines/glk/detection.cpp
engines/glk/frotz/frotz.h
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/scott/scott.h
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index e6a129f..a91c603 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -120,13 +120,22 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
return Common::kNoGameDataFoundError;
}
+ // Get the MD5
+ Common::File f;
+ if (!f.open(Common::FSNode(ConfMan.get("path")).getChild(gameDesc._filename)))
+ return Common::kNoGameDataFoundError;
+
+ gameDesc._md5 = Common::computeStreamMD5AsString(f, 5000);
+ f.close();
+
// Correct the correct engine
- if (Glk::Frotz::FrotzMetaEngine::findGame(gameDesc._gameId.c_str()).description)
+ if (Glk::Frotz::FrotzMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
*engine = new Glk::Frotz::Frotz(syst, gameDesc);
- else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description)
+ } else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
*engine = new Glk::Scott::Scott(syst, gameDesc);
- else
+ } else {
return Common::kNoGameDataFoundError;
+ }
return Common::kNoError;
}
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index 00aeb59..0dd8b69 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -49,6 +49,11 @@ public:
void initialize();
/**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_FROTZ; }
+
+ /**
* Execute the game
*/
virtual void runGame(Common::SeekableReadStream *gameFile) override;
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index a3cd167..9488c66 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -149,7 +149,7 @@ Common::Error GlkEngine::loadGameState(int slot) {
if (file == nullptr)
return Common::kReadingFailed;
- Common::Error result = saveGameData(file);
+ Common::Error result = loadGameData(file);
file->close();
return result;
@@ -163,7 +163,7 @@ Common::Error GlkEngine::saveGameState(int slot, const Common::String &desc) {
if (file == nullptr)
return Common::kWritingFailed;
- Common::Error result = loadGameData(file);
+ Common::Error result = saveGameData(file);
file->close();
return result;
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index f925fd0..63b5727 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -76,7 +76,6 @@ struct GlkGameDescription {
Common::Language _language;
Common::Platform _platform;
Common::String _filename;
- InterpreterType _interpType;
Common::String _md5;
};
@@ -162,7 +161,7 @@ public:
/**
* Returns the running interpreter type
*/
- InterpreterType getInterpreterType() const { return _gameDescription._interpType; }
+ virtual InterpreterType getInterpreterType() const = 0;
/**
* Returns the game's md5
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index a22f88b..ad1313d 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -167,6 +167,11 @@ public:
Scott(OSystem *syst, const GlkGameDescription &gameDesc);
/**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_SCOTT; }
+
+ /**
* Execute the game
*/
virtual void runGame(Common::SeekableReadStream *gameFile) override;
Commit: fc86b3705bf2e46f03e27ed7b3934bc4b306a3a2
https://github.com/scummvm/scummvm/commit/fc86b3705bf2e46f03e27ed7b3934bc4b306a3a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix initializing fields of created streams
Changed paths:
engines/glk/streams.cpp
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index cd7130f..b491b89 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -33,8 +33,8 @@
namespace Glk {
Stream::Stream(Streams *streams, bool readable, bool writable, uint32 rock, bool unicode) :
- _streams(streams), _readable(readable), _writable(writable), _readCount(0),
- _writeCount(0), _prev(nullptr), _next(nullptr), _rock(0) {
+ _streams(streams), _readable(readable), _writable(writable), _rock(0), _unicode(unicode),
+ _readCount(0), _writeCount(0), _prev(nullptr), _next(nullptr) {
}
Stream::~Stream() {
Commit: 0167d988fae3a54f526e004ac866db6636307f6f
https://github.com/scummvm/scummvm/commit/0167d988fae3a54f526e004ac866db6636307f6f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Free windows on exit
Changed paths:
engines/glk/window_pair.cpp
engines/glk/window_pair.h
engines/glk/windows.cpp
diff --git a/engines/glk/window_pair.cpp b/engines/glk/window_pair.cpp
index a0fdbb4..41b4e20 100644
--- a/engines/glk/window_pair.cpp
+++ b/engines/glk/window_pair.cpp
@@ -38,6 +38,11 @@ PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size
_type = wintype_Pair;
}
+PairWindow::~PairWindow() {
+ delete _child1;
+ delete _child2;
+}
+
void PairWindow::rearrange(const Rect &box) {
Rect box1, box2;
int min, diff, split, splitwid, max;
diff --git a/engines/glk/window_pair.h b/engines/glk/window_pair.h
index f77ae92..dabae77 100644
--- a/engines/glk/window_pair.h
+++ b/engines/glk/window_pair.h
@@ -49,6 +49,11 @@ public:
PairWindow(Windows *windows, glui32 method, Window *key, glui32 size);
/**
+ * Destructor
+ */
+ ~PairWindow();
+
+ /**
* Rearranges the window
*/
virtual void rearrange(const Rect &box) override;
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
index ce1929f..4db231c 100644
--- a/engines/glk/windows.cpp
+++ b/engines/glk/windows.cpp
@@ -509,12 +509,20 @@ Window::~Window() {
if (g_vm->gli_unregister_obj)
(*g_vm->gli_unregister_obj)(this, gidisp_Class_Window, _dispRock);
-
+ // Remove the window from any parent
+ PairWindow *parent = dynamic_cast<PairWindow *>(_parent);
+ if (parent && parent->_child1 == this)
+ parent->_child1 = nullptr;
+ if (parent && parent->_child2 == this)
+ parent->_child2 = nullptr;
+
+ // Delete any attached window stream
_echoStream = nullptr;
delete _stream;
delete[] _lineTerminatorsBase;
+ // Remove the window from the master list of windows
Window *prev = _prev;
Window *next = _next;
Commit: 88b0e5d52fa26f64b089f1b8d406ada46434e6d3
https://github.com/scummvm/scummvm/commit/88b0e5d52fa26f64b089f1b8d406ada46434e6d3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Change text buffer history array to use Array of U32Strings
Changed paths:
engines/glk/window_text_buffer.cpp
engines/glk/window_text_buffer.h
diff --git a/engines/glk/window_text_buffer.cpp b/engines/glk/window_text_buffer.cpp
index 21de0d9..2a98581 100644
--- a/engines/glk/window_text_buffer.cpp
+++ b/engines/glk/window_text_buffer.cpp
@@ -37,13 +37,13 @@ namespace Glk {
TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
- _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
- _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
- _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
- _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
- _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
+ _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
+ _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
+ _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
+ _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
+ _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
_type = wintype_TextBuffer;
- Common::fill(&_history[0], &_history[HISTORYLEN], (glui32 *)nullptr);
+ _history.resize(HISTORYLEN);
_lines.resize(SCROLLBACK);
_chars = _lines[0]._chars;
@@ -1239,6 +1239,7 @@ void TextBufferWindow::acceptReadChar(glui32 arg) {
void TextBufferWindow::acceptReadLine(glui32 arg) {
glui32 *cx;
+ Common::U32String s;
int len;
if (_height < 2)
@@ -1268,23 +1269,17 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
return;
if (_historyPos == _historyPresent) {
len = _numChars - _inFence;
- if (len > 0) {
- cx = new glui32[len + 1];
- memcpy(cx, &(_chars[_inFence]), len * 4);
- cx[len] = 0;
- } else {
- cx = nullptr;
- }
- if (_history[_historyPos])
- free(_history[_historyPos]);
- _history[_historyPos] = cx;
+
+ if (len > 0)
+ s = Common::U32String(&(_chars[_inFence]), len);
+ _history[_historyPos] = s;
}
+
_historyPos--;
if (_historyPos < 0)
_historyPos += HISTORYLEN;
- cx = _history[_historyPos];
- putTextUni(cx, cx ? strlen_uni(cx) : 0, _inFence,
- _numChars - _inFence);
+ s = _history[_historyPos];
+ putTextUni(s.c_str(), s.size(), _inFence, _numChars - _inFence);
break;
case keycode_Down:
@@ -1293,9 +1288,8 @@ void TextBufferWindow::acceptReadLine(glui32 arg) {
_historyPos++;
if (_historyPos >= HISTORYLEN)
_historyPos -= HISTORYLEN;
- cx = _history[_historyPos];
- putTextUni(cx, cx ? strlen_uni(cx) : 0, _inFence,
- _numChars - _inFence);
+ s = _history[_historyPos];
+ putTextUni(s.c_str(), s.size(), _inFence, _numChars - _inFence);
break;
// Cursor movement keys, during line input.
@@ -1377,7 +1371,7 @@ void TextBufferWindow::acceptLine(glui32 keycode) {
int ix;
int len, olen;
void *inbuf;
- glui32 *s, *o;
+ Common::U32String s, o;
int inmax;
gidispatch_rock_t inarrayrock;
int unicode = _lineRequestUni;
@@ -1407,17 +1401,13 @@ void TextBufferWindow::acceptLine(glui32 keycode) {
* A history entry should not repeat the string from the entry before it.
*/
if (len) {
- s = new glui32[len + 1];
- memcpy(s, _chars + _inFence, len * sizeof(glui32));
- s[len] = 0;
-
- free(_history[_historyPresent]);
- _history[_historyPresent] = nullptr;
+ s = Common::U32String(_chars + _inFence, len);
+ _history[_historyPresent].clear();
o = _history[(_historyPresent == 0 ? HISTORYLEN : _historyPresent) - 1];
- olen = o ? strlen_uni(o) : 0;
+ olen = o.size();
- if (len != olen || memcmp(s, o, olen * sizeof(glui32))) {
+ if (len != olen || !s.equals(o)) {
_history[_historyPresent] = s;
_historyPresent++;
@@ -1429,8 +1419,6 @@ void TextBufferWindow::acceptLine(glui32 keycode) {
if (_historyFirst == HISTORYLEN)
_historyFirst = 0;
}
- } else {
- free(s);
}
}
diff --git a/engines/glk/window_text_buffer.h b/engines/glk/window_text_buffer.h
index 4384986..728919f 100644
--- a/engines/glk/window_text_buffer.h
+++ b/engines/glk/window_text_buffer.h
@@ -26,6 +26,8 @@
#include "glk/windows.h"
#include "glk/picture.h"
#include "glk/speech.h"
+#include "common/array.h"
+#include "common/ustr.h"
namespace Glk {
@@ -106,7 +108,7 @@ public:
int _radjn;
/* Command history. */
- glui32 *_history[HISTORYLEN];
+ Common::Array<Common::U32String> _history;
int _historyPos;
int _historyFirst, _historyPresent;
Commit: 41a437816999c913f30f3ef2c1c751f646399c91
https://github.com/scummvm/scummvm/commit/41a437816999c913f30f3ef2c1c751f646399c91
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: SCOTT: Don't show another line prompt when game is exiting
Changed paths:
engines/glk/glk_api.cpp
engines/glk/scott/scott.cpp
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index 6094015..e04040f 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -62,7 +62,10 @@ void GlkAPI::glk_exit(void) {
glk_put_string("[ press any key to exit ]");
_events->waitForPress();
+ // Trigger a ScumMVM shutdown of game
quitGame();
+ Common::Event e;
+ g_system->getEventManager()->pollEvent(e);
}
void GlkAPI::glk_set_interrupt_handler(void(*func)(void)) {
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index cbc5886..dc0ae0b 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -102,6 +102,8 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
default:
break;
}
+ if (shouldQuit())
+ return;
// Brian Howarth games seem to use -1 for forever
if (_items[LIGHT_SOURCE]._location != DESTROYED && _gameHeader._lightTime != -1) {
@@ -789,7 +791,7 @@ int Scott::performLine(int ct) {
doneit:
output("The game is now over.\n");
glk_exit();
- break;
+ return 0;
case 64:
break;
case 65: {
@@ -1022,6 +1024,9 @@ int Scott::performActions(int vb, int no) {
if (vb != 0 && doagain == 0)
return 0;
}
+
+ if (shouldQuit())
+ return 0;
}
}
ct++;
Commit: 79f3d946ef23ff121f30d9e429d2c4ab985ce29c
https://github.com/scummvm/scummvm/commit/79f3d946ef23ff121f30d9e429d2c4ab985ce29c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Shift Header class into it's own file
Changed paths:
A engines/glk/frotz/header.cpp
A engines/glk/frotz/header.h
engines/glk/frotz/mem.cpp
engines/glk/frotz/mem.h
engines/glk/module.mk
diff --git a/engines/glk/frotz/header.cpp b/engines/glk/frotz/header.cpp
new file mode 100644
index 0000000..f7ebb5e
--- /dev/null
+++ b/engines/glk/frotz/header.cpp
@@ -0,0 +1,112 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/header.h"
+#include "common/textconsole.h"
+
+namespace Glk {
+namespace Frotz {
+
+const Header::StoryEntry Header::RECORDS[25] = {
+ { SHERLOCK, 21, "871214" },
+ { SHERLOCK, 26, "880127" },
+ { BEYOND_ZORK, 47, "870915" },
+ { BEYOND_ZORK, 49, "870917" },
+ { BEYOND_ZORK, 51, "870923" },
+ { BEYOND_ZORK, 57, "871221" },
+ { ZORK_ZERO, 296, "881019" },
+ { ZORK_ZERO, 366, "890323" },
+ { ZORK_ZERO, 383, "890602" },
+ { ZORK_ZERO, 393, "890714" },
+ { SHOGUN, 292, "890314" },
+ { SHOGUN, 295, "890321" },
+ { SHOGUN, 311, "890510" },
+ { SHOGUN, 322, "890706" },
+ { ARTHUR, 54, "890606" },
+ { ARTHUR, 63, "890622" },
+ { ARTHUR, 74, "890714" },
+ { JOURNEY, 26, "890316" },
+ { JOURNEY, 30, "890322" },
+ { JOURNEY, 77, "890616" },
+ { JOURNEY, 83, "890706" },
+ { LURKING_HORROR, 203, "870506" },
+ { LURKING_HORROR, 219, "870912" },
+ { LURKING_HORROR, 221, "870918" },
+ { UNKNOWN, 0, "------" }
+};
+
+void Header::loadHeader(Common::SeekableReadStream &f) {
+ h_version = f.readByte();
+ h_config = f.readByte();
+
+ if (h_version < V1 || h_version > V8)
+ error("Unknown Z-code version");
+
+ if (h_version == V6)
+ error("Cannot play Z-code version 6");
+
+ if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
+ error("Byte swapped story file");
+
+ h_release = f.readUint16BE();
+ h_resident_size = f.readUint16BE();
+ h_start_pc = f.readUint16BE();
+ h_dictionary = f.readUint16BE();
+ h_objects = f.readUint16BE();
+ h_globals = f.readUint16BE();
+ h_dynamic_size = f.readUint16BE();
+ h_flags = f.readUint16BE();
+ f.read(h_serial, 6);
+
+ /* Auto-detect buggy story files that need special fixes */
+ _storyId = UNKNOWN;
+
+ for (int i = 0; RECORDS[i]._storyId != UNKNOWN; ++i) {
+ if (h_release == RECORDS[i]._release) {
+ if (!strncmp((const char *)h_serial, RECORDS[i]._serial, 6)) {
+ _storyId = RECORDS[i]._storyId;
+ break;
+ }
+ }
+ }
+
+ h_abbreviations = f.readUint16BE();
+ h_file_size = f.readUint16BE();
+ h_checksum = f.readUint16BE();
+
+ f.seek(H_FUNCTIONS_OFFSET);
+ h_functions_offset = f.readUint16BE();
+ h_strings_offset = f.readUint16BE();
+ f.seek(H_TERMINATING_KEYS);
+ h_terminating_keys = f.readUint16BE();
+ f.seek(H_ALPHABET);
+ h_alphabet = f.readUint16BE();
+ h_extension_table = f.readUint16BE();
+
+
+ // Zork Zero Macintosh doesn't have the graphics flag set
+ if (_storyId == ZORK_ZERO && h_release == 296)
+ h_flags |= GRAPHICS_FLAG;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/frotz/header.h b/engines/glk/frotz/header.h
new file mode 100644
index 0000000..cf7ab64
--- /dev/null
+++ b/engines/glk/frotz/header.h
@@ -0,0 +1,159 @@
+/* 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_FROTZ_HEADER
+#define GLK_FROTZ_HEADER
+
+#include "glk/frotz/frotz_types.h"
+
+namespace Glk {
+namespace Frotz {
+
+enum HeaderByte {
+ H_VERSION = 0,
+ H_CONFIG = 1,
+ H_RELEASE = 2,
+ H_RESIDENT_SIZE = 4,
+ H_START_PC = 6,
+ H_DICTIONARY = 8,
+ H_OBJECTS = 10,
+ H_GLOBALS = 12,
+ H_DYNAMIC_SIZE = 14,
+ H_FLAGS = 16,
+ H_SERIAL = 18,
+ H_ABBREVIATIONS = 24,
+ H_FILE_SIZE = 26,
+ H_CHECKSUM = 28,
+ H_INTERPRETER_NUMBER = 30,
+ H_INTERPRETER_VERSION = 31,
+ H_SCREEN_ROWS = 32,
+ H_SCREEN_COLS = 33,
+ H_SCREEN_WIDTH = 34,
+ H_SCREEN_HEIGHT = 36,
+ H_FONT_HEIGHT = 38, ///< this is the font width in V5
+ H_FONT_WIDTH = 39, ///< this is the font height in V5
+ H_FUNCTIONS_OFFSET = 40,
+ H_STRINGS_OFFSET = 42,
+ H_DEFAULT_BACKGROUND = 44,
+ H_DEFAULT_FOREGROUND = 45,
+ H_TERMINATING_KEYS = 46,
+ H_LINE_WIDTH = 48,
+ H_STANDARD_HIGH = 50,
+ H_STANDARD_LOW = 51,
+ H_ALPHABET = 52,
+ H_EXTENSION_TABLE = 54,
+ H_USER_NAME = 56
+};
+
+enum {
+ HX_TABLE_SIZE = 0,
+ HX_MOUSE_X = 1,
+ HX_MOUSE_Y = 2,
+ HX_UNICODE_TABLE = 3,
+ HX_FLAGS = 4,
+ HX_FORE_COLOUR = 5,
+ HX_BACK_COLOUR = 6
+};
+
+/**
+ * Story file header data
+ */
+struct Header {
+private:
+ struct StoryEntry {
+ Story _storyId;
+ zword _release;
+ char _serial[7];
+ };
+ static const StoryEntry RECORDS[25];
+public:
+ zbyte h_version;
+ zbyte h_config;
+ zword h_release;
+ zword h_resident_size;
+ zword h_start_pc;
+ zword h_dictionary;
+ zword h_objects;
+ zword h_globals;
+ zword h_dynamic_size;
+ zword h_flags;
+ zbyte h_serial[6];
+ zword h_abbreviations;
+ zword h_file_size;
+ zword h_checksum;
+ zbyte h_interpreter_number;
+ zbyte h_interpreter_version;
+ zbyte h_screen_rows;
+ zbyte h_screen_cols;
+ zword h_screen_width;
+ zword h_screen_height;
+ zbyte h_font_height;
+ zbyte h_font_width;
+ zword h_functions_offset;
+ zword h_strings_offset;
+ zbyte h_default_background;
+ zbyte h_default_foreground;
+ zword h_terminating_keys;
+ zword h_line_width;
+ zbyte h_standard_high;
+ zbyte h_standard_low;
+ zword h_alphabet;
+ zword h_extension_table;
+ zbyte h_user_name[8];
+
+ zword hx_table_size;
+ zword hx_mouse_x;
+ zword hx_mouse_y;
+ zword hx_unicode_table;
+ zword hx_flags;
+ zword hx_fore_colour;
+ zword hx_back_colour;
+
+ Story _storyId;
+
+ /**
+ * Constructor
+ */
+ Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
+ h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
+ h_abbreviations(0), h_file_size(0), h_checksum(0), h_interpreter_number(0),
+ h_interpreter_version(0), h_screen_rows(0), h_screen_cols(0), h_screen_width(0),
+ h_screen_height(0), h_font_height(1), h_font_width(1), h_functions_offset(0),
+ h_strings_offset(0), h_default_background(0), h_default_foreground(0),
+ h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
+ h_alphabet(0), h_extension_table(0),
+ hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
+ hx_flags(0), hx_fore_colour(0), hx_back_colour(0), _storyId(UNKNOWN) {
+ Common::fill(&h_serial[0], &h_serial[6], '\0');
+ Common::fill(&h_user_name[0], &h_user_name[8], '\0');
+ }
+
+ /**
+ * Load the header
+ */
+ void loadHeader(Common::SeekableReadStream &f);
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index 6ee6781..da0acaa 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -28,90 +28,6 @@
namespace Glk {
namespace Frotz {
-const Header::StoryEntry Header::RECORDS[25] = {
- { SHERLOCK, 21, "871214" },
- { SHERLOCK, 26, "880127" },
- { BEYOND_ZORK, 47, "870915" },
- { BEYOND_ZORK, 49, "870917" },
- { BEYOND_ZORK, 51, "870923" },
- { BEYOND_ZORK, 57, "871221" },
- { ZORK_ZERO, 296, "881019" },
- { ZORK_ZERO, 366, "890323" },
- { ZORK_ZERO, 383, "890602" },
- { ZORK_ZERO, 393, "890714" },
- { SHOGUN, 292, "890314" },
- { SHOGUN, 295, "890321" },
- { SHOGUN, 311, "890510" },
- { SHOGUN, 322, "890706" },
- { ARTHUR, 54, "890606" },
- { ARTHUR, 63, "890622" },
- { ARTHUR, 74, "890714" },
- { JOURNEY, 26, "890316" },
- { JOURNEY, 30, "890322" },
- { JOURNEY, 77, "890616" },
- { JOURNEY, 83, "890706" },
- { LURKING_HORROR, 203, "870506" },
- { LURKING_HORROR, 219, "870912" },
- { LURKING_HORROR, 221, "870918" },
- { UNKNOWN, 0, "------" }
-};
-
-void Header::loadHeader(Common::SeekableReadStream &f) {
- h_version = f.readByte();
- h_config = f.readByte();
-
- if (h_version < V1 || h_version > V8)
- error("Unknown Z-code version");
-
- if (h_version == V6)
- error("Cannot play Z-code version 6");
-
- if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
- error("Byte swapped story file");
-
- h_release = f.readUint16BE();
- h_resident_size = f.readUint16BE();
- h_start_pc = f.readUint16BE();
- h_dictionary = f.readUint16BE();
- h_objects = f.readUint16BE();
- h_globals = f.readUint16BE();
- h_dynamic_size = f.readUint16BE();
- h_flags = f.readUint16BE();
- f.read(h_serial, 6);
-
- /* Auto-detect buggy story files that need special fixes */
- _storyId = UNKNOWN;
-
- for (int i = 0; RECORDS[i]._storyId != UNKNOWN; ++i) {
- if (h_release == RECORDS[i]._release) {
- if (!strncmp((const char *)h_serial, RECORDS[i]._serial, 6)) {
- _storyId = RECORDS[i]._storyId;
- break;
- }
- }
- }
-
- h_abbreviations = f.readUint16BE();
- h_file_size = f.readUint16BE();
- h_checksum = f.readUint16BE();
-
- f.seek(H_FUNCTIONS_OFFSET);
- h_functions_offset = f.readUint16BE();
- h_strings_offset = f.readUint16BE();
- f.seek(H_TERMINATING_KEYS);
- h_terminating_keys = f.readUint16BE();
- f.seek(H_ALPHABET);
- h_alphabet = f.readUint16BE();
- h_extension_table = f.readUint16BE();
-
-
- // Zork Zero Macintosh doesn't have the graphics flag set
- if (_storyId == ZORK_ZERO && h_release == 296)
- h_flags |= GRAPHICS_FLAG;
-}
-
-/*--------------------------------------------------------------------------*/
-
Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0),
first_undo(nullptr), last_undo(nullptr), curr_undo(nullptr),
undo_mem(nullptr), prev_zmp(nullptr), undo_diff(nullptr),
diff --git a/engines/glk/frotz/mem.h b/engines/glk/frotz/mem.h
index 372c7e7..3b1b81b 100644
--- a/engines/glk/frotz/mem.h
+++ b/engines/glk/frotz/mem.h
@@ -24,6 +24,7 @@
#define GLK_FROTZ_MEM
#include "glk/frotz/frotz_types.h"
+#include "glk/frotz/header.h"
namespace Glk {
namespace Frotz {
@@ -35,52 +36,6 @@ namespace Frotz {
#define SET_BYTE(addr,v) zmp[addr] = v
#define LOW_BYTE(addr,v) v = zmp[addr]
-enum HeaderByte {
- H_VERSION = 0,
- H_CONFIG = 1,
- H_RELEASE = 2,
- H_RESIDENT_SIZE = 4,
- H_START_PC = 6,
- H_DICTIONARY = 8,
- H_OBJECTS = 10,
- H_GLOBALS = 12,
- H_DYNAMIC_SIZE = 14,
- H_FLAGS = 16,
- H_SERIAL = 18,
- H_ABBREVIATIONS = 24,
- H_FILE_SIZE = 26,
- H_CHECKSUM = 28,
- H_INTERPRETER_NUMBER = 30,
- H_INTERPRETER_VERSION = 31,
- H_SCREEN_ROWS = 32,
- H_SCREEN_COLS = 33,
- H_SCREEN_WIDTH = 34,
- H_SCREEN_HEIGHT = 36,
- H_FONT_HEIGHT = 38, ///< this is the font width in V5
- H_FONT_WIDTH = 39, ///< this is the font height in V5
- H_FUNCTIONS_OFFSET = 40,
- H_STRINGS_OFFSET = 42,
- H_DEFAULT_BACKGROUND = 44,
- H_DEFAULT_FOREGROUND = 45,
- H_TERMINATING_KEYS = 46,
- H_LINE_WIDTH = 48,
- H_STANDARD_HIGH = 50,
- H_STANDARD_LOW = 51,
- H_ALPHABET = 52,
- H_EXTENSION_TABLE = 54,
- H_USER_NAME = 56
-};
-
-enum {
- HX_TABLE_SIZE = 0,
- HX_MOUSE_X = 1,
- HX_MOUSE_Y = 2,
- HX_UNICODE_TABLE = 3,
- HX_FLAGS = 4,
- HX_FORE_COLOUR = 5,
- HX_BACK_COLOUR = 6
-};
-
/**
* Stores undo information
*/
@@ -97,84 +52,8 @@ struct undo_struct {
typedef undo_struct undo_t;
/**
- * Story file header data
+ * Handles the memory, header, and user options
*/
-struct Header {
-private:
- struct StoryEntry {
- Story _storyId;
- zword _release;
- char _serial[7];
- };
- static const StoryEntry RECORDS[25];
-public:
- zbyte h_version;
- zbyte h_config;
- zword h_release;
- zword h_resident_size;
- zword h_start_pc;
- zword h_dictionary;
- zword h_objects;
- zword h_globals;
- zword h_dynamic_size;
- zword h_flags;
- zbyte h_serial[6];
- zword h_abbreviations;
- zword h_file_size;
- zword h_checksum;
- zbyte h_interpreter_number;
- zbyte h_interpreter_version;
- zbyte h_screen_rows;
- zbyte h_screen_cols;
- zword h_screen_width;
- zword h_screen_height;
- zbyte h_font_height;
- zbyte h_font_width;
- zword h_functions_offset;
- zword h_strings_offset;
- zbyte h_default_background;
- zbyte h_default_foreground;
- zword h_terminating_keys;
- zword h_line_width;
- zbyte h_standard_high;
- zbyte h_standard_low;
- zword h_alphabet;
- zword h_extension_table;
- zbyte h_user_name[8];
-
- zword hx_table_size;
- zword hx_mouse_x;
- zword hx_mouse_y;
- zword hx_unicode_table;
- zword hx_flags;
- zword hx_fore_colour;
- zword hx_back_colour;
-
- Story _storyId;
-
- /**
- * Constructor
- */
- Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
- h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
- h_abbreviations(0), h_file_size(0), h_checksum(0), h_interpreter_number(0),
- h_interpreter_version(0), h_screen_rows(0), h_screen_cols(0), h_screen_width(0),
- h_screen_height(0), h_font_height(1), h_font_width(1), h_functions_offset(0),
- h_strings_offset(0), h_default_background(0), h_default_foreground(0),
- h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
- h_alphabet(0), h_extension_table(0),
- hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
- hx_flags(0), hx_fore_colour(0), hx_back_colour(0), _storyId(UNKNOWN) {
- Common::fill(&h_serial[0], &h_serial[6], '\0');
- Common::fill(&h_user_name[0], &h_user_name[8], '\0');
- }
-
- /**
- * Load the header
- */
- void loadHeader(Common::SeekableReadStream &f);
-};
-
class Mem : public Header, public virtual UserOptions {
protected:
Common::SeekableReadStream *story_fp;
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index b523034..10cef32 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -24,6 +24,7 @@ MODULE_OBJS := \
frotz/detection.o \
frotz/frotz.o \
frotz/glk_interface.o \
+ frotz/header.o \
frotz/mem.o \
frotz/processor.o \
frotz/processor_buffer.o \
Commit: ada80dedc0d39d76a2cd3c3b4af6c3219738d0bf
https://github.com/scummvm/scummvm/commit/ada80dedc0d39d76a2cd3c3b4af6c3219738d0bf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Further merging together of configuration into a new config.cpp file
Changed paths:
A engines/glk/frotz/config.cpp
A engines/glk/frotz/config.h
R engines/glk/frotz/header.cpp
R engines/glk/frotz/header.h
engines/glk/frotz/frotz.cpp
engines/glk/frotz/frotz_types.h
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/mem.h
engines/glk/frotz/processor.cpp
engines/glk/module.mk
diff --git a/engines/glk/frotz/config.cpp b/engines/glk/frotz/config.cpp
new file mode 100644
index 0000000..0461e25
--- /dev/null
+++ b/engines/glk/frotz/config.cpp
@@ -0,0 +1,196 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/config.h"
+#include "common/config-manager.h"
+#include "common/textconsole.h"
+
+namespace Glk {
+namespace Frotz {
+
+const Header::StoryEntry Header::RECORDS[25] = {
+ { SHERLOCK, 21, "871214" },
+ { SHERLOCK, 26, "880127" },
+ { BEYOND_ZORK, 47, "870915" },
+ { BEYOND_ZORK, 49, "870917" },
+ { BEYOND_ZORK, 51, "870923" },
+ { BEYOND_ZORK, 57, "871221" },
+ { ZORK_ZERO, 296, "881019" },
+ { ZORK_ZERO, 366, "890323" },
+ { ZORK_ZERO, 383, "890602" },
+ { ZORK_ZERO, 393, "890714" },
+ { SHOGUN, 292, "890314" },
+ { SHOGUN, 295, "890321" },
+ { SHOGUN, 311, "890510" },
+ { SHOGUN, 322, "890706" },
+ { ARTHUR, 54, "890606" },
+ { ARTHUR, 63, "890622" },
+ { ARTHUR, 74, "890714" },
+ { JOURNEY, 26, "890316" },
+ { JOURNEY, 30, "890322" },
+ { JOURNEY, 77, "890616" },
+ { JOURNEY, 83, "890706" },
+ { LURKING_HORROR, 203, "870506" },
+ { LURKING_HORROR, 219, "870912" },
+ { LURKING_HORROR, 221, "870918" },
+ { UNKNOWN, 0, "------" }
+};
+
+static uint getConfigBool(const Common::String &profileName, bool defaultVal = false) {
+ return ConfMan.hasKey(profileName) ? ConfMan.getBool(profileName) : defaultVal;
+}
+
+static uint getConfigInt(const Common::String &profileName, uint defaultVal, uint maxVal) {
+ uint val = ConfMan.hasKey(profileName) ? ConfMan.getInt(profileName) : defaultVal;
+ if (val > maxVal)
+ error("Invalid value for configuration value %s", profileName.c_str());
+
+ return val;
+}
+
+Header::Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
+ h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
+ h_abbreviations(0), h_file_size(0), h_checksum(0),
+ h_interpreter_version(0), h_screen_rows(0), h_screen_cols(0), h_screen_width(0),
+ h_screen_height(0), h_font_height(1), h_font_width(1), h_functions_offset(0),
+ h_strings_offset(0), h_default_background(0), h_default_foreground(0),
+ h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
+ h_alphabet(0), h_extension_table(0),
+ hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
+ hx_flags(0), hx_fore_colour(0), hx_back_colour(0), _storyId(UNKNOWN) {
+ Common::fill(&h_serial[0], &h_serial[6], '\0');
+ Common::fill(&h_user_name[0], &h_user_name[8], '\0');
+
+ h_interpreter_number = getConfigInt("interpreter_number", INTERP_AMIGA, INTERP_TANDY);
+
+
+ if (ConfMan.hasKey("username")) {
+ Common::String username = ConfMan.get("username");
+ strncpy((char *)h_user_name, username.c_str(), 7);
+ }
+}
+
+void Header::loadHeader(Common::SeekableReadStream &f) {
+ h_version = f.readByte();
+ h_config = f.readByte();
+
+ if (h_version < V1 || h_version > V8)
+ error("Unknown Z-code version");
+
+ if (h_version == V6)
+ error("Cannot play Z-code version 6");
+
+ if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
+ error("Byte swapped story file");
+
+ h_release = f.readUint16BE();
+ h_resident_size = f.readUint16BE();
+ h_start_pc = f.readUint16BE();
+ h_dictionary = f.readUint16BE();
+ h_objects = f.readUint16BE();
+ h_globals = f.readUint16BE();
+ h_dynamic_size = f.readUint16BE();
+ h_flags = f.readUint16BE();
+ f.read(h_serial, 6);
+
+ /* Auto-detect buggy story files that need special fixes */
+ _storyId = UNKNOWN;
+
+ for (int i = 0; RECORDS[i]._storyId != UNKNOWN; ++i) {
+ if (h_release == RECORDS[i]._release) {
+ if (!strncmp((const char *)h_serial, RECORDS[i]._serial, 6)) {
+ _storyId = RECORDS[i]._storyId;
+ break;
+ }
+ }
+ }
+
+ h_abbreviations = f.readUint16BE();
+ h_file_size = f.readUint16BE();
+ h_checksum = f.readUint16BE();
+
+ f.seek(H_FUNCTIONS_OFFSET);
+ h_functions_offset = f.readUint16BE();
+ h_strings_offset = f.readUint16BE();
+ f.seek(H_TERMINATING_KEYS);
+ h_terminating_keys = f.readUint16BE();
+ f.seek(H_ALPHABET);
+ h_alphabet = f.readUint16BE();
+ h_extension_table = f.readUint16BE();
+
+
+ // Zork Zero Macintosh doesn't have the graphics flag set
+ if (_storyId == ZORK_ZERO && h_release == 296)
+ h_flags |= GRAPHICS_FLAG;
+}
+
+/*--------------------------------------------------------------------------*/
+
+UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true) {
+ _err_report_mode = getConfigInt("err_report_mode", ERR_REPORT_ONCE, ERR_REPORT_FATAL);
+ _ignore_errors = getConfigBool("ignore_errors");
+ _expand_abbreviations = getConfigBool("expand_abbreviations");
+ _quetzal = getConfigBool("quetzal", true);
+ _tandyBit = getConfigBool("tandy_bit");
+ _piracy = getConfigBool("piracy");
+ _script_cols = getConfigInt("wrap_script_lines", 80, 999);
+ _left_margin = getConfigInt("left_margin", 0, 999);
+ _right_margin = getConfigInt("right_margin", 0, 999);
+
+ // Debugging flags
+ _attribute_assignment = getConfigBool("attribute_assignment");
+ _attribute_testing = getConfigBool("attribute_testing");
+ _object_locating = getConfigBool("object_locating");
+ _object_movement = getConfigBool("object_movement");
+}
+
+#ifdef REMOVE_ME
+if (ConfMan.hasKey("attribute_assignment") && ConfMan.getBool("attribute_assignment"))
+_attribute_assignment = true;
+if (ConfMan.hasKey("attribute_testing") && ConfMan.getBool("attribute_testing"))
+_attribute_testing = true;
+if (ConfMan.hasKey("object_movement") && ConfMan.getBool("object_movement"))
+_object_movement = true;
+if (ConfMan.hasKey("object_locating") && ConfMan.getBool("object_locating"))
+_object_locating = true;
+if (ConfMan.hasKey("piracy") && ConfMan.getBool("piracy"))
+_piracy = true;
+if (ConfMan.hasKey("random_seed"))
+_random.setSeed(ConfMan.getInt("random_seed"));
+if (ConfMan.hasKey("script_cols"))
+_script_cols = ConfMan.getInt("script_cols");
+if (ConfMan.hasKey("tandy_bit") && ConfMan.getBool("tandy_bit"))
+_user_tandy_bit = true;
+if (ConfMan.hasKey("undo_slots"))
+_undo_slots = ConfMan.getInt("undo_slots");
+if (ConfMan.hasKey("expand_abbreviations") && ConfMan.getBool("expand_abbreviations"))
+_expand_abbreviations = true;
+if (ConfMan.hasKey("err_report_mode")) {
+ _err_report_mode = ConfMan.getInt("err_report_mode");
+ if ((_err_report_mode < ERR_REPORT_NEVER) || (_err_report_mode > ERR_REPORT_FATAL))
+ _err_report_mode = ERR_DEFAULT_REPORT_MODE;
+}
+
+#endif
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/frotz/config.h b/engines/glk/frotz/config.h
new file mode 100644
index 0000000..a210ba2
--- /dev/null
+++ b/engines/glk/frotz/config.h
@@ -0,0 +1,228 @@
+/* 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_FROTZ_CONFIG
+#define GLK_FROTZ_CONFIG
+
+#include "glk/frotz/frotz_types.h"
+
+namespace Glk {
+namespace Frotz {
+
+/**
+ * Configuration flags
+ */
+enum ConfigFlag {
+ CONFIG_BYTE_SWAPPED = 0x01, ///< Story file is byte swapped - V3
+ CONFIG_TIME = 0x02, ///< Status line displays time - V3
+ CONFIG_TWODISKS = 0x04, ///< Story file occupied two disks - V3
+ CONFIG_TANDY = 0x08, ///< Tandy licensed game - V3
+ CONFIG_NOSTATUSLINE = 0x10, ///< Interpr can't support status lines - V3
+ CONFIG_SPLITSCREEN = 0x20, ///< Interpr supports split screen mode - V3
+ CONFIG_PROPORTIONAL = 0x40, ///< Interpr uses proportional font - V3
+
+ CONFIG_COLOUR = 0x01, ///< Interpr supports colour - V5+
+ CONFIG_PICTURES = 0x02, ///< Interpr supports pictures - V6
+ CONFIG_BOLDFACE = 0x04, ///< Interpr supports boldface style - V4+
+ CONFIG_EMPHASIS = 0x08, ///< Interpr supports emphasis style - V4+
+ CONFIG_FIXED = 0x10, ///< Interpr supports fixed width style - V4+
+ CONFIG_SOUND = 0x20, ///< Interpr supports sound - V6
+ CONFIG_TIMEDINPUT = 0x80, ///< Interpr supports timed input - V4+
+
+ SCRIPTING_FLAG = 0x0001, ///< Outputting to transscription file - V1+
+ FIXED_FONT_FLAG = 0x0002, ///< Use fixed width font - V3+
+ REFRESH_FLAG = 0x0004, ///< Refresh the screen - V6
+ GRAPHICS_FLAG = 0x0008, ///< Game wants to use graphics - V5+
+ OLD_SOUND_FLAG = 0x0010, ///< Game wants to use sound effects - V3
+ UNDO_FLAG = 0x0010, ///< Game wants to use UNDO feature - V5+
+ MOUSE_FLAG = 0x0020, ///< Game wants to use a mouse - V5+
+ COLOUR_FLAG = 0x0040, ///< Game wants to use colours - V5+
+ SOUND_FLAG = 0x0080, ///< Game wants to use sound effects - V5+
+ MENU_FLAG = 0x0100 ///< Game wants to use menus - V6
+};
+
+/**
+ * There are four error reporting modes: never report errors;
+ * report only the first time a given error type occurs;
+ * report every time an error occurs;
+ * or treat all errors as fatal errors, killing the interpreter.
+ * I strongly recommend "report once" as the default. But you can compile in a
+ * different default by changing the definition of ERR_DEFAULT_REPORT_MODE.
+ */
+enum ErrorReport {
+ ERR_REPORT_NEVER = 0,
+ ERR_REPORT_ONCE = 1,
+ ERR_REPORT_ALWAYS = 2,
+ ERR_REPORT_FATAL = 3,
+
+ ERR_DEFAULT_REPORT_MODE = ERR_REPORT_NEVER
+};
+
+/**
+ * Enumeration of the game header byte indexes
+ */
+enum HeaderByte {
+ H_VERSION = 0,
+ H_CONFIG = 1,
+ H_RELEASE = 2,
+ H_RESIDENT_SIZE = 4,
+ H_START_PC = 6,
+ H_DICTIONARY = 8,
+ H_OBJECTS = 10,
+ H_GLOBALS = 12,
+ H_DYNAMIC_SIZE = 14,
+ H_FLAGS = 16,
+ H_SERIAL = 18,
+ H_ABBREVIATIONS = 24,
+ H_FILE_SIZE = 26,
+ H_CHECKSUM = 28,
+ H_INTERPRETER_NUMBER = 30,
+ H_INTERPRETER_VERSION = 31,
+ H_SCREEN_ROWS = 32,
+ H_SCREEN_COLS = 33,
+ H_SCREEN_WIDTH = 34,
+ H_SCREEN_HEIGHT = 36,
+ H_FONT_HEIGHT = 38, ///< this is the font width in V5
+ H_FONT_WIDTH = 39, ///< this is the font height in V5
+ H_FUNCTIONS_OFFSET = 40,
+ H_STRINGS_OFFSET = 42,
+ H_DEFAULT_BACKGROUND = 44,
+ H_DEFAULT_FOREGROUND = 45,
+ H_TERMINATING_KEYS = 46,
+ H_LINE_WIDTH = 48,
+ H_STANDARD_HIGH = 50,
+ H_STANDARD_LOW = 51,
+ H_ALPHABET = 52,
+ H_EXTENSION_TABLE = 54,
+ H_USER_NAME = 56
+};
+
+/**
+ * Header extension fields
+ */
+enum {
+ HX_TABLE_SIZE = 0,
+ HX_MOUSE_X = 1,
+ HX_MOUSE_Y = 2,
+ HX_UNICODE_TABLE = 3,
+ HX_FLAGS = 4,
+ HX_FORE_COLOUR = 5,
+ HX_BACK_COLOUR = 6
+};
+
+/**
+ * User options
+ */
+struct UserOptions {
+ bool _attribute_assignment;
+ bool _attribute_testing;
+ bool _object_locating;
+ bool _object_movement;
+ bool _expand_abbreviations;
+ bool _ignore_errors;
+ bool _piracy;
+ bool _quetzal;
+ bool _sound;
+ bool _tandyBit;
+ int _left_margin;
+ int _right_margin;
+ int _undo_slots;
+ int _script_cols;
+ int _err_report_mode;
+
+ /**
+ * Constructor
+ */
+ UserOptions();
+};
+
+/**
+ * Story file header data
+ */
+struct Header {
+private:
+ struct StoryEntry {
+ Story _storyId;
+ zword _release;
+ char _serial[7];
+ };
+ static const StoryEntry RECORDS[25];
+public:
+ zbyte h_version;
+ zbyte h_config;
+ zword h_release;
+ zword h_resident_size;
+ zword h_start_pc;
+ zword h_dictionary;
+ zword h_objects;
+ zword h_globals;
+ zword h_dynamic_size;
+ zword h_flags;
+ zbyte h_serial[6];
+ zword h_abbreviations;
+ zword h_file_size;
+ zword h_checksum;
+ zbyte h_interpreter_number;
+ zbyte h_interpreter_version;
+ zbyte h_screen_rows;
+ zbyte h_screen_cols;
+ zword h_screen_width;
+ zword h_screen_height;
+ zbyte h_font_height;
+ zbyte h_font_width;
+ zword h_functions_offset;
+ zword h_strings_offset;
+ zbyte h_default_background;
+ zbyte h_default_foreground;
+ zword h_terminating_keys;
+ zword h_line_width;
+ zbyte h_standard_high;
+ zbyte h_standard_low;
+ zword h_alphabet;
+ zword h_extension_table;
+ zbyte h_user_name[8];
+
+ zword hx_table_size;
+ zword hx_mouse_x;
+ zword hx_mouse_y;
+ zword hx_unicode_table;
+ zword hx_flags;
+ zword hx_fore_colour;
+ zword hx_back_colour;
+
+ Story _storyId;
+
+ /**
+ * Constructor
+ */
+ Header();
+
+ /**
+ * Load the header
+ */
+ void loadHeader(Common::SeekableReadStream &f);
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 344aa92..5828790 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -47,36 +47,6 @@ void Frotz::runGame(Common::SeekableReadStream *gameFile) {
}
void Frotz::initialize() {
- if (ConfMan.hasKey("attribute_assignment") && ConfMan.getBool("attribute_assignment"))
- _attribute_assignment = true;
- if (ConfMan.hasKey("attribute_testing") && ConfMan.getBool("attribute_testing"))
- _attribute_testing = true;
- if (ConfMan.hasKey("ignore_errors") && ConfMan.getBool("ignore_errors"))
- _ignore_errors = true;
- if (ConfMan.hasKey("object_movement") && ConfMan.getBool("object_movement"))
- _object_movement = true;
- if (ConfMan.hasKey("object_locating") && ConfMan.getBool("object_locating"))
- _object_locating = true;
- if (ConfMan.hasKey("piracy") && ConfMan.getBool("piracy"))
- _piracy = true;
- if (ConfMan.hasKey("save_quetzal") && ConfMan.getBool("save_quetzal"))
- _save_quetzal = true;
- if (ConfMan.hasKey("random_seed"))
- _random.setSeed(ConfMan.getInt("random_seed"));
- if (ConfMan.hasKey("script_cols"))
- _script_cols = ConfMan.getInt("script_cols");
- if (ConfMan.hasKey("tandy_bit") && ConfMan.getBool("tandy_bit"))
- _user_tandy_bit = true;
- if (ConfMan.hasKey("undo_slots"))
- _undo_slots = ConfMan.getInt("undo_slots");
- if (ConfMan.hasKey("expand_abbreviations") && ConfMan.getBool("expand_abbreviations"))
- _expand_abbreviations = true;
- if (ConfMan.hasKey("err_report_mode")) {
- _err_report_mode = ConfMan.getInt("err_report_mode");
- if ((_err_report_mode < ERR_REPORT_NEVER) || (_err_report_mode > ERR_REPORT_FATAL))
- _err_report_mode = ERR_DEFAULT_REPORT_MODE;
- }
-
// Call process initialization
Processor::initialize();
@@ -97,7 +67,7 @@ Common::Error Frotz::saveGameData(strid_t file) {
if ((gfp = frotzopenprompt(FILE_SAVE)) == nullptr)
goto finished;
- if (_save_quetzal) {
+ if (_quetzal) {
success = save_quetzal(gfp, story_fp, blorb_ofs);
}
else {
@@ -164,7 +134,7 @@ Common::Error Frotz::loadGameData(strid_t file) {
if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
goto finished;
- if (_save_quetzal) {
+ if (_quetzal) {
success = restore_quetzal (gfp, story_fp, blorb_ofs);
} else {
diff --git a/engines/glk/frotz/frotz_types.h b/engines/glk/frotz/frotz_types.h
index e68f55e..bf3067f 100644
--- a/engines/glk/frotz/frotz_types.h
+++ b/engines/glk/frotz/frotz_types.h
@@ -35,22 +35,6 @@ namespace Frotz {
#define lo(v) (v & 0xff)
#define hi(v) (v >> 8)
-/* There are four error reporting modes: never report errors;
- * report only the first time a given error type occurs;
- * report every time an error occurs;
- * or treat all errors as fatal errors, killing the interpreter.
- * I strongly recommend "report once" as the default. But you can compile in a
- * different default by changing the definition of ERR_DEFAULT_REPORT_MODE.
- */
-enum ErrorReport {
- ERR_REPORT_NEVER = 0,
- ERR_REPORT_ONCE = 1,
- ERR_REPORT_ALWAYS = 2,
- ERR_REPORT_FATAL = 3,
-
- ERR_DEFAULT_REPORT_MODE = ERR_REPORT_NEVER
-};
-
/**
* Character codes
*/
@@ -116,35 +100,6 @@ enum Version {
V9 = 9
};
-enum ConfigFlag {
- CONFIG_BYTE_SWAPPED = 0x01, ///< Story file is byte swapped - V3
- CONFIG_TIME = 0x02, ///< Status line displays time - V3
- CONFIG_TWODISKS = 0x04, ///< Story file occupied two disks - V3
- CONFIG_TANDY = 0x08, ///< Tandy licensed game - V3
- CONFIG_NOSTATUSLINE = 0x10, ///< Interpr can't support status lines - V3
- CONFIG_SPLITSCREEN = 0x20, ///< Interpr supports split screen mode - V3
- CONFIG_PROPORTIONAL = 0x40, ///< Interpr uses proportional font - V3
-
- CONFIG_COLOUR = 0x01, ///< Interpr supports colour - V5+
- CONFIG_PICTURES = 0x02, ///< Interpr supports pictures - V6
- CONFIG_BOLDFACE = 0x04, ///< Interpr supports boldface style - V4+
- CONFIG_EMPHASIS = 0x08, ///< Interpr supports emphasis style - V4+
- CONFIG_FIXED = 0x10, ///< Interpr supports fixed width style - V4+
- CONFIG_SOUND = 0x20, ///< Interpr supports sound - V6
- CONFIG_TIMEDINPUT = 0x80, ///< Interpr supports timed input - V4+
-
- SCRIPTING_FLAG = 0x0001, ///< Outputting to transscription file - V1+
- FIXED_FONT_FLAG = 0x0002, ///< Use fixed width font - V3+
- REFRESH_FLAG = 0x0004, ///< Refresh the screen - V6
- GRAPHICS_FLAG = 0x0008, ///< Game wants to use graphics - V5+
- OLD_SOUND_FLAG = 0x0010, ///< Game wants to use sound effects - V3
- UNDO_FLAG = 0x0010, ///< Game wants to use UNDO feature - V5+
- MOUSE_FLAG = 0x0020, ///< Game wants to use a mouse - V5+
- COLOUR_FLAG = 0x0040, ///< Game wants to use colours - V5+
- SOUND_FLAG = 0x0080, ///< Game wants to use sound effects - V5+
- MENU_FLAG = 0x0100 ///< Game wants to use menus - V6
-};
-
enum {
TRANSPARENT_FLAG = 0x0001 ///< Game wants to use transparency - V6
};
@@ -249,36 +204,6 @@ typedef byte zbyte;
typedef uint zchar;
typedef uint16 zword;
-/**
- * User options
- */
-struct UserOptions {
- int _attribute_assignment;
- int _attribute_testing;
- int _context_lines;
- int _object_locating;
- int _object_movement;
- int _left_margin;
- int _right_margin;
- bool _ignore_errors;
- bool _piracy;
- int _undo_slots;
- int _expand_abbreviations;
- int _script_cols;
- bool _save_quetzal;
- int _err_report_mode;
- bool _sound;
- bool _user_tandy_bit;
-
- UserOptions() : _attribute_assignment(0), _attribute_testing(0),
- _context_lines(0), _object_locating(0), _object_movement(0),
- _left_margin(0), _right_margin(0), _ignore_errors(false), _piracy(false),
- _undo_slots(MAX_UNDO_SLOTS), _expand_abbreviations(0), _script_cols(80),
- _save_quetzal(true), _err_report_mode(ERR_DEFAULT_REPORT_MODE), _sound(true),
- _user_tandy_bit(false) {
- }
-};
-
#define MAX_NESTING 16
struct Redirect {
zword _xSize;
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index 292409f..477891a 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -110,7 +110,7 @@ void GlkInterface::initialize() {
* Icky magic bit setting
*/
- if (h_version == V3 && _user_tandy_bit)
+ if (h_version == V3 && _tandyBit)
h_config |= CONFIG_TANDY;
if (h_version == V3 && gos_upper)
diff --git a/engines/glk/frotz/header.cpp b/engines/glk/frotz/header.cpp
deleted file mode 100644
index f7ebb5e..0000000
--- a/engines/glk/frotz/header.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/* 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.
- *
- */
-
-#include "glk/frotz/header.h"
-#include "common/textconsole.h"
-
-namespace Glk {
-namespace Frotz {
-
-const Header::StoryEntry Header::RECORDS[25] = {
- { SHERLOCK, 21, "871214" },
- { SHERLOCK, 26, "880127" },
- { BEYOND_ZORK, 47, "870915" },
- { BEYOND_ZORK, 49, "870917" },
- { BEYOND_ZORK, 51, "870923" },
- { BEYOND_ZORK, 57, "871221" },
- { ZORK_ZERO, 296, "881019" },
- { ZORK_ZERO, 366, "890323" },
- { ZORK_ZERO, 383, "890602" },
- { ZORK_ZERO, 393, "890714" },
- { SHOGUN, 292, "890314" },
- { SHOGUN, 295, "890321" },
- { SHOGUN, 311, "890510" },
- { SHOGUN, 322, "890706" },
- { ARTHUR, 54, "890606" },
- { ARTHUR, 63, "890622" },
- { ARTHUR, 74, "890714" },
- { JOURNEY, 26, "890316" },
- { JOURNEY, 30, "890322" },
- { JOURNEY, 77, "890616" },
- { JOURNEY, 83, "890706" },
- { LURKING_HORROR, 203, "870506" },
- { LURKING_HORROR, 219, "870912" },
- { LURKING_HORROR, 221, "870918" },
- { UNKNOWN, 0, "------" }
-};
-
-void Header::loadHeader(Common::SeekableReadStream &f) {
- h_version = f.readByte();
- h_config = f.readByte();
-
- if (h_version < V1 || h_version > V8)
- error("Unknown Z-code version");
-
- if (h_version == V6)
- error("Cannot play Z-code version 6");
-
- if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
- error("Byte swapped story file");
-
- h_release = f.readUint16BE();
- h_resident_size = f.readUint16BE();
- h_start_pc = f.readUint16BE();
- h_dictionary = f.readUint16BE();
- h_objects = f.readUint16BE();
- h_globals = f.readUint16BE();
- h_dynamic_size = f.readUint16BE();
- h_flags = f.readUint16BE();
- f.read(h_serial, 6);
-
- /* Auto-detect buggy story files that need special fixes */
- _storyId = UNKNOWN;
-
- for (int i = 0; RECORDS[i]._storyId != UNKNOWN; ++i) {
- if (h_release == RECORDS[i]._release) {
- if (!strncmp((const char *)h_serial, RECORDS[i]._serial, 6)) {
- _storyId = RECORDS[i]._storyId;
- break;
- }
- }
- }
-
- h_abbreviations = f.readUint16BE();
- h_file_size = f.readUint16BE();
- h_checksum = f.readUint16BE();
-
- f.seek(H_FUNCTIONS_OFFSET);
- h_functions_offset = f.readUint16BE();
- h_strings_offset = f.readUint16BE();
- f.seek(H_TERMINATING_KEYS);
- h_terminating_keys = f.readUint16BE();
- f.seek(H_ALPHABET);
- h_alphabet = f.readUint16BE();
- h_extension_table = f.readUint16BE();
-
-
- // Zork Zero Macintosh doesn't have the graphics flag set
- if (_storyId == ZORK_ZERO && h_release == 296)
- h_flags |= GRAPHICS_FLAG;
-}
-
-} // End of namespace Scott
-} // End of namespace Glk
diff --git a/engines/glk/frotz/header.h b/engines/glk/frotz/header.h
deleted file mode 100644
index cf7ab64..0000000
--- a/engines/glk/frotz/header.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* 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_FROTZ_HEADER
-#define GLK_FROTZ_HEADER
-
-#include "glk/frotz/frotz_types.h"
-
-namespace Glk {
-namespace Frotz {
-
-enum HeaderByte {
- H_VERSION = 0,
- H_CONFIG = 1,
- H_RELEASE = 2,
- H_RESIDENT_SIZE = 4,
- H_START_PC = 6,
- H_DICTIONARY = 8,
- H_OBJECTS = 10,
- H_GLOBALS = 12,
- H_DYNAMIC_SIZE = 14,
- H_FLAGS = 16,
- H_SERIAL = 18,
- H_ABBREVIATIONS = 24,
- H_FILE_SIZE = 26,
- H_CHECKSUM = 28,
- H_INTERPRETER_NUMBER = 30,
- H_INTERPRETER_VERSION = 31,
- H_SCREEN_ROWS = 32,
- H_SCREEN_COLS = 33,
- H_SCREEN_WIDTH = 34,
- H_SCREEN_HEIGHT = 36,
- H_FONT_HEIGHT = 38, ///< this is the font width in V5
- H_FONT_WIDTH = 39, ///< this is the font height in V5
- H_FUNCTIONS_OFFSET = 40,
- H_STRINGS_OFFSET = 42,
- H_DEFAULT_BACKGROUND = 44,
- H_DEFAULT_FOREGROUND = 45,
- H_TERMINATING_KEYS = 46,
- H_LINE_WIDTH = 48,
- H_STANDARD_HIGH = 50,
- H_STANDARD_LOW = 51,
- H_ALPHABET = 52,
- H_EXTENSION_TABLE = 54,
- H_USER_NAME = 56
-};
-
-enum {
- HX_TABLE_SIZE = 0,
- HX_MOUSE_X = 1,
- HX_MOUSE_Y = 2,
- HX_UNICODE_TABLE = 3,
- HX_FLAGS = 4,
- HX_FORE_COLOUR = 5,
- HX_BACK_COLOUR = 6
-};
-
-/**
- * Story file header data
- */
-struct Header {
-private:
- struct StoryEntry {
- Story _storyId;
- zword _release;
- char _serial[7];
- };
- static const StoryEntry RECORDS[25];
-public:
- zbyte h_version;
- zbyte h_config;
- zword h_release;
- zword h_resident_size;
- zword h_start_pc;
- zword h_dictionary;
- zword h_objects;
- zword h_globals;
- zword h_dynamic_size;
- zword h_flags;
- zbyte h_serial[6];
- zword h_abbreviations;
- zword h_file_size;
- zword h_checksum;
- zbyte h_interpreter_number;
- zbyte h_interpreter_version;
- zbyte h_screen_rows;
- zbyte h_screen_cols;
- zword h_screen_width;
- zword h_screen_height;
- zbyte h_font_height;
- zbyte h_font_width;
- zword h_functions_offset;
- zword h_strings_offset;
- zbyte h_default_background;
- zbyte h_default_foreground;
- zword h_terminating_keys;
- zword h_line_width;
- zbyte h_standard_high;
- zbyte h_standard_low;
- zword h_alphabet;
- zword h_extension_table;
- zbyte h_user_name[8];
-
- zword hx_table_size;
- zword hx_mouse_x;
- zword hx_mouse_y;
- zword hx_unicode_table;
- zword hx_flags;
- zword hx_fore_colour;
- zword hx_back_colour;
-
- Story _storyId;
-
- /**
- * Constructor
- */
- Header() : h_version(0), h_config(0), h_release(0), h_resident_size(0), h_start_pc(0),
- h_dictionary(0), h_objects(0), h_globals(0), h_dynamic_size(0), h_flags(0),
- h_abbreviations(0), h_file_size(0), h_checksum(0), h_interpreter_number(0),
- h_interpreter_version(0), h_screen_rows(0), h_screen_cols(0), h_screen_width(0),
- h_screen_height(0), h_font_height(1), h_font_width(1), h_functions_offset(0),
- h_strings_offset(0), h_default_background(0), h_default_foreground(0),
- h_terminating_keys(0), h_line_width(0), h_standard_high(1), h_standard_low(1),
- h_alphabet(0), h_extension_table(0),
- hx_table_size(0), hx_mouse_x(0), hx_mouse_y(0), hx_unicode_table(0),
- hx_flags(0), hx_fore_colour(0), hx_back_colour(0), _storyId(UNKNOWN) {
- Common::fill(&h_serial[0], &h_serial[6], '\0');
- Common::fill(&h_user_name[0], &h_user_name[8], '\0');
- }
-
- /**
- * Load the header
- */
- void loadHeader(Common::SeekableReadStream &f);
-};
-
-} // End of namespace Frotz
-} // End of namespace Glk
-
-#endif
diff --git a/engines/glk/frotz/mem.h b/engines/glk/frotz/mem.h
index 3b1b81b..d973890 100644
--- a/engines/glk/frotz/mem.h
+++ b/engines/glk/frotz/mem.h
@@ -24,7 +24,7 @@
#define GLK_FROTZ_MEM
#include "glk/frotz/frotz_types.h"
-#include "glk/frotz/header.h"
+#include "glk/frotz/config.h"
namespace Glk {
namespace Frotz {
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index 343299e..09eb82b 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -304,7 +304,7 @@ void Processor::call(zword routine, int argc, zword *args, int ct) {
*--_sp = (zword)(pc >> 9);
*--_sp = (zword)(pc & 0x1ff);
*--_sp = (zword)(_fp - _stack - 1);
- *--_sp = (zword)(argc | (ct << (_save_quetzal ? 12 : 8)));
+ *--_sp = (zword)(argc | (ct << (_quetzal ? 12 : 8)));
_fp = _sp;
_frameCount++;
@@ -337,7 +337,7 @@ void Processor::call(zword routine, int argc, zword *args, int ct) {
if (_sp - _stack < count)
runtimeError(ERR_STK_OVF);
- if (_save_quetzal)
+ if (_quetzal)
_fp[0] |= (zword)count << 8; // Save local var count for Quetzal.
value = 0;
@@ -363,7 +363,7 @@ void Processor::ret(zword value) {
_sp = _fp;
- ct = *_sp++ >> (_save_quetzal ? 12 : 8);
+ ct = *_sp++ >> (_quetzal ? 12 : 8);
_frameCount--;
_fp = _stack + 1 + *_sp++;
pc = *_sp++;
@@ -496,11 +496,11 @@ void Processor::__illegal__() {
}
void Processor::z_catch() {
- store(_save_quetzal ? _frameCount : (zword)(_fp - _stack));
+ store(_quetzal ? _frameCount : (zword)(_fp - _stack));
}
void Processor::z_throw() {
- if (_save_quetzal) {
+ if (_quetzal) {
if (zargs[1] > _frameCount)
runtimeError(ERR_BAD_FRAME);
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 10cef32..eedab57 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -21,10 +21,10 @@ MODULE_OBJS := \
window_pair.o \
window_text_buffer.o \
window_text_grid.o \
+ frotz/config.o \
frotz/detection.o \
frotz/frotz.o \
frotz/glk_interface.o \
- frotz/header.o \
frotz/mem.o \
frotz/processor.o \
frotz/processor_buffer.o \
Commit: 2a3e6c49bf6d664d7c91dd17e41e97f042f70206
https://github.com/scummvm/scummvm/commit/2a3e6c49bf6d664d7c91dd17e41e97f042f70206
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Set up default Frotz white on blue screen colors
Changed paths:
engines/glk/frotz/config.cpp
engines/glk/frotz/config.h
engines/glk/frotz/frotz.cpp
diff --git a/engines/glk/frotz/config.cpp b/engines/glk/frotz/config.cpp
index 0461e25..21cfb03 100644
--- a/engines/glk/frotz/config.cpp
+++ b/engines/glk/frotz/config.cpp
@@ -161,36 +161,10 @@ UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true) {
_attribute_testing = getConfigBool("attribute_testing");
_object_locating = getConfigBool("object_locating");
_object_movement = getConfigBool("object_movement");
-}
-#ifdef REMOVE_ME
-if (ConfMan.hasKey("attribute_assignment") && ConfMan.getBool("attribute_assignment"))
-_attribute_assignment = true;
-if (ConfMan.hasKey("attribute_testing") && ConfMan.getBool("attribute_testing"))
-_attribute_testing = true;
-if (ConfMan.hasKey("object_movement") && ConfMan.getBool("object_movement"))
-_object_movement = true;
-if (ConfMan.hasKey("object_locating") && ConfMan.getBool("object_locating"))
-_object_locating = true;
-if (ConfMan.hasKey("piracy") && ConfMan.getBool("piracy"))
-_piracy = true;
-if (ConfMan.hasKey("random_seed"))
-_random.setSeed(ConfMan.getInt("random_seed"));
-if (ConfMan.hasKey("script_cols"))
-_script_cols = ConfMan.getInt("script_cols");
-if (ConfMan.hasKey("tandy_bit") && ConfMan.getBool("tandy_bit"))
-_user_tandy_bit = true;
-if (ConfMan.hasKey("undo_slots"))
-_undo_slots = ConfMan.getInt("undo_slots");
-if (ConfMan.hasKey("expand_abbreviations") && ConfMan.getBool("expand_abbreviations"))
-_expand_abbreviations = true;
-if (ConfMan.hasKey("err_report_mode")) {
- _err_report_mode = ConfMan.getInt("err_report_mode");
- if ((_err_report_mode < ERR_REPORT_NEVER) || (_err_report_mode > ERR_REPORT_FATAL))
- _err_report_mode = ERR_DEFAULT_REPORT_MODE;
+ _defaultForeground = getConfigInt("foreground", 0xffffff, 0xffffff);
+ _defaultBackground = getConfigInt("background", 0x000080, 0xffffff);
}
-#endif
-
} // End of namespace Scott
} // End of namespace Glk
diff --git a/engines/glk/frotz/config.h b/engines/glk/frotz/config.h
index a210ba2..17e787d 100644
--- a/engines/glk/frotz/config.h
+++ b/engines/glk/frotz/config.h
@@ -148,6 +148,8 @@ struct UserOptions {
int _undo_slots;
int _script_cols;
int _err_report_mode;
+ uint _defaultForeground;
+ uint _defaultBackground;
/**
* Constructor
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 5828790..6b79cfa 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -50,6 +50,9 @@ void Frotz::initialize() {
// Call process initialization
Processor::initialize();
+ // Set the screen colors
+ garglk_set_zcolors(_defaultForeground, _defaultBackground);
+
// Restart the game
z_restart();
}
Commit: dfe497cb79b52a4835700f806e5eb5a17543dd37
https://github.com/scummvm/scummvm/commit/dfe497cb79b52a4835700f806e5eb5a17543dd37
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Move setting default colors to GlkInterface
Changed paths:
engines/glk/frotz/frotz.cpp
engines/glk/frotz/glk_interface.cpp
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 6b79cfa..5828790 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -50,9 +50,6 @@ void Frotz::initialize() {
// Call process initialization
Processor::initialize();
- // Set the screen colors
- garglk_set_zcolors(_defaultForeground, _defaultBackground);
-
// Restart the game
z_restart();
}
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index 477891a..a8b25a2 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -106,6 +106,9 @@ void GlkInterface::initialize() {
glk_set_window(gos_lower);
gos_curwin = gos_lower;
+ // Set the screen colors
+ garglk_set_zcolors(_defaultForeground, _defaultBackground);
+
/*
* Icky magic bit setting
*/
@@ -148,13 +151,13 @@ void GlkInterface::initialize() {
h_font_width = 1;
h_font_height = 1;
- /* Must be after screen dimensions are computed. */
+ // Must be after screen dimensions are computed
if (h_version == V6) {
h_flags &= ~GRAPHICS_FLAG;
}
// Use the ms-dos interpreter number for v6, because that's the
- // kind of graphics files we understand. Otherwise, use DEC.
+ // kind of graphics files we understand
h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_AMIGA;
h_interpreter_version = 'F';
Commit: 9bc637947603643c02b27a5c0954564811603bd7
https://github.com/scummvm/scummvm/commit/9bc637947603643c02b27a5c0954564811603bd7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Change lots of comments from multiline to single line
Changed paths:
engines/glk/blorb.h
engines/glk/frotz/frotz.cpp
engines/glk/frotz/mem.cpp
engines/glk/frotz/processor_screen.cpp
engines/glk/frotz/processor_table.cpp
engines/glk/frotz/processor_text.cpp
engines/glk/streams.cpp
engines/glk/unicode.cpp
engines/glk/unicode.h
engines/glk/window_graphics.cpp
engines/glk/window_pair.h
engines/glk/window_text_buffer.h
engines/glk/windows.cpp
diff --git a/engines/glk/blorb.h b/engines/glk/blorb.h
index 352d01a..ae9c503 100644
--- a/engines/glk/blorb.h
+++ b/engines/glk/blorb.h
@@ -85,7 +85,9 @@ enum {
*/
typedef struct giblorb_map_struct giblorb_map_t;
-/* giblorb_result_t: Result when you try to load a chunk. */
+/**
+ * giblorb_result_t: Result when you try to load a chunk.
+ */
typedef struct giblorb_result_struct {
glui32 chunknum; // The chunk number (for use in giblorb_unload_chunk(), etc.)
union {
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 5828790..95cdb22 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -62,7 +62,7 @@ Common::Error Frotz::saveGameData(strid_t file) {
int skip;
int i;
- /* Open game file */
+ // Open game file
if ((gfp = frotzopenprompt(FILE_SAVE)) == nullptr)
goto finished;
@@ -71,7 +71,7 @@ Common::Error Frotz::saveGameData(strid_t file) {
success = save_quetzal(gfp, story_fp, blorb_ofs);
}
else {
- /* Write game file */
+ // Write game file
fputc((int)hi(h_release), gfp);
fputc((int)lo(h_release), gfp);
@@ -108,15 +108,14 @@ Common::Error Frotz::saveGameData(strid_t file) {
else skip++;
}
- /* Close game file and check for errors */
+ // Close game file and check for errors
if (fclose(gfp) == EOF || ferror(story_fp)) {
print_string("Error writing save file\n");
goto finished;
}
- /* Success */
-
+ // Success
success = 1;
#endif
return Common::kNoError;
@@ -129,8 +128,7 @@ Common::Error Frotz::loadGameData(strid_t file) {
zword addr;
int i;
- /* Open game file */
-
+ // Open game file
if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
goto finished;
@@ -138,7 +136,7 @@ Common::Error Frotz::loadGameData(strid_t file) {
success = restore_quetzal (gfp, story_fp, blorb_ofs);
} else {
- /* Load game file */
+ // Load game file
release = (unsigned) fgetc (gfp) << 8;
release |= fgetc (gfp);
@@ -146,8 +144,7 @@ Common::Error Frotz::loadGameData(strid_t file) {
() fgetc (gfp);
() fgetc (gfp);
- /* Check the release number */
-
+ // Check the release number
if (release == h_release) {
pc = (long) fgetc (gfp) << 16;
@@ -176,14 +173,12 @@ Common::Error Frotz::loadGameData(strid_t file) {
() fgetc (story_fp);
}
- /* Check for errors */
-
+ // Check for errors
if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
success = -1;
else
- /* Success */
-
+ // Success
success = 2;
} else print_string ("Invalid save file\n");
@@ -191,15 +186,14 @@ Common::Error Frotz::loadGameData(strid_t file) {
if ((short) success >= 0) {
- /* Close game file */
-
+ // Close game file
fclose (gfp);
if ((short) success > 0) {
zbyte old_screen_rows;
zbyte old_screen_cols;
- /* In V3, reset the upper window. */
+ // In V3, reset the upper window.
if (h_version == V3)
split_window (0);
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index da0acaa..12e860a 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -176,8 +176,8 @@ void Mem::restart_header(void) {
SET_BYTE(H_SCREEN_COLS, h_screen_cols);
}
- /* It's less trouble to use font size 1x1 for V5 games, especially
- because of a bug in the unreleased German version of "Zork 1" */
+ // It's less trouble to use font size 1x1 for V5 games, especially because of
+ // a bug in the unreleased German version of "Zork 1"
if (h_version != V6) {
screen_x_size = (zword)h_screen_cols;
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index c0d8ca1..6ee7f1d 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -312,7 +312,8 @@ void Processor::z_set_font() {
store (curr_font);
break;
- case 1: /* normal font */
+ case 1:
+ // normal font
prev_font = curr_font;
curr_font = 1;
zargs[0] = 0xf000; // tickle tickle!
@@ -320,7 +321,8 @@ void Processor::z_set_font() {
store (prev_font);
break;
- case 4: /* fixed-pitch font*/
+ case 4:
+ // fixed-pitch font
prev_font = curr_font;
curr_font = 4;
zargs[0] = 0xf000; // tickle tickle!
@@ -355,7 +357,8 @@ void Processor::z_set_text_style() {
if (zargs[0] == 0)
curstyle = 0;
- else if (zargs[0] != 0xf000) /* not tickle time */
+ else if (zargs[0] != 0xf000)
+ // not tickle time
curstyle |= zargs[0];
if (h_flags & FIXED_FONT_FLAG || curr_font == 4)
diff --git a/engines/glk/frotz/processor_table.cpp b/engines/glk/frotz/processor_table.cpp
index c586355..57afc76 100644
--- a/engines/glk/frotz/processor_table.cpp
+++ b/engines/glk/frotz/processor_table.cpp
@@ -31,17 +31,17 @@ void Processor::z_copy_table() {
zbyte value;
int i;
- if (zargs[1] == 0) /* zero table */
-
- for (i = 0; i < size; i++)
- storeb((zword) (zargs[0] + i), 0);
-
- else if ((short) size < 0 || zargs[0] > zargs[1]) /* copy forwards */
-
- for (i = 0; i < (((short) size < 0) ? - (short) size : size); i++) {
- addr = zargs[0] + i;
- LOW_BYTE(addr, value);
- storeb((zword) (zargs[1] + i), value);
+ if (zargs[1] == 0) {
+ // zero table
+ for (i = 0; i < size; i++)
+ storeb((zword)(zargs[0] + i), 0);
+ } else if ((short) size < 0 || zargs[0] > zargs[1]) {
+ // copy forwards
+ for (i = 0; i < (((short)size < 0) ? -(short)size : size); i++) {
+ addr = zargs[0] + i;
+ LOW_BYTE(addr, value);
+ storeb((zword)(zargs[1] + i), value);
+ }
} else {
// copy backwards
for (i = size - 1; i >= 0; i--) {
diff --git a/engines/glk/frotz/processor_text.cpp b/engines/glk/frotz/processor_text.cpp
index 3cfe50b..abb0430 100644
--- a/engines/glk/frotz/processor_text.cpp
+++ b/engines/glk/frotz/processor_text.cpp
@@ -444,15 +444,13 @@ void Processor::decode_text(enum string_type st, zword addr) {
void Processor::print_num(zword value) {
int i;
- /* Print sign */
-
+ // Print sign
if ((short)value < 0) {
print_char('-');
value = -(short)value;
}
- /* Print absolute value */
-
+ // Print absolute value
for (i = 10000; i != 0; i /= 10)
if (value >= i || i == 1)
print_char('0' + (value / i) % 10);
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index b491b89..911f6d9 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -652,7 +652,7 @@ glui32 MemoryStream::getLine(char *buf, glui32 len) {
if (len == 0)
return 0;
- len -= 1; /* for the terminal null */
+ len -= 1; // for the terminal null
if (!_unicode) {
if (_bufPtr >= _bufEnd) {
len = 0;
@@ -1294,7 +1294,7 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) {
ubuf[lx] = '\0';
return lx;
} else if (_textFile) {
- len -= 1; /* for the terminal null */
+ len -= 1; // for the terminal null
gotNewline = false;
for (lx = 0; lx < (int)len && !gotNewline; lx++) {
glui32 ch;
diff --git a/engines/glk/unicode.cpp b/engines/glk/unicode.cpp
index d9f2ee1..909f4ee 100644
--- a/engines/glk/unicode.cpp
+++ b/engines/glk/unicode.cpp
@@ -93,7 +93,7 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
}
if (res != 0xFFFFFFFF || res == ch) {
- /* simple case */
+ // simple case
if (outcount < len)
outbuf[outcount] = res;
outcount++;
@@ -102,7 +102,7 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
target = (isfirst ? dest_spec_first : dest_spec_rest);
- /* complicated cases */
+ // complicated cases
GET_CASE_SPECIAL(ch, &special);
if (!special) {
warning("inconsistency in cgunigen.c");
@@ -112,7 +112,7 @@ glui32 bufferChangeCase(glui32 *buf, glui32 len, glui32 numchars, BufferChangeCa
speccount = *(ptr++);
if (speccount == 1) {
- /* simple after all */
+ // simple after all
if (outcount < len)
outbuf[outcount] = ptr[0];
outcount++;
diff --git a/engines/glk/unicode.h b/engines/glk/unicode.h
index 3165d39..f49a841 100644
--- a/engines/glk/unicode.h
+++ b/engines/glk/unicode.h
@@ -27,7 +27,7 @@
namespace Glk {
-typedef glui32 gli_case_block_t[2]; /* upper, lower */
+typedef glui32 gli_case_block_t[2]; // upper, lower
enum BufferChangeCase { CASE_UPPER = 0, CASE_LOWER = 1, CASE_TITLE = 2, CASE_IDENT = 3 };
enum BufferChangeCond { COND_ALL = 0, COND_LINESTART = 1 };
diff --git a/engines/glk/window_graphics.cpp b/engines/glk/window_graphics.cpp
index f81313e..b18e2b2 100644
--- a/engines/glk/window_graphics.cpp
+++ b/engines/glk/window_graphics.cpp
@@ -143,7 +143,7 @@ void GraphicsWindow::eraseRect(bool whole, const Rect &box) {
hy0 = _bbox.top + y0;
hy1 = _bbox.top + y1;
- /* zero out hyperlinks for these coordinates */
+ // zero out hyperlinks for these coordinates
g_vm->_selection->putHyperlink(0, hx0, hy0, hx1, hy1);
_surface->fillRect(Rect(x0, y0, x1, y1), MKTAG(_bgnd[0], _bgnd[1], _bgnd[2], 0));
@@ -173,7 +173,7 @@ void GraphicsWindow::fillRect(glui32 color, const Rect &box) {
hy0 = _bbox.top + y0;
hy1 = _bbox.top + y1;
- /* zero out hyperlinks for these coordinates */
+ // zero out hyperlinks for these coordinates
g_vm->_selection->putHyperlink(0, hx0, hy0, hx1, hy1);
_surface->fillRect(Rect(x0, y0, x1, y1), MKTAG(col[0], col[1], col[2], 0));
@@ -225,7 +225,7 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
hy0 = _bbox.top + y0;
hy1 = _bbox.top + y1;
- /* zero out or set hyperlink for these coordinates */
+ // zero out or set hyperlink for these coordinates
g_vm->_selection->putHyperlink(linkval, hx0, hy0, hx1, hy1);
w = sx1 - sx0;
diff --git a/engines/glk/window_pair.h b/engines/glk/window_pair.h
index dabae77..b588192 100644
--- a/engines/glk/window_pair.h
+++ b/engines/glk/window_pair.h
@@ -34,7 +34,7 @@ class PairWindow : public Window {
public:
Window *_child1, *_child2;
- /* split info... */
+ // split info...
glui32 _dir; ///< winmethod_Left, Right, Above, or Below
bool _vertical, _backward; ///< flags
glui32 _division; ///< winmethod_Fixed or winmethod_Proportional
diff --git a/engines/glk/window_text_buffer.h b/engines/glk/window_text_buffer.h
index 728919f..86b0319 100644
--- a/engines/glk/window_text_buffer.h
+++ b/engines/glk/window_text_buffer.h
@@ -107,17 +107,17 @@ public:
int _radjw;
int _radjn;
- /* Command history. */
+ // Command history.
Common::Array<Common::U32String> _history;
int _historyPos;
int _historyFirst, _historyPresent;
- /* for paging */
+ // for paging
int _lastSeen;
int _scrollPos;
int _scrollMax;
- /* for line input */
+ // for line input
void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
int _inMax;
long _inFence;
@@ -128,10 +128,10 @@ public:
glui32 _echoLineInput;
glui32 *_lineTerminators;
- /* style hints and settings */
+ // style hints and settings
WindowStyle _styles[style_NUMSTYLES];
- /* for copy selection */
+ // for copy selection
glui32 *_copyBuf;
int _copyPos;
public:
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
index 4db231c..1e53f25 100644
--- a/engines/glk/windows.cpp
+++ b/engines/glk/windows.cpp
@@ -88,7 +88,7 @@ Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
return nullptr;
}
- /* ignore method and size now */
+ // ignore method and size now
oldparent = nullptr;
} else {
if (!splitwin) {
Commit: 0f0b8ae3b72d066259332a728eab1edc760de5df
https://github.com/scummvm/scummvm/commit/0f0b8ae3b72d066259332a728eab1edc760de5df
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Don't have a Y margin above title bar
Changed paths:
engines/glk/conf.cpp
engines/glk/conf.h
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/glk_types.h
diff --git a/engines/glk/conf.cpp b/engines/glk/conf.cpp
index ae99e6b..89b08fb 100644
--- a/engines/glk/conf.cpp
+++ b/engines/glk/conf.cpp
@@ -64,7 +64,7 @@ WindowStyle G_STYLES[style_NUMSTYLES] = {
Conf *g_conf;
-Conf::Conf() {
+Conf::Conf(InterpreterType interpType) {
g_conf = this;
_imageW = g_system->getWidth();
_imageH = g_system->getHeight();
@@ -108,10 +108,13 @@ Conf::Conf() {
if (ConfMan.hasKey("maxcols"))
_cols = MIN(_cols, strToInt(ConfMan.get("maxcols").c_str()));
+ const int DEFAULT_MARGIN_X = (interpType == INTERPRETER_FROTZ) ? 2 : 15;
+ const int DEFAULT_MARGIN_Y = (interpType == INTERPRETER_FROTZ) ? 0 : 15;
+
get("lockrows", _lockRows);
get("lockcols", _lockCols);
- get("wmarginx", _wMarginX, 15);
- get("wmarginy", _wMarginY, 15);
+ get("wmarginx", _wMarginX, DEFAULT_MARGIN_X);
+ get("wmarginy", _wMarginY, DEFAULT_MARGIN_Y);
_wMarginSaveX = _wMarginX;
_wMarginSaveY = _wMarginY;
diff --git a/engines/glk/conf.h b/engines/glk/conf.h
index fb68427..bf68e34 100644
--- a/engines/glk/conf.h
+++ b/engines/glk/conf.h
@@ -29,6 +29,11 @@
namespace Glk {
+
+
+/**
+ * Engine configuration
+ */
class Conf {
private:
/**
@@ -126,7 +131,7 @@ public:
/**
* Constructor
*/
- Conf();
+ Conf(InterpreterType interpType);
};
extern Conf *g_conf;
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 9488c66..0c90fc7 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -68,7 +68,7 @@ void GlkEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphicsMode();
- _conf = new Conf();
+ _conf = new Conf(getInterpreterType());
_screen = new Screen();
_clipboard = new Clipboard();
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 63b5727..8f973f0 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -43,24 +43,6 @@ class Selection;
class Streams;
class Windows;
-enum InterpreterType {
- INTERPRETER_ADVSYS = 0,
- INTERPRETER_AGILITY = 1,
- INTERPRETER_ALAN2 = 2,
- INTERPRETER_ALAN3 = 3,
- INTERPRETER_BOCFEL = 4,
- INTERPRETER_FROTZ = 5,
- INTERPRETER_GEAS = 6,
- INTERPRETER_HUGO = 7,
- INTERPRETER_JACL = 8,
- INTERPRETER_LEVEL9 = 9,
- INTERPRETER_MAGNETIC = 10,
- INTERPRETER_NITFOL = 11,
- INTERPRETER_SCARE = 12,
- INTERPRETER_SCOTT = 13,
- INTERPRETER_TADS = 14
-};
-
enum GlkDebugChannels {
kDebugCore = 1 << 0,
kDebugScripts = 1 << 1,
diff --git a/engines/glk/glk_types.h b/engines/glk/glk_types.h
index 1745178..4ac9566 100644
--- a/engines/glk/glk_types.h
+++ b/engines/glk/glk_types.h
@@ -33,6 +33,27 @@ typedef int32 glsi32;
class Window;
/**
+ * List of the different sub-engines the engine will likely eventually support
+ */
+enum InterpreterType {
+ INTERPRETER_ADVSYS = 0,
+ INTERPRETER_AGILITY = 1,
+ INTERPRETER_ALAN2 = 2,
+ INTERPRETER_ALAN3 = 3,
+ INTERPRETER_BOCFEL = 4,
+ INTERPRETER_FROTZ = 5,
+ INTERPRETER_GEAS = 6,
+ INTERPRETER_HUGO = 7,
+ INTERPRETER_JACL = 8,
+ INTERPRETER_LEVEL9 = 9,
+ INTERPRETER_MAGNETIC = 10,
+ INTERPRETER_NITFOL = 11,
+ INTERPRETER_SCARE = 12,
+ INTERPRETER_SCOTT = 13,
+ INTERPRETER_TADS = 14
+};
+
+/**
* These are the compile-time conditionals that reveal various Glk optional modules.
*/
#define GLK_MODULE_LINE_ECHO
Commit: bd86fd7bbf19324e06834ee8f2e08e7e0df02e14
https://github.com/scummvm/scummvm/commit/bd86fd7bbf19324e06834ee8f2e08e7e0df02e14
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Implementing picture loading
Changed paths:
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/glk_api.cpp
engines/glk/picture.cpp
engines/glk/picture.h
engines/glk/window_graphics.cpp
engines/glk/window_text_buffer.cpp
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 0c90fc7..0e44f04 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -43,7 +43,7 @@ GlkEngine *g_vm;
GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription &gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Glk"), _clipboard(nullptr),
- _conf(nullptr), _events(nullptr), _picList(nullptr), _screen(nullptr),
+ _conf(nullptr), _events(nullptr), _pictures(nullptr), _screen(nullptr),
_selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
@@ -53,7 +53,7 @@ GlkEngine::~GlkEngine() {
delete _clipboard;
delete _conf;
delete _events;
- delete _picList;
+ delete _pictures;
delete _screen;
delete _selection;
delete _streams;
@@ -73,7 +73,7 @@ void GlkEngine::initialize() {
_clipboard = new Clipboard();
_events = new Events();
- _picList = new PicList();
+ _pictures = new Pictures();
_selection = new Selection();
_streams = new Streams();
_windows = new Windows(_screen);
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 8f973f0..50722ae 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -37,7 +37,7 @@ namespace Glk {
class Clipboard;
class Conf;
class Events;
-class PicList;
+class Pictures;
class Screen;
class Selection;
class Streams;
@@ -96,7 +96,7 @@ public:
Clipboard *_clipboard;
Conf *_conf;
Events *_events;
- PicList *_picList;
+ Pictures *_pictures;
Screen *_screen;
Selection *_selection;
Streams *_streams;
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index e04040f..ec98ab6 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -924,7 +924,7 @@ glui32 GlkAPI::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
if (!g_conf->_graphics)
return false;
- Picture *pic = Picture::load(image);
+ Picture *pic = g_vm->_pictures->load(image);
if (!pic)
return false;
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index b87b129..8461983 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -21,15 +21,109 @@
*/
#include "glk/picture.h"
+#include "common/file.h"
+#include "image/jpeg.h"
+#include "image/png.h"
namespace Glk {
-void PicList::increment() {
- // TODO
+void Pictures::clear() {
+ for (uint idx = 0; idx < _store.size(); ++idx) {
+ delete _store[idx]._picture;
+ delete _store[idx]._scaled;
+ }
+
+ _store.clear();
+}
+
+void Pictures::increment() {
+ ++_refCount;
+}
+
+void Pictures::decrement() {
+ if (_refCount > 0 && --_refCount == 0)
+ clear();
+}
+
+PictureEntry *Pictures::search(uint id) {
+ Picture *pic;
+
+ for (uint idx = 0; idx < _store.size(); ++idx) {
+ pic = _store[idx]._picture;
+
+ if (pic && pic->_id == id)
+ return &_store[idx];
+ }
+
+ return nullptr;
+}
+
+void Pictures::storeOriginal(Picture *pic) {
+ PictureEntry newPic;
+ newPic._picture = pic;
+
+ _store.push_back(newPic);
+}
+
+void Pictures::storeScaled(Picture *pic) {
+ PictureEntry *entry = search(pic->_id);
+ if (!entry)
+ return;
+
+ delete entry->_scaled;
+ entry->_scaled = pic;
}
-void PicList::decrement() {
- // TODO
+void Pictures::store(Picture *pic) {
+ if (!pic)
+ return;
+
+ if (!pic->_scaled)
+ storeOriginal(pic);
+ else
+ storeScaled(pic);
+}
+
+Picture *Pictures::retrieve(uint id, bool scaled) {
+ Picture *pic;
+
+ for (uint idx = 0; idx < _store.size(); ++idx) {
+ pic = scaled ? _store[idx]._scaled : _store[idx]._picture;
+
+ if (pic && pic->_id == id)
+ return pic;
+ }
+
+ return nullptr;
+}
+
+Picture *Pictures::load(uint32 id) {
+ ::Image::PNGDecoder png;
+ ::Image::JPEGDecoder jpg;
+ const Graphics::Surface *img;
+ Picture *pic;
+
+ // Check if the picture is already in the store
+ pic = retrieve(id, false);
+ if (pic)
+ return pic;
+
+ Common::File f;
+ if (f.open(Common::String::format("PIC%lu.png", id))) {
+ png.loadStream(f);
+ img = png.getSurface();
+ } else if (f.open(Common::String::format("PIC%lu.jpg", id))) {
+ jpg.loadStream(f);
+ img = jpg.getSurface();
+ }
+
+ pic = new Picture();
+ pic->_refCount = 1;
+ pic->_id = id;
+ pic->_scaled = false;
+
+ store(pic);
+ return pic;
}
/*--------------------------------------------------------------------------*/
@@ -40,16 +134,11 @@ void Picture::increment() {
void Picture::decrement() {
if (_refCount > 0 && --_refCount == 0) {
- free();
+ // No longer any references to this picture, so remove it
delete this;
}
}
-Picture *Picture::load(uint32 id) {
- // TODO: gli_picture_load
- return nullptr;
-}
-
Picture *Picture::scale(int sx, int sy) {
// TODO: gli_picture_scale
return nullptr;
diff --git a/engines/glk/picture.h b/engines/glk/picture.h
index 3ca615b..ca4f999 100644
--- a/engines/glk/picture.h
+++ b/engines/glk/picture.h
@@ -23,20 +23,15 @@
#ifndef GLK_PICTURE_H
#define GLK_PICTURE_H
-#include "graphics/surface.h"
+#include "common/array.h"
+#include "graphics/managed_surface.h"
namespace Glk {
-class PicList {
-public:
- void increment();
-
- void decrement();
-};
-
-struct Picture : Graphics::Surface {
-public:
- static Picture *load(uint32 id);
+/**
+ * Picture/image class
+ */
+struct Picture : Graphics::ManagedSurface {
public:
int _refCount;
uint32 _id;
@@ -45,7 +40,7 @@ public:
/**
* Constructor
*/
- Picture() : Graphics::Surface(), _refCount(0), _id(0), _scaled(0) {}
+ Picture() : Graphics::ManagedSurface(), _refCount(0), _id(0), _scaled(0) {}
/**
* Increment reference counter
@@ -68,6 +63,79 @@ public:
void drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1);
};
+/**
+ * Picture entry in the in-memory store
+ */
+struct PictureEntry {
+ Picture *_picture;
+ Picture *_scaled;
+ PictureEntry() : _picture(nullptr), _scaled(nullptr) {}
+};
+
+/**
+ * Pictures manager
+ */
+class Pictures {
+private:
+ int _refCount;
+ Common::Array<PictureEntry> _store;
+private:
+ /**
+ * Stores an original picture in the store
+ */
+ void storeOriginal(Picture *pic);
+
+ /**
+ * Stores a scaled picture in the store
+ */
+ void storeScaled(Picture *pic);
+public:
+ /**
+ * Constructor
+ */
+ Pictures() : _refCount(0) {}
+
+ /**
+ * Destructor
+ */
+ ~Pictures() { clear(); }
+
+ /**
+ * Clear the picture list
+ */
+ void clear();
+
+ /**
+ * Increments the count of the number of pictures in use
+ */
+ void increment();
+
+ /**
+ * Decrements the count of the number of pictures in use
+ */
+ void decrement();
+
+ /**
+ * Searches for an existing picture entry
+ */
+ PictureEntry *search(uint id);
+
+ /**
+ * Stores a picture in the store
+ */
+ void store(Picture *pic);
+
+ /**
+ * Retrieves a picture from the store
+ */
+ Picture *retrieve(uint id, bool scaled);
+
+ /**
+ * Load a given picture
+ */
+ Picture *load(uint32 id);
+};
+
} // End of namespace Glk
#endif
diff --git a/engines/glk/window_graphics.cpp b/engines/glk/window_graphics.cpp
index b18e2b2..13e6645 100644
--- a/engines/glk/window_graphics.cpp
+++ b/engines/glk/window_graphics.cpp
@@ -96,14 +96,14 @@ void GraphicsWindow::redraw() {
glui32 GraphicsWindow::drawPicture(glui32 image, glsi32 xpos, glsi32 ypos, int scale,
glui32 imagewidth, glui32 imageheight) {
- Picture *pic = Picture::load(image);
+ Picture *pic = g_vm->_pictures->load(image);
glui32 hyperlink = _attr.hyper;
if (!pic)
return false;
if (!_imageLoaded) {
- g_vm->_picList->increment();
+ g_vm->_pictures->increment();
_imageLoaded = true;
}
diff --git a/engines/glk/window_text_buffer.cpp b/engines/glk/window_text_buffer.cpp
index 2a98581..6f861fb 100644
--- a/engines/glk/window_text_buffer.cpp
+++ b/engines/glk/window_text_buffer.cpp
@@ -274,13 +274,13 @@ glui32 TextBufferWindow::drawPicture(glui32 image, glui32 align, glui32 scaled,
glui32 hyperlink;
int error;
- pic = Picture::load(image);
+ pic = g_vm->_pictures->load(image);
if (!pic)
return false;
if (!_imageLoaded) {
- g_vm->_picList->increment();
+ g_vm->_pictures->increment();
_imageLoaded = true;
}
Commit: 5a05140ac34a6a177b90a22f8601f2adff4831d5
https://github.com/scummvm/scummvm/commit/5a05140ac34a6a177b90a22f8601f2adff4831d5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add picture scaling
Changed paths:
engines/glk/picture.cpp
engines/glk/picture.h
engines/glk/window_graphics.cpp
engines/glk/window_text_buffer.cpp
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 8461983..89e75fa 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -126,6 +126,21 @@ Picture *Pictures::load(uint32 id) {
return pic;
}
+Picture *Pictures::scale(Picture *src, size_t sx, size_t sy) {
+ // Check for the presence of an already scaled version of that size
+ Picture *dst = retrieve(src->_id, true);
+ if (dst && dst->w == sx && dst->h == sy)
+ return dst;
+
+ // Create a new picture of the destination size and rescale the source picture
+ dst = new Picture(sx, sy, src->format);
+ dst->_id = src->_id;
+ dst->_scaled = true;
+ dst->transBlitFrom(*src, src->getBounds(), dst->getBounds(), (uint)-1);
+
+ storeScaled(dst);
+}
+
/*--------------------------------------------------------------------------*/
void Picture::increment() {
@@ -139,11 +154,6 @@ void Picture::decrement() {
}
}
-Picture *Picture::scale(int sx, int sy) {
- // TODO: gli_picture_scale
- return nullptr;
-}
-
void Picture::drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1) {
// TODO: drawPicture
}
diff --git a/engines/glk/picture.h b/engines/glk/picture.h
index ca4f999..c0108dd 100644
--- a/engines/glk/picture.h
+++ b/engines/glk/picture.h
@@ -40,7 +40,13 @@ public:
/**
* Constructor
*/
- Picture() : Graphics::ManagedSurface(), _refCount(0), _id(0), _scaled(0) {}
+ Picture() : Graphics::ManagedSurface(), _refCount(0), _id(0), _scaled(false) {}
+
+ /**
+ * Constructor
+ */
+ Picture(int width, int height, const Graphics::PixelFormat &format) :
+ Graphics::ManagedSurface(width, height, format), _refCount(0), _id(0), _scaled(false) {}
/**
* Increment reference counter
@@ -53,11 +59,6 @@ public:
void decrement();
/**
- * Rescale the picture to a new picture of a given size
- */
- Picture *scale(int sx, int sy);
-
- /**
* Draw the picture
*/
void drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1);
@@ -134,6 +135,11 @@ public:
* Load a given picture
*/
Picture *load(uint32 id);
+
+ /**
+ * Rescale the passed picture to a new picture of a given size
+ */
+ Picture *scale(Picture *src, size_t sx, size_t sy);
};
} // End of namespace Glk
diff --git a/engines/glk/window_graphics.cpp b/engines/glk/window_graphics.cpp
index 13e6645..92224b6 100644
--- a/engines/glk/window_graphics.cpp
+++ b/engines/glk/window_graphics.cpp
@@ -186,7 +186,7 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
int w, h;
if (width != src->w || height != src->h) {
- src = src->scale(width, height);
+ src = g_vm->_pictures->scale(src, width, height);
if (!src)
return;
}
diff --git a/engines/glk/window_text_buffer.cpp b/engines/glk/window_text_buffer.cpp
index 6f861fb..4c55066 100644
--- a/engines/glk/window_text_buffer.cpp
+++ b/engines/glk/window_text_buffer.cpp
@@ -286,7 +286,7 @@ glui32 TextBufferWindow::drawPicture(glui32 image, glui32 align, glui32 scaled,
if (scaled) {
Picture *tmp;
- tmp = pic->scale(width, height);
+ tmp = g_vm->_pictures->scale(pic, width, height);
pic = tmp;
}
Commit: f7cb4170847373a84268479bd7487c20c58d5639
https://github.com/scummvm/scummvm/commit/f7cb4170847373a84268479bd7487c20c58d5639
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add picture drawing
Changed paths:
engines/glk/picture.cpp
engines/glk/picture.h
engines/glk/window_text_buffer.cpp
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 89e75fa..122d9c3 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -21,6 +21,8 @@
*/
#include "glk/picture.h"
+#include "glk/glk.h"
+#include "glk/screen.h"
#include "common/file.h"
#include "image/jpeg.h"
#include "image/png.h"
@@ -29,8 +31,8 @@ namespace Glk {
void Pictures::clear() {
for (uint idx = 0; idx < _store.size(); ++idx) {
- delete _store[idx]._picture;
- delete _store[idx]._scaled;
+ _store[idx]._picture->decrement();
+ _store[idx]._scaled->decrement();
}
_store.clear();
@@ -139,6 +141,7 @@ Picture *Pictures::scale(Picture *src, size_t sx, size_t sy) {
dst->transBlitFrom(*src, src->getBounds(), dst->getBounds(), (uint)-1);
storeScaled(dst);
+ return dst;
}
/*--------------------------------------------------------------------------*/
@@ -154,9 +157,9 @@ void Picture::decrement() {
}
}
-void Picture::drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1) {
- // TODO: drawPicture
+void Picture::drawPicture(const Common::Point &destPos, const Common::Rect &box) {
+ Graphics::Surface s = g_vm->_screen->getSubArea(box);
+ s.copyRectToSurface(*this, destPos.x - box.left, destPos.y, getBounds());
}
-
} // End of namespace Glk
diff --git a/engines/glk/picture.h b/engines/glk/picture.h
index c0108dd..f221569 100644
--- a/engines/glk/picture.h
+++ b/engines/glk/picture.h
@@ -61,7 +61,7 @@ public:
/**
* Draw the picture
*/
- void drawPicture(int x0, int y0, int dx0, int dy0, int dx1, int dy1);
+ void drawPicture(const Common::Point &destPos, const Common::Rect &box);
};
/**
diff --git a/engines/glk/window_text_buffer.cpp b/engines/glk/window_text_buffer.cpp
index 4c55066..35f5af9 100644
--- a/engines/glk/window_text_buffer.cpp
+++ b/engines/glk/window_text_buffer.cpp
@@ -1070,7 +1070,8 @@ void TextBufferWindow::redraw() {
if (ln->_lPic) {
if (y < y1 && y + ln->_lPic->h > y0) {
- ln->_lPic->drawPicture(x0 / GLI_SUBPIX, y, x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1);
+ ln->_lPic->drawPicture(Point(x0 / GLI_SUBPIX, y),
+ Rect(x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1));
link = ln->_lHyper;
hy0 = y > y0 ? y : y0;
hy1 = y + ln->_lPic->h < y1 ? y + ln->_lPic->h : y1;
@@ -1084,8 +1085,8 @@ void TextBufferWindow::redraw() {
if (ln->_rPic) {
if (y < y1 && y + ln->_rPic->h > y0) {
- ln->_rPic->drawPicture(x1 / GLI_SUBPIX - ln->_rPic->w, y,
- x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1);
+ ln->_rPic->drawPicture(Point(x1 / GLI_SUBPIX - ln->_rPic->w, y),
+ Rect(x0 / GLI_SUBPIX, y0, x1 / GLI_SUBPIX, y1));
link = ln->_rHyper;
hy0 = y > y0 ? y : y0;
hy1 = y + ln->_rPic->h < y1 ? y + ln->_rPic->h : y1;
Commit: 525c09ef38c00d71cf3037d61d221783d3b48cf3
https://github.com/scummvm/scummvm/commit/525c09ef38c00d71cf3037d61d221783d3b48cf3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: In progress transforming Blorb code to be a Common::Archive
Changed paths:
engines/glk/blorb.cpp
engines/glk/blorb.h
engines/glk/frotz/mem.cpp
engines/glk/frotz/mem.h
engines/glk/frotz/processor_streams.cpp
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/glk_api.h
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index ed730bf..2a8ef45 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -54,7 +54,6 @@ struct giblorb_resdesc_struct {
*/
struct giblorb_map_struct {
glui32 inited; ///< holds giblorb_Inited_Magic if the map structure is valid
- Common::SeekableReadStream *file;
uint numchunks;
giblorb_chunkdesc_t *chunks; ///< list of chunk descriptors
@@ -66,13 +65,68 @@ struct giblorb_map_struct {
/*--------------------------------------------------------------------------*/
-giblorb_err_t Blorb::giblorb_initialize() {
- _file = nullptr;
- _map = nullptr;
- return giblorb_err_None;
+Blorb::Blorb(const Common::String &filename, InterpreterType interpType) :
+ Common::Archive(), _interpType(interpType), _map(nullptr) {
+ if (!_file.open(filename))
+ error("Could not open blorb file");
+
+ if (create_map() != giblorb_err_None)
+ error("Could not parse blorb file");
+}
+
+Blorb::~Blorb() {
+ for (uint ix = 0; ix < _map->numchunks; ix++) {
+ giblorb_chunkdesc_t *chu = &(_map->chunks[ix]);
+ if (chu->ptr) {
+ delete chu->ptr;
+ chu->ptr = nullptr;
+ }
+ }
+
+ if (_map->chunks) {
+ delete[] _map->chunks;
+ _map->chunks = nullptr;
+ }
+
+ _map->numchunks = 0;
+
+ if (_map->resources) {
+ delete[] _map->resources;
+ _map->resources = nullptr;
+ }
+
+ if (_map->ressorted) {
+ delete[] _map->ressorted;
+ _map->ressorted = nullptr;
+ }
+
+ _map->numresources = 0;
+ _map->inited = 0;
+
+ delete _map;
+}
+
+bool Blorb::hasFile(const Common::String &name) const {
+ return false;
+}
+
+int Blorb::listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const {
+ return 0;
+}
+
+int Blorb::listMembers(Common::ArchiveMemberList &list) const {
+ return 0;
}
-giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap) {
+const Common::ArchiveMemberPtr Blorb::getMember(const Common::String &name) const {
+ return Common::ArchiveMemberPtr();
+}
+
+Common::SeekableReadStream *Blorb::createReadStreamForMember(const Common::String &name) const {
+ return nullptr;
+}
+
+giblorb_err_t Blorb::create_map() {
giblorb_err_t err;
giblorb_map_t *map;
glui32 readlen;
@@ -81,21 +135,12 @@ giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblor
int chunks_size, numchunks;
char buffer[16];
- *newmap = nullptr;
-
- if (!_libInited) {
- err = giblorb_initialize();
- if (err)
- return err;
- _libInited = true;
- }
-
- /* First, chew through the file and index the chunks. */
- file->seek(0);
+ // First, chew through the file and index the chunks
+ _file.seek(0);
- readlen = file->read(buffer, 12);
+ readlen = _file.read(buffer, 12);
if (readlen != 12)
- return giblorb_err_Read;
+ return giblorb_err_Format;
if (READ_BE_INT32(buffer + 0) != giblorb_ID_FORM)
return giblorb_err_Format;
@@ -114,9 +159,9 @@ giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblor
int chunum;
giblorb_chunkdesc_t *chu;
- file->seek(nextpos);
+ _file.seek(nextpos);
- readlen = file->read(buffer, 8);
+ readlen = _file.read(buffer, 8);
if (readlen != 8) {
delete[] chunks;
return giblorb_err_Read;
@@ -158,34 +203,29 @@ giblorb_err_t Blorb::giblorb_create_map(Common::SeekableReadStream *file, giblor
// The basic IFF structure seems to be ok, and we have a list of chunks.
// Now we allocate the map structure itself.
- map = new giblorb_map_t();
- if (!map) {
+ _map = new giblorb_map_t();
+ if (!_map) {
delete[] chunks;
return giblorb_err_Alloc;
}
- map->inited = giblorb_Inited_Magic;
- map->file = file;
- map->chunks = chunks;
- map->numchunks = numchunks;
- map->resources = nullptr;
- map->ressorted = nullptr;
- map->numresources = 0;
+ _map->inited = giblorb_Inited_Magic;
+ _map->chunks = chunks;
+ _map->numchunks = numchunks;
+ _map->resources = nullptr;
+ _map->ressorted = nullptr;
+ _map->numresources = 0;
// Now we do everything else involved in loading the Blorb file,
// such as building resource lists.
- err = giblorb_initialize_map(map);
- if (err) {
- giblorb_destroy_map(map);
+ err = initialize_map();
+ if (err)
return err;
- }
- *newmap = map;
return giblorb_err_None;
}
-
-giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
+giblorb_err_t Blorb::initialize_map() {
// It is important that the map structure be kept valid during this function.
// If this returns an error, giblorb_destroy_map() will be called.
uint ix, jx;
@@ -196,8 +236,8 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
glui32 numres;
int gotindex = false;
- for (ix = 0; ix<map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &map->chunks[ix];
+ for (ix = 0; ix < _map->numchunks; ix++) {
+ giblorb_chunkdesc_t *chu = &_map->chunks[ix];
switch (chu->type) {
case giblorb_ID_RIdx:
@@ -205,7 +245,7 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
if (gotindex)
return giblorb_err_Format; // duplicate index chunk
- err = giblorb_load_chunk_by_number(map, giblorb_method_Memory, &chunkres, ix);
+ err = load_chunk_by_number(giblorb_method_Memory, &chunkres, ix);
if (err)
return err;
@@ -238,12 +278,12 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
res->resnum = READ_BE_INT32(ptr + jx * 12 + 8);
respos = READ_BE_INT32(ptr + jx * 12 + 12);
- while (ix2 < map->numchunks
- && map->chunks[ix2].startpos < respos)
+ while (ix2 < _map->numchunks
+ && _map->chunks[ix2].startpos < respos)
ix2++;
- if (ix2 >= map->numchunks
- || map->chunks[ix2].startpos != respos) {
+ if (ix2 >= _map->numchunks
+ || _map->chunks[ix2].startpos != respos) {
delete[] resources;
delete[] ressorted;
return giblorb_err_Format; // start pos does not match a real chunk
@@ -254,16 +294,16 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
ressorted[jx] = res;
}
- // Sort a resource list (actually a list of pointers to structures in map->resources.)
+ // Sort a resource list (actually a list of pointers to structures in _map->resources.)
// This makes it easy to find resources by usage and resource number.
- giblorb_qsort(ressorted, numres);
+ qsort(ressorted, numres);
- map->numresources = numres;
- map->resources = resources;
- map->ressorted = ressorted;
+ _map->numresources = numres;
+ _map->resources = resources;
+ _map->ressorted = ressorted;
}
- giblorb_unload_chunk(map, ix);
+ unload_chunk(ix);
gotindex = true;
break;
}
@@ -272,7 +312,7 @@ giblorb_err_t Blorb::giblorb_initialize_map(giblorb_map_t *map) {
return giblorb_err_None;
}
-void Blorb::giblorb_qsort(giblorb_resdesc_t **list, size_t len) {
+void Blorb::qsort(giblorb_resdesc_t **list, size_t len) {
int ix, jx, res;
giblorb_resdesc_t *tmpptr, *pivot;
@@ -306,12 +346,12 @@ void Blorb::giblorb_qsort(giblorb_resdesc_t **list, size_t len) {
}
ix++;
// Sort the halves.
- giblorb_qsort(list + 0, ix);
- giblorb_qsort(list + ix, len - ix);
+ qsort(list + 0, ix);
+ qsort(list + ix, len - ix);
}
}
-giblorb_resdesc_t *Blorb::giblorb_bsearch(giblorb_resdesc_t *sample,
+giblorb_resdesc_t *Blorb::bsearch(giblorb_resdesc_t *sample,
giblorb_resdesc_t **list, int len) {
int top, bot, val, res;
@@ -345,71 +385,31 @@ int Blorb::sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2) {
return 0;
}
-giblorb_err_t Blorb::giblorb_destroy_map(giblorb_map_t *map) {
- if (!map || !map->chunks || map->inited != giblorb_Inited_Magic)
- return giblorb_err_NotAMap;
-
- for (uint ix = 0; ix<map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &(map->chunks[ix]);
- if (chu->ptr) {
- delete chu->ptr;
- chu->ptr = nullptr;
- }
- }
-
- if (map->chunks) {
- delete[] map->chunks;
- map->chunks = nullptr;
- }
-
- map->numchunks = 0;
-
- if (map->resources) {
- delete[] map->resources;
- map->resources = nullptr;
- }
-
- if (map->ressorted) {
- delete[] map->ressorted;
- map->ressorted = nullptr;
- }
-
- map->numresources = 0;
- map->file = nullptr;
- map->inited = 0;
-
- delete map;
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::giblorb_load_chunk_by_type(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
+giblorb_err_t Blorb::load_chunk_by_type(glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
uint ix;
- for (ix = 0; ix < map->numchunks; ix++) {
- if (map->chunks[ix].type == chunktype) {
+ for (ix = 0; ix < _map->numchunks; ix++) {
+ if (_map->chunks[ix].type == chunktype) {
if (count == 0)
break;
count--;
}
}
- if (ix >= map->numchunks) {
+ if (ix >= _map->numchunks) {
return giblorb_err_NotFound;
}
- return giblorb_load_chunk_by_number(map, method, res, ix);
+ return load_chunk_by_number(method, res, ix);
}
-giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunknum) {
+giblorb_err_t Blorb::load_chunk_by_number(glui32 method, giblorb_result_t *res, glui32 chunknum) {
giblorb_chunkdesc_t *chu;
- if (chunknum >= map->numchunks)
+ if (chunknum >= _map->numchunks)
return giblorb_err_NotFound;
- chu = &(map->chunks[chunknum]);
+ chu = &(_map->chunks[chunknum]);
switch (method) {
case giblorb_method_DontLoad:
@@ -428,9 +428,9 @@ giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
if (!dat)
return giblorb_err_Alloc;
- map->file->seek(chu->datpos);
+ _file.seek(chu->datpos);
- readlen = map->file->read(dat, chu->len);
+ readlen = _file.read(dat, chu->len);
if (readlen != chu->len)
return giblorb_err_Read;
@@ -448,13 +448,13 @@ giblorb_err_t Blorb::giblorb_load_chunk_by_number(giblorb_map_t *map,
return giblorb_err_None;
}
-giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
+giblorb_err_t Blorb::unload_chunk(glui32 chunknum) {
giblorb_chunkdesc_t *chu;
- if (chunknum >= map->numchunks)
+ if (chunknum >= _map->numchunks)
return giblorb_err_NotFound;
- chu = &(map->chunks[chunknum]);
+ chu = &(_map->chunks[chunknum]);
if (chu->ptr) {
delete chu->ptr;
@@ -464,24 +464,22 @@ giblorb_err_t Blorb::giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum) {
return giblorb_err_None;
}
-giblorb_err_t Blorb::giblorb_load_resource(giblorb_map_t *map, glui32 method,
- giblorb_result_t *res, glui32 usage, glui32 resnum) {
+giblorb_err_t Blorb::load_resource(glui32 method, giblorb_result_t *res, glui32 usage, glui32 resnum) {
giblorb_resdesc_t sample;
giblorb_resdesc_t *found;
sample.usage = usage;
sample.resnum = resnum;
- found = giblorb_bsearch(&sample, map->ressorted, map->numresources);
+ found = bsearch(&sample, _map->ressorted, _map->numresources);
if (!found)
return giblorb_err_NotFound;
- return giblorb_load_chunk_by_number(map, method, res, found->chunknum);
+ return load_chunk_by_number(method, res, found->chunknum);
}
-giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
- glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
+giblorb_err_t Blorb::count_resources(glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
int ix;
int count;
glui32 val;
@@ -491,9 +489,9 @@ giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
minval = 0;
maxval = 0;
- for (ix = 0; ix<map->numresources; ix++) {
- if (map->resources[ix].usage == usage) {
- val = map->resources[ix].resnum;
+ for (ix = 0; ix<_map->numresources; ix++) {
+ if (_map->resources[ix].usage == usage) {
+ val = _map->resources[ix].resnum;
if (count == 0) {
count++;
minval = val;
@@ -519,25 +517,4 @@ giblorb_err_t Blorb::giblorb_count_resources(giblorb_map_t *map,
return giblorb_err_None;
}
-giblorb_err_t Blorb::giblorb_set_resource_map(Common::SeekableReadStream *file) {
- giblorb_err_t err;
-
- err = giblorb_create_map(file, &_map);
- if (err) {
- _map = nullptr;
- return err;
- }
-
- _file = file;
- return giblorb_err_None;
-}
-
-giblorb_map_t *Blorb::giblorb_get_resource_map(void) {
- return _map;
-}
-
-bool Blorb::giblorb_is_resource_map(void) const {
- return _map != nullptr;
-}
-
} // End of namespace Glk
diff --git a/engines/glk/blorb.h b/engines/glk/blorb.h
index ae9c503..97fd520 100644
--- a/engines/glk/blorb.h
+++ b/engines/glk/blorb.h
@@ -25,10 +25,11 @@
#include "glk/glk_types.h"
#include "glk/streams.h"
+#include "common/archive.h"
+#include "common/array.h"
namespace Glk {
-
/**
* Error type
*/
@@ -101,46 +102,81 @@ typedef struct giblorb_result_struct {
typedef struct giblorb_resdesc_struct giblorb_resdesc_t;
-class Blorb {
+/**
+ * Blorb file manager
+ */
+class Blorb : public Common::Archive {
private:
- bool _libInited;
- Common::SeekableReadStream *_file;
+ Common::File _file;
+ InterpreterType _interpType;
giblorb_map_t *_map;
private:
/**
- * Initializes Blorb
+ * Parses the Blorb file index to load in a list of the chunks
*/
- giblorb_err_t giblorb_initialize();
+ giblorb_err_t create_map();
- giblorb_err_t giblorb_initialize_map(giblorb_map_t *map);
- void giblorb_qsort(giblorb_resdesc_t **list, size_t len);
- giblorb_resdesc_t *giblorb_bsearch(giblorb_resdesc_t *sample,
- giblorb_resdesc_t **list, int len);
+ giblorb_err_t initialize_map();
+ void qsort(giblorb_resdesc_t **list, size_t len);
+ giblorb_resdesc_t *bsearch(giblorb_resdesc_t *sample, giblorb_resdesc_t **list, int len);
int sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2);
public:
/**
* Constructor
*/
- Blorb() : _libInited(false), _file(nullptr), _map(nullptr) {}
+ Blorb(const Common::String &filename, InterpreterType interpType);
- giblorb_err_t giblorb_set_resource_map(Common::SeekableReadStream *file);
- giblorb_map_t *giblorb_get_resource_map(void);
- bool giblorb_is_resource_map(void) const;
+ /**
+ * Destructor
+ */
+ ~Blorb();
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ virtual bool hasFile(const Common::String &name) const override;
- giblorb_err_t giblorb_create_map(Common::SeekableReadStream *file, giblorb_map_t **newmap);
- giblorb_err_t giblorb_destroy_map(giblorb_map_t *map);
+ /**
+ * Add all members of the Archive matching the specified pattern to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of members added to list
+ */
+ virtual int listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const override;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ virtual int listMembers(Common::ArchiveMemberList &list) const override;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+public:
+ /**
+ * Get a pointer to the Blorb's resource map
+ */
+ giblorb_map_t *get_resource_map() const { return _map; }
- giblorb_err_t giblorb_load_chunk_by_type(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
- giblorb_err_t giblorb_load_chunk_by_number(giblorb_map_t *map,
- glui32 method, giblorb_result_t *res, glui32 chunknum);
- giblorb_err_t giblorb_unload_chunk(giblorb_map_t *map, glui32 chunknum);
+ giblorb_err_t load_chunk_by_type(glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
+ giblorb_err_t load_chunk_by_number(glui32 method, giblorb_result_t *res, glui32 chunknum);
+ giblorb_err_t unload_chunk(glui32 chunknum);
- giblorb_err_t giblorb_load_resource(giblorb_map_t *map, glui32 method,
- giblorb_result_t *res, glui32 usage, glui32 resnum);
- giblorb_err_t giblorb_count_resources(giblorb_map_t *map,
- glui32 usage, glui32 *num, glui32 *min, glui32 *max);
+ giblorb_err_t load_resource(glui32 method, giblorb_result_t *res, glui32 usage, glui32 resnum);
+ giblorb_err_t count_resources(glui32 usage, glui32 *num, glui32 *min, glui32 *max);
};
} // End of namespace Glk
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index 12e860a..bec30b0 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -28,10 +28,9 @@
namespace Glk {
namespace Frotz {
-Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0),
- first_undo(nullptr), last_undo(nullptr), curr_undo(nullptr),
- undo_mem(nullptr), prev_zmp(nullptr), undo_diff(nullptr),
- undo_count(0), reserve_mem(0) {
+Mem::Mem() : story_fp(nullptr), story_size(0), first_undo(nullptr), last_undo(nullptr),
+ curr_undo(nullptr), undo_mem(nullptr), zmp(nullptr), prev_zmp(nullptr),
+ undo_diff(nullptr), undo_count(0), reserve_mem(0) {
}
void Mem::initialize() {
@@ -60,32 +59,7 @@ void Mem::initialize() {
}
void Mem::initializeStoryFile() {
- Common::SeekableReadStream *f = story_fp;
- giblorb_map_t *map;
- giblorb_result_t res;
- uint32 magic;
-
- magic = f->readUint32BE();
-
- if (magic == MKTAG('F', 'O', 'R', 'M')) {
- if (g_vm->giblorb_set_resource_map(f))
- error("This Blorb file seems to be invalid.");
-
- map = g_vm->giblorb_get_resource_map();
-
- if (g_vm->giblorb_load_resource(map, giblorb_method_FilePos, &res, giblorb_ID_Exec, 0))
- error("This Blorb file does not contain an executable chunk.");
- if (res.chunktype != MKTAG('Z', 'C', 'O', 'D'))
- error("This Blorb file contains an executable chunk, but it is not a Z-code file.");
-
- blorb_ofs = res.data.startpos;
- blorb_len = res.length;
- } else {
- blorb_ofs = 0;
- blorb_len = f->size();
- }
-
- if (blorb_len < 64)
+ if (story_fp->size() < 64)
error("This file is too small to be a Z-code file.");
}
@@ -115,7 +89,7 @@ void Mem::initializeUndo() {
void Mem::loadGameHeader() {
// Load header
zmp = new byte[64];
- story_fp->seek(blorb_ofs);
+ story_fp->seek(0);
story_fp->read(zmp, 64);
Common::MemoryReadStream h(zmp, 64);
@@ -131,7 +105,7 @@ void Mem::loadGameHeader() {
story_size *= 2;
} else {
// Some old games lack the file size entry
- story_size = blorb_len;
+ story_size = story_fp->size();
}
}
@@ -254,8 +228,6 @@ void Mem::free_undo(int count) {
void Mem::reset_memory() {
story_fp = nullptr;
- blorb_ofs = 0;
- blorb_len = 0;
if (undo_mem) {
free_undo(undo_count);
diff --git a/engines/glk/frotz/mem.h b/engines/glk/frotz/mem.h
index d973890..a632bc6 100644
--- a/engines/glk/frotz/mem.h
+++ b/engines/glk/frotz/mem.h
@@ -57,7 +57,6 @@ typedef undo_struct undo_t;
class Mem : public Header, public virtual UserOptions {
protected:
Common::SeekableReadStream *story_fp;
- uint blorb_ofs, blorb_len;
uint story_size;
byte *pcp;
byte *zmp;
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index cbef38a..095ef24 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -519,7 +519,7 @@ void Processor::z_restart() {
seed_random(0);
if (!first_restart) {
- story_fp->seek(blorb_ofs);
+ story_fp->seek(0);
if (story_fp->read(zmp, h_dynamic_size) != h_dynamic_size)
error("Story file read error");
@@ -599,7 +599,7 @@ void Processor::z_verify() {
zword checksum = 0;
// Sum all bytes in story file except header bytes
- story_fp->seek(blorb_ofs + 64);
+ story_fp->seek(64);
for (uint i = 64; i < story_size; i++)
checksum += story_fp->readByte();
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 0e44f04..c2a8264 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -29,6 +29,7 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "glk/glk.h"
+#include "glk/blorb.h"
#include "glk/conf.h"
#include "glk/events.h"
#include "glk/picture.h"
@@ -42,14 +43,16 @@ namespace Glk {
GlkEngine *g_vm;
GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription &gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Glk"), _clipboard(nullptr),
- _conf(nullptr), _events(nullptr), _pictures(nullptr), _screen(nullptr),
- _selection(nullptr), _windows(nullptr), _copySelect(false), _terminated(false),
- gli_unregister_obj(nullptr), gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
+ _gameDescription(gameDesc), Engine(syst), _random("Glk"), _blorb(nullptr),
+ _clipboard(nullptr), _conf(nullptr), _events(nullptr), _pictures(nullptr),
+ _screen(nullptr), _selection(nullptr), _windows(nullptr), _copySelect(false),
+ _terminated(false), gli_unregister_obj(nullptr), gli_register_arr(nullptr),
+ gli_unregister_arr(nullptr) {
g_vm = this;
}
GlkEngine::~GlkEngine() {
+ delete _blorb;
delete _clipboard;
delete _conf;
delete _events;
@@ -96,11 +99,26 @@ void GlkEngine::initGraphicsMode() {
}
Common::Error GlkEngine::run() {
+ Common::File f;
+ Common::String filename = getFilename();
+ if (!Common::File::exists(filename))
+ return Common::kNoGameDataFoundError;
+
initialize();
- Common::File f;
- if (f.open(getFilename()))
- runGame(&f);
+ if (filename.hasSuffixIgnoreCase(".blorb") || filename.hasSuffixIgnoreCase(".zblorb")) {
+ // Blorb archive
+ _blorb = new Blorb(filename, getInterpreterType());
+ SearchMan.add("blorb", _blorb, 99, false);
+
+ if (!f.open("EXEC", *_blorb))
+ return Common::kNoGameDataFoundError;
+ } else {
+ if (!f.open(filename))
+ return Common::kNoGameDataFoundError;
+ }
+
+ runGame(&f);
return Common::kNoError;
}
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 50722ae..af9a42b 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -35,6 +35,7 @@
namespace Glk {
class Clipboard;
+class Blorb;
class Conf;
class Events;
class Pictures;
@@ -93,6 +94,7 @@ protected:
*/
virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
public:
+ Blorb *_blorb;
Clipboard *_clipboard;
Conf *_conf;
Events *_events;
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index 400f3c0..b625f69 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -34,7 +34,7 @@ namespace Glk {
/**
* Implements the GLK interface
*/
-class GlkAPI : public GlkEngine, public Blorb {
+class GlkAPI : public GlkEngine {
private:
bool _gliFirstEvent;
unsigned char _charTolowerTable[256];
Commit: 13e28c0d0dad6727050e282eb475ab0052d892a6
https://github.com/scummvm/scummvm/commit/13e28c0d0dad6727050e282eb475ab0052d892a6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Finish refactoring Blorb class
Changed paths:
engines/glk/blorb.cpp
engines/glk/blorb.h
engines/glk/glk.cpp
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 2a8ef45..ace0e91 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -24,497 +24,162 @@
namespace Glk {
-#define giblorb_Inited_Magic 0xB7012BEDU
-
-/**
- * Describes one chunk of the Blorb file.
- */
-struct giblorb_chunkdesc_struct {
- glui32 type;
- glui32 len;
- glui32 startpos; ///< start of chunk header
- glui32 datpos; ///< start of data (either startpos or startpos+8)
-
- byte *ptr; ///< pointer to malloc'd data, if loaded
- int auxdatnum; ///< entry in the auxsound/auxpict array; -1 if none. This only applies to chunks that represent resources;
-};
-typedef giblorb_chunkdesc_struct giblorb_chunkdesc_t;
-
-/**
- * Describes one resource in the Blorb file.
- */
-struct giblorb_resdesc_struct {
- glui32 usage;
- glui32 resnum;
- glui32 chunknum;
-};
-
-/**
- * Holds the complete description of an open Blorb file.
- */
-struct giblorb_map_struct {
- glui32 inited; ///< holds giblorb_Inited_Magic if the map structure is valid
-
- uint numchunks;
- giblorb_chunkdesc_t *chunks; ///< list of chunk descriptors
-
- int numresources;
- giblorb_resdesc_t *resources; ///< list of resource descriptors
- giblorb_resdesc_t **ressorted; ///< list of pointers to descriptors in map->resources -- sorted by usage and resource number.
+enum {
+ ID_FORM = MKTAG('F', 'O', 'R', 'M'),
+ ID_IFRS = MKTAG('I', 'F', 'R', 'S'),
+ ID_RIdx = MKTAG('R', 'I', 'd', 'x'),
+
+ ID_Snd = MKTAG('S', 'n', 'd', ' '),
+ ID_Exec = MKTAG('E', 'x', 'e', 'c'),
+ ID_Pict = MKTAG('P', 'i', 'c', 't'),
+ ID_Data = MKTAG('D', 'a', 't', 'a'),
+
+ ID_Copyright = MKTAG('(', 'c', ')', ' '),
+ ID_AUTH = MKTAG('A', 'U', 'T', 'H'),
+ ID_ANNO = MKTAG('A', 'N', 'N', 'O'),
+
+ ID_JPEG = MKTAG('J', 'P', 'E', 'G'),
+ ID_PNG = MKTAG('P', 'N', 'G', ' '),
+
+ ID_MIDI = MKTAG('M', 'I', 'D', 'I'),
+ ID_MP3 = MKTAG('M', 'P', '3', ' '),
+ ID_WAVE = MKTAG('W', 'A', 'V', 'E'),
+ ID_AIFF = MKTAG('A', 'I', 'F', 'F'),
+ ID_OGG = MKTAG('O', 'G', 'G', ' '),
+ ID_MOD = MKTAG('M', 'O', 'D', ' '),
};
/*--------------------------------------------------------------------------*/
Blorb::Blorb(const Common::String &filename, InterpreterType interpType) :
- Common::Archive(), _interpType(interpType), _map(nullptr) {
- if (!_file.open(filename))
- error("Could not open blorb file");
-
- if (create_map() != giblorb_err_None)
+ Common::Archive(), _filename(filename), _interpType(interpType) {
+ if (load() != Common::kNoError)
error("Could not parse blorb file");
}
-Blorb::~Blorb() {
- for (uint ix = 0; ix < _map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &(_map->chunks[ix]);
- if (chu->ptr) {
- delete chu->ptr;
- chu->ptr = nullptr;
- }
- }
-
- if (_map->chunks) {
- delete[] _map->chunks;
- _map->chunks = nullptr;
- }
-
- _map->numchunks = 0;
-
- if (_map->resources) {
- delete[] _map->resources;
- _map->resources = nullptr;
- }
-
- if (_map->ressorted) {
- delete[] _map->ressorted;
- _map->ressorted = nullptr;
+bool Blorb::hasFile(const Common::String &name) const {
+ for (uint idx = 0; idx < _chunks.size(); ++idx) {
+ if (_chunks[idx]._filename.equalsIgnoreCase(name))
+ return true;
}
- _map->numresources = 0;
- _map->inited = 0;
-
- delete _map;
-}
-
-bool Blorb::hasFile(const Common::String &name) const {
return false;
}
-int Blorb::listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const {
- return 0;
-}
-
int Blorb::listMembers(Common::ArchiveMemberList &list) const {
- return 0;
-}
-
-const Common::ArchiveMemberPtr Blorb::getMember(const Common::String &name) const {
- return Common::ArchiveMemberPtr();
-}
-
-Common::SeekableReadStream *Blorb::createReadStreamForMember(const Common::String &name) const {
- return nullptr;
-}
-
-giblorb_err_t Blorb::create_map() {
- giblorb_err_t err;
- giblorb_map_t *map;
- glui32 readlen;
- glui32 nextpos, totallength;
- giblorb_chunkdesc_t *chunks;
- int chunks_size, numchunks;
- char buffer[16];
-
- // First, chew through the file and index the chunks
- _file.seek(0);
-
- readlen = _file.read(buffer, 12);
- if (readlen != 12)
- return giblorb_err_Format;
-
- if (READ_BE_INT32(buffer + 0) != giblorb_ID_FORM)
- return giblorb_err_Format;
- if (READ_BE_INT32(buffer + 8) != giblorb_ID_IFRS)
- return giblorb_err_Format;
-
- totallength = READ_BE_INT32(buffer + 4) + 8;
- nextpos = 12;
-
- chunks_size = 8;
- numchunks = 0;
- chunks = new giblorb_chunkdesc_t[chunks_size];
-
- while (nextpos < totallength) {
- glui32 type, len;
- int chunum;
- giblorb_chunkdesc_t *chu;
-
- _file.seek(nextpos);
-
- readlen = _file.read(buffer, 8);
- if (readlen != 8) {
- delete[] chunks;
- return giblorb_err_Read;
- }
-
- type = READ_BE_INT32(buffer + 0);
- len = READ_BE_INT32(buffer + 4);
-
- if (numchunks >= chunks_size) {
- chunks_size *= 2;
- chunks = new giblorb_chunkdesc_t[chunks_size];
- }
-
- chunum = numchunks;
- chu = &(chunks[chunum]);
- numchunks++;
-
- chu->type = type;
- chu->startpos = nextpos;
- if (type == giblorb_ID_FORM) {
- chu->datpos = nextpos;
- chu->len = len + 8;
- } else {
- chu->datpos = nextpos + 8;
- chu->len = len;
- }
- chu->ptr = nullptr;
- chu->auxdatnum = -1;
-
- nextpos = nextpos + len + 8;
- if (nextpos & 1)
- nextpos++;
-
- if (nextpos > totallength) {
- delete[] chunks;
- return giblorb_err_Format;
- }
- }
-
- // The basic IFF structure seems to be ok, and we have a list of chunks.
- // Now we allocate the map structure itself.
- _map = new giblorb_map_t();
- if (!_map) {
- delete[] chunks;
- return giblorb_err_Alloc;
+ for (uint idx = 0; idx < _chunks.size(); ++idx) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(_chunks[idx]._filename, this)));
}
- _map->inited = giblorb_Inited_Magic;
- _map->chunks = chunks;
- _map->numchunks = numchunks;
- _map->resources = nullptr;
- _map->ressorted = nullptr;
- _map->numresources = 0;
-
- // Now we do everything else involved in loading the Blorb file,
- // such as building resource lists.
- err = initialize_map();
- if (err)
- return err;
-
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::initialize_map() {
- // It is important that the map structure be kept valid during this function.
- // If this returns an error, giblorb_destroy_map() will be called.
- uint ix, jx;
- giblorb_result_t chunkres;
- giblorb_err_t err;
- char *ptr;
- glui32 len;
- glui32 numres;
- int gotindex = false;
-
- for (ix = 0; ix < _map->numchunks; ix++) {
- giblorb_chunkdesc_t *chu = &_map->chunks[ix];
-
- switch (chu->type) {
- case giblorb_ID_RIdx:
- // Resource index chunk: build the resource list and sort it.
-
- if (gotindex)
- return giblorb_err_Format; // duplicate index chunk
- err = load_chunk_by_number(giblorb_method_Memory, &chunkres, ix);
- if (err)
- return err;
-
- ptr = (char *)chunkres.data.ptr;
- len = chunkres.length;
- numres = READ_BE_INT32(ptr + 0);
-
- if (numres) {
- uint ix2;
- giblorb_resdesc_t *resources;
- giblorb_resdesc_t **ressorted;
-
- if (len != numres * 12 + 4)
- return giblorb_err_Format; // bad length field
-
- resources = new giblorb_resdesc_t[numres];
- ressorted = new giblorb_resdesc_t *[numres];
- if (!ressorted || !resources) {
- delete[] resources;
- delete[] ressorted;
- return giblorb_err_Alloc;
- }
-
- ix2 = 0;
- for (jx = 0; jx < numres; jx++) {
- giblorb_resdesc_t *res = &(resources[jx]);
- glui32 respos;
-
- res->usage = READ_BE_INT32(ptr + jx * 12 + 4);
- res->resnum = READ_BE_INT32(ptr + jx * 12 + 8);
- respos = READ_BE_INT32(ptr + jx * 12 + 12);
-
- while (ix2 < _map->numchunks
- && _map->chunks[ix2].startpos < respos)
- ix2++;
-
- if (ix2 >= _map->numchunks
- || _map->chunks[ix2].startpos != respos) {
- delete[] resources;
- delete[] ressorted;
- return giblorb_err_Format; // start pos does not match a real chunk
- }
-
- res->chunknum = ix2;
-
- ressorted[jx] = res;
- }
-
- // Sort a resource list (actually a list of pointers to structures in _map->resources.)
- // This makes it easy to find resources by usage and resource number.
- qsort(ressorted, numres);
-
- _map->numresources = numres;
- _map->resources = resources;
- _map->ressorted = ressorted;
- }
-
- unload_chunk(ix);
- gotindex = true;
- break;
- }
- }
-
- return giblorb_err_None;
+ return (int)_chunks.size();
}
-void Blorb::qsort(giblorb_resdesc_t **list, size_t len) {
- int ix, jx, res;
- giblorb_resdesc_t *tmpptr, *pivot;
-
- if (len < 6) {
- // The list is short enough for a bubble-sort.
- for (jx = len - 1; jx>0; jx--) {
- for (ix = 0; ix<jx; ix++) {
- res = sortsplot(list[ix], list[ix + 1]);
- if (res > 0) {
- tmpptr = list[ix];
- list[ix] = list[ix + 1];
- list[ix + 1] = tmpptr;
- }
- }
- }
- } else {
- // Split the list.
- pivot = list[len / 2];
- ix = 0;
- jx = len;
- for (;;) {
- while (ix < jx - 1 && sortsplot(list[ix], pivot) < 0)
- ix++;
- while (ix < jx - 1 && sortsplot(list[jx - 1], pivot) > 0)
- jx--;
- if (ix >= jx - 1)
- break;
- tmpptr = list[ix];
- list[ix] = list[jx - 1];
- list[jx - 1] = tmpptr;
- }
- ix++;
- // Sort the halves.
- qsort(list + 0, ix);
- qsort(list + ix, len - ix);
- }
-}
-
-giblorb_resdesc_t *Blorb::bsearch(giblorb_resdesc_t *sample,
- giblorb_resdesc_t **list, int len) {
- int top, bot, val, res;
-
- bot = 0;
- top = len;
-
- while (bot < top) {
- val = (top + bot) / 2;
- res = sortsplot(list[val], sample);
- if (res == 0)
- return list[val];
- if (res < 0) {
- bot = val + 1;
- } else {
- top = val;
- }
- }
-
- return nullptr;
-}
-
-int Blorb::sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2) {
- if (v1->usage < v2->usage)
- return -1;
- if (v1->usage > v2->usage)
- return 1;
- if (v1->resnum < v2->resnum)
- return -1;
- if (v1->resnum > v2->resnum)
- return 1;
- return 0;
-}
-
-giblorb_err_t Blorb::load_chunk_by_type(glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count) {
- uint ix;
-
- for (ix = 0; ix < _map->numchunks; ix++) {
- if (_map->chunks[ix].type == chunktype) {
- if (count == 0)
- break;
- count--;
- }
- }
-
- if (ix >= _map->numchunks) {
- return giblorb_err_NotFound;
- }
+const Common::ArchiveMemberPtr Blorb::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
- return load_chunk_by_number(method, res, ix);
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
}
-giblorb_err_t Blorb::load_chunk_by_number(glui32 method, giblorb_result_t *res, glui32 chunknum) {
- giblorb_chunkdesc_t *chu;
-
- if (chunknum >= _map->numchunks)
- return giblorb_err_NotFound;
-
- chu = &(_map->chunks[chunknum]);
-
- switch (method) {
- case giblorb_method_DontLoad:
- // do nothing
- break;
-
- case giblorb_method_FilePos:
- res->data.startpos = chu->datpos;
- break;
-
- case giblorb_method_Memory:
- if (!chu->ptr) {
- glui32 readlen;
- byte *dat = new byte[chu->len];
-
- if (!dat)
- return giblorb_err_Alloc;
-
- _file.seek(chu->datpos);
+Common::SeekableReadStream *Blorb::createReadStreamForMember(const Common::String &name) const {
+ for (uint idx = 0; idx < _chunks.size(); ++idx) {
+ if (_chunks[idx]._filename.equalsIgnoreCase(name)) {
+ Common::File f;
+ if (!f.open(_filename))
+ error("Reading failed");
- readlen = _file.read(dat, chu->len);
- if (readlen != chu->len)
- return giblorb_err_Read;
+ f.seek(_chunks[idx]._offset);
+ Common::SeekableReadStream *result = f.readStream(_chunks[idx]._size);
+ f.close();
- chu->ptr = dat;
+ return result;
}
-
- res->data.ptr = chu->ptr;
- break;
}
- res->chunknum = chunknum;
- res->length = chu->len;
- res->chunktype = chu->type;
-
- return giblorb_err_None;
+ return nullptr;
}
-giblorb_err_t Blorb::unload_chunk(glui32 chunknum) {
- giblorb_chunkdesc_t *chu;
-
- if (chunknum >= _map->numchunks)
- return giblorb_err_NotFound;
-
- chu = &(_map->chunks[chunknum]);
-
- if (chu->ptr) {
- delete chu->ptr;
- chu->ptr = nullptr;
+Common::ErrorCode Blorb::load() {
+ // First, chew through the file and index the chunks
+ Common::File f;
+ if (!f.open(_filename) || f.size() < 12)
+ return Common::kReadingFailed;
+
+ if (f.readUint32BE() != ID_FORM)
+ return Common::kReadingFailed;
+ f.readUint32BE();
+ if (f.readUint32BE() != ID_IFRS)
+ return Common::kReadingFailed;
+ if (f.readUint32BE() != ID_RIdx)
+ return Common::kReadingFailed;
+
+ f.readUint32BE();
+ uint count = f.readUint32BE();
+
+ // First read in the resource index
+ for (uint idx = 0; idx < count; ++idx) {
+ ChunkEntry ce;
+ ce._type = f.readUint32BE();
+ ce._number = f.readUint32BE();
+ ce._offset = f.readUint32BE();
+
+ _chunks.push_back(ce);
}
- return giblorb_err_None;
-}
-
-giblorb_err_t Blorb::load_resource(glui32 method, giblorb_result_t *res, glui32 usage, glui32 resnum) {
- giblorb_resdesc_t sample;
- giblorb_resdesc_t *found;
-
- sample.usage = usage;
- sample.resnum = resnum;
-
- found = bsearch(&sample, _map->ressorted, _map->numresources);
-
- if (!found)
- return giblorb_err_NotFound;
-
- return load_chunk_by_number(method, res, found->chunknum);
-}
-
-giblorb_err_t Blorb::count_resources(glui32 usage, glui32 *num, glui32 *min, glui32 *max) {
- int ix;
- int count;
- glui32 val;
- glui32 minval, maxval;
-
- count = 0;
- minval = 0;
- maxval = 0;
-
- for (ix = 0; ix<_map->numresources; ix++) {
- if (_map->resources[ix].usage == usage) {
- val = _map->resources[ix].resnum;
- if (count == 0) {
- count++;
- minval = val;
- maxval = val;
- }
- else {
- count++;
- if (val < minval)
- minval = val;
- if (val > maxval)
- maxval = val;
+ // Further iterate through the resources
+ for (uint idx = 0; idx < _chunks.size(); ++idx) {
+ ChunkEntry &ce = _chunks[idx];
+ f.seek(ce._offset);
+ ce._offset += 8;
+
+ ce._id = f.readUint32BE();
+ ce._size = f.readUint32BE();
+
+ if (ce._type == ID_Pict) {
+ ce._filename = Common::String::format("pic%u", ce._number);
+ if (ce._id == ID_JPEG)
+ ce._filename += ".jpeg";
+ else if (ce._id == ID_PNG)
+ ce._filename += ".png";
+
+ } else if (ce._type == ID_Snd) {
+ ce._filename = Common::String::format("snd%u", ce._number);
+ if (ce._id == ID_MIDI)
+ ce._filename += ".midi";
+ else if (ce._id == ID_MP3)
+ ce._filename += ".mp3";
+ else if (ce._id == ID_WAVE)
+ ce._filename += ".wav";
+ else if (ce._id == ID_AIFF)
+ ce._filename += ".aiff";
+ else if (ce._id == ID_OGG)
+ ce._filename += ".ogg";
+ else if (ce._id == ID_MOD)
+ ce._filename += ".mod";
+
+ } else if (ce._type == ID_Data) {
+ ce._filename = Common::String::format("data%u", ce._number);
+
+ } else if (ce._type == ID_Exec) {
+ char buffer[5];
+ WRITE_BE_UINT32(buffer, ce._id);
+ buffer[4] = '\0';
+ Common::String type(buffer);
+
+ if (
+ (_interpType == INTERPRETER_FROTZ && type == "ZCOD") ||
+ (_interpType == INTERPRETER_TADS && (type == "TAD2" || type == "TAD3")) ||
+ (_interpType == INTERPRETER_HUGO && type == "HUGO")
+ ) {
+ // Game executable
+ ce._filename = "game";
+ } else {
+ ce._filename = type;
}
}
}
- if (num)
- *num = count;
- if (min)
- *min = minval;
- if (max)
- *max = maxval;
-
- return giblorb_err_None;
+ return Common::kNoError;
}
} // End of namespace Glk
diff --git a/engines/glk/blorb.h b/engines/glk/blorb.h
index 97fd520..afd52af 100644
--- a/engines/glk/blorb.h
+++ b/engines/glk/blorb.h
@@ -31,95 +31,30 @@
namespace Glk {
/**
- * Error type
+ * Describes one chunk of the Blorb file.
*/
-typedef glui32 giblorb_err_t;
-
-/**
- * Error codes
- */
-enum giblorbError {
- giblorb_err_None = 0,
- giblorb_err_CompileTime = 1,
- giblorb_err_Alloc = 2,
- giblorb_err_Read = 3,
- giblorb_err_NotAMap = 4,
- giblorb_err_Format = 5,
- giblorb_err_NotFound = 6
-};
-
-/**
- * Methods for loading a chunk
- */
-enum giblorbMethod {
- giblorb_method_DontLoad = 0,
- giblorb_method_Memory = 1,
- giblorb_method_FilePos = 2
-};
-
-enum {
- giblorb_ID_Snd = MKTAG('S', 'n', 'd', ' '),
- giblorb_ID_Exec = MKTAG('E', 'x', 'e', 'c'),
- giblorb_ID_Pict = MKTAG('P', 'i', 'c', 't'),
- giblorb_ID_Copyright = MKTAG('(', 'c', ')', ' '),
- giblorb_ID_AUTH = MKTAG('A', 'U', 'T', 'H'),
- giblorb_ID_ANNO = MKTAG('A', 'N', 'N', 'O')
-};
-
-
-enum {
- giblorb_ID_MOD = MKTAG('M', 'O', 'D', ' '),
- giblorb_ID_FORM = MKTAG('F', 'O', 'R', 'M'),
- giblorb_ID_IFRS = MKTAG('I', 'F', 'R', 'S'),
- giblorb_ID_RIdx = MKTAG('R', 'I', 'd', 'x'),
- giblorb_ID_OGG = MKTAG('O', 'G', 'G', 'V'),
-
- // non-standard types
- giblorb_ID_MIDI = MKTAG('M', 'I', 'D', 'I'),
- giblorb_ID_MP3 = MKTAG('M', 'P', '3', ' '),
- giblorb_ID_WAVE = MKTAG('W', 'A', 'V', 'E')
+struct ChunkEntry {
+ uint _type;
+ uint _number;
+ uint _id;
+ size_t _offset;
+ size_t _size;
+ Common::String _filename;
};
/**
- * Holds the complete description of an open Blorb file.
- * This type is opaque for normal interpreter use.
- */
-typedef struct giblorb_map_struct giblorb_map_t;
-
-/**
- * giblorb_result_t: Result when you try to load a chunk.
- */
-typedef struct giblorb_result_struct {
- glui32 chunknum; // The chunk number (for use in giblorb_unload_chunk(), etc.)
- union {
- void *ptr; ///< A pointer to the data (if you used giblorb_method_Memory)
- glui32 startpos; ///< The position in the file (if you used giblorb_method_FilePos)
- } data;
-
- glui32 length; ///< The length of the data
- glui32 chunktype; ///< The type of the chunk.
-} giblorb_result_t;
-
-typedef struct giblorb_resdesc_struct giblorb_resdesc_t;
-
-/**
* Blorb file manager
*/
class Blorb : public Common::Archive {
private:
- Common::File _file;
+ Common::String _filename;
InterpreterType _interpType;
- giblorb_map_t *_map;
+ Common::Array<ChunkEntry> _chunks; ///< list of chunk descriptors
private:
/**
* Parses the Blorb file index to load in a list of the chunks
*/
- giblorb_err_t create_map();
-
- giblorb_err_t initialize_map();
- void qsort(giblorb_resdesc_t **list, size_t len);
- giblorb_resdesc_t *bsearch(giblorb_resdesc_t *sample, giblorb_resdesc_t **list, int len);
- int sortsplot(giblorb_resdesc_t *v1, giblorb_resdesc_t *v2);
+ Common::ErrorCode load();
public:
/**
* Constructor
@@ -127,11 +62,6 @@ public:
Blorb(const Common::String &filename, InterpreterType interpType);
/**
- * Destructor
- */
- ~Blorb();
-
- /**
* Check if a member with the given name is present in the Archive.
* Patterns are not allowed, as this is meant to be a quick File::exists()
* replacement.
@@ -139,14 +69,6 @@ public:
virtual bool hasFile(const Common::String &name) const override;
/**
- * Add all members of the Archive matching the specified pattern to list.
- * Must only append to list, and not remove elements from it.
- *
- * @return the number of members added to list
- */
- virtual int listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) const override;
-
- /**
* Add all members of the Archive to list.
* Must only append to list, and not remove elements from it.
*
@@ -165,18 +87,6 @@ public:
* @return the newly created input stream
*/
virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
-public:
- /**
- * Get a pointer to the Blorb's resource map
- */
- giblorb_map_t *get_resource_map() const { return _map; }
-
- giblorb_err_t load_chunk_by_type(glui32 method, giblorb_result_t *res, glui32 chunktype, glui32 count);
- giblorb_err_t load_chunk_by_number(glui32 method, giblorb_result_t *res, glui32 chunknum);
- giblorb_err_t unload_chunk(glui32 chunknum);
-
- giblorb_err_t load_resource(glui32 method, giblorb_result_t *res, glui32 usage, glui32 resnum);
- giblorb_err_t count_resources(glui32 usage, glui32 *num, glui32 *min, glui32 *max);
};
} // End of namespace Glk
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index c2a8264..87b736c 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -111,7 +111,7 @@ Common::Error GlkEngine::run() {
_blorb = new Blorb(filename, getInterpreterType());
SearchMan.add("blorb", _blorb, 99, false);
- if (!f.open("EXEC", *_blorb))
+ if (!f.open("game", *_blorb))
return Common::kNoGameDataFoundError;
} else {
if (!f.open(filename))
Commit: 720ef67a7d124f1d83fdea68879461bca9429a9b
https://github.com/scummvm/scummvm/commit/720ef67a7d124f1d83fdea68879461bca9429a9b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fixed detection of Infocom .dat gamefiles
Changed paths:
engines/glk/frotz/detection.cpp
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 29eb5d7..e1c60bd 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -44,7 +44,7 @@ PlainGameDescriptor FrotzMetaEngine::findGame(const char *gameId) {
}
bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
- const char *const EXTENSIONS[9] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
+ const char *const EXTENSIONS[10] = { ".dat", ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
@@ -53,7 +53,7 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
continue;
Common::String filename = file->getName();
bool hasExt = false;
- for (int idx = 0; idx < 9 && !hasExt; ++idx)
+ for (int idx = 0; idx < 10 && !hasExt; ++idx)
hasExt = filename.hasSuffixIgnoreCase(EXTENSIONS[idx]);
if (!hasExt)
continue;
@@ -71,9 +71,12 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
}
gameFile.close();
- // Check for known game
+ // Check for known games. Note that there has been some variation in exact filesizes
+ // for Infocom games due to padding at the end of files. So we match on md5s for the
+ // first 5Kb, and only worry about filesize for more recent Blorb based Zcode games
const FrotzGameDescription *p = FROTZ_GAMES;
- while (p->_gameId && p->_md5 && (md5 != p->_md5 || filesize != p->_filesize))
+ while (p->_gameId && p->_md5 && (md5 != p->_md5 ||
+ (filesize != p->_filesize && filename.hasSuffix(".zblorb"))))
++p;
DetectedGame gd;
Commit: 0b1e695f249d695333279eaf711b779c43b7b13d
https://github.com/scummvm/scummvm/commit/0b1e695f249d695333279eaf711b779c43b7b13d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Beginnings of support for Infocom picture files
Changed paths:
A engines/glk/frotz/pics.cpp
A engines/glk/frotz/pics.h
engines/glk/blorb.cpp
engines/glk/conf.cpp
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/glk_api.cpp
engines/glk/glk_api.h
engines/glk/module.mk
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index ace0e91..f8a8cbd 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -40,6 +40,7 @@ enum {
ID_JPEG = MKTAG('J', 'P', 'E', 'G'),
ID_PNG = MKTAG('P', 'N', 'G', ' '),
+ ID_Rect = MKTAG('R', 'e', 'c', 't'),
ID_MIDI = MKTAG('M', 'I', 'D', 'I'),
ID_MP3 = MKTAG('M', 'P', '3', ' '),
@@ -138,9 +139,11 @@ Common::ErrorCode Blorb::load() {
if (ce._type == ID_Pict) {
ce._filename = Common::String::format("pic%u", ce._number);
if (ce._id == ID_JPEG)
- ce._filename += ".jpeg";
+ ce._filename += ".jpg";
else if (ce._id == ID_PNG)
ce._filename += ".png";
+ else if (ce._id == ID_Rect)
+ ce._filename += ".rect";
} else if (ce._type == ID_Snd) {
ce._filename = Common::String::format("snd%u", ce._number);
diff --git a/engines/glk/conf.cpp b/engines/glk/conf.cpp
index 89b08fb..4775f26 100644
--- a/engines/glk/conf.cpp
+++ b/engines/glk/conf.cpp
@@ -155,6 +155,10 @@ Conf::Conf(InterpreterType interpType) {
get("stylehint", _styleHint, 1);
get("safeclicks", _safeClicks);
+ // For simplicity's sake, only allow graphics when in non-paletted graphics modes
+ if (g_system->getScreenFormat().bytesPerPixel == 1)
+ _graphics = false;
+
Common::copy(T_STYLES, T_STYLES + style_NUMSTYLES, _tStyles);
Common::copy(G_STYLES, G_STYLES + style_NUMSTYLES, _gStyles);
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index a8b25a2..2790e30 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -21,13 +21,16 @@
*/
#include "glk/frotz/glk_interface.h"
+#include "glk/frotz/pics.h"
+#include "glk/conf.h"
+#include "glk/screen.h"
namespace Glk {
namespace Frotz {
GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) :
GlkAPI(syst, gameDesc),
- oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
+ _pics(nullptr), oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
gos_lower(nullptr), gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr),
@@ -38,6 +41,10 @@ GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) :
Common::fill(&statusline[0], &statusline[256], '\0');
}
+GlkInterface::~GlkInterface() {
+ delete _pics;
+}
+
void GlkInterface::initialize() {
uint width, height;
@@ -152,8 +159,13 @@ void GlkInterface::initialize() {
h_font_height = 1;
// Must be after screen dimensions are computed
- if (h_version == V6) {
- h_flags &= ~GRAPHICS_FLAG;
+ if (g_conf->_graphics) {
+ if (_blorb)
+ // Blorb file containers allow graphics
+ h_flags |= GRAPHICS_FLAG;
+ else if ((h_version == V6 || _storyId == BEYOND_ZORK) && initPictures())
+ // Earlier Infocom game with picture files
+ h_flags |= GRAPHICS_FLAG;
}
// Use the ms-dos interpreter number for v6, because that's the
@@ -170,6 +182,18 @@ void GlkInterface::initialize() {
}
}
+bool GlkInterface::initPictures() {
+ if (Pics::exists()) {
+ _pics = new Pics();
+ SearchMan.add("Pics", _pics, 99, false);
+ return true;
+ }
+
+ if (h_version == V6)
+ warning("Could not locate MG1 file");
+ return false;
+}
+
int GlkInterface::os_char_width(zchar z) {
return 1;
}
@@ -234,6 +258,18 @@ void GlkInterface::os_stop_sample(int a) {
void GlkInterface::os_beep(int volume) {
}
+bool GlkInterface::os_picture_data(int picture, glui32 *height, glui32 *width) {
+ if (_pics && picture == 0) {
+ *width = _pics->version();
+ *height = _pics->size();
+ return true;
+ } else {
+ return glk_image_get_info(picture, width, height);
+ }
+}
+
+
+
void GlkInterface::start_sample(int number, int volume, int repeats, zword eos) {
// TODO
}
@@ -405,6 +441,24 @@ void GlkInterface::gos_cancel_pending_line() {
gos_linepending = 0;
}
+void GlkInterface::os_restart_game(RestartAction stage) {
+ // Show Beyond Zork's title screen
+ if ((stage == RESTART_END) && (_storyId == BEYOND_ZORK)) {
+/*
+ uint w, h;
+ if (os_picture_data(1, &h, &w)) {
+ _screen->clear();
+ os_draw_picture(1, Common::Point(1, 1));
+ _events->waitForPress();
+ }
+ */
+ }
+}
+
+void GlkInterface::os_draw_picture(int picture, winid_t win, const Common::Point &pos) {
+ glk_image_draw(win, picture, pos.x - 1, pos.y - 1);
+}
+
zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
event_t ev;
winid_t win = gos_curwin ? gos_curwin : gos_lower;
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index 5e2fa62..0dc8846 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -42,6 +42,7 @@ enum RestartAction {
RESTART_END = 2
};
+class Pics;
/**
* Implements an intermediate interface on top of the GLK layer, providing screen
@@ -49,6 +50,7 @@ enum RestartAction {
*/
class GlkInterface : public GlkAPI, public virtual UserOptions, public virtual Mem {
public:
+ Pics *_pics;
zchar statusline[256];
int oldstyle;
int curstyle;
@@ -93,6 +95,11 @@ public:
bool _soundLocked;
bool _soundPlaying;
+private:
+ /**
+ * Loads the pictures file for Infocom V6 games
+ */
+ bool initPictures();
protected:
/**
* Return the length of the character in screen units.
@@ -133,10 +140,30 @@ protected:
*/
void os_start_sample(int number, int volume, int repeats, zword eos);
+ /**
+ * Stop playing a given sound number
+ */
void os_stop_sample(int a);
+
+ /**
+ * Make a beep sound
+ */
void os_beep(int volume);
/**
+ * Return true if the given picture is available. If so, write the
+ * width and height of the picture into the appropriate variables.
+ * Only when picture 0 is asked for, write the number of available
+ * pictures and the release number instead.
+ */
+ bool os_picture_data(int picture, glui32 *height, glui32 *width);
+
+ /**
+ * Display a picture at the given coordinates. Top left is (1,1).
+ */
+ void os_draw_picture(int picture, winid_t win, const Common::Point &pos);
+
+ /**
* Call the IO interface to play a sample.
*/
void start_sample(int number, int volume, int repeats, zword eos);
@@ -165,7 +192,7 @@ protected:
/**
* Called during game restarts
*/
- void os_restart_game(RestartAction) {}
+ void os_restart_game(RestartAction stage);
/**
* Reads the mouse buttons
@@ -197,7 +224,11 @@ public:
* Constructor
*/
GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc);
- virtual ~GlkInterface() {}
+
+ /**
+ * Destructor
+ */
+ virtual ~GlkInterface();
/**
* Initialization
diff --git a/engines/glk/frotz/pics.cpp b/engines/glk/frotz/pics.cpp
new file mode 100644
index 0000000..29d2ec5
--- /dev/null
+++ b/engines/glk/frotz/pics.cpp
@@ -0,0 +1,116 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/pics.h"
+#include "glk/glk.h"
+
+namespace Glk {
+namespace Frotz {
+
+enum {
+ PIC_FILE_HEADER_FLAGS = 1,
+ PIC_FILE_HEADER_NUM_IMAGES = 4,
+ PIC_FILE_HEADER_ENTRY_SIZE = 8,
+ PIC_FILE_HEADER_VERSION = 14
+};
+
+Pics::Pics() : Common::Archive(), _filename(getFilename()) {
+ Common::File f;
+ if (!f.open(_filename))
+ error("Error reading Pics file");
+
+ byte buffer[16];
+ f.read(buffer, 16);
+ _index.resize(READ_LE_UINT16(&buffer[PIC_FILE_HEADER_NUM_IMAGES]));
+ _entrySize = buffer[PIC_FILE_HEADER_ENTRY_SIZE];
+ _version = buffer[PIC_FILE_HEADER_FLAGS];
+
+ // Iterate through loading the index
+ for (uint idx = 0; idx < _index.size(); ++idx) {
+ Entry &e = _index[idx];
+ e._number = f.readUint16LE();
+ e._offset = f.pos();
+ e._size = _entrySize - 2;
+ f.skip(_entrySize - 2);
+
+ e._filename = Common::String::format("PIC%u", e._number);
+ }
+
+ f.close();
+}
+
+Common::String Pics::getFilename() {
+ Common::String filename = g_vm->getFilename();
+ while (filename.contains('.'))
+ filename.deleteLastChar();
+
+ return filename + ".mg1";
+}
+
+bool Pics::exists() {
+ return Common::File::exists(getFilename());
+}
+
+bool Pics::hasFile(const Common::String &name) const {
+ for (uint idx = 0; idx < _index.size(); ++idx) {
+ if (_index[idx]._filename.equalsIgnoreCase(name))
+ return true;
+ }
+
+ return false;
+}
+
+int Pics::listMembers(Common::ArchiveMemberList &list) const {
+ for (uint idx = 0; idx < _index.size(); ++idx) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(_index[idx]._filename, this)));
+ }
+
+ return (int)_index.size();
+}
+
+const Common::ArchiveMemberPtr Pics::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::String &name) const {
+ for (uint idx = 0; idx < _index.size(); ++idx) {
+ if (_index[idx]._filename.equalsIgnoreCase(name)) {
+ Common::File f;
+ if (!f.open(_filename))
+ error("Reading failed");
+
+ f.seek(_index[idx]._offset);
+ Common::SeekableReadStream *result = f.readStream(_index[idx]._size);
+ f.close();
+
+ return result;
+ }
+ }
+
+ return nullptr;
+}
+
+} // End of namespace Frotz
+} // End of namespace Glk
diff --git a/engines/glk/frotz/pics.h b/engines/glk/frotz/pics.h
new file mode 100644
index 0000000..55e3c0d
--- /dev/null
+++ b/engines/glk/frotz/pics.h
@@ -0,0 +1,107 @@
+/* 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_FROTZ_PICS
+#define GLK_FROTZ_PICS
+
+#include "common/archive.h"
+#include "common/array.h"
+
+namespace Glk {
+namespace Frotz {
+
+/**
+ * Infocom graphics file manager
+ */
+class Pics : public Common::Archive {
+ /**
+ * Describes one chunk of the Blorb file.
+ */
+ struct Entry {
+ uint _number;
+ size_t _offset;
+ size_t _size;
+ Common::String _filename;
+ };
+private:
+ Common::String _filename;
+ Common::Array<Entry> _index; ///< list of entries
+ uint _entrySize;
+ uint _version;
+private:
+ /**
+ * Returns the filename for the pictures archive
+ */
+ static Common::String getFilename();
+public:
+ /**
+ * Returns true if an mg1 file exists for the game
+ */
+ static bool exists();
+public:
+ /**
+ * Constructor
+ */
+ Pics();
+
+ /**
+ * Return the number of entries in the file
+ */
+ size_t size() const { return _index.size(); }
+
+ /**
+ * Return the version of the file
+ */
+ uint version() const { return _version; }
+
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ virtual bool hasFile(const Common::String &name) const override;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ virtual int listMembers(Common::ArchiveMemberList &list) const override;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index ec98ab6..981c41e 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -920,7 +920,7 @@ glui32 GlkAPI::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, gls
return false;
}
-glui32 GlkAPI::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
+bool GlkAPI::glk_image_get_info(glui32 image, glui32 *width, glui32 *height) {
if (!g_conf->_graphics)
return false;
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index b625f69..5c19e09 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -193,7 +193,7 @@ public:
glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
glui32 glk_image_draw_scaled(winid_t win, glui32 image,
glsi32 val1, glsi32 val2, glui32 width, glui32 height);
- glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
+ bool glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
void glk_window_flow_break(winid_t win);
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index eedab57..d1d9100 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -26,6 +26,7 @@ MODULE_OBJS := \
frotz/frotz.o \
frotz/glk_interface.o \
frotz/mem.o \
+ frotz/pics.o \
frotz/processor.o \
frotz/processor_buffer.o \
frotz/processor_input.o \
Commit: 3e8ed4eafcfe3fd8198c65b0838022c1dd32eea8
https://github.com/scummvm/scummvm/commit/3e8ed4eafcfe3fd8198c65b0838022c1dd32eea8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GRAPHICS: Add convertToInPlace method to ManagedSurface
Changed paths:
graphics/managed_surface.h
diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h
index 422b461..a7cf70f8 100644
--- a/graphics/managed_surface.h
+++ b/graphics/managed_surface.h
@@ -368,9 +368,22 @@ public:
addDirtyRect(area);
return _innerSurface.getSubArea(area);
}
+
+ /**
+ * Convert the data to another pixel format.
+ *
+ * This works in-place. This means it will not create an additional buffer
+ * for the conversion process. The value of 'pixels' might change though
+ * (that means it might realloc the pixel data).
+ *
+ * @param dstFormat The desired format
+ * @param palette The palette (in RGB888), if the source format has a Bpp of 1
+ */
+ void convertToInPlace(const PixelFormat &dstFormat, const byte *palette = 0) {
+ _innerSurface.convertToInPlace(dstFormat, palette);
+ }
};
} // End of namespace Graphics
-
#endif
Commit: 6f508124937df1b0cda5a2732039a82c4ec16b85
https://github.com/scummvm/scummvm/commit/6f508124937df1b0cda5a2732039a82c4ec16b85
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Added RawDecoder class for new raw picture data format
Changed paths:
A engines/glk/raw_decoder.cpp
A engines/glk/raw_decoder.h
engines/glk/glk_api.cpp
engines/glk/glk_api.h
engines/glk/module.mk
engines/glk/picture.cpp
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index 981c41e..2a5fd11 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -887,7 +887,7 @@ glui32 GlkAPI::glk_buffer_canon_normalize_uni(glui32 *buf, glui32 len, glui32 nu
return 0;
}
-glui32 GlkAPI::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
+bool GlkAPI::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
if (!win) {
warning("image_draw: invalid ref");
} else if (g_conf->_graphics) {
@@ -903,7 +903,7 @@ glui32 GlkAPI::glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val
return false;
}
-glui32 GlkAPI::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2,
+bool GlkAPI::glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2,
glui32 width, glui32 height) {
if (!win) {
warning("image_draw_scaled: invalid ref");
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index 5c19e09..fe25930 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -190,8 +190,8 @@ public:
#ifdef GLK_MODULE_IMAGE
- glui32 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
- glui32 glk_image_draw_scaled(winid_t win, glui32 image,
+ bool glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2);
+ bool glk_image_draw_scaled(winid_t win, glui32 image,
glsi32 val1, glsi32 val2, glui32 width, glui32 height);
bool glk_image_get_info(glui32 image, glui32 *width, glui32 *height);
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index d1d9100..a4344df 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
glk.o \
glk_api.o \
picture.o \
+ raw_decoder.o \
screen.o \
selection.o \
streams.o \
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 122d9c3..7770bb8 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -22,6 +22,7 @@
#include "glk/picture.h"
#include "glk/glk.h"
+#include "glk/raw_decoder.h"
#include "glk/screen.h"
#include "common/file.h"
#include "image/jpeg.h"
@@ -102,7 +103,9 @@ Picture *Pictures::retrieve(uint id, bool scaled) {
Picture *Pictures::load(uint32 id) {
::Image::PNGDecoder png;
::Image::JPEGDecoder jpg;
+ RawDecoder raw;
const Graphics::Surface *img;
+ const byte *palette = nullptr;
Picture *pic;
// Check if the picture is already in the store
@@ -114,15 +117,25 @@ Picture *Pictures::load(uint32 id) {
if (f.open(Common::String::format("PIC%lu.png", id))) {
png.loadStream(f);
img = png.getSurface();
+ palette = png.getPalette();
} else if (f.open(Common::String::format("PIC%lu.jpg", id))) {
jpg.loadStream(f);
img = jpg.getSurface();
+ } else if (f.open(Common::String::format("PIC%lu.raw", id))) {
+ raw.loadStream(f);
+ img = raw.getSurface();
+ palette = raw.getPalette();
}
pic = new Picture();
pic->_refCount = 1;
pic->_id = id;
pic->_scaled = false;
+ pic->create(img->w, img->h, g_system->getScreenFormat());
+ pic->blitFrom(*img);
+
+ if (palette)
+ pic->convertToInPlace(g_system->getScreenFormat(), palette);
store(pic);
return pic;
diff --git a/engines/glk/raw_decoder.cpp b/engines/glk/raw_decoder.cpp
new file mode 100644
index 0000000..a5cd593
--- /dev/null
+++ b/engines/glk/raw_decoder.cpp
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+#include "glk/raw_decoder.h"
+#include "common/stream.h"
+
+namespace Glk {
+
+RawDecoder::RawDecoder() : Image::ImageDecoder(), _palette(nullptr), _paletteColorCount(0) {
+}
+
+RawDecoder::~RawDecoder() {
+ destroy();
+}
+
+void RawDecoder::destroy() {
+ _surface.free();
+ delete[] _palette;
+ _palette = nullptr;
+}
+
+bool RawDecoder::loadStream(Common::SeekableReadStream &stream) {
+ // Reset member variables from previous decodings
+ destroy();
+
+ uint width = stream.readUint16LE();
+ uint height = stream.readUint16LE();
+ _paletteColorCount = stream.readByte();
+ assert(_paletteColorCount > 0);
+
+ // Read in the palette
+ _palette = new byte[_paletteColorCount * 3];
+ stream.read(_palette, _paletteColorCount * 3);
+
+ // Set up the surface and read it in
+ _surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ stream.read(_surface.getPixels(), width * height);
+
+ return true;
+}
+
+} // End of namespace Glk
diff --git a/engines/glk/raw_decoder.h b/engines/glk/raw_decoder.h
new file mode 100644
index 0000000..96f25c2
--- /dev/null
+++ b/engines/glk/raw_decoder.h
@@ -0,0 +1,61 @@
+/* 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_RAW_DECODER_H
+#define GLK_RAW_DECODER_H
+
+#include "graphics/surface.h"
+#include "image/image_decoder.h"
+
+namespace Glk {
+
+/**
+ * This image decoder class implements loading of a simplified image format.
+ * It's used for sub-engines like Frotz with custom picture formats. They can
+ * expose their picture archives using Common::Archive, and have the individual
+ * picture files stored in the format for this decoder to load
+ * Format:
+ * width 2 bytes
+ * height 2 bytes
+ * pal size 1 byte
+ * palette 3 bytes * pal size
+ * pixels width * height pixels
+ */
+class RawDecoder : public Image::ImageDecoder {
+private:
+ Graphics::Surface _surface;
+ byte *_palette;
+ uint16 _paletteColorCount;
+public:
+ RawDecoder();
+ ~RawDecoder();
+
+ virtual bool loadStream(Common::SeekableReadStream &stream) override;
+ virtual void destroy() override;
+ virtual const Graphics::Surface *getSurface() const override { return &_surface; }
+ virtual const byte *getPalette() const override { return _palette; }
+ virtual uint16 getPaletteColorCount() const override { return _paletteColorCount; }
+};
+
+} // End of namespace Glk
+
+#endif
Commit: a334cd704e21044e0660f918e1c9e3a5040c5837
https://github.com/scummvm/scummvm/commit/a334cd704e21044e0660f918e1c9e3a5040c5837
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Further loading of Infocom pictures files
Changed paths:
A engines/glk/frotz/pics_decoder.cpp
A engines/glk/frotz/pics_decoder.h
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/frotz/pics.cpp
engines/glk/frotz/pics.h
engines/glk/module.mk
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index 2790e30..4e7a503 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -96,11 +96,17 @@ void GlkInterface::initialize() {
glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Weight, 1);
glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Oblique, 1);
+ /*
+ * Open game windows
+ */
+ if (_storyId == BEYOND_ZORK)
+ showBeyondZorkTitle();
+
gos_lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
if (!gos_lower)
gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
glk_window_get_size(gos_lower, &width, &height);
- glk_window_close(gos_lower, NULL);
+ glk_window_close(gos_lower, nullptr);
gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
gos_upper = glk_window_open(gos_lower,
@@ -108,7 +114,7 @@ void GlkInterface::initialize() {
0,
wintype_TextGrid, 0);
- gos_channel = NULL;
+ gos_channel = nullptr;
glk_set_window(gos_lower);
gos_curwin = gos_lower;
@@ -441,18 +447,17 @@ void GlkInterface::gos_cancel_pending_line() {
gos_linepending = 0;
}
-void GlkInterface::os_restart_game(RestartAction stage) {
- // Show Beyond Zork's title screen
- if ((stage == RESTART_END) && (_storyId == BEYOND_ZORK)) {
-/*
- uint w, h;
- if (os_picture_data(1, &h, &w)) {
- _screen->clear();
- os_draw_picture(1, Common::Point(1, 1));
- _events->waitForPress();
- }
- */
+void GlkInterface::showBeyondZorkTitle() {
+ uint winW, winH, imgW, imgH;
+ winid_t win = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
+ glk_window_get_size(gos_lower, &winW, &winH);
+
+ if (os_picture_data(1, &imgW, &imgH)) {
+ os_draw_picture(1, win, Common::Point(1, 1));
+ _events->waitForPress();
}
+
+ glk_window_close(win, nullptr);
}
void GlkInterface::os_draw_picture(int picture, winid_t win, const Common::Point &pos) {
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index 0dc8846..b279ec8 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -100,6 +100,11 @@ private:
* Loads the pictures file for Infocom V6 games
*/
bool initPictures();
+
+ /**
+ * Displays the title screen for the game Beyond Zork
+ */
+ void showBeyondZorkTitle();
protected:
/**
* Return the length of the character in screen units.
@@ -192,7 +197,7 @@ protected:
/**
* Called during game restarts
*/
- void os_restart_game(RestartAction stage);
+ void os_restart_game(RestartAction stage) {}
/**
* Reads the mouse buttons
diff --git a/engines/glk/frotz/pics.cpp b/engines/glk/frotz/pics.cpp
index 29d2ec5..976c2b2 100644
--- a/engines/glk/frotz/pics.cpp
+++ b/engines/glk/frotz/pics.cpp
@@ -21,7 +21,9 @@
*/
#include "glk/frotz/pics.h"
+#include "glk/frotz/pics_decoder.h"
#include "glk/glk.h"
+#include "common/algorithm.h"
namespace Glk {
namespace Frotz {
@@ -38,21 +40,53 @@ Pics::Pics() : Common::Archive(), _filename(getFilename()) {
if (!f.open(_filename))
error("Error reading Pics file");
+ Common::Array<uint> offsets;
byte buffer[16];
f.read(buffer, 16);
_index.resize(READ_LE_UINT16(&buffer[PIC_FILE_HEADER_NUM_IMAGES]));
_entrySize = buffer[PIC_FILE_HEADER_ENTRY_SIZE];
_version = buffer[PIC_FILE_HEADER_FLAGS];
+ assert(_entrySize >= 6 && _entrySize <= 14);
// Iterate through loading the index
for (uint idx = 0; idx < _index.size(); ++idx) {
Entry &e = _index[idx];
- e._number = f.readUint16LE();
- e._offset = f.pos();
- e._size = _entrySize - 2;
- f.skip(_entrySize - 2);
+ f.read(buffer, _entrySize);
+
+ e._number = READ_LE_UINT16(buffer);
+ e._width = READ_LE_UINT16(buffer + 2);
+ e._height = READ_LE_UINT16(buffer + 4);
+
+ if (_entrySize >= 11) {
+ e._dataOffset = READ_BE_UINT32(buffer + 7) & 0xffffff;
+ if (e._dataOffset)
+ offsets.push_back(e._dataOffset);
+
+ if (_entrySize == 14) {
+ e._paletteOffset = READ_BE_UINT32(buffer + 10) & 0xffffff;
+ e._paletteSize = e._dataOffset - e._paletteOffset;
+ assert((e._paletteSize % 3) == 0);
+ }
+ }
- e._filename = Common::String::format("PIC%u", e._number);
+ e._filename = Common::String::format("pic%u.raw", e._number);
+ }
+
+ // Further processing of index to calculate data sizes
+ Common::sort(offsets.begin(), offsets.end());
+
+ for (uint idx = 0; idx < _index.size(); ++idx) {
+ Entry &e = _index[idx];
+ if (!e._dataOffset)
+ continue;
+
+ // Find the entry in the offsets array
+ uint oidx = 0;
+ while (oidx < offsets.size() && offsets[oidx] != e._dataOffset)
+ ++oidx;
+
+ // Set the size
+ e._dataSize = (oidx == (offsets.size() - 1) ? f.size() : offsets[oidx + 1]) - e._dataOffset;
}
f.close();
@@ -96,16 +130,27 @@ const Common::ArchiveMemberPtr Pics::getMember(const Common::String &name) const
Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::String &name) const {
for (uint idx = 0; idx < _index.size(); ++idx) {
- if (_index[idx]._filename.equalsIgnoreCase(name)) {
+ const Entry &e = _index[idx];
+ if (e._filename.equalsIgnoreCase(name)) {
Common::File f;
if (!f.open(_filename))
error("Reading failed");
- f.seek(_index[idx]._offset);
- Common::SeekableReadStream *result = f.readStream(_index[idx]._size);
- f.close();
-
- return result;
+ // Read in the image's palette
+ assert(e._paletteSize);
+ Common::Array<byte> palette;
+ palette.resize(e._paletteSize);
+ f.seek(e._paletteOffset);
+ f.read(&palette[0], e._paletteSize);
+
+ if (e._dataSize) {
+ Common::SeekableReadStream *src = f.readStream(e._dataSize);
+ f.close();
+ return PictureDecoder::decode(*src, &palette[0]);
+
+ } else {
+ error("TODO: Empty rect renderings");
+ }
}
}
diff --git a/engines/glk/frotz/pics.h b/engines/glk/frotz/pics.h
index 55e3c0d..b05acc5 100644
--- a/engines/glk/frotz/pics.h
+++ b/engines/glk/frotz/pics.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef GLK_FROTZ_PICS
-#define GLK_FROTZ_PICS
+#ifndef GLK_FROTZ_PICS_H
+#define GLK_FROTZ_PICS_H
#include "common/archive.h"
#include "common/array.h"
@@ -38,9 +38,15 @@ class Pics : public Common::Archive {
*/
struct Entry {
uint _number;
- size_t _offset;
- size_t _size;
+ size_t _width, _height;
+ size_t _dataOffset;
+ size_t _dataSize;
+ size_t _paletteOffset;
+ size_t _paletteSize;
Common::String _filename;
+
+ Entry() : _number(0), _width(0), _height(0), _dataOffset(0), _dataSize(0),
+ _paletteOffset(0), _paletteSize(0) {}
};
private:
Common::String _filename;
diff --git a/engines/glk/frotz/pics_decoder.cpp b/engines/glk/frotz/pics_decoder.cpp
new file mode 100644
index 0000000..a67ed12
--- /dev/null
+++ b/engines/glk/frotz/pics_decoder.cpp
@@ -0,0 +1,34 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/pics_decoder.h"
+
+namespace Glk {
+namespace Frotz {
+
+Common::MemoryReadStream *PictureDecoder::decode(Common::ReadStream &src, const byte *palette) {
+ // TODO
+ return nullptr;
+}
+
+} // End of namespace Frotz
+} // End of namespace Glk
diff --git a/engines/glk/frotz/pics_decoder.h b/engines/glk/frotz/pics_decoder.h
new file mode 100644
index 0000000..41484a1
--- /dev/null
+++ b/engines/glk/frotz/pics_decoder.h
@@ -0,0 +1,47 @@
+/* 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_FROTZ_PICS_DECODER_H
+#define GLK_FROTZ_PICS_DECODER_H
+
+#include "common/memstream.h"
+#include "common/stream.h"
+
+namespace Glk {
+namespace Frotz {
+
+/**
+ * Decodes an Infocom encoded picture into a raw pixel stream that the outer
+ * Glk engine is capable of then loading into a picture object
+ */
+class PictureDecoder {
+public:
+ /**
+ * Decode method
+ */
+ static Common::MemoryReadStream *decode(Common::ReadStream &src, const byte *palette);
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index a4344df..0206643 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -28,6 +28,7 @@ MODULE_OBJS := \
frotz/glk_interface.o \
frotz/mem.o \
frotz/pics.o \
+ frotz/pics_decoder.o \
frotz/processor.o \
frotz/processor_buffer.o \
frotz/processor_input.o \
Commit: f92b82664dd099ac4d4439f614188a6544bfff2c
https://github.com/scummvm/scummvm/commit/f92b82664dd099ac4d4439f614188a6544bfff2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Fix gcc warnings
Changed paths:
engines/glk/blorb.cpp
engines/glk/picture.cpp
engines/glk/picture.h
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index f8a8cbd..5c1f0bd 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -47,7 +47,7 @@ enum {
ID_WAVE = MKTAG('W', 'A', 'V', 'E'),
ID_AIFF = MKTAG('A', 'I', 'F', 'F'),
ID_OGG = MKTAG('O', 'G', 'G', ' '),
- ID_MOD = MKTAG('M', 'O', 'D', ' '),
+ ID_MOD = MKTAG('M', 'O', 'D', ' ')
};
/*--------------------------------------------------------------------------*/
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 7770bb8..6d8fce9 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -109,22 +109,25 @@ Picture *Pictures::load(uint32 id) {
Picture *pic;
// Check if the picture is already in the store
- pic = retrieve(id, false);
- if (pic)
- return pic;
+ pic = retrieve(id, false);
+ if (pic)
+ return pic;
Common::File f;
- if (f.open(Common::String::format("PIC%lu.png", id))) {
+ if (f.open(Common::String::format("PIC%u.png", id))) {
png.loadStream(f);
img = png.getSurface();
palette = png.getPalette();
- } else if (f.open(Common::String::format("PIC%lu.jpg", id))) {
+ } else if (f.open(Common::String::format("PIC%u.jpg", id))) {
jpg.loadStream(f);
img = jpg.getSurface();
- } else if (f.open(Common::String::format("PIC%lu.raw", id))) {
+ } else if (f.open(Common::String::format("PIC%u.raw", id))) {
raw.loadStream(f);
img = raw.getSurface();
palette = raw.getPalette();
+ } else {
+ // No such picture
+ return nullptr;
}
pic = new Picture();
diff --git a/engines/glk/picture.h b/engines/glk/picture.h
index f221569..06d598b 100644
--- a/engines/glk/picture.h
+++ b/engines/glk/picture.h
@@ -45,8 +45,8 @@ public:
/**
* Constructor
*/
- Picture(int width, int height, const Graphics::PixelFormat &format) :
- Graphics::ManagedSurface(width, height, format), _refCount(0), _id(0), _scaled(false) {}
+ Picture(int width, int height, const Graphics::PixelFormat &fmt) :
+ Graphics::ManagedSurface(width, height, fmt), _refCount(0), _id(0), _scaled(false) {}
/**
* Increment reference counter
Commit: 0aff016ad9633ee38b74a91d73743267456977c9
https://github.com/scummvm/scummvm/commit/0aff016ad9633ee38b74a91d73743267456977c9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix deletion of undo_mem
Changed paths:
engines/glk/frotz/mem.cpp
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index bec30b0..656b822 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -231,7 +231,7 @@ void Mem::reset_memory() {
if (undo_mem) {
free_undo(undo_count);
- delete undo_mem;
+ delete[] undo_mem;
}
undo_mem = nullptr;
Commit: 5b9e1a53ad4c2baca32dbb3fce22230cc7e8bc40
https://github.com/scummvm/scummvm/commit/5b9e1a53ad4c2baca32dbb3fce22230cc7e8bc40
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix mismatch allocation/free
Changed paths:
engines/glk/frotz/mem.cpp
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index 656b822..19d2c3d 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -88,7 +88,7 @@ void Mem::initializeUndo() {
void Mem::loadGameHeader() {
// Load header
- zmp = new byte[64];
+ zmp = (byte *)malloc(64);
story_fp->seek(0);
story_fp->read(zmp, 64);
@@ -236,7 +236,7 @@ void Mem::reset_memory() {
undo_mem = nullptr;
undo_count = 0;
- delete[] zmp;
+ free(zmp);
zmp = nullptr;
}
Commit: c7a632ae2ed6a11500bc77b53540bb7ea23cb0d1
https://github.com/scummvm/scummvm/commit/c7a632ae2ed6a11500bc77b53540bb7ea23cb0d1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix initialization of undo data
Changed paths:
engines/glk/frotz/mem.cpp
diff --git a/engines/glk/frotz/mem.cpp b/engines/glk/frotz/mem.cpp
index 19d2c3d..0665eea 100644
--- a/engines/glk/frotz/mem.cpp
+++ b/engines/glk/frotz/mem.cpp
@@ -35,8 +35,8 @@ Mem::Mem() : story_fp(nullptr), story_size(0), first_undo(nullptr), last_undo(nu
void Mem::initialize() {
initializeStoryFile();
- initializeUndo();
loadGameHeader();
+ initializeUndo();
// Allocate memory for story data
if ((zmp = (zbyte *)realloc(zmp, story_size)) == nullptr)
Commit: 4a3f517b719d4ee07fab8f704d5884c52c0da4c1
https://github.com/scummvm/scummvm/commit/4a3f517b719d4ee07fab8f704d5884c52c0da4c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Prompt for exit when game quits
Changed paths:
engines/glk/frotz/frotz.cpp
engines/glk/frotz/processor.h
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 95cdb22..d3b0749 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -44,6 +44,11 @@ void Frotz::runGame(Common::SeekableReadStream *gameFile) {
// Game loop
interpret();
+
+ if (!shouldQuit()) {
+ flush_buffer();
+ glk_exit();
+ }
}
void Frotz::initialize() {
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index 5f61a2e..77a673d 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -169,11 +169,6 @@ private:
* @{
*/
- /**
- * Copy the contents of the text buffer to the output streams.
- */
- void flush_buffer();
-
/**
* High level output function.
*/
@@ -1545,6 +1540,18 @@ protected:
void z_store();
/**@}*/
+
+ /**
+ * \defgroup Input support methods
+ * @{
+ */
+
+ /**
+ * Copy the contents of the text buffer to the output streams.
+ */
+ void flush_buffer();
+
+ /**@}*/
public:
/**
* Constructor
Commit: 1c190e50b45701802bcc8fe9e96d0c782e7d96a2
https://github.com/scummvm/scummvm/commit/1c190e50b45701802bcc8fe9e96d0c782e7d96a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Mark text strings as translateable
Changed paths:
engines/glk/glk_api.cpp
engines/glk/scott/scott.cpp
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index 2a5fd11..19f8aef 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -30,7 +30,7 @@
#include "glk/window_graphics.h"
#include "glk/window_text_buffer.h"
#include "glk/window_pair.h"
-
+#include "common/translation.h"
namespace Glk {
@@ -59,7 +59,7 @@ GlkAPI::GlkAPI(OSystem *syst, const GlkGameDescription &gameDesc) :
}
void GlkAPI::glk_exit(void) {
- glk_put_string("[ press any key to exit ]");
+ glk_put_string(_("[ press any key to exit ]"));
_events->waitForPress();
// Trigger a ScumMVM shutdown of game
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index dc0ae0b..eb8cd40 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -22,6 +22,7 @@
#include "glk/scott/scott.h"
#include "common/config-manager.h"
+#include "common/translation.h"
namespace Glk {
namespace Scott {
@@ -94,10 +95,10 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
switch (performActions(vb, no)) {
case -1:
- output("I don't understand your command. ");
+ output(_("I don't understand your command. "));
break;
case -2:
- output("I can't do that yet. ");
+ output(_("I can't do that yet. "));
break;
default:
break;
@@ -113,9 +114,9 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
if (_items[LIGHT_SOURCE]._location == CARRIED ||
_items[LIGHT_SOURCE]._location == MY_LOC) {
if (_options & SCOTTLIGHT)
- output("Light has run out! ");
+ output(_("Light has run out! "));
else
- output("Your light has run out. ");
+ output(_("Your light has run out. "));
}
if (_options & PREHISTORIC_LAMP)
_items[LIGHT_SOURCE]._location = DESTROYED;
@@ -124,12 +125,12 @@ void Scott::runGame(Common::SeekableReadStream *gameFile) {
_items[LIGHT_SOURCE]._location == MY_LOC) {
if (_options & SCOTTLIGHT) {
- output("Light runs out in ");
+ output(_("Light runs out in "));
outputNumber(_gameHeader._lightTime);
- output(" turns. ");
+ output(_(" turns. "));
} else {
if (_gameHeader._lightTime % 5 == 0)
- output("Your light is growing dim. ");
+ output(_("Your light is growing dim. "));
}
}
}
@@ -388,7 +389,9 @@ void Scott::outputNumber(int a) {
}
void Scott::look(void) {
- const char *const ExitNames[6] = { "North", "South", "East", "West", "Up", "Down" };
+ const char *const ExitNames[6] = {
+ _("North"), _("South"), _("East"), _("West"), _("Up"), _("Down")
+ };
Room *r;
int ct, f;
int pos;
@@ -399,9 +402,9 @@ void Scott::look(void) {
if ((_bitFlags & (1 << DARKBIT)) && _items[LIGHT_SOURCE]._location != CARRIED
&& _items[LIGHT_SOURCE]._location != MY_LOC) {
if (_options & YOUARE)
- display(_topWindow, "You can't see. It is too dark!\n");
+ display(_topWindow, _("You can't see. It is too dark!\n"));
else
- display(_topWindow, "I can't see. It is too dark!\n");
+ display(_topWindow, _("I can't see. It is too dark!\n"));
if (_options & TRS80_STYLE)
display(_topWindow, TRS80_LINE);
return;
@@ -411,14 +414,14 @@ void Scott::look(void) {
display(_topWindow, "%s\n", r->_text.c_str() + 1);
else {
if (_options & YOUARE)
- display(_topWindow, "You are in a %s\n", r->_text.c_str());
+ display(_topWindow, _("You are in a %s\n"), r->_text.c_str());
else
- display(_topWindow, "I'm in a %s\n", r->_text.c_str());
+ display(_topWindow, _("I'm in a %s\n"), r->_text.c_str());
}
ct = 0;
f = 0;
- display(_topWindow, "\nObvious exits: ");
+ display(_topWindow, _("\nObvious exits: "));
while (ct < 6) {
if (r->_exits[ct] != 0) {
if (f == 0)
@@ -431,7 +434,7 @@ void Scott::look(void) {
}
if (f == 0)
- display(_topWindow, "none");
+ display(_topWindow, _("none"));
display(_topWindow, ".\n");
ct = 0;
f = 0;
@@ -440,10 +443,10 @@ void Scott::look(void) {
if (_items[ct]._location == MY_LOC) {
if (f == 0) {
if (_options & YOUARE) {
- display(_topWindow, "\nYou can also see: ");
+ display(_topWindow, _("\nYou can also see: "));
pos = 18;
} else {
- display(_topWindow, "\nI can also see: ");
+ display(_topWindow, _("\nI can also see: "));
pos = 16;
}
f++;
@@ -523,7 +526,7 @@ Common::Error Scott::saveGameData(strid_t file) {
glk_put_string_stream(file, msg.c_str());
}
- output("Saved.\n");
+ output(_("Saved.\n"));
return Common::kNoError;
}
@@ -614,7 +617,7 @@ int Scott::getInput(int *vb, int *no) {
*vb = vc;
*no = nc;
if (vc == -1) {
- output("You use word(s) I don't know! ");
+ output(_("You use word(s) I don't know! "));
}
} while (vc == -1);
@@ -742,9 +745,9 @@ int Scott::performLine(int ct) {
case 52:
if (countCarried() == _gameHeader._maxCarry) {
if (_options & YOUARE)
- output("You are carrying too much. ");
+ output(_("You are carrying too much. "));
else
- output("I've too much to carry! ");
+ output(_("I've too much to carry! "));
break;
}
_items[param[pptr++]]._location = CARRIED;
@@ -775,9 +778,9 @@ int Scott::performLine(int ct) {
break;
case 61:
if (_options & YOUARE)
- output("You are dead.\n");
+ output(_("You are dead.\n"));
else
- output("I am dead.\n");
+ output(_("I am dead.\n"));
_bitFlags &= ~(1 << DARKBIT);
MY_LOC = _gameHeader._numRooms;// It seems to be what the code says!
break;
@@ -789,7 +792,7 @@ int Scott::performLine(int ct) {
}
case 63:
doneit:
- output("The game is now over.\n");
+ output(_("The game is now over.\n"));
glk_exit();
return 0;
case 64:
@@ -804,15 +807,15 @@ doneit:
i++;
}
if (_options & YOUARE)
- output("You have stored ");
+ output(_("You have stored "));
else
- output("I've stored ");
+ output(_("I've stored "));
outputNumber(n);
- output(" treasures. On a scale of 0 to 100, that rates ");
+ output(_(" treasures. On a scale of 0 to 100, that rates "));
outputNumber((n * 100) / _gameHeader._treasures);
output(".\n");
if (n == _gameHeader._treasures) {
- output("Well done.\n");
+ output(_("Well done.\n"));
goto doneit;
}
break;
@@ -821,9 +824,9 @@ doneit:
int i = 0;
int f = 0;
if (_options & YOUARE)
- output("You are carrying:\n");
+ output(_("You are carrying:\n"));
else
- output("I'm carrying:\n");
+ output(_("I'm carrying:\n"));
while (i <= _gameHeader._numItems) {
if (_items[i]._location == CARRIED) {
if (f == 1) {
@@ -838,7 +841,7 @@ doneit:
i++;
}
if (f == 0)
- output("Nothing");
+ output(_("Nothing"));
output(".\n");
break;
}
@@ -967,7 +970,7 @@ int Scott::performActions(int vb, int no) {
int fl;
int doagain = 0;
if (vb == 1 && no == -1) {
- output("Give me a direction too.");
+ output(_("Give me a direction too."));
return 0;
}
if (vb == 1 && no >= 1 && no <= 6) {
@@ -976,7 +979,7 @@ int Scott::performActions(int vb, int no) {
_items[LIGHT_SOURCE]._location == CARRIED)
d = 0;
if (d)
- output("Dangerous to move in the dark! ");
+ output(_("Dangerous to move in the dark! "));
nl = _rooms[MY_LOC]._exits[no - 1];
if (nl != 0) {
MY_LOC = nl;
@@ -984,16 +987,16 @@ int Scott::performActions(int vb, int no) {
}
if (d) {
if (_options & YOUARE)
- output("You fell down and broke your neck. ");
+ output(_("You fell down and broke your neck. "));
else
- output("I fell down and broke my neck. ");
+ output(_("I fell down and broke my neck. "));
glk_exit();
return 0;
}
if (_options & YOUARE)
- output("You can't go in that direction. ");
+ output(_("You can't go in that direction. "));
else
- output("I can't go in that direction. ");
+ output(_("I can't go in that direction. "));
return 0;
}
@@ -1051,7 +1054,7 @@ int Scott::performActions(int vb, int no) {
int f = 0;
if (d) {
- output("It is dark.\n");
+ output(_("It is dark.\n"));
return 0;
}
while (i <= _gameHeader._numItems) {
@@ -1065,43 +1068,43 @@ int Scott::performActions(int vb, int no) {
if (countCarried() == _gameHeader._maxCarry) {
if (_options & YOUARE)
- output("You are carrying too much. ");
+ output(_("You are carrying too much. "));
else
- output("I've too much to carry. ");
+ output(_("I've too much to carry. "));
return 0;
}
_items[i]._location = CARRIED;
output(_items[i]._text);
- output(": O.K.\n");
+ output(_(": O.K.\n"));
f = 1;
}
i++;
}
if (f == 0)
- output("Nothing taken.");
+ output(_("Nothing taken."));
return 0;
}
if (no == -1) {
- output("What ? ");
+ output(_("What ? "));
return 0;
}
if (countCarried() == _gameHeader._maxCarry) {
if (_options & YOUARE)
- output("You are carrying too much. ");
+ output(_("You are carrying too much. "));
else
- output("I've too much to carry. ");
+ output(_("I've too much to carry. "));
return 0;
}
item = matchUpItem(_nounText, MY_LOC);
if (item == -1) {
if (_options & YOUARE)
- output("It is beyond your power to do that. ");
+ output(_("It is beyond your power to do that. "));
else
- output("It's beyond my power to do that. ");
+ output(_("It's beyond my power to do that. "));
return 0;
}
_items[item]._location = CARRIED;
- output("O.K. ");
+ output(_("O.K. "));
return 0;
}
if (vb == 18) {
@@ -1120,25 +1123,25 @@ int Scott::performActions(int vb, int no) {
_items[i]._location = MY_LOC;
output(_items[i]._text);
- output(": O.K.\n");
+ output(_(": O.K.\n"));
f = 1;
}
i++;
}
if (f == 0)
- output("Nothing dropped.\n");
+ output(_("Nothing dropped.\n"));
return 0;
}
if (no == -1) {
- output("What ? ");
+ output(_("What ? "));
return 0;
}
item = matchUpItem(_nounText, CARRIED);
if (item == -1) {
if (_options & YOUARE)
- output("It's beyond your power to do that.\n");
+ output(_("It's beyond your power to do that.\n"));
else
- output("It's beyond my power to do that.\n");
+ output(_("It's beyond my power to do that.\n"));
return 0;
}
_items[item]._location = MY_LOC;
Commit: 3700919881a9636ae02478691d8c7c73a6d5084b
https://github.com/scummvm/scummvm/commit/3700919881a9636ae02478691d8c7c73a6d5084b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add POTFILES
Changed paths:
A engines/glk/POTFILES
diff --git a/engines/glk/POTFILES b/engines/glk/POTFILES
new file mode 100644
index 0000000..9caee0e
--- /dev/null
+++ b/engines/glk/POTFILES
@@ -0,0 +1,2 @@
+engines/glk/streams.cpp
+engines/glk/scott/scott.cpp
Commit: 62af5ea8919a5148154413eaec80a9e686d64114
https://github.com/scummvm/scummvm/commit/62af5ea8919a5148154413eaec80a9e686d64114
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: More work on displaying Beyond Zork title screen
Changed paths:
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/pics.cpp
engines/glk/frotz/pics.h
engines/glk/frotz/pics_decoder.cpp
engines/glk/frotz/pics_decoder.h
engines/glk/picture.cpp
engines/glk/raw_decoder.cpp
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index 4e7a503..c046bb4 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -97,10 +97,8 @@ void GlkInterface::initialize() {
glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Oblique, 1);
/*
- * Open game windows
+ * Get the screen size
*/
- if (_storyId == BEYOND_ZORK)
- showBeyondZorkTitle();
gos_lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
if (!gos_lower)
@@ -108,20 +106,8 @@ void GlkInterface::initialize() {
glk_window_get_size(gos_lower, &width, &height);
glk_window_close(gos_lower, nullptr);
- gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
- gos_upper = glk_window_open(gos_lower,
- winmethod_Above | winmethod_Fixed,
- 0,
- wintype_TextGrid, 0);
-
gos_channel = nullptr;
- glk_set_window(gos_lower);
- gos_curwin = gos_lower;
-
- // Set the screen colors
- garglk_set_zcolors(_defaultForeground, _defaultBackground);
-
/*
* Icky magic bit setting
*/
@@ -186,6 +172,24 @@ void GlkInterface::initialize() {
if (h_flags & COLOUR_FLAG)
h_flags &= ~COLOUR_FLAG;
}
+
+ /*
+ * Open the windows
+ */
+ if (_storyId == BEYOND_ZORK)
+ showBeyondZorkTitle();
+
+ gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
+ gos_upper = glk_window_open(gos_lower,
+ winmethod_Above | winmethod_Fixed,
+ 0,
+ wintype_TextGrid, 0);
+
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+
+ // Set the screen colors
+ garglk_set_zcolors(_defaultForeground, _defaultBackground);
}
bool GlkInterface::initPictures() {
@@ -274,8 +278,6 @@ bool GlkInterface::os_picture_data(int picture, glui32 *height, glui32 *width) {
}
}
-
-
void GlkInterface::start_sample(int number, int volume, int repeats, zword eos) {
// TODO
}
diff --git a/engines/glk/frotz/pics.cpp b/engines/glk/frotz/pics.cpp
index 976c2b2..4953f04 100644
--- a/engines/glk/frotz/pics.cpp
+++ b/engines/glk/frotz/pics.cpp
@@ -46,7 +46,7 @@ Pics::Pics() : Common::Archive(), _filename(getFilename()) {
_index.resize(READ_LE_UINT16(&buffer[PIC_FILE_HEADER_NUM_IMAGES]));
_entrySize = buffer[PIC_FILE_HEADER_ENTRY_SIZE];
_version = buffer[PIC_FILE_HEADER_FLAGS];
- assert(_entrySize >= 6 && _entrySize <= 14);
+ assert(_entrySize >= 8 && _entrySize <= 14);
// Iterate through loading the index
for (uint idx = 0; idx < _index.size(); ++idx) {
@@ -56,6 +56,7 @@ Pics::Pics() : Common::Archive(), _filename(getFilename()) {
e._number = READ_LE_UINT16(buffer);
e._width = READ_LE_UINT16(buffer + 2);
e._height = READ_LE_UINT16(buffer + 4);
+ e._flags = READ_LE_UINT16(buffer + 6);
if (_entrySize >= 11) {
e._dataOffset = READ_BE_UINT32(buffer + 7) & 0xffffff;
@@ -64,8 +65,6 @@ Pics::Pics() : Common::Archive(), _filename(getFilename()) {
if (_entrySize == 14) {
e._paletteOffset = READ_BE_UINT32(buffer + 10) & 0xffffff;
- e._paletteSize = e._dataOffset - e._paletteOffset;
- assert((e._paletteSize % 3) == 0);
}
}
@@ -132,25 +131,29 @@ Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::String
for (uint idx = 0; idx < _index.size(); ++idx) {
const Entry &e = _index[idx];
if (e._filename.equalsIgnoreCase(name)) {
+ Common::Array<byte> palette;
Common::File f;
+ Common::SeekableReadStream *dest;
if (!f.open(_filename))
error("Reading failed");
// Read in the image's palette
- assert(e._paletteSize);
- Common::Array<byte> palette;
- palette.resize(e._paletteSize);
+ assert(e._paletteOffset);
f.seek(e._paletteOffset);
- f.read(&palette[0], e._paletteSize);
+ palette.resize(f.readByte() * 3);
+ f.read(&palette[0], palette.size());
+ PictureDecoder decoder;
if (e._dataSize) {
Common::SeekableReadStream *src = f.readStream(e._dataSize);
- f.close();
- return PictureDecoder::decode(*src, &palette[0]);
-
+ dest = decoder.decode(*src, e._flags, palette, MCGA, e._width, e._height);
+ delete src;
} else {
error("TODO: Empty rect renderings");
}
+
+ f.close();
+ return dest;
}
}
diff --git a/engines/glk/frotz/pics.h b/engines/glk/frotz/pics.h
index b05acc5..2c6d17a 100644
--- a/engines/glk/frotz/pics.h
+++ b/engines/glk/frotz/pics.h
@@ -29,24 +29,36 @@
namespace Glk {
namespace Frotz {
+enum PicturesMode {
+ MONO = 0,
+ TEXT = 1,
+ CGA = 2,
+ MCGA = 3,
+ EGA = 4,
+ AMIGA = 5
+};
+
/**
* Infocom graphics file manager
*/
class Pics : public Common::Archive {
/**
- * Describes one chunk of the Blorb file.
+ * Describes a single index entry
*/
struct Entry {
uint _number;
size_t _width, _height;
+ uint _flags;
size_t _dataOffset;
size_t _dataSize;
size_t _paletteOffset;
- size_t _paletteSize;
Common::String _filename;
- Entry() : _number(0), _width(0), _height(0), _dataOffset(0), _dataSize(0),
- _paletteOffset(0), _paletteSize(0) {}
+ /**
+ * Constructor
+ */
+ Entry() : _number(0), _width(0), _height(0), _flags(0), _dataOffset(0), _dataSize(0),
+ _paletteOffset(0) {}
};
private:
Common::String _filename;
diff --git a/engines/glk/frotz/pics_decoder.cpp b/engines/glk/frotz/pics_decoder.cpp
index a67ed12..dbe8aed 100644
--- a/engines/glk/frotz/pics_decoder.cpp
+++ b/engines/glk/frotz/pics_decoder.cpp
@@ -21,13 +21,226 @@
*/
#include "glk/frotz/pics_decoder.h"
+#include "glk/frotz/pics.h"
+#include "common/memstream.h"
namespace Glk {
namespace Frotz {
-Common::MemoryReadStream *PictureDecoder::decode(Common::ReadStream &src, const byte *palette) {
- // TODO
- return nullptr;
+PictureDecoder::PictureDecoder() {
+ _tableVal = new byte[3 * 3840];
+ _tableRef = (uint16 *)(_tableVal + 3840);
+}
+
+PictureDecoder::~PictureDecoder() {
+ delete[] _tableVal;
+}
+
+Common::SeekableReadStream *PictureDecoder::decode(Common::ReadStream &src, uint flags,
+ const Common::Array<byte> &palette, uint display, size_t width, size_t height) {
+ static const int raise_bits[4] = { 0x0100, 0x0300, 0x0700, 0x0000 };
+ Common::MemoryWriteStreamDynamic out(DisposeAfterUse::NO);
+ byte buf[512];
+ byte transparent;
+// int colour_shift;
+// int first_colour;
+ int code, prev_code = 0;
+ int next_entry;
+ int bits_per_code;
+ int bits_shift;
+ int bits;
+ int bufpos = 0;
+ int i;
+
+ /*
+ * Write out dimensions of image
+ */
+ out.writeUint16LE(width);
+ out.writeUint16LE(height);
+
+ /* Set up the color mapping. This is only used for MCGA pictures; the colour
+ * map affects every picture on the screen. The first colour to be defined is
+ * colour 2. Every map defines up to 14 colours (colour 2 to 15). These colours
+ * are not related to the standard Z-machine colour scheme which remains unchanged.
+ * (This is based on the Amiga interpreter which had to work with 16 colours.
+ * Colours 0 and 1 were used for text; changing the text colours actually changed
+ * palette entries 0 and 1. This interface uses the same trick in Amiga mode.)
+ */
+/*
+ switch (display) {
+ case CGA:
+ colour_shift = -2;
+ break;
+ case EGA:
+ colour_shift = 0;
+ break;
+ case MCGA:
+ colour_shift = 32;
+ first_colour = 34;
+ break;
+ case AMIGA:
+ colour_shift = -1;
+ first_colour = 65;
+ break;
+ default:
+ break;
+ }
+ */
+ out.writeUint16LE(palette.size() / 3);
+ if (!palette.empty())
+ out.write(&palette[0], palette.size());
+
+ /* Bit 0 of "flags" indicates that the picture uses a transparent colour,
+ * the top four bits tell us which colour it is. For CGA and MCGA pictures
+ * this is always 0; for EGA pictures it can be any colour between 0 and 15.
+ */
+ transparent = 0xff;
+ if (flags & 1)
+ transparent = flags >> 12;
+ out.writeByte(transparent);
+
+ /* The uncompressed picture is a long sequence of bytes. Every byte holds
+ * the colour of a pixel, starting at the top left, stopping at the bottom right.
+ * We keep track of our position in the current line. (There is a special case:
+ * CGA pictures with no transparent colour are stored as bit patterns, i.e.
+ * every byte holds the pattern for eight pixels. A pixel must be white if the
+ * corresponding bit is set, otherwise it must be black.)
+ */
+// current_x = 1 + width;
+// current_y = 1 - 1;
+
+ /* The compressed picture is a stream of bits. We read the file byte-wise,
+ * storing the current byte in the variable "bits". Several bits make one code;
+ * the variable "bits_shift" helps us to build the next code.
+ */
+ bits_shift = 0;
+ bits = 0;
+
+reset_table:
+ /* Clear the table. We use a table of 3840 entries. Each entry consists of both
+ * a value and a reference to another table entry. Following these references
+ * we get a sequence of values. At the start of decompression all table entries
+ * are undefined. Later we see how entries are set and used.
+ */
+ next_entry = 1;
+
+ /* At the start of decompression 9 bits make one code; during the process this can
+ * rise to 12 bits per code. 9 bits are sufficient to address both 256 literal values
+ * and 256 table entries; 12 bits are sufficient to address both 256 literal values
+ * and all 3840 table entries. The number of bits per code rises with the number of
+ * table entries. When the table is cleared, the number of bits per code drops back to 9.
+ */
+ bits_per_code = 9;
+
+next_code:
+
+ /* Read the next code from the graphics file. This requires some confusing bit operations.
+ * Note that low bits always come first. Usually there are a few bits left over from
+ * the previous code; these bits must be used before further bits are read from the
+ * graphics file.
+ */
+ code = bits >> (8 - bits_shift);
+
+ do {
+ bits = src.readByte();
+ code |= bits << bits_shift;
+
+ bits_shift += 8;
+ } while (bits_shift < bits_per_code);
+
+ bits_shift -= bits_per_code;
+
+ code &= 0xfff >> (12 - bits_per_code);
+
+ /* There are two codes with a special meaning. The first one is 256 which clears
+ * the table and sets the number of bits per code to 9. (This is necessary when
+ * the table is full.) The second one is 257 which marks the end of the picture.
+ * For the sake of efficiency, we drecement the code by 256.
+ */
+ code -= 256;
+
+ if (code == 0)
+ goto reset_table;
+ if (code == 1) {
+ return new Common::MemoryReadStream(out.getData(), out.size(), DisposeAfterUse::YES);
+ }
+
+ /* Codes from 0 to 255 are literals, i.e. they represent a plain byte value.
+ * Codes from 258 onwards are references to table entries, i.e. they represent
+ * a sequence of byte values (see the remarks on the table above). This means
+ * that for each code one or several byte values are added to the decompressed
+ * picture. But there is yet more work to do: Every time we read a code one
+ * table entry is set. As we said above, a table entry consist of both a value
+ * and a reference to another table entry. If the current code is a literal,
+ * then the value has to be set to this literal; but if the code refers to a
+ * sequence of byte values, then the value has to be set to the last byte of
+ * this sequence. In any case, the reference is set to the previous code.
+ * Finally, one should be aware that a code may legally refer to the table entry
+ * which is currently being set. This requires some extra care.
+ */
+ _tableRef[next_entry] = prev_code;
+
+ prev_code = code;
+
+ while (code >= 0) {
+ buf[bufpos++] = _tableVal[code];
+ code = (short) _tableRef[code];
+ }
+
+ if (next_entry == prev_code)
+ buf[0] = code;
+
+ _tableVal[next_entry] = code;
+
+ /* The number of bits per code is incremented when the current number of bits
+ * no longer suffices to address all defined table entries; but in any case
+ * the number of bits may never be greater than 12.
+ */
+ next_entry++;
+
+ if (next_entry == raise_bits[bits_per_code - 9])
+ bits_per_code++;
+
+reverse_buffer:
+ /* Output the sequence of byte values (pixels). The order of the sequence
+ * must be reversed. (This is why we have stored the sequence in a buffer;
+ * experiments show that a buffer of 512 bytes suffices.)
+ *
+ * Either add a single pixel or a pattern of eight bits (b/w CGA pictures without
+ * a transparent colour) to the current line. Increment our position by 1 or 8
+ * respectively. The pixel may have to be painted several times if the scaling
+ * factor is greater than one.
+ */
+ if (display == CGA && transparent == 0xff) {
+ // TODO
+ } else {
+ byte v = code;
+
+ if (v != transparent) {
+ //v += colour_shift;
+
+ if (display != MCGA) {
+ // TODO
+ } else {
+ // position shift
+ }
+
+ out.writeByte(v);
+
+ if (display == AMIGA) {
+ // TODO
+ }
+ }
+ }
+
+ /* If there are no more values in the buffer then read the next code from the file.
+ * Otherwise fetch the next byte value from the buffer and continue outputing the picture.
+ */
+ if (bufpos == 0)
+ goto next_code;
+
+ code = (code & ~0xff) | buf[--bufpos];
+ goto reverse_buffer;
}
} // End of namespace Frotz
diff --git a/engines/glk/frotz/pics_decoder.h b/engines/glk/frotz/pics_decoder.h
index 41484a1..3d2165f 100644
--- a/engines/glk/frotz/pics_decoder.h
+++ b/engines/glk/frotz/pics_decoder.h
@@ -23,8 +23,8 @@
#ifndef GLK_FROTZ_PICS_DECODER_H
#define GLK_FROTZ_PICS_DECODER_H
-#include "common/memstream.h"
#include "common/stream.h"
+#include "common/array.h"
namespace Glk {
namespace Frotz {
@@ -34,11 +34,25 @@ namespace Frotz {
* Glk engine is capable of then loading into a picture object
*/
class PictureDecoder {
+private:
+ byte *_tableVal;
+ uint16 *_tableRef;
public:
/**
+ * Constructor
+ */
+ PictureDecoder();
+
+ /**
+ * Destructor
+ */
+ ~PictureDecoder();
+
+ /**
* Decode method
*/
- static Common::MemoryReadStream *decode(Common::ReadStream &src, const byte *palette);
+ Common::SeekableReadStream *decode(Common::ReadStream &src, uint flags,
+ const Common::Array<byte> &palette, uint display, size_t width, size_t height);
};
} // End of namespace Frotz
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 6d8fce9..c8dcbc5 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -130,11 +130,10 @@ Picture *Pictures::load(uint32 id) {
return nullptr;
}
- pic = new Picture();
+ pic = new Picture(img->w, img->h, img->format);
pic->_refCount = 1;
pic->_id = id;
pic->_scaled = false;
- pic->create(img->w, img->h, g_system->getScreenFormat());
pic->blitFrom(*img);
if (palette)
diff --git a/engines/glk/raw_decoder.cpp b/engines/glk/raw_decoder.cpp
index a5cd593..e0899e0 100644
--- a/engines/glk/raw_decoder.cpp
+++ b/engines/glk/raw_decoder.cpp
@@ -22,6 +22,7 @@
#include "glk/raw_decoder.h"
#include "common/stream.h"
+#include "common/textconsole.h"
namespace Glk {
@@ -44,7 +45,7 @@ bool RawDecoder::loadStream(Common::SeekableReadStream &stream) {
uint width = stream.readUint16LE();
uint height = stream.readUint16LE();
- _paletteColorCount = stream.readByte();
+ _paletteColorCount = stream.readUint16LE();
assert(_paletteColorCount > 0);
// Read in the palette
@@ -52,8 +53,18 @@ bool RawDecoder::loadStream(Common::SeekableReadStream &stream) {
stream.read(_palette, _paletteColorCount * 3);
// Set up the surface and read it in
+ stream.readByte();
_surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- stream.read(_surface.getPixels(), width * height);
+
+ assert((stream.size() - stream.pos()) == (int)(width * height));
+ byte *pixels = (byte *)_surface.getPixels();
+ stream.read(pixels, width * height);
+
+ for (uint idx = 0; idx < width * height; ++idx, ++pixels) {
+ assert(*pixels != 0xff);
+ if (*pixels >= _paletteColorCount)
+ *pixels = _paletteColorCount - 1;
+ }
return true;
}
Commit: 77468312de507fcd7e01c95f1135afc33a6f4b24
https://github.com/scummvm/scummvm/commit/77468312de507fcd7e01c95f1135afc33a6f4b24
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Beyond Zork title screen now showing
Changed paths:
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/frotz/pics_decoder.cpp
engines/glk/picture.cpp
engines/glk/window_graphics.cpp
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index c046bb4..c2d6ca2 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -165,13 +165,11 @@ void GlkInterface::initialize() {
h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_AMIGA;
h_interpreter_version = 'F';
- {
- // Set these per spec 8.3.2.
- h_default_foreground = WHITE_COLOUR;
- h_default_background = BLACK_COLOUR;
- if (h_flags & COLOUR_FLAG)
- h_flags &= ~COLOUR_FLAG;
- }
+ // Set these per spec 8.3.2.
+ h_default_foreground = WHITE_COLOUR;
+ h_default_background = BLACK_COLOUR;
+ if (h_flags & COLOUR_FLAG)
+ h_flags &= ~COLOUR_FLAG;
/*
* Open the windows
@@ -451,11 +449,11 @@ void GlkInterface::gos_cancel_pending_line() {
void GlkInterface::showBeyondZorkTitle() {
uint winW, winH, imgW, imgH;
- winid_t win = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
- glk_window_get_size(gos_lower, &winW, &winH);
+ winid_t win = glk_window_open(0, 0, 0, wintype_Graphics, 0);
+ glk_window_get_size(win, &winW, &winH);
if (os_picture_data(1, &imgW, &imgH)) {
- os_draw_picture(1, win, Common::Point(1, 1));
+ os_draw_picture(1, win, Common::Rect(0, 0, winW, winH));
_events->waitForPress();
}
@@ -466,6 +464,10 @@ void GlkInterface::os_draw_picture(int picture, winid_t win, const Common::Point
glk_image_draw(win, picture, pos.x - 1, pos.y - 1);
}
+void GlkInterface::os_draw_picture(int picture, winid_t win, const Common::Rect &r) {
+ glk_image_draw_scaled(win, picture, r.left, r.top, r.width(), r.height());
+}
+
zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
event_t ev;
winid_t win = gos_curwin ? gos_curwin : gos_lower;
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index b279ec8..4e531ee 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -169,6 +169,11 @@ protected:
void os_draw_picture(int picture, winid_t win, const Common::Point &pos);
/**
+ * Display a picture using the specified bounds
+ */
+ void os_draw_picture(int picture, winid_t win, const Common::Rect &r);
+
+ /**
* Call the IO interface to play a sample.
*/
void start_sample(int number, int volume, int repeats, zword eos);
diff --git a/engines/glk/frotz/pics_decoder.cpp b/engines/glk/frotz/pics_decoder.cpp
index dbe8aed..d601874 100644
--- a/engines/glk/frotz/pics_decoder.cpp
+++ b/engines/glk/frotz/pics_decoder.cpp
@@ -42,8 +42,8 @@ Common::SeekableReadStream *PictureDecoder::decode(Common::ReadStream &src, uint
Common::MemoryWriteStreamDynamic out(DisposeAfterUse::NO);
byte buf[512];
byte transparent;
-// int colour_shift;
-// int first_colour;
+ int colour_shift;
+ int first_colour;
int code, prev_code = 0;
int next_entry;
int bits_per_code;
@@ -66,7 +66,7 @@ Common::SeekableReadStream *PictureDecoder::decode(Common::ReadStream &src, uint
* Colours 0 and 1 were used for text; changing the text colours actually changed
* palette entries 0 and 1. This interface uses the same trick in Amiga mode.)
*/
-/*
+
switch (display) {
case CGA:
colour_shift = -2;
@@ -85,7 +85,11 @@ Common::SeekableReadStream *PictureDecoder::decode(Common::ReadStream &src, uint
default:
break;
}
- */
+
+ // Note: we don't actually use paletted indexes, so adjust colour_shift
+ // relative to first_colour
+ colour_shift -= first_colour;
+
out.writeUint16LE(palette.size() / 3);
if (!palette.empty())
out.write(&palette[0], palette.size());
@@ -162,6 +166,12 @@ next_code:
if (code == 0)
goto reset_table;
if (code == 1) {
+ bool t[256];
+ // *******DEBUG*******
+ Common::fill(&t[0], &t[256], false);
+ for (uint idx = 0; idx < out.size(); ++idx)
+ t[*((byte *)out.getData() + idx)] = true;
+
return new Common::MemoryReadStream(out.getData(), out.size(), DisposeAfterUse::YES);
}
@@ -217,7 +227,7 @@ reverse_buffer:
byte v = code;
if (v != transparent) {
- //v += colour_shift;
+ v += colour_shift;
if (display != MCGA) {
// TODO
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index c8dcbc5..3404315 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -106,6 +106,7 @@ Picture *Pictures::load(uint32 id) {
RawDecoder raw;
const Graphics::Surface *img;
const byte *palette = nullptr;
+ int palCount = 0;
Picture *pic;
// Check if the picture is already in the store
@@ -114,30 +115,46 @@ Picture *Pictures::load(uint32 id) {
return pic;
Common::File f;
- if (f.open(Common::String::format("PIC%u.png", id))) {
+ if (f.open(Common::String::format("pic%u.png", id))) {
png.loadStream(f);
img = png.getSurface();
palette = png.getPalette();
- } else if (f.open(Common::String::format("PIC%u.jpg", id))) {
+ palCount = png.getPaletteColorCount();
+ } else if (f.open(Common::String::format("pic%u.jpg", id))) {
jpg.loadStream(f);
img = jpg.getSurface();
- } else if (f.open(Common::String::format("PIC%u.raw", id))) {
+ } else if (f.open(Common::String::format("pic%u.raw", id))) {
raw.loadStream(f);
img = raw.getSurface();
palette = raw.getPalette();
+ palCount = raw.getPaletteColorCount();
} else {
// No such picture
return nullptr;
}
- pic = new Picture(img->w, img->h, img->format);
+ pic = new Picture(img->w, img->h, g_system->getScreenFormat());
pic->_refCount = 1;
pic->_id = id;
pic->_scaled = false;
- pic->blitFrom(*img);
- if (palette)
- pic->convertToInPlace(g_system->getScreenFormat(), palette);
+ if (!palette) {
+ pic->blitFrom(*img);
+ } else {
+ uint pal[256];
+ for (uint idx = 0; idx < palCount; ++idx)
+ pal[idx] = pic->format.RGBToColor(palette[idx * 3],
+ palette[idx * 3 + 1], palette[idx * 3 + 2]);
+
+ byte *srcP = (byte *)img->getPixels(), *destP = (byte *)pic->getPixels();
+ for (int idx = 0; idx < img->w * img->h; ++idx, srcP++, destP += pic->format.bytesPerPixel) {
+ uint val = (*srcP >= palCount) ? 0 : pal[*srcP];
+ if (pic->format.bytesPerPixel == 2)
+ WRITE_LE_UINT16(destP, val);
+ else
+ WRITE_LE_UINT32(destP, val);
+ }
+ }
store(pic);
return pic;
diff --git a/engines/glk/window_graphics.cpp b/engines/glk/window_graphics.cpp
index 92224b6..7343d51 100644
--- a/engines/glk/window_graphics.cpp
+++ b/engines/glk/window_graphics.cpp
@@ -62,8 +62,7 @@ void GraphicsWindow::rearrange(const Rect &box) {
if (newhgt < bothhgt)
bothhgt = newhgt;
- newSurface = new Graphics::ManagedSurface(newwid, newhgt,
- Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
+ newSurface = new Graphics::ManagedSurface(newwid, newhgt, g_system->getScreenFormat());
// If the new surface is equal or bigger than the old one, copy it over
if (_surface && bothwid && bothhgt)
@@ -231,7 +230,7 @@ void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int h
w = sx1 - sx0;
h = sy1 - sy0;
- _surface->blitFrom(*g_vm->_screen, Rect(sx0, sy0, sx0 + w, sy0 + h), Point(0, 0));
+ _surface->blitFrom(*src, Rect(sx0, sy0, sx0 + w, sy0 + h), Point(0, 0));
}
void GraphicsWindow::getSize(glui32 *width, glui32 *height) const {
Commit: c2625264fb4e0a0abde96257ea86c83dde60fad2
https://github.com/scummvm/scummvm/commit/c2625264fb4e0a0abde96257ea86c83dde60fad2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Change int 0 to false
Changed paths:
engines/glk/windows.cpp
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
index 1e53f25..58a1648 100644
--- a/engines/glk/windows.cpp
+++ b/engines/glk/windows.cpp
@@ -411,7 +411,7 @@ void Windows::redraw() {
if (_moreFocus)
refocus(_focusWin);
- _forceRedraw = 0;
+ _forceRedraw = false;
}
void Windows::redrawRect(const Rect &r) {
Commit: 5cc3d40c2831ef9d0760178b091e668f5b46195f
https://github.com/scummvm/scummvm/commit/5cc3d40c2831ef9d0760178b091e668f5b46195f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Adding bitmap font class for Infocom character graphics
Changed paths:
A engines/glk/frotz/bitmap_font.cpp
A engines/glk/frotz/bitmap_font.h
engines/glk/fonts.cpp
engines/glk/frotz/frotz_types.h
engines/glk/frotz/processor_screen.cpp
engines/glk/module.mk
engines/glk/picture.cpp
diff --git a/engines/glk/fonts.cpp b/engines/glk/fonts.cpp
index bc699af..4164966 100644
--- a/engines/glk/fonts.cpp
+++ b/engines/glk/fonts.cpp
@@ -24,10 +24,12 @@
#include "glk/glk_types.h"
#include "glk/conf.h"
#include "glk/glk.h"
+#include "glk/frotz/bitmap_font.h"
#include "common/memstream.h"
#include "common/unzip.h"
#include "graphics/fonts/ttf.h"
#include "graphics/fontman.h"
+#include "image/bmp.h"
namespace Glk {
@@ -100,16 +102,27 @@ bool Fonts::loadFonts() {
const Graphics::Font *Fonts::loadFont(FACES face, Common::Archive *archive, double size, double aspect, int
style) {
+ Common::File f;
const char *const FILENAMES[8] = {
"GoMono-Regular.ttf", "GoMono-Bold.ttf", "GoMono-Italic.ttf", "GoMono-Bold-Italic.ttf",
"NotoSerif-Regular.ttf", "NotoSerif-Bold.ttf", "NotoSerif-Italic.ttf", "NotoSerif-Bold-Italic.ttf"
};
- Common::File f;
- if (!f.open(FILENAMES[face], *archive))
- error("Could not load font");
+ // TODO: Properly create a derived Fonts manager for the Frotz sub-engine
+ if (face == MONOZ && g_vm->getInterpreterType() == INTERPRETER_FROTZ) {
+ if (!f.open("infocom_graphics.bmp", *archive))
+ error("Could not load font");
+
+ Image::BitmapDecoder decoder;
+ decoder.loadStream(f);
+ return new Frotz::BitmapFont(*decoder.getSurface());
- return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
+ } else {
+ if (!f.open(FILENAMES[face], *archive))
+ error("Could not load font");
+
+ return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
+ }
}
FACES Fonts::getId(const Common::String &name) {
diff --git a/engines/glk/frotz/bitmap_font.cpp b/engines/glk/frotz/bitmap_font.cpp
new file mode 100644
index 0000000..91f44a9
--- /dev/null
+++ b/engines/glk/frotz/bitmap_font.cpp
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/bitmap_font.h"
+
+namespace Glk {
+namespace Frotz {
+
+BitmapFont::BitmapFont(const Graphics::Surface &src, uint charWidth,
+ uint charHeight, unsigned char startingChar) : _startingChar(startingChar) {
+ assert(src.format.bytesPerPixel == 1);
+ assert((src.w % charWidth) == 0);
+ assert((src.h % charHeight) == 0);
+ _surface.copyFrom(src);
+
+ Common::Rect r(charWidth, charHeight);
+ for (uint y = 0; y < src.h; y += charHeight) {
+ r.moveTo(0, y);
+ for (uint x = 0; x < src.w; x += charWidth, r.translate(charWidth, 0))
+ _chars.push_back(r);
+ }
+}
+
+BitmapFont::~BitmapFont() {
+ _surface.free();
+}
+
+void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ const Common::Rect &r = _chars[chr - _startingChar];
+ for (int yCtr = 0; yCtr < r.height(); ++yCtr) {
+ const byte *srcP = (const byte *)_surface.getBasePtr(r.left, r.top + yCtr);
+
+ for (int xCtr = 0; xCtr < r.width(); ++xCtr, ++srcP) {
+ if (*srcP)
+ dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
+ }
+ }
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/frotz/bitmap_font.h b/engines/glk/frotz/bitmap_font.h
new file mode 100644
index 0000000..dac716c
--- /dev/null
+++ b/engines/glk/frotz/bitmap_font.h
@@ -0,0 +1,81 @@
+/* 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_FROTZ_FONTS
+#define GLK_FROTZ_FONTS
+
+#include "graphics/font.h"
+#include "graphics/surface.h"
+#include "common/archive.h"
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace Glk {
+namespace Frotz {
+
+/**
+ * Implements a fixed width font stored as a grid on a passed surface
+ */
+class BitmapFont : public Graphics::Font {
+private:
+ Graphics::Surface _surface;
+ Common::Array<Common::Rect> _chars;
+ size_t _startingChar;
+public:
+ /**
+ * Constructor
+ */
+ BitmapFont(const Graphics::Surface &src, uint charWidth = 8, uint charHeight = 8,
+ unsigned char startingChar = ' ');
+
+ /**
+ * Destructor
+ */
+ ~BitmapFont();
+
+ /**
+ * Get the font height
+ */
+ virtual int getFontHeight() const override { return _chars[0].height(); }
+
+ /**
+ * Get the maximum character width
+ */
+ virtual int getMaxCharWidth() const override { return _chars[0].width(); }
+
+ /**
+ * Get the width of the given character
+ */
+ virtual int getCharWidth(uint32 chr) const override {
+ return _chars[chr - _startingChar].width();
+ }
+
+ /**
+ * Draw a character
+ */
+ virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/frotz/frotz_types.h b/engines/glk/frotz/frotz_types.h
index bf3067f..555a204 100644
--- a/engines/glk/frotz/frotz_types.h
+++ b/engines/glk/frotz/frotz_types.h
@@ -183,6 +183,7 @@ enum Style {
};
enum FontStyle {
+ PREVIOUS_FONT = 0,
TEXT_FONT = 1,
PICTURE_FONT = 2,
GRAPHICS_FONT = 3,
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 6ee7f1d..696ce78 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -302,39 +302,30 @@ void Processor::z_set_font() {
zword font = zargs[0];
switch (font) {
- case 0:
- // previous font
- temp_font = curr_font;
- curr_font = prev_font;
- prev_font = temp_font;
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- store (curr_font);
- break;
-
- case 1:
- // normal font
- prev_font = curr_font;
- curr_font = 1;
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- store (prev_font);
- break;
-
- case 4:
- // fixed-pitch font
- prev_font = curr_font;
- curr_font = 4;
- zargs[0] = 0xf000; // tickle tickle!
- z_set_text_style();
- store (prev_font);
- break;
-
- case 2: // picture font, undefined per 1.1
- case 3: // character graphics font
- default: // unavailable
- store (0);
- break;
+ case PREVIOUS_FONT:
+ // previous font
+ temp_font = curr_font;
+ curr_font = prev_font;
+ prev_font = temp_font;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store(curr_font);
+ break;
+
+ case TEXT_FONT:
+ case GRAPHICS_FONT:
+ case FIXED_WIDTH_FONT:
+ prev_font = curr_font;
+ curr_font = font;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store(prev_font);
+ break;
+
+ case PICTURE_FONT: // picture font, undefined per 1.1
+ default: // unavailable
+ store(0);
+ break;
}
}
@@ -361,7 +352,7 @@ void Processor::z_set_text_style() {
// not tickle time
curstyle |= zargs[0];
- if (h_flags & FIXED_FONT_FLAG || curr_font == 4)
+ if (h_flags & FIXED_FONT_FLAG || curr_font == FIXED_WIDTH_FONT)
style = curstyle | FIXED_WIDTH_STYLE;
else
style = curstyle;
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 0206643..7c7a85b 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS := \
window_pair.o \
window_text_buffer.o \
window_text_grid.o \
+ frotz/bitmap_font.o \
frotz/config.o \
frotz/detection.o \
frotz/frotz.o \
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 3404315..4422e46 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -106,7 +106,7 @@ Picture *Pictures::load(uint32 id) {
RawDecoder raw;
const Graphics::Surface *img;
const byte *palette = nullptr;
- int palCount = 0;
+ uint palCount = 0;
Picture *pic;
// Check if the picture is already in the store
Commit: fb7dbffd59b797ed00785a2d3762355f9dbb9f7d
https://github.com/scummvm/scummvm/commit/fb7dbffd59b797ed00785a2d3762355f9dbb9f7d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Merge Fonts class into Screen class
Changed paths:
A engines/glk/frotz/screen.cpp
A engines/glk/frotz/screen.h
R engines/glk/fonts.cpp
R engines/glk/fonts.h
R engines/glk/frotz/bitmap_font.cpp
R engines/glk/frotz/bitmap_font.h
engines/glk/conf.cpp
engines/glk/conf.h
engines/glk/module.mk
engines/glk/screen.cpp
engines/glk/screen.h
engines/glk/windows.h
diff --git a/engines/glk/conf.cpp b/engines/glk/conf.cpp
index 4775f26..ee2fd9b 100644
--- a/engines/glk/conf.cpp
+++ b/engines/glk/conf.cpp
@@ -21,7 +21,6 @@
*/
#include "glk/conf.h"
-#include "glk/fonts.h"
#include "glk/utils.h"
#include "glk/windows.h"
#include "common/config-manager.h"
@@ -197,9 +196,9 @@ Conf::Conf(InterpreterType interpType) {
char *font = strtok(buffer, "\r\n\t ");
if (tg == 0)
- _tStyles[style].font = Fonts::getId(font);
+ _tStyles[style].font = Screen::getFontId(font);
else
- _gStyles[style].font = Fonts::getId(font);
+ _gStyles[style].font = Screen::getFontId(font);
}
}
@@ -231,7 +230,7 @@ void Conf::get(const Common::String &key, bool &field, bool defaultVal) {
}
void Conf::get(const Common::String &key, FACES &field, FACES defaultFont) {
- field = ConfMan.hasKey(key) ? Fonts::getId(ConfMan.get(key)) : defaultFont;
+ field = ConfMan.hasKey(key) ? Screen::getFontId(ConfMan.get(key)) : defaultFont;
}
void Conf::get(const Common::String &key, double &field, double defaultVal) {
diff --git a/engines/glk/conf.h b/engines/glk/conf.h
index bf68e34..ca9de2e 100644
--- a/engines/glk/conf.h
+++ b/engines/glk/conf.h
@@ -24,13 +24,10 @@
#define GLK_CONF_H
#include "glk/glk_types.h"
-#include "glk/fonts.h"
#include "glk/windows.h"
namespace Glk {
-
-
/**
* Engine configuration
*/
diff --git a/engines/glk/fonts.cpp b/engines/glk/fonts.cpp
deleted file mode 100644
index 4164966..0000000
--- a/engines/glk/fonts.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/* 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.
- *
- */
-
-#include "glk/fonts.h"
-#include "glk/glk_types.h"
-#include "glk/conf.h"
-#include "glk/glk.h"
-#include "glk/frotz/bitmap_font.h"
-#include "common/memstream.h"
-#include "common/unzip.h"
-#include "graphics/fonts/ttf.h"
-#include "graphics/fontman.h"
-#include "image/bmp.h"
-
-namespace Glk {
-
-#define FONTS_VERSION 1.0
-#define FONTS_FILENAME "fonts.dat"
-
-Fonts::Fonts(Graphics::ManagedSurface *surface) : _surface(surface), _fontsMissing(false) {
- if (!loadFonts())
- error("Could not load data file");
-
- // TODO: See if there's any better way for getting the leading and baseline
- Common::Rect r1 = _fontTable[7]->getBoundingBox('o');
- Common::Rect r2 = _fontTable[7]->getBoundingBox('y');
- double baseLine = (double)r1.bottom;
- double leading = (double)r2.bottom + 2;
-
- g_conf->_leading = MAX((double)g_conf->_leading, leading);
- g_conf->_baseLine = MAX((double)g_conf->_baseLine, baseLine);
- g_conf->_cellW = _fontTable[0]->getStringWidth("0");
- g_conf->_cellH = g_conf->_leading;
-}
-
-Fonts::~Fonts() {
- for (int idx = 0; idx < FONTS_TOTAL; ++idx)
- delete _fontTable[idx];
-}
-
-bool Fonts::loadFonts() {
- Common::Archive *archive = nullptr;
-
- if (!Common::File::exists(FONTS_FILENAME) || (archive = Common::makeZipArchive(FONTS_FILENAME)) == nullptr)
- return false;
-
- // Open the version.txt file within it to validate the version
- Common::File f;
- if (!f.open("version.txt", *archive)) {
- delete archive;
- return false;
- }
-
- // Validate the version
- char buffer[4];
- f.read(buffer, 3);
- buffer[3] = '\0';
-
- if (Common::String(buffer) != "1.0") {
- delete archive;
- return false;
- }
-
- // R ead in the fonts
- double monoAspect = g_conf->_monoAspect;
- double propAspect = g_conf->_propAspect;
- double monoSize = g_conf->_monoSize;
- double propSize = g_conf->_propSize;
-
- _fontTable[0] = loadFont(MONOR, archive, monoSize, monoAspect, FONTR);
- _fontTable[1] = loadFont(MONOB, archive, monoSize, monoAspect, FONTB);
- _fontTable[2] = loadFont(MONOI, archive, monoSize, monoAspect, FONTI);
- _fontTable[3] = loadFont(MONOZ, archive, monoSize, monoAspect, FONTZ);
-
- _fontTable[4] = loadFont(PROPR, archive, propSize, propAspect, FONTR);
- _fontTable[5] = loadFont(PROPB, archive, propSize, propAspect, FONTB);
- _fontTable[6] = loadFont(PROPI, archive, propSize, propAspect, FONTI);
- _fontTable[7] = loadFont(PROPZ, archive, propSize, propAspect, FONTZ);
-
- delete archive;
- return true;
-}
-
-const Graphics::Font *Fonts::loadFont(FACES face, Common::Archive *archive, double size, double aspect, int
- style) {
- Common::File f;
- const char *const FILENAMES[8] = {
- "GoMono-Regular.ttf", "GoMono-Bold.ttf", "GoMono-Italic.ttf", "GoMono-Bold-Italic.ttf",
- "NotoSerif-Regular.ttf", "NotoSerif-Bold.ttf", "NotoSerif-Italic.ttf", "NotoSerif-Bold-Italic.ttf"
- };
-
- // TODO: Properly create a derived Fonts manager for the Frotz sub-engine
- if (face == MONOZ && g_vm->getInterpreterType() == INTERPRETER_FROTZ) {
- if (!f.open("infocom_graphics.bmp", *archive))
- error("Could not load font");
-
- Image::BitmapDecoder decoder;
- decoder.loadStream(f);
- return new Frotz::BitmapFont(*decoder.getSurface());
-
- } else {
- if (!f.open(FILENAMES[face], *archive))
- error("Could not load font");
-
- return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
- }
-}
-
-FACES Fonts::getId(const Common::String &name) {
- if (name == "monor") return MONOR;
- if (name == "monob") return MONOB;
- if (name == "monoi") return MONOI;
- if (name == "monoz") return MONOZ;
- if (name == "propr") return PROPR;
- if (name == "propb") return PROPB;
- if (name == "propi") return PROPI;
- if (name == "propz") return PROPZ;
- return MONOR;
-}
-
-int Fonts::drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
- Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
- const Graphics::Font *font = _fontTable[fontIdx];
- const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
-
- pt.x += font->getStringWidth(text);
- return MIN((int)pt.x, (int)_surface->w) * GLI_SUBPIX;
-}
-
-int Fonts::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
- Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
- const Graphics::Font *font = _fontTable[fontIdx];
- const uint32 color = _surface->format.RGBToColor(rgb[0], rgb[1], rgb[2]);
- font->drawString(_surface, text, pt.x, pt.y, _surface->w - pt.x, color);
-
- pt.x += font->getStringWidth(text);
- return MIN((int)pt.x, (int)_surface->w) * GLI_SUBPIX;
-}
-
-size_t Fonts::stringWidth(int fontIdx, const Common::String &text, int spw) {
- const Graphics::Font *font = _fontTable[fontIdx];
- return font->getStringWidth(text) * GLI_SUBPIX;
-}
-
-size_t Fonts::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
- const Graphics::Font *font = _fontTable[fontIdx];
- return font->getStringWidth(text) * GLI_SUBPIX;
-}
-
-} // End of namespace Glk
diff --git a/engines/glk/fonts.h b/engines/glk/fonts.h
deleted file mode 100644
index 364b023..0000000
--- a/engines/glk/fonts.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* 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_FONTS_H
-#define GLK_FONTS_H
-
-#include "glk/glk_types.h"
-#include "glk/utils.h"
-#include "common/archive.h"
-#include "common/array.h"
-#include "common/file.h"
-#include "common/str.h"
-#include "common/ustr.h"
-#include "graphics/font.h"
-
-namespace Glk {
-
-#define FONTS_TOTAL 8
-
-enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
-enum TYPES { MONOF, PROPF };
-enum STYLES { FONTR, FONTB, FONTI, FONTZ };
-
-/**
- * Fonts manager
- */
-class Fonts {
-private:
- Graphics::ManagedSurface *_surface;
- const Graphics::Font *_fontTable[FONTS_TOTAL];
- bool _fontsMissing;
-private:
- /**
- * Load all the fonts
- */
- bool loadFonts();
-
- /**
- * Load a single font
- */
- const Graphics::Font *loadFont(FACES face, Common::Archive *archive, double size, double aspect, int style);
-public:
- /**
- * Get the index/id of a font by name
- */
- static FACES getId(const Common::String &name);
-public:
- /**
- * Constructor
- */
- Fonts(Graphics::ManagedSurface *surface);
-
- /**
- * Destructor
- */
- virtual ~Fonts();
-
- /**
- * Draws a string using the specified font at the given co-ordinates
- * @param pos Position for the bottom-left corner the text will be drawn with
- * @param fontIdx Which font to use
- * @param rgb RGB tuplet specifying the text color
- * @param text The text to draw
- * @param spw ??
- */
- int drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
-
- /**
- * Draws a unicode string using the specified font at the given co-ordinates
- * @param pos Position for the bottom-left corner the text will be drawn with
- * @param fontIdx Which font to use
- * @param rgb RGB tuplet specifying the text color
- * @param text The text to draw
- * @param spw ??
- */
- int drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
-
- /**
- * Get the width in pixels of a string
- * @param fontIdx Which font to use
- * @param text Text to get the width of
- * @param spw Delta X
- * @returns Width of string multiplied by GLI_SUBPIX
- */
- size_t stringWidth(int fontIdx, const Common::String &text, int spw = 0);
-
- /**
- * Get the width in pixels of a unicode string
- * @param fontIdx Which font to use
- * @param text Text to get the width of
- * @param spw Delta X
- * @returns Width of string multiplied by GLI_SUBPIX
- */
- size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = 0);
-};
-
-} // End of namespace Glk
-
-#endif
diff --git a/engines/glk/frotz/bitmap_font.cpp b/engines/glk/frotz/bitmap_font.cpp
deleted file mode 100644
index 91f44a9..0000000
--- a/engines/glk/frotz/bitmap_font.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 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.
- *
- */
-
-#include "glk/frotz/bitmap_font.h"
-
-namespace Glk {
-namespace Frotz {
-
-BitmapFont::BitmapFont(const Graphics::Surface &src, uint charWidth,
- uint charHeight, unsigned char startingChar) : _startingChar(startingChar) {
- assert(src.format.bytesPerPixel == 1);
- assert((src.w % charWidth) == 0);
- assert((src.h % charHeight) == 0);
- _surface.copyFrom(src);
-
- Common::Rect r(charWidth, charHeight);
- for (uint y = 0; y < src.h; y += charHeight) {
- r.moveTo(0, y);
- for (uint x = 0; x < src.w; x += charWidth, r.translate(charWidth, 0))
- _chars.push_back(r);
- }
-}
-
-BitmapFont::~BitmapFont() {
- _surface.free();
-}
-
-void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
- const Common::Rect &r = _chars[chr - _startingChar];
- for (int yCtr = 0; yCtr < r.height(); ++yCtr) {
- const byte *srcP = (const byte *)_surface.getBasePtr(r.left, r.top + yCtr);
-
- for (int xCtr = 0; xCtr < r.width(); ++xCtr, ++srcP) {
- if (*srcP)
- dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
- }
- }
-}
-
-} // End of namespace Scott
-} // End of namespace Glk
diff --git a/engines/glk/frotz/bitmap_font.h b/engines/glk/frotz/bitmap_font.h
deleted file mode 100644
index dac716c..0000000
--- a/engines/glk/frotz/bitmap_font.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* 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_FROTZ_FONTS
-#define GLK_FROTZ_FONTS
-
-#include "graphics/font.h"
-#include "graphics/surface.h"
-#include "common/archive.h"
-#include "common/array.h"
-#include "common/rect.h"
-
-namespace Glk {
-namespace Frotz {
-
-/**
- * Implements a fixed width font stored as a grid on a passed surface
- */
-class BitmapFont : public Graphics::Font {
-private:
- Graphics::Surface _surface;
- Common::Array<Common::Rect> _chars;
- size_t _startingChar;
-public:
- /**
- * Constructor
- */
- BitmapFont(const Graphics::Surface &src, uint charWidth = 8, uint charHeight = 8,
- unsigned char startingChar = ' ');
-
- /**
- * Destructor
- */
- ~BitmapFont();
-
- /**
- * Get the font height
- */
- virtual int getFontHeight() const override { return _chars[0].height(); }
-
- /**
- * Get the maximum character width
- */
- virtual int getMaxCharWidth() const override { return _chars[0].width(); }
-
- /**
- * Get the width of the given character
- */
- virtual int getCharWidth(uint32 chr) const override {
- return _chars[chr - _startingChar].width();
- }
-
- /**
- * Draw a character
- */
- virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
-};
-
-} // End of namespace Frotz
-} // End of namespace Glk
-
-#endif
diff --git a/engines/glk/frotz/screen.cpp b/engines/glk/frotz/screen.cpp
new file mode 100644
index 0000000..eef6d61
--- /dev/null
+++ b/engines/glk/frotz/screen.cpp
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/screen.h"
+
+namespace Glk {
+namespace Frotz {
+
+BitmapFont::BitmapFont(const Graphics::Surface &src, uint charWidth,
+ uint charHeight, unsigned char startingChar) : _startingChar(startingChar) {
+ assert(src.format.bytesPerPixel == 1);
+ assert((src.w % charWidth) == 0);
+ assert((src.h % charHeight) == 0);
+ _surface.copyFrom(src);
+
+ Common::Rect r(charWidth, charHeight);
+ for (uint y = 0; y < src.h; y += charHeight) {
+ r.moveTo(0, y);
+ for (uint x = 0; x < src.w; x += charWidth, r.translate(charWidth, 0))
+ _chars.push_back(r);
+ }
+}
+
+BitmapFont::~BitmapFont() {
+ _surface.free();
+}
+
+void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ const Common::Rect &r = _chars[chr - _startingChar];
+ for (int yCtr = 0; yCtr < r.height(); ++yCtr) {
+ const byte *srcP = (const byte *)_surface.getBasePtr(r.left, r.top + yCtr);
+
+ for (int xCtr = 0; xCtr < r.width(); ++xCtr, ++srcP) {
+ if (*srcP)
+ dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
+ }
+ }
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/frotz/screen.h b/engines/glk/frotz/screen.h
new file mode 100644
index 0000000..dac716c
--- /dev/null
+++ b/engines/glk/frotz/screen.h
@@ -0,0 +1,81 @@
+/* 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_FROTZ_FONTS
+#define GLK_FROTZ_FONTS
+
+#include "graphics/font.h"
+#include "graphics/surface.h"
+#include "common/archive.h"
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace Glk {
+namespace Frotz {
+
+/**
+ * Implements a fixed width font stored as a grid on a passed surface
+ */
+class BitmapFont : public Graphics::Font {
+private:
+ Graphics::Surface _surface;
+ Common::Array<Common::Rect> _chars;
+ size_t _startingChar;
+public:
+ /**
+ * Constructor
+ */
+ BitmapFont(const Graphics::Surface &src, uint charWidth = 8, uint charHeight = 8,
+ unsigned char startingChar = ' ');
+
+ /**
+ * Destructor
+ */
+ ~BitmapFont();
+
+ /**
+ * Get the font height
+ */
+ virtual int getFontHeight() const override { return _chars[0].height(); }
+
+ /**
+ * Get the maximum character width
+ */
+ virtual int getMaxCharWidth() const override { return _chars[0].width(); }
+
+ /**
+ * Get the width of the given character
+ */
+ virtual int getCharWidth(uint32 chr) const override {
+ return _chars[chr - _startingChar].width();
+ }
+
+ /**
+ * Draw a character
+ */
+ virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 7c7a85b..4112a9f 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -5,7 +5,6 @@ MODULE_OBJS := \
conf.o \
detection.o \
events.o \
- fonts.o \
glk.o \
glk_api.o \
picture.o \
@@ -22,7 +21,6 @@ MODULE_OBJS := \
window_pair.o \
window_text_buffer.o \
window_text_grid.o \
- frotz/bitmap_font.o \
frotz/config.o \
frotz/detection.o \
frotz/frotz.o \
@@ -42,6 +40,7 @@ MODULE_OBJS := \
frotz/processor_text.o \
frotz/processor_variables.o \
frotz/quetzal.o \
+ frotz/screen.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/glk/screen.cpp b/engines/glk/screen.cpp
index 1a76ac8..cfe8cde 100644
--- a/engines/glk/screen.cpp
+++ b/engines/glk/screen.cpp
@@ -22,9 +22,38 @@
#include "glk/screen.h"
#include "glk/conf.h"
+#include "common/unzip.h"
+#include "image/bmp.h"
+#include "graphics/fonts/ttf.h"
+#include "graphics/fontman.h"
namespace Glk {
+
+#define FONTS_VERSION 1.0
+#define FONTS_FILENAME "fonts.dat"
+
+Screen::Screen() {
+ if (!loadFonts())
+ error("Could not load data file");
+
+ // TODO: See if there's any better way for getting the leading and baseline
+ Common::Rect r1 = _fonts[7]->getBoundingBox('o');
+ Common::Rect r2 = _fonts[7]->getBoundingBox('y');
+ double baseLine = (double)r1.bottom;
+ double leading = (double)r2.bottom + 2;
+
+ g_conf->_leading = MAX((double)g_conf->_leading, leading);
+ g_conf->_baseLine = MAX((double)g_conf->_baseLine, baseLine);
+ g_conf->_cellW = _fonts[0]->getStringWidth("0");
+ g_conf->_cellH = g_conf->_leading;
+}
+
+Screen::~Screen() {
+ for (int idx = 0; idx < FONTS_TOTAL; ++idx)
+ delete _fonts[idx];
+}
+
void Screen::fill(const byte *rgb) {
uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
clear(color);
@@ -69,4 +98,104 @@ void Screen::drawCaret(const Point &pos) {
}
}
+bool Screen::loadFonts() {
+ Common::Archive *archive = nullptr;
+ _fonts.resize(FONTS_TOTAL);
+
+ if (!Common::File::exists(FONTS_FILENAME) || (archive = Common::makeZipArchive(FONTS_FILENAME)) == nullptr)
+ return false;
+
+ // Open the version.txt file within it to validate the version
+ Common::File f;
+ if (!f.open("version.txt", *archive)) {
+ delete archive;
+ return false;
+ }
+
+ // Validate the version
+ char buffer[4];
+ f.read(buffer, 3);
+ buffer[3] = '\0';
+
+ if (Common::String(buffer) != "1.0") {
+ delete archive;
+ return false;
+ }
+
+ // R ead in the fonts
+ double monoAspect = g_conf->_monoAspect;
+ double propAspect = g_conf->_propAspect;
+ double monoSize = g_conf->_monoSize;
+ double propSize = g_conf->_propSize;
+
+ _fonts[0] = loadFont(MONOR, archive, monoSize, monoAspect, FONTR);
+ _fonts[1] = loadFont(MONOB, archive, monoSize, monoAspect, FONTB);
+ _fonts[2] = loadFont(MONOI, archive, monoSize, monoAspect, FONTI);
+ _fonts[3] = loadFont(MONOZ, archive, monoSize, monoAspect, FONTZ);
+
+ _fonts[4] = loadFont(PROPR, archive, propSize, propAspect, FONTR);
+ _fonts[5] = loadFont(PROPB, archive, propSize, propAspect, FONTB);
+ _fonts[6] = loadFont(PROPI, archive, propSize, propAspect, FONTI);
+ _fonts[7] = loadFont(PROPZ, archive, propSize, propAspect, FONTZ);
+
+ delete archive;
+ return true;
+}
+
+const Graphics::Font *Screen::loadFont(FACES face, Common::Archive *archive, double size, double aspect, int
+ style) {
+ Common::File f;
+ const char *const FILENAMES[8] = {
+ "GoMono-Regular.ttf", "GoMono-Bold.ttf", "GoMono-Italic.ttf", "GoMono-Bold-Italic.ttf",
+ "NotoSerif-Regular.ttf", "NotoSerif-Bold.ttf", "NotoSerif-Italic.ttf", "NotoSerif-Bold-Italic.ttf"
+ };
+
+ if (!f.open(FILENAMES[face], *archive))
+ error("Could not load font");
+
+ return Graphics::loadTTFFont(f, size, Graphics::kTTFSizeModeCharacter);
+}
+
+FACES Screen::getFontId(const Common::String &name) {
+ if (name == "monor") return MONOR;
+ if (name == "monob") return MONOB;
+ if (name == "monoi") return MONOI;
+ if (name == "monoz") return MONOZ;
+ if (name == "propr") return PROPR;
+ if (name == "propb") return PROPB;
+ if (name == "propi") return PROPI;
+ if (name == "propz") return PROPZ;
+ return MONOR;
+}
+
+int Screen::drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw) {
+ Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
+ const Graphics::Font *font = _fonts[fontIdx];
+ const uint32 color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ font->drawString(this, text, pt.x, pt.y, w - pt.x, color);
+
+ pt.x += font->getStringWidth(text);
+ return MIN((int)pt.x, (int)w) * GLI_SUBPIX;
+}
+
+int Screen::drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw) {
+ Point pt(pos.x / GLI_SUBPIX, pos.y - g_conf->_baseLine);
+ const Graphics::Font *font = _fonts[fontIdx];
+ const uint32 color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
+ font->drawString(this, text, pt.x, pt.y, w - pt.x, color);
+
+ pt.x += font->getStringWidth(text);
+ return MIN((int)pt.x, (int)w) * GLI_SUBPIX;
+}
+
+size_t Screen::stringWidth(int fontIdx, const Common::String &text, int spw) {
+ const Graphics::Font *font = _fonts[fontIdx];
+ return font->getStringWidth(text) * GLI_SUBPIX;
+}
+
+size_t Screen::stringWidthUni(int fontIdx, const Common::U32String &text, int spw) {
+ const Graphics::Font *font = _fonts[fontIdx];
+ return font->getStringWidth(text) * GLI_SUBPIX;
+}
+
} // End of namespace Glk
diff --git a/engines/glk/screen.h b/engines/glk/screen.h
index 0020d86..541e9e1 100644
--- a/engines/glk/screen.h
+++ b/engines/glk/screen.h
@@ -23,24 +23,56 @@
#ifndef GLK_DRAW_H
#define GLK_DRAW_H
+#include "common/archive.h"
+#include "common/array.h"
#include "graphics/screen.h"
-#include "glk/fonts.h"
+#include "graphics/font.h"
+#include "glk/utils.h"
namespace Glk {
+#define FONTS_TOTAL 8
+
enum CaretShape {
SMALL_DOT = 0, FAT_DOT = 1, THIN_LINE = 2, FAT_LINE = 3, BLOCK = 4
};
+enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
+enum TYPES { MONOF, PROPF };
+enum STYLES { FONTR, FONTB, FONTI, FONTZ };
+
/**
* Screen surface class
*/
-class Screen : public Graphics::Screen, public Fonts {
+class Screen : public Graphics::Screen {
+private:
+ Common::Array<const Graphics::Font *> _fonts;
+private:
+ /**
+ * Load all the fonts
+ */
+ bool loadFonts();
+
+ /**
+ * Load a single font
+ */
+ const Graphics::Font *loadFont(FACES face, Common::Archive *archive,
+ double size, double aspect, int style);
+public:
+ /**
+ * Return the font Id for a given name
+ */
+ static FACES getFontId(const Common::String &name);
public:
/**
* Constructor
*/
- Screen() : Graphics::Screen(), Fonts(this) {}
+ Screen();
+
+ /**
+ * Destructor
+ */
+ virtual ~Screen();
/**
* Fills the screen with a given rgb color
@@ -58,6 +90,44 @@ public:
* and the X position is in multiples of GLI_SUBPIX
*/
void drawCaret(const Point &pos);
+
+ /**
+ * Draws a string using the specified font at the given co-ordinates
+ * @param pos Position for the bottom-left corner the text will be drawn with
+ * @param fontIdx Which font to use
+ * @param rgb RGB tuplet specifying the text color
+ * @param text The text to draw
+ * @param spw ??
+ */
+ int drawString(const Point &pos, int fontIdx, const byte *rgb, const Common::String &text, int spw = 0);
+
+ /**
+ * Draws a unicode string using the specified font at the given co-ordinates
+ * @param pos Position for the bottom-left corner the text will be drawn with
+ * @param fontIdx Which font to use
+ * @param rgb RGB tuplet specifying the text color
+ * @param text The text to draw
+ * @param spw ??
+ */
+ int drawStringUni(const Point &pos, int fontIdx, const byte *rgb, const Common::U32String &text, int spw = 0);
+
+ /**
+ * Get the width in pixels of a string
+ * @param fontIdx Which font to use
+ * @param text Text to get the width of
+ * @param spw Delta X
+ * @returns Width of string multiplied by GLI_SUBPIX
+ */
+ size_t stringWidth(int fontIdx, const Common::String &text, int spw = 0);
+
+ /**
+ * Get the width in pixels of a unicode string
+ * @param fontIdx Which font to use
+ * @param text Text to get the width of
+ * @param spw Delta X
+ * @returns Width of string multiplied by GLI_SUBPIX
+ */
+ size_t stringWidthUni(int fontIdx, const Common::U32String &text, int spw = 0);
};
} // End of namespace Glk
diff --git a/engines/glk/windows.h b/engines/glk/windows.h
index 7abb9e5..27380fa 100644
--- a/engines/glk/windows.h
+++ b/engines/glk/windows.h
@@ -29,7 +29,7 @@
#include "graphics/screen.h"
#include "glk/events.h"
#include "glk/glk_types.h"
-#include "glk/fonts.h"
+#include "glk/screen.h"
#include "glk/selection.h"
#include "glk/streams.h"
Commit: 3a543a1e6d35a5bcab61a8fb4257b7d567d9e278
https://github.com/scummvm/scummvm/commit/3a543a1e6d35a5bcab61a8fb4257b7d567d9e278
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add derived Screen class to add Infocom character graphics font
Changed paths:
engines/glk/frotz/frotz.cpp
engines/glk/frotz/frotz.h
engines/glk/frotz/pics_decoder.cpp
engines/glk/frotz/screen.cpp
engines/glk/frotz/screen.h
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/screen.cpp
engines/glk/screen.h
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index d3b0749..421b778 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -22,6 +22,7 @@
#include "glk/frotz/frotz.h"
#include "glk/frotz/frotz_types.h"
+#include "glk/frotz/screen.h"
#include "common/config-manager.h"
namespace Glk {
@@ -38,6 +39,10 @@ Frotz::~Frotz() {
reset_memory();
}
+Screen *Frotz::createScreen() {
+ return new FrotzScreen();
+}
+
void Frotz::runGame(Common::SeekableReadStream *gameFile) {
story_fp = gameFile;
initialize();
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index 0dd8b69..22604e5 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -32,6 +32,11 @@ namespace Frotz {
* Frotz interpreter for Z-code games
*/
class Frotz : public Processor {
+protected:
+ /**
+ * Create the screen class
+ */
+ virtual Screen *createScreen() override;
public:
/**
* Constructor
diff --git a/engines/glk/frotz/pics_decoder.cpp b/engines/glk/frotz/pics_decoder.cpp
index d601874..6dde910 100644
--- a/engines/glk/frotz/pics_decoder.cpp
+++ b/engines/glk/frotz/pics_decoder.cpp
@@ -42,15 +42,14 @@ Common::SeekableReadStream *PictureDecoder::decode(Common::ReadStream &src, uint
Common::MemoryWriteStreamDynamic out(DisposeAfterUse::NO);
byte buf[512];
byte transparent;
- int colour_shift;
- int first_colour;
+ int colour_shift = 0;
+ int first_colour = 0;
int code, prev_code = 0;
int next_entry;
int bits_per_code;
int bits_shift;
int bits;
int bufpos = 0;
- int i;
/*
* Write out dimensions of image
@@ -83,6 +82,7 @@ Common::SeekableReadStream *PictureDecoder::decode(Common::ReadStream &src, uint
first_colour = 65;
break;
default:
+ error("Unsupported mode");
break;
}
diff --git a/engines/glk/frotz/screen.cpp b/engines/glk/frotz/screen.cpp
index eef6d61..a71217c 100644
--- a/engines/glk/frotz/screen.cpp
+++ b/engines/glk/frotz/screen.cpp
@@ -21,10 +21,26 @@
*/
#include "glk/frotz/screen.h"
+#include "common/file.h"
+#include "image/bmp.h"
namespace Glk {
namespace Frotz {
+void FrotzScreen::loadFonts(Common::Archive *archive) {
+ Screen::loadFonts(archive);
+
+ Image::BitmapDecoder decoder;
+ Common::File f;
+ if (!f.open("infocom_graphics.bmp", *archive))
+ error("Could not load font");
+
+ decoder.loadStream(f);
+ _fonts.push_back(new Frotz::BitmapFont(*decoder.getSurface()));
+}
+
+/*--------------------------------------------------------------------------*/
+
BitmapFont::BitmapFont(const Graphics::Surface &src, uint charWidth,
uint charHeight, unsigned char startingChar) : _startingChar(startingChar) {
assert(src.format.bytesPerPixel == 1);
diff --git a/engines/glk/frotz/screen.h b/engines/glk/frotz/screen.h
index dac716c..d8b2b89 100644
--- a/engines/glk/frotz/screen.h
+++ b/engines/glk/frotz/screen.h
@@ -28,11 +28,23 @@
#include "common/archive.h"
#include "common/array.h"
#include "common/rect.h"
+#include "glk/screen.h"
namespace Glk {
namespace Frotz {
/**
+ * Derived screen class that adds in the Infocom character graphics font
+ */
+class FrotzScreen : public Glk::Screen {
+protected:
+ /**
+ * Load the fonts
+ */
+ virtual void loadFonts(Common::Archive *archive) override;
+};
+
+/**
* Implements a fixed width font stored as a grid on a passed surface
*/
class BitmapFont : public Graphics::Font {
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 87b736c..98ce410 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -71,9 +71,10 @@ void GlkEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
initGraphicsMode();
- _conf = new Conf(getInterpreterType());
- _screen = new Screen();
+ _conf = new Conf(getInterpreterType());
+ _screen = createScreen();
+ _screen->initialize();
_clipboard = new Clipboard();
_events = new Events();
_pictures = new Pictures();
@@ -82,6 +83,10 @@ void GlkEngine::initialize() {
_windows = new Windows(_screen);
}
+Screen *GlkEngine::createScreen() {
+ return new Screen();
+}
+
void GlkEngine::initGraphicsMode() {
uint width = ConfMan.hasKey("width") ? ConfMan.getInt("width") : 640;
uint height = ConfMan.hasKey("height") ? ConfMan.getInt("height") : 480;
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index af9a42b..526755b 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -90,6 +90,11 @@ protected:
virtual bool hasFeature(EngineFeature f) const;
/**
+ * Create the screen
+ */
+ virtual Screen *createScreen();
+
+ /**
* Main game loop for the individual interpreters
*/
virtual void runGame(Common::SeekableReadStream *gameFile) = 0;
diff --git a/engines/glk/screen.cpp b/engines/glk/screen.cpp
index cfe8cde..6768360 100644
--- a/engines/glk/screen.cpp
+++ b/engines/glk/screen.cpp
@@ -33,7 +33,12 @@ namespace Glk {
#define FONTS_VERSION 1.0
#define FONTS_FILENAME "fonts.dat"
-Screen::Screen() {
+Screen::~Screen() {
+ for (int idx = 0; idx < FONTS_TOTAL; ++idx)
+ delete _fonts[idx];
+}
+
+void Screen::initialize() {
if (!loadFonts())
error("Could not load data file");
@@ -49,11 +54,6 @@ Screen::Screen() {
g_conf->_cellH = g_conf->_leading;
}
-Screen::~Screen() {
- for (int idx = 0; idx < FONTS_TOTAL; ++idx)
- delete _fonts[idx];
-}
-
void Screen::fill(const byte *rgb) {
uint color = format.RGBToColor(rgb[0], rgb[1], rgb[2]);
clear(color);
@@ -100,7 +100,6 @@ void Screen::drawCaret(const Point &pos) {
bool Screen::loadFonts() {
Common::Archive *archive = nullptr;
- _fonts.resize(FONTS_TOTAL);
if (!Common::File::exists(FONTS_FILENAME) || (archive = Common::makeZipArchive(FONTS_FILENAME)) == nullptr)
return false;
@@ -122,12 +121,20 @@ bool Screen::loadFonts() {
return false;
}
+ loadFonts(archive);
+
+ delete archive;
+ return true;
+}
+
+void Screen::loadFonts(Common::Archive *archive) {
// R ead in the fonts
double monoAspect = g_conf->_monoAspect;
double propAspect = g_conf->_propAspect;
double monoSize = g_conf->_monoSize;
double propSize = g_conf->_propSize;
+ _fonts.resize(FONTS_TOTAL);
_fonts[0] = loadFont(MONOR, archive, monoSize, monoAspect, FONTR);
_fonts[1] = loadFont(MONOB, archive, monoSize, monoAspect, FONTB);
_fonts[2] = loadFont(MONOI, archive, monoSize, monoAspect, FONTI);
@@ -137,9 +144,6 @@ bool Screen::loadFonts() {
_fonts[5] = loadFont(PROPB, archive, propSize, propAspect, FONTB);
_fonts[6] = loadFont(PROPI, archive, propSize, propAspect, FONTI);
_fonts[7] = loadFont(PROPZ, archive, propSize, propAspect, FONTZ);
-
- delete archive;
- return true;
}
const Graphics::Font *Screen::loadFont(FACES face, Common::Archive *archive, double size, double aspect, int
diff --git a/engines/glk/screen.h b/engines/glk/screen.h
index 541e9e1..bb5d7f6 100644
--- a/engines/glk/screen.h
+++ b/engines/glk/screen.h
@@ -46,10 +46,8 @@ enum STYLES { FONTR, FONTB, FONTI, FONTZ };
*/
class Screen : public Graphics::Screen {
private:
- Common::Array<const Graphics::Font *> _fonts;
-private:
/**
- * Load all the fonts
+ * Open the fonts archive and load all the fonts
*/
bool loadFonts();
@@ -58,6 +56,13 @@ private:
*/
const Graphics::Font *loadFont(FACES face, Common::Archive *archive,
double size, double aspect, int style);
+protected:
+ Common::Array<const Graphics::Font *> _fonts;
+protected:
+ /**
+ * Load the fonts
+ */
+ virtual void loadFonts(Common::Archive *archive);
public:
/**
* Return the font Id for a given name
@@ -67,7 +72,7 @@ public:
/**
* Constructor
*/
- Screen();
+ Screen() : Graphics::Screen() {}
/**
* Destructor
@@ -75,6 +80,11 @@ public:
virtual ~Screen();
/**
+ * Initialize the screen
+ */
+ void initialize();
+
+ /**
* Fills the screen with a given rgb color
*/
void fill(const byte *rgb);
Commit: 9fa7e9be8180614b5f7c94440a8243f775e56aef
https://github.com/scummvm/scummvm/commit/9fa7e9be8180614b5f7c94440a8243f775e56aef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix selection of the character graphics font
Changed paths:
engines/glk/frotz/processor_screen.cpp
engines/glk/frotz/screen.cpp
engines/glk/frotz/screen.h
engines/glk/screen.h
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 696ce78..6a518cf 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -352,7 +352,7 @@ void Processor::z_set_text_style() {
// not tickle time
curstyle |= zargs[0];
- if (h_flags & FIXED_FONT_FLAG || curr_font == FIXED_WIDTH_FONT)
+ if (h_flags & FIXED_FONT_FLAG || curr_font == FIXED_WIDTH_FONT || curr_font == GRAPHICS_FONT)
style = curstyle | FIXED_WIDTH_STYLE;
else
style = curstyle;
@@ -367,7 +367,9 @@ void Processor::z_set_text_style() {
}
if (style & FIXED_WIDTH_STYLE) {
- if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+ if (curr_font == GRAPHICS_FONT)
+ glk_set_style(style_User1); // character graphics
+ else if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
glk_set_style(style_BlockQuote); // monoz
else if (style & EMPHASIS_STYLE)
glk_set_style(style_Alert); // monoi
diff --git a/engines/glk/frotz/screen.cpp b/engines/glk/frotz/screen.cpp
index a71217c..edd62eb 100644
--- a/engines/glk/frotz/screen.cpp
+++ b/engines/glk/frotz/screen.cpp
@@ -21,12 +21,17 @@
*/
#include "glk/frotz/screen.h"
+#include "glk/conf.h"
#include "common/file.h"
#include "image/bmp.h"
namespace Glk {
namespace Frotz {
+FrotzScreen::FrotzScreen() : Glk::Screen() {
+ g_conf->_tStyles[style_User1].font = CUSTOM;
+}
+
void FrotzScreen::loadFonts(Common::Archive *archive) {
Screen::loadFonts(archive);
@@ -66,7 +71,7 @@ void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint
const byte *srcP = (const byte *)_surface.getBasePtr(r.left, r.top + yCtr);
for (int xCtr = 0; xCtr < r.width(); ++xCtr, ++srcP) {
- if (*srcP)
+ if (!*srcP)
dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
}
}
diff --git a/engines/glk/frotz/screen.h b/engines/glk/frotz/screen.h
index d8b2b89..568c3c7 100644
--- a/engines/glk/frotz/screen.h
+++ b/engines/glk/frotz/screen.h
@@ -42,6 +42,11 @@ protected:
* Load the fonts
*/
virtual void loadFonts(Common::Archive *archive) override;
+public:
+ /**
+ * Constructor
+ */
+ FrotzScreen();
};
/**
diff --git a/engines/glk/screen.h b/engines/glk/screen.h
index bb5d7f6..10f8b14 100644
--- a/engines/glk/screen.h
+++ b/engines/glk/screen.h
@@ -37,7 +37,7 @@ enum CaretShape {
SMALL_DOT = 0, FAT_DOT = 1, THIN_LINE = 2, FAT_LINE = 3, BLOCK = 4
};
-enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ };
+enum FACES { MONOR, MONOB, MONOI, MONOZ, PROPR, PROPB, PROPI, PROPZ, CUSTOM };
enum TYPES { MONOF, PROPF };
enum STYLES { FONTR, FONTB, FONTI, FONTZ };
Commit: 6080a1d09105c8c743d9e739df91109c809fcef1
https://github.com/scummvm/scummvm/commit/6080a1d09105c8c743d9e739df91109c809fcef1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Draw character graphic chars at the same size as the fixed width font
Changed paths:
engines/glk/frotz/screen.cpp
engines/glk/frotz/screen.h
diff --git a/engines/glk/frotz/screen.cpp b/engines/glk/frotz/screen.cpp
index edd62eb..08bf8c9 100644
--- a/engines/glk/frotz/screen.cpp
+++ b/engines/glk/frotz/screen.cpp
@@ -40,37 +40,40 @@ void FrotzScreen::loadFonts(Common::Archive *archive) {
if (!f.open("infocom_graphics.bmp", *archive))
error("Could not load font");
+ Common::Point fontSize(_fonts[0]->getMaxCharWidth(), _fonts[0]->getFontHeight());
decoder.loadStream(f);
- _fonts.push_back(new Frotz::BitmapFont(*decoder.getSurface()));
+ _fonts.push_back(new Frotz::BitmapFont(*decoder.getSurface(), fontSize));
}
/*--------------------------------------------------------------------------*/
-BitmapFont::BitmapFont(const Graphics::Surface &src, uint charWidth,
- uint charHeight, unsigned char startingChar) : _startingChar(startingChar) {
+BitmapFont::BitmapFont(const Graphics::Surface &src, const Common::Point &size,
+ uint srcWidth, uint srcHeight, unsigned char startingChar) :
+ _startingChar(startingChar), _size(size) {
assert(src.format.bytesPerPixel == 1);
- assert((src.w % charWidth) == 0);
- assert((src.h % charHeight) == 0);
- _surface.copyFrom(src);
+ assert((src.w % srcWidth) == 0);
+ assert((src.h % srcHeight) == 0);
- Common::Rect r(charWidth, charHeight);
- for (uint y = 0; y < src.h; y += charHeight) {
- r.moveTo(0, y);
- for (uint x = 0; x < src.w; x += charWidth, r.translate(charWidth, 0))
- _chars.push_back(r);
- }
-}
+ // Set up a characters array
+ _chars.resize((src.w / srcWidth) * (src.h / srcHeight));
-BitmapFont::~BitmapFont() {
- _surface.free();
+ // Iterate through loading characters
+ Common::Rect r(srcWidth, srcHeight);
+ int charsPerRow = src.w / srcWidth;
+ for (uint idx = 0; idx < _chars.size(); ++idx) {
+ r.moveTo((idx % charsPerRow) * srcWidth, (idx / charsPerRow) * srcHeight);
+
+ _chars[idx].create(size.x, size.y, src.format);
+ _chars[idx].transBlitFrom(src, r, Common::Rect(0, 0, size.x, size.y));
+ }
}
void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
- const Common::Rect &r = _chars[chr - _startingChar];
- for (int yCtr = 0; yCtr < r.height(); ++yCtr) {
- const byte *srcP = (const byte *)_surface.getBasePtr(r.left, r.top + yCtr);
+ const Graphics::ManagedSurface &c = _chars[chr - _startingChar];
+ for (int yCtr = 0; yCtr < c.h; ++yCtr) {
+ const byte *srcP = (const byte *)c.getBasePtr(0, yCtr);
- for (int xCtr = 0; xCtr < r.width(); ++xCtr, ++srcP) {
+ for (int xCtr = 0; xCtr < c.w; ++xCtr, ++srcP) {
if (!*srcP)
dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
}
diff --git a/engines/glk/frotz/screen.h b/engines/glk/frotz/screen.h
index 568c3c7..223ef3b 100644
--- a/engines/glk/frotz/screen.h
+++ b/engines/glk/frotz/screen.h
@@ -54,37 +54,30 @@ public:
*/
class BitmapFont : public Graphics::Font {
private:
- Graphics::Surface _surface;
- Common::Array<Common::Rect> _chars;
+ Common::Array<Graphics::ManagedSurface> _chars;
size_t _startingChar;
+ Common::Point _size;
public:
/**
* Constructor
*/
- BitmapFont(const Graphics::Surface &src, uint charWidth = 8, uint charHeight = 8,
- unsigned char startingChar = ' ');
-
- /**
- * Destructor
- */
- ~BitmapFont();
+ BitmapFont(const Graphics::Surface &src, const Common::Point &size,
+ uint srcWidth = 8, uint srcHeight = 8, unsigned char startingChar = ' ');
/**
* Get the font height
*/
- virtual int getFontHeight() const override { return _chars[0].height(); }
+ virtual int getFontHeight() const override { return _size.y; }
/**
* Get the maximum character width
*/
- virtual int getMaxCharWidth() const override { return _chars[0].width(); }
+ virtual int getMaxCharWidth() const override { return _size.x; }
/**
* Get the width of the given character
*/
- virtual int getCharWidth(uint32 chr) const override {
- return _chars[chr - _startingChar].width();
- }
+ virtual int getCharWidth(uint32 chr) const override { return _size.x; }
/**
* Draw a character
Commit: 6e6b285e83d44e0b35b1c8df3fd5fe325310810e
https://github.com/scummvm/scummvm/commit/6e6b285e83d44e0b35b1c8df3fd5fe325310810e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Savegame listing now reads Quetzal savegames
Changed paths:
engines/glk/POTFILES
engines/glk/detection.cpp
engines/glk/frotz/detection.cpp
engines/glk/frotz/detection.h
diff --git a/engines/glk/POTFILES b/engines/glk/POTFILES
index 9caee0e..d672609 100644
--- a/engines/glk/POTFILES
+++ b/engines/glk/POTFILES
@@ -1,2 +1,3 @@
engines/glk/streams.cpp
engines/glk/scott/scott.cpp
+engines/glk/frotz/detection.cpp
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index a91c603..4e9dee3 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -210,6 +210,8 @@ SaveStateList GlkMetaEngine::listSaves(const char *target) const {
if (in) {
if (Glk::FileStream::readSavegameHeader(in, header))
saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+ else if (Glk::Frotz::FrotzMetaEngine::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
delete in;
}
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index e1c60bd..b1d751a 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -25,6 +25,7 @@
#include "common/debug.h"
#include "common/file.h"
#include "common/md5.h"
+#include "common/translation.h"
namespace Glk {
namespace Frotz {
@@ -113,5 +114,37 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
return !gameList.empty();
}
+bool FrotzMetaEngine::readSavegameHeader(Common::SeekableReadStream *stream, Glk::SavegameHeader &header) {
+ stream->seek(0);
+ if (stream->readUint32BE() != MKTAG('F', 'O', 'R', 'M'))
+ return false;
+ stream->readUint32BE();
+ if (stream->readUint32BE() != MKTAG('I', 'F', 'Z', 'S'))
+ return false;
+
+ header._saveName = _("Unnamed savegame");
+
+ while (stream->pos() < stream->size()) {
+ uint type = stream->readUint32BE();
+ size_t len = stream->readUint32BE();
+
+ if (type == MKTAG('A', 'N', 'N', 'O')) {
+ // Read savegame name from the annotation chunk
+ char *buffer = new char[len + 1];
+ stream->read(buffer, len);
+ buffer[len] = '\0';
+ header._saveName = Common::String(buffer);
+ break;
+ } else {
+ if (len & 1)
+ // Length must be even
+ ++len;
+ stream->skip(len);
+ }
+ }
+
+ return true;
+}
+
} // End of namespace Frotz
} // End of namespace Glk
diff --git a/engines/glk/frotz/detection.h b/engines/glk/frotz/detection.h
index 6c70f98..4fa555b 100644
--- a/engines/glk/frotz/detection.h
+++ b/engines/glk/frotz/detection.h
@@ -25,6 +25,7 @@
#include "common/fs.h"
#include "engines/game.h"
+#include "glk/streams.h"
namespace Glk {
namespace Frotz {
@@ -46,6 +47,11 @@ public:
* Detect supported games
*/
static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
+
+ /**
+ * Check a passed stream for a Quetzal save, and if so, get header information
+ */
+ static bool readSavegameHeader(Common::SeekableReadStream *stream, Glk::SavegameHeader &header);
};
} // End of namespace Frotz
Commit: 33a23bca1c0363340d14ed4c84e558e82a9f245e
https://github.com/scummvm/scummvm/commit/33a23bca1c0363340d14ed4c84e558e82a9f245e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Further reading/writing setup for savegames using Quetzal
Changed paths:
engines/glk/frotz/detection.cpp
engines/glk/frotz/frotz.cpp
engines/glk/frotz/frotz.h
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/scott/scott.cpp
engines/glk/scott/scott.h
engines/glk/streams.cpp
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index b1d751a..6e1d23c 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -122,6 +122,7 @@ bool FrotzMetaEngine::readSavegameHeader(Common::SeekableReadStream *stream, Glk
if (stream->readUint32BE() != MKTAG('I', 'F', 'Z', 'S'))
return false;
+ header._interpType = INTERPRETER_FROTZ;
header._saveName = _("Unnamed savegame");
while (stream->pos() < stream->size()) {
@@ -143,6 +144,7 @@ bool FrotzMetaEngine::readSavegameHeader(Common::SeekableReadStream *stream, Glk
}
}
+ stream->seek(0);
return true;
}
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 421b778..993c65e 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -64,7 +64,7 @@ void Frotz::initialize() {
z_restart();
}
-Common::Error Frotz::saveGameData(strid_t file) {
+Common::Error Frotz::saveGameData(strid_t file, const Common::String &desc) {
#ifdef TODO
long pc;
zword addr;
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index 22604e5..28902c5 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -71,7 +71,7 @@ public:
/**
* Save the game to the passed stream
*/
- virtual Common::Error saveGameData(strid_t file) override;
+ virtual Common::Error saveGameData(strid_t file, const Common::String &desc) override;
};
extern Frotz *g_vm;
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 98ce410..a22f9e9 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -186,7 +186,7 @@ Common::Error GlkEngine::saveGameState(int slot, const Common::String &desc) {
if (file == nullptr)
return Common::kWritingFailed;
- Common::Error result = saveGameData(file);
+ Common::Error result = saveGameData(file, desc);
file->close();
return result;
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 526755b..923e295 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -209,7 +209,7 @@ public:
/**
* Save the game to the passed file
*/
- virtual Common::Error saveGameData(strid_t file) = 0;
+ virtual Common::Error saveGameData(strid_t file, const Common::String &desc) = 0;
};
extern GlkEngine *g_vm;
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index eb8cd40..1efc683 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -508,7 +508,7 @@ void Scott::lineInput(char *buf, size_t n) {
buf[ev.val1] = 0;
}
-Common::Error Scott::saveGameData(strid_t file) {
+Common::Error Scott::saveGameData(strid_t file, const Common::String &desc) {
Common::String msg;
for (int ct = 0; ct < 16; ct++) {
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index ad1313d..b490fd6 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -184,7 +184,7 @@ public:
/**
* Save the game to the passed stream
*/
- virtual Common::Error saveGameData(strid_t file) override;
+ virtual Common::Error saveGameData(strid_t file, const Common::String &desc) override;
};
} // End of namespace Scott
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index 911f6d9..80f03dd 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -25,6 +25,7 @@
#include "glk/events.h"
#include "glk/glk.h"
#include "glk/windows.h"
+#include "glk/frotz/detection.h"
#include "gui/saveload.h"
#include "common/file.h"
#include "common/savefile.h"
@@ -771,7 +772,9 @@ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 roc
if (!_outFile)
error("Could open file for writing - %s", fname.c_str());
- if (fref->_slotNumber != -1)
+ // For creating savegames, write out the header. Frotz is a special case,
+ // since the Quetzal format is used for compatibility
+ if (fref->_slotNumber != -1 && g_vm->getInterpreterType() != INTERPRETER_FROTZ)
writeSavegameHeader(_outFile, fref->_description);
} else if (fmode == filemode_Read) {
if (_file.open(fname)) {
@@ -787,8 +790,11 @@ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 roc
if (_inFile) {
// It's a save file, so skip over the header
SavegameHeader header;
- if (!readSavegameHeader(_inStream, header))
+ if (!(g_vm->getInterpreterType() == INTERPRETER_FROTZ ?
+ Frotz::FrotzMetaEngine::readSavegameHeader(_inStream, header) :
+ readSavegameHeader(_inStream, header)))
error("Invalid savegame");
+
if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
|| header._md5 != g_vm->getGameMD5())
error("Savegame is for a different game");
Commit: 2331a0e9fb3dfe335c15c470d3e7da49cc7ac5f7
https://github.com/scummvm/scummvm/commit/2331a0e9fb3dfe335c15c470d3e7da49cc7ac5f7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Quetzal saving and loading now works
Changed paths:
engines/glk/frotz/config.cpp
engines/glk/frotz/detection.cpp
engines/glk/frotz/frotz.cpp
engines/glk/frotz/processor.h
engines/glk/frotz/quetzal.cpp
engines/glk/frotz/quetzal.h
engines/glk/streams.cpp
engines/glk/streams.h
diff --git a/engines/glk/frotz/config.cpp b/engines/glk/frotz/config.cpp
index 21cfb03..e53cd8c 100644
--- a/engines/glk/frotz/config.cpp
+++ b/engines/glk/frotz/config.cpp
@@ -145,11 +145,10 @@ void Header::loadHeader(Common::SeekableReadStream &f) {
/*--------------------------------------------------------------------------*/
-UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true) {
+UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true), _quetzal(true) {
_err_report_mode = getConfigInt("err_report_mode", ERR_REPORT_ONCE, ERR_REPORT_FATAL);
_ignore_errors = getConfigBool("ignore_errors");
_expand_abbreviations = getConfigBool("expand_abbreviations");
- _quetzal = getConfigBool("quetzal", true);
_tandyBit = getConfigBool("tandy_bit");
_piracy = getConfigBool("piracy");
_script_cols = getConfigInt("wrap_script_lines", 80, 999);
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 6e1d23c..895dd4e 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -22,6 +22,7 @@
#include "glk/frotz/detection.h"
#include "glk/frotz/detection_tables.h"
+#include "glk/frotz/quetzal.h"
#include "common/debug.h"
#include "common/file.h"
#include "common/md5.h"
@@ -116,10 +117,10 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
bool FrotzMetaEngine::readSavegameHeader(Common::SeekableReadStream *stream, Glk::SavegameHeader &header) {
stream->seek(0);
- if (stream->readUint32BE() != MKTAG('F', 'O', 'R', 'M'))
+ if (stream->readUint32BE() != ID_FORM)
return false;
stream->readUint32BE();
- if (stream->readUint32BE() != MKTAG('I', 'F', 'Z', 'S'))
+ if (stream->readUint32BE() != ID_IFZS)
return false;
header._interpType = INTERPRETER_FROTZ;
@@ -129,13 +130,14 @@ bool FrotzMetaEngine::readSavegameHeader(Common::SeekableReadStream *stream, Glk
uint type = stream->readUint32BE();
size_t len = stream->readUint32BE();
- if (type == MKTAG('A', 'N', 'N', 'O')) {
+ if (type == ID_ANNO) {
// Read savegame name from the annotation chunk
char *buffer = new char[len + 1];
stream->read(buffer, len);
buffer[len] = '\0';
header._saveName = Common::String(buffer);
break;
+
} else {
if (len & 1)
// Length must be even
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 993c65e..2ec7585 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -23,6 +23,7 @@
#include "glk/frotz/frotz.h"
#include "glk/frotz/frotz_types.h"
#include "glk/frotz/screen.h"
+#include "glk/frotz/quetzal.h"
#include "common/config-manager.h"
namespace Glk {
@@ -65,167 +66,44 @@ void Frotz::initialize() {
}
Common::Error Frotz::saveGameData(strid_t file, const Common::String &desc) {
-#ifdef TODO
- long pc;
- zword addr;
- zword nsp, nfp;
- int skip;
- int i;
+ Quetzal q(story_fp);
+ bool success = q.save(*file, this, desc);
- // Open game file
-
- if ((gfp = frotzopenprompt(FILE_SAVE)) == nullptr)
- goto finished;
-
- if (_quetzal) {
- success = save_quetzal(gfp, story_fp, blorb_ofs);
- }
- else {
- // Write game file
-
- fputc((int)hi(h_release), gfp);
- fputc((int)lo(h_release), gfp);
- fputc((int)hi(h_checksum), gfp);
- fputc((int)lo(h_checksum), gfp);
-
- GET_PC(pc)
-
- fputc((int)(pc >> 16) & 0xff, gfp);
- fputc((int)(pc >> 8) & 0xff, gfp);
- fputc((int)(pc)& 0xff, gfp);
-
- nsp = (int)(_sp - _stack);
- nfp = (int)(_fp - _stack);
-
- fputc((int)hi(nsp), gfp);
- fputc((int)lo(nsp), gfp);
- fputc((int)hi(nfp), gfp);
- fputc((int)lo(nfp), gfp);
-
- for (i = nsp; i < STACK_SIZE; i++) {
- fputc((int)hi(_stack[i]), gfp);
- fputc((int)lo(_stack[i]), gfp);
- }
-
- fseek(story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
- if (zmp[addr] != fgetc(story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
- fputc(skip, gfp);
- fputc(zmp[addr], gfp);
- skip = 0;
- }
- else skip++;
- }
-
- // Close game file and check for errors
-
- if (fclose(gfp) == EOF || ferror(story_fp)) {
+ if (!success)
print_string("Error writing save file\n");
- goto finished;
- }
- // Success
- success = 1;
-#endif
return Common::kNoError;
}
Common::Error Frotz::loadGameData(strid_t file) {
-#ifdef TODO
- long pc;
- zword release;
- zword addr;
- int i;
-
- // Open game file
- if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
- goto finished;
-
- if (_quetzal) {
- success = restore_quetzal (gfp, story_fp, blorb_ofs);
-
+ Quetzal q(story_fp);
+ bool success = q.restore(*file, this) == 2;
+
+ if (success) {
+ zbyte old_screen_rows;
+ zbyte old_screen_cols;
+
+ // In V3, reset the upper window.
+ if (h_version == V3)
+ split_window(0);
+
+ LOW_BYTE(H_SCREEN_ROWS, old_screen_rows);
+ LOW_BYTE(H_SCREEN_COLS, old_screen_cols);
+
+ // Reload cached header fields
+ restart_header ();
+
+ /* Since QUETZAL files may be saved on many different machines,
+ * the screen sizes may vary a lot. Erasing the status window
+ * seems to cover up most of the resulting badness.
+ */
+ if (h_version > V3 && h_version != V6 && (h_screen_rows != old_screen_rows
+ || h_screen_cols != old_screen_cols))
+ erase_window (1);
} else {
- // Load game file
-
- release = (unsigned) fgetc (gfp) << 8;
- release |= fgetc (gfp);
-
- () fgetc (gfp);
- () fgetc (gfp);
-
- // Check the release number
- if (release == h_release) {
-
- pc = (long) fgetc (gfp) << 16;
- pc |= (unsigned) fgetc (gfp) << 8;
- pc |= fgetc (gfp);
-
- SET_PC (pc);
-
- _sp = _stack + (fgetc (gfp) << 8);
- _sp += fgetc (gfp);
- _fp = _stack + (fgetc (gfp) << 8);
- _fp += fgetc (gfp);
-
- for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
- _stack[i] = (unsigned) fgetc (gfp) << 8;
- _stack[i] |= fgetc (gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0; addr < h_dynamic_size; addr++) {
- int skip = fgetc (gfp);
- for (i = 0; i < skip; i++)
- zmp[addr++] = fgetc (story_fp);
- zmp[addr] = fgetc (gfp);
- () fgetc (story_fp);
- }
-
- // Check for errors
- if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
- success = -1;
- else
-
- // Success
- success = 2;
-
- } else print_string ("Invalid save file\n");
+ error("Error reading save file");
}
- if ((short) success >= 0) {
-
- // Close game file
- fclose (gfp);
-
- if ((short) success > 0) {
- zbyte old_screen_rows;
- zbyte old_screen_cols;
-
- // In V3, reset the upper window.
- if (h_version == V3)
- split_window (0);
-
- LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
- LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
-
- /* Reload cached header fields. */
- restart_header ();
-
- /*
- * Since QUETZAL files may be saved on many different machines,
- * the screen sizes may vary a lot. Erasing the status window
- * seems to cover up most of the resulting badness.
- */
- if (h_version > V3 && h_version != V6
- && (h_screen_rows != old_screen_rows
- || h_screen_cols != old_screen_cols))
- erase_window (1);
- }
- } else
- os_fatal ("Error reading save file");
-#endif
return Common::kNoError;
}
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index 77a673d..fb9c12f 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -95,7 +95,7 @@ private:
bool istream_replay;
bool message;
Common::FixedStack<Redirect, MAX_NESTING> _redirect;
-private:
+protected:
/**
* \defgroup General support methods
* @{
@@ -190,6 +190,11 @@ private:
void new_line();
/**
+ * Copy the contents of the text buffer to the output streams.
+ */
+ void flush_buffer();
+
+ /**
* Returns true if the buffer is empty
*/
bool bufferEmpty() const { return !_bufPos; }
@@ -1540,18 +1545,6 @@ protected:
void z_store();
/**@}*/
-
- /**
- * \defgroup Input support methods
- * @{
- */
-
- /**
- * Copy the contents of the text buffer to the output streams.
- */
- void flush_buffer();
-
- /**@}*/
public:
/**
* Constructor
diff --git a/engines/glk/frotz/quetzal.cpp b/engines/glk/frotz/quetzal.cpp
index 9ff33ab..d727515 100644
--- a/engines/glk/frotz/quetzal.cpp
+++ b/engines/glk/frotz/quetzal.cpp
@@ -50,9 +50,9 @@ bool Quetzal::read_long(Common::ReadStream *f, uint *result) {
return true;
}
-bool Quetzal::save(Common::WriteStream *svf, Processor *proc) {
+bool Quetzal::save(Common::WriteStream *svf, Processor *proc, const Common::String &desc) {
Processor &p = *proc;
- uint ifzslen = 0, cmemlen = 0, stkslen = 0;
+ uint ifzslen = 0, cmemlen = 0, stkslen = 0, descLen = 0;
uint pc;
zword i, j, n;
zword nvars, nargs, nstk;
@@ -79,10 +79,20 @@ bool Quetzal::save(Common::WriteStream *svf, Processor *proc) {
write_word(p.h_checksum);
write_long(pc << 8); // Includes pad
+ // Write 'ANNO' chunk
+ descLen = desc.size() + 1;
+ write_chnk(ID_ANNO, descLen);
+ saveData.write(desc.c_str(), desc.size());
+ write_byte(0);
+ if ((desc.size() % 2) == 0) {
+ write_byte(0);
+ ++descLen;
+ }
+
// Write `CMem' chunk.
- cmempos = svf->pos();
+ cmempos = saveData.pos();
write_chnk(ID_CMem, 0);
- _storyFile->seek(_blorbOffset);
+ _storyFile->seek(0);
// j holds current run length.
for (i = 0, j = 0, cmemlen = 0; i < p.h_dynamic_size; ++i) {
@@ -116,7 +126,7 @@ bool Quetzal::save(Common::WriteStream *svf, Processor *proc) {
write_byte(0);
// Write `Stks' chunk. You are not expected to understand this. ;)
- stkspos = _storyFile->pos();
+ stkspos = saveData.pos();
write_chnk(ID_Stks, 0);
// We construct a list of frame indices, most recent first, in `frames'.
@@ -182,7 +192,7 @@ bool Quetzal::save(Common::WriteStream *svf, Processor *proc) {
}
// Fill in variable chunk lengths
- ifzslen = 3 * 8 + 4 + 14 + cmemlen + stkslen;
+ ifzslen = 4 * 8 + 4 + 14 + cmemlen + stkslen + descLen;
if (cmemlen & 1)
++ifzslen;
@@ -281,7 +291,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
fatal = -1; // Setting PC means errors must be fatal
p.setPC(pc);
- svf->skip(13); // Skip rest of chunk
+ svf->skip(currlen - 13); // Skip rest of chunk
break;
// `Stks' stacks chunk; restoring this is quite complex. ;)
@@ -394,8 +404,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
// `CMem' compressed memory chunk; uncompress it
case ID_CMem:
if (!(progress & GOT_MEMORY)) {
- // Don't complain if two
- _storyFile->seek(_blorbOffset);
+ _storyFile->seek(0);
i = 0; // Bytes written to data area
for (; currlen > 0; --currlen) {
@@ -416,10 +425,10 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
--currlen;
x = svf->readByte();
for (; x >= 0 && i < p.h_dynamic_size; --x, ++i)
- p[i] = svf->readByte();
+ p[i] = _storyFile->readByte();
} else {
// Not a run
- y = svf->readByte();
+ y = _storyFile->readByte();
p[i] = (zbyte)(x ^ y);
++i;
}
@@ -434,14 +443,14 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
// If chunk is short, assume a run
for (; i < p.h_dynamic_size; ++i)
- p[i] = svf->readByte();
+ p[i] = _storyFile->readByte();
if (currlen == 0)
progress |= GOT_MEMORY; // Only if succeeded
break;
}
- // Intentional fall-through
+ // Intentional fall-through on error
case ID_UMem:
if (!(progress & GOT_MEMORY)) {
@@ -458,7 +467,7 @@ int Quetzal::restore(Common::SeekableReadStream *svf, Processor *proc) {
// Fall into default action (skip chunk) on errors
}
- // Intentional fall-through
+ // Intentional fall-through on error
default:
svf->seek(currlen, SEEK_CUR); // Skip chunk
diff --git a/engines/glk/frotz/quetzal.h b/engines/glk/frotz/quetzal.h
index 9d382ab..98765b8 100644
--- a/engines/glk/frotz/quetzal.h
+++ b/engines/glk/frotz/quetzal.h
@@ -36,7 +36,8 @@ enum QueztalTag {
ID_UMem = MKTAG('U', 'M', 'e', 'm'),
ID_CMem = MKTAG('C', 'M', 'e', 'm'),
ID_Stks = MKTAG('S', 't', 'k', 's'),
- ID_ANNO = MKTAG('A', 'N', 'N', 'O')
+ ID_ANNO = MKTAG('A', 'N', 'N', 'O'),
+ ID_SCVM = MKTAG('S', 'C', 'V', 'M')
};
class Processor;
@@ -45,8 +46,6 @@ class Quetzal {
private:
Common::SeekableReadStream *_storyFile;
Common::WriteStream *_out;
- size_t _blorbOffset;
- int _slot;
zword frames[STACK_SIZE / 4 + 1];
private:
/**
@@ -63,7 +62,7 @@ private:
void write_bytx(zword b) { _out->writeByte(b & 0xFF); }
void write_word(zword w) { _out->writeUint16BE(w); }
void write_long(uint l) { _out->writeUint32BE(l); }
- void write_run(zword run) { _out->writeUint16LE(run); }
+ void write_run(zword run) { write_byte(0); write_byte(run); }
void write_chnk(QueztalTag id, zword len) {
_out->writeUint32BE(id);
_out->writeUint32BE(len);
@@ -72,19 +71,21 @@ public:
/**
* Constructor
*/
- Quetzal(Common::SeekableReadStream *storyFile, size_t blorbOffset, int slot) :
- _storyFile(storyFile), _blorbOffset(blorbOffset), _slot(slot) {}
+ Quetzal(Common::SeekableReadStream *storyFile) : _storyFile(storyFile) {}
/*
* Save a game using Quetzal format.
* @param svf Savegame file
+ * @param proc Pointer to the Frotz processor
+ * @param desc Savegame description
* @returns Returns true if OK, false if failed
*/
- bool save(Common::WriteStream *svf, Processor *proc);
+ bool save(Common::WriteStream *svf, Processor *proc, const Common::String &desc);
/**
* Restore a saved game using Quetzal format
* @param svf Savegame file
+ * @param proc Pointer to the Frotz processor
* @returns Return 2 if OK, 0 if an error occurred before any damage was done,
* -1 on a fatal error
*/
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index 80f03dd..d6c71ca 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -768,7 +768,7 @@ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 roc
Common::String fname = fref->_slotNumber == -1 ? fref->_filename : fref->getSaveName();
if (fmode == filemode_Write || fmode == filemode_ReadWrite || fmode == filemode_WriteAppend) {
- _outFile = g_system->getSavefileManager()->openForSaving(fname, fref->_slotNumber != -1);
+ _outFile = g_system->getSavefileManager()->openForSaving(fname, fref->_slotNumber != -1 && g_vm->getInterpreterType() != INTERPRETER_FROTZ);
if (!_outFile)
error("Could open file for writing - %s", fname.c_str());
@@ -795,11 +795,13 @@ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 roc
readSavegameHeader(_inStream, header)))
error("Invalid savegame");
- if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
- || header._md5 != g_vm->getGameMD5())
- error("Savegame is for a different game");
+ if (g_vm->getInterpreterType() != INTERPRETER_FROTZ) {
+ if (header._interpType != g_vm->getInterpreterType() || header._language != g_vm->getLanguage()
+ || header._md5 != g_vm->getGameMD5())
+ error("Savegame is for a different game");
- g_vm->_events->setTotalPlayTicks(header._totalFrames);
+ g_vm->_events->setTotalPlayTicks(header._totalFrames);
+ }
}
}
}
diff --git a/engines/glk/streams.h b/engines/glk/streams.h
index 3150ce9..0b82b36 100644
--- a/engines/glk/streams.h
+++ b/engines/glk/streams.h
@@ -283,6 +283,16 @@ public:
* 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;
@@ -528,6 +538,16 @@ public:
* 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; }
};
/**
Commit: bfbc0ba0edc7a84e49660781d840035d4de7f076
https://github.com/scummvm/scummvm/commit/bfbc0ba0edc7a84e49660781d840035d4de7f076
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Allow loading savegames from launcher
Changed paths:
engines/glk/frotz/frotz.cpp
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index 2ec7585..69ca0a3 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -48,6 +48,17 @@ void Frotz::runGame(Common::SeekableReadStream *gameFile) {
story_fp = gameFile;
initialize();
+ // If save was selected from the launcher, handle loading it
+ int saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
+ if (saveSlot != -1) {
+ bool success = loadGameState(saveSlot).getCode() == Common::kNoError;
+
+ if (h_version <= V3)
+ branch(success);
+ else
+ store(success);
+ }
+
// Game loop
interpret();
Commit: 855911d0c0d8536edd9330540380345fd3b5eb3f
https://github.com/scummvm/scummvm/commit/855911d0c0d8536edd9330540380345fd3b5eb3f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix display of character graphics in text grid windows
Changed paths:
engines/glk/frotz/screen.cpp
diff --git a/engines/glk/frotz/screen.cpp b/engines/glk/frotz/screen.cpp
index 08bf8c9..971ea2f 100644
--- a/engines/glk/frotz/screen.cpp
+++ b/engines/glk/frotz/screen.cpp
@@ -30,6 +30,7 @@ namespace Frotz {
FrotzScreen::FrotzScreen() : Glk::Screen() {
g_conf->_tStyles[style_User1].font = CUSTOM;
+ g_conf->_gStyles[style_User1].font = CUSTOM;
}
void FrotzScreen::loadFonts(Common::Archive *archive) {
Commit: 0b7a29c7973025d32d8952e97cdc4d13a2794c36
https://github.com/scummvm/scummvm/commit/0b7a29c7973025d32d8952e97cdc4d13a2794c36
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Skeleton engine
Changed paths:
A engines/glk/tads/detection.cpp
A engines/glk/tads/detection.h
A engines/glk/tads/detection_tables.h
A engines/glk/tads/tads.cpp
A engines/glk/tads/tads.h
engines/glk/detection.cpp
engines/glk/module.mk
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index 4e9dee3..d5b0ce8 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -25,6 +25,8 @@
#include "glk/frotz/frotz.h"
#include "glk/scott/detection.h"
#include "glk/scott/scott.h"
+#include "glk/tads/detection.h"
+#include "glk/tads/tads.h"
#include "base/plugins.h"
#include "common/md5.h"
@@ -133,6 +135,8 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
*engine = new Glk::Frotz::Frotz(syst, gameDesc);
} else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
*engine = new Glk::Scott::Scott(syst, gameDesc);
+ } else if (Glk::TADS::TADSMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
+ *engine = new Glk::TADS::TADS(syst, gameDesc);
} else {
return Common::kNoGameDataFoundError;
}
@@ -166,6 +170,7 @@ PlainGameList GlkMetaEngine::getSupportedGames() const {
PlainGameList list;
Glk::Frotz::FrotzMetaEngine::getSupportedGames(list);
Glk::Scott::ScottMetaEngine::getSupportedGames(list);
+ Glk::TADS::TADSMetaEngine::getSupportedGames(list);
return list;
}
@@ -179,6 +184,9 @@ PlainGameDescriptor GlkMetaEngine::findGame(const char *gameId) const {
gd = Glk::Scott::ScottMetaEngine::findGame(gameId);
if (gd.description) return gd;
+ gd = Glk::TADS::TADSMetaEngine::findGame(gameId);
+ if (gd.description) return gd;
+
return PlainGameDescriptor();
}
@@ -186,6 +194,7 @@ DetectedGames GlkMetaEngine::detectGames(const Common::FSList &fslist) const {
DetectedGames detectedGames;
Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
+ Glk::TADS::TADSMetaEngine::detectGames(fslist, detectedGames);
return detectedGames;
}
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 4112a9f..b75772d 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -42,7 +42,9 @@ MODULE_OBJS := \
frotz/quetzal.o \
frotz/screen.o \
scott/detection.o \
- scott/scott.o
+ scott/scott.o \
+ tads/detection.o \
+ tads/tads.o
# This module can be built as a plugin
ifeq ($(ENABLE_GLK), DYNAMIC_PLUGIN)
diff --git a/engines/glk/tads/detection.cpp b/engines/glk/tads/detection.cpp
new file mode 100644
index 0000000..ef2caa2
--- /dev/null
+++ b/engines/glk/tads/detection.cpp
@@ -0,0 +1,81 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/detection.h"
+#include "glk/tads/detection_tables.h"
+#include "common/file.h"
+#include "common/md5.h"
+#include "engines/game.h"
+
+namespace Glk {
+namespace TADS {
+
+void TADSMetaEngine::getSupportedGames(PlainGameList &games) {
+ for (const PlainGameDescriptor *pd = TADS_GAME_LIST; pd->gameId; ++pd)
+ games.push_back(*pd);
+}
+
+PlainGameDescriptor TADSMetaEngine::findGame(const char *gameId) {
+ for (const PlainGameDescriptor *pd = TADS_GAME_LIST; pd->gameId; ++pd) {
+ if (!strcmp(gameId, pd->gameId))
+ return *pd;
+ }
+
+ return PlainGameDescriptor();;
+}
+
+bool TADSMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
+ Common::File gameFile;
+ Common::String md5;
+
+ // Loop through the files of the folder
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ if (file->isDirectory() || !(file->getName().hasSuffixIgnoreCase(".saga")
+ || file->getName().hasSuffixIgnoreCase(".dat")))
+ continue;
+
+ if (gameFile.open(*file)) {
+ md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+
+ // Scan through the TADS game list for a match
+ const TADSGame *p = TADS_GAMES;
+ while (p->_md5 && p->_filesize != gameFile.size() && md5 != p->_md5)
+ ++p;
+
+ if (p->_filesize) {
+ // Found a match
+ PlainGameDescriptor gameDesc = findGame(p->_gameId);
+ DetectedGame gd(p->_gameId, gameDesc.description, Common::EN_ANY, Common::kPlatformUnknown);
+ gd.addExtraEntry("filename", file->getName());
+
+ gameList.push_back(gd);
+ }
+
+ gameFile.close();
+ }
+ }
+
+ return !gameList.empty();
+}
+
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/detection.h b/engines/glk/tads/detection.h
new file mode 100644
index 0000000..59a6bc7
--- /dev/null
+++ b/engines/glk/tads/detection.h
@@ -0,0 +1,56 @@
+/* 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_TADS_DETECTION
+#define GLK_TADS_DETECTION
+
+#include "common/fs.h"
+#include "engines/game.h"
+
+namespace Glk {
+namespace TADS {
+
+/**
+ * Meta engine for TADS interpreter
+ */
+class TADSMetaEngine {
+public:
+ /**
+ * Get a list of supported games
+ */
+ static void getSupportedGames(PlainGameList &games);
+
+ /**
+ * Returns a game description for the given game Id, if it's supported
+ */
+ static PlainGameDescriptor findGame(const char *gameId);
+
+ /**
+ * Detect supported games
+ */
+ static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
+};
+
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/tads/detection_tables.h b/engines/glk/tads/detection_tables.h
new file mode 100644
index 0000000..eb9441f
--- /dev/null
+++ b/engines/glk/tads/detection_tables.h
@@ -0,0 +1,49 @@
+/* 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.
+ *
+ */
+
+#include "engines/game.h"
+#include "common/gui_options.h"
+#include "common/language.h"
+
+namespace Glk {
+namespace TADS {
+
+/**
+ * Game descriptor
+ */
+struct TADSGame {
+ const char *_md5;
+ const char *_gameId;
+ int32 _filesize;
+};
+
+const PlainGameDescriptor TADS_GAME_LIST[] = {
+ { "tads", "TADS" },
+ { nullptr, nullptr }
+};
+
+const TADSGame TADS_GAMES[] = {
+ { nullptr, nullptr, 0 }
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads.cpp b/engines/glk/tads/tads.cpp
new file mode 100644
index 0000000..8a40dbd
--- /dev/null
+++ b/engines/glk/tads/tads.cpp
@@ -0,0 +1,48 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/tads.h"
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+namespace Glk {
+namespace TADS {
+
+TADS::TADS(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {
+}
+
+void TADS::runGame(Common::SeekableReadStream *gameFile) {
+ // TODO
+}
+
+Common::Error TADS::loadGameData(strid_t file) {
+ // TODO
+ return Common::kNoError;
+}
+
+Common::Error TADS::saveGameData(strid_t file, const Common::String &desc) {
+ // TODO
+ return Common::kNoError;
+}
+
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads.h b/engines/glk/tads/tads.h
new file mode 100644
index 0000000..23caef7
--- /dev/null
+++ b/engines/glk/tads/tads.h
@@ -0,0 +1,66 @@
+/* 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_TADS
+#define GLK_TADS
+
+#include "common/scummsys.h"
+#include "glk/glk_api.h"
+
+namespace Glk {
+namespace TADS {
+
+/**
+ * tads game interpreter
+ */
+class TADS : public GlkAPI {
+public:
+ /**
+ * Constructor
+ */
+ TADS(OSystem *syst, const GlkGameDescription &gameDesc);
+
+ /**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_SCOTT; }
+
+ /**
+ * Execute the game
+ */
+ virtual void runGame(Common::SeekableReadStream *gameFile) override;
+
+ /**
+ * Load a savegame from the passed stream
+ */
+ virtual Common::Error loadGameData(strid_t file) override;
+
+ /**
+ * Save the game to the passed stream
+ */
+ virtual Common::Error saveGameData(strid_t file, const Common::String &desc) override;
+};
+
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
Commit: 09b682cb63fed029f43133f4a2d9daa3438ac8e2
https://github.com/scummvm/scummvm/commit/09b682cb63fed029f43133f4a2d9daa3438ac8e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Skeletons for TADS 2 & 3 subengines, extra detection logic
Changed paths:
A engines/glk/tads/tads2/tads2.cpp
A engines/glk/tads/tads2/tads2.h
A engines/glk/tads/tads3/tads3.cpp
A engines/glk/tads/tads3/tads3.h
engines/glk/blorb.cpp
engines/glk/detection.cpp
engines/glk/glk_types.h
engines/glk/module.mk
engines/glk/tads/detection.cpp
engines/glk/tads/detection.h
engines/glk/tads/detection_tables.h
engines/glk/tads/tads.cpp
engines/glk/tads/tads.h
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 5c1f0bd..038a79e 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -171,7 +171,8 @@ Common::ErrorCode Blorb::load() {
if (
(_interpType == INTERPRETER_FROTZ && type == "ZCOD") ||
- (_interpType == INTERPRETER_TADS && (type == "TAD2" || type == "TAD3")) ||
+ (_interpType == INTERPRETER_TADS2 && type == "TAD2") ||
+ (_interpType == INTERPRETER_TADS3 && type == "TAD3") ||
(_interpType == INTERPRETER_HUGO && type == "HUGO")
) {
// Game executable
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index d5b0ce8..491c6c8 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -26,7 +26,8 @@
#include "glk/scott/detection.h"
#include "glk/scott/scott.h"
#include "glk/tads/detection.h"
-#include "glk/tads/tads.h"
+#include "glk/tads/tads2/tads2.h"
+#include "glk/tads/tads3/tads3.h"
#include "base/plugins.h"
#include "common/md5.h"
@@ -100,6 +101,7 @@ bool Glk::GlkEngine::hasFeature(EngineFeature f) const {
}
Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
+ Glk::TADS::TADSDescriptor td;
assert(engine);
// Populate the game description
@@ -135,8 +137,11 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
*engine = new Glk::Frotz::Frotz(syst, gameDesc);
} else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
*engine = new Glk::Scott::Scott(syst, gameDesc);
- } else if (Glk::TADS::TADSMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
- *engine = new Glk::TADS::TADS(syst, gameDesc);
+ } else if ((td = Glk::TADS::TADSMetaEngine::findGame(gameDesc._gameId.c_str())).description) {
+ if (td.isTADS3)
+ *engine = new Glk::TADS::TADS3::TADS3(syst, gameDesc);
+ else
+ *engine = new Glk::TADS::TADS2::TADS2(syst, gameDesc);
} else {
return Common::kNoGameDataFoundError;
}
diff --git a/engines/glk/glk_types.h b/engines/glk/glk_types.h
index 4ac9566..81a36d8 100644
--- a/engines/glk/glk_types.h
+++ b/engines/glk/glk_types.h
@@ -50,7 +50,8 @@ enum InterpreterType {
INTERPRETER_NITFOL = 11,
INTERPRETER_SCARE = 12,
INTERPRETER_SCOTT = 13,
- INTERPRETER_TADS = 14
+ INTERPRETER_TADS2 = 14,
+ INTERPRETER_TADS3 = 15
};
/**
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index b75772d..bb55c98 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -44,7 +44,9 @@ MODULE_OBJS := \
scott/detection.o \
scott/scott.o \
tads/detection.o \
- tads/tads.o
+ tads/tads.o \
+ tads/tads2/tads2.o \
+ tads/tads3/tads3.o
# This module can be built as a plugin
ifeq ($(ENABLE_GLK), DYNAMIC_PLUGIN)
diff --git a/engines/glk/tads/detection.cpp b/engines/glk/tads/detection.cpp
index ef2caa2..6627b8f 100644
--- a/engines/glk/tads/detection.cpp
+++ b/engines/glk/tads/detection.cpp
@@ -30,17 +30,18 @@ namespace Glk {
namespace TADS {
void TADSMetaEngine::getSupportedGames(PlainGameList &games) {
- for (const PlainGameDescriptor *pd = TADS_GAME_LIST; pd->gameId; ++pd)
+ for (const TADSDescriptor *pd = TADS_GAME_LIST; pd->gameId; ++pd) {
games.push_back(*pd);
+ }
}
-PlainGameDescriptor TADSMetaEngine::findGame(const char *gameId) {
- for (const PlainGameDescriptor *pd = TADS_GAME_LIST; pd->gameId; ++pd) {
+TADSDescriptor TADSMetaEngine::findGame(const char *gameId) {
+ for (const TADSDescriptor *pd = TADS_GAME_LIST; pd->gameId; ++pd) {
if (!strcmp(gameId, pd->gameId))
return *pd;
}
- return PlainGameDescriptor();;
+ return TADSDescriptor();;
}
bool TADSMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
@@ -49,8 +50,8 @@ bool TADSMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &ga
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory() || !(file->getName().hasSuffixIgnoreCase(".saga")
- || file->getName().hasSuffixIgnoreCase(".dat")))
+ if (file->isDirectory() || !(file->getName().hasSuffixIgnoreCase(".gam")
+ || file->getName().hasSuffixIgnoreCase(".t3")))
continue;
if (gameFile.open(*file)) {
@@ -63,7 +64,7 @@ bool TADSMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &ga
if (p->_filesize) {
// Found a match
- PlainGameDescriptor gameDesc = findGame(p->_gameId);
+ TADSDescriptor gameDesc = findGame(p->_gameId);
DetectedGame gd(p->_gameId, gameDesc.description, Common::EN_ANY, Common::kPlatformUnknown);
gd.addExtraEntry("filename", file->getName());
diff --git a/engines/glk/tads/detection.h b/engines/glk/tads/detection.h
index 59a6bc7..3e4d3e3 100644
--- a/engines/glk/tads/detection.h
+++ b/engines/glk/tads/detection.h
@@ -30,6 +30,22 @@ namespace Glk {
namespace TADS {
/**
+ * TADS game descriptior
+ */
+struct TADSDescriptor {
+ const char *gameId;
+ const char *description;
+ bool isTADS3;
+
+ operator PlainGameDescriptor() const {
+ PlainGameDescriptor pd;
+ pd.gameId = gameId;
+ pd.description = description;
+ return pd;
+ }
+};
+
+/**
* Meta engine for TADS interpreter
*/
class TADSMetaEngine {
@@ -42,7 +58,7 @@ public:
/**
* Returns a game description for the given game Id, if it's supported
*/
- static PlainGameDescriptor findGame(const char *gameId);
+ static TADSDescriptor findGame(const char *gameId);
/**
* Detect supported games
diff --git a/engines/glk/tads/detection_tables.h b/engines/glk/tads/detection_tables.h
index eb9441f..c8fe318 100644
--- a/engines/glk/tads/detection_tables.h
+++ b/engines/glk/tads/detection_tables.h
@@ -36,9 +36,10 @@ struct TADSGame {
int32 _filesize;
};
-const PlainGameDescriptor TADS_GAME_LIST[] = {
- { "tads", "TADS" },
- { nullptr, nullptr }
+const TADSDescriptor TADS_GAME_LIST[] = {
+ { "tads2", "TADS 2 Game", false },
+ { "tads3", "TADS 3 Game", true },
+ { nullptr, nullptr, false }
};
const TADSGame TADS_GAMES[] = {
diff --git a/engines/glk/tads/tads.cpp b/engines/glk/tads/tads.cpp
index 8a40dbd..8301813 100644
--- a/engines/glk/tads/tads.cpp
+++ b/engines/glk/tads/tads.cpp
@@ -30,10 +30,6 @@ namespace TADS {
TADS::TADS(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {
}
-void TADS::runGame(Common::SeekableReadStream *gameFile) {
- // TODO
-}
-
Common::Error TADS::loadGameData(strid_t file) {
// TODO
return Common::kNoError;
diff --git a/engines/glk/tads/tads.h b/engines/glk/tads/tads.h
index 23caef7..8582897 100644
--- a/engines/glk/tads/tads.h
+++ b/engines/glk/tads/tads.h
@@ -45,11 +45,6 @@ public:
virtual InterpreterType getInterpreterType() const override { return INTERPRETER_SCOTT; }
/**
- * Execute the game
- */
- virtual void runGame(Common::SeekableReadStream *gameFile) override;
-
- /**
* Load a savegame from the passed stream
*/
virtual Common::Error loadGameData(strid_t file) override;
diff --git a/engines/glk/tads/tads2/tads2.cpp b/engines/glk/tads/tads2/tads2.cpp
new file mode 100644
index 0000000..81f7272
--- /dev/null
+++ b/engines/glk/tads/tads2/tads2.cpp
@@ -0,0 +1,38 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/tads2/tads2.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+TADS2::TADS2(OSystem *syst, const GlkGameDescription &gameDesc) : TADS(syst, gameDesc) {
+}
+
+void TADS2::runGame(Common::SeekableReadStream *gameFile) {
+ // TODO
+}
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads2/tads2.h b/engines/glk/tads/tads2/tads2.h
new file mode 100644
index 0000000..e07b5c8
--- /dev/null
+++ b/engines/glk/tads/tads2/tads2.h
@@ -0,0 +1,57 @@
+/* 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_TADS_TADS2
+#define GLK_TADS_TADS2
+
+#include "glk/tads/tads.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+/**
+ * TADS 2 game interpreter
+ */
+class TADS2 : public TADS {
+public:
+ /**
+ * Constructor
+ */
+ TADS2(OSystem *syst, const GlkGameDescription &gameDesc);
+
+ /**
+ * Execute the game
+ */
+ virtual void runGame(Common::SeekableReadStream *gameFile) override;
+
+ /**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_TADS2; }
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/tads/tads3/tads3.cpp b/engines/glk/tads/tads3/tads3.cpp
new file mode 100644
index 0000000..911e87f
--- /dev/null
+++ b/engines/glk/tads/tads3/tads3.cpp
@@ -0,0 +1,38 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/tads3/tads3.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS3 {
+
+TADS3::TADS3(OSystem *syst, const GlkGameDescription &gameDesc) : TADS(syst, gameDesc) {
+}
+
+void TADS3::runGame(Common::SeekableReadStream *gameFile) {
+ // TODO
+}
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads3/tads3.h b/engines/glk/tads/tads3/tads3.h
new file mode 100644
index 0000000..2fc4961
--- /dev/null
+++ b/engines/glk/tads/tads3/tads3.h
@@ -0,0 +1,57 @@
+/* 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_TADS_TADS3
+#define GLK_TADS_TADS3
+
+#include "glk/tads/tads.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS3 {
+
+/**
+ * TADS 3 game interpreter
+ */
+class TADS3 : public TADS {
+public:
+ /**
+ * Constructor
+ */
+ TADS3(OSystem *syst, const GlkGameDescription &gameDesc);
+
+ /**
+ * Execute the game
+ */
+ virtual void runGame(Common::SeekableReadStream *gameFile) override;
+
+ /**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_TADS3; }
+};
+
+} // End of namespace TADS3
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
Commit: 75f4d34070a874437f6f339bac590f99d4b28f65
https://github.com/scummvm/scummvm/commit/75f4d34070a874437f6f339bac590f99d4b28f65
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Add first detection entry, further fallback detection
Changed paths:
engines/glk/tads/detection.cpp
engines/glk/tads/detection_tables.h
diff --git a/engines/glk/tads/detection.cpp b/engines/glk/tads/detection.cpp
index 6627b8f..5f0bfea 100644
--- a/engines/glk/tads/detection.cpp
+++ b/engines/glk/tads/detection.cpp
@@ -22,6 +22,7 @@
#include "glk/tads/detection.h"
#include "glk/tads/detection_tables.h"
+#include "common/debug.h"
#include "common/file.h"
#include "common/md5.h"
#include "engines/game.h"
@@ -45,34 +46,52 @@ TADSDescriptor TADSMetaEngine::findGame(const char *gameId) {
}
bool TADSMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
- Common::File gameFile;
- Common::String md5;
-
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory() || !(file->getName().hasSuffixIgnoreCase(".gam")
- || file->getName().hasSuffixIgnoreCase(".t3")))
+ // Check for a recognised filename
+ Common::String filename = file->getName();
+ if (file->isDirectory() || !(filename.hasSuffixIgnoreCase(".gam")
+ || filename.hasSuffixIgnoreCase(".blorb")))
continue;
- if (gameFile.open(*file)) {
- md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+ // Open up the file and calculate the md5
+ Common::File gameFile;
+ if (!gameFile.open(*file))
+ continue;
+ Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+ size_t filesize = gameFile.size();
+ gameFile.close();
- // Scan through the TADS game list for a match
- const TADSGame *p = TADS_GAMES;
- while (p->_md5 && p->_filesize != gameFile.size() && md5 != p->_md5)
- ++p;
+ // Check for known games
+ const TADSGameDescription *p = TADS_GAMES;
+ while (p->_gameId && p->_md5 && (md5 != p->_md5 || filesize != p->_filesize))
+ ++p;
- if (p->_filesize) {
- // Found a match
- TADSDescriptor gameDesc = findGame(p->_gameId);
- DetectedGame gd(p->_gameId, gameDesc.description, Common::EN_ANY, Common::kPlatformUnknown);
- gd.addExtraEntry("filename", file->getName());
+ DetectedGame gd;
+ if (!p->_gameId) {
+ if (!filename.hasSuffixIgnoreCase(".gam"))
+ continue;
- gameList.push_back(gd);
- }
+ if (gDebugLevel > 0) {
+ // Print an entry suitable for putting into the detection_tables.h, using the
+ Common::String fname = filename;
+ const char *dot = strchr(fname.c_str(), '.');
+ if (dot)
+ fname = Common::String(fname.c_str(), dot);
- gameFile.close();
+ debug("ENTRY0(\"%s\", \"%s\", %lu),",
+ fname.c_str(), md5.c_str(), filesize);
+ }
+ const TADSDescriptor &desc = TADS_GAME_LIST[0];
+ gd = DetectedGame(desc.gameId, desc.description, Common::UNK_LANG, Common::kPlatformUnknown);
+ }
+ else {
+ PlainGameDescriptor gameDesc = findGame(p->_gameId);
+ gd = DetectedGame(p->_gameId, gameDesc.description, p->_language, Common::kPlatformUnknown, p->_extra);
}
+
+ gd.addExtraEntry("filename", filename);
+ gameList.push_back(gd);
}
return !gameList.empty();
diff --git a/engines/glk/tads/detection_tables.h b/engines/glk/tads/detection_tables.h
index c8fe318..d4d5709 100644
--- a/engines/glk/tads/detection_tables.h
+++ b/engines/glk/tads/detection_tables.h
@@ -28,22 +28,32 @@ namespace Glk {
namespace TADS {
/**
- * Game descriptor
+ * Game description
*/
-struct TADSGame {
- const char *_md5;
- const char *_gameId;
- int32 _filesize;
+struct TADSGameDescription {
+ const char *const _gameId;
+ const char *const _extra;
+ const char *const _md5;
+ size_t _filesize;
+ Common::Language _language;
};
const TADSDescriptor TADS_GAME_LIST[] = {
+ // TADS 2 Games
{ "tads2", "TADS 2 Game", false },
+ { "oncefuture", "Once and Future", false },
+
+ // TADS 3 Games
{ "tads3", "TADS 3 Game", true },
{ nullptr, nullptr, false }
};
-const TADSGame TADS_GAMES[] = {
- { nullptr, nullptr, 0 }
+#define ENTRY0(ID, MD5, FILESIZE) { ID, "", MD5, FILESIZE, Common::EN_ANY }
+#define TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY }
+
+const TADSGameDescription TADS_GAMES[] = {
+ ENTRY0("oncefuture", "4ed995d0784520ca6f0ec5391d92f4d8", 909993),
+ TABLE_END_MARKER
};
} // End of namespace Frotz
Commit: d2836360fbf4f8ec5f90cbaba99002bb23e0aeb6
https://github.com/scummvm/scummvm/commit/d2836360fbf4f8ec5f90cbaba99002bb23e0aeb6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: GLK window initialization
Changed paths:
engines/glk/tads/tads.cpp
engines/glk/tads/tads.h
diff --git a/engines/glk/tads/tads.cpp b/engines/glk/tads/tads.cpp
index 8301813..aa30927 100644
--- a/engines/glk/tads/tads.cpp
+++ b/engines/glk/tads/tads.cpp
@@ -28,6 +28,36 @@ namespace Glk {
namespace TADS {
TADS::TADS(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {
+ /*
+ * GLK Initialization
+ */
+ mainwin = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
+
+ if (!mainwin)
+ error("fatal: could not open window!\n");
+
+ // get default colors for main window
+ if (!glk_style_measure(mainwin, style_Normal, stylehint_TextColor, &mainfg))
+ mainfg = 0;
+
+ if (!glk_style_measure(mainwin, style_Normal, stylehint_BackColor, &mainbg))
+ mainbg = 0;
+
+ // get default colors for status window
+ statuswin = glk_window_open(mainwin, winmethod_Above | winmethod_Fixed, 1,
+ wintype_TextGrid, 0);
+
+ if (!glk_style_measure(statuswin, style_Normal, stylehint_TextColor, &statusfg))
+ statusfg = 0;
+
+ if (!glk_style_measure(statuswin, style_Normal, stylehint_BackColor, &statusbg))
+ statusbg = 0;
+
+ // close status window; reopened on request
+ glk_window_close(statuswin, 0);
+ statuswin = nullptr;
+
+ glk_set_window(mainwin);
}
Common::Error TADS::loadGameData(strid_t file) {
diff --git a/engines/glk/tads/tads.h b/engines/glk/tads/tads.h
index 8582897..0f1565a 100644
--- a/engines/glk/tads/tads.h
+++ b/engines/glk/tads/tads.h
@@ -33,6 +33,10 @@ namespace TADS {
* tads game interpreter
*/
class TADS : public GlkAPI {
+protected:
+ winid_t mainwin, statuswin;
+ glui32 mainfg, mainbg;
+ glui32 statusfg, statusbg;
public:
/**
* Constructor
Commit: 5ab65b0954ba69ed31edfdbd563a549f7da692af
https://github.com/scummvm/scummvm/commit/5ab65b0954ba69ed31edfdbd563a549f7da692af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: TADS2: Add ler file
Changed paths:
A engines/glk/tads/tads2/ler.cpp
A engines/glk/tads/tads2/ler.h
engines/glk/module.mk
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index bb55c98..9a3aa37 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -45,6 +45,7 @@ MODULE_OBJS := \
scott/scott.o \
tads/detection.o \
tads/tads.o \
+ tads/tads2/ler.o \
tads/tads2/tads2.o \
tads/tads3/tads3.o
diff --git a/engines/glk/tads/tads2/ler.cpp b/engines/glk/tads/tads2/ler.cpp
new file mode 100644
index 0000000..9213d0b
--- /dev/null
+++ b/engines/glk/tads/tads2/ler.cpp
@@ -0,0 +1,179 @@
+/* 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.
+ *
+ */
+
+#include "ler.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
+ int outlen = 0;
+ int argi = 0;
+ int len;
+ char buf[20];
+ char *p = nullptr;
+ char fmtchar;
+
+ while (*fmt != '\0' && outbufl > 1) {
+ switch(*fmt) {
+ case '\\':
+ ++fmt;
+ len = 1;
+ switch(*fmt) {
+ case '\0':
+ --fmt;
+ break;
+ case '\n':
+ p = "\n";
+ break;
+ case '\t':
+ p = "\t";
+ break;
+ default:
+ p = fmt;
+ break;
+ }
+ break;
+
+ case '%':
+ ++fmt;
+ fmtchar = *fmt;
+ if (argi >= argc) fmtchar = 1; // too many - ignore it
+ switch(fmtchar) {
+ case '\0':
+ --fmt;
+ len = 0;
+ break;
+
+ case '%':
+ p = "%";
+ len = 1;
+ break;
+
+ case 'd':
+ sprintf(buf, "%d", argv[argi].erraint);
+ len = strlen(buf);
+ p = buf;
+ break;
+
+ case 'u':
+ sprintf(buf, "%u", argv[argi].erraint);
+ len = strlen(buf);
+ p = buf;
+ break;
+
+ case 's':
+ p = argv[argi].errastr;
+ len = strlen(p);
+ break;
+
+ default:
+ p = "";
+ len = 0;
+ --argi;
+ break;
+ }
+ ++argi;
+ break;
+
+ default:
+ p = fmt;
+ len = 1;
+ break;
+ }
+
+ /* copy output that was set up above */
+ if (len != 0) {
+ if (outbufl >= len) {
+ memcpy(outbuf, p, (size_t)len);
+ outbufl -= len;
+ outbuf += len;
+ } else if (outbufl > 1) {
+ memcpy(outbuf, p, (size_t)outbufl - 1);
+ outbufl = 1;
+ }
+ outlen += len;
+ }
+ ++fmt;
+ }
+
+ // add a null terminator
+ if (outbufl != 0)
+ *outbuf++ = '\0';
+
+ // return the length
+ return outlen;
+}
+
+#if defined(DEBUG) && !defined(ERR_NO_MACRO)
+void errjmp(jmp_buf buf, int e) {
+ longjmp(buf, e);
+}
+#endif /* DEBUG */
+
+#ifdef ERR_NO_MACRO
+
+void errsign(errcxdef *ctx, int e, char *facility) {
+ strncpy(ctx->errcxptr->errfac, facility, ERRFACMAX);
+ ctx->errcxptr->errfac[ERRFACMAX] = '\0';
+ ctx->errcxofs = 0;
+ longjmp(ctx->errcxptr->errbuf, e);
+}
+
+void errsigf(errcxdef *ctx, char *facility, int e) {
+ errargc(ctx, 0);
+ errsign(ctx, e, facility);
+}
+
+char *errstr(errcxdef *ctx, const char *str, int len) {
+ char *ret = &ctx->errcxbuf[ctx->errcxofs];
+
+ memcpy(ret, str, (size_t)len);
+ ret[len] = '\0';
+ ctx->errcxofs += len + 1;
+ return(ret);
+}
+
+void errrse1(errcxdef *ctx, errdef *fr) {
+ errargc(ctx, fr->erraac);
+ memcpy(ctx->errcxptr->erraav, fr->erraav,
+ (size_t)(fr->erraac * sizeof(erradef)));
+ errsign(ctx, fr->errcode, fr->errfac);
+}
+
+void errlogn(errcxdef *ctx, int err, char *facility) {
+ ctx->errcxofs = 0;
+ (*ctx->errcxlog)(ctx->errcxlgc, facility, err, ctx->errcxptr->erraac,
+ ctx->errcxptr->erraav);
+}
+
+void errlogf(errcxdef *ctx, char *facility, int err) {
+ errargc(ctx, 0);
+ errlogn(ctx, err, facility);
+}
+
+#endif /* ERR_NO_MACRO */
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads2/ler.h b/engines/glk/tads/tads2/ler.h
new file mode 100644
index 0000000..5301a0f
--- /dev/null
+++ b/engines/glk/tads/tads2/ler.h
@@ -0,0 +1,287 @@
+/* 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_TADS_TADS2_LER
+#define GLK_TADS_TADS2_LER
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+// maximum length of a facility identifier
+#define ERRFACMAX 6
+
+union erradef {
+ int erraint; // integer argument
+ char *errastr; // text string argument
+};
+
+struct errdef {
+ errdef * errprv; // previous error frame
+ int errcode; // error code of exception being handled
+ char errfac[ERRFACMAX+1]; // facility of current error
+ erradef erraav[10]; // parameters for error
+ int erraac; // count of parameters in argc
+// jmp_buf errbuf; // jump buffer for current error frame
+};
+
+#define ERRBUFSIZ 512
+
+// seek location record for an error message by number
+struct errmfdef {
+ uint errmfnum; // error number
+ size_t errmfseek; // seek location of this message
+};
+
+struct errcxdef {
+ errdef *errcxptr; // current error frame
+ void (*errcxlog)(void *, char *fac, int err, int argc, erradef *);
+ // error logging callback function
+ void *errcxlgc; // context for error logging callback
+ int errcxofs; // offset in argument buffer
+ char errcxbuf[ERRBUFSIZ]; // space for argument strings
+ Common::SeekableReadStream *errcxfp; // message file, if one is being used
+ errmfdef *errcxseek; // seek locations of messages in file
+ uint errcxsksz; // size of errcxseek array
+ size_t errcxbase; // offset in physical file of logical error file
+ struct appctxdef *errcxappctx; // host application context
+};
+typedef struct errcxdef errcxdef;
+
+// begin protected code
+#define ERRBEGIN(ctx) \
+ { \
+ errdef fr_; \
+ if ((fr_.errcode = setjmp(fr_.errbuf)) == 0) \
+ { \
+ fr_.errprv = (ctx)->errcxptr; \
+ (ctx)->errcxptr = &fr_;
+
+// end protected code, begin error handler
+#define ERRCATCH(ctx, e) \
+ assert(1==1 && (ctx)->errcxptr != fr_.errprv); \
+ (ctx)->errcxptr = fr_.errprv; \
+ } \
+ else \
+ { \
+ assert(2==2 && (ctx)->errcxptr != fr_.errprv); \
+ (e) = fr_.errcode; \
+ (ctx)->errcxptr = fr_.errprv;
+
+// retrieve argument (int, string) in current error frame
+#define errargint(argnum) (fr_.erraav[argnum].erraint)
+#define errargstr(argnum) (fr_.erraav[argnum].errastr)
+
+
+#define ERREND(ctx) \
+ } \
+ }
+
+// end protected code, begin cleanup (no handling; just cleaning up)
+#define ERRCLEAN(ctx) \
+ assert((ctx)->errcxptr != fr_.errprv); \
+ (ctx)->errcxptr = fr_.errprv; \
+ } \
+ else \
+ { \
+ assert((ctx)->errcxptr != fr_.errprv); \
+ (ctx)->errcxptr = fr_.errprv;
+
+#define ERRENDCLN(ctx) \
+ errrse(ctx); \
+ } \
+ }
+
+
+
+// argument types for errors with arguments
+#define ERRTINT erraint
+#define ERRTSTR errastr
+
+// set argument count in error frame
+#define errargc(ctx,cnt) ((ctx)->errcxptr->erraac=(cnt))
+
+// enter string argument; returns pointer to argument used in errargv
+#ifdef ERR_NO_MACRO
+char *errstr(errcxdef *ctx, const char *str, int len);
+#else /* ERR_NO_MACRO */
+
+#define errstr(ctx,str,len) \
+ ((memcpy(&(ctx)->errcxbuf[(ctx)->errcxofs],str,(size_t)len), \
+ (ctx)->errcxofs += (len), \
+ (ctx)->errcxbuf[(ctx)->errcxofs++] = '\0'), \
+ &(ctx)->errcxbuf[(ctx)->errcxofs-(len)-1])
+
+#endif /* ERR_NO_MACRO */
+
+/* set argument in error frame argument vector */
+#define errargv(ctx,index,typ,arg) \
+ ((ctx)->errcxptr->erraav[index].typ=(arg))
+
+// signal an error with argument count already set
+#ifdef ERR_NO_MACRO
+void errsign(errcxdef *ctx, int e, char *facility);
+#else /* ERR_NO_MACRO */
+# ifdef DEBUG
+void errjmp(jmp_buf buf, int e);
+# define errsign(ctx, e, fac) \
+ (strncpy((ctx)->errcxptr->errfac, fac, ERRFACMAX),\
+ (ctx)->errcxptr->errfac[ERRFACMAX]='\0',\
+ (ctx)->errcxofs=0, errjmp((ctx)->errcxptr->errbuf, e))
+# else /* DEBUG */
+# define errsign(ctx, e, fac) \
+ (strncpy((ctx)->errcxptr->errfac, fac, ERRFACMAX),\
+ (ctx)->errcxptr->errfac[ERRFACMAX]='\0',\
+ (ctx)->errcxofs=0, longjmp((ctx)->errcxptr->errbuf, e))
+# endif /* DEBUG */
+#endif /* ERR_NO_MACRO */
+
+
+// signal an error with no arguments
+#ifdef ERR_NO_MACRO
+void errsigf(errcxdef *ctx, char *facility, int err);
+#else /* ERR_NO_MACRO */
+#define errsigf(ctx, fac, e) (errargc(ctx,0),errsign(ctx,e,fac))
+#endif /* ERR_NO_MACRO */
+
+// signal an error with one argument
+#define errsigf1(ctx, fac, e, typ1, arg1) \
+ (errargv(ctx,0,typ1,arg1),errargc(ctx,1),errsign(ctx,e,fac))
+
+// signal an error with two arguments
+#define errsigf2(ctx, fac, e, typ1, arg1, typ2, arg2) \
+ (errargv(ctx,0,typ1,arg1), errargv(ctx,1,typ2,arg2), \
+ errargc(ctx,2), errsign(ctx,e,fac))
+
+// resignal the current error - only usable within exception handlers
+#ifdef ERR_NO_MACRO
+void errrse1(errcxdef *ctx, errdef *fr);
+# define errrse(ctx) errrse1(ctx, &fr_)
+#else /* ERR_NO_MACRO */
+
+// void errrse(errcxdef *ctx);
+# define errrse(ctx) \
+ (errargc(ctx, fr_.erraac),\
+ memcpy((ctx)->errcxptr->erraav, fr_.erraav, \
+ (size_t)(fr_.erraac*sizeof(erradef))),\
+ errsign(ctx, fr_.errcode, fr_.errfac))
+
+#endif /* ERR_NO_MACRO */
+
+/**
+ * For use in an error handler (ERRCATCH..ERREND) only: Copy the
+ * parameters from the error currently being handled to the enclosing
+ * frame. This is useful when "keeping" an error being handled - i.e.,
+ * the arguments will continue to be used outside of the
+ * ERRCATCH..ERREND code.
+ */
+#define errkeepargs(ctx) errcopyargs(ctx, &fr_)
+
+/**
+ * copy the parameters for an error from another frame into the current
+ * frame - this can be used when we want to be able to display an error
+ * that occurred in an inner frame within code that is protected by a
+ * new enclosing error frame
+ */
+#define errcopyargs(ctx, fr) \
+ (errargc((ctx), (fr)->erraac), \
+ memcpy((ctx)->errcxptr->erraav, (fr)->erraav, \
+ (size_t)((fr)->erraac*sizeof(erradef))))
+
+// log error that's been caught, using arguments already caught
+#define errclog(ctx) \
+ ((*(ctx)->errcxlog)((ctx)->errcxlgc,fr_.errfac,fr_.errcode,\
+ fr_.erraac,fr_.erraav))
+
+// log an error that's been set up but not signalled yet
+#define errprelog(ctx, err) \
+ ((*(ctx)->errcxlog)((ctx)->errcxlgc,(ctx)->errcxptr->errfac,\
+ err,(ctx)->errcxptr->erraac,\
+ (ctx)->errcxptr->erraav))
+
+// log an error (no signalling, just reporting)
+#ifdef ERR_NO_MACRO
+void errlogn(errcxdef *ctx, int err, char *facility);
+#else /* ERR_NO_MACRO */
+
+#define errlogn(ctx,err,fac) \
+ ((ctx)->errcxofs=0,\
+ (*(ctx)->errcxlog)((ctx)->errcxlgc,fac,err,(ctx)->errcxptr->erraac,\
+ (ctx)->errcxptr->erraav))
+
+#endif /* ERR_NO_MACRO */
+
+// log an error with no arguments
+#ifdef ERR_NO_MACRO
+void errlogf(errcxdef *ctx, char *facility, int err);
+#else /* ERR_NO_MACRO */
+
+// void errlogf(errcxdef *ctx, char *facility, int err);
+#define errlogf(ctx,fac,err) (errargc(ctx,0),errlogn(ctx,err,fac))
+
+#endif /* ERR_NO_MACRO */
+
+// log an error with one argument
+#define errlogf1(ctx, fac, e, typ1, arg1) \
+ (errargv(ctx,0,typ1,arg1),errargc(ctx,1),errlogn(ctx,e,fac))
+
+// log an error with two arguments
+#define errlogf2(ctx, fac, e, typ1, arg1, typ2, arg2) \
+ (errargv(ctx,0,typ1,arg1),errargv(ctx,1,typ2,arg2),\
+ errargc(ctx,2),errlogn(ctx,e,fac))
+
+
+/**
+ * Format an error message, sprintf-style, using arguments in an
+ * erradef array (which is passed to the error-logging callback).
+ * Returns the length of the output string, even if the actual
+ * output string was truncated because the outbuf was too short.
+ * (If called with outbufl == 0, nothing will be written out, but
+ * the size of the buffer needed, minus the terminating null byte,
+ * will be computed and returned.)
+ */
+extern int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv);
+
+// get the text of an error
+void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
+
+// initialize error subsystem, opening error message file if necessary
+void errini(errcxdef *ctx, Common::SeekableReadStream *fp);
+
+// allocate and initialize error context, free error context
+errcxdef *lerini();
+void lerfre(errcxdef *ctx);
+
+// error message structure - number + text
+struct errmdef {
+ uint errmerr; // error number
+ char *errmtxt; // text of error message
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
Commit: 41b62ab00db1d1730b1d61b77fda0df2c65753c0
https://github.com/scummvm/scummvm/commit/41b62ab00db1d1730b1d61b77fda0df2c65753c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Add a number of GLK interface methods
Changed paths:
A engines/glk/tads/tads2/os.cpp
A engines/glk/tads/tads2/os.h
engines/glk/glk_api.cpp
engines/glk/glk_api.h
engines/glk/module.mk
engines/glk/tads/tads.cpp
engines/glk/tads/tads.h
engines/glk/tads/tads2/ler.cpp
engines/glk/tads/tads2/ler.h
engines/glk/tads/tads2/tads2.cpp
engines/glk/tads/tads2/tads2.h
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index 19f8aef..32d6177 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -394,7 +394,7 @@ void GlkAPI::glk_put_string_stream(strid_t str, const char *s) {
str->putBuffer(s, strlen(s));
}
-void GlkAPI::glk_put_buffer(char *buf, glui32 len) {
+void GlkAPI::glk_put_buffer(const char *buf, glui32 len) {
_streams->getCurrent()->putBuffer(buf, len);
}
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index fe25930..3081ac2 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -100,7 +100,7 @@ public:
void glk_put_char_stream(strid_t str, unsigned char ch);
void glk_put_string(const char *s);
void glk_put_string_stream(strid_t str, const char *s);
- void glk_put_buffer(char *buf, glui32 len);
+ void glk_put_buffer(const char *buf, glui32 len);
void glk_put_buffer_stream(strid_t str, const char *buf, glui32 len);
void glk_set_style(glui32 styl);
void glk_set_style_stream(strid_t str, glui32 styl);
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 9a3aa37..89be6a2 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -46,6 +46,7 @@ MODULE_OBJS := \
tads/detection.o \
tads/tads.o \
tads/tads2/ler.o \
+ tads/tads2/os.o \
tads/tads2/tads2.o \
tads/tads3/tads3.o
diff --git a/engines/glk/tads/tads.cpp b/engines/glk/tads/tads.cpp
index aa30927..5dc400b 100644
--- a/engines/glk/tads/tads.cpp
+++ b/engines/glk/tads/tads.cpp
@@ -31,33 +31,34 @@ TADS::TADS(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
/*
* GLK Initialization
*/
- mainwin = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
- if (!mainwin)
+ // Open the story window
+ story_win = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
+ if (!story_win)
error("fatal: could not open window!\n");
// get default colors for main window
- if (!glk_style_measure(mainwin, style_Normal, stylehint_TextColor, &mainfg))
+ if (!glk_style_measure(story_win, style_Normal, stylehint_TextColor, &mainfg))
mainfg = 0;
- if (!glk_style_measure(mainwin, style_Normal, stylehint_BackColor, &mainbg))
+ if (!glk_style_measure(story_win, style_Normal, stylehint_BackColor, &mainbg))
mainbg = 0;
// get default colors for status window
- statuswin = glk_window_open(mainwin, winmethod_Above | winmethod_Fixed, 1,
+ status_win = glk_window_open(story_win, winmethod_Above | winmethod_Fixed, 1,
wintype_TextGrid, 0);
- if (!glk_style_measure(statuswin, style_Normal, stylehint_TextColor, &statusfg))
+ if (!glk_style_measure(status_win, style_Normal, stylehint_TextColor, &statusfg))
statusfg = 0;
- if (!glk_style_measure(statuswin, style_Normal, stylehint_BackColor, &statusbg))
+ if (!glk_style_measure(status_win, style_Normal, stylehint_BackColor, &statusbg))
statusbg = 0;
// close status window; reopened on request
- glk_window_close(statuswin, 0);
- statuswin = nullptr;
+ glk_window_close(status_win, 0);
+ status_win = nullptr;
- glk_set_window(mainwin);
+ glk_set_window(story_win);
}
Common::Error TADS::loadGameData(strid_t file) {
diff --git a/engines/glk/tads/tads.h b/engines/glk/tads/tads.h
index 0f1565a..ec9ea93 100644
--- a/engines/glk/tads/tads.h
+++ b/engines/glk/tads/tads.h
@@ -34,7 +34,7 @@ namespace TADS {
*/
class TADS : public GlkAPI {
protected:
- winid_t mainwin, statuswin;
+ winid_t story_win, status_win;
glui32 mainfg, mainbg;
glui32 statusfg, statusbg;
public:
diff --git a/engines/glk/tads/tads2/ler.cpp b/engines/glk/tads/tads2/ler.cpp
index 9213d0b..930fdf0 100644
--- a/engines/glk/tads/tads2/ler.cpp
+++ b/engines/glk/tads/tads2/ler.cpp
@@ -26,7 +26,9 @@ namespace Glk {
namespace TADS {
namespace TADS2 {
-int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
+#define TRDLOGERR_PREFIX "\n[An error has occurred within TADS: "
+
+int errcxdef::errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
int outlen = 0;
int argi = 0;
int len;
@@ -125,55 +127,26 @@ int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
return outlen;
}
-#if defined(DEBUG) && !defined(ERR_NO_MACRO)
-void errjmp(jmp_buf buf, int e) {
- longjmp(buf, e);
-}
-#endif /* DEBUG */
-
-#ifdef ERR_NO_MACRO
-
-void errsign(errcxdef *ctx, int e, char *facility) {
- strncpy(ctx->errcxptr->errfac, facility, ERRFACMAX);
- ctx->errcxptr->errfac[ERRFACMAX] = '\0';
- ctx->errcxofs = 0;
- longjmp(ctx->errcxptr->errbuf, e);
-}
-
-void errsigf(errcxdef *ctx, char *facility, int e) {
- errargc(ctx, 0);
- errsign(ctx, e, facility);
-}
-
-char *errstr(errcxdef *ctx, const char *str, int len) {
- char *ret = &ctx->errcxbuf[ctx->errcxofs];
-
- memcpy(ret, str, (size_t)len);
- ret[len] = '\0';
- ctx->errcxofs += len + 1;
- return(ret);
+void errcxdef::errcxlog(void *ctx0, char *fac, int err, int argc, erradef *argv) {
+#ifdef TODO
+ errcxdef *ctx = (errcxdef *)ctx0;
+ char buf[256];
+ char msg[256];
+
+ // display the prefix message to the console and log file
+ sprintf(buf, TRDLOGERR_PREFIX, fac, err);
+ trdptf("%s", buf);
+ out_logfile_print(buf, false);
+
+ /* display the error message text to the console and log file */
+ errmsg(ctx, msg, (uint)sizeof(msg), err);
+ errfmt(buf, (int)sizeof(buf), msg, argc, argv);
+ trdptf("%s]\n", buf);
+ out_logfile_print(buf, false);
+ out_logfile_print("]", true);
+#endif
}
-void errrse1(errcxdef *ctx, errdef *fr) {
- errargc(ctx, fr->erraac);
- memcpy(ctx->errcxptr->erraav, fr->erraav,
- (size_t)(fr->erraac * sizeof(erradef)));
- errsign(ctx, fr->errcode, fr->errfac);
-}
-
-void errlogn(errcxdef *ctx, int err, char *facility) {
- ctx->errcxofs = 0;
- (*ctx->errcxlog)(ctx->errcxlgc, facility, err, ctx->errcxptr->erraac,
- ctx->errcxptr->erraav);
-}
-
-void errlogf(errcxdef *ctx, char *facility, int err) {
- errargc(ctx, 0);
- errlogn(ctx, err, facility);
-}
-
-#endif /* ERR_NO_MACRO */
-
} // End of namespace TADS2
} // End of namespace TADS
} // End of namespace Glk
diff --git a/engines/glk/tads/tads2/ler.h b/engines/glk/tads/tads2/ler.h
index 5301a0f..000aa09 100644
--- a/engines/glk/tads/tads2/ler.h
+++ b/engines/glk/tads/tads2/ler.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/stream.h"
+#include "common/algorithm.h"
namespace Glk {
namespace TADS {
@@ -49,26 +50,47 @@ struct errdef {
#define ERRBUFSIZ 512
+class TADS2;
+
// seek location record for an error message by number
struct errmfdef {
uint errmfnum; // error number
size_t errmfseek; // seek location of this message
};
-struct errcxdef {
- errdef *errcxptr; // current error frame
- void (*errcxlog)(void *, char *fac, int err, int argc, erradef *);
- // error logging callback function
+class errcxdef {
+public:
+ errdef *errcxptr; // current error frame
void *errcxlgc; // context for error logging callback
int errcxofs; // offset in argument buffer
char errcxbuf[ERRBUFSIZ]; // space for argument strings
- Common::SeekableReadStream *errcxfp; // message file, if one is being used
+ Common::SeekableReadStream *errcxfp; // message file, if one is being used
errmfdef *errcxseek; // seek locations of messages in file
uint errcxsksz; // size of errcxseek array
size_t errcxbase; // offset in physical file of logical error file
- struct appctxdef *errcxappctx; // host application context
+ TADS2 * errcxappctx; // host application context
+public:
+ /**
+ * Format an error message, sprintf-style, using arguments in an
+ * erradef array (which is passed to the error-logging callback).
+ * Returns the length of the output string, even if the actual
+ * output string was truncated because the outbuf was too short.
+ * (If called with outbufl == 0, nothing will be written out, but
+ * the size of the buffer needed, minus the terminating null byte,
+ * will be computed and returned.)
+ */
+ static int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv);
+ public:
+ errcxdef() : errcxptr(nullptr), errcxlgc(nullptr), errcxofs(0),
+ errcxseek(nullptr), errcxsksz(0), errcxbase(0), errcxappctx(nullptr) {
+ Common::fill(&errcxbuf[0], &errcxbuf[ERRBUFSIZ], '\0');
+ }
+
+ /**
+ * Error logging method
+ */
+ void errcxlog(void *ctx0, char *fac, int err, int argc, erradef *argv);
};
-typedef struct errcxdef errcxdef;
// begin protected code
#define ERRBEGIN(ctx) \
@@ -252,18 +274,7 @@ void errlogf(errcxdef *ctx, char *facility, int err);
(errargv(ctx,0,typ1,arg1),errargv(ctx,1,typ2,arg2),\
errargc(ctx,2),errlogn(ctx,e,fac))
-
-/**
- * Format an error message, sprintf-style, using arguments in an
- * erradef array (which is passed to the error-logging callback).
- * Returns the length of the output string, even if the actual
- * output string was truncated because the outbuf was too short.
- * (If called with outbufl == 0, nothing will be written out, but
- * the size of the buffer needed, minus the terminating null byte,
- * will be computed and returned.)
- */
-extern int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv);
-
+
// get the text of an error
void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
diff --git a/engines/glk/tads/tads2/os.cpp b/engines/glk/tads/tads2/os.cpp
new file mode 100644
index 0000000..df7cb42
--- /dev/null
+++ b/engines/glk/tads/tads2/os.cpp
@@ -0,0 +1,309 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/tads2/os.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+OS::OS(OSystem *syst, const GlkGameDescription &gameDesc) : TADS(syst, gameDesc),
+ status_mode(0) {
+ Common::fill(&status_left[0], &status_left[OSS_STATUS_STRING_LEN], '\0');
+ Common::fill(&status_right[0], &status_right[OSS_STATUS_STRING_LEN], '\0');
+}
+
+void OS::os_terminate(int rc) {
+ glk_exit();
+}
+
+glui32 OS::oss_convert_prompt_type(int type) {
+ if (type == OS_AFP_OPEN)
+ return filemode_Read;
+ return filemode_ReadWrite;
+}
+
+glui32 OS::oss_convert_file_type(int type) {
+ if (type == OSFTSAVE)
+ return fileusage_SavedGame;
+ if (type == OSFTLOG || type == OSFTTEXT)
+ return fileusage_Transcript;
+ return fileusage_Data;
+}
+
+glui32 OS::oss_convert_fileref_to_string(frefid_t file_to_convert, char *buffer, int buf_len) {
+ char temp_string[32];
+ glui32 value, i = 0, digit,
+ digit_flag = false, // Have we put a digit in the string yet?
+ divisor = 1e9; // The max 32-bit integer is 4294967295
+
+ // This could probably be done by using sprintf("%s%ld%s") but I don't want to risk it
+ value = (glui32)file_to_convert;
+ while (divisor != 1) {
+ digit = (char)(value / divisor);
+ if (digit != 0 || digit_flag) { // This lets us handle, eg, 102
+ temp_string[i++] = digit + '0';
+ digit_flag = true;
+ }
+ value = value % divisor;
+ divisor /= 10;
+ }
+ temp_string[i++] = (char)value + '0';
+ temp_string[i] = 0;
+ if (strlen(temp_string) + strlen(OSS_FILEREF_STRING_PREFIX) +
+ strlen(OSS_FILEREF_STRING_SUFFIX) > (size_t)buf_len)
+ return false;
+ sprintf(buffer, "%s%s%s", OSS_FILEREF_STRING_PREFIX,
+ temp_string, OSS_FILEREF_STRING_SUFFIX);
+ return true;
+}
+
+frefid_t OS::oss_convert_string_to_fileref(char *buffer, glui32 usage) {
+ char temp_string[32];
+ glui32 value = 0, i, multiplier = 1;
+
+ // Does the buffer contain a hashed fileref?
+ if (oss_is_string_a_fileref(buffer)) {
+ // If so, we need only decode the string in the middle and return its value
+ strcpy(temp_string, buffer + strlen(OSS_FILEREF_STRING_PREFIX));
+ i = strlen(temp_string) - strlen(OSS_FILEREF_STRING_SUFFIX);
+ temp_string[i] = 0;
+ while (i != 0) {
+ i--;
+ value += ((glui32)(temp_string[i] - '0') * multiplier);
+ multiplier *= 10;
+ }
+ return ((frefid_t)value);
+ }
+
+ // If not, return the new fileref
+ return (glk_fileref_create_by_name(usage, os_get_root_name(buffer), 0));
+}
+
+bool OS::oss_is_string_a_fileref(char *buffer) {
+ if ((strncmp(buffer, OSS_FILEREF_STRING_PREFIX,
+ strlen(OSS_FILEREF_STRING_PREFIX)) == 0) &&
+ (strncmp(buffer + strlen(buffer) - strlen(OSS_FILEREF_STRING_SUFFIX),
+ OSS_FILEREF_STRING_SUFFIX,
+ strlen(OSS_FILEREF_STRING_SUFFIX)) == 0))
+ return true;
+ return false;
+}
+
+unsigned char OS::oss_convert_keystroke_to_tads(glui32 key) {
+ // Characters 0 - 255 we return per normal */
+ if (key <= 255)
+ return ((unsigned char)key);
+ switch (key) {
+ case keycode_Up:
+ return CMD_UP;
+ case keycode_Down:
+ return CMD_DOWN;
+ case keycode_Left:
+ return CMD_LEFT;
+ case keycode_Right:
+ return CMD_RIGHT;
+ case keycode_PageUp:
+ return CMD_PGUP;
+ case keycode_PageDown:
+ return CMD_PGDN;
+ case keycode_Home:
+ return CMD_HOME;
+ case keycode_End:
+ return CMD_END;
+ case keycode_Func1:
+ return CMD_F1;
+ case keycode_Func2:
+ return CMD_F2;
+ case keycode_Func3:
+ return CMD_F3;
+ case keycode_Func4:
+ return CMD_F4;
+ case keycode_Func5:
+ return CMD_F5;
+ case keycode_Func6:
+ return CMD_F6;
+ case keycode_Func7:
+ return CMD_F7;
+ case keycode_Func8:
+ return CMD_F8;
+ case keycode_Func9:
+ return CMD_F9;
+ case keycode_Func10:
+ return CMD_F10;
+ default:
+ return 0;
+ }
+}
+
+bool OS::oss_check_path(char *filename) {
+ return false;
+}
+
+void OS::oss_revert_path() {
+ // No implementation
+}
+
+osfildef *OS::oss_open_stream(char *buffer, glui32 tadsusage, glui32 tbusage,
+ glui32 fmode, glui32 rock) {
+ frefid_t fileref;
+ strid_t osf;
+ int changed_dirs;
+
+ fileref = oss_convert_string_to_fileref(buffer,
+ oss_convert_file_type(tadsusage) | tbusage);
+ changed_dirs = oss_check_path(buffer);
+ osf = glk_stream_open_file(fileref, (FileMode)fmode, rock);
+ if (changed_dirs)
+ oss_revert_path();
+ return *osf;
+}
+
+void OS::oss_put_string_with_hilite(winid_t win, const char *str, size_t len) {
+ glk_set_window(win);
+ glk_put_buffer(str, len);
+}
+
+void OS::oss_draw_status_line(void) {
+ glui32 width, height, division;
+
+ if (status_win == nullptr) return; // In case this is a CheapGlk port
+
+ glk_window_get_size(status_win, &width, &height);
+ if (height == 0) return; // Don't bother if status is invisible
+ division = width - strlen(status_right) - 1;
+ glk_set_window(status_win);
+ glk_window_clear(status_win);
+ oss_put_string_with_hilite(status_win, status_left, strlen(status_left));
+ glk_window_move_cursor(status_win, division, 0);
+ glk_put_string(status_right);
+}
+
+void OS::oss_change_status_string(char *dest, const char *src, size_t len) {
+ if (len > OSS_STATUS_STRING_LEN - 1)
+ len = OSS_STATUS_STRING_LEN - 1;
+ memcpy(dest, src, len);
+ dest[len] = '\0';
+}
+
+void OS::oss_change_status_left(const char *str, size_t len) {
+ oss_change_status_string(status_left, str, len);
+ oss_draw_status_line();
+}
+
+void OS::oss_change_status_right(const char *str) {
+ oss_change_status_string(status_right, str, strlen(str));
+ oss_draw_status_line();
+}
+
+int OS::memicmp(char *s1, char *s2, int len) {
+ char *x1, *x2;
+ int i, result;
+
+ x1 = (char *)malloc(len); x2 = (char *)malloc(len);
+
+ if (!x1 || !x2) {
+ glk_set_window(story_win);
+ glk_put_string("memicmp has run out of memory. Quitting.\n");
+ os_waitc();
+ glk_exit();
+ }
+
+ for (i = 0; i < len; i++) {
+ if (Common::isUpper(s1[i]))
+ x1[i] = glk_char_to_lower((unsigned char)s1[i]);
+ else x1[i] = s1[i];
+
+ if (Common::isUpper(s2[i]))
+ x2[i] = glk_char_to_lower((unsigned char)s2[i]);
+ else x2[i] = s2[i];
+ }
+
+ result = memcmp(x1, x2, len);
+ free(x1);
+ free(x2);
+ return result;
+}
+
+void OS::os_flush() {
+ glk_tick();
+}
+
+void OS::os_print(const char *str, size_t len) {
+ int current_status_mode;
+
+ // Decide what to do based on our status mode
+ current_status_mode = os_get_status();
+ if (current_status_mode == OSS_STATUS_MODE_STORY) {
+ oss_put_string_with_hilite(story_win, str, len);
+ } else if (current_status_mode == OSS_STATUS_MODE_STATUS) {
+ const char *p;
+ size_t rem;
+
+ // The string requires some fiddling for the status window
+ for (p = str, rem = len; rem != 0 && *p == '\n'; p++, --rem);
+ if (rem != 0 && p[rem - 1] == '\n')
+ --rem;
+
+ // if that leaves anything, update the statusline
+ if (rem != 0)
+ oss_change_status_left(p, rem);
+ }
+}
+
+void OS::os_expause() {
+ os_printz("(Strike any key to exit...)");
+ os_flush();
+ os_waitc();
+}
+
+int OS::oss_getc_from_window(winid_t win) {
+ static unsigned char buffered_char = 0;
+ int i;
+ event_t ev;
+
+ if (buffered_char != 0) {
+ i = (int)buffered_char;
+ buffered_char = 0;
+ return i;
+ }
+ glk_request_char_event(win);
+ do {
+ glk_select(&ev);
+ if (ev.type == evtype_Arrange)
+ oss_draw_status_line();
+ } while (ev.type != evtype_CharInput);
+ if (ev.val1 == keycode_Return)
+ ev.val1 = '\n';
+ else if (ev.val1 == keycode_Tab)
+ ev.val1 = '\t';
+ if (ev.val1 <= 255)
+ return ((int)ev.val1);
+
+ // We got a special character, so handle it appropriately
+ buffered_char = oss_convert_keystroke_to_tads(ev.val1);
+ return 0;
+}
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads2/os.h b/engines/glk/tads/tads2/os.h
new file mode 100644
index 0000000..ba0058d
--- /dev/null
+++ b/engines/glk/tads/tads2/os.h
@@ -0,0 +1,334 @@
+/* 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_TADS_TADS2_OS
+#define GLK_TADS_TADS2_OS
+
+#include "glk/tads/tads.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+/**
+ * The character (or characters) which mark the beginning of a special fileref string.
+ * The important thing is that the string be one that is either not allowed in
+ * filenames on your platform or is unlikely to be the first part of a filename.
+ */
+#define OSS_FILEREF_STRING_PREFIX ":"
+
+/**
+ * The character (or characters) which mark the end of a special fileref string.
+ * Using this and OSS_FILEREF_STRING_PREFIX, you should be able to come up with
+ * something which forms an invalid filename
+ */
+#define OSS_FILEREF_STRING_SUFFIX ""
+
+/**
+ * Maximum length of status line text
+ */
+#define OSS_STATUS_STRING_LEN 80
+
+/**
+ * Important note: do not change these values when porting TADS. These
+ * values can be used by games, so they must be the same on all platforms.
+ */
+enum {
+ OS_AFP_OPEN = 1, ///< choose an existing file to open for reading
+ OS_AFP_SAVE = 2 ///< choose a filename for saving to a file
+};
+
+/**
+ * File types.These type codes are used when opening or creating a file,
+ * so that the OS routine can set appropriate file system metadata
+ * to describe or find the file type.
+ *
+ * The type os_filetype_t is defined for documentary purposes; it's
+ * always just an int.
+ */
+enum os_filetype_t {
+ OSFTGAME = 0, ///< a game data file (.gam)
+ OSFTSAVE = 1, ///< a saved game (.sav)
+ OSFTLOG = 2, ///< a transcript (log) file
+ OSFTSWAP = 3, ///< swap file
+ OSFTDATA = 4, ///< user data file (used with the TADS fopen() call)
+ OSFTCMD = 5, ///< QA command/log file
+ OSFTERRS = 6, ///< error message file
+ OSFTTEXT = 7, ///< text file - used for source files
+ OSFTBIN = 8, ///< binary file of unknown type - resources, etc
+ OSFTCMAP = 9, ///< character mapping file
+ OSFTPREF = 10, ///< preferences file
+ OSFTUNK = 11, ///< unknown - as a filter, matches any file type
+ OSFTT3IMG = 12, ///< T3 image file (.t3 - formerly .t3x)
+ OSFTT3OBJ = 13, ///< T3 object file (.t3o)
+ OSFTT3SYM = 14, ///< T3 symbol export file (.t3s)
+ OSFTT3SAV = 15 ///< T3 saved state file (.t3v)
+};
+
+/**
+ * Constants for os_getc() when returning commands. When used for command line
+ * editing, special keys (arrows, END, etc.) should cause os_getc() to return 0,
+ * and return the appropriate CMD_ value on the NEXT call. Hence, os_getc() must
+ * keep the appropriate information around statically for the next call when a
+ * command key is issued.
+ *
+ * The comments indicate which CMD_xxx codes are "translated" codes and which are
+ * "raw"; the difference is that, when a particular keystroke could be interpreted
+ * as two different CMD_xxx codes, one translated and the other raw, os_getc()
+ * should always return the translated version of the key, and os_getc_raw()
+ * should return the raw version.
+ */
+enum KeyCmd {
+ CMD_UP = 1, ///< move up/up arrow (translated)
+ CMD_DOWN = 2, ///< move down/down arrow (translated)
+ CMD_RIGHT = 3, ///< move right/right arrow (translated)
+ CMD_LEFT = 4, ///< move left/left arrow (translated)
+ CMD_END = 5, ///< move cursor to end of line (translated)
+ CMD_HOME = 6, ///< move cursor to start of line (translated)
+ CMD_DEOL = 7, ///< delete to end of line (translated)
+ CMD_KILL = 8, ///< delete entire line (translated)
+ CMD_DEL = 9, ///< delete current character (translated)
+ CMD_SCR = 10, ///< toggle scrollback mode (translated)
+ CMD_PGUP = 11, ///< page up (translated)
+ CMD_PGDN = 12, ///< page down (translated)
+ CMD_TOP = 13, ///< top of file (translated)
+ CMD_BOT = 14, ///< bottom of file (translated)
+ CMD_F1 = 15, ///< function key F1 (raw)
+ CMD_F2 = 16, ///< function key F2 (raw)
+ CMD_F3 = 17, ///< function key F3 (raw)
+ CMD_F4 = 18, ///< function key F4 (raw)
+ CMD_F5 = 19, ///< function key F5 (raw)
+ CMD_F6 = 20, ///< function key F6 (raw)
+ CMD_F7 = 21, ///< function key F7 (raw)
+ CMD_F8 = 22, ///< function key F8 (raw)
+ CMD_F9 = 23, ///< function key F9 (raw)
+ CMD_F10 = 24, ///< function key F10 (raw)
+ CMD_CHOME = 25, ///< control-home (raw)
+ CMD_TAB = 26, ///< tab (translated)
+ CMD_SF2 = 27, ///< shift-F2 (raw)
+ ///< not used (obsolete) - 28
+ CMD_WORD_LEFT = 29, ///< word left (ctrl-left on dos) (translated)
+ CMD_WORD_RIGHT = 30, ///< word right (ctrl-right on dos) (translated)
+ CMD_WORDKILL = 31, ///< delete word right (translated)
+ CMD_EOF = 32, ///< end-of-file (raw)
+ CMD_BREAK = 33, ///< break (Ctrl-C or local equivalent) (translated)
+ CMD_INS = 34, ///< insert key (raw)
+
+ /**
+ * ALT-keys - add alphabetical code to CMD_ALT: ALT-A == CMD_ALT + 0,
+ * ALT-B == CMD_ALT + 1, ALT-C == CMD_ALT + 2, etc
+ *
+ * These keys are all raw (untranslated).
+ */
+ CMD_ALT = 128 ///< start of ALT keys
+};
+
+/**
+ * Status mode codes
+ */
+enum StatusMode {
+ OSS_STATUS_MODE_STORY = 0,
+ OSS_STATUS_MODE_STATUS = 1
+};
+
+typedef Common::SeekableReadStream osfildef;
+
+/**
+ * Operating system compatibility layer
+ */
+class OS : public TADS {
+protected:
+ char status_left[OSS_STATUS_STRING_LEN];
+ char status_right[OSS_STATUS_STRING_LEN];
+ int status_mode;
+protected:
+ /**
+ * Constructor
+ */
+ OS(OSystem *syst, const GlkGameDescription &gameDesc);
+
+ /**
+ * Terminates the game
+ */
+ void os_terminate(int rc);
+
+ /**
+ * \defgroup Type Conversions
+ * @{
+ */
+
+ /**
+ * Change a TADS prompt type (OS_AFP_*) into a Glk prompt type.
+ */
+ glui32 oss_convert_prompt_type(int type);
+
+ /**
+ * Change a TADS file type (OSFT*) into a Glk file type.
+ */
+ glui32 oss_convert_file_type(int type);
+
+ /**
+ * Change a fileref ID (frefid_t) to a special string and put it in the
+ * buffer which is passed to it. The string is given by
+ * OSS_FILEREF_STRING_PREFIX + 'nnnnn' + OSS_FILEREF_STRING_SUFFIX
+ * where 'nnnnn' is the frefid_t pointer converted into a string of decimal
+ * numbers. This is only really practical for 32-bit pointers; if we use
+ * 64-bit pointers I'll have to start using a hash table or use hex
+ * numbers.
+ */
+ glui32 oss_convert_fileref_to_string(frefid_t file_to_convert, char *buffer, int buf_len);
+
+ /**
+ * Turn a filename or a special fileref string into an actual fileref.
+ * Notice that, since Glk doesn't know paths, we take this opportunity to
+ * call oss_check_path, which should do the OS-dependent path changing
+ * in the event that the filename contains path information
+ */
+ frefid_t oss_convert_string_to_fileref(char *buffer, glui32 usage);
+
+ /**
+ * Tell us if the passed string is a hashed fileref or not
+ */
+ bool oss_is_string_a_fileref(char *buffer);
+
+ /**
+ * Change a Glk key into a TADS one, using the CMD_xxx codes
+ */
+ unsigned char oss_convert_keystroke_to_tads(glui32 key);
+
+ /**@}*/
+
+ /**
+ * \defgroup Directory/File methods
+ * @{
+ */
+
+ /**
+ * If a filename contains path information, change dirs to that path.
+ * Returns true if the path was fiddled with
+ */
+ bool oss_check_path(char *filename);
+
+ /**
+ * In case we changed directories in oss_check_path, change back to the
+ * original executable directory
+ */
+ void oss_revert_path();
+
+ /**
+ * Open a stream, given a string, usage, and a filemode. tadsusage is the
+ * TADS filemode (OSFT*); tbusage is either fileusage_TextMode or
+ * fileusage_BinaryMode (from Glk).
+ */
+ osfildef *oss_open_stream(char *buffer, glui32 tadsusage, glui32 tbusage,
+ glui32 fmode, glui32 rock);
+
+ /**
+ * Get a pointer to the root name portion of a filename. This is the part
+ * of the filename after any path or directory prefix. For example, on
+ * Unix, given the string "/home/mjr/deep.gam", this function should return
+ * a pointer to the 'd' in "deep.gam". If the filename doesn't appear to
+ * have a path prefix, it should simply return the argument unchanged.
+ */
+ const char *os_get_root_name(const char *buf) const { return buf; }
+
+ /**@}*/
+
+ /**
+ * \defgroup The main text area print routines
+ * @{
+ */
+
+ /**
+ * Process hilighting codes while printing a string
+ */
+ void oss_put_string_with_hilite(winid_t win, const char *str, size_t len);
+
+ /**
+ * Status line handling
+ */
+ void oss_draw_status_line();
+
+ void oss_change_status_string(char *dest, const char *src, size_t len);
+ void oss_change_status_left(const char *str, size_t len);
+ void oss_change_status_right(const char *str);
+ int os_get_status() const { return status_mode; }
+
+ /**
+ * Flush the output
+ */
+ void os_flush();
+
+ /**
+ * Print a null terminated string
+ */
+ void os_printz(const char *str) { os_print(str, strlen(str)); }
+
+ /**
+ * Print a string
+ */
+ void os_print(const char *str, size_t len);
+
+ /**
+ * Compare two strings
+ */
+ int memicmp(char *s1, char *s2, int len);
+
+ /**@}*/
+
+ /**
+ * \defgroup Input routines
+ * @{
+ */
+
+ /**
+ * Wait for a key to be hit
+ */
+ void os_waitc(void) { os_getc(); }
+
+ /**
+ * Get a character from the keyboard. For extended characters, return 0,
+ * then return the extended key at the next call to this function
+ */
+ int os_getc() {
+ return oss_getc_from_window(story_win);
+ }
+
+ /**
+ * Accept a keystroke in the passed window
+ */
+ int oss_getc_from_window(winid_t win);
+
+
+ /**
+ * Print a message (with os_print) and wait for a key
+ */
+ void os_expause();
+
+ /**@}*/
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/tads/tads2/tads2.cpp b/engines/glk/tads/tads2/tads2.cpp
index 81f7272..9c50c20d 100644
--- a/engines/glk/tads/tads2/tads2.cpp
+++ b/engines/glk/tads/tads2/tads2.cpp
@@ -26,11 +26,46 @@ namespace Glk {
namespace TADS {
namespace TADS2 {
-TADS2::TADS2(OSystem *syst, const GlkGameDescription &gameDesc) : TADS(syst, gameDesc) {
+TADS2::TADS2(OSystem *syst, const GlkGameDescription &gameDesc) : OS(syst, gameDesc) {
}
void TADS2::runGame(Common::SeekableReadStream *gameFile) {
- // TODO
+ errcxdef errctx;
+ errctx.errcxlgc = &errctx;
+ errctx.errcxfp = nullptr;
+ errctx.errcxofs = 0;
+ errctx.errcxappctx = this;
+
+ /* copyright-date-string */
+#ifdef T2_COPYRIGHT_NOTICE
+ trdptf("%s - A %s TADS %s Interpreter.\n",
+ G_tads_oem_app_name, G_tads_oem_display_mode,
+ TADS_RUNTIME_VERSION);
+ trdptf("%sopyright (c) 1993, 2012 by Michael J. Roberts.\n",
+ G_tads_oem_copyright_prefix ? "TADS c" : "C");
+ trdptf("%s\n", G_tads_oem_author);
+#endif
+
+ trdmain1(&errctx);
+
+ // pause before exiting if the OS desires it
+ os_expause();
+}
+
+void TADS2::trdmain1(errcxdef *errctx) {
+
+}
+
+void TADS2::trdptf(const char *fmt, ...) {
+ va_list va;
+
+ // format the string */
+ va_start(va, fmt);
+ Common::String msg = Common::String::vformat(fmt, va);
+ va_end(va);
+
+ // print the formatted buffer
+ os_printz(msg);
}
} // End of namespace TADS2
diff --git a/engines/glk/tads/tads2/tads2.h b/engines/glk/tads/tads2/tads2.h
index e07b5c8..2c799a3 100644
--- a/engines/glk/tads/tads2/tads2.h
+++ b/engines/glk/tads/tads2/tads2.h
@@ -23,7 +23,8 @@
#ifndef GLK_TADS_TADS2
#define GLK_TADS_TADS2
-#include "glk/tads/tads.h"
+#include "glk/tads/tads2/os.h"
+#include "glk/tads/tads2/ler.h"
namespace Glk {
namespace TADS {
@@ -32,7 +33,10 @@ namespace TADS2 {
/**
* TADS 2 game interpreter
*/
-class TADS2 : public TADS {
+class TADS2 : public OS {
+private:
+ // STUBS
+ void os_printz(const Common::String &s) {}
public:
/**
* Constructor
@@ -48,8 +52,17 @@ public:
* Returns the running interpreter type
*/
virtual InterpreterType getInterpreterType() const override { return INTERPRETER_TADS2; }
+
+ void trdmain1(errcxdef *errctx);
+
+ /**
+ * printf-style formatting
+ */
+ void trdptf(const char *fmt, ...);
};
+typedef TADS2 appctxdef;
+
} // End of namespace TADS2
} // End of namespace TADS
} // End of namespace Glk
Commit: d3c46f7078c05fc38bde26d38f6d767167c54c6f
https://github.com/scummvm/scummvm/commit/d3c46f7078c05fc38bde26d38f6d767167c54c6f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Add Regex class
Changed paths:
engines/glk/module.mk
engines/glk/tads/tads2/os.cpp
engines/glk/tads/tads2/os.h
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 89be6a2..a812850 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -47,6 +47,7 @@ MODULE_OBJS := \
tads/tads.o \
tads/tads2/ler.o \
tads/tads2/os.o \
+ tads/tads2/regex.o \
tads/tads2/tads2.o \
tads/tads3/tads3.o
diff --git a/engines/glk/tads/tads2/os.cpp b/engines/glk/tads/tads2/os.cpp
index df7cb42..248611d 100644
--- a/engines/glk/tads/tads2/os.cpp
+++ b/engines/glk/tads/tads2/os.cpp
@@ -215,7 +215,7 @@ void OS::oss_change_status_right(const char *str) {
oss_draw_status_line();
}
-int OS::memicmp(char *s1, char *s2, int len) {
+int OS::memicmp(const char *s1, const char *s2, int len) {
char *x1, *x2;
int i, result;
diff --git a/engines/glk/tads/tads2/os.h b/engines/glk/tads/tads2/os.h
index ba0058d..3c50cb5 100644
--- a/engines/glk/tads/tads2/os.h
+++ b/engines/glk/tads/tads2/os.h
@@ -30,6 +30,17 @@ namespace TADS {
namespace TADS2 {
/**
+ * Allocate a memory block
+ */
+#define mchalo(CTX, SIZE, COMMENT) ((byte *)new byte[SIZE])
+
+/**
+ * Free a memory block
+ */
+#define mchfre(PTR) delete[] (byte *)PTR
+
+
+/**
* The character (or characters) which mark the beginning of a special fileref string.
* The important thing is that the string be one that is either not allowed in
* filenames on your platform or is unlikely to be the first part of a filename.
@@ -288,10 +299,17 @@ protected:
*/
void os_print(const char *str, size_t len);
+ /**@}*/
+
+ /**
+ * \defgroup Memory routines
+ * @{
+ */
+
/**
* Compare two strings
*/
- int memicmp(char *s1, char *s2, int len);
+ int memicmp(const char *s1, const char *s2, int len);
/**@}*/
Commit: f20d07381cfdbb625550167e259a2ea58f81fcd9
https://github.com/scummvm/scummvm/commit/f20d07381cfdbb625550167e259a2ea58f81fcd9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Added cmap file
Changed paths:
A engines/glk/tads/tads2/regex.cpp
A engines/glk/tads/tads2/regex.h
A engines/glk/tads/tads2/tads2_cmap.cpp
A engines/glk/tads/tads2/types.h
engines/glk/module.mk
engines/glk/tads/tads2/ler.h
engines/glk/tads/tads2/os.cpp
engines/glk/tads/tads2/os.h
engines/glk/tads/tads2/tads2.cpp
engines/glk/tads/tads2/tads2.h
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index a812850..5c17362 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -49,6 +49,7 @@ MODULE_OBJS := \
tads/tads2/os.o \
tads/tads2/regex.o \
tads/tads2/tads2.o \
+ tads/tads2/tads2_cmap.o \
tads/tads3/tads3.o
# This module can be built as a plugin
diff --git a/engines/glk/tads/tads2/ler.h b/engines/glk/tads/tads2/ler.h
index 000aa09..8edb945 100644
--- a/engines/glk/tads/tads2/ler.h
+++ b/engines/glk/tads/tads2/ler.h
@@ -34,6 +34,314 @@ namespace TADS2 {
// maximum length of a facility identifier
#define ERRFACMAX 6
+enum ErrorCode {
+ /* memory/cache manager errors */
+ ERR_NOMEM = 1, /* out of memory */
+ ERR_FSEEK = 2, /* error seeking in file */
+ ERR_FREAD = 3, /* error reading from file */
+ ERR_NOPAGE = 4, /* no more page slots */
+ ERR_REALCK = 5, /* attempting to reallocate a locked object */
+ ERR_SWAPBIG = 6, /* swapfile limit reached - out of virtual memory */
+ ERR_FWRITE = 7, /* error writing file */
+ ERR_SWAPPG = 8, /* exceeded swap page table limit */
+ ERR_CLIUSE = 9, /* requested client object number already in use */
+ ERR_CLIFULL = 10, /* client mapping table is full */
+ ERR_NOMEM1 = 11, /* swapping/garbage collection failed to find enuf */
+ ERR_NOMEM2 = 12, /* no memory to resize (expand) an object */
+ ERR_OPSWAP = 13, /* unable to open swap file */
+ ERR_NOHDR = 14, /* can't get a new object header */
+ ERR_NOLOAD = 15, /* mcm cannot find object to load (internal error) */
+ ERR_LCKFRE = 16, /* attempting to free a locked object (internal) */
+ ERR_INVOBJ = 17, /* invalid object */
+ ERR_BIGOBJ = 18, /* object too big - exceeds memory allocation limit */
+
+ /* lexical analysis errors */
+ ERR_INVTOK = 100, /* invalid token */
+ ERR_STREOF = 101, /* end of file while scanning string */
+ ERR_TRUNC = 102, /* symbol too long - truncated */
+ ERR_NOLCLSY = 103, /* no space in local symbol table */
+ ERR_PRPDIR = 104, /* invalid preprocessor (#) directive */
+ ERR_INCNOFN = 105, /* no filename in #include directive */
+ ERR_INCSYN = 106, /* invalid #include syntax */
+ ERR_INCSEAR = 107, /* can't find included file */
+ ERR_INCMTCH = 108, /* no matching delimiter in #include filename */
+ ERR_MANYSYM = 109, /* out of space for symbol table */
+ ERR_LONGLIN = 110, /* line too long */
+ ERR_INCRPT = 111, /* header file already included - ignored */
+ ERR_PRAGMA = 112, /* unknown pragma (ignored) */
+ ERR_BADPELSE = 113, /* unexpected #else */
+ ERR_BADENDIF = 114, /* unexpected #endif */
+ ERR_BADELIF = 115, /* unexpected #elif */
+ ERR_MANYPIF = 116, /* #if nesting too deep */
+ ERR_DEFREDEF = 117, /* symbol already defined */
+ ERR_PUNDEF = 118, /* #undef symbol not defined */
+ ERR_NOENDIF = 119, /* missing #endif */
+ ERR_MACNEST = 120, /* macros nested too deeply */
+ ERR_BADISDEF = 121, /* invalid argument for defined() operator */
+ ERR_PIF_NA = 122, /* #if is not implemented */
+ ERR_PELIF_NA = 123, /* #elif is not implemented */
+ ERR_P_ERROR = 124, /* error directive: %s */
+ ERR_LONG_FILE_MACRO = 125, /* __FILE__ expansion too long */
+ ERR_LONG_LINE_MACRO = 126, /* __LINE__ expansion too long */
+
+ /* undo errors */
+ ERR_UNDOVF = 200, /* operation is too big for undo log */
+ ERR_NOUNDO = 201, /* no more undo information */
+ ERR_ICUNDO = 202, /* incomplete undo (no previous savepoint) */
+
+ /* parser errors */
+ ERR_REQTOK = 300, /* expected token (arg 1) - found something else */
+ ERR_REQSYM = 301, /* expected symbol */
+ ERR_REQPRP = 302, /* expected a property name */
+ ERR_REQOPN = 303, /* expected operand */
+ ERR_REQARG = 304, /* expected comma or closing paren (arg list) */
+ ERR_NONODE = 305, /* no space for new parse node */
+ ERR_REQOBJ = 306, /* epxected object name */
+ ERR_REQEXT = 307, /* redefining symbol as external function */
+ ERR_REQFCN = 308, /* redefining symbol as function */
+ ERR_NOCLASS = 309, /* can't use CLASS with function/external function */
+ ERR_REQUNO = 310, /* required unary operator */
+ ERR_REQBIN = 311, /* required binary operator */
+ ERR_INVBIN = 312, /* invalid binary operator */
+ ERR_INVASI = 313, /* invalid assignment */
+ ERR_REQVAR = 314, /* required variable name */
+ ERR_LCLSYN = 315, /* required comma or semicolon in local list */
+ ERR_REQRBR = 316, /* required right brace (eof before end of group) */
+ ERR_BADBRK = 317, /* 'break' without 'while' */
+ ERR_BADCNT = 318, /* 'continue' without 'while' */
+ ERR_BADELS = 319, /* 'else' without 'if' */
+ ERR_WEQASI = 320, /* warning: possible use of '=' where ':=' intended */
+ ERR_EOF = 321, /* unexpected end of file */
+ ERR_SYNTAX = 322, /* general syntax error */
+ ERR_INVOP = 323, /* invalid operand type */
+ ERR_NOMEMLC = 324, /* no memory for new local symbol table */
+ ERR_NOMEMAR = 325, /* no memory for argument symbol table */
+ ERR_FREDEF = 326, /* redefining a function which is already defined */
+ ERR_NOSW = 327, /* 'case' or 'default' and not in switch block */
+ ERR_SWRQCN = 328, /* constant required in switch case value */
+ ERR_REQLBL = 329, /* label required for 'goto' */
+ ERR_NOGOTO = 330, /* 'goto' label never defined */
+ ERR_MANYSC = 331, /* too many superclasses for object */
+ ERR_OREDEF = 332, /* redefining symbol as object */
+ ERR_PREDEF = 333, /* property being redefined in object */
+ ERR_BADPVL = 334, /* invalid property value */
+ ERR_BADVOC = 335, /* bad vocabulary property value */
+ ERR_BADTPL = 336, /* bad template property value (need sstring) */
+ ERR_LONGTPL = 337, /* template base property name too long */
+ ERR_MANYTPL = 338, /* too many templates (internal compiler limit) */
+ ERR_BADCMPD = 339, /* bad value for compound word (sstring required) */
+ ERR_BADFMT = 340, /* bad value for format string (sstring needed) */
+ ERR_BADSYN = 341, /* invalid value for synonym (sstring required) */
+ ERR_UNDFSYM = 342, /* undefined symbol */
+ ERR_BADSPEC = 343, /* bad special word */
+ ERR_NOSELF = 344, /* "self" not valid in this context */
+ ERR_STREND = 345, /* warning: possible unterminated string */
+ ERR_MODRPLX = 346, /* modify/replace not allowed with external func */
+ ERR_MODFCN = 347, /* modify not allowed with function */
+ ERR_MODFWD = 348, /* modify/replace not allowed with forward func */
+ ERR_MODOBJ = 349, /* modify can only be used with a defined object */
+ ERR_RPLSPEC = 350, /* warning - replacing specialWords */
+ ERR_SPECNIL = 351, /* nil only allowed with modify specialWords */
+ ERR_BADLCL = 353, /* 'local' statement must precede executable code */
+ ERR_IMPPROP = 354, /* implied verifier '%s' is not a property */
+ ERR_BADTPLF = 355, /* invalid command template flag */
+ ERR_NOTPLFLG = 356, /* flags are not allowed with old file format */
+ ERR_AMBIGBIN = 357, /* warning: operator '%s' could be binary */
+ ERR_PIA = 358, /* warning: possibly incorrect assignment */
+ ERR_BADSPECEXPR = 359, /* invalid speculation evaluation */
+
+ /* code generation errors */
+ ERR_OBJOVF = 400, /* object cannot grow any bigger - code too big */
+ ERR_NOLBL = 401, /* no more temporary labels/fixups */
+ ERR_LBNOSET = 402, /* (internal error) label never set */
+ ERR_INVLSTE = 403, /* invalid datatype for list element */
+ ERR_MANYDBG = 404, /* too many debugger line records (internal limit) */
+
+ /* vocabulary setup errors */
+ ERR_VOCINUS = 450, /* vocabulary being redefined for object */
+ ERR_VOCMNPG = 451, /* too many vocwdef pages (internal limit) */
+ ERR_VOCREVB = 452, /* redefining same verb */
+ ERR_VOCREVB2 = 453, /* redefining same verb - two arguments */
+
+ /* set-up errors */
+ ERR_LOCNOBJ = 500, /* location of object %s is not an object */
+ ERR_CNTNLST = 501, /* contents of object %s is not list */
+ ERR_SUPOVF = 502, /* overflow trying to build contents list */
+ ERR_RQOBJNF = 503, /* required object %s not found */
+ ERR_WRNONF = 504, /* warning - object %s not found */
+ ERR_MANYBIF = 505, /* too many built-in functions (internal error) */
+
+ /* fio errors */
+ ERR_OPWGAM = 600, /* unable to open game for writing */
+ ERR_WRTGAM = 601, /* error writing to game file */
+ ERR_FIOMSC = 602, /* too many sc's for writing in fiowrt */
+ ERR_UNDEFF = 603, /* undefined function */
+ ERR_UNDEFO = 604, /* undefined object */
+ ERR_UNDEF = 605, /* undefined symbols found */
+ ERR_OPRGAM = 606, /* unable to open game for reading */
+ ERR_RDGAM = 607, /* error reading game file */
+ ERR_BADHDR = 608, /* file has invalid header - not TADS game file */
+ ERR_UNKRSC = 609, /* unknown resource type in .gam file */
+ ERR_UNKOTYP = 610, /* unknown object type in OBJ resource */
+ ERR_BADVSN = 611, /* file saved by different incompatible version */
+ ERR_LDGAM = 612, /* error loading object on demand */
+ ERR_LDBIG = 613, /* object too big for load region (prob. internal) */
+ ERR_UNXEXT = 614, /* did not expect external function */
+ ERR_WRTVSN = 615, /* compiler cannot write the requested version */
+ ERR_VNOCTAB = 616, /* format version cannot be used with -ctab */
+ ERR_BADHDRRSC = 617, /* invalid resource file header in file %s */
+ ERR_RDRSC = 618, /* error reading resource file "xxx" */
+
+ /* character mapping errors */
+ ERR_CHRNOFILE = 700, /* unable to load character mapping file */
+
+ /* user interrupt */
+ ERR_USRINT = 990, /* user requested cancel of current operation */
+
+ /* run-time errors */
+ ERR_STKOVF = 1001, /* stack overflow */
+ ERR_HPOVF = 1002, /* heap overflow */
+ ERR_REQNUM = 1003, /* numeric value required */
+ ERR_STKUND = 1004, /* stack underflow */
+ ERR_REQLOG = 1005, /* logical value required */
+ ERR_INVCMP = 1006, /* invalid datatypes for magnitude comparison */
+ ERR_REQSTR = 1007, /* string value required */
+ ERR_INVADD = 1008, /* invalid datatypes for '+' operator */
+ ERR_INVSUB = 1009, /* invalid datatypes for binary '-' operator */
+ ERR_REQVOB = 1010, /* require object value */
+ ERR_REQVFN = 1011, /* required function pointer */
+ ERR_REQVPR = 1012, /* required property number value */
+
+ /* non-error conditions: run-time EXIT, ABORT, ASKIO, ASKDO */
+ ERR_RUNEXIT = 1013, /* 'exit' statement executed */
+ ERR_RUNABRT = 1014, /* 'abort' statement executed */
+ ERR_RUNASKD = 1015, /* 'askdo' statement executed */
+ ERR_RUNASKI = 1016, /* 'askio' executed; int arg 1 is prep */
+ ERR_RUNQUIT = 1017, /* 'quit' executed */
+ ERR_RUNRESTART = 1018, /* 'reset' executed */
+ ERR_RUNEXITOBJ = 1019, /* 'exitobj' executed */
+
+ ERR_REQVLS = 1020, /* list value required */
+ ERR_LOWINX = 1021, /* index value too low (must be >= 1) */
+ ERR_HIGHINX = 1022, /* index value too high (must be <= length(list)) */
+ ERR_INVTBIF = 1023, /* invalid type for built-in function */
+ ERR_INVVBIF = 1024, /* invalid value for built-in function */
+ ERR_BIFARGC = 1025, /* wrong number of arguments to built-in */
+ ERR_ARGC = 1026, /* wrong number of arguments to user function */
+ ERR_FUSEVAL = 1027, /* string/list not allowed for fuse/daemon arg */
+ ERR_BADSETF = 1028, /* internal error in setfuse/setdaemon/notify */
+ ERR_MANYFUS = 1029, /* too many fuses */
+ ERR_MANYDMN = 1030, /* too many daemons */
+ ERR_MANYNFY = 1031, /* too many notifiers */
+ ERR_NOFUSE = 1032, /* fuse not found in remfuse */
+ ERR_NODMN = 1033, /* daemon not found in remdaemon */
+ ERR_NONFY = 1034, /* notifier not found in unnotify */
+ ERR_BADREMF = 1035, /* internal error in remfuse/remdaemon/unnotify */
+ ERR_DMDLOOP = 1036, /* load-on-demand loop: property not being set */
+ ERR_UNDFOBJ = 1037, /* undefined object in vocabulary tree */
+ ERR_BIFCSTR = 1038, /* c-string conversion overflows buffer */
+ ERR_INVOPC = 1039, /* invalid opcode */
+ ERR_RUNNOBJ = 1040, /* runtime error: property taken of non-object */
+ ERR_EXTLOAD = 1041, /* unable to load external function "%s" */
+ ERR_EXTRUN = 1042, /* error executing external function "%s" */
+ ERR_CIRCSYN = 1043, /* circular synonym */
+ ERR_DIVZERO = 1044, /* divide by zero */
+ ERR_BADDEL = 1045, /* can only delete objects created with "new" */
+ ERR_BADNEWSC = 1046, /* superclass for "new" cannot be a new object */
+ ERR_VOCSTK = 1047, /* insufficient space in parser stack */
+ ERR_BADFILE = 1048, /* invalid file handle */
+
+ ERR_RUNEXITPRECMD = 1049, /* exited from preCommand */
+
+ /* run-time parser errors */
+ ERR_PRS_SENT_UNK = 1200, /* sentence structure not recognized */
+ ERR_PRS_VERDO_FAIL = 1201, /* verDoVerb failed */
+ ERR_PRS_VERIO_FAIL = 1202, /* verIoVerb failed */
+ ERR_PRS_NO_VERDO = 1203, /* no verDoVerb for direct object */
+ ERR_PRS_NO_VERIO = 1204, /* no verIoVerb for direct object */
+ ERR_PRS_VAL_DO_FAIL = 1205, /* direct object validation failed */
+ ERR_PRS_VAL_IO_FAIL = 1206, /* indirect object validation failed */
+
+ /* compiler/runtime/debugger driver errors */
+ ERR_USAGE = 1500, /* invalid usage */
+ ERR_OPNINP = 1501, /* error opening input file */
+ ERR_NODBG = 1502, /* game not compiled for debugging */
+ ERR_ERRFIL = 1503, /* unable to open error capture file */
+ ERR_PRSCXSIZ = 1504, /* parse pool + local size too large */
+ ERR_STKSIZE = 1505, /* stack size too large */
+ ERR_OPNSTRFIL = 1506, /* error opening string capture file */
+ ERR_INVCMAP = 1507, /* invalid character map file */
+
+ /* debugger errors */
+ ERR_BPSYM = 2000, /* symbol not found for breakpoint */
+ ERR_BPPROP = 2002, /* breakpoint symbol is not a property */
+ ERR_BPFUNC = 2003, /* breakpoint symbol is not a function */
+ ERR_BPNOPRP = 2004, /* property is not defined for object */
+ ERR_BPPRPNC = 2005, /* property is not code */
+ ERR_BPSET = 2006, /* breakpoint already set at this location */
+ ERR_BPNOTLN = 2007, /* breakpoint is not at a line (OPCLINE instr) */
+ ERR_MANYBP = 2008, /* too many breakpoints */
+ ERR_BPNSET = 2009, /* breakpoint to be deleted was not set */
+ ERR_DBGMNSY = 2010, /* too many symbols in debug expression (int lim) */
+ ERR_NOSOURC = 2011, /* unable to find source file %s */
+ ERR_WTCHLCL = 2012, /* illegal to assign to local in watch expr */
+ ERR_INACTFR = 2013, /* inactive frame (expression value not available) */
+ ERR_MANYWX = 2014, /* too many watch expressions */
+ ERR_WXNSET = 2015, /* watchpoint not set */
+ ERR_EXTRTXT = 2016, /* extraneous text at end of command */
+ ERR_BPOBJ = 2017, /* breakpoint symbol is not an object */
+ ERR_DBGINACT = 2018, /* debugger is not active */
+ ERR_BPINUSE = 2019, /* breakpoint is already used */
+ ERR_RTBADSPECEXPR = 2020, /* invalid speculative expression */
+ ERR_NEEDLIN2 = 2021, /* -ds2 information not found - must recompile */
+
+ /* usage error messages */
+ ERR_TCUS1 = 3000, /* first tc usage message */
+ ERR_TCUSL = 3024, /* last tc usage message */
+ ERR_TCTGUS1 = 3030, /* first tc toggle message */
+ ERR_TCTGUSL = 3032,
+ ERR_TCZUS1 = 3040, /* first tc -Z suboptions usage message */
+ ERR_TCZUSL = 3041,
+ ERR_TC1US1 = 3050, /* first tc -1 suboptions usage message */
+ ERR_TC1USL = 3058,
+ ERR_TCMUS1 = 3070, /* first tc -m suboptions usage message */
+ ERR_TCMUSL = 3076,
+ ERR_TCVUS1 = 3080, /* first -v suboption usage message */
+ ERR_TCVUSL = 3082,
+ ERR_TRUSPARM = 3099,
+ ERR_TRUS1 = 3100, /* first tr usage message */
+ ERR_TRUSL = 3117,
+ ERR_TRUSFT1 = 3118, /* first tr "footer" message */
+ ERR_TRUSFTL = 3119, /* last tr "footer" message */
+ ERR_TRSUS1 = 3150, /* first tr -s suboptions usage message */
+ ERR_TRSUSL = 3157,
+ ERR_TDBUSPARM = 3199,
+ ERR_TDBUS1 = 3200, /* first tdb usage message */
+ ERR_TDBUSL = 3214, /* last tdb usage message */
+
+ /* TR 16-bit MSDOS-specific usage messages */
+ ERR_TRUS_DOS_1 = 3300,
+ ERR_TRUS_DOS_L = 3300,
+
+ /* TR 32-bit MSDOS console mode usage messages */
+ ERR_TRUS_DOS32_1 = 3310,
+ ERR_TRUS_DOS32_L = 3312,
+
+ /* TADS/Graphic errors */
+ ERR_GNOFIL = 4001, /* can't find graphics file %s */
+ ERR_GNORM = 4002, /* can't find room %s */
+ ERR_GNOOBJ = 4003, /* can't find hot spot object %s */
+ ERR_GNOICN = 4004 /* can't find icon object %s */
+};
+
+/*
+ * Special error flag - this is returned from execmd() when preparseCmd
+ * returns a command list. This indicates to voc1cmd that it should try
+ * the command over again, using the words in the new list.
+ */
+#define ERR_PREPRSCMDREDO 30000 /* preparseCmd returned a list */
+#define ERR_PREPRSCMDCAN 30001 /* preparseCmd returned 'nil' to cancel */
+
union erradef {
int erraint; // integer argument
char *errastr; // text string argument
@@ -274,6 +582,17 @@ void errlogf(errcxdef *ctx, char *facility, int err);
(errargv(ctx,0,typ1,arg1),errargv(ctx,1,typ2,arg2),\
errargc(ctx,2),errlogn(ctx,e,fac))
+/**
+ * For compatility with old facility-free mechanism, signal with facility "TADS"
+ */
+#define errsig(ctx, err) errsigf(ctx, "TADS", err)
+#define errsig1(c, e, t, a) errsigf1(c,"TADS",e,t,a)
+//#define errsig2(c, e, t1, a1, t2, a2) errsigf2(c,"TADS",e,t1,a1,t2,a2)
+#define errlog(c, e) errlogf(c, "TADS", e)
+#define errlog1(c, e, t, a) errlogf1(c,"TADS",e,t,a)
+#define errlog2(c, e, t1, a1, t2, a2) errlogf2(c,"TADS",e,t1,a1,t2,a2)
+
+#define errsig2(c, e, t1, a1, t2, a2) error("Error occurred")
// get the text of an error
void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
diff --git a/engines/glk/tads/tads2/os.cpp b/engines/glk/tads/tads2/os.cpp
index 248611d..514a912 100644
--- a/engines/glk/tads/tads2/os.cpp
+++ b/engines/glk/tads/tads2/os.cpp
@@ -178,6 +178,42 @@ osfildef *OS::oss_open_stream(char *buffer, glui32 tadsusage, glui32 tbusage,
return *osf;
}
+osfildef *OS::osfoprb(const char *fname, uint typ) {
+ Common::File *f = new Common::File();
+ if (f->open(fname))
+ return f;
+
+ f->close();
+ delete f;
+ return nullptr;
+}
+
+void OS::os_gen_charmap_filename(char *filename, const char *internal_id,
+ const char *argv0) {
+ const char *p;
+ const char *rootname;
+ size_t pathlen;
+
+ // find the path prefix of the original executable filename
+ for (p = rootname = argv0; *p != '\0'; ++p) {
+ if (*p == '/' || *p == '\\' || *p == ':')
+ rootname = p + 1;
+ }
+
+ // copy the path prefix
+ pathlen = rootname - argv0;
+ memcpy(filename, argv0, pathlen);
+
+ // if there's no trailing backslash, add one
+ if (pathlen == 0 || filename[pathlen - 1] != '\\')
+ filename[pathlen++] = '\\';
+
+ // add "win_", plus the character set ID, plus the extension
+ strcpy(filename + pathlen, "win_");
+ strcat(filename + pathlen, internal_id);
+ strcat(filename + pathlen, ".tcp");
+}
+
void OS::oss_put_string_with_hilite(winid_t win, const char *str, size_t len) {
glk_set_window(win);
glk_put_buffer(str, len);
diff --git a/engines/glk/tads/tads2/os.h b/engines/glk/tads/tads2/os.h
index 3c50cb5..ecd0468 100644
--- a/engines/glk/tads/tads2/os.h
+++ b/engines/glk/tads/tads2/os.h
@@ -24,146 +24,13 @@
#define GLK_TADS_TADS2_OS
#include "glk/tads/tads.h"
+#include "glk/tads/tads2/types.h"
namespace Glk {
namespace TADS {
namespace TADS2 {
/**
- * Allocate a memory block
- */
-#define mchalo(CTX, SIZE, COMMENT) ((byte *)new byte[SIZE])
-
-/**
- * Free a memory block
- */
-#define mchfre(PTR) delete[] (byte *)PTR
-
-
-/**
- * The character (or characters) which mark the beginning of a special fileref string.
- * The important thing is that the string be one that is either not allowed in
- * filenames on your platform or is unlikely to be the first part of a filename.
- */
-#define OSS_FILEREF_STRING_PREFIX ":"
-
-/**
- * The character (or characters) which mark the end of a special fileref string.
- * Using this and OSS_FILEREF_STRING_PREFIX, you should be able to come up with
- * something which forms an invalid filename
- */
-#define OSS_FILEREF_STRING_SUFFIX ""
-
-/**
- * Maximum length of status line text
- */
-#define OSS_STATUS_STRING_LEN 80
-
-/**
- * Important note: do not change these values when porting TADS. These
- * values can be used by games, so they must be the same on all platforms.
- */
-enum {
- OS_AFP_OPEN = 1, ///< choose an existing file to open for reading
- OS_AFP_SAVE = 2 ///< choose a filename for saving to a file
-};
-
-/**
- * File types.These type codes are used when opening or creating a file,
- * so that the OS routine can set appropriate file system metadata
- * to describe or find the file type.
- *
- * The type os_filetype_t is defined for documentary purposes; it's
- * always just an int.
- */
-enum os_filetype_t {
- OSFTGAME = 0, ///< a game data file (.gam)
- OSFTSAVE = 1, ///< a saved game (.sav)
- OSFTLOG = 2, ///< a transcript (log) file
- OSFTSWAP = 3, ///< swap file
- OSFTDATA = 4, ///< user data file (used with the TADS fopen() call)
- OSFTCMD = 5, ///< QA command/log file
- OSFTERRS = 6, ///< error message file
- OSFTTEXT = 7, ///< text file - used for source files
- OSFTBIN = 8, ///< binary file of unknown type - resources, etc
- OSFTCMAP = 9, ///< character mapping file
- OSFTPREF = 10, ///< preferences file
- OSFTUNK = 11, ///< unknown - as a filter, matches any file type
- OSFTT3IMG = 12, ///< T3 image file (.t3 - formerly .t3x)
- OSFTT3OBJ = 13, ///< T3 object file (.t3o)
- OSFTT3SYM = 14, ///< T3 symbol export file (.t3s)
- OSFTT3SAV = 15 ///< T3 saved state file (.t3v)
-};
-
-/**
- * Constants for os_getc() when returning commands. When used for command line
- * editing, special keys (arrows, END, etc.) should cause os_getc() to return 0,
- * and return the appropriate CMD_ value on the NEXT call. Hence, os_getc() must
- * keep the appropriate information around statically for the next call when a
- * command key is issued.
- *
- * The comments indicate which CMD_xxx codes are "translated" codes and which are
- * "raw"; the difference is that, when a particular keystroke could be interpreted
- * as two different CMD_xxx codes, one translated and the other raw, os_getc()
- * should always return the translated version of the key, and os_getc_raw()
- * should return the raw version.
- */
-enum KeyCmd {
- CMD_UP = 1, ///< move up/up arrow (translated)
- CMD_DOWN = 2, ///< move down/down arrow (translated)
- CMD_RIGHT = 3, ///< move right/right arrow (translated)
- CMD_LEFT = 4, ///< move left/left arrow (translated)
- CMD_END = 5, ///< move cursor to end of line (translated)
- CMD_HOME = 6, ///< move cursor to start of line (translated)
- CMD_DEOL = 7, ///< delete to end of line (translated)
- CMD_KILL = 8, ///< delete entire line (translated)
- CMD_DEL = 9, ///< delete current character (translated)
- CMD_SCR = 10, ///< toggle scrollback mode (translated)
- CMD_PGUP = 11, ///< page up (translated)
- CMD_PGDN = 12, ///< page down (translated)
- CMD_TOP = 13, ///< top of file (translated)
- CMD_BOT = 14, ///< bottom of file (translated)
- CMD_F1 = 15, ///< function key F1 (raw)
- CMD_F2 = 16, ///< function key F2 (raw)
- CMD_F3 = 17, ///< function key F3 (raw)
- CMD_F4 = 18, ///< function key F4 (raw)
- CMD_F5 = 19, ///< function key F5 (raw)
- CMD_F6 = 20, ///< function key F6 (raw)
- CMD_F7 = 21, ///< function key F7 (raw)
- CMD_F8 = 22, ///< function key F8 (raw)
- CMD_F9 = 23, ///< function key F9 (raw)
- CMD_F10 = 24, ///< function key F10 (raw)
- CMD_CHOME = 25, ///< control-home (raw)
- CMD_TAB = 26, ///< tab (translated)
- CMD_SF2 = 27, ///< shift-F2 (raw)
- ///< not used (obsolete) - 28
- CMD_WORD_LEFT = 29, ///< word left (ctrl-left on dos) (translated)
- CMD_WORD_RIGHT = 30, ///< word right (ctrl-right on dos) (translated)
- CMD_WORDKILL = 31, ///< delete word right (translated)
- CMD_EOF = 32, ///< end-of-file (raw)
- CMD_BREAK = 33, ///< break (Ctrl-C or local equivalent) (translated)
- CMD_INS = 34, ///< insert key (raw)
-
- /**
- * ALT-keys - add alphabetical code to CMD_ALT: ALT-A == CMD_ALT + 0,
- * ALT-B == CMD_ALT + 1, ALT-C == CMD_ALT + 2, etc
- *
- * These keys are all raw (untranslated).
- */
- CMD_ALT = 128 ///< start of ALT keys
-};
-
-/**
- * Status mode codes
- */
-enum StatusMode {
- OSS_STATUS_MODE_STORY = 0,
- OSS_STATUS_MODE_STATUS = 1
-};
-
-typedef Common::SeekableReadStream osfildef;
-
-/**
* Operating system compatibility layer
*/
class OS : public TADS {
@@ -262,6 +129,27 @@ protected:
*/
const char *os_get_root_name(const char *buf) const { return buf; }
+ /**
+ * Open a file for access
+ */
+ osfildef *osfoprb(const char *fname, uint typ = 0);
+
+ /**
+ * Receive notification that a character mapping file has been loaded. We
+ * don't need to do anything with this information, since we we're relying
+ * on the Glk layer and ScummVM backend to handle all that
+ */
+ void os_advise_load_charmap(const char *id, const char *ldesc, const char *sysinfo) {
+ // No implementation needed
+ }
+
+ /**
+ * Generate a filename for a character mapping table. On Windows, the
+ * filename is always simply "win" plus the internal ID plus ".tcp".
+ */
+ void os_gen_charmap_filename(char *filename, const char *internal_id,
+ const char *argv0);
+
/**@}*/
/**
diff --git a/engines/glk/tads/tads2/regex.cpp b/engines/glk/tads/tads2/regex.cpp
new file mode 100644
index 0000000..f6a009a
--- /dev/null
+++ b/engines/glk/tads/tads2/regex.cpp
@@ -0,0 +1,1276 @@
+/* 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.
+ *
+ */
+
+/*
+Regular Expression Parser and Recognizer for TADS
+Function
+ Parses and recognizes regular expressions
+Notes
+ Regular expression syntax:
+
+ abc|def either abc or def
+ (abc) abc
+ abc+ abc, abcc, abccc, ...
+ abc* ab, abc, abcc, ...
+ abc? ab or abc
+ . any single character
+ abc$ abc at the end of the line
+ ^abc abc at the beginning of the line
+ %^abc literally ^abc
+ [abcx-z] matches a, b, c, x, y, or z
+ [^abcx-z] matches any character except a, b, c, x, y, or z
+ [^]-q] matches any character except ], -, or q
+
+ Note that using ']' or '-' in a character range expression requires
+ special ordering. If ']' is to be used, it must be the first character
+ after the '^', if present, within the brackets. If '-' is to be used,
+ it must be the first character after the '^' and/or ']', if present.
+
+ '%' is used to escape the special characters: | . ( ) * ? + ^ $ % [
+ (We use '%' rather than a backslash because it's less trouble to
+ enter in a TADS string -- a backslash needs to be quoted with another
+ backslash, which is error-prone and hard to read. '%' doesn't need
+ any special quoting in a TADS string, which makes it a lot more
+ readable.)
+
+ In addition, '%' is used to introduce additional special sequences:
+
+ %1 text matching first parenthesized expression
+ %9 text matching ninth parenthesized experssion
+ %< matches at the beginning of a word only
+ %> matches at the end of a word only
+ %w matches any word character
+ %W matches any non-word character
+ %b matches at any word boundary (beginning or end of word)
+ %B matches except at a word boundary
+
+ For the word matching sequences, a word is any sequence of letters and
+ numbers.
+*/
+
+#include "engines/glk/tads/tads2/regex.h"
+#include "engines/glk/tads/tads2/ler.h"
+#include "engines/glk/tads/tads2/os.h"
+//#include "engines/glk/tads/tads2/std.h"
+#//include "engines/glk/tads/tads2/ler.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+/**
+ * A "machine" (i.e., a finite state automaton) is a set of state
+ * transition tuples. A tuple has three elements: the state ID, the ID
+ * of the state that we transition to, and the condition for the
+ * transition. The condition is simply the character that we must match
+ * to make the transition, or a special distinguished symbol "epsilon,"
+ * which refers to a transition with no input character consumed.
+ *
+ * The primitive elements of our machines guarantee that we never have
+ * more than two transitions out of a particular state, so we can
+ * denormalize the representation of a state by storing the two possible
+ * tuples for that state in a single combined tuple. This has the
+ * performance advantage that we can use the state ID as an index into
+ * an array of state tuples.
+ *
+ * A particular machine always has a single initial and single final
+ * (successful) state, so we can define a machine by its initial and
+ * final state ID's.
+ */
+enum {
+ // the special symbol value for "epsilon"
+ RE_EPSILON = '\001',
+
+ // the special symbol value for a wildcard character
+ RE_WILDCARD = '\002',
+
+ // special symbol values for beginning and end of text
+ RE_TEXT_BEGIN = '\003',
+ RE_TEXT_END = '\004',
+
+ // special symbol values for start and end of a word
+ RE_WORD_BEGIN = '\005',
+ RE_WORD_END = '\006',
+
+ // special symbols for word-char and non-word-char
+ RE_WORD_CHAR = '\007',
+ RE_NON_WORD_CHAR = '\010',
+
+ // special symbols for word-boundary and non-word-boundary
+ RE_WORD_BOUNDARY = '\011',
+ RE_NON_WORD_BOUNDARY = '\012',
+
+ // special symbol for a character range/exclusion range
+ RE_RANGE = '\013',
+ RE_RANGE_EXCL = '\014',
+
+ // a range of special symbol values for group matchers
+ RE_GROUP_MATCH_0 = '\015',
+ RE_GROUP_MATCH_9 = (RE_GROUP_MATCH_0 + 9)
+};
+
+re_context::re_context(errcxdef *errctx) {
+ // save the error context
+ _errctx = errctx;
+
+ // clear states
+ _next_state = RE_STATE_FIRST_VALID;
+
+ // clear groups
+ _cur_group = 0;
+
+ // no string buffer yet
+ _strbuf = 0;
+}
+
+re_context::~re_context() {
+ // reset state
+ reset();
+
+ // if we allocated a string buffer, delete it
+ if (_strbuf != 0) {
+ mchfre(_strbuf);
+ _strbuf = nullptr;
+ }
+}
+
+void re_context::reset() {
+ int i;
+
+ // delete any range tables we've allocated
+ for (i = 0 ; i < _next_state ; ++i) {
+ if (_tuple_arr[i].char_range != 0) {
+ mchfre(_tuple_arr[i].char_range);
+ _tuple_arr[i].char_range = 0;
+ }
+ }
+
+ // clear states
+ _next_state = RE_STATE_FIRST_VALID;
+
+ // clear groups
+ _cur_group = 0;
+}
+
+re_state_id re_context::alloc_state() {
+ // If we don't have enough room for another state, expand the array
+ if (_next_state >= (int)_tuple_arr.size()) {
+ // bump the size by a bit
+ _tuple_arr.resize(_tuple_arr.size() + 100);
+ }
+
+ // initialize the next state
+ _tuple_arr[_next_state].next_state_1 = RE_STATE_INVALID;
+ _tuple_arr[_next_state].next_state_2 = RE_STATE_INVALID;
+ _tuple_arr[_next_state].ch = RE_EPSILON;
+ _tuple_arr[_next_state].flags = 0;
+ _tuple_arr[_next_state].char_range = 0;
+
+ // return the new state's ID
+ return _next_state++;
+}
+
+void re_context::set_trans(re_state_id id, re_state_id dest_id, char ch) {
+ re_tuple *tuple;
+
+ /*
+ * get the tuple containing the transitions for this state ID - the
+ * state ID is the index of the state's transition tuple in the array
+ */
+ tuple = &_tuple_arr[id];
+
+ /*
+ * If the first state pointer hasn't been set yet, set it to the new
+ * destination. Otherwise, set the second state pointer.
+ *
+ * Only set the character on setting the first state. When setting
+ * the second state, we must assume that the character for the state
+ * has already been set, since any given state can have only one
+ * character setting.
+ */
+ if (tuple->next_state_1 == RE_STATE_INVALID) {
+ /*
+ * set the character ID, unless the state has been marked with a
+ * special flag which indicates that the character value has
+ * another meaning (in particular, a group marker)
+ */
+ if (!(tuple->flags & (RE_STATE_GROUP_BEGIN | RE_STATE_GROUP_END)))
+ tuple->ch = ch;
+
+ // set the first transition
+ tuple->next_state_1 = dest_id;
+ } else {
+ // set only the second transition state - don't set the character
+ tuple->next_state_2 = dest_id;
+ }
+}
+
+void re_context::init_machine(re_machine *machine) {
+ machine->init = alloc_state();
+ machine->final = alloc_state();
+}
+
+void re_context::build_char(re_machine *machine, char ch) {
+ // initialize our new machine
+ init_machine(machine);
+
+ // allocate a transition tuple for the new state
+ set_trans(machine->init, machine->final, ch);
+}
+
+void re_context::build_char_range(re_machine *machine, unsigned char *range, int exclusion) {
+ unsigned char *range_copy;
+
+ // initialize our new machine
+ init_machine(machine);
+
+ // allocate a transition table for the new state
+ set_trans(machine->init, machine->final, (char)(exclusion ? RE_RANGE_EXCL : RE_RANGE));
+
+ // allocate a copy of the range bit vector
+ range_copy = (unsigned char *)mchalo(_errctx, 32, "regex range");
+
+ // copy the caller's range
+ memcpy(range_copy, range, 32);
+
+ // store it in the tuple
+ _tuple_arr[machine->init].char_range = range_copy;
+}
+
+void re_context::build_group_matcher(re_machine *machine, int group_num) {
+ // initialize our new machine
+ init_machine(machine);
+
+ /*
+ * Allocate a transition tuple for the new state, using the group ID
+ * as the character code. Store the special code for a group
+ * recognizer rather than the normal literal character code.
+ */
+ set_trans(machine->init, machine->final, (char)(group_num + RE_GROUP_MATCH_0));
+}
+
+void re_context::build_concat(re_machine *new_machine, re_machine *lhs, re_machine *rhs) {
+ // initialize the new machine
+ init_machine(new_machine);
+
+ /*
+ * Set up an epsilon transition from the new machine's initial state
+ * to the first submachine's initial state
+ */
+ set_trans(new_machine->init, lhs->init, RE_EPSILON);
+
+ /*
+ * Set up an epsilon transition from the first submachine's final
+ * state to the second submachine's initial state
+ */
+ set_trans(lhs->final, rhs->init, RE_EPSILON);
+
+ /*
+ * Set up an epsilon transition from the second submachine's final
+ * state to our new machine's final state
+ */
+ set_trans(rhs->final, new_machine->final, RE_EPSILON);
+}
+
+void re_context::build_group(re_machine *new_machine, re_machine *sub_machine, int group_id) {
+ // initialize the container machine
+ init_machine(new_machine);
+
+ /*
+ * set up an epsilon transition from the new machine's initial state
+ * into the initial state of the group, and another transition from
+ * the group's final state into the container's final state
+ */
+ set_trans(new_machine->init, sub_machine->init, RE_EPSILON);
+ set_trans(sub_machine->final, new_machine->final, RE_EPSILON);
+
+ // Mark the initial and final states of the group machine as being group markers
+ _tuple_arr[new_machine->init].flags |= RE_STATE_GROUP_BEGIN;
+ _tuple_arr[new_machine->final].flags |= RE_STATE_GROUP_END;
+
+ // store the group ID in the 'ch' member of the start and end states
+ _tuple_arr[new_machine->init].ch = group_id;
+ _tuple_arr[new_machine->final].ch = group_id;
+}
+
+void re_context::build_alter(re_machine *new_machine, re_machine *lhs, re_machine *rhs) {
+ // initialize the new machine
+ init_machine(new_machine);
+
+ /*
+ * Set up an epsilon transition from our new machine's initial state
+ * to the initial state of each submachine
+ */
+ set_trans(new_machine->init, lhs->init, RE_EPSILON);
+ set_trans(new_machine->init, rhs->init, RE_EPSILON);
+
+ /*
+ * Set up an epsilon transition from the final state of each
+ * submachine to our final state
+ */
+ set_trans(lhs->final, new_machine->final, RE_EPSILON);
+ set_trans(rhs->final, new_machine->final, RE_EPSILON);
+}
+
+void re_context::build_closure(re_machine *new_machine, re_machine *sub, char specifier) {
+ // initialize the new machine
+ init_machine(new_machine);
+
+ /*
+ * Set up an epsilon transition from our initial state to the submachine's initial
+ * state, and from the submachine's final state to our final state
+ */
+ set_trans(new_machine->init, sub->init, RE_EPSILON);
+ set_trans(sub->final, new_machine->final, RE_EPSILON);
+
+ /*
+ * If this is an unbounded closure ('*' or '+', but not '?'), set up
+ * the loop transition that takes us from the new machine's final
+ * state back to its initial state. We don't do this on the
+ * zero-or-one closure, because we can only match the expression
+ * once.
+ */
+ if (specifier != '?')
+ set_trans(sub->final, sub->init, RE_EPSILON);
+
+ /*
+ * If this is a zero-or-one closure or a zero-or-more closure, set
+ * up an epsilon transition from our initial state to our final
+ * state, since we can skip the entire subexpression. We don't do
+ * this on the one-or-more closure, because we can't skip the
+ * subexpression in this case.
+ */
+ if (specifier != '+')
+ set_trans(new_machine->init, new_machine->final, RE_EPSILON);
+}
+
+void re_context::concat_onto(re_machine *dest, re_machine *rhs) {
+ // check for a null destination machine
+ if (dest->isNull()) {
+ /*
+ * the first machine is null - simply copy the second machine
+ * onto the first unchanged
+ */
+ *dest = *rhs;
+ } else {
+ re_machine new_machine;
+
+ // build the concatenated machine
+ build_concat(&new_machine, dest, rhs);
+
+ // copy the concatenated machine onto the first machine
+ *dest = new_machine;
+ }
+}
+
+void re_context::alternate_onto(re_machine *dest, re_machine *rhs) {
+ // check to see if the first machine is null
+ if (dest->isNull()) {
+ /*
+ * the first machine is null - simply copy the second machine
+ * onto the first
+ */
+ *dest = *rhs;
+ } else {
+ /*
+ * if the second machine is null, don't do anything; otherwise,
+ * build the alternation
+ */
+ if (!rhs->isNull()) {
+ re_machine new_machine;
+
+ // build the alternation
+ build_alter(&new_machine, dest, rhs);
+
+ // replace the first machine with the alternation
+ *dest = new_machine;
+ }
+ }
+}
+
+/**
+ * Set a bit in a bit vector.
+ */
+#define re_set_bit(set, bit) \
+ (((unsigned char *)(set))[(bit) >> 3] |= (1 << ((bit) & 7)))
+
+/**
+ * Test a bit in a bit vector
+ */
+#define re_is_bit_set(set, bit) \
+ ((((unsigned char *)(set))[(bit) >> 3] & (1 << ((bit) & 7))) != 0)
+
+re_status_t re_context::compile(const char *expr, size_t exprlen, re_machine *result_machine) {
+ re_machine cur_machine;
+ re_machine alter_machine;
+ re_machine new_machine;
+ size_t group_stack_level;
+ struct {
+ re_machine old_cur;
+ re_machine old_alter;
+ int group_id;
+ } group_stack[50];
+
+ // reset everything
+ reset();
+
+ // start out with no current machine and no alternate machine
+ cur_machine.build_null_machine();
+ alter_machine.build_null_machine();
+
+ // nothing on the stack yet
+ group_stack_level = 0;
+
+ // loop until we run out of expression to parse
+ for (; exprlen != 0 ; ++expr, --exprlen) {
+ switch(*expr) {
+ case '^':
+ /*
+ * beginning of line - if we're not at the beginning of the
+ * current expression (i.e., we already have some
+ * concatentations accumulated), treat it as an ordinary
+ * character
+ */
+ if (!cur_machine.isNull())
+ goto normal_char;
+
+ // build a new start-of-text recognizer
+ build_char(&new_machine, RE_TEXT_BEGIN);
+
+ /*
+ * concatenate it onto the string - note that this can't
+ * have any postfix operators
+ */
+ concat_onto(&cur_machine, &new_machine);
+ break;
+
+ case '$':
+ /*
+ * End of line specifier - if there's anything left after
+ * the '$' other than a close parens or alternation
+ * specifier, great it as a normal character
+ */
+ if (exprlen > 1
+ && (*(expr+1) != ')' && *(expr+1) != '|'))
+ goto normal_char;
+
+ // build a new end-of-text recognizer
+ build_char(&new_machine, RE_TEXT_END);
+
+ /*
+ * concatenate it onto the string - note that this can't
+ * have any postfix operators
+ */
+ concat_onto(&cur_machine, &new_machine);
+ break;
+
+ case '(':
+ /*
+ * Add a nesting level. Push the current machine and
+ * alternate machines onto the group stack, and clear
+ * everything out for the new group.
+ */
+ if (group_stack_level > sizeof(group_stack)/sizeof(group_stack[0])) {
+ /* we cannot proceed - return an error */
+ return RE_STATUS_GROUP_NESTING_TOO_DEEP;
+ }
+
+ // save the current state on the stack
+ group_stack[group_stack_level].old_cur = cur_machine;
+ group_stack[group_stack_level].old_alter = alter_machine;
+
+ /*
+ * Assign the group a group ID - groups are numbered in
+ * order of their opening (left) parentheses, so we want to
+ * assign a group number now. We won't actually need to
+ * know the group number until we get to the matching close
+ * paren, but we need to assign it now, so store it in the
+ * group stack.
+ */
+ group_stack[group_stack_level].group_id = _cur_group;
+
+ // consume the group number
+ _cur_group++;
+
+ // push the level
+ ++group_stack_level;
+
+ // start the new group with empty machines
+ cur_machine.build_null_machine();
+ alter_machine.build_null_machine();
+ break;
+
+ case ')':
+ // if there's nothing on the stack, ignore this
+ if (group_stack_level == 0)
+ break;
+
+ // take a level off the stack
+ --group_stack_level;
+
+ /*
+ * Remove a nesting level. If we have a pending alternate
+ * expression, build the alternation expression. This will
+ * leave the entire group expression in alter_machine,
+ * regardless of whether an alternation was in progress or
+ * not.
+ */
+ alternate_onto(&alter_machine, &cur_machine);
+
+ /*
+ * Create a group machine that encloses the group and marks
+ * it with a group number. We assigned the group number
+ * when we parsed the open paren, so read that group number
+ * from the stack.
+ *
+ * Note that this will leave 'new_machine' with the entire
+ * group machine.
+ */
+ build_group(&new_machine, &alter_machine,
+ group_stack[group_stack_level].group_id);
+
+ /*
+ * Pop the stack - restore the alternation and current
+ * machines that were in progress before the group started.
+ */
+ cur_machine = group_stack[group_stack_level].old_cur;
+ alter_machine = group_stack[group_stack_level].old_alter;
+
+ /*
+ * Check the group expression (in new_machine) for postfix
+ * expressions
+ */
+ goto apply_postfix;
+
+ case '|':
+ /*
+ * Start a new alternation. This ends the current
+ * alternation; if we have a previous pending alternate,
+ * build an alternation machine out of the previous
+ * alternate and the current machine and move that to the
+ * alternate; otherwise, simply move the current machine to
+ * the pending alternate.
+ */
+ alternate_onto(&alter_machine, &cur_machine);
+
+ /*
+ * the alternation starts out with a blank slate, so null
+ * out the current machine
+ */
+ cur_machine.build_null_machine();
+ break;
+
+ case '%':
+ // quoted character - skip the quote mark and see what we have
+ ++expr;
+ --exprlen;
+
+ // check to see if we're at the end of the expression
+ if (exprlen == 0) {
+ /*
+ * end of the string - ignore it, but undo the extra
+ * increment of the expression index so that we exit the
+ * enclosing loop properly
+ */
+ --expr;
+ ++exprlen;
+ break;
+ }
+
+ // see what we have
+ switch(*expr) {
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ // group match - build a new literal group recognizer
+ build_group_matcher(&new_machine, (int)(*expr - '1'));
+
+ // apply any postfix expression to the group recognizer
+ goto apply_postfix;
+
+ case '<':
+ // build a beginning-of-word recognizer
+ build_char(&new_machine, RE_WORD_BEGIN);
+
+ // it can't be postfixed - just concatenate it
+ concat_onto(&cur_machine, &new_machine);
+ break;
+
+ case '>':
+ // build an end-of-word recognizer */
+ build_char(&new_machine, RE_WORD_END);
+
+ // it can't be postfixed - just concatenate it
+ concat_onto(&cur_machine, &new_machine);
+ break;
+
+ case 'w':
+ // word character
+ build_char(&new_machine, RE_WORD_CHAR);
+ goto apply_postfix;
+
+ case 'W':
+ // non-word character
+ build_char(&new_machine, RE_NON_WORD_CHAR);
+ goto apply_postfix;
+
+ case 'b':
+ // word boundary
+ build_char(&new_machine, RE_WORD_BOUNDARY);
+
+ // it can't be postfixed
+ concat_onto(&cur_machine, &new_machine);
+ break;
+
+ case 'B':
+ // not a word boundary
+ build_char(&new_machine, RE_NON_WORD_BOUNDARY);
+
+ // it can't be postfixed
+ concat_onto(&cur_machine, &new_machine);
+ break;
+
+ default:
+ // build a new literal character recognizer
+ build_char(&new_machine, *expr);
+
+ // apply any postfix expression to the character
+ goto apply_postfix;
+ }
+ break;
+
+ case '.':
+ /*
+ * wildcard character - build a single character recognizer
+ * for the special wildcard symbol, then go check it for a
+ * postfix operator
+ */
+ build_char(&new_machine, RE_WILDCARD);
+ goto apply_postfix;
+ break;
+
+ case '[': {
+ // range expression
+ int is_exclusive = false;
+ unsigned char set[32];
+
+ // clear out the set of characters in the range
+ memset(set, 0, sizeof(set));
+
+ // first, skip the open bracket
+ ++expr;
+ --exprlen;
+
+ // check to see if starts with the exclusion character
+ if (exprlen != 0 && *expr == '^') {
+ // skip the exclusion specifier
+ ++expr;
+ --exprlen;
+
+ // note it
+ is_exclusive = true;
+ }
+
+ // if the first character is a ']', include it in the range
+ if (exprlen != 0 && *expr == ']') {
+ re_set_bit(set, (int)']');
+ ++expr;
+ --exprlen;
+ }
+
+ // if the next character is a '-', include it in the range
+ if (exprlen != 0 && *expr == '-') {
+ re_set_bit(set, (int)'-');
+ ++expr;
+ --exprlen;
+ }
+
+ // scan the character set
+ while (exprlen != 0 && *expr != ']') {
+ int ch;
+
+ // note this character
+ ch = (int)(unsigned char)*expr;
+
+ // set it
+ re_set_bit(set, ch);
+
+ // skip this character of the expression
+ ++expr;
+ --exprlen;
+
+ // check for a range
+ if (exprlen != 0 && *expr == '-') {
+ int ch2;
+
+ // skip the '-'
+ ++expr;
+ --exprlen;
+ if (exprlen != 0) {
+ // get the other end of the range
+ ch2 = (int)(unsigned char)*expr;
+
+ // skip the second character
+ ++expr;
+ --exprlen;
+
+ // if the range is reversed, swap it
+ if (ch > ch2)
+ SWAP(ch, ch2);
+
+ // fill in the range
+ for ( ; ch <= ch2 ; ++ch)
+ re_set_bit(set, ch);
+ }
+ }
+ }
+
+ // create a character range machine
+ build_char_range(&new_machine, set, is_exclusive);
+
+ // apply any postfix operator
+ goto apply_postfix;
+ break;
+ }
+
+ default:
+ normal_char:
+ /*
+ * it's an ordinary character - build a single character
+ * recognizer machine, and then concatenate it onto any
+ * existing machine
+ */
+ build_char(&new_machine, *expr);
+
+ apply_postfix:
+ /*
+ * Check for a postfix operator, and apply it to the machine
+ * in 'new_machine' if present. In any case, concatenate
+ * the 'new_machine' (modified by a postix operator or not)
+ * to the current machien.
+ */
+ if (exprlen > 1) {
+ switch(*(expr+1)) {
+ case '*':
+ case '+':
+ case '?':
+ /*
+ * We have a postfix closure operator. Build a new
+ * closure machine out of 'new_machine'.
+ */
+ {
+ re_machine closure_machine;
+
+ // move onto the closure operator
+ ++expr;
+ --exprlen;
+
+ // build the closure machine
+ build_closure(&closure_machine, &new_machine, *expr);
+
+ // replace the original machine with the closure
+ new_machine = closure_machine;
+
+ /*
+ * skip any redundant closure symbols, keeping
+ * only the first one we saw
+ */
+ while (exprlen > 1 && (*(expr+1) == '?'
+ || *(expr+1) == '+'
+ || *(expr+1) == '*')) {
+ ++expr;
+ --exprlen;
+ }
+ }
+ break;
+
+ default:
+ /* no postfix operator */
+ break;
+ }
+ }
+
+ /*
+ * Concatenate the new machine onto the current machine
+ * under construction.
+ */
+ concat_onto(&cur_machine, &new_machine);
+ break;
+ }
+ }
+
+ // complete any pending alternation
+ alternate_onto(&alter_machine, &cur_machine);
+
+ // store the resulting machine in the caller's machine descriptor
+ *result_machine = alter_machine;
+
+ // no errors encountered
+ return RE_STATUS_SUCCESS;
+}
+
+void re_context::note_group(re_group_register *regs, re_state_id id, const char *p) {
+ int group_index;
+
+ /*
+ * Check to see if this is a valid state and it's a group marker -
+ * if not, there's nothing to do
+ */
+ if (id == RE_STATE_INVALID
+ || !(_tuple_arr[id].flags
+ & (RE_STATE_GROUP_BEGIN | RE_STATE_GROUP_END))
+ || (group_index = (int)_tuple_arr[id].ch) >= RE_GROUP_REG_CNT)
+ return;
+
+ // It's a valid group marker - note the appropriate register value
+ if ((_tuple_arr[id].flags & RE_STATE_GROUP_BEGIN) != 0)
+ regs[group_index].start_ofs = p;
+ else
+ regs[group_index].end_ofs = p;
+}
+
+bool re_context::is_word_char(char c) const {
+ return Common::isAlnum(c);
+}
+
+int re_context::match(const char *entire_str, const char *str, size_t origlen,
+ const re_machine *machine, re_group_register *regs) {
+ re_state_id cur_state;
+ const char *p;
+ size_t curlen;
+
+ // start at the machine's initial state
+ cur_state = machine->init;
+
+ // start at the beginning of the string
+ p = str;
+ curlen = origlen;
+
+ // note any group involved in the initial state
+ note_group(regs, cur_state, p);
+
+ /*
+ * if we're starting in the final state, immediately return success
+ * with a zero-length match
+ */
+ if (cur_state == machine->final) {
+ // return success with a zero-length match
+ return 0;
+ }
+
+ // run the machine
+ for (;;) {
+ re_tuple *tuple;
+
+ // get the tuple for this state
+ tuple = &_tuple_arr[cur_state];
+
+ // if this is a group state, adjust the group registers
+ note_group(regs, cur_state, p);
+
+ // see what kind of state we're in
+ if (!(tuple->flags & (RE_STATE_GROUP_BEGIN | RE_STATE_GROUP_END))
+ && tuple->ch != RE_EPSILON) {
+ /*
+ * This is a character or group recognizer state. If we
+ * match the character or group, continue on to the next
+ * state; otherwise, return failure.
+ */
+ switch(tuple->ch) {
+ case RE_GROUP_MATCH_0:
+ case RE_GROUP_MATCH_0 + 1:
+ case RE_GROUP_MATCH_0 + 2:
+ case RE_GROUP_MATCH_0 + 3:
+ case RE_GROUP_MATCH_0 + 4:
+ case RE_GROUP_MATCH_0 + 5:
+ case RE_GROUP_MATCH_0 + 6:
+ case RE_GROUP_MATCH_0 + 7:
+ case RE_GROUP_MATCH_0 + 8:
+ case RE_GROUP_MATCH_0 + 9: {
+ int group_num;
+ re_group_register *group_reg;
+ size_t reg_len;
+
+ // it's a group - get the group number
+ group_num = tuple->ch - RE_GROUP_MATCH_0;
+ group_reg = ®s[group_num];
+
+ /*
+ * if this register isn't defined, there's nothing
+ * to match, so fail
+ */
+ if (group_reg->start_ofs == 0 || group_reg->end_ofs == 0)
+ return -1;
+
+ // calculate the length of the register value
+ reg_len = group_reg->end_ofs - group_reg->start_ofs;
+
+ // if we don't have enough left to match, it fails
+ if (curlen < reg_len)
+ return -1;
+
+ // if the string doesn't match exactly, we fail
+ if (memcmp(p, group_reg->start_ofs, reg_len) != 0)
+ return -1;
+
+ /*
+ * It matches exactly - skip the entire length of
+ * the register in the source string
+ */
+ p += reg_len;
+ curlen -= reg_len;
+ break;
+ }
+
+ case RE_TEXT_BEGIN:
+ /*
+ * Match only the exact beginning of the string - if
+ * we're anywhere else, this isn't a match. If this
+ * succeeds, we don't skip any characters.
+ */
+ if (p != entire_str)
+ return -1;
+ break;
+
+ case RE_TEXT_END:
+ /*
+ * Match only the exact end of the string - if we're
+ * anywhere else, this isn't a match. Don't skip any
+ * characters on success.
+ */
+ if (curlen != 0)
+ return -1;
+ break;
+
+ case RE_WORD_BEGIN:
+ /*
+ * if the previous character is a word character, we're
+ * not at the beginning of a word
+ */
+ if (p != entire_str && is_word_char(*(p - 1)))
+ return -1;
+
+ /*
+ * if we're at the end of the string, or the current
+ * character isn't the start of a word, we're not at the
+ * beginning of a word
+ */
+ if (curlen == 0 || !is_word_char(*p))
+ return -1;
+ break;
+
+ case RE_WORD_END:
+ /*
+ * if the current character is a word character, we're not
+ * at the end of a word
+ */
+ if (curlen != 0 && is_word_char(*p))
+ return -1;
+
+ /*
+ * if we're at the beginning of the string, or the
+ * previous character is not a word character, we're not
+ * at the end of a word
+ */
+ if (p == entire_str || !is_word_char(*(p - 1)))
+ return -1;
+ break;
+
+ case RE_WORD_CHAR:
+ /* if it's not a word character, it's a failure */
+ if (curlen == 0 || !is_word_char(*p))
+ return -1;
+
+ /* skip this character of input */
+ ++p;
+ --curlen;
+ break;
+
+ case RE_NON_WORD_CHAR:
+ /* if it's a word character, it's a failure */
+ if (curlen == 0 || is_word_char(*p))
+ return -1;
+
+ /* skip the input */
+ ++p;
+ --curlen;
+ break;
+
+ case RE_WORD_BOUNDARY:
+ case RE_NON_WORD_BOUNDARY:
+ {
+ int prev_is_word;
+ int next_is_word;
+ int boundary;
+
+ /*
+ * Determine if the previous character is a word
+ * character -- if we're at the beginning of the
+ * string, it's obviously not, otherwise check its
+ * classification
+ */
+ prev_is_word = (p != entire_str
+ && is_word_char(*(p - 1)));
+
+ /* make the same check for the current character */
+ next_is_word = (curlen != 0
+ && is_word_char(*p));
+
+ /*
+ * Determine if this is a boundary - it is if the
+ * two states are different
+ */
+ boundary = ((prev_is_word != 0) ^ (next_is_word != 0));
+
+ /*
+ * make sure it matches what was desired, and return
+ * failure if not
+ */
+ if ((tuple->ch == RE_WORD_BOUNDARY && !boundary)
+ || (tuple->ch == RE_NON_WORD_BOUNDARY && boundary))
+ return -1;
+ }
+ break;
+
+ case RE_WILDCARD:
+ // make sure we have a character to match
+ if (curlen == 0)
+ return -1;
+
+ // skip this character
+ ++p;
+ --curlen;
+ break;
+
+ case RE_RANGE:
+ case RE_RANGE_EXCL: {
+ int match;
+
+ // make sure we have a character to match
+ if (curlen == 0)
+ return -1;
+
+ // see if we match
+ match = re_is_bit_set(tuple->char_range,
+ (int)(unsigned char)*p);
+
+ // make sure we got what we wanted
+ if ((tuple->ch == RE_RANGE && !match)
+ || (tuple->ch == RE_RANGE_EXCL && match))
+ return -1;
+
+ // skip this character of the input
+ ++p;
+ --curlen;
+ break;
+ }
+
+ default:
+ // make sure we have an exact match
+ if (curlen == 0 || tuple->ch != *p)
+ return -1;
+
+ // skip this character of the input
+ ++p;
+ --curlen;
+ break;
+ }
+
+ /*
+ * if we got this far, we were successful - move on to the
+ * next state
+ */
+ cur_state = tuple->next_state_1;
+ } else if (tuple->next_state_2 == RE_STATE_INVALID) {
+ /*
+ * We have only one transition, so this state is entirely
+ * deterministic. Simply move on to the next state.
+ */
+ cur_state = tuple->next_state_1;
+ } else {
+ re_machine sub_machine;
+ re_group_register regs1[RE_GROUP_REG_CNT];
+ re_group_register regs2[RE_GROUP_REG_CNT];
+ int ret1;
+ int ret2;
+
+ /*
+ * This state has two possible transitions, and we don't
+ * know which one to take. So, try both, see which one
+ * works better, and return the result. Try the first
+ * transition first. Note that each separate attempt must
+ * use a separate copy of the registers.
+ */
+ memcpy(regs1, regs, sizeof(regs1));
+ sub_machine.init = tuple->next_state_1;
+ sub_machine.final = machine->final;
+ ret1 = match(entire_str, p, curlen, &sub_machine, regs1);
+
+ /*
+ * Now try the second transition
+ */
+ memcpy(regs2, regs, sizeof(regs2));
+ sub_machine.init = tuple->next_state_2;
+ sub_machine.final = machine->final;
+ ret2 = match(entire_str, p, curlen, &sub_machine, regs2);
+
+ /*
+ * If they both failed, the whole thing failed. Otherwise,
+ * return the longer of the two, plus the length we
+ * ourselves matched previously. Note that we return the
+ * register set from the winning match.
+ */
+ if (ret1 < 0 && ret2 < 0) {
+ // they both failed
+ return -1;
+ } else if (ret1 > ret2) {
+ // use the first register set and result length
+ memcpy(regs, regs1, sizeof(regs1));
+ return ret1 + (p - str);
+ } else {
+ // use the second register set and result length
+ memcpy(regs, regs2, sizeof(regs2));
+ return ret2 + (p - str);
+ }
+ }
+
+ // If we're in the final state, return success
+ if (cur_state == machine->final) {
+ // finish off any group involved in the final state
+ note_group(regs, cur_state, p);
+
+ // return the length we matched
+ return p - str;
+ }
+ }
+}
+
+int re_context::search(const char *str, size_t len, const re_machine *machine,
+ re_group_register *regs, int *result_len) {
+ int ofs;
+
+ /*
+ * Starting at the first character in the string, search for the
+ * pattern at each subsequent character until we either find the
+ * pattern or run out of string to test.
+ */
+ for (ofs = 0 ; ofs < (int)len ; ++ofs) {
+ int matchlen;
+
+ // check for a match
+ matchlen = match(str, str + ofs, len - ofs, machine, regs);
+ if (matchlen >= 0) {
+ // we found a match here - return the length and offset
+ *result_len = matchlen;
+ return ofs;
+ }
+ }
+
+ // we didn't find a match
+ return -1;
+}
+
+void re_context::save_search_str(const char *str, size_t len) {
+ // if the string is empty, this is easy
+ if (len == 0) {
+ // nothing to store - just save the length and return
+ _curlen = 0;
+ return;
+ }
+
+ // if the current buffer isn't big enough, allocate a new one
+ if (_strbuf == 0 || _strbufsiz < len) {
+ /*
+ * free any previous buffer - its contents are no longer
+ * important, since we're about to overwrite it with a new
+ * string
+ */
+ if (_strbuf != 0)
+ mchfre(_strbuf);
+
+ /*
+ * allocate a new buffer; round up to the next 256-byte
+ * increment to make sure we're not constantly reallocating to
+ * random sizes
+ */
+ _strbufsiz = ((len + 255) & ~255);
+
+ // allocate it
+ _strbuf = (char *)mchalo(_errctx, _strbufsiz, "regex str");
+ }
+
+ // copy the string
+ memcpy(_strbuf, str, len);
+
+ // save the length
+ _curlen = len;
+}
+
+int re_context::compile_and_search(const char *pattern, size_t patlen,
+ const char *searchstr, size_t searchlen, int *result_len) {
+ re_machine machine;
+
+ // compile the expression - return failure if we get an error
+ if (compile(pattern, patlen, &machine) != RE_STATUS_SUCCESS)
+ return -1;
+
+ // save the search string in our internal buffer
+ save_search_str(searchstr, searchlen);
+
+ // clear the group registers
+ memset(_regs, 0, sizeof(_regs));
+
+ /*
+ * search for the pattern in our copy of the string - use the copy
+ * so that the group registers stay valid even if the caller
+ * deallocates the original string after we return
+ */
+ return search(_strbuf, _curlen, &machine, _regs, result_len);
+}
+
+int re_context::compile_and_match(const char *pattern, size_t patlen,
+ const char *searchstr, size_t searchlen) {
+ re_machine machine;
+
+ // compile the expression - return failure if we get an error
+ if (compile(pattern, patlen, &machine) != RE_STATUS_SUCCESS)
+ return 0;
+
+ // save the search string in our internal buffer
+ save_search_str(searchstr, searchlen);
+
+ // clear the group registers
+ memset(_regs, 0, sizeof(_regs));
+
+ // match the string
+ return match(_strbuf, _strbuf, _curlen, &machine, _regs);
+}
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // Engine of namespace GLK
diff --git a/engines/glk/tads/tads2/regex.h b/engines/glk/tads/tads2/regex.h
new file mode 100644
index 0000000..9040a02
--- /dev/null
+++ b/engines/glk/tads/tads2/regex.h
@@ -0,0 +1,315 @@
+/* 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_TADS_TADS2_REGEX
+#define GLK_TADS_TADS2_REGEX
+
+#include "common/array.h"
+#include "engines/glk/tads/tads2/ler.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+/**
+ * state ID
+ */
+typedef int re_state_id;
+
+/**
+ * invalid state ID - used to mark null machines
+ */
+#define RE_STATE_INVALID ((re_state_id)-1)
+
+/**
+ * first valid state ID
+ */
+#define RE_STATE_FIRST_VALID ((re_state_id)0)
+
+
+/**
+ * Group register structure. Each register keeps track of the starting
+ * and ending offset of the group's text.
+ */
+struct re_group_register {
+ const char *start_ofs;
+ const char *end_ofs;
+};
+
+/**
+ * number of group registers we keep
+ */
+#define RE_GROUP_REG_CNT 10
+
+/**
+ * Denormalized state transition tuple. Each tuple represents the
+ * complete set of transitions out of a particular state. A particular
+ * state can have one character transition, or two epsilon transitions.
+ * Note that we don't need to store the state ID in the tuple, because
+ * the state ID is the index of the tuple in an array of state tuples.
+ */
+struct re_tuple {
+ // the character we must match to transition to the target state
+ char ch;
+
+ // the target states
+ re_state_id next_state_1;
+ re_state_id next_state_2;
+
+ // character range match table, if used
+ unsigned char *char_range;
+
+ // flags
+ byte flags;
+};
+
+
+/**
+ * Tuple flags
+ */
+enum {
+ // this state is the start of a group - the 'ch' value is the group ID
+ RE_STATE_GROUP_BEGIN = 0x02,
+
+ // this state is the end of a group - 'ch' is the group ID */
+ RE_STATE_GROUP_END = 0x04
+};
+
+/**
+ * Status codes
+ */
+typedef enum {
+ // success
+ RE_STATUS_SUCCESS = 0,
+
+ // compilation error - group nesting too deep
+ RE_STATUS_GROUP_NESTING_TOO_DEEP
+} re_status_t;
+
+
+/**
+ * Regular expression compilation. This tracks the state of the compilation and
+ * stores the resources associated with the compiled expression.
+ */
+class re_context {
+ /**
+ * A machine description. Machines are fully described by their initial
+ * and final state ID's.
+ */
+ struct re_machine {
+ re_state_id init; ///< the machine's initial state
+ re_state_id final; ///< the machine's final state
+
+ re_machine() : init(0), final(0) {}
+
+ /**
+ * Build a null machine
+ */
+ void build_null_machine() {
+ init = final = RE_STATE_INVALID;
+ }
+
+ /**
+ * Determine if a machine is null
+ */
+ bool isNull() const {
+ return (init == RE_STATE_INVALID);
+ }
+ };
+private:
+ /**
+ * Reset compiler - clears states and tuples
+ */
+ void reset();
+
+ /**
+ * Set a transition from a state to a given destination state
+ */
+ void set_trans(re_state_id id, re_state_id dest_id, char ch);
+
+ /**
+ * Initialize a new machine, giving it an initial and final state
+ */
+ void init_machine(re_machine *machine);
+
+ /**
+ * Build a character recognizer
+ */
+ void build_char(re_machine *machine, char ch);
+
+ /**
+ * Build a character range recognizer. 'range' is a 256-bit (32-byte) bit vector.
+ */
+ void build_char_range(re_machine *machine, unsigned char *range, int exclusion);
+
+ /**
+ * Build a group recognizer. This is almost the same as a character
+ * recognizer, but matches a previous group rather than a literal character.
+ */
+ void build_group_matcher(re_machine *machine, int group_num);
+
+ /**
+ * Build a concatenation recognizer
+ */
+ void build_concat(re_machine *new_machine, re_machine *lhs, re_machine *rhs);
+
+ /**
+ * Build a group machine. sub_machine contains the machine that
+ * expresses the group's contents; we'll fill in new_machine with a
+ * newly-created machine that encloses and marks the group.
+ */
+ void build_group(re_machine *new_machine, re_machine *sub_machine, int group_id);
+
+ /**
+ * Build an alternation recognizer
+ */
+ void build_alter(re_machine *new_machine, re_machine *lhs, re_machine *rhs);
+
+ /**
+ * Build a closure recognizer
+ */
+ void build_closure(re_machine *new_machine, re_machine *sub, char specifier);
+
+ /**
+ * Concatenate the second machine onto the first machine, replacing the
+ * first machine with the resulting machine. If the first machine is a
+ * null machine (created with re_build_null_machine), we'll simply copy
+ * the second machine into the first.
+ */
+ void concat_onto(re_machine *dest, re_machine *rhs);
+
+ /**
+ * Alternate the second machine onto the first machine, replacing the
+ * first machine with the resulting machine. If the first machine is a
+ * null machine, this simply replaces the first machine with the second
+ * machine. If the second machine is null, this simply leaves the first
+ * machine unchanged.
+ */
+ void alternate_onto(re_machine *dest, re_machine *rhs);
+
+ /**
+ * Compile an expression
+ */
+ re_status_t compile(const char *expr, size_t exprlen, re_machine *result_machine);
+
+ /**
+ * Note a group position if appropriate
+ */
+ void note_group(re_group_register *regs, re_state_id id, const char *p);
+
+ /**
+ * Determine if a character is part of a word. We consider letters and
+ * numbers to be word characters.
+ */
+ bool is_word_char(char c) const;
+
+ /**
+ * Match a string to a compiled expression. Returns the length of the
+ * match if successful, or -1 if no match was found.
+ */
+ int match(const char *entire_str, const char *str, size_t origlen,
+ const re_machine *machine, re_group_register *regs);
+
+ /**
+ * Search for a regular expression within a string. Returns -1 if the string
+ * cannot be found, otherwise returns the offset from the start of the string
+ * to be searched of the start of the first match for the pattern.
+ */
+ int search(const char *str, size_t len, const re_machine *machine,
+ re_group_register *regs, int *result_len);
+
+ /**
+ * Make a copy of a search string in our private buffer.
+ */
+ void save_search_str(const char *str, size_t len);
+public:
+ errcxdef *_errctx; ///< error context
+ re_state_id _next_state; ///< next available state ID
+
+ /**
+ * The array of transition tuples. We'll allocate this array and
+ * expand it as necessary.
+ */
+ Common::Array<re_tuple> _tuple_arr;
+
+ // current group ID
+ int _cur_group;
+
+ // group registers
+ re_group_register _regs[RE_GROUP_REG_CNT];
+
+ /**
+ * Buffer for retaining a copy of the last string we scanned. We
+ * retain our own copy of each string, and point the group registers
+ * into this copy rather than the caller's original string -- this
+ * ensures that the group registers remain valid even after the
+ * caller has deallocated the original string.
+ */
+ char *_strbuf;
+
+ /**
+ * length of the string currently in the buffer
+ */
+ size_t _curlen;
+
+ /**
+ * size of the buffer allocated to strbuf
+ */
+ size_t _strbufsiz;
+public:
+ /**
+ * Constructor. The memory for the context structure itself
+ * must be allocated and maintained by the caller.
+ */
+ re_context(errcxdef *errctx);
+
+ /**
+ * Destructor
+ */
+ ~re_context();
+
+ /**
+ * Allocate a new state ID
+ */
+ re_state_id alloc_state();
+
+ /**
+ * Compile an expression and search for a match within the given string.
+ * Returns the offset of the match, or -1 if no match was found.
+ */
+ int compile_and_search(const char *pattern, size_t patlen,
+ const char *searchstr, size_t searchlen, int *result_len);
+
+ /**
+ * Compile an expression and check for a match. Returns the length of the match
+ * if we found a match, -1 if we found no match. This is not a search function;
+ * we merely match the leading substring of the given string to the given pattern.
+ */
+ int compile_and_match(const char *pattern, size_t patlen,
+ const char *searchstr, size_t searchlen);
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // Engine of namespace GLK
+
+#endif
diff --git a/engines/glk/tads/tads2/tads2.cpp b/engines/glk/tads/tads2/tads2.cpp
index 9c50c20d..79a36fa 100644
--- a/engines/glk/tads/tads2/tads2.cpp
+++ b/engines/glk/tads/tads2/tads2.cpp
@@ -27,6 +27,7 @@ namespace TADS {
namespace TADS2 {
TADS2::TADS2(OSystem *syst, const GlkGameDescription &gameDesc) : OS(syst, gameDesc) {
+ cmap_init_default();
}
void TADS2::runGame(Common::SeekableReadStream *gameFile) {
diff --git a/engines/glk/tads/tads2/tads2.h b/engines/glk/tads/tads2/tads2.h
index 2c799a3..f0c42b3 100644
--- a/engines/glk/tads/tads2/tads2.h
+++ b/engines/glk/tads/tads2/tads2.h
@@ -31,27 +31,75 @@ namespace TADS {
namespace TADS2 {
/**
+ * map a native character (read externally) into an internal character
+ */
+#define cmap_n2i(c) (G_cmap_input[(unsigned char)(c)])
+
+/**
+ * map an internal character into a native character (for display)
+ */
+#define cmap_i2n(c) (G_cmap_output[(unsigned char)(c)])
+
+/**
+ * the full name (for display purposes) of the loaded character set
+ */
+#define CMAP_LDESC_MAX_LEN 40
+
+/**
+ * Maximum expansion for an HTML entity mapping
+ */
+#define CMAP_MAX_ENTITY_EXPANSION 50
+
+
+/**
* TADS 2 game interpreter
*/
class TADS2 : public OS {
private:
// STUBS
void os_printz(const Common::String &s) {}
-public:
+ void tio_set_html_expansion(unsigned int html_char_val,
+ const char *expansion, size_t expansion_len) {}
+private:
/**
- * Constructor
+ * \defgroup cmap
+ * @{
*/
- TADS2(OSystem *syst, const GlkGameDescription &gameDesc);
/**
- * Execute the game
+ * flag: true -> a character set has been explicitly loaded, so we
+ * should ignore any game character set setting
*/
- virtual void runGame(Common::SeekableReadStream *gameFile) override;
+ bool S_cmap_loaded;
/**
- * Returns the running interpreter type
+ * input-mapping table - for native character 'n', cmap_input[n] yields
+ * the internal character code
+ */
+ unsigned char G_cmap_input[256];
+
+ /**
+ * output-mapping table - for internal character 'n', cmap_output[n]
+ * yields the output character code
+ */
+ unsigned char G_cmap_output[256];
+
+ /**
+ * the ID of the loaded character set
+ */
+ char G_cmap_id[5];
+
+ /**
+ * the full name (for display purposes) of the loaded character set
+ */
+ char G_cmap_ldesc[CMAP_LDESC_MAX_LEN + 1];
+
+ /**@}*/
+private:
+ /**
+ * \defgroup trd
+ * @{
*/
- virtual InterpreterType getInterpreterType() const override { return INTERPRETER_TADS2; }
void trdmain1(errcxdef *errctx);
@@ -59,6 +107,72 @@ public:
* printf-style formatting
*/
void trdptf(const char *fmt, ...);
+
+ /**@}*/
+
+ /**
+ * \defgroup cmap
+ * @{
+ */
+
+ /**
+ * Initialize the default character mappings. If no mapping file is to
+ * be read, this function will establish identify mappings that leave
+ * characters untranslated.
+ */
+ void cmap_init_default();
+
+ /**
+ * Load a character map file. Returns zero on success, non-zero on
+ * failure. If filename is null, we'll use the default mapping.
+ */
+ int cmap_load(const char *filename);
+
+ /**
+ * Turn off character translation. This overrides any game character
+ * set that we find and simply uses the default translation.
+ */
+ void cmap_override(void);
+
+ /**
+ * Set the game's internal character set. This should be called when a
+ * game is loaded, and the game specifies an internal character set. If
+ * there is no character map file explicitly loaded, we will attempt to
+ * load a character mapping file that maps this character set to the
+ * current native character set. Signals an error on failure. This
+ * routine will succeed (without doing anything) if a character set has
+ * already been explicitly loaded, since an explicitly-loaded character
+ * set overrides the automatic character set selection that we attempt
+ * when loading a game.
+ *
+ * argv0 must be provided so that we know where to look for our mapping
+ * file on systems where mapping files are stored in the same directory
+ * as the TADS executables.
+ */
+ void cmap_set_game_charset(errcxdef *errctx, const char *internal_id,
+ const char *internal_ldesc, const char *argv0);
+
+ /**
+ * Internal routine to load a character map from a file
+ */
+ int cmap_load_internal(const char *filename);
+
+ /**@}*/
+public:
+ /**
+ * Constructor
+ */
+ TADS2(OSystem *syst, const GlkGameDescription &gameDesc);
+
+ /**
+ * Execute the game
+ */
+ virtual void runGame(Common::SeekableReadStream *gameFile) override;
+
+ /**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_TADS2; }
};
typedef TADS2 appctxdef;
diff --git a/engines/glk/tads/tads2/tads2_cmap.cpp b/engines/glk/tads/tads2/tads2_cmap.cpp
new file mode 100644
index 0000000..cf63c9a
--- /dev/null
+++ b/engines/glk/tads/tads2/tads2_cmap.cpp
@@ -0,0 +1,268 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/tads2/tads2.h"
+#include "glk/tads/tads2/types.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+/**
+ * Signatures for character map files. The signature is stored at the
+ * beginning of the file.
+ */
+// single-byte character map version 1.0.0
+#define CMAP_SIG_S100 "TADS2 charmap S100\n\r\01a"
+
+void TADS2::cmap_init_default() {
+ size_t i;
+
+ // initialize the input table
+ for (i = 0 ; i < sizeof(G_cmap_input)/sizeof(G_cmap_input[0]) ; ++i)
+ G_cmap_input[i] = (unsigned char)i;
+
+ // initialize the output table
+ for (i = 0 ; i < sizeof(G_cmap_output)/sizeof(G_cmap_output[0]) ; ++i)
+ G_cmap_output[i] = (unsigned char)i;
+
+ // we have a null ID
+ memset(G_cmap_id, 0, sizeof(G_cmap_id));
+
+ // indicate that it's the default
+ strcpy(G_cmap_ldesc, "(native/no mapping)");
+
+ // note that we have no character set loaded
+ S_cmap_loaded = false;
+}
+
+int TADS2::cmap_load_internal(const char *filename) {
+ osfildef *fp;
+ static char sig1[] = CMAP_SIG_S100;
+ char buf[256];
+ uchar lenbuf[2];
+ size_t len;
+ int sysblk;
+
+ // if there's no mapping file, use the default mapping
+ if (filename == 0) {
+ // initialize with the default mapping
+ cmap_init_default();
+
+ // return success
+ return 0;
+ }
+
+ // open the file
+ fp = osfoprb(filename, OSFTCMAP);
+ if (fp == 0)
+ return 1;
+
+ // check the signature
+ if (osfrb(fp, buf, sizeof(sig1))
+ || memcmp(buf, sig1, sizeof(sig1)) != 0) {
+ osfcls(fp);
+ return 2;
+ }
+
+ // load the ID
+ G_cmap_id[4] = '\0';
+ if (osfrb(fp, G_cmap_id, 4)) {
+ osfcls(fp);
+ return 3;
+ }
+
+ // load the long description
+ if (osfrb(fp, lenbuf, 2)
+ || (len = osrp2(lenbuf)) > sizeof(G_cmap_ldesc)
+ || osfrb(fp, G_cmap_ldesc, len)) {
+ osfcls(fp);
+ return 4;
+ }
+
+ // load the two tables - input, then output
+ if (osfrb(fp, G_cmap_input, sizeof(G_cmap_input))
+ || osfrb(fp, G_cmap_output, sizeof(G_cmap_output))) {
+ osfcls(fp);
+ return 5;
+ }
+
+ // read the next section header
+ if (osfrb(fp, buf, 4)) {
+ osfcls(fp);
+ return 6;
+ }
+
+ // if it's "SYSI", read the system information string
+ if (!memcmp(buf, "SYSI", 4)) {
+ // read the length prefix, then the string
+ if (osfrb(fp, lenbuf, 2)
+ || (len = osrp2(lenbuf)) > sizeof(buf)
+ || osfrb(fp, buf, len)) {
+ osfcls(fp);
+ return 7;
+ }
+
+ // we have a system information block
+ sysblk = true;
+ } else {
+ // there's no system information block
+ sysblk = false;
+ }
+
+ /*
+ * call the OS code, so that it can do any system-dependent
+ * initialization for the new character mapping
+ */
+ os_advise_load_charmap(G_cmap_id, G_cmap_ldesc, sysblk ? buf : "");
+
+ // read the next section header
+ if (sysblk && osfrb(fp, buf, 4)) {
+ osfcls(fp);
+ return 8;
+ }
+
+ // see if we have an entity list
+ if (!memcmp(buf, "ENTY", 4)) {
+ // read the entities
+ for (;;) {
+ unsigned int cval;
+ char expansion[CMAP_MAX_ENTITY_EXPANSION];
+
+ // read the next item's length and character value
+ if (osfrb(fp, buf, 4)) {
+ osfcls(fp);
+ return 9;
+ }
+
+ // decode the values
+ len = osrp2(buf);
+ cval = osrp2(buf+2);
+
+ // if we've reached the zero marker, we're done
+ if (len == 0 && cval == 0)
+ break;
+
+ // read the string
+ if (len > CMAP_MAX_ENTITY_EXPANSION
+ || osfrb(fp, expansion, len)) {
+ osfcls(fp);
+ return 10;
+ }
+
+ // tell the output code about the expansion
+ tio_set_html_expansion(cval, expansion, len);
+ }
+ }
+
+ /*
+ * ignore anything else we find - if the file format is updated to
+ * include extra information in the future, and this old code tries
+ * to load an updated file, we'll just ignore the new information,
+ * which should always be placed after the "SYSI" block (if present)
+ * to ensure compatibility with past versions (such as this code)
+ */
+ // no problems - close the file and return success
+ osfcls(fp);
+ return 0;
+}
+
+int TADS2::cmap_load(const char *filename) {
+ int err;
+
+ // try loading the file
+ if ((err = cmap_load_internal(filename)) != 0)
+ return err;
+
+ /*
+ * note that we've explicitly loaded a character set, if they named
+ * a character set (if not, this simply establishes the default
+ * setting, so we haven't explicitly loaded anything)
+ */
+ if (filename != nullptr)
+ S_cmap_loaded = true;
+
+ // success
+ return 0;
+}
+
+void TADS2::cmap_override() {
+ // apply the default mapping
+ cmap_init_default();
+
+ /*
+ * pretend we have a character map loaded, so that we don't try to
+ * load another one if the game specifies a character set
+ */
+ S_cmap_loaded = true;
+}
+
+void TADS2::cmap_set_game_charset(errcxdef *ec, const char *internal_id,
+ const char *internal_ldesc, const char *argv0) {
+ char filename[OSFNMAX];
+
+ /*
+ * If a character set is already explicitly loaded, ignore the
+ * game's character set - the player asked us to use a particular
+ * mapping, so ignore what the game wants. (This will probably
+ * result in incorrect display of non-ASCII character values, but
+ * the player is most likely to use this to avoid errors when an
+ * appropriate mapping file for the game is not available. In this
+ * case, the player informs us by setting the option that he or she
+ * knows and accepts that the game will not look exactly right.)
+ */
+ if (S_cmap_loaded)
+ return;
+
+ /*
+ * ask the operating system to name the mapping file -- this routine
+ * will determine, if possible, the current native character set,
+ * and apply a system-specific naming convention to tell us what
+ * mapping file we should open
+ */
+ os_gen_charmap_filename(filename, internal_id, argv0);
+
+ // try loading the mapping file
+ if (cmap_load_internal(filename))
+ errsig2(ec, ERR_CHRNOFILE,
+ ERRTSTR, errstr(ec, filename, strlen(filename)),
+ ERRTSTR, errstr(ec, internal_ldesc, strlen(internal_ldesc)));
+
+ /**
+ * We were successful - the game's internal character set is now
+ * mapped to the current native character set. Even though we
+ * loaded an ldesc from the mapping file, forget that and store the
+ * internal ldesc that the game specified. The reason we do this is
+ * that it's possible that the player will dynamically switch native
+ * character sets in the future, at which point we'll need to
+ * re-load the mapping table, which could raise an error if a
+ * mapping file for the new character set isn't available. So, we
+ * may need to provide the same explanation later that we needed to
+ * provide here. Save the game's character set ldesc for that
+ * eventuality, since it describes exactly what the *game* wanted.
+ */
+ strcpy(G_cmap_ldesc, internal_ldesc);
+}
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads2/types.h b/engines/glk/tads/tads2/types.h
new file mode 100644
index 0000000..52a5309
--- /dev/null
+++ b/engines/glk/tads/tads2/types.h
@@ -0,0 +1,188 @@
+/* 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_TADS_TADS2_TYPES
+#define GLK_TADS_TADS2_TYPES
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+typedef unsigned char uchar;
+typedef Common::SeekableReadStream osfildef;
+
+/**
+ * Allocate a memory block
+ */
+#define mchalo(CTX, SIZE, COMMENT) ((byte *)new byte[SIZE])
+
+/**
+ * Free a memory block
+ */
+#define mchfre(PTR) delete[] (byte *)PTR
+
+/**
+ * Close a file
+ */
+#define osfcls(FP) delete FP
+
+/**
+ * Read from a file
+ */
+#define osfrb(FP, BUF, SIZE) FP->read(BUF, SIZE)
+
+/**
+ * Read a 16-bit integer from memory
+ */
+#define osrp2(MEM) READ_LE_UINT16(MEM)
+
+/**
+ * The character (or characters) which mark the beginning of a special fileref string.
+ * The important thing is that the string be one that is either not allowed in
+ * filenames on your platform or is unlikely to be the first part of a filename.
+ */
+#define OSS_FILEREF_STRING_PREFIX ":"
+
+/**
+ * The character (or characters) which mark the end of a special fileref string.
+ * Using this and OSS_FILEREF_STRING_PREFIX, you should be able to come up with
+ * something which forms an invalid filename
+ */
+#define OSS_FILEREF_STRING_SUFFIX ""
+
+/**
+ * Maximum length of status line text
+ */
+#define OSS_STATUS_STRING_LEN 80
+
+/**
+ * Maximum size for filenames
+ */
+#define OSFNMAX 1024
+
+/**
+ * Important note: do not change these values when porting TADS. These
+ * values can be used by games, so they must be the same on all platforms.
+ */
+enum {
+ OS_AFP_OPEN = 1, ///< choose an existing file to open for reading
+ OS_AFP_SAVE = 2 ///< choose a filename for saving to a file
+};
+
+/**
+ * File types.These type codes are used when opening or creating a file,
+ * so that the OS routine can set appropriate file system metadata
+ * to describe or find the file type.
+ *
+ * The type os_filetype_t is defined for documentary purposes; it's
+ * always just an int.
+ */
+enum os_filetype_t {
+ OSFTGAME = 0, ///< a game data file (.gam)
+ OSFTSAVE = 1, ///< a saved game (.sav)
+ OSFTLOG = 2, ///< a transcript (log) file
+ OSFTSWAP = 3, ///< swap file
+ OSFTDATA = 4, ///< user data file (used with the TADS fopen() call)
+ OSFTCMD = 5, ///< QA command/log file
+ OSFTERRS = 6, ///< error message file
+ OSFTTEXT = 7, ///< text file - used for source files
+ OSFTBIN = 8, ///< binary file of unknown type - resources, etc
+ OSFTCMAP = 9, ///< character mapping file
+ OSFTPREF = 10, ///< preferences file
+ OSFTUNK = 11, ///< unknown - as a filter, matches any file type
+ OSFTT3IMG = 12, ///< T3 image file (.t3 - formerly .t3x)
+ OSFTT3OBJ = 13, ///< T3 object file (.t3o)
+ OSFTT3SYM = 14, ///< T3 symbol export file (.t3s)
+ OSFTT3SAV = 15 ///< T3 saved state file (.t3v)
+};
+
+/**
+ * Constants for os_getc() when returning commands. When used for command line
+ * editing, special keys (arrows, END, etc.) should cause os_getc() to return 0,
+ * and return the appropriate CMD_ value on the NEXT call. Hence, os_getc() must
+ * keep the appropriate information around statically for the next call when a
+ * command key is issued.
+ *
+ * The comments indicate which CMD_xxx codes are "translated" codes and which are
+ * "raw"; the difference is that, when a particular keystroke could be interpreted
+ * as two different CMD_xxx codes, one translated and the other raw, os_getc()
+ * should always return the translated version of the key, and os_getc_raw()
+ * should return the raw version.
+ */
+enum KeyCmd {
+ CMD_UP = 1, ///< move up/up arrow (translated)
+ CMD_DOWN = 2, ///< move down/down arrow (translated)
+ CMD_RIGHT = 3, ///< move right/right arrow (translated)
+ CMD_LEFT = 4, ///< move left/left arrow (translated)
+ CMD_END = 5, ///< move cursor to end of line (translated)
+ CMD_HOME = 6, ///< move cursor to start of line (translated)
+ CMD_DEOL = 7, ///< delete to end of line (translated)
+ CMD_KILL = 8, ///< delete entire line (translated)
+ CMD_DEL = 9, ///< delete current character (translated)
+ CMD_SCR = 10, ///< toggle scrollback mode (translated)
+ CMD_PGUP = 11, ///< page up (translated)
+ CMD_PGDN = 12, ///< page down (translated)
+ CMD_TOP = 13, ///< top of file (translated)
+ CMD_BOT = 14, ///< bottom of file (translated)
+ CMD_F1 = 15, ///< function key F1 (raw)
+ CMD_F2 = 16, ///< function key F2 (raw)
+ CMD_F3 = 17, ///< function key F3 (raw)
+ CMD_F4 = 18, ///< function key F4 (raw)
+ CMD_F5 = 19, ///< function key F5 (raw)
+ CMD_F6 = 20, ///< function key F6 (raw)
+ CMD_F7 = 21, ///< function key F7 (raw)
+ CMD_F8 = 22, ///< function key F8 (raw)
+ CMD_F9 = 23, ///< function key F9 (raw)
+ CMD_F10 = 24, ///< function key F10 (raw)
+ CMD_CHOME = 25, ///< control-home (raw)
+ CMD_TAB = 26, ///< tab (translated)
+ CMD_SF2 = 27, ///< shift-F2 (raw)
+ ///< not used (obsolete) - 28
+ CMD_WORD_LEFT = 29, ///< word left (ctrl-left on dos) (translated)
+ CMD_WORD_RIGHT = 30,///< word right (ctrl-right on dos) (translated)
+ CMD_WORDKILL = 31, ///< delete word right (translated)
+ CMD_EOF = 32, ///< end-of-file (raw)
+ CMD_BREAK = 33, ///< break (Ctrl-C or local equivalent) (translated)
+ CMD_INS = 34, ///< insert key (raw)
+
+ /**
+ * ALT-keys - add alphabetical code to CMD_ALT: ALT-A == CMD_ALT + 0,
+ * ALT-B == CMD_ALT + 1, ALT-C == CMD_ALT + 2, etc
+ *
+ * These keys are all raw (untranslated).
+ */
+ CMD_ALT = 128 ///< start of ALT keys
+};
+
+/**
+ * Status mode codes
+ */
+enum StatusMode {
+ OSS_STATUS_MODE_STORY = 0,
+ OSS_STATUS_MODE_STATUS = 1
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
Commit: 14871c28bc9ec1b210412a072f0ab292febfd368
https://github.com/scummvm/scummvm/commit/14871c28bc9ec1b210412a072f0ab292febfd368
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Added Data class
Changed paths:
A engines/glk/tads/tads2/data.cpp
A engines/glk/tads/tads2/data.h
A engines/glk/tads/tads2/vocabulary.cpp
A engines/glk/tads/tads2/vocabulary.h
engines/glk/module.mk
engines/glk/tads/tads2/types.h
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 5c17362..003f8dc 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -45,11 +45,13 @@ MODULE_OBJS := \
scott/scott.o \
tads/detection.o \
tads/tads.o \
+ tads/tads2/data.o \
tads/tads2/ler.o \
tads/tads2/os.o \
tads/tads2/regex.o \
tads/tads2/tads2.o \
tads/tads2/tads2_cmap.o \
+ tads/tads2/vocabulary.o \
tads/tads3/tads3.o
# This module can be built as a plugin
diff --git a/engines/glk/tads/tads2/data.cpp b/engines/glk/tads/tads2/data.cpp
new file mode 100644
index 0000000..e142f37
--- /dev/null
+++ b/engines/glk/tads/tads2/data.cpp
@@ -0,0 +1,72 @@
+/* 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.
+ *
+ */
+
+#include "engines/glk/tads/tads2/data.h"
+#include "engines/glk/tads/tads2/types.h"
+#include "engines/glk/tads/tads2/vocabulary.h"
+#include "common/algorithm.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+Data::Data(DataType type) : _type(type) {
+}
+
+size_t Data::size() const {
+ switch (_type) {
+ case DAT_NUMBER:
+ return 4; // numbers are in 4-byte lsb-first format
+
+ case DAT_OBJECT:
+ return 2; // object numbers are in 2-byte lsb-first format
+
+ case DAT_SSTRING:
+ case DAT_DSTRING:
+ case DAT_LIST:
+ return osrp2(_ptr);
+
+ case DAT_NIL:
+ case DAT_TRUE:
+ return 0;
+
+ case DAT_PROPNUM:
+ case DAT_SYN:
+ case DAT_FNADDR:
+ case DAT_REDIR:
+ return 2;
+
+ case DAT_TPL:
+ // template is counted array of 10-byte entries, plus length byte */
+ return 1 + ((*(uchar *)_ptr) * VOCTPLSIZ);
+
+ case DAT_TPL2:
+ return 1 + ((*(uchar *)_ptr) * VOCTPL2SIZ);
+
+ default:
+ return 0;
+ }
+}
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // Engine of namespace GLK
diff --git a/engines/glk/tads/tads2/data.h b/engines/glk/tads/tads2/data.h
new file mode 100644
index 0000000..b2d8df6
--- /dev/null
+++ b/engines/glk/tads/tads2/data.h
@@ -0,0 +1,69 @@
+/* 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_TADS_TADS2_DATA
+#define GLK_TADS_TADS2_DATA
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+enum DataType {
+ DAT_NUMBER = 1,
+ DAT_OBJECT = 2,
+ DAT_SSTRING = 3,
+ DAT_BASEPTR = 4,
+ DAT_NIL = 5, ///< nil, as in FALSE or empty list
+ DAT_CODE = 6,
+ DAT_LIST = 7,
+ DAT_TRUE = 8, ///< inverse of nil
+ DAT_DSTRING = 9,
+ DAT_FNADDR = 10, ///< a function address
+ DAT_TPL = 11, ///< template list pointer
+ DAT_PROPNUM = 13, ///< a property number
+ DAT_DEMAND = 14, ///< special flag: use callback to set on use
+ DAT_SYN = 15, ///< synonym to indicated property value
+ DAT_REDIR = 16, ///< redirection to different object
+ DAT_TPL2 = 17 ///< new-style template
+};
+
+class Data {
+private:
+ DataType _type;
+ void *_ptr;
+public:
+ /**
+ * Constructor
+ */
+ Data(DataType type);
+
+ /**
+ * Return the size of the data
+ */
+ size_t size() const;
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // Engine of namespace Glk
+
+#endif
diff --git a/engines/glk/tads/tads2/types.h b/engines/glk/tads/tads2/types.h
index 52a5309..5da759f 100644
--- a/engines/glk/tads/tads2/types.h
+++ b/engines/glk/tads/tads2/types.h
@@ -23,6 +23,8 @@
#ifndef GLK_TADS_TADS2_TYPES
#define GLK_TADS_TADS2_TYPES
+#include "common/stream.h"
+
namespace Glk {
namespace TADS {
namespace TADS2 {
diff --git a/engines/glk/tads/tads2/vocabulary.cpp b/engines/glk/tads/tads2/vocabulary.cpp
new file mode 100644
index 0000000..4647b1b
--- /dev/null
+++ b/engines/glk/tads/tads2/vocabulary.cpp
@@ -0,0 +1,33 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/tads2/vocabulary.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+// TODO: Rest of vocabulary stuff
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
diff --git a/engines/glk/tads/tads2/vocabulary.h b/engines/glk/tads/tads2/vocabulary.h
new file mode 100644
index 0000000..b407993
--- /dev/null
+++ b/engines/glk/tads/tads2/vocabulary.h
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+/*
+ * Defines TADS vocabulary (player command parser) functionality
+ */
+
+#ifndef GLK_TADS_TADS2_OS
+#define GLK_TADS_TADS2_OS
+
+#include "glk/tads/tads2/types.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+// TODO: Rest of vocabulary stuff
+#define VOCTPLSIZ 10
+#define VOCTPL2SIZ 16
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif
Commit: c68542dba8ecf7a9ad061c015061832eaa4bb016
https://github.com/scummvm/scummvm/commit/c68542dba8ecf7a9ad061c015061832eaa4bb016
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Compilation fix
Changed paths:
engines/glk/tads/tads2/data.h
diff --git a/engines/glk/tads/tads2/data.h b/engines/glk/tads/tads2/data.h
index b2d8df6..2276d37 100644
--- a/engines/glk/tads/tads2/data.h
+++ b/engines/glk/tads/tads2/data.h
@@ -23,6 +23,8 @@
#ifndef GLK_TADS_TADS2_DATA
#define GLK_TADS_TADS2_DATA
+#include "common/scummsys.h"
+
namespace Glk {
namespace TADS {
namespace TADS2 {
Commit: 7212924b1ead017b4c769ca4fb8cdad6bf95e78e
https://github.com/scummvm/scummvm/commit/7212924b1ead017b4c769ca4fb8cdad6bf95e78e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: TADS: Compilation fixes
Changed paths:
engines/glk/picture.cpp
engines/glk/tads/tads2/ler.cpp
engines/glk/tads/tads2/os.cpp
engines/glk/tads/tads2/regex.cpp
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 4422e46..631f9be 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -146,7 +146,8 @@ Picture *Pictures::load(uint32 id) {
pal[idx] = pic->format.RGBToColor(palette[idx * 3],
palette[idx * 3 + 1], palette[idx * 3 + 2]);
- byte *srcP = (byte *)img->getPixels(), *destP = (byte *)pic->getPixels();
+ const byte *srcP = (const byte *)img->getPixels();
+ byte *destP = (byte *)pic->getPixels();
for (int idx = 0; idx < img->w * img->h; ++idx, srcP++, destP += pic->format.bytesPerPixel) {
uint val = (*srcP >= palCount) ? 0 : pal[*srcP];
if (pic->format.bytesPerPixel == 2)
diff --git a/engines/glk/tads/tads2/ler.cpp b/engines/glk/tads/tads2/ler.cpp
index 930fdf0..970fe31 100644
--- a/engines/glk/tads/tads2/ler.cpp
+++ b/engines/glk/tads/tads2/ler.cpp
@@ -33,7 +33,7 @@ int errcxdef::errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *ar
int argi = 0;
int len;
char buf[20];
- char *p = nullptr;
+ const char *p = nullptr;
char fmtchar;
while (*fmt != '\0' && outbufl > 1) {
diff --git a/engines/glk/tads/tads2/os.cpp b/engines/glk/tads/tads2/os.cpp
index 514a912..17bdc34 100644
--- a/engines/glk/tads/tads2/os.cpp
+++ b/engines/glk/tads/tads2/os.cpp
@@ -51,6 +51,7 @@ glui32 OS::oss_convert_file_type(int type) {
}
glui32 OS::oss_convert_fileref_to_string(frefid_t file_to_convert, char *buffer, int buf_len) {
+#ifdef TODO
char temp_string[32];
glui32 value, i = 0, digit,
digit_flag = false, // Have we put a digit in the string yet?
@@ -74,10 +75,12 @@ glui32 OS::oss_convert_fileref_to_string(frefid_t file_to_convert, char *buffer,
return false;
sprintf(buffer, "%s%s%s", OSS_FILEREF_STRING_PREFIX,
temp_string, OSS_FILEREF_STRING_SUFFIX);
+#endif
return true;
}
frefid_t OS::oss_convert_string_to_fileref(char *buffer, glui32 usage) {
+#ifdef TODO
char temp_string[32];
glui32 value = 0, i, multiplier = 1;
@@ -97,6 +100,9 @@ frefid_t OS::oss_convert_string_to_fileref(char *buffer, glui32 usage) {
// If not, return the new fileref
return (glk_fileref_create_by_name(usage, os_get_root_name(buffer), 0));
+#else
+ return nullptr;
+#endif
}
bool OS::oss_is_string_a_fileref(char *buffer) {
diff --git a/engines/glk/tads/tads2/regex.cpp b/engines/glk/tads/tads2/regex.cpp
index f6a009a..d5eee3a 100644
--- a/engines/glk/tads/tads2/regex.cpp
+++ b/engines/glk/tads/tads2/regex.cpp
@@ -1069,19 +1069,18 @@ int re_context::match(const char *entire_str, const char *str, size_t origlen,
case RE_RANGE:
case RE_RANGE_EXCL: {
- int match;
+ int match_val;
// make sure we have a character to match
if (curlen == 0)
return -1;
// see if we match
- match = re_is_bit_set(tuple->char_range,
- (int)(unsigned char)*p);
+ match_val = re_is_bit_set(tuple->char_range, (int)(unsigned char)*p);
// make sure we got what we wanted
- if ((tuple->ch == RE_RANGE && !match)
- || (tuple->ch == RE_RANGE_EXCL && match))
+ if ((tuple->ch == RE_RANGE && !match_val)
+ || (tuple->ch == RE_RANGE_EXCL && match_val))
return -1;
// skip this character of the input
Commit: 1933130dfcc417c96e0dfd5eadee68833daf0821
https://github.com/scummvm/scummvm/commit/1933130dfcc417c96e0dfd5eadee68833daf0821
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix setting cwin field when window changes
Changed paths:
engines/glk/frotz/processor_screen.cpp
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 6a518cf..6627bf6 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -396,9 +396,9 @@ void Processor::z_set_text_style() {
}
void Processor::z_set_window() {
- int win = zargs[0];
+ cwin = zargs[0];
- if (win == 0) {
+ if (cwin == 0) {
glk_set_window(gos_lower);
gos_curwin = gos_lower;
} else {
@@ -407,7 +407,7 @@ void Processor::z_set_window() {
gos_curwin = gos_upper;
}
- if (win == 0)
+ if (cwin == 0)
enable_scripting = true;
else
enable_scripting = false;
Commit: 63079834fa7fd7f4592b0a52e709d01b431740e2
https://github.com/scummvm/scummvm/commit/63079834fa7fd7f4592b0a52e709d01b431740e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Improved rendering of Beyond Zork description area
Changed paths:
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/processor_screen.cpp
engines/glk/window_text_grid.h
engines/glk/windows.h
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index c2d6ca2..7367375 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -203,6 +203,8 @@ bool GlkInterface::initPictures() {
}
int GlkInterface::os_char_width(zchar z) {
+ // Note: I'm presuming this is 1 because Glk Text Grid windows take care of font sizes internally,
+ // so we can pretend that any font has a 1x1 size
return 1;
}
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 6627bf6..2ec0128 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -181,8 +181,9 @@ void Processor::z_get_cursor() {
void Processor::z_print_table() {
zword addr = zargs[0];
- zword x;
+ zword xs = curx;
int i, j;
+ zbyte c;
// Supply default arguments
if (zargc < 3)
@@ -191,18 +192,10 @@ void Processor::z_print_table() {
zargs[3] = 0;
// Write text in width x height rectangle
- x = curx;
-
- for (i = 0; i < zargs[2]; i++) {
- if (i != 0) {
- cury += 1;
- curx = x;
- }
+ for (i = 0; i < zargs[2]; i++, curx = xs, cury++) {
+ glk_window_move_cursor(cwin == 0 ? gos_lower : gos_upper, xs - 1, cury - 1);
for (j = 0; j < zargs[1]; j++) {
-
- zbyte c;
-
LOW_BYTE(addr, c);
addr++;
@@ -330,17 +323,33 @@ void Processor::z_set_font() {
}
void Processor::z_set_cursor() {
- cury = zargs[0];
- curx = zargs[1];
+ int x = (int16)zargs[1], y = (int16)zargs[0];
+ assert(gos_upper);
- if (gos_upper) {
- if (cury > mach_status_ht) {
- mach_status_ht = cury;
- reset_status_ht();
- }
+ flush_buffer();
- glk_window_move_cursor(gos_upper, curx - 1, cury - 1);
+ if (y < 0) {
+ // Cursor on/off
+ error("TODO: Turning cursor on/off");
}
+
+ if (!x || !y) {
+ Point cursorPos = gos_upper->getCursor();
+ if (!x)
+ x = cursorPos.x;
+ if (!y)
+ y = cursorPos.y;
+ }
+
+ curx = x;
+ cury = y;
+
+ if (cury > mach_status_ht) {
+ mach_status_ht = cury;
+ reset_status_ht();
+ }
+
+ glk_window_move_cursor(gos_upper, curx - 1, cury - 1);
}
void Processor::z_set_text_style() {
diff --git a/engines/glk/window_text_grid.h b/engines/glk/window_text_grid.h
index 30a0f79..d7830e0 100644
--- a/engines/glk/window_text_grid.h
+++ b/engines/glk/window_text_grid.h
@@ -108,6 +108,11 @@ public:
virtual bool unputCharUni(uint32 ch) override;
/**
+ * Get the cursor position
+ */
+ virtual Point getCursor() const override { return Point(_curX, _curY); }
+
+ /**
* Move the cursor
*/
virtual void moveCursor(const Point &newPos) override;
diff --git a/engines/glk/windows.h b/engines/glk/windows.h
index 27380fa..4b71aa0 100644
--- a/engines/glk/windows.h
+++ b/engines/glk/windows.h
@@ -440,6 +440,11 @@ public:
}
/**
+ * Get the cursor position
+ */
+ virtual Point getCursor() const { return Point(); }
+
+ /**
* Move the cursor
*/
virtual void moveCursor(const Point &newPos);
Commit: d7c015a17e83c5bc0ce6ceb2601e15e14928b872
https://github.com/scummvm/scummvm/commit/d7c015a17e83c5bc0ce6ceb2601e15e14928b872
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Detect Infocom games using .zip extensions
Changed paths:
engines/glk/frotz/detection.cpp
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index 895dd4e..c869c92 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -46,7 +46,7 @@ PlainGameDescriptor FrotzMetaEngine::findGame(const char *gameId) {
}
bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
- const char *const EXTENSIONS[10] = { ".dat", ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb" };
+ const char *const EXTENSIONS[11] = { ".z1", ".z2", ".z3", ".z4", ".z5", ".z6", ".z7", ".z8", ".zblorb", ".dat", ".zip" };
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
@@ -55,7 +55,7 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
continue;
Common::String filename = file->getName();
bool hasExt = false;
- for (int idx = 0; idx < 10 && !hasExt; ++idx)
+ for (int idx = 0; idx < 11 && !hasExt; ++idx)
hasExt = filename.hasSuffixIgnoreCase(EXTENSIONS[idx]);
if (!hasExt)
continue;
@@ -83,8 +83,8 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
DetectedGame gd;
if (!p->_gameId) {
- // Generic .dat files don't get reported as matches unless they have a known md5
- if (filename.hasSuffixIgnoreCase(".dat"))
+ // Generic .dat/.zip files don't get reported as matches unless they have a known md5
+ if (filename.hasSuffixIgnoreCase(".dat") || filename.hasSuffixIgnoreCase(".zip"))
continue;
if (gDebugLevel > 0) {
Commit: 4894ce2134b6ec903c9be7dc26d9826ac947e008
https://github.com/scummvm/scummvm/commit/4894ce2134b6ec903c9be7dc26d9826ac947e008
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add all the new V6 methods, commented out until I can fix each one
Changed paths:
A engines/glk/frotz/processor_windows.cpp
engines/glk/frotz/config.cpp
engines/glk/frotz/processor.cpp
engines/glk/frotz/processor.h
engines/glk/frotz/processor_screen.cpp
engines/glk/module.mk
diff --git a/engines/glk/frotz/config.cpp b/engines/glk/frotz/config.cpp
index e53cd8c..1d0264b 100644
--- a/engines/glk/frotz/config.cpp
+++ b/engines/glk/frotz/config.cpp
@@ -96,9 +96,6 @@ void Header::loadHeader(Common::SeekableReadStream &f) {
if (h_version < V1 || h_version > V8)
error("Unknown Z-code version");
- if (h_version == V6)
- error("Cannot play Z-code version 6");
-
if (h_version == V3 && (h_config & CONFIG_BYTE_SWAPPED))
error("Byte swapped story file");
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index 09eb82b..e9f0d87 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -104,10 +104,10 @@ Opcode Processor::ext_opcodes[64] = {
&Processor::z_log_shift,
&Processor::z_art_shift,
&Processor::z_set_font,
- &Processor::__illegal__, // glkify - Processor::z_draw_picture,
- &Processor::__illegal__, // glkify - Processor::z_picture_data,
- &Processor::__illegal__, // glkify - Processor::z_erase_picture,
- &Processor::__illegal__, // glkify - Processor::z_set_margins,
+ &Processor::z_draw_picture,
+ &Processor::z_picture_data,
+ &Processor::z_erase_picture,
+ &Processor::z_set_margins,
&Processor::z_save_undo,
&Processor::z_restore_undo,
&Processor::z_print_unicode,
@@ -115,20 +115,20 @@ Opcode Processor::ext_opcodes[64] = {
&Processor::z_set_true_colour, // spec 1.1
&Processor::__illegal__,
&Processor::__illegal__,
- &Processor::__illegal__, // glkify - Processor::z_move_window,
- &Processor::__illegal__, // glkify - Processor::z_window_size,
- &Processor::__illegal__, // glkify - Processor::z_window_style,
- &Processor::__illegal__, // glkify - Processor::z_get_wind_prop,
- &Processor::__illegal__, // glkify - Processor::z_scroll_window,
+ &Processor::z_move_window,
+ &Processor::z_window_size,
+ &Processor::z_window_style,
+ &Processor::z_get_wind_prop,
+ &Processor::z_scroll_window,
&Processor::z_pop_stack,
- &Processor::__illegal__, // glkify - Processor::z_read_mouse,
- &Processor::__illegal__, // glkify - Processor::z_mouse_window,
+ &Processor::z_read_mouse,
+ &Processor::z_mouse_window,
&Processor::z_push_stack,
- &Processor::__illegal__, // glkify - Processor::z_put_wind_prop,
+ &Processor::z_put_wind_prop,
&Processor::z_print_form,
&Processor::z_make_menu,
- &Processor::__illegal__, // glkify - Processor::z_picture_table
- &Processor::z_buffer_screen, // spec 1.1
+ &Processor::z_picture_table,
+ &Processor::z_buffer_screen // spec 1.1
};
Processor::Processor(OSystem *syst, const GlkGameDescription &gameDesc) :
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index fb9c12f..dcf3986 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -1545,6 +1545,116 @@ protected:
void z_store();
/**@}*/
+
+ /**
+ * \defgroup Window/V6 Opcode methods
+ * @{
+ */
+
+ /**
+ * z_draw_picture, draw a picture.
+ *
+ * zargs[0] = number of picture to draw
+ * zargs[1] = y-coordinate of top left corner
+ * zargs[2] = x-coordinate of top left corner
+ */
+ void z_draw_picture();
+
+ /**
+ * Get information on a picture or the graphics file.
+ *
+ * zargs[0] = number of picture or 0 for the graphics file
+ * zargs[1] = address to write information to
+ */
+ void z_picture_data();
+
+ /**
+ * Erase a picture with background colour.
+ *
+ * zargs[0] = number of picture to erase
+ * zargs[1] = y-coordinate of top left corner (optional)
+ * zargs[2] = x-coordinate of top left corner (optional)
+ */
+ void z_erase_picture();
+
+ /**
+ * Set the left and right margins of a window.
+ *
+ * zargs[0] = left margin in pixels
+ * zargs[1] = right margin in pixels
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_margins();
+
+
+ /**
+ * Place a window on the screen.
+ *
+ * zargs[0] = window (-3 is the current one)
+ * zargs[1] = y-coordinate
+ * zargs[2] = x-coordinate
+ *
+ */
+ void z_move_window();
+
+ /**
+ * Change the width and height of a window.
+ *
+ * zargs[0] = window (-3 is the current one)
+ * zargs[1] = new height in screen units
+ * zargs[2] = new width in screen units
+ */
+ void z_window_size();
+
+ /**
+ * Set / clear / toggle window attributes.
+ *
+ * zargs[0] = window (-3 is the current one)
+ * zargs[1] = window attribute flags
+ * zargs[2] = operation to perform (optional, defaults to 0)
+ */
+ void z_window_style();
+
+ /**
+ * Store the value of a window property.
+ *
+ * zargs[0] = window (-3 is the current one)
+ * zargs[1] = number of window property to be stored
+ */
+ void z_get_wind_prop();
+
+ /**
+ * Set the value of a window property.
+ *
+ * zargs[0] = window (-3 is the current one)
+ * zargs[1] = number of window property to set
+ * zargs[2] = value to set window property to
+ */
+ void z_put_wind_prop();
+
+ /**
+ * Scroll a window up or down.
+ *
+ * zargs[0] = window (-3 is the current one)
+ * zargs[1] = #screen units to scroll up (positive) or down (negative)
+ */
+ void z_scroll_window();
+
+ /**
+ * Select a window as mouse window.
+ *
+ * zargs[0] = window number (-3 is the current) or -1 for the screen
+ */
+ void z_mouse_window();
+
+ /**
+ * Prepare a group of pictures for faster display.
+ *
+ * zargs[0] = address of table holding the picture numbers
+ */
+ void z_picture_table();
+
+ /**@}*/
public:
/**
* Constructor
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
index 2ec0128..3adec66 100644
--- a/engines/glk/frotz/processor_screen.cpp
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -127,7 +127,11 @@ void Processor::z_buffer_mode() {
}
void Processor::z_buffer_screen() {
+#ifdef TODO
+store((zword)os_buffer_screen((zargs[0] == (zword)-1) ? -1 : zargs[0]));
+#else
store(0);
+#endif
}
void Processor::z_erase_line() {
diff --git a/engines/glk/frotz/processor_windows.cpp b/engines/glk/frotz/processor_windows.cpp
new file mode 100644
index 0000000..2f1956f
--- /dev/null
+++ b/engines/glk/frotz/processor_windows.cpp
@@ -0,0 +1,316 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/processor.h"
+
+namespace Glk {
+namespace Frotz {
+
+static struct {
+ Story story_id;
+ int pic;
+ int pic1;
+ int pic2;
+} mapper[] = {
+ { ZORK_ZERO, 5, 497, 498 },
+ { ZORK_ZERO, 6, 501, 502 },
+ { ZORK_ZERO, 7, 499, 500 },
+ { ZORK_ZERO, 8, 503, 504 },
+ { ARTHUR, 54, 170, 171 },
+ { SHOGUN, 50, 61, 62 },
+ { UNKNOWN, 0, 0, 0 }
+};
+
+void Processor::z_draw_picture() {
+#ifdef TODO
+ zword pic = zargs[0];
+ zword y = zargs[1];
+ zword x = zargs[2];
+ int i;
+
+ flush_buffer ();
+
+ if (y == 0) // use cursor line if y-coordinate is 0
+ y = cwp->y_cursor;
+ if (x == 0) // use cursor column if x-coordinate is 0 */
+ x = cwp->x_cursor;
+
+ y += cwp->y_pos - 1;
+ x += cwp->x_pos - 1;
+
+ /* The following is necessary to make Amiga and Macintosh story
+ files work with MCGA graphics files. Some screen-filling
+ pictures of the original Amiga release like the borders of
+ Zork Zero were split into several MCGA pictures (left, right
+ and top borders). We pretend this has not happened. */
+
+ for (i = 0; mapper[i].story_id != UNKNOWN; i++) {
+ if (_storyId == mapper[i].story_id && pic == mapper[i].pic) {
+ int height1, width1;
+ int height2, width2;
+
+ int delta = 0;
+
+ os_picture_data (pic, &height1, &width1);
+ os_picture_data (mapper[i].pic2, &height2, &width2);
+
+ if (_storyId == ARTHUR && pic == 54)
+ delta = h_screen_width / 160;
+
+ os_draw_picture(mapper[i].pic1, gos_lower, Point(x + delta, y + height1));
+ os_draw_picture(mapper[i].pic2, gos_lower, Point(x + width1 - width2 - delta, y + height1));
+ }
+ }
+
+ os_draw_picture(pic, gos_lower, Point(x, y));
+
+ if (_storyId == SHOGUN && pic == 3) {
+ glui32 height, width;
+
+ os_picture_data(59, &height, &width);
+ os_draw_picture(59, gos_lower, Point(h_screen_width - width + 1, y));
+ }
+#endif
+}
+
+void Processor::z_picture_data() {
+#ifdef TODO
+ zword pic = zargs[0];
+ zword table = zargs[1];
+
+ int height, width;
+ int i;
+
+ bool avail = os_picture_data(pic, &height, &width);
+
+ for (i = 0; mapper[i].story_id != UNKNOWN; i++)
+
+ if (story_id == mapper[i].story_id) {
+
+ if (pic == mapper[i].pic) {
+
+ int height2, width2;
+
+ avail &= os_picture_data(mapper[i].pic1, &height2, &width2);
+ avail &= os_picture_data(mapper[i].pic2, &height2, &width2);
+
+ height += height2;
+
+ }
+ else if (pic == mapper[i].pic1 || pic == mapper[i].pic2)
+
+ avail = FALSE;
+ }
+
+ storew((zword)(table + 0), (zword)(height));
+ storew((zword)(table + 2), (zword)(width));
+
+ branch(avail);
+#endif
+}
+
+void Processor::z_erase_picture() {
+#ifdef TODO
+ int height, width;
+
+ zword y = zargs[1];
+ zword x = zargs[2];
+
+ flush_buffer();
+
+ /* Do nothing if the background is transparent */
+
+ if (hi(cwp->colour) == TRANSPARENT_COLOUR)
+ return;
+
+ if (y == 0) /* use cursor line if y-coordinate is 0 */
+ y = cwp->y_cursor;
+ if (x == 0) /* use cursor column if x-coordinate is 0 */
+ x = cwp->x_cursor;
+
+ os_picture_data(zargs[0], &height, &width);
+
+ y += cwp->y_pos - 1;
+ x += cwp->x_pos - 1;
+
+ os_erase_area(y, x, y + height - 1, x + width - 1, -1);
+#endif
+}
+
+void Processor::z_set_margins() {
+#ifdef TODO
+ zword win = winarg2();
+
+ flush_buffer();
+
+ wp[win].left = zargs[0];
+ wp[win].right = zargs[1];
+
+ /* Protect the margins */
+
+ if (wp[win].x_cursor <= zargs[0] || wp[win].x_cursor > wp[win].x_size - zargs[1]) {
+
+ wp[win].x_cursor = zargs[0] + 1;
+
+ if (win == cwin)
+ update_cursor();
+
+ }
+#endif
+}
+
+void Processor::z_move_window(void) {
+#ifdef TODO
+ zword win = winarg0();
+
+ flush_buffer();
+
+ wp[win].y_pos = zargs[1];
+ wp[win].x_pos = zargs[2];
+
+ if (win == cwin)
+ update_cursor();
+#endif
+}
+
+void Processor::z_window_size() {
+#ifdef TODO
+ zword win = winarg0();
+
+ flush_buffer();
+
+ wp[win].y_size = zargs[1];
+ wp[win].x_size = zargs[2];
+
+ /* Keep the cursor within the window */
+
+ if (wp[win].y_cursor > zargs[1] || wp[win].x_cursor > zargs[2])
+ reset_cursor(win);
+
+ os_window_height(win, wp[win].y_size);
+#endif
+}
+
+void Processor::z_window_style() {
+#ifdef TODO
+ zword win = winarg0();
+ zword flags = zargs[1];
+
+ flush_buffer();
+
+ /* Supply default arguments */
+
+ if (zargc < 3)
+ zargs[2] = 0;
+
+ /* Set window style */
+
+ switch (zargs[2]) {
+ case 0: wp[win].attribute = flags; break;
+ case 1: wp[win].attribute |= flags; break;
+ case 2: wp[win].attribute &= ~flags; break;
+ case 3: wp[win].attribute ^= flags; break;
+ }
+
+ if (cwin == win)
+ update_attributes();
+#endif
+}
+
+void Processor::z_get_wind_prop() {
+#ifdef TODO
+ flush_buffer();
+
+ if (zargs[1] < 16)
+ store(((zword *)(wp + winarg0()))[zargs[1]]);
+
+ else if (zargs[1] == 16)
+ store(os_to_true_colour(lo(wp[winarg0()].colour)));
+
+ else if (zargs[1] == 17) {
+
+ zword bg = hi(wp[winarg0()].colour);
+
+ if (bg == TRANSPARENT_COLOUR)
+ store((zword)-4);
+ else
+ store(os_to_true_colour(bg));
+
+ }
+ else
+ runtime_error(ERR_ILL_WIN_PROP);
+#endif
+}
+
+void Processor::z_put_wind_prop() {
+#ifdef TODO
+ flush_buffer();
+
+ if (zargs[1] >= 16)
+ runtime_error(ERR_ILL_WIN_PROP);
+
+ ((zword *)(wp + winarg0()))[zargs[1]] = zargs[2];
+#endif
+}
+
+void Processor::z_scroll_window() {
+#ifdef TODO
+ zword win = winarg0();
+ zword y, x;
+
+ flush_buffer();
+
+ /* Use the correct set of colours when scrolling the window */
+
+ if (win != cwin && !amiga_screen_model())
+ os_set_colour(lo(wp[win].colour), hi(wp[win].colour));
+
+ y = wp[win].y_pos;
+ x = wp[win].x_pos;
+
+ os_scroll_area(y,
+ x,
+ y + wp[win].y_size - 1,
+ x + wp[win].x_size - 1,
+ (short)zargs[1]);
+
+ if (win != cwin && !amiga_screen_model())
+ os_set_colour(lo(cwp->colour), hi(cwp->colour));
+#endif
+}
+
+void Processor::z_mouse_window() {
+#ifdef TODO
+ mwin = ((short)zargs[0] == -1) ? -1 : winarg0();
+#endif
+}
+
+void Processor::z_picture_table() {
+ /* This opcode is used by Shogun and Zork Zero when the player
+ * encounters built-in games such as Peggleboz. Nowadays it is
+ * not very helpful to hold the picture data in memory because
+ * even a small disk cache avoids re-loading of data.
+ */
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 003f8dc..dd0c2a4 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -39,6 +39,7 @@ MODULE_OBJS := \
frotz/processor_table.o \
frotz/processor_text.o \
frotz/processor_variables.o \
+ frotz/processor_windows.o \
frotz/quetzal.o \
frotz/screen.o \
scott/detection.o \
Commit: 7fda941302358b55d05005837e7719d33bf6ede7
https://github.com/scummvm/scummvm/commit/7fda941302358b55d05005837e7719d33bf6ede7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Implement some of the V6 opcodes
Changed paths:
engines/glk/frotz/processor_windows.cpp
diff --git a/engines/glk/frotz/processor_windows.cpp b/engines/glk/frotz/processor_windows.cpp
index 2f1956f..34c3be1 100644
--- a/engines/glk/frotz/processor_windows.cpp
+++ b/engines/glk/frotz/processor_windows.cpp
@@ -41,37 +41,43 @@ static struct {
};
void Processor::z_draw_picture() {
-#ifdef TODO
- zword pic = zargs[0];
- zword y = zargs[1];
- zword x = zargs[2];
- int i;
-
- flush_buffer ();
-
- if (y == 0) // use cursor line if y-coordinate is 0
- y = cwp->y_cursor;
- if (x == 0) // use cursor column if x-coordinate is 0 */
- x = cwp->x_cursor;
+ zword pic = zargs[0];
+ zword y = zargs[1];
+ zword x = zargs[2];
+ int i;
- y += cwp->y_pos - 1;
- x += cwp->x_pos - 1;
+ flush_buffer ();
+
+ if (!x || !y) {
+ // Currently I only support getting the cursor for the text grid area
+ assert(cwin == 1);
+ Point cursPos = gos_upper->getCursor();
+ // use cursor column if x-coordinate is 0
+ if (!x)
+ x = cursPos.x;
+ // use cursor line if y-coordinate is 0
+ if (!y)
+ y = cursPos.y;
+ }
- /* The following is necessary to make Amiga and Macintosh story
- files work with MCGA graphics files. Some screen-filling
- pictures of the original Amiga release like the borders of
- Zork Zero were split into several MCGA pictures (left, right
- and top borders). We pretend this has not happened. */
+// y += cwp->y_pos - 1;
+// x += cwp->x_pos - 1;
- for (i = 0; mapper[i].story_id != UNKNOWN; i++) {
+ /* The following is necessary to make Amiga and Macintosh story
+ * files work with MCGA graphics files. Some screen-filling
+ * pictures of the original Amiga release like the borders of
+ * Zork Zero were split into several MCGA pictures (left, right
+ * and top borders). We pretend this has not happened.
+ */
+ for (i = 0; mapper[i].story_id != UNKNOWN; i++) {
if (_storyId == mapper[i].story_id && pic == mapper[i].pic) {
- int height1, width1;
- int height2, width2;
+ glui32 height1, width1;
+ glui32 height2, width2;
int delta = 0;
- os_picture_data (pic, &height1, &width1);
- os_picture_data (mapper[i].pic2, &height2, &width2);
+ os_picture_data(pic, &height1, &width1);
+ os_picture_data(mapper[i].pic2, &height2, &width2);
if (_storyId == ARTHUR && pic == 54)
delta = h_screen_width / 160;
@@ -81,51 +87,43 @@ void Processor::z_draw_picture() {
}
}
- os_draw_picture(pic, gos_lower, Point(x, y));
+ os_draw_picture(pic, gos_lower, Point(x, y));
- if (_storyId == SHOGUN && pic == 3) {
- glui32 height, width;
+ if (_storyId == SHOGUN && pic == 3) {
+ glui32 height, width;
- os_picture_data(59, &height, &width);
- os_draw_picture(59, gos_lower, Point(h_screen_width - width + 1, y));
+ os_picture_data(59, &height, &width);
+ os_draw_picture(59, gos_lower, Point(h_screen_width - width + 1, y));
}
-#endif
}
void Processor::z_picture_data() {
-#ifdef TODO
zword pic = zargs[0];
zword table = zargs[1];
-
- int height, width;
+ glui32 height, width;
int i;
bool avail = os_picture_data(pic, &height, &width);
- for (i = 0; mapper[i].story_id != UNKNOWN; i++)
-
- if (story_id == mapper[i].story_id) {
-
+ for (i = 0; mapper[i].story_id != UNKNOWN; i++) {
+ if (_storyId == mapper[i].story_id) {
if (pic == mapper[i].pic) {
-
- int height2, width2;
+ glui32 height2, width2;
avail &= os_picture_data(mapper[i].pic1, &height2, &width2);
avail &= os_picture_data(mapper[i].pic2, &height2, &width2);
height += height2;
-
+ } else if (pic == mapper[i].pic1 || pic == mapper[i].pic2) {
+ avail = false;
}
- else if (pic == mapper[i].pic1 || pic == mapper[i].pic2)
-
- avail = FALSE;
}
+ }
storew((zword)(table + 0), (zword)(height));
storew((zword)(table + 2), (zword)(width));
branch(avail);
-#endif
}
void Processor::z_erase_picture() {
@@ -299,9 +297,8 @@ void Processor::z_scroll_window() {
}
void Processor::z_mouse_window() {
-#ifdef TODO
- mwin = ((short)zargs[0] == -1) ? -1 : winarg0();
-#endif
+ // No implementation - since ScummVM can run as a window, it's better
+ // not to constrain the area the mouse can move
}
void Processor::z_picture_table() {
Commit: ab8ff73453005f55acdf13ebbc39cb3acb7aa74a
https://github.com/scummvm/scummvm/commit/ab8ff73453005f55acdf13ebbc39cb3acb7aa74a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Fix handling of empty rect picture resources
Changed paths:
engines/glk/frotz/pics.cpp
engines/glk/picture.cpp
diff --git a/engines/glk/frotz/pics.cpp b/engines/glk/frotz/pics.cpp
index 4953f04..2d05fc9 100644
--- a/engines/glk/frotz/pics.cpp
+++ b/engines/glk/frotz/pics.cpp
@@ -24,6 +24,7 @@
#include "glk/frotz/pics_decoder.h"
#include "glk/glk.h"
#include "common/algorithm.h"
+#include "common/memstream.h"
namespace Glk {
namespace Frotz {
@@ -68,7 +69,10 @@ Pics::Pics() : Common::Archive(), _filename(getFilename()) {
}
}
- e._filename = Common::String::format("pic%u.raw", e._number);
+ if (e._dataOffset)
+ e._filename = Common::String::format("pic%u.raw", e._number);
+ else
+ e._filename = Common::String::format("pic%u.rect", e._number);
}
// Further processing of index to calculate data sizes
@@ -128,6 +132,8 @@ const Common::ArchiveMemberPtr Pics::getMember(const Common::String &name) const
}
Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::String &name) const {
+ PictureDecoder decoder;
+
for (uint idx = 0; idx < _index.size(); ++idx) {
const Entry &e = _index[idx];
if (e._filename.equalsIgnoreCase(name)) {
@@ -137,19 +143,21 @@ Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::String
if (!f.open(_filename))
error("Reading failed");
- // Read in the image's palette
- assert(e._paletteOffset);
- f.seek(e._paletteOffset);
- palette.resize(f.readByte() * 3);
- f.read(&palette[0], palette.size());
-
- PictureDecoder decoder;
if (e._dataSize) {
+ // Read in the image's palette
+ assert(e._paletteOffset);
+ f.seek(e._paletteOffset);
+ palette.resize(f.readByte() * 3);
+ f.read(&palette[0], palette.size());
+
Common::SeekableReadStream *src = f.readStream(e._dataSize);
dest = decoder.decode(*src, e._flags, palette, MCGA, e._width, e._height);
delete src;
} else {
- error("TODO: Empty rect renderings");
+ byte *rect = (byte *)malloc(2 * sizeof(uint16));
+ WRITE_LE_UINT16(rect, e._width);
+ WRITE_LE_UINT16(rect + 2, e._height);
+ dest = new Common::MemoryReadStream(rect, 2 * sizeof(uint16), DisposeAfterUse::YES);
}
f.close();
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 631f9be..c7c8f70 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -103,6 +103,7 @@ Picture *Pictures::retrieve(uint id, bool scaled) {
Picture *Pictures::load(uint32 id) {
::Image::PNGDecoder png;
::Image::JPEGDecoder jpg;
+ Graphics::Surface rectImg;
RawDecoder raw;
const Graphics::Surface *img;
const byte *palette = nullptr;
@@ -128,6 +129,10 @@ Picture *Pictures::load(uint32 id) {
img = raw.getSurface();
palette = raw.getPalette();
palCount = raw.getPaletteColorCount();
+ } else if (f.open(Common::String::format("pic%u.rect", id))) {
+ rectImg.w = f.readUint16LE();
+ rectImg.h = f.readUint16LE();
+ img = &rectImg;
} else {
// No such picture
return nullptr;
@@ -138,7 +143,9 @@ Picture *Pictures::load(uint32 id) {
pic->_id = id;
pic->_scaled = false;
- if (!palette) {
+ if (!img->getPixels()) {
+ // Area definition without any content
+ } else if (!palette) {
pic->blitFrom(*img);
} else {
uint pal[256];
Commit: 88b47cdd8bd20e54fcfdf5e98c24c8e7d0c97415
https://github.com/scummvm/scummvm/commit/88b47cdd8bd20e54fcfdf5e98c24c8e7d0c97415
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Added winarg methods
Changed paths:
engines/glk/frotz/processor.h
engines/glk/frotz/processor_windows.cpp
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
index dcf3986..5d6d448 100644
--- a/engines/glk/frotz/processor.h
+++ b/engines/glk/frotz/processor.h
@@ -549,7 +549,6 @@ protected:
/**
* Map a Unicode character onto the ZSCII alphabet.
- *
*/
zbyte translate_to_zscii(zchar c);
@@ -668,6 +667,26 @@ protected:
zchar unicode_tolower(zchar c);
/**@}*/
+
+ /**
+ * \defgroup Window/V6 Opcode methods
+ * @{
+ */
+
+ /**
+ * Return the window number in zargs[0]. In V6 only, -3 refers to the
+ * current window.
+ */
+ zword winarg0();
+
+ /**
+ * Return the (optional) window number in zargs[2]. -3 refers to the
+ * current window. This optional window number was only used by some
+ * V6 opcodes: set_cursor, set_margins, set_colour.
+ */
+ zword winarg2();
+
+ /**@}*/
protected:
/**
* \defgroup General Opcode methods
diff --git a/engines/glk/frotz/processor_windows.cpp b/engines/glk/frotz/processor_windows.cpp
index 34c3be1..5e24ac8 100644
--- a/engines/glk/frotz/processor_windows.cpp
+++ b/engines/glk/frotz/processor_windows.cpp
@@ -255,7 +255,7 @@ void Processor::z_get_wind_prop() {
}
else
- runtime_error(ERR_ILL_WIN_PROP);
+ runtimeError(ERR_ILL_WIN_PROP);
#endif
}
@@ -264,7 +264,7 @@ void Processor::z_put_wind_prop() {
flush_buffer();
if (zargs[1] >= 16)
- runtime_error(ERR_ILL_WIN_PROP);
+ runtimeError(ERR_ILL_WIN_PROP);
((zword *)(wp + winarg0()))[zargs[1]] = zargs[2];
#endif
@@ -309,5 +309,25 @@ void Processor::z_picture_table() {
*/
}
+zword Processor::winarg0() {
+ if (h_version == V6 && (short)zargs[0] == -3)
+ return cwin;
+
+ if (zargs[0] >= ((h_version == V6) ? 8 : 2))
+ runtimeError(ERR_ILL_WIN);
+
+ return zargs[0];
+}
+
+zword Processor::winarg2() {
+ if (zargc < 3 || (short)zargs[2] == -3)
+ return cwin;
+
+ if (zargs[2] >= 8)
+ runtimeError(ERR_ILL_WIN);
+
+ return zargs[2];
+}
+
} // End of namespace Scott
} // End of namespace Glk
Commit: 2ae0edd58ba0258b4f3278e334468b12a0b73573
https://github.com/scummvm/scummvm/commit/2ae0edd58ba0258b4f3278e334468b12a0b73573
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Add sound playing code
Changed paths:
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/processor.cpp
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index 7367375..f800f73 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -279,11 +279,27 @@ bool GlkInterface::os_picture_data(int picture, glui32 *height, glui32 *width) {
}
void GlkInterface::start_sample(int number, int volume, int repeats, zword eos) {
- // TODO
+ static zbyte LURKING_REPEATS[] = {
+ 0x00, 0x00, 0x00, 0x01, 0xff,
+ 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0xff, 0x01, 0x01, 0xff, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+ if (_storyId == LURKING_HORROR)
+ repeats = LURKING_REPEATS[number];
+
+ os_start_sample(number, volume, repeats, eos);
+
+ _soundPlaying = true;
}
void GlkInterface::start_next_sample() {
- // TODO
+ if (next_sample != 0)
+ start_sample(next_sample, next_volume, 0, 0);
+
+ next_sample = 0;
+ next_volume = 0;
}
void GlkInterface::gos_update_width() {
diff --git a/engines/glk/frotz/processor.cpp b/engines/glk/frotz/processor.cpp
index e9f0d87..8cfff9c 100644
--- a/engines/glk/frotz/processor.cpp
+++ b/engines/glk/frotz/processor.cpp
@@ -628,12 +628,11 @@ void Processor::z_sound_effect() {
_soundPlaying = false;
switch (effect) {
-
case EFFECT_PREPARE:
- os_prepare_sample (number);
+ os_prepare_sample(number);
break;
case EFFECT_PLAY:
- start_sample(number, lo (volume), hi (volume), (zargc == 4) ? zargs[3] : 0);
+ start_sample(number, lo(volume), hi(volume), (zargc == 4) ? zargs[3] : 0);
break;
case EFFECT_STOP:
os_stop_sample (number);
Commit: f6abb3ea33c7b073066732f794a9d071c38a044d
https://github.com/scummvm/scummvm/commit/f6abb3ea33c7b073066732f794a9d071c38a044d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Simplify accessing sounds for Lurking Horror & Sherlock
Changed paths:
A engines/glk/frotz/sound_folder.cpp
A engines/glk/frotz/sound_folder.h
engines/glk/frotz/glk_interface.cpp
engines/glk/frotz/glk_interface.h
engines/glk/module.mk
diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp
index f800f73..79907cb 100644
--- a/engines/glk/frotz/glk_interface.cpp
+++ b/engines/glk/frotz/glk_interface.cpp
@@ -22,8 +22,11 @@
#include "glk/frotz/glk_interface.h"
#include "glk/frotz/pics.h"
+#include "glk/frotz/sound_folder.h"
#include "glk/conf.h"
#include "glk/screen.h"
+#include "common/config-manager.h"
+#include "common/unzip.h"
namespace Glk {
namespace Frotz {
@@ -52,49 +55,49 @@ void GlkInterface::initialize() {
* Init glk stuff
*/
- // monor
- glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Oblique, 0);
+ // monor
+ glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Preformatted, stylehint_Oblique, 0);
// monob
- glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Oblique, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Subheader, stylehint_Oblique, 0);
// monoi
- glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Oblique, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Alert, stylehint_Oblique, 1);
// monoz
- glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Oblique, 1);
+ glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_BlockQuote, stylehint_Oblique, 1);
// propr
- glk_stylehint_set(wintype_TextBuffer, style_Normal, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Normal, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Oblique, 0);
+ glk_stylehint_set(wintype_TextBuffer, style_Normal, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Normal, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Normal, stylehint_Oblique, 0);
// propb
- glk_stylehint_set(wintype_TextBuffer, style_Header, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Header, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Oblique, 0);
+ glk_stylehint_set(wintype_TextBuffer, style_Header, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Header, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Header, stylehint_Oblique, 0);
// propi
- glk_stylehint_set(wintype_TextBuffer, style_Emphasized, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Emphasized, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Weight, 0);
- glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Oblique, 1);
+ glk_stylehint_set(wintype_TextBuffer, style_Emphasized, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Emphasized, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Weight, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Emphasized, stylehint_Oblique, 1);
// propi
- glk_stylehint_set(wintype_TextBuffer, style_Note, stylehint_Proportional, 1);
- glk_stylehint_set(wintype_TextGrid, style_Note, stylehint_Proportional, 0);
- glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Weight, 1);
- glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Oblique, 1);
+ glk_stylehint_set(wintype_TextBuffer, style_Note, stylehint_Proportional, 1);
+ glk_stylehint_set(wintype_TextGrid, style_Note, stylehint_Proportional, 0);
+ glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Weight, 1);
+ glk_stylehint_set(wintype_AllTypes, style_Note, stylehint_Oblique, 1);
/*
* Get the screen size
@@ -123,7 +126,7 @@ void GlkInterface::initialize() {
if (h_version >= V4)
h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS |
- CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR;
+ CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR;
if (h_version >= V5)
h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG);
@@ -134,7 +137,7 @@ void GlkInterface::initialize() {
if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG))
h_flags |= OLD_SOUND_FLAG;
- if ((h_version == 6) && (_sound != 0))
+ if ((h_version == 6) && (_sound != 0))
h_config |= CONFIG_SOUND;
if (h_version >= V5 && (h_flags & UNDO_FLAG))
@@ -188,6 +191,15 @@ void GlkInterface::initialize() {
// Set the screen colors
garglk_set_zcolors(_defaultForeground, _defaultBackground);
+
+ // Add any sound folder or zip
+ addSound();
+}
+
+void GlkInterface::addSound() {
+ Common::FSNode gameDir(ConfMan.get("path"));
+ SoundSubfolder::check(gameDir);
+ SoundZip::check(gameDir, _storyId);
}
bool GlkInterface::initPictures() {
diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h
index 4e531ee..ce5da8a 100644
--- a/engines/glk/frotz/glk_interface.h
+++ b/engines/glk/frotz/glk_interface.h
@@ -105,6 +105,11 @@ private:
* Displays the title screen for the game Beyond Zork
*/
void showBeyondZorkTitle();
+
+ /**
+ * Add any Sound subfolder or sound zip file for access
+ */
+ void addSound();
protected:
/**
* Return the length of the character in screen units.
diff --git a/engines/glk/frotz/sound_folder.cpp b/engines/glk/frotz/sound_folder.cpp
new file mode 100644
index 0000000..20f22a8
--- /dev/null
+++ b/engines/glk/frotz/sound_folder.cpp
@@ -0,0 +1,146 @@
+/* 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.
+ *
+ */
+
+#include "glk/frotz/sound_folder.h"
+#include "common/file.h"
+#include "common/unzip.h"
+
+namespace Glk {
+namespace Frotz {
+
+void SoundSubfolder::check(const Common::FSNode &gameDir) {
+ Common::FSNode sound = gameDir.getChild("sound");
+ if (sound.isDirectory())
+ SearchMan.add("sound", new SoundSubfolder(sound));
+}
+
+SoundSubfolder::SoundSubfolder(const Common::FSNode &folder) : _folder(folder) {
+ Common::FSList files;
+ if (folder.getChildren(files, Common::FSNode::kListFilesOnly)) {
+ for (uint idx = 0; idx < files.size(); ++idx) {
+ Common::String filename = files[idx].getName();
+ if (filename.hasSuffixIgnoreCase(".snd")) {
+ int fileNum = atoi(filename.c_str() + filename.size() - 6);
+ Common::String newName = Common::String::format("sound%d.snd", fileNum);
+
+ _filenames[newName] = filename;
+ }
+ }
+ }
+}
+
+bool SoundSubfolder::hasFile(const Common::String &name) const {
+ return _filenames.contains(name);
+}
+
+int SoundSubfolder::listMembers(Common::ArchiveMemberList &list) const {
+ int total = 0;
+ for (Common::StringMap::iterator i = _filenames.begin(); i != _filenames.end(); ++i) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember((*i)._key, this)));
+ ++total;
+ }
+
+ return total;
+}
+
+const Common::ArchiveMemberPtr SoundSubfolder::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *SoundSubfolder::createReadStreamForMember(const Common::String &name) const {
+ Common::File *f = new Common::File();
+ if (f->open(_folder.getChild(name)))
+ return f;
+
+ delete f;
+ return nullptr;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void SoundZip::check(const Common::FSNode &gameDir, Story story) {
+ if (story != LURKING_HORROR && story != SHERLOCK)
+ return;
+ Common::String zipName = (story == LURKING_HORROR) ? "lhsound.zip" : "shsound.zip";
+
+ // Check for the existance of the zip
+ Common::FSNode zipNode = gameDir.getChild(zipName);
+ if (!zipNode.exists())
+ return;
+
+ SearchMan.add("sound", Common::makeZipArchive(zipNode));
+}
+
+SoundZip::SoundZip(Common::Archive *zip) : _zip(zip) {
+ Common::ArchiveMemberList files;
+ zip->listMembers(files);
+
+ for (Common::ArchiveMemberList::iterator i = files.begin(); i != files.end(); ++i) {
+ Common::String filename = (*i)->getName();
+ if (filename.hasSuffixIgnoreCase(".snd")) {
+ int fileNum = atoi(filename.c_str() + filename.size() - 6);
+ Common::String newName = Common::String::format("sound%d.snd", fileNum);
+
+ _filenames[newName] = filename;
+ }
+ }
+}
+
+SoundZip::~SoundZip() {
+ delete _zip;
+}
+
+bool SoundZip::hasFile(const Common::String &name) const {
+ return _filenames.contains(name);
+}
+
+int SoundZip::listMembers(Common::ArchiveMemberList &list) const {
+ int total = 0;
+
+ for (Common::StringMap::iterator i = _filenames.begin(); i != _filenames.end(); ++i) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember((*i)._key, this)));
+ ++total;
+ }
+
+ return total;
+}
+
+const Common::ArchiveMemberPtr SoundZip::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+
+}
+
+Common::SeekableReadStream *SoundZip::createReadStreamForMember(const Common::String &name) const {
+ if (!_filenames.contains(name))
+ return nullptr;
+
+ return _zip->createReadStreamForMember(_filenames[name]);
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/frotz/sound_folder.h b/engines/glk/frotz/sound_folder.h
new file mode 100644
index 0000000..50eef06
--- /dev/null
+++ b/engines/glk/frotz/sound_folder.h
@@ -0,0 +1,138 @@
+/* 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_FROTZ_SOUND_FOLDER_H
+#define GLK_FROTZ_SOUND_FOLDER_H
+
+#include "glk/frotz/frotz_types.h"
+#include "common/archive.h"
+#include "common/fs.h"
+#include "common/hash-str.h"
+
+namespace Glk {
+namespace Frotz {
+
+/**
+ * Acts as an interface to an Infocom sound subfolder for the Lurking Horror or
+ * Sherlock. Any file which ends with a number and '.snd' will be accessible as
+ * 'sound<num>.snd' in the outer Glk layer
+ */
+class SoundSubfolder : public Common::Archive {
+private:
+ Common::FSNode _folder;
+ Common::StringMap _filenames;
+private:
+ /**
+ * Constructor
+ */
+ SoundSubfolder(const Common::FSNode &folder);
+public:
+ /**
+ * Checks for a sound subfolder, and if so, instantiates the class for it
+ */
+ static void check(const Common::FSNode &gameDir);
+
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ virtual bool hasFile(const Common::String &name) const override;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ virtual int listMembers(Common::ArchiveMemberList &list) const override;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+};
+
+/**
+ * Acts as an interface to a Zip file from if-archive for the Lurking Horror or
+ * Sherlock. Any file which ends with a number and '.snd' will be accessible as
+ * 'sound<num>.snd' in the outer Glk layer
+ */
+class SoundZip : public Common::Archive {
+private:
+ Common::Archive *_zip;
+ Common::StringMap _filenames;
+private:
+ /**
+ * Constructor
+ */
+ SoundZip(Common::Archive *zip);
+public:
+ /**
+ * Checks for a sound subfolder, and if so, instantiates the class for it
+ */
+ static void check(const Common::FSNode &gameDir, Story story);
+
+ /**
+ * Destructor
+ */
+ ~SoundZip();
+
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ virtual bool hasFile(const Common::String &name) const override;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ virtual int listMembers(Common::ArchiveMemberList &list) const override;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+};
+
+} // End of namespace Frotz
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index dd0c2a4..c09bfac 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -42,6 +42,7 @@ MODULE_OBJS := \
frotz/processor_windows.o \
frotz/quetzal.o \
frotz/screen.o \
+ frotz/sound_folder.o \
scott/detection.o \
scott/scott.o \
tads/detection.o \
Commit: 3661fc61ec319752a767e5981581ded026a57dd1
https://github.com/scummvm/scummvm/commit/3661fc61ec319752a767e5981581ded026a57dd1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Beginnings of Sounds manager
Changed paths:
A engines/glk/sound.cpp
A engines/glk/sound.h
engines/glk/blorb.cpp
engines/glk/glk.cpp
engines/glk/glk.h
engines/glk/glk_api.cpp
engines/glk/glk_api.h
engines/glk/glk_types.h
engines/glk/module.mk
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 038a79e..5ffd0b0 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -146,7 +146,7 @@ Common::ErrorCode Blorb::load() {
ce._filename += ".rect";
} else if (ce._type == ID_Snd) {
- ce._filename = Common::String::format("snd%u", ce._number);
+ ce._filename = Common::String::format("sound%u", ce._number);
if (ce._id == ID_MIDI)
ce._filename += ".midi";
else if (ce._id == ID_MP3)
@@ -156,7 +156,7 @@ Common::ErrorCode Blorb::load() {
else if (ce._id == ID_AIFF)
ce._filename += ".aiff";
else if (ce._id == ID_OGG)
- ce._filename += ".ogg";
+ ce._filename += ".ogg";
else if (ce._id == ID_MOD)
ce._filename += ".mod";
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index a22f9e9..c8a63c5 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -35,6 +35,7 @@
#include "glk/picture.h"
#include "glk/screen.h"
#include "glk/selection.h"
+#include "glk/sound.h"
#include "glk/streams.h"
#include "glk/windows.h"
@@ -45,9 +46,9 @@ GlkEngine *g_vm;
GlkEngine::GlkEngine(OSystem *syst, const GlkGameDescription &gameDesc) :
_gameDescription(gameDesc), Engine(syst), _random("Glk"), _blorb(nullptr),
_clipboard(nullptr), _conf(nullptr), _events(nullptr), _pictures(nullptr),
- _screen(nullptr), _selection(nullptr), _windows(nullptr), _copySelect(false),
- _terminated(false), gli_unregister_obj(nullptr), gli_register_arr(nullptr),
- gli_unregister_arr(nullptr) {
+ _screen(nullptr), _selection(nullptr), _sounds(nullptr), _windows(nullptr),
+ _copySelect(false), _terminated(false), gli_unregister_obj(nullptr),
+ gli_register_arr(nullptr), gli_unregister_arr(nullptr) {
g_vm = this;
}
@@ -59,6 +60,7 @@ GlkEngine::~GlkEngine() {
delete _pictures;
delete _screen;
delete _selection;
+ delete _sounds;
delete _streams;
delete _windows;
}
@@ -79,6 +81,7 @@ void GlkEngine::initialize() {
_events = new Events();
_pictures = new Pictures();
_selection = new Selection();
+ _sounds = new Sounds();
_streams = new Streams();
_windows = new Windows(_screen);
}
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 923e295..91702c5 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -41,6 +41,7 @@ class Events;
class Pictures;
class Screen;
class Selection;
+class Sounds;
class Streams;
class Windows;
@@ -107,6 +108,7 @@ public:
Screen *_screen;
Selection *_selection;
Streams *_streams;
+ Sounds *_sounds;
Windows *_windows;
bool _copySelect;
bool _terminated;
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index 32d6177..1104789 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -24,6 +24,7 @@
#include "glk/conf.h"
#include "glk/events.h"
#include "glk/picture.h"
+#include "glk/sound.h"
#include "glk/streams.h"
#include "glk/unicode.h"
#include "glk/windows.h"
@@ -970,22 +971,19 @@ void GlkAPI::glk_window_set_background_color(winid_t win, glui32 color) {
}
schanid_t GlkAPI::glk_schannel_create(glui32 rock) {
- // TODO
- return nullptr;
+ return _sounds->create(rock);
}
void GlkAPI::glk_schannel_destroy(schanid_t chan) {
- // TODO
+ delete chan;
}
schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
- // TODO
- return nullptr;
+ return _sounds->iterate(chan, rockptr);
}
glui32 GlkAPI::glk_schannel_get_rock(schanid_t chan) {
- // TODO
- return 0;
+ return chan->_rock;
}
glui32 GlkAPI::glk_schannel_play(schanid_t chan, glui32 snd) {
diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h
index 3081ac2..2dd2501 100644
--- a/engines/glk/glk_api.h
+++ b/engines/glk/glk_api.h
@@ -26,6 +26,7 @@
#include "glk/glk.h"
#include "glk/glk_types.h"
#include "glk/blorb.h"
+#include "glk/sound.h"
#include "glk/time.h"
#include "glk/windows.h"
diff --git a/engines/glk/glk_types.h b/engines/glk/glk_types.h
index 81a36d8..abae785 100644
--- a/engines/glk/glk_types.h
+++ b/engines/glk/glk_types.h
@@ -68,8 +68,6 @@ enum InterpreterType {
#define GLK_MODULE_DATETIME
#define GLK_MODULE_GARGLKTEXT
-typedef struct glk_schannel_struct *schanid_t;
-
/**
* Usurp C1 space for ligatures and smart typography glyphs
*/
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index c09bfac..de69645 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -11,6 +11,7 @@ MODULE_OBJS := \
raw_decoder.o \
screen.o \
selection.o \
+ sound.o \
streams.o \
time.o \
unicode.o \
diff --git a/engines/glk/sound.cpp b/engines/glk/sound.cpp
new file mode 100644
index 0000000..5c98b93
--- /dev/null
+++ b/engines/glk/sound.cpp
@@ -0,0 +1,72 @@
+/* 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.
+ *
+ */
+
+#include "glk/sound.h"
+
+namespace Glk {
+
+Sounds::~Sounds() {
+ for (int idx = (int)_sounds.size() - 1; idx >= 0; --idx)
+ delete _sounds[idx];
+}
+
+void Sounds::removeSound(schanid_t snd) {
+ for (uint idx = 0; idx < _sounds.size(); ++idx) {
+ if (_sounds[idx] == snd) {
+ _sounds.remove_at(idx);
+ break;
+ }
+ }
+}
+
+schanid_t Sounds::create(glui32 rock) {
+ schanid_t snd = new SoundChannel();
+ _sounds.push_back(snd);
+ return snd;
+}
+
+schanid_t Sounds::iterate(schanid_t chan, glui32 *rockptr) {
+ for (int idx = 0; idx < (int)_sounds.size() - 1; ++idx) {
+ if (_sounds[idx] == chan) {
+ schanid_t next = _sounds[idx + 1];
+ if (*rockptr)
+ *rockptr = next->_rock;
+
+ return next;
+ }
+ }
+
+ return nullptr;
+}
+
+/*--------------------------------------------------------------------------*/
+
+SoundChannel::~SoundChannel() {
+ _owner->removeSound(this);
+ delete _stream;
+}
+
+void SoundChannel::play(uint soundNum) {
+ // TODO
+}
+
+} // End of namespace Glk
diff --git a/engines/glk/sound.h b/engines/glk/sound.h
new file mode 100644
index 0000000..05875ea
--- /dev/null
+++ b/engines/glk/sound.h
@@ -0,0 +1,87 @@
+/* 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_SOUND_H
+#define GLK_SOUND_H
+
+#include "glk/glk_types.h"
+#include "audio/audiostream.h"
+#include "common/array.h"
+
+namespace Glk {
+
+class Sounds;
+
+/**
+ * Holds the data for a playing sound
+ */
+struct SoundChannel {
+ Sounds *_owner;
+ Audio::AudioStream *_stream;
+ glui32 _rock;
+
+ /**
+ * Destructor
+ */
+ SoundChannel() : _stream(nullptr), _rock(0) {}
+
+ /**
+ * Destructor
+ */
+ ~SoundChannel();
+
+ /**
+ * Play a sound
+ */
+ void play(uint soundNum);
+};
+typedef SoundChannel *schanid_t;
+
+/**
+ * Sound manager
+ */
+class Sounds {
+ friend struct SoundChannel;
+private:
+ Common::Array<schanid_t> _sounds;
+private:
+ /**
+ * Remove a sound from the sounds list
+ */
+ void removeSound(schanid_t snd);
+public:
+ ~Sounds();
+
+ /**
+ * Create a new channel
+ */
+ schanid_t create(glui32 rock = 0);
+
+ /**
+ * Used to iterate over the current list of sound channels
+ */
+ schanid_t iterate(schanid_t chan, glui32 *rockptr = nullptr);
+};
+
+} // End of namespace Glk
+
+#endif
Commit: 0cbd51641b0bc1b205f90324399eca6b08a75c32
https://github.com/scummvm/scummvm/commit/0cbd51641b0bc1b205f90324399eca6b08a75c32
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Further sound handling
Changed paths:
audio/decoders/mp3.h
engines/glk/events.cpp
engines/glk/frotz/sound_folder.cpp
engines/glk/glk_api.cpp
engines/glk/sound.cpp
engines/glk/sound.h
diff --git a/audio/decoders/mp3.h b/audio/decoders/mp3.h
index 4740d52..5054cac 100644
--- a/audio/decoders/mp3.h
+++ b/audio/decoders/mp3.h
@@ -25,6 +25,7 @@
* Sound decoder used in engines:
* - agos
* - draci
+ * - glk
* - kyra
* - mohawk
* - queen
diff --git a/engines/glk/events.cpp b/engines/glk/events.cpp
index 8f3d5ef..e6f046c 100644
--- a/engines/glk/events.cpp
+++ b/engines/glk/events.cpp
@@ -25,6 +25,7 @@
#include "glk/glk.h"
#include "glk/screen.h"
#include "glk/selection.h"
+#include "glk/sound.h"
#include "glk/windows.h"
#include "graphics/cursorman.h"
@@ -107,7 +108,9 @@ void Events::checkForNextFrameCounter() {
g_vm->_windows->redraw();
_redraw = false;
g_vm->_screen->update();
- return;
+
+ // Poll for any finished sounds
+ g_vm->_sounds->poll();
}
}
diff --git a/engines/glk/frotz/sound_folder.cpp b/engines/glk/frotz/sound_folder.cpp
index 20f22a8..91916c4 100644
--- a/engines/glk/frotz/sound_folder.cpp
+++ b/engines/glk/frotz/sound_folder.cpp
@@ -71,7 +71,7 @@ const Common::ArchiveMemberPtr SoundSubfolder::getMember(const Common::String &n
Common::SeekableReadStream *SoundSubfolder::createReadStreamForMember(const Common::String &name) const {
Common::File *f = new Common::File();
- if (f->open(_folder.getChild(name)))
+ if (_filenames.contains(name) && f->open(_folder.getChild(_filenames[name])))
return f;
delete f;
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index 1104789..c24d452 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -975,7 +975,11 @@ schanid_t GlkAPI::glk_schannel_create(glui32 rock) {
}
void GlkAPI::glk_schannel_destroy(schanid_t chan) {
- delete chan;
+ if (chan) {
+ delete chan;
+ } else {
+ warning("schannel_dest roy: invalid ref");
+ }
}
schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
@@ -983,21 +987,38 @@ schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) {
}
glui32 GlkAPI::glk_schannel_get_rock(schanid_t chan) {
- return chan->_rock;
+ if (chan) {
+ return chan->_rock;
+ } else {
+ warning("schannel_get_rock: invalid ref");
+ return 0;
+ }
}
glui32 GlkAPI::glk_schannel_play(schanid_t chan, glui32 snd) {
- // TODO
- return 0;
+ if (chan) {
+ return chan->play(snd);
+ } else {
+ warning("schannel_play_ext: invalid ref");
+ return 0;
+ }
}
glui32 GlkAPI::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) {
- // TODO
- return 0;
+ if (chan) {
+ chan->play(snd, repeats, notify);
+ } else {
+ warning("schannel_play_ext: invalid ref");
+ return 0;
+ }
}
void GlkAPI::glk_schannel_stop(schanid_t chan) {
- // TODO
+ if (chan) {
+ chan->stop();
+ } else {
+ warning("schannel_stop: invalid ref");
+ }
}
void GlkAPI::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
@@ -1005,17 +1026,17 @@ void GlkAPI::glk_schannel_set_volume(schanid_t chan, glui32 vol) {
}
void GlkAPI::glk_sound_load_hint(glui32 snd, glui32 flag) {
- // TODO
+ // No implementation
}
schanid_t GlkAPI::glk_schannel_create_ext(glui32 rock, glui32 volume) {
- // TODO
+ // No implementation
return nullptr;
}
glui32 GlkAPI::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount,
glui32 *sndarray, glui32 soundcount, glui32 notify) {
- // TODO
+ // No implementation
return 0;
}
diff --git a/engines/glk/sound.cpp b/engines/glk/sound.cpp
index 5c98b93..85f7e01 100644
--- a/engines/glk/sound.cpp
+++ b/engines/glk/sound.cpp
@@ -21,6 +21,13 @@
*/
#include "glk/sound.h"
+#include "glk/glk.h"
+#include "glk/events.h"
+#include "common/file.h"
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "audio/decoders/mp3.h"
+#include "audio/decoders/wave.h"
namespace Glk {
@@ -39,7 +46,7 @@ void Sounds::removeSound(schanid_t snd) {
}
schanid_t Sounds::create(glui32 rock) {
- schanid_t snd = new SoundChannel();
+ schanid_t snd = new SoundChannel(this);
_sounds.push_back(snd);
return snd;
}
@@ -58,15 +65,83 @@ schanid_t Sounds::iterate(schanid_t chan, glui32 *rockptr) {
return nullptr;
}
+void Sounds::poll() {
+ for (uint idx = 0; idx < _sounds.size(); ++idx)
+ _sounds[idx]->poll();
+}
+
/*--------------------------------------------------------------------------*/
+SoundChannel::SoundChannel(Sounds *owner) : _owner(owner), _soundNum(0),
+ _rock(0), _notify(0) {
+}
+
SoundChannel::~SoundChannel() {
+ stop();
_owner->removeSound(this);
- delete _stream;
}
-void SoundChannel::play(uint soundNum) {
- // TODO
+glui32 SoundChannel::play(glui32 soundNum, glui32 repeats, glui32 notify) {
+ stop();
+ if (repeats == 0)
+ return 1;
+
+ // Find a sound of the given name
+ Audio::AudioStream *stream;
+ Common::File f;
+ Common::String nameSnd = Common::String::format("sound%u.snd", soundNum);
+ Common::String nameMp3 = Common::String::format("sound%u.mp3", soundNum);
+ Common::String nameWav = Common::String::format("sound%u.wav", soundNum);
+
+ if (f.exists(nameSnd) && f.open(nameSnd)) {
+ if (f.readUint16BE() != (f.size() - 2))
+ error("Invalid sound filesize");
+ repeats = f.readByte();
+ f.skip(1);
+ uint freq = f.readUint16BE();
+ f.skip(2);
+ uint size = f.readUint16BE();
+
+ Common::SeekableReadStream *s = f.readStream(size);
+ stream = Audio::makeRawStream(s, freq, Audio::FLAG_UNSIGNED);
+
+ } else if (f.exists(nameMp3) && f.open(nameMp3)) {
+ Common::SeekableReadStream *s = f.readStream(f.size());
+ stream = Audio::makeMP3Stream(s, DisposeAfterUse::YES);
+
+ } else if (f.exists(nameWav) && f.open(nameWav)) {
+ Common::SeekableReadStream *s = f.readStream(f.size());
+ stream = Audio::makeWAVStream(s, DisposeAfterUse::YES);
+
+ } else {
+ warning("Could not find sound %u", soundNum);
+ return 1;
+ }
+
+ _soundNum = soundNum;
+ _notify = notify;
+
+ // Set up a repeat if multiple repeats are specified
+ if (repeats > 1) {
+ Audio::RewindableAudioStream *rwStream = dynamic_cast<Audio::RewindableAudioStream *>(stream);
+ assert(rwStream);
+ stream = new Audio::LoopingAudioStream(rwStream, repeats, DisposeAfterUse::YES);
+ }
+
+ // Start playing the audio
+ g_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, stream);
+ return 0;
+}
+
+void SoundChannel::stop() {
+ g_vm->_mixer->stopHandle(_handle);
+}
+
+void SoundChannel::poll() {
+ if (!g_vm->_mixer->isSoundHandleActive(_handle) && _notify != 0)
+ g_vm->_events->store(evtype_SoundNotify, 0,
+ _soundNum, _notify);
+
}
} // End of namespace Glk
diff --git a/engines/glk/sound.h b/engines/glk/sound.h
index 05875ea..514a5f6 100644
--- a/engines/glk/sound.h
+++ b/engines/glk/sound.h
@@ -25,6 +25,7 @@
#include "glk/glk_types.h"
#include "audio/audiostream.h"
+#include "audio/mixer.h"
#include "common/array.h"
namespace Glk {
@@ -34,15 +35,19 @@ class Sounds;
/**
* Holds the data for a playing sound
*/
-struct SoundChannel {
+class SoundChannel {
+private:
Sounds *_owner;
- Audio::AudioStream *_stream;
+ glui32 _soundNum;
+ glui32 _notify;
+ Audio::SoundHandle _handle;
+public:
glui32 _rock;
-
+public:
/**
- * Destructor
+ * Constructor
*/
- SoundChannel() : _stream(nullptr), _rock(0) {}
+ SoundChannel(Sounds *owner);
/**
* Destructor
@@ -52,7 +57,17 @@ struct SoundChannel {
/**
* Play a sound
*/
- void play(uint soundNum);
+ glui32 play(glui32 soundNum, glui32 repeats = 1, glui32 notify = 0);
+
+ /**
+ * Stop playing sound
+ */
+ void stop();
+
+ /**
+ * Poll for whether a playing sound was finished
+ */
+ void poll();
};
typedef SoundChannel *schanid_t;
@@ -60,7 +75,7 @@ typedef SoundChannel *schanid_t;
* Sound manager
*/
class Sounds {
- friend struct SoundChannel;
+ friend class SoundChannel;
private:
Common::Array<schanid_t> _sounds;
private:
@@ -80,6 +95,11 @@ public:
* Used to iterate over the current list of sound channels
*/
schanid_t iterate(schanid_t chan, glui32 *rockptr = nullptr);
+
+ /**
+ * Poll for whether any playing sounds are finished
+ */
+ void poll();
};
} // End of namespace Glk
Commit: 43283ff561233d5e67cc15d8f1c3da4489156c0c
https://github.com/scummvm/scummvm/commit/43283ff561233d5e67cc15d8f1c3da4489156c0c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Playing sounds now works directly from lhsound.zip and shsound.zip
Changed paths:
engines/glk/frotz/sound_folder.cpp
diff --git a/engines/glk/frotz/sound_folder.cpp b/engines/glk/frotz/sound_folder.cpp
index 91916c4..fd99b0b 100644
--- a/engines/glk/frotz/sound_folder.cpp
+++ b/engines/glk/frotz/sound_folder.cpp
@@ -90,7 +90,7 @@ void SoundZip::check(const Common::FSNode &gameDir, Story story) {
if (!zipNode.exists())
return;
- SearchMan.add("sound", Common::makeZipArchive(zipNode));
+ SearchMan.add("sound", new SoundZip(Common::makeZipArchive(zipNode)));
}
SoundZip::SoundZip(Common::Archive *zip) : _zip(zip) {
Commit: 08db684864f0734a2d93641dc7a23ce117073eb4
https://github.com/scummvm/scummvm/commit/08db684864f0734a2d93641dc7a23ce117073eb4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: Add support for secondary Blorb files separate from the gamefile
It also hads further support for playing AIFF files. However, the
Blorb files for Lurking Horror & Sherlock on the if-archive website
don't seem to be valid AIFF files, so sound doesn't play using them
Changed paths:
audio/decoders/wave.h
engines/glk/blorb.cpp
engines/glk/glk.cpp
engines/glk/sound.cpp
diff --git a/audio/decoders/wave.h b/audio/decoders/wave.h
index aaf4a01..75581f1 100644
--- a/audio/decoders/wave.h
+++ b/audio/decoders/wave.h
@@ -28,6 +28,7 @@
* - cge
* - cge2
* - fullpipe
+ * - glk
* - gob
* - hopkins
* - mohawk
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 5ffd0b0..4a4cf8c 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -153,7 +153,7 @@ Common::ErrorCode Blorb::load() {
ce._filename += ".mp3";
else if (ce._id == ID_WAVE)
ce._filename += ".wav";
- else if (ce._id == ID_AIFF)
+ else if (ce._id == ID_AIFF || ce._id == ID_FORM)
ce._filename += ".aiff";
else if (ce._id == ID_OGG)
ce._filename += ".ogg";
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index c8a63c5..849de8d 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -122,6 +122,20 @@ Common::Error GlkEngine::run() {
if (!f.open("game", *_blorb))
return Common::kNoGameDataFoundError;
} else {
+ // Check for a secondary blorb file with the same filename
+ Common::String baseName = filename;
+ while (baseName.contains('.'))
+ baseName.deleteLastChar();
+
+ if (f.exists(baseName + ".blorb")) {
+ _blorb = new Blorb(baseName + ".blorb", getInterpreterType());
+ SearchMan.add("blorb", _blorb, 99, false);
+ } else if (f.exists(baseName + ".blb")) {
+ _blorb = new Blorb(baseName + ".blb", getInterpreterType());
+ SearchMan.add("blorb", _blorb, 99, false);
+ }
+
+ // Open up the game file
if (!f.open(filename))
return Common::kNoGameDataFoundError;
}
diff --git a/engines/glk/sound.cpp b/engines/glk/sound.cpp
index 85f7e01..02fb7f9 100644
--- a/engines/glk/sound.cpp
+++ b/engines/glk/sound.cpp
@@ -25,6 +25,7 @@
#include "glk/events.h"
#include "common/file.h"
#include "audio/audiostream.h"
+#include "audio/decoders/aiff.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/wave.h"
@@ -92,6 +93,7 @@ glui32 SoundChannel::play(glui32 soundNum, glui32 repeats, glui32 notify) {
Common::String nameSnd = Common::String::format("sound%u.snd", soundNum);
Common::String nameMp3 = Common::String::format("sound%u.mp3", soundNum);
Common::String nameWav = Common::String::format("sound%u.wav", soundNum);
+ Common::String nameAiff = Common::String::format("sound%u.aiff", soundNum);
if (f.exists(nameSnd) && f.open(nameSnd)) {
if (f.readUint16BE() != (f.size() - 2))
@@ -113,6 +115,10 @@ glui32 SoundChannel::play(glui32 soundNum, glui32 repeats, glui32 notify) {
Common::SeekableReadStream *s = f.readStream(f.size());
stream = Audio::makeWAVStream(s, DisposeAfterUse::YES);
+ } else if (f.exists(nameAiff) && f.open(nameAiff)) {
+ Common::SeekableReadStream *s = f.readStream(f.size());
+ stream = Audio::makeAIFFStream(s, DisposeAfterUse::YES);
+
} else {
warning("Could not find sound %u", soundNum);
return 1;
Commit: ecb0c10fdb90cf57dca0a528d3b7291979ee7ab8
https://github.com/scummvm/scummvm/commit/ecb0c10fdb90cf57dca0a528d3b7291979ee7ab8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Properly flag the detections of Infocom games that have sound effects
Changed paths:
engines/glk/frotz/detection.cpp
engines/glk/frotz/detection_tables.h
diff --git a/engines/glk/frotz/detection.cpp b/engines/glk/frotz/detection.cpp
index c869c92..7afeec2 100644
--- a/engines/glk/frotz/detection.cpp
+++ b/engines/glk/frotz/detection.cpp
@@ -106,6 +106,7 @@ bool FrotzMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
} else {
PlainGameDescriptor gameDesc = findGame(p->_gameId);
gd = DetectedGame(p->_gameId, gameDesc.description, p->_language, Common::kPlatformUnknown, p->_extra);
+ gd.setGUIOptions(p->_guiOptions);
}
gd.addExtraEntry("filename", filename);
diff --git a/engines/glk/frotz/detection_tables.h b/engines/glk/frotz/detection_tables.h
index 179067c..2bcb011 100644
--- a/engines/glk/frotz/detection_tables.h
+++ b/engines/glk/frotz/detection_tables.h
@@ -88,6 +88,8 @@ const PlainGameDescriptor FROTZ_GAME_LIST[] = {
#define NONE GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES)
#define ENTRY0(ID, VERSION, MD5, FILESIZE) { ID, VERSION, MD5, FILESIZE, Common::EN_ANY, NONE }
#define ENTRY1(ID, VERSION, MD5, FILESIZE, LANG) { ID, VERSION, MD5, FILESIZE, LANG, NONE }
+#define ENTRYS(ID, VERSION, MD5, FILESIZE) { ID, VERSION, MD5, FILESIZE, Common::EN_ANY, GUIO3(GUIO_NOSPEECH, GUIO_NOMUSIC, GUIO_NOSUBTITLES) }
+
#define FROTZ_TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY, "" }
const FrotzGameDescription FROTZ_GAMES[] = {
@@ -124,9 +126,9 @@ const FrotzGameDescription FROTZ_GAMES[] = {
ENTRY0("lgop", "R0", "69b3534570851b90d7f53ebe9d224a6a", 128998),
ENTRY0("lgop", "R4-880405", "6bdae7434df7c03f3589ece0bed3317d", 159928),
ENTRY0("lgop", "R59-860730", "e81237e220a612c5a93fbcc1fdf85a0a", 129022),
- ENTRY0("lurkinghorror", "R203", "e2d2505510479fec0405727e3d0abc10", 128986),
- ENTRY0("lurkinghorror", "R219", "83936d75c2cfd71fb64bf63c4696b9ac", 129704),
- ENTRY0("lurkinghorror", "R221", "c60cd0bf3c6eda867241378c7cb5464a", 129944),
+ ENTRYS("lurkinghorror", "R203", "e2d2505510479fec0405727e3d0abc10", 128986),
+ ENTRYS("lurkinghorror", "R219", "83936d75c2cfd71fb64bf63c4696b9ac", 129704),
+ ENTRYS("lurkinghorror", "R221", "c60cd0bf3c6eda867241378c7cb5464a", 129944),
ENTRY0("minizork1", "R34-871124", "0d7700679e5e63dec97f712698610a46", 52216),
ENTRY0("moonmist", "R4-860918", "284797c3025ffaf76aecfa5c2bbffa86", 129002),
ENTRY0("moonmist", "R9-861022", "698475de2769c66bc5a1eca600c71561", 128866),
@@ -146,8 +148,8 @@ const FrotzGameDescription FROTZ_GAMES[] = {
ENTRY0("seastalker", "R16-850515", "eb39dff7beb3589c8581dd2e3569eb78", 117752),
ENTRY0("seastalker", "R16-850603", "bccf194b1e823e37db2431b586662773", 117762),
ENTRY0("seastalker", "R86-840320", "64fb27e7b9fd682ff4f0d0ec6616a468", 116456),
- ENTRY0("sherlockriddle", "R21-871214", "69862f7f07a4e977159ea4da7f2f2ba6", 188444),
- ENTRY0("sherlockriddle", "R26-880127", "2cb2bda2e34eb7f9494cb585720e74cd", 190180),
+ ENTRYS("sherlockriddle", "R21-871214", "69862f7f07a4e977159ea4da7f2f2ba6", 188444),
+ ENTRYS("sherlockriddle", "R26-880127", "2cb2bda2e34eb7f9494cb585720e74cd", 190180),
ENTRY0("shogun", "R322-890706", "62cca41feb94082442026f44f3e48e19", 344816),
ENTRY0("sorcerer", "R4-840131", "d4a914fdfe90f5cd055a03b9aa24addd", 109734),
ENTRY0("sorcerer", "R6-840508", "7ee357c10a9e049fe7c641a4817ee575", 109482),
Commit: 754819f9281d5207deaff1922a915bd9dc0437b5
https://github.com/scummvm/scummvm/commit/754819f9281d5207deaff1922a915bd9dc0437b5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: FROTZ: Reduce window margin to 0 to have status bar fill entire width
Changed paths:
engines/glk/conf.cpp
diff --git a/engines/glk/conf.cpp b/engines/glk/conf.cpp
index ee2fd9b..efd1687 100644
--- a/engines/glk/conf.cpp
+++ b/engines/glk/conf.cpp
@@ -107,7 +107,7 @@ Conf::Conf(InterpreterType interpType) {
if (ConfMan.hasKey("maxcols"))
_cols = MIN(_cols, strToInt(ConfMan.get("maxcols").c_str()));
- const int DEFAULT_MARGIN_X = (interpType == INTERPRETER_FROTZ) ? 2 : 15;
+ const int DEFAULT_MARGIN_X = (interpType == INTERPRETER_FROTZ) ? 0 : 15;
const int DEFAULT_MARGIN_Y = (interpType == INTERPRETER_FROTZ) ? 0 : 15;
get("lockrows", _lockRows);
Commit: 290196946dab0ee60498be16d8e33bb911e5a166
https://github.com/scummvm/scummvm/commit/290196946dab0ee60498be16d8e33bb911e5a166
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: GLULXE: Skeleton sub-engine
Changed paths:
A engines/glk/glulxe/detection.cpp
A engines/glk/glulxe/detection.h
A engines/glk/glulxe/detection_tables.h
A engines/glk/glulxe/glulxe.cpp
A engines/glk/glulxe/glulxe.h
engines/glk/blorb.cpp
engines/glk/detection.cpp
engines/glk/glk.cpp
engines/glk/glk_types.h
engines/glk/module.mk
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 4a4cf8c..1438abb 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -171,6 +171,7 @@ Common::ErrorCode Blorb::load() {
if (
(_interpType == INTERPRETER_FROTZ && type == "ZCOD") ||
+ (_interpType == INTERPRETER_GLULXE && type == "GLUL") ||
(_interpType == INTERPRETER_TADS2 && type == "TAD2") ||
(_interpType == INTERPRETER_TADS3 && type == "TAD3") ||
(_interpType == INTERPRETER_HUGO && type == "HUGO")
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index 491c6c8..b848178 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -23,6 +23,8 @@
#include "glk/glk.h"
#include "glk/frotz/detection.h"
#include "glk/frotz/frotz.h"
+#include "glk/glulxe/detection.h"
+#include "glk/glulxe/glulxe.h"
#include "glk/scott/detection.h"
#include "glk/scott/scott.h"
#include "glk/tads/detection.h"
@@ -132,9 +134,11 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
gameDesc._md5 = Common::computeStreamMD5AsString(f, 5000);
f.close();
- // Correct the correct engine
+ // Create the correct engine
if (Glk::Frotz::FrotzMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
*engine = new Glk::Frotz::Frotz(syst, gameDesc);
+ } else if (Glk::Glulxe::GlulxeMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
+ *engine = new Glk::Glulxe::Glulxe(syst, gameDesc);
} else if (Glk::Scott::ScottMetaEngine::findGame(gameDesc._gameId.c_str()).description) {
*engine = new Glk::Scott::Scott(syst, gameDesc);
} else if ((td = Glk::TADS::TADSMetaEngine::findGame(gameDesc._gameId.c_str())).description) {
@@ -174,6 +178,7 @@ Common::String GlkMetaEngine::findFileByGameId(const Common::String &gameId) con
PlainGameList GlkMetaEngine::getSupportedGames() const {
PlainGameList list;
Glk::Frotz::FrotzMetaEngine::getSupportedGames(list);
+ Glk::Glulxe::GlulxeMetaEngine::getSupportedGames(list);
Glk::Scott::ScottMetaEngine::getSupportedGames(list);
Glk::TADS::TADSMetaEngine::getSupportedGames(list);
@@ -186,6 +191,9 @@ PlainGameDescriptor GlkMetaEngine::findGame(const char *gameId) const {
gd = Glk::Frotz::FrotzMetaEngine::findGame(gameId);
if (gd.description) return gd;
+ gd = Glk::Glulxe::GlulxeMetaEngine::findGame(gameId);
+ if (gd.description) return gd;
+
gd = Glk::Scott::ScottMetaEngine::findGame(gameId);
if (gd.description) return gd;
@@ -198,6 +206,7 @@ PlainGameDescriptor GlkMetaEngine::findGame(const char *gameId) const {
DetectedGames GlkMetaEngine::detectGames(const Common::FSList &fslist) const {
DetectedGames detectedGames;
Glk::Frotz::FrotzMetaEngine::detectGames(fslist, detectedGames);
+ Glk::Glulxe::GlulxeMetaEngine::detectGames(fslist, detectedGames);
Glk::Scott::ScottMetaEngine::detectGames(fslist, detectedGames);
Glk::TADS::TADSMetaEngine::detectGames(fslist, detectedGames);
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 849de8d..8c35cfe 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -114,7 +114,8 @@ Common::Error GlkEngine::run() {
initialize();
- if (filename.hasSuffixIgnoreCase(".blorb") || filename.hasSuffixIgnoreCase(".zblorb")) {
+ if (filename.hasSuffixIgnoreCase(".blorb") || filename.hasSuffixIgnoreCase(".zblorb")
+ || filename.hasSuffixIgnoreCase(".gblorb")) {
// Blorb archive
_blorb = new Blorb(filename, getInterpreterType());
SearchMan.add("blorb", _blorb, 99, false);
diff --git a/engines/glk/glk_types.h b/engines/glk/glk_types.h
index abae785..3c8f60f 100644
--- a/engines/glk/glk_types.h
+++ b/engines/glk/glk_types.h
@@ -43,15 +43,16 @@ enum InterpreterType {
INTERPRETER_BOCFEL = 4,
INTERPRETER_FROTZ = 5,
INTERPRETER_GEAS = 6,
- INTERPRETER_HUGO = 7,
- INTERPRETER_JACL = 8,
- INTERPRETER_LEVEL9 = 9,
- INTERPRETER_MAGNETIC = 10,
- INTERPRETER_NITFOL = 11,
- INTERPRETER_SCARE = 12,
- INTERPRETER_SCOTT = 13,
- INTERPRETER_TADS2 = 14,
- INTERPRETER_TADS3 = 15
+ INTERPRETER_GLULXE = 7,
+ INTERPRETER_HUGO = 8,
+ INTERPRETER_JACL = 9,
+ INTERPRETER_LEVEL9 = 10,
+ INTERPRETER_MAGNETIC = 11,
+ INTERPRETER_NITFOL = 12,
+ INTERPRETER_SCARE = 13,
+ INTERPRETER_SCOTT = 14,
+ INTERPRETER_TADS2 = 15,
+ INTERPRETER_TADS3 = 16
};
/**
diff --git a/engines/glk/glulxe/detection.cpp b/engines/glk/glulxe/detection.cpp
new file mode 100644
index 0000000..0e1ec1f
--- /dev/null
+++ b/engines/glk/glulxe/detection.cpp
@@ -0,0 +1,111 @@
+/* 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.
+ *
+ */
+
+#include "glk/glulxe/detection.h"
+#include "glk/glulxe/detection_tables.h"
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/md5.h"
+#include "engines/game.h"
+
+namespace Glk {
+namespace Glulxe {
+
+void GlulxeMetaEngine::getSupportedGames(PlainGameList &games) {
+ for (const GlulxeDescriptor *pd = GLULXE_GAME_LIST; pd->gameId; ++pd) {
+ games.push_back(*pd);
+ }
+}
+
+GlulxeDescriptor GlulxeMetaEngine::findGame(const char *gameId) {
+ for (const GlulxeDescriptor *pd = GLULXE_GAME_LIST; pd->gameId; ++pd) {
+ if (!strcmp(gameId, pd->gameId))
+ return *pd;
+ }
+
+ return GlulxeDescriptor();
+}
+
+bool GlulxeMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
+ const char *const EXTENSIONS[3] = { ".ulx", ".blb", ".gblorb" };
+
+ // Loop through the files of the folder
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ // Check for a recognised filename
+ if (file->isDirectory())
+ continue;
+ Common::String filename = file->getName();
+ bool hasExt = false;
+ for (int idx = 0; idx < 3 && !hasExt; ++idx)
+ hasExt = filename.hasSuffixIgnoreCase(EXTENSIONS[idx]);
+ if (!hasExt)
+ continue;
+
+ // Open up the file and calculate the md5
+ Common::File gameFile;
+ if (!gameFile.open(*file))
+ continue;
+ Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+ size_t filesize = gameFile.size();
+ gameFile.close();
+
+ // Check for known games
+ const GlulxeGameDescription *p = GLULXE_GAMES;
+ while (p->_gameId && (md5 != p->_md5 || filesize != p->_filesize))
+ ++p;
+
+ DetectedGame gd;
+ if (!p->_gameId) {
+ if (filename.hasSuffixIgnoreCase(".blb"))
+ continue;
+
+ if (gDebugLevel > 0) {
+ // Print an entry suitable for putting into the detection_tables.h, using the
+ // name of the parent folder the game is in as the presumed game Id
+ Common::String folderName = file->getParent().getName();
+ if (folderName.hasSuffix("\\"))
+ folderName.deleteLastChar();
+ Common::String fname = filename;
+ const char *dot = strchr(fname.c_str(), '.');
+ if (dot)
+ fname = Common::String(fname.c_str(), dot);
+
+ debug("ENTRY0(\"%s\", \"%s\", %lu),",
+ fname.c_str(), md5.c_str(), filesize);
+ }
+ const PlainGameDescriptor &desc = GLULXE_GAME_LIST[0];
+ gd = DetectedGame(desc.gameId, desc.description, Common::UNK_LANG, Common::kPlatformUnknown);
+ } else {
+ PlainGameDescriptor gameDesc = findGame(p->_gameId);
+ gd = DetectedGame(p->_gameId, gameDesc.description, p->_language, Common::kPlatformUnknown, p->_extra);
+ gd.setGUIOptions(GUIO4(GUIO_NOSPEECH, GUIO_NOSFX, GUIO_NOMUSIC, GUIO_NOSUBTITLES));
+ }
+
+ gd.addExtraEntry("filename", filename);
+ gameList.push_back(gd);
+ }
+
+ return !gameList.empty();
+}
+
+} // End of namespace Glulxe
+} // End of namespace Glk
diff --git a/engines/glk/glulxe/detection.h b/engines/glk/glulxe/detection.h
new file mode 100644
index 0000000..d6d5c6a
--- /dev/null
+++ b/engines/glk/glulxe/detection.h
@@ -0,0 +1,71 @@
+/* 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_GLULXE_DETECTION
+#define GLK_GLULXE_DETECTION
+
+#include "common/fs.h"
+#include "engines/game.h"
+
+namespace Glk {
+namespace Glulxe {
+
+/**
+ * Glulxe game descriptior
+ */
+struct GlulxeDescriptor {
+ const char *gameId;
+ const char *description;
+
+ operator PlainGameDescriptor() const {
+ PlainGameDescriptor pd;
+ pd.gameId = gameId;
+ pd.description = description;
+ return pd;
+ }
+};
+
+/**
+ * Meta engine for Glulxe interpreter
+ */
+class GlulxeMetaEngine {
+public:
+ /**
+ * Get a list of supported games
+ */
+ static void getSupportedGames(PlainGameList &games);
+
+ /**
+ * Returns a game description for the given game Id, if it's supported
+ */
+ static GlulxeDescriptor findGame(const char *gameId);
+
+ /**
+ * Detect supported games
+ */
+ static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
+};
+
+} // End of namespace Glulxe
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/glulxe/detection_tables.h b/engines/glk/glulxe/detection_tables.h
new file mode 100644
index 0000000..17c5ffd
--- /dev/null
+++ b/engines/glk/glulxe/detection_tables.h
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+#include "engines/game.h"
+#include "common/gui_options.h"
+#include "common/language.h"
+
+namespace Glk {
+namespace Glulxe {
+
+/**
+ * Game description
+ */
+struct GlulxeGameDescription {
+ const char *const _gameId;
+ const char *const _extra;
+ const char *const _md5;
+ size_t _filesize;
+ Common::Language _language;
+};
+
+const GlulxeDescriptor GLULXE_GAME_LIST[] = {
+ { "glulxe", "Glulxe Game" },
+ { "cragne", "Cragne Manor" },
+
+ { nullptr, nullptr }
+};
+
+#define ENTRY0(ID, MD5, FILESIZE) { ID, nullptr, MD5, FILESIZE, Common::EN_ANY }
+#define TABLE_END_MARKER { nullptr, nullptr, nullptr, 0, Common::EN_ANY }
+
+const GlulxeGameDescription GLULXE_GAMES[] = {
+ ENTRY0("cragne", "082f518c0120d2323ce340bef8a2d5a9", 8869096),
+ TABLE_END_MARKER
+};
+
+} // End of namespace Glulxe
+} // End of namespace Glk
diff --git a/engines/glk/glulxe/glulxe.cpp b/engines/glk/glulxe/glulxe.cpp
new file mode 100644
index 0000000..25af4c2
--- /dev/null
+++ b/engines/glk/glulxe/glulxe.cpp
@@ -0,0 +1,48 @@
+/* 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.
+ *
+ */
+
+#include "glk/glulxe/glulxe.h"
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+namespace Glk {
+namespace Glulxe {
+
+Glulxe::Glulxe(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {
+}
+
+void Glulxe::runGame(Common::SeekableReadStream *gameFile) {
+ // TODO
+}
+
+Common::Error Glulxe::loadGameData(strid_t file) {
+ // TODO
+ return Common::kNoError;
+}
+
+Common::Error Glulxe::saveGameData(strid_t file, const Common::String &desc) {
+ // TODO
+ return Common::kNoError;
+}
+
+} // End of namespace Glulxe
+} // End of namespace Glk
diff --git a/engines/glk/glulxe/glulxe.h b/engines/glk/glulxe/glulxe.h
new file mode 100644
index 0000000..eb4aaf3
--- /dev/null
+++ b/engines/glk/glulxe/glulxe.h
@@ -0,0 +1,66 @@
+/* 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_GLULXE
+#define GLK_GLULXE
+
+#include "common/scummsys.h"
+#include "glk/glk_api.h"
+
+namespace Glk {
+namespace Glulxe {
+
+/**
+ * Glulxe game interpreter
+ */
+class Glulxe : public GlkAPI {
+public:
+ /**
+ * Constructor
+ */
+ Glulxe(OSystem *syst, const GlkGameDescription &gameDesc);
+
+ /**
+ * Run the game
+ */
+ void runGame(Common::SeekableReadStream *gameFile);
+
+ /**
+ * Returns the running interpreter type
+ */
+ virtual InterpreterType getInterpreterType() const override { return INTERPRETER_GLULXE; }
+
+ /**
+ * Load a savegame from the passed stream
+ */
+ virtual Common::Error loadGameData(strid_t file) override;
+
+ /**
+ * Save the game to the passed stream
+ */
+ virtual Common::Error saveGameData(strid_t file, const Common::String &desc) override;
+};
+
+} // End of namespace Glulxe
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index de69645..7164481 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -44,6 +44,8 @@ MODULE_OBJS := \
frotz/quetzal.o \
frotz/screen.o \
frotz/sound_folder.o \
+ glulxe/detection.o \
+ glulxe/glulxe.o \
scott/detection.o \
scott/scott.o \
tads/detection.o \
Commit: ac9830614d07d80f0c02d9d7c75d709f9d534466
https://github.com/scummvm/scummvm/commit/ac9830614d07d80f0c02d9d7c75d709f9d534466
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-12-08T19:05:59-08:00
Commit Message:
GLK: GLULXE: Validate game file version
Changed paths:
engines/glk/POTFILES
engines/glk/glulxe/glulxe.cpp
engines/glk/glulxe/glulxe.h
diff --git a/engines/glk/POTFILES b/engines/glk/POTFILES
index d672609..935c263 100644
--- a/engines/glk/POTFILES
+++ b/engines/glk/POTFILES
@@ -1,3 +1,4 @@
engines/glk/streams.cpp
engines/glk/scott/scott.cpp
engines/glk/frotz/detection.cpp
+engines/glk/glulxe/glulxe.cpp
diff --git a/engines/glk/glulxe/glulxe.cpp b/engines/glk/glulxe/glulxe.cpp
index 25af4c2..e2e1a47 100644
--- a/engines/glk/glulxe/glulxe.cpp
+++ b/engines/glk/glulxe/glulxe.cpp
@@ -27,10 +27,16 @@
namespace Glk {
namespace Glulxe {
-Glulxe::Glulxe(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {
+Glulxe::Glulxe(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
+ vm_exited_cleanly(false) {
}
void Glulxe::runGame(Common::SeekableReadStream *gameFile) {
+ _gameFile = gameFile;
+
+ if (!is_gamefile_valid())
+ return;
+
// TODO
}
@@ -44,5 +50,30 @@ Common::Error Glulxe::saveGameData(strid_t file, const Common::String &desc) {
return Common::kNoError;
}
+bool Glulxe::is_gamefile_valid() {
+ if (_gameFile->size() < 8) {
+ GUIError(_("This is too short to be a valid Glulx file."));
+ return false;
+ }
+
+ if (_gameFile->readUint32BE() != MKTAG('G', 'l', 'u', 'l')) {
+ GUIError(_("This is not a valid Glulx file."));
+ return false;
+ }
+
+ // We support version 2.0 through 3.1.*
+ uint version = _gameFile->readUint32BE();
+ if (version < 0x20000) {
+ GUIError(_("This Glulx file is too old a version to execute."));
+ return false;
+ }
+ if (version >= 0x30200) {
+ GUIError(_("This Glulx file is too new a version to execute."));
+ return false;
+ }
+
+ return true;
+}
+
} // End of namespace Glulxe
} // End of namespace Glk
diff --git a/engines/glk/glulxe/glulxe.h b/engines/glk/glulxe/glulxe.h
index eb4aaf3..3764ca4 100644
--- a/engines/glk/glulxe/glulxe.h
+++ b/engines/glk/glulxe/glulxe.h
@@ -34,6 +34,14 @@ namespace Glulxe {
*/
class Glulxe : public GlkAPI {
public:
+ Common::SeekableReadStream *_gameFile;
+ bool vm_exited_cleanly;
+private:
+ /**
+ * Validates the game file, and if it's invalid, displays an error dialog
+ */
+ bool is_gamefile_valid();
+public:
/**
* Constructor
*/
More information about the Scummvm-git-logs
mailing list