[Scummvm-cvs-logs] scummvm master -> f1b6542fd2f705b771f8c46efb328b783f9c5d78
sev-
sev at scummvm.org
Thu Mar 24 23:07:54 CET 2016
This automated email contains information about 61 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c8ab2909c6 ADL: Initial check-in for ADL engine
87e2c4c1a9 ADL: Rename game type
9717aa9561 ADL: Clean-up string handling
183fe8b217 ADL: Move members into base class
d30cfa24fa ADL: Remove dead code
43a37e94dd ADL: Rename AdlEngine_v1 to HiRes1Engine
1e17a23879 ADL: Rename adl_v1.cpp/h to hires1.cpp/h
6a1dd07197 ADL: Move more functionality into base class
ce97d0a26e ADL: Use #defines instead of literals
f9c9f2ac9d ADL: Rename Item struct fields
8f9d4b9653 ADL: Use #defines instead of literals
2104a5095d ADL: Rename Room struct fields
00d87cca90 ADL: Add more #defines for literals
ede25c19bc ADL: Rename some #defines and variables for clarity
24c478c5ec ADL: Add ARG #define to improve readability
34cb2f4c53 ADL: Move functionality into base class
1abaf60cf0 ADL: Rename rightAngles to lineArt
dc2e5e09ba ADL: Put state-related members in _state struct
301b2fdc21 ADL: Remove leftover debug code
727469d4a7 ADL: Add restarting
e3d13d06ee ADL: Add save game support
e1fb585357 ADL: Use #define instead of literal
475eb0cc95 ADL: Fix bug in item taking
9928e51bd7 ADL: Add functions to adjust for 1-based arrays
ba54955bff ADL: Add loading from launcher
339d3bc868 ADL: Move input code into AdlEngine
93f5e36c9f ADL: Add GMM loading and saving
baa2410a1c ADL: Fix "don't understand" parser response override
84a9f6ce95 ADL: Add save game meta info support
912a31fa65 ADL: Add monochrome and scanline rendering
b30fb417ac ADL: Disable scanlines when saving thumbnail
d5cc42f1c2 ADL: Make frame buffer linear
4f7e5da4da ADL: Clean up Display class
115e4cab0d ADL: Fix restoring on restart prompt
ec14c397ee ADL: Clean up Display class
e6d478ad15 ADL: Clean up Display class
6f91289838 ADL: Clean up Display class
f5430f961b ADL: Implement half-pixel shift in color mode
50d6e6938a ADL: Refactor graphics code
d3bfdc3657 ADL: Add more #defines to replace literals
b2d2f3405e ADL: Make palettes static
165e333f4f ADL: Implement half-pixel shift for monochrome
1e1a5d4f07 ADL: Fix darkness setting in a move too late
6379fbc124 ADL: Add more #defines to replace literals
f62c56e384 ADL: Clean up line drawing
af42795ffa ADL: Improve error messages
a73dcdf224 ADL: Move functionality into base class
0ec3ab1422 ADL: Fix const'ness
58e7c53909 ADL: Clean up AdlEngine class
07d0997bef ADL: Clean up AdlMetaEngine
ac79cb081c ADL: Move #defines into header file
fd8a5f419f ADL: Refactor string handling
86d58534e7 ADL: Move ASCII print function into Display class
63adab81ed ADL: Clean up HiRes1Engine class
57af92e0c1 ADL: Fix shadowing warning (GCC 4.8)
d01da596ef ADL: Add note about font
ac39224958 ADL: Limit keyboard input to 256 characters
9d65f901d0 ADL: Clarify detection entry
349245d9b4 ADL: Fix regression in GMM saving/loading
ce3af91ef8 ADL: Disable GMM restore on restart prompt
f1b6542fd2 Merge pull request #700 from waltervn/adl-engine
Commit: c8ab2909c67703ad1255aa27159049f058d1a361
https://github.com/scummvm/scummvm/commit/c8ab2909c67703ad1255aa27159049f058d1a361
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Initial check-in for ADL engine
Changed paths:
A engines/adl/adl.cpp
A engines/adl/adl.h
A engines/adl/adl_v1.cpp
A engines/adl/adl_v1.h
A engines/adl/configure.engine
A engines/adl/detection.cpp
A engines/adl/display.cpp
A engines/adl/display.h
A engines/adl/module.mk
A engines/adl/parser.cpp
A engines/adl/parser.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
new file mode 100644
index 0000000..be3d8d7
--- /dev/null
+++ b/engines/adl/adl.cpp
@@ -0,0 +1,155 @@
+/* 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.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/file.h"
+#include "common/fs.h"
+#include "common/system.h"
+#include "common/events.h"
+#include "common/stream.h"
+#include "graphics/palette.h"
+
+#include "engines/util.h"
+
+#include "adl/adl.h"
+#include "adl/display.h"
+#include "adl/parser.h"
+
+namespace Adl {
+
+Common::String asciiToApple(Common::String str) {
+ Common::String ret(str);
+ Common::String::iterator it;
+
+ for (it = ret.begin(); it != ret.end(); ++it)
+ *it = *it | 0x80;
+
+ return ret;
+}
+
+Common::String appleToAscii(Common::String str) {
+ Common::String ret(str);
+ Common::String::iterator it;
+
+ for (it = ret.begin(); it != ret.end(); ++it)
+ *it = *it & 0x7f;
+
+ return ret;
+}
+
+AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
+ Engine(syst),
+ _gameDescription(gd),
+ _console(nullptr),
+ _display(nullptr) {
+ // Put your engine in a sane state, but do nothing big yet;
+ // in particular, do not load data from files; rather, if you
+ // need to do such things, do them from run().
+
+ // Do not initialize graphics here
+ // Do not initialize audio devices here
+
+ // However this is the place to specify all default directories
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
+
+ // Don't forget to register your random source
+ _rnd = new Common::RandomSource("adl");
+
+ debug("AdlEngine::AdlEngine");
+}
+
+AdlEngine::~AdlEngine() {
+ debug("AdlEngine::~AdlEngine");
+
+ delete _rnd;
+ delete _console;
+ delete _display;
+
+ DebugMan.clearAllDebugChannels();
+}
+
+Common::Error AdlEngine::run() {
+ initGraphics(560, 384, true);
+
+ byte palette[6 * 3] = {
+ 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff,
+ 0xc7, 0x34, 0xff,
+ 0x38, 0xcb, 0x00,
+ 0x00, 0x00, 0xff, // FIXME
+ 0xff, 0xa5, 0x00 // FIXME
+ };
+
+ g_system->getPaletteManager()->setPalette(palette, 0, 6);
+
+ _console = new Console(this);
+ _display = new Display();
+ _parser = new Parser(*this, *_display);
+
+ runGame();
+
+ return Common::kNoError;
+}
+
+Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) {
+ Common::String str;
+
+ while (1) {
+ byte b = stream.readByte();
+
+ if (stream.eos() || stream.err() || b == until)
+ break;
+
+ str += b;
+ };
+
+ return str;
+}
+
+void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) {
+ while (1) {
+ Common::String str = readString(stream);
+ _display->printString(str);
+
+ if (--count == 0)
+ break;
+
+ stream.seek(3, SEEK_CUR);
+ };
+}
+
+AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
+ switch(type) {
+ case kGameTypeAdl1:
+ return AdlEngine_v1__create(syst, gd);
+ default:
+ error("Unknown GameType");
+ }
+}
+
+} // End of namespace Adl
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
new file mode 100644
index 0000000..d5a518fa
--- /dev/null
+++ b/engines/adl/adl.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 ADL_ADL_H
+#define ADL_ADL_H
+
+#include "common/random.h"
+#include "engines/engine.h"
+#include "gui/debugger.h"
+
+namespace Common {
+class ReadStream;
+class SeekableReadStream;
+}
+
+namespace Adl {
+
+class Display;
+class Parser;
+class Console;
+struct AdlGameDescription;
+
+enum GameType {
+ kGameTypeNone = 0,
+ kGameTypeAdl1
+};
+
+Common::String asciiToApple(Common::String str);
+Common::String appleToAscii(Common::String str);
+
+enum {
+ STR_COMMON_ENTERCMD,
+ STR_COMMON_VERBERR,
+ STR_COMMON_NOUNERR,
+ STR_CUSTOM_START
+};
+
+#define A2CHAR(C) ((C) | 0x80)
+
+class AdlEngine : public Engine {
+public:
+ AdlEngine(OSystem *syst, const AdlGameDescription *gd);
+ virtual ~AdlEngine();
+
+ const AdlGameDescription *_gameDescription;
+ uint32 getFeatures() const;
+ const char *getGameId() const;
+
+ static AdlEngine *create(GameType type, OSystem *syst, const AdlGameDescription *gd);
+
+ Common::Error run();
+ virtual Common::String getExeString(uint id) = 0;
+
+protected:
+ virtual void runGame() = 0;
+ Common::String readString(Common::ReadStream &stream, byte until = 0);
+ void printStrings(Common::SeekableReadStream &stream, int count = 1);
+ Display *_display;
+ Parser *_parser;
+
+private:
+ Console *_console;
+
+ // We need random numbers
+ Common::RandomSource *_rnd;
+};
+
+// Example console class
+class Console : public GUI::Debugger {
+public:
+ Console(AdlEngine *vm) {}
+ virtual ~Console(void) {}
+};
+
+AdlEngine *AdlEngine_v1__create(OSystem *syst, const AdlGameDescription *gd);
+
+} // End of namespace Adl
+
+#endif
diff --git a/engines/adl/adl_v1.cpp b/engines/adl/adl_v1.cpp
new file mode 100644
index 0000000..61671e5
--- /dev/null
+++ b/engines/adl/adl_v1.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 "common/scummsys.h"
+
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/file.h"
+#include "common/fs.h"
+#include "common/system.h"
+#include "common/events.h"
+#include "common/stream.h"
+#include "graphics/palette.h"
+
+#include "engines/util.h"
+
+#include "adl/adl_v1.h"
+#include "adl/display.h"
+#include "adl/parser.h"
+
+namespace Adl {
+
+static uint exeStrings[STR_MH_TOTAL] = {
+ 23484, 23375, 23438, 27658, 0x6c31, 27729, 27772, 0x5f1e
+};
+
+AdlEngine_v1::AdlEngine_v1(OSystem *syst, const AdlGameDescription *gd) :
+ AdlEngine(syst, gd),
+ _state(kIntro),
+ _room(1),
+ _steps(1),
+ _isDark(false) {
+ _variables.resize(20);
+}
+
+void AdlEngine_v1::runIntro() {
+ Common::File file;
+
+ if (!file.open("AUTO LOAD OBJ"))
+ error("Failed to open file");
+
+ file.seek(0x1003);
+ _display->setMode(Display::kModeHires);
+ _display->loadFrameBuffer(file);
+ _display->decodeFrameBuffer();
+ _display->delay(4000);
+
+ if (shouldQuit())
+ return;
+
+ _display->setMode(Display::kModeText);
+
+ Common::File basic;
+ if (!basic.open("MYSTERY.HELLO"))
+ error("Failed to open file");
+
+ Common::String str;
+
+ basic.seek(93);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + '\r');
+
+ basic.seek(299);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + "\r\r");
+
+ basic.seek(365);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + "\r\r");
+
+ basic.seek(601);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + '\r');
+
+ _display->inputKey();
+ if (g_engine->shouldQuit())
+ return;
+
+ _display->setMode(Display::kModeMixed);
+
+ file.seek(15);
+ str = readString(file);
+
+ while (1) {
+ _display->printString(str);
+ Common::String s = _display->inputString();
+
+ if (g_engine->shouldQuit())
+ break;
+
+ if (s.empty())
+ continue;
+
+ if ((byte)s[0] == ('I' | 0x80))
+ break;
+ else if ((byte)s[0] == ('G' | 0x80))
+ return;
+ };
+
+ _display->setMode(Display::kModeText);
+ file.seek(102);
+
+ const int pages[] = { 6, 6, 4, 5, 8, 7, 0 };
+
+ int page = 0;
+ while (pages[page] != 0) {
+ _display->home();
+ printStrings(file, pages[page++]);
+ _display->inputString();
+
+ if (g_engine->shouldQuit())
+ return;
+
+ file.seek(9, SEEK_CUR);
+ }
+}
+
+void AdlEngine_v1::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset) {
+ byte x, y;
+ bool bNewLine = false;
+ byte oldX = 0, oldY = 0;
+ while (1) {
+ x = stream.readByte();
+ y = stream.readByte();
+
+ if (stream.err() || stream.eos())
+ error("Failed to read picture");
+
+ if (x == 0xff && y == 0xff)
+ return;
+
+ if (x == 0 && y == 0) {
+ bNewLine = true;
+ continue;
+ }
+
+ x += xOffset;
+ y += yOffset;
+
+ if (y > 160)
+ y = 160;
+
+ if (bNewLine) {
+ _display->drawPixel(x, y, 0x7f);
+ bNewLine = false;
+ } else {
+ _display->drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
+ }
+
+ oldX = x;
+ oldY = y;
+ }
+}
+
+void AdlEngine_v1::drawPic(byte pic, byte xOffset, byte yOffset) {
+ Common::File f;
+ Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
+
+ if (!f.open(name))
+ error("Failed to open file");
+
+ f.seek(_pictures[pic].offset);
+ drawPic(f, xOffset, yOffset);
+}
+
+void AdlEngine_v1::drawItems() {
+ Common::Array<Item>::const_iterator it;
+
+ uint dropped = 0;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field2 != _room)
+ continue;
+
+ if (it->field7 == 1) {
+ if (_rooms[_room].field8 == _rooms[_room].picture) {
+ const Common::Point &p = _itemOffsets[dropped];
+ if (it->field4)
+ _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
+ else
+ drawPic(it->field3, p.x, p.y);
+ ++dropped;
+ }
+ continue;
+ }
+
+ Common::Array<byte>::const_iterator it2;
+
+ for (it2 = it->field10.begin(); it2 != it->field10.end(); ++it2) {
+ if (*it2 == _rooms[_room].picture) {
+ if (it->field4)
+ _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(it->field5, it->field6), 0, 1, 0x7f);
+ else
+ drawPic(it->field3, it->field5, it->field6);
+ continue;
+ }
+ }
+ }
+}
+
+void AdlEngine_v1::showRoom() {
+ if (!_isDark) {
+ drawPic(_rooms[_room].picture, 0, 0);
+ drawItems();
+ }
+
+ _display->decodeFrameBuffer();
+ printMessage(_rooms[_room].description, false);
+}
+
+Common::String AdlEngine_v1::getExeString(uint idx) {
+ return _exeStrings[idx];
+}
+
+void AdlEngine_v1::wordWrap(Common::String &str) {
+ uint end = 39;
+
+ while (1) {
+ if (str.size() <= end)
+ return;
+
+ while (str[end] != (char)A2CHAR(' '))
+ --end;
+
+ str.setChar((char)A2CHAR('\r'), end);
+ end += 40;
+ }
+}
+
+void AdlEngine_v1::printMessage(uint idx, bool wait) {
+ // Hardcoded overrides that don't wait after printing
+ // Note: strings may differ slightly from the ones in MESSAGES
+ switch (idx) {
+ case 137:
+ _display->printString(_exeStrings[STR_MH_DIRERR]);
+ return;
+ case 127:
+ _display->printString(_exeStrings[STR_MH_DONTHAVEIT]);
+ return;
+ case 37:
+ _display->printString(_exeStrings[STR_MH_DONTUNDERSTAND]);
+ return;
+ case 7:
+ _display->printString(_exeStrings[STR_MH_GETTINGDARK]);
+ return;
+ }
+
+ Common::String msg = _msgStrings[idx - 1];
+ wordWrap(msg);
+ _display->printString(msg);
+
+ if (wait)
+ _display->delay(14 * 166018 / 1000);
+}
+
+void AdlEngine_v1::readCommands(Common::ReadStream &stream, Commands &commands) {
+ while (1) {
+ Command command;
+ command.room = stream.readByte();
+
+ if (command.room == 0xff)
+ return;
+
+ command.verb = stream.readByte();
+ command.noun = stream.readByte();
+
+ byte scriptSize = stream.readByte() - 6;
+
+ command.numCond = stream.readByte();
+ command.numAct = stream.readByte();
+
+ for (uint i = 0; i < scriptSize; ++i)
+ command.script.push_back(stream.readByte());
+
+ if (stream.eos() || stream.err())
+ error("Failed to read commands");
+
+ commands.push_back(command);
+ }
+}
+
+void AdlEngine_v1::takeItem(byte noun) {
+ Common::Array<Item>::iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field1 != noun || it->field2 != _room)
+ continue;
+
+ if (it->field7 == 2) {
+ // It doesn't move
+ printMessage(151);
+ return;
+ }
+
+ if (it->field7 == 1) {
+ it->field2 = 0xfe;
+ it->field7 = 1;
+ return;
+ }
+
+ Common::Array<byte>::const_iterator it2;
+ for (it2 = it->field10.begin(); it->field10.end(); ++it2) {
+ if (*it2 == _rooms[_room].picture) {
+ it->field2 = 0xfe;
+ it->field7 = 1;
+ return;
+ }
+ }
+ }
+
+ // Item not here
+ printMessage(152);
+}
+
+void AdlEngine_v1::dropItem(byte noun) {
+ Common::Array<Item>::iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field1 != noun || it->field2 != 0xfe)
+ continue;
+
+ it->field2 = _room;
+ it->field7 = 1;
+ return;
+ }
+
+ // Don't understand
+ printMessage(37);
+}
+
+void AdlEngine_v1::doActions(const Command &command, byte noun, byte offset) {
+ for (uint i = 0; i < command.numAct; ++i) {
+ switch (command.script[offset]) {
+ case 1:
+ _variables[command.script[offset + 2]] += command.script[offset + 1];
+ offset += 3;
+ break;
+ case 2:
+ _variables[command.script[offset + 2]] -= command.script[offset + 1];
+ offset += 3;
+ break;
+ case 3:
+ _variables[command.script[offset + 1]] = command.script[offset + 2];
+ offset += 3;
+ break;
+ case 4: {
+ Common::Array<Item>::const_iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it)
+ if (it->field2 == 0xfe)
+ printMessage(it->field8);
+
+ ++offset;
+ break;
+ }
+ case 5:
+ _inventory[command.script[offset + 1] - 1].field2 = command.script[offset + 2];
+ offset += 3;
+ break;
+ case 6:
+ _rooms[_room].picture = _rooms[_room].field8;
+ _room = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 7:
+ _rooms[_room].picture = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 8:
+ _rooms[_room].field8 = _rooms[_room].picture = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 9:
+ printMessage(command.script[offset + 1]);
+ offset += 2;
+ break;
+ case 0xa:
+ _isDark = false;
+ ++offset;
+ break;
+ case 0xb:
+ _isDark = true;
+ ++offset;
+ break;
+ case 0xf:
+ warning("Save game not implemented");
+ ++offset;
+ break;
+ case 0x10:
+ warning("Load game not implemented");
+ ++offset;
+ break;
+ case 0x11: {
+ _display->printString(_exeStrings[STR_MH_PLAYAGAIN]);
+ Common::String input = _display->inputString();
+ if (input.size() == 0 || input[0] != (char)A2CHAR('N')) {
+ warning("Restart game not implemented");
+ return;
+ }
+ // Fall-through
+ }
+ case 0xd:
+ printMessage(140);
+ quitGame();
+ return;
+ case 0x12: {
+ byte item = command.script[offset + 1] - 1;
+ _inventory[item].field2 = command.script[offset + 2];
+ _inventory[item].field5 = command.script[offset + 3];
+ _inventory[item].field6 = command.script[offset + 4];
+ offset += 5;
+ break;
+ }
+ case 0x13: {
+ byte item = command.script[offset + 2] - 1;
+ _inventory[item].field3 = command.script[offset + 1];
+ offset += 3;
+ break;
+ }
+ case 0x14:
+ _rooms[_room].picture = _rooms[_room].field8;
+ ++offset;
+ break;
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a: {
+ byte room = _rooms[_room].connections[command.script[offset] - 0x15];
+
+ if (room == 0) {
+ printMessage(137);
+ return;
+ }
+
+ _rooms[_room].picture = _rooms[_room].field8;
+ _room = room;
+ return;
+ }
+ case 0x1b:
+ takeItem(noun);
+ ++offset;
+ break;
+ case 0x1c:
+ dropItem(noun);
+ ++offset;
+ break;
+ case 0x1d:
+ _rooms[command.script[offset + 1]].field8 = _rooms[command.script[offset + 1]].picture = command.script[offset + 2];
+ offset += 3;
+ break;
+ default:
+ error("Invalid action opcode %02x", command.script[offset]);
+ }
+ }
+}
+
+bool AdlEngine_v1::checkCommand(const Command &command, byte verb, byte noun) {
+ if (command.room != 0xfe && command.room != _room)
+ return false;
+
+ if (command.verb != 0xfe && command.verb != verb)
+ return false;
+
+ if (command.noun != 0xfe && command.noun != noun)
+ return false;
+
+ uint offset = 0;
+ for (uint i = 0; i < command.numCond; ++i) {
+ switch (command.script[offset]) {
+ case 3:
+ if (_inventory[command.script[offset + 1] - 1].field2 != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ case 5:
+ if (command.script[offset + 1] > _steps)
+ return false;
+ offset += 2;
+ break;
+ case 6:
+ if (_variables[command.script[offset + 1]] != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ case 9:
+ if (_rooms[_room].picture != command.script[offset + 1])
+ return false;
+ offset += 2;
+ break;
+ case 10:
+ if (_inventory[command.script[offset + 1] - 1].field3 != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ default:
+ error("Invalid condition opcode %02x", command.script[offset]);
+ }
+ }
+
+ doActions(command, noun, offset);
+
+ return true;
+}
+
+bool AdlEngine_v1::doOneCommand(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator it;
+
+ for (it = commands.begin(); it != commands.end(); ++it) {
+ if (checkCommand(*it, verb, noun)) {
+ debug("Found match: %i %i %i", it->room, it->verb, it->noun);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void AdlEngine_v1::doAllCommands(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator it;
+
+ for (it = commands.begin(); it != commands.end(); ++it) {
+ if (checkCommand(*it, verb, noun)) {
+ debug("Found match: %i %i %i", it->room, it->verb, it->noun);
+ }
+ }
+}
+
+void AdlEngine_v1::clearScreen() {
+ _display->setMode(Display::kModeMixed);
+ _display->clear(0x00);
+}
+
+void AdlEngine_v1::runGame() {
+ runIntro();
+ _display->printASCIIString("\r");
+
+ Common::File f;
+
+ if (!f.open("MESSAGES"))
+ error("Failed to open file");
+
+ while (!f.eos() && !f.err())
+ _msgStrings.push_back(readString(f, A2CHAR('\r')) + (char)A2CHAR('\r'));
+
+ f.close();
+
+ if (!f.open("ADVENTURE"))
+ error("Failed to open file");
+
+ // Load strings from executable
+ for (uint idx = 0; idx < STR_MH_TOTAL; ++idx) {
+ f.seek(exeStrings[idx]);
+ _exeStrings.push_back(readString(f));
+ }
+
+ // Load room data from executable
+ f.seek(1280);
+ for (uint i = 0; i < MH_ROOMS; ++i) {
+ struct Room room;
+ f.readByte();
+ room.description = f.readByte();
+ for (uint j = 0; j < 6; ++j)
+ room.connections[j] = f.readByte();
+ room.field8 = f.readByte();
+ room.picture = f.readByte();
+ _rooms.push_back(room);
+ }
+
+ // Load inventory data from executable
+ f.seek(0x100);
+ while (f.readByte() != 0xff) {
+ struct Item item;
+ item.field1 = f.readByte();
+ item.field2 = f.readByte();
+ item.field3 = f.readByte();
+ item.field4 = f.readByte();
+ item.field5 = f.readByte();
+ item.field6 = f.readByte();
+ item.field7 = f.readByte();
+ item.field8 = f.readByte();
+
+ f.readByte();
+
+ byte size = f.readByte();
+
+ for (uint i = 0; i < size; ++i)
+ item.field10.push_back(f.readByte());
+
+ _inventory.push_back(item);
+ }
+
+ // Load picture data from executable
+ f.seek(0x4b00);
+ for (uint i = 0; i < MH_PICS; ++i) {
+ struct Picture pic;
+ pic.block = f.readByte();
+ pic.offset = f.readUint16LE();
+ _pictures.push_back(pic);
+ }
+
+ // Load commands from executable
+ f.seek(0x3D00);
+ readCommands(f, _roomCommands);
+
+ f.seek(0x3C00);
+ readCommands(f, _globalCommands);
+
+ // Load dropped item offsets
+ f.seek(0x68ff);
+ for (uint i = 0; i < MH_ITEM_OFFSETS; ++i) {
+ Common::Point p;
+ p.x = f.readByte();
+ p.y = f.readByte();
+ _itemOffsets.push_back(p);
+ }
+
+ // Load right-angle drawings
+ f.seek(0x4f00);
+ uint16 drawingsTotal = f.readUint16LE();
+ for (uint i = 0; i < drawingsTotal; ++i) {
+ f.seek(0x4f00 + 2 + i * 2);
+ uint16 offset = f.readUint16LE();
+ f.seek(0x4f00 + offset);
+
+ Common::Array<byte> drawing;
+ byte b = f.readByte();
+ while (b != 0) {
+ drawing.push_back(b);
+ b = f.readByte();
+ }
+ _drawings.push_back(drawing);
+ }
+
+ // Title screen shown during loading
+ f.seek(0x1800);
+ _display->loadFrameBuffer(f);
+ _display->decodeFrameBuffer();
+ _display->delay(2000);
+
+ f.seek(0x3800);
+ _parser->loadVerbs(f);
+
+ f.seek(0xf00);
+ _parser->loadNouns(f);
+
+ while (1) {
+ uint verb = 0, noun = 0;
+ clearScreen();
+ showRoom();
+ _parser->getInput(verb, noun);
+
+ if (!doOneCommand(_roomCommands, verb, noun))
+ printMessage(37);
+ doAllCommands(_globalCommands, verb, noun);
+
+ _steps++;
+
+ if (shouldQuit())
+ return;
+ }
+}
+
+AdlEngine *AdlEngine_v1__create(OSystem *syst, const AdlGameDescription *gd) {
+ return new AdlEngine_v1(syst, gd);
+}
+
+} // End of namespace Adl
diff --git a/engines/adl/adl_v1.h b/engines/adl/adl_v1.h
new file mode 100644
index 0000000..b8f4c53
--- /dev/null
+++ b/engines/adl/adl_v1.h
@@ -0,0 +1,133 @@
+/* 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 ADL_ADL_V1_H
+#define ADL_ADL_V1_H
+
+#include "adl/adl.h"
+
+namespace Common {
+class ReadStream;
+}
+
+namespace Adl {
+
+enum {
+ // Some of these are probably common
+ STR_MH_DIRERR = STR_CUSTOM_START,
+ STR_MH_DONTHAVEIT,
+ STR_MH_DONTUNDERSTAND,
+ STR_MH_GETTINGDARK,
+ STR_MH_PLAYAGAIN,
+
+ STR_MH_TOTAL
+};
+
+class AdlEngine_v1 : public AdlEngine {
+public:
+ AdlEngine_v1(OSystem *syst, const AdlGameDescription *gd);
+ Common::String getExeString(uint idx);
+
+protected:
+ void runGame();
+
+private:
+ enum {
+ MH_ROOMS = 42,
+ MH_PICS = 98,
+ MH_ITEM_OFFSETS = 21
+ };
+
+ enum State {
+ kIntro,
+ kIdle
+ };
+
+ struct Room {
+ byte description;
+ byte connections[6];
+ byte field8;
+ byte picture;
+ };
+
+ struct Picture {
+ byte block;
+ uint16 offset;
+ };
+
+ struct Command {
+ byte room;
+ byte verb, noun;
+ byte numCond, numAct;
+ Common::Array<byte> script;
+ };
+
+ struct Item {
+ byte field1;
+ byte field2;
+ byte field3;
+ byte field4;
+ byte field5;
+ byte field6;
+ byte field7;
+ byte field8;
+ Common::Array<byte> field10;
+ };
+
+ typedef Common::List<Command> Commands;
+
+ int _state;
+
+ void runIntro();
+ void drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset);
+ void showRoom();
+ void printMessage(uint idx, bool wait = true);
+ void wordWrap(Common::String &str);
+ void readCommands(Common::ReadStream &stream, Commands &commands);
+ bool checkCommand(const Command &command, byte verb, byte noun);
+ bool doOneCommand(const Commands &commands, byte verb, byte noun);
+ void doAllCommands(const Commands &commands, byte verb, byte noun);
+ void doActions(const Command &command, byte noun, byte offset);
+ void clearScreen();
+ void takeItem(byte noun);
+ void dropItem(byte noun);
+ void drawItems();
+ void drawPic(byte pic, byte xOffset, byte yOffset);
+
+ Common::Array<Common::String> _exeStrings;
+ Common::Array<Common::String> _msgStrings;
+ Common::Array<Room> _rooms;
+ Common::Array<Picture> _pictures;
+ Common::Array<Item> _inventory;
+ Common::Array<Common::Point> _itemOffsets;
+ Common::Array<Common::Array<byte> > _drawings;
+ Commands _roomCommands;
+ Commands _globalCommands;
+ byte _room;
+ uint16 _steps;
+ Common::Array<byte> _variables;
+ bool _isDark;
+};
+
+} // End of namespace Adl
+
+#endif
diff --git a/engines/adl/configure.engine b/engines/adl/configure.engine
new file mode 100644
index 0000000..844e2b8
--- /dev/null
+++ b/engines/adl/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 adl "ADL" no
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
new file mode 100644
index 0000000..ba4e010
--- /dev/null
+++ b/engines/adl/detection.cpp
@@ -0,0 +1,108 @@
+/* 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 "adl/adl.h"
+
+#include "common/config-manager.h"
+#include "common/error.h"
+#include "common/fs.h"
+
+#include "engines/advancedDetector.h"
+#include "engines/metaengine.h"
+
+namespace Adl {
+
+struct AdlGameDescription {
+ ADGameDescription desc;
+ GameType gameType;
+};
+
+uint32 AdlEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+const char *AdlEngine::getGameId() const {
+ return _gameDescription->desc.gameid;
+}
+
+const char *const directoryGlobs[] = {
+ "game",
+ "datafiles",
+ 0
+};
+
+static const PlainGameDescriptor adlGames[] = {
+ // Games
+ {"hires1", "Hi-Res Adventure #1: Mystery House"},
+ {0, 0}
+};
+
+static const AdlGameDescription gameDescriptions[] = {
+
+ { // MD5 by waltervn
+ {
+ "hires1", 0,
+ {
+ {"ADVENTURE", 0, "22d9e63a11d69fa033ba1738715ad09a", 29952},
+ {"AUTO LOAD OBJ", 0, "23bfccfe9fcff9b22cf6c41bde9078ac", 12291},
+ {"MYSTERY.HELLO", 0, "2289b7fea300b506e902a4c597968369", 836},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformApple2GS, // FIXME
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdl1
+ },
+ {AD_TABLE_END_MARKER, kGameTypeNone}
+};
+
+class AdlMetaEngine : public AdvancedMetaEngine {
+public:
+ AdlMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(AdlGameDescription), adlGames) { }
+
+ const char *getName() const {
+ return "Hi-Res Adventure";
+ }
+
+ const char *getOriginalCopyright() const {
+ return "Copyright (C) Sierra On-Line";
+ }
+
+ bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
+};
+
+bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
+ if (gd) {
+ *engine = AdlEngine::create(((const AdlGameDescription *)gd)->gameType, syst, (const AdlGameDescription *)gd);
+ }
+ return gd != 0;
+}
+
+} // End of namespace Adl
+
+#if PLUGIN_ENABLED_DYNAMIC(ADL)
+ REGISTER_PLUGIN_DYNAMIC(ADL, PLUGIN_TYPE_ENGINE, Adl::AdlMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(ADL, PLUGIN_TYPE_ENGINE, Adl::AdlMetaEngine);
+#endif
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
new file mode 100644
index 0000000..02b8d51
--- /dev/null
+++ b/engines/adl/display.cpp
@@ -0,0 +1,611 @@
+/* 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 "adl/display.h"
+#include "common/stream.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "common/system.h"
+#include "common/str.h"
+#include "common/events.h"
+#include "common/rect.h"
+#include "common/array.h"
+#include "engines/engine.h"
+
+namespace Adl {
+
+static byte font[64][5] = {
+ { 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A
+ { 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC
+ { 0xfe, 0x82, 0x82, 0x82, 0x7c }, { 0xfe, 0x92, 0x92, 0x92, 0x82 }, // DE
+ { 0xfe, 0x12, 0x12, 0x12, 0x02 }, { 0x7c, 0x82, 0x82, 0xa2, 0xe2 }, // FG
+ { 0xfe, 0x10, 0x10, 0x10, 0xfe }, { 0x00, 0x82, 0xfe, 0x82, 0x00 }, // HI
+ { 0x40, 0x80, 0x80, 0x80, 0x7e }, { 0xfe, 0x10, 0x28, 0x44, 0x82 }, // JK
+ { 0xfe, 0x80, 0x80, 0x80, 0x80 }, { 0xfe, 0x04, 0x18, 0x04, 0xfe }, // LM
+ { 0xfe, 0x08, 0x10, 0x20, 0xfe }, { 0x7c, 0x82, 0x82, 0x82, 0x7c }, // NO
+ { 0xfe, 0x12, 0x12, 0x12, 0x0c }, { 0x7c, 0x82, 0xa2, 0x42, 0xbc }, // PQ
+ { 0xfe, 0x12, 0x32, 0x52, 0x8c }, { 0x4c, 0x92, 0x92, 0x92, 0x64 }, // RS
+ { 0x02, 0x02, 0xfe, 0x02, 0x02 }, { 0x7e, 0x80, 0x80, 0x80, 0x7e }, // TU
+ { 0x3e, 0x40, 0x80, 0x40, 0x3e }, { 0xfe, 0x40, 0x30, 0x40, 0xfe }, // VW
+ { 0xc6, 0x28, 0x10, 0x28, 0xc6 }, { 0x06, 0x08, 0xf0, 0x08, 0x06 }, // XY
+ { 0xc2, 0xa2, 0x92, 0x8a, 0x86 }, { 0xfe, 0xfe, 0x82, 0x82, 0x82 }, // Z[
+ { 0x04, 0x08, 0x10, 0x20, 0x40 }, { 0x82, 0x82, 0x82, 0xfe, 0xfe }, // \]
+ { 0x20, 0x10, 0x08, 0x10, 0x20 }, { 0x80, 0x80, 0x80, 0x80, 0x80 }, // ^_
+ { 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0xbe, 0x00, 0x00 }, // !
+ { 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x28, 0xfe, 0x28, 0xfe, 0x28 }, // "#
+ { 0x48, 0x54, 0xfe, 0x54, 0x24 }, { 0x46, 0x26, 0x10, 0xc8, 0xc4 }, // $%
+ { 0x6c, 0x92, 0xac, 0x40, 0xa0 }, { 0x00, 0x00, 0x0e, 0x00, 0x00 }, // &'
+ { 0x38, 0x44, 0x82, 0x00, 0x00 }, { 0x00, 0x00, 0x82, 0x44, 0x38 }, // ()
+ { 0x44, 0x28, 0xfe, 0x28, 0x44 }, { 0x10, 0x10, 0x7c, 0x10, 0x10 }, // *+
+ { 0x00, 0x80, 0x60, 0x00, 0x00 }, { 0x10, 0x10, 0x10, 0x10, 0x10 }, // ,-
+ { 0x00, 0x00, 0x80, 0x00, 0x00 }, { 0x40, 0x20, 0x10, 0x08, 0x04 }, // ./
+ { 0x7c, 0xa2, 0x92, 0x8a, 0x7c }, { 0x00, 0x84, 0xfe, 0x80, 0x00 }, // 01
+ { 0xc4, 0xa2, 0x92, 0x92, 0x8c }, { 0x42, 0x82, 0x92, 0x9a, 0x66 }, // 23
+ { 0x30, 0x28, 0x24, 0xfe, 0x20 }, { 0x4e, 0x8a, 0x8a, 0x8a, 0x72 }, // 45
+ { 0x78, 0x94, 0x92, 0x92, 0x62 }, { 0x02, 0xe2, 0x12, 0x0a, 0x06 }, // 67
+ { 0x6c, 0x92, 0x92, 0x92, 0x6c }, { 0x8c, 0x92, 0x92, 0x52, 0x3c }, // 89
+ { 0x00, 0x00, 0x28, 0x00, 0x00 }, { 0x00, 0x80, 0x68, 0x00, 0x00 }, // :;
+ { 0x10, 0x28, 0x44, 0x82, 0x00 }, { 0x28, 0x28, 0x28, 0x28, 0x28 }, // <=
+ { 0x00, 0x82, 0x44, 0x28, 0x10 }, { 0x04, 0x02, 0xb2, 0x0a, 0x04 } // >?
+};
+
+Display::Display() :
+ _scanlines(false),
+ _cursorPos(0),
+ _mode(kModeText) {
+ _frameBuf = new byte[kFrameBufSize];
+ _frameBufSurface = new Graphics::Surface;
+ _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
+
+ _textBuf = new byte[kTextBufSize];
+ memset(_textBuf, ' ' | 0x80, kTextBufSize);
+ _textBufSurface = new Graphics::Surface;
+ _textBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
+
+ createFont();
+
+ struct PixelPos rel = getPixelPos(0, 191);
+ struct PixelPos absy;
+ for (int i = 191; i >= 0; --i) {
+ absy = getPixelPos(0, i);
+ if (absy.rowAddr != rel.rowAddr)
+ debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr);
+ moveY(rel, false);
+ }
+ absy = getPixelPos(0, 191);
+ if (absy.rowAddr != rel.rowAddr)
+ debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr);
+
+ rel = getPixelPos(0, 0);
+ for (int i = 0; i < 192; ++i) {
+ absy = getPixelPos(0, i);
+ if (absy.rowAddr != rel.rowAddr)
+ debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr);
+ moveY(rel, true);
+ }
+ absy = getPixelPos(0, 0);
+ if (absy.rowAddr != rel.rowAddr)
+ debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr);
+}
+
+Display::~Display() {
+ delete[] _frameBuf;
+ _frameBufSurface->free();
+ delete _frameBufSurface;
+
+ delete[] _textBuf;
+ _textBufSurface->free();
+ delete _textBufSurface;
+
+ _font->free();
+ delete _font;
+}
+
+void Display::loadFrameBuffer(Common::ReadStream &stream) {
+ stream.read(_frameBuf, kFrameBufSize);
+}
+
+void Display::decodeScanline(byte *dst, int pitch, byte *src) {
+ // TODO: shift secondPal by half a pixel
+
+ bool prevOn = false;
+
+ for (uint j = 0; j < 39; ++j) {
+ bool secondPal = src[j] & 0x80;
+ byte cur = src[j];
+ byte next = 0;
+ if (j != 39)
+ next = src[j + 1];
+
+ for (uint k = 0; k < 7; ++k) {
+ bool curOn = cur & (1 << k);
+ bool nextOn;
+
+ if (k != 6)
+ nextOn = cur & (1 << (k + 1));
+ else
+ nextOn = next & 1;
+
+ byte color;
+ if (curOn == prevOn || curOn == nextOn)
+ color = curOn ? 1 : 0;
+ else {
+ if (secondPal)
+ color = (curOn == ((j + k) % 2) ? 5 : 4);
+ else
+ color = (curOn == ((j + k) % 2) ? 3 : 2);
+ }
+
+ dst[0] = color;
+ dst[1] = color;
+
+ if (!_scanlines) {
+ dst[pitch] = color;
+ dst[pitch + 1] = color;
+ }
+
+ dst += 2;
+ prevOn = curOn;
+ }
+ }
+}
+
+Display::PixelPos Display::getPixelPos(byte x, byte y) {
+ PixelPos pixelPos;
+
+ // FIXME: check X, Y range
+
+ byte offsetL = y & 0xc0;
+ offsetL |= offsetL >> 2;
+ byte offsetH = y;
+ y <<= 2;
+ offsetH <<= 1;
+ offsetH |= y >> 7;
+ y <<= 1;
+ offsetH <<= 1;
+ offsetH |= y >> 7;
+ y <<= 1;
+ offsetL >>= 1;
+ offsetL |= y & 0x80;
+ y <<= 1;
+ offsetH = offsetH & 0x1f;
+ pixelPos.rowAddr = (offsetH << 8) | offsetL;
+ pixelPos.byteOffset = x / 7;
+ pixelPos.bitMask = 0x80 | (1 << x % 7);
+
+ return pixelPos;
+}
+
+byte Display::getPixelColor(byte offset, byte color) {
+ if (offset & 1) {
+ byte c = color << 1;
+ if (c >= 0x40 && c < 0xc0)
+ return color ^ 0x7f;
+ }
+
+ return color;
+}
+
+void Display::decodeFrameBuffer() {
+ byte *src = _frameBuf;
+ int pitch = _frameBufSurface->pitch;
+ for (int j = 0; j < 8; ++j) {
+ for (int i = 0; i < 8; ++i) {
+ byte *dst = (byte *)_frameBufSurface->getPixels() + pitch * 2 * (i * 8 + j);
+ decodeScanline(dst, pitch, src);
+ src += 40;
+ dst += pitch * 2 * 64;
+ decodeScanline(dst, pitch, src);
+ src += 40;
+ dst += pitch * 2 * 64;
+ decodeScanline(dst, pitch, src);
+ src += 48;
+ dst += pitch * 2 * 64;
+ }
+ }
+}
+
+void Display::drawPixel(byte x, byte y, byte color) {
+ PixelPos p = getPixelPos(x, y);
+ byte c = getPixelColor(p.byteOffset, color);
+ byte *b = _frameBuf + p.rowAddr + p.byteOffset;
+ c ^= *b;
+ c &= p.bitMask;
+ c ^= *b;
+ *b = c;
+}
+
+void Display::moveX(PixelPos &p, byte &color, bool left) {
+ if (left) {
+ byte bit = p.bitMask;
+ bool b = bit & 1;
+ bit >>= 1;
+ if (!b) {
+ bit ^= 0xc0;
+ p.bitMask = bit;
+ return;
+ }
+ --p.byteOffset;
+ if (p.byteOffset & 0x80)
+ p.byteOffset = 39;
+ p.bitMask = 0xc0;
+ } else {
+ byte bit = p.bitMask;
+ bit <<= 1;
+ bit ^= 0x80;
+ if (bit & 0x80) {
+ p.bitMask = bit;
+ return;
+ }
+ p.bitMask = 0x81;
+ ++p.byteOffset;
+ if (p.byteOffset == 40)
+ p.byteOffset = 0;
+ }
+
+ color = getPixelColor(p.byteOffset, color);
+}
+
+void Display::moveY(PixelPos &p, bool down) {
+ if (!down) {
+ if (p.rowAddr & 0x1c00)
+ p.rowAddr -= 0x400;
+ else if (p.rowAddr & 0x380)
+ p.rowAddr += 0x1b80;
+ else {
+ p.rowAddr += 0x1f58;
+ if (!(p.rowAddr & 0x80))
+ p.rowAddr += 0x78; // Wrap around
+ }
+ } else {
+ p.rowAddr += 0x400;
+ if (p.rowAddr & 0x1c00)
+ return;
+ else if ((p.rowAddr & 0x380) != 0x380)
+ p.rowAddr -= 0x1f80;
+ else {
+ p.rowAddr -= 0x2358;
+ if ((p.rowAddr & 0x78) == 0x78)
+ p.rowAddr -= 0x78; // Wrap around
+ }
+ }
+}
+
+void Display::drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant) {
+ if (bits & 4) {
+ byte b = (_frameBuf[p.rowAddr + p.byteOffset] ^ color) & p.bitMask;
+ _frameBuf[p.rowAddr + p.byteOffset] ^= b;
+ }
+
+ bits += quadrant;
+
+ if (bits & 1)
+ moveX(p, color, bits & 2);
+ else
+ moveY(p, bits & 2);
+}
+
+void Display::drawRightAngles(Common::Array<byte> &rightAngles, Common::Point p, byte rotation, byte scaling, byte color) {
+ const byte stepping[] = {
+ 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
+ 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
+ 0xff
+ };
+
+ PixelPos pos = getPixelPos(p.x, p.y);
+ byte c = getPixelColor(pos.byteOffset, color);
+
+ byte quadrant = rotation >> 4;
+ rotation &= 0xf;
+ byte xStep = stepping[rotation];
+ byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
+
+ for (uint i = 0; i < rightAngles.size(); ++i) {
+ byte b = rightAngles[i];
+
+ do {
+ byte xFrac = 0x80;
+ byte yFrac = 0x80;
+ for (uint j = 0; j < scaling; ++j) {
+ if (xFrac + xStep + 1 > 255)
+ drawNextPixel(pos, c, b, quadrant);
+ xFrac += xStep + 1;
+ if (yFrac + yStep > 255)
+ drawNextPixel(pos, c, b, quadrant + 1);
+ yFrac += yStep;
+ }
+ b >>= 3;
+ } while (b != 0);
+ }
+}
+
+void Display::drawLine(Common::Point p1, Common::Point p2, byte color) {
+ PixelPos p = getPixelPos(p1.x, p1.y);
+ byte c = getPixelColor(p.byteOffset, color);
+
+ int16 deltaX = p2.x - p1.x;
+ byte dir = deltaX >> 8;
+
+ if (deltaX < 0)
+ deltaX = -deltaX;
+
+ int16 err = deltaX;
+
+ int16 deltaY = p2.y - p1.y - 1;
+ dir >>= 1;
+ if (deltaY >= 0) {
+ deltaY = -deltaY - 2;
+ dir |= 0x80;
+ }
+
+ int16 steps = deltaY - deltaX;
+
+ err += deltaY + 1;
+
+ while (1) {
+ byte *b = _frameBuf + p.rowAddr + p.byteOffset;
+ byte d = *b;
+ d ^= c;
+ d &= p.bitMask;
+ d ^= *b;
+ *b = d;
+
+ if (++steps == 0)
+ return;
+
+ if (err < 0) {
+ moveY(p, dir & 0x80);
+ err += deltaX;
+ } else {
+ moveX(p, c, dir & 0x40);
+ err += deltaY + 1;
+ }
+ }
+}
+
+void Display::clear(byte color) {
+ for (uint i = 0; i < kFrameBufSize; ++i)
+ _frameBuf[i] = getPixelColor(i & 1, color);
+}
+
+void Display::updateTextSurface() {
+ for (uint row = 0; row < 24; ++row)
+ for (uint col = 0; col < 40; ++col) {
+ char c = _textBuf[row * 40 + col];
+
+ Common::Rect r(7 * 2, 8 * 2);
+ r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
+
+ if (!(c & 0x80)) {
+ if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1))
+ r.translate(0, 4 * 8 * 2);
+ }
+
+ _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
+ }
+}
+
+void Display::printString(const Common::String &str) {
+ Common::String::const_iterator it;
+ for (it = str.begin(); it != str.end(); ++it) {
+ byte b = *it;
+
+ if (b == ('\r' | 0x80))
+ _cursorPos = (_cursorPos / 40 + 1) * 40;
+ else if (b < 0x80 || b >= 0xa0)
+ _textBuf[_cursorPos++] = b;
+
+ if (_cursorPos == kTextBufSize) {
+ memmove(_textBuf, _textBuf + 40, kTextBufSize - 40);
+ memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40);
+ _cursorPos -= 40;
+ }
+ }
+
+ updateTextSurface();
+}
+
+void Display::printASCIIString(const Common::String &str) {
+ Common::String aStr;
+
+ Common::String::const_iterator it;
+ for (it = str.begin(); it != str.end(); ++it)
+ aStr += *it | 0x80;
+
+ printString(aStr);
+}
+
+void Display::drawChar(byte c, int x, int y) {
+ byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
+
+ for (uint row = 0; row < 8; ++row) {
+ for (uint col = 1; col < 6; ++col)
+ if (font[c][col - 1] & (1 << row)) {
+ buf[col * 2] = 1;
+ buf[col * 2 + 1] = 1;
+
+ if (!_scanlines) {
+ buf[_font->pitch + col * 2] = 1;
+ buf[_font->pitch + col * 2 + 1] = 1;
+ }
+ }
+
+ buf += 2 * _font->pitch;
+ }
+}
+
+void Display::createFont() {
+ _font = new Graphics::Surface;
+ _font->create(16 * 7 * 2, 4 * 8 * 2 * 2, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (uint i = 0; i < 4; ++i)
+ for (uint j = 0; j < 16; ++j)
+ drawChar(i * 16 + j, j * 7 * 2, i * 8 * 2);
+
+ // Create inverted font
+ byte *buf = (byte *)_font->getPixels();
+ byte *bufInv = buf + (_font->h / 2) * _font->pitch;
+
+ for (uint row = 0; row < _font->h / 2; ++row) {
+ if (!_scanlines || !(row & 1))
+ for (uint col = 0; col < _font->w; ++col)
+ bufInv[col] = buf[col] ? 0 : 1;
+
+ buf += _font->pitch;
+ bufInv += _font->pitch;
+ }
+}
+
+void Display::updateScreen() {
+ if (_mode == kModeText) {
+ g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h);
+ } else if (_mode == kModeHires) {
+ g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h);
+ } else {
+ g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2);
+ g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2);
+ }
+}
+
+Common::String Display::inputString(byte prompt) {
+ Common::String s;
+
+ if (prompt > 0)
+ printString(Common::String(prompt));
+
+ while (1) {
+ byte b = inputKey();
+
+ if (g_engine->shouldQuit())
+ return 0;
+
+ if (b == 0)
+ continue;
+
+ if (b == ('\r' | 0x80)) {
+ s += b;
+ printString(Common::String(b));
+ return s;
+ }
+
+ if (b < 0xa0) {
+ switch (b) {
+ case Common::KEYCODE_BACKSPACE | 0x80:
+ if (!s.empty()) {
+ --_cursorPos;
+ _textBuf[_cursorPos] = ' ' | 0x80;
+ s.deleteLastChar();
+ }
+ break;
+ };
+ } else {
+ s += b;
+ printString(Common::String(b));
+ }
+ }
+}
+
+byte Display::convertKey(uint16 ascii) {
+ ascii = toupper(ascii);
+
+ if (ascii >= 0x80)
+ return 0;
+
+ ascii |= 0x80;
+
+ if (ascii >= 0x80 && ascii <= 0xe0)
+ return ascii;
+
+ return 0;
+}
+
+byte Display::inputKey() {
+ Common::EventManager *ev = g_system->getEventManager();
+
+ byte orgChar = _textBuf[_cursorPos];
+ _textBuf[_cursorPos] = (orgChar & 0x3f) | 0x40;
+
+ byte key = 0;
+
+ while (!g_engine->shouldQuit() && key == 0) {
+ Common::Event event;
+ if (ev->pollEvent(event)) {
+ if (event.type != Common::EVENT_KEYDOWN)
+ continue;
+
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ if (event.kbd.keycode == Common::KEYCODE_q)
+ g_engine->quitGame();
+ continue;
+ }
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ case Common::KEYCODE_RETURN:
+ key = convertKey(event.kbd.keycode);
+ break;
+ default:
+ if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80)
+ key = convertKey(event.kbd.ascii);
+ };
+ }
+
+ updateTextSurface();
+ updateScreen();
+ g_system->updateScreen();
+ g_system->delayMillis(16);
+ }
+
+ _textBuf[_cursorPos] = orgChar;
+ return key;
+}
+
+void Display::delay(uint32 ms) {
+ Common::EventManager *ev = g_system->getEventManager();
+
+ uint32 start = g_system->getMillis();
+
+ while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) {
+ Common::Event event;
+ if (ev->pollEvent(event)) {
+ if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) {
+ switch(event.kbd.keycode) {
+ case Common::KEYCODE_q:
+ g_engine->quitGame();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ updateScreen();
+ g_system->updateScreen();
+ g_system->delayMillis(16);
+ }
+}
+
+void Display::home() {
+ memset(_textBuf, ' ' | 0x80, kTextBufSize);
+ _cursorPos = 0;
+}
+
+} // End of namespace Adl
diff --git a/engines/adl/display.h b/engines/adl/display.h
new file mode 100644
index 0000000..eabf340
--- /dev/null
+++ b/engines/adl/display.h
@@ -0,0 +1,103 @@
+/* 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 ADL_DISPLAY_H
+#define ADL_DISPLAY_H
+
+#include <common/types.h>
+#include <common/array.h>
+
+namespace Common {
+class ReadStream;
+class String;
+class Point;
+}
+
+namespace Graphics {
+class Surface;
+}
+
+namespace Adl {
+
+class Display {
+public:
+ enum Mode {
+ kModeHires,
+ kModeText,
+ kModeMixed
+ };
+
+ Display();
+ ~Display();
+ void loadFrameBuffer(Common::ReadStream &stream);
+ void decodeFrameBuffer();
+ void printString(const Common::String &str);
+ void printASCIIString(const Common::String &str);
+ void updateScreen();
+ Common::String inputString(byte prompt = 0);
+ void delay(uint32 ms);
+ void setMode(Mode mode) { _mode = mode; }
+ byte inputKey();
+ void home();
+ void drawPixel(byte x, byte y, byte color);
+ void drawLine(Common::Point p1, Common::Point p2, byte color);
+ void clear(byte color);
+ void drawRightAngles(Common::Array<byte> &rightAngles, Common::Point p, byte rotation, byte scaling, byte color);
+
+private:
+ enum {
+ kWidth = 280,
+ kHeight = 192,
+ kFrameBufSize = 0x2000,
+ kTextBufSize = 40 * 24
+ };
+
+ struct PixelPos {
+ uint16 rowAddr;
+ byte byteOffset;
+ byte bitMask;
+ };
+
+ void decodeScanline(byte *dst, int pitch, byte *src);
+ PixelPos getPixelPos(byte x, byte y);
+ byte getPixelColor(byte x, byte color);
+ void drawChar(byte c, int x, int y);
+ void createFont();
+ void updateTextSurface();
+ byte convertKey(uint16 ascii);
+ void moveX(PixelPos &p, byte &color, bool left);
+ void moveY(PixelPos &p, bool down);
+ void drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant);
+
+ bool _scanlines;
+ byte *_frameBuf;
+ byte *_textBuf;
+ Graphics::Surface *_frameBufSurface;
+ Graphics::Surface *_textBufSurface;
+ Graphics::Surface *_font;
+ int _cursorPos;
+ Mode _mode;
+};
+
+} // End of namespace Adl
+
+#endif
diff --git a/engines/adl/module.mk b/engines/adl/module.mk
new file mode 100644
index 0000000..8f86eee
--- /dev/null
+++ b/engines/adl/module.mk
@@ -0,0 +1,19 @@
+MODULE := engines/adl
+
+MODULE_OBJS := \
+ detection.o \
+ display.o \
+ adl.o \
+ adl_v1.o \
+ parser.o
+
+MODULE_DIRS += \
+ engines/adl
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_ADL), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/adl/parser.cpp b/engines/adl/parser.cpp
new file mode 100644
index 0000000..cdbaf3b
--- /dev/null
+++ b/engines/adl/parser.cpp
@@ -0,0 +1,172 @@
+/* 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 "adl/adl.h"
+#include "adl/parser.h"
+#include "adl/display.h"
+
+#include "engines/engine.h"
+
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/debug.h"
+#include "common/textconsole.h"
+
+namespace Adl {
+
+Parser::Parser(AdlEngine &engine, Display &display) :
+ _engine(engine),
+ _display(display) {
+
+}
+
+void Parser::loadWords(Common::ReadStream &stream, WordMap &map) {
+ uint index = 0;
+
+ while (1) {
+ ++index;
+
+ byte buf[kWordSize];
+
+ if (stream.read(buf, kWordSize) < kWordSize)
+ error("Error reading word list");
+
+ Common::String word((char *)buf, kWordSize);
+
+ if (!map.contains(word))
+ map[word] = index;
+
+ byte synonyms = stream.readByte();
+
+ if (stream.err() || stream.eos())
+ error("Error reading word list");
+
+ if (synonyms == 0xff)
+ break;
+
+ for (uint i = 0; i < synonyms; ++i) {
+ if (stream.read((char *)buf, kWordSize) < kWordSize)
+ error("Error reading word list");
+
+ word = Common::String((char *)buf, kWordSize);
+
+ if (!map.contains(word))
+ map[word] = index;
+ }
+ }
+}
+
+Common::String Parser::getLine() {
+ // Original engine uses a global here, which isn't reset between
+ // calls and may not match actual mode
+ bool textMode = false;
+
+ while (1) {
+ Common::String line = _display.inputString(A2CHAR('?'));
+
+ if (g_engine->shouldQuit())
+ return "";
+
+ if ((byte)line[0] == ('\r' | 0x80)) {
+ textMode = !textMode;
+ _display.setMode(textMode ? Display::kModeText : Display::kModeMixed);
+ continue;
+ }
+
+ // Remove the return
+ line.deleteLastChar();
+ return line;
+ }
+}
+
+Common::String Parser::getWord(const Common::String &line, uint &index) {
+ Common::String str;
+
+ for (uint i = 0; i < 8; ++i)
+ str += (char)(A2CHAR(' '));
+
+ int copied = 0;
+
+ // Skip initial whitespace
+ while (1) {
+ if (index == line.size())
+ return str;
+ if (line[index] != (char)(A2CHAR(' ')))
+ break;
+ ++index;
+ }
+
+ // Copy up to 8 characters
+ while (1) {
+ if (copied < 8)
+ str.setChar(line[index], copied++);
+
+ index++;
+
+ if (index == line.size() || line[index] == (char)(A2CHAR(' ')))
+ return str;
+ }
+}
+
+void Parser::getInput(uint &verb, uint &noun) {
+ while (1) {
+ _display.printString(_engine.getExeString(STR_COMMON_ENTERCMD));
+ Common::String line = getLine();
+
+ if (g_engine->shouldQuit())
+ return;
+
+ uint index = 0;
+ Common::String verbStr = getWord(line, index);
+ debug("Verb: \"%s\"", appleToAscii(verbStr).c_str());
+
+ if (!_verbs.contains(verbStr)) {
+ Common::String err = _engine.getExeString(STR_COMMON_VERBERR);
+ for (uint i = 0; i < verbStr.size(); ++i)
+ err.setChar(verbStr[i], i + 19);
+ _display.printString(err);
+ continue;
+ }
+
+ verb = _verbs[verbStr];
+ debug("Verb ID: %i", verb);
+
+ Common::String nounStr = getWord(line, index);
+ debug("Noun: \"%s\"", appleToAscii(nounStr).c_str());
+
+ if (!_nouns.contains(nounStr)) {
+ Common::String err = _engine.getExeString(STR_COMMON_NOUNERR);
+ for (uint i = 0; i < verbStr.size(); ++i)
+ err.setChar(verbStr[i], i + 19);
+ for (uint i = 0; i < nounStr.size(); ++i)
+ err.setChar(nounStr[i], i + 30);
+ _display.printString(err);
+ continue;
+ }
+
+ noun = _nouns[nounStr];
+ debug("Noun ID: %i", noun);
+ return;
+ }
+}
+
+} // End of namespace Adl
diff --git a/engines/adl/parser.h b/engines/adl/parser.h
new file mode 100644
index 0000000..3c191d9
--- /dev/null
+++ b/engines/adl/parser.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 ADL_PARSER_H
+#define ADL_PARSER_H
+
+#include "common/types.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace Common {
+class ReadStream;
+class String;
+}
+
+namespace Adl {
+
+class Display;
+
+class Parser {
+public:
+ Parser(AdlEngine &engine, Display &display);
+
+ void loadVerbs(Common::ReadStream &stream) { loadWords(stream, _verbs); }
+ void loadNouns(Common::ReadStream &stream) { loadWords(stream, _nouns); }
+ void getInput(uint &verb, uint &noun);
+
+private:
+ enum {
+ kWordSize = 8
+ };
+
+ typedef Common::HashMap<Common::String, uint> WordMap;
+
+ void loadWords(Common::ReadStream &stream, WordMap &map);
+ Common::String getLine();
+ Common::String getWord(const Common::String &line, uint &index);
+
+ AdlEngine &_engine;
+ Display &_display;
+ WordMap _verbs;
+ WordMap _nouns;
+};
+
+} // End of namespace Adl
+
+#endif
Commit: 87e2c4c1a933cbfb8cb03e36531503f0d1122053
https://github.com/scummvm/scummvm/commit/87e2c4c1a933cbfb8cb03e36531503f0d1122053
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename game type
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/detection.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index be3d8d7..b96ecc8 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -145,7 +145,7 @@ void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) {
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
- case kGameTypeAdl1:
+ case kGameTypeHires1:
return AdlEngine_v1__create(syst, gd);
default:
error("Unknown GameType");
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index d5a518fa..e945a45 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -41,7 +41,7 @@ struct AdlGameDescription;
enum GameType {
kGameTypeNone = 0,
- kGameTypeAdl1
+ kGameTypeHires1
};
Common::String asciiToApple(Common::String str);
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index ba4e010..9fadb9d 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -20,14 +20,9 @@
*
*/
-#include "adl/adl.h"
-
-#include "common/config-manager.h"
-#include "common/error.h"
-#include "common/fs.h"
-
#include "engines/advancedDetector.h"
-#include "engines/metaengine.h"
+
+#include "adl/adl.h"
namespace Adl {
@@ -36,22 +31,7 @@ struct AdlGameDescription {
GameType gameType;
};
-uint32 AdlEngine::getFeatures() const {
- return _gameDescription->desc.flags;
-}
-
-const char *AdlEngine::getGameId() const {
- return _gameDescription->desc.gameid;
-}
-
-const char *const directoryGlobs[] = {
- "game",
- "datafiles",
- 0
-};
-
static const PlainGameDescriptor adlGames[] = {
- // Games
{"hires1", "Hi-Res Adventure #1: Mystery House"},
{0, 0}
};
@@ -72,7 +52,7 @@ static const AdlGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO0()
},
- kGameTypeAdl1
+ kGameTypeHires1
},
{AD_TABLE_END_MARKER, kGameTypeNone}
};
@@ -82,7 +62,7 @@ public:
AdlMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(AdlGameDescription), adlGames) { }
const char *getName() const {
- return "Hi-Res Adventure";
+ return "ADL";
}
const char *getOriginalCopyright() const {
@@ -93,10 +73,9 @@ public:
};
bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
- if (gd) {
+ if (gd)
*engine = AdlEngine::create(((const AdlGameDescription *)gd)->gameType, syst, (const AdlGameDescription *)gd);
- }
- return gd != 0;
+ return gd != nullptr;
}
} // End of namespace Adl
Commit: 9717aa956197480a608622a2e294fa8302258a0e
https://github.com/scummvm/scummvm/commit/9717aa956197480a608622a2e294fa8302258a0e
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean-up string handling
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/adl_v1.cpp
engines/adl/display.cpp
engines/adl/display.h
engines/adl/parser.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index b96ecc8..9925e04 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -20,77 +20,35 @@
*
*/
- #include "common/scummsys.h"
-
+#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug.h"
-#include "common/debug-channels.h"
#include "common/error.h"
#include "common/file.h"
-#include "common/fs.h"
#include "common/system.h"
#include "common/events.h"
#include "common/stream.h"
-#include "graphics/palette.h"
#include "engines/util.h"
+#include "graphics/palette.h"
+
#include "adl/adl.h"
#include "adl/display.h"
#include "adl/parser.h"
namespace Adl {
-Common::String asciiToApple(Common::String str) {
- Common::String ret(str);
- Common::String::iterator it;
-
- for (it = ret.begin(); it != ret.end(); ++it)
- *it = *it | 0x80;
-
- return ret;
-}
-
-Common::String appleToAscii(Common::String str) {
- Common::String ret(str);
- Common::String::iterator it;
-
- for (it = ret.begin(); it != ret.end(); ++it)
- *it = *it & 0x7f;
-
- return ret;
-}
-
AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
_console(nullptr),
_display(nullptr) {
- // Put your engine in a sane state, but do nothing big yet;
- // in particular, do not load data from files; rather, if you
- // need to do such things, do them from run().
-
- // Do not initialize graphics here
- // Do not initialize audio devices here
-
- // However this is the place to specify all default directories
- const Common::FSNode gameDataDir(ConfMan.get("path"));
- SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
-
- // Don't forget to register your random source
- _rnd = new Common::RandomSource("adl");
-
- debug("AdlEngine::AdlEngine");
}
AdlEngine::~AdlEngine() {
- debug("AdlEngine::~AdlEngine");
-
- delete _rnd;
delete _console;
delete _display;
-
- DebugMan.clearAllDebugChannels();
}
Common::Error AdlEngine::run() {
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index e945a45..954c613 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -44,9 +44,6 @@ enum GameType {
kGameTypeHires1
};
-Common::String asciiToApple(Common::String str);
-Common::String appleToAscii(Common::String str);
-
enum {
STR_COMMON_ENTERCMD,
STR_COMMON_VERBERR,
@@ -54,7 +51,38 @@ enum {
STR_CUSTOM_START
};
-#define A2CHAR(C) ((C) | 0x80)
+struct Room {
+ byte description;
+ byte connections[6];
+ byte field8;
+ byte picture;
+};
+
+struct Picture {
+ byte block;
+ uint16 offset;
+};
+
+struct Command {
+ byte room;
+ byte verb, noun;
+ byte numCond, numAct;
+ Common::Array<byte> script;
+};
+
+struct Item {
+ byte field1;
+ byte field2;
+ byte field3;
+ byte field4;
+ byte field5;
+ byte field6;
+ byte field7;
+ byte field8;
+ Common::Array<byte> field10;
+};
+
+typedef Common::List<Command> Commands;
class AdlEngine : public Engine {
public:
diff --git a/engines/adl/adl_v1.cpp b/engines/adl/adl_v1.cpp
index 61671e5..4218239 100644
--- a/engines/adl/adl_v1.cpp
+++ b/engines/adl/adl_v1.cpp
@@ -240,10 +240,10 @@ void AdlEngine_v1::wordWrap(Common::String &str) {
if (str.size() <= end)
return;
- while (str[end] != (char)A2CHAR(' '))
+ while (str[end] != APPLECHAR(' '))
--end;
- str.setChar((char)A2CHAR('\r'), end);
+ str.setChar(APPLECHAR('\r'), end);
end += 40;
}
}
@@ -414,7 +414,7 @@ void AdlEngine_v1::doActions(const Command &command, byte noun, byte offset) {
case 0x11: {
_display->printString(_exeStrings[STR_MH_PLAYAGAIN]);
Common::String input = _display->inputString();
- if (input.size() == 0 || input[0] != (char)A2CHAR('N')) {
+ if (input.size() == 0 || input[0] != APPLECHAR('N')) {
warning("Restart game not implemented");
return;
}
@@ -528,12 +528,9 @@ bool AdlEngine_v1::checkCommand(const Command &command, byte verb, byte noun) {
bool AdlEngine_v1::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator it;
- for (it = commands.begin(); it != commands.end(); ++it) {
- if (checkCommand(*it, verb, noun)) {
- debug("Found match: %i %i %i", it->room, it->verb, it->noun);
+ for (it = commands.begin(); it != commands.end(); ++it)
+ if (checkCommand(*it, verb, noun))
return true;
- }
- }
return false;
}
@@ -541,11 +538,8 @@ bool AdlEngine_v1::doOneCommand(const Commands &commands, byte verb, byte noun)
void AdlEngine_v1::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator it;
- for (it = commands.begin(); it != commands.end(); ++it) {
- if (checkCommand(*it, verb, noun)) {
- debug("Found match: %i %i %i", it->room, it->verb, it->noun);
- }
- }
+ for (it = commands.begin(); it != commands.end(); ++it)
+ checkCommand(*it, verb, noun);
}
void AdlEngine_v1::clearScreen() {
@@ -563,7 +557,7 @@ void AdlEngine_v1::runGame() {
error("Failed to open file");
while (!f.eos() && !f.err())
- _msgStrings.push_back(readString(f, A2CHAR('\r')) + (char)A2CHAR('\r'));
+ _msgStrings.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
f.close();
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 02b8d51..47b1533 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -429,7 +429,7 @@ void Display::printASCIIString(const Common::String &str) {
Common::String::const_iterator it;
for (it = str.begin(); it != str.end(); ++it)
- aStr += *it | 0x80;
+ aStr += APPLECHAR(*it);
printString(aStr);
}
diff --git a/engines/adl/display.h b/engines/adl/display.h
index eabf340..62294d3 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -37,7 +37,9 @@ class Surface;
}
namespace Adl {
-
+
+#define APPLECHAR(C) ((char)((C) | 0x80))
+
class Display {
public:
enum Mode {
diff --git a/engines/adl/parser.cpp b/engines/adl/parser.cpp
index cdbaf3b..1611fc7 100644
--- a/engines/adl/parser.cpp
+++ b/engines/adl/parser.cpp
@@ -81,7 +81,7 @@ Common::String Parser::getLine() {
bool textMode = false;
while (1) {
- Common::String line = _display.inputString(A2CHAR('?'));
+ Common::String line = _display.inputString(APPLECHAR('?'));
if (g_engine->shouldQuit())
return "";
@@ -102,7 +102,7 @@ Common::String Parser::getWord(const Common::String &line, uint &index) {
Common::String str;
for (uint i = 0; i < 8; ++i)
- str += (char)(A2CHAR(' '));
+ str += APPLECHAR(' ');
int copied = 0;
@@ -110,7 +110,7 @@ Common::String Parser::getWord(const Common::String &line, uint &index) {
while (1) {
if (index == line.size())
return str;
- if (line[index] != (char)(A2CHAR(' ')))
+ if (line[index] != APPLECHAR(' '))
break;
++index;
}
@@ -122,7 +122,7 @@ Common::String Parser::getWord(const Common::String &line, uint &index) {
index++;
- if (index == line.size() || line[index] == (char)(A2CHAR(' ')))
+ if (index == line.size() || line[index] == APPLECHAR(' '))
return str;
}
}
@@ -137,7 +137,6 @@ void Parser::getInput(uint &verb, uint &noun) {
uint index = 0;
Common::String verbStr = getWord(line, index);
- debug("Verb: \"%s\"", appleToAscii(verbStr).c_str());
if (!_verbs.contains(verbStr)) {
Common::String err = _engine.getExeString(STR_COMMON_VERBERR);
@@ -148,10 +147,8 @@ void Parser::getInput(uint &verb, uint &noun) {
}
verb = _verbs[verbStr];
- debug("Verb ID: %i", verb);
Common::String nounStr = getWord(line, index);
- debug("Noun: \"%s\"", appleToAscii(nounStr).c_str());
if (!_nouns.contains(nounStr)) {
Common::String err = _engine.getExeString(STR_COMMON_NOUNERR);
@@ -164,7 +161,6 @@ void Parser::getInput(uint &verb, uint &noun) {
}
noun = _nouns[nounStr];
- debug("Noun ID: %i", noun);
return;
}
}
Commit: 183fe8b217c09df4deef3e31d5c01531bb532c50
https://github.com/scummvm/scummvm/commit/183fe8b217c09df4deef3e31d5c01531bb532c50
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move members into base class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/adl_v1.cpp
engines/adl/adl_v1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 9925e04..8042a9a 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -42,12 +42,15 @@ namespace Adl {
AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
- _console(nullptr),
- _display(nullptr) {
+ _display(nullptr),
+ _parser(nullptr),
+ _room(1),
+ _steps(0),
+ _isDark(false) {
}
AdlEngine::~AdlEngine() {
- delete _console;
+ delete _parser;
delete _display;
}
@@ -65,7 +68,6 @@ Common::Error AdlEngine::run() {
g_system->getPaletteManager()->setPalette(palette, 0, 6);
- _console = new Console(this);
_display = new Display();
_parser = new Parser(*this, *_display);
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 954c613..55ba0fc 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -24,7 +24,10 @@
#define ADL_ADL_H
#include "common/random.h"
+#include "common/rect.h"
+
#include "engines/engine.h"
+
#include "gui/debugger.h"
namespace Common {
@@ -102,14 +105,24 @@ protected:
virtual void runGame() = 0;
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
+
Display *_display;
Parser *_parser;
-private:
- Console *_console;
-
- // We need random numbers
- Common::RandomSource *_rnd;
+ Common::Array<Common::String> _msgStrings;
+ Common::Array<Picture> _pictures;
+ Common::Array<Item> _inventory;
+ Common::Array<Common::Point> _itemOffsets;
+ Common::Array<Common::Array<byte> > _drawings;
+ Commands _roomCommands;
+ Commands _globalCommands;
+
+ // Game state
+ Common::Array<Room> _rooms;
+ byte _room;
+ uint16 _steps;
+ Common::Array<byte> _variables;
+ bool _isDark;
};
// Example console class
diff --git a/engines/adl/adl_v1.cpp b/engines/adl/adl_v1.cpp
index 4218239..28aa895 100644
--- a/engines/adl/adl_v1.cpp
+++ b/engines/adl/adl_v1.cpp
@@ -46,11 +46,7 @@ static uint exeStrings[STR_MH_TOTAL] = {
};
AdlEngine_v1::AdlEngine_v1(OSystem *syst, const AdlGameDescription *gd) :
- AdlEngine(syst, gd),
- _state(kIntro),
- _room(1),
- _steps(1),
- _isDark(false) {
+ AdlEngine(syst, gd) {
_variables.resize(20);
}
diff --git a/engines/adl/adl_v1.h b/engines/adl/adl_v1.h
index b8f4c53..c1e28bc 100644
--- a/engines/adl/adl_v1.h
+++ b/engines/adl/adl_v1.h
@@ -57,46 +57,6 @@ private:
MH_ITEM_OFFSETS = 21
};
- enum State {
- kIntro,
- kIdle
- };
-
- struct Room {
- byte description;
- byte connections[6];
- byte field8;
- byte picture;
- };
-
- struct Picture {
- byte block;
- uint16 offset;
- };
-
- struct Command {
- byte room;
- byte verb, noun;
- byte numCond, numAct;
- Common::Array<byte> script;
- };
-
- struct Item {
- byte field1;
- byte field2;
- byte field3;
- byte field4;
- byte field5;
- byte field6;
- byte field7;
- byte field8;
- Common::Array<byte> field10;
- };
-
- typedef Common::List<Command> Commands;
-
- int _state;
-
void runIntro();
void drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset);
void showRoom();
@@ -114,18 +74,6 @@ private:
void drawPic(byte pic, byte xOffset, byte yOffset);
Common::Array<Common::String> _exeStrings;
- Common::Array<Common::String> _msgStrings;
- Common::Array<Room> _rooms;
- Common::Array<Picture> _pictures;
- Common::Array<Item> _inventory;
- Common::Array<Common::Point> _itemOffsets;
- Common::Array<Common::Array<byte> > _drawings;
- Commands _roomCommands;
- Commands _globalCommands;
- byte _room;
- uint16 _steps;
- Common::Array<byte> _variables;
- bool _isDark;
};
} // End of namespace Adl
Commit: d30cfa24fad35a668d0006f67b9d39901f0757a9
https://github.com/scummvm/scummvm/commit/d30cfa24fad35a668d0006f67b9d39901f0757a9
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Remove dead code
Changed paths:
engines/adl/adl.h
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 55ba0fc..cc20edf 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -125,13 +125,6 @@ protected:
bool _isDark;
};
-// Example console class
-class Console : public GUI::Debugger {
-public:
- Console(AdlEngine *vm) {}
- virtual ~Console(void) {}
-};
-
AdlEngine *AdlEngine_v1__create(OSystem *syst, const AdlGameDescription *gd);
} // End of namespace Adl
Commit: 43a37e94dd466887eabdeb589bdc54ca4cec6c41
https://github.com/scummvm/scummvm/commit/43a37e94dd466887eabdeb589bdc54ca4cec6c41
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename AdlEngine_v1 to HiRes1Engine
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/adl_v1.cpp
engines/adl/adl_v1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 8042a9a..3ee72e8 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -106,7 +106,7 @@ void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) {
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
- return AdlEngine_v1__create(syst, gd);
+ return HiRes1Engine__create(syst, gd);
default:
error("Unknown GameType");
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index cc20edf..5252916 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -125,7 +125,7 @@ protected:
bool _isDark;
};
-AdlEngine *AdlEngine_v1__create(OSystem *syst, const AdlGameDescription *gd);
+AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd);
} // End of namespace Adl
diff --git a/engines/adl/adl_v1.cpp b/engines/adl/adl_v1.cpp
index 28aa895..566a467 100644
--- a/engines/adl/adl_v1.cpp
+++ b/engines/adl/adl_v1.cpp
@@ -45,12 +45,12 @@ static uint exeStrings[STR_MH_TOTAL] = {
23484, 23375, 23438, 27658, 0x6c31, 27729, 27772, 0x5f1e
};
-AdlEngine_v1::AdlEngine_v1(OSystem *syst, const AdlGameDescription *gd) :
+HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine(syst, gd) {
_variables.resize(20);
}
-void AdlEngine_v1::runIntro() {
+void HiRes1Engine::runIntro() {
Common::File file;
if (!file.open("AUTO LOAD OBJ"))
@@ -132,7 +132,7 @@ void AdlEngine_v1::runIntro() {
}
}
-void AdlEngine_v1::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset) {
+void HiRes1Engine::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset) {
byte x, y;
bool bNewLine = false;
byte oldX = 0, oldY = 0;
@@ -169,7 +169,7 @@ void AdlEngine_v1::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffse
}
}
-void AdlEngine_v1::drawPic(byte pic, byte xOffset, byte yOffset) {
+void HiRes1Engine::drawPic(byte pic, byte xOffset, byte yOffset) {
Common::File f;
Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
@@ -180,7 +180,7 @@ void AdlEngine_v1::drawPic(byte pic, byte xOffset, byte yOffset) {
drawPic(f, xOffset, yOffset);
}
-void AdlEngine_v1::drawItems() {
+void HiRes1Engine::drawItems() {
Common::Array<Item>::const_iterator it;
uint dropped = 0;
@@ -215,7 +215,7 @@ void AdlEngine_v1::drawItems() {
}
}
-void AdlEngine_v1::showRoom() {
+void HiRes1Engine::showRoom() {
if (!_isDark) {
drawPic(_rooms[_room].picture, 0, 0);
drawItems();
@@ -225,11 +225,11 @@ void AdlEngine_v1::showRoom() {
printMessage(_rooms[_room].description, false);
}
-Common::String AdlEngine_v1::getExeString(uint idx) {
+Common::String HiRes1Engine::getExeString(uint idx) {
return _exeStrings[idx];
}
-void AdlEngine_v1::wordWrap(Common::String &str) {
+void HiRes1Engine::wordWrap(Common::String &str) {
uint end = 39;
while (1) {
@@ -244,7 +244,7 @@ void AdlEngine_v1::wordWrap(Common::String &str) {
}
}
-void AdlEngine_v1::printMessage(uint idx, bool wait) {
+void HiRes1Engine::printMessage(uint idx, bool wait) {
// Hardcoded overrides that don't wait after printing
// Note: strings may differ slightly from the ones in MESSAGES
switch (idx) {
@@ -270,7 +270,7 @@ void AdlEngine_v1::printMessage(uint idx, bool wait) {
_display->delay(14 * 166018 / 1000);
}
-void AdlEngine_v1::readCommands(Common::ReadStream &stream, Commands &commands) {
+void HiRes1Engine::readCommands(Common::ReadStream &stream, Commands &commands) {
while (1) {
Command command;
command.room = stream.readByte();
@@ -296,7 +296,7 @@ void AdlEngine_v1::readCommands(Common::ReadStream &stream, Commands &commands)
}
}
-void AdlEngine_v1::takeItem(byte noun) {
+void HiRes1Engine::takeItem(byte noun) {
Common::Array<Item>::iterator it;
for (it = _inventory.begin(); it != _inventory.end(); ++it) {
@@ -329,7 +329,7 @@ void AdlEngine_v1::takeItem(byte noun) {
printMessage(152);
}
-void AdlEngine_v1::dropItem(byte noun) {
+void HiRes1Engine::dropItem(byte noun) {
Common::Array<Item>::iterator it;
for (it = _inventory.begin(); it != _inventory.end(); ++it) {
@@ -345,7 +345,7 @@ void AdlEngine_v1::dropItem(byte noun) {
printMessage(37);
}
-void AdlEngine_v1::doActions(const Command &command, byte noun, byte offset) {
+void HiRes1Engine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
switch (command.script[offset]) {
case 1:
@@ -473,7 +473,7 @@ void AdlEngine_v1::doActions(const Command &command, byte noun, byte offset) {
}
}
-bool AdlEngine_v1::checkCommand(const Command &command, byte verb, byte noun) {
+bool HiRes1Engine::checkCommand(const Command &command, byte verb, byte noun) {
if (command.room != 0xfe && command.room != _room)
return false;
@@ -521,7 +521,7 @@ bool AdlEngine_v1::checkCommand(const Command &command, byte verb, byte noun) {
return true;
}
-bool AdlEngine_v1::doOneCommand(const Commands &commands, byte verb, byte noun) {
+bool HiRes1Engine::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator it;
for (it = commands.begin(); it != commands.end(); ++it)
@@ -531,19 +531,19 @@ bool AdlEngine_v1::doOneCommand(const Commands &commands, byte verb, byte noun)
return false;
}
-void AdlEngine_v1::doAllCommands(const Commands &commands, byte verb, byte noun) {
+void HiRes1Engine::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator it;
for (it = commands.begin(); it != commands.end(); ++it)
checkCommand(*it, verb, noun);
}
-void AdlEngine_v1::clearScreen() {
+void HiRes1Engine::clearScreen() {
_display->setMode(Display::kModeMixed);
_display->clear(0x00);
}
-void AdlEngine_v1::runGame() {
+void HiRes1Engine::runGame() {
runIntro();
_display->printASCIIString("\r");
@@ -673,8 +673,8 @@ void AdlEngine_v1::runGame() {
}
}
-AdlEngine *AdlEngine_v1__create(OSystem *syst, const AdlGameDescription *gd) {
- return new AdlEngine_v1(syst, gd);
+AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd) {
+ return new HiRes1Engine(syst, gd);
}
} // End of namespace Adl
diff --git a/engines/adl/adl_v1.h b/engines/adl/adl_v1.h
index c1e28bc..e9e274c 100644
--- a/engines/adl/adl_v1.h
+++ b/engines/adl/adl_v1.h
@@ -42,9 +42,9 @@ enum {
STR_MH_TOTAL
};
-class AdlEngine_v1 : public AdlEngine {
+class HiRes1Engine : public AdlEngine {
public:
- AdlEngine_v1(OSystem *syst, const AdlGameDescription *gd);
+ HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
Common::String getExeString(uint idx);
protected:
Commit: 1e17a23879c6e81a09e2ad80d0ae7a1c0cc10732
https://github.com/scummvm/scummvm/commit/1e17a23879c6e81a09e2ad80d0ae7a1c0cc10732
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename adl_v1.cpp/h to hires1.cpp/h
Changed paths:
A engines/adl/hires1.cpp
A engines/adl/hires1.h
R engines/adl/adl_v1.cpp
R engines/adl/adl_v1.h
engines/adl/module.mk
diff --git a/engines/adl/adl_v1.cpp b/engines/adl/adl_v1.cpp
deleted file mode 100644
index 566a467..0000000
--- a/engines/adl/adl_v1.cpp
+++ /dev/null
@@ -1,680 +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.h"
-#include "common/debug-channels.h"
-#include "common/error.h"
-#include "common/file.h"
-#include "common/fs.h"
-#include "common/system.h"
-#include "common/events.h"
-#include "common/stream.h"
-#include "graphics/palette.h"
-
-#include "engines/util.h"
-
-#include "adl/adl_v1.h"
-#include "adl/display.h"
-#include "adl/parser.h"
-
-namespace Adl {
-
-static uint exeStrings[STR_MH_TOTAL] = {
- 23484, 23375, 23438, 27658, 0x6c31, 27729, 27772, 0x5f1e
-};
-
-HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
- AdlEngine(syst, gd) {
- _variables.resize(20);
-}
-
-void HiRes1Engine::runIntro() {
- Common::File file;
-
- if (!file.open("AUTO LOAD OBJ"))
- error("Failed to open file");
-
- file.seek(0x1003);
- _display->setMode(Display::kModeHires);
- _display->loadFrameBuffer(file);
- _display->decodeFrameBuffer();
- _display->delay(4000);
-
- if (shouldQuit())
- return;
-
- _display->setMode(Display::kModeText);
-
- Common::File basic;
- if (!basic.open("MYSTERY.HELLO"))
- error("Failed to open file");
-
- Common::String str;
-
- basic.seek(93);
- str = readString(basic, '"');
- _display->printASCIIString(str + '\r');
-
- basic.seek(299);
- str = readString(basic, '"');
- _display->printASCIIString(str + "\r\r");
-
- basic.seek(365);
- str = readString(basic, '"');
- _display->printASCIIString(str + "\r\r");
-
- basic.seek(601);
- str = readString(basic, '"');
- _display->printASCIIString(str + '\r');
-
- _display->inputKey();
- if (g_engine->shouldQuit())
- return;
-
- _display->setMode(Display::kModeMixed);
-
- file.seek(15);
- str = readString(file);
-
- while (1) {
- _display->printString(str);
- Common::String s = _display->inputString();
-
- if (g_engine->shouldQuit())
- break;
-
- if (s.empty())
- continue;
-
- if ((byte)s[0] == ('I' | 0x80))
- break;
- else if ((byte)s[0] == ('G' | 0x80))
- return;
- };
-
- _display->setMode(Display::kModeText);
- file.seek(102);
-
- const int pages[] = { 6, 6, 4, 5, 8, 7, 0 };
-
- int page = 0;
- while (pages[page] != 0) {
- _display->home();
- printStrings(file, pages[page++]);
- _display->inputString();
-
- if (g_engine->shouldQuit())
- return;
-
- file.seek(9, SEEK_CUR);
- }
-}
-
-void HiRes1Engine::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset) {
- byte x, y;
- bool bNewLine = false;
- byte oldX = 0, oldY = 0;
- while (1) {
- x = stream.readByte();
- y = stream.readByte();
-
- if (stream.err() || stream.eos())
- error("Failed to read picture");
-
- if (x == 0xff && y == 0xff)
- return;
-
- if (x == 0 && y == 0) {
- bNewLine = true;
- continue;
- }
-
- x += xOffset;
- y += yOffset;
-
- if (y > 160)
- y = 160;
-
- if (bNewLine) {
- _display->drawPixel(x, y, 0x7f);
- bNewLine = false;
- } else {
- _display->drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
- }
-
- oldX = x;
- oldY = y;
- }
-}
-
-void HiRes1Engine::drawPic(byte pic, byte xOffset, byte yOffset) {
- Common::File f;
- Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
-
- if (!f.open(name))
- error("Failed to open file");
-
- f.seek(_pictures[pic].offset);
- drawPic(f, xOffset, yOffset);
-}
-
-void HiRes1Engine::drawItems() {
- Common::Array<Item>::const_iterator it;
-
- uint dropped = 0;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field2 != _room)
- continue;
-
- if (it->field7 == 1) {
- if (_rooms[_room].field8 == _rooms[_room].picture) {
- const Common::Point &p = _itemOffsets[dropped];
- if (it->field4)
- _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
- else
- drawPic(it->field3, p.x, p.y);
- ++dropped;
- }
- continue;
- }
-
- Common::Array<byte>::const_iterator it2;
-
- for (it2 = it->field10.begin(); it2 != it->field10.end(); ++it2) {
- if (*it2 == _rooms[_room].picture) {
- if (it->field4)
- _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(it->field5, it->field6), 0, 1, 0x7f);
- else
- drawPic(it->field3, it->field5, it->field6);
- continue;
- }
- }
- }
-}
-
-void HiRes1Engine::showRoom() {
- if (!_isDark) {
- drawPic(_rooms[_room].picture, 0, 0);
- drawItems();
- }
-
- _display->decodeFrameBuffer();
- printMessage(_rooms[_room].description, false);
-}
-
-Common::String HiRes1Engine::getExeString(uint idx) {
- return _exeStrings[idx];
-}
-
-void HiRes1Engine::wordWrap(Common::String &str) {
- uint end = 39;
-
- while (1) {
- if (str.size() <= end)
- return;
-
- while (str[end] != APPLECHAR(' '))
- --end;
-
- str.setChar(APPLECHAR('\r'), end);
- end += 40;
- }
-}
-
-void HiRes1Engine::printMessage(uint idx, bool wait) {
- // Hardcoded overrides that don't wait after printing
- // Note: strings may differ slightly from the ones in MESSAGES
- switch (idx) {
- case 137:
- _display->printString(_exeStrings[STR_MH_DIRERR]);
- return;
- case 127:
- _display->printString(_exeStrings[STR_MH_DONTHAVEIT]);
- return;
- case 37:
- _display->printString(_exeStrings[STR_MH_DONTUNDERSTAND]);
- return;
- case 7:
- _display->printString(_exeStrings[STR_MH_GETTINGDARK]);
- return;
- }
-
- Common::String msg = _msgStrings[idx - 1];
- wordWrap(msg);
- _display->printString(msg);
-
- if (wait)
- _display->delay(14 * 166018 / 1000);
-}
-
-void HiRes1Engine::readCommands(Common::ReadStream &stream, Commands &commands) {
- while (1) {
- Command command;
- command.room = stream.readByte();
-
- if (command.room == 0xff)
- return;
-
- command.verb = stream.readByte();
- command.noun = stream.readByte();
-
- byte scriptSize = stream.readByte() - 6;
-
- command.numCond = stream.readByte();
- command.numAct = stream.readByte();
-
- for (uint i = 0; i < scriptSize; ++i)
- command.script.push_back(stream.readByte());
-
- if (stream.eos() || stream.err())
- error("Failed to read commands");
-
- commands.push_back(command);
- }
-}
-
-void HiRes1Engine::takeItem(byte noun) {
- Common::Array<Item>::iterator it;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field1 != noun || it->field2 != _room)
- continue;
-
- if (it->field7 == 2) {
- // It doesn't move
- printMessage(151);
- return;
- }
-
- if (it->field7 == 1) {
- it->field2 = 0xfe;
- it->field7 = 1;
- return;
- }
-
- Common::Array<byte>::const_iterator it2;
- for (it2 = it->field10.begin(); it->field10.end(); ++it2) {
- if (*it2 == _rooms[_room].picture) {
- it->field2 = 0xfe;
- it->field7 = 1;
- return;
- }
- }
- }
-
- // Item not here
- printMessage(152);
-}
-
-void HiRes1Engine::dropItem(byte noun) {
- Common::Array<Item>::iterator it;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field1 != noun || it->field2 != 0xfe)
- continue;
-
- it->field2 = _room;
- it->field7 = 1;
- return;
- }
-
- // Don't understand
- printMessage(37);
-}
-
-void HiRes1Engine::doActions(const Command &command, byte noun, byte offset) {
- for (uint i = 0; i < command.numAct; ++i) {
- switch (command.script[offset]) {
- case 1:
- _variables[command.script[offset + 2]] += command.script[offset + 1];
- offset += 3;
- break;
- case 2:
- _variables[command.script[offset + 2]] -= command.script[offset + 1];
- offset += 3;
- break;
- case 3:
- _variables[command.script[offset + 1]] = command.script[offset + 2];
- offset += 3;
- break;
- case 4: {
- Common::Array<Item>::const_iterator it;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it)
- if (it->field2 == 0xfe)
- printMessage(it->field8);
-
- ++offset;
- break;
- }
- case 5:
- _inventory[command.script[offset + 1] - 1].field2 = command.script[offset + 2];
- offset += 3;
- break;
- case 6:
- _rooms[_room].picture = _rooms[_room].field8;
- _room = command.script[offset + 1];
- offset += 2;
- break;
- case 7:
- _rooms[_room].picture = command.script[offset + 1];
- offset += 2;
- break;
- case 8:
- _rooms[_room].field8 = _rooms[_room].picture = command.script[offset + 1];
- offset += 2;
- break;
- case 9:
- printMessage(command.script[offset + 1]);
- offset += 2;
- break;
- case 0xa:
- _isDark = false;
- ++offset;
- break;
- case 0xb:
- _isDark = true;
- ++offset;
- break;
- case 0xf:
- warning("Save game not implemented");
- ++offset;
- break;
- case 0x10:
- warning("Load game not implemented");
- ++offset;
- break;
- case 0x11: {
- _display->printString(_exeStrings[STR_MH_PLAYAGAIN]);
- Common::String input = _display->inputString();
- if (input.size() == 0 || input[0] != APPLECHAR('N')) {
- warning("Restart game not implemented");
- return;
- }
- // Fall-through
- }
- case 0xd:
- printMessage(140);
- quitGame();
- return;
- case 0x12: {
- byte item = command.script[offset + 1] - 1;
- _inventory[item].field2 = command.script[offset + 2];
- _inventory[item].field5 = command.script[offset + 3];
- _inventory[item].field6 = command.script[offset + 4];
- offset += 5;
- break;
- }
- case 0x13: {
- byte item = command.script[offset + 2] - 1;
- _inventory[item].field3 = command.script[offset + 1];
- offset += 3;
- break;
- }
- case 0x14:
- _rooms[_room].picture = _rooms[_room].field8;
- ++offset;
- break;
- case 0x15:
- case 0x16:
- case 0x17:
- case 0x18:
- case 0x19:
- case 0x1a: {
- byte room = _rooms[_room].connections[command.script[offset] - 0x15];
-
- if (room == 0) {
- printMessage(137);
- return;
- }
-
- _rooms[_room].picture = _rooms[_room].field8;
- _room = room;
- return;
- }
- case 0x1b:
- takeItem(noun);
- ++offset;
- break;
- case 0x1c:
- dropItem(noun);
- ++offset;
- break;
- case 0x1d:
- _rooms[command.script[offset + 1]].field8 = _rooms[command.script[offset + 1]].picture = command.script[offset + 2];
- offset += 3;
- break;
- default:
- error("Invalid action opcode %02x", command.script[offset]);
- }
- }
-}
-
-bool HiRes1Engine::checkCommand(const Command &command, byte verb, byte noun) {
- if (command.room != 0xfe && command.room != _room)
- return false;
-
- if (command.verb != 0xfe && command.verb != verb)
- return false;
-
- if (command.noun != 0xfe && command.noun != noun)
- return false;
-
- uint offset = 0;
- for (uint i = 0; i < command.numCond; ++i) {
- switch (command.script[offset]) {
- case 3:
- if (_inventory[command.script[offset + 1] - 1].field2 != command.script[offset + 2])
- return false;
- offset += 3;
- break;
- case 5:
- if (command.script[offset + 1] > _steps)
- return false;
- offset += 2;
- break;
- case 6:
- if (_variables[command.script[offset + 1]] != command.script[offset + 2])
- return false;
- offset += 3;
- break;
- case 9:
- if (_rooms[_room].picture != command.script[offset + 1])
- return false;
- offset += 2;
- break;
- case 10:
- if (_inventory[command.script[offset + 1] - 1].field3 != command.script[offset + 2])
- return false;
- offset += 3;
- break;
- default:
- error("Invalid condition opcode %02x", command.script[offset]);
- }
- }
-
- doActions(command, noun, offset);
-
- return true;
-}
-
-bool HiRes1Engine::doOneCommand(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator it;
-
- for (it = commands.begin(); it != commands.end(); ++it)
- if (checkCommand(*it, verb, noun))
- return true;
-
- return false;
-}
-
-void HiRes1Engine::doAllCommands(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator it;
-
- for (it = commands.begin(); it != commands.end(); ++it)
- checkCommand(*it, verb, noun);
-}
-
-void HiRes1Engine::clearScreen() {
- _display->setMode(Display::kModeMixed);
- _display->clear(0x00);
-}
-
-void HiRes1Engine::runGame() {
- runIntro();
- _display->printASCIIString("\r");
-
- Common::File f;
-
- if (!f.open("MESSAGES"))
- error("Failed to open file");
-
- while (!f.eos() && !f.err())
- _msgStrings.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
-
- f.close();
-
- if (!f.open("ADVENTURE"))
- error("Failed to open file");
-
- // Load strings from executable
- for (uint idx = 0; idx < STR_MH_TOTAL; ++idx) {
- f.seek(exeStrings[idx]);
- _exeStrings.push_back(readString(f));
- }
-
- // Load room data from executable
- f.seek(1280);
- for (uint i = 0; i < MH_ROOMS; ++i) {
- struct Room room;
- f.readByte();
- room.description = f.readByte();
- for (uint j = 0; j < 6; ++j)
- room.connections[j] = f.readByte();
- room.field8 = f.readByte();
- room.picture = f.readByte();
- _rooms.push_back(room);
- }
-
- // Load inventory data from executable
- f.seek(0x100);
- while (f.readByte() != 0xff) {
- struct Item item;
- item.field1 = f.readByte();
- item.field2 = f.readByte();
- item.field3 = f.readByte();
- item.field4 = f.readByte();
- item.field5 = f.readByte();
- item.field6 = f.readByte();
- item.field7 = f.readByte();
- item.field8 = f.readByte();
-
- f.readByte();
-
- byte size = f.readByte();
-
- for (uint i = 0; i < size; ++i)
- item.field10.push_back(f.readByte());
-
- _inventory.push_back(item);
- }
-
- // Load picture data from executable
- f.seek(0x4b00);
- for (uint i = 0; i < MH_PICS; ++i) {
- struct Picture pic;
- pic.block = f.readByte();
- pic.offset = f.readUint16LE();
- _pictures.push_back(pic);
- }
-
- // Load commands from executable
- f.seek(0x3D00);
- readCommands(f, _roomCommands);
-
- f.seek(0x3C00);
- readCommands(f, _globalCommands);
-
- // Load dropped item offsets
- f.seek(0x68ff);
- for (uint i = 0; i < MH_ITEM_OFFSETS; ++i) {
- Common::Point p;
- p.x = f.readByte();
- p.y = f.readByte();
- _itemOffsets.push_back(p);
- }
-
- // Load right-angle drawings
- f.seek(0x4f00);
- uint16 drawingsTotal = f.readUint16LE();
- for (uint i = 0; i < drawingsTotal; ++i) {
- f.seek(0x4f00 + 2 + i * 2);
- uint16 offset = f.readUint16LE();
- f.seek(0x4f00 + offset);
-
- Common::Array<byte> drawing;
- byte b = f.readByte();
- while (b != 0) {
- drawing.push_back(b);
- b = f.readByte();
- }
- _drawings.push_back(drawing);
- }
-
- // Title screen shown during loading
- f.seek(0x1800);
- _display->loadFrameBuffer(f);
- _display->decodeFrameBuffer();
- _display->delay(2000);
-
- f.seek(0x3800);
- _parser->loadVerbs(f);
-
- f.seek(0xf00);
- _parser->loadNouns(f);
-
- while (1) {
- uint verb = 0, noun = 0;
- clearScreen();
- showRoom();
- _parser->getInput(verb, noun);
-
- if (!doOneCommand(_roomCommands, verb, noun))
- printMessage(37);
- doAllCommands(_globalCommands, verb, noun);
-
- _steps++;
-
- if (shouldQuit())
- return;
- }
-}
-
-AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd) {
- return new HiRes1Engine(syst, gd);
-}
-
-} // End of namespace Adl
diff --git a/engines/adl/adl_v1.h b/engines/adl/adl_v1.h
deleted file mode 100644
index e9e274c..0000000
--- a/engines/adl/adl_v1.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 ADL_ADL_V1_H
-#define ADL_ADL_V1_H
-
-#include "adl/adl.h"
-
-namespace Common {
-class ReadStream;
-}
-
-namespace Adl {
-
-enum {
- // Some of these are probably common
- STR_MH_DIRERR = STR_CUSTOM_START,
- STR_MH_DONTHAVEIT,
- STR_MH_DONTUNDERSTAND,
- STR_MH_GETTINGDARK,
- STR_MH_PLAYAGAIN,
-
- STR_MH_TOTAL
-};
-
-class HiRes1Engine : public AdlEngine {
-public:
- HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
- Common::String getExeString(uint idx);
-
-protected:
- void runGame();
-
-private:
- enum {
- MH_ROOMS = 42,
- MH_PICS = 98,
- MH_ITEM_OFFSETS = 21
- };
-
- void runIntro();
- void drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset);
- void showRoom();
- void printMessage(uint idx, bool wait = true);
- void wordWrap(Common::String &str);
- void readCommands(Common::ReadStream &stream, Commands &commands);
- bool checkCommand(const Command &command, byte verb, byte noun);
- bool doOneCommand(const Commands &commands, byte verb, byte noun);
- void doAllCommands(const Commands &commands, byte verb, byte noun);
- void doActions(const Command &command, byte noun, byte offset);
- void clearScreen();
- void takeItem(byte noun);
- void dropItem(byte noun);
- void drawItems();
- void drawPic(byte pic, byte xOffset, byte yOffset);
-
- Common::Array<Common::String> _exeStrings;
-};
-
-} // End of namespace Adl
-
-#endif
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
new file mode 100644
index 0000000..28aa135
--- /dev/null
+++ b/engines/adl/hires1.cpp
@@ -0,0 +1,680 @@
+/* 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.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/file.h"
+#include "common/fs.h"
+#include "common/system.h"
+#include "common/events.h"
+#include "common/stream.h"
+#include "graphics/palette.h"
+
+#include "engines/util.h"
+
+#include "adl/hires1.h"
+#include "adl/display.h"
+#include "adl/parser.h"
+
+namespace Adl {
+
+static uint exeStrings[STR_MH_TOTAL] = {
+ 23484, 23375, 23438, 27658, 0x6c31, 27729, 27772, 0x5f1e
+};
+
+HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
+ AdlEngine(syst, gd) {
+ _variables.resize(20);
+}
+
+void HiRes1Engine::runIntro() {
+ Common::File file;
+
+ if (!file.open("AUTO LOAD OBJ"))
+ error("Failed to open file");
+
+ file.seek(0x1003);
+ _display->setMode(Display::kModeHires);
+ _display->loadFrameBuffer(file);
+ _display->decodeFrameBuffer();
+ _display->delay(4000);
+
+ if (shouldQuit())
+ return;
+
+ _display->setMode(Display::kModeText);
+
+ Common::File basic;
+ if (!basic.open("MYSTERY.HELLO"))
+ error("Failed to open file");
+
+ Common::String str;
+
+ basic.seek(93);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + '\r');
+
+ basic.seek(299);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + "\r\r");
+
+ basic.seek(365);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + "\r\r");
+
+ basic.seek(601);
+ str = readString(basic, '"');
+ _display->printASCIIString(str + '\r');
+
+ _display->inputKey();
+ if (g_engine->shouldQuit())
+ return;
+
+ _display->setMode(Display::kModeMixed);
+
+ file.seek(15);
+ str = readString(file);
+
+ while (1) {
+ _display->printString(str);
+ Common::String s = _display->inputString();
+
+ if (g_engine->shouldQuit())
+ break;
+
+ if (s.empty())
+ continue;
+
+ if ((byte)s[0] == ('I' | 0x80))
+ break;
+ else if ((byte)s[0] == ('G' | 0x80))
+ return;
+ };
+
+ _display->setMode(Display::kModeText);
+ file.seek(102);
+
+ const int pages[] = { 6, 6, 4, 5, 8, 7, 0 };
+
+ int page = 0;
+ while (pages[page] != 0) {
+ _display->home();
+ printStrings(file, pages[page++]);
+ _display->inputString();
+
+ if (g_engine->shouldQuit())
+ return;
+
+ file.seek(9, SEEK_CUR);
+ }
+}
+
+void HiRes1Engine::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset) {
+ byte x, y;
+ bool bNewLine = false;
+ byte oldX = 0, oldY = 0;
+ while (1) {
+ x = stream.readByte();
+ y = stream.readByte();
+
+ if (stream.err() || stream.eos())
+ error("Failed to read picture");
+
+ if (x == 0xff && y == 0xff)
+ return;
+
+ if (x == 0 && y == 0) {
+ bNewLine = true;
+ continue;
+ }
+
+ x += xOffset;
+ y += yOffset;
+
+ if (y > 160)
+ y = 160;
+
+ if (bNewLine) {
+ _display->drawPixel(x, y, 0x7f);
+ bNewLine = false;
+ } else {
+ _display->drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
+ }
+
+ oldX = x;
+ oldY = y;
+ }
+}
+
+void HiRes1Engine::drawPic(byte pic, byte xOffset, byte yOffset) {
+ Common::File f;
+ Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
+
+ if (!f.open(name))
+ error("Failed to open file");
+
+ f.seek(_pictures[pic].offset);
+ drawPic(f, xOffset, yOffset);
+}
+
+void HiRes1Engine::drawItems() {
+ Common::Array<Item>::const_iterator it;
+
+ uint dropped = 0;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field2 != _room)
+ continue;
+
+ if (it->field7 == 1) {
+ if (_rooms[_room].field8 == _rooms[_room].picture) {
+ const Common::Point &p = _itemOffsets[dropped];
+ if (it->field4)
+ _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
+ else
+ drawPic(it->field3, p.x, p.y);
+ ++dropped;
+ }
+ continue;
+ }
+
+ Common::Array<byte>::const_iterator it2;
+
+ for (it2 = it->field10.begin(); it2 != it->field10.end(); ++it2) {
+ if (*it2 == _rooms[_room].picture) {
+ if (it->field4)
+ _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(it->field5, it->field6), 0, 1, 0x7f);
+ else
+ drawPic(it->field3, it->field5, it->field6);
+ continue;
+ }
+ }
+ }
+}
+
+void HiRes1Engine::showRoom() {
+ if (!_isDark) {
+ drawPic(_rooms[_room].picture, 0, 0);
+ drawItems();
+ }
+
+ _display->decodeFrameBuffer();
+ printMessage(_rooms[_room].description, false);
+}
+
+Common::String HiRes1Engine::getExeString(uint idx) {
+ return _exeStrings[idx];
+}
+
+void HiRes1Engine::wordWrap(Common::String &str) {
+ uint end = 39;
+
+ while (1) {
+ if (str.size() <= end)
+ return;
+
+ while (str[end] != APPLECHAR(' '))
+ --end;
+
+ str.setChar(APPLECHAR('\r'), end);
+ end += 40;
+ }
+}
+
+void HiRes1Engine::printMessage(uint idx, bool wait) {
+ // Hardcoded overrides that don't wait after printing
+ // Note: strings may differ slightly from the ones in MESSAGES
+ switch (idx) {
+ case 137:
+ _display->printString(_exeStrings[STR_MH_DIRERR]);
+ return;
+ case 127:
+ _display->printString(_exeStrings[STR_MH_DONTHAVEIT]);
+ return;
+ case 37:
+ _display->printString(_exeStrings[STR_MH_DONTUNDERSTAND]);
+ return;
+ case 7:
+ _display->printString(_exeStrings[STR_MH_GETTINGDARK]);
+ return;
+ }
+
+ Common::String msg = _msgStrings[idx - 1];
+ wordWrap(msg);
+ _display->printString(msg);
+
+ if (wait)
+ _display->delay(14 * 166018 / 1000);
+}
+
+void HiRes1Engine::readCommands(Common::ReadStream &stream, Commands &commands) {
+ while (1) {
+ Command command;
+ command.room = stream.readByte();
+
+ if (command.room == 0xff)
+ return;
+
+ command.verb = stream.readByte();
+ command.noun = stream.readByte();
+
+ byte scriptSize = stream.readByte() - 6;
+
+ command.numCond = stream.readByte();
+ command.numAct = stream.readByte();
+
+ for (uint i = 0; i < scriptSize; ++i)
+ command.script.push_back(stream.readByte());
+
+ if (stream.eos() || stream.err())
+ error("Failed to read commands");
+
+ commands.push_back(command);
+ }
+}
+
+void HiRes1Engine::takeItem(byte noun) {
+ Common::Array<Item>::iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field1 != noun || it->field2 != _room)
+ continue;
+
+ if (it->field7 == 2) {
+ // It doesn't move
+ printMessage(151);
+ return;
+ }
+
+ if (it->field7 == 1) {
+ it->field2 = 0xfe;
+ it->field7 = 1;
+ return;
+ }
+
+ Common::Array<byte>::const_iterator it2;
+ for (it2 = it->field10.begin(); it->field10.end(); ++it2) {
+ if (*it2 == _rooms[_room].picture) {
+ it->field2 = 0xfe;
+ it->field7 = 1;
+ return;
+ }
+ }
+ }
+
+ // Item not here
+ printMessage(152);
+}
+
+void HiRes1Engine::dropItem(byte noun) {
+ Common::Array<Item>::iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field1 != noun || it->field2 != 0xfe)
+ continue;
+
+ it->field2 = _room;
+ it->field7 = 1;
+ return;
+ }
+
+ // Don't understand
+ printMessage(37);
+}
+
+void HiRes1Engine::doActions(const Command &command, byte noun, byte offset) {
+ for (uint i = 0; i < command.numAct; ++i) {
+ switch (command.script[offset]) {
+ case 1:
+ _variables[command.script[offset + 2]] += command.script[offset + 1];
+ offset += 3;
+ break;
+ case 2:
+ _variables[command.script[offset + 2]] -= command.script[offset + 1];
+ offset += 3;
+ break;
+ case 3:
+ _variables[command.script[offset + 1]] = command.script[offset + 2];
+ offset += 3;
+ break;
+ case 4: {
+ Common::Array<Item>::const_iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it)
+ if (it->field2 == 0xfe)
+ printMessage(it->field8);
+
+ ++offset;
+ break;
+ }
+ case 5:
+ _inventory[command.script[offset + 1] - 1].field2 = command.script[offset + 2];
+ offset += 3;
+ break;
+ case 6:
+ _rooms[_room].picture = _rooms[_room].field8;
+ _room = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 7:
+ _rooms[_room].picture = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 8:
+ _rooms[_room].field8 = _rooms[_room].picture = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 9:
+ printMessage(command.script[offset + 1]);
+ offset += 2;
+ break;
+ case 0xa:
+ _isDark = false;
+ ++offset;
+ break;
+ case 0xb:
+ _isDark = true;
+ ++offset;
+ break;
+ case 0xf:
+ warning("Save game not implemented");
+ ++offset;
+ break;
+ case 0x10:
+ warning("Load game not implemented");
+ ++offset;
+ break;
+ case 0x11: {
+ _display->printString(_exeStrings[STR_MH_PLAYAGAIN]);
+ Common::String input = _display->inputString();
+ if (input.size() == 0 || input[0] != APPLECHAR('N')) {
+ warning("Restart game not implemented");
+ return;
+ }
+ // Fall-through
+ }
+ case 0xd:
+ printMessage(140);
+ quitGame();
+ return;
+ case 0x12: {
+ byte item = command.script[offset + 1] - 1;
+ _inventory[item].field2 = command.script[offset + 2];
+ _inventory[item].field5 = command.script[offset + 3];
+ _inventory[item].field6 = command.script[offset + 4];
+ offset += 5;
+ break;
+ }
+ case 0x13: {
+ byte item = command.script[offset + 2] - 1;
+ _inventory[item].field3 = command.script[offset + 1];
+ offset += 3;
+ break;
+ }
+ case 0x14:
+ _rooms[_room].picture = _rooms[_room].field8;
+ ++offset;
+ break;
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a: {
+ byte room = _rooms[_room].connections[command.script[offset] - 0x15];
+
+ if (room == 0) {
+ printMessage(137);
+ return;
+ }
+
+ _rooms[_room].picture = _rooms[_room].field8;
+ _room = room;
+ return;
+ }
+ case 0x1b:
+ takeItem(noun);
+ ++offset;
+ break;
+ case 0x1c:
+ dropItem(noun);
+ ++offset;
+ break;
+ case 0x1d:
+ _rooms[command.script[offset + 1]].field8 = _rooms[command.script[offset + 1]].picture = command.script[offset + 2];
+ offset += 3;
+ break;
+ default:
+ error("Invalid action opcode %02x", command.script[offset]);
+ }
+ }
+}
+
+bool HiRes1Engine::checkCommand(const Command &command, byte verb, byte noun) {
+ if (command.room != 0xfe && command.room != _room)
+ return false;
+
+ if (command.verb != 0xfe && command.verb != verb)
+ return false;
+
+ if (command.noun != 0xfe && command.noun != noun)
+ return false;
+
+ uint offset = 0;
+ for (uint i = 0; i < command.numCond; ++i) {
+ switch (command.script[offset]) {
+ case 3:
+ if (_inventory[command.script[offset + 1] - 1].field2 != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ case 5:
+ if (command.script[offset + 1] > _steps)
+ return false;
+ offset += 2;
+ break;
+ case 6:
+ if (_variables[command.script[offset + 1]] != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ case 9:
+ if (_rooms[_room].picture != command.script[offset + 1])
+ return false;
+ offset += 2;
+ break;
+ case 10:
+ if (_inventory[command.script[offset + 1] - 1].field3 != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ default:
+ error("Invalid condition opcode %02x", command.script[offset]);
+ }
+ }
+
+ doActions(command, noun, offset);
+
+ return true;
+}
+
+bool HiRes1Engine::doOneCommand(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator it;
+
+ for (it = commands.begin(); it != commands.end(); ++it)
+ if (checkCommand(*it, verb, noun))
+ return true;
+
+ return false;
+}
+
+void HiRes1Engine::doAllCommands(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator it;
+
+ for (it = commands.begin(); it != commands.end(); ++it)
+ checkCommand(*it, verb, noun);
+}
+
+void HiRes1Engine::clearScreen() {
+ _display->setMode(Display::kModeMixed);
+ _display->clear(0x00);
+}
+
+void HiRes1Engine::runGame() {
+ runIntro();
+ _display->printASCIIString("\r");
+
+ Common::File f;
+
+ if (!f.open("MESSAGES"))
+ error("Failed to open file");
+
+ while (!f.eos() && !f.err())
+ _msgStrings.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
+
+ f.close();
+
+ if (!f.open("ADVENTURE"))
+ error("Failed to open file");
+
+ // Load strings from executable
+ for (uint idx = 0; idx < STR_MH_TOTAL; ++idx) {
+ f.seek(exeStrings[idx]);
+ _exeStrings.push_back(readString(f));
+ }
+
+ // Load room data from executable
+ f.seek(1280);
+ for (uint i = 0; i < MH_ROOMS; ++i) {
+ struct Room room;
+ f.readByte();
+ room.description = f.readByte();
+ for (uint j = 0; j < 6; ++j)
+ room.connections[j] = f.readByte();
+ room.field8 = f.readByte();
+ room.picture = f.readByte();
+ _rooms.push_back(room);
+ }
+
+ // Load inventory data from executable
+ f.seek(0x100);
+ while (f.readByte() != 0xff) {
+ struct Item item;
+ item.field1 = f.readByte();
+ item.field2 = f.readByte();
+ item.field3 = f.readByte();
+ item.field4 = f.readByte();
+ item.field5 = f.readByte();
+ item.field6 = f.readByte();
+ item.field7 = f.readByte();
+ item.field8 = f.readByte();
+
+ f.readByte();
+
+ byte size = f.readByte();
+
+ for (uint i = 0; i < size; ++i)
+ item.field10.push_back(f.readByte());
+
+ _inventory.push_back(item);
+ }
+
+ // Load picture data from executable
+ f.seek(0x4b00);
+ for (uint i = 0; i < MH_PICS; ++i) {
+ struct Picture pic;
+ pic.block = f.readByte();
+ pic.offset = f.readUint16LE();
+ _pictures.push_back(pic);
+ }
+
+ // Load commands from executable
+ f.seek(0x3D00);
+ readCommands(f, _roomCommands);
+
+ f.seek(0x3C00);
+ readCommands(f, _globalCommands);
+
+ // Load dropped item offsets
+ f.seek(0x68ff);
+ for (uint i = 0; i < MH_ITEM_OFFSETS; ++i) {
+ Common::Point p;
+ p.x = f.readByte();
+ p.y = f.readByte();
+ _itemOffsets.push_back(p);
+ }
+
+ // Load right-angle drawings
+ f.seek(0x4f00);
+ uint16 drawingsTotal = f.readUint16LE();
+ for (uint i = 0; i < drawingsTotal; ++i) {
+ f.seek(0x4f00 + 2 + i * 2);
+ uint16 offset = f.readUint16LE();
+ f.seek(0x4f00 + offset);
+
+ Common::Array<byte> drawing;
+ byte b = f.readByte();
+ while (b != 0) {
+ drawing.push_back(b);
+ b = f.readByte();
+ }
+ _drawings.push_back(drawing);
+ }
+
+ // Title screen shown during loading
+ f.seek(0x1800);
+ _display->loadFrameBuffer(f);
+ _display->decodeFrameBuffer();
+ _display->delay(2000);
+
+ f.seek(0x3800);
+ _parser->loadVerbs(f);
+
+ f.seek(0xf00);
+ _parser->loadNouns(f);
+
+ while (1) {
+ uint verb = 0, noun = 0;
+ clearScreen();
+ showRoom();
+ _parser->getInput(verb, noun);
+
+ if (!doOneCommand(_roomCommands, verb, noun))
+ printMessage(37);
+ doAllCommands(_globalCommands, verb, noun);
+
+ _steps++;
+
+ if (shouldQuit())
+ return;
+ }
+}
+
+AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd) {
+ return new HiRes1Engine(syst, gd);
+}
+
+} // End of namespace Adl
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
new file mode 100644
index 0000000..e9e274c
--- /dev/null
+++ b/engines/adl/hires1.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 ADL_ADL_V1_H
+#define ADL_ADL_V1_H
+
+#include "adl/adl.h"
+
+namespace Common {
+class ReadStream;
+}
+
+namespace Adl {
+
+enum {
+ // Some of these are probably common
+ STR_MH_DIRERR = STR_CUSTOM_START,
+ STR_MH_DONTHAVEIT,
+ STR_MH_DONTUNDERSTAND,
+ STR_MH_GETTINGDARK,
+ STR_MH_PLAYAGAIN,
+
+ STR_MH_TOTAL
+};
+
+class HiRes1Engine : public AdlEngine {
+public:
+ HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
+ Common::String getExeString(uint idx);
+
+protected:
+ void runGame();
+
+private:
+ enum {
+ MH_ROOMS = 42,
+ MH_PICS = 98,
+ MH_ITEM_OFFSETS = 21
+ };
+
+ void runIntro();
+ void drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset);
+ void showRoom();
+ void printMessage(uint idx, bool wait = true);
+ void wordWrap(Common::String &str);
+ void readCommands(Common::ReadStream &stream, Commands &commands);
+ bool checkCommand(const Command &command, byte verb, byte noun);
+ bool doOneCommand(const Commands &commands, byte verb, byte noun);
+ void doAllCommands(const Commands &commands, byte verb, byte noun);
+ void doActions(const Command &command, byte noun, byte offset);
+ void clearScreen();
+ void takeItem(byte noun);
+ void dropItem(byte noun);
+ void drawItems();
+ void drawPic(byte pic, byte xOffset, byte yOffset);
+
+ Common::Array<Common::String> _exeStrings;
+};
+
+} // End of namespace Adl
+
+#endif
diff --git a/engines/adl/module.mk b/engines/adl/module.mk
index 8f86eee..012b027 100644
--- a/engines/adl/module.mk
+++ b/engines/adl/module.mk
@@ -1,10 +1,10 @@
MODULE := engines/adl
MODULE_OBJS := \
+ adl.o \
detection.o \
display.o \
- adl.o \
- adl_v1.o \
+ hires1.o \
parser.o
MODULE_DIRS += \
Commit: 6a1dd071978f8ef48cb980d736877f1944a9a78f
https://github.com/scummvm/scummvm/commit/6a1dd071978f8ef48cb980d736877f1944a9a78f
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move more functionality into base class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
engines/adl/parser.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 3ee72e8..2c11290 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -103,6 +103,309 @@ void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) {
};
}
+Common::String AdlEngine::getEngineString(int str) {
+ return _strings[str];
+}
+
+void AdlEngine::wordWrap(Common::String &str) {
+ uint end = 39;
+
+ while (1) {
+ if (str.size() <= end)
+ return;
+
+ while (str[end] != APPLECHAR(' '))
+ --end;
+
+ str.setChar(APPLECHAR('\r'), end);
+ end += 40;
+ }
+}
+
+void AdlEngine::printMessage(uint idx, bool wait) {
+ Common::String msg = _messages[idx - 1];
+ wordWrap(msg);
+ _display->printString(msg);
+
+ if (wait)
+ _display->delay(14 * 166018 / 1000);
+}
+
+void AdlEngine::printEngineMessage(EngineMessage msg) {
+ printMessage(getEngineMessage(msg));
+}
+
+void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
+ while (1) {
+ Command command;
+ command.room = stream.readByte();
+
+ if (command.room == 0xff)
+ return;
+
+ command.verb = stream.readByte();
+ command.noun = stream.readByte();
+
+ byte scriptSize = stream.readByte() - 6;
+
+ command.numCond = stream.readByte();
+ command.numAct = stream.readByte();
+
+ for (uint i = 0; i < scriptSize; ++i)
+ command.script.push_back(stream.readByte());
+
+ if (stream.eos() || stream.err())
+ error("Failed to read commands");
+
+ commands.push_back(command);
+ }
+}
+
+void AdlEngine::takeItem(byte noun) {
+ Common::Array<Item>::iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field1 != noun || it->field2 != _room)
+ continue;
+
+ if (it->field7 == 2) {
+ printEngineMessage(IDI_MSG_ITEM_DOESNT_MOVE);
+ return;
+ }
+
+ if (it->field7 == 1) {
+ it->field2 = 0xfe;
+ it->field7 = 1;
+ return;
+ }
+
+ Common::Array<byte>::const_iterator it2;
+ for (it2 = it->field10.begin(); it->field10.end(); ++it2) {
+ if (*it2 == _rooms[_room].picture) {
+ it->field2 = 0xfe;
+ it->field7 = 1;
+ return;
+ }
+ }
+ }
+
+ printEngineMessage(IDI_MSG_ITEM_NOT_HERE);
+}
+
+void AdlEngine::dropItem(byte noun) {
+ Common::Array<Item>::iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it) {
+ if (it->field1 != noun || it->field2 != 0xfe)
+ continue;
+
+ it->field2 = _room;
+ it->field7 = 1;
+ return;
+ }
+
+ // Don't understand
+ printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
+}
+
+void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
+ for (uint i = 0; i < command.numAct; ++i) {
+ switch (command.script[offset]) {
+ case 1:
+ _variables[command.script[offset + 2]] += command.script[offset + 1];
+ offset += 3;
+ break;
+ case 2:
+ _variables[command.script[offset + 2]] -= command.script[offset + 1];
+ offset += 3;
+ break;
+ case 3:
+ _variables[command.script[offset + 1]] = command.script[offset + 2];
+ offset += 3;
+ break;
+ case 4: {
+ Common::Array<Item>::const_iterator it;
+
+ for (it = _inventory.begin(); it != _inventory.end(); ++it)
+ if (it->field2 == 0xfe)
+ printMessage(it->field8);
+
+ ++offset;
+ break;
+ }
+ case 5:
+ _inventory[command.script[offset + 1] - 1].field2 = command.script[offset + 2];
+ offset += 3;
+ break;
+ case 6:
+ _rooms[_room].picture = _rooms[_room].field8;
+ _room = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 7:
+ _rooms[_room].picture = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 8:
+ _rooms[_room].field8 = _rooms[_room].picture = command.script[offset + 1];
+ offset += 2;
+ break;
+ case 9:
+ printMessage(command.script[offset + 1]);
+ offset += 2;
+ break;
+ case 0xa:
+ _isDark = false;
+ ++offset;
+ break;
+ case 0xb:
+ _isDark = true;
+ ++offset;
+ break;
+ case 0xf:
+ warning("Save game not implemented");
+ ++offset;
+ break;
+ case 0x10:
+ warning("Load game not implemented");
+ ++offset;
+ break;
+ case 0x11: {
+ _display->printString(_strings[IDI_STR_PLAY_AGAIN]);
+ Common::String input = _display->inputString();
+ if (input.size() == 0 || input[0] != APPLECHAR('N')) {
+ warning("Restart game not implemented");
+ return;
+ }
+ // Fall-through
+ }
+ case 0xd:
+ printEngineMessage(IDI_MSG_THANKS_FOR_PLAYING);
+ quitGame();
+ return;
+ case 0x12: {
+ byte item = command.script[offset + 1] - 1;
+ _inventory[item].field2 = command.script[offset + 2];
+ _inventory[item].field5 = command.script[offset + 3];
+ _inventory[item].field6 = command.script[offset + 4];
+ offset += 5;
+ break;
+ }
+ case 0x13: {
+ byte item = command.script[offset + 2] - 1;
+ _inventory[item].field3 = command.script[offset + 1];
+ offset += 3;
+ break;
+ }
+ case 0x14:
+ _rooms[_room].picture = _rooms[_room].field8;
+ ++offset;
+ break;
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a: {
+ byte room = _rooms[_room].connections[command.script[offset] - 0x15];
+
+ if (room == 0) {
+ printEngineMessage(IDI_MSG_CANT_GO_THERE);
+ return;
+ }
+
+ _rooms[_room].picture = _rooms[_room].field8;
+ _room = room;
+ return;
+ }
+ case 0x1b:
+ takeItem(noun);
+ ++offset;
+ break;
+ case 0x1c:
+ dropItem(noun);
+ ++offset;
+ break;
+ case 0x1d:
+ _rooms[command.script[offset + 1]].field8 = _rooms[command.script[offset + 1]].picture = command.script[offset + 2];
+ offset += 3;
+ break;
+ default:
+ error("Invalid action opcode %02x", command.script[offset]);
+ }
+ }
+}
+
+bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
+ if (command.room != 0xfe && command.room != _room)
+ return false;
+
+ if (command.verb != 0xfe && command.verb != verb)
+ return false;
+
+ if (command.noun != 0xfe && command.noun != noun)
+ return false;
+
+ uint offset = 0;
+ for (uint i = 0; i < command.numCond; ++i) {
+ switch (command.script[offset]) {
+ case 3:
+ if (_inventory[command.script[offset + 1] - 1].field2 != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ case 5:
+ if (command.script[offset + 1] > _steps)
+ return false;
+ offset += 2;
+ break;
+ case 6:
+ if (_variables[command.script[offset + 1]] != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ case 9:
+ if (_rooms[_room].picture != command.script[offset + 1])
+ return false;
+ offset += 2;
+ break;
+ case 10:
+ if (_inventory[command.script[offset + 1] - 1].field3 != command.script[offset + 2])
+ return false;
+ offset += 3;
+ break;
+ default:
+ error("Invalid condition opcode %02x", command.script[offset]);
+ }
+ }
+
+ doActions(command, noun, offset);
+
+ return true;
+}
+
+bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator it;
+
+ for (it = commands.begin(); it != commands.end(); ++it)
+ if (checkCommand(*it, verb, noun))
+ return true;
+
+ return false;
+}
+
+void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator it;
+
+ for (it = commands.begin(); it != commands.end(); ++it)
+ checkCommand(*it, verb, noun);
+}
+
+void AdlEngine::clearScreen() {
+ _display->setMode(Display::kModeMixed);
+ _display->clear(0x00);
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 5252916..beb915c 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -42,16 +42,33 @@ class Parser;
class Console;
struct AdlGameDescription;
+struct StringOffset {
+ int stringIdx;
+ uint offset;
+};
+
enum GameType {
kGameTypeNone = 0,
kGameTypeHires1
};
-enum {
- STR_COMMON_ENTERCMD,
- STR_COMMON_VERBERR,
- STR_COMMON_NOUNERR,
- STR_CUSTOM_START
+// Messages used outside of scripts
+enum EngineMessage {
+ IDI_MSG_CANT_GO_THERE,
+ IDI_MSG_DONT_UNDERSTAND,
+ IDI_MSG_ITEM_DOESNT_MOVE,
+ IDI_MSG_ITEM_NOT_HERE,
+ IDI_MSG_THANKS_FOR_PLAYING
+};
+
+// Strings embedded in the executable
+enum EngineString {
+ IDI_STR_ENTER_COMMAND,
+ IDI_STR_VERB_ERROR,
+ IDI_STR_NOUN_ERROR,
+ IDI_STR_PLAY_AGAIN,
+
+ IDI_STR_TOTAL
};
struct Room {
@@ -99,17 +116,29 @@ public:
static AdlEngine *create(GameType type, OSystem *syst, const AdlGameDescription *gd);
Common::Error run();
- virtual Common::String getExeString(uint id) = 0;
+ virtual Common::String getEngineString(int str);
protected:
virtual void runGame() = 0;
+ virtual uint getEngineMessage(EngineMessage msg) = 0;
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
+ virtual void printMessage(uint idx, bool wait = true);
+ void wordWrap(Common::String &str);
+ void readCommands(Common::ReadStream &stream, Commands &commands);
+ bool checkCommand(const Command &command, byte verb, byte noun);
+ bool doOneCommand(const Commands &commands, byte verb, byte noun);
+ void doAllCommands(const Commands &commands, byte verb, byte noun);
+ void doActions(const Command &command, byte noun, byte offset);
+ void clearScreen();
+ void takeItem(byte noun);
+ void dropItem(byte noun);
Display *_display;
Parser *_parser;
- Common::Array<Common::String> _msgStrings;
+ Common::Array<Common::String> _strings;
+ Common::Array<Common::String> _messages;
Common::Array<Picture> _pictures;
Common::Array<Item> _inventory;
Common::Array<Common::Point> _itemOffsets;
@@ -123,6 +152,9 @@ protected:
uint16 _steps;
Common::Array<byte> _variables;
bool _isDark;
+
+private:
+ void printEngineMessage(EngineMessage);
};
AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 28aa135..7d52d2a 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -41,8 +41,34 @@
namespace Adl {
-static uint exeStrings[STR_MH_TOTAL] = {
- 23484, 23375, 23438, 27658, 0x6c31, 27729, 27772, 0x5f1e
+// Messages used outside of scripts
+#define IDI_HR1_MSG_CANT_GO_THERE 137
+#define IDI_HR1_MSG_DONT_UNDERSTAND 37
+#define IDI_HR1_MSG_ITEM_DOESNT_MOVE 151
+#define IDI_HR1_MSG_ITEM_NOT_HERE 152
+#define IDI_HR1_MSG_THANKS_FOR_PLAYING 140
+#define IDI_HR1_MSG_DONT_HAVE_IT 127
+#define IDI_HR1_MSG_GETTING_DARK 7
+
+// Strings embedded in the executable
+enum {
+ IDI_HR1_STR_CANT_GO_THERE = IDI_STR_TOTAL,
+ IDI_HR1_STR_DONT_HAVE_IT,
+ IDI_HR1_STR_DONT_UNDERSTAND,
+ IDI_HR1_STR_GETTING_DARK,
+
+ IDI_HR1_STR_TOTAL
+};
+
+static const StringOffset stringOffsets[] = {
+ { IDI_STR_ENTER_COMMAND, 0x5bbc },
+ { IDI_STR_VERB_ERROR, 0x5b4f },
+ { IDI_STR_NOUN_ERROR, 0x5b8e },
+ { IDI_STR_PLAY_AGAIN, 0x5f1e },
+ { IDI_HR1_STR_CANT_GO_THERE, 0x6c0a },
+ { IDI_HR1_STR_DONT_HAVE_IT, 0x6c31 },
+ { IDI_HR1_STR_DONT_UNDERSTAND, 0x6c51 },
+ { IDI_HR1_STR_GETTING_DARK, 0x6c7c }
};
HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
@@ -225,324 +251,6 @@ void HiRes1Engine::showRoom() {
printMessage(_rooms[_room].description, false);
}
-Common::String HiRes1Engine::getExeString(uint idx) {
- return _exeStrings[idx];
-}
-
-void HiRes1Engine::wordWrap(Common::String &str) {
- uint end = 39;
-
- while (1) {
- if (str.size() <= end)
- return;
-
- while (str[end] != APPLECHAR(' '))
- --end;
-
- str.setChar(APPLECHAR('\r'), end);
- end += 40;
- }
-}
-
-void HiRes1Engine::printMessage(uint idx, bool wait) {
- // Hardcoded overrides that don't wait after printing
- // Note: strings may differ slightly from the ones in MESSAGES
- switch (idx) {
- case 137:
- _display->printString(_exeStrings[STR_MH_DIRERR]);
- return;
- case 127:
- _display->printString(_exeStrings[STR_MH_DONTHAVEIT]);
- return;
- case 37:
- _display->printString(_exeStrings[STR_MH_DONTUNDERSTAND]);
- return;
- case 7:
- _display->printString(_exeStrings[STR_MH_GETTINGDARK]);
- return;
- }
-
- Common::String msg = _msgStrings[idx - 1];
- wordWrap(msg);
- _display->printString(msg);
-
- if (wait)
- _display->delay(14 * 166018 / 1000);
-}
-
-void HiRes1Engine::readCommands(Common::ReadStream &stream, Commands &commands) {
- while (1) {
- Command command;
- command.room = stream.readByte();
-
- if (command.room == 0xff)
- return;
-
- command.verb = stream.readByte();
- command.noun = stream.readByte();
-
- byte scriptSize = stream.readByte() - 6;
-
- command.numCond = stream.readByte();
- command.numAct = stream.readByte();
-
- for (uint i = 0; i < scriptSize; ++i)
- command.script.push_back(stream.readByte());
-
- if (stream.eos() || stream.err())
- error("Failed to read commands");
-
- commands.push_back(command);
- }
-}
-
-void HiRes1Engine::takeItem(byte noun) {
- Common::Array<Item>::iterator it;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field1 != noun || it->field2 != _room)
- continue;
-
- if (it->field7 == 2) {
- // It doesn't move
- printMessage(151);
- return;
- }
-
- if (it->field7 == 1) {
- it->field2 = 0xfe;
- it->field7 = 1;
- return;
- }
-
- Common::Array<byte>::const_iterator it2;
- for (it2 = it->field10.begin(); it->field10.end(); ++it2) {
- if (*it2 == _rooms[_room].picture) {
- it->field2 = 0xfe;
- it->field7 = 1;
- return;
- }
- }
- }
-
- // Item not here
- printMessage(152);
-}
-
-void HiRes1Engine::dropItem(byte noun) {
- Common::Array<Item>::iterator it;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field1 != noun || it->field2 != 0xfe)
- continue;
-
- it->field2 = _room;
- it->field7 = 1;
- return;
- }
-
- // Don't understand
- printMessage(37);
-}
-
-void HiRes1Engine::doActions(const Command &command, byte noun, byte offset) {
- for (uint i = 0; i < command.numAct; ++i) {
- switch (command.script[offset]) {
- case 1:
- _variables[command.script[offset + 2]] += command.script[offset + 1];
- offset += 3;
- break;
- case 2:
- _variables[command.script[offset + 2]] -= command.script[offset + 1];
- offset += 3;
- break;
- case 3:
- _variables[command.script[offset + 1]] = command.script[offset + 2];
- offset += 3;
- break;
- case 4: {
- Common::Array<Item>::const_iterator it;
-
- for (it = _inventory.begin(); it != _inventory.end(); ++it)
- if (it->field2 == 0xfe)
- printMessage(it->field8);
-
- ++offset;
- break;
- }
- case 5:
- _inventory[command.script[offset + 1] - 1].field2 = command.script[offset + 2];
- offset += 3;
- break;
- case 6:
- _rooms[_room].picture = _rooms[_room].field8;
- _room = command.script[offset + 1];
- offset += 2;
- break;
- case 7:
- _rooms[_room].picture = command.script[offset + 1];
- offset += 2;
- break;
- case 8:
- _rooms[_room].field8 = _rooms[_room].picture = command.script[offset + 1];
- offset += 2;
- break;
- case 9:
- printMessage(command.script[offset + 1]);
- offset += 2;
- break;
- case 0xa:
- _isDark = false;
- ++offset;
- break;
- case 0xb:
- _isDark = true;
- ++offset;
- break;
- case 0xf:
- warning("Save game not implemented");
- ++offset;
- break;
- case 0x10:
- warning("Load game not implemented");
- ++offset;
- break;
- case 0x11: {
- _display->printString(_exeStrings[STR_MH_PLAYAGAIN]);
- Common::String input = _display->inputString();
- if (input.size() == 0 || input[0] != APPLECHAR('N')) {
- warning("Restart game not implemented");
- return;
- }
- // Fall-through
- }
- case 0xd:
- printMessage(140);
- quitGame();
- return;
- case 0x12: {
- byte item = command.script[offset + 1] - 1;
- _inventory[item].field2 = command.script[offset + 2];
- _inventory[item].field5 = command.script[offset + 3];
- _inventory[item].field6 = command.script[offset + 4];
- offset += 5;
- break;
- }
- case 0x13: {
- byte item = command.script[offset + 2] - 1;
- _inventory[item].field3 = command.script[offset + 1];
- offset += 3;
- break;
- }
- case 0x14:
- _rooms[_room].picture = _rooms[_room].field8;
- ++offset;
- break;
- case 0x15:
- case 0x16:
- case 0x17:
- case 0x18:
- case 0x19:
- case 0x1a: {
- byte room = _rooms[_room].connections[command.script[offset] - 0x15];
-
- if (room == 0) {
- printMessage(137);
- return;
- }
-
- _rooms[_room].picture = _rooms[_room].field8;
- _room = room;
- return;
- }
- case 0x1b:
- takeItem(noun);
- ++offset;
- break;
- case 0x1c:
- dropItem(noun);
- ++offset;
- break;
- case 0x1d:
- _rooms[command.script[offset + 1]].field8 = _rooms[command.script[offset + 1]].picture = command.script[offset + 2];
- offset += 3;
- break;
- default:
- error("Invalid action opcode %02x", command.script[offset]);
- }
- }
-}
-
-bool HiRes1Engine::checkCommand(const Command &command, byte verb, byte noun) {
- if (command.room != 0xfe && command.room != _room)
- return false;
-
- if (command.verb != 0xfe && command.verb != verb)
- return false;
-
- if (command.noun != 0xfe && command.noun != noun)
- return false;
-
- uint offset = 0;
- for (uint i = 0; i < command.numCond; ++i) {
- switch (command.script[offset]) {
- case 3:
- if (_inventory[command.script[offset + 1] - 1].field2 != command.script[offset + 2])
- return false;
- offset += 3;
- break;
- case 5:
- if (command.script[offset + 1] > _steps)
- return false;
- offset += 2;
- break;
- case 6:
- if (_variables[command.script[offset + 1]] != command.script[offset + 2])
- return false;
- offset += 3;
- break;
- case 9:
- if (_rooms[_room].picture != command.script[offset + 1])
- return false;
- offset += 2;
- break;
- case 10:
- if (_inventory[command.script[offset + 1] - 1].field3 != command.script[offset + 2])
- return false;
- offset += 3;
- break;
- default:
- error("Invalid condition opcode %02x", command.script[offset]);
- }
- }
-
- doActions(command, noun, offset);
-
- return true;
-}
-
-bool HiRes1Engine::doOneCommand(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator it;
-
- for (it = commands.begin(); it != commands.end(); ++it)
- if (checkCommand(*it, verb, noun))
- return true;
-
- return false;
-}
-
-void HiRes1Engine::doAllCommands(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator it;
-
- for (it = commands.begin(); it != commands.end(); ++it)
- checkCommand(*it, verb, noun);
-}
-
-void HiRes1Engine::clearScreen() {
- _display->setMode(Display::kModeMixed);
- _display->clear(0x00);
-}
-
void HiRes1Engine::runGame() {
runIntro();
_display->printASCIIString("\r");
@@ -553,7 +261,7 @@ void HiRes1Engine::runGame() {
error("Failed to open file");
while (!f.eos() && !f.err())
- _msgStrings.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
+ _messages.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
f.close();
@@ -561,9 +269,10 @@ void HiRes1Engine::runGame() {
error("Failed to open file");
// Load strings from executable
- for (uint idx = 0; idx < STR_MH_TOTAL; ++idx) {
- f.seek(exeStrings[idx]);
- _exeStrings.push_back(readString(f));
+ _strings.resize(IDI_HR1_STR_TOTAL);
+ for (uint idx = 0; idx < IDI_HR1_STR_TOTAL; ++idx) {
+ f.seek(stringOffsets[idx].offset);
+ _strings[stringOffsets[idx].stringIdx] = readString(f);
}
// Load room data from executable
@@ -673,6 +382,44 @@ void HiRes1Engine::runGame() {
}
}
+void HiRes1Engine::printMessage(uint idx, bool wait) {
+ // Hardcoded overrides that don't wait after printing
+ // Note: strings may differ slightly from the ones in MESSAGES
+ switch (idx) {
+ case 137:
+ _display->printString(_strings[IDI_HR1_STR_CANT_GO_THERE]);
+ return;
+ case 127:
+ _display->printString(_strings[IDI_HR1_STR_DONT_HAVE_IT]);
+ return;
+ case 37:
+ _display->printString(_strings[IDI_HR1_STR_DONT_UNDERSTAND]);
+ return;
+ case 7:
+ _display->printString(_strings[IDI_HR1_STR_GETTING_DARK]);
+ return;
+ }
+
+ AdlEngine::printMessage(idx, wait);
+}
+
+uint HiRes1Engine::getEngineMessage(EngineMessage msg) {
+ switch (msg) {
+ case IDI_MSG_CANT_GO_THERE:
+ return IDI_HR1_MSG_CANT_GO_THERE;
+ case IDI_MSG_DONT_UNDERSTAND:
+ return IDI_HR1_MSG_DONT_UNDERSTAND;
+ case IDI_MSG_ITEM_DOESNT_MOVE:
+ return IDI_HR1_MSG_ITEM_DOESNT_MOVE;
+ case IDI_MSG_ITEM_NOT_HERE:
+ return IDI_HR1_MSG_ITEM_NOT_HERE;
+ case IDI_MSG_THANKS_FOR_PLAYING:
+ return IDI_HR1_MSG_THANKS_FOR_PLAYING;
+ default:
+ error("Cannot find engine message %i", msg);
+ }
+}
+
AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd) {
return new HiRes1Engine(syst, gd);
}
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index e9e274c..19aa55e 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -32,20 +32,12 @@ class ReadStream;
namespace Adl {
enum {
- // Some of these are probably common
- STR_MH_DIRERR = STR_CUSTOM_START,
- STR_MH_DONTHAVEIT,
- STR_MH_DONTUNDERSTAND,
- STR_MH_GETTINGDARK,
- STR_MH_PLAYAGAIN,
-
- STR_MH_TOTAL
+ IDI_HR1_MSG_
};
class HiRes1Engine : public AdlEngine {
public:
HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
- Common::String getExeString(uint idx);
protected:
void runGame();
@@ -57,23 +49,14 @@ private:
MH_ITEM_OFFSETS = 21
};
+ void printMessage(uint idx, bool wait = true);
+ uint getEngineMessage(EngineMessage msg);
+
void runIntro();
void drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset);
void showRoom();
- void printMessage(uint idx, bool wait = true);
- void wordWrap(Common::String &str);
- void readCommands(Common::ReadStream &stream, Commands &commands);
- bool checkCommand(const Command &command, byte verb, byte noun);
- bool doOneCommand(const Commands &commands, byte verb, byte noun);
- void doAllCommands(const Commands &commands, byte verb, byte noun);
- void doActions(const Command &command, byte noun, byte offset);
- void clearScreen();
- void takeItem(byte noun);
- void dropItem(byte noun);
void drawItems();
void drawPic(byte pic, byte xOffset, byte yOffset);
-
- Common::Array<Common::String> _exeStrings;
};
} // End of namespace Adl
diff --git a/engines/adl/parser.cpp b/engines/adl/parser.cpp
index 1611fc7..a697301 100644
--- a/engines/adl/parser.cpp
+++ b/engines/adl/parser.cpp
@@ -129,7 +129,7 @@ Common::String Parser::getWord(const Common::String &line, uint &index) {
void Parser::getInput(uint &verb, uint &noun) {
while (1) {
- _display.printString(_engine.getExeString(STR_COMMON_ENTERCMD));
+ _display.printString(_engine.getEngineString(IDI_STR_ENTER_COMMAND));
Common::String line = getLine();
if (g_engine->shouldQuit())
@@ -139,7 +139,7 @@ void Parser::getInput(uint &verb, uint &noun) {
Common::String verbStr = getWord(line, index);
if (!_verbs.contains(verbStr)) {
- Common::String err = _engine.getExeString(STR_COMMON_VERBERR);
+ Common::String err = _engine.getEngineString(IDI_STR_VERB_ERROR);
for (uint i = 0; i < verbStr.size(); ++i)
err.setChar(verbStr[i], i + 19);
_display.printString(err);
@@ -151,7 +151,7 @@ void Parser::getInput(uint &verb, uint &noun) {
Common::String nounStr = getWord(line, index);
if (!_nouns.contains(nounStr)) {
- Common::String err = _engine.getExeString(STR_COMMON_NOUNERR);
+ Common::String err = _engine.getEngineString(IDI_STR_NOUN_ERROR);
for (uint i = 0; i < verbStr.size(); ++i)
err.setChar(verbStr[i], i + 19);
for (uint i = 0; i < nounStr.size(); ++i)
Commit: ce97d0a26e51ff1253ae3268f09673f0aa31f4a7
https://github.com/scummvm/scummvm/commit/ce97d0a26e51ff1253ae3268f09673f0aa31f4a7
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Use #defines instead of literals
Changed paths:
engines/adl/hires1.cpp
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 7d52d2a..65aa665 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -386,16 +386,16 @@ void HiRes1Engine::printMessage(uint idx, bool wait) {
// Hardcoded overrides that don't wait after printing
// Note: strings may differ slightly from the ones in MESSAGES
switch (idx) {
- case 137:
+ case IDI_HR1_MSG_CANT_GO_THERE:
_display->printString(_strings[IDI_HR1_STR_CANT_GO_THERE]);
return;
- case 127:
+ case IDI_HR1_MSG_DONT_HAVE_IT:
_display->printString(_strings[IDI_HR1_STR_DONT_HAVE_IT]);
return;
- case 37:
+ case IDI_MSG_DONT_UNDERSTAND:
_display->printString(_strings[IDI_HR1_STR_DONT_UNDERSTAND]);
return;
- case 7:
+ case IDI_HR1_MSG_GETTING_DARK:
_display->printString(_strings[IDI_HR1_STR_GETTING_DARK]);
return;
}
Commit: f9c9f2ac9de984aed7fb2438899aff33104ab3b8
https://github.com/scummvm/scummvm/commit/f9c9f2ac9de984aed7fb2438899aff33104ab3b8
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename Item struct fields
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 2c11290..3ce6d70 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -165,25 +165,24 @@ void AdlEngine::takeItem(byte noun) {
Common::Array<Item>::iterator it;
for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field1 != noun || it->field2 != _room)
+ if (it->noun != noun || it->room != _room)
continue;
- if (it->field7 == 2) {
+ if (it->state == IDI_ITEM_DOESNT_MOVE) {
printEngineMessage(IDI_MSG_ITEM_DOESNT_MOVE);
return;
}
- if (it->field7 == 1) {
- it->field2 = 0xfe;
- it->field7 = 1;
+ if (it->state == IDI_ITEM_MOVED) {
+ it->room = IDI_NONE;
return;
}
Common::Array<byte>::const_iterator it2;
- for (it2 = it->field10.begin(); it->field10.end(); ++it2) {
+ for (it2 = it->roomPictures.begin(); it->roomPictures.end(); ++it2) {
if (*it2 == _rooms[_room].picture) {
- it->field2 = 0xfe;
- it->field7 = 1;
+ it->room = IDI_NONE;
+ it->state = IDI_ITEM_MOVED;
return;
}
}
@@ -196,11 +195,11 @@ void AdlEngine::dropItem(byte noun) {
Common::Array<Item>::iterator it;
for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field1 != noun || it->field2 != 0xfe)
+ if (it->noun != noun || it->room != IDI_NONE)
continue;
- it->field2 = _room;
- it->field7 = 1;
+ it->room = _room;
+ it->state = IDI_ITEM_MOVED;
return;
}
@@ -227,14 +226,14 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
Common::Array<Item>::const_iterator it;
for (it = _inventory.begin(); it != _inventory.end(); ++it)
- if (it->field2 == 0xfe)
- printMessage(it->field8);
+ if (it->room == IDI_NONE)
+ printMessage(it->description);
++offset;
break;
}
case 5:
- _inventory[command.script[offset + 1] - 1].field2 = command.script[offset + 2];
+ _inventory[command.script[offset + 1] - 1].room = command.script[offset + 2];
offset += 3;
break;
case 6:
@@ -285,15 +284,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
return;
case 0x12: {
byte item = command.script[offset + 1] - 1;
- _inventory[item].field2 = command.script[offset + 2];
- _inventory[item].field5 = command.script[offset + 3];
- _inventory[item].field6 = command.script[offset + 4];
+ _inventory[item].room = command.script[offset + 2];
+ _inventory[item].position.x = command.script[offset + 3];
+ _inventory[item].position.y = command.script[offset + 4];
offset += 5;
break;
}
case 0x13: {
byte item = command.script[offset + 2] - 1;
- _inventory[item].field3 = command.script[offset + 1];
+ _inventory[item].picture = command.script[offset + 1];
offset += 3;
break;
}
@@ -337,20 +336,20 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
}
bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
- if (command.room != 0xfe && command.room != _room)
+ if (command.room != IDI_NONE && command.room != _room)
return false;
- if (command.verb != 0xfe && command.verb != verb)
+ if (command.verb != IDI_NONE && command.verb != verb)
return false;
- if (command.noun != 0xfe && command.noun != noun)
+ if (command.noun != IDI_NONE && command.noun != noun)
return false;
uint offset = 0;
for (uint i = 0; i < command.numCond; ++i) {
switch (command.script[offset]) {
case 3:
- if (_inventory[command.script[offset + 1] - 1].field2 != command.script[offset + 2])
+ if (_inventory[command.script[offset + 1] - 1].room != command.script[offset + 2])
return false;
offset += 3;
break;
@@ -370,7 +369,7 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
offset += 2;
break;
case 10:
- if (_inventory[command.script[offset + 1] - 1].field3 != command.script[offset + 2])
+ if (_inventory[command.script[offset + 1] - 1].picture != command.script[offset + 2])
return false;
offset += 3;
break;
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index beb915c..987a962 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -90,16 +90,23 @@ struct Command {
Common::Array<byte> script;
};
+enum {
+ IDI_ITEM_NOT_MOVED,
+ IDI_ITEM_MOVED,
+ IDI_ITEM_DOESNT_MOVE
+};
+
+#define IDI_NONE 0xfe
+
struct Item {
- byte field1;
- byte field2;
- byte field3;
- byte field4;
- byte field5;
- byte field6;
- byte field7;
- byte field8;
- Common::Array<byte> field10;
+ byte noun;
+ byte room;
+ byte picture;
+ bool isDrawing;
+ Common::Point position;
+ int state;
+ byte description;
+ Common::Array<byte> roomPictures;
};
typedef Common::List<Command> Commands;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 65aa665..a078340 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -212,16 +212,16 @@ void HiRes1Engine::drawItems() {
uint dropped = 0;
for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->field2 != _room)
+ if (it->room != _room)
continue;
- if (it->field7 == 1) {
+ if (it->state == IDI_ITEM_MOVED) {
if (_rooms[_room].field8 == _rooms[_room].picture) {
const Common::Point &p = _itemOffsets[dropped];
- if (it->field4)
- _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
+ if (it->isDrawing)
+ _display->drawRightAngles(_drawings[it->picture - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
else
- drawPic(it->field3, p.x, p.y);
+ drawPic(it->picture, p.x, p.y);
++dropped;
}
continue;
@@ -229,12 +229,12 @@ void HiRes1Engine::drawItems() {
Common::Array<byte>::const_iterator it2;
- for (it2 = it->field10.begin(); it2 != it->field10.end(); ++it2) {
+ for (it2 = it->roomPictures.begin(); it2 != it->roomPictures.end(); ++it2) {
if (*it2 == _rooms[_room].picture) {
- if (it->field4)
- _display->drawRightAngles(_drawings[it->field3 - 1], Common::Point(it->field5, it->field6), 0, 1, 0x7f);
+ if (it->isDrawing)
+ _display->drawRightAngles(_drawings[it->picture - 1], it->position, 0, 1, 0x7f);
else
- drawPic(it->field3, it->field5, it->field6);
+ drawPic(it->picture, it->position.x, it->position.y);
continue;
}
}
@@ -292,21 +292,21 @@ void HiRes1Engine::runGame() {
f.seek(0x100);
while (f.readByte() != 0xff) {
struct Item item;
- item.field1 = f.readByte();
- item.field2 = f.readByte();
- item.field3 = f.readByte();
- item.field4 = f.readByte();
- item.field5 = f.readByte();
- item.field6 = f.readByte();
- item.field7 = f.readByte();
- item.field8 = f.readByte();
+ item.noun = f.readByte();
+ item.room = f.readByte();
+ item.picture = f.readByte();
+ item.isDrawing = f.readByte();
+ item.position.x = f.readByte();
+ item.position.y = f.readByte();
+ item.state = f.readByte();
+ item.description = f.readByte();
f.readByte();
byte size = f.readByte();
for (uint i = 0; i < size; ++i)
- item.field10.push_back(f.readByte());
+ item.roomPictures.push_back(f.readByte());
_inventory.push_back(item);
}
Commit: 8f9d4b96530a8b30ec2208aa217d6b339e4e94b7
https://github.com/scummvm/scummvm/commit/8f9d4b96530a8b30ec2208aa217d6b339e4e94b7
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Use #defines instead of literals
Changed paths:
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 987a962..4c8180e 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -42,16 +42,16 @@ class Parser;
class Console;
struct AdlGameDescription;
-struct StringOffset {
- int stringIdx;
- uint offset;
-};
-
enum GameType {
kGameTypeNone = 0,
kGameTypeHires1
};
+struct StringOffset {
+ int stringIdx;
+ uint offset;
+};
+
// Messages used outside of scripts
enum EngineMessage {
IDI_MSG_CANT_GO_THERE,
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index a078340..a5dbb89 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -60,6 +60,7 @@ enum {
IDI_HR1_STR_TOTAL
};
+// Offsets for strings inside executable
static const StringOffset stringOffsets[] = {
{ IDI_STR_ENTER_COMMAND, 0x5bbc },
{ IDI_STR_VERB_ERROR, 0x5b4f },
@@ -71,6 +72,16 @@ static const StringOffset stringOffsets[] = {
{ IDI_HR1_STR_GETTING_DARK, 0x6c7c }
};
+#define IDI_HR1_OFS_PD_TEXT_0 0x5d
+#define IDI_HR1_OFS_PD_TEXT_1 0x12b
+#define IDI_HR1_OFS_PD_TEXT_2 0x16d
+#define IDI_HR1_OFS_PD_TEXT_3 0x259
+
+#define IDI_HR1_OFS_INTRO_TEXT 0x66
+#define IDI_HR1_OFS_GAME_OR_HELP 0xf
+
+#define IDI_HR1_OFS_LOGO_0 0x1003
+
HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine(syst, gd) {
_variables.resize(20);
@@ -82,7 +93,7 @@ void HiRes1Engine::runIntro() {
if (!file.open("AUTO LOAD OBJ"))
error("Failed to open file");
- file.seek(0x1003);
+ file.seek(IDI_HR1_OFS_LOGO_0);
_display->setMode(Display::kModeHires);
_display->loadFrameBuffer(file);
_display->decodeFrameBuffer();
@@ -99,19 +110,19 @@ void HiRes1Engine::runIntro() {
Common::String str;
- basic.seek(93);
+ basic.seek(IDI_HR1_OFS_PD_TEXT_0);
str = readString(basic, '"');
_display->printASCIIString(str + '\r');
- basic.seek(299);
+ basic.seek(IDI_HR1_OFS_PD_TEXT_1);
str = readString(basic, '"');
_display->printASCIIString(str + "\r\r");
- basic.seek(365);
+ basic.seek(IDI_HR1_OFS_PD_TEXT_2);
str = readString(basic, '"');
_display->printASCIIString(str + "\r\r");
- basic.seek(601);
+ basic.seek(IDI_HR1_OFS_PD_TEXT_3);
str = readString(basic, '"');
_display->printASCIIString(str + '\r');
@@ -121,7 +132,7 @@ void HiRes1Engine::runIntro() {
_display->setMode(Display::kModeMixed);
- file.seek(15);
+ file.seek(IDI_HR1_OFS_GAME_OR_HELP);
str = readString(file);
while (1) {
@@ -141,7 +152,7 @@ void HiRes1Engine::runIntro() {
};
_display->setMode(Display::kModeText);
- file.seek(102);
+ file.seek(IDI_HR1_OFS_INTRO_TEXT);
const int pages[] = { 6, 6, 4, 5, 8, 7, 0 };
Commit: 2104a5095d9d338a05cdf1e3a8e8b7f680b15f46
https://github.com/scummvm/scummvm/commit/2104a5095d9d338a05cdf1e3a8e8b7f680b15f46
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename Room struct fields
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 3ce6d70..6109004 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -180,7 +180,7 @@ void AdlEngine::takeItem(byte noun) {
Common::Array<byte>::const_iterator it2;
for (it2 = it->roomPictures.begin(); it->roomPictures.end(); ++it2) {
- if (*it2 == _rooms[_room].picture) {
+ if (*it2 == _rooms[_room].curPicture) {
it->room = IDI_NONE;
it->state = IDI_ITEM_MOVED;
return;
@@ -237,16 +237,16 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
offset += 3;
break;
case 6:
- _rooms[_room].picture = _rooms[_room].field8;
+ _rooms[_room].curPicture = _rooms[_room].picture;
_room = command.script[offset + 1];
offset += 2;
break;
case 7:
- _rooms[_room].picture = command.script[offset + 1];
+ _rooms[_room].curPicture = command.script[offset + 1];
offset += 2;
break;
case 8:
- _rooms[_room].field8 = _rooms[_room].picture = command.script[offset + 1];
+ _rooms[_room].picture = _rooms[_room].curPicture = command.script[offset + 1];
offset += 2;
break;
case 9:
@@ -297,7 +297,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
}
case 0x14:
- _rooms[_room].picture = _rooms[_room].field8;
+ _rooms[_room].curPicture = _rooms[_room].picture;
++offset;
break;
case 0x15:
@@ -313,7 +313,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
return;
}
- _rooms[_room].picture = _rooms[_room].field8;
+ _rooms[_room].curPicture = _rooms[_room].picture;
_room = room;
return;
}
@@ -326,7 +326,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case 0x1d:
- _rooms[command.script[offset + 1]].field8 = _rooms[command.script[offset + 1]].picture = command.script[offset + 2];
+ _rooms[command.script[offset + 1]].picture = _rooms[command.script[offset + 1]].curPicture = command.script[offset + 2];
offset += 3;
break;
default:
@@ -364,7 +364,7 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
offset += 3;
break;
case 9:
- if (_rooms[_room].picture != command.script[offset + 1])
+ if (_rooms[_room].curPicture != command.script[offset + 1])
return false;
offset += 2;
break;
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 4c8180e..fffe61e 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -74,8 +74,8 @@ enum EngineString {
struct Room {
byte description;
byte connections[6];
- byte field8;
byte picture;
+ byte curPicture;
};
struct Picture {
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index a5dbb89..730f229 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -42,13 +42,13 @@
namespace Adl {
// Messages used outside of scripts
-#define IDI_HR1_MSG_CANT_GO_THERE 137
-#define IDI_HR1_MSG_DONT_UNDERSTAND 37
-#define IDI_HR1_MSG_ITEM_DOESNT_MOVE 151
-#define IDI_HR1_MSG_ITEM_NOT_HERE 152
+#define IDI_HR1_MSG_CANT_GO_THERE 137
+#define IDI_HR1_MSG_DONT_UNDERSTAND 37
+#define IDI_HR1_MSG_ITEM_DOESNT_MOVE 151
+#define IDI_HR1_MSG_ITEM_NOT_HERE 152
#define IDI_HR1_MSG_THANKS_FOR_PLAYING 140
-#define IDI_HR1_MSG_DONT_HAVE_IT 127
-#define IDI_HR1_MSG_GETTING_DARK 7
+#define IDI_HR1_MSG_DONT_HAVE_IT 127
+#define IDI_HR1_MSG_GETTING_DARK 7
// Strings embedded in the executable
enum {
@@ -227,7 +227,7 @@ void HiRes1Engine::drawItems() {
continue;
if (it->state == IDI_ITEM_MOVED) {
- if (_rooms[_room].field8 == _rooms[_room].picture) {
+ if (_rooms[_room].picture == _rooms[_room].curPicture) {
const Common::Point &p = _itemOffsets[dropped];
if (it->isDrawing)
_display->drawRightAngles(_drawings[it->picture - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
@@ -241,7 +241,7 @@ void HiRes1Engine::drawItems() {
Common::Array<byte>::const_iterator it2;
for (it2 = it->roomPictures.begin(); it2 != it->roomPictures.end(); ++it2) {
- if (*it2 == _rooms[_room].picture) {
+ if (*it2 == _rooms[_room].curPicture) {
if (it->isDrawing)
_display->drawRightAngles(_drawings[it->picture - 1], it->position, 0, 1, 0x7f);
else
@@ -254,7 +254,7 @@ void HiRes1Engine::drawItems() {
void HiRes1Engine::showRoom() {
if (!_isDark) {
- drawPic(_rooms[_room].picture, 0, 0);
+ drawPic(_rooms[_room].curPicture, 0, 0);
drawItems();
}
@@ -294,8 +294,8 @@ void HiRes1Engine::runGame() {
room.description = f.readByte();
for (uint j = 0; j < 6; ++j)
room.connections[j] = f.readByte();
- room.field8 = f.readByte();
room.picture = f.readByte();
+ room.curPicture = f.readByte();
_rooms.push_back(room);
}
Commit: 00d87cca9007ef69314b00eec5bffd6b9a9f2e72
https://github.com/scummvm/scummvm/commit/00d87cca9007ef69314b00eec5bffd6b9a9f2e72
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add more #defines for literals
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 6109004..af71bba 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -210,19 +210,19 @@ void AdlEngine::dropItem(byte noun) {
void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
switch (command.script[offset]) {
- case 1:
+ case IDO_ACT_VAR_ADD:
_variables[command.script[offset + 2]] += command.script[offset + 1];
offset += 3;
break;
- case 2:
+ case IDO_ACT_VAR_SUB:
_variables[command.script[offset + 2]] -= command.script[offset + 1];
offset += 3;
break;
- case 3:
+ case IDO_ACT_VAR_SET:
_variables[command.script[offset + 1]] = command.script[offset + 2];
offset += 3;
break;
- case 4: {
+ case IDO_ACT_LIST_ITEMS: {
Common::Array<Item>::const_iterator it;
for (it = _inventory.begin(); it != _inventory.end(); ++it)
@@ -232,44 +232,44 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
}
- case 5:
+ case IDO_ACT_MOVE_ITEM:
_inventory[command.script[offset + 1] - 1].room = command.script[offset + 2];
offset += 3;
break;
- case 6:
+ case IDO_ACT_SET_ROOM:
_rooms[_room].curPicture = _rooms[_room].picture;
_room = command.script[offset + 1];
offset += 2;
break;
- case 7:
+ case IDO_ACT_SET_CUR_PIC:
_rooms[_room].curPicture = command.script[offset + 1];
offset += 2;
break;
- case 8:
+ case IDO_ACT_SET_PIC:
_rooms[_room].picture = _rooms[_room].curPicture = command.script[offset + 1];
offset += 2;
break;
- case 9:
+ case IDO_ACT_PRINT_MSG:
printMessage(command.script[offset + 1]);
offset += 2;
break;
- case 0xa:
+ case IDO_ACT_SET_LIGHT:
_isDark = false;
++offset;
break;
- case 0xb:
+ case IDO_ACT_SET_DARK:
_isDark = true;
++offset;
break;
- case 0xf:
+ case IDO_ACT_SAVE:
warning("Save game not implemented");
++offset;
break;
- case 0x10:
+ case IDO_ACT_LOAD:
warning("Load game not implemented");
++offset;
break;
- case 0x11: {
+ case IDO_ACT_RESTART: {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
Common::String input = _display->inputString();
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
@@ -278,11 +278,11 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
}
// Fall-through
}
- case 0xd:
+ case IDO_ACT_QUIT:
printEngineMessage(IDI_MSG_THANKS_FOR_PLAYING);
quitGame();
return;
- case 0x12: {
+ case IDO_ACT_SET_ITEM_POS: {
byte item = command.script[offset + 1] - 1;
_inventory[item].room = command.script[offset + 2];
_inventory[item].position.x = command.script[offset + 3];
@@ -290,22 +290,22 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
offset += 5;
break;
}
- case 0x13: {
+ case IDO_ACT_SET_ITEM_PIC: {
byte item = command.script[offset + 2] - 1;
_inventory[item].picture = command.script[offset + 1];
offset += 3;
break;
}
- case 0x14:
+ case IDO_ACT_RESET_PIC:
_rooms[_room].curPicture = _rooms[_room].picture;
++offset;
break;
- case 0x15:
- case 0x16:
- case 0x17:
- case 0x18:
- case 0x19:
- case 0x1a: {
+ case IDO_ACT_GO_NORTH:
+ case IDO_ACT_GO_SOUTH:
+ case IDO_ACT_GO_EAST:
+ case IDO_ACT_GO_WEST:
+ case IDO_ACT_GO_UP:
+ case IDO_ACT_GO_DOWN: {
byte room = _rooms[_room].connections[command.script[offset] - 0x15];
if (room == 0) {
@@ -317,15 +317,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
_room = room;
return;
}
- case 0x1b:
+ case IDO_ACT_TAKE_ITEM:
takeItem(noun);
++offset;
break;
- case 0x1c:
+ case IDO_ACT_DROP_ITEM:
dropItem(noun);
++offset;
break;
- case 0x1d:
+ case IDO_ACT_SET_ROOM_PIC:
_rooms[command.script[offset + 1]].picture = _rooms[command.script[offset + 1]].curPicture = command.script[offset + 2];
offset += 3;
break;
@@ -348,27 +348,27 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
uint offset = 0;
for (uint i = 0; i < command.numCond; ++i) {
switch (command.script[offset]) {
- case 3:
+ case IDO_CND_ITEM_IN_ROOM:
if (_inventory[command.script[offset + 1] - 1].room != command.script[offset + 2])
return false;
offset += 3;
break;
- case 5:
+ case IDO_CND_STEPS_GE:
if (command.script[offset + 1] > _steps)
return false;
offset += 2;
break;
- case 6:
+ case IDO_CND_VAR_EQ:
if (_variables[command.script[offset + 1]] != command.script[offset + 2])
return false;
offset += 3;
break;
- case 9:
+ case IDO_CND_CUR_PIC_EQ:
if (_rooms[_room].curPicture != command.script[offset + 1])
return false;
offset += 2;
break;
- case 10:
+ case IDO_CND_ITEM_PIC_EQ:
if (_inventory[command.script[offset + 1] - 1].picture != command.script[offset + 2])
return false;
offset += 3;
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index fffe61e..e78d9ae 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -71,6 +71,42 @@ enum EngineString {
IDI_STR_TOTAL
};
+// Conditional opcodes
+#define IDO_CND_ITEM_IN_ROOM 0x03
+#define IDO_CND_STEPS_GE 0x05
+#define IDO_CND_VAR_EQ 0x06
+#define IDO_CND_CUR_PIC_EQ 0x09
+#define IDO_CND_ITEM_PIC_EQ 0x0a
+
+// Action opcodes
+#define IDO_ACT_VAR_ADD 0x01
+#define IDO_ACT_VAR_SUB 0x02
+#define IDO_ACT_VAR_SET 0x03
+#define IDO_ACT_LIST_ITEMS 0x04
+#define IDO_ACT_MOVE_ITEM 0x05
+#define IDO_ACT_SET_ROOM 0x06
+#define IDO_ACT_SET_CUR_PIC 0x07
+#define IDO_ACT_SET_PIC 0x08
+#define IDO_ACT_PRINT_MSG 0x09
+#define IDO_ACT_SET_LIGHT 0x0a
+#define IDO_ACT_SET_DARK 0x0b
+#define IDO_ACT_QUIT 0x0d
+#define IDO_ACT_SAVE 0x0f
+#define IDO_ACT_LOAD 0x10
+#define IDO_ACT_RESTART 0x11
+#define IDO_ACT_SET_ITEM_POS 0x12
+#define IDO_ACT_SET_ITEM_PIC 0x13
+#define IDO_ACT_RESET_PIC 0x14
+#define IDO_ACT_GO_NORTH 0x15
+#define IDO_ACT_GO_SOUTH 0x16
+#define IDO_ACT_GO_EAST 0x17
+#define IDO_ACT_GO_WEST 0x18
+#define IDO_ACT_GO_UP 0x19
+#define IDO_ACT_GO_DOWN 0x1a
+#define IDO_ACT_TAKE_ITEM 0x1b
+#define IDO_ACT_DROP_ITEM 0x1c
+#define IDO_ACT_SET_ROOM_PIC 0x1d
+
struct Room {
byte description;
byte connections[6];
Commit: ede25c19bcedb802f3b0a7a1a5dc20238277012c
https://github.com/scummvm/scummvm/commit/ede25c19bcedb802f3b0a7a1a5dc20238277012c
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename some #defines and variables for clarity
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index af71bba..eaffbb5 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -162,27 +162,27 @@ void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
}
void AdlEngine::takeItem(byte noun) {
- Common::Array<Item>::iterator it;
+ Common::Array<Item>::iterator item;
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->noun != noun || it->room != _room)
+ for (item = _inventory.begin(); item != _inventory.end(); ++item) {
+ if (item->noun != noun || item->room != _room)
continue;
- if (it->state == IDI_ITEM_DOESNT_MOVE) {
+ if (item->state == IDI_ITEM_DOESNT_MOVE) {
printEngineMessage(IDI_MSG_ITEM_DOESNT_MOVE);
return;
}
- if (it->state == IDI_ITEM_MOVED) {
- it->room = IDI_NONE;
+ if (item->state == IDI_ITEM_MOVED) {
+ item->room = IDI_NONE;
return;
}
- Common::Array<byte>::const_iterator it2;
- for (it2 = it->roomPictures.begin(); it->roomPictures.end(); ++it2) {
- if (*it2 == _rooms[_room].curPicture) {
- it->room = IDI_NONE;
- it->state = IDI_ITEM_MOVED;
+ Common::Array<byte>::const_iterator pic;
+ for (pic = item->roomPictures.begin(); item->roomPictures.end(); ++pic) {
+ if (*pic == _rooms[_room].curPicture) {
+ item->room = IDI_NONE;
+ item->state = IDI_ITEM_MOVED;
return;
}
}
@@ -192,18 +192,17 @@ void AdlEngine::takeItem(byte noun) {
}
void AdlEngine::dropItem(byte noun) {
- Common::Array<Item>::iterator it;
+ Common::Array<Item>::iterator item;
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->noun != noun || it->room != IDI_NONE)
+ for (item = _inventory.begin(); item != _inventory.end(); ++item) {
+ if (item->noun != noun || item->room != IDI_NONE)
continue;
- it->room = _room;
- it->state = IDI_ITEM_MOVED;
+ item->room = _room;
+ item->state = IDI_ITEM_MOVED;
return;
}
- // Don't understand
printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
}
@@ -223,11 +222,11 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
offset += 3;
break;
case IDO_ACT_LIST_ITEMS: {
- Common::Array<Item>::const_iterator it;
+ Common::Array<Item>::const_iterator item;
- for (it = _inventory.begin(); it != _inventory.end(); ++it)
- if (it->room == IDI_NONE)
- printMessage(it->description);
+ for (item = _inventory.begin(); item != _inventory.end(); ++item)
+ if (item->room == IDI_NONE)
+ printMessage(item->description);
++offset;
break;
@@ -282,7 +281,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
printEngineMessage(IDI_MSG_THANKS_FOR_PLAYING);
quitGame();
return;
- case IDO_ACT_SET_ITEM_POS: {
+ case IDO_ACT_PLACE_ITEM: {
byte item = command.script[offset + 1] - 1;
_inventory[item].room = command.script[offset + 2];
_inventory[item].position.x = command.script[offset + 3];
@@ -384,20 +383,20 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
}
bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator it;
+ Commands::const_iterator cmd;
- for (it = commands.begin(); it != commands.end(); ++it)
- if (checkCommand(*it, verb, noun))
+ for (cmd = commands.begin(); cmd != commands.end(); ++cmd)
+ if (checkCommand(*cmd, verb, noun))
return true;
return false;
}
void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator it;
+ Commands::const_iterator cmd;
- for (it = commands.begin(); it != commands.end(); ++it)
- checkCommand(*it, verb, noun);
+ for (cmd = commands.begin(); cmd != commands.end(); ++cmd)
+ checkCommand(*cmd, verb, noun);
}
void AdlEngine::clearScreen() {
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index e78d9ae..02207d9 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -94,7 +94,7 @@ enum EngineString {
#define IDO_ACT_SAVE 0x0f
#define IDO_ACT_LOAD 0x10
#define IDO_ACT_RESTART 0x11
-#define IDO_ACT_SET_ITEM_POS 0x12
+#define IDO_ACT_PLACE_ITEM 0x12
#define IDO_ACT_SET_ITEM_PIC 0x13
#define IDO_ACT_RESET_PIC 0x14
#define IDO_ACT_GO_NORTH 0x15
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 730f229..dde8ed0 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -218,34 +218,34 @@ void HiRes1Engine::drawPic(byte pic, byte xOffset, byte yOffset) {
}
void HiRes1Engine::drawItems() {
- Common::Array<Item>::const_iterator it;
+ Common::Array<Item>::const_iterator item;
uint dropped = 0;
- for (it = _inventory.begin(); it != _inventory.end(); ++it) {
- if (it->room != _room)
+ for (item = _inventory.begin(); item != _inventory.end(); ++item) {
+ if (item->room != _room)
continue;
- if (it->state == IDI_ITEM_MOVED) {
+ if (item->state == IDI_ITEM_MOVED) {
if (_rooms[_room].picture == _rooms[_room].curPicture) {
const Common::Point &p = _itemOffsets[dropped];
- if (it->isDrawing)
- _display->drawRightAngles(_drawings[it->picture - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
+ if (item->isDrawing)
+ _display->drawRightAngles(_drawings[item->picture - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
else
- drawPic(it->picture, p.x, p.y);
+ drawPic(item->picture, p.x, p.y);
++dropped;
}
continue;
}
- Common::Array<byte>::const_iterator it2;
+ Common::Array<byte>::const_iterator pic;
- for (it2 = it->roomPictures.begin(); it2 != it->roomPictures.end(); ++it2) {
- if (*it2 == _rooms[_room].curPicture) {
- if (it->isDrawing)
- _display->drawRightAngles(_drawings[it->picture - 1], it->position, 0, 1, 0x7f);
+ for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
+ if (*pic == _rooms[_room].curPicture) {
+ if (item->isDrawing)
+ _display->drawRightAngles(_drawings[item->picture - 1], item->position, 0, 1, 0x7f);
else
- drawPic(it->picture, it->position.x, it->position.y);
+ drawPic(item->picture, item->position.x, item->position.y);
continue;
}
}
Commit: 24c478c5ecd61d42a1456a7b8cbecec70e24cd1a
https://github.com/scummvm/scummvm/commit/24c478c5ecd61d42a1456a7b8cbecec70e24cd1a
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add ARG #define to improve readability
Changed paths:
engines/adl/adl.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index eaffbb5..c46b747 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -206,19 +206,21 @@ void AdlEngine::dropItem(byte noun) {
printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
}
+#define ARG(N) (command.script[offset + N])
+
void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
- switch (command.script[offset]) {
+ switch (ARG(0)) {
case IDO_ACT_VAR_ADD:
- _variables[command.script[offset + 2]] += command.script[offset + 1];
+ _variables[ARG(2)] += ARG(1);
offset += 3;
break;
case IDO_ACT_VAR_SUB:
- _variables[command.script[offset + 2]] -= command.script[offset + 1];
+ _variables[ARG(2)] -= ARG(1);
offset += 3;
break;
case IDO_ACT_VAR_SET:
- _variables[command.script[offset + 1]] = command.script[offset + 2];
+ _variables[ARG(1)] = ARG(2);
offset += 3;
break;
case IDO_ACT_LIST_ITEMS: {
@@ -232,24 +234,24 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
}
case IDO_ACT_MOVE_ITEM:
- _inventory[command.script[offset + 1] - 1].room = command.script[offset + 2];
+ _inventory[ARG(1) - 1].room = ARG(2);
offset += 3;
break;
case IDO_ACT_SET_ROOM:
_rooms[_room].curPicture = _rooms[_room].picture;
- _room = command.script[offset + 1];
+ _room = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_CUR_PIC:
- _rooms[_room].curPicture = command.script[offset + 1];
+ _rooms[_room].curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_PIC:
- _rooms[_room].picture = _rooms[_room].curPicture = command.script[offset + 1];
+ _rooms[_room].picture = _rooms[_room].curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_PRINT_MSG:
- printMessage(command.script[offset + 1]);
+ printMessage(ARG(1));
offset += 2;
break;
case IDO_ACT_SET_LIGHT:
@@ -281,20 +283,16 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
printEngineMessage(IDI_MSG_THANKS_FOR_PLAYING);
quitGame();
return;
- case IDO_ACT_PLACE_ITEM: {
- byte item = command.script[offset + 1] - 1;
- _inventory[item].room = command.script[offset + 2];
- _inventory[item].position.x = command.script[offset + 3];
- _inventory[item].position.y = command.script[offset + 4];
+ case IDO_ACT_PLACE_ITEM:
+ _inventory[ARG(1) - 1].room = ARG(2);
+ _inventory[ARG(1) - 1].position.x = ARG(3);
+ _inventory[ARG(1) - 1].position.y = ARG(4);
offset += 5;
break;
- }
- case IDO_ACT_SET_ITEM_PIC: {
- byte item = command.script[offset + 2] - 1;
- _inventory[item].picture = command.script[offset + 1];
+ case IDO_ACT_SET_ITEM_PIC:
+ _inventory[ARG(2) - 1].picture = ARG(1);
offset += 3;
break;
- }
case IDO_ACT_RESET_PIC:
_rooms[_room].curPicture = _rooms[_room].picture;
++offset;
@@ -305,7 +303,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
case IDO_ACT_GO_WEST:
case IDO_ACT_GO_UP:
case IDO_ACT_GO_DOWN: {
- byte room = _rooms[_room].connections[command.script[offset] - 0x15];
+ byte room = _rooms[_room].connections[ARG(0) - 0x15];
if (room == 0) {
printEngineMessage(IDI_MSG_CANT_GO_THERE);
@@ -325,11 +323,11 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case IDO_ACT_SET_ROOM_PIC:
- _rooms[command.script[offset + 1]].picture = _rooms[command.script[offset + 1]].curPicture = command.script[offset + 2];
+ _rooms[ARG(1)].picture = _rooms[ARG(1)].curPicture = ARG(2);
offset += 3;
break;
default:
- error("Invalid action opcode %02x", command.script[offset]);
+ error("Invalid action opcode %02x", ARG(0));
}
}
}
@@ -348,27 +346,27 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
for (uint i = 0; i < command.numCond; ++i) {
switch (command.script[offset]) {
case IDO_CND_ITEM_IN_ROOM:
- if (_inventory[command.script[offset + 1] - 1].room != command.script[offset + 2])
+ if (_inventory[ARG(1) - 1].room != ARG(2))
return false;
offset += 3;
break;
case IDO_CND_STEPS_GE:
- if (command.script[offset + 1] > _steps)
+ if (ARG(1) > _steps)
return false;
offset += 2;
break;
case IDO_CND_VAR_EQ:
- if (_variables[command.script[offset + 1]] != command.script[offset + 2])
+ if (_variables[ARG(1)] != ARG(2))
return false;
offset += 3;
break;
case IDO_CND_CUR_PIC_EQ:
- if (_rooms[_room].curPicture != command.script[offset + 1])
+ if (_rooms[_room].curPicture != ARG(1))
return false;
offset += 2;
break;
case IDO_CND_ITEM_PIC_EQ:
- if (_inventory[command.script[offset + 1] - 1].picture != command.script[offset + 2])
+ if (_inventory[ARG(1) - 1].picture != ARG(2))
return false;
offset += 3;
break;
@@ -382,6 +380,8 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
return true;
}
+#undef ARG
+
bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
Commit: 34cb2f4c53280d5b1f10ded5951d0ca5c0bf754d
https://github.com/scummvm/scummvm/commit/34cb2f4c53280d5b1f10ded5951d0ca5c0bf754d
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move functionality into base class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index c46b747..9676924 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -206,7 +206,7 @@ void AdlEngine::dropItem(byte noun) {
printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
}
-#define ARG(N) (command.script[offset + N])
+#define ARG(N) (command.script[offset + (N)])
void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
@@ -404,6 +404,51 @@ void AdlEngine::clearScreen() {
_display->clear(0x00);
}
+void AdlEngine::drawItems() {
+ Common::Array<Item>::const_iterator item;
+
+ uint dropped = 0;
+
+ for (item = _inventory.begin(); item != _inventory.end(); ++item) {
+ if (item->room != _room)
+ continue;
+
+ if (item->state == IDI_ITEM_MOVED) {
+ if (_rooms[_room].picture == _rooms[_room].curPicture) {
+ const Common::Point &p = _itemOffsets[dropped];
+ if (item->isDrawing)
+ _display->drawRightAngles(_drawings[item->picture - 1], p, 0, 1, 0x7f);
+ else
+ drawPic(item->picture, p);
+ ++dropped;
+ }
+ continue;
+ }
+
+ Common::Array<byte>::const_iterator pic;
+
+ for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
+ if (*pic == _rooms[_room].curPicture) {
+ if (item->isDrawing)
+ _display->drawRightAngles(_drawings[item->picture - 1], item->position, 0, 1, 0x7f);
+ else
+ drawPic(item->picture, item->position);
+ continue;
+ }
+ }
+ }
+}
+
+void AdlEngine::showRoom() {
+ if (!_isDark) {
+ drawPic(_rooms[_room].curPicture);
+ drawItems();
+ }
+
+ _display->decodeFrameBuffer();
+ printMessage(_rooms[_room].description, false);
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 02207d9..a030059 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -174,6 +174,9 @@ protected:
void doAllCommands(const Commands &commands, byte verb, byte noun);
void doActions(const Command &command, byte noun, byte offset);
void clearScreen();
+ virtual void drawPic(byte pic, Common::Point pos = Common::Point()) = 0;
+ void drawItems();
+ void showRoom();
void takeItem(byte noun);
void dropItem(byte noun);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index dde8ed0..64ae81f 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -169,7 +169,7 @@ void HiRes1Engine::runIntro() {
}
}
-void HiRes1Engine::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset) {
+void HiRes1Engine::drawPic(Common::ReadStream &stream, Common::Point pos) {
byte x, y;
bool bNewLine = false;
byte oldX = 0, oldY = 0;
@@ -188,8 +188,8 @@ void HiRes1Engine::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffse
continue;
}
- x += xOffset;
- y += yOffset;
+ x += pos.x;
+ y += pos.y;
if (y > 160)
y = 160;
@@ -206,7 +206,7 @@ void HiRes1Engine::drawPic(Common::ReadStream &stream, byte xOffset, byte yOffse
}
}
-void HiRes1Engine::drawPic(byte pic, byte xOffset, byte yOffset) {
+void HiRes1Engine::drawPic(byte pic, Common::Point pos) {
Common::File f;
Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
@@ -214,52 +214,7 @@ void HiRes1Engine::drawPic(byte pic, byte xOffset, byte yOffset) {
error("Failed to open file");
f.seek(_pictures[pic].offset);
- drawPic(f, xOffset, yOffset);
-}
-
-void HiRes1Engine::drawItems() {
- Common::Array<Item>::const_iterator item;
-
- uint dropped = 0;
-
- for (item = _inventory.begin(); item != _inventory.end(); ++item) {
- if (item->room != _room)
- continue;
-
- if (item->state == IDI_ITEM_MOVED) {
- if (_rooms[_room].picture == _rooms[_room].curPicture) {
- const Common::Point &p = _itemOffsets[dropped];
- if (item->isDrawing)
- _display->drawRightAngles(_drawings[item->picture - 1], Common::Point(p.x, p.y), 0, 1, 0x7f);
- else
- drawPic(item->picture, p.x, p.y);
- ++dropped;
- }
- continue;
- }
-
- Common::Array<byte>::const_iterator pic;
-
- for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == _rooms[_room].curPicture) {
- if (item->isDrawing)
- _display->drawRightAngles(_drawings[item->picture - 1], item->position, 0, 1, 0x7f);
- else
- drawPic(item->picture, item->position.x, item->position.y);
- continue;
- }
- }
- }
-}
-
-void HiRes1Engine::showRoom() {
- if (!_isDark) {
- drawPic(_rooms[_room].curPicture, 0, 0);
- drawItems();
- }
-
- _display->decodeFrameBuffer();
- printMessage(_rooms[_room].description, false);
+ drawPic(f, pos);
}
void HiRes1Engine::runGame() {
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 19aa55e..4bd0a87 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -53,10 +53,9 @@ private:
uint getEngineMessage(EngineMessage msg);
void runIntro();
- void drawPic(Common::ReadStream &stream, byte xOffset, byte yOffset);
- void showRoom();
+ void drawPic(Common::ReadStream &stream, Common::Point pos);
void drawItems();
- void drawPic(byte pic, byte xOffset, byte yOffset);
+ void drawPic(byte pic, Common::Point pos);
};
} // End of namespace Adl
Commit: 1abaf60cf04c5bc2bf8a3fb37aa8dd83816a7771
https://github.com/scummvm/scummvm/commit/1abaf60cf04c5bc2bf8a3fb37aa8dd83816a7771
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Rename rightAngles to lineArt
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 9676924..d93b771 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -416,8 +416,8 @@ void AdlEngine::drawItems() {
if (item->state == IDI_ITEM_MOVED) {
if (_rooms[_room].picture == _rooms[_room].curPicture) {
const Common::Point &p = _itemOffsets[dropped];
- if (item->isDrawing)
- _display->drawRightAngles(_drawings[item->picture - 1], p, 0, 1, 0x7f);
+ if (item->isLineArt)
+ _display->drawLineArt(_lineArt[item->picture - 1], p);
else
drawPic(item->picture, p);
++dropped;
@@ -429,8 +429,8 @@ void AdlEngine::drawItems() {
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
if (*pic == _rooms[_room].curPicture) {
- if (item->isDrawing)
- _display->drawRightAngles(_drawings[item->picture - 1], item->position, 0, 1, 0x7f);
+ if (item->isLineArt)
+ _display->drawLineArt(_lineArt[item->picture - 1], item->position);
else
drawPic(item->picture, item->position);
continue;
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index a030059..5335211 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -138,7 +138,7 @@ struct Item {
byte noun;
byte room;
byte picture;
- bool isDrawing;
+ bool isLineArt;
Common::Point position;
int state;
byte description;
@@ -188,7 +188,7 @@ protected:
Common::Array<Picture> _pictures;
Common::Array<Item> _inventory;
Common::Array<Common::Point> _itemOffsets;
- Common::Array<Common::Array<byte> > _drawings;
+ Common::Array<Common::Array<byte> > _lineArt;
Commands _roomCommands;
Commands _globalCommands;
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 47b1533..8ea0a7b 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -304,7 +304,7 @@ void Display::drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte q
moveY(p, bits & 2);
}
-void Display::drawRightAngles(Common::Array<byte> &rightAngles, Common::Point p, byte rotation, byte scaling, byte color) {
+void Display::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation, byte scaling, byte color) {
const byte stepping[] = {
0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
@@ -319,8 +319,8 @@ void Display::drawRightAngles(Common::Array<byte> &rightAngles, Common::Point p,
byte xStep = stepping[rotation];
byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
- for (uint i = 0; i < rightAngles.size(); ++i) {
- byte b = rightAngles[i];
+ for (uint i = 0; i < lineArt.size(); ++i) {
+ byte b = lineArt[i];
do {
byte xFrac = 0x80;
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 62294d3..229446f 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -63,7 +63,7 @@ public:
void drawPixel(byte x, byte y, byte color);
void drawLine(Common::Point p1, Common::Point p2, byte color);
void clear(byte color);
- void drawRightAngles(Common::Array<byte> &rightAngles, Common::Point p, byte rotation, byte scaling, byte color);
+ void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f);
private:
enum {
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 64ae81f..9163875 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -261,7 +261,7 @@ void HiRes1Engine::runGame() {
item.noun = f.readByte();
item.room = f.readByte();
item.picture = f.readByte();
- item.isDrawing = f.readByte();
+ item.isLineArt = f.readByte();
item.position.x = f.readByte();
item.position.y = f.readByte();
item.state = f.readByte();
@@ -302,21 +302,21 @@ void HiRes1Engine::runGame() {
_itemOffsets.push_back(p);
}
- // Load right-angle drawings
+ // Load right-angle line art
f.seek(0x4f00);
- uint16 drawingsTotal = f.readUint16LE();
- for (uint i = 0; i < drawingsTotal; ++i) {
+ uint16 lineArtTotal = f.readUint16LE();
+ for (uint i = 0; i < lineArtTotal; ++i) {
f.seek(0x4f00 + 2 + i * 2);
uint16 offset = f.readUint16LE();
f.seek(0x4f00 + offset);
- Common::Array<byte> drawing;
+ Common::Array<byte> lineArt;
byte b = f.readByte();
while (b != 0) {
- drawing.push_back(b);
+ lineArt.push_back(b);
b = f.readByte();
}
- _drawings.push_back(drawing);
+ _lineArt.push_back(lineArt);
}
// Title screen shown during loading
Commit: dc2e5e09ba045474284521e8db4ff7e40b0fe68a
https://github.com/scummvm/scummvm/commit/dc2e5e09ba045474284521e8db4ff7e40b0fe68a
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Put state-related members in _state struct
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index d93b771..e395c82 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -43,10 +43,7 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
_display(nullptr),
- _parser(nullptr),
- _room(1),
- _steps(0),
- _isDark(false) {
+ _parser(nullptr) {
}
AdlEngine::~AdlEngine() {
@@ -164,8 +161,8 @@ void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
void AdlEngine::takeItem(byte noun) {
Common::Array<Item>::iterator item;
- for (item = _inventory.begin(); item != _inventory.end(); ++item) {
- if (item->noun != noun || item->room != _room)
+ for (item = _state.items.begin(); item != _state.items.end(); ++item) {
+ if (item->noun != noun || item->room != _state.room)
continue;
if (item->state == IDI_ITEM_DOESNT_MOVE) {
@@ -180,7 +177,7 @@ void AdlEngine::takeItem(byte noun) {
Common::Array<byte>::const_iterator pic;
for (pic = item->roomPictures.begin(); item->roomPictures.end(); ++pic) {
- if (*pic == _rooms[_room].curPicture) {
+ if (*pic == _state.rooms[_state.room].curPicture) {
item->room = IDI_NONE;
item->state = IDI_ITEM_MOVED;
return;
@@ -194,11 +191,11 @@ void AdlEngine::takeItem(byte noun) {
void AdlEngine::dropItem(byte noun) {
Common::Array<Item>::iterator item;
- for (item = _inventory.begin(); item != _inventory.end(); ++item) {
+ for (item = _state.items.begin(); item != _state.items.end(); ++item) {
if (item->noun != noun || item->room != IDI_NONE)
continue;
- item->room = _room;
+ item->room = _state.room;
item->state = IDI_ITEM_MOVED;
return;
}
@@ -212,21 +209,21 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
switch (ARG(0)) {
case IDO_ACT_VAR_ADD:
- _variables[ARG(2)] += ARG(1);
+ _state.vars[ARG(2)] += ARG(1);
offset += 3;
break;
case IDO_ACT_VAR_SUB:
- _variables[ARG(2)] -= ARG(1);
+ _state.vars[ARG(2)] -= ARG(1);
offset += 3;
break;
case IDO_ACT_VAR_SET:
- _variables[ARG(1)] = ARG(2);
+ _state.vars[ARG(1)] = ARG(2);
offset += 3;
break;
case IDO_ACT_LIST_ITEMS: {
Common::Array<Item>::const_iterator item;
- for (item = _inventory.begin(); item != _inventory.end(); ++item)
+ for (item = _state.items.begin(); item != _state.items.end(); ++item)
if (item->room == IDI_NONE)
printMessage(item->description);
@@ -234,20 +231,20 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
}
case IDO_ACT_MOVE_ITEM:
- _inventory[ARG(1) - 1].room = ARG(2);
+ _state.items[ARG(1) - 1].room = ARG(2);
offset += 3;
break;
case IDO_ACT_SET_ROOM:
- _rooms[_room].curPicture = _rooms[_room].picture;
- _room = ARG(1);
+ _state.rooms[_state.room].curPicture = _state.rooms[_state.room].picture;
+ _state.room = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_CUR_PIC:
- _rooms[_room].curPicture = ARG(1);
+ _state.rooms[_state.room].curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_PIC:
- _rooms[_room].picture = _rooms[_room].curPicture = ARG(1);
+ _state.rooms[_state.room].picture = _state.rooms[_state.room].curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_PRINT_MSG:
@@ -255,11 +252,11 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
offset += 2;
break;
case IDO_ACT_SET_LIGHT:
- _isDark = false;
+ _state.isDark = false;
++offset;
break;
case IDO_ACT_SET_DARK:
- _isDark = true;
+ _state.isDark = true;
++offset;
break;
case IDO_ACT_SAVE:
@@ -284,17 +281,17 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
quitGame();
return;
case IDO_ACT_PLACE_ITEM:
- _inventory[ARG(1) - 1].room = ARG(2);
- _inventory[ARG(1) - 1].position.x = ARG(3);
- _inventory[ARG(1) - 1].position.y = ARG(4);
+ _state.items[ARG(1) - 1].room = ARG(2);
+ _state.items[ARG(1) - 1].position.x = ARG(3);
+ _state.items[ARG(1) - 1].position.y = ARG(4);
offset += 5;
break;
case IDO_ACT_SET_ITEM_PIC:
- _inventory[ARG(2) - 1].picture = ARG(1);
+ _state.items[ARG(2) - 1].picture = ARG(1);
offset += 3;
break;
case IDO_ACT_RESET_PIC:
- _rooms[_room].curPicture = _rooms[_room].picture;
+ _state.rooms[_state.room].curPicture = _state.rooms[_state.room].picture;
++offset;
break;
case IDO_ACT_GO_NORTH:
@@ -303,15 +300,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
case IDO_ACT_GO_WEST:
case IDO_ACT_GO_UP:
case IDO_ACT_GO_DOWN: {
- byte room = _rooms[_room].connections[ARG(0) - 0x15];
+ byte room = _state.rooms[_state.room].connections[ARG(0) - 0x15];
if (room == 0) {
printEngineMessage(IDI_MSG_CANT_GO_THERE);
return;
}
- _rooms[_room].curPicture = _rooms[_room].picture;
- _room = room;
+ _state.rooms[_state.room].curPicture = _state.rooms[_state.room].picture;
+ _state.room = room;
return;
}
case IDO_ACT_TAKE_ITEM:
@@ -323,7 +320,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case IDO_ACT_SET_ROOM_PIC:
- _rooms[ARG(1)].picture = _rooms[ARG(1)].curPicture = ARG(2);
+ _state.rooms[ARG(1)].picture = _state.rooms[ARG(1)].curPicture = ARG(2);
offset += 3;
break;
default:
@@ -333,7 +330,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
}
bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
- if (command.room != IDI_NONE && command.room != _room)
+ if (command.room != IDI_NONE && command.room != _state.room)
return false;
if (command.verb != IDI_NONE && command.verb != verb)
@@ -346,27 +343,27 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
for (uint i = 0; i < command.numCond; ++i) {
switch (command.script[offset]) {
case IDO_CND_ITEM_IN_ROOM:
- if (_inventory[ARG(1) - 1].room != ARG(2))
+ if (_state.items[ARG(1) - 1].room != ARG(2))
return false;
offset += 3;
break;
- case IDO_CND_STEPS_GE:
- if (ARG(1) > _steps)
+ case IDO_CND_MOVES_GE:
+ if (ARG(1) > _state.moves)
return false;
offset += 2;
break;
case IDO_CND_VAR_EQ:
- if (_variables[ARG(1)] != ARG(2))
+ if (_state.vars[ARG(1)] != ARG(2))
return false;
offset += 3;
break;
case IDO_CND_CUR_PIC_EQ:
- if (_rooms[_room].curPicture != ARG(1))
+ if (_state.rooms[_state.room].curPicture != ARG(1))
return false;
offset += 2;
break;
case IDO_CND_ITEM_PIC_EQ:
- if (_inventory[ARG(1) - 1].picture != ARG(2))
+ if (_state.items[ARG(1) - 1].picture != ARG(2))
return false;
offset += 3;
break;
@@ -409,12 +406,12 @@ void AdlEngine::drawItems() {
uint dropped = 0;
- for (item = _inventory.begin(); item != _inventory.end(); ++item) {
- if (item->room != _room)
+ for (item = _state.items.begin(); item != _state.items.end(); ++item) {
+ if (item->room != _state.room)
continue;
if (item->state == IDI_ITEM_MOVED) {
- if (_rooms[_room].picture == _rooms[_room].curPicture) {
+ if (_state.rooms[_state.room].picture == _state.rooms[_state.room].curPicture) {
const Common::Point &p = _itemOffsets[dropped];
if (item->isLineArt)
_display->drawLineArt(_lineArt[item->picture - 1], p);
@@ -428,7 +425,7 @@ void AdlEngine::drawItems() {
Common::Array<byte>::const_iterator pic;
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == _rooms[_room].curPicture) {
+ if (*pic == _state.rooms[_state.room].curPicture) {
if (item->isLineArt)
_display->drawLineArt(_lineArt[item->picture - 1], item->position);
else
@@ -440,13 +437,13 @@ void AdlEngine::drawItems() {
}
void AdlEngine::showRoom() {
- if (!_isDark) {
- drawPic(_rooms[_room].curPicture);
+ if (!_state.isDark) {
+ drawPic(_state.rooms[_state.room].curPicture);
drawItems();
}
_display->decodeFrameBuffer();
- printMessage(_rooms[_room].description, false);
+ printMessage(_state.rooms[_state.room].description, false);
}
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 5335211..d39e0e3 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -73,7 +73,7 @@ enum EngineString {
// Conditional opcodes
#define IDO_CND_ITEM_IN_ROOM 0x03
-#define IDO_CND_STEPS_GE 0x05
+#define IDO_CND_MOVES_GE 0x05
#define IDO_CND_VAR_EQ 0x06
#define IDO_CND_CUR_PIC_EQ 0x09
#define IDO_CND_ITEM_PIC_EQ 0x0a
@@ -145,6 +145,18 @@ struct Item {
Common::Array<byte> roomPictures;
};
+struct State {
+ Common::Array<Room> rooms;
+ Common::Array<Item> items;
+ Common::Array<byte> vars;
+
+ byte room;
+ uint16 moves;
+ bool isDark;
+
+ State() : room(1), moves(0), isDark(false) { }
+};
+
typedef Common::List<Command> Commands;
class AdlEngine : public Engine {
@@ -186,18 +198,13 @@ protected:
Common::Array<Common::String> _strings;
Common::Array<Common::String> _messages;
Common::Array<Picture> _pictures;
- Common::Array<Item> _inventory;
Common::Array<Common::Point> _itemOffsets;
Common::Array<Common::Array<byte> > _lineArt;
Commands _roomCommands;
Commands _globalCommands;
// Game state
- Common::Array<Room> _rooms;
- byte _room;
- uint16 _steps;
- Common::Array<byte> _variables;
- bool _isDark;
+ State _state;
private:
void printEngineMessage(EngineMessage);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 9163875..1316bf2 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -84,7 +84,6 @@ static const StringOffset stringOffsets[] = {
HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine(syst, gd) {
- _variables.resize(20);
}
void HiRes1Engine::runIntro() {
@@ -217,47 +216,38 @@ void HiRes1Engine::drawPic(byte pic, Common::Point pos) {
drawPic(f, pos);
}
-void HiRes1Engine::runGame() {
- runIntro();
- _display->printASCIIString("\r");
-
+void HiRes1Engine::initState() {
Common::File f;
- if (!f.open("MESSAGES"))
- error("Failed to open file");
+ _state.room = 1;
+ _state.moves = 0;
+ _state.isDark = false;
- while (!f.eos() && !f.err())
- _messages.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
-
- f.close();
+ _state.vars.clear();
+ _state.vars.resize(20);
if (!f.open("ADVENTURE"))
error("Failed to open file");
- // Load strings from executable
- _strings.resize(IDI_HR1_STR_TOTAL);
- for (uint idx = 0; idx < IDI_HR1_STR_TOTAL; ++idx) {
- f.seek(stringOffsets[idx].offset);
- _strings[stringOffsets[idx].stringIdx] = readString(f);
- }
-
// Load room data from executable
+ _state.rooms.clear();
f.seek(1280);
for (uint i = 0; i < MH_ROOMS; ++i) {
- struct Room room;
+ Room room;
f.readByte();
room.description = f.readByte();
for (uint j = 0; j < 6; ++j)
room.connections[j] = f.readByte();
room.picture = f.readByte();
room.curPicture = f.readByte();
- _rooms.push_back(room);
+ _state.rooms.push_back(room);
}
// Load inventory data from executable
+ _state.items.clear();
f.seek(0x100);
while (f.readByte() != 0xff) {
- struct Item item;
+ Item item;
item.noun = f.readByte();
item.room = f.readByte();
item.picture = f.readByte();
@@ -274,7 +264,34 @@ void HiRes1Engine::runGame() {
for (uint i = 0; i < size; ++i)
item.roomPictures.push_back(f.readByte());
- _inventory.push_back(item);
+ _state.items.push_back(item);
+ }
+}
+
+void HiRes1Engine::runGame() {
+ runIntro();
+ _display->printASCIIString("\r");
+
+ Common::File f;
+
+ if (!f.open("MESSAGES"))
+ error("Failed to open file");
+
+ while (!f.eos() && !f.err())
+ _messages.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
+
+ f.close();
+
+ initState();
+
+ if (!f.open("ADVENTURE"))
+ error("Failed to open file");
+
+ // Load strings from executable
+ _strings.resize(IDI_HR1_STR_TOTAL);
+ for (uint idx = 0; idx < IDI_HR1_STR_TOTAL; ++idx) {
+ f.seek(stringOffsets[idx].offset);
+ _strings[stringOffsets[idx].stringIdx] = readString(f);
}
// Load picture data from executable
@@ -341,7 +358,7 @@ void HiRes1Engine::runGame() {
printMessage(37);
doAllCommands(_globalCommands, verb, noun);
- _steps++;
+ _state.moves++;
if (shouldQuit())
return;
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 4bd0a87..5cc9f3a 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -52,6 +52,7 @@ private:
void printMessage(uint idx, bool wait = true);
uint getEngineMessage(EngineMessage msg);
+ void initState();
void runIntro();
void drawPic(Common::ReadStream &stream, Common::Point pos);
void drawItems();
Commit: 301b2fdc219ecc92cc81cc94d8e2904fc21cec6e
https://github.com/scummvm/scummvm/commit/301b2fdc219ecc92cc81cc94d8e2904fc21cec6e
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Remove leftover debug code
Changed paths:
engines/adl/display.cpp
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 8ea0a7b..05e7c2e 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -82,29 +82,6 @@ Display::Display() :
_textBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
createFont();
-
- struct PixelPos rel = getPixelPos(0, 191);
- struct PixelPos absy;
- for (int i = 191; i >= 0; --i) {
- absy = getPixelPos(0, i);
- if (absy.rowAddr != rel.rowAddr)
- debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr);
- moveY(rel, false);
- }
- absy = getPixelPos(0, 191);
- if (absy.rowAddr != rel.rowAddr)
- debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr);
-
- rel = getPixelPos(0, 0);
- for (int i = 0; i < 192; ++i) {
- absy = getPixelPos(0, i);
- if (absy.rowAddr != rel.rowAddr)
- debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr);
- moveY(rel, true);
- }
- absy = getPixelPos(0, 0);
- if (absy.rowAddr != rel.rowAddr)
- debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr);
}
Display::~Display() {
Commit: 727469d4a7ad9ba516538009efdac3834a6daccd
https://github.com/scummvm/scummvm/commit/727469d4a7ad9ba516538009efdac3834a6daccd
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add restarting
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index e395c82..24a18d6 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -43,7 +43,8 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
_display(nullptr),
- _parser(nullptr) {
+ _parser(nullptr),
+ _isRestarting(false) {
}
AdlEngine::~AdlEngine() {
@@ -271,7 +272,8 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
Common::String input = _display->inputString();
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
- warning("Restart game not implemented");
+ _isRestarting = true;
+ restartGame();
return;
}
// Fall-through
@@ -392,8 +394,11 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
- for (cmd = commands.begin(); cmd != commands.end(); ++cmd)
+ for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
checkCommand(*cmd, verb, noun);
+ if (_isRestarting)
+ return;
+ }
}
void AdlEngine::clearScreen() {
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index d39e0e3..8b0aa45 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -175,6 +175,8 @@ public:
protected:
virtual void runGame() = 0;
+ virtual void initState() = 0;
+ virtual void restartGame() = 0;
virtual uint getEngineMessage(EngineMessage msg) = 0;
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
@@ -194,6 +196,7 @@ protected:
Display *_display;
Parser *_parser;
+ bool _isRestarting;
Common::Array<Common::String> _strings;
Common::Array<Common::String> _messages;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 1316bf2..4cf7b45 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -56,6 +56,7 @@ enum {
IDI_HR1_STR_DONT_HAVE_IT,
IDI_HR1_STR_DONT_UNDERSTAND,
IDI_HR1_STR_GETTING_DARK,
+ IDI_HR1_STR_PRESS_RETURN,
IDI_HR1_STR_TOTAL
};
@@ -69,7 +70,8 @@ static const StringOffset stringOffsets[] = {
{ IDI_HR1_STR_CANT_GO_THERE, 0x6c0a },
{ IDI_HR1_STR_DONT_HAVE_IT, 0x6c31 },
{ IDI_HR1_STR_DONT_UNDERSTAND, 0x6c51 },
- { IDI_HR1_STR_GETTING_DARK, 0x6c7c }
+ { IDI_HR1_STR_GETTING_DARK, 0x6c7c },
+ { IDI_HR1_STR_PRESS_RETURN, 0x5f68 }
};
#define IDI_HR1_OFS_PD_TEXT_0 0x5d
@@ -268,6 +270,13 @@ void HiRes1Engine::initState() {
}
}
+void HiRes1Engine::restartGame() {
+ initState();
+ _display->printString(_strings[IDI_HR1_STR_PRESS_RETURN]);
+ _display->inputString(); // Missing in the original
+ _display->printASCIIString("\r\r\r\r\r");
+}
+
void HiRes1Engine::runGame() {
runIntro();
_display->printASCIIString("\r");
@@ -348,7 +357,12 @@ void HiRes1Engine::runGame() {
f.seek(0xf00);
_parser->loadNouns(f);
+ _display->printASCIIString("\r\r\r\r\r");
+
while (1) {
+ if (_isRestarting)
+ _isRestarting = false;
+
uint verb = 0, noun = 0;
clearScreen();
showRoom();
@@ -356,8 +370,15 @@ void HiRes1Engine::runGame() {
if (!doOneCommand(_roomCommands, verb, noun))
printMessage(37);
+
+ if (_isRestarting)
+ continue;
+
doAllCommands(_globalCommands, verb, noun);
+ if (_isRestarting)
+ continue;
+
_state.moves++;
if (shouldQuit())
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 5cc9f3a..a378dc9 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -49,6 +49,7 @@ private:
MH_ITEM_OFFSETS = 21
};
+ void restartGame();
void printMessage(uint idx, bool wait = true);
uint getEngineMessage(EngineMessage msg);
Commit: e3d13d06ee32fa1cb3663c0e9c46f356f08b5c9b
https://github.com/scummvm/scummvm/commit/e3d13d06ee32fa1cb3663c0e9c46f356f08b5c9b
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add save game support
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 24a18d6..9c86b3a 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -28,6 +28,7 @@
#include "common/system.h"
#include "common/events.h"
#include "common/stream.h"
+#include "common/savefile.h"
#include "engines/util.h"
@@ -261,18 +262,21 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case IDO_ACT_SAVE:
- warning("Save game not implemented");
+ saveState(0);
++offset;
break;
case IDO_ACT_LOAD:
- warning("Load game not implemented");
+ loadState(0);
++offset;
+ // Original engine continues processing here (?)
break;
case IDO_ACT_RESTART: {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
Common::String input = _display->inputString();
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
_isRestarting = true;
+ _display->clear(0x00);
+ _display->decodeFrameBuffer();
restartGame();
return;
}
@@ -451,6 +455,116 @@ void AdlEngine::showRoom() {
printMessage(_state.rooms[_state.room].description, false);
}
+bool AdlEngine::saveState(uint slot) {
+ Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
+ Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName);
+
+ if (!outFile) {
+ warning("Failed to open file '%s'", fileName.c_str());
+ return false;
+ }
+
+ outFile->writeUint32BE(getTag());
+ outFile->writeByte(SAVEGAME_VERSION);
+
+ outFile->writeByte(_state.room);
+ outFile->writeByte(_state.moves);
+ outFile->writeByte(_state.isDark);
+
+ outFile->writeUint32BE(_state.rooms.size());
+ for (uint i = 0; i < _state.rooms.size(); ++i) {
+ outFile->writeByte(_state.rooms[i].picture);
+ outFile->writeByte(_state.rooms[i].curPicture);
+ }
+
+ outFile->writeUint32BE(_state.items.size());
+ for (uint i = 0; i < _state.items.size(); ++i) {
+ outFile->writeByte(_state.items[i].room);
+ outFile->writeByte(_state.items[i].picture);
+ outFile->writeByte(_state.items[i].position.x);
+ outFile->writeByte(_state.items[i].position.y);
+ outFile->writeByte(_state.items[i].state);
+ }
+
+ outFile->writeUint32BE(_state.vars.size());
+ for (uint i = 0; i < _state.vars.size(); ++i)
+ outFile->writeByte(_state.vars[i]);
+
+ outFile->finalize();
+
+ if (outFile->err()) {
+ delete outFile;
+ warning("Failed to save game '%s'", fileName.c_str());
+ return false;
+ }
+
+ delete outFile;
+ return true;
+}
+
+bool AdlEngine::loadState(uint slot) {
+ Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
+ Common::InSaveFile *inFile = getSaveFileManager()->openForLoading(fileName);
+
+ if (!inFile) {
+ warning("Failed to open file '%s'", fileName.c_str());
+ return false;
+ }
+
+ if (inFile->readUint32BE() != getTag()) {
+ warning("No header found in '%s'", fileName.c_str());
+ delete inFile;
+ return false;
+ }
+
+ byte saveVersion = inFile->readByte();
+ if (saveVersion != SAVEGAME_VERSION) {
+ warning("Save game version %i not supported", saveVersion);
+ delete inFile;
+ return false;
+ }
+
+ initState();
+
+ _state.room = inFile->readByte();
+ _state.moves = inFile->readByte();
+ _state.isDark = inFile->readByte();
+
+ uint32 size = inFile->readUint32BE();
+ if (size != _state.rooms.size())
+ error("Room count mismatch (expected %i; found %i)", _state.rooms.size(), size);
+
+ for (uint i = 0; i < size; ++i) {
+ _state.rooms[i].picture = inFile->readByte();
+ _state.rooms[i].curPicture = inFile->readByte();
+ }
+
+ size = inFile->readUint32BE();
+ if (size != _state.items.size())
+ error("Item count mismatch (expected %i; found %i)", _state.items.size(), size);
+
+ for (uint i = 0; i < size; ++i) {
+ _state.items[i].room = inFile->readByte();
+ _state.items[i].picture = inFile->readByte();
+ _state.items[i].position.x = inFile->readByte();
+ _state.items[i].position.y = inFile->readByte();
+ _state.items[i].state = inFile->readByte();
+ }
+
+ size = inFile->readUint32BE();
+ if (size != _state.vars.size())
+ error("Variable count mismatch (expected %i; found %i)", _state.vars.size(), size);
+
+ for (uint i = 0; i < size; ++i)
+ _state.vars[i] = inFile->readByte();
+
+ if (inFile->err() || inFile->eos())
+ error("Failed to load game '%s'", fileName.c_str());
+
+ delete inFile;
+ return true;
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 8b0aa45..abb62ee 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -37,6 +37,8 @@ class SeekableReadStream;
namespace Adl {
+#define SAVEGAME_VERSION 0
+
class Display;
class Parser;
class Console;
@@ -178,6 +180,7 @@ protected:
virtual void initState() = 0;
virtual void restartGame() = 0;
virtual uint getEngineMessage(EngineMessage msg) = 0;
+ virtual uint32 getTag() = 0;
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
virtual void printMessage(uint idx, bool wait = true);
@@ -211,6 +214,9 @@ protected:
private:
void printEngineMessage(EngineMessage);
+ bool saveState(uint slot);
+ bool loadState(uint slot);
+ Common::String getTargetName() { return _targetName; }
};
AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd);
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index a378dc9..ab26b2c 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -52,6 +52,7 @@ private:
void restartGame();
void printMessage(uint idx, bool wait = true);
uint getEngineMessage(EngineMessage msg);
+ uint32 getTag() { return MKTAG('H', 'R', 'A', '1'); }
void initState();
void runIntro();
Commit: e1fb5853576d8b0c05710ad70e22e10254467153
https://github.com/scummvm/scummvm/commit/e1fb5853576d8b0c05710ad70e22e10254467153
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Use #define instead of literal
Changed paths:
engines/adl/adl.cpp
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 9c86b3a..711e538 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -306,7 +306,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
case IDO_ACT_GO_WEST:
case IDO_ACT_GO_UP:
case IDO_ACT_GO_DOWN: {
- byte room = _state.rooms[_state.room].connections[ARG(0) - 0x15];
+ byte room = _state.rooms[_state.room].connections[ARG(0) - IDO_ACT_GO_NORTH];
if (room == 0) {
printEngineMessage(IDI_MSG_CANT_GO_THERE);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 4cf7b45..dac6d4c 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -155,9 +155,9 @@ void HiRes1Engine::runIntro() {
_display->setMode(Display::kModeText);
file.seek(IDI_HR1_OFS_INTRO_TEXT);
- const int pages[] = { 6, 6, 4, 5, 8, 7, 0 };
+ const uint pages[] = { 6, 6, 4, 5, 8, 7, 0 };
- int page = 0;
+ uint page = 0;
while (pages[page] != 0) {
_display->home();
printStrings(file, pages[page++]);
Commit: 475eb0cc95c46be651d15de8eb1c0f42a2921c6a
https://github.com/scummvm/scummvm/commit/475eb0cc95c46be651d15de8eb1c0f42a2921c6a
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix bug in item taking
Changed paths:
engines/adl/adl.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 711e538..1847f7f 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -178,7 +178,7 @@ void AdlEngine::takeItem(byte noun) {
}
Common::Array<byte>::const_iterator pic;
- for (pic = item->roomPictures.begin(); item->roomPictures.end(); ++pic) {
+ for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
if (*pic == _state.rooms[_state.room].curPicture) {
item->room = IDI_NONE;
item->state = IDI_ITEM_MOVED;
Commit: 9928e51bd73985f48c8378308a278fff433eaae1
https://github.com/scummvm/scummvm/commit/9928e51bd73985f48c8378308a278fff433eaae1
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add functions to adjust for 1-based arrays
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 1847f7f..be90678 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -179,7 +179,7 @@ void AdlEngine::takeItem(byte noun) {
Common::Array<byte>::const_iterator pic;
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == _state.rooms[_state.room].curPicture) {
+ if (*pic == curRoom().curPicture) {
item->room = IDI_NONE;
item->state = IDI_ITEM_MOVED;
return;
@@ -211,15 +211,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
switch (ARG(0)) {
case IDO_ACT_VAR_ADD:
- _state.vars[ARG(2)] += ARG(1);
+ var(ARG(2)) += ARG(1);
offset += 3;
break;
case IDO_ACT_VAR_SUB:
- _state.vars[ARG(2)] -= ARG(1);
+ var(ARG(2)) -= ARG(1);
offset += 3;
break;
case IDO_ACT_VAR_SET:
- _state.vars[ARG(1)] = ARG(2);
+ var(ARG(1)) = ARG(2);
offset += 3;
break;
case IDO_ACT_LIST_ITEMS: {
@@ -233,20 +233,20 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
}
case IDO_ACT_MOVE_ITEM:
- _state.items[ARG(1) - 1].room = ARG(2);
+ item(ARG(1)).room = ARG(2);
offset += 3;
break;
case IDO_ACT_SET_ROOM:
- _state.rooms[_state.room].curPicture = _state.rooms[_state.room].picture;
+ curRoom().curPicture = curRoom().picture;
_state.room = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_CUR_PIC:
- _state.rooms[_state.room].curPicture = ARG(1);
+ curRoom().curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_PIC:
- _state.rooms[_state.room].picture = _state.rooms[_state.room].curPicture = ARG(1);
+ curRoom().picture = curRoom().curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_PRINT_MSG:
@@ -287,17 +287,17 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
quitGame();
return;
case IDO_ACT_PLACE_ITEM:
- _state.items[ARG(1) - 1].room = ARG(2);
- _state.items[ARG(1) - 1].position.x = ARG(3);
- _state.items[ARG(1) - 1].position.y = ARG(4);
+ item(ARG(1)).room = ARG(2);
+ item(ARG(1)).position.x = ARG(3);
+ item(ARG(1)).position.y = ARG(4);
offset += 5;
break;
case IDO_ACT_SET_ITEM_PIC:
- _state.items[ARG(2) - 1].picture = ARG(1);
+ item(ARG(2)).picture = ARG(1);
offset += 3;
break;
case IDO_ACT_RESET_PIC:
- _state.rooms[_state.room].curPicture = _state.rooms[_state.room].picture;
+ curRoom().curPicture = curRoom().picture;
++offset;
break;
case IDO_ACT_GO_NORTH:
@@ -306,14 +306,14 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
case IDO_ACT_GO_WEST:
case IDO_ACT_GO_UP:
case IDO_ACT_GO_DOWN: {
- byte room = _state.rooms[_state.room].connections[ARG(0) - IDO_ACT_GO_NORTH];
+ byte room = curRoom().connections[ARG(0) - IDO_ACT_GO_NORTH];
if (room == 0) {
printEngineMessage(IDI_MSG_CANT_GO_THERE);
return;
}
- _state.rooms[_state.room].curPicture = _state.rooms[_state.room].picture;
+ curRoom().curPicture = curRoom().picture;
_state.room = room;
return;
}
@@ -326,7 +326,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case IDO_ACT_SET_ROOM_PIC:
- _state.rooms[ARG(1)].picture = _state.rooms[ARG(1)].curPicture = ARG(2);
+ room(ARG(1)).picture = room(ARG(1)).curPicture = ARG(2);
offset += 3;
break;
default:
@@ -347,9 +347,9 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
uint offset = 0;
for (uint i = 0; i < command.numCond; ++i) {
- switch (command.script[offset]) {
+ switch (ARG(0)) {
case IDO_CND_ITEM_IN_ROOM:
- if (_state.items[ARG(1) - 1].room != ARG(2))
+ if (item(ARG(1)).room != ARG(2))
return false;
offset += 3;
break;
@@ -359,17 +359,17 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
offset += 2;
break;
case IDO_CND_VAR_EQ:
- if (_state.vars[ARG(1)] != ARG(2))
+ if (var(ARG(1)) != ARG(2))
return false;
offset += 3;
break;
case IDO_CND_CUR_PIC_EQ:
- if (_state.rooms[_state.room].curPicture != ARG(1))
+ if (curRoom().curPicture != ARG(1))
return false;
offset += 2;
break;
case IDO_CND_ITEM_PIC_EQ:
- if (_state.items[ARG(1) - 1].picture != ARG(2))
+ if (item(ARG(1)).picture != ARG(2))
return false;
offset += 3;
break;
@@ -420,7 +420,7 @@ void AdlEngine::drawItems() {
continue;
if (item->state == IDI_ITEM_MOVED) {
- if (_state.rooms[_state.room].picture == _state.rooms[_state.room].curPicture) {
+ if (curRoom().picture == curRoom().curPicture) {
const Common::Point &p = _itemOffsets[dropped];
if (item->isLineArt)
_display->drawLineArt(_lineArt[item->picture - 1], p);
@@ -434,7 +434,7 @@ void AdlEngine::drawItems() {
Common::Array<byte>::const_iterator pic;
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == _state.rooms[_state.room].curPicture) {
+ if (*pic == curRoom().curPicture) {
if (item->isLineArt)
_display->drawLineArt(_lineArt[item->picture - 1], item->position);
else
@@ -447,12 +447,12 @@ void AdlEngine::drawItems() {
void AdlEngine::showRoom() {
if (!_state.isDark) {
- drawPic(_state.rooms[_state.room].curPicture);
+ drawPic(curRoom().curPicture);
drawItems();
}
_display->decodeFrameBuffer();
- printMessage(_state.rooms[_state.room].description, false);
+ printMessage(curRoom().description, false);
}
bool AdlEngine::saveState(uint slot) {
@@ -565,6 +565,31 @@ bool AdlEngine::loadState(uint slot) {
return true;
}
+Room &AdlEngine::room(uint i) {
+ if (i < 1 || i > _state.rooms.size())
+ error("Room %i out of range [1, %i]", i, _state.rooms.size());
+
+ return _state.rooms[i - 1];
+}
+
+Room &AdlEngine::curRoom() {
+ return room(_state.room);
+}
+
+Item &AdlEngine::item(uint i) {
+ if (i < 1 || i > _state.items.size())
+ error("Item %i out of range [1, %i]", i, _state.items.size());
+
+ return _state.items[i - 1];
+}
+
+byte &AdlEngine::var(uint i) {
+ if (i >= _state.vars.size())
+ error("Variable %i out of range [0, %i]", i, _state.vars.size() - 1);
+
+ return _state.vars[i];
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index abb62ee..b7fd3dc 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -196,6 +196,10 @@ protected:
void showRoom();
void takeItem(byte noun);
void dropItem(byte noun);
+ Room &room(uint i);
+ Room &curRoom();
+ Item &item(uint i);
+ byte &var(uint i);
Display *_display;
Parser *_parser;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index dac6d4c..45a011a 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -233,7 +233,7 @@ void HiRes1Engine::initState() {
// Load room data from executable
_state.rooms.clear();
- f.seek(1280);
+ f.seek(0x50a);
for (uint i = 0; i < MH_ROOMS; ++i) {
Room room;
f.readByte();
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index ab26b2c..247625c 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -44,7 +44,7 @@ protected:
private:
enum {
- MH_ROOMS = 42,
+ MH_ROOMS = 41,
MH_PICS = 98,
MH_ITEM_OFFSETS = 21
};
Commit: ba54955bffec15ed95aa1ca1ec955aecaa315478
https://github.com/scummvm/scummvm/commit/ba54955bffec15ed95aa1ca1ec955aecaa315478
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add loading from launcher
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/detection.cpp
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index be90678..ab05c40 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -70,6 +70,16 @@ Common::Error AdlEngine::run() {
_display = new Display();
_parser = new Parser(*this, *_display);
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0) {
+ if (!loadState(saveSlot))
+ error("Failed to load save game from slot %i", saveSlot);
+ _display->setCursorPos(Common::Point(0, 23));
+ } else {
+ runIntro();
+ initState();
+ }
+
runGame();
return Common::kNoError;
@@ -455,7 +465,7 @@ void AdlEngine::showRoom() {
printMessage(curRoom().description, false);
}
-bool AdlEngine::saveState(uint slot) {
+bool AdlEngine::saveState(uint slot, const Common::String *description) {
Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName);
@@ -464,9 +474,21 @@ bool AdlEngine::saveState(uint slot) {
return false;
}
- outFile->writeUint32BE(getTag());
+ outFile->writeUint32BE(MKTAG('A', 'D', 'L', ':'));
outFile->writeByte(SAVEGAME_VERSION);
+ char name[SAVEGAME_NAME_LEN] = { };
+
+ if (description)
+ strncpy(name, description->c_str(), sizeof(name) - 1);
+ else {
+ Common::String defaultName("Save ");
+ defaultName += 'A' + slot;
+ strncpy(name, defaultName.c_str(), sizeof(name) - 1);
+ }
+
+ outFile->write(name, sizeof(name));
+
outFile->writeByte(_state.room);
outFile->writeByte(_state.moves);
outFile->writeByte(_state.isDark);
@@ -511,7 +533,7 @@ bool AdlEngine::loadState(uint slot) {
return false;
}
- if (inFile->readUint32BE() != getTag()) {
+ if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
warning("No header found in '%s'", fileName.c_str());
delete inFile;
return false;
@@ -526,6 +548,8 @@ bool AdlEngine::loadState(uint slot) {
initState();
+ inFile->seek(SAVEGAME_NAME_LEN, SEEK_CUR);
+
_state.room = inFile->readByte();
_state.moves = inFile->readByte();
_state.isDark = inFile->readByte();
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index b7fd3dc..9955b0d 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -38,6 +38,7 @@ class SeekableReadStream;
namespace Adl {
#define SAVEGAME_VERSION 0
+#define SAVEGAME_NAME_LEN 32
class Display;
class Parser;
@@ -176,11 +177,11 @@ public:
virtual Common::String getEngineString(int str);
protected:
+ virtual void runIntro() { }
virtual void runGame() = 0;
virtual void initState() = 0;
virtual void restartGame() = 0;
virtual uint getEngineMessage(EngineMessage msg) = 0;
- virtual uint32 getTag() = 0;
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
virtual void printMessage(uint idx, bool wait = true);
@@ -218,7 +219,7 @@ protected:
private:
void printEngineMessage(EngineMessage);
- bool saveState(uint slot);
+ bool saveState(uint slot, const Common::String *description = nullptr);
bool loadState(uint slot);
Common::String getTargetName() { return _targetName; }
};
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 9fadb9d..5fe469d 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -20,6 +20,9 @@
*
*/
+#include "common/system.h"
+#include "common/savefile.h"
+
#include "engines/advancedDetector.h"
#include "adl/adl.h"
@@ -69,9 +72,63 @@ public:
return "Copyright (C) Sierra On-Line";
}
+ bool hasFeature(MetaEngineFeature f) const;
+ int getMaximumSaveSlot() const { return 15; }
+ SaveStateList listSaves(const char *target) const;
+
bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
};
+bool AdlMetaEngine::hasFeature(MetaEngineFeature f) const {
+ switch(f) {
+ case kSupportsListSaves:
+ case kSupportsLoadingDuringStartup:
+ return true;
+ default:
+ return false;
+ }
+}
+
+SaveStateList AdlMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray files = saveFileMan->listSavefiles(Common::String(target) + ".s##");
+
+ SaveStateList saveList;
+ for (uint i = 0; i < files.size(); ++i) {
+ const Common::String &fileName = files[i];
+ Common::InSaveFile *inFile = saveFileMan->openForLoading(fileName);
+ if (!inFile) {
+ warning("Cannot open save file %s", fileName.c_str());
+ continue;
+ }
+
+ if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
+ warning("No header found in '%s'", fileName.c_str());
+ delete inFile;
+ continue;
+ }
+
+ byte saveVersion = inFile->readByte();
+ if (saveVersion != SAVEGAME_VERSION) {
+ warning("Save game version %i not supported in '%s'", saveVersion, fileName.c_str());
+ delete inFile;
+ continue;
+ }
+
+ char name[SAVEGAME_NAME_LEN] = { };
+ inFile->read(name, sizeof(name) - 1);
+ delete inFile;
+
+ int slotNum = atoi(fileName.c_str() + fileName.size() - 2);
+ SaveStateDescriptor sd(slotNum, name);
+ saveList.push_back(sd);
+ }
+
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+ return saveList;
+}
+
bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
if (gd)
*engine = AdlEngine::create(((const AdlGameDescription *)gd)->gameType, syst, (const AdlGameDescription *)gd);
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 05e7c2e..ffb98c4 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -585,4 +585,8 @@ void Display::home() {
_cursorPos = 0;
}
+void Display::setCursorPos(Common::Point pos) {
+ _cursorPos = pos.y * 40 + pos.x;
+}
+
} // End of namespace Adl
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 229446f..91d8b0e 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -64,6 +64,7 @@ public:
void drawLine(Common::Point p1, Common::Point p2, byte color);
void clear(byte color);
void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f);
+ void setCursorPos(Common::Point pos);
private:
enum {
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 45a011a..ba6f19a 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -136,6 +136,8 @@ void HiRes1Engine::runIntro() {
file.seek(IDI_HR1_OFS_GAME_OR_HELP);
str = readString(file);
+ bool instructions = false;
+
while (1) {
_display->printString(str);
Common::String s = _display->inputString();
@@ -146,28 +148,47 @@ void HiRes1Engine::runIntro() {
if (s.empty())
continue;
- if ((byte)s[0] == ('I' | 0x80))
+ if (s[0] == APPLECHAR('I')) {
+ instructions = true;
break;
- else if ((byte)s[0] == ('G' | 0x80))
- return;
+ } else if (s[0] == APPLECHAR('G')) {
+ break;
+ }
};
- _display->setMode(Display::kModeText);
- file.seek(IDI_HR1_OFS_INTRO_TEXT);
+ if (instructions) {
+ _display->setMode(Display::kModeText);
+ file.seek(IDI_HR1_OFS_INTRO_TEXT);
- const uint pages[] = { 6, 6, 4, 5, 8, 7, 0 };
+ const uint pages[] = { 6, 6, 4, 5, 8, 7, 0 };
- uint page = 0;
- while (pages[page] != 0) {
- _display->home();
- printStrings(file, pages[page++]);
- _display->inputString();
+ uint page = 0;
+ while (pages[page] != 0) {
+ _display->home();
+ printStrings(file, pages[page++]);
+ _display->inputString();
- if (g_engine->shouldQuit())
- return;
+ if (g_engine->shouldQuit())
+ return;
- file.seek(9, SEEK_CUR);
+ file.seek(9, SEEK_CUR);
+ }
}
+
+ _display->printASCIIString("\r");
+
+ file.close();
+
+ _display->setMode(Display::kModeMixed);
+
+ if (!file.open("ADVENTURE"))
+ error("Failed to open file");
+
+ // Title screen shown during loading
+ file.seek(0x1800);
+ _display->loadFrameBuffer(file);
+ _display->decodeFrameBuffer();
+ _display->delay(2000);
}
void HiRes1Engine::drawPic(Common::ReadStream &stream, Common::Point pos) {
@@ -278,8 +299,7 @@ void HiRes1Engine::restartGame() {
}
void HiRes1Engine::runGame() {
- runIntro();
- _display->printASCIIString("\r");
+ _display->setMode(Display::kModeMixed);
Common::File f;
@@ -291,8 +311,6 @@ void HiRes1Engine::runGame() {
f.close();
- initState();
-
if (!f.open("ADVENTURE"))
error("Failed to open file");
@@ -345,12 +363,6 @@ void HiRes1Engine::runGame() {
_lineArt.push_back(lineArt);
}
- // Title screen shown during loading
- f.seek(0x1800);
- _display->loadFrameBuffer(f);
- _display->decodeFrameBuffer();
- _display->delay(2000);
-
f.seek(0x3800);
_parser->loadVerbs(f);
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 247625c..897327c 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -52,7 +52,6 @@ private:
void restartGame();
void printMessage(uint idx, bool wait = true);
uint getEngineMessage(EngineMessage msg);
- uint32 getTag() { return MKTAG('H', 'R', 'A', '1'); }
void initState();
void runIntro();
Commit: 339d3bc86813b454447b02481f82b85c4c8be75b
https://github.com/scummvm/scummvm/commit/339d3bc86813b454447b02481f82b85c4c8be75b
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move input code into AdlEngine
Changed paths:
R engines/adl/parser.cpp
R engines/adl/parser.h
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
engines/adl/module.mk
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index ab05c40..3c405b6 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -36,7 +36,6 @@
#include "adl/adl.h"
#include "adl/display.h"
-#include "adl/parser.h"
namespace Adl {
@@ -44,12 +43,10 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
_display(nullptr),
- _parser(nullptr),
_isRestarting(false) {
}
AdlEngine::~AdlEngine() {
- delete _parser;
delete _display;
}
@@ -68,7 +65,6 @@ Common::Error AdlEngine::run() {
g_system->getPaletteManager()->setPalette(palette, 0, 6);
_display = new Display();
- _parser = new Parser(*this, *_display);
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot >= 0) {
@@ -137,7 +133,7 @@ void AdlEngine::printMessage(uint idx, bool wait) {
_display->printString(msg);
if (wait)
- _display->delay(14 * 166018 / 1000);
+ delay(14 * 166018 / 1000);
}
void AdlEngine::printEngineMessage(EngineMessage msg) {
@@ -282,7 +278,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
case IDO_ACT_RESTART: {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
- Common::String input = _display->inputString();
+ Common::String input = inputString();
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
_isRestarting = true;
_display->clear(0x00);
@@ -614,6 +610,259 @@ byte &AdlEngine::var(uint i) {
return _state.vars[i];
}
+void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) {
+ uint index = 0;
+
+ while (1) {
+ ++index;
+
+ byte buf[kWordSize];
+
+ if (stream.read(buf, kWordSize) < kWordSize)
+ error("Error reading word list");
+
+ Common::String word((char *)buf, kWordSize);
+
+ if (!map.contains(word))
+ map[word] = index;
+
+ byte synonyms = stream.readByte();
+
+ if (stream.err() || stream.eos())
+ error("Error reading word list");
+
+ if (synonyms == 0xff)
+ break;
+
+ for (uint i = 0; i < synonyms; ++i) {
+ if (stream.read((char *)buf, kWordSize) < kWordSize)
+ error("Error reading word list");
+
+ word = Common::String((char *)buf, kWordSize);
+
+ if (!map.contains(word))
+ map[word] = index;
+ }
+ }
+}
+
+Common::String AdlEngine::getLine() {
+ // Original engine uses a global here, which isn't reset between
+ // calls and may not match actual mode
+ bool textMode = false;
+
+ while (1) {
+ Common::String line = inputString(APPLECHAR('?'));
+
+ if (shouldQuit())
+ return "";
+
+ if ((byte)line[0] == ('\r' | 0x80)) {
+ textMode = !textMode;
+ _display->setMode(textMode ? Display::kModeText : Display::kModeMixed);
+ continue;
+ }
+
+ // Remove the return
+ line.deleteLastChar();
+ return line;
+ }
+}
+
+Common::String AdlEngine::getWord(const Common::String &line, uint &index) {
+ Common::String str;
+
+ for (uint i = 0; i < 8; ++i)
+ str += APPLECHAR(' ');
+
+ int copied = 0;
+
+ // Skip initial whitespace
+ while (1) {
+ if (index == line.size())
+ return str;
+ if (line[index] != APPLECHAR(' '))
+ break;
+ ++index;
+ }
+
+ // Copy up to 8 characters
+ while (1) {
+ if (copied < 8)
+ str.setChar(line[index], copied++);
+
+ index++;
+
+ if (index == line.size() || line[index] == APPLECHAR(' '))
+ return str;
+ }
+}
+
+void AdlEngine::getInput(uint &verb, uint &noun) {
+ while (1) {
+ _display->printString(getEngineString(IDI_STR_ENTER_COMMAND));
+ Common::String line = getLine();
+
+ if (shouldQuit())
+ return;
+
+ uint index = 0;
+ Common::String verbStr = getWord(line, index);
+
+ if (!_verbs.contains(verbStr)) {
+ Common::String err = getEngineString(IDI_STR_VERB_ERROR);
+ for (uint i = 0; i < verbStr.size(); ++i)
+ err.setChar(verbStr[i], i + 19);
+ _display->printString(err);
+ continue;
+ }
+
+ verb = _verbs[verbStr];
+
+ Common::String nounStr = getWord(line, index);
+
+ if (!_nouns.contains(nounStr)) {
+ Common::String err = getEngineString(IDI_STR_NOUN_ERROR);
+ for (uint i = 0; i < verbStr.size(); ++i)
+ err.setChar(verbStr[i], i + 19);
+ for (uint i = 0; i < nounStr.size(); ++i)
+ err.setChar(nounStr[i], i + 30);
+ _display->printString(err);
+ continue;
+ }
+
+ noun = _nouns[nounStr];
+ return;
+ }
+}
+
+void AdlEngine::printASCIIString(const Common::String &str) {
+ Common::String aStr;
+
+ Common::String::const_iterator it;
+ for (it = str.begin(); it != str.end(); ++it)
+ aStr += APPLECHAR(*it);
+
+ _display->printString(aStr);
+}
+
+Common::String AdlEngine::inputString(byte prompt) {
+ Common::String s;
+
+ if (prompt > 0)
+ _display->printString(Common::String(prompt));
+
+ while (1) {
+ byte b = inputKey();
+
+ if (g_engine->shouldQuit())
+ return 0;
+
+ if (b == 0)
+ continue;
+
+ if (b == ('\r' | 0x80)) {
+ s += b;
+ _display->printString(Common::String(b));
+ return s;
+ }
+
+ if (b < 0xa0) {
+ switch (b) {
+ case Common::KEYCODE_BACKSPACE | 0x80:
+ if (!s.empty()) {
+ _display->moveCursorBackward();
+ _display->setCharAtCursor(APPLECHAR(' '));
+ s.deleteLastChar();
+ }
+ break;
+ };
+ } else {
+ s += b;
+ _display->printString(Common::String(b));
+ }
+ }
+}
+
+byte AdlEngine::convertKey(uint16 ascii) {
+ ascii = toupper(ascii);
+
+ if (ascii >= 0x80)
+ return 0;
+
+ ascii |= 0x80;
+
+ if (ascii >= 0x80 && ascii <= 0xe0)
+ return ascii;
+
+ return 0;
+}
+
+byte AdlEngine::inputKey() {
+ Common::EventManager *ev = g_system->getEventManager();
+
+ byte key = 0;
+
+ _display->showCursor(true);
+
+ while (!g_engine->shouldQuit() && key == 0) {
+ Common::Event event;
+ if (ev->pollEvent(event)) {
+ if (event.type != Common::EVENT_KEYDOWN)
+ continue;
+
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ if (event.kbd.keycode == Common::KEYCODE_q)
+ g_engine->quitGame();
+ continue;
+ }
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ case Common::KEYCODE_RETURN:
+ key = convertKey(event.kbd.keycode);
+ break;
+ default:
+ if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80)
+ key = convertKey(event.kbd.ascii);
+ };
+ }
+
+ _display->updateTextSurface();
+ _display->updateScreen();
+ g_system->updateScreen();
+ g_system->delayMillis(16);
+ }
+
+ _display->showCursor(false);
+
+ return key;
+}
+
+void AdlEngine::delay(uint32 ms) {
+ Common::EventManager *ev = g_system->getEventManager();
+
+ uint32 start = g_system->getMillis();
+
+ while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) {
+ Common::Event event;
+ if (ev->pollEvent(event)) {
+ if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) {
+ switch(event.kbd.keycode) {
+ case Common::KEYCODE_q:
+ g_engine->quitGame();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ _display->updateScreen();
+ g_system->updateScreen();
+ g_system->delayMillis(16);
+ }
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 9955b0d..a9ac79d 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -177,6 +177,8 @@ public:
virtual Common::String getEngineString(int str);
protected:
+ typedef Common::HashMap<Common::String, uint> WordMap;
+
virtual void runIntro() { }
virtual void runGame() = 0;
virtual void initState() = 0;
@@ -201,6 +203,16 @@ protected:
Room &curRoom();
Item &item(uint i);
byte &var(uint i);
+ void loadVerbs(Common::ReadStream &stream) { loadWords(stream, _verbs); }
+ void loadNouns(Common::ReadStream &stream) { loadWords(stream, _nouns); }
+ void getInput(uint &verb, uint &noun);
+ void loadWords(Common::ReadStream &stream, WordMap &map);
+ Common::String getLine();
+ Common::String getWord(const Common::String &line, uint &index);
+ void printASCIIString(const Common::String &str);
+ Common::String inputString(byte prompt = 0);
+ void delay(uint32 ms);
+ byte inputKey();
Display *_display;
Parser *_parser;
@@ -222,6 +234,14 @@ private:
bool saveState(uint slot, const Common::String *description = nullptr);
bool loadState(uint slot);
Common::String getTargetName() { return _targetName; }
+ byte convertKey(uint16 ascii);
+
+ enum {
+ kWordSize = 8
+ };
+
+ WordMap _verbs;
+ WordMap _nouns;
};
AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd);
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index ffb98c4..a6d94f6 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -71,7 +71,8 @@ static byte font[64][5] = {
Display::Display() :
_scanlines(false),
_cursorPos(0),
- _mode(kModeText) {
+ _mode(kModeText),
+ _showCursor(false) {
_frameBuf = new byte[kFrameBufSize];
_frameBufSurface = new Graphics::Surface;
_frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
@@ -367,8 +368,12 @@ void Display::clear(byte color) {
void Display::updateTextSurface() {
for (uint row = 0; row < 24; ++row)
for (uint col = 0; col < 40; ++col) {
+ int charPos = row * 40 + col;
char c = _textBuf[row * 40 + col];
+ if (charPos == _cursorPos && _showCursor)
+ c = (c & 0x3f) | 0x40;
+
Common::Rect r(7 * 2, 8 * 2);
r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
@@ -381,36 +386,6 @@ void Display::updateTextSurface() {
}
}
-void Display::printString(const Common::String &str) {
- Common::String::const_iterator it;
- for (it = str.begin(); it != str.end(); ++it) {
- byte b = *it;
-
- if (b == ('\r' | 0x80))
- _cursorPos = (_cursorPos / 40 + 1) * 40;
- else if (b < 0x80 || b >= 0xa0)
- _textBuf[_cursorPos++] = b;
-
- if (_cursorPos == kTextBufSize) {
- memmove(_textBuf, _textBuf + 40, kTextBufSize - 40);
- memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40);
- _cursorPos -= 40;
- }
- }
-
- updateTextSurface();
-}
-
-void Display::printASCIIString(const Common::String &str) {
- Common::String aStr;
-
- Common::String::const_iterator it;
- for (it = str.begin(); it != str.end(); ++it)
- aStr += APPLECHAR(*it);
-
- printString(aStr);
-}
-
void Display::drawChar(byte c, int x, int y) {
byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
@@ -463,126 +438,63 @@ void Display::updateScreen() {
}
}
-Common::String Display::inputString(byte prompt) {
- Common::String s;
-
- if (prompt > 0)
- printString(Common::String(prompt));
-
- while (1) {
- byte b = inputKey();
-
- if (g_engine->shouldQuit())
- return 0;
-
- if (b == 0)
- continue;
-
- if (b == ('\r' | 0x80)) {
- s += b;
- printString(Common::String(b));
- return s;
- }
-
- if (b < 0xa0) {
- switch (b) {
- case Common::KEYCODE_BACKSPACE | 0x80:
- if (!s.empty()) {
- --_cursorPos;
- _textBuf[_cursorPos] = ' ' | 0x80;
- s.deleteLastChar();
- }
- break;
- };
- } else {
- s += b;
- printString(Common::String(b));
- }
- }
+void Display::home() {
+ memset(_textBuf, APPLECHAR(' '), kTextBufSize);
+ _cursorPos = 0;
}
-byte Display::convertKey(uint16 ascii) {
- ascii = toupper(ascii);
-
- if (ascii >= 0x80)
- return 0;
+void Display::moveCursorForward() {
+ ++_cursorPos;
- ascii |= 0x80;
+ if (_cursorPos >= kTextBufSize)
+ scrollUp();
+}
- if (ascii >= 0x80 && ascii <= 0xe0)
- return ascii;
+void Display::moveCursorBackward() {
+ --_cursorPos;
- return 0;
+ if (_cursorPos < 0)
+ _cursorPos = 0;
}
-byte Display::inputKey() {
- Common::EventManager *ev = g_system->getEventManager();
+void Display::moveCursorTo(const Common::Point &pos) {
+ _cursorPos = pos.y * 40 + pos.x;
- byte orgChar = _textBuf[_cursorPos];
- _textBuf[_cursorPos] = (orgChar & 0x3f) | 0x40;
+ if (_cursorPos >= kTextBufSize)
+ error("Cursor position (%i, %i) out of bounds", pos.x, pos.y);
+}
- byte key = 0;
+void Display::setCharAtCursor(byte c) {
+ _textBuf[_cursorPos] = c;
+}
- while (!g_engine->shouldQuit() && key == 0) {
- Common::Event event;
- if (ev->pollEvent(event)) {
- if (event.type != Common::EVENT_KEYDOWN)
- continue;
+void Display::scrollUp() {
+ memmove(_textBuf, _textBuf + 40, kTextBufSize - 40);
+ memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40);
+ _cursorPos -= 40;
+}
- if (event.kbd.flags & Common::KBD_CTRL) {
- if (event.kbd.keycode == Common::KEYCODE_q)
- g_engine->quitGame();
- continue;
- }
+void Display::printString(const Common::String &str) {
+ Common::String::const_iterator c;
+ for (c = str.begin(); c != str.end(); ++c) {
+ byte b = *c;
- switch (event.kbd.keycode) {
- case Common::KEYCODE_BACKSPACE:
- case Common::KEYCODE_RETURN:
- key = convertKey(event.kbd.keycode);
- break;
- default:
- if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80)
- key = convertKey(event.kbd.ascii);
- };
+ if (*c == APPLECHAR('\r'))
+ _cursorPos = (_cursorPos / 40 + 1) * 40;
+ else if (b < 0x80 || b >= 0xa0) {
+ setCharAtCursor(b);
+ ++_cursorPos;
}
- updateTextSurface();
- updateScreen();
- g_system->updateScreen();
- g_system->delayMillis(16);
+ if (_cursorPos == kTextBufSize)
+ scrollUp();
}
- _textBuf[_cursorPos] = orgChar;
- return key;
-}
-
-void Display::delay(uint32 ms) {
- Common::EventManager *ev = g_system->getEventManager();
-
- uint32 start = g_system->getMillis();
-
- while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) {
- Common::Event event;
- if (ev->pollEvent(event)) {
- if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) {
- switch(event.kbd.keycode) {
- case Common::KEYCODE_q:
- g_engine->quitGame();
- break;
- default:
- break;
- }
- }
- }
- updateScreen();
- g_system->updateScreen();
- g_system->delayMillis(16);
- }
+ updateTextSurface();
}
-void Display::home() {
- memset(_textBuf, ' ' | 0x80, kTextBufSize);
- _cursorPos = 0;
+void Display::showCursor(bool enable) {
+ _showCursor = enable;
}
void Display::setCursorPos(Common::Point pos) {
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 91d8b0e..91ae447 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -52,20 +52,23 @@ public:
~Display();
void loadFrameBuffer(Common::ReadStream &stream);
void decodeFrameBuffer();
- void printString(const Common::String &str);
- void printASCIIString(const Common::String &str);
void updateScreen();
- Common::String inputString(byte prompt = 0);
- void delay(uint32 ms);
void setMode(Mode mode) { _mode = mode; }
- byte inputKey();
- void home();
void drawPixel(byte x, byte y, byte color);
void drawLine(Common::Point p1, Common::Point p2, byte color);
void clear(byte color);
void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f);
void setCursorPos(Common::Point pos);
+ void home();
+ void moveCursorTo(const Common::Point &pos);
+ void moveCursorForward();
+ void moveCursorBackward();
+ void printString(const Common::String &str);
+ void setCharAtCursor(byte c);
+ void showCursor(bool enable);
+ void updateTextSurface();
+
private:
enum {
kWidth = 280,
@@ -85,12 +88,12 @@ private:
byte getPixelColor(byte x, byte color);
void drawChar(byte c, int x, int y);
void createFont();
- void updateTextSurface();
- byte convertKey(uint16 ascii);
void moveX(PixelPos &p, byte &color, bool left);
void moveY(PixelPos &p, bool down);
void drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant);
+ void scrollUp();
+
bool _scanlines;
byte *_frameBuf;
byte *_textBuf;
@@ -99,6 +102,7 @@ private:
Graphics::Surface *_font;
int _cursorPos;
Mode _mode;
+ bool _showCursor;
};
} // End of namespace Adl
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index ba6f19a..5912166 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -37,7 +37,6 @@
#include "adl/hires1.h"
#include "adl/display.h"
-#include "adl/parser.h"
namespace Adl {
@@ -98,7 +97,7 @@ void HiRes1Engine::runIntro() {
_display->setMode(Display::kModeHires);
_display->loadFrameBuffer(file);
_display->decodeFrameBuffer();
- _display->delay(4000);
+ delay(4000);
if (shouldQuit())
return;
@@ -113,21 +112,21 @@ void HiRes1Engine::runIntro() {
basic.seek(IDI_HR1_OFS_PD_TEXT_0);
str = readString(basic, '"');
- _display->printASCIIString(str + '\r');
+ printASCIIString(str + '\r');
basic.seek(IDI_HR1_OFS_PD_TEXT_1);
str = readString(basic, '"');
- _display->printASCIIString(str + "\r\r");
+ printASCIIString(str + "\r\r");
basic.seek(IDI_HR1_OFS_PD_TEXT_2);
str = readString(basic, '"');
- _display->printASCIIString(str + "\r\r");
+ printASCIIString(str + "\r\r");
basic.seek(IDI_HR1_OFS_PD_TEXT_3);
str = readString(basic, '"');
- _display->printASCIIString(str + '\r');
+ printASCIIString(str + '\r');
- _display->inputKey();
+ inputKey();
if (g_engine->shouldQuit())
return;
@@ -140,7 +139,7 @@ void HiRes1Engine::runIntro() {
while (1) {
_display->printString(str);
- Common::String s = _display->inputString();
+ Common::String s = inputString();
if (g_engine->shouldQuit())
break;
@@ -166,7 +165,7 @@ void HiRes1Engine::runIntro() {
while (pages[page] != 0) {
_display->home();
printStrings(file, pages[page++]);
- _display->inputString();
+ inputString();
if (g_engine->shouldQuit())
return;
@@ -175,7 +174,7 @@ void HiRes1Engine::runIntro() {
}
}
- _display->printASCIIString("\r");
+ printASCIIString("\r");
file.close();
@@ -188,7 +187,7 @@ void HiRes1Engine::runIntro() {
file.seek(0x1800);
_display->loadFrameBuffer(file);
_display->decodeFrameBuffer();
- _display->delay(2000);
+ delay(2000);
}
void HiRes1Engine::drawPic(Common::ReadStream &stream, Common::Point pos) {
@@ -294,8 +293,8 @@ void HiRes1Engine::initState() {
void HiRes1Engine::restartGame() {
initState();
_display->printString(_strings[IDI_HR1_STR_PRESS_RETURN]);
- _display->inputString(); // Missing in the original
- _display->printASCIIString("\r\r\r\r\r");
+ inputString(); // Missing in the original
+ printASCIIString("\r\r\r\r\r");
}
void HiRes1Engine::runGame() {
@@ -364,12 +363,12 @@ void HiRes1Engine::runGame() {
}
f.seek(0x3800);
- _parser->loadVerbs(f);
+ loadVerbs(f);
f.seek(0xf00);
- _parser->loadNouns(f);
+ loadNouns(f);
- _display->printASCIIString("\r\r\r\r\r");
+ printASCIIString("\r\r\r\r\r");
while (1) {
if (_isRestarting)
@@ -378,7 +377,7 @@ void HiRes1Engine::runGame() {
uint verb = 0, noun = 0;
clearScreen();
showRoom();
- _parser->getInput(verb, noun);
+ getInput(verb, noun);
if (!doOneCommand(_roomCommands, verb, noun))
printMessage(37);
diff --git a/engines/adl/module.mk b/engines/adl/module.mk
index 012b027..6acd06f 100644
--- a/engines/adl/module.mk
+++ b/engines/adl/module.mk
@@ -4,8 +4,7 @@ MODULE_OBJS := \
adl.o \
detection.o \
display.o \
- hires1.o \
- parser.o
+ hires1.o
MODULE_DIRS += \
engines/adl
diff --git a/engines/adl/parser.cpp b/engines/adl/parser.cpp
deleted file mode 100644
index a697301..0000000
--- a/engines/adl/parser.cpp
+++ /dev/null
@@ -1,168 +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 "adl/adl.h"
-#include "adl/parser.h"
-#include "adl/display.h"
-
-#include "engines/engine.h"
-
-#include "common/str.h"
-#include "common/stream.h"
-#include "common/debug.h"
-#include "common/textconsole.h"
-
-namespace Adl {
-
-Parser::Parser(AdlEngine &engine, Display &display) :
- _engine(engine),
- _display(display) {
-
-}
-
-void Parser::loadWords(Common::ReadStream &stream, WordMap &map) {
- uint index = 0;
-
- while (1) {
- ++index;
-
- byte buf[kWordSize];
-
- if (stream.read(buf, kWordSize) < kWordSize)
- error("Error reading word list");
-
- Common::String word((char *)buf, kWordSize);
-
- if (!map.contains(word))
- map[word] = index;
-
- byte synonyms = stream.readByte();
-
- if (stream.err() || stream.eos())
- error("Error reading word list");
-
- if (synonyms == 0xff)
- break;
-
- for (uint i = 0; i < synonyms; ++i) {
- if (stream.read((char *)buf, kWordSize) < kWordSize)
- error("Error reading word list");
-
- word = Common::String((char *)buf, kWordSize);
-
- if (!map.contains(word))
- map[word] = index;
- }
- }
-}
-
-Common::String Parser::getLine() {
- // Original engine uses a global here, which isn't reset between
- // calls and may not match actual mode
- bool textMode = false;
-
- while (1) {
- Common::String line = _display.inputString(APPLECHAR('?'));
-
- if (g_engine->shouldQuit())
- return "";
-
- if ((byte)line[0] == ('\r' | 0x80)) {
- textMode = !textMode;
- _display.setMode(textMode ? Display::kModeText : Display::kModeMixed);
- continue;
- }
-
- // Remove the return
- line.deleteLastChar();
- return line;
- }
-}
-
-Common::String Parser::getWord(const Common::String &line, uint &index) {
- Common::String str;
-
- for (uint i = 0; i < 8; ++i)
- str += APPLECHAR(' ');
-
- int copied = 0;
-
- // Skip initial whitespace
- while (1) {
- if (index == line.size())
- return str;
- if (line[index] != APPLECHAR(' '))
- break;
- ++index;
- }
-
- // Copy up to 8 characters
- while (1) {
- if (copied < 8)
- str.setChar(line[index], copied++);
-
- index++;
-
- if (index == line.size() || line[index] == APPLECHAR(' '))
- return str;
- }
-}
-
-void Parser::getInput(uint &verb, uint &noun) {
- while (1) {
- _display.printString(_engine.getEngineString(IDI_STR_ENTER_COMMAND));
- Common::String line = getLine();
-
- if (g_engine->shouldQuit())
- return;
-
- uint index = 0;
- Common::String verbStr = getWord(line, index);
-
- if (!_verbs.contains(verbStr)) {
- Common::String err = _engine.getEngineString(IDI_STR_VERB_ERROR);
- for (uint i = 0; i < verbStr.size(); ++i)
- err.setChar(verbStr[i], i + 19);
- _display.printString(err);
- continue;
- }
-
- verb = _verbs[verbStr];
-
- Common::String nounStr = getWord(line, index);
-
- if (!_nouns.contains(nounStr)) {
- Common::String err = _engine.getEngineString(IDI_STR_NOUN_ERROR);
- for (uint i = 0; i < verbStr.size(); ++i)
- err.setChar(verbStr[i], i + 19);
- for (uint i = 0; i < nounStr.size(); ++i)
- err.setChar(nounStr[i], i + 30);
- _display.printString(err);
- continue;
- }
-
- noun = _nouns[nounStr];
- return;
- }
-}
-
-} // End of namespace Adl
diff --git a/engines/adl/parser.h b/engines/adl/parser.h
deleted file mode 100644
index 3c191d9..0000000
--- a/engines/adl/parser.h
+++ /dev/null
@@ -1,66 +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 ADL_PARSER_H
-#define ADL_PARSER_H
-
-#include "common/types.h"
-#include "common/hashmap.h"
-#include "common/hash-str.h"
-
-namespace Common {
-class ReadStream;
-class String;
-}
-
-namespace Adl {
-
-class Display;
-
-class Parser {
-public:
- Parser(AdlEngine &engine, Display &display);
-
- void loadVerbs(Common::ReadStream &stream) { loadWords(stream, _verbs); }
- void loadNouns(Common::ReadStream &stream) { loadWords(stream, _nouns); }
- void getInput(uint &verb, uint &noun);
-
-private:
- enum {
- kWordSize = 8
- };
-
- typedef Common::HashMap<Common::String, uint> WordMap;
-
- void loadWords(Common::ReadStream &stream, WordMap &map);
- Common::String getLine();
- Common::String getWord(const Common::String &line, uint &index);
-
- AdlEngine &_engine;
- Display &_display;
- WordMap _verbs;
- WordMap _nouns;
-};
-
-} // End of namespace Adl
-
-#endif
Commit: 93f5e36c9f9a75a2fa939408a76b0a2632c09425
https://github.com/scummvm/scummvm/commit/93f5e36c9f9a75a2fa939408a76b0a2632c09425
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add GMM loading and saving
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 3c405b6..8ffb929 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -43,13 +43,31 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
_display(nullptr),
- _isRestarting(false) {
+ _isRestarting(false),
+ _isRestoring(false),
+ _saveVerb(0),
+ _saveNoun(0),
+ _restoreVerb(0),
+ _restoreNoun(0),
+ _canSaveNow(false),
+ _canRestoreNow(false) {
}
AdlEngine::~AdlEngine() {
delete _display;
}
+bool AdlEngine::hasFeature(EngineFeature f) const {
+ switch (f) {
+ case kSupportsLoadingDuringRuntime:
+ case kSupportsSavingDuringRuntime:
+ case kSupportsRTL:
+ return true;
+ default:
+ return false;
+ }
+}
+
Common::Error AdlEngine::run() {
initGraphics(560, 384, true);
@@ -71,6 +89,7 @@ Common::Error AdlEngine::run() {
if (!loadState(saveSlot))
error("Failed to load save game from slot %i", saveSlot);
_display->setCursorPos(Common::Point(0, 23));
+ _isRestoring = true;
} else {
runIntro();
initState();
@@ -162,6 +181,16 @@ void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
if (stream.eos() || stream.err())
error("Failed to read commands");
+ if (command.numCond == 0 && command.script[0] == IDO_ACT_SAVE) {
+ _saveVerb = command.verb;
+ _saveNoun = command.noun;
+ }
+
+ if (command.numCond == 0 && command.script[0] == IDO_ACT_LOAD) {
+ _restoreVerb = command.verb;
+ _restoreNoun = command.noun;
+ }
+
commands.push_back(command);
}
}
@@ -278,7 +307,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
case IDO_ACT_RESTART: {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
+
+ // We allow restoring via GMM here
+ _canRestoreNow = true;
Common::String input = inputString();
+ _canRestoreNow = false;
+
+ if (_isRestoring)
+ return;
+
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
_isRestarting = true;
_display->clear(0x00);
@@ -341,7 +378,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
}
}
-bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
+bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, bool run) {
if (command.room != IDI_NONE && command.room != _state.room)
return false;
@@ -384,7 +421,8 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
}
}
- doActions(command, noun, offset);
+ if (run)
+ doActions(command, noun, offset);
return true;
}
@@ -395,7 +433,7 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd)
- if (checkCommand(*cmd, verb, noun))
+ if (matchCommand(*cmd, verb, noun))
return true;
return false;
@@ -403,14 +441,43 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
+ bool oldIsRestoring = _isRestoring;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
- checkCommand(*cmd, verb, noun);
- if (_isRestarting)
- return;
+ matchCommand(*cmd, verb, noun);
+
+ // We assume no restarts happen in this command group. This
+ // simplifies enabling GMM savegame loading on the restart
+ // prompt.
+ if (_isRestarting || _isRestoring != oldIsRestoring)
+ error("Unexpected restart action encountered");
}
}
+bool AdlEngine::canSaveGameStateCurrently() {
+ if (!_canSaveNow)
+ return false;
+
+ Commands::const_iterator cmd;
+
+ // Here we check whether or not the game currently accepts the command
+ // "SAVE GAME". This prevents saving via the GMM in situations where
+ // it wouldn't otherwise be possible to do so.
+ for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
+ if (matchCommand(*cmd, _saveVerb, _saveNoun, false)) {
+ if (cmd->verb != _saveVerb || cmd->noun != _saveNoun)
+ return false;
+ return cmd->numCond == 0 && cmd->script[0] == IDO_ACT_SAVE;
+ }
+ }
+
+ return false;
+}
+
+bool AdlEngine::canLoadGameStateCurrently() {
+ return _canRestoreNow;
+}
+
void AdlEngine::clearScreen() {
_display->setMode(Display::kModeMixed);
_display->clear(0x00);
@@ -654,7 +721,7 @@ Common::String AdlEngine::getLine() {
while (1) {
Common::String line = inputString(APPLECHAR('?'));
- if (shouldQuit())
+ if (shouldQuit() || _isRestoring)
return "";
if ((byte)line[0] == ('\r' | 0x80)) {
@@ -703,7 +770,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
_display->printString(getEngineString(IDI_STR_ENTER_COMMAND));
Common::String line = getLine();
- if (shouldQuit())
+ if (shouldQuit() || _isRestoring)
return;
uint index = 0;
@@ -755,7 +822,7 @@ Common::String AdlEngine::inputString(byte prompt) {
while (1) {
byte b = inputKey();
- if (g_engine->shouldQuit())
+ if (g_engine->shouldQuit() || _isRestoring)
return 0;
if (b == 0)
@@ -805,7 +872,7 @@ byte AdlEngine::inputKey() {
_display->showCursor(true);
- while (!g_engine->shouldQuit() && key == 0) {
+ while (!g_engine->shouldQuit() && !_isRestoring && key == 0) {
Common::Event event;
if (ev->pollEvent(event)) {
if (event.type != Common::EVENT_KEYDOWN)
@@ -863,6 +930,22 @@ void AdlEngine::delay(uint32 ms) {
}
}
+Common::Error AdlEngine::loadGameState(int slot) {
+ if (loadState(slot)) {
+ _isRestoring = true;
+ return Common::kNoError;
+ }
+
+ return Common::kUnknownError;
+}
+
+Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
+ if (saveState(slot, &desc))
+ return Common::kNoError;
+
+ return Common::kUnknownError;
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index a9ac79d..4d160f0 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -168,7 +168,7 @@ public:
virtual ~AdlEngine();
const AdlGameDescription *_gameDescription;
- uint32 getFeatures() const;
+ bool hasFeature(EngineFeature f) const;
const char *getGameId() const;
static AdlEngine *create(GameType type, OSystem *syst, const AdlGameDescription *gd);
@@ -184,12 +184,14 @@ protected:
virtual void initState() = 0;
virtual void restartGame() = 0;
virtual uint getEngineMessage(EngineMessage msg) = 0;
+ bool canSaveGameStateCurrently();
+ bool canLoadGameStateCurrently();
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
virtual void printMessage(uint idx, bool wait = true);
void wordWrap(Common::String &str);
void readCommands(Common::ReadStream &stream, Commands &commands);
- bool checkCommand(const Command &command, byte verb, byte noun);
+ bool matchCommand(const Command &command, byte verb, byte noun, bool run = true);
bool doOneCommand(const Commands &commands, byte verb, byte noun);
void doAllCommands(const Commands &commands, byte verb, byte noun);
void doActions(const Command &command, byte noun, byte offset);
@@ -213,10 +215,14 @@ protected:
Common::String inputString(byte prompt = 0);
void delay(uint32 ms);
byte inputKey();
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const Common::String &desc);
Display *_display;
Parser *_parser;
- bool _isRestarting;
+ bool _isRestarting, _isRestoring;
+ byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
+ bool _canSaveNow, _canRestoreNow;
Common::Array<Common::String> _strings;
Common::Array<Common::String> _messages;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 5912166..db69a2d 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -371,29 +371,49 @@ void HiRes1Engine::runGame() {
printASCIIString("\r\r\r\r\r");
while (1) {
- if (_isRestarting)
- _isRestarting = false;
-
uint verb = 0, noun = 0;
- clearScreen();
- showRoom();
- getInput(verb, noun);
- if (!doOneCommand(_roomCommands, verb, noun))
- printMessage(37);
+ // When restoring from the launcher, we don't read
+ // input on the first iteration. This is needed to
+ // ensure that restoring from the launcher and
+ // restoring in-game brings us to the same game state.
+ // (Also see comment below.)
+ if (!_isRestoring) {
+ clearScreen();
+ showRoom();
- if (_isRestarting)
- continue;
+ _canSaveNow = _canRestoreNow = true;
+ getInput(verb, noun);
+ _canSaveNow = _canRestoreNow = false;
- doAllCommands(_globalCommands, verb, noun);
+ if (shouldQuit())
+ return;
+
+ if (!doOneCommand(_roomCommands, verb, noun))
+ printMessage(IDI_HR1_MSG_DONT_UNDERSTAND);
+ }
- if (_isRestarting)
+ if (_isRestoring) {
+ // We restored from the GMM or launcher. As restoring
+ // with "RESTORE GAME" does not end command processing,
+ // we don't break it off here either. This essentially
+ // means that restoring a game will always run through
+ // the global commands and increase the move counter
+ // before the first user input.
+ printASCIIString("\r");
+ _isRestoring = false;
+ verb = _restoreVerb;
+ noun = _restoreNoun;
+ }
+
+ // Restarting does end command processing
+ if (_isRestarting) {
+ _isRestarting = false;
continue;
+ }
+ doAllCommands(_globalCommands, verb, noun);
_state.moves++;
-
- if (shouldQuit())
- return;
}
}
Commit: baa2410a1cbe34606cbb6c0939a800edb09dfc65
https://github.com/scummvm/scummvm/commit/baa2410a1cbe34606cbb6c0939a800edb09dfc65
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix "don't understand" parser response override
Changed paths:
engines/adl/hires1.cpp
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index db69a2d..5435191 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -427,7 +427,7 @@ void HiRes1Engine::printMessage(uint idx, bool wait) {
case IDI_HR1_MSG_DONT_HAVE_IT:
_display->printString(_strings[IDI_HR1_STR_DONT_HAVE_IT]);
return;
- case IDI_MSG_DONT_UNDERSTAND:
+ case IDI_HR1_MSG_DONT_UNDERSTAND:
_display->printString(_strings[IDI_HR1_STR_DONT_UNDERSTAND]);
return;
case IDI_HR1_MSG_GETTING_DARK:
Commit: 84a9f6ce95822efd2c2e0600daf2aeb27a841106
https://github.com/scummvm/scummvm/commit/84a9f6ce95822efd2c2e0600daf2aeb27a841106
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add save game meta info support
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/detection.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 8ffb929..633705f 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -33,6 +33,7 @@
#include "engines/util.h"
#include "graphics/palette.h"
+#include "graphics/thumbnail.h"
#include "adl/adl.h"
#include "adl/display.h"
@@ -86,7 +87,7 @@ Common::Error AdlEngine::run() {
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot >= 0) {
- if (!loadState(saveSlot))
+ if (loadGameState(saveSlot).getCode() != Common::kNoError)
error("Failed to load save game from slot %i", saveSlot);
_display->setCursorPos(Common::Point(0, 23));
_isRestoring = true;
@@ -297,11 +298,11 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case IDO_ACT_SAVE:
- saveState(0);
+ saveGameState(0, "");
++offset;
break;
case IDO_ACT_LOAD:
- loadState(0);
+ loadGameState(0);
++offset;
// Original engine continues processing here (?)
break;
@@ -528,13 +529,13 @@ void AdlEngine::showRoom() {
printMessage(curRoom().description, false);
}
-bool AdlEngine::saveState(uint slot, const Common::String *description) {
+Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName);
if (!outFile) {
warning("Failed to open file '%s'", fileName.c_str());
- return false;
+ return Common::kUnknownError;
}
outFile->writeUint32BE(MKTAG('A', 'D', 'L', ':'));
@@ -542,8 +543,8 @@ bool AdlEngine::saveState(uint slot, const Common::String *description) {
char name[SAVEGAME_NAME_LEN] = { };
- if (description)
- strncpy(name, description->c_str(), sizeof(name) - 1);
+ if (!desc.empty())
+ strncpy(name, desc.c_str(), sizeof(name) - 1);
else {
Common::String defaultName("Save ");
defaultName += 'A' + slot;
@@ -552,6 +553,20 @@ bool AdlEngine::saveState(uint slot, const Common::String *description) {
outFile->write(name, sizeof(name));
+ TimeDate t;
+ g_system->getTimeAndDate(t);
+
+ outFile->writeUint16BE(t.tm_year);
+ outFile->writeByte(t.tm_mon);
+ outFile->writeByte(t.tm_mday);
+ outFile->writeByte(t.tm_hour);
+ outFile->writeByte(t.tm_min);
+
+ uint32 playTime = getTotalPlayTime();
+ outFile->writeUint32BE(playTime);
+
+ Graphics::saveThumbnail(*outFile);
+
outFile->writeByte(_state.room);
outFile->writeByte(_state.moves);
outFile->writeByte(_state.isDark);
@@ -580,38 +595,45 @@ bool AdlEngine::saveState(uint slot, const Common::String *description) {
if (outFile->err()) {
delete outFile;
warning("Failed to save game '%s'", fileName.c_str());
- return false;
+ return Common::kUnknownError;
}
delete outFile;
- return true;
+ return Common::kNoError;
}
-bool AdlEngine::loadState(uint slot) {
+Common::Error AdlEngine::loadGameState(int slot) {
Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
Common::InSaveFile *inFile = getSaveFileManager()->openForLoading(fileName);
if (!inFile) {
warning("Failed to open file '%s'", fileName.c_str());
- return false;
+ return Common::kUnknownError;
}
if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
warning("No header found in '%s'", fileName.c_str());
delete inFile;
- return false;
+ return Common::kUnknownError;
}
byte saveVersion = inFile->readByte();
if (saveVersion != SAVEGAME_VERSION) {
warning("Save game version %i not supported", saveVersion);
delete inFile;
- return false;
+ return Common::kUnknownError;
}
- initState();
-
+ // Skip description
inFile->seek(SAVEGAME_NAME_LEN, SEEK_CUR);
+ // Skip save time
+ inFile->seek(6, SEEK_CUR);
+
+ uint32 playTime = inFile->readUint32BE();
+
+ Graphics::skipThumbnail(*inFile);
+
+ initState();
_state.room = inFile->readByte();
_state.moves = inFile->readByte();
@@ -649,7 +671,10 @@ bool AdlEngine::loadState(uint slot) {
error("Failed to load game '%s'", fileName.c_str());
delete inFile;
- return true;
+
+ setTotalPlayTime(playTime);
+
+ return Common::kNoError;
}
Room &AdlEngine::room(uint i) {
@@ -930,22 +955,6 @@ void AdlEngine::delay(uint32 ms) {
}
}
-Common::Error AdlEngine::loadGameState(int slot) {
- if (loadState(slot)) {
- _isRestoring = true;
- return Common::kNoError;
- }
-
- return Common::kUnknownError;
-}
-
-Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
- if (saveState(slot, &desc))
- return Common::kNoError;
-
- return Common::kUnknownError;
-}
-
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 4d160f0..f8b2dca 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -237,8 +237,6 @@ protected:
private:
void printEngineMessage(EngineMessage);
- bool saveState(uint slot, const Common::String *description = nullptr);
- bool loadState(uint slot);
Common::String getTargetName() { return _targetName; }
byte convertKey(uint16 ascii);
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 5fe469d..27ce593 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -23,6 +23,8 @@
#include "common/system.h"
#include "common/savefile.h"
+#include "graphics/thumbnail.h"
+
#include "engines/advancedDetector.h"
#include "adl/adl.h"
@@ -73,8 +75,10 @@ public:
}
bool hasFeature(MetaEngineFeature f) const;
- int getMaximumSaveSlot() const { return 15; }
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+ int getMaximumSaveSlot() const { return 'O' - 'A'; }
SaveStateList listSaves(const char *target) const;
+ void removeSaveState(const char *target, int slot) const;
bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
};
@@ -83,17 +87,76 @@ bool AdlMetaEngine::hasFeature(MetaEngineFeature f) const {
switch(f) {
case kSupportsListSaves:
case kSupportsLoadingDuringStartup:
+ case kSupportsDeleteSave:
+ case kSavesSupportMetaInfo:
+ case kSavesSupportThumbnail:
+ case kSavesSupportCreationDate:
+ case kSavesSupportPlayTime:
return true;
default:
return false;
}
}
+SaveStateDescriptor AdlMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.s%02d", target, slot);
+ Common::InSaveFile *inFile = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (!inFile)
+ return SaveStateDescriptor();
+
+ if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
+ delete inFile;
+ return SaveStateDescriptor();
+ }
+
+ byte saveVersion = inFile->readByte();
+ if (saveVersion != SAVEGAME_VERSION) {
+ delete inFile;
+ return SaveStateDescriptor();
+ }
+
+ char name[SAVEGAME_NAME_LEN] = { };
+ inFile->read(name, sizeof(name) - 1);
+ inFile->readByte();
+
+ if (inFile->eos() || inFile->err()) {
+ delete inFile;
+ return SaveStateDescriptor();
+ }
+
+ SaveStateDescriptor sd(slot, name);
+
+ int year = inFile->readUint16BE();
+ int month = inFile->readByte();
+ int day = inFile->readByte();
+ sd.setSaveDate(year + 1900, month + 1, day);
+
+ int hour = inFile->readByte();
+ int minutes = inFile->readByte();
+ sd.setSaveTime(hour, minutes);
+
+ uint32 playTime = inFile->readUint32BE();
+ sd.setPlayTime(playTime);
+
+ if (inFile->eos() || inFile->err()) {
+ delete inFile;
+ return SaveStateDescriptor();
+ }
+
+ Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*inFile);
+ sd.setThumbnail(thumbnail);
+
+ delete inFile;
+ return sd;
+}
+
SaveStateList AdlMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray files = saveFileMan->listSavefiles(Common::String(target) + ".s##");
SaveStateList saveList;
+
for (uint i = 0; i < files.size(); ++i) {
const Common::String &fileName = files[i];
Common::InSaveFile *inFile = saveFileMan->openForLoading(fileName);
@@ -129,6 +192,11 @@ SaveStateList AdlMetaEngine::listSaves(const char *target) const {
return saveList;
}
+void AdlMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.s%02d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
if (gd)
*engine = AdlEngine::create(((const AdlGameDescription *)gd)->gameType, syst, (const AdlGameDescription *)gd);
Commit: 912a31fa652c389b14e3d77998736813e3b621d0
https://github.com/scummvm/scummvm/commit/912a31fa652c389b14e3d77998736813e3b621d0
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add monochrome and scanline rendering
Changed paths:
engines/adl/adl.cpp
engines/adl/detection.cpp
engines/adl/display.cpp
engines/adl/display.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 633705f..15a6c32 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -70,19 +70,6 @@ bool AdlEngine::hasFeature(EngineFeature f) const {
}
Common::Error AdlEngine::run() {
- initGraphics(560, 384, true);
-
- byte palette[6 * 3] = {
- 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff,
- 0xc7, 0x34, 0xff,
- 0x38, 0xcb, 0x00,
- 0x00, 0x00, 0xff, // FIXME
- 0xff, 0xa5, 0x00 // FIXME
- };
-
- g_system->getPaletteManager()->setPalette(palette, 0, 6);
-
_display = new Display();
int saveSlot = ConfMan.getInt("save_slot");
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 27ce593..e556e12 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -22,6 +22,7 @@
#include "common/system.h"
#include "common/savefile.h"
+#include "common/translation.h"
#include "graphics/thumbnail.h"
@@ -31,6 +32,33 @@
namespace Adl {
+#define GAMEOPTION_COLOR GUIO_GAMEOPTIONS1
+#define GAMEOPTION_SCANLINES GUIO_GAMEOPTIONS2
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_COLOR,
+ {
+ _s("Color mode"),
+ _s("Use color graphics"),
+ "color",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_SCANLINES,
+ {
+ _s("Scanlines"),
+ _s("Show scanlines"),
+ "scanlines",
+ false
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
struct AdlGameDescription {
ADGameDescription desc;
GameType gameType;
@@ -55,7 +83,7 @@ static const AdlGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformApple2GS, // FIXME
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO2(GAMEOPTION_COLOR, GAMEOPTION_SCANLINES)
},
kGameTypeHires1
},
@@ -64,7 +92,7 @@ static const AdlGameDescription gameDescriptions[] = {
class AdlMetaEngine : public AdvancedMetaEngine {
public:
- AdlMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(AdlGameDescription), adlGames) { }
+ AdlMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(AdlGameDescription), adlGames, optionsList) { }
const char *getName() const {
return "ADL";
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index a6d94f6..ade05ab 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -29,11 +29,14 @@
#include "common/events.h"
#include "common/rect.h"
#include "common/array.h"
+#include "common/config-manager.h"
#include "engines/engine.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
namespace Adl {
-static byte font[64][5] = {
+static const byte font[64][5] = {
{ 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A
{ 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC
{ 0xfe, 0x82, 0x82, 0x82, 0x7c }, { 0xfe, 0x92, 0x92, 0x92, 0x82 }, // DE
@@ -69,10 +72,17 @@ static byte font[64][5] = {
};
Display::Display() :
- _scanlines(false),
_cursorPos(0),
_mode(kModeText),
_showCursor(false) {
+
+ initGraphics(560, 384, true);
+
+ _monochrome = !ConfMan.getBool("color");
+ _scanlines = ConfMan.getBool("scanlines");
+
+ setPalette(_scanlines, _monochrome);
+
_frameBuf = new byte[kFrameBufSize];
_frameBufSurface = new Graphics::Surface;
_frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
@@ -98,11 +108,37 @@ Display::~Display() {
delete _font;
}
+void Display::setPalette(bool scanlines, bool monochrome) {
+ const byte colorPal[6 * 3] = {
+ 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff,
+ 0xc7, 0x34, 0xff,
+ 0x38, 0xcb, 0x00,
+ 0x0d, 0xa1, 0xff,
+ 0xf2, 0x5e, 0x00
+ };
+
+ const byte monoPal[2 * 3] = {
+ 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0x01
+ };
+
+ if (monochrome) {
+ g_system->getPaletteManager()->setPalette(monoPal, 0, 2);
+ if (!scanlines)
+ g_system->getPaletteManager()->setPalette(monoPal, 6, 2);
+ } else {
+ g_system->getPaletteManager()->setPalette(colorPal, 0, 6);
+ if (!scanlines)
+ g_system->getPaletteManager()->setPalette(colorPal, 6, 6);
+ }
+}
+
void Display::loadFrameBuffer(Common::ReadStream &stream) {
stream.read(_frameBuf, kFrameBufSize);
}
-void Display::decodeScanline(byte *dst, int pitch, byte *src) {
+void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) {
// TODO: shift secondPal by half a pixel
bool prevOn = false;
@@ -135,11 +171,8 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) {
dst[0] = color;
dst[1] = color;
-
- if (!_scanlines) {
- dst[pitch] = color;
- dst[pitch + 1] = color;
- }
+ dst[pitch] = color + 6;
+ dst[pitch + 1] = color + 6;
dst += 2;
prevOn = curOn;
@@ -147,6 +180,33 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) {
}
}
+void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) {
+ // TODO: shift secondPal by half a pixel
+
+ for (uint j = 0; j < 39; ++j) {
+ for (uint k = 0; k < 7; ++k) {
+ byte color = 0;
+
+ if (src[j] & (1 << k))
+ color = 1;
+
+ dst[0] = color;
+ dst[1] = color;
+ dst[pitch] = color + 6;
+ dst[pitch + 1] = color + 6;
+
+ dst += 2;
+ }
+ }
+}
+
+void Display::decodeScanline(byte *dst, int pitch, byte *src) {
+ if (_monochrome)
+ decodeScanlineMono(dst, pitch, src);
+ else
+ decodeScanlineColor(dst, pitch, src);
+}
+
Display::PixelPos Display::getPixelPos(byte x, byte y) {
PixelPos pixelPos;
@@ -390,16 +450,23 @@ void Display::drawChar(byte c, int x, int y) {
byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
for (uint row = 0; row < 8; ++row) {
- for (uint col = 1; col < 6; ++col)
+ if (row & 1) {
+ buf[_font->pitch] = 6;
+ buf[_font->pitch + 1] = 6;
+ buf[_font->pitch + 6 * 2] = 6;
+ buf[_font->pitch + 6 * 2 + 1] = 6;
+ }
+ for (uint col = 1; col < 6; ++col) {
if (font[c][col - 1] & (1 << row)) {
buf[col * 2] = 1;
buf[col * 2 + 1] = 1;
-
- if (!_scanlines) {
- buf[_font->pitch + col * 2] = 1;
- buf[_font->pitch + col * 2 + 1] = 1;
- }
+ buf[_font->pitch + col * 2] = 1 + 6;
+ buf[_font->pitch + col * 2 + 1] = 1 + 6;
+ } else {
+ buf[_font->pitch + col * 2] = 6;
+ buf[_font->pitch + col * 2 + 1] = 6;
}
+ }
buf += 2 * _font->pitch;
}
@@ -417,10 +484,15 @@ void Display::createFont() {
byte *buf = (byte *)_font->getPixels();
byte *bufInv = buf + (_font->h / 2) * _font->pitch;
- for (uint row = 0; row < _font->h / 2; ++row) {
- if (!_scanlines || !(row & 1))
- for (uint col = 0; col < _font->w; ++col)
- bufInv[col] = buf[col] ? 0 : 1;
+ for (uint row = 0; row < _font->h / 2; row += 2) {
+ for (uint col = 0; col < _font->w; ++col)
+ bufInv[col] = (buf[col] ? 0 : 1);
+
+ buf += _font->pitch;
+ bufInv += _font->pitch;
+
+ for (uint col = 0; col < _font->w; ++col)
+ bufInv[col] = (buf[col] == 7 ? 6 : 7);
buf += _font->pitch;
bufInv += _font->pitch;
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 91ae447..21cc599 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -50,6 +50,7 @@ public:
Display();
~Display();
+ void setPalette(bool monochrome, bool scanlines);
void loadFrameBuffer(Common::ReadStream &stream);
void decodeFrameBuffer();
void updateScreen();
@@ -84,6 +85,8 @@ private:
};
void decodeScanline(byte *dst, int pitch, byte *src);
+ void decodeScanlineColor(byte *dst, int pitch, byte *src);
+ void decodeScanlineMono(byte *dst, int pitch, byte *src);
PixelPos getPixelPos(byte x, byte y);
byte getPixelColor(byte x, byte color);
void drawChar(byte c, int x, int y);
@@ -103,6 +106,7 @@ private:
int _cursorPos;
Mode _mode;
bool _showCursor;
+ bool _monochrome;
};
} // End of namespace Adl
Commit: b30fb417acb29dee415a784f15f63772a010b4d3
https://github.com/scummvm/scummvm/commit/b30fb417acb29dee415a784f15f63772a010b4d3
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Disable scanlines when saving thumbnail
Changed paths:
engines/adl/adl.cpp
engines/adl/display.cpp
engines/adl/display.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 15a6c32..083fde9 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -552,7 +552,7 @@ Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
uint32 playTime = getTotalPlayTime();
outFile->writeUint32BE(playTime);
- Graphics::saveThumbnail(*outFile);
+ _display->saveThumbnail(*outFile);
outFile->writeByte(_state.room);
outFile->writeByte(_state.moves);
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index ade05ab..6a7cc69 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -33,6 +33,7 @@
#include "engines/engine.h"
#include "engines/util.h"
#include "graphics/palette.h"
+#include "graphics/thumbnail.h"
namespace Adl {
@@ -81,7 +82,12 @@ Display::Display() :
_monochrome = !ConfMan.getBool("color");
_scanlines = ConfMan.getBool("scanlines");
- setPalette(_scanlines, _monochrome);
+ if (_monochrome)
+ setMonoPalette();
+ else
+ setColorPalette();
+
+ enableScanlines(_scanlines);
_frameBuf = new byte[kFrameBufSize];
_frameBufSurface = new Graphics::Surface;
@@ -108,7 +114,34 @@ Display::~Display() {
delete _font;
}
-void Display::setPalette(bool scanlines, bool monochrome) {
+bool Display::saveThumbnail(Common::WriteStream &out) {
+ if (_scanlines) {
+ enableScanlines(false);
+ g_system->updateScreen();
+ }
+
+ bool retval = Graphics::saveThumbnail(out);
+
+ if (_scanlines) {
+ enableScanlines(true);
+ g_system->updateScreen();
+ }
+
+ return retval;
+}
+
+void Display::enableScanlines(bool enable) {
+ byte pal[6 * 3] = { };
+
+ if (enable)
+ g_system->getPaletteManager()->setPalette(pal, 6, 6);
+ else {
+ g_system->getPaletteManager()->grabPalette(pal, 0, 6);
+ g_system->getPaletteManager()->setPalette(pal, 6, 6);
+ }
+}
+
+void Display::setColorPalette() {
const byte colorPal[6 * 3] = {
0x00, 0x00, 0x00,
0xff, 0xff, 0xff,
@@ -118,20 +151,16 @@ void Display::setPalette(bool scanlines, bool monochrome) {
0xf2, 0x5e, 0x00
};
+ g_system->getPaletteManager()->setPalette(colorPal, 0, 6);
+}
+
+void Display::setMonoPalette() {
const byte monoPal[2 * 3] = {
0x00, 0x00, 0x00,
0x00, 0xc0, 0x01
};
- if (monochrome) {
- g_system->getPaletteManager()->setPalette(monoPal, 0, 2);
- if (!scanlines)
- g_system->getPaletteManager()->setPalette(monoPal, 6, 2);
- } else {
- g_system->getPaletteManager()->setPalette(colorPal, 0, 6);
- if (!scanlines)
- g_system->getPaletteManager()->setPalette(colorPal, 6, 6);
- }
+ g_system->getPaletteManager()->setPalette(monoPal, 0, 2);
}
void Display::loadFrameBuffer(Common::ReadStream &stream) {
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 21cc599..12e3ab9 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -28,6 +28,7 @@
namespace Common {
class ReadStream;
+class WriteStream;
class String;
class Point;
}
@@ -50,7 +51,9 @@ public:
Display();
~Display();
- void setPalette(bool monochrome, bool scanlines);
+ void enableScanlines(bool enable);
+ void setMonoPalette();
+ void setColorPalette();
void loadFrameBuffer(Common::ReadStream &stream);
void decodeFrameBuffer();
void updateScreen();
@@ -69,6 +72,7 @@ public:
void setCharAtCursor(byte c);
void showCursor(bool enable);
void updateTextSurface();
+ bool saveThumbnail(Common::WriteStream &out);
private:
enum {
Commit: d5cc42f1c233a45abb879818af503ec7b91c6f34
https://github.com/scummvm/scummvm/commit/d5cc42f1c233a45abb879818af503ec7b91c6f34
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Make frame buffer linear
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 083fde9..90a9a0d 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -484,7 +484,7 @@ void AdlEngine::drawItems() {
if (curRoom().picture == curRoom().curPicture) {
const Common::Point &p = _itemOffsets[dropped];
if (item->isLineArt)
- _display->drawLineArt(_lineArt[item->picture - 1], p);
+ drawLineArt(_lineArt[item->picture - 1], p);
else
drawPic(item->picture, p);
++dropped;
@@ -497,7 +497,7 @@ void AdlEngine::drawItems() {
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
if (*pic == curRoom().curPicture) {
if (item->isLineArt)
- _display->drawLineArt(_lineArt[item->picture - 1], item->position);
+ drawLineArt(_lineArt[item->picture - 1], item->position);
else
drawPic(item->picture, item->position);
continue;
@@ -942,6 +942,50 @@ void AdlEngine::delay(uint32 ms) {
}
}
+void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) {
+ if (bits & 4) {
+ _display->putPixel(p, color);
+ }
+
+ bits += quadrant;
+
+ if (bits & 1)
+ p.x += (bits & 2 ? -1 : 1);
+ else
+ p.y += (bits & 2 ? 1 : -1);
+}
+
+void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation, byte scaling, byte color) {
+ const byte stepping[] = {
+ 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
+ 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
+ 0xff
+ };
+
+ byte quadrant = rotation >> 4;
+ rotation &= 0xf;
+ byte xStep = stepping[rotation];
+ byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
+
+ for (uint i = 0; i < lineArt.size(); ++i) {
+ byte b = lineArt[i];
+
+ do {
+ byte xFrac = 0x80;
+ byte yFrac = 0x80;
+ for (uint j = 0; j < scaling; ++j) {
+ if (xFrac + xStep + 1 > 255)
+ drawNextPixel(p, color, b, quadrant);
+ xFrac += xStep + 1;
+ if (yFrac + yStep > 255)
+ drawNextPixel(p, color, b, quadrant + 1);
+ yFrac += yStep;
+ }
+ b >>= 3;
+ } while (b != 0);
+ }
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index f8b2dca..84b9214 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -198,6 +198,8 @@ protected:
void clearScreen();
virtual void drawPic(byte pic, Common::Point pos = Common::Point()) = 0;
void drawItems();
+ void drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant);
+ void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f);
void showRoom();
void takeItem(byte noun);
void dropItem(byte noun);
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 6a7cc69..90ca1b6 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -89,7 +89,7 @@ Display::Display() :
enableScanlines(_scanlines);
- _frameBuf = new byte[kFrameBufSize];
+ _frameBuf = new byte[kWidth * kHeight / 7];
_frameBufSurface = new Graphics::Surface;
_frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
@@ -164,7 +164,19 @@ void Display::setMonoPalette() {
}
void Display::loadFrameBuffer(Common::ReadStream &stream) {
- stream.read(_frameBuf, kFrameBufSize);
+ for (uint j = 0; j < 8; ++j) {
+ for (uint i = 0; i < 8; ++i) {
+ byte *dst = _frameBuf + kWidth / 7 * (i * 8 + j);
+ stream.read(dst, kWidth / 7);
+ dst += kWidth / 7 * 64;
+ stream.read(dst, kWidth / 7);
+ dst += kWidth / 7 * 64;
+ stream.read(dst, kWidth / 7);
+ stream.readUint32LE();
+ stream.readUint32LE();
+ dst += kWidth / 7 * 64;
+ }
+ }
}
void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) {
@@ -236,224 +248,45 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) {
decodeScanlineColor(dst, pitch, src);
}
-Display::PixelPos Display::getPixelPos(byte x, byte y) {
- PixelPos pixelPos;
-
- // FIXME: check X, Y range
-
- byte offsetL = y & 0xc0;
- offsetL |= offsetL >> 2;
- byte offsetH = y;
- y <<= 2;
- offsetH <<= 1;
- offsetH |= y >> 7;
- y <<= 1;
- offsetH <<= 1;
- offsetH |= y >> 7;
- y <<= 1;
- offsetL >>= 1;
- offsetL |= y & 0x80;
- y <<= 1;
- offsetH = offsetH & 0x1f;
- pixelPos.rowAddr = (offsetH << 8) | offsetL;
- pixelPos.byteOffset = x / 7;
- pixelPos.bitMask = 0x80 | (1 << x % 7);
-
- return pixelPos;
-}
-
-byte Display::getPixelColor(byte offset, byte color) {
- if (offset & 1) {
- byte c = color << 1;
- if (c >= 0x40 && c < 0xc0)
- return color ^ 0x7f;
- }
-
- return color;
-}
-
void Display::decodeFrameBuffer() {
byte *src = _frameBuf;
- int pitch = _frameBufSurface->pitch;
- for (int j = 0; j < 8; ++j) {
- for (int i = 0; i < 8; ++i) {
- byte *dst = (byte *)_frameBufSurface->getPixels() + pitch * 2 * (i * 8 + j);
- decodeScanline(dst, pitch, src);
- src += 40;
- dst += pitch * 2 * 64;
- decodeScanline(dst, pitch, src);
- src += 40;
- dst += pitch * 2 * 64;
- decodeScanline(dst, pitch, src);
- src += 48;
- dst += pitch * 2 * 64;
- }
- }
-}
-
-void Display::drawPixel(byte x, byte y, byte color) {
- PixelPos p = getPixelPos(x, y);
- byte c = getPixelColor(p.byteOffset, color);
- byte *b = _frameBuf + p.rowAddr + p.byteOffset;
- c ^= *b;
- c &= p.bitMask;
- c ^= *b;
- *b = c;
-}
+ byte *dst = (byte *)_frameBufSurface->getPixels();
-void Display::moveX(PixelPos &p, byte &color, bool left) {
- if (left) {
- byte bit = p.bitMask;
- bool b = bit & 1;
- bit >>= 1;
- if (!b) {
- bit ^= 0xc0;
- p.bitMask = bit;
- return;
- }
- --p.byteOffset;
- if (p.byteOffset & 0x80)
- p.byteOffset = 39;
- p.bitMask = 0xc0;
- } else {
- byte bit = p.bitMask;
- bit <<= 1;
- bit ^= 0x80;
- if (bit & 0x80) {
- p.bitMask = bit;
- return;
- }
- p.bitMask = 0x81;
- ++p.byteOffset;
- if (p.byteOffset == 40)
- p.byteOffset = 0;
+ for (uint i = 0; i < kHeight; ++i) {
+ decodeScanline(dst, _frameBufSurface->pitch, src);
+ src += kWidth / 7;
+ dst += _frameBufSurface->pitch * 2;
}
-
- color = getPixelColor(p.byteOffset, color);
}
-void Display::moveY(PixelPos &p, bool down) {
- if (!down) {
- if (p.rowAddr & 0x1c00)
- p.rowAddr -= 0x400;
- else if (p.rowAddr & 0x380)
- p.rowAddr += 0x1b80;
- else {
- p.rowAddr += 0x1f58;
- if (!(p.rowAddr & 0x80))
- p.rowAddr += 0x78; // Wrap around
- }
- } else {
- p.rowAddr += 0x400;
- if (p.rowAddr & 0x1c00)
- return;
- else if ((p.rowAddr & 0x380) != 0x380)
- p.rowAddr -= 0x1f80;
- else {
- p.rowAddr -= 0x2358;
- if ((p.rowAddr & 0x78) == 0x78)
- p.rowAddr -= 0x78; // Wrap around
- }
- }
-}
+void Display::putPixel(Common::Point p, byte color) {
+ byte offset = p.x / 7;
-void Display::drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant) {
- if (bits & 4) {
- byte b = (_frameBuf[p.rowAddr + p.byteOffset] ^ color) & p.bitMask;
- _frameBuf[p.rowAddr + p.byteOffset] ^= b;
+ if (offset & 1) {
+ byte c = color << 1;
+ if (c >= 0x40 && c < 0xc0)
+ color ^= 0x7f;
}
- bits += quadrant;
-
- if (bits & 1)
- moveX(p, color, bits & 2);
- else
- moveY(p, bits & 2);
-}
-
-void Display::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation, byte scaling, byte color) {
- const byte stepping[] = {
- 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
- 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
- 0xff
- };
-
- PixelPos pos = getPixelPos(p.x, p.y);
- byte c = getPixelColor(pos.byteOffset, color);
-
- byte quadrant = rotation >> 4;
- rotation &= 0xf;
- byte xStep = stepping[rotation];
- byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
-
- for (uint i = 0; i < lineArt.size(); ++i) {
- byte b = lineArt[i];
-
- do {
- byte xFrac = 0x80;
- byte yFrac = 0x80;
- for (uint j = 0; j < scaling; ++j) {
- if (xFrac + xStep + 1 > 255)
- drawNextPixel(pos, c, b, quadrant);
- xFrac += xStep + 1;
- if (yFrac + yStep > 255)
- drawNextPixel(pos, c, b, quadrant + 1);
- yFrac += yStep;
- }
- b >>= 3;
- } while (b != 0);
- }
+ byte *b = _frameBuf + p.y * kWidth / 7 + offset;
+ color ^= *b;
+ color &= 1 << (p.x % 7);
+ *b ^= color;
}
-void Display::drawLine(Common::Point p1, Common::Point p2, byte color) {
- PixelPos p = getPixelPos(p1.x, p1.y);
- byte c = getPixelColor(p.byteOffset, color);
-
- int16 deltaX = p2.x - p1.x;
- byte dir = deltaX >> 8;
-
- if (deltaX < 0)
- deltaX = -deltaX;
-
- int16 err = deltaX;
-
- int16 deltaY = p2.y - p1.y - 1;
- dir >>= 1;
- if (deltaY >= 0) {
- deltaY = -deltaY - 2;
- dir |= 0x80;
- }
-
- int16 steps = deltaY - deltaX;
-
- err += deltaY + 1;
-
- while (1) {
- byte *b = _frameBuf + p.rowAddr + p.byteOffset;
- byte d = *b;
- d ^= c;
- d &= p.bitMask;
- d ^= *b;
- *b = d;
+void Display::clear(byte color) {
+ byte val = 0;
- if (++steps == 0)
- return;
+ byte c = color << 1;
+ if (c >= 0x40 && c < 0xc0)
+ val = 0x7f;
- if (err < 0) {
- moveY(p, dir & 0x80);
- err += deltaX;
- } else {
- moveX(p, c, dir & 0x40);
- err += deltaY + 1;
- }
+ for (uint i = 0; i < kWidth / 7 * kHeight; ++i) {
+ _frameBuf[i] = color;
+ color ^= val;
}
}
-void Display::clear(byte color) {
- for (uint i = 0; i < kFrameBufSize; ++i)
- _frameBuf[i] = getPixelColor(i & 1, color);
-}
-
void Display::updateTextSurface() {
for (uint row = 0; row < 24; ++row)
for (uint col = 0; col < 40; ++col) {
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 12e3ab9..0452b27 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -58,10 +58,8 @@ public:
void decodeFrameBuffer();
void updateScreen();
void setMode(Mode mode) { _mode = mode; }
- void drawPixel(byte x, byte y, byte color);
- void drawLine(Common::Point p1, Common::Point p2, byte color);
+ void putPixel(Common::Point p1, byte color);
void clear(byte color);
- void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f);
void setCursorPos(Common::Point pos);
void home();
@@ -78,7 +76,6 @@ private:
enum {
kWidth = 280,
kHeight = 192,
- kFrameBufSize = 0x2000,
kTextBufSize = 40 * 24
};
@@ -91,13 +88,8 @@ private:
void decodeScanline(byte *dst, int pitch, byte *src);
void decodeScanlineColor(byte *dst, int pitch, byte *src);
void decodeScanlineMono(byte *dst, int pitch, byte *src);
- PixelPos getPixelPos(byte x, byte y);
- byte getPixelColor(byte x, byte color);
void drawChar(byte c, int x, int y);
void createFont();
- void moveX(PixelPos &p, byte &color, bool left);
- void moveY(PixelPos &p, bool down);
- void drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant);
void scrollUp();
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 5435191..04df01e 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -216,10 +216,10 @@ void HiRes1Engine::drawPic(Common::ReadStream &stream, Common::Point pos) {
y = 160;
if (bNewLine) {
- _display->drawPixel(x, y, 0x7f);
+ _display->putPixel(Common::Point(x, y), 0x7f);
bNewLine = false;
} else {
- _display->drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
+ drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
}
oldX = x;
@@ -455,6 +455,42 @@ uint HiRes1Engine::getEngineMessage(EngineMessage msg) {
}
}
+void HiRes1Engine::drawLine(Common::Point p1, Common::Point p2, byte color) {
+ int16 deltaX = p2.x - p1.x;
+ byte dir = deltaX >> 8;
+
+ if (deltaX < 0)
+ deltaX = -deltaX;
+
+ int16 err = deltaX;
+
+ int16 deltaY = p2.y - p1.y - 1;
+ dir >>= 1;
+ if (deltaY >= 0) {
+ deltaY = -deltaY - 2;
+ dir |= 0x80;
+ }
+
+ int16 steps = deltaY - deltaX;
+
+ err += deltaY + 1;
+
+ while (1) {
+ _display->putPixel(p1, color);
+
+ if (++steps == 0)
+ return;
+
+ if (err < 0) {
+ p1.y += (dir & 0x80 ? 1 : -1);
+ err += deltaX;
+ } else {
+ p1.x += (dir & 0x40 ? -1 : 1);
+ err += deltaY + 1;
+ }
+ }
+}
+
AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd) {
return new HiRes1Engine(syst, gd);
}
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 897327c..cae5980 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -57,6 +57,7 @@ private:
void runIntro();
void drawPic(Common::ReadStream &stream, Common::Point pos);
void drawItems();
+ void drawLine(Common::Point p1, Common::Point p2, byte color);
void drawPic(byte pic, Common::Point pos);
};
Commit: 4f7e5da4dad61f11553e5f51f00d33506b9ef342
https://github.com/scummvm/scummvm/commit/4f7e5da4dad61f11553e5f51f00d33506b9ef342
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up Display class
Changed paths:
engines/adl/display.cpp
engines/adl/display.h
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 90ca1b6..55166f4 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -20,23 +20,40 @@
*
*/
-#include "adl/display.h"
#include "common/stream.h"
#include "common/rect.h"
-#include "graphics/surface.h"
#include "common/system.h"
#include "common/str.h"
-#include "common/events.h"
-#include "common/rect.h"
-#include "common/array.h"
#include "common/config-manager.h"
-#include "engines/engine.h"
-#include "engines/util.h"
+
+#include "graphics/surface.h"
#include "graphics/palette.h"
#include "graphics/thumbnail.h"
+#include "engines/util.h"
+
+#include "adl/display.h"
+
namespace Adl {
+#define DISPLAY_PITCH (DISPLAY_WIDTH / 7)
+
+#define COLOR_PALETTE_SIZE 6
+const byte colorPalette[COLOR_PALETTE_SIZE * 3] = {
+ 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff,
+ 0xc7, 0x34, 0xff,
+ 0x38, 0xcb, 0x00,
+ 0x0d, 0xa1, 0xff,
+ 0xf2, 0x5e, 0x00
+};
+
+#define MONO_PALETTE_SIZE 2
+const byte monoPalette[MONO_PALETTE_SIZE * 3] = {
+ 0x00, 0x00, 0x00,
+ 0x00, 0xc0, 0x01
+};
+
static const byte font[64][5] = {
{ 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A
{ 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC
@@ -73,8 +90,8 @@ static const byte font[64][5] = {
};
Display::Display() :
- _cursorPos(0),
_mode(kModeText),
+ _cursorPos(0),
_showCursor(false) {
initGraphics(560, 384, true);
@@ -83,20 +100,23 @@ Display::Display() :
_scanlines = ConfMan.getBool("scanlines");
if (_monochrome)
- setMonoPalette();
+ g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_SIZE);
else
- setColorPalette();
+ g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_SIZE);
enableScanlines(_scanlines);
- _frameBuf = new byte[kWidth * kHeight / 7];
+ _frameBuf = new byte[DISPLAY_PITCH * DISPLAY_HEIGHT];
_frameBufSurface = new Graphics::Surface;
- _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
+ // We need 2x scaling to properly render the half-pixel shift
+ // of the second palette
+ _frameBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8());
_textBuf = new byte[kTextBufSize];
- memset(_textBuf, ' ' | 0x80, kTextBufSize);
+ memset(_textBuf, APPLECHAR(' '), kTextBufSize);
_textBufSurface = new Graphics::Surface;
- _textBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8());
+ // For ease of copying, also use 2x scaling here
+ _textBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8());
createFont();
}
@@ -114,6 +134,17 @@ Display::~Display() {
delete _font;
}
+void Display::updateScreen() {
+ if (_mode == kModeText) {
+ g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h);
+ } else if (_mode == kModeHires) {
+ g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h);
+ } else {
+ g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2);
+ g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2);
+ }
+}
+
bool Display::saveThumbnail(Common::WriteStream &out) {
if (_scanlines) {
enableScanlines(false);
@@ -130,56 +161,153 @@ bool Display::saveThumbnail(Common::WriteStream &out) {
return retval;
}
-void Display::enableScanlines(bool enable) {
- byte pal[6 * 3] = { };
+void Display::loadFrameBuffer(Common::ReadStream &stream) {
+ for (uint j = 0; j < 8; ++j) {
+ for (uint i = 0; i < 8; ++i) {
+ byte *dst = _frameBuf + DISPLAY_PITCH * (i * 8 + j);
+ stream.read(dst, DISPLAY_PITCH);
+ dst += DISPLAY_PITCH * 64;
+ stream.read(dst, DISPLAY_PITCH);
+ dst += DISPLAY_PITCH * 64;
+ stream.read(dst, DISPLAY_PITCH);
+ stream.readUint32LE();
+ stream.readUint32LE();
+ dst += DISPLAY_PITCH * 64;
+ }
+ }
+}
- if (enable)
- g_system->getPaletteManager()->setPalette(pal, 6, 6);
- else {
- g_system->getPaletteManager()->grabPalette(pal, 0, 6);
- g_system->getPaletteManager()->setPalette(pal, 6, 6);
+void Display::decodeFrameBuffer() {
+ byte *src = _frameBuf;
+ byte *dst = (byte *)_frameBufSurface->getPixels();
+
+ for (uint i = 0; i < DISPLAY_HEIGHT; ++i) {
+ decodeScanline(dst, _frameBufSurface->pitch, src);
+ src += DISPLAY_PITCH;
+ dst += _frameBufSurface->pitch * 2;
}
}
-void Display::setColorPalette() {
- const byte colorPal[6 * 3] = {
- 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff,
- 0xc7, 0x34, 0xff,
- 0x38, 0xcb, 0x00,
- 0x0d, 0xa1, 0xff,
- 0xf2, 0x5e, 0x00
- };
-
- g_system->getPaletteManager()->setPalette(colorPal, 0, 6);
+void Display::putPixel(Common::Point p, byte color) {
+ byte offset = p.x / 7;
+
+ if (offset & 1) {
+ byte c = color << 1;
+ if (c >= 0x40 && c < 0xc0)
+ color ^= 0x7f;
+ }
+
+ byte *b = _frameBuf + p.y * DISPLAY_PITCH + offset;
+ color ^= *b;
+ color &= 1 << (p.x % 7);
+ *b ^= color;
}
-void Display::setMonoPalette() {
- const byte monoPal[2 * 3] = {
- 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0x01
- };
+void Display::clear(byte color) {
+ byte val = 0;
+
+ byte c = color << 1;
+ if (c >= 0x40 && c < 0xc0)
+ val = 0x7f;
- g_system->getPaletteManager()->setPalette(monoPal, 0, 2);
+ for (uint i = 0; i < DISPLAY_PITCH * DISPLAY_HEIGHT; ++i) {
+ _frameBuf[i] = color;
+ color ^= val;
+ }
}
-void Display::loadFrameBuffer(Common::ReadStream &stream) {
- for (uint j = 0; j < 8; ++j) {
- for (uint i = 0; i < 8; ++i) {
- byte *dst = _frameBuf + kWidth / 7 * (i * 8 + j);
- stream.read(dst, kWidth / 7);
- dst += kWidth / 7 * 64;
- stream.read(dst, kWidth / 7);
- dst += kWidth / 7 * 64;
- stream.read(dst, kWidth / 7);
- stream.readUint32LE();
- stream.readUint32LE();
- dst += kWidth / 7 * 64;
+void Display::updateTextSurface() {
+ for (uint row = 0; row < 24; ++row)
+ for (uint col = 0; col < 40; ++col) {
+ int charPos = row * 40 + col;
+ char c = _textBuf[row * 40 + col];
+
+ if (charPos == _cursorPos && _showCursor)
+ c = (c & 0x3f) | 0x40;
+
+ Common::Rect r(7 * 2, 8 * 2);
+ r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
+
+ if (!(c & 0x80)) {
+ if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1))
+ r.translate(0, 4 * 8 * 2);
+ }
+
+ _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
+ }
+}
+
+
+void Display::setCursorPos(Common::Point pos) {
+ _cursorPos = pos.y * 40 + pos.x;
+}
+
+
+void Display::home() {
+ memset(_textBuf, APPLECHAR(' '), kTextBufSize);
+ _cursorPos = 0;
+}
+
+void Display::moveCursorForward() {
+ ++_cursorPos;
+
+ if (_cursorPos >= kTextBufSize)
+ scrollUp();
+}
+
+void Display::moveCursorBackward() {
+ --_cursorPos;
+
+ if (_cursorPos < 0)
+ _cursorPos = 0;
+}
+
+void Display::moveCursorTo(const Common::Point &pos) {
+ _cursorPos = pos.y * 40 + pos.x;
+
+ if (_cursorPos >= kTextBufSize)
+ error("Cursor position (%i, %i) out of bounds", pos.x, pos.y);
+}
+
+void Display::printString(const Common::String &str) {
+ Common::String::const_iterator c;
+ for (c = str.begin(); c != str.end(); ++c) {
+ byte b = *c;
+
+ if (*c == APPLECHAR('\r'))
+ _cursorPos = (_cursorPos / 40 + 1) * 40;
+ else if (b < 0x80 || b >= 0xa0) {
+ setCharAtCursor(b);
+ ++_cursorPos;
}
+
+ if (_cursorPos == kTextBufSize)
+ scrollUp();
}
+
+ updateTextSurface();
}
-void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) {
+void Display::setCharAtCursor(byte c) {
+ _textBuf[_cursorPos] = c;
+}
+
+void Display::showCursor(bool enable) {
+ _showCursor = enable;
+}
+
+void Display::enableScanlines(bool enable) {
+ byte pal[6 * 3] = { };
+
+ if (enable)
+ g_system->getPaletteManager()->setPalette(pal, 6, 6);
+ else {
+ g_system->getPaletteManager()->grabPalette(pal, 0, 6);
+ g_system->getPaletteManager()->setPalette(pal, 6, 6);
+ }
+}
+
+void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
// TODO: shift secondPal by half a pixel
bool prevOn = false;
@@ -221,7 +349,7 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) {
}
}
-void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) {
+void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) const {
// TODO: shift secondPal by half a pixel
for (uint j = 0; j < 39; ++j) {
@@ -241,73 +369,13 @@ void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) {
}
}
-void Display::decodeScanline(byte *dst, int pitch, byte *src) {
+void Display::decodeScanline(byte *dst, int pitch, byte *src) const {
if (_monochrome)
decodeScanlineMono(dst, pitch, src);
else
decodeScanlineColor(dst, pitch, src);
}
-void Display::decodeFrameBuffer() {
- byte *src = _frameBuf;
- byte *dst = (byte *)_frameBufSurface->getPixels();
-
- for (uint i = 0; i < kHeight; ++i) {
- decodeScanline(dst, _frameBufSurface->pitch, src);
- src += kWidth / 7;
- dst += _frameBufSurface->pitch * 2;
- }
-}
-
-void Display::putPixel(Common::Point p, byte color) {
- byte offset = p.x / 7;
-
- if (offset & 1) {
- byte c = color << 1;
- if (c >= 0x40 && c < 0xc0)
- color ^= 0x7f;
- }
-
- byte *b = _frameBuf + p.y * kWidth / 7 + offset;
- color ^= *b;
- color &= 1 << (p.x % 7);
- *b ^= color;
-}
-
-void Display::clear(byte color) {
- byte val = 0;
-
- byte c = color << 1;
- if (c >= 0x40 && c < 0xc0)
- val = 0x7f;
-
- for (uint i = 0; i < kWidth / 7 * kHeight; ++i) {
- _frameBuf[i] = color;
- color ^= val;
- }
-}
-
-void Display::updateTextSurface() {
- for (uint row = 0; row < 24; ++row)
- for (uint col = 0; col < 40; ++col) {
- int charPos = row * 40 + col;
- char c = _textBuf[row * 40 + col];
-
- if (charPos == _cursorPos && _showCursor)
- c = (c & 0x3f) | 0x40;
-
- Common::Rect r(7 * 2, 8 * 2);
- r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
-
- if (!(c & 0x80)) {
- if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1))
- r.translate(0, 4 * 8 * 2);
- }
-
- _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
- }
-}
-
void Display::drawChar(byte c, int x, int y) {
byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
@@ -361,78 +429,10 @@ void Display::createFont() {
}
}
-void Display::updateScreen() {
- if (_mode == kModeText) {
- g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h);
- } else if (_mode == kModeHires) {
- g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h);
- } else {
- g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2);
- g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2);
- }
-}
-
-void Display::home() {
- memset(_textBuf, APPLECHAR(' '), kTextBufSize);
- _cursorPos = 0;
-}
-
-void Display::moveCursorForward() {
- ++_cursorPos;
-
- if (_cursorPos >= kTextBufSize)
- scrollUp();
-}
-
-void Display::moveCursorBackward() {
- --_cursorPos;
-
- if (_cursorPos < 0)
- _cursorPos = 0;
-}
-
-void Display::moveCursorTo(const Common::Point &pos) {
- _cursorPos = pos.y * 40 + pos.x;
-
- if (_cursorPos >= kTextBufSize)
- error("Cursor position (%i, %i) out of bounds", pos.x, pos.y);
-}
-
-void Display::setCharAtCursor(byte c) {
- _textBuf[_cursorPos] = c;
-}
-
void Display::scrollUp() {
memmove(_textBuf, _textBuf + 40, kTextBufSize - 40);
- memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40);
+ memset(_textBuf + kTextBufSize - 40, APPLECHAR(' '), 40);
_cursorPos -= 40;
}
-void Display::printString(const Common::String &str) {
- Common::String::const_iterator c;
- for (c = str.begin(); c != str.end(); ++c) {
- byte b = *c;
-
- if (*c == APPLECHAR('\r'))
- _cursorPos = (_cursorPos / 40 + 1) * 40;
- else if (b < 0x80 || b >= 0xa0) {
- setCharAtCursor(b);
- ++_cursorPos;
- }
-
- if (_cursorPos == kTextBufSize)
- scrollUp();
- }
-
- updateTextSurface();
-}
-
-void Display::showCursor(bool enable) {
- _showCursor = enable;
-}
-
-void Display::setCursorPos(Common::Point pos) {
- _cursorPos = pos.y * 40 + pos.x;
-}
-
} // End of namespace Adl
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 0452b27..70dc42d 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -24,7 +24,6 @@
#define ADL_DISPLAY_H
#include <common/types.h>
-#include <common/array.h>
namespace Common {
class ReadStream;
@@ -39,6 +38,9 @@ class Surface;
namespace Adl {
+#define DISPLAY_WIDTH 280
+#define DISPLAY_HEIGHT 192
+
#define APPLECHAR(C) ((char)((C) | 0x80))
class Display {
@@ -51,17 +53,20 @@ public:
Display();
~Display();
- void enableScanlines(bool enable);
- void setMonoPalette();
- void setColorPalette();
+
+ void setMode(Mode mode) { _mode = mode; }
+ void updateScreen();
+ bool saveThumbnail(Common::WriteStream &out);
+
+ // Graphics
void loadFrameBuffer(Common::ReadStream &stream);
void decodeFrameBuffer();
- void updateScreen();
- void setMode(Mode mode) { _mode = mode; }
void putPixel(Common::Point p1, byte color);
void clear(byte color);
- void setCursorPos(Common::Point pos);
+ // Text
+ void updateTextSurface();
+ void setCursorPos(Common::Point pos);
void home();
void moveCursorTo(const Common::Point &pos);
void moveCursorForward();
@@ -69,40 +74,33 @@ public:
void printString(const Common::String &str);
void setCharAtCursor(byte c);
void showCursor(bool enable);
- void updateTextSurface();
- bool saveThumbnail(Common::WriteStream &out);
private:
enum {
- kWidth = 280,
- kHeight = 192,
kTextBufSize = 40 * 24
};
- struct PixelPos {
- uint16 rowAddr;
- byte byteOffset;
- byte bitMask;
- };
+ void enableScanlines(bool enable);
+ void decodeScanlineColor(byte *dst, int pitch, byte *src) const;
+ void decodeScanlineMono(byte *dst, int pitch, byte *src) const;
+ void decodeScanline(byte *dst, int pitch, byte *src) const;
- void decodeScanline(byte *dst, int pitch, byte *src);
- void decodeScanlineColor(byte *dst, int pitch, byte *src);
- void decodeScanlineMono(byte *dst, int pitch, byte *src);
void drawChar(byte c, int x, int y);
void createFont();
-
void scrollUp();
- bool _scanlines;
+ Mode _mode;
+
byte *_frameBuf;
- byte *_textBuf;
Graphics::Surface *_frameBufSurface;
+ bool _scanlines;
+ bool _monochrome;
+
+ byte *_textBuf;
Graphics::Surface *_textBufSurface;
Graphics::Surface *_font;
int _cursorPos;
- Mode _mode;
bool _showCursor;
- bool _monochrome;
};
} // End of namespace Adl
Commit: 115e4cab0d3bd18b0e189c7c304e32f122836f75
https://github.com/scummvm/scummvm/commit/115e4cab0d3bd18b0e189c7c304e32f122836f75
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix restoring on restart prompt
Changed paths:
engines/adl/adl.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 90a9a0d..d2d8492 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -291,7 +291,11 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
case IDO_ACT_LOAD:
loadGameState(0);
++offset;
- // Original engine continues processing here (?)
+ // Original engine does not jump out of the loop,
+ // so we don't either.
+ // We reset the restore flag, as the restore game
+ // process is complete
+ _isRestoring = false;
break;
case IDO_ACT_RESTART: {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
@@ -301,6 +305,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
Common::String input = inputString();
_canRestoreNow = false;
+ // If the user restored with the GMM, we break off the restart
if (_isRestoring)
return;
@@ -661,6 +666,7 @@ Common::Error AdlEngine::loadGameState(int slot) {
setTotalPlayTime(playTime);
+ _isRestoring = true;
return Common::kNoError;
}
Commit: ec14c397eec87ee66337a9f15c044b47fec8855d
https://github.com/scummvm/scummvm/commit/ec14c397eec87ee66337a9f15c044b47fec8855d
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up Display class
Changed paths:
engines/adl/adl.cpp
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index d2d8492..99267ba 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -76,7 +76,7 @@ Common::Error AdlEngine::run() {
if (saveSlot >= 0) {
if (loadGameState(saveSlot).getCode() != Common::kNoError)
error("Failed to load save game from slot %i", saveSlot);
- _display->setCursorPos(Common::Point(0, 23));
+ _display->moveCursorTo(Common::Point(0, 23));
_isRestoring = true;
} else {
runIntro();
@@ -472,7 +472,7 @@ bool AdlEngine::canLoadGameStateCurrently() {
}
void AdlEngine::clearScreen() {
- _display->setMode(Display::kModeMixed);
+ _display->setMode(DISPLAY_MODE_MIXED);
_display->clear(0x00);
}
@@ -744,7 +744,7 @@ Common::String AdlEngine::getLine() {
if ((byte)line[0] == ('\r' | 0x80)) {
textMode = !textMode;
- _display->setMode(textMode ? Display::kModeText : Display::kModeMixed);
+ _display->setMode(textMode ? DISPLAY_MODE_TEXT : DISPLAY_MODE_MIXED);
continue;
}
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 55166f4..a75b129 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -90,7 +90,7 @@ static const byte font[64][5] = {
};
Display::Display() :
- _mode(kModeText),
+ _mode(DISPLAY_MODE_TEXT),
_cursorPos(0),
_showCursor(false) {
@@ -135,9 +135,9 @@ Display::~Display() {
}
void Display::updateScreen() {
- if (_mode == kModeText) {
+ if (_mode == DISPLAY_MODE_TEXT) {
g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h);
- } else if (_mode == kModeHires) {
+ } else if (_mode == DISPLAY_MODE_HIRES) {
g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h);
} else {
g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2);
@@ -237,12 +237,6 @@ void Display::updateTextSurface() {
}
}
-
-void Display::setCursorPos(Common::Point pos) {
- _cursorPos = pos.y * 40 + pos.x;
-}
-
-
void Display::home() {
memset(_textBuf, APPLECHAR(' '), kTextBufSize);
_cursorPos = 0;
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 70dc42d..40151c1 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -41,20 +41,20 @@ namespace Adl {
#define DISPLAY_WIDTH 280
#define DISPLAY_HEIGHT 192
+enum DisplayMode {
+ DISPLAY_MODE_HIRES,
+ DISPLAY_MODE_TEXT,
+ DISPLAY_MODE_MIXED
+};
+
#define APPLECHAR(C) ((char)((C) | 0x80))
class Display {
public:
- enum Mode {
- kModeHires,
- kModeText,
- kModeMixed
- };
-
Display();
~Display();
- void setMode(Mode mode) { _mode = mode; }
+ void setMode(DisplayMode mode) { _mode = mode; }
void updateScreen();
bool saveThumbnail(Common::WriteStream &out);
@@ -66,7 +66,6 @@ public:
// Text
void updateTextSurface();
- void setCursorPos(Common::Point pos);
void home();
void moveCursorTo(const Common::Point &pos);
void moveCursorForward();
@@ -89,7 +88,7 @@ private:
void createFont();
void scrollUp();
- Mode _mode;
+ DisplayMode _mode;
byte *_frameBuf;
Graphics::Surface *_frameBufSurface;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 04df01e..6c36922 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -94,7 +94,7 @@ void HiRes1Engine::runIntro() {
error("Failed to open file");
file.seek(IDI_HR1_OFS_LOGO_0);
- _display->setMode(Display::kModeHires);
+ _display->setMode(DISPLAY_MODE_HIRES);
_display->loadFrameBuffer(file);
_display->decodeFrameBuffer();
delay(4000);
@@ -102,7 +102,7 @@ void HiRes1Engine::runIntro() {
if (shouldQuit())
return;
- _display->setMode(Display::kModeText);
+ _display->setMode(DISPLAY_MODE_TEXT);
Common::File basic;
if (!basic.open("MYSTERY.HELLO"))
@@ -130,7 +130,7 @@ void HiRes1Engine::runIntro() {
if (g_engine->shouldQuit())
return;
- _display->setMode(Display::kModeMixed);
+ _display->setMode(DISPLAY_MODE_MIXED);
file.seek(IDI_HR1_OFS_GAME_OR_HELP);
str = readString(file);
@@ -156,7 +156,7 @@ void HiRes1Engine::runIntro() {
};
if (instructions) {
- _display->setMode(Display::kModeText);
+ _display->setMode(DISPLAY_MODE_TEXT);
file.seek(IDI_HR1_OFS_INTRO_TEXT);
const uint pages[] = { 6, 6, 4, 5, 8, 7, 0 };
@@ -178,7 +178,7 @@ void HiRes1Engine::runIntro() {
file.close();
- _display->setMode(Display::kModeMixed);
+ _display->setMode(DISPLAY_MODE_MIXED);
if (!file.open("ADVENTURE"))
error("Failed to open file");
@@ -298,7 +298,7 @@ void HiRes1Engine::restartGame() {
}
void HiRes1Engine::runGame() {
- _display->setMode(Display::kModeMixed);
+ _display->setMode(DISPLAY_MODE_MIXED);
Common::File f;
Commit: e6d478ad150f7eb702f12c8d3a60bfcd416f2b2e
https://github.com/scummvm/scummvm/commit/e6d478ad150f7eb702f12c8d3a60bfcd416f2b2e
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up Display class
Changed paths:
engines/adl/adl.cpp
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 99267ba..313b146 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -312,7 +312,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
_isRestarting = true;
_display->clear(0x00);
- _display->decodeFrameBuffer();
+ _display->updateHiResScreen();
restartGame();
return;
}
@@ -515,9 +515,9 @@ void AdlEngine::showRoom() {
if (!_state.isDark) {
drawPic(curRoom().curPicture);
drawItems();
+ _display->updateHiResScreen();
}
- _display->decodeFrameBuffer();
printMessage(curRoom().description, false);
}
@@ -913,9 +913,7 @@ byte AdlEngine::inputKey() {
};
}
- _display->updateTextSurface();
- _display->updateScreen();
- g_system->updateScreen();
+ _display->updateTextScreen();
g_system->delayMillis(16);
}
@@ -942,8 +940,6 @@ void AdlEngine::delay(uint32 ms) {
}
}
}
- _display->updateScreen();
- g_system->updateScreen();
g_system->delayMillis(16);
}
}
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index a75b129..05c96cf 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -36,10 +36,12 @@
namespace Adl {
+// TODO: Implement partial screen updates
+
#define DISPLAY_PITCH (DISPLAY_WIDTH / 7)
-#define COLOR_PALETTE_SIZE 6
-const byte colorPalette[COLOR_PALETTE_SIZE * 3] = {
+#define COLOR_PALETTE_ENTRIES 6
+const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
0x00, 0x00, 0x00,
0xff, 0xff, 0xff,
0xc7, 0x34, 0xff,
@@ -48,8 +50,8 @@ const byte colorPalette[COLOR_PALETTE_SIZE * 3] = {
0xf2, 0x5e, 0x00
};
-#define MONO_PALETTE_SIZE 2
-const byte monoPalette[MONO_PALETTE_SIZE * 3] = {
+#define MONO_PALETTE_ENTRIES 2
+const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
0x00, 0x00, 0x00,
0x00, 0xc0, 0x01
};
@@ -100,9 +102,9 @@ Display::Display() :
_scanlines = ConfMan.getBool("scanlines");
if (_monochrome)
- g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_SIZE);
+ g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_ENTRIES);
else
- g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_SIZE);
+ g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES);
enableScanlines(_scanlines);
@@ -134,15 +136,35 @@ Display::~Display() {
delete _font;
}
-void Display::updateScreen() {
- if (_mode == DISPLAY_MODE_TEXT) {
+void Display::setMode(DisplayMode mode) {
+ _mode = mode;
+
+ if (_mode == DISPLAY_MODE_TEXT || _mode == DISPLAY_MODE_MIXED)
+ updateTextScreen();
+ if (_mode == DISPLAY_MODE_HIRES || _mode == DISPLAY_MODE_MIXED)
+ updateHiResScreen();
+}
+
+void Display::updateTextScreen() {
+ updateTextSurface();
+
+ if (_mode == DISPLAY_MODE_TEXT)
g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h);
- } else if (_mode == DISPLAY_MODE_HIRES) {
+ else if (_mode == DISPLAY_MODE_MIXED)
+ g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2);
+
+ g_system->updateScreen();
+}
+
+void Display::updateHiResScreen() {
+ updateHiResSurface();
+
+ if (_mode == DISPLAY_MODE_HIRES)
g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h);
- } else {
+ else if (_mode == DISPLAY_MODE_MIXED)
g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2);
- g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2);
- }
+
+ g_system->updateScreen();
}
bool Display::saveThumbnail(Common::WriteStream &out) {
@@ -177,17 +199,6 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) {
}
}
-void Display::decodeFrameBuffer() {
- byte *src = _frameBuf;
- byte *dst = (byte *)_frameBufSurface->getPixels();
-
- for (uint i = 0; i < DISPLAY_HEIGHT; ++i) {
- decodeScanline(dst, _frameBufSurface->pitch, src);
- src += DISPLAY_PITCH;
- dst += _frameBufSurface->pitch * 2;
- }
-}
-
void Display::putPixel(Common::Point p, byte color) {
byte offset = p.x / 7;
@@ -216,27 +227,6 @@ void Display::clear(byte color) {
}
}
-void Display::updateTextSurface() {
- for (uint row = 0; row < 24; ++row)
- for (uint col = 0; col < 40; ++col) {
- int charPos = row * 40 + col;
- char c = _textBuf[row * 40 + col];
-
- if (charPos == _cursorPos && _showCursor)
- c = (c & 0x3f) | 0x40;
-
- Common::Rect r(7 * 2, 8 * 2);
- r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
-
- if (!(c & 0x80)) {
- if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1))
- r.translate(0, 4 * 8 * 2);
- }
-
- _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
- }
-}
-
void Display::home() {
memset(_textBuf, APPLECHAR(' '), kTextBufSize);
_cursorPos = 0;
@@ -279,7 +269,7 @@ void Display::printString(const Common::String &str) {
scrollUp();
}
- updateTextSurface();
+ updateTextScreen();
}
void Display::setCharAtCursor(byte c) {
@@ -291,7 +281,7 @@ void Display::showCursor(bool enable) {
}
void Display::enableScanlines(bool enable) {
- byte pal[6 * 3] = { };
+ byte pal[COLOR_PALETTE_ENTRIES * 3] = { };
if (enable)
g_system->getPaletteManager()->setPalette(pal, 6, 6);
@@ -301,6 +291,17 @@ void Display::enableScanlines(bool enable) {
}
}
+void Display::updateHiResSurface() {
+ byte *src = _frameBuf;
+ byte *dst = (byte *)_frameBufSurface->getPixels();
+
+ for (uint i = 0; i < DISPLAY_HEIGHT; ++i) {
+ decodeScanline(dst, _frameBufSurface->pitch, src);
+ src += DISPLAY_PITCH;
+ dst += _frameBufSurface->pitch * 2;
+ }
+}
+
void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
// TODO: shift secondPal by half a pixel
@@ -370,6 +371,27 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) const {
decodeScanlineColor(dst, pitch, src);
}
+void Display::updateTextSurface() {
+ for (uint row = 0; row < 24; ++row)
+ for (uint col = 0; col < 40; ++col) {
+ int charPos = row * 40 + col;
+ char c = _textBuf[row * 40 + col];
+
+ if (charPos == _cursorPos && _showCursor)
+ c = (c & 0x3f) | 0x40;
+
+ Common::Rect r(7 * 2, 8 * 2);
+ r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
+
+ if (!(c & 0x80)) {
+ if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1))
+ r.translate(0, 4 * 8 * 2);
+ }
+
+ _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
+ }
+}
+
void Display::drawChar(byte c, int x, int y) {
byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 40151c1..16b52bf 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -54,18 +54,17 @@ public:
Display();
~Display();
- void setMode(DisplayMode mode) { _mode = mode; }
- void updateScreen();
+ void setMode(DisplayMode mode);
+ void updateTextScreen();
+ void updateHiResScreen();
bool saveThumbnail(Common::WriteStream &out);
// Graphics
void loadFrameBuffer(Common::ReadStream &stream);
- void decodeFrameBuffer();
void putPixel(Common::Point p1, byte color);
void clear(byte color);
// Text
- void updateTextSurface();
void home();
void moveCursorTo(const Common::Point &pos);
void moveCursorForward();
@@ -79,11 +78,13 @@ private:
kTextBufSize = 40 * 24
};
+ void updateHiResSurface();
void enableScanlines(bool enable);
void decodeScanlineColor(byte *dst, int pitch, byte *src) const;
void decodeScanlineMono(byte *dst, int pitch, byte *src) const;
void decodeScanline(byte *dst, int pitch, byte *src) const;
+ void updateTextSurface();
void drawChar(byte c, int x, int y);
void createFont();
void scrollUp();
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 6c36922..8b5b922 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -96,7 +96,7 @@ void HiRes1Engine::runIntro() {
file.seek(IDI_HR1_OFS_LOGO_0);
_display->setMode(DISPLAY_MODE_HIRES);
_display->loadFrameBuffer(file);
- _display->decodeFrameBuffer();
+ _display->updateHiResScreen();
delay(4000);
if (shouldQuit())
@@ -186,7 +186,7 @@ void HiRes1Engine::runIntro() {
// Title screen shown during loading
file.seek(0x1800);
_display->loadFrameBuffer(file);
- _display->decodeFrameBuffer();
+ _display->updateHiResScreen();
delay(2000);
}
Commit: 6f9128983847d78a41da7cf2f16a1243c7c1fa28
https://github.com/scummvm/scummvm/commit/6f9128983847d78a41da7cf2f16a1243c7c1fa28
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up Display class
Changed paths:
engines/adl/display.cpp
engines/adl/display.h
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 05c96cf..e8ea821 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -106,7 +106,7 @@ Display::Display() :
else
g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES);
- enableScanlines(_scanlines);
+ showScanlines(_scanlines);
_frameBuf = new byte[DISPLAY_PITCH * DISPLAY_HEIGHT];
_frameBufSurface = new Graphics::Surface;
@@ -169,14 +169,14 @@ void Display::updateHiResScreen() {
bool Display::saveThumbnail(Common::WriteStream &out) {
if (_scanlines) {
- enableScanlines(false);
+ showScanlines(false);
g_system->updateScreen();
}
bool retval = Graphics::saveThumbnail(out);
if (_scanlines) {
- enableScanlines(true);
+ showScanlines(true);
g_system->updateScreen();
}
@@ -280,14 +280,14 @@ void Display::showCursor(bool enable) {
_showCursor = enable;
}
-void Display::enableScanlines(bool enable) {
+void Display::showScanlines(bool enable) {
byte pal[COLOR_PALETTE_ENTRIES * 3] = { };
if (enable)
- g_system->getPaletteManager()->setPalette(pal, 6, 6);
+ g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES);
else {
- g_system->getPaletteManager()->grabPalette(pal, 0, 6);
- g_system->getPaletteManager()->setPalette(pal, 6, 6);
+ g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES);
+ g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES);
}
}
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 16b52bf..b93128f 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -79,7 +79,7 @@ private:
};
void updateHiResSurface();
- void enableScanlines(bool enable);
+ void showScanlines(bool enable);
void decodeScanlineColor(byte *dst, int pitch, byte *src) const;
void decodeScanlineMono(byte *dst, int pitch, byte *src) const;
void decodeScanline(byte *dst, int pitch, byte *src) const;
Commit: f5430f961bd937755e85da17d24e8d3f22470545
https://github.com/scummvm/scummvm/commit/f5430f961bd937755e85da17d24e8d3f22470545
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Implement half-pixel shift in color mode
Changed paths:
engines/adl/display.cpp
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index e8ea821..678b8c8 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -36,20 +36,23 @@
namespace Adl {
-// TODO: Implement partial screen updates
+// This implements the Apple II "Hi-Res" display mode
#define DISPLAY_PITCH (DISPLAY_WIDTH / 7)
-#define COLOR_PALETTE_ENTRIES 6
+#define COLOR_PALETTE_ENTRIES 8
const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
0x00, 0x00, 0x00,
0xff, 0xff, 0xff,
0xc7, 0x34, 0xff,
0x38, 0xcb, 0x00,
+ 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff,
0x0d, 0xa1, 0xff,
0xf2, 0x5e, 0x00
};
+// Green monochrome palette
#define MONO_PALETTE_ENTRIES 2
const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
0x00, 0x00, 0x00,
@@ -303,11 +306,12 @@ void Display::updateHiResSurface() {
}
void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
- // TODO: shift secondPal by half a pixel
-
bool prevOn = false;
- for (uint j = 0; j < 39; ++j) {
+ if (src[0] & 0x80)
+ dst++;
+
+ for (uint j = 0; j < 40; ++j) {
bool secondPal = src[j] & 0x80;
byte cur = src[j];
byte next = 0;
@@ -326,19 +330,39 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
byte color;
if (curOn == prevOn || curOn == nextOn)
color = curOn ? 1 : 0;
- else {
- if (secondPal)
- color = (curOn == ((j + k) % 2) ? 5 : 4);
- else
- color = (curOn == ((j + k) % 2) ? 3 : 2);
- }
+ else
+ color = (curOn == ((j + k) % 2) ? 3 : 2);
+
+ if (secondPal)
+ color |= 4;
dst[0] = color;
- dst[1] = color;
- dst[pitch] = color + 6;
- dst[pitch + 1] = color + 6;
+ dst[pitch] = color + COLOR_PALETTE_ENTRIES;
+ ++dst;
+
+ if (k == 6) {
+ if (secondPal) {
+ if (next & 0x80) {
+ dst[0] = color;
+ dst[pitch] = color + COLOR_PALETTE_ENTRIES;
+ ++dst;
+ }
+ } else {
+ dst[0] = color;
+ dst[pitch] = color + COLOR_PALETTE_ENTRIES;
+ ++dst;
+ if (next & 0x80) {
+ dst[0] = color | 4;
+ dst[pitch] = (color | 4) + COLOR_PALETTE_ENTRIES;
+ ++dst;
+ }
+ }
+ } else {
+ dst[0] = color;
+ dst[pitch] = color + COLOR_PALETTE_ENTRIES;
+ ++dst;
+ }
- dst += 2;
prevOn = curOn;
}
}
@@ -397,20 +421,20 @@ void Display::drawChar(byte c, int x, int y) {
for (uint row = 0; row < 8; ++row) {
if (row & 1) {
- buf[_font->pitch] = 6;
- buf[_font->pitch + 1] = 6;
- buf[_font->pitch + 6 * 2] = 6;
- buf[_font->pitch + 6 * 2 + 1] = 6;
+ buf[_font->pitch] = COLOR_PALETTE_ENTRIES;
+ buf[_font->pitch + 1] = COLOR_PALETTE_ENTRIES;
+ buf[_font->pitch + 6 * 2] = COLOR_PALETTE_ENTRIES;
+ buf[_font->pitch + 6 * 2 + 1] = COLOR_PALETTE_ENTRIES;
}
for (uint col = 1; col < 6; ++col) {
if (font[c][col - 1] & (1 << row)) {
buf[col * 2] = 1;
buf[col * 2 + 1] = 1;
- buf[_font->pitch + col * 2] = 1 + 6;
- buf[_font->pitch + col * 2 + 1] = 1 + 6;
+ buf[_font->pitch + col * 2] = 1 + COLOR_PALETTE_ENTRIES;
+ buf[_font->pitch + col * 2 + 1] = 1 + COLOR_PALETTE_ENTRIES;
} else {
- buf[_font->pitch + col * 2] = 6;
- buf[_font->pitch + col * 2 + 1] = 6;
+ buf[_font->pitch + col * 2] = COLOR_PALETTE_ENTRIES;
+ buf[_font->pitch + col * 2 + 1] = COLOR_PALETTE_ENTRIES;
}
}
@@ -438,7 +462,7 @@ void Display::createFont() {
bufInv += _font->pitch;
for (uint col = 0; col < _font->w; ++col)
- bufInv[col] = (buf[col] == 7 ? 6 : 7);
+ bufInv[col] = (buf[col] == COLOR_PALETTE_ENTRIES + 1 ? COLOR_PALETTE_ENTRIES : COLOR_PALETTE_ENTRIES + 1);
buf += _font->pitch;
bufInv += _font->pitch;
Commit: 50d6e6938a60b323e1a1fbe2559e175492625cba
https://github.com/scummvm/scummvm/commit/50d6e6938a60b323e1a1fbe2559e175492625cba
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Refactor graphics code
Changed paths:
engines/adl/display.cpp
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 678b8c8..2a24b65 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -52,6 +52,12 @@ const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
0xf2, 0x5e, 0x00
};
+// Corresponding color in second palette
+#define PAL2(X) ((X) | 0x04)
+
+// Alternate color for odd pixel rows (for scanlines)
+#define ALTCOL(X) ((X) | 0x08)
+
// Green monochrome palette
#define MONO_PALETTE_ENTRIES 2
const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
@@ -294,6 +300,17 @@ void Display::showScanlines(bool enable) {
}
}
+static void copyEvenSurfaceRows(Graphics::Surface &surf) {
+ byte *src = (byte *)surf.getPixels();
+
+ for (uint y = 0; y < surf.h / 2; ++y) {
+ byte *dst = src + surf.pitch;
+ for (uint x = 0; x < surf.w; ++x)
+ dst[x] = ALTCOL(src[x]);
+ src += surf.pitch * 2;
+ }
+}
+
void Display::updateHiResSurface() {
byte *src = _frameBuf;
byte *dst = (byte *)_frameBufSurface->getPixels();
@@ -303,68 +320,78 @@ void Display::updateHiResSurface() {
src += DISPLAY_PITCH;
dst += _frameBufSurface->pitch * 2;
}
+
+ copyEvenSurfaceRows(*_frameBufSurface);
}
-void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
- bool prevOn = false;
+static inline byte processColorBits(uint16 &bits, bool &odd, bool secondPal) {
+ byte color = 0;
+
+ switch (bits & 0x7) {
+ case 0x3: // 011 (white)
+ case 0x6: // 110
+ case 0x7: // 111
+ color = 1;
+ break;
+ case 0x2: // 010 (color)
+ color = 2 + odd;
+ break;
+ case 0x5: // 101 (color)
+ color = 2 + !odd;
+ }
- if (src[0] & 0x80)
- dst++;
+ if (secondPal)
+ color = PAL2(color);
- for (uint j = 0; j < 40; ++j) {
- bool secondPal = src[j] & 0x80;
- byte cur = src[j];
- byte next = 0;
- if (j != 39)
- next = src[j + 1];
+ odd = !odd;
+ bits >>= 1;
- for (uint k = 0; k < 7; ++k) {
- bool curOn = cur & (1 << k);
- bool nextOn;
+ return color;
+}
- if (k != 6)
- nextOn = cur & (1 << (k + 1));
- else
- nextOn = next & 1;
+void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
+ uint16 bits = (src[0] & 0x7f) << 1;
+ byte pal = src[0] >> 7;
- byte color;
- if (curOn == prevOn || curOn == nextOn)
- color = curOn ? 1 : 0;
- else
- color = (curOn == ((j + k) % 2) ? 3 : 2);
+ if (pal != 0)
+ *dst++ = 0;
- if (secondPal)
- color |= 4;
+ bool odd = false;
- dst[0] = color;
- dst[pitch] = color + COLOR_PALETTE_ENTRIES;
- ++dst;
-
- if (k == 6) {
- if (secondPal) {
- if (next & 0x80) {
- dst[0] = color;
- dst[pitch] = color + COLOR_PALETTE_ENTRIES;
- ++dst;
- }
- } else {
- dst[0] = color;
- dst[pitch] = color + COLOR_PALETTE_ENTRIES;
- ++dst;
- if (next & 0x80) {
- dst[0] = color | 4;
- dst[pitch] = (color | 4) + COLOR_PALETTE_ENTRIES;
- ++dst;
- }
- }
- } else {
- dst[0] = color;
- dst[pitch] = color + COLOR_PALETTE_ENTRIES;
- ++dst;
- }
+ for (uint i = 0; i < 40; ++i) {
+ if (i != 39) {
+ bits |= (src[i + 1] & 0x7f) << 8;
+ pal |= (src[i + 1] >> 7) << 1;
+ }
- prevOn = curOn;
+ // For the first 6 bits in the block we draw two pixels
+ for (uint j = 0; j < 6; ++j) {
+ byte color = processColorBits(bits, odd, pal & 1);
+ *dst++ = color;
+ *dst++ = color;
}
+
+ // Last bit of the block, draw one, two or three pixels
+ byte color = processColorBits(bits, odd, pal & 1);
+
+ // Draw the first pixel
+ *dst++ = color;
+
+ switch (pal) {
+ case 0x0:
+ case 0x3:
+ // If palette stays the same, draw a second pixel
+ *dst++ = color;
+ break;
+ case 0x2:
+ // If we're moving from first to second palette,
+ // draw a second pixel, and a third in the second
+ // palette.
+ *dst++ = color;
+ *dst++ = PAL2(color);
+ }
+
+ pal >>= 1;
}
}
@@ -420,21 +447,10 @@ void Display::drawChar(byte c, int x, int y) {
byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
for (uint row = 0; row < 8; ++row) {
- if (row & 1) {
- buf[_font->pitch] = COLOR_PALETTE_ENTRIES;
- buf[_font->pitch + 1] = COLOR_PALETTE_ENTRIES;
- buf[_font->pitch + 6 * 2] = COLOR_PALETTE_ENTRIES;
- buf[_font->pitch + 6 * 2 + 1] = COLOR_PALETTE_ENTRIES;
- }
for (uint col = 1; col < 6; ++col) {
if (font[c][col - 1] & (1 << row)) {
buf[col * 2] = 1;
buf[col * 2 + 1] = 1;
- buf[_font->pitch + col * 2] = 1 + COLOR_PALETTE_ENTRIES;
- buf[_font->pitch + col * 2 + 1] = 1 + COLOR_PALETTE_ENTRIES;
- } else {
- buf[_font->pitch + col * 2] = COLOR_PALETTE_ENTRIES;
- buf[_font->pitch + col * 2 + 1] = COLOR_PALETTE_ENTRIES;
}
}
@@ -458,21 +474,18 @@ void Display::createFont() {
for (uint col = 0; col < _font->w; ++col)
bufInv[col] = (buf[col] ? 0 : 1);
- buf += _font->pitch;
- bufInv += _font->pitch;
-
- for (uint col = 0; col < _font->w; ++col)
- bufInv[col] = (buf[col] == COLOR_PALETTE_ENTRIES + 1 ? COLOR_PALETTE_ENTRIES : COLOR_PALETTE_ENTRIES + 1);
-
- buf += _font->pitch;
- bufInv += _font->pitch;
+ buf += _font->pitch * 2;
+ bufInv += _font->pitch * 2;
}
+
+ copyEvenSurfaceRows(*_font);
}
void Display::scrollUp() {
memmove(_textBuf, _textBuf + 40, kTextBufSize - 40);
memset(_textBuf + kTextBufSize - 40, APPLECHAR(' '), 40);
- _cursorPos -= 40;
+ if (_cursorPos >= 40)
+ _cursorPos -= 40;
}
} // End of namespace Adl
Commit: d3bfdc36578f137352589b8efacc3f4eb24054aa
https://github.com/scummvm/scummvm/commit/d3bfdc36578f137352589b8efacc3f4eb24054aa
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add more #defines to replace literals
Changed paths:
engines/adl/display.cpp
engines/adl/display.h
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 2a24b65..6f72f91 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -39,6 +39,11 @@ namespace Adl {
// This implements the Apple II "Hi-Res" display mode
#define DISPLAY_PITCH (DISPLAY_WIDTH / 7)
+#define DISPLAY_SIZE (DISPLAY_PITCH * DISPLAY_HEIGHT)
+
+#define TEXT_WIDTH 40
+#define TEXT_HEIGHT 24
+#define TEXT_BUF_SIZE (TEXT_WIDTH * TEXT_HEIGHT)
#define COLOR_PALETTE_ENTRIES 8
const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
@@ -117,14 +122,15 @@ Display::Display() :
showScanlines(_scanlines);
- _frameBuf = new byte[DISPLAY_PITCH * DISPLAY_HEIGHT];
+ _frameBuf = new byte[DISPLAY_SIZE];
+ memset(_frameBuf, 0, DISPLAY_SIZE);
_frameBufSurface = new Graphics::Surface;
// We need 2x scaling to properly render the half-pixel shift
// of the second palette
_frameBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8());
- _textBuf = new byte[kTextBufSize];
- memset(_textBuf, APPLECHAR(' '), kTextBufSize);
+ _textBuf = new byte[TEXT_BUF_SIZE];
+ memset(_textBuf, APPLECHAR(' '), TEXT_BUF_SIZE);
_textBufSurface = new Graphics::Surface;
// For ease of copying, also use 2x scaling here
_textBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8());
@@ -193,9 +199,9 @@ bool Display::saveThumbnail(Common::WriteStream &out) {
}
void Display::loadFrameBuffer(Common::ReadStream &stream) {
+ byte *dst = _frameBuf;
for (uint j = 0; j < 8; ++j) {
for (uint i = 0; i < 8; ++i) {
- byte *dst = _frameBuf + DISPLAY_PITCH * (i * 8 + j);
stream.read(dst, DISPLAY_PITCH);
dst += DISPLAY_PITCH * 64;
stream.read(dst, DISPLAY_PITCH);
@@ -203,12 +209,13 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) {
stream.read(dst, DISPLAY_PITCH);
stream.readUint32LE();
stream.readUint32LE();
- dst += DISPLAY_PITCH * 64;
+ dst -= DISPLAY_PITCH * 120;
}
+ dst -= DISPLAY_PITCH * 63;
}
}
-void Display::putPixel(Common::Point p, byte color) {
+void Display::putPixel(const Common::Point &p, byte color) {
byte offset = p.x / 7;
if (offset & 1) {
@@ -230,35 +237,33 @@ void Display::clear(byte color) {
if (c >= 0x40 && c < 0xc0)
val = 0x7f;
- for (uint i = 0; i < DISPLAY_PITCH * DISPLAY_HEIGHT; ++i) {
+ for (uint i = 0; i < DISPLAY_SIZE; ++i) {
_frameBuf[i] = color;
color ^= val;
}
}
void Display::home() {
- memset(_textBuf, APPLECHAR(' '), kTextBufSize);
+ memset(_textBuf, APPLECHAR(' '), TEXT_BUF_SIZE);
_cursorPos = 0;
}
void Display::moveCursorForward() {
++_cursorPos;
- if (_cursorPos >= kTextBufSize)
+ if (_cursorPos >= TEXT_BUF_SIZE)
scrollUp();
}
void Display::moveCursorBackward() {
- --_cursorPos;
-
- if (_cursorPos < 0)
- _cursorPos = 0;
+ if (_cursorPos > 0)
+ --_cursorPos;
}
void Display::moveCursorTo(const Common::Point &pos) {
- _cursorPos = pos.y * 40 + pos.x;
+ _cursorPos = pos.y * TEXT_WIDTH + pos.x;
- if (_cursorPos >= kTextBufSize)
+ if (_cursorPos >= TEXT_BUF_SIZE)
error("Cursor position (%i, %i) out of bounds", pos.x, pos.y);
}
@@ -268,13 +273,13 @@ void Display::printString(const Common::String &str) {
byte b = *c;
if (*c == APPLECHAR('\r'))
- _cursorPos = (_cursorPos / 40 + 1) * 40;
+ _cursorPos = (_cursorPos / TEXT_WIDTH + 1) * TEXT_WIDTH;
else if (b < 0x80 || b >= 0xa0) {
setCharAtCursor(b);
++_cursorPos;
}
- if (_cursorPos == kTextBufSize)
+ if (_cursorPos == TEXT_BUF_SIZE)
scrollUp();
}
@@ -358,8 +363,8 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
bool odd = false;
- for (uint i = 0; i < 40; ++i) {
- if (i != 39) {
+ for (uint i = 0; i < DISPLAY_PITCH; ++i) {
+ if (i != DISPLAY_PITCH - 1) {
bits |= (src[i + 1] & 0x7f) << 8;
pal |= (src[i + 1] >> 7) << 1;
}
@@ -424,9 +429,9 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) const {
void Display::updateTextSurface() {
for (uint row = 0; row < 24; ++row)
- for (uint col = 0; col < 40; ++col) {
- int charPos = row * 40 + col;
- char c = _textBuf[row * 40 + col];
+ for (uint col = 0; col < TEXT_WIDTH; ++col) {
+ uint charPos = row * TEXT_WIDTH + col;
+ char c = _textBuf[row * TEXT_WIDTH + col];
if (charPos == _cursorPos && _showCursor)
c = (c & 0x3f) | 0x40;
@@ -482,10 +487,10 @@ void Display::createFont() {
}
void Display::scrollUp() {
- memmove(_textBuf, _textBuf + 40, kTextBufSize - 40);
- memset(_textBuf + kTextBufSize - 40, APPLECHAR(' '), 40);
- if (_cursorPos >= 40)
- _cursorPos -= 40;
+ memmove(_textBuf, _textBuf + TEXT_WIDTH, TEXT_BUF_SIZE - TEXT_WIDTH);
+ memset(_textBuf + TEXT_BUF_SIZE - TEXT_WIDTH, APPLECHAR(' '), TEXT_WIDTH);
+ if (_cursorPos >= TEXT_WIDTH)
+ _cursorPos -= TEXT_WIDTH;
}
} // End of namespace Adl
diff --git a/engines/adl/display.h b/engines/adl/display.h
index b93128f..102622e 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -61,7 +61,7 @@ public:
// Graphics
void loadFrameBuffer(Common::ReadStream &stream);
- void putPixel(Common::Point p1, byte color);
+ void putPixel(const Common::Point &p, byte color);
void clear(byte color);
// Text
@@ -99,7 +99,7 @@ private:
byte *_textBuf;
Graphics::Surface *_textBufSurface;
Graphics::Surface *_font;
- int _cursorPos;
+ uint _cursorPos;
bool _showCursor;
};
Commit: b2d2f3405e0b36e92402b6c38bc2c406ea960147
https://github.com/scummvm/scummvm/commit/b2d2f3405e0b36e92402b6c38bc2c406ea960147
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Make palettes static
Changed paths:
engines/adl/display.cpp
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 6f72f91..235e42b 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -46,7 +46,7 @@ namespace Adl {
#define TEXT_BUF_SIZE (TEXT_WIDTH * TEXT_HEIGHT)
#define COLOR_PALETTE_ENTRIES 8
-const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
+static const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
0x00, 0x00, 0x00,
0xff, 0xff, 0xff,
0xc7, 0x34, 0xff,
@@ -65,7 +65,7 @@ const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
// Green monochrome palette
#define MONO_PALETTE_ENTRIES 2
-const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
+static const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
0x00, 0x00, 0x00,
0x00, 0xc0, 0x01
};
@@ -110,7 +110,7 @@ Display::Display() :
_cursorPos(0),
_showCursor(false) {
- initGraphics(560, 384, true);
+ initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true);
_monochrome = !ConfMan.getBool("color");
_scanlines = ConfMan.getBool("scanlines");
Commit: 165e333f4f3fbde90f83c6cd8fe587e89e7455d7
https://github.com/scummvm/scummvm/commit/165e333f4f3fbde90f83c6cd8fe587e89e7455d7
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Implement half-pixel shift for monochrome
Changed paths:
engines/adl/display.cpp
engines/adl/display.h
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 235e42b..cc51e4a 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -305,31 +305,7 @@ void Display::showScanlines(bool enable) {
}
}
-static void copyEvenSurfaceRows(Graphics::Surface &surf) {
- byte *src = (byte *)surf.getPixels();
-
- for (uint y = 0; y < surf.h / 2; ++y) {
- byte *dst = src + surf.pitch;
- for (uint x = 0; x < surf.w; ++x)
- dst[x] = ALTCOL(src[x]);
- src += surf.pitch * 2;
- }
-}
-
-void Display::updateHiResSurface() {
- byte *src = _frameBuf;
- byte *dst = (byte *)_frameBufSurface->getPixels();
-
- for (uint i = 0; i < DISPLAY_HEIGHT; ++i) {
- decodeScanline(dst, _frameBufSurface->pitch, src);
- src += DISPLAY_PITCH;
- dst += _frameBufSurface->pitch * 2;
- }
-
- copyEvenSurfaceRows(*_frameBufSurface);
-}
-
-static inline byte processColorBits(uint16 &bits, bool &odd, bool secondPal) {
+static byte processColorBits(uint16 &bits, bool &odd, bool secondPal) {
byte color = 0;
switch (bits & 0x7) {
@@ -354,7 +330,7 @@ static inline byte processColorBits(uint16 &bits, bool &odd, bool secondPal) {
return color;
}
-void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
+static void renderPixelRowColor(byte *dst, byte *src) {
uint16 bits = (src[0] & 0x7f) << 1;
byte pal = src[0] >> 7;
@@ -400,31 +376,65 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const {
}
}
-void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) const {
- // TODO: shift secondPal by half a pixel
+static void renderPixelRowMono(byte *dst, byte *src) {
+ byte pal = src[0] >> 7;
- for (uint j = 0; j < 39; ++j) {
- for (uint k = 0; k < 7; ++k) {
- byte color = 0;
+ if (pal != 0)
+ *dst++ = 0;
+
+ for (uint i = 0; i < DISPLAY_PITCH; ++i) {
+ if (i != DISPLAY_PITCH - 1)
+ pal |= (src[i + 1] >> 7) << 1;
+
+ for (uint j = 0; j < 6; ++j) {
+ bool color = src[i] & (1 << j);
+ *dst++ = color;
+ *dst++ = color;
+ }
- if (src[j] & (1 << k))
- color = 1;
+ bool color = src[i] & (1 << 6);
- dst[0] = color;
- dst[1] = color;
- dst[pitch] = color + 6;
- dst[pitch + 1] = color + 6;
+ *dst++ = color;
- dst += 2;
+ switch (pal) {
+ case 0x0:
+ case 0x3:
+ *dst++ = color;
+ break;
+ case 0x2:
+ *dst++ = color;
+ *dst++ = color;
}
+
+ pal >>= 1;
}
}
-void Display::decodeScanline(byte *dst, int pitch, byte *src) const {
- if (_monochrome)
- decodeScanlineMono(dst, pitch, src);
- else
- decodeScanlineColor(dst, pitch, src);
+static void copyEvenSurfaceRows(Graphics::Surface &surf) {
+ byte *src = (byte *)surf.getPixels();
+
+ for (uint y = 0; y < surf.h / 2; ++y) {
+ byte *dst = src + surf.pitch;
+ for (uint x = 0; x < surf.w; ++x)
+ dst[x] = ALTCOL(src[x]);
+ src += surf.pitch * 2;
+ }
+}
+
+void Display::updateHiResSurface() {
+ byte *src = _frameBuf;
+ byte *dst = (byte *)_frameBufSurface->getPixels();
+
+ for (uint i = 0; i < DISPLAY_HEIGHT; ++i) {
+ if (_monochrome)
+ renderPixelRowMono(dst, src);
+ else
+ renderPixelRowColor(dst, src);
+ src += DISPLAY_PITCH;
+ dst += _frameBufSurface->pitch * 2;
+ }
+
+ copyEvenSurfaceRows(*_frameBufSurface);
}
void Display::updateTextSurface() {
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 102622e..8690659 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -80,9 +80,6 @@ private:
void updateHiResSurface();
void showScanlines(bool enable);
- void decodeScanlineColor(byte *dst, int pitch, byte *src) const;
- void decodeScanlineMono(byte *dst, int pitch, byte *src) const;
- void decodeScanline(byte *dst, int pitch, byte *src) const;
void updateTextSurface();
void drawChar(byte c, int x, int y);
Commit: 1e1a5d4f0761ba22257f59cfd70aeb53a47b0321
https://github.com/scummvm/scummvm/commit/1e1a5d4f0761ba22257f59cfd70aeb53a47b0321
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix darkness setting in a move too late
Changed paths:
engines/adl/adl.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 313b146..c58f28a 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -515,9 +515,9 @@ void AdlEngine::showRoom() {
if (!_state.isDark) {
drawPic(curRoom().curPicture);
drawItems();
- _display->updateHiResScreen();
}
+ _display->updateHiResScreen();
printMessage(curRoom().description, false);
}
Commit: 6379fbc124b63221576206bed070fa2a91b99718
https://github.com/scummvm/scummvm/commit/6379fbc124b63221576206bed070fa2a91b99718
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add more #defines to replace literals
Changed paths:
engines/adl/display.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/display.h b/engines/adl/display.h
index 8690659..ce8f86b 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -74,10 +74,6 @@ public:
void showCursor(bool enable);
private:
- enum {
- kTextBufSize = 40 * 24
- };
-
void updateHiResSurface();
void showScanlines(bool enable);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 8b5b922..d3e4c3e 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -40,6 +40,11 @@
namespace Adl {
+#define IDI_HR1_NUM_ROOMS 41
+#define IDI_HR1_NUM_PICS 98
+#define IDI_HR1_NUM_VARS 20
+#define IDI_HR1_NUM_ITEM_OFFSETS 21
+
// Messages used outside of scripts
#define IDI_HR1_MSG_CANT_GO_THERE 137
#define IDI_HR1_MSG_DONT_UNDERSTAND 37
@@ -73,15 +78,28 @@ static const StringOffset stringOffsets[] = {
{ IDI_HR1_STR_PRESS_RETURN, 0x5f68 }
};
-#define IDI_HR1_OFS_PD_TEXT_0 0x5d
-#define IDI_HR1_OFS_PD_TEXT_1 0x12b
-#define IDI_HR1_OFS_PD_TEXT_2 0x16d
-#define IDI_HR1_OFS_PD_TEXT_3 0x259
+#define IDI_HR1_OFS_PD_TEXT_0 0x005d
+#define IDI_HR1_OFS_PD_TEXT_1 0x012b
+#define IDI_HR1_OFS_PD_TEXT_2 0x016d
+#define IDI_HR1_OFS_PD_TEXT_3 0x0259
+
+#define IDI_HR1_OFS_INTRO_TEXT 0x0066
+#define IDI_HR1_OFS_GAME_OR_HELP 0x000f
+
+#define IDI_HR1_OFS_LOGO_0 0x1003
+#define IDI_HR1_OFS_LOGO_1 0x1800
+
+#define IDI_HR1_OFS_ITEMS 0x0100
+#define IDI_HR1_OFS_ROOMS 0x050a
+#define IDI_HR1_OFS_PICS 0x4b00
+#define IDI_HR1_OFS_CMDS_0 0x3c00
+#define IDI_HR1_OFS_CMDS_1 0x3d00
-#define IDI_HR1_OFS_INTRO_TEXT 0x66
-#define IDI_HR1_OFS_GAME_OR_HELP 0xf
+#define IDI_HR1_OFS_ITEM_OFFSETS 0x68ff
+#define IDI_HR1_OFS_LINE_ART 0x4f00
-#define IDI_HR1_OFS_LOGO_0 0x1003
+#define IDI_HR1_OFS_VERBS 0x3800
+#define IDI_HR1_OFS_NOUNS 0x0f00
HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine(syst, gd) {
@@ -184,7 +202,7 @@ void HiRes1Engine::runIntro() {
error("Failed to open file");
// Title screen shown during loading
- file.seek(0x1800);
+ file.seek(IDI_HR1_OFS_LOGO_1);
_display->loadFrameBuffer(file);
_display->updateHiResScreen();
delay(2000);
@@ -246,15 +264,15 @@ void HiRes1Engine::initState() {
_state.isDark = false;
_state.vars.clear();
- _state.vars.resize(20);
+ _state.vars.resize(IDI_HR1_NUM_VARS);
if (!f.open("ADVENTURE"))
error("Failed to open file");
// Load room data from executable
_state.rooms.clear();
- f.seek(0x50a);
- for (uint i = 0; i < MH_ROOMS; ++i) {
+ f.seek(IDI_HR1_OFS_ROOMS);
+ for (uint i = 0; i < IDI_HR1_NUM_ROOMS; ++i) {
Room room;
f.readByte();
room.description = f.readByte();
@@ -265,9 +283,9 @@ void HiRes1Engine::initState() {
_state.rooms.push_back(room);
}
- // Load inventory data from executable
+ // Load item data from executable
_state.items.clear();
- f.seek(0x100);
+ f.seek(IDI_HR1_OFS_ITEMS);
while (f.readByte() != 0xff) {
Item item;
item.noun = f.readByte();
@@ -321,8 +339,8 @@ void HiRes1Engine::runGame() {
}
// Load picture data from executable
- f.seek(0x4b00);
- for (uint i = 0; i < MH_PICS; ++i) {
+ f.seek(IDI_HR1_OFS_PICS);
+ for (uint i = 0; i < IDI_HR1_NUM_PICS; ++i) {
struct Picture pic;
pic.block = f.readByte();
pic.offset = f.readUint16LE();
@@ -330,15 +348,15 @@ void HiRes1Engine::runGame() {
}
// Load commands from executable
- f.seek(0x3D00);
+ f.seek(IDI_HR1_OFS_CMDS_1);
readCommands(f, _roomCommands);
- f.seek(0x3C00);
+ f.seek(IDI_HR1_OFS_CMDS_0);
readCommands(f, _globalCommands);
// Load dropped item offsets
- f.seek(0x68ff);
- for (uint i = 0; i < MH_ITEM_OFFSETS; ++i) {
+ f.seek(IDI_HR1_OFS_ITEM_OFFSETS);
+ for (uint i = 0; i < IDI_HR1_NUM_ITEM_OFFSETS; ++i) {
Common::Point p;
p.x = f.readByte();
p.y = f.readByte();
@@ -346,12 +364,12 @@ void HiRes1Engine::runGame() {
}
// Load right-angle line art
- f.seek(0x4f00);
+ f.seek(IDI_HR1_OFS_LINE_ART);
uint16 lineArtTotal = f.readUint16LE();
for (uint i = 0; i < lineArtTotal; ++i) {
- f.seek(0x4f00 + 2 + i * 2);
+ f.seek(IDI_HR1_OFS_LINE_ART + 2 + i * 2);
uint16 offset = f.readUint16LE();
- f.seek(0x4f00 + offset);
+ f.seek(IDI_HR1_OFS_LINE_ART + offset);
Common::Array<byte> lineArt;
byte b = f.readByte();
@@ -362,10 +380,10 @@ void HiRes1Engine::runGame() {
_lineArt.push_back(lineArt);
}
- f.seek(0x3800);
+ f.seek(IDI_HR1_OFS_VERBS);
loadVerbs(f);
- f.seek(0xf00);
+ f.seek(IDI_HR1_OFS_NOUNS);
loadNouns(f);
printASCIIString("\r\r\r\r\r");
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index cae5980..f5c6d5b 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef ADL_ADL_V1_H
-#define ADL_ADL_V1_H
+#ifndef ADL_HIRES1_H
+#define ADL_HIRES1_H
#include "adl/adl.h"
@@ -31,10 +31,6 @@ class ReadStream;
namespace Adl {
-enum {
- IDI_HR1_MSG_
-};
-
class HiRes1Engine : public AdlEngine {
public:
HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
@@ -43,12 +39,6 @@ protected:
void runGame();
private:
- enum {
- MH_ROOMS = 41,
- MH_PICS = 98,
- MH_ITEM_OFFSETS = 21
- };
-
void restartGame();
void printMessage(uint idx, bool wait = true);
uint getEngineMessage(EngineMessage msg);
Commit: f62c56e38475ccab0c94db949a14991e5423fc13
https://github.com/scummvm/scummvm/commit/f62c56e38475ccab0c94db949a14991e5423fc13
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up line drawing
Changed paths:
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index d3e4c3e..1345489 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -20,20 +20,11 @@
*
*/
-#include "common/scummsys.h"
-
-#include "common/config-manager.h"
+#include "common/system.h"
#include "common/debug.h"
-#include "common/debug-channels.h"
#include "common/error.h"
#include "common/file.h"
-#include "common/fs.h"
-#include "common/system.h"
-#include "common/events.h"
#include "common/stream.h"
-#include "graphics/palette.h"
-
-#include "engines/util.h"
#include "adl/hires1.h"
#include "adl/display.h"
@@ -208,7 +199,7 @@ void HiRes1Engine::runIntro() {
delay(2000);
}
-void HiRes1Engine::drawPic(Common::ReadStream &stream, Common::Point pos) {
+void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos) {
byte x, y;
bool bNewLine = false;
byte oldX = 0, oldY = 0;
@@ -473,38 +464,39 @@ uint HiRes1Engine::getEngineMessage(EngineMessage msg) {
}
}
-void HiRes1Engine::drawLine(Common::Point p1, Common::Point p2, byte color) {
+void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) {
int16 deltaX = p2.x - p1.x;
- byte dir = deltaX >> 8;
+ int8 xStep = 1;
- if (deltaX < 0)
+ if (deltaX < 0) {
deltaX = -deltaX;
+ xStep = -1;
+ }
- int16 err = deltaX;
+ int16 deltaY = p2.y - p1.y;
+ int8 yStep = -1;
- int16 deltaY = p2.y - p1.y - 1;
- dir >>= 1;
- if (deltaY >= 0) {
- deltaY = -deltaY - 2;
- dir |= 0x80;
+ if (deltaY > 0) {
+ deltaY = -deltaY;
+ yStep = 1;
}
- int16 steps = deltaY - deltaX;
-
- err += deltaY + 1;
+ Common::Point p(p1);
+ int16 steps = deltaX - deltaY + 1;
+ int16 err = deltaX + deltaY;
while (1) {
- _display->putPixel(p1, color);
+ _display->putPixel(p, color);
- if (++steps == 0)
+ if (--steps == 0)
return;
if (err < 0) {
- p1.y += (dir & 0x80 ? 1 : -1);
+ p.y += yStep;
err += deltaX;
} else {
- p1.x += (dir & 0x40 ? -1 : 1);
- err += deltaY + 1;
+ p.x += xStep;
+ err += deltaY;
}
}
}
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index f5c6d5b..12c3c94 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -45,9 +45,9 @@ private:
void initState();
void runIntro();
- void drawPic(Common::ReadStream &stream, Common::Point pos);
+ void drawPic(Common::ReadStream &stream, const Common::Point &pos);
void drawItems();
- void drawLine(Common::Point p1, Common::Point p2, byte color);
+ void drawLine(const Common::Point &p1, const Common::Point &p2, byte color);
void drawPic(byte pic, Common::Point pos);
};
Commit: af42795ffa9331a16c1c6fa819f5c3960fd3cfe1
https://github.com/scummvm/scummvm/commit/af42795ffa9331a16c1c6fa819f5c3960fd3cfe1
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Improve error messages
Changed paths:
engines/adl/adl.cpp
engines/adl/display.cpp
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index c58f28a..c395fbb 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -94,7 +94,10 @@ Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) {
while (1) {
byte b = stream.readByte();
- if (stream.eos() || stream.err() || b == until)
+ if (stream.eos() || stream.err())
+ error("Error reading string");
+
+ if (b == until)
break;
str += b;
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index cc51e4a..7af6f66 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -213,6 +213,9 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) {
}
dst -= DISPLAY_PITCH * 63;
}
+
+ if (stream.eos() || stream.err())
+ error("Failed to read frame buffer");
}
void Display::putPixel(const Common::Point &p, byte color) {
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 1345489..9140780 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -31,10 +31,16 @@
namespace Adl {
-#define IDI_HR1_NUM_ROOMS 41
-#define IDI_HR1_NUM_PICS 98
-#define IDI_HR1_NUM_VARS 20
-#define IDI_HR1_NUM_ITEM_OFFSETS 21
+#define IDS_HR1_EXE_0 "AUTO LOAD OBJ"
+#define IDS_HR1_EXE_1 "ADVENTURE"
+#define IDS_HR1_LOADER "MYSTERY.HELLO"
+#define IDS_HR1_MESSAGES "MESSAGES"
+
+#define IDI_HR1_NUM_ROOMS 41
+#define IDI_HR1_NUM_PICS 98
+#define IDI_HR1_NUM_VARS 20
+#define IDI_HR1_NUM_ITEM_OFFSETS 21
+#define IDI_HR1_NUM_MESSAGES 167
// Messages used outside of scripts
#define IDI_HR1_MSG_CANT_GO_THERE 137
@@ -99,8 +105,8 @@ HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
void HiRes1Engine::runIntro() {
Common::File file;
- if (!file.open("AUTO LOAD OBJ"))
- error("Failed to open file");
+ if (!file.open(IDS_HR1_EXE_0))
+ error("Failed to open file '" IDS_HR1_EXE_0 "'");
file.seek(IDI_HR1_OFS_LOGO_0);
_display->setMode(DISPLAY_MODE_HIRES);
@@ -114,8 +120,8 @@ void HiRes1Engine::runIntro() {
_display->setMode(DISPLAY_MODE_TEXT);
Common::File basic;
- if (!basic.open("MYSTERY.HELLO"))
- error("Failed to open file");
+ if (!basic.open(IDS_HR1_LOADER))
+ error("Failed to open file '" IDS_HR1_LOADER "'");
Common::String str;
@@ -189,8 +195,8 @@ void HiRes1Engine::runIntro() {
_display->setMode(DISPLAY_MODE_MIXED);
- if (!file.open("ADVENTURE"))
- error("Failed to open file");
+ if (!file.open(IDS_HR1_EXE_1))
+ error("Failed to open file '" IDS_HR1_EXE_1 "'");
// Title screen shown during loading
file.seek(IDI_HR1_OFS_LOGO_1);
@@ -241,7 +247,7 @@ void HiRes1Engine::drawPic(byte pic, Common::Point pos) {
Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
if (!f.open(name))
- error("Failed to open file");
+ error("Failed to open file '%s'", name.c_str());
f.seek(_pictures[pic].offset);
drawPic(f, pos);
@@ -257,8 +263,8 @@ void HiRes1Engine::initState() {
_state.vars.clear();
_state.vars.resize(IDI_HR1_NUM_VARS);
- if (!f.open("ADVENTURE"))
- error("Failed to open file");
+ if (!f.open(IDS_HR1_EXE_1))
+ error("Failed to open file '" IDS_HR1_EXE_1 "'");
// Load room data from executable
_state.rooms.clear();
@@ -311,16 +317,16 @@ void HiRes1Engine::runGame() {
Common::File f;
- if (!f.open("MESSAGES"))
- error("Failed to open file");
+ if (!f.open(IDS_HR1_MESSAGES))
+ error("Failed to open file '" IDS_HR1_MESSAGES "'");
- while (!f.eos() && !f.err())
+ for (uint i = 0; i < IDI_HR1_NUM_MESSAGES; ++i)
_messages.push_back(readString(f, APPLECHAR('\r')) + APPLECHAR('\r'));
f.close();
- if (!f.open("ADVENTURE"))
- error("Failed to open file");
+ if (!f.open(IDS_HR1_EXE_1))
+ error("Failed to open file '" IDS_HR1_EXE_1 "'");
// Load strings from executable
_strings.resize(IDI_HR1_STR_TOTAL);
@@ -371,6 +377,9 @@ void HiRes1Engine::runGame() {
_lineArt.push_back(lineArt);
}
+ if (f.eos() || f.err())
+ error("Failed to read game data from '" IDS_HR1_EXE_1 "'");
+
f.seek(IDI_HR1_OFS_VERBS);
loadVerbs(f);
@@ -465,6 +474,8 @@ uint HiRes1Engine::getEngineMessage(EngineMessage msg) {
}
void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) {
+ // This draws a four-connected line
+
int16 deltaX = p2.x - p1.x;
int8 xStep = 1;
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 12c3c94..64cf8f3 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -27,6 +27,7 @@
namespace Common {
class ReadStream;
+class Point;
}
namespace Adl {
@@ -35,9 +36,6 @@ class HiRes1Engine : public AdlEngine {
public:
HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
-protected:
- void runGame();
-
private:
void restartGame();
void printMessage(uint idx, bool wait = true);
@@ -45,6 +43,7 @@ private:
void initState();
void runIntro();
+ void runGame();
void drawPic(Common::ReadStream &stream, const Common::Point &pos);
void drawItems();
void drawLine(const Common::Point &p1, const Common::Point &p2, byte color);
Commit: a73dcdf224ae88c7bcf73d754781052835af4cd0
https://github.com/scummvm/scummvm/commit/a73dcdf224ae88c7bcf73d754781052835af4cd0
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move functionality into base class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index c395fbb..701f902 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -72,6 +72,8 @@ bool AdlEngine::hasFeature(EngineFeature f) const {
Common::Error AdlEngine::run() {
_display = new Display();
+ loadData();
+
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot >= 0) {
if (loadGameState(saveSlot).getCode() != Common::kNoError)
@@ -83,7 +85,54 @@ Common::Error AdlEngine::run() {
initState();
}
- runGame();
+ _display->setMode(DISPLAY_MODE_MIXED);
+ printASCIIString("\r\r\r\r\r");
+
+ while (1) {
+ uint verb = 0, noun = 0;
+
+ // When restoring from the launcher, we don't read
+ // input on the first iteration. This is needed to
+ // ensure that restoring from the launcher and
+ // restoring in-game brings us to the same game state.
+ // (Also see comment below.)
+ if (!_isRestoring) {
+ clearScreen();
+ showRoom();
+
+ _canSaveNow = _canRestoreNow = true;
+ getInput(verb, noun);
+ _canSaveNow = _canRestoreNow = false;
+
+ if (shouldQuit())
+ break;
+
+ if (!doOneCommand(_roomCommands, verb, noun))
+ printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
+ }
+
+ if (_isRestoring) {
+ // We restored from the GMM or launcher. As restoring
+ // with "RESTORE GAME" does not end command processing,
+ // we don't break it off here either. This essentially
+ // means that restoring a game will always run through
+ // the global commands and increase the move counter
+ // before the first user input.
+ printASCIIString("\r");
+ _isRestoring = false;
+ verb = _restoreVerb;
+ noun = _restoreNoun;
+ }
+
+ // Restarting does end command processing
+ if (_isRestarting) {
+ _isRestarting = false;
+ continue;
+ }
+
+ doAllCommands(_globalCommands, verb, noun);
+ _state.moves++;
+ }
return Common::kNoError;
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 84b9214..66a5395 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -180,7 +180,8 @@ protected:
typedef Common::HashMap<Common::String, uint> WordMap;
virtual void runIntro() { }
- virtual void runGame() = 0;
+ virtual void loadData() = 0;
+ void runGame();
virtual void initState() = 0;
virtual void restartGame() = 0;
virtual uint getEngineMessage(EngineMessage msg) = 0;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 9140780..11d576b 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -312,9 +312,7 @@ void HiRes1Engine::restartGame() {
printASCIIString("\r\r\r\r\r");
}
-void HiRes1Engine::runGame() {
- _display->setMode(DISPLAY_MODE_MIXED);
-
+void HiRes1Engine::loadData() {
Common::File f;
if (!f.open(IDS_HR1_MESSAGES))
@@ -385,54 +383,6 @@ void HiRes1Engine::runGame() {
f.seek(IDI_HR1_OFS_NOUNS);
loadNouns(f);
-
- printASCIIString("\r\r\r\r\r");
-
- while (1) {
- uint verb = 0, noun = 0;
-
- // When restoring from the launcher, we don't read
- // input on the first iteration. This is needed to
- // ensure that restoring from the launcher and
- // restoring in-game brings us to the same game state.
- // (Also see comment below.)
- if (!_isRestoring) {
- clearScreen();
- showRoom();
-
- _canSaveNow = _canRestoreNow = true;
- getInput(verb, noun);
- _canSaveNow = _canRestoreNow = false;
-
- if (shouldQuit())
- return;
-
- if (!doOneCommand(_roomCommands, verb, noun))
- printMessage(IDI_HR1_MSG_DONT_UNDERSTAND);
- }
-
- if (_isRestoring) {
- // We restored from the GMM or launcher. As restoring
- // with "RESTORE GAME" does not end command processing,
- // we don't break it off here either. This essentially
- // means that restoring a game will always run through
- // the global commands and increase the move counter
- // before the first user input.
- printASCIIString("\r");
- _isRestoring = false;
- verb = _restoreVerb;
- noun = _restoreNoun;
- }
-
- // Restarting does end command processing
- if (_isRestarting) {
- _isRestarting = false;
- continue;
- }
-
- doAllCommands(_globalCommands, verb, noun);
- _state.moves++;
- }
}
void HiRes1Engine::printMessage(uint idx, bool wait) {
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 64cf8f3..f72093a 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -43,7 +43,7 @@ private:
void initState();
void runIntro();
- void runGame();
+ void loadData();
void drawPic(Common::ReadStream &stream, const Common::Point &pos);
void drawItems();
void drawLine(const Common::Point &p1, const Common::Point &p2, byte color);
Commit: 0ec3ab142244cbaf24f0f6c97a931d0d073d4f97
https://github.com/scummvm/scummvm/commit/0ec3ab142244cbaf24f0f6c97a931d0d073d4f97
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix const'ness
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 701f902..e0c0b3a 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -137,7 +137,7 @@ Common::Error AdlEngine::run() {
return Common::kNoError;
}
-Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) {
+Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) const {
Common::String str;
while (1) {
@@ -155,7 +155,7 @@ Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) {
return str;
}
-void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) {
+void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) const {
while (1) {
Common::String str = readString(stream);
_display->printString(str);
@@ -167,11 +167,11 @@ void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) {
};
}
-Common::String AdlEngine::getEngineString(int str) {
+Common::String AdlEngine::getEngineString(int str) const {
return _strings[str];
}
-void AdlEngine::wordWrap(Common::String &str) {
+void AdlEngine::wordWrap(Common::String &str) const {
uint end = 39;
while (1) {
@@ -186,7 +186,7 @@ void AdlEngine::wordWrap(Common::String &str) {
}
}
-void AdlEngine::printMessage(uint idx, bool wait) {
+void AdlEngine::printMessage(uint idx, bool wait) const {
Common::String msg = _messages[idx - 1];
wordWrap(msg);
_display->printString(msg);
@@ -195,7 +195,7 @@ void AdlEngine::printMessage(uint idx, bool wait) {
delay(14 * 166018 / 1000);
}
-void AdlEngine::printEngineMessage(EngineMessage msg) {
+void AdlEngine::printEngineMessage(EngineMessage msg) const {
printMessage(getEngineMessage(msg));
}
@@ -423,7 +423,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
}
}
-bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, bool run) {
+bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, uint *actions) const {
if (command.room != IDI_NONE && command.room != _state.room)
return false;
@@ -466,8 +466,7 @@ bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, bool
}
}
- if (run)
- doActions(command, noun, offset);
+ *actions = offset;
return true;
}
@@ -477,9 +476,13 @@ bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, bool
bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
- for (cmd = commands.begin(); cmd != commands.end(); ++cmd)
- if (matchCommand(*cmd, verb, noun))
+ for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
+ uint offset = 0;
+ if (matchCommand(*cmd, verb, noun, &offset)) {
+ doActions(*cmd, noun, offset);
return true;
+ }
+ }
return false;
}
@@ -489,7 +492,9 @@ void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
bool oldIsRestoring = _isRestoring;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
- matchCommand(*cmd, verb, noun);
+ uint offset = 0;
+ if (matchCommand(*cmd, verb, noun, &offset))
+ doActions(*cmd, noun, offset);
// We assume no restarts happen in this command group. This
// simplifies enabling GMM savegame loading on the restart
@@ -499,7 +504,7 @@ void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
}
}
-bool AdlEngine::canSaveGameStateCurrently() {
+bool AdlEngine::canSaveGameStateCurrently() const {
if (!_canSaveNow)
return false;
@@ -509,7 +514,7 @@ bool AdlEngine::canSaveGameStateCurrently() {
// "SAVE GAME". This prevents saving via the GMM in situations where
// it wouldn't otherwise be possible to do so.
for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
- if (matchCommand(*cmd, _saveVerb, _saveNoun, false)) {
+ if (matchCommand(*cmd, _saveVerb, _saveNoun)) {
if (cmd->verb != _saveVerb || cmd->noun != _saveNoun)
return false;
return cmd->numCond == 0 && cmd->script[0] == IDO_ACT_SAVE;
@@ -519,16 +524,16 @@ bool AdlEngine::canSaveGameStateCurrently() {
return false;
}
-bool AdlEngine::canLoadGameStateCurrently() {
+bool AdlEngine::canLoadGameStateCurrently() const {
return _canRestoreNow;
}
-void AdlEngine::clearScreen() {
+void AdlEngine::clearScreen() const {
_display->setMode(DISPLAY_MODE_MIXED);
_display->clear(0x00);
}
-void AdlEngine::drawItems() {
+void AdlEngine::drawItems() const {
Common::Array<Item>::const_iterator item;
uint dropped = 0;
@@ -563,7 +568,7 @@ void AdlEngine::drawItems() {
}
}
-void AdlEngine::showRoom() {
+void AdlEngine::showRoom() const {
if (!_state.isDark) {
drawPic(curRoom().curPicture);
drawItems();
@@ -722,6 +727,13 @@ Common::Error AdlEngine::loadGameState(int slot) {
return Common::kNoError;
}
+const Room &AdlEngine::room(uint i) const {
+ if (i < 1 || i > _state.rooms.size())
+ error("Room %i out of range [1, %i]", i, _state.rooms.size());
+
+ return _state.rooms[i - 1];
+}
+
Room &AdlEngine::room(uint i) {
if (i < 1 || i > _state.rooms.size())
error("Room %i out of range [1, %i]", i, _state.rooms.size());
@@ -729,10 +741,21 @@ Room &AdlEngine::room(uint i) {
return _state.rooms[i - 1];
}
+const Room &AdlEngine::curRoom() const {
+ return room(_state.room);
+}
+
Room &AdlEngine::curRoom() {
return room(_state.room);
}
+const Item &AdlEngine::item(uint i) const {
+ if (i < 1 || i > _state.items.size())
+ error("Item %i out of range [1, %i]", i, _state.items.size());
+
+ return _state.items[i - 1];
+}
+
Item &AdlEngine::item(uint i) {
if (i < 1 || i > _state.items.size())
error("Item %i out of range [1, %i]", i, _state.items.size());
@@ -740,6 +763,13 @@ Item &AdlEngine::item(uint i) {
return _state.items[i - 1];
}
+const byte &AdlEngine::var(uint i) const {
+ if (i >= _state.vars.size())
+ error("Variable %i out of range [0, %i]", i, _state.vars.size() - 1);
+
+ return _state.vars[i];
+}
+
byte &AdlEngine::var(uint i) {
if (i >= _state.vars.size())
error("Variable %i out of range [0, %i]", i, _state.vars.size() - 1);
@@ -783,7 +813,7 @@ void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) {
}
}
-Common::String AdlEngine::getLine() {
+Common::String AdlEngine::getLine() const {
// Original engine uses a global here, which isn't reset between
// calls and may not match actual mode
bool textMode = false;
@@ -806,7 +836,7 @@ Common::String AdlEngine::getLine() {
}
}
-Common::String AdlEngine::getWord(const Common::String &line, uint &index) {
+Common::String AdlEngine::getWord(const Common::String &line, uint &index) const {
Common::String str;
for (uint i = 0; i < 8; ++i)
@@ -873,7 +903,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
}
}
-void AdlEngine::printASCIIString(const Common::String &str) {
+void AdlEngine::printASCIIString(const Common::String &str) const {
Common::String aStr;
Common::String::const_iterator it;
@@ -883,7 +913,7 @@ void AdlEngine::printASCIIString(const Common::String &str) {
_display->printString(aStr);
}
-Common::String AdlEngine::inputString(byte prompt) {
+Common::String AdlEngine::inputString(byte prompt) const {
Common::String s;
if (prompt > 0)
@@ -921,7 +951,7 @@ Common::String AdlEngine::inputString(byte prompt) {
}
}
-byte AdlEngine::convertKey(uint16 ascii) {
+byte AdlEngine::convertKey(uint16 ascii) const {
ascii = toupper(ascii);
if (ascii >= 0x80)
@@ -935,7 +965,7 @@ byte AdlEngine::convertKey(uint16 ascii) {
return 0;
}
-byte AdlEngine::inputKey() {
+byte AdlEngine::inputKey() const {
Common::EventManager *ev = g_system->getEventManager();
byte key = 0;
@@ -974,7 +1004,7 @@ byte AdlEngine::inputKey() {
return key;
}
-void AdlEngine::delay(uint32 ms) {
+void AdlEngine::delay(uint32 ms) const {
Common::EventManager *ev = g_system->getEventManager();
uint32 start = g_system->getMillis();
@@ -996,10 +1026,9 @@ void AdlEngine::delay(uint32 ms) {
}
}
-void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) {
- if (bits & 4) {
+void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const {
+ if (bits & 4)
_display->putPixel(p, color);
- }
bits += quadrant;
@@ -1009,7 +1038,7 @@ void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quad
p.y += (bits & 2 ? 1 : -1);
}
-void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation, byte scaling, byte color) {
+void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation, byte scaling, byte color) const {
const byte stepping[] = {
0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 66a5395..5afcb0f 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -161,71 +161,30 @@ struct State {
};
typedef Common::List<Command> Commands;
+typedef Common::HashMap<Common::String, uint> WordMap;
class AdlEngine : public Engine {
public:
- AdlEngine(OSystem *syst, const AdlGameDescription *gd);
virtual ~AdlEngine();
- const AdlGameDescription *_gameDescription;
- bool hasFeature(EngineFeature f) const;
- const char *getGameId() const;
-
static AdlEngine *create(GameType type, OSystem *syst, const AdlGameDescription *gd);
- Common::Error run();
- virtual Common::String getEngineString(int str);
-
protected:
- typedef Common::HashMap<Common::String, uint> WordMap;
+ AdlEngine(OSystem *syst, const AdlGameDescription *gd);
- virtual void runIntro() { }
- virtual void loadData() = 0;
- void runGame();
- virtual void initState() = 0;
- virtual void restartGame() = 0;
- virtual uint getEngineMessage(EngineMessage msg) = 0;
- bool canSaveGameStateCurrently();
- bool canLoadGameStateCurrently();
- Common::String readString(Common::ReadStream &stream, byte until = 0);
- void printStrings(Common::SeekableReadStream &stream, int count = 1);
- virtual void printMessage(uint idx, bool wait = true);
- void wordWrap(Common::String &str);
- void readCommands(Common::ReadStream &stream, Commands &commands);
- bool matchCommand(const Command &command, byte verb, byte noun, bool run = true);
- bool doOneCommand(const Commands &commands, byte verb, byte noun);
- void doAllCommands(const Commands &commands, byte verb, byte noun);
- void doActions(const Command &command, byte noun, byte offset);
- void clearScreen();
- virtual void drawPic(byte pic, Common::Point pos = Common::Point()) = 0;
- void drawItems();
- void drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant);
- void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f);
- void showRoom();
- void takeItem(byte noun);
- void dropItem(byte noun);
- Room &room(uint i);
- Room &curRoom();
- Item &item(uint i);
- byte &var(uint i);
+ Common::String readString(Common::ReadStream &stream, byte until = 0) const;
+ void printStrings(Common::SeekableReadStream &stream, int count = 1) const;
+ void printMessage(uint idx, bool wait = true) const;
+ void printASCIIString(const Common::String &str) const;
void loadVerbs(Common::ReadStream &stream) { loadWords(stream, _verbs); }
void loadNouns(Common::ReadStream &stream) { loadWords(stream, _nouns); }
- void getInput(uint &verb, uint &noun);
- void loadWords(Common::ReadStream &stream, WordMap &map);
- Common::String getLine();
- Common::String getWord(const Common::String &line, uint &index);
- void printASCIIString(const Common::String &str);
- Common::String inputString(byte prompt = 0);
- void delay(uint32 ms);
- byte inputKey();
- Common::Error loadGameState(int slot);
- Common::Error saveGameState(int slot, const Common::String &desc);
+ void readCommands(Common::ReadStream &stream, Commands &commands);
+ Common::String inputString(byte prompt = 0) const;
+ void delay(uint32 ms) const;
+ byte inputKey() const;
Display *_display;
Parser *_parser;
- bool _isRestarting, _isRestoring;
- byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
- bool _canSaveNow, _canRestoreNow;
Common::Array<Common::String> _strings;
Common::Array<Common::String> _messages;
@@ -239,14 +198,64 @@ protected:
State _state;
private:
- void printEngineMessage(EngineMessage);
- Common::String getTargetName() { return _targetName; }
- byte convertKey(uint16 ascii);
+ virtual void runIntro() { }
+ virtual void loadData() = 0;
+ virtual void initState() = 0;
+ virtual void restartGame() = 0;
+ virtual uint getEngineMessage(EngineMessage msg) const = 0;
+ virtual void drawPic(byte pic, Common::Point pos = Common::Point()) const = 0;
+
+ // Engine
+ Common::Error run();
+ bool hasFeature(EngineFeature f) const;
+ Common::Error loadGameState(int slot);
+ bool canLoadGameStateCurrently() const;
+ Common::Error saveGameState(int slot, const Common::String &desc);
+ bool canSaveGameStateCurrently() const;
+
+ // Text output
+ Common::String getEngineString(int str) const;
+ void printEngineMessage(EngineMessage) const;
+ void wordWrap(Common::String &str) const;
+
+ // Text input
+ void loadWords(Common::ReadStream &stream, WordMap &map);
+ byte convertKey(uint16 ascii) const;
+ Common::String getLine() const;
+ Common::String getWord(const Common::String &line, uint &index) const;
+ void getInput(uint &verb, uint &noun);
+
+ // Graphics
+ void showRoom() const;
+ void clearScreen() const;
+ void drawItems() const;
+ void drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const;
+ void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const;
+
+ // Game state functions
+ const Room &room(uint i) const;
+ Room &room(uint i);
+ const Room &curRoom() const;
+ Room &curRoom();
+ const Item &item(uint i) const;
+ Item &item(uint i);
+ const byte &var(uint i) const;
+ byte &var(uint i);
+ void takeItem(byte noun);
+ void dropItem(byte noun);
+ bool matchCommand(const Command &command, byte verb, byte noun, uint *actions = nullptr) const;
+ bool doOneCommand(const Commands &commands, byte verb, byte noun);
+ void doAllCommands(const Commands &commands, byte verb, byte noun);
+ void doActions(const Command &command, byte noun, byte offset);
enum {
kWordSize = 8
};
+ const AdlGameDescription *_gameDescription;
+ bool _isRestarting, _isRestoring;
+ byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
+ bool _canSaveNow, _canRestoreNow;
WordMap _verbs;
WordMap _nouns;
};
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 11d576b..c7b62c1 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -205,7 +205,7 @@ void HiRes1Engine::runIntro() {
delay(2000);
}
-void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos) {
+void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos) const {
byte x, y;
bool bNewLine = false;
byte oldX = 0, oldY = 0;
@@ -242,7 +242,7 @@ void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos)
}
}
-void HiRes1Engine::drawPic(byte pic, Common::Point pos) {
+void HiRes1Engine::drawPic(byte pic, Common::Point pos) const {
Common::File f;
Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
@@ -406,7 +406,7 @@ void HiRes1Engine::printMessage(uint idx, bool wait) {
AdlEngine::printMessage(idx, wait);
}
-uint HiRes1Engine::getEngineMessage(EngineMessage msg) {
+uint HiRes1Engine::getEngineMessage(EngineMessage msg) const {
switch (msg) {
case IDI_MSG_CANT_GO_THERE:
return IDI_HR1_MSG_CANT_GO_THERE;
@@ -423,7 +423,7 @@ uint HiRes1Engine::getEngineMessage(EngineMessage msg) {
}
}
-void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) {
+void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const {
// This draws a four-connected line
int16 deltaX = p2.x - p1.x;
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index f72093a..7446e10 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -39,15 +39,15 @@ public:
private:
void restartGame();
void printMessage(uint idx, bool wait = true);
- uint getEngineMessage(EngineMessage msg);
+ uint getEngineMessage(EngineMessage msg) const;
void initState();
void runIntro();
void loadData();
- void drawPic(Common::ReadStream &stream, const Common::Point &pos);
+ void drawPic(Common::ReadStream &stream, const Common::Point &pos) const;
void drawItems();
- void drawLine(const Common::Point &p1, const Common::Point &p2, byte color);
- void drawPic(byte pic, Common::Point pos);
+ void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const;
+ void drawPic(byte pic, Common::Point pos) const;
};
} // End of namespace Adl
Commit: 58e7c539096f6b37c40dd0afa13c7ed500037be8
https://github.com/scummvm/scummvm/commit/58e7c539096f6b37c40dd0afa13c7ed500037be8
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up AdlEngine class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index e0c0b3a..442edb7 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -777,18 +777,18 @@ byte &AdlEngine::var(uint i) {
return _state.vars[i];
}
-void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) {
+void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) const {
uint index = 0;
while (1) {
++index;
- byte buf[kWordSize];
+ byte buf[IDI_WORD_SIZE];
- if (stream.read(buf, kWordSize) < kWordSize)
+ if (stream.read(buf, IDI_WORD_SIZE) < IDI_WORD_SIZE)
error("Error reading word list");
- Common::String word((char *)buf, kWordSize);
+ Common::String word((char *)buf, IDI_WORD_SIZE);
if (!map.contains(word))
map[word] = index;
@@ -802,10 +802,10 @@ void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) {
break;
for (uint i = 0; i < synonyms; ++i) {
- if (stream.read((char *)buf, kWordSize) < kWordSize)
+ if (stream.read((char *)buf, IDI_WORD_SIZE) < IDI_WORD_SIZE)
error("Error reading word list");
- word = Common::String((char *)buf, kWordSize);
+ word = Common::String((char *)buf, IDI_WORD_SIZE);
if (!map.contains(word))
map[word] = index;
@@ -1038,7 +1038,7 @@ void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quad
p.y += (bits & 2 ? 1 : -1);
}
-void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation, byte scaling, byte color) const {
+void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, const Common::Point &pos, byte rotation, byte scaling, byte color) const {
const byte stepping[] = {
0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
@@ -1050,6 +1050,8 @@ void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, Common::Point p,
byte xStep = stepping[rotation];
byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
+ Common::Point p(pos);
+
for (uint i = 0; i < lineArt.size(); ++i) {
byte b = lineArt[i];
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 5afcb0f..6d5ab42 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -28,8 +28,6 @@
#include "engines/engine.h"
-#include "gui/debugger.h"
-
namespace Common {
class ReadStream;
class SeekableReadStream;
@@ -110,6 +108,8 @@ enum EngineString {
#define IDO_ACT_DROP_ITEM 0x1c
#define IDO_ACT_SET_ROOM_PIC 0x1d
+#define IDI_WORD_SIZE 8
+
struct Room {
byte description;
byte connections[6];
@@ -176,24 +176,33 @@ protected:
void printStrings(Common::SeekableReadStream &stream, int count = 1) const;
void printMessage(uint idx, bool wait = true) const;
void printASCIIString(const Common::String &str) const;
- void loadVerbs(Common::ReadStream &stream) { loadWords(stream, _verbs); }
- void loadNouns(Common::ReadStream &stream) { loadWords(stream, _nouns); }
void readCommands(Common::ReadStream &stream, Commands &commands);
Common::String inputString(byte prompt = 0) const;
void delay(uint32 ms) const;
byte inputKey() const;
+ void loadWords(Common::ReadStream &stream, WordMap &map) const;
Display *_display;
Parser *_parser;
+ // Strings inside executable
Common::Array<Common::String> _strings;
+ // Message strings in data file
Common::Array<Common::String> _messages;
+ // Picture data
Common::Array<Picture> _pictures;
+ // Dropped item screen offsets
Common::Array<Common::Point> _itemOffsets;
+ // Drawings consisting of horizontal and vertical lines only, but
+ // supporting scaling and rotation
Common::Array<Common::Array<byte> > _lineArt;
+ // <room, verb, noun, script> lists
Commands _roomCommands;
Commands _globalCommands;
+ WordMap _verbs;
+ WordMap _nouns;
+
// Game state
State _state;
@@ -219,7 +228,6 @@ private:
void wordWrap(Common::String &str) const;
// Text input
- void loadWords(Common::ReadStream &stream, WordMap &map);
byte convertKey(uint16 ascii) const;
Common::String getLine() const;
Common::String getWord(const Common::String &line, uint &index) const;
@@ -230,7 +238,7 @@ private:
void clearScreen() const;
void drawItems() const;
void drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const;
- void drawLineArt(const Common::Array<byte> &lineArt, Common::Point p, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const;
+ void drawLineArt(const Common::Array<byte> &lineArt, const Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const;
// Game state functions
const Room &room(uint i) const;
@@ -248,16 +256,10 @@ private:
void doAllCommands(const Commands &commands, byte verb, byte noun);
void doActions(const Command &command, byte noun, byte offset);
- enum {
- kWordSize = 8
- };
-
const AdlGameDescription *_gameDescription;
bool _isRestarting, _isRestoring;
byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
bool _canSaveNow, _canRestoreNow;
- WordMap _verbs;
- WordMap _nouns;
};
AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index c7b62c1..314434d 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -379,10 +379,10 @@ void HiRes1Engine::loadData() {
error("Failed to read game data from '" IDS_HR1_EXE_1 "'");
f.seek(IDI_HR1_OFS_VERBS);
- loadVerbs(f);
+ loadWords(f, _verbs);
f.seek(IDI_HR1_OFS_NOUNS);
- loadNouns(f);
+ loadWords(f, _nouns);
}
void HiRes1Engine::printMessage(uint idx, bool wait) {
Commit: 07d0997befe416c56e38b831031b81a30e63925a
https://github.com/scummvm/scummvm/commit/07d0997befe416c56e38b831031b81a30e63925a
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up AdlMetaEngine
Changed paths:
A engines/adl/detection.h
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/detection.cpp
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 442edb7..8884015 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -37,6 +37,7 @@
#include "adl/adl.h"
#include "adl/display.h"
+#include "adl/detection.h"
namespace Adl {
@@ -1071,13 +1072,4 @@ void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, const Common::Po
}
}
-AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
- switch(type) {
- case kGameTypeHires1:
- return HiRes1Engine__create(syst, gd);
- default:
- error("Unknown GameType");
- }
-}
-
} // End of namespace Adl
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 6d5ab42..6f9b24d 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -34,20 +34,11 @@ class SeekableReadStream;
}
namespace Adl {
-
-#define SAVEGAME_VERSION 0
-#define SAVEGAME_NAME_LEN 32
-
class Display;
class Parser;
class Console;
struct AdlGameDescription;
-enum GameType {
- kGameTypeNone = 0,
- kGameTypeHires1
-};
-
struct StringOffset {
int stringIdx;
uint offset;
@@ -167,8 +158,6 @@ class AdlEngine : public Engine {
public:
virtual ~AdlEngine();
- static AdlEngine *create(GameType type, OSystem *syst, const AdlGameDescription *gd);
-
protected:
AdlEngine(OSystem *syst, const AdlGameDescription *gd);
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index e556e12..d96d94c 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -28,7 +28,7 @@
#include "engines/advancedDetector.h"
-#include "adl/adl.h"
+#include "adl/detection.h"
namespace Adl {
@@ -59,18 +59,12 @@ static const ADExtraGuiOptionsMap optionsList[] = {
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
-struct AdlGameDescription {
- ADGameDescription desc;
- GameType gameType;
-};
-
static const PlainGameDescriptor adlGames[] = {
{"hires1", "Hi-Res Adventure #1: Mystery House"},
{0, 0}
};
static const AdlGameDescription gameDescriptions[] = {
-
{ // MD5 by waltervn
{
"hires1", 0,
@@ -85,9 +79,9 @@ static const AdlGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_COLOR, GAMEOPTION_SCANLINES)
},
- kGameTypeHires1
+ GAME_TYPE_HIRES1
},
- {AD_TABLE_END_MARKER, kGameTypeNone}
+ { AD_TABLE_END_MARKER, GAME_TYPE_NONE }
};
class AdlMetaEngine : public AdvancedMetaEngine {
@@ -189,7 +183,7 @@ SaveStateList AdlMetaEngine::listSaves(const char *target) const {
const Common::String &fileName = files[i];
Common::InSaveFile *inFile = saveFileMan->openForLoading(fileName);
if (!inFile) {
- warning("Cannot open save file %s", fileName.c_str());
+ warning("Cannot open save file '%s'", fileName.c_str());
continue;
}
@@ -201,7 +195,7 @@ SaveStateList AdlMetaEngine::listSaves(const char *target) const {
byte saveVersion = inFile->readByte();
if (saveVersion != SAVEGAME_VERSION) {
- warning("Save game version %i not supported in '%s'", saveVersion, fileName.c_str());
+ warning("Unsupported save game version %i found in '%s'", saveVersion, fileName.c_str());
delete inFile;
continue;
}
@@ -225,10 +219,23 @@ void AdlMetaEngine::removeSaveState(const char *target, int slot) const {
g_system->getSavefileManager()->removeSavefile(fileName);
}
+Engine *HiRes1Engine_create(OSystem *syst, const AdlGameDescription *gd);
+
bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
- if (gd)
- *engine = AdlEngine::create(((const AdlGameDescription *)gd)->gameType, syst, (const AdlGameDescription *)gd);
- return gd != nullptr;
+ if (!gd)
+ return false;
+
+ const AdlGameDescription *adlGd = (const AdlGameDescription *)gd;
+
+ switch (adlGd->gameType) {
+ case GAME_TYPE_HIRES1:
+ *engine = HiRes1Engine_create(syst, adlGd);
+ break;
+ default:
+ error("Unknown GameType");
+ }
+
+ return true;
}
} // End of namespace Adl
diff --git a/engines/adl/detection.h b/engines/adl/detection.h
new file mode 100644
index 0000000..c646aeb
--- /dev/null
+++ b/engines/adl/detection.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 ADL_DETECTION_H
+#define ADL_DETECTION_H
+
+#include "engines/advancedDetector.h"
+
+namespace Adl {
+
+#define SAVEGAME_VERSION 0
+#define SAVEGAME_NAME_LEN 32
+
+enum GameType {
+ GAME_TYPE_NONE,
+ GAME_TYPE_HIRES1
+};
+
+struct AdlGameDescription {
+ ADGameDescription desc;
+ GameType gameType;
+};
+
+} // End of namespace Adl
+
+#endif
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 314434d..ad02308 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -98,10 +98,6 @@ static const StringOffset stringOffsets[] = {
#define IDI_HR1_OFS_VERBS 0x3800
#define IDI_HR1_OFS_NOUNS 0x0f00
-HiRes1Engine::HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
- AdlEngine(syst, gd) {
-}
-
void HiRes1Engine::runIntro() {
Common::File file;
@@ -462,7 +458,7 @@ void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, by
}
}
-AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd) {
+Engine *HiRes1Engine_create(OSystem *syst, const AdlGameDescription *gd) {
return new HiRes1Engine(syst, gd);
}
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 7446e10..540e613 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -34,7 +34,7 @@ namespace Adl {
class HiRes1Engine : public AdlEngine {
public:
- HiRes1Engine(OSystem *syst, const AdlGameDescription *gd);
+ HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) : AdlEngine(syst, gd) { }
private:
void restartGame();
Commit: ac79cb081c2e7a137f2196b14e1fb2b7b4099c7f
https://github.com/scummvm/scummvm/commit/ac79cb081c2e7a137f2196b14e1fb2b7b4099c7f
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move #defines into header file
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 8884015..af379c0 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -156,18 +156,6 @@ Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) con
return str;
}
-void AdlEngine::printStrings(Common::SeekableReadStream &stream, int count) const {
- while (1) {
- Common::String str = readString(stream);
- _display->printString(str);
-
- if (--count == 0)
- break;
-
- stream.seek(3, SEEK_CUR);
- };
-}
-
Common::String AdlEngine::getEngineString(int str) const {
return _strings[str];
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 6f9b24d..591b918 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -162,14 +162,16 @@ protected:
AdlEngine(OSystem *syst, const AdlGameDescription *gd);
Common::String readString(Common::ReadStream &stream, byte until = 0) const;
- void printStrings(Common::SeekableReadStream &stream, int count = 1) const;
- void printMessage(uint idx, bool wait = true) const;
+
+ virtual void printMessage(uint idx, bool wait = true) const;
void printASCIIString(const Common::String &str) const;
- void readCommands(Common::ReadStream &stream, Commands &commands);
- Common::String inputString(byte prompt = 0) const;
void delay(uint32 ms) const;
+
+ Common::String inputString(byte prompt = 0) const;
byte inputKey() const;
+
void loadWords(Common::ReadStream &stream, WordMap &map) const;
+ void readCommands(Common::ReadStream &stream, Commands &commands);
Display *_display;
Parser *_parser;
@@ -196,7 +198,7 @@ protected:
State _state;
private:
- virtual void runIntro() { }
+ virtual void runIntro() const { }
virtual void loadData() = 0;
virtual void initState() = 0;
virtual void restartGame() = 0;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index ad02308..754ee30 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -31,37 +31,6 @@
namespace Adl {
-#define IDS_HR1_EXE_0 "AUTO LOAD OBJ"
-#define IDS_HR1_EXE_1 "ADVENTURE"
-#define IDS_HR1_LOADER "MYSTERY.HELLO"
-#define IDS_HR1_MESSAGES "MESSAGES"
-
-#define IDI_HR1_NUM_ROOMS 41
-#define IDI_HR1_NUM_PICS 98
-#define IDI_HR1_NUM_VARS 20
-#define IDI_HR1_NUM_ITEM_OFFSETS 21
-#define IDI_HR1_NUM_MESSAGES 167
-
-// Messages used outside of scripts
-#define IDI_HR1_MSG_CANT_GO_THERE 137
-#define IDI_HR1_MSG_DONT_UNDERSTAND 37
-#define IDI_HR1_MSG_ITEM_DOESNT_MOVE 151
-#define IDI_HR1_MSG_ITEM_NOT_HERE 152
-#define IDI_HR1_MSG_THANKS_FOR_PLAYING 140
-#define IDI_HR1_MSG_DONT_HAVE_IT 127
-#define IDI_HR1_MSG_GETTING_DARK 7
-
-// Strings embedded in the executable
-enum {
- IDI_HR1_STR_CANT_GO_THERE = IDI_STR_TOTAL,
- IDI_HR1_STR_DONT_HAVE_IT,
- IDI_HR1_STR_DONT_UNDERSTAND,
- IDI_HR1_STR_GETTING_DARK,
- IDI_HR1_STR_PRESS_RETURN,
-
- IDI_HR1_STR_TOTAL
-};
-
// Offsets for strings inside executable
static const StringOffset stringOffsets[] = {
{ IDI_STR_ENTER_COMMAND, 0x5bbc },
@@ -75,30 +44,7 @@ static const StringOffset stringOffsets[] = {
{ IDI_HR1_STR_PRESS_RETURN, 0x5f68 }
};
-#define IDI_HR1_OFS_PD_TEXT_0 0x005d
-#define IDI_HR1_OFS_PD_TEXT_1 0x012b
-#define IDI_HR1_OFS_PD_TEXT_2 0x016d
-#define IDI_HR1_OFS_PD_TEXT_3 0x0259
-
-#define IDI_HR1_OFS_INTRO_TEXT 0x0066
-#define IDI_HR1_OFS_GAME_OR_HELP 0x000f
-
-#define IDI_HR1_OFS_LOGO_0 0x1003
-#define IDI_HR1_OFS_LOGO_1 0x1800
-
-#define IDI_HR1_OFS_ITEMS 0x0100
-#define IDI_HR1_OFS_ROOMS 0x050a
-#define IDI_HR1_OFS_PICS 0x4b00
-#define IDI_HR1_OFS_CMDS_0 0x3c00
-#define IDI_HR1_OFS_CMDS_1 0x3d00
-
-#define IDI_HR1_OFS_ITEM_OFFSETS 0x68ff
-#define IDI_HR1_OFS_LINE_ART 0x4f00
-
-#define IDI_HR1_OFS_VERBS 0x3800
-#define IDI_HR1_OFS_NOUNS 0x0f00
-
-void HiRes1Engine::runIntro() {
+void HiRes1Engine::runIntro() const {
Common::File file;
if (!file.open(IDS_HR1_EXE_0))
@@ -175,13 +121,20 @@ void HiRes1Engine::runIntro() {
uint page = 0;
while (pages[page] != 0) {
_display->home();
- printStrings(file, pages[page++]);
+
+ uint count = pages[page++];
+ for (uint i = 0; i < count; ++i) {
+ str = readString(file);
+ _display->printString(str);
+ file.seek(3, SEEK_CUR);
+ }
+
inputString();
if (g_engine->shouldQuit())
return;
- file.seek(9, SEEK_CUR);
+ file.seek(6, SEEK_CUR);
}
}
@@ -381,7 +334,7 @@ void HiRes1Engine::loadData() {
loadWords(f, _nouns);
}
-void HiRes1Engine::printMessage(uint idx, bool wait) {
+void HiRes1Engine::printMessage(uint idx, bool wait) const {
// Hardcoded overrides that don't wait after printing
// Note: strings may differ slightly from the ones in MESSAGES
switch (idx) {
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index 540e613..a19e9c0 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -32,22 +32,76 @@ class Point;
namespace Adl {
+#define IDS_HR1_EXE_0 "AUTO LOAD OBJ"
+#define IDS_HR1_EXE_1 "ADVENTURE"
+#define IDS_HR1_LOADER "MYSTERY.HELLO"
+#define IDS_HR1_MESSAGES "MESSAGES"
+
+#define IDI_HR1_NUM_ROOMS 41
+#define IDI_HR1_NUM_PICS 98
+#define IDI_HR1_NUM_VARS 20
+#define IDI_HR1_NUM_ITEM_OFFSETS 21
+#define IDI_HR1_NUM_MESSAGES 167
+
+// Messages used outside of scripts
+#define IDI_HR1_MSG_CANT_GO_THERE 137
+#define IDI_HR1_MSG_DONT_UNDERSTAND 37
+#define IDI_HR1_MSG_ITEM_DOESNT_MOVE 151
+#define IDI_HR1_MSG_ITEM_NOT_HERE 152
+#define IDI_HR1_MSG_THANKS_FOR_PLAYING 140
+#define IDI_HR1_MSG_DONT_HAVE_IT 127
+#define IDI_HR1_MSG_GETTING_DARK 7
+
+// Strings embedded in the executable
+enum {
+ IDI_HR1_STR_CANT_GO_THERE = IDI_STR_TOTAL,
+ IDI_HR1_STR_DONT_HAVE_IT,
+ IDI_HR1_STR_DONT_UNDERSTAND,
+ IDI_HR1_STR_GETTING_DARK,
+ IDI_HR1_STR_PRESS_RETURN,
+
+ IDI_HR1_STR_TOTAL
+};
+
+#define IDI_HR1_OFS_PD_TEXT_0 0x005d
+#define IDI_HR1_OFS_PD_TEXT_1 0x012b
+#define IDI_HR1_OFS_PD_TEXT_2 0x016d
+#define IDI_HR1_OFS_PD_TEXT_3 0x0259
+
+#define IDI_HR1_OFS_INTRO_TEXT 0x0066
+#define IDI_HR1_OFS_GAME_OR_HELP 0x000f
+
+#define IDI_HR1_OFS_LOGO_0 0x1003
+#define IDI_HR1_OFS_LOGO_1 0x1800
+
+#define IDI_HR1_OFS_ITEMS 0x0100
+#define IDI_HR1_OFS_ROOMS 0x050a
+#define IDI_HR1_OFS_PICS 0x4b00
+#define IDI_HR1_OFS_CMDS_0 0x3c00
+#define IDI_HR1_OFS_CMDS_1 0x3d00
+
+#define IDI_HR1_OFS_ITEM_OFFSETS 0x68ff
+#define IDI_HR1_OFS_LINE_ART 0x4f00
+
+#define IDI_HR1_OFS_VERBS 0x3800
+#define IDI_HR1_OFS_NOUNS 0x0f00
+
class HiRes1Engine : public AdlEngine {
public:
HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) : AdlEngine(syst, gd) { }
private:
+ // AdlEngine
+ void runIntro() const;
+ void loadData();
+ void initState();
void restartGame();
- void printMessage(uint idx, bool wait = true);
uint getEngineMessage(EngineMessage msg) const;
+ void drawPic(byte pic, Common::Point pos) const;
+ void printMessage(uint idx, bool wait = true) const;
- void initState();
- void runIntro();
- void loadData();
- void drawPic(Common::ReadStream &stream, const Common::Point &pos) const;
- void drawItems();
void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const;
- void drawPic(byte pic, Common::Point pos) const;
+ void drawPic(Common::ReadStream &stream, const Common::Point &pos) const;
};
} // End of namespace Adl
Commit: fd8a5f419f0855babb99f716e526fc20e50882d6
https://github.com/scummvm/scummvm/commit/fd8a5f419f0855babb99f716e526fc20e50882d6
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Refactor string handling
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index af379c0..f466f80 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -109,7 +109,7 @@ Common::Error AdlEngine::run() {
break;
if (!doOneCommand(_roomCommands, verb, noun))
- printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
+ printMessage(_messageIds.dontUnderstand);
}
if (_isRestoring) {
@@ -156,8 +156,9 @@ Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) con
return str;
}
-Common::String AdlEngine::getEngineString(int str) const {
- return _strings[str];
+Common::String AdlEngine::readStringAt(Common::SeekableReadStream &stream, uint offset, byte until) const {
+ stream.seek(offset);
+ return readString(stream, until);
}
void AdlEngine::wordWrap(Common::String &str) const {
@@ -184,10 +185,6 @@ void AdlEngine::printMessage(uint idx, bool wait) const {
delay(14 * 166018 / 1000);
}
-void AdlEngine::printEngineMessage(EngineMessage msg) const {
- printMessage(getEngineMessage(msg));
-}
-
void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
while (1) {
Command command;
@@ -232,7 +229,7 @@ void AdlEngine::takeItem(byte noun) {
continue;
if (item->state == IDI_ITEM_DOESNT_MOVE) {
- printEngineMessage(IDI_MSG_ITEM_DOESNT_MOVE);
+ printMessage(_messageIds.itemDoesntMove);
return;
}
@@ -251,7 +248,7 @@ void AdlEngine::takeItem(byte noun) {
}
}
- printEngineMessage(IDI_MSG_ITEM_NOT_HERE);
+ printMessage(_messageIds.itemNotHere);
}
void AdlEngine::dropItem(byte noun) {
@@ -266,7 +263,7 @@ void AdlEngine::dropItem(byte noun) {
return;
}
- printEngineMessage(IDI_MSG_DONT_UNDERSTAND);
+ printMessage(_messageIds.dontUnderstand);
}
#define ARG(N) (command.script[offset + (N)])
@@ -339,7 +336,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
_isRestoring = false;
break;
case IDO_ACT_RESTART: {
- _display->printString(_strings[IDI_STR_PLAY_AGAIN]);
+ _display->printString(_strings.playAgain);
// We allow restoring via GMM here
_canRestoreNow = true;
@@ -360,7 +357,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
// Fall-through
}
case IDO_ACT_QUIT:
- printEngineMessage(IDI_MSG_THANKS_FOR_PLAYING);
+ printMessage(_messageIds.thanksForPlaying);
quitGame();
return;
case IDO_ACT_PLACE_ITEM:
@@ -386,7 +383,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
byte room = curRoom().connections[ARG(0) - IDO_ACT_GO_NORTH];
if (room == 0) {
- printEngineMessage(IDI_MSG_CANT_GO_THERE);
+ printMessage(_messageIds.cantGoThere);
return;
}
@@ -856,7 +853,7 @@ Common::String AdlEngine::getWord(const Common::String &line, uint &index) const
void AdlEngine::getInput(uint &verb, uint &noun) {
while (1) {
- _display->printString(getEngineString(IDI_STR_ENTER_COMMAND));
+ _display->printString(_strings.enterCommand);
Common::String line = getLine();
if (shouldQuit() || _isRestoring)
@@ -866,7 +863,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
Common::String verbStr = getWord(line, index);
if (!_verbs.contains(verbStr)) {
- Common::String err = getEngineString(IDI_STR_VERB_ERROR);
+ Common::String err = _strings.verbError;
for (uint i = 0; i < verbStr.size(); ++i)
err.setChar(verbStr[i], i + 19);
_display->printString(err);
@@ -878,7 +875,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
Common::String nounStr = getWord(line, index);
if (!_nouns.contains(nounStr)) {
- Common::String err = getEngineString(IDI_STR_NOUN_ERROR);
+ Common::String err = _strings.nounError;
for (uint i = 0; i < verbStr.size(); ++i)
err.setChar(verbStr[i], i + 19);
for (uint i = 0; i < nounStr.size(); ++i)
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 591b918..303f197 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -44,25 +44,6 @@ struct StringOffset {
uint offset;
};
-// Messages used outside of scripts
-enum EngineMessage {
- IDI_MSG_CANT_GO_THERE,
- IDI_MSG_DONT_UNDERSTAND,
- IDI_MSG_ITEM_DOESNT_MOVE,
- IDI_MSG_ITEM_NOT_HERE,
- IDI_MSG_THANKS_FOR_PLAYING
-};
-
-// Strings embedded in the executable
-enum EngineString {
- IDI_STR_ENTER_COMMAND,
- IDI_STR_VERB_ERROR,
- IDI_STR_NOUN_ERROR,
- IDI_STR_PLAY_AGAIN,
-
- IDI_STR_TOTAL
-};
-
// Conditional opcodes
#define IDO_CND_ITEM_IN_ROOM 0x03
#define IDO_CND_MOVES_GE 0x05
@@ -162,6 +143,7 @@ protected:
AdlEngine(OSystem *syst, const AdlGameDescription *gd);
Common::String readString(Common::ReadStream &stream, byte until = 0) const;
+ Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const;
virtual void printMessage(uint idx, bool wait = true) const;
void printASCIIString(const Common::String &str) const;
@@ -176,8 +158,6 @@ protected:
Display *_display;
Parser *_parser;
- // Strings inside executable
- Common::Array<Common::String> _strings;
// Message strings in data file
Common::Array<Common::String> _messages;
// Picture data
@@ -194,6 +174,23 @@ protected:
WordMap _verbs;
WordMap _nouns;
+ struct {
+ Common::String enterCommand;
+ Common::String dontHaveIt;
+ Common::String gettingDark;
+ Common::String verbError;
+ Common::String nounError;
+ Common::String playAgain;
+ } _strings;
+
+ struct {
+ uint cantGoThere;
+ uint dontUnderstand;
+ uint itemDoesntMove;
+ uint itemNotHere;
+ uint thanksForPlaying;
+ } _messageIds;
+
// Game state
State _state;
@@ -202,7 +199,6 @@ private:
virtual void loadData() = 0;
virtual void initState() = 0;
virtual void restartGame() = 0;
- virtual uint getEngineMessage(EngineMessage msg) const = 0;
virtual void drawPic(byte pic, Common::Point pos = Common::Point()) const = 0;
// Engine
@@ -214,8 +210,6 @@ private:
bool canSaveGameStateCurrently() const;
// Text output
- Common::String getEngineString(int str) const;
- void printEngineMessage(EngineMessage) const;
void wordWrap(Common::String &str) const;
// Text input
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 754ee30..80ea094 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -31,19 +31,6 @@
namespace Adl {
-// Offsets for strings inside executable
-static const StringOffset stringOffsets[] = {
- { IDI_STR_ENTER_COMMAND, 0x5bbc },
- { IDI_STR_VERB_ERROR, 0x5b4f },
- { IDI_STR_NOUN_ERROR, 0x5b8e },
- { IDI_STR_PLAY_AGAIN, 0x5f1e },
- { IDI_HR1_STR_CANT_GO_THERE, 0x6c0a },
- { IDI_HR1_STR_DONT_HAVE_IT, 0x6c31 },
- { IDI_HR1_STR_DONT_UNDERSTAND, 0x6c51 },
- { IDI_HR1_STR_GETTING_DARK, 0x6c7c },
- { IDI_HR1_STR_PRESS_RETURN, 0x5f68 }
-};
-
void HiRes1Engine::runIntro() const {
Common::File file;
@@ -67,20 +54,16 @@ void HiRes1Engine::runIntro() const {
Common::String str;
- basic.seek(IDI_HR1_OFS_PD_TEXT_0);
- str = readString(basic, '"');
+ str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_0, '"');
printASCIIString(str + '\r');
- basic.seek(IDI_HR1_OFS_PD_TEXT_1);
- str = readString(basic, '"');
+ str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_1, '"');
printASCIIString(str + "\r\r");
- basic.seek(IDI_HR1_OFS_PD_TEXT_2);
- str = readString(basic, '"');
+ str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_2, '"');
printASCIIString(str + "\r\r");
- basic.seek(IDI_HR1_OFS_PD_TEXT_3);
- str = readString(basic, '"');
+ str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_3, '"');
printASCIIString(str + '\r');
inputKey();
@@ -89,8 +72,7 @@ void HiRes1Engine::runIntro() const {
_display->setMode(DISPLAY_MODE_MIXED);
- file.seek(IDI_HR1_OFS_GAME_OR_HELP);
- str = readString(file);
+ str = readStringAt(file, IDI_HR1_OFS_GAME_OR_HELP);
bool instructions = false;
@@ -256,7 +238,7 @@ void HiRes1Engine::initState() {
void HiRes1Engine::restartGame() {
initState();
- _display->printString(_strings[IDI_HR1_STR_PRESS_RETURN]);
+ _display->printString(_gameStrings.pressReturn);
inputString(); // Missing in the original
printASCIIString("\r\r\r\r\r");
}
@@ -275,12 +257,27 @@ void HiRes1Engine::loadData() {
if (!f.open(IDS_HR1_EXE_1))
error("Failed to open file '" IDS_HR1_EXE_1 "'");
- // Load strings from executable
- _strings.resize(IDI_HR1_STR_TOTAL);
- for (uint idx = 0; idx < IDI_HR1_STR_TOTAL; ++idx) {
- f.seek(stringOffsets[idx].offset);
- _strings[stringOffsets[idx].stringIdx] = readString(f);
- }
+ // Some messages have overrides inside the executable
+ _messages[IDI_HR1_MSG_CANT_GO_THERE - 1] = readStringAt(f, IDI_HR1_OFS_STR_CANT_GO_THERE);
+ _messages[IDI_HR1_MSG_DONT_HAVE_IT - 1] = readStringAt(f, IDI_HR1_OFS_STR_DONT_HAVE_IT);
+ _messages[IDI_HR1_MSG_DONT_UNDERSTAND - 1] = readStringAt(f, IDI_HR1_OFS_STR_DONT_UNDERSTAND);
+ _messages[IDI_HR1_MSG_GETTING_DARK - 1] = readStringAt(f, IDI_HR1_OFS_STR_GETTING_DARK);
+
+ // Load other strings from executable
+ _strings.enterCommand = readStringAt(f, IDI_HR1_OFS_STR_ENTER_COMMAND);
+ _strings.dontHaveIt = readStringAt(f, IDI_HR1_OFS_STR_DONT_HAVE_IT);
+ _strings.gettingDark = readStringAt(f, IDI_HR1_OFS_STR_GETTING_DARK);
+ _strings.verbError = readStringAt(f, IDI_HR1_OFS_STR_VERB_ERROR);
+ _strings.nounError = readStringAt(f, IDI_HR1_OFS_STR_NOUN_ERROR);
+ _strings.playAgain = readStringAt(f, IDI_HR1_OFS_STR_PLAY_AGAIN);
+ _gameStrings.pressReturn = readStringAt(f, IDI_HR1_OFS_STR_PRESS_RETURN);
+
+ // Set message IDs
+ _messageIds.cantGoThere = IDI_HR1_MSG_CANT_GO_THERE;
+ _messageIds.dontUnderstand = IDI_HR1_MSG_DONT_UNDERSTAND;
+ _messageIds.itemDoesntMove = IDI_HR1_MSG_ITEM_DOESNT_MOVE;
+ _messageIds.itemNotHere = IDI_HR1_MSG_ITEM_NOT_HERE;
+ _messageIds.thanksForPlaying = IDI_HR1_MSG_THANKS_FOR_PLAYING;
// Load picture data from executable
f.seek(IDI_HR1_OFS_PICS);
@@ -335,43 +332,24 @@ void HiRes1Engine::loadData() {
}
void HiRes1Engine::printMessage(uint idx, bool wait) const {
- // Hardcoded overrides that don't wait after printing
- // Note: strings may differ slightly from the ones in MESSAGES
+ // Messages with hardcoded overrides don't delay after printing.
+ // It's unclear if this is a bug or not. In some cases the result
+ // is that these strings will scroll past the four-line text window
+ // before the user gets a chance to read them.
+ // NOTE: later games seem to wait for a key when the text window
+ // overflows and don't use delays. It might be better to use
+ // that system for this game as well.
switch (idx) {
case IDI_HR1_MSG_CANT_GO_THERE:
- _display->printString(_strings[IDI_HR1_STR_CANT_GO_THERE]);
- return;
case IDI_HR1_MSG_DONT_HAVE_IT:
- _display->printString(_strings[IDI_HR1_STR_DONT_HAVE_IT]);
- return;
case IDI_HR1_MSG_DONT_UNDERSTAND:
- _display->printString(_strings[IDI_HR1_STR_DONT_UNDERSTAND]);
- return;
case IDI_HR1_MSG_GETTING_DARK:
- _display->printString(_strings[IDI_HR1_STR_GETTING_DARK]);
- return;
+ wait = false;
}
AdlEngine::printMessage(idx, wait);
}
-uint HiRes1Engine::getEngineMessage(EngineMessage msg) const {
- switch (msg) {
- case IDI_MSG_CANT_GO_THERE:
- return IDI_HR1_MSG_CANT_GO_THERE;
- case IDI_MSG_DONT_UNDERSTAND:
- return IDI_HR1_MSG_DONT_UNDERSTAND;
- case IDI_MSG_ITEM_DOESNT_MOVE:
- return IDI_HR1_MSG_ITEM_DOESNT_MOVE;
- case IDI_MSG_ITEM_NOT_HERE:
- return IDI_HR1_MSG_ITEM_NOT_HERE;
- case IDI_MSG_THANKS_FOR_PLAYING:
- return IDI_HR1_MSG_THANKS_FOR_PLAYING;
- default:
- error("Cannot find engine message %i", msg);
- }
-}
-
void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const {
// This draws a four-connected line
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index a19e9c0..b7c7f41 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -52,16 +52,15 @@ namespace Adl {
#define IDI_HR1_MSG_DONT_HAVE_IT 127
#define IDI_HR1_MSG_GETTING_DARK 7
-// Strings embedded in the executable
-enum {
- IDI_HR1_STR_CANT_GO_THERE = IDI_STR_TOTAL,
- IDI_HR1_STR_DONT_HAVE_IT,
- IDI_HR1_STR_DONT_UNDERSTAND,
- IDI_HR1_STR_GETTING_DARK,
- IDI_HR1_STR_PRESS_RETURN,
-
- IDI_HR1_STR_TOTAL
-};
+#define IDI_HR1_OFS_STR_ENTER_COMMAND 0x5bbc
+#define IDI_HR1_OFS_STR_VERB_ERROR 0x5b4f
+#define IDI_HR1_OFS_STR_NOUN_ERROR 0x5b8e
+#define IDI_HR1_OFS_STR_PLAY_AGAIN 0x5f1e
+#define IDI_HR1_OFS_STR_CANT_GO_THERE 0x6c0a
+#define IDI_HR1_OFS_STR_DONT_HAVE_IT 0x6c31
+#define IDI_HR1_OFS_STR_DONT_UNDERSTAND 0x6c51
+#define IDI_HR1_OFS_STR_GETTING_DARK 0x6c7c
+#define IDI_HR1_OFS_STR_PRESS_RETURN 0x5f68
#define IDI_HR1_OFS_PD_TEXT_0 0x005d
#define IDI_HR1_OFS_PD_TEXT_1 0x012b
@@ -96,12 +95,15 @@ private:
void loadData();
void initState();
void restartGame();
- uint getEngineMessage(EngineMessage msg) const;
void drawPic(byte pic, Common::Point pos) const;
void printMessage(uint idx, bool wait = true) const;
void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const;
void drawPic(Common::ReadStream &stream, const Common::Point &pos) const;
+
+ struct {
+ Common::String pressReturn;
+ } _gameStrings;
};
} // End of namespace Adl
Commit: 86d58534e7138c7b58995e1f730c8531ca2d4273
https://github.com/scummvm/scummvm/commit/86d58534e7138c7b58995e1f730c8531ca2d4273
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Move ASCII print function into Display class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/display.cpp
engines/adl/display.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index f466f80..5b43a6c 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -87,7 +87,7 @@ Common::Error AdlEngine::run() {
}
_display->setMode(DISPLAY_MODE_MIXED);
- printASCIIString("\r\r\r\r\r");
+ _display->printAsciiString("\r\r\r\r\r");
while (1) {
uint verb = 0, noun = 0;
@@ -119,7 +119,7 @@ Common::Error AdlEngine::run() {
// means that restoring a game will always run through
// the global commands and increase the move counter
// before the first user input.
- printASCIIString("\r");
+ _display->printAsciiString("\r");
_isRestoring = false;
verb = _restoreVerb;
noun = _restoreNoun;
@@ -889,16 +889,6 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
}
}
-void AdlEngine::printASCIIString(const Common::String &str) const {
- Common::String aStr;
-
- Common::String::const_iterator it;
- for (it = str.begin(); it != str.end(); ++it)
- aStr += APPLECHAR(*it);
-
- _display->printString(aStr);
-}
-
Common::String AdlEngine::inputString(byte prompt) const {
Common::String s;
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 303f197..b1d5b7c 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -146,7 +146,6 @@ protected:
Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const;
virtual void printMessage(uint idx, bool wait = true) const;
- void printASCIIString(const Common::String &str) const;
void delay(uint32 ms) const;
Common::String inputString(byte prompt = 0) const;
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 7af6f66..d48296e 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -289,6 +289,16 @@ void Display::printString(const Common::String &str) {
updateTextScreen();
}
+void Display::printAsciiString(const Common::String &str) {
+ Common::String aStr;
+
+ Common::String::const_iterator it;
+ for (it = str.begin(); it != str.end(); ++it)
+ aStr += APPLECHAR(*it);
+
+ printString(aStr);
+}
+
void Display::setCharAtCursor(byte c) {
_textBuf[_cursorPos] = c;
}
diff --git a/engines/adl/display.h b/engines/adl/display.h
index ce8f86b..e61477d 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -70,6 +70,7 @@ public:
void moveCursorForward();
void moveCursorBackward();
void printString(const Common::String &str);
+ void printAsciiString(const Common::String &str);
void setCharAtCursor(byte c);
void showCursor(bool enable);
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 80ea094..95f0289 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -55,16 +55,16 @@ void HiRes1Engine::runIntro() const {
Common::String str;
str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_0, '"');
- printASCIIString(str + '\r');
+ _display->printAsciiString(str + '\r');
str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_1, '"');
- printASCIIString(str + "\r\r");
+ _display->printAsciiString(str + "\r\r");
str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_2, '"');
- printASCIIString(str + "\r\r");
+ _display->printAsciiString(str + "\r\r");
str = readStringAt(basic, IDI_HR1_OFS_PD_TEXT_3, '"');
- printASCIIString(str + '\r');
+ _display->printAsciiString(str + '\r');
inputKey();
if (g_engine->shouldQuit())
@@ -120,7 +120,7 @@ void HiRes1Engine::runIntro() const {
}
}
- printASCIIString("\r");
+ _display->printAsciiString("\r");
file.close();
@@ -240,7 +240,7 @@ void HiRes1Engine::restartGame() {
initState();
_display->printString(_gameStrings.pressReturn);
inputString(); // Missing in the original
- printASCIIString("\r\r\r\r\r");
+ _display->printAsciiString("\r\r\r\r\r");
}
void HiRes1Engine::loadData() {
Commit: 63adab81edc8f44d4b4387352e0869e3042c2a13
https://github.com/scummvm/scummvm/commit/63adab81edc8f44d4b4387352e0869e3042c2a13
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clean up HiRes1Engine class
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
engines/adl/hires1.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 5b43a6c..dd4f406 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -41,10 +41,14 @@
namespace Adl {
+AdlEngine::~AdlEngine() {
+ delete _display;
+}
+
AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
- _gameDescription(gd),
_display(nullptr),
+ _gameDescription(gd),
_isRestarting(false),
_isRestoring(false),
_saveVerb(0),
@@ -55,18 +59,206 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
_canRestoreNow(false) {
}
-AdlEngine::~AdlEngine() {
- delete _display;
+Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) const {
+ Common::String str;
+
+ while (1) {
+ byte b = stream.readByte();
+
+ if (stream.eos() || stream.err())
+ error("Error reading string");
+
+ if (b == until)
+ break;
+
+ str += b;
+ };
+
+ return str;
}
-bool AdlEngine::hasFeature(EngineFeature f) const {
- switch (f) {
- case kSupportsLoadingDuringRuntime:
- case kSupportsSavingDuringRuntime:
- case kSupportsRTL:
- return true;
- default:
- return false;
+Common::String AdlEngine::readStringAt(Common::SeekableReadStream &stream, uint offset, byte until) const {
+ stream.seek(offset);
+ return readString(stream, until);
+}
+
+void AdlEngine::printMessage(uint idx, bool wait) const {
+ Common::String msg = _messages[idx - 1];
+ wordWrap(msg);
+ _display->printString(msg);
+
+ if (wait)
+ delay(14 * 166018 / 1000);
+}
+
+void AdlEngine::delay(uint32 ms) const {
+ Common::EventManager *ev = g_system->getEventManager();
+
+ uint32 start = g_system->getMillis();
+
+ while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) {
+ Common::Event event;
+ if (ev->pollEvent(event)) {
+ if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) {
+ switch(event.kbd.keycode) {
+ case Common::KEYCODE_q:
+ g_engine->quitGame();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ g_system->delayMillis(16);
+ }
+}
+
+Common::String AdlEngine::inputString(byte prompt) const {
+ Common::String s;
+
+ if (prompt > 0)
+ _display->printString(Common::String(prompt));
+
+ while (1) {
+ byte b = inputKey();
+
+ if (g_engine->shouldQuit() || _isRestoring)
+ return 0;
+
+ if (b == 0)
+ continue;
+
+ if (b == ('\r' | 0x80)) {
+ s += b;
+ _display->printString(Common::String(b));
+ return s;
+ }
+
+ if (b < 0xa0) {
+ switch (b) {
+ case Common::KEYCODE_BACKSPACE | 0x80:
+ if (!s.empty()) {
+ _display->moveCursorBackward();
+ _display->setCharAtCursor(APPLECHAR(' '));
+ s.deleteLastChar();
+ }
+ break;
+ };
+ } else {
+ s += b;
+ _display->printString(Common::String(b));
+ }
+ }
+}
+
+byte AdlEngine::inputKey() const {
+ Common::EventManager *ev = g_system->getEventManager();
+
+ byte key = 0;
+
+ _display->showCursor(true);
+
+ while (!g_engine->shouldQuit() && !_isRestoring && key == 0) {
+ Common::Event event;
+ if (ev->pollEvent(event)) {
+ if (event.type != Common::EVENT_KEYDOWN)
+ continue;
+
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ if (event.kbd.keycode == Common::KEYCODE_q)
+ g_engine->quitGame();
+ continue;
+ }
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ case Common::KEYCODE_RETURN:
+ key = convertKey(event.kbd.keycode);
+ break;
+ default:
+ if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80)
+ key = convertKey(event.kbd.ascii);
+ };
+ }
+
+ _display->updateTextScreen();
+ g_system->delayMillis(16);
+ }
+
+ _display->showCursor(false);
+
+ return key;
+}
+
+void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) const {
+ uint index = 0;
+
+ while (1) {
+ ++index;
+
+ byte buf[IDI_WORD_SIZE];
+
+ if (stream.read(buf, IDI_WORD_SIZE) < IDI_WORD_SIZE)
+ error("Error reading word list");
+
+ Common::String word((char *)buf, IDI_WORD_SIZE);
+
+ if (!map.contains(word))
+ map[word] = index;
+
+ byte synonyms = stream.readByte();
+
+ if (stream.err() || stream.eos())
+ error("Error reading word list");
+
+ if (synonyms == 0xff)
+ break;
+
+ for (uint i = 0; i < synonyms; ++i) {
+ if (stream.read((char *)buf, IDI_WORD_SIZE) < IDI_WORD_SIZE)
+ error("Error reading word list");
+
+ word = Common::String((char *)buf, IDI_WORD_SIZE);
+
+ if (!map.contains(word))
+ map[word] = index;
+ }
+ }
+}
+
+void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
+ while (1) {
+ Command command;
+ command.room = stream.readByte();
+
+ if (command.room == 0xff)
+ return;
+
+ command.verb = stream.readByte();
+ command.noun = stream.readByte();
+
+ byte scriptSize = stream.readByte() - 6;
+
+ command.numCond = stream.readByte();
+ command.numAct = stream.readByte();
+
+ for (uint i = 0; i < scriptSize; ++i)
+ command.script.push_back(stream.readByte());
+
+ if (stream.eos() || stream.err())
+ error("Failed to read commands");
+
+ if (command.numCond == 0 && command.script[0] == IDO_ACT_SAVE) {
+ _saveVerb = command.verb;
+ _saveNoun = command.noun;
+ }
+
+ if (command.numCond == 0 && command.script[0] == IDO_ACT_LOAD) {
+ _restoreVerb = command.verb;
+ _restoreNoun = command.noun;
+ }
+
+ commands.push_back(command);
}
}
@@ -138,380 +330,317 @@ Common::Error AdlEngine::run() {
return Common::kNoError;
}
-Common::String AdlEngine::readString(Common::ReadStream &stream, byte until) const {
- Common::String str;
-
- while (1) {
- byte b = stream.readByte();
+bool AdlEngine::hasFeature(EngineFeature f) const {
+ switch (f) {
+ case kSupportsLoadingDuringRuntime:
+ case kSupportsSavingDuringRuntime:
+ case kSupportsRTL:
+ return true;
+ default:
+ return false;
+ }
+}
- if (stream.eos() || stream.err())
- error("Error reading string");
+Common::Error AdlEngine::loadGameState(int slot) {
+ Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
+ Common::InSaveFile *inFile = getSaveFileManager()->openForLoading(fileName);
- if (b == until)
- break;
+ if (!inFile) {
+ warning("Failed to open file '%s'", fileName.c_str());
+ return Common::kUnknownError;
+ }
- str += b;
- };
+ if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
+ warning("No header found in '%s'", fileName.c_str());
+ delete inFile;
+ return Common::kUnknownError;
+ }
- return str;
-}
+ byte saveVersion = inFile->readByte();
+ if (saveVersion != SAVEGAME_VERSION) {
+ warning("Save game version %i not supported", saveVersion);
+ delete inFile;
+ return Common::kUnknownError;
+ }
-Common::String AdlEngine::readStringAt(Common::SeekableReadStream &stream, uint offset, byte until) const {
- stream.seek(offset);
- return readString(stream, until);
-}
+ // Skip description
+ inFile->seek(SAVEGAME_NAME_LEN, SEEK_CUR);
+ // Skip save time
+ inFile->seek(6, SEEK_CUR);
-void AdlEngine::wordWrap(Common::String &str) const {
- uint end = 39;
+ uint32 playTime = inFile->readUint32BE();
- while (1) {
- if (str.size() <= end)
- return;
+ Graphics::skipThumbnail(*inFile);
- while (str[end] != APPLECHAR(' '))
- --end;
+ initState();
- str.setChar(APPLECHAR('\r'), end);
- end += 40;
+ _state.room = inFile->readByte();
+ _state.moves = inFile->readByte();
+ _state.isDark = inFile->readByte();
+
+ uint32 size = inFile->readUint32BE();
+ if (size != _state.rooms.size())
+ error("Room count mismatch (expected %i; found %i)", _state.rooms.size(), size);
+
+ for (uint i = 0; i < size; ++i) {
+ _state.rooms[i].picture = inFile->readByte();
+ _state.rooms[i].curPicture = inFile->readByte();
}
-}
-void AdlEngine::printMessage(uint idx, bool wait) const {
- Common::String msg = _messages[idx - 1];
- wordWrap(msg);
- _display->printString(msg);
+ size = inFile->readUint32BE();
+ if (size != _state.items.size())
+ error("Item count mismatch (expected %i; found %i)", _state.items.size(), size);
- if (wait)
- delay(14 * 166018 / 1000);
+ for (uint i = 0; i < size; ++i) {
+ _state.items[i].room = inFile->readByte();
+ _state.items[i].picture = inFile->readByte();
+ _state.items[i].position.x = inFile->readByte();
+ _state.items[i].position.y = inFile->readByte();
+ _state.items[i].state = inFile->readByte();
+ }
+
+ size = inFile->readUint32BE();
+ if (size != _state.vars.size())
+ error("Variable count mismatch (expected %i; found %i)", _state.vars.size(), size);
+
+ for (uint i = 0; i < size; ++i)
+ _state.vars[i] = inFile->readByte();
+
+ if (inFile->err() || inFile->eos())
+ error("Failed to load game '%s'", fileName.c_str());
+
+ delete inFile;
+
+ setTotalPlayTime(playTime);
+
+ _isRestoring = true;
+ return Common::kNoError;
}
-void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
- while (1) {
- Command command;
- command.room = stream.readByte();
+bool AdlEngine::canLoadGameStateCurrently() const {
+ return _canRestoreNow;
+}
- if (command.room == 0xff)
- return;
+Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
+ Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
+ Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName);
- command.verb = stream.readByte();
- command.noun = stream.readByte();
+ if (!outFile) {
+ warning("Failed to open file '%s'", fileName.c_str());
+ return Common::kUnknownError;
+ }
- byte scriptSize = stream.readByte() - 6;
+ outFile->writeUint32BE(MKTAG('A', 'D', 'L', ':'));
+ outFile->writeByte(SAVEGAME_VERSION);
- command.numCond = stream.readByte();
- command.numAct = stream.readByte();
+ char name[SAVEGAME_NAME_LEN] = { };
- for (uint i = 0; i < scriptSize; ++i)
- command.script.push_back(stream.readByte());
+ if (!desc.empty())
+ strncpy(name, desc.c_str(), sizeof(name) - 1);
+ else {
+ Common::String defaultName("Save ");
+ defaultName += 'A' + slot;
+ strncpy(name, defaultName.c_str(), sizeof(name) - 1);
+ }
- if (stream.eos() || stream.err())
- error("Failed to read commands");
+ outFile->write(name, sizeof(name));
- if (command.numCond == 0 && command.script[0] == IDO_ACT_SAVE) {
- _saveVerb = command.verb;
- _saveNoun = command.noun;
- }
+ TimeDate t;
+ g_system->getTimeAndDate(t);
- if (command.numCond == 0 && command.script[0] == IDO_ACT_LOAD) {
- _restoreVerb = command.verb;
- _restoreNoun = command.noun;
- }
+ outFile->writeUint16BE(t.tm_year);
+ outFile->writeByte(t.tm_mon);
+ outFile->writeByte(t.tm_mday);
+ outFile->writeByte(t.tm_hour);
+ outFile->writeByte(t.tm_min);
- commands.push_back(command);
+ uint32 playTime = getTotalPlayTime();
+ outFile->writeUint32BE(playTime);
+
+ _display->saveThumbnail(*outFile);
+
+ outFile->writeByte(_state.room);
+ outFile->writeByte(_state.moves);
+ outFile->writeByte(_state.isDark);
+
+ outFile->writeUint32BE(_state.rooms.size());
+ for (uint i = 0; i < _state.rooms.size(); ++i) {
+ outFile->writeByte(_state.rooms[i].picture);
+ outFile->writeByte(_state.rooms[i].curPicture);
}
-}
-void AdlEngine::takeItem(byte noun) {
- Common::Array<Item>::iterator item;
+ outFile->writeUint32BE(_state.items.size());
+ for (uint i = 0; i < _state.items.size(); ++i) {
+ outFile->writeByte(_state.items[i].room);
+ outFile->writeByte(_state.items[i].picture);
+ outFile->writeByte(_state.items[i].position.x);
+ outFile->writeByte(_state.items[i].position.y);
+ outFile->writeByte(_state.items[i].state);
+ }
- for (item = _state.items.begin(); item != _state.items.end(); ++item) {
- if (item->noun != noun || item->room != _state.room)
- continue;
+ outFile->writeUint32BE(_state.vars.size());
+ for (uint i = 0; i < _state.vars.size(); ++i)
+ outFile->writeByte(_state.vars[i]);
- if (item->state == IDI_ITEM_DOESNT_MOVE) {
- printMessage(_messageIds.itemDoesntMove);
- return;
- }
+ outFile->finalize();
- if (item->state == IDI_ITEM_MOVED) {
- item->room = IDI_NONE;
- return;
- }
+ if (outFile->err()) {
+ delete outFile;
+ warning("Failed to save game '%s'", fileName.c_str());
+ return Common::kUnknownError;
+ }
- Common::Array<byte>::const_iterator pic;
- for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == curRoom().curPicture) {
- item->room = IDI_NONE;
- item->state = IDI_ITEM_MOVED;
- return;
- }
+ delete outFile;
+ return Common::kNoError;
+}
+
+bool AdlEngine::canSaveGameStateCurrently() const {
+ if (!_canSaveNow)
+ return false;
+
+ Commands::const_iterator cmd;
+
+ // Here we check whether or not the game currently accepts the command
+ // "SAVE GAME". This prevents saving via the GMM in situations where
+ // it wouldn't otherwise be possible to do so.
+ for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
+ if (matchCommand(*cmd, _saveVerb, _saveNoun)) {
+ if (cmd->verb != _saveVerb || cmd->noun != _saveNoun)
+ return false;
+ return cmd->numCond == 0 && cmd->script[0] == IDO_ACT_SAVE;
}
}
- printMessage(_messageIds.itemNotHere);
+ return false;
}
-void AdlEngine::dropItem(byte noun) {
- Common::Array<Item>::iterator item;
+void AdlEngine::wordWrap(Common::String &str) const {
+ uint end = 39;
- for (item = _state.items.begin(); item != _state.items.end(); ++item) {
- if (item->noun != noun || item->room != IDI_NONE)
- continue;
+ while (1) {
+ if (str.size() <= end)
+ return;
- item->room = _state.room;
- item->state = IDI_ITEM_MOVED;
- return;
+ while (str[end] != APPLECHAR(' '))
+ --end;
+
+ str.setChar(APPLECHAR('\r'), end);
+ end += 40;
}
+}
- printMessage(_messageIds.dontUnderstand);
+byte AdlEngine::convertKey(uint16 ascii) const {
+ ascii = toupper(ascii);
+
+ if (ascii >= 0x80)
+ return 0;
+
+ ascii |= 0x80;
+
+ if (ascii >= 0x80 && ascii <= 0xe0)
+ return ascii;
+
+ return 0;
}
-#define ARG(N) (command.script[offset + (N)])
+Common::String AdlEngine::getLine() const {
+ // Original engine uses a global here, which isn't reset between
+ // calls and may not match actual mode
+ bool textMode = false;
-void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
- for (uint i = 0; i < command.numAct; ++i) {
- switch (ARG(0)) {
- case IDO_ACT_VAR_ADD:
- var(ARG(2)) += ARG(1);
- offset += 3;
- break;
- case IDO_ACT_VAR_SUB:
- var(ARG(2)) -= ARG(1);
- offset += 3;
- break;
- case IDO_ACT_VAR_SET:
- var(ARG(1)) = ARG(2);
- offset += 3;
- break;
- case IDO_ACT_LIST_ITEMS: {
- Common::Array<Item>::const_iterator item;
+ while (1) {
+ Common::String line = inputString(APPLECHAR('?'));
- for (item = _state.items.begin(); item != _state.items.end(); ++item)
- if (item->room == IDI_NONE)
- printMessage(item->description);
+ if (shouldQuit() || _isRestoring)
+ return "";
- ++offset;
- break;
+ if ((byte)line[0] == ('\r' | 0x80)) {
+ textMode = !textMode;
+ _display->setMode(textMode ? DISPLAY_MODE_TEXT : DISPLAY_MODE_MIXED);
+ continue;
}
- case IDO_ACT_MOVE_ITEM:
- item(ARG(1)).room = ARG(2);
- offset += 3;
- break;
- case IDO_ACT_SET_ROOM:
- curRoom().curPicture = curRoom().picture;
- _state.room = ARG(1);
- offset += 2;
- break;
- case IDO_ACT_SET_CUR_PIC:
- curRoom().curPicture = ARG(1);
- offset += 2;
- break;
- case IDO_ACT_SET_PIC:
- curRoom().picture = curRoom().curPicture = ARG(1);
- offset += 2;
- break;
- case IDO_ACT_PRINT_MSG:
- printMessage(ARG(1));
- offset += 2;
- break;
- case IDO_ACT_SET_LIGHT:
- _state.isDark = false;
- ++offset;
- break;
- case IDO_ACT_SET_DARK:
- _state.isDark = true;
- ++offset;
- break;
- case IDO_ACT_SAVE:
- saveGameState(0, "");
- ++offset;
- break;
- case IDO_ACT_LOAD:
- loadGameState(0);
- ++offset;
- // Original engine does not jump out of the loop,
- // so we don't either.
- // We reset the restore flag, as the restore game
- // process is complete
- _isRestoring = false;
- break;
- case IDO_ACT_RESTART: {
- _display->printString(_strings.playAgain);
-
- // We allow restoring via GMM here
- _canRestoreNow = true;
- Common::String input = inputString();
- _canRestoreNow = false;
-
- // If the user restored with the GMM, we break off the restart
- if (_isRestoring)
- return;
-
- if (input.size() == 0 || input[0] != APPLECHAR('N')) {
- _isRestarting = true;
- _display->clear(0x00);
- _display->updateHiResScreen();
- restartGame();
- return;
- }
- // Fall-through
- }
- case IDO_ACT_QUIT:
- printMessage(_messageIds.thanksForPlaying);
- quitGame();
- return;
- case IDO_ACT_PLACE_ITEM:
- item(ARG(1)).room = ARG(2);
- item(ARG(1)).position.x = ARG(3);
- item(ARG(1)).position.y = ARG(4);
- offset += 5;
- break;
- case IDO_ACT_SET_ITEM_PIC:
- item(ARG(2)).picture = ARG(1);
- offset += 3;
- break;
- case IDO_ACT_RESET_PIC:
- curRoom().curPicture = curRoom().picture;
- ++offset;
- break;
- case IDO_ACT_GO_NORTH:
- case IDO_ACT_GO_SOUTH:
- case IDO_ACT_GO_EAST:
- case IDO_ACT_GO_WEST:
- case IDO_ACT_GO_UP:
- case IDO_ACT_GO_DOWN: {
- byte room = curRoom().connections[ARG(0) - IDO_ACT_GO_NORTH];
-
- if (room == 0) {
- printMessage(_messageIds.cantGoThere);
- return;
- }
- curRoom().curPicture = curRoom().picture;
- _state.room = room;
- return;
- }
- case IDO_ACT_TAKE_ITEM:
- takeItem(noun);
- ++offset;
- break;
- case IDO_ACT_DROP_ITEM:
- dropItem(noun);
- ++offset;
- break;
- case IDO_ACT_SET_ROOM_PIC:
- room(ARG(1)).picture = room(ARG(1)).curPicture = ARG(2);
- offset += 3;
- break;
- default:
- error("Invalid action opcode %02x", ARG(0));
- }
+ // Remove the return
+ line.deleteLastChar();
+ return line;
}
}
-bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, uint *actions) const {
- if (command.room != IDI_NONE && command.room != _state.room)
- return false;
+Common::String AdlEngine::getWord(const Common::String &line, uint &index) const {
+ Common::String str;
- if (command.verb != IDI_NONE && command.verb != verb)
- return false;
+ for (uint i = 0; i < 8; ++i)
+ str += APPLECHAR(' ');
- if (command.noun != IDI_NONE && command.noun != noun)
- return false;
+ int copied = 0;
- uint offset = 0;
- for (uint i = 0; i < command.numCond; ++i) {
- switch (ARG(0)) {
- case IDO_CND_ITEM_IN_ROOM:
- if (item(ARG(1)).room != ARG(2))
- return false;
- offset += 3;
- break;
- case IDO_CND_MOVES_GE:
- if (ARG(1) > _state.moves)
- return false;
- offset += 2;
- break;
- case IDO_CND_VAR_EQ:
- if (var(ARG(1)) != ARG(2))
- return false;
- offset += 3;
- break;
- case IDO_CND_CUR_PIC_EQ:
- if (curRoom().curPicture != ARG(1))
- return false;
- offset += 2;
- break;
- case IDO_CND_ITEM_PIC_EQ:
- if (item(ARG(1)).picture != ARG(2))
- return false;
- offset += 3;
+ // Skip initial whitespace
+ while (1) {
+ if (index == line.size())
+ return str;
+ if (line[index] != APPLECHAR(' '))
break;
- default:
- error("Invalid condition opcode %02x", command.script[offset]);
- }
+ ++index;
}
- *actions = offset;
+ // Copy up to 8 characters
+ while (1) {
+ if (copied < 8)
+ str.setChar(line[index], copied++);
- return true;
+ index++;
+
+ if (index == line.size() || line[index] == APPLECHAR(' '))
+ return str;
+ }
}
-#undef ARG
+void AdlEngine::getInput(uint &verb, uint &noun) {
+ while (1) {
+ _display->printString(_strings.enterCommand);
+ Common::String line = getLine();
-bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator cmd;
+ if (shouldQuit() || _isRestoring)
+ return;
- for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
- uint offset = 0;
- if (matchCommand(*cmd, verb, noun, &offset)) {
- doActions(*cmd, noun, offset);
- return true;
+ uint index = 0;
+ Common::String verbStr = getWord(line, index);
+
+ if (!_verbs.contains(verbStr)) {
+ Common::String err = _strings.verbError;
+ for (uint i = 0; i < verbStr.size(); ++i)
+ err.setChar(verbStr[i], i + 19);
+ _display->printString(err);
+ continue;
}
- }
- return false;
-}
+ verb = _verbs[verbStr];
-void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
- Commands::const_iterator cmd;
- bool oldIsRestoring = _isRestoring;
+ Common::String nounStr = getWord(line, index);
- for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
- uint offset = 0;
- if (matchCommand(*cmd, verb, noun, &offset))
- doActions(*cmd, noun, offset);
+ if (!_nouns.contains(nounStr)) {
+ Common::String err = _strings.nounError;
+ for (uint i = 0; i < verbStr.size(); ++i)
+ err.setChar(verbStr[i], i + 19);
+ for (uint i = 0; i < nounStr.size(); ++i)
+ err.setChar(nounStr[i], i + 30);
+ _display->printString(err);
+ continue;
+ }
- // We assume no restarts happen in this command group. This
- // simplifies enabling GMM savegame loading on the restart
- // prompt.
- if (_isRestarting || _isRestoring != oldIsRestoring)
- error("Unexpected restart action encountered");
+ noun = _nouns[nounStr];
+ return;
}
}
-bool AdlEngine::canSaveGameStateCurrently() const {
- if (!_canSaveNow)
- return false;
-
- Commands::const_iterator cmd;
-
- // Here we check whether or not the game currently accepts the command
- // "SAVE GAME". This prevents saving via the GMM in situations where
- // it wouldn't otherwise be possible to do so.
- for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
- if (matchCommand(*cmd, _saveVerb, _saveNoun)) {
- if (cmd->verb != _saveVerb || cmd->noun != _saveNoun)
- return false;
- return cmd->numCond == 0 && cmd->script[0] == IDO_ACT_SAVE;
- }
+void AdlEngine::showRoom() const {
+ if (!_state.isDark) {
+ drawPic(curRoom().curPicture);
+ drawItems();
}
- return false;
-}
-
-bool AdlEngine::canLoadGameStateCurrently() const {
- return _canRestoreNow;
+ _display->updateHiResScreen();
+ printMessage(curRoom().description, false);
}
void AdlEngine::clearScreen() const {
@@ -554,163 +683,49 @@ void AdlEngine::drawItems() const {
}
}
-void AdlEngine::showRoom() const {
- if (!_state.isDark) {
- drawPic(curRoom().curPicture);
- drawItems();
- }
-
- _display->updateHiResScreen();
- printMessage(curRoom().description, false);
-}
-
-Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
- Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
- Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName);
-
- if (!outFile) {
- warning("Failed to open file '%s'", fileName.c_str());
- return Common::kUnknownError;
- }
-
- outFile->writeUint32BE(MKTAG('A', 'D', 'L', ':'));
- outFile->writeByte(SAVEGAME_VERSION);
-
- char name[SAVEGAME_NAME_LEN] = { };
-
- if (!desc.empty())
- strncpy(name, desc.c_str(), sizeof(name) - 1);
- else {
- Common::String defaultName("Save ");
- defaultName += 'A' + slot;
- strncpy(name, defaultName.c_str(), sizeof(name) - 1);
- }
-
- outFile->write(name, sizeof(name));
-
- TimeDate t;
- g_system->getTimeAndDate(t);
-
- outFile->writeUint16BE(t.tm_year);
- outFile->writeByte(t.tm_mon);
- outFile->writeByte(t.tm_mday);
- outFile->writeByte(t.tm_hour);
- outFile->writeByte(t.tm_min);
-
- uint32 playTime = getTotalPlayTime();
- outFile->writeUint32BE(playTime);
-
- _display->saveThumbnail(*outFile);
-
- outFile->writeByte(_state.room);
- outFile->writeByte(_state.moves);
- outFile->writeByte(_state.isDark);
-
- outFile->writeUint32BE(_state.rooms.size());
- for (uint i = 0; i < _state.rooms.size(); ++i) {
- outFile->writeByte(_state.rooms[i].picture);
- outFile->writeByte(_state.rooms[i].curPicture);
- }
-
- outFile->writeUint32BE(_state.items.size());
- for (uint i = 0; i < _state.items.size(); ++i) {
- outFile->writeByte(_state.items[i].room);
- outFile->writeByte(_state.items[i].picture);
- outFile->writeByte(_state.items[i].position.x);
- outFile->writeByte(_state.items[i].position.y);
- outFile->writeByte(_state.items[i].state);
- }
-
- outFile->writeUint32BE(_state.vars.size());
- for (uint i = 0; i < _state.vars.size(); ++i)
- outFile->writeByte(_state.vars[i]);
-
- outFile->finalize();
+void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const {
+ if (bits & 4)
+ _display->putPixel(p, color);
- if (outFile->err()) {
- delete outFile;
- warning("Failed to save game '%s'", fileName.c_str());
- return Common::kUnknownError;
- }
+ bits += quadrant;
- delete outFile;
- return Common::kNoError;
+ if (bits & 1)
+ p.x += (bits & 2 ? -1 : 1);
+ else
+ p.y += (bits & 2 ? 1 : -1);
}
-Common::Error AdlEngine::loadGameState(int slot) {
- Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot);
- Common::InSaveFile *inFile = getSaveFileManager()->openForLoading(fileName);
-
- if (!inFile) {
- warning("Failed to open file '%s'", fileName.c_str());
- return Common::kUnknownError;
- }
-
- if (inFile->readUint32BE() != MKTAG('A', 'D', 'L', ':')) {
- warning("No header found in '%s'", fileName.c_str());
- delete inFile;
- return Common::kUnknownError;
- }
-
- byte saveVersion = inFile->readByte();
- if (saveVersion != SAVEGAME_VERSION) {
- warning("Save game version %i not supported", saveVersion);
- delete inFile;
- return Common::kUnknownError;
- }
-
- // Skip description
- inFile->seek(SAVEGAME_NAME_LEN, SEEK_CUR);
- // Skip save time
- inFile->seek(6, SEEK_CUR);
-
- uint32 playTime = inFile->readUint32BE();
-
- Graphics::skipThumbnail(*inFile);
-
- initState();
-
- _state.room = inFile->readByte();
- _state.moves = inFile->readByte();
- _state.isDark = inFile->readByte();
+void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, const Common::Point &pos, byte rotation, byte scaling, byte color) const {
+ const byte stepping[] = {
+ 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
+ 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
+ 0xff
+ };
- uint32 size = inFile->readUint32BE();
- if (size != _state.rooms.size())
- error("Room count mismatch (expected %i; found %i)", _state.rooms.size(), size);
+ byte quadrant = rotation >> 4;
+ rotation &= 0xf;
+ byte xStep = stepping[rotation];
+ byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
- for (uint i = 0; i < size; ++i) {
- _state.rooms[i].picture = inFile->readByte();
- _state.rooms[i].curPicture = inFile->readByte();
- }
+ Common::Point p(pos);
- size = inFile->readUint32BE();
- if (size != _state.items.size())
- error("Item count mismatch (expected %i; found %i)", _state.items.size(), size);
+ for (uint i = 0; i < lineArt.size(); ++i) {
+ byte b = lineArt[i];
- for (uint i = 0; i < size; ++i) {
- _state.items[i].room = inFile->readByte();
- _state.items[i].picture = inFile->readByte();
- _state.items[i].position.x = inFile->readByte();
- _state.items[i].position.y = inFile->readByte();
- _state.items[i].state = inFile->readByte();
+ do {
+ byte xFrac = 0x80;
+ byte yFrac = 0x80;
+ for (uint j = 0; j < scaling; ++j) {
+ if (xFrac + xStep + 1 > 255)
+ drawNextPixel(p, color, b, quadrant);
+ xFrac += xStep + 1;
+ if (yFrac + yStep > 255)
+ drawNextPixel(p, color, b, quadrant + 1);
+ yFrac += yStep;
+ }
+ b >>= 3;
+ } while (b != 0);
}
-
- size = inFile->readUint32BE();
- if (size != _state.vars.size())
- error("Variable count mismatch (expected %i; found %i)", _state.vars.size(), size);
-
- for (uint i = 0; i < size; ++i)
- _state.vars[i] = inFile->readByte();
-
- if (inFile->err() || inFile->eos())
- error("Failed to load game '%s'", fileName.c_str());
-
- delete inFile;
-
- setTotalPlayTime(playTime);
-
- _isRestoring = true;
- return Common::kNoError;
}
const Room &AdlEngine::room(uint i) const {
@@ -763,287 +778,272 @@ byte &AdlEngine::var(uint i) {
return _state.vars[i];
}
-void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map) const {
- uint index = 0;
-
- while (1) {
- ++index;
-
- byte buf[IDI_WORD_SIZE];
-
- if (stream.read(buf, IDI_WORD_SIZE) < IDI_WORD_SIZE)
- error("Error reading word list");
-
- Common::String word((char *)buf, IDI_WORD_SIZE);
-
- if (!map.contains(word))
- map[word] = index;
-
- byte synonyms = stream.readByte();
-
- if (stream.err() || stream.eos())
- error("Error reading word list");
+void AdlEngine::takeItem(byte noun) {
+ Common::Array<Item>::iterator item;
- if (synonyms == 0xff)
- break;
+ for (item = _state.items.begin(); item != _state.items.end(); ++item) {
+ if (item->noun != noun || item->room != _state.room)
+ continue;
- for (uint i = 0; i < synonyms; ++i) {
- if (stream.read((char *)buf, IDI_WORD_SIZE) < IDI_WORD_SIZE)
- error("Error reading word list");
+ if (item->state == IDI_ITEM_DOESNT_MOVE) {
+ printMessage(_messageIds.itemDoesntMove);
+ return;
+ }
- word = Common::String((char *)buf, IDI_WORD_SIZE);
+ if (item->state == IDI_ITEM_MOVED) {
+ item->room = IDI_NONE;
+ return;
+ }
- if (!map.contains(word))
- map[word] = index;
+ Common::Array<byte>::const_iterator pic;
+ for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
+ if (*pic == curRoom().curPicture) {
+ item->room = IDI_NONE;
+ item->state = IDI_ITEM_MOVED;
+ return;
+ }
}
}
-}
-Common::String AdlEngine::getLine() const {
- // Original engine uses a global here, which isn't reset between
- // calls and may not match actual mode
- bool textMode = false;
-
- while (1) {
- Common::String line = inputString(APPLECHAR('?'));
+ printMessage(_messageIds.itemNotHere);
+}
- if (shouldQuit() || _isRestoring)
- return "";
+void AdlEngine::dropItem(byte noun) {
+ Common::Array<Item>::iterator item;
- if ((byte)line[0] == ('\r' | 0x80)) {
- textMode = !textMode;
- _display->setMode(textMode ? DISPLAY_MODE_TEXT : DISPLAY_MODE_MIXED);
+ for (item = _state.items.begin(); item != _state.items.end(); ++item) {
+ if (item->noun != noun || item->room != IDI_NONE)
continue;
- }
- // Remove the return
- line.deleteLastChar();
- return line;
+ item->room = _state.room;
+ item->state = IDI_ITEM_MOVED;
+ return;
}
+
+ printMessage(_messageIds.dontUnderstand);
}
-Common::String AdlEngine::getWord(const Common::String &line, uint &index) const {
- Common::String str;
+#define ARG(N) (command.script[offset + (N)])
- for (uint i = 0; i < 8; ++i)
- str += APPLECHAR(' ');
+bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, uint *actions) const {
+ if (command.room != IDI_NONE && command.room != _state.room)
+ return false;
- int copied = 0;
+ if (command.verb != IDI_NONE && command.verb != verb)
+ return false;
- // Skip initial whitespace
- while (1) {
- if (index == line.size())
- return str;
- if (line[index] != APPLECHAR(' '))
+ if (command.noun != IDI_NONE && command.noun != noun)
+ return false;
+
+ uint offset = 0;
+ for (uint i = 0; i < command.numCond; ++i) {
+ switch (ARG(0)) {
+ case IDO_CND_ITEM_IN_ROOM:
+ if (item(ARG(1)).room != ARG(2))
+ return false;
+ offset += 3;
break;
- ++index;
+ case IDO_CND_MOVES_GE:
+ if (ARG(1) > _state.moves)
+ return false;
+ offset += 2;
+ break;
+ case IDO_CND_VAR_EQ:
+ if (var(ARG(1)) != ARG(2))
+ return false;
+ offset += 3;
+ break;
+ case IDO_CND_CUR_PIC_EQ:
+ if (curRoom().curPicture != ARG(1))
+ return false;
+ offset += 2;
+ break;
+ case IDO_CND_ITEM_PIC_EQ:
+ if (item(ARG(1)).picture != ARG(2))
+ return false;
+ offset += 3;
+ break;
+ default:
+ error("Invalid condition opcode %02x", command.script[offset]);
+ }
}
- // Copy up to 8 characters
- while (1) {
- if (copied < 8)
- str.setChar(line[index], copied++);
-
- index++;
+ *actions = offset;
- if (index == line.size() || line[index] == APPLECHAR(' '))
- return str;
- }
+ return true;
}
-void AdlEngine::getInput(uint &verb, uint &noun) {
- while (1) {
- _display->printString(_strings.enterCommand);
- Common::String line = getLine();
-
- if (shouldQuit() || _isRestoring)
- return;
-
- uint index = 0;
- Common::String verbStr = getWord(line, index);
-
- if (!_verbs.contains(verbStr)) {
- Common::String err = _strings.verbError;
- for (uint i = 0; i < verbStr.size(); ++i)
- err.setChar(verbStr[i], i + 19);
- _display->printString(err);
- continue;
- }
-
- verb = _verbs[verbStr];
+void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
+ for (uint i = 0; i < command.numAct; ++i) {
+ switch (ARG(0)) {
+ case IDO_ACT_VAR_ADD:
+ var(ARG(2)) += ARG(1);
+ offset += 3;
+ break;
+ case IDO_ACT_VAR_SUB:
+ var(ARG(2)) -= ARG(1);
+ offset += 3;
+ break;
+ case IDO_ACT_VAR_SET:
+ var(ARG(1)) = ARG(2);
+ offset += 3;
+ break;
+ case IDO_ACT_LIST_ITEMS: {
+ Common::Array<Item>::const_iterator item;
- Common::String nounStr = getWord(line, index);
+ for (item = _state.items.begin(); item != _state.items.end(); ++item)
+ if (item->room == IDI_NONE)
+ printMessage(item->description);
- if (!_nouns.contains(nounStr)) {
- Common::String err = _strings.nounError;
- for (uint i = 0; i < verbStr.size(); ++i)
- err.setChar(verbStr[i], i + 19);
- for (uint i = 0; i < nounStr.size(); ++i)
- err.setChar(nounStr[i], i + 30);
- _display->printString(err);
- continue;
+ ++offset;
+ break;
}
+ case IDO_ACT_MOVE_ITEM:
+ item(ARG(1)).room = ARG(2);
+ offset += 3;
+ break;
+ case IDO_ACT_SET_ROOM:
+ curRoom().curPicture = curRoom().picture;
+ _state.room = ARG(1);
+ offset += 2;
+ break;
+ case IDO_ACT_SET_CUR_PIC:
+ curRoom().curPicture = ARG(1);
+ offset += 2;
+ break;
+ case IDO_ACT_SET_PIC:
+ curRoom().picture = curRoom().curPicture = ARG(1);
+ offset += 2;
+ break;
+ case IDO_ACT_PRINT_MSG:
+ printMessage(ARG(1));
+ offset += 2;
+ break;
+ case IDO_ACT_SET_LIGHT:
+ _state.isDark = false;
+ ++offset;
+ break;
+ case IDO_ACT_SET_DARK:
+ _state.isDark = true;
+ ++offset;
+ break;
+ case IDO_ACT_SAVE:
+ saveGameState(0, "");
+ ++offset;
+ break;
+ case IDO_ACT_LOAD:
+ loadGameState(0);
+ ++offset;
+ // Original engine does not jump out of the loop,
+ // so we don't either.
+ // We reset the restore flag, as the restore game
+ // process is complete
+ _isRestoring = false;
+ break;
+ case IDO_ACT_RESTART: {
+ _display->printString(_strings.playAgain);
- noun = _nouns[nounStr];
- return;
- }
-}
-
-Common::String AdlEngine::inputString(byte prompt) const {
- Common::String s;
-
- if (prompt > 0)
- _display->printString(Common::String(prompt));
-
- while (1) {
- byte b = inputKey();
-
- if (g_engine->shouldQuit() || _isRestoring)
- return 0;
-
- if (b == 0)
- continue;
+ // We allow restoring via GMM here
+ _canRestoreNow = true;
+ Common::String input = inputString();
+ _canRestoreNow = false;
- if (b == ('\r' | 0x80)) {
- s += b;
- _display->printString(Common::String(b));
- return s;
- }
+ // If the user restored with the GMM, we break off the restart
+ if (_isRestoring)
+ return;
- if (b < 0xa0) {
- switch (b) {
- case Common::KEYCODE_BACKSPACE | 0x80:
- if (!s.empty()) {
- _display->moveCursorBackward();
- _display->setCharAtCursor(APPLECHAR(' '));
- s.deleteLastChar();
- }
- break;
- };
- } else {
- s += b;
- _display->printString(Common::String(b));
+ if (input.size() == 0 || input[0] != APPLECHAR('N')) {
+ _isRestarting = true;
+ _display->clear(0x00);
+ _display->updateHiResScreen();
+ restartGame();
+ return;
+ }
+ // Fall-through
}
- }
-}
-
-byte AdlEngine::convertKey(uint16 ascii) const {
- ascii = toupper(ascii);
-
- if (ascii >= 0x80)
- return 0;
-
- ascii |= 0x80;
-
- if (ascii >= 0x80 && ascii <= 0xe0)
- return ascii;
-
- return 0;
-}
-
-byte AdlEngine::inputKey() const {
- Common::EventManager *ev = g_system->getEventManager();
-
- byte key = 0;
-
- _display->showCursor(true);
-
- while (!g_engine->shouldQuit() && !_isRestoring && key == 0) {
- Common::Event event;
- if (ev->pollEvent(event)) {
- if (event.type != Common::EVENT_KEYDOWN)
- continue;
+ case IDO_ACT_QUIT:
+ printMessage(_messageIds.thanksForPlaying);
+ quitGame();
+ return;
+ case IDO_ACT_PLACE_ITEM:
+ item(ARG(1)).room = ARG(2);
+ item(ARG(1)).position.x = ARG(3);
+ item(ARG(1)).position.y = ARG(4);
+ offset += 5;
+ break;
+ case IDO_ACT_SET_ITEM_PIC:
+ item(ARG(2)).picture = ARG(1);
+ offset += 3;
+ break;
+ case IDO_ACT_RESET_PIC:
+ curRoom().curPicture = curRoom().picture;
+ ++offset;
+ break;
+ case IDO_ACT_GO_NORTH:
+ case IDO_ACT_GO_SOUTH:
+ case IDO_ACT_GO_EAST:
+ case IDO_ACT_GO_WEST:
+ case IDO_ACT_GO_UP:
+ case IDO_ACT_GO_DOWN: {
+ byte room = curRoom().connections[ARG(0) - IDO_ACT_GO_NORTH];
- if (event.kbd.flags & Common::KBD_CTRL) {
- if (event.kbd.keycode == Common::KEYCODE_q)
- g_engine->quitGame();
- continue;
+ if (room == 0) {
+ printMessage(_messageIds.cantGoThere);
+ return;
}
- switch (event.kbd.keycode) {
- case Common::KEYCODE_BACKSPACE:
- case Common::KEYCODE_RETURN:
- key = convertKey(event.kbd.keycode);
- break;
- default:
- if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80)
- key = convertKey(event.kbd.ascii);
- };
+ curRoom().curPicture = curRoom().picture;
+ _state.room = room;
+ return;
+ }
+ case IDO_ACT_TAKE_ITEM:
+ takeItem(noun);
+ ++offset;
+ break;
+ case IDO_ACT_DROP_ITEM:
+ dropItem(noun);
+ ++offset;
+ break;
+ case IDO_ACT_SET_ROOM_PIC:
+ room(ARG(1)).picture = room(ARG(1)).curPicture = ARG(2);
+ offset += 3;
+ break;
+ default:
+ error("Invalid action opcode %02x", ARG(0));
}
-
- _display->updateTextScreen();
- g_system->delayMillis(16);
}
-
- _display->showCursor(false);
-
- return key;
}
-void AdlEngine::delay(uint32 ms) const {
- Common::EventManager *ev = g_system->getEventManager();
+#undef ARG
- uint32 start = g_system->getMillis();
+bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator cmd;
- while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) {
- Common::Event event;
- if (ev->pollEvent(event)) {
- if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) {
- switch(event.kbd.keycode) {
- case Common::KEYCODE_q:
- g_engine->quitGame();
- break;
- default:
- break;
- }
- }
+ for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
+ uint offset = 0;
+ if (matchCommand(*cmd, verb, noun, &offset)) {
+ doActions(*cmd, noun, offset);
+ return true;
}
- g_system->delayMillis(16);
}
-}
-void AdlEngine::drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const {
- if (bits & 4)
- _display->putPixel(p, color);
-
- bits += quadrant;
-
- if (bits & 1)
- p.x += (bits & 2 ? -1 : 1);
- else
- p.y += (bits & 2 ? 1 : -1);
+ return false;
}
-void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, const Common::Point &pos, byte rotation, byte scaling, byte color) const {
- const byte stepping[] = {
- 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
- 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
- 0xff
- };
-
- byte quadrant = rotation >> 4;
- rotation &= 0xf;
- byte xStep = stepping[rotation];
- byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
-
- Common::Point p(pos);
+void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
+ Commands::const_iterator cmd;
+ bool oldIsRestoring = _isRestoring;
- for (uint i = 0; i < lineArt.size(); ++i) {
- byte b = lineArt[i];
+ for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
+ uint offset = 0;
+ if (matchCommand(*cmd, verb, noun, &offset))
+ doActions(*cmd, noun, offset);
- do {
- byte xFrac = 0x80;
- byte yFrac = 0x80;
- for (uint j = 0; j < scaling; ++j) {
- if (xFrac + xStep + 1 > 255)
- drawNextPixel(p, color, b, quadrant);
- xFrac += xStep + 1;
- if (yFrac + yStep > 255)
- drawNextPixel(p, color, b, quadrant + 1);
- yFrac += yStep;
- }
- b >>= 3;
- } while (b != 0);
+ // We assume no restarts happen in this command group. This
+ // simplifies enabling GMM savegame loading on the restart
+ // prompt.
+ if (_isRestarting || _isRestoring != oldIsRestoring)
+ error("Unexpected restart action encountered");
}
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index b1d5b7c..a230f0f 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -23,8 +23,9 @@
#ifndef ADL_ADL_H
#define ADL_ADL_H
-#include "common/random.h"
+#include "common/array.h"
#include "common/rect.h"
+#include "common/str.h"
#include "engines/engine.h"
@@ -34,16 +35,10 @@ class SeekableReadStream;
}
namespace Adl {
+
class Display;
-class Parser;
-class Console;
struct AdlGameDescription;
-struct StringOffset {
- int stringIdx;
- uint offset;
-};
-
// Conditional opcodes
#define IDO_CND_ITEM_IN_ROOM 0x03
#define IDO_CND_MOVES_GE 0x05
@@ -155,7 +150,6 @@ protected:
void readCommands(Common::ReadStream &stream, Commands &commands);
Display *_display;
- Parser *_parser;
// Message strings in data file
Common::Array<Common::String> _messages;
@@ -236,9 +230,9 @@ private:
void takeItem(byte noun);
void dropItem(byte noun);
bool matchCommand(const Command &command, byte verb, byte noun, uint *actions = nullptr) const;
+ void doActions(const Command &command, byte noun, byte offset);
bool doOneCommand(const Commands &commands, byte verb, byte noun);
void doAllCommands(const Commands &commands, byte verb, byte noun);
- void doActions(const Command &command, byte noun, byte offset);
const AdlGameDescription *_gameDescription;
bool _isRestarting, _isRestoring;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 95f0289..6e1e31d 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -136,113 +136,6 @@ void HiRes1Engine::runIntro() const {
delay(2000);
}
-void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos) const {
- byte x, y;
- bool bNewLine = false;
- byte oldX = 0, oldY = 0;
- while (1) {
- x = stream.readByte();
- y = stream.readByte();
-
- if (stream.err() || stream.eos())
- error("Failed to read picture");
-
- if (x == 0xff && y == 0xff)
- return;
-
- if (x == 0 && y == 0) {
- bNewLine = true;
- continue;
- }
-
- x += pos.x;
- y += pos.y;
-
- if (y > 160)
- y = 160;
-
- if (bNewLine) {
- _display->putPixel(Common::Point(x, y), 0x7f);
- bNewLine = false;
- } else {
- drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
- }
-
- oldX = x;
- oldY = y;
- }
-}
-
-void HiRes1Engine::drawPic(byte pic, Common::Point pos) const {
- Common::File f;
- Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
-
- if (!f.open(name))
- error("Failed to open file '%s'", name.c_str());
-
- f.seek(_pictures[pic].offset);
- drawPic(f, pos);
-}
-
-void HiRes1Engine::initState() {
- Common::File f;
-
- _state.room = 1;
- _state.moves = 0;
- _state.isDark = false;
-
- _state.vars.clear();
- _state.vars.resize(IDI_HR1_NUM_VARS);
-
- if (!f.open(IDS_HR1_EXE_1))
- error("Failed to open file '" IDS_HR1_EXE_1 "'");
-
- // Load room data from executable
- _state.rooms.clear();
- f.seek(IDI_HR1_OFS_ROOMS);
- for (uint i = 0; i < IDI_HR1_NUM_ROOMS; ++i) {
- Room room;
- f.readByte();
- room.description = f.readByte();
- for (uint j = 0; j < 6; ++j)
- room.connections[j] = f.readByte();
- room.picture = f.readByte();
- room.curPicture = f.readByte();
- _state.rooms.push_back(room);
- }
-
- // Load item data from executable
- _state.items.clear();
- f.seek(IDI_HR1_OFS_ITEMS);
- while (f.readByte() != 0xff) {
- Item item;
- item.noun = f.readByte();
- item.room = f.readByte();
- item.picture = f.readByte();
- item.isLineArt = f.readByte();
- item.position.x = f.readByte();
- item.position.y = f.readByte();
- item.state = f.readByte();
- item.description = f.readByte();
-
- f.readByte();
-
- byte size = f.readByte();
-
- for (uint i = 0; i < size; ++i)
- item.roomPictures.push_back(f.readByte());
-
- _state.items.push_back(item);
- }
-}
-
-void HiRes1Engine::restartGame() {
- initState();
- _display->printString(_gameStrings.pressReturn);
- inputString(); // Missing in the original
- _display->printAsciiString("\r\r\r\r\r");
-}
-
void HiRes1Engine::loadData() {
Common::File f;
@@ -331,6 +224,76 @@ void HiRes1Engine::loadData() {
loadWords(f, _nouns);
}
+void HiRes1Engine::initState() {
+ Common::File f;
+
+ _state.room = 1;
+ _state.moves = 0;
+ _state.isDark = false;
+
+ _state.vars.clear();
+ _state.vars.resize(IDI_HR1_NUM_VARS);
+
+ if (!f.open(IDS_HR1_EXE_1))
+ error("Failed to open file '" IDS_HR1_EXE_1 "'");
+
+ // Load room data from executable
+ _state.rooms.clear();
+ f.seek(IDI_HR1_OFS_ROOMS);
+ for (uint i = 0; i < IDI_HR1_NUM_ROOMS; ++i) {
+ Room room;
+ f.readByte();
+ room.description = f.readByte();
+ for (uint j = 0; j < 6; ++j)
+ room.connections[j] = f.readByte();
+ room.picture = f.readByte();
+ room.curPicture = f.readByte();
+ _state.rooms.push_back(room);
+ }
+
+ // Load item data from executable
+ _state.items.clear();
+ f.seek(IDI_HR1_OFS_ITEMS);
+ while (f.readByte() != 0xff) {
+ Item item;
+ item.noun = f.readByte();
+ item.room = f.readByte();
+ item.picture = f.readByte();
+ item.isLineArt = f.readByte();
+ item.position.x = f.readByte();
+ item.position.y = f.readByte();
+ item.state = f.readByte();
+ item.description = f.readByte();
+
+ f.readByte();
+
+ byte size = f.readByte();
+
+ for (uint i = 0; i < size; ++i)
+ item.roomPictures.push_back(f.readByte());
+
+ _state.items.push_back(item);
+ }
+}
+
+void HiRes1Engine::restartGame() {
+ initState();
+ _display->printString(_gameStrings.pressReturn);
+ inputString(); // Missing in the original
+ _display->printAsciiString("\r\r\r\r\r");
+}
+
+void HiRes1Engine::drawPic(byte pic, Common::Point pos) const {
+ Common::File f;
+ Common::String name = Common::String::format("BLOCK%i", _pictures[pic].block);
+
+ if (!f.open(name))
+ error("Failed to open file '%s'", name.c_str());
+
+ f.seek(_pictures[pic].offset);
+ drawPic(f, pos);
+}
+
void HiRes1Engine::printMessage(uint idx, bool wait) const {
// Messages with hardcoded overrides don't delay after printing.
// It's unclear if this is a bug or not. In some cases the result
@@ -389,6 +352,43 @@ void HiRes1Engine::drawLine(const Common::Point &p1, const Common::Point &p2, by
}
}
+void HiRes1Engine::drawPic(Common::ReadStream &stream, const Common::Point &pos) const {
+ byte x, y;
+ bool bNewLine = false;
+ byte oldX = 0, oldY = 0;
+ while (1) {
+ x = stream.readByte();
+ y = stream.readByte();
+
+ if (stream.err() || stream.eos())
+ error("Failed to read picture");
+
+ if (x == 0xff && y == 0xff)
+ return;
+
+ if (x == 0 && y == 0) {
+ bNewLine = true;
+ continue;
+ }
+
+ x += pos.x;
+ y += pos.y;
+
+ if (y > 160)
+ y = 160;
+
+ if (bNewLine) {
+ _display->putPixel(Common::Point(x, y), 0x7f);
+ bNewLine = false;
+ } else {
+ drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
+ }
+
+ oldX = x;
+ oldY = y;
+ }
+}
+
Engine *HiRes1Engine_create(OSystem *syst, const AdlGameDescription *gd) {
return new HiRes1Engine(syst, gd);
}
diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h
index b7c7f41..d9d67c4 100644
--- a/engines/adl/hires1.h
+++ b/engines/adl/hires1.h
@@ -23,6 +23,8 @@
#ifndef ADL_HIRES1_H
#define ADL_HIRES1_H
+#include "common/str.h"
+
#include "adl/adl.h"
namespace Common {
Commit: 57af92e0c11d578ba5361d07d569f0d480a9a29f
https://github.com/scummvm/scummvm/commit/57af92e0c11d578ba5361d07d569f0d480a9a29f
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix shadowing warning (GCC 4.8)
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index dd4f406..92b74d2 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -635,12 +635,12 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
void AdlEngine::showRoom() const {
if (!_state.isDark) {
- drawPic(curRoom().curPicture);
+ drawPic(getCurRoom().curPicture);
drawItems();
}
_display->updateHiResScreen();
- printMessage(curRoom().description, false);
+ printMessage(getCurRoom().description, false);
}
void AdlEngine::clearScreen() const {
@@ -658,7 +658,7 @@ void AdlEngine::drawItems() const {
continue;
if (item->state == IDI_ITEM_MOVED) {
- if (curRoom().picture == curRoom().curPicture) {
+ if (getCurRoom().picture == getCurRoom().curPicture) {
const Common::Point &p = _itemOffsets[dropped];
if (item->isLineArt)
drawLineArt(_lineArt[item->picture - 1], p);
@@ -672,7 +672,7 @@ void AdlEngine::drawItems() const {
Common::Array<byte>::const_iterator pic;
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == curRoom().curPicture) {
+ if (*pic == getCurRoom().curPicture) {
if (item->isLineArt)
drawLineArt(_lineArt[item->picture - 1], item->position);
else
@@ -728,54 +728,54 @@ void AdlEngine::drawLineArt(const Common::Array<byte> &lineArt, const Common::Po
}
}
-const Room &AdlEngine::room(uint i) const {
+const Room &AdlEngine::getRoom(uint i) const {
if (i < 1 || i > _state.rooms.size())
error("Room %i out of range [1, %i]", i, _state.rooms.size());
return _state.rooms[i - 1];
}
-Room &AdlEngine::room(uint i) {
+Room &AdlEngine::getRoom(uint i) {
if (i < 1 || i > _state.rooms.size())
error("Room %i out of range [1, %i]", i, _state.rooms.size());
return _state.rooms[i - 1];
}
-const Room &AdlEngine::curRoom() const {
- return room(_state.room);
+const Room &AdlEngine::getCurRoom() const {
+ return getRoom(_state.room);
}
-Room &AdlEngine::curRoom() {
- return room(_state.room);
+Room &AdlEngine::getCurRoom() {
+ return getRoom(_state.room);
}
-const Item &AdlEngine::item(uint i) const {
+const Item &AdlEngine::getItem(uint i) const {
if (i < 1 || i > _state.items.size())
error("Item %i out of range [1, %i]", i, _state.items.size());
return _state.items[i - 1];
}
-Item &AdlEngine::item(uint i) {
+Item &AdlEngine::getItem(uint i) {
if (i < 1 || i > _state.items.size())
error("Item %i out of range [1, %i]", i, _state.items.size());
return _state.items[i - 1];
}
-const byte &AdlEngine::var(uint i) const {
+byte AdlEngine::getVar(uint i) const {
if (i >= _state.vars.size())
error("Variable %i out of range [0, %i]", i, _state.vars.size() - 1);
return _state.vars[i];
}
-byte &AdlEngine::var(uint i) {
+void AdlEngine::setVar(uint i, byte value) {
if (i >= _state.vars.size())
error("Variable %i out of range [0, %i]", i, _state.vars.size() - 1);
- return _state.vars[i];
+ _state.vars[i] = value;
}
void AdlEngine::takeItem(byte noun) {
@@ -797,7 +797,7 @@ void AdlEngine::takeItem(byte noun) {
Common::Array<byte>::const_iterator pic;
for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) {
- if (*pic == curRoom().curPicture) {
+ if (*pic == getCurRoom().curPicture) {
item->room = IDI_NONE;
item->state = IDI_ITEM_MOVED;
return;
@@ -839,7 +839,7 @@ bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, uint
for (uint i = 0; i < command.numCond; ++i) {
switch (ARG(0)) {
case IDO_CND_ITEM_IN_ROOM:
- if (item(ARG(1)).room != ARG(2))
+ if (getItem(ARG(1)).room != ARG(2))
return false;
offset += 3;
break;
@@ -849,17 +849,17 @@ bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, uint
offset += 2;
break;
case IDO_CND_VAR_EQ:
- if (var(ARG(1)) != ARG(2))
+ if (getVar(ARG(1)) != ARG(2))
return false;
offset += 3;
break;
case IDO_CND_CUR_PIC_EQ:
- if (curRoom().curPicture != ARG(1))
+ if (getCurRoom().curPicture != ARG(1))
return false;
offset += 2;
break;
case IDO_CND_ITEM_PIC_EQ:
- if (item(ARG(1)).picture != ARG(2))
+ if (getItem(ARG(1)).picture != ARG(2))
return false;
offset += 3;
break;
@@ -877,15 +877,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
for (uint i = 0; i < command.numAct; ++i) {
switch (ARG(0)) {
case IDO_ACT_VAR_ADD:
- var(ARG(2)) += ARG(1);
+ setVar(ARG(2), getVar(ARG(2) + ARG(1)));
offset += 3;
break;
case IDO_ACT_VAR_SUB:
- var(ARG(2)) -= ARG(1);
+ setVar(ARG(2), getVar(ARG(2)) - ARG(1));
offset += 3;
break;
case IDO_ACT_VAR_SET:
- var(ARG(1)) = ARG(2);
+ setVar(ARG(1), ARG(2));
offset += 3;
break;
case IDO_ACT_LIST_ITEMS: {
@@ -899,20 +899,20 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
}
case IDO_ACT_MOVE_ITEM:
- item(ARG(1)).room = ARG(2);
+ getItem(ARG(1)).room = ARG(2);
offset += 3;
break;
case IDO_ACT_SET_ROOM:
- curRoom().curPicture = curRoom().picture;
+ getCurRoom().curPicture = getCurRoom().picture;
_state.room = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_CUR_PIC:
- curRoom().curPicture = ARG(1);
+ getCurRoom().curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_SET_PIC:
- curRoom().picture = curRoom().curPicture = ARG(1);
+ getCurRoom().picture = getCurRoom().curPicture = ARG(1);
offset += 2;
break;
case IDO_ACT_PRINT_MSG:
@@ -966,17 +966,17 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
quitGame();
return;
case IDO_ACT_PLACE_ITEM:
- item(ARG(1)).room = ARG(2);
- item(ARG(1)).position.x = ARG(3);
- item(ARG(1)).position.y = ARG(4);
+ getItem(ARG(1)).room = ARG(2);
+ getItem(ARG(1)).position.x = ARG(3);
+ getItem(ARG(1)).position.y = ARG(4);
offset += 5;
break;
case IDO_ACT_SET_ITEM_PIC:
- item(ARG(2)).picture = ARG(1);
+ getItem(ARG(2)).picture = ARG(1);
offset += 3;
break;
case IDO_ACT_RESET_PIC:
- curRoom().curPicture = curRoom().picture;
+ getCurRoom().curPicture = getCurRoom().picture;
++offset;
break;
case IDO_ACT_GO_NORTH:
@@ -985,14 +985,14 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
case IDO_ACT_GO_WEST:
case IDO_ACT_GO_UP:
case IDO_ACT_GO_DOWN: {
- byte room = curRoom().connections[ARG(0) - IDO_ACT_GO_NORTH];
+ byte room = getCurRoom().connections[ARG(0) - IDO_ACT_GO_NORTH];
if (room == 0) {
printMessage(_messageIds.cantGoThere);
return;
}
- curRoom().curPicture = curRoom().picture;
+ getCurRoom().curPicture = getCurRoom().picture;
_state.room = room;
return;
}
@@ -1005,7 +1005,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
++offset;
break;
case IDO_ACT_SET_ROOM_PIC:
- room(ARG(1)).picture = room(ARG(1)).curPicture = ARG(2);
+ getRoom(ARG(1)).picture = getRoom(ARG(1)).curPicture = ARG(2);
offset += 3;
break;
default:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index a230f0f..8064375 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -219,14 +219,14 @@ private:
void drawLineArt(const Common::Array<byte> &lineArt, const Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const;
// Game state functions
- const Room &room(uint i) const;
- Room &room(uint i);
- const Room &curRoom() const;
- Room &curRoom();
- const Item &item(uint i) const;
- Item &item(uint i);
- const byte &var(uint i) const;
- byte &var(uint i);
+ const Room &getRoom(uint i) const;
+ Room &getRoom(uint i);
+ const Room &getCurRoom() const;
+ Room &getCurRoom();
+ const Item &getItem(uint i) const;
+ Item &getItem(uint i);
+ byte getVar(uint i) const;
+ void setVar(uint i, byte value);
void takeItem(byte noun);
void dropItem(byte noun);
bool matchCommand(const Command &command, byte verb, byte noun, uint *actions = nullptr) const;
Commit: d01da596ef596883847d6c3da2b714367e314a06
https://github.com/scummvm/scummvm/commit/d01da596ef596883847d6c3da2b714367e314a06
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Add note about font
Changed paths:
engines/adl/display.cpp
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index d48296e..6342504 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -70,6 +70,7 @@ static const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
0x00, 0xc0, 0x01
};
+// Uppercase-only Apple II font (manually created).
static const byte font[64][5] = {
{ 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A
{ 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC
Commit: ac39224958f6433a98da53606ce57ec8b3f123ee
https://github.com/scummvm/scummvm/commit/ac39224958f6433a98da53606ce57ec8b3f123ee
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Limit keyboard input to 256 characters
Changed paths:
engines/adl/adl.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 92b74d2..e9401cb 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -145,8 +145,10 @@ Common::String AdlEngine::inputString(byte prompt) const {
break;
};
} else {
- s += b;
- _display->printString(Common::String(b));
+ if (s.size() < 255) {
+ s += b;
+ _display->printString(Common::String(b));
+ }
}
}
}
Commit: 9d65f901d08955a78841581a4c05b1139b3fb41a
https://github.com/scummvm/scummvm/commit/9d65f901d08955a78841581a4c05b1139b3fb41a
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Clarify detection entry
Changed paths:
engines/adl/detection.cpp
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index d96d94c..1a8c502 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -65,7 +65,7 @@ static const PlainGameDescriptor adlGames[] = {
};
static const AdlGameDescription gameDescriptions[] = {
- { // MD5 by waltervn
+ { // Hi-Res Adventure #1: Mystery House - Apple II - 1987 PD release
{
"hires1", 0,
{
Commit: 349245d9b42dbe72f8aaa9c8a7a1fe09f60c9787
https://github.com/scummvm/scummvm/commit/349245d9b42dbe72f8aaa9c8a7a1fe09f60c9787
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Fix regression in GMM saving/loading
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index e9401cb..8e374fa 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -302,8 +302,11 @@ Common::Error AdlEngine::run() {
if (shouldQuit())
break;
- if (!doOneCommand(_roomCommands, verb, noun))
- printMessage(_messageIds.dontUnderstand);
+ // If we just restored from the GMM, we skip this command
+ // set, as no command has been input by the user
+ if (!_isRestoring)
+ if (!doOneCommand(_roomCommands, verb, noun))
+ printMessage(_messageIds.dontUnderstand);
}
if (_isRestoring) {
@@ -419,7 +422,7 @@ Common::Error AdlEngine::loadGameState(int slot) {
return Common::kNoError;
}
-bool AdlEngine::canLoadGameStateCurrently() const {
+bool AdlEngine::canLoadGameStateCurrently() {
return _canRestoreNow;
}
@@ -496,7 +499,7 @@ Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
return Common::kNoError;
}
-bool AdlEngine::canSaveGameStateCurrently() const {
+bool AdlEngine::canSaveGameStateCurrently() {
if (!_canSaveNow)
return false;
@@ -506,11 +509,9 @@ bool AdlEngine::canSaveGameStateCurrently() const {
// "SAVE GAME". This prevents saving via the GMM in situations where
// it wouldn't otherwise be possible to do so.
for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
- if (matchCommand(*cmd, _saveVerb, _saveNoun)) {
- if (cmd->verb != _saveVerb || cmd->noun != _saveNoun)
- return false;
- return cmd->numCond == 0 && cmd->script[0] == IDO_ACT_SAVE;
- }
+ uint offset;
+ if (matchCommand(*cmd, _saveVerb, _saveNoun, &offset))
+ return cmd->script[offset] == IDO_ACT_SAVE;
}
return false;
@@ -870,7 +871,8 @@ bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, uint
}
}
- *actions = offset;
+ if (actions)
+ *actions = offset;
return true;
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 8064375..4ea7566 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -198,9 +198,9 @@ private:
Common::Error run();
bool hasFeature(EngineFeature f) const;
Common::Error loadGameState(int slot);
- bool canLoadGameStateCurrently() const;
+ bool canLoadGameStateCurrently();
Common::Error saveGameState(int slot, const Common::String &desc);
- bool canSaveGameStateCurrently() const;
+ bool canSaveGameStateCurrently();
// Text output
void wordWrap(Common::String &str) const;
Commit: ce3af91ef865992fb744463f2bbb8dff8d0369cb
https://github.com/scummvm/scummvm/commit/ce3af91ef865992fb744463f2bbb8dff8d0369cb
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2016-03-09T10:03:13+01:00
Commit Message:
ADL: Disable GMM restore on restart prompt
At the end of the game a restart command is executed
from the global command list. As we assumed that this
would not occur, we disable restoring on the restart
prompt, at least for now.
Changed paths:
engines/adl/adl.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 8e374fa..1ab74c3 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -946,16 +946,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
case IDO_ACT_RESTART: {
_display->printString(_strings.playAgain);
-
- // We allow restoring via GMM here
- _canRestoreNow = true;
Common::String input = inputString();
- _canRestoreNow = false;
-
- // If the user restored with the GMM, we break off the restart
- if (_isRestoring)
- return;
-
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
_isRestarting = true;
_display->clear(0x00);
@@ -1036,18 +1027,11 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
- bool oldIsRestoring = _isRestoring;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
uint offset = 0;
if (matchCommand(*cmd, verb, noun, &offset))
doActions(*cmd, noun, offset);
-
- // We assume no restarts happen in this command group. This
- // simplifies enabling GMM savegame loading on the restart
- // prompt.
- if (_isRestarting || _isRestoring != oldIsRestoring)
- error("Unexpected restart action encountered");
}
}
Commit: f1b6542fd2f705b771f8c46efb328b783f9c5d78
https://github.com/scummvm/scummvm/commit/f1b6542fd2f705b771f8c46efb328b783f9c5d78
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-03-24T23:07:15+01:00
Commit Message:
Merge pull request #700 from waltervn/adl-engine
ADL: New engine
Changed paths:
A engines/adl/adl.cpp
A engines/adl/adl.h
A engines/adl/configure.engine
A engines/adl/detection.cpp
A engines/adl/detection.h
A engines/adl/display.cpp
A engines/adl/display.h
A engines/adl/hires1.cpp
A engines/adl/hires1.h
A engines/adl/module.mk
More information about the Scummvm-git-logs
mailing list