aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2014-12-19 07:20:40 -0500
committerPaul Gilbert2014-12-19 07:20:40 -0500
commit3c2ac653b2ee2c7f2efd2684516a13eb47cbf102 (patch)
tree87b2802ac2a14a8660c8fd8ef0a4ec4b768f5f9a /engines
parent2170c9bc39fa0b0e9598515211bcef602ddaca48 (diff)
parent93bbe3a45e4d9a6542b93ec9747bc0c6031054ae (diff)
downloadscummvm-rg350-3c2ac653b2ee2c7f2efd2684516a13eb47cbf102.tar.gz
scummvm-rg350-3c2ac653b2ee2c7f2efd2684516a13eb47cbf102.tar.bz2
scummvm-rg350-3c2ac653b2ee2c7f2efd2684516a13eb47cbf102.zip
Merge pull request #548 from dreammaster/access
ACCESS: Support for Amazon - Guardians of Eden
Diffstat (limited to 'engines')
-rw-r--r--engines/access/access.cpp570
-rw-r--r--engines/access/access.h297
-rw-r--r--engines/access/amazon/amazon_game.cpp780
-rw-r--r--engines/access/amazon/amazon_game.h139
-rw-r--r--engines/access/amazon/amazon_logic.cpp2217
-rw-r--r--engines/access/amazon/amazon_logic.h251
-rw-r--r--engines/access/amazon/amazon_player.cpp86
-rw-r--r--engines/access/amazon/amazon_player.h48
-rw-r--r--engines/access/amazon/amazon_resources.cpp2411
-rw-r--r--engines/access/amazon/amazon_resources.h148
-rw-r--r--engines/access/amazon/amazon_room.cpp241
-rw-r--r--engines/access/amazon/amazon_room.h72
-rw-r--r--engines/access/amazon/amazon_scripts.cpp516
-rw-r--r--engines/access/amazon/amazon_scripts.h67
-rw-r--r--engines/access/animation.cpp342
-rw-r--r--engines/access/animation.h140
-rw-r--r--engines/access/asurface.cpp344
-rw-r--r--engines/access/asurface.h166
-rw-r--r--engines/access/bubble_box.cpp282
-rw-r--r--engines/access/bubble_box.h89
-rw-r--r--engines/access/char.cpp162
-rw-r--r--engines/access/char.h67
-rw-r--r--engines/access/configure.engine3
-rw-r--r--engines/access/data.cpp76
-rw-r--r--engines/access/data.h103
-rw-r--r--engines/access/debugger.cpp164
-rw-r--r--engines/access/debugger.h64
-rw-r--r--engines/access/decompress.cpp127
-rw-r--r--engines/access/decompress.h43
-rw-r--r--engines/access/detection.cpp209
-rw-r--r--engines/access/detection_tables.h91
-rw-r--r--engines/access/events.cpp371
-rw-r--r--engines/access/events.h157
-rw-r--r--engines/access/files.cpp239
-rw-r--r--engines/access/files.h142
-rw-r--r--engines/access/font.cpp177
-rw-r--r--engines/access/font.h103
-rw-r--r--engines/access/inventory.cpp535
-rw-r--r--engines/access/inventory.h140
-rw-r--r--engines/access/martian/martian_game.cpp168
-rw-r--r--engines/access/martian/martian_game.h76
-rw-r--r--engines/access/martian/martian_resources.cpp722
-rw-r--r--engines/access/martian/martian_resources.h52
-rw-r--r--engines/access/martian/martian_room.cpp141
-rw-r--r--engines/access/martian/martian_room.h66
-rw-r--r--engines/access/martian/martian_scripts.cpp48
-rw-r--r--engines/access/martian/martian_scripts.h49
-rw-r--r--engines/access/module.mk41
-rw-r--r--engines/access/player.cpp820
-rw-r--r--engines/access/player.h153
-rw-r--r--engines/access/resources.cpp109
-rw-r--r--engines/access/resources.h53
-rw-r--r--engines/access/room.cpp833
-rw-r--r--engines/access/room.h202
-rw-r--r--engines/access/screen.cpp368
-rw-r--r--engines/access/screen.h182
-rw-r--r--engines/access/scripts.cpp885
-rw-r--r--engines/access/scripts.h168
-rw-r--r--engines/access/sound.cpp310
-rw-r--r--engines/access/sound.h109
-rw-r--r--engines/access/video.cpp176
-rw-r--r--engines/access/video.h82
62 files changed, 17992 insertions, 0 deletions
diff --git a/engines/access/access.cpp b/engines/access/access.cpp
new file mode 100644
index 0000000000..6ad1b22408
--- /dev/null
+++ b/engines/access/access.cpp
@@ -0,0 +1,570 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "access/access.h"
+
+namespace Access {
+
+AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc)
+ : _gameDescription(gameDesc), Engine(syst), _randomSource("Access"),
+ _useItem(_flags[99]), _startup(_flags[170]), _manScaleOff(_flags[172]) {
+ _animation = nullptr;
+ _bubbleBox = nullptr;
+ _char = nullptr;
+ _debugger = nullptr;
+ _events = nullptr;
+ _files = nullptr;
+ _inventory = nullptr;
+ _player = nullptr;
+ _room = nullptr;
+ _screen = nullptr;
+ _scripts = nullptr;
+ _sound = nullptr;
+ _video = nullptr;
+
+ _destIn = nullptr;
+ _current = nullptr;
+ _mouseMode = 0;
+ _currentMan = 0;
+ _currentManOld = -1;
+ _converseMode = 0;
+ _startAboutBox = 0;
+ _startTravelBox = 0;
+ _numAnimTimers = 0;
+ _startup = 0;
+ _currentCharFlag = false;
+ _boxSelect = false;
+ _scale = 0;
+ _scaleH1 = _scaleH2 = 0;
+ _scaleN1 = 0;
+ _scaleT1 = 0;
+ _scaleMaxY = 0;
+ _scaleI = 0;
+ _scrollCol = _scrollRow = 0;
+ _scrollX = _scrollY = 0;
+ _imgUnscaled = false;
+ _canSaveLoad = false;
+ _establish = nullptr;
+
+ _conversation = 0;
+ _currentMan = 0;
+ _newTime = 0;
+ _newDate = 0;
+ Common::fill(&_objectsTable[0], &_objectsTable[100], (SpriteResource *)nullptr);
+ Common::fill(&_establishTable[0], &_establishTable[100], false);
+ Common::fill(&_flags[0], &_flags[256], 0);
+ _establishFlag = false;
+ _establishMode = 0;
+ _establishGroup = 0;
+ _establishCtrlTblOfs = 0;
+ _lastTime = g_system->getMillis();
+ _curTime = 0;
+ _narateFile = 0;
+ _txtPages = 0;
+ _sndSubFile = 0;
+ _loadSaveSlot = -1;
+ _vidX = _vidY = 0;
+ _cheatFl = false;
+ _restartFl = false;
+}
+
+AccessEngine::~AccessEngine() {
+ delete _animation;
+ delete _bubbleBox;
+ delete _char;
+ delete _debugger;
+ delete _events;
+ delete _files;
+ delete _inventory;
+ delete _midi;
+ delete _player;
+ delete _room;
+ delete _screen;
+ delete _scripts;
+ delete _sound;
+ delete _video;
+
+ freeCells();
+ delete _establish;
+}
+
+void AccessEngine::setVGA() {
+ initGraphics(320, 200, false);
+}
+
+void AccessEngine::initialize() {
+ // Set up debug channels
+ DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level");
+ DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
+ DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling");
+ DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
+
+ if (isCD()) {
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ // The CD version contains two versions of the game.
+ // - The MCGA version, in the CDROM folder
+ // - The VESA version, in the TDROM folder
+ // We use the hires version.
+ const Common::FSNode cdromDir = gameDataDir.getChild("tdrom");
+
+ for (int idx = 0; idx < 15; ++idx) {
+ Common::String folder = (idx == 0) ? "game" :
+ Common::String::format("chap%.2d", idx);
+ SearchMan.addSubDirectoryMatching(cdromDir, folder);
+ }
+ }
+
+ // Create sub-objects of the engine
+ _animation = new AnimationManager(this);
+ _bubbleBox = new BubbleBox(this);
+ _char = new CharManager(this);
+ _debugger = Debugger::init(this);
+ _events = new EventsManager(this);
+ _files = new FileManager(this);
+ _inventory = new InventoryManager(this);
+ _player = Player::init(this);
+ _screen = new Screen(this);
+ _sound = new SoundManager(this, _mixer);
+ _midi = new MusicManager(this);
+ _video = new VideoPlayer(this);
+
+ _buffer1.create(g_system->getWidth() + TILE_WIDTH, g_system->getHeight());
+ _buffer2.create(g_system->getWidth(), g_system->getHeight());
+ _vidBuf.create(160, 101);
+
+ // If requested, load a savegame instead of showing the intro
+ if (ConfMan.hasKey("save_slot")) {
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0 && saveSlot <= 999)
+ _loadSaveSlot = saveSlot;
+ }
+}
+
+Common::Error AccessEngine::run() {
+ setVGA();
+ initialize();
+
+ playGame();
+
+ return Common::kNoError;
+}
+
+int AccessEngine::getRandomNumber(int maxNumber) {
+ return _randomSource.getRandomNumber(maxNumber);
+}
+
+void AccessEngine::loadCells(Common::Array<CellIdent> &cells) {
+ for (uint i = 0; i < cells.size(); ++i) {
+ Resource *spriteData = _files->loadFile(cells[i]);
+ _objectsTable[cells[i]._cell] = new SpriteResource(this, spriteData);
+ delete spriteData;
+ }
+}
+
+void AccessEngine::freeCells() {
+ for (int i = 0; i < 100; ++i) {
+ delete _objectsTable[i];
+ _objectsTable[i] = nullptr;
+ }
+}
+
+void AccessEngine::speakText(ASurface *s, const Common::String &msg) {
+ Common::String lines = msg;
+ Common::String line;
+ int curPage = 0;
+ int soundsLeft = 0;
+
+ while (!shouldQuit()) {
+ soundsLeft = _countTbl[curPage];
+ _events->zeroKeys();
+
+ int width = 0;
+ bool lastLine = _fonts._font2.getLine(lines, s->_maxChars * 6, line, width);
+
+ // Set font colors
+ _fonts._font2._fontColors[0] = 0;
+ _fonts._font2._fontColors[1] = 28;
+ _fonts._font2._fontColors[2] = 29;
+ _fonts._font2._fontColors[3] = 30;
+
+ _fonts._font2.drawString(s, line, s->_printOrg);
+ s->_printOrg = Common::Point(s->_printStart.x, s->_printOrg.y + 9);
+
+ if ((s->_printOrg.y > _printEnd) && (!lastLine)) {
+ _events->clearEvents();
+ while (!shouldQuit()) {
+ _sound->freeSounds();
+ Resource *sound = _sound->loadSound(_narateFile + 99, _sndSubFile);
+ _sound->_soundTable.push_back(SoundEntry(sound, 1));
+ _sound->playSound(0);
+ _scripts->cmdFreeSound();
+
+ _events->pollEvents();
+
+ if (_events->isKeyMousePressed()) {
+ _sndSubFile += soundsLeft;
+ break;
+ } else {
+ ++_sndSubFile;
+ --soundsLeft;
+ if (soundsLeft == 0)
+ break;
+ _events->clearEvents();
+ }
+ }
+
+ s->copyBuffer(&_buffer2);
+ s->_printOrg.y = s->_printStart.y;
+ ++curPage;
+ soundsLeft = _countTbl[curPage];
+ }
+
+ if (lastLine)
+ break;
+ }
+
+ while (soundsLeft) {
+ _sound->freeSounds();
+ Resource *res = _sound->loadSound(_narateFile + 99, _sndSubFile);
+ _sound->_soundTable.push_back(SoundEntry(res, 1));
+ _sound->playSound(0);
+ _scripts->cmdFreeSound();
+
+ _events->pollEvents();
+
+ if (_events->_leftButton) {
+ _events->debounceLeft();
+ _sndSubFile += soundsLeft;
+ break;
+ } else if (_events->isKeyPending()) {
+ _sndSubFile += soundsLeft;
+ break;
+ } else {
+ ++_sndSubFile;
+ --soundsLeft;
+ }
+ }
+}
+
+void AccessEngine::printText(ASurface *s, const Common::String &msg) {
+ Common::String lines = msg;
+ Common::String line;
+ int width = 0;
+
+ for (;;) {
+ bool lastLine = _fonts._font2.getLine(lines, s->_maxChars * 6, line, width);
+
+ // Set font colors
+ _fonts._font2._fontColors[0] = 0;
+ _fonts._font2._fontColors[1] = 28;
+ _fonts._font2._fontColors[2] = 29;
+ _fonts._font2._fontColors[3] = 30;
+ _fonts._font2.drawString(s, line, s->_printOrg);
+
+ s->_printOrg = Common::Point(s->_printStart.x, s->_printOrg.y + 9);
+
+ if (s->_printOrg.y >_printEnd && !lastLine) {
+ _events->waitKeyMouse();
+ s->copyBuffer(&_buffer2);
+ s->_printOrg.y = s->_printStart.y;
+ }
+
+ if (lastLine)
+ break;
+ }
+ _events->waitKeyMouse();
+}
+
+
+void AccessEngine::plotList() {
+ _player->calcPlayer();
+ plotList1();
+}
+
+void AccessEngine::plotList1() {
+ for (uint idx = 0; idx < _images.size(); ++idx) {
+ ImageEntry &ie = _images[idx];
+
+ _imgUnscaled = (ie._flags & IMGFLAG_UNSCALED) != 0;
+ Common::Point pt = ie._position - _screen->_bufferStart;
+ SpriteResource *sprites = ie._spritesPtr;
+ SpriteFrame *frame = sprites->getFrame(ie._frameNumber);
+
+ Common::Rect bounds(pt.x, pt.y, pt.x + frame->w, pt.y + frame->h);
+ if (!_imgUnscaled) {
+ bounds.setWidth(_screen->_scaleTable1[frame->w]);
+ bounds.setHeight(_screen->_scaleTable1[frame->h]);
+ }
+
+ // Make a copy - some of the drawing methods I've adapted need the full
+ // scaled dimensions on-screen, and handle clipping themselves
+ Common::Rect destBounds = bounds;
+
+ if (_buffer2.clip(bounds)) {
+ ie._flags |= IMGFLAG_CROPPED;
+ } else {
+ ie._flags &= ~IMGFLAG_CROPPED;
+ if (_buffer2._leftSkip != 0 || _buffer2._rightSkip != 0
+ || _buffer2._topSkip != 0 || _buffer2._bottomSkip != 0)
+ ie._flags |= IMGFLAG_CROPPED;
+
+ _newRects.push_back(bounds);
+
+ if (!_imgUnscaled) {
+ _buffer2._rightSkip /= _scale;
+ bounds.setWidth(bounds.width() / _scale);
+
+ if (ie._flags & IMGFLAG_BACKWARDS) {
+ _buffer2.sPlotB(frame, destBounds);
+ } else {
+ _buffer2.sPlotF(frame, destBounds);
+ }
+ } else {
+ if (ie._flags & IMGFLAG_BACKWARDS) {
+ _buffer2.plotB(frame, Common::Point(destBounds.left, destBounds.top));
+ } else {
+ _buffer2.plotF(frame, Common::Point(destBounds.left, destBounds.top));
+ }
+ }
+ }
+
+ ie._flags |= IMGFLAG_DRAWN;
+ }
+}
+
+void AccessEngine::copyBlocks() {
+ // Copy the block list from the previous frame
+ for (uint i = 0; i < _oldRects.size(); ++i) {
+ _screen->copyBlock(&_buffer2, _oldRects[i]);
+ }
+
+ copyRects();
+}
+
+void AccessEngine::copyRects() {
+ _oldRects.clear();
+ for (uint i = 0; i < _newRects.size(); ++i) {
+ _screen->copyBlock(&_buffer2, _newRects[i]);
+ _oldRects.push_back(_newRects[i]);
+ }
+}
+
+void AccessEngine::copyBF1BF2() {
+ _buffer2.copyRectToSurface(_buffer1, 0, 0,
+ Common::Rect(_scrollX, _scrollY,
+ _scrollX + _screen->_vWindowBytesWide,
+ _scrollY + _screen->_vWindowLinesTall));
+}
+
+void AccessEngine::copyBF2Vid() {
+ const byte *srcP = (const byte *)_buffer2.getPixels();
+ byte *destP = (byte *)_screen->getBasePtr(_screen->_windowXAdd,
+ _screen->_windowYAdd + _screen->_screenYOff);
+
+ for (int yp = 0; yp < _screen->_vWindowLinesTall; ++yp) {
+ Common::copy(srcP, srcP + _screen->_vWindowBytesWide, destP);
+ srcP += _buffer2.pitch;
+ destP += _screen->pitch;
+ }
+
+ // Add dirty rect for affected area
+ Common::Rect r(_screen->_vWindowBytesWide, _screen->_vWindowLinesTall);
+ r.moveTo(_screen->_windowXAdd, _screen->_windowYAdd + _screen->_screenYOff);
+ _screen->addDirtyRect(r);
+}
+
+void AccessEngine::playVideo(int videoNum, const Common::Point &pt) {
+ _video->setVideo(_screen, pt, FileIdent(96, videoNum), 10);
+
+ while (!shouldQuit() && !_video->_videoEnd) {
+ _video->playVideo();
+ _events->pollEventsAndWait();
+ }
+}
+
+void AccessEngine::doLoadSave() {
+ error("TODO: doLoadSave");
+}
+
+void AccessEngine::freeChar() {
+ _scripts->freeScriptData();
+ _animation->clearTimers();
+ _animation->freeAnimationData();
+}
+
+Common::Error AccessEngine::saveGameState(int slot, const Common::String &desc) {
+ Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(
+ generateSaveName(slot));
+ if (!out)
+ return Common::kCreatingFileFailed;
+
+ AccessSavegameHeader header;
+ header._saveName = desc;
+ writeSavegameHeader(out, header);
+
+ Common::Serializer s(nullptr, out);
+ synchronize(s);
+
+ out->finalize();
+ delete out;
+
+ return Common::kNoError;
+}
+
+Common::Error AccessEngine::loadGameState(int slot) {
+ Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
+ generateSaveName(slot));
+ if (!saveFile)
+ return Common::kReadingFailed;
+
+ Common::Serializer s(saveFile, nullptr);
+
+ // Load the savaegame header
+ AccessSavegameHeader header;
+ if (!readSavegameHeader(saveFile, header))
+ error("Invalid savegame");
+
+ if (header._thumbnail) {
+ header._thumbnail->free();
+ delete header._thumbnail;
+ }
+
+ // Load most of the savegame data
+ synchronize(s);
+ delete saveFile;
+
+ // Set extra post-load state
+ _room->_function = FN_CLEAR1;
+ _timers._timersSavedFlag = false;
+ _events->clearEvents();
+
+ return Common::kNoError;
+}
+
+Common::String AccessEngine::generateSaveName(int slot) {
+ return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+bool AccessEngine::canLoadGameStateCurrently() {
+ return _canSaveLoad;
+}
+
+bool AccessEngine::canSaveGameStateCurrently() {
+ return _canSaveLoad;
+}
+
+void AccessEngine::synchronize(Common::Serializer &s) {
+ s.syncAsUint16LE(_conversation);
+ s.syncAsUint16LE(_currentMan);
+ s.syncAsUint32LE(_newTime);
+ s.syncAsUint32LE(_newDate);
+
+ for (int i = 0; i < 256; ++i)
+ s.syncAsUint16LE(_flags[i]);
+ for (int i = 0; i < 100; ++i)
+ s.syncAsByte(_establishTable[i]);
+
+ // Synchronize sub-objects
+ _timers.synchronize(s);
+ _inventory->synchronize(s);
+ _player->synchronize(s);
+}
+
+const char *const SAVEGAME_STR = "ACCESS";
+#define SAVEGAME_STR_SIZE 6
+
+bool AccessEngine::readSavegameHeader(Common::InSaveFile *in, AccessSavegameHeader &header) {
+ char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
+ header._thumbnail = nullptr;
+
+ // Validate the header Id
+ in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
+ if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE))
+ return false;
+
+ header._version = in->readByte();
+ if (header._version > ACCESS_SAVEGAME_VERSION)
+ return false;
+
+ // Read in the string
+ header._saveName.clear();
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0')
+ header._saveName += ch;
+
+ // Get the thumbnail
+ header._thumbnail = Graphics::loadThumbnail(*in);
+ if (!header._thumbnail)
+ return false;
+
+ // Read in save date/time
+ header._year = in->readSint16LE();
+ header._month = in->readSint16LE();
+ header._day = in->readSint16LE();
+ header._hour = in->readSint16LE();
+ header._minute = in->readSint16LE();
+ header._totalFrames = in->readUint32LE();
+
+ return true;
+}
+
+void AccessEngine::writeSavegameHeader(Common::OutSaveFile *out, AccessSavegameHeader &header) {
+ // Write out a savegame header
+ out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
+
+ out->writeByte(ACCESS_SAVEGAME_VERSION);
+
+ // Write savegame name
+ out->writeString(header._saveName);
+ out->writeByte('\0');
+
+ // Write a thumbnail of the screen
+ uint8 thumbPalette[PALETTE_SIZE];
+ _screen->getPalette(thumbPalette);
+ Graphics::Surface saveThumb;
+ ::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(),
+ _screen->w, _screen->h, thumbPalette);
+ Graphics::saveThumbnail(*out, saveThumb);
+ saveThumb.free();
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ out->writeSint16LE(td.tm_year + 1900);
+ out->writeSint16LE(td.tm_mon + 1);
+ out->writeSint16LE(td.tm_mday);
+ out->writeSint16LE(td.tm_hour);
+ out->writeSint16LE(td.tm_min);
+ out->writeUint32LE(_events->getFrameCounter());
+}
+
+bool AccessEngine::shouldQuitOrRestart() {
+ return shouldQuit() || _restartFl;
+}
+} // End of namespace Access
diff --git a/engines/access/access.h b/engines/access/access.h
new file mode 100644
index 0000000000..a082b969c4
--- /dev/null
+++ b/engines/access/access.h
@@ -0,0 +1,297 @@
+/* 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 ACCESS_ACCESS_H
+#define ACCESS_ACCESS_H
+
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/error.h"
+#include "common/random.h"
+#include "common/savefile.h"
+#include "common/serializer.h"
+#include "common/util.h"
+#include "engines/engine.h"
+#include "graphics/surface.h"
+#include "access/animation.h"
+#include "access/bubble_box.h"
+#include "access/char.h"
+#include "access/data.h"
+#include "access/debugger.h"
+#include "access/events.h"
+#include "access/files.h"
+#include "access/font.h"
+#include "access/inventory.h"
+#include "access/player.h"
+#include "access/room.h"
+#include "access/screen.h"
+#include "access/scripts.h"
+#include "access/sound.h"
+#include "access/video.h"
+
+/**
+ * This is the namespace of the Access engine.
+ *
+ * Status of this engine: In Development
+ *
+ * Games using this engine:
+ * - Amazon: Guardians of Eden
+ */
+namespace Access {
+
+enum {
+ GType_Amazon = 1,
+ GType_MartianMemorandum = 2,
+ GType_Noctropolis = 3
+};
+
+enum AccessDebugChannels {
+ kDebugPath = 1 << 0,
+ kDebugScripts = 1 << 1,
+ kDebugGraphics = 1 << 2,
+ kDebugSound = 1 << 3
+};
+
+struct AccessGameDescription;
+
+extern const char *const _estTable[];
+
+#define ACCESS_SAVEGAME_VERSION 1
+
+struct AccessSavegameHeader {
+ uint8 _version;
+ Common::String _saveName;
+ Graphics::Surface *_thumbnail;
+ int _year, _month, _day;
+ int _hour, _minute;
+ int _totalFrames;
+};
+
+class AccessEngine : public Engine {
+private:
+ uint32 _lastTime, _curTime;
+
+ /**
+ * Handles basic initialization
+ */
+ void initialize();
+
+ /**
+ * Set VGA mode
+ */
+ void setVGA();
+
+protected:
+ const AccessGameDescription *_gameDescription;
+ Common::RandomSource _randomSource;
+ int _loadSaveSlot;
+
+ /**
+ * Main handler for showing game rooms
+ */
+ void doRoom();
+
+ /**
+ * Support method that generates a savegame name
+ * @param slot Slot number
+ */
+ Common::String generateSaveName(int slot);
+
+ /**
+ * Play back an entire video
+ */
+ void playVideo(int videoNum, const Common::Point &pt);
+
+ // Engine APIs
+ virtual Common::Error run();
+ virtual bool hasFeature(EngineFeature f) const;
+protected:
+ /**
+ * Play the game
+ */
+ virtual void playGame() = 0;
+
+ /**
+ * Synchronize savegame data
+ */
+ virtual void synchronize(Common::Serializer &s);
+public:
+ AnimationManager *_animation;
+ BubbleBox *_bubbleBox;
+ CharManager *_char;
+ Debugger *_debugger;
+ EventsManager *_events;
+ FileManager *_files;
+ InventoryManager *_inventory;
+ Player *_player;
+ Room *_room;
+ Screen *_screen;
+ Scripts *_scripts;
+ SoundManager *_sound;
+ MusicManager *_midi;
+ VideoPlayer *_video;
+
+ ASurface *_destIn;
+ ASurface *_current;
+ ASurface _buffer1;
+ ASurface _buffer2;
+ ASurface _vidBuf;
+ int _vidX, _vidY;
+ Common::Array<CharEntry *> _charTable;
+ SpriteResource *_objectsTable[100];
+ bool _establishTable[100];
+ bool _establishFlag;
+ int _establishMode;
+ int _establishGroup;
+ int _establishCtrlTblOfs;
+ int _numAnimTimers;
+ TimerList _timers;
+ DeathList _deaths;
+ FontManager _fonts;
+ Common::Array<Common::Rect> _newRects;
+ Common::Array<Common::Rect> _oldRects;
+ Common::Array<ExtraCell> _extraCells;
+ ImageEntryList _images;
+ int _mouseMode;
+
+ int _currentManOld;
+ int _converseMode;
+ int _startAboutBox;
+ int _startTravelBox;
+ bool _currentCharFlag;
+ bool _boxSelect;
+ int _scale;
+ int _scaleH1, _scaleH2;
+ int _scaleN1;
+ int _scaleT1;
+ int _scaleMaxY;
+ int _scaleI;
+ int _scrollX, _scrollY;
+ int _scrollCol, _scrollRow;
+ bool _imgUnscaled;
+ bool _canSaveLoad;
+
+ Resource *_establish;
+ int _et;
+ int _printEnd;
+ int _txtPages;
+ int _narateFile;
+ int _sndSubFile;
+ int _countTbl[6];
+
+ // Fields that are included in savegames
+ int _conversation;
+ int _currentMan;
+ uint32 _newTime;
+ uint32 _newDate;
+ int _flags[256];
+
+ bool _clearSummaryFlag;
+ bool _cheatFl;
+ bool _restartFl;
+ // Fields mapped into the flags array
+ int &_useItem;
+ int &_startup;
+ int &_manScaleOff;
+
+public:
+ AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc);
+ virtual ~AccessEngine();
+
+ virtual void dead(int deathId) = 0;
+
+ uint32 getFeatures() const;
+ bool isCD() const;
+ bool isDemo() const;
+ Common::Language getLanguage() const;
+ Common::Platform getPlatform() const;
+ uint16 getVersion() const;
+ uint32 getGameID() const;
+ uint32 getGameFeatures() const;
+ bool shouldQuitOrRestart();
+
+ int getRandomNumber(int maxNumber);
+
+ void loadCells(Common::Array<CellIdent> &cells);
+
+ /**
+ * Free the sprites list
+ */
+ void freeCells();
+
+ virtual void establish(int esatabIndex, int sub) = 0;
+
+ void plotList();
+ void plotList1();
+
+ void copyBlocks();
+
+ void copyRects();
+
+ void copyBF1BF2();
+
+ void copyBF2Vid();
+
+ void doLoadSave();
+
+ void freeChar();
+
+ /**
+ * Draw a string on a given surface and update text positioning
+ */
+ void printText(ASurface *s, const Common::String &msg);
+ void speakText(ASurface *s, const Common::String &msg);
+
+ /**
+ * Load a savegame
+ */
+ virtual Common::Error loadGameState(int slot);
+
+ /**
+ * Save the game
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+
+ /**
+ * Returns true if a savegame can currently be loaded
+ */
+ bool canLoadGameStateCurrently();
+
+ /**
+ * Returns true if the game can currently be saved
+ */
+ bool canSaveGameStateCurrently();
+
+ /**
+ * Read in a savegame header
+ */
+ static bool readSavegameHeader(Common::InSaveFile *in, AccessSavegameHeader &header);
+
+ /**
+ * Write out a savegame header
+ */
+ void writeSavegameHeader(Common::OutSaveFile *out, AccessSavegameHeader &header);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_ACCESS_H */
diff --git a/engines/access/amazon/amazon_game.cpp b/engines/access/amazon/amazon_game.cpp
new file mode 100644
index 0000000000..933a98aded
--- /dev/null
+++ b/engines/access/amazon/amazon_game.cpp
@@ -0,0 +1,780 @@
+/* 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 "access/resources.h"
+#include "access/amazon/amazon_game.h"
+#include "access/amazon/amazon_resources.h"
+#include "access/amazon/amazon_room.h"
+#include "access/amazon/amazon_scripts.h"
+
+namespace Access {
+
+namespace Amazon {
+
+AmazonEngine::AmazonEngine(OSystem *syst, const AccessGameDescription *gameDesc)
+ : AccessEngine(syst, gameDesc), _guardLocation(_flags[122]), _guardFind(_flags[128]),
+ _helpLevel(_flags[167]), _jasMayaFlag(_flags[168]), _moreHelp(_flags[169]),
+ _flashbackFlag(_flags[171]), _riverFlag(_flags[185]), _aniOutFlag(_flags[195]),
+ _badEnd(_flags[218]), _noHints(_flags[219]), _aniFlag(_flags[229]),
+ _allenFlag(_flags[237]), _noSound(_flags[239]) {
+ _ant = nullptr;
+ _cast = nullptr;
+ _guard = nullptr;
+ _jungle = nullptr;
+ _opening = nullptr;
+ _plane = nullptr;
+ _river = nullptr;
+
+ _charSegSwitch = false;
+
+ _oldTitleChapter = _chapter = 0;
+ _updateChapter = -1;
+ _rawInactiveX = 0;
+ _rawInactiveY = 0;
+ _inactiveYOff = 0;
+ _hintLevel = 0;
+
+ Common::fill(&_tileData[0], &_tileData[0] + sizeof(_tileData), 0);
+ Common::fill(&_help1[0], &_help1[0] + sizeof(_help1), 0);
+ Common::fill(&_help2[0], &_help2[0] + sizeof(_help2), 0);
+ Common::fill(&_help3[0], &_help3[0] + sizeof(_help3), 0);
+ _helpTbl[0] = _help1;
+ _helpTbl[1] = _help2;
+ _helpTbl[2] = _help3;
+
+ _chapterCells.push_back(CellIdent(0, 96, 17));
+ _inactive._spritesPtr = nullptr;
+ _inactive._altSpritesPtr = nullptr;
+ _inactive._flags = _inactive._frameNumber = _inactive._offsetY = 0;
+ _inactive._position = Common::Point(0, 0);
+}
+
+AmazonEngine::~AmazonEngine() {
+ delete _inactive._altSpritesPtr;
+
+ delete _ant;
+ delete _cast;
+ delete _guard;
+ delete _jungle;
+ delete _opening;
+ delete _plane;
+ delete _river;
+}
+
+void AmazonEngine::freeInactivePlayer() {
+ delete _inactive._altSpritesPtr;
+ _inactive._altSpritesPtr = nullptr;
+}
+
+void AmazonEngine::configSelect() {
+ // Initialize fields contained in the config file.
+ _hintLevel = 3;
+}
+
+void AmazonEngine::initObjects() {
+ _room = new AmazonRoom(this);
+ _scripts = new AmazonScripts(this);
+
+ _ant = new Ant(this);
+ _cast = new Cast(this);
+ _guard = new Guard(this);
+ _jungle = new Jungle(this);
+ _opening = new Opening(this);
+ _plane = new Plane(this);
+ _river = new River(this);
+}
+
+void AmazonEngine::playGame() {
+ // Initialize Amazon game-specific objects
+ initObjects();
+
+ // Setup the game
+ setupGame();
+ configSelect();
+
+ if (_loadSaveSlot == -1) {
+ // Do introduction
+ _opening->doIntroduction();
+ if (shouldQuit())
+ return;
+ }
+
+ do {
+ _restartFl = false;
+ _screen->clearScreen();
+ _screen->setPanel(0);
+ _screen->forceFadeOut();
+ _events->showCursor();
+
+ initVariables();
+
+ // If there's a pending savegame to load, load it
+ if (_loadSaveSlot != -1) {
+ loadGameState(_loadSaveSlot);
+ _loadSaveSlot = -1;
+ }
+
+ // Execute the room
+ _room->doRoom();
+ } while (_restartFl);
+}
+
+void AmazonEngine::setupGame() {
+ // Load death list
+ if (isDemo()) {
+ _deaths.resize(34);
+ for (int i = 0; i < 34; ++i) {
+ _deaths[i]._screenId = DEATH_SCREENS_DEMO[i];
+ _deaths[i]._msg = DEATH_TEXT_DEMO[i];
+ }
+ } else {
+ _deaths.resize(58);
+ for (int i = 0; i < 58; ++i) {
+ _deaths[i]._screenId = DEATH_SCREENS[i];
+ _deaths[i]._msg = DEATH_TEXT[i];
+ }
+ }
+ _deaths._cells.resize(13);
+ for (int i = 0; i < 13; ++i)
+ _deaths._cells[i] = CellIdent(DEATH_CELLS[i][0], DEATH_CELLS[i][1], DEATH_CELLS[i][2]);
+
+ // Miscellaneous
+ _fonts._font1.load(FONT6x6_INDEX, FONT6x6_DATA);
+ _fonts._font2.load(FONT2_INDEX, FONT2_DATA);
+
+ initVariables();
+}
+
+void AmazonEngine::initVariables() {
+ _chapter = 1;
+ // Set player room and position
+ if (isDemo())
+ _player->_roomNumber = 33;
+ else
+ _player->_roomNumber = 4;
+
+ _converseMode = 0;
+ _inventory->_startInvItem = 0;
+ _inventory->_startInvBox = 0;
+ Common::fill(&_objectsTable[0], &_objectsTable[100], (SpriteResource *)nullptr);
+ _player->_playerOff = false;
+
+ // Setup timers
+ const int TIMER_DEFAULTS[] = { 3, 10, 8, 1, 1, 1, 1, 2 };
+ for (int i = 0; i < 32; ++i) {
+ TimerEntry te;
+ te._initTm = te._timer = (i < 8) ? TIMER_DEFAULTS[i] : 1;
+ te._flag = 1;
+
+ _timers.push_back(te);
+ }
+
+ _player->_playerX = _player->_rawPlayer.x = TRAVEL_POS[_player->_roomNumber][0];
+ _player->_playerY = _player->_rawPlayer.y = TRAVEL_POS[_player->_roomNumber][1];
+ _room->_selectCommand = -1;
+ _events->setNormalCursor(CURSOR_CROSSHAIRS);
+ _mouseMode = 0;
+ _numAnimTimers = 0;
+}
+
+void AmazonEngine::establish(int screenId, int esatabIndex) {
+ _establishMode = 0;
+ _establishGroup = 0;
+ doEstablish(screenId, esatabIndex);
+}
+
+void AmazonEngine::establishCenter(int screenId, int esatabIndex) {
+ _establishMode = 1;
+ doEstablish(screenId, esatabIndex);
+}
+
+const char *const _estTable[] = { "ETEXT0.DAT", "ETEXT1.DAT", "ETEXT2.DAT", "ETEXT3.DAT" };
+
+void AmazonEngine::loadEstablish(int estabIndex) {
+ if (!_files->existFile("ETEXT.DAT")) {
+ int oldGroup = _establishGroup;
+ _establishGroup = 0;
+
+ _establish = _files->loadFile(_estTable[oldGroup]);
+ _establishCtrlTblOfs = READ_LE_UINT16(_establish->data());
+
+ int ofs = _establishCtrlTblOfs + (estabIndex * 2);
+ int idx = READ_LE_UINT16(_establish->data() + ofs);
+ _narateFile = READ_LE_UINT16(_establish->data() + idx);
+ _txtPages = READ_LE_UINT16(_establish->data() + idx + 2);
+
+ if (!_txtPages)
+ return;
+
+ _sndSubFile = READ_LE_UINT16(_establish->data() + idx + 4);
+ for (int i = 0; i < _txtPages; ++i)
+ _countTbl[i] = READ_LE_UINT16(_establish->data() + idx + 6 + (2 * i));
+ } else {
+ _establishGroup = 0;
+ _narateFile = 0;
+ _txtPages = 0;
+ _sndSubFile = 0;
+ _establish = _files->loadFile("ETEXT.DAT");
+ }
+}
+
+void AmazonEngine::doEstablish(int screenId, int estabIndex) {
+ _establishMode = 1;
+
+ _events->clearEvents();
+ _screen->forceFadeOut();
+ _screen->clearScreen();
+ _screen->setPanel(3);
+
+ if (screenId != -1) {
+ _files->loadScreen(95, screenId);
+ _buffer2.copyBuffer(_screen);
+ }
+
+ _screen->setIconPalette();
+ _screen->forceFadeIn();
+
+ _fonts._charSet._lo = 1;
+ _fonts._charSet._hi = 10;
+ _fonts._charFor._lo = 29;
+ _fonts._charFor._hi = 32;
+
+ _screen->_maxChars = 37;
+ _screen->_printOrg = _screen->_printStart = Common::Point(48, 35);
+ loadEstablish(estabIndex);
+ _et = estabIndex;
+ uint16 msgOffset;
+ if (!isCD())
+ msgOffset = READ_LE_UINT16(_establish->data() + (estabIndex * 2));
+ else
+ msgOffset = READ_LE_UINT16(_establish->data() + (estabIndex * 2) + 2);
+
+ _printEnd = 155;
+ Common::String msg((const char *)_establish->data() + msgOffset);
+
+ if ((_txtPages == 0) || !isCD()) {
+ printText(_screen, msg);
+ } else {
+ speakText(_screen, msg);
+ }
+
+ _screen->forceFadeOut();
+ _screen->clearScreen();
+
+ delete _establish;
+ _establish = nullptr;
+
+ if (_establishMode == 0)
+ _room->init4Quads();
+}
+
+const char *const _tileFiles[] = {
+ "GRAY.BLK", "RED.BLK", "LTBROWN.BLK", "DKBROWN.BLK", "VIOLET.BLK", "LITEBLUE.BLK",
+ "DARKBLUE.BLK", "CYAN.BLK", "GREEN.BLK", "OLIVE.BLK", "GRAY.BLK", "RED.BLK",
+ "LTBROWN.BLK", "DKBROWN.BLK", "VIOLET.BLK", "OLIVE.BLK"
+};
+
+void AmazonEngine::tileScreen() {
+ if (!_screen->_vesaMode)
+ return;
+
+ if (!_clearSummaryFlag && (_oldTitleChapter == _chapter))
+ return;
+
+ _oldTitleChapter = _chapter;
+ int idx = _chapter - 1;
+
+ if (!_files->existFile(_tileFiles[idx]))
+ return;
+
+ Resource *res = _files->loadFile(_tileFiles[idx]);
+ int x = res->_stream->readSint16LE();
+ int y = res->_stream->readSint16LE();
+ int size = ((x + 2) * y) + 10;
+
+ for (int i = 0; i < size; ++i)
+ _tileData[i] = res->_stream->readByte();
+
+ // CHECKME: Depending on the Vesa mode during initialization, 400 or 480
+ Common::Point tilePos;
+ for (tilePos.y = 0; tilePos.y < 480; tilePos.y += y) {
+ for (tilePos.x = 0; tilePos.x < 640; tilePos.x += x)
+ warning("TODO: DRAWOBJECT");
+ }
+
+ delete res;
+}
+
+void AmazonEngine::updateSummary(int chap) {
+ if (!_screen->_vesaMode)
+ return;
+
+ int chapter = chap;
+ if (chapter > 16)
+ chapter = 16;
+
+ if (!_clearSummaryFlag && (chapter == _updateChapter))
+ return;
+
+ _clearSummaryFlag = false;
+ int celSubFile = 0;
+ _updateChapter = chapter;
+ Common::Array<CellIdent> summaryCells;
+ loadCells(summaryCells);
+
+ for (int i = celSubFile; i < 16; ++i) {
+ if (i > 7)
+ warning("TODO: DRAWOBJECT");
+ else
+ warning("TODO: DRAWOBJECT");
+ }
+
+ delete _objectsTable[93];
+ _objectsTable[93] = nullptr;
+
+ for (int i = 1; i <= _updateChapter; ++i) {
+ celSubFile = i;
+ loadCells(summaryCells);
+ if (i > 8)
+ warning("TODO: DRAWOBJECT");
+ else
+ warning("TODO: DRAWOBJECT");
+
+ delete _objectsTable[93];
+ _objectsTable[93] = nullptr;
+ }
+}
+
+void AmazonEngine::calcIQ() {
+ int tmpIQ = 170;
+ for (int i = 0; i < 256; i++) {
+ if (_help1[i] == 1)
+ tmpIQ -= 3;
+ }
+
+ for (int i = 0; i < 256; i++) {
+ if (_help2[i] == 1)
+ tmpIQ -= 5;
+ }
+
+ for (int i = 0; i < 256; i++) {
+ if (_help3[i] == 1)
+ tmpIQ -= 10;
+ }
+
+ if (tmpIQ < 0)
+ tmpIQ = 0;
+
+ _iqValue = tmpIQ;
+
+ if (_iqValue <= 100)
+ _badEnd = 1;
+
+ if (_iqValue <= 0)
+ _noHints = 1;
+}
+
+void AmazonEngine::helpTitle() {
+ int width = _fonts._font2.stringWidth(_bubbleBox->_bubbleTitle);
+ int posX = 160 - (width / 2);
+ _fonts._font2._fontColors[0] = 0;
+ _fonts._font2._fontColors[1] = 33;
+ _fonts._font2._fontColors[2] = 34;
+ _fonts._font2._fontColors[3] = 35;
+ _fonts._font2.drawString(_screen, _bubbleBox->_bubbleTitle, Common::Point(posX, 24));
+
+ width = _fonts._font2.stringWidth(HELPLVLTXT[_helpLevel]);
+ posX = 160 - (width / 2);
+ _fonts._font2._fontColors[0] = 0;
+ _fonts._font2._fontColors[1] = 10;
+ _fonts._font2._fontColors[2] = 11;
+ _fonts._font2._fontColors[3] = 12;
+ _fonts._font2.drawString(_screen, HELPLVLTXT[_helpLevel], Common::Point(posX, 36));
+
+ Common::String iqText = "IQ: ";
+ calcIQ();
+ Common::String scoreIQ = Common::String::format("%d", _iqValue);
+ while (scoreIQ.size() < 4)
+ scoreIQ = " " + scoreIQ;
+
+ iqText += scoreIQ;
+ int index = _iqValue;
+ if (index == 170)
+ index = 169;
+
+ index /= 20;
+
+ iqText += " ";
+ iqText += IQLABELS[index];
+
+ width = _fonts._font2.stringWidth(iqText);
+ posX = 160 - (width / 2);
+ _fonts._font2._fontColors[0] = 0;
+ _fonts._font2._fontColors[1] = 10;
+ _fonts._font2._fontColors[2] = 11;
+ _fonts._font2._fontColors[3] = 12;
+ _fonts._font2.drawString(_screen, iqText, Common::Point(posX, 44));
+}
+
+void AmazonEngine::drawHelpText(const Common::String &msg) {
+ _screen->_maxChars = 39;
+ _screen->_printOrg = Common::Point(26, 58);
+ _screen->_printStart = Common::Point(26, 58);
+
+ Common::String lines = msg;
+ Common::String line;
+ int width = 0;
+ bool lastLine = false;
+ do {
+ lastLine = _fonts._font2.getLine(lines, _screen->_maxChars * 6, line, width);
+
+ // Set font colors
+ _fonts._font2._fontColors[0] = 0;
+ _fonts._font2._fontColors[1] = 27;
+ _fonts._font2._fontColors[2] = 28;
+ _fonts._font2._fontColors[3] = 29;
+
+ _fonts._font2.drawString(_screen, line, _screen->_printOrg);
+ _screen->_printOrg = Common::Point(_screen->_printStart.x, _screen->_printOrg.y + 8);
+ } while (!lastLine);
+
+ _events->showCursor();
+}
+
+void AmazonEngine::drawHelp(const Common::String str) {
+ _events->hideCursor();
+ if (_useItem == 0) {
+ _buffer2.copyBuffer(_screen);
+ if (_screen->_vesaMode) {
+ _screen->setPanel(2);
+ _screen->saveScreen();
+ }
+ _screen->savePalette();
+ _screen->fadeOut();
+ _screen->clearBuffer();
+ if (_moreHelp == 1) {
+ // Set cells
+ Common::Array<CellIdent> cells;
+ cells.push_back(CellIdent(95, 95, 3));
+ loadCells(cells);
+ }
+ }
+
+ _files->loadScreen(95, 2);
+ if (_moreHelp == 1) {
+ ASurface *oldDest = _destIn;
+ _destIn = _screen;
+ int oldClip = _screen->_clipHeight;
+ _screen->_clipHeight = 200;
+ _screen->plotImage(_objectsTable[95], 0, Common::Point(76, 168));
+ _destIn = oldDest;
+ _screen->_clipHeight = oldClip;
+ }
+
+ if ((_useItem == 0) && (_screen->_vesaMode == 0))
+ _screen->fadeIn();
+
+ helpTitle();
+ drawHelpText(str);
+}
+
+void AmazonEngine::startChapter(int chapter) {
+ _chapter = chapter;
+ assert(_chapter <= 14);
+
+ if (chapter != 1) {
+ _room->clearRoom();
+ freeChar();
+
+ _midi->newMusic(32, 0);
+ playVideo(0, Common::Point());
+ if (shouldQuit())
+ return;
+
+ _events->debounceLeft();
+ _events->zeroKeys();
+ playVideo(_chapter, Common::Point(4, 113));
+ if (shouldQuit())
+ return;
+
+ _timers[20]._timer = 500;
+ _timers[20]._initTm = 500;
+ _timers[20]._flag++;
+ _sound->freeSounds();
+
+ if (isCD()) {
+ _sound->_soundTable.push_back(SoundEntry(_sound->loadSound(115, 0), 1));
+ _sound->_soundTable.push_back(SoundEntry(_sound->loadSound(115, 1), 1));
+ _sound->playSound(0);
+ _sound->playSound(1);
+
+ _sound->freeSounds();
+ }
+
+ // Wait loop
+ while (!shouldQuit() && !_events->isKeyMousePressed() && _timers[20]._flag) {
+ _events->pollEventsAndWait();
+ }
+ }
+
+ _screen->forceFadeOut();
+ _events->debounceLeft();
+ _events->zeroKeys();
+ _screen->clearScreen();
+
+ _screen->setPanel(3);
+
+ // Set up cells for the chapter display
+ Common::Array<CellIdent> chapterCells;
+ chapterCells.push_back(CellIdent(0, 96, 17));
+ const int *chapCell = &CHAPTER_CELLS[_chapter - 1][0];
+ chapterCells.push_back(CellIdent(chapCell[0], chapCell[1], chapCell[2]));
+ loadCells(chapterCells);
+
+ // Show chapter screen
+ _files->loadScreen(96, 15);
+ _buffer2.copyFrom(*_screen);
+
+ const int *chapImg = &CHAPTER_TABLE[_chapter - 1][0];
+ _screen->plotImage(_objectsTable[0], _chapter - 1,
+ Common::Point(chapImg[1], chapImg[2]));
+ _screen->plotImage(_objectsTable[_chapter], 0,
+ Common::Point(chapImg[3], chapImg[4]));
+ if (chapter == 14)
+ _screen->plotImage(_objectsTable[_chapter], 1, Common::Point(169, 76));
+
+ _midi->newMusic(chapImg[4], 1);
+ _midi->newMusic(33, 0);
+ _screen->forceFadeIn();
+
+ _timers[20]._timer = 950;
+ _timers[20]._initTm = 950;
+ _timers[20]._flag++;
+
+ // Wait loop
+ while (!shouldQuit() && !_events->isKeyMousePressed() && _timers[20]._flag) {
+ _events->pollEventsAndWait();
+ }
+ if (shouldQuit())
+ return;
+
+ _screen->forceFadeOut();
+ _events->debounceLeft();
+ _events->zeroKeys();
+
+ _screen->clearBuffer();
+ _files->loadScreen(96, 16);
+ _buffer2.copyFrom(*_screen);
+ _screen->plotImage(_objectsTable[0], chapImg[0], Common::Point(90, 7));
+
+ _midi->newMusic(7, 1);
+ _midi->newMusic(34, 0);
+
+ _screen->forceFadeIn();
+ _buffer2.copyFrom(*_screen);
+
+ _fonts._charSet._lo = 1;
+ _fonts._charSet._hi = 10;
+ _fonts._charFor._lo = 55;
+ _fonts._charFor._hi = 0xFF;
+ _screen->_maxChars = 43;
+ _screen->_printOrg = Common::Point(31, 77);
+ _screen->_printStart = Common::Point(31, 77);
+
+ _establishGroup = 1;
+ loadEstablish(0x40 + _chapter);
+ uint16 msgOffset = READ_LE_UINT16(_establish->data() + ((0x40 + _chapter) * 2) + 2);
+ _printEnd = 170;
+
+ Common::String msg((const char *)_establish->data() + msgOffset);
+
+ if ((_txtPages == 0) || !isCD()) {
+ printText(_screen, msg);
+ } else {
+ speakText(_screen, msg);
+ }
+ if (shouldQuit())
+ return;
+
+ _screen->forceFadeOut();
+ _screen->clearBuffer();
+ freeCells();
+
+ _midi->newMusic(_chapter * 2, 1);
+
+ if (chapter != 1 && chapter != 14) {
+ _room->init4Quads();
+ }
+
+ if (chapter == 14) {
+ _conversation = 31;
+ _char->loadChar(_conversation);
+ _events->setCursor(CURSOR_ARROW);
+
+ _images.clear();
+ _oldRects.clear();
+ _scripts->_sequence = 0;
+ _scripts->searchForSequence();
+
+ if (_screen->_vesaMode) {
+ _converseMode = 1;
+ }
+ } else if (chapter != 1) {
+ _player->_roomNumber = CHAPTER_JUMP[_chapter - 1];
+ _room->_function = FN_CLEAR1;
+ _converseMode = 0;
+
+ _scripts->cmdRetPos();
+ }
+}
+
+
+void AmazonEngine::dead(int deathId) {
+ _events->hideCursor();
+ _screen->forceFadeOut();
+ _scripts->cmdFreeSound();
+ _events->debounceLeft();
+ _events->zeroKeys();
+
+ _sound->_soundTable.push_back(SoundEntry(_files->loadFile(98, 44), 1));
+
+ _screen->clearScreen();
+ _screen->setPanel(3);
+
+ if ((deathId == 10) && !isDemo()) {
+ quitGame();
+ _events->pollEvents();
+ return;
+ } else {
+ if (!isDemo())
+ _midi->newMusic(62, 0);
+ _files->_setPaletteFlag = false;
+ _files->loadScreen(94, 0);
+ _files->_setPaletteFlag = true;
+ _buffer2.copyFrom(*_screen);
+
+ if (!isDemo() || deathId != 10) {
+ for (int i = 0; i < 3; ++i) {
+ _sound->playSound(0);
+ _screen->forceFadeIn();
+ _sound->playSound(0);
+ _screen->forceFadeOut();
+
+ _events->pollEvents();
+ if (shouldQuit())
+ return;
+ }
+ }
+
+ if (!isDemo()) {
+ freeCells();
+
+ // Load the cell list for the death screen
+ DeathEntry &de = _deaths[deathId];
+ Common::Array<CellIdent> cells;
+ cells.push_back(_deaths._cells[de._screenId]);
+ loadCells(cells);
+
+ _screen->setDisplayScan();
+ _files->_setPaletteFlag = false;
+ _files->loadScreen(&_buffer2, 94, 1);
+ _screen->setIconPalette();
+
+ _buffer2.plotImage(_objectsTable[0], 0, Common::Point(105, 25));
+ _buffer2.copyTo(_screen);
+ _screen->forceFadeIn();
+
+ _fonts._charSet._hi = 10;
+ _fonts._charSet._lo = 1;
+ _fonts._charFor._lo = 55;
+ _fonts._charFor._hi = 255;
+ _screen->_maxChars = 46;
+ _screen->_printOrg = Common::Point(20, 155);
+ _screen->_printStart = Common::Point(20, 155);
+
+ Common::String &msg = de._msg;
+ _printEnd = 180;
+
+ printText(_screen, msg);
+ _screen->forceFadeOut();
+
+ _midi->newMusic(0, 1);
+ _events->showCursor();
+ _room->clearRoom();
+ freeChar();
+
+ _currentManOld = 1;
+ _player->removeSprite1();
+
+ } else {
+ _files->loadScreen(_screen, 94, _deaths[deathId]._screenId);
+ _screen->forceFadeIn();
+
+ _fonts._charSet._hi = 10;
+ _fonts._charSet._lo = 1;
+ _fonts._charFor._lo = 55;
+ _fonts._charFor._hi = 255;
+ _screen->_maxChars = 49;
+ _screen->_printOrg = Common::Point(15, 165);
+ _screen->_printStart = Common::Point(15, 165);
+
+ Common::String msg = Common::String(_deaths[deathId]._msg);
+ _printEnd = 200;
+
+ printText(_screen, msg);
+ _screen->fadeOut();
+
+ _events->showCursor();
+ _room->clearRoom();
+ freeChar();
+
+ _currentManOld = 1;
+ _player->removeSprite1();
+ }
+
+ // The original was jumping to the restart label in main
+ _restartFl = true;
+ _events->pollEvents();
+ }
+}
+
+void AmazonEngine::synchronize(Common::Serializer &s) {
+ AccessEngine::synchronize(s);
+
+ s.syncAsSint16LE(_chapter);
+ s.syncAsSint16LE(_rawInactiveX);
+ s.syncAsSint16LE(_rawInactiveY);
+ s.syncAsSint16LE(_inactiveYOff);
+
+ for (int i = 0; i < 366; ++i) {
+ s.syncAsByte(_help1[i]);
+ s.syncAsByte(_help2[i]);
+ s.syncAsByte(_help3[i]);
+ }
+
+ _river->synchronize(s);
+ _ant->synchronize(s);
+}
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/amazon/amazon_game.h b/engines/access/amazon/amazon_game.h
new file mode 100644
index 0000000000..8f6dffe28c
--- /dev/null
+++ b/engines/access/amazon/amazon_game.h
@@ -0,0 +1,139 @@
+/* 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 ACCESS_AMAZON_GAME_H
+#define ACCESS_AMAZON_GAME_H
+
+#include "access/access.h"
+#include "access/amazon/amazon_logic.h"
+
+namespace Access {
+
+namespace Amazon {
+
+class AmazonEngine;
+
+class AmazonEngine : public AccessEngine {
+private:
+ byte _tileData[1455];
+ Common::Array<CellIdent> _chapterCells;
+
+ /**
+ * Setup variables for the game
+ */
+ void setupGame();
+
+ /**
+ * Initialize variables found in the config file
+ */
+ void configSelect();
+
+ void initVariables();
+ void initObjects();
+ void calcIQ();
+ void helpTitle();
+ void drawHelpText(const Common::String &msg);
+ void loadEstablish(int estabIndex);
+ void doEstablish(int screenId, int estabIndex);
+
+protected:
+ /**
+ * Play the game
+ */
+ virtual void playGame();
+
+ /**
+ * Synchronize savegame data
+ */
+ virtual void synchronize(Common::Serializer &s);
+public:
+ InactivePlayer _inactive;
+ bool _charSegSwitch;
+ byte _help1[366];
+ byte _help2[366];
+ byte _help3[366];
+ byte *_helpTbl[3];
+
+ // Fields that are mapped to flags
+ int &_guardLocation;
+ int &_guardFind;
+ int &_helpLevel;
+ int &_jasMayaFlag;
+ int &_moreHelp;
+ int &_flashbackFlag;
+ int &_riverFlag;
+ int &_aniOutFlag;
+ int &_badEnd;
+ int &_noHints;
+ int &_aniFlag;
+ int &_allenFlag;
+ int &_noSound;
+
+ // Saved fields
+ int _chapter;
+ int _rawInactiveX;
+ int _rawInactiveY;
+ int _inactiveYOff;
+
+ // Other game specific fields
+ Ant *_ant;
+ Cast *_cast;
+ Guard *_guard;
+ Jungle *_jungle;
+ Opening *_opening;
+ Plane *_plane;
+ River *_river;
+ int _hintLevel;
+ int _updateChapter;
+ int _oldTitleChapter;
+ int _iqValue;
+public:
+ AmazonEngine(OSystem *syst, const AccessGameDescription *gameDesc);
+
+ virtual ~AmazonEngine();
+
+ virtual void dead(int deathId);
+
+ /**
+ * Free the inactive player data
+ */
+ void freeInactivePlayer();
+
+ void drawHelp(const Common::String str);
+
+ virtual void establish(int esatabIndex, int sub);
+
+ void tileScreen();
+ void updateSummary(int chap);
+ void establishCenter(int screenId, int esatabIndex);
+
+ /**
+ * Show the start of a chapter
+ */
+ void startChapter(int chapter);
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_ACCESS_H */
diff --git a/engines/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp
new file mode 100644
index 0000000000..436a875688
--- /dev/null
+++ b/engines/access/amazon/amazon_logic.cpp
@@ -0,0 +1,2217 @@
+/* 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 "access/access.h"
+#include "access/resources.h"
+#include "access/screen.h"
+#include "access/amazon/amazon_game.h"
+#include "access/amazon/amazon_logic.h"
+#include "access/amazon/amazon_resources.h"
+
+namespace Access {
+
+namespace Amazon {
+
+PannedScene::PannedScene(AmazonEngine *vm) : AmazonManager(vm) {
+ for (int i = 0; i < PAN_SIZE; ++i) {
+ _pan[i]._pObject = nullptr;
+ _pan[i]._pImgNum = 0;
+ _pan[i]._pObjX = _pan[i]._pObjY = _pan[i]._pObjZ = 0;
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+
+ _xCount = 0;
+ _xTrack = _yTrack = _zTrack = 0;
+ _xCam = _yCam = _zCam = 0;
+ _pNumObj = 0;
+}
+
+void PannedScene::pan() {
+ _zCam += _zTrack;
+ _xCam += _xTrack;
+ int tx = (_xTrack << 8) / _zCam;
+ _yCam += _yTrack;
+ int ty = (_yTrack << 8) / _zCam;
+
+ if (_vm->_timers[24]._flag != 1) {
+ ++_vm->_timers[24]._flag;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[i]._pObjZ += _zTrack;
+ _pan[i]._pObjXl += (_pan[i]._pObjZ * tx) & 0xff;
+ _pan[i]._pObjX += ((_pan[i]._pObjZ * tx) >> 8) + (_pan[i]._pObjXl >> 8);
+ _pan[i]._pObjXl &= 0xff;
+
+ _pan[i]._pObjYl += (_pan[i]._pObjZ * ty) & 0xff;
+ _pan[i]._pObjY += ((_pan[i]._pObjZ * ty) >> 8) + (_pan[i]._pObjYl >> 8);
+ _pan[i]._pObjYl &= 0xff;
+ }
+ }
+
+ for (int i = 0; i < _pNumObj; i++) {
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._position = Common::Point(_pan[i]._pObjX, _pan[i]._pObjY);
+ ie._offsetY = 255;
+ ie._spritesPtr = _pan[i]._pObject;
+ ie._frameNumber = _pan[i]._pImgNum;
+
+ _vm->_images.addToList(ie);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+CampScene::CampScene(AmazonEngine *vm) : PannedScene(vm) {
+ _skipStart = false;
+}
+
+void CampScene::mWhileDoOpen() {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+
+ screen.setDisplayScan();
+ events.hideCursor();
+ screen.forceFadeOut();
+ _skipStart = false;
+ if (_vm->_conversation != 2) {
+ // Cutscene at start of chapter 1
+ screen.setPanel(3);
+ _vm->startChapter(1);
+ _vm->establishCenter(0, 1);
+ }
+
+ Resource *data = _vm->_files->loadFile(1, 0);
+ _vm->_objectsTable[1] = new SpriteResource(_vm, data);
+ delete data;
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(1, 2);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+
+ // Load animation data
+ _vm->_animation->freeAnimationData();
+ Resource *animResource = _vm->_files->loadFile(1, 1);
+ _vm->_animation->loadAnimations(animResource);
+ delete animResource;
+
+ _xTrack = 8;
+ _yTrack = -3;
+ _zTrack = 0;
+ _xCam = _yCam = 0;
+ _zCam = 270;
+ _vm->_timers[24]._timer = _vm->_timers[24]._initTm = 1;
+ ++_vm->_timers[24]._flag;
+ _vm->_timers.updateTimers();
+
+ _pNumObj = 10;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[i]._pObject = _vm->_objectsTable[1];
+ _pan[i]._pImgNum = OPENING_OBJS[i][0];
+ _pan[i]._pObjX = OPENING_OBJS[i][1];
+ _pan[i]._pObjY = OPENING_OBJS[i][2];
+ _pan[i]._pObjZ = OPENING_OBJS[i][3];
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ Animation *anim = _vm->_animation->setAnimation(0);
+ _vm->_animation->setAnimTimer(anim);
+ anim = _vm->_animation->setAnimation(1);
+ _vm->_animation->setAnimTimer(anim);
+ _vm->_midi->newMusic(10, 0);
+
+ bool startFl = false;
+ while (!_vm->shouldQuit()) {
+ _vm->_images.clear();
+ _vm->_animation->animate(0);
+ _vm->_animation->animate(1);
+ pan();
+ _vm->_buffer2.copyFrom(_vm->_buffer1);
+ _vm->_newRects.clear();
+ _vm->plotList();
+ _vm->copyBlocks();
+ if (!startFl) {
+ startFl = true;
+ screen.forceFadeIn();
+ }
+
+ events.pollEventsAndWait();
+
+ if (_vm->_events->isKeyMousePressed()) {
+ _skipStart = true;
+ _vm->_midi->newMusic(10, 1);
+ break;
+ }
+
+ if (_xCam > 680) {
+ events._vbCount = 125;
+
+ while (!_vm->shouldQuit() && !events.isKeyMousePressed() && events._vbCount > 0) {
+ events.pollEventsAndWait();
+ }
+ break;
+ }
+ }
+
+ events.showCursor();
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+
+ _vm->freeCells();
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_numAnimTimers = 0;
+ _vm->_images.clear();
+
+ if (_vm->_conversation == 2) {
+ // Cutscene at end of Chapter 6
+ Resource *spriteData = _vm->_files->loadFile(28, 37);
+ _vm->_objectsTable[28] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_animation->freeAnimationData();
+ animResource = _vm->_files->loadFile(28, 38);
+ _vm->_animation->loadAnimations(animResource);
+ delete animResource;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Opening::Opening(AmazonEngine *vm) : CampScene(vm) {
+ _pCount = 0;
+}
+
+void Opening::doIntroduction() {
+ Screen &screen = *_vm->_screen;
+
+ screen.setInitialPalettte();
+ _vm->_events->setCursor(CURSOR_ARROW);
+ _vm->_events->showCursor();
+ screen.setPanel(0);
+ screen.setPalette();
+
+ _vm->_events->setCursor(CURSOR_ARROW);
+ _vm->_events->showCursor();
+ screen.setPanel(3);
+ doTitle();
+
+ if (_vm->shouldQuit() || _skipStart || _vm->isDemo())
+ return;
+
+ screen.setPanel(3);
+ mWhileDoOpen();
+
+ if (_vm->shouldQuit() || _skipStart)
+ return;
+
+ doTent();
+}
+
+void Opening::doCredit() {
+ if (_pCount < 15)
+ return;
+
+ if (_pCount <= 75)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], _vm->isDemo()? 24 : 0, Common::Point(90, 35));
+ else if (_pCount <= 210)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 1, Common::Point(65, 35));
+ else if (_pCount <= 272)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 2, Common::Point(96, 45));
+ else if (_pCount <= 334)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 3, Common::Point(68, 54));
+ else if (_pCount <= 396)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(103, 54));
+ else if (_pCount <= 458) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 5, Common::Point(8, 5));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 12, Common::Point(88, 55));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 6, Common::Point(194, 98));
+ } else if (_pCount <= 520) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 7, Common::Point(32, 13));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 8, Common::Point(162, 80));
+ } else if (_pCount <= 580) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 9, Common::Point(18, 15));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 10, Common::Point(164, 81));
+ } else
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 11, Common::Point(106, 55));
+}
+
+void Opening::doCreditDemo() {
+ if (_pCount < 15)
+ return;
+
+ if (_pCount <= 75)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], _vm->isDemo()? 24 : 0, Common::Point(90, 35));
+ else if (_pCount <= 210)
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 25, Common::Point(82, 35));
+ else if (_pCount <= 272) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 23, Common::Point(77, 20));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(50, 35));
+ } else if (_pCount <= 334) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 16, Common::Point(200, 70));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(170, 85));
+ } else if (_pCount <= 396) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 15, Common::Point(65, 15));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 2, Common::Point(30, 30));
+ } else if (_pCount <= 458) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 19, Common::Point(123, 40));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 10, Common::Point(115, 55));
+ } else if (_pCount <= 520) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 18, Common::Point(50, 15));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 9, Common::Point(40, 30));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 0, Common::Point(40, 55));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 20, Common::Point(198, 95));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 3, Common::Point(160, 110));
+ } else if (_pCount <= 580) {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 21, Common::Point(40, 10));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 6, Common::Point(20, 25));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 22, Common::Point(145, 50));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 7, Common::Point(125, 65));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 12, Common::Point(207, 90));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 5, Common::Point(200, 105));
+ } else {
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 11, Common::Point(125, 30));
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(115, 45));
+ }
+}
+
+void Opening::scrollTitle() {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ if (_vm->isDemo())
+ doCreditDemo();
+ else
+ doCredit();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+}
+
+void Opening::doTitle() {
+ Screen &screen = *_vm->_screen;
+
+ screen.setDisplayScan();
+
+ screen.forceFadeOut();
+ _vm->_events->hideCursor();
+
+ if (!_vm->isDemo()) {
+ _vm->_sound->queueSound(0, 98, 30);
+ _vm->_sound->queueSound(1, 98, 8);
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(0, 3);
+
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ screen.forceFadeIn();
+ _vm->_sound->playSound(1);
+
+ // WORKAROUND: This delay has been added to replace original game delay that
+ // came from loading resources, since nowadays it would be too fast to be visible
+ // nowadays to be visible.
+ _vm->_events->_vbCount = 70;
+ while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0)
+ _vm->_events->pollEventsAndWait();
+ if (_vm->shouldQuit())
+ return;
+
+ Resource *spriteData = _vm->_files->loadFile(0, 2);
+ _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_sound->playSound(1);
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(0, 4);
+ _vm->_sound->playSound(1);
+
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_sound->playSound(1);
+
+ const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 };
+ for (_pCount = 0; _pCount < 3 && !_vm->shouldQuit(); ++_pCount) {
+ _vm->_buffer2.copyFrom(_vm->_buffer1);
+ int id = COUNTDOWN[_pCount * 2];
+ int xp = COUNTDOWN[_pCount * 2 + 1];
+ _vm->_buffer2.plotImage(_vm->_objectsTable[0], id, Common::Point(xp, 71));
+ _vm->_buffer2.copyTo(_vm->_screen);
+
+ _vm->_sound->playSound(1);
+ _vm->_events->_vbCount = 70;
+ while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0 && !_skipStart) {
+ _vm->_events->pollEventsAndWait();
+ if (_vm->_events->_rightButton)
+ _skipStart = true;
+ }
+ }
+ if (_vm->shouldQuit())
+ return;
+
+ _vm->_sound->stopSound();
+ _vm->_sound->playSound(0);
+ screen.forceFadeOut();
+ _vm->_events->_vbCount = 100;
+ while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0)
+ _vm->_events->pollEventsAndWait();
+ if (_vm->shouldQuit())
+ return;
+
+ _vm->_sound->freeSounds();
+ delete _vm->_objectsTable[0];
+ _vm->_objectsTable[0] = nullptr;
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(0, 5);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ screen.forceFadeIn();
+ _vm->_midi->newMusic(1, 0);
+ _vm->_events->_vbCount = 700;
+ while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0) && !_vm->_events->isKeyMousePressed()) {
+ _vm->_events->pollEventsAndWait();
+ }
+
+ if (_vm->_events->_rightButton) {
+ _skipStart = true;
+ _vm->_room->clearRoom();
+ _vm->_events->showCursor();
+ return;
+ }
+
+ _vm->_midi->newMusic(1, 1);
+ _vm->_midi->setLoop(false);
+ _vm->_events->zeroKeys();
+ }
+
+ _vm->_buffer1.create(_vm->_screen->w + TILE_WIDTH, _vm->_screen->h);
+ _vm->_room->loadRoom(0);
+ screen.clearScreen();
+ screen.setBufferScan();
+ _vm->_scrollRow = _vm->_scrollCol = 0;
+ _vm->_scrollX = _vm->_scrollY = 0;
+ _vm->_player->_rawPlayer = Common::Point(0, 0);
+ screen.forceFadeOut();
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ screen.forceFadeIn();
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_events->clearEvents();
+ _vm->_player->_scrollAmount = 1;
+ _pCount = 0;
+
+ while (!_vm->shouldQuit()) {
+ if (_vm->_events->isKeyMousePressed()) {
+ if (_vm->_events->_rightButton)
+ _skipStart = true;
+ _vm->_room->clearRoom();
+ _vm->_events->showCursor();
+ return;
+ }
+
+ _vm->_events->_vbCount = 4;
+ if (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth) {
+ _vm->_scrollX += _vm->_player->_scrollAmount;
+
+ while (_vm->_scrollX >= TILE_WIDTH) {
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
+ }
+ scrollTitle();
+ ++_pCount;
+
+ while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0)) {
+ _vm->_events->pollEventsAndWait();
+ }
+ continue;
+ }
+
+ _vm->_events->_vbCount = 120;
+ while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0))
+ _vm->_events->pollEventsAndWait();
+
+ while (!_vm->shouldQuit()) {
+ _pCount = 0;
+ _vm->_events->_vbCount = 3;
+ if (_vm->_scrollRow + screen._vWindowHeight >= _vm->_room->_playFieldHeight) {
+ _vm->_room->clearRoom();
+ _vm->_events->showCursor();
+ return;
+ }
+
+ _vm->_scrollY = _vm->_scrollY + _vm->_player->_scrollAmount;
+
+ while (_vm->_scrollY >= TILE_HEIGHT && !_vm->shouldQuit()) {
+ _vm->_scrollY -= TILE_HEIGHT;
+ ++_vm->_scrollRow;
+ _vm->_buffer1.moveBufferUp();
+
+ // WORKAROUND: the original was using screen._vWindowBytesWide * screen._vWindowLinesTall
+ _vm->_room->buildRow(_vm->_scrollRow + screen._vWindowHeight, screen._vWindowLinesTall);
+
+ if (_vm->_scrollRow + screen._vWindowHeight >= _vm->_room->_playFieldHeight) {
+ _vm->_room->clearRoom();
+ _vm->_events->showCursor();
+ return;
+ }
+ }
+ scrollTitle();
+ while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0))
+ _vm->_events->pollEventsAndWait();
+ }
+ }
+}
+
+void Opening::doTent() {
+ int step = 0;
+ _vm->_screen->setDisplayScan();
+ _vm->_screen->forceFadeOut();
+ _vm->_events->hideCursor();
+ _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 39), 1));
+ _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 14), 1));
+ _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 15), 1));
+ _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 16), 1));
+ _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 31), 2));
+ _vm->_sound->_soundTable.push_back(SoundEntry(_vm->_sound->loadSound(98, 52), 2));
+ _vm->_sound->playSound(0);
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(2, 0);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_screen->forceFadeIn();
+
+ _vm->_video->setVideo(_vm->_screen, Common::Point(126, 73), FileIdent(2, 1), 10);
+ while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) {
+ _vm->_video->playVideo();
+ if ((_vm->_video->_videoFrame == 32) || (_vm->_video->_videoFrame == 34))
+ _vm->_sound->playSound(4);
+ else if (_vm->_video->_videoFrame == 36) {
+ if (step != 2) {
+ _vm->_sound->playSound(2);
+ step = 2;
+ }
+ } else if (_vm->_video->_videoFrame == 18) {
+ if (step != 1) {
+ _vm->_midi->newMusic(73, 1);
+ _vm->_midi->newMusic(11, 0);
+ step = 1;
+ _vm->_sound->playSound(1);
+ }
+ }
+
+ _vm->_events->pollEventsAndWait();
+ }
+
+ _vm->_sound->playSound(5);
+ _vm->_video->setVideo(_vm->_screen, Common::Point(43, 11), FileIdent(2, 2), 10);
+ while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) {
+ _vm->_video->playVideo();
+ if (_vm->_video->_videoFrame == 26) {
+ _vm->_sound->playSound(5);
+ } else if (_vm->_video->_videoFrame == 15) {
+ if (step !=3) {
+ _vm->_sound->playSound(3);
+ step = 3;
+ }
+ }
+
+ _vm->_events->pollEventsAndWait();
+ }
+
+ _vm->_events->_vbCount = 200;
+ while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0)
+ _vm->_events->pollEventsAndWait();
+
+ _vm->_events->showCursor();
+ _vm->_midi->newMusic(11, 1);
+ _vm->_sound->_soundTable.clear();
+
+ _vm->establishCenter(0, 4);
+}
+
+/*------------------------------------------------------------------------*/
+
+Plane::Plane(AmazonEngine *vm) : PannedScene(vm) {
+ _pCount = 0;
+ _planeCount = 0;
+ _propCount = 0;
+}
+
+
+void Plane::doFlyCell() {
+ SpriteResource *sprites = _vm->_objectsTable[15];
+
+ if (_pCount <= 40) {
+ _vm->_buffer2.plotImage(sprites, 3, Common::Point(70, 74));
+ } else if (_pCount <= 80) {
+ _vm->_buffer2.plotImage(sprites, 6, Common::Point(70, 74));
+ } else if (_pCount <= 120) {
+ _vm->_buffer2.plotImage(sprites, 2, Common::Point(50, 76));
+ } else if (_pCount <= 160) {
+ _vm->_buffer2.plotImage(sprites, 14, Common::Point(63, 78));
+ } else if (_pCount <= 200) {
+ _vm->_buffer2.plotImage(sprites, 5, Common::Point(86, 74));
+ } else if (_pCount <= 240) {
+ _vm->_buffer2.plotImage(sprites, 0, Common::Point(103, 76));
+ } else if (_pCount <= 280) {
+ _vm->_buffer2.plotImage(sprites, 4, Common::Point(119, 77));
+ } else {
+ _vm->_buffer2.plotImage(sprites, 1, Common::Point(111, 77));
+ }
+
+ if (_planeCount == 11 || _planeCount == 12)
+ ++_position.y;
+ else if (_planeCount >= 28)
+ --_position.y;
+
+ _vm->_buffer2.plotImage(sprites, 7, _position);
+ _vm->_buffer2.plotImage(sprites, 8 + _propCount, Common::Point(
+ _position.x + 99, _position.y + 10));
+ _vm->_buffer2.plotImage(sprites, 11 + _propCount, Common::Point(
+ _position.x + 104, _position.y + 18));
+
+ if (++_planeCount >= 30)
+ _planeCount = 0;
+ if (++_propCount >= 3)
+ _propCount = 0;
+
+ ++_xCount;
+ if (_xCount == 1)
+ ++_position.x;
+ else
+ _xCount = 0;
+}
+
+void Plane::doFallCell() {
+ if (_vm->_scaleI <= 20)
+ return;
+
+ SpriteFrame *frame = _vm->_objectsTable[20]->getFrame(_planeCount / 6);
+ Common::Rect r(115, 11, 115 + _vm->_screen->_scaleTable1[frame->w],
+ 11 + _vm->_screen->_scaleTable1[frame->h]);
+ _vm->_buffer2.sPlotF(frame, r);
+
+ _vm->_scaleI -= 3;
+ _vm->_scale = _vm->_scaleI;
+ _vm->_screen->setScaleTable(_vm->_scale);
+ ++_xCount;
+ if (_xCount == 5)
+ return;
+ _xCount = 0;
+ if (_planeCount == 18)
+ _planeCount = 0;
+ else
+ _planeCount += 6;
+}
+
+void Plane::scrollFly() {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ doFlyCell();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+}
+
+void Plane::scrollFall() {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ doFallCell();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+}
+
+void Plane::mWhileFly() {
+ Screen &screen = *_vm->_screen;
+ Player &player = *_vm->_player;
+ EventsManager &events = *_vm->_events;
+
+ events.hideCursor();
+ screen.clearScreen();
+ screen.setBufferScan();
+ screen.fadeOut();
+ _vm->_scrollX = 0;
+
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ screen.fadeIn();
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_events->clearEvents();
+
+ _vm->_scrollRow = _vm->_scrollCol = 0;
+ _vm->_scrollX = _vm->_scrollY = 0;
+ player._rawPlayer = Common::Point(0, 0);
+ player._scrollAmount = 1;
+
+ _pCount = 0;
+ _planeCount = 0;
+ _propCount = 0;
+ _xCount = 0;
+ _position = Common::Point(20, 29);
+
+ while (!_vm->shouldQuit() && !events.isKeyMousePressed() &&
+ ((_vm->_scrollCol + screen._vWindowWidth) != _vm->_room->_playFieldWidth)) {
+ events._vbCount = 4;
+ _vm->_scrollX += player._scrollAmount;
+
+ while (_vm->_scrollX >= TILE_WIDTH) {
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
+ }
+
+ scrollFly();
+ ++_pCount;
+
+ while (!_vm->shouldQuit() && events._vbCount > 0) {
+ _vm->_sound->playSound(0);
+ events.pollEventsAndWait();
+ }
+ }
+
+ events.showCursor();
+}
+
+void Plane::mWhileFall() {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+
+ events.hideCursor();
+ screen.clearScreen();
+ screen.setBufferScan();
+ screen.fadeOut();
+ _vm->_scrollX = 0;
+
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ screen.fadeIn();
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_events->clearEvents();
+
+ _vm->_scrollRow = _vm->_scrollCol = 0;
+ _vm->_scrollX = _vm->_scrollY = 0;
+ _vm->_player->_scrollAmount = 3;
+ _vm->_scaleI = 255;
+
+ _xCount = 0;
+ _planeCount = 0;
+
+ while (!_vm->shouldQuit() && !events.isKeyMousePressed() &&
+ (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth)) {
+ events._vbCount = 4;
+ _vm->_scrollX += _vm->_player->_scrollAmount;
+
+ while (_vm->_scrollX >= TILE_WIDTH) {
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
+ }
+
+ scrollFall();
+
+ while (!_vm->shouldQuit() && events._vbCount > 0) {
+ events.pollEventsAndWait();
+ }
+ }
+
+ events.showCursor();
+}
+
+/*------------------------------------------------------------------------*/
+
+Jungle::Jungle(AmazonEngine *vm) : CampScene(vm) {
+ for (int i = 0; i < JUNGLE_SIZE; ++i) {
+ _jCnt[i] = _jungleX[i] = -1;
+ }
+}
+
+void Jungle::jungleMove() {
+ const static int jungleY[3] = { 27, 30, 29 };
+ int count = 1;
+ int frameOffset = 0;
+
+ if (!_vm->_timers[0]._flag) {
+ ++_vm->_timers[0]._flag;
+ _vm->_scrollX += _vm->_player->_scrollAmount;
+
+ for (int i = 0; i < 3; ++i) {
+ int newJCnt = (_jCnt[i] + 1) % 8;
+ _jCnt[i] = newJCnt;
+ _jungleX[i] += 5;
+ }
+
+ frameOffset = 4;
+ count = (_vm->_allenFlag != 1) ? 2 : 3;
+ }
+
+ for (int i = 0; i < count; ++i) {
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._spritesPtr = _vm->_objectsTable[24];
+ ie._frameNumber = _jCnt[i] + frameOffset;
+ ie._position = Common::Point(_jungleX[i], jungleY[i]);
+ ie._offsetY = jungleY[i];
+
+ _vm->_images.addToList(ie);
+ frameOffset += 8;
+ }
+}
+
+void Jungle::initJWalk2() {
+ const int JUNGLE1OBJ[7][4] = {
+ { 2, 470, 0, 20 },
+ { 0, 290, 0, 50 },
+ { 1, 210, 0, 40 },
+ { 0, 500, 0, 30 },
+ { 1, 550, 0, 20 },
+ { 0, 580, 0, 60 },
+ { 1, 650, 0, 30 }
+ };
+
+ Screen &screen = *_vm->_screen;
+ screen.fadeOut();
+ _vm->_events->hideCursor();
+ screen.clearScreen();
+ _vm->_buffer2.clearBuffer();
+ screen.setBufferScan();
+
+ _vm->_scrollX = _vm->_scrollY;
+ _vm->_scrollCol = _vm->_scrollRow;
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ screen.fadeIn();
+ _vm->_events->clearEvents();
+
+ _xCount = 2;
+ _vm->_player->_scrollAmount = 5;
+ _xTrack = -10;
+ _yTrack = _zTrack = 0;
+ _xCam = 480;
+ _yCam = 0;
+ _zCam = 80;
+
+ _vm->_timers[24]._timer = 1;
+ _vm->_timers[24]._initTm = 1;
+ ++_vm->_timers[24]._flag;
+
+ _pNumObj = 7;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[i]._pObject = _vm->_objectsTable[24];
+ _pan[i]._pImgNum = JUNGLE1OBJ[i][0];
+ _pan[i]._pObjX = JUNGLE1OBJ[i][1];
+ _pan[i]._pObjY = JUNGLE1OBJ[i][2];
+ _pan[i]._pObjZ = JUNGLE1OBJ[i][3];
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+
+ _jCnt[0] = 0;
+ _jCnt[1] = 3;
+ _jCnt[2] = 5;
+
+ _jungleX[0] = 50;
+ _jungleX[1] = 16;
+ _jungleX[2] = 93;
+}
+
+void Jungle::mWhileJWalk() {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ Player &player = *_vm->_player;
+
+ static const int JUNGLE_OBJ[7][4] = {
+ { 2, 77, 0, 40 },
+ { 0, 290, 0, 50 },
+ { 1, 210, 0, 70 },
+ { 0, 50, 0, 30 },
+ { 1, 70, 0, 20 },
+ { 0, -280, 0, 60 },
+ { 1, -150, 0, 30 },
+ };
+
+ screen.fadeOut();
+ events.hideCursor();
+ screen.clearScreen();
+ _vm->_buffer2.clearBuffer();
+ screen.setBufferScan();
+ _vm->_scrollX = 0;
+
+ // Build the initial jungle scene and fade it in
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ screen.fadeIn();
+
+ // Set up the player to walk horizontally
+ player._xFlag = 1;
+ player._yFlag = 0;
+ player._moveTo.x = 160;
+ player._playerMove = true;
+
+ _xCount = 2;
+ _xTrack = 10;
+ _yTrack = _zTrack = 0;
+ _xCam = 480;
+ _yCam = 0;
+ _zCam = 80;
+
+ TimerEntry *te = &_vm->_timers[24];
+ te->_initTm = te->_timer = 1;
+ te->_flag++;
+
+ _pNumObj = 7;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[i]._pObject = _vm->_objectsTable[24];
+ _pan[i]._pImgNum = JUNGLE_OBJ[i][0];
+ _pan[i]._pObjX = JUNGLE_OBJ[i][1];
+ _pan[i]._pObjY = JUNGLE_OBJ[i][2];
+ _pan[i]._pObjZ = JUNGLE_OBJ[i][3];
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+
+ while (!_vm->shouldQuit() && !events.isKeyMousePressed() && (player._xFlag != 2)) {
+ _vm->_images.clear();
+ events._vbCount = 6;
+
+ _pan[0]._pImgNum = _xCount;
+ if (_xCount == 2)
+ ++_xCount;
+ else
+ --_xCount;
+
+ player.checkMove();
+ player.checkScroll();
+ pan();
+ scrollJWalk();
+
+ while (!_vm->shouldQuit() && events._vbCount > 0) {
+ events.pollEventsAndWait();
+ }
+ }
+
+ _vm->_images.clear();
+ events.showCursor();
+}
+
+void Jungle::mWhileJWalk2() {
+ Screen &screen = *_vm->_screen;
+
+ initJWalk2();
+
+ while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() &&
+ (_vm->_scrollCol + screen._vWindowWidth) != _vm->_room->_playFieldWidth) {
+ _vm->_images.clear();
+ _vm->_events->_vbCount = 6;
+ _pan[0]._pImgNum = _xCount;
+
+ jungleMove();
+ while (_vm->_scrollX >= TILE_WIDTH) {
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
+ }
+
+ if (_xCount == 2)
+ ++_xCount;
+ else
+ --_xCount;
+
+ pan();
+ scrollJWalk();
+
+ while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) {
+ _vm->_events->pollEventsAndWait();
+ }
+ }
+
+ _vm->_events->showCursor();
+}
+
+void Jungle::scrollJWalk() {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ _vm->plotList();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+}
+
+/*------------------------------------------------------------------------*/
+
+Guard::Guard(AmazonEngine *vm) : PannedScene(vm) {
+ _guardCel = 0;
+ _gCode1 = _gCode2 = 0;
+ _xMid = _yMid = 0;
+}
+
+void Guard::setVerticalCode() {
+ Screen &screen = *_vm->_screen;
+
+ _gCode1 = 0;
+ _gCode2 = 0;
+ if (_topLeft.x < screen._orgX1)
+ _gCode1 |= 8;
+ else if (_topLeft.x == screen._orgX1) {
+ _gCode1 |= 8;
+ _gCode1 |= 2;
+ } else
+ _gCode1 |= 2;
+
+ if (_bottomRight.x < screen._orgX1)
+ _gCode2 |= 8;
+ else if (_bottomRight.x == screen._orgX1) {
+ _gCode2 |= 8;
+ _gCode2 |= 2;
+ } else
+ _gCode2 |= 2;
+
+ if (_topLeft.y < screen._orgY1)
+ _gCode1 |= 4;
+ else if (_topLeft.y > screen._orgY2)
+ _gCode1 |= 1;
+
+ if (_bottomRight.y < screen._orgY1)
+ _gCode2 |= 4;
+ else if (_bottomRight.y > screen._orgY2)
+ _gCode2 |= 1;
+}
+
+void Guard::setHorizontalCode() {
+ Screen &screen = *_vm->_screen;
+
+ _gCode1 = 0;
+ _gCode2 = 0;
+
+ if (_topLeft.y < screen._orgY1)
+ _gCode1 |= 4;
+ else if (_topLeft.x == screen._orgX1) {
+ _gCode1 |= 4;
+ _gCode1 |= 1;
+ } else
+ _gCode1 |= 1;
+
+ if (_bottomRight.y < screen._orgY1)
+ _gCode2 |= 4;
+ else if (_bottomRight.x == screen._orgX1) {
+ _gCode2 |= 4;
+ _gCode2 |= 1;
+ } else
+ _gCode2 |= 1;
+
+ if (_topLeft.x < screen._orgX1)
+ _gCode1 |= 8;
+ else if (_topLeft.x > screen._orgX2)
+ _gCode1 |= 2;
+
+ if (_bottomRight.x < screen._orgX1)
+ _gCode2 |= 8;
+ else if (_bottomRight.y > screen._orgX2)
+ _gCode2 |= 2;
+}
+
+void Guard::chkVLine() {
+ if (_position.x > _vm->_player->_rawPlayer.x) {
+ _topLeft = _vm->_player->_rawPlayer;
+ _bottomRight = _position;
+ } else {
+ _topLeft = _position;
+ _bottomRight = _vm->_player->_rawPlayer;
+ }
+
+ if (_vm->_screen->_orgY1 > _vm->_screen->_orgY2)
+ SWAP(_vm->_screen->_orgY1, _vm->_screen->_orgY2);
+
+ for (;;) {
+ setVerticalCode();
+ int code = _gCode1 | _gCode2;
+ if (code == 10) {
+ _vm->_guardFind = 0;
+ return;
+ }
+
+ int code2 = _gCode1 & _gCode2;
+ code2 &= 5;
+ if (((code & 10) == 8) || ((code & 10) == 2) || (code2 != 0))
+ return;
+
+ int midX = (_topLeft.x + _bottomRight.x) / 2;
+ int midY = (_topLeft.y + _bottomRight.y) / 2;
+
+ if (midX < _vm->_screen->_orgX1) {
+ if ((midX == _topLeft.x) && (midY == _topLeft.y))
+ return;
+
+ _topLeft.x = midX;
+ _topLeft.y = midY;
+ } else {
+ if ((midX == _bottomRight.x) && (midY == _bottomRight.y))
+ return;
+
+ _bottomRight.x = midX;
+ _bottomRight.y = midY;
+ }
+ }
+}
+
+void Guard::chkHLine() {
+ if (_position.y > _vm->_player->_rawPlayer.y) {
+ _topLeft = _vm->_player->_rawPlayer;
+ _bottomRight = _position;
+ } else {
+ _topLeft = _position;
+ _bottomRight = _vm->_player->_rawPlayer;
+ }
+
+ if (_vm->_screen->_orgX1 > _vm->_screen->_orgX2)
+ SWAP(_vm->_screen->_orgX1, _vm->_screen->_orgX2);
+
+ while (true) {
+ setHorizontalCode();
+ int code = _gCode1 | _gCode2;
+ if (code == 5) {
+ _vm->_guardFind = 0;
+ return;
+ }
+
+ int code2 = _gCode1 & _gCode2;
+ code2 &= 10;
+ if (((code & 5) == 4) || ((code & 5) == 1) || (code2 != 0))
+ return;
+
+ int midX = (_topLeft.x + _bottomRight.x) / 2;
+ int midY = (_topLeft.y + _bottomRight.y) / 2;
+
+ if (midY < _vm->_screen->_orgY1) {
+ if ((midX == _topLeft.x) && (midY == _topLeft.y))
+ return;
+
+ _topLeft.x = midX;
+ _topLeft.y = midY;
+ } else {
+ if ((midX == _bottomRight.x) && (midY == _bottomRight.y))
+ return;
+
+ _bottomRight.x = midX;
+ _bottomRight.y = midY;
+ }
+ }
+}
+
+void Guard::guardSee() {
+ Screen &screen = *_vm->_screen;
+ int tmpY = (_vm->_scrollRow << 4) + _vm->_scrollY;
+ _vm->_flags[140] = 0;
+ if (tmpY > _position.y)
+ return;
+
+ tmpY += screen._vWindowLinesTall;
+ tmpY -= 11;
+
+ if (tmpY < _position.y)
+ return;
+
+ _vm->_guardFind = 1;
+ _vm->_flags[140] = 1;
+
+ for (uint16 idx = 0; idx < _vm->_room->_plotter._walls.size(); idx++) {
+ screen._orgX1 = _vm->_room->_plotter._walls[idx].left;
+ screen._orgY1 = _vm->_room->_plotter._walls[idx].top;
+ screen._orgX2 = _vm->_room->_plotter._walls[idx].right;
+ screen._orgY2 = _vm->_room->_plotter._walls[idx].bottom;
+ if (screen._orgX1 == screen._orgX2) {
+ chkVLine();
+ if (_vm->_guardFind == 0)
+ return;
+ } else if (screen._orgY1 == screen._orgY2) {
+ chkHLine();
+ if (_vm->_guardFind == 0)
+ return;
+ }
+ }
+}
+
+void Guard::setGuardFrame() {
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+
+ if (_vm->_guardLocation == 4)
+ ie._flags |= IMGFLAG_BACKWARDS;
+ ie._spritesPtr = _vm->_objectsTable[37];
+ ie._frameNumber = _guardCel;
+ ie._position = _position;
+ ie._offsetY = 10;
+ _vm->_images.addToList(ie);
+}
+
+void Guard::doGuard() {
+ // Skip the code dealing with the guard on the boat (chapter 8)
+ // if the cheat mode is activated
+ if (_vm->_cheatFl)
+ return;
+
+ if (_vm->_timers[8]._flag) {
+ setGuardFrame();
+ return;
+ }
+
+ ++_vm->_timers[8]._flag;
+ ++_guardCel;
+ int curCel = _guardCel;
+
+ switch (_vm->_guardLocation) {
+ case 1:
+ // Guard walking down
+ if (curCel <= 8 || curCel > 13)
+ _guardCel = curCel = 8;
+
+ _position.y += _vm->_player->_walkOffDown[curCel - 8];
+ guardSee();
+ if (_position.y >= 272) {
+ _position.y = 272;
+ _vm->_guardLocation = 2;
+ }
+ break;
+ case 2:
+ // Guard walking left
+ if (curCel <= 43 || curCel > 48)
+ _guardCel = curCel = 43;
+
+ _position.x -= _vm->_player->_walkOffLeft[curCel - 43];
+ guardSee();
+ if (_position.x <= 56) {
+ _position.x = 56;
+ _vm->_guardLocation = 3;
+ }
+ break;
+ case 3:
+ // Guard walking up
+ if (curCel <= 0 || curCel > 5)
+ _guardCel = curCel = 0;
+
+ _position.y -= _vm->_player->_walkOffUp[curCel];
+ guardSee();
+ if (_position.y <= 89) {
+ _position.y = 89;
+ _vm->_guardLocation = 4;
+ if (_vm->_flags[121] == 1)
+ _vm->_guardLocation = 5;
+ }
+ break;
+ default:
+ // Guard walking right
+ if (curCel <= 43 || curCel > 48)
+ _guardCel = curCel = 43;
+
+ _position.x += _vm->_player->_walkOffRight[curCel - 43];
+ guardSee();
+ if (_position.x >= 127) {
+ _position.x = 127;
+ _vm->_guardLocation = 1;
+ }
+ break;
+ }
+
+ setGuardFrame();
+}
+
+void Guard::setPosition(const Common::Point &pt) {
+ _position = pt;
+}
+
+/*------------------------------------------------------------------------*/
+
+Cast::Cast(AmazonEngine *vm) : PannedScene(vm) {
+}
+
+void Cast::doCast(int param1) {
+ Screen &screen = *_vm->_screen;
+
+ screen.setDisplayScan();
+ _vm->_events->hideCursor();
+ screen.forceFadeOut();
+ screen._clipHeight = 173;
+ screen.clearScreen();
+ _vm->_chapter = 16;
+ _vm->tileScreen();
+ _vm->updateSummary(param1);
+ screen.setPanel(3);
+ _vm->_chapter = 14;
+
+ Resource *spriteData = _vm->_files->loadFile(91, 0);
+ _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+ spriteData = _vm->_files->loadFile(91, 1);
+ _vm->_objectsTable[1] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(58, 1);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+
+ _xTrack = 0;
+ _yTrack = -6;
+ _zTrack = 0;
+ _xCam = _yCam = 0;
+ _zCam = 60;
+
+ _vm->_timers[24]._timer = 1;
+ _vm->_timers[24]._initTm = 1;
+ ++_vm->_timers[24]._flag;
+
+ _pNumObj = 26;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[i]._pObject = _vm->_objectsTable[0];
+ _pan[i]._pImgNum = CAST_END_OBJ[i][0];
+ _pan[i]._pObjX = CAST_END_OBJ[i][1];
+ _pan[i]._pObjY = CAST_END_OBJ[i][2];
+ _pan[i]._pObjZ = CAST_END_OBJ[i][3];
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+
+ _pNumObj = 4;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[26 + i]._pObject = _vm->_objectsTable[1];
+ _pan[26 + i]._pImgNum = CAST_END_OBJ1[i][0];
+ _pan[26 + i]._pObjX = CAST_END_OBJ1[i][1];
+ _pan[26 + i]._pObjY = CAST_END_OBJ1[i][2];
+ _pan[26 + i]._pObjZ = CAST_END_OBJ1[i][3];
+ _pan[26 + i]._pObjXl = _pan[26 + i]._pObjYl = 0;
+ }
+
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_numAnimTimers = 0;
+
+ _vm->_midi->newMusic(58, 0);
+ screen.forceFadeIn();
+
+ while (!_vm->shouldQuit()) {
+ _vm->_images.clear();
+ pan();
+ _vm->_buffer2.copyFrom(_vm->_buffer1);
+ _vm->_newRects.clear();
+ _vm->plotList();
+ _vm->copyBlocks();
+
+ _vm->_events->pollEvents();
+ if (_vm->_events->isKeyMousePressed())
+ break;
+
+ if (_yCam < -7550) {
+ _vm->_events->_vbCount = 50;
+
+ while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() && _vm->_events->_vbCount > 0) {
+ _vm->_events->pollEventsAndWait();
+ }
+
+ while (!_vm->shouldQuit() && !_vm->_midi->checkMidiDone())
+ _vm->_events->pollEventsAndWait();
+
+ break;
+ }
+ }
+
+ _vm->_midi->newMusic(58, 1);
+ _vm->_events->showCursor();
+
+ _vm->freeCells();
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_numAnimTimers = 0;
+ _vm->_images.clear();
+ screen.forceFadeOut();
+
+ _vm->quitGame();
+ _vm->_events->pollEvents();
+}
+
+/*------------------------------------------------------------------------*/
+
+River::River(AmazonEngine *vm) : PannedScene(vm) {
+ _chickenOutFl = false;
+ _rScrollRow = 0;
+ _rScrollCol = 0;
+ _rScrollX = 0;
+ _rScrollY = 0;
+ _mapOffset = 0;
+ _screenVertX = 0;
+ _saveRiver = false;
+ _deathFlag = false;
+ _deathCount = 0;
+ _oldScrollCol = 0;
+ _maxHits = 0;
+}
+
+void River::setRiverPan() {
+ int delta = (_vm->_scrollCol * 16) + _vm->_scrollX;
+
+ _xTrack = 9;
+ _yTrack = _zTrack = 0;
+ _xCam = 160;
+ _yCam = 0;
+ _zCam = 80;
+
+ _vm->_timers[24]._timer = 1;
+ _vm->_timers[24]._initTm = 1;
+ ++_vm->_timers[24]._flag;
+
+ _pNumObj = 23;
+ for (int i = 0; i < _pNumObj; i++) {
+ _pan[i]._pObject = _vm->_objectsTable[45];
+ _pan[i]._pImgNum = RIVER1OBJ[i][0];
+ _pan[i]._pObjX = RIVER1OBJ[i][1] + delta;
+ _pan[i]._pObjY = RIVER1OBJ[i][2];
+ _pan[i]._pObjZ = RIVER1OBJ[i][3];
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+}
+
+void River::initRiver() {
+ static const int RIVERVXTBL[3] = { 6719, 7039, 8319 };
+ Screen &screen = *_vm->_screen;
+
+ _vm->_events->centerMousePos();
+ _vm->_events->restrictMouse();
+ screen.setDisplayScan();
+ screen.clearScreen();
+ screen.savePalette();
+ screen.forceFadeOut();
+
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(95, 4);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+
+ screen.restorePalette();
+ screen.setBufferScan();
+ _vm->_destIn = &_vm->_buffer2;
+ _vm->_room->roomMenu();
+
+ if (_saveRiver) {
+ // Restoring a savegame, so set properties from saved fields
+ _vm->_scrollRow = _rScrollRow;
+ _vm->_scrollCol = _rScrollCol;
+ _vm->_scrollX = _rScrollX;
+ _vm->_scrollY = _rScrollY;
+ } else {
+ // Set initial scene state
+ _vm->_scrollRow = 0;
+ _vm->_scrollCol = 140;
+ _vm->_scrollX = 0;
+ _vm->_scrollY = 0;
+ }
+
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ screen.forceFadeIn();
+
+ if (!_saveRiver) {
+ // Reset draw rects
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+ _vm->_events->clearEvents();
+
+ }
+
+ _vm->_player->_scrollAmount = 2;
+ setRiverPan();
+ _vm->_timers[3]._timer = 1;
+ _vm->_timers[3]._initTm = 1;
+ ++_vm->_timers[3]._flag;
+
+ _canoeFrame = 0;
+ _mapPtr = (const byte *)MAPTBL[_vm->_riverFlag] + 1;
+ if (_saveRiver) {
+ _mapPtr--;
+ _mapPtr += _mapOffset;
+ } else {
+ _screenVertX = RIVERVXTBL[_vm->_riverFlag] - 320;
+ _canoeLane = 3;
+ _hitCount = 0;
+ _hitSafe = 0;
+ _canoeYPos = 71;
+ }
+
+ _riverIndex = _vm->_riverFlag;
+ _topList = RIVER_OBJECTS[_riverIndex][RIVER_START];
+ updateObstacles();
+ riverSetPhysX();
+ _canoeDir = 0;
+ _deathFlag = false;
+ _deathCount = 0;
+
+ _vm->_timers[11]._timer = 1200;
+ _vm->_timers[11]._initTm = 1200;
+ ++_vm->_timers[11]._flag;
+ _vm->_timers[12]._timer = 1500;
+ _vm->_timers[12]._initTm = 1500;
+ ++_vm->_timers[12]._flag;
+
+ _maxHits = 2 - _vm->_riverFlag;
+ _saveRiver = false;
+
+ Font &font2 = _vm->_fonts._font2;
+ font2._fontColors[0] = 0;
+ font2._fontColors[1] = 33;
+ font2._fontColors[2] = 34;
+ font2._fontColors[3] = 35;
+}
+
+void River::resetPositions() {
+ riverSetPhysX();
+ int val = (_vm->_scrollCol + 1 - _oldScrollCol) * 16;
+ if (val < 0) {
+ val |= 0x80;
+ }
+
+ for (int i = 0; i < _pNumObj; i++)
+ _pan[i]._pObjX += val;
+}
+
+void River::checkRiverPan() {
+ int val = _vm->_scrollCol * 16 + 320;
+
+ for (int i = 0; i < _pNumObj; i++) {
+ if (_pan[i]._pObjX < val)
+ return;
+ }
+
+ setRiverPan();
+}
+
+bool River::riverJumpTest() {
+ Screen &screen = *_vm->_screen;
+
+ if (_vm->_scrollCol == 120 || _vm->_scrollCol == 60 || _vm->_scrollCol == 0) {
+ int val = *++_mapPtr;
+ if (val == 0xFF)
+ return true;
+
+ _oldScrollCol = _vm->_scrollCol;
+
+ if (val == 0) {
+ _vm->_scrollCol = 139;
+ _vm->_scrollX = 14;
+ _vm->_room->buildScreen();
+ resetPositions();
+ return false;
+ }
+ } else if (_vm->_scrollCol == 105) {
+ int val1 = _mapPtr[1];
+ int val2 = _mapPtr[2];
+ _mapPtr += 3;
+ if (_canoeLane < 3) {
+ if (val1 != 0) {
+ _deathFlag = true;
+ _deathCount = 300;
+ _deathType = val2;
+ }
+ } else {
+ if (val1 != 1) {
+ _deathFlag = true;
+ _deathCount = 300;
+ _deathType = val2;
+ }
+ _oldScrollCol = _vm->_scrollCol;
+ _vm->_scrollCol = 44;
+ _vm->_scrollX = 14;
+ _vm->_room->buildScreen();
+ resetPositions();
+ return false;
+ }
+ }
+
+ _vm->_scrollX = 14;
+ --_vm->_scrollCol;
+ _vm->_buffer1.moveBufferRight();
+ _vm->_room->buildColumn(_vm->_scrollCol, 0);
+ checkRiverPan();
+ return false;
+}
+
+void River::riverSound() {
+ if (_vm->_timers[11]._flag == 0) {
+ ++_vm->_timers[11]._flag;
+ _vm->_sound->playSound(2);
+ }
+
+ if (_vm->_timers[12]._flag == 0) {
+ ++_vm->_timers[12]._flag;
+ _vm->_sound->playSound(3);
+ }
+
+ if ((_xCam >= 1300) && (_xCam <= 1320))
+ _vm->_sound->playSound(1);
+}
+
+void River::moveCanoe() {
+ EventsManager &events = *_vm->_events;
+ Common::Point pt = events.calcRawMouse();
+ Common::Point mousePos = events.getMousePos();
+
+ // Do an event polling
+ _vm->_canSaveLoad = true;
+ events.pollEvents();
+ _vm->_canSaveLoad = false;
+ if (_vm->_room->_function == FN_CLEAR1)
+ return;
+
+ if (_canoeDir) {
+ // Canoe movement in progress
+ moveCanoe2();
+ } else {
+ if (events._leftButton && pt.y >= 140) {
+ if (pt.x < RMOUSE[8][0]) {
+ // Disk icon wasn't clicked
+ _vm->_scripts->printString(BAR_MESSAGE);
+ } else {
+ // Clicked on the Disc icon. Show the ScummVM menu
+ _vm->_room->handleCommand(9);
+
+ if (_vm->_room->_function != FN_CLEAR1) {
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+ }
+ }
+ } else if (events._leftButton && mousePos.x < 35 && mousePos.y < 12) {
+ // Clicked on the Skip button. So chicken out
+ _chickenOutFl = true;
+ } else if ((events._leftButton && pt.y <= _canoeYPos) ||
+ (!events._leftButton && _vm->_player->_move == UP)) {
+ // Move canoe up
+ if (_canoeLane > 0) {
+ _canoeDir = -1;
+ _canoeMoveCount = 0;
+
+ moveCanoe2();
+ }
+ } else if (events._leftButton || _vm->_player->_move == DOWN) {
+ // Move canoe down
+ if (_canoeLane < 7) {
+ _canoeDir = 1;
+ _canoeMoveCount = 0;
+
+ moveCanoe2();
+ }
+ }
+ }
+}
+
+void River::moveCanoe2() {
+ _canoeYPos += _canoeDir;
+
+ if (++_canoeMoveCount == 5) {
+ _canoeLane += _canoeDir;
+ _canoeDir = 0;
+ }
+}
+
+void River::updateObstacles() {
+ RiverStruct *cur;
+ for (cur = _topList; cur < RIVER_OBJECTS[_riverIndex][RIVER_END]; ++cur) {
+ int val = cur->_riverX + cur->_width - 1;
+ if (val < _screenVertX)
+ // Obstacle is not yet on-screen
+ break;
+
+ if (cur->_riverX < (_screenVertX + 319)) {
+ // Object is now on-screen. So set _topList/_botList to the range
+ // of river obstacles that are currently visible
+ _topList = cur;
+ _botList = cur;
+
+ while (cur < RIVER_OBJECTS[_riverIndex][RIVER_END]) {
+ ++cur;
+ val = cur->_riverX + cur->_width - 1;
+ if (val < _screenVertX || (cur->_riverX >= (_screenVertX + 319)))
+ break;
+
+ _botList = cur;
+ }
+
+ return;
+ }
+ }
+
+ cur = _topList;
+ cur--;
+ _botList = cur;
+}
+
+void River::riverSetPhysX() {
+ int xAmt = (_vm->_scrollCol * 16) + _vm->_scrollX;
+
+ for (RiverStruct *cur = _topList; cur <= _botList; ++cur) {
+ cur->_xp = xAmt - (_screenVertX - cur->_riverX);
+ }
+}
+
+bool River::checkRiverCollide() {
+ if (_hitSafe)
+ return false;
+
+ _canoeVXPos = _screenVertX + 170;
+
+ for (RiverStruct *cur = _topList; cur <= _botList; ++cur) {
+ if (cur->_lane < _canoeLane)
+ continue;
+
+ if ((cur->_lane == _canoeLane) || (cur->_lane == _canoeLane + 1)) {
+ if ((cur->_riverX + cur->_width - 1) >= _canoeVXPos &&
+ cur->_riverX < (_canoeVXPos + 124)) {
+ _vm->_sound->playSound(4);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void River::plotRiver() {
+ // Handle cycling through the canoe rowing frames
+ if (_vm->_timers[3]._flag == 0) {
+ ++_vm->_timers[3]._flag;
+
+ if (_canoeFrame++ == 12)
+ _canoeFrame = 0;
+ }
+
+ // Draw the canoe
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._spritesPtr = _vm->_objectsTable[45];
+ ie._frameNumber = _canoeFrame;
+ ie._position.x = (_vm->_scrollCol * 16) + _vm->_scrollX + 160;
+ ie._position.y = _canoeYPos - 41;
+ ie._offsetY = 41;
+ _vm->_images.addToList(ie);
+
+ // Draw any on-screen obstacles
+ for (RiverStruct *cur = _topList; cur <= _botList; ++cur) {
+ if (cur->_id != -1) {
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._spritesPtr = _vm->_objectsTable[45];
+ ie._frameNumber = cur->_id;
+ ie._position.x = cur->_xp;
+ ie._position.y = (cur->_lane * 5) + 56 - cur->_offsetY;
+ ie._offsetY = cur->_offsetY;
+ _vm->_images.addToList(ie);
+ }
+ }
+
+ // Draw the text for skipping the river
+ Font &font2 = _vm->_fonts._font2;
+ font2.drawString(_vm->_screen, "SKIP", Common::Point(5, 5));
+}
+
+void River::mWhileDownRiver() {
+ Screen &screen = *_vm->_screen;
+ _vm->_events->hideCursor();
+
+ screen.setDisplayScan();
+ screen.clearScreen();
+ screen.savePalette();
+ if (!_vm->isDemo())
+ _vm->_files->loadScreen(95, 4);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ screen.restorePalette();
+ screen.setPalette();
+ screen.setBufferScan();
+
+ _vm->_scrollX = 0;
+ _vm->_room->buildScreen();
+ _vm->copyBF2Vid();
+
+ _vm->_player->_scrollAmount = 2;
+ _vm->_destIn = &_vm->_buffer2;
+ _xTrack = -7;
+ _yTrack = _zTrack = 0;
+ _xCam = _yCam = 0;
+ _zCam = 80;
+
+ _vm->_timers[24]._timer = 1;
+ _vm->_timers[24]._initTm = 1;
+ ++_vm->_timers[24]._flag;
+
+ _pNumObj = 14;
+ for (int i = 0; i <_pNumObj; i++) {
+ _pan[i]._pObject = _vm->_objectsTable[33];
+ _pan[i]._pImgNum = DOWNRIVEROBJ[i][0];
+ _pan[i]._pObjX = DOWNRIVEROBJ[i][1];
+ _pan[i]._pObjY = DOWNRIVEROBJ[i][2];
+ _pan[i]._pObjZ = DOWNRIVEROBJ[i][3];
+ _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
+ }
+
+ _vm->_timers[3]._timer = 200;
+ _vm->_timers[3]._initTm = 200;
+ ++_vm->_timers[3]._flag;
+ _vm->_timers[4]._timer = 350;
+ _vm->_timers[4]._initTm = 350;
+ ++_vm->_timers[4]._flag;
+
+ while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() &&
+ (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth)) {
+ _vm->_images.clear();
+ _vm->_events->_vbCount = 6;
+
+ _vm->_scrollX += _vm->_player->_scrollAmount;
+ while (_vm->_scrollX >= TILE_WIDTH) {
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
+ }
+
+ pan();
+ scrollRiver();
+
+ if (!_vm->_timers[3]._flag) {
+ ++_vm->_timers[3]._flag;
+ _vm->_sound->playSound(1);
+ } else if (!_vm->_timers[4]._flag) {
+ ++_vm->_timers[4]._flag;
+ _vm->_sound->playSound(0);
+ }
+
+ while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) {
+ _vm->_events->pollEventsAndWait();
+ }
+ }
+
+ _vm->_events->showCursor();
+}
+
+void River::scrollRiver() {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ _vm->_buffer2.plotImage(_vm->_objectsTable[33], 0, Common::Point(66, 30));
+ _vm->plotList();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+}
+
+void River::scrollRiver1() {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ plotRiver();
+ _vm->plotList();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+}
+
+void River::doRiver() {
+ static const int RIVERDEATH[5] = { 22, 23, 24, 25, 26 };
+
+ initRiver();
+ _vm->_events->showCursor();
+
+ while (!_vm->shouldQuit()) {
+ _vm->_events->_vbCount = 4;
+
+ // Move the river position
+ _screenVertX -= _vm->_player->_scrollAmount;
+
+ if (_vm->_scrollX == 0) {
+ _vm->_midi->midiRepeat();
+ if (riverJumpTest()) {
+ _chickenOutFl = false;
+ return;
+ }
+ } else {
+ _vm->_scrollX -= _vm->_player->_scrollAmount;
+ }
+
+ if (_chickenOutFl) {
+ _chickenOutFl = false;
+ return;
+ }
+
+ _vm->_images.clear();
+ _vm->_animation->animate(0);
+
+ riverSound();
+ pan();
+ moveCanoe();
+
+ if (_vm->_room->_function != FN_CLEAR1) {
+ updateObstacles();
+ riverSetPhysX();
+ bool checkCollide = checkRiverCollide();
+ if (_hitSafe != 0)
+ _hitSafe -= 2;
+
+ if (checkCollide) {
+ _vm->dead(RIVERDEATH[0]);
+ return;
+ }
+
+ if (_deathFlag) {
+ if (--_deathCount == 0) {
+ _vm->dead(RIVERDEATH[_deathType]);
+ return;
+ }
+ }
+
+ // Scroll the river
+ scrollRiver1();
+
+ // Allow time for new scrolled river position to be shown
+ _vm->_canSaveLoad = true;
+ while (!_vm->shouldQuit() && _vm->_room->_function == FN_NONE &&
+ _vm->_events->_vbCount > 0) {
+ _vm->_events->pollEventsAndWait();
+ }
+ _vm->_canSaveLoad = false;
+ }
+
+ if (_vm->_room->_function == FN_CLEAR1) {
+ _vm->_scripts->_endFlag = true;
+ _vm->_scripts->_returnCode = 0;
+ _chickenOutFl = false;
+ break;
+ }
+ }
+}
+
+void River::synchronize(Common::Serializer &s) {
+ if (_vm->_player->_roomNumber == 45) {
+ if (s.isSaving()) {
+ // Set river properties to be saved out
+ Screen &screen = *_vm->_screen;
+ _rScrollRow = _vm->_scrollRow;
+ _rScrollCol = _vm->_scrollCol;
+ _rScrollX = _vm->_scrollX;
+ _rScrollY = _vm->_scrollY;
+ _mapOffset = _mapPtr - MAPTBL[_vm->_riverFlag];
+ }
+
+ s.syncAsSint16LE(_canoeLane);
+ s.syncAsSint16LE(_canoeYPos);
+ s.syncAsSint16LE(_hitCount);
+ s.syncAsSint16LE(_riverIndex);
+ s.syncAsSint16LE(_hitSafe);
+ s.syncAsUint16LE(_rScrollRow);
+ s.syncAsUint16LE(_rScrollCol);
+ s.syncAsSint16LE(_rScrollX);
+ s.syncAsSint16LE(_rScrollY);
+ s.syncAsUint16LE(_mapOffset);
+ s.syncAsUint16LE(_screenVertX);
+
+ _saveRiver = s.isLoading();
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Ant::Ant(AmazonEngine *vm) : AmazonManager(vm) {
+ _antDirection = ANT_RIGHT;
+ _pitDirection = ANT_RIGHT;
+ _antCel = 0;
+ _torchCel = 0;
+ _pitCel = 0;
+ _stabCel = 0;
+ _antPos = Common::Point(0, 0);
+ _antDieFl = _antEatFl = false;
+ _stabFl = false;
+ _pitPos = Common::Point(0, 0);
+}
+
+void Ant::plotTorchSpear(int indx, const int *&buf) {
+ int idx = indx;
+
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._spritesPtr = _vm->_objectsTable[62];
+ ie._frameNumber = buf[(idx / 2)];
+ ie._position = Common::Point(_pitPos.x + buf[(idx / 2) + 1], _pitPos.y + buf[(idx / 2) + 2]);
+ ie._offsetY = 255;
+ _vm->_images.addToList(ie);
+}
+
+void Ant::plotPit(int indx, const int *&buf) {
+ int idx = indx;
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._spritesPtr = _vm->_objectsTable[62];
+ ie._frameNumber = buf[(idx / 2)];
+ ie._position = Common::Point(_pitPos.x, _pitPos.y);
+ ie._offsetY = _pitPos.y;
+ _vm->_images.addToList(ie);
+
+ _vm->_player->_rawPlayer = _pitPos;
+ if (_vm->_inventory->_inv[INV_TORCH]._value == ITEM_IN_INVENTORY) {
+ // Player has torch
+ idx = _torchCel;
+ buf = Amazon::TORCH;
+ _vm->_timers[14]._flag = 1;
+ idx += 6;
+ if (buf[idx / 2] == -1)
+ idx = 0;
+ _torchCel = idx;
+ plotTorchSpear(idx, buf);
+ } else if (!_stabFl && (_vm->_inventory->_inv[INV_KNIFE_SPEAR]._value == ITEM_IN_INVENTORY)) {
+ // Player has spear
+ idx = 0;
+ buf = Amazon::SPEAR;
+ plotTorchSpear(idx, buf);
+ }
+}
+
+int Ant::antHandleRight(int indx, const int *&buf) {
+ int retval = indx;
+ if (_pitDirection == ANT_RIGHT) {
+ _pitDirection = ANT_LEFT;
+ _pitPos.y = 127;
+ }
+ retval = _pitCel;
+ buf = Amazon::PITWALK;
+ if (_pitPos.x < 230) {
+ if (retval == 0) {
+ retval = 48;
+ _pitPos.y = 127;
+ }
+ retval -= 6;
+ _pitPos.x -= buf[(retval / 2) + 1];
+ _pitPos.y -= buf[(retval / 2) + 2];
+ _pitCel = retval;
+ }
+ return retval;
+}
+
+int Ant::antHandleLeft(int indx, const int *&buf) {
+ int retval = indx;
+ if (_pitDirection == ANT_LEFT) {
+ _pitDirection = ANT_RIGHT;
+ _pitPos.y = 127;
+ }
+ retval = _pitCel;
+ buf = Amazon::PITWALK;
+ retval += 6;
+ if (buf[retval / 2] == -1) {
+ retval = 0;
+ _pitPos.y = 127;
+ }
+ _pitPos.x += buf[(retval / 2) + 1];
+ _pitPos.y += buf[(retval / 2) + 2];
+ _pitCel = retval;
+
+ return retval;
+}
+
+int Ant::antHandleStab(int indx, const int *&buf) {
+ int retval = indx;
+ if (_vm->_inventory->_inv[INV_KNIFE_SPEAR]._value == ITEM_IN_INVENTORY) {
+ if (_stabFl) {
+ buf = Amazon::PITSTAB;
+ retval = _stabCel;
+ if (_vm->_timers[13]._flag == 0) {
+ _vm->_timers[13]._flag = 1;
+ retval += 6;
+ _stabCel = retval;
+
+ if (buf[retval] == -1) {
+ _stabFl = false;
+ _pitCel = 0;
+ _pitPos.y = 127;
+ retval = 0;
+ buf = Amazon::PITWALK;
+ } else {
+ _pitPos.x += buf[(retval / 2) + 1];
+ _pitPos.y += buf[(retval / 2) + 2];
+ _pitCel = retval;
+ }
+ }
+ } else {
+ _stabFl = true;
+ _pitCel = 0;
+ retval = 0;
+ _stabCel = 0;
+ int dist = _pitPos.x - _antPos.x;
+ if (_antEatFl && !_antDieFl && (dist <= 80)) {
+ _antDieFl = true;
+ _antCel = 0;
+ _antPos.y = 123;
+ _vm->_sound->playSound(1);
+ }
+ }
+ }
+
+ return retval;
+}
+
+void Ant::doAnt() {
+ _antDirection = ANT_RIGHT;
+ if (_vm->_aniFlag != 1) {
+ _vm->_aniFlag = 1;
+ _antCel = 0;
+ _torchCel = 0;
+ _pitCel = 0;
+
+ _vm->_timers[15]._timer = 16;
+ _vm->_timers[15]._initTm = 16;
+ _vm->_timers[15]._flag = 1;
+
+ _vm->_timers[13]._timer = 5;
+ _vm->_timers[13]._initTm = 5;
+ _vm->_timers[13]._flag = 1;
+
+ _vm->_timers[14]._timer = 10;
+ _vm->_timers[14]._initTm = 10;
+ _vm->_timers[14]._flag = 1;
+
+ _antPos = Common::Point(-40, 123);
+ _antDieFl = _antEatFl = false;
+ _stabFl = false;
+ _pitPos = Common::Point(_vm->_player->_rawPlayer.x, 127);
+ }
+
+ const int *buf = nullptr;
+ if (_antDieFl) {
+ buf = Amazon::ANTDIE;
+ } else if (_antEatFl) {
+ buf = Amazon::ANTEAT;
+ } else if (_antPos.x > 120 && _vm->_flags[198] == 1) {
+ _antEatFl = true;
+ _vm->_flags[235] = 1;
+ _antCel = 0;
+ buf = Amazon::ANTEAT;
+ } else {
+ buf = Amazon::ANTWALK;
+ if (_vm->_inventory->_inv[INV_TORCH]._value == ITEM_IN_INVENTORY)
+ // Player has burning torch, which scares the Ant
+ _antDirection = ANT_LEFT;
+ }
+
+ int idx = _antCel;
+ if (_vm->_timers[15]._flag == 0) {
+ _vm->_timers[15]._flag = 1;
+ if (_antDirection == ANT_LEFT) {
+ if (_antPos.x > 10) {
+ if (idx == 0)
+ idx = 36;
+ else
+ idx -= 6;
+
+ _antPos -= Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]);
+ _antCel = idx;
+ }
+ } else {
+ idx += 6;
+ if (buf[(idx / 2)] != -1) {
+ _antPos += Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]);
+ _antCel = idx;
+ } else if (!_antDieFl) {
+ idx = 0;
+ _antPos += Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]);
+ _antCel = idx;
+ } else {
+ idx -= 6;
+ if (_vm->_flags[200] == 0)
+ _vm->_flags[200] = 1;
+ }
+ }
+ }
+
+ ImageEntry ie;
+ ie._flags = IMGFLAG_UNSCALED;
+ ie._spritesPtr = _vm->_objectsTable[61];
+ ie._frameNumber = buf[(idx / 2)];
+ ie._position = Common::Point(_antPos.x, _antPos.y);
+ ie._offsetY = _antPos.y - 70;
+ _vm->_images.addToList(ie);
+ _antCel = idx;
+
+ if (_vm->_flags[196] != 1) {
+ idx = _pitCel;
+ if (_stabFl) {
+ idx = antHandleStab(idx, buf);
+ } else {
+ buf = Amazon::PITWALK;
+ if (_vm->_timers[13]._flag == 0) {
+ _vm->_timers[13]._flag = 1;
+ _vm->_events->pollEvents();
+ if (_vm->_events->_leftButton) {
+ // Handle moving the player whilst the mouse button is held down
+ Common::Point pt = _vm->_events->calcRawMouse();
+ if (pt.x < _pitPos.x)
+ idx = antHandleLeft(idx, buf);
+ else if (pt.x > _pitPos.x)
+ idx = antHandleRight(idx, buf);
+ } else {
+ // Handle movement based on keyboard keys
+ buf = Amazon::PITWALK;
+ if (_vm->_player->_move == UP)
+ idx = antHandleStab(idx, buf);
+ else if (_vm->_player->_move == LEFT)
+ idx = antHandleLeft(idx, buf);
+ else if (_vm->_player->_move == RIGHT)
+ idx = antHandleRight(idx, buf);
+ }
+ }
+ }
+ plotPit(idx, buf);
+ }
+
+ if (!_antDieFl) {
+ int dist = _pitPos.x - _antPos.x;
+ if ((_antEatFl && (dist <= 45)) || (!_antEatFl && (dist <= 80))) {
+ _vm->_flags[199] = 1;
+ _vm->_aniFlag = 0;
+ }
+ }
+}
+
+void Ant::synchronize(Common::Serializer &s) {
+ if (_vm->_player->_roomNumber == 61) {
+ s.syncAsByte(_antDirection);
+ s.syncAsByte(_pitDirection);
+ s.syncAsSint16LE(_antCel);
+ s.syncAsSint16LE(_torchCel);
+ s.syncAsSint16LE(_pitCel);
+ s.syncAsSint16LE(_stabCel);
+ s.syncAsSint16LE(_antPos.x);
+ s.syncAsSint16LE(_antPos.y);
+ s.syncAsSint16LE(_pitPos.x);
+ s.syncAsSint16LE(_pitPos.y);
+ s.syncAsByte(_antDieFl);
+ s.syncAsByte(_antEatFl);
+ s.syncAsByte(_stabFl);
+ }
+}
+
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/amazon/amazon_logic.h b/engines/access/amazon/amazon_logic.h
new file mode 100644
index 0000000000..a1fb4eef77
--- /dev/null
+++ b/engines/access/amazon/amazon_logic.h
@@ -0,0 +1,251 @@
+/* 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 ACCESS_AMAZON_LOGIC_H
+#define ACCESS_AMAZON_LOGIC_H
+
+#include "common/scummsys.h"
+#include "access/scripts.h"
+#include "access/asurface.h"
+
+namespace Access {
+
+namespace Amazon {
+
+class AmazonEngine;
+
+#define PAN_SIZE 32
+
+class AmazonManager {
+protected:
+ AmazonEngine *_vm;
+public:
+ AmazonManager(AmazonEngine *vm) : _vm(vm) {}
+};
+
+class PannedScene : public AmazonManager {
+ struct PanEntry {
+ SpriteResource *_pObject;
+ int _pImgNum;
+ int _pObjX;
+ int _pObjY;
+ int _pObjZ;
+ int _pObjXl;
+ int _pObjYl;
+ };
+protected:
+ int _xCount;
+ int _xTrack;
+ int _yTrack;
+ int _zTrack;
+ int _xCam;
+ int _yCam;
+ int _zCam;
+ int _pNumObj;
+
+ PanEntry _pan[PAN_SIZE];
+public:
+ PannedScene(AmazonEngine *vm);
+
+ void pan();
+};
+
+class CampScene : public PannedScene {
+protected:
+ bool _skipStart;
+public:
+ CampScene(AmazonEngine *vm);
+
+ void mWhileDoOpen();
+};
+
+class Opening : public CampScene {
+private:
+ int _pCount;
+
+ void doTitle();
+ void doCredit();
+ void doCreditDemo();
+ void scrollTitle();
+ void doTent();
+public:
+ Opening(AmazonEngine *vm);
+
+ void doIntroduction();
+};
+
+class Plane : public PannedScene {
+public:
+ int _pCount;
+ Common::Point _position;
+ int _planeCount;
+ int _propCount;
+
+ void doFlyCell();
+ void doFallCell();
+ void scrollFly();
+ void scrollFall();
+ void mWhileFly();
+ void mWhileFall();
+public:
+ Plane(AmazonEngine *vm);
+};
+
+#define JUNGLE_SIZE 3
+class Jungle : public CampScene {
+private:
+ void initJWalk2();
+ void jungleMove();
+ void scrollJWalk();
+
+ int _jCnt[JUNGLE_SIZE];
+ int _jungleX[JUNGLE_SIZE];
+public:
+ Jungle(AmazonEngine *vm);
+
+ void mWhileJWalk();
+ void mWhileJWalk2();
+};
+
+class Guard : public PannedScene {
+private:
+ int _guardCel;
+ Common::Point _position;
+ int _gCode1;
+ int _gCode2;
+ Common::Point _topLeft;
+ Common::Point _bottomRight;
+ int _xMid, _yMid;
+
+ void chkVLine();
+ void chkHLine();
+ void setVerticalCode();
+ void setHorizontalCode();
+ void guardSee();
+ void setGuardFrame();
+public:
+ Guard(AmazonEngine *vm);
+
+ void doGuard();
+
+ void setPosition(const Common::Point &pt);
+};
+
+class Cast : public PannedScene {
+public:
+ Cast(AmazonEngine *vm);
+
+ void doCast(int param1);
+};
+
+class River : public PannedScene {
+private:
+ bool _chickenOutFl;
+ const byte *_mapPtr;
+ int _canoeVXPos;
+ int _canoeMoveCount;
+ int _canoeFrame;
+ RiverStruct *_topList;
+ RiverStruct *_botList;
+ int _canoeDir;
+ bool _saveRiver;
+ bool _deathFlag;
+ int _deathCount;
+ int _deathType;
+ int _maxHits;
+
+ // Saved fields
+ int _canoeLane;
+ int _canoeYPos;
+ int _hitCount;
+ int _riverIndex;
+ int _hitSafe;
+ int _rScrollRow;
+ int _rScrollCol;
+ int _rScrollX;
+ int _rScrollY;
+ int _mapOffset;
+ int _screenVertX;
+ int _oldScrollCol;
+
+ void initRiver();
+ void resetPositions();
+ void checkRiverPan();
+ bool riverJumpTest();
+ void riverSound();
+ void moveCanoe();
+ void moveCanoe2();
+ void updateObstacles();
+ void riverSetPhysX();
+ bool checkRiverCollide();
+ void plotRiver();
+ void scrollRiver();
+ void scrollRiver1();
+ void setRiverPan();
+public:
+ River(AmazonEngine *vm);
+
+ void doRiver();
+ void mWhileDownRiver();
+
+ void synchronize(Common::Serializer &s);
+};
+
+enum AntDirection { ANT_RIGHT = 0, ANT_LEFT = 1 };
+
+class Ant : public AmazonManager {
+private:
+ AntDirection _antDirection;
+ AntDirection _pitDirection;
+ int _antCel;
+ int _torchCel;
+ int _pitCel;
+ int _stabCel;
+ Common::Point _antPos;
+ bool _antDieFl;
+ bool _antEatFl;
+ bool _stabFl;
+ Common::Point _pitPos;
+
+ void plotTorchSpear(int indx, const int *&buf);
+ void plotPit(int indx, const int *&buf);
+ int antHandleRight(int indx, const int *&buf);
+ int antHandleLeft(int indx, const int *&buf);
+ int antHandleStab(int indx, const int *&buf);
+public:
+ Ant(AmazonEngine *vm);
+
+ void doAnt();
+
+ void synchronize(Common::Serializer &s);
+};
+
+class InactivePlayer : public ImageEntry {
+public:
+ SpriteResource *_altSpritesPtr;
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_AMAZON_LOGIC_H */
diff --git a/engines/access/amazon/amazon_player.cpp b/engines/access/amazon/amazon_player.cpp
new file mode 100644
index 0000000000..b1ed501fce
--- /dev/null
+++ b/engines/access/amazon/amazon_player.cpp
@@ -0,0 +1,86 @@
+/* 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 "access/access.h"
+#include "access/room.h"
+#include "access/amazon/amazon_game.h"
+#include "access/amazon/amazon_player.h"
+#include "access/amazon/amazon_resources.h"
+
+namespace Access {
+
+namespace Amazon {
+
+AmazonPlayer::AmazonPlayer(AccessEngine *vm) : Player(vm) {
+ _game = (AmazonEngine *)vm;
+}
+
+void AmazonPlayer::load() {
+ Player::load();
+
+ // Special scene setup for the top-down view when on the Slaver ship
+ if (_vm->_room->_roomFlag == 3) {
+ _playerOffset.x = _vm->_screen->_scaleTable1[8];
+ _playerOffset.y = _vm->_screen->_scaleTable1[11];
+ _leftDelta = 0;
+ _rightDelta = 8;
+ _upDelta = 2;
+ _downDelta = -2;
+ _scrollConst = 2;
+
+ for (int i = 0; i < PLAYER_DATA_COUNT; ++i) {
+ _walkOffRight[i] = OVEROFFR[i];
+ _walkOffLeft[i] = OVEROFFL[i];
+ _walkOffUp[i] = OVEROFFU[i];
+ _walkOffDown[i] = OVEROFFD[i];
+ _walkOffUR[i].x = OVEROFFURX[i];
+ _walkOffUR[i].y = OVEROFFURY[i];
+ _walkOffDR[i].x = OVEROFFDRX[i];
+ _walkOffDR[i].y = OVEROFFDRY[i];
+ _walkOffUL[i].x = OVEROFFULX[i];
+ _walkOffUL[i].y = OVEROFFULY[i];
+ _walkOffDL[i].x = OVEROFFDLX[i];
+ _walkOffDL[i].y = OVEROFFDLY[i];
+ }
+
+ _vm->_timers[8]._initTm = 7;
+ _vm->_timers[8]._timer = 7;
+ ++_vm->_timers[8]._flag;
+
+ _sideWalkMin = 0;
+ _sideWalkMax = 5;
+ _upWalkMin = 12;
+ _upWalkMax = 17;
+ _downWalkMin = 6;
+ _downWalkMax = 11;
+ _diagUpWalkMin = 0;
+ _diagUpWalkMax = 5;
+ _diagDownWalkMin = 0;
+ _diagDownWalkMax = 5;
+ _game->_guard->setPosition(Common::Point(56, 190));
+ }
+}
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/amazon/amazon_player.h b/engines/access/amazon/amazon_player.h
new file mode 100644
index 0000000000..236b8bd1bd
--- /dev/null
+++ b/engines/access/amazon/amazon_player.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_AMAZON_PLAYER_H
+#define ACCESS_AMAZON_PLAYER_H
+
+#include "common/scummsys.h"
+#include "access/player.h"
+
+namespace Access {
+
+namespace Amazon {
+
+class AmazonEngine;
+
+class AmazonPlayer : public Player {
+private:
+ AmazonEngine *_game;
+public:
+ AmazonPlayer(AccessEngine *vm);
+
+ virtual void load();
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_AMAZON_PLAYER_H */
diff --git a/engines/access/amazon/amazon_resources.cpp b/engines/access/amazon/amazon_resources.cpp
new file mode 100644
index 0000000000..2010c7d842
--- /dev/null
+++ b/engines/access/amazon/amazon_resources.cpp
@@ -0,0 +1,2411 @@
+/* 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 "access/amazon/amazon_resources.h"
+#include "access/access.h"
+
+namespace Access {
+
+namespace Amazon {
+
+const char *const FILENAMES[] = {
+ "S00.AP", "S01.AP", "S02.AP", "R03.AP", "S04.AP", "S05.AP",
+ "S06.AP", "S07.AP", "S08.AP", "S09.AP", "S10.AP", "S11.AP",
+ "S12.AP", "S13.AP", "S14.AP", "S15.AP", "S16.AP", "S17.AP",
+ "S18.AP", "S19.AP", "S20.AP", "S21.AP", "S22.AP", "S23.AP",
+ "S24.AP", "S25.AP", "S26.AP", "S27.AP", "S28.AP", "S29.AP",
+ "S30.AP", "S31.AP", "S32.AP", "S33.AP", "S34.AP", "R35.AP",
+ "S36.AP", "S37.AP", "S38.AP", "S39.AP", "S40.AP", "C26.AP",
+ "S42.AP", "S01.AP", "S44.AP", "S45.AP", "S46.AP", "S47.AP",
+ "C36.AP", nullptr, "S50.AP", nullptr, nullptr, "S53.AP",
+ "S54.AP", "S55.AP", "C35.AP", "S57.AP", "S58.AP", nullptr,
+ nullptr, "S61.AP", nullptr, nullptr, "S64.AP", "C00.AP",
+ "C01.AP", "C06.AP", "C07.AP", "C08.AP", "C05.AP", "C09.AP",
+ "C12.AP", "C03.AP", "C13.AP", "C15.AP", "C14.AP", "C16.AP",
+ "C17.AP", "C19.AP", "C20.AP", "C21.AP", "C22.AP", "C23.AP",
+ "C24.AP", "C25.AP", "C29.AP", "C30.AP", "C32.AP", "C33.AP",
+ "C34.AP", "CREDITS.AP", "MIDIDRV.AP", "SUMMARY.AP", "DEAD.AP",
+ "EST.AP", "CHAPTER.AP", "MIDI.AP", "SOUND.AP", "INV.AP",
+ // The following files are only present in the CD version
+ "NARATE01.AP", "NARATE02.AP", "NARATE03.AP", "NARATE04.AP",
+ "NARATE05.AP", "NARATE06.AP", "NARATE07.AP", "NARATE08.AP",
+ "NARATE09.AP", "NARATE10.AP", "NARATE11.AP", "NARATE12.AP",
+ "NARATE13.AP", "NARATE14.AP", "S00.AP", "TAG.AP"
+};
+
+const char *const FILENAMES_DEMO[] = {
+ "S00.AP", "S01.AP", "S02.AP", "R03.AP", "S04.AP", "S05.AP",
+ "S06.AP", "S07.AP", "S08.AP", "S09.AP", "S10.AP", "S11.AP",
+ "S12.AP", "S13.AP", "S14.AP", "S15.AP", "S16.AP", "S17.AP",
+ "S18.AP", "S19.AP", "S20.AP", "S21.AP", "S22.AP", "S23.AP",
+ "S24.AP", "S25.AP", "S26.AP", "S27.AP", "S28.AP", "S29.AP",
+ "S30.AP", "S31.AP", "S32.AP", "S33.AP", "S34.AP", "R35.AP",
+ "S36.AP", "S37.AP", "S38.AP", "S39.AP", "S40.AP", "TITLE.AP",
+ "S42.AP", "S01.AP", "S44.AP", "S45.AP", "S46.AP", "S47.AP",
+ nullptr, nullptr, "S50.AP", nullptr, nullptr, "S53.AP",
+ "S54.AP", nullptr, nullptr, "S57.AP", nullptr, nullptr,
+ nullptr, "S61.AP", nullptr, "C23.AP", "C12.AP", "C00.AP",
+ "C01.AP", "C06.AP", "C07.AP", "C08.AP", "C05.AP", "C09.AP",
+ "C12.AP", "C03.AP", "C13.AP", "C15.AP", "C14.AP", "C16.AP",
+ "C17.AP", "C19.AP", "C20.AP", "C21.AP", "C22.AP", "C23.AP",
+ "C24.AP", "C25.AP", "R49.AP", "R49.AP", "R49.AP", "R49.AP",
+ "R49.AP", "R49.AP", "R49.AP", "R49.AP", "DEAD.AP", "EST.AP",
+ "CHAPTER.AP", "MUSIC.AP", "SOUND.AP", "INV.AP"
+};
+
+const byte MOUSE0[] = {
+ // hotspot x and y, uint16 LE
+ 0, 0, 0, 0,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0, 2, 6, 1,
+ 0, 3, 6, 6, 1,
+ 0, 3, 6, 6, 1,
+ 0, 4, 6, 6, 6, 1,
+ 0, 4, 6, 6, 6, 1,
+ 0, 5, 6, 6, 6, 6, 1,
+ 0, 5, 6, 6, 6, 6, 1,
+ 0, 6, 6, 6, 6, 6, 6, 1,
+ 0, 6, 6, 6, 6, 6, 6, 1,
+ 0, 7, 6, 6, 6, 6, 6, 6, 1,
+ 0, 6, 6, 6, 6, 6, 6, 1,
+ 0, 5, 6, 6, 6, 6, 1,
+ 2, 3, 6, 6, 1,
+ 3, 3, 6, 6, 1,
+ 3, 3, 6, 6, 1,
+ 4, 2, 6, 1
+};
+
+const byte MOUSE1[] = {
+ // hotspot x and y, uint16 LE
+ 0x07, 0x00, 0x07, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x06, 0x01, 0x05,
+ 0x04, 0x05, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
+ 0x03, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x02, 0x09, 0xFF, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xFF,
+ 0x01, 0x0B, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x01, 0x0B, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x00, 0x0D, 0x05, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x05,
+ 0x01, 0x0B, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x01, 0x0B, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x02, 0x09, 0xFF, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xFF,
+ 0x03, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x04, 0x05, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
+ 0x06, 0x01, 0x05,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+
+const byte MOUSE2[] = {
+ // hotspot x and y, uint16 LE
+ 0x08, 0x00, 0x08, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x02, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x07, 0x02, 0x04, 0x05,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+
+const byte MOUSE3[] = {
+ // hotspot x and y, uint16 LE
+ 0x00, 0x00, 0x00, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x00, 0x0B, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x0C, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x05, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x05, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x00, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
+ 0x01, 0x0B, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+const byte CURSEYE[] = {
+ // hotspot x and y, uint16 LE
+ 0x01, 0x00, 0x08, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x04, 0x06, 0x0E, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x03, 0x09, 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0D, 0x0D,
+ 0x02, 0x0B, 0x0E, 0x01, 0x33, 0x33, 0x01, 0x01, 0x33, 0x34, 0x01, 0x01, 0x0D,
+ 0x01, 0x0D, 0x0E, 0x01, 0x04, 0x34, 0x01, 0x01, 0x01, 0x07, 0x33, 0x04, 0x04, 0x01, 0x0D,
+ 0x00, 0x0F, 0x0E, 0x0E, 0x01, 0x07, 0x33, 0x33, 0x01, 0x01, 0x33, 0x34, 0x07, 0x07, 0x06, 0x01, 0x0E,
+ 0x01, 0x0D, 0x0F, 0x0F, 0x06, 0x07, 0x34, 0x33, 0x33, 0x34, 0x07, 0x07, 0x06, 0x0F, 0x0E,
+ 0x03, 0x09, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E,
+ 0x01, 0x01, 0x07,
+ 0x00, 0x03, 0x07, 0x01, 0x07,
+ 0x01, 0x01, 0x07,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+
+const byte CURSHAND[] = {
+ // hotspot x and y, uint16 LE
+ 0x02, 0x00, 0x03, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x07, 0x02, 0x17, 0x0E,
+ 0x05, 0x07, 0x0E, 0x12, 0x17, 0x0E, 0x13, 0x17, 0x0E,
+ 0x02, 0x0C, 0x07, 0x00, 0x17, 0x0E, 0x11, 0x0F, 0x0E, 0x11, 0x17, 0x0E, 0x00, 0x17,
+ 0x01, 0x0E, 0x07, 0x01, 0x07, 0x0F, 0x0E, 0x11, 0x17, 0x0E, 0x11, 0x0F, 0x0E, 0x12, 0x17, 0x0E,
+ 0x02, 0x0D, 0x07, 0x00, 0x17, 0x0F, 0x12, 0x0F, 0x0F, 0x11, 0x17, 0x0E, 0x12, 0x0F, 0x0E,
+ 0x04, 0x0B, 0x0F, 0x0E, 0x11, 0x17, 0x0E, 0x12, 0x0F, 0x0F, 0x11, 0x17, 0x0E,
+ 0x04, 0x0B, 0x17, 0x0E, 0x12, 0x17, 0x0E, 0x12, 0x17, 0x0E, 0x11, 0x0F, 0x0E,
+ 0x00, 0x0F, 0x0E, 0x0D, 0x12, 0x00, 0x17, 0x0F, 0x0F, 0x0F, 0x0F, 0x12, 0x0F, 0x0E, 0x12, 0x17, 0x0F,
+ 0x00, 0x0F, 0x0F, 0x17, 0x0D, 0x11, 0x0F, 0x0E, 0x0D, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E, 0x0D,
+ 0x01, 0x0E, 0x0F, 0x17, 0x0F, 0x0E, 0x0F, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0F, 0x0F, 0x0E, 0x0D,
+ 0x02, 0x0D, 0x0F, 0x17, 0x0F, 0x0E, 0x0D, 0x0D, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0E, 0x12,
+ 0x03, 0x0C, 0x0F, 0x17, 0x0F, 0x0F, 0x0F, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x0D, 0x12,
+ 0x04, 0x0A, 0x0F, 0x17, 0x0F, 0x0F, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0D,
+ 0x05, 0x09, 0x0F, 0x17, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E, 0x0D, 0x12,
+ 0x06, 0x08, 0x17, 0x0F, 0x0F, 0x0F, 0x0F, 0x0E, 0x0D, 0x12,
+ 0x06, 0x07, 0x17, 0x0F, 0x0F, 0x0F, 0x3D, 0x0E, 0x0D
+};
+
+const byte CURSGET[] = {
+ // hotspot x and y, uint16 LE
+ 0x07, 0x00, 0x0E, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x0A, 0x05, 0x1C, 0x07, 0x0F, 0x0F, 0x0F,
+ 0x08, 0x08, 0x1C, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x06, 0x0A, 0x1C, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x05, 0x0A, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x03, 0x0C, 0x07, 0x1C, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x02, 0x0D, 0x1C, 0x0F, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x01, 0x0E, 0x07, 0x0F, 0x0E, 0x0D, 0x0F, 0x0E, 0x0D, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x00, 0x0F, 0x1C, 0x0F, 0x0E, 0x0D, 0x0F, 0x0E, 0x0D, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x00, 0x0F, 0x1C, 0x0E, 0x0D, 0x0F, 0x0E, 0x0D, 0x0F, 0x0F, 0x0C, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0C,
+ 0x00, 0x0E, 0x1C, 0x0D, 0x0F, 0x0E, 0x0D, 0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x0E, 0x0F, 0x0F, 0x0C,
+ 0x00, 0x0E, 0x1C, 0x0E, 0x0F, 0x0D, 0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x0E, 0x1C, 0x0F, 0x0F, 0x0C,
+ 0x00, 0x0D, 0x1C, 0x0D, 0x0F, 0x0D, 0x0F, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x1C, 0x0F, 0x0C,
+ 0x01, 0x0B, 0x0E, 0x0F, 0x0E, 0x0F, 0x0C, 0x00, 0x00, 0x0E, 0x07, 0x0F, 0x0C,
+ 0x02, 0x09, 0x0E, 0x0D, 0x0F, 0x0C, 0x00, 0x07, 0x0E, 0x0F, 0x0C,
+ 0x03, 0x06, 0x0E, 0x0F, 0x0E, 0x07, 0x01, 0x07,
+ 0x07, 0x01, 0x07
+};
+
+const byte CURSCLIMB[] = {
+ // hotspot x and y, uint16 LE
+ 0x03, 0x00, 0x0E, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x06, 0x04, 0x01, 0x01, 0x01, 0x01,
+ 0x06, 0x04, 0x0F, 0x0E, 0x01, 0x01,
+ 0x06, 0x04, 0x0F, 0x0E, 0x0D, 0x01,
+ 0x07, 0x02, 0x0F, 0x0D,
+ 0x00, 0x0C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x13, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11,
+ 0x00, 0x0D, 0x0D, 0x0E, 0x00, 0x00, 0x13, 0x14, 0x13, 0x12, 0x12, 0x12, 0x11, 0x11, 0x0E,
+ 0x01, 0x0C, 0x0D, 0x0D, 0x0D, 0x0E, 0x11, 0x13, 0x13, 0x12, 0x11, 0x11, 0x0E, 0x0D,
+ 0x02, 0x0C, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x13, 0x12, 0x11, 0x00, 0x00, 0x0E, 0x0D,
+ 0x03, 0x0B, 0x04, 0x04, 0x04, 0x22, 0x21, 0x21, 0x20, 0x00, 0x00, 0x00, 0x0D,
+ 0x02, 0x0D, 0x22, 0x04, 0x20, 0x22, 0x04, 0x21, 0x04, 0x20, 0x00, 0x00, 0x00, 0x0E, 0x0E,
+ 0x03, 0x07, 0x22, 0x21, 0x20, 0x20, 0x22, 0x04, 0x20,
+ 0x04, 0x06, 0x01, 0x01, 0x00, 0x04, 0x22, 0x20,
+ 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x20,
+ 0x03, 0x09, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x22, 0x04, 0x20,
+ 0x02, 0x0B, 0x07, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20,
+ 0x03, 0x0A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01
+};
+
+const byte CURSTALK[] = {
+ // hotspot x and y, uint16 LE
+ 0x02, 0x00, 0x0B, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x03, 0x08, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x01, 0x0C, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06,
+ 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x06, 0x07, 0x07, 0x06, 0x07, 0x06,
+ 0x00, 0x0F, 0x06, 0x08, 0x08, 0x08, 0x06, 0x08, 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x06, 0x08, 0x06,
+ 0x00, 0x0F, 0x06, 0x06, 0x08, 0x06, 0x08, 0x06, 0x08, 0x06, 0x08, 0x06, 0x06, 0x08, 0x08, 0x06, 0x06,
+ 0x00, 0x0F, 0x06, 0x06, 0x08, 0x06, 0x08, 0x08, 0x08, 0x06, 0x08, 0x06, 0x06, 0x08, 0x06, 0x08, 0x06,
+ 0x01, 0x0E, 0x06, 0x08, 0x06, 0x08, 0x06, 0x08, 0x06, 0x08, 0x08, 0x06, 0x08, 0x06, 0x08, 0x06,
+ 0x02, 0x0C, 0x06, 0x06, 0x06, 0x07, 0x06, 0x07, 0x06, 0x06, 0x07, 0x06, 0x07, 0x06,
+ 0x04, 0x09, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06,
+ 0x07, 0x04, 0x06, 0x07, 0x07, 0x06,
+ 0x02, 0x08, 0x07, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x01, 0x06, 0x07, 0x01, 0x07, 0x06, 0x06, 0x06,
+ 0x02, 0x01, 0x07,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+const byte CURSHELP[] = {
+ // hotspot x and y, uint16 LE
+ 0x02, 0x00, 0x0B, 0x00,
+ // byte 1: number of skipped pixels
+ // byte 2: number of plotted pixels
+ // then, pixels
+ 0x04, 0x06, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+ 0x02, 0x0A, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x20, 0x20,
+ 0x01, 0x0C, 0x24, 0x22, 0x22, 0x22, 0x20, 0x20, 0x20, 0x22, 0x22, 0x22, 0x22, 0x20,
+ 0x00, 0x0E, 0x24, 0x22, 0x22, 0x22, 0x20, 0x00, 0x00, 0x00, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20,
+ 0x00, 0x0E, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20, 0x00, 0x00, 0x00, 0x24, 0x22, 0x22, 0x22, 0x20,
+ 0x00, 0x0E, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20, 0x00, 0x00, 0x00, 0x24, 0x22, 0x22, 0x22, 0x20,
+ 0x01, 0x0D, 0x24, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20,
+ 0x07, 0x06, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20,
+ 0x05, 0x07, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20, 0x20,
+ 0x04, 0x05, 0x24, 0x22, 0x22, 0x22, 0x20,
+ 0x02, 0x07, 0x07, 0x00, 0x24, 0x20, 0x20, 0x20, 0x20,
+ 0x01, 0x03, 0x07, 0x01, 0x07,
+ 0x02, 0x07, 0x07, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
+ 0x04, 0x06, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20,
+ 0x04, 0x06, 0x24, 0x22, 0x22, 0x22, 0x22, 0x20,
+ 0x05, 0x04, 0x20, 0x20, 0x20, 0x20
+};
+const byte *const CURSORS[10] = {
+ MOUSE0, MOUSE1, MOUSE2, MOUSE3, CURSEYE, CURSHAND, CURSGET, CURSCLIMB, CURSTALK, CURSHELP
+};
+
+const int TRAVEL_POS[][2] = {
+ { -1, 0 },
+ { 228, 117 },
+ { 28, 98 },
+ { 161, 140 },
+ { 130, 139 },
+ { 884, 95 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 41, 185 },
+ { 60, 138 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 170, 155 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 108, 95 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 100, 115 },
+ { 480, 90 },
+ { 154, 63 },
+ { 0, 0 },
+ { 145, 85 },
+ { 0, 0 },
+ { 110, 107 },
+ { 0, 0 },
+ { 105, 154 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 20, 160 },
+ { 130, 314 },
+ { 0, 0 },
+ { 50, 125 },
+ { 0, 0 },
+ { 0, 0 },
+ { 123, 123 },
+ { -1, 7 },
+ { 266, 168 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { -1, 18 },
+ { -1, 19 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 203, 160 },
+ { 0, 0 },
+ { 283, 163 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 180, 165 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+};
+
+const int OVEROFFR[] = { 2, 2, 1, 2, 2, 1, 0, 0, 0 };
+const int OVEROFFL[] = { 2, 2, 1, 2, 2, 1, 0, 0, 0 };
+const int OVEROFFU[] = { 1, 1, 1, 1, 1, 1, 0, 0, 0 };
+const int OVEROFFD[] = { 1, 1, 1, 1, 1, 1, 0, 0, 0 };
+const int OVEROFFURX[] = { 3, 1, 1, 2, 2, 1, 0, 0, 0 };
+const int OVEROFFURY[] = { 1, 0, 0, 1, 1, 0, 0, 0, 0 };
+const int OVEROFFDRX[] = { 1, 2, 1, 1, 2, 1, 0, 0, 0 };
+const int OVEROFFDRY[] = { 0, 1, 0, 0, 1, 1, 0, 0, 0 };
+const int OVEROFFULX[] = { 2, 1, 1, 1, 2, 1, 0, 0, 0 };
+const int OVEROFFULY[] = { 1, 0, 0, 2, 1, 0, 0, 0, 0 };
+const int OVEROFFDLX[] = { 1, 2, 1, 1, 2, 1, 0, 0, 0 };
+const int OVEROFFDLY[] = { 0, 1, 0, 0, 1, 1, 0, 0, 0 };
+
+const byte CREDITS[] = {
+ 0x2, 0xFF, 0xFF, 0x61, 0x0, 0x3, 0x0, 0x30, 0x22, 0x30, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0xFF,
+ 0x0, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ALLISTER[] = {
+ 0x0, 0xFF, 0xFF, 0x61, 0x0, 0x0, 0x0, 0x36, 0x0F, 0x5E, 0x4, 0x0, 0x0,
+ 0x0, 0x4, 0x4, 0x0, 0x3, 0x0, 0xFF, 0x4, 0x0, 0x2, 0x0, 0x4, 0x0, 0x1, 0x0, 0x8C,
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0, 0x0, 0x0,
+ 0x1, 0x0, 0x62, 0x0, 0x0B, 0x0, 0x1, 0x0, 0x62, 0x0, 0x0C, 0x0, 0x1, 0x0, 0x62,
+ 0x0, 0x0D, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte HALL[] = {
+ 0x0, 0xFF, 0xFF, 0x61, 0x0, 0x0, 0x0, 0x40, 0x3E, 0x1A, 0x5, 0x0, 0x0,
+ 0x0, 0x5, 0x5, 0x0, 0x3, 0x0, 0xFF, 0x5, 0x0, 0x2, 0x0, 0x5, 0x0, 0x1, 0x0, 0xFF,
+ 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0, 0x0,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x0D, 0x0, 0x1, 0x0, 0x62, 0x0, 0x13, 0x0, 0x1, 0x0,
+ 0x62, 0x0, 0x14, 0x0, 0x2, 0x0, 0x62, 0x0, 0x4, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte JASONLAB[] = {
+ 0x1, 0x6, 0x0, 0x61, 0x0, 0x0D, 0x0, 0x40, 0x20, 0x0C4, 0x6, 0x0, 0x0, 0x0,
+ 0x6, 0x6, 0x0, 0x3, 0x0, 0xFF, 0x6, 0x0, 0x2, 0x0, 0x6, 0x0, 0x1, 0x0, 0xFF, 0x0,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0, 0x0, 0x0, 0x1,
+ 0x0, 0x62, 0x0, 0x1, 0x0, 0x1, 0x0, 0x62, 0x0, 0x2, 0x0, 0x1, 0x0, 0x62, 0x0, 0x3,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x26, 0x0, 0x1, 0x0, 0x62, 0x0, 0x0D, 0x0, 0x1, 0x0,
+ 0x62, 0x0, 0x35, 0x0, 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte ALLENLAB[] = {
+ 0x1, 0x8, 0x0, 0x61, 0x0, 0x0D, 0x0, 0x40, 0x20, 0x0C4, 0x8, 0x0, 0x0, 0x0,
+ 0x8, 0x8, 0x0, 0x3, 0x0, 0xFF, 0x8, 0x0, 0x2, 0x0, 0x8, 0x0, 0x1, 0x0, 0xFF, 0x0,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0, 0x0, 0x0, 0x1,
+ 0x0, 0x62, 0x0, 0x7, 0x0, 0x1, 0x0, 0x62, 0x0, 0x8, 0x0, 0x2, 0x0, 0x62, 0x0, 0x9,
+ 0x0, 0x1, 0x0, 0x62, 0x0, 0x0A, 0x0, 0x1, 0x0, 0x62, 0x0, 0x0D, 0x0, 0x1, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte OUTVAULT[] = {
+ 0x0, 0x9, 0x0, 0x61, 0x0, 0x2B, 0x0, 0x30, 0x18, 0x9B, 0x9, 0x0, 0x0, 0x0,
+ 0x9, 0x9, 0x0, 0x3, 0x0, 0xFF, 0x9, 0x0, 0x2, 0x0, 0x9, 0x0, 0x1, 0x0, 0x0B4, 0x10,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0, 0x0, 0x0, 0x3,
+ 0x0, 0x62, 0x0, 0x4, 0x0, 0x1, 0x0, 0x62, 0x0, 0x5, 0x0, 0x2, 0x0, 0x62, 0x0, 0x6,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x36, 0x0, 0x1, 0x0, 0x62, 0x0, 0x47, 0x0, 0x1, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte VAULT[] = {
+ 0x0, 0xFF, 0xFF, 0x61, 0x0, 0x29, 0x0, 0x40, 0x3A, 0x37, 0x0A, 0x0,
+ 0x0, 0x0, 0x0A, 0x0A, 0x0, 0x3, 0x0, 0xFF, 0x0A, 0x0, 0x2, 0x0, 0x0A, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x37, 0x0, 0x2, 0x0, 0x62, 0x0, 0x39, 0x0,
+ 0x1, 0x0, 0x62, 0x0, 0x38, 0x0, 0x2, 0x0, 0x62, 0x0, 0x15, 0x0, 0x2, 0x0, 0xFF,
+ 0xFF
+};
+
+const byte LIBRARY[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x0C, 0x0, 0x40, 0x3A, 0x22, 0x0B, 0x0,
+ 0x0, 0x0, 0x0B, 0x0B, 0x0, 0x3, 0x0, 0xFF, 0x0B, 0x0, 0x2, 0x0, 0x0B, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x1, 0x0, 0x1, 0x0, 0xFF, 0xFF,
+};
+
+const byte JASAPT[] = {
+ 0x1, 0x0C, 0x0, 0x61, 0x0, 0x19, 0x0, 0x40, 0x30, 0x14, 0x0C, 0x0, 0x0,
+ 0x0, 0x0C, 0x0C, 0x0, 0x3, 0x0, 0xFF, 0x0C, 0x0, 0x2, 0x0, 0x0C, 0x0, 0x1,
+ 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x18, 0x0, 0x2, 0x0, 0x62, 0x0, 0x17, 0x0, 0x1, 0x0, 0x62, 0x0, 0x11,
+ 0x0, 0x1, 0x0, 0x62, 0x0, 0x0D, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte RANSACKED[] = {
+ 0x1, 0x0D, 0x0, 0x61, 0x0, 0x2D, 0x0, 0x40, 0x36, 0x2C, 0x0D, 0x0, 0x0,
+ 0x0, 0x0D, 0x0D, 0x0, 0x3, 0x0, 0xFF, 0x0D, 0x0, 0x2, 0x0, 0x0D, 0x0, 0x1,
+ 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x17, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte MEAN1[] = {
+ 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x3E, 0x33,
+ 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0x0E, 0x0, 0x5, 0x0, 0x0E, 0x0, 0x4, 0x0,
+ 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte FLYSOUTH[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x10, 0x0, 0x28, 0x0C, 0x5E, 0x0F, 0x0,
+ 0x0, 0x0, 0x0F, 0x0F, 0x0, 0x2, 0x0, 0xFF, 0x0F, 0x0, 0x1, 0x0, 0xFF, 0xFF,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x44, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte CUZCO[] = {
+ 0x2, 0x10, 0x0, 0x61, 0x0, 0x10, 0x0, 0x40, 0x20, 0x30, 0x10, 0x0, 0x0,
+ 0x0, 0x10, 0x10, 0x0, 0x3, 0x0, 0xFF, 0x10, 0x0, 0x2, 0x0, 0x10, 0x0, 0x1,
+ 0x0, 0x6E, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x2, 0x0, 0x62, 0x0, 0x44, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte INAIR[] = {
+ 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x19, 0x2B,
+ 0x11, 0x0, 0x0, 0x0, 0x11, 0x11, 0x0, 0x3, 0x0, 0xFF, 0x11, 0x0, 0x2, 0x0,
+ 0x11, 0x0, 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF
+};
+
+const byte GREENMONKEY[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x11, 0x0, 0x2D, 0x14, 0x3C, 0x12, 0x0,
+ 0x0, 0x0, 0x12, 0x12, 0x0, 0x3, 0x0, 0xFF, 0x12, 0x0, 0x2, 0x0, 0x12, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte INPLANE[] = {
+ 0x2, 0x13, 0x0, 0x61, 0x0, 0x26, 0x0, 0x2D, 0x28, 0x28, 0x13, 0x0, 0x0,
+ 0x0, 0x13, 0x13, 0x0, 0x3, 0x0, 0xFF, 0x13, 0x0, 0x2, 0x0, 0x13, 0x0, 0x1,
+ 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0, 0x0, 0x0,
+ 0x2, 0x0, 0x62, 0x0, 0x29, 0x0, 0x2, 0x0, 0x62, 0x0, 0x1F, 0x0, 0x1, 0x0,
+ 0x62, 0x0, 0x38, 0x0, 0x2, 0x0, 0x62, 0x0, 0x33, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte PILFALL[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x16, 0x0, 0x28, 0x0C, 0x5E, 0x14, 0x0,
+ 0x0, 0x0, 0x14, 0x14, 0x0, 0x2, 0x0, 0xFF, 0x14, 0x0, 0x1, 0x0, 0xFF, 0xFF,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x3A, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte COCKPIT[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x12, 0x0, 0x3C, 0x2A, 0x29, 0x15, 0x0,
+ 0x0, 0x0, 0x15, 0x15, 0x0, 0x3, 0x0, 0xFF, 0x15, 0x0, 0x2, 0x0, 0x15, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x23, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte CRASH[] = {
+ 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x2D, 0x64,
+ 0x16, 0x0, 0x0, 0x0, 0xFF, 0x16, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0x0, 0x0,
+ 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0x0, 0x2, 0x0, 0xFF,
+ 0xFF, 0x62, 0x0, 0x2A, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte SINKING[] = {
+ 0x2, 0xFF, 0xFF, 0x61, 0x0, 0x14, 0x0, 0x40, 0x3C, 0x19, 0x17, 0x0,
+ 0x0, 0x0, 0x17, 0x17, 0x0, 0x3, 0x0, 0xFF, 0x17, 0x0, 0x2, 0x0, 0x17, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x48, 0x0, 0x1, 0x0, 0x62, 0x0, 0x17, 0x0,
+ 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte JNGLWLK[] = {
+ 0x2, 0xFF, 0xFF, 0x61, 0x0, 0x17, 0x0, 0x40, 0x3F, 0x5A, 0x18, 0x0,
+ 0x0, 0x0, 0x18, 0x18, 0x0, 0x2, 0x0, 0xFF, 0x18, 0x0, 0x1, 0x0, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0DC, 0x0A0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x62, 0x0, 0x0, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte TOWN[] = {
+ 0x2, 0x19, 0x0, 0x61, 0x0, 0x18, 0x0, 0x3E, 0x32, 0x80, 0x19, 0x0, 0x0,
+ 0x0, 0x19, 0x19, 0x0, 0x3, 0x0, 0xFF, 0x19, 0x0, 0x2, 0x0, 0x19, 0x0, 0x1,
+ 0x0, 0x64, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x3D, 0x0, 0x1, 0x0, 0x62, 0x0, 0x3B, 0x0,
+ 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte HOTEL[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x19, 0x0, 0x34, 0x28, 0x28, 0x1A, 0x0,
+ 0x0, 0x0, 0x1A, 0x1A, 0x0, 0x3, 0x0, 0xFF, 0x1A, 0x0, 0x2, 0x0, 0x1A, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x28, 0x0, 0x1, 0x0, 0x62, 0x0, 0x2B, 0x0, 0x1, 0x0, 0x62, 0x0, 0x46,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x45, 0x0, 0x1, 0x0, 0x62, 0x0, 0x0E, 0x0, 0x1, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte CANTINA[] = {
+ 0x2, 0xFF, 0xFF, 0x61, 0x0, 0x27, 0x0, 0x40, 0x3A, 0x6C, 0x1B, 0x0,
+ 0x0, 0x0, 0x1B, 0x1B, 0x0, 0x3, 0x0, 0xFF, 0x1B, 0x0, 0x2, 0x0, 0x1B, 0x0,
+ 0x1, 0x0, 0x0C8, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte MASSACRE[] = {
+ 0x2, 0x1D, 0x0, 0x61, 0x0, 0x32, 0x0, 0x20, 0x18, 0x73, 0x1D, 0x0, 0x0,
+ 0x0, 0x1D, 0x1D, 0x0, 0x3, 0x0, 0xFF, 0x1D, 0x0, 0x2, 0x0, 0x1D, 0x0, 0x1,
+ 0x0, 0x96, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x0C, 0x0, 0x1, 0x0, 0x62, 0x0, 0x3, 0x0, 0x2,
+ 0x0, 0x62, 0x0, 0x49, 0x0, 0x2, 0x0, 0x62, 0x0, 0x4A, 0x0, 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte TRADE[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x18, 0x0, 0x3F, 0x1C, 0x27, 0x1E, 0x0,
+ 0x0, 0x0, 0x1E, 0x1E, 0x0, 0x3, 0x0, 0xFF, 0x1E, 0x0, 0x2, 0x0, 0x1E, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte BRIDGE[] = {
+ 0x2, 0x1F, 0x0, 0x61, 0x0, 0x1B, 0x0, 0x40, 0x3F, 0x78, 0x1F, 0x0, 0x0,
+ 0x0, 0x1F, 0x1F, 0x0, 0x3, 0x0, 0xFF, 0x1F, 0x0, 0x2, 0x0, 0x1F, 0x0, 0x1,
+ 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x2, 0x0, 0x62, 0x0, 0x1F, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte DOCK[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x1E, 0x0, 0x40, 0x3B, 0x4B, 0x20, 0x0,
+ 0x0, 0x0, 0xFF, 0x20, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0x0,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte DRIVER[] = {
+ 0x1, 0x21, 0x0, 0x61, 0x0, 0x28, 0x0, 0x30, 0x10, 0x51, 0x21, 0x0, 0x0,
+ 0x0, 0x21, 0x21, 0x0, 0x2, 0x0, 0xFF, 0x21, 0x0, 0x1, 0x0, 0xFF, 0xFF,
+ 0x0, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x2E, 0x0, 0x1, 0x0, 0x62, 0x0, 0x2F, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte SHORE[] = {
+ 0x2, 0x24, 0x0, 0x61, 0x0, 0x4, 0x0, 0x3E, 0x3A, 0x32, 0x24, 0x0, 0x0, 0x0,
+ 0x24, 0x24, 0x0, 0x3, 0x0, 0xFF, 0x24, 0x0, 0x2, 0x0, 0x24, 0x0, 0x1, 0x0,
+ 0x0B4, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0,
+ 0x2D, 0x0, 0x2, 0x0, 0x62, 0x0, 0x1F, 0x0, 0x1, 0x0, 0x62, 0x0, 0x2E, 0x0,
+ 0x1, 0x0, 0x62, 0x0, 0x2F, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte BOAT[] = {
+ 0x3, 0xFF, 0xFF, 0x61, 0x0, 0x8, 0x0, 0x3F, 0x3F, 0xFF, 0x25, 0x0,
+ 0x0, 0x0, 0x25, 0x25, 0x0, 0x3, 0x0, 0xFF, 0x25, 0x0, 0x2, 0x0, 0x25, 0x0,
+ 0x1, 0x0, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x62, 0x0, 0x0, 0x0, 0x2, 0x0, 0x62, 0x0, 0x21, 0x0, 0x1, 0x0, 0x62, 0x0, 0x25,
+ 0x0, 0x1, 0x0, 0x62, 0x0, 0x1F, 0x0, 0x1, 0x0, 0x62, 0x0, 0x30, 0x0, 0x1, 0x0,
+ 0x62, 0x0, 0x32, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte CABIN[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x8, 0x0, 0x40, 0x32, 0x50, 0x26, 0x0,
+ 0x0, 0x0, 0x26, 0x26, 0x0, 0x3, 0x0, 0xFF, 0x26, 0x0, 0x2, 0x0, 0x26, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x22, 0x0, 0x2, 0x0, 0x62, 0x0, 0x31, 0x0,
+ 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte CAPTIVE[] = {
+ 0x2, 0x27, 0x0, 0x61, 0x0, 0x9, 0x0, 0x40, 0x3F, 0x37, 0x27, 0x0, 0x0, 0x0,
+ 0x27, 0x27, 0x0, 0x3, 0x0, 0xFF, 0x27, 0x0, 0x2, 0x0, 0x27, 0x0, 0x1, 0x0,
+ 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x0,
+ 0x0, 0x0, 0x4, 0x0, 0x62, 0x0, 0x1B, 0x0, 0x3, 0x0, 0x62, 0x0, 0x1C, 0x0, 0x1,
+ 0x0, 0x62, 0x0, 0x1F, 0x0, 0x2, 0x0, 0x62, 0x0, 0x23, 0x0, 0x1, 0x0, 0x62,
+ 0x0, 0x32, 0x0, 0x1, 0x0, 0x62, 0x0, 0x33, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte VILLAGE[] = {
+ 0x2, 0x2A, 0x0, 0x61, 0x0, 0x2E, 0x0, 0x1E, 0x1B, 0x6E, 0x2A, 0x0, 0x0,
+ 0x0, 0x2A, 0x2A, 0x0, 0x3, 0x0, 0xFF, 0x2A, 0x0, 0x2, 0x0, 0x2A, 0x0, 0x1,
+ 0x0, 0x0A5, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x2D, 0x0, 0x3, 0x0, 0x62, 0x0, 0x3F, 0x0, 0x1, 0x0, 0x62, 0x0, 0x40,
+ 0x0, 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte TREE[] = {
+ 0x2, 0x2C, 0x0, 0x61, 0x0, 0x31, 0x0, 0x1E, 0x1D, 0x0BE, 0x2C, 0x0, 0x0,
+ 0x0, 0x2C, 0x2C, 0x0, 0x3, 0x0, 0xFF, 0x2C, 0x0, 0x2, 0x0, 0x2C, 0x0, 0x1,
+ 0x0, 0x50, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x2, 0x0, 0x62, 0x0, 0x2E, 0x0, 0x1, 0x0, 0x62, 0x0, 0x2F, 0x0,
+ 0x1, 0x0, 0x62, 0x0, 0x4, 0x0, 0x1, 0x0, 0x62, 0x0, 0x42, 0x0, 0x1, 0x0, 0xFF,
+ 0xFF
+};
+
+const byte CANOE[] = {
+ 0x1, 0x2D, 0x0, 0x61, 0x0, 0x2F, 0x0, 0x1E, 0x1D, 0x78, 0x2D, 0x0, 0x0,
+ 0x0, 0x2D, 0x2D, 0x0, 0x3, 0x0, 0xFF, 0x2D, 0x0, 0x2, 0x0, 0x2D, 0x0, 0x1,
+ 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x40, 0x0, 0x3, 0x0, 0x62, 0x0, 0x41, 0x0, 0x2, 0x0, 0x62, 0x0, 0x2E,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x2F, 0x0, 0x2, 0x0, 0x62, 0x0, 0x16, 0x0, 0x1, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte INTREE[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x33, 0x0, 0x28, 0x1E, 0x32, 0x2E, 0x0,
+ 0x0, 0x0, 0x2E, 0x2E, 0x0, 0x3, 0x0, 0xFF, 0x2E, 0x0, 0x2, 0x0, 0x2E, 0x0,
+ 0x1, 0x0, 0x0F0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte FALLS[] = {
+ 0x1, 0xFF, 0xFF, 0x61, 0x0, 0x3B, 0x0, 0x28, 0x1E, 0x32, 0x2F, 0x0,
+ 0x0, 0x0, 0x2F, 0x2F, 0x0, 0x3, 0x0, 0xFF, 0x2F, 0x0, 0x2, 0x0, 0x2F, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x4, 0x0, 0x1, 0x0, 0x62, 0x0, 0x2A, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte WATERFALL[] = {
+ 0x1, 0x36, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x1E, 0x6E, 0x36,
+ 0x0, 0x0, 0x0, 0x36, 0x36, 0x0, 0x3, 0x0, 0xFF, 0x36, 0x0, 0x2, 0x0, 0x36,
+ 0x0, 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x0, 0x4,
+ 0x0, 0xFF, 0xFF, 0x62, 0x0, 0x1F, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte INWATER[] = {
+ 0x2, 0xFF, 0xFF, 0x61, 0x0, 0x36, 0x0, 0x40, 0x3F, 0x2A, 0x37, 0x0,
+ 0x0, 0x0, 0x37, 0x37, 0x0, 0x3, 0x0, 0xFF, 0x37, 0x0, 0x2, 0x0, 0x37, 0x0,
+ 0x1, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x38, 0x0, 0x1, 0x0, 0xFF, 0xFF
+};
+
+const byte CAVE[] = {
+ 0x2, 0x39, 0x0, 0x61, 0x0, 0x37, 0x0, 0x32, 0x14, 0x73, 0x39, 0x0, 0x0,
+ 0x0, 0x39, 0x39, 0x0, 0x3, 0x0, 0xFF, 0x39, 0x0, 0x2, 0x0, 0x39, 0x0, 0x1,
+ 0x0, 0x0B4, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x0, 0x0, 0x0, 0x1, 0x0, 0x62, 0x0, 0x1F, 0x0, 0x1, 0x0, 0x62, 0x0, 0x4B, 0x0,
+ 0x2, 0x0, 0x62, 0x0, 0x4C, 0x0, 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte PIT[] = {
+ 0x2, 0xFF, 0xFF, 0x61, 0x0, 0x38, 0x0, 0x41, 0x3F, 0x19, 0x3D, 0x0,
+ 0x0, 0x0, 0x3D, 0x3D, 0x0, 0x3, 0x0, 0x3E, 0x3D, 0x0, 0x4, 0x0, 0xFF, 0x3D,
+ 0x0, 0x2, 0x0, 0x3D, 0x0, 0x1, 0x0, 0x0BE, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x62, 0x0, 0x0, 0x0, 0x2, 0x0, 0x62, 0x0, 0x27, 0x0, 0x1, 0x0,
+ 0x62, 0x0, 0x4D, 0x0, 0x2, 0x0, 0xFF, 0xFF, 0x0
+};
+
+const byte *const ROOM_TABLE[] = {
+ CREDITS, nullptr, nullptr, nullptr, ALLISTER, HALL, JASONLAB, nullptr,
+ ALLENLAB, OUTVAULT, VAULT, LIBRARY, JASAPT, RANSACKED, MEAN1, FLYSOUTH,
+ CUZCO, INAIR, GREENMONKEY, INPLANE, PILFALL, COCKPIT, CRASH, SINKING,
+ JNGLWLK, TOWN, HOTEL, CANTINA, nullptr, MASSACRE, TRADE, BRIDGE, DOCK,
+ DRIVER, nullptr, nullptr, SHORE, BOAT, CABIN, CAPTIVE, nullptr,
+ nullptr, VILLAGE, nullptr, TREE, CANOE, INTREE, FALLS, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, WATERFALL, INWATER, nullptr,
+ CAVE, nullptr, nullptr, nullptr, PIT, nullptr, nullptr
+};
+
+const char *const ROOM_DESCR[] = {
+ "Credits", nullptr, nullptr, nullptr, "Outside of Allister Center",
+ "Hall", "Jason's Lab", nullptr, "Allen's Lab", "Outside of the Vault",
+ "Inside the Vault", "Reader", "Jason's Apartment", "Jason's ransacked apartment", "Cutscene 1",
+ "TBD FLYSOUTH", "Cuzco Airport", "TBD INAIR", "Green Monkey Club", "In Plane",
+ "TBD PILFALL", "TBD COCKPIT", "TBD CRASH", "TBD SINKING", "Cutscene Jungle Walk",
+ "TBD TOWN", "TBD HOTEL", "TBD CANTINA", nullptr, "TBD MASSACRE",
+ "TBD TRADE", "TBD BRIDGE", "TBD DOCK", "TBD DRIVER", nullptr,
+ nullptr, "TBD SHORE", "TBD BOAT", "TBD CABIN", "TBD CAPTIVE",
+ nullptr, nullptr, "TBD VILLAGE", nullptr, "TBD TREE",
+ "TBD CANOE", "TBD INTREE", "TBD FALLS", nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, "TBD WATERFALL",
+ "TBD INWATER", nullptr, "Cave Bridge", nullptr, nullptr,
+ nullptr, "Pit with Ants", nullptr, nullptr
+};
+
+const byte ROOM_TABLE1_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x03, 0x00, 0x30, 0x22, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE5_DEMO[] = {
+ 0x00, 0x61, 0x00, 0x0E, 0x00, 0x36, 0x0F, 0x5E, 0x04, 0x00,
+ 0x00, 0x00, 0x04, 0x04, 0x00, 0x03, 0x00, 0xFF, 0x04, 0x00,
+ 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x8C, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x62, 0x00, 0x0C, 0x00,
+ 0x01, 0x00, 0x62, 0x00, 0x0D, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE6_DEMO[] = {
+ 0x00, 0x61, 0x00, 0x0E, 0x00, 0x40, 0x3E, 0x1A, 0x05, 0x00,
+ 0x00, 0x00, 0x05, 0x05, 0x00, 0x03, 0x00, 0xFF, 0x05, 0x00,
+ 0x02, 0x00, 0x05, 0x00, 0x01, 0x00, 0xFF, 0x30, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x62, 0x00, 0x12, 0x00, 0x03, 0x00, 0x62, 0x00, 0x13, 0x00,
+ 0x01, 0x00, 0x62, 0x00, 0x14, 0x00, 0x02, 0x00, 0x62, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE7_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x0D, 0x00, 0x40, 0x20, 0xC4, 0x06, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x03, 0x00, 0xFF, 0x06, 0x00,
+ 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x01, 0x00, 0x01, 0x00, 0x62, 0x00, 0x02, 0x00,
+ 0x01, 0x00, 0x62, 0x00, 0x03, 0x00, 0x02, 0x00, 0x62, 0x00,
+ 0x26, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE9_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x0D, 0x00, 0x40, 0x20, 0xC4, 0x08, 0x00,
+ 0x00, 0x00, 0x08, 0x08, 0x00, 0x03, 0x00, 0xFF, 0x08, 0x00,
+ 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x07, 0x00, 0x01, 0x00, 0x62, 0x00, 0x08, 0x00,
+ 0x02, 0x00, 0x62, 0x00, 0x09, 0x00, 0x01, 0x00, 0x62, 0x00,
+ 0x0A, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE10_DEMO[] = {
+ 0x00, 0x61, 0x00, 0x0E, 0x00, 0x30, 0x18, 0x9B, 0x09, 0x00,
+ 0x00, 0x00, 0x09, 0x09, 0x00, 0x03, 0x00, 0xFF, 0x09, 0x00,
+ 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0xB4, 0x10, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x62, 0x00, 0x04, 0x00, 0x01, 0x00, 0x62, 0x00, 0x05, 0x00,
+ 0x02, 0x00, 0x62, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE11_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x0E, 0x00, 0x40, 0x30, 0x14, 0x0A, 0x00,
+ 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x03, 0x00, 0xFF, 0x0A, 0x00,
+ 0x02, 0x00, 0x0A, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x15, 0x00, 0x01, 0x00, 0x62, 0x00, 0x16, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE12_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x0E, 0x00, 0x40, 0x3A, 0x22, 0x0B, 0x00,
+ 0x00, 0x00, 0x0B, 0x0B, 0x00, 0x03, 0x00, 0xFF, 0x0B, 0x00,
+ 0x02, 0x00, 0x0B, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE13_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x08, 0x00, 0x40, 0x30, 0x14, 0x0C, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x03, 0x00, 0xFF, 0x0C, 0x00,
+ 0x02, 0x00, 0x0C, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x18, 0x00, 0x02, 0x00,
+ 0x62, 0x00, 0x17, 0x00, 0x01, 0x00, 0x62, 0x00, 0x11, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE14_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x0D, 0x00, 0x40, 0x36, 0x2C, 0x0D, 0x00,
+ 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x03, 0x00, 0xFF, 0x0D, 0x00,
+ 0x02, 0x00, 0x0D, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE15_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x3E, 0x33, 0xFF, 0xFF,
+ 0x00, 0x00, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x04,
+ 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF
+};
+
+const byte ROOM_TABLE16_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x10, 0x00, 0x28, 0x0C, 0x5E, 0x0F, 0x00,
+ 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x02, 0x00, 0xFF, 0x0F, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE17_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x10, 0x00, 0x40, 0x20, 0x30, 0x10, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x00, 0x03, 0x00, 0xFF, 0x10, 0x00,
+ 0x02, 0x00, 0x10, 0x00, 0x01, 0x00, 0x6E, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE18_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x19, 0x2B, 0x11, 0x00,
+ 0x00, 0x00, 0x11, 0x11, 0x00, 0x03, 0x00, 0xFF, 0x11, 0x00,
+ 0x02, 0x00, 0x11, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE19_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x11, 0x00, 0x2D, 0x14, 0x3C, 0x12, 0x00,
+ 0x00, 0x00, 0x12, 0x12, 0x00, 0x03, 0x00, 0xFF, 0x12, 0x00,
+ 0x02, 0x00, 0x12, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE20_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x12, 0x00, 0x2D, 0x28, 0x28, 0x13, 0x00,
+ 0x00, 0x00, 0x13, 0x13, 0x00, 0x03, 0x00, 0xFF, 0x13, 0x00,
+ 0x02, 0x00, 0x13, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x62, 0x00, 0x29, 0x00, 0x01, 0x00, 0x62, 0x00, 0x24, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE21_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x16, 0x00, 0x28, 0x0C, 0x5E, 0x14, 0x00,
+ 0x00, 0x00, 0x14, 0x14, 0x00, 0x02, 0x00, 0xFF, 0x14, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE22_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x12, 0x00, 0x3C, 0x2A, 0x29, 0x15, 0x00,
+ 0x00, 0x00, 0x15, 0x15, 0x00, 0x03, 0x00, 0xFF, 0x15, 0x00,
+ 0x02, 0x00, 0x15, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x23, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE23_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x13, 0x00, 0x40, 0x2D, 0x64, 0x16, 0x00,
+ 0x00, 0x00, 0xFF, 0x16, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x02,
+ 0x00, 0xFF, 0xFF, 0x62, 0x00, 0x2A, 0x00, 0x01, 0x00, 0xFF,
+ 0xFF
+};
+
+const byte ROOM_TABLE24_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x14, 0x00, 0x40, 0x3C, 0x19, 0x17, 0x00,
+ 0x00, 0x00, 0x17, 0x17, 0x00, 0x03, 0x00, 0xFF, 0x17, 0x00,
+ 0x02, 0x00, 0x17, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE25_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x3F, 0x5A, 0x18, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x00, 0xFF, 0x18, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xDC, 0xA0, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE26_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x17, 0x00, 0x3E, 0x32, 0x80, 0x19, 0x00,
+ 0x00, 0x00, 0x19, 0x19, 0x00, 0x03, 0x00, 0xFF, 0x19, 0x00,
+ 0x02, 0x00, 0x19, 0x00, 0x01, 0x00, 0x64, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE27_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x19, 0x00, 0x34, 0x28, 0x28, 0x1A, 0x00,
+ 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x03, 0x00, 0xFF, 0x1A, 0x00,
+ 0x02, 0x00, 0x1A, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x28, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x2B, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE28_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x18, 0x00, 0x40, 0x3A, 0x6C, 0x1B, 0x00,
+ 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x03, 0x00, 0xFF, 0x1B, 0x00,
+ 0x02, 0x00, 0x1B, 0x00, 0x01, 0x00, 0xC8, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE30_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x18, 0x73, 0x1D, 0x00,
+ 0x00, 0x00, 0x1D, 0x1D, 0x00, 0x03, 0x00, 0xFF, 0x1D, 0x00,
+ 0x02, 0x00, 0x1D, 0x00, 0x01, 0x00, 0x80, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE31_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1C, 0x27, 0x1E, 0x00,
+ 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x03, 0x00, 0xFF, 0x1E, 0x00,
+ 0x02, 0x00, 0x1E, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE32_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x1B, 0x00, 0x40, 0x10, 0x78, 0x1F, 0x00,
+ 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0x00, 0xFF, 0x1F, 0x00,
+ 0x02, 0x00, 0x1F, 0x00, 0x01, 0x00, 0xFE, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x62, 0x00, 0x1F, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE33_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x1E, 0x00, 0x40, 0x3B, 0x4B, 0x20, 0x00,
+ 0x00, 0x00, 0x20, 0x20, 0x00, 0x03, 0x00, 0xFF, 0x20, 0x00,
+ 0x02, 0x00, 0x20, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE34_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x04, 0x00, 0x30, 0x10, 0x51, 0x21, 0x00,
+ 0x00, 0x00, 0x21, 0x21, 0x00, 0x02, 0x00, 0xFF, 0x21, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x2E, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x2F, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE37_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x04, 0x00, 0x3E, 0x3A, 0x32, 0x24, 0x00,
+ 0x00, 0x00, 0x24, 0x24, 0x00, 0x03, 0x00, 0xFF, 0x24, 0x00,
+ 0x02, 0x00, 0x24, 0x00, 0x01, 0x00, 0xB4, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x2D, 0x00, 0x02, 0x00,
+ 0x62, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x62, 0x00, 0x2E, 0x00,
+ 0x01, 0x00, 0x62, 0x00, 0x2F, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE38_DEMO[] = {
+ 0x03, 0x61, 0x00, 0x08, 0x00, 0x3F, 0x3F, 0xFF, 0x25, 0x00,
+ 0x00, 0x00, 0x25, 0x25, 0x00, 0x03, 0x00, 0xFF, 0x25, 0x00,
+ 0x02, 0x00, 0x25, 0x00, 0x01, 0x00, 0xFF, 0x40, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x62, 0x00, 0x21, 0x00, 0x01, 0x00, 0x62, 0x00, 0x25, 0x00,
+ 0x01, 0x00, 0x62, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x62, 0x00,
+ 0x30, 0x00, 0x01, 0x00, 0x62, 0x00, 0x32, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE39_DEMO[] = {
+ 0x01, 0x61, 0x00, 0x08, 0x00, 0x40, 0x32, 0x50, 0x26, 0x00,
+ 0x00, 0x00, 0x26, 0x26, 0x00, 0x03, 0x00, 0xFF, 0x26, 0x00,
+ 0x02, 0x00, 0x26, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x62, 0x00, 0x22, 0x00, 0x02, 0x00, 0x62, 0x00, 0x31, 0x00,
+ 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE40_DEMO[] = {
+ 0x02, 0x61, 0x00, 0x09, 0x00, 0x40, 0x3F, 0x37, 0x27, 0x00,
+ 0x00, 0x00, 0x27, 0x27, 0x00, 0x03, 0x00, 0xFF, 0x27, 0x00,
+ 0x02, 0x00, 0x27, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x62, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x62, 0x00, 0x1C, 0x00,
+ 0x01, 0x00, 0x62, 0x00, 0x1F, 0x00, 0x02, 0x00, 0x62, 0x00,
+ 0x23, 0x00, 0x01, 0x00, 0x62, 0x00, 0x32, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE43_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x1B, 0x6E, 0x2A, 0x00,
+ 0x00, 0x00, 0x2A, 0x2A, 0x00, 0x03, 0x00, 0xFF, 0x2A, 0x00,
+ 0x02, 0x00, 0x2A, 0x00, 0x01, 0x00, 0xA5, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE45_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x1D, 0xBE, 0x2C, 0x00,
+ 0x00, 0x00, 0x2C, 0x2C, 0x00, 0x03, 0x00, 0xFF, 0x2C, 0x00,
+ 0x02, 0x00, 0x2C, 0x00, 0x01, 0x00, 0x50, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE46_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x1D, 0x78, 0x2D, 0x00,
+ 0x00, 0x00, 0x2D, 0x2D, 0x00, 0x03, 0x00, 0xFF, 0x2D, 0x00,
+ 0x02, 0x00, 0x2D, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE47_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x1E, 0x32, 0x2E, 0x00,
+ 0x00, 0x00, 0x2E, 0x2E, 0x00, 0x03, 0x00, 0xFF, 0x2E, 0x00,
+ 0x02, 0x00, 0x2E, 0x00, 0x01, 0x00, 0xF0, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE48_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x1E, 0x32, 0x2F, 0x00,
+ 0x00, 0x00, 0x2F, 0x2F, 0x00, 0x03, 0x00, 0xFF, 0x2F, 0x00,
+ 0x02, 0x00, 0x2F, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE51_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x1E, 0x32, 0xFF, 0xFF,
+ 0x00, 0x00, 0xFF, 0x32, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x04,
+ 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x32,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE55_DEMO[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x1E, 0x6E, 0x36, 0x00,
+ 0x00, 0x00, 0x36, 0x36, 0x00, 0x03, 0x00, 0xFF, 0x36, 0x00,
+ 0x02, 0x00, 0x36, 0x00, 0x01, 0x00, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x36, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE58_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x14, 0x73, 0x39, 0x00,
+ 0x00, 0x00, 0x39, 0x39, 0x00, 0x03, 0x00, 0xFF, 0x39, 0x00,
+ 0x02, 0x00, 0x39, 0x00, 0x01, 0x00, 0xB4, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte ROOM_TABLE62_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x3F, 0x19, 0x3D, 0x00,
+ 0x00, 0x00, 0x3D, 0x3D, 0x00, 0x03, 0x00, 0x3E, 0x3D, 0x00,
+ 0x04, 0x00, 0xFF, 0x3D, 0x00, 0x02, 0x00, 0x3D, 0x00, 0x01,
+ 0x00, 0xBE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00
+};
+
+const byte *const ROOM_TABLE_DEMO[] = {
+ ROOM_TABLE1_DEMO, nullptr, nullptr, nullptr, ROOM_TABLE5_DEMO,
+ ROOM_TABLE6_DEMO, ROOM_TABLE7_DEMO, nullptr, ROOM_TABLE9_DEMO, ROOM_TABLE10_DEMO,
+ ROOM_TABLE11_DEMO, ROOM_TABLE12_DEMO, ROOM_TABLE13_DEMO, ROOM_TABLE14_DEMO, ROOM_TABLE15_DEMO,
+ ROOM_TABLE16_DEMO, ROOM_TABLE17_DEMO, ROOM_TABLE18_DEMO, ROOM_TABLE19_DEMO, ROOM_TABLE20_DEMO,
+ ROOM_TABLE21_DEMO, ROOM_TABLE22_DEMO, ROOM_TABLE23_DEMO, ROOM_TABLE24_DEMO, ROOM_TABLE25_DEMO,
+ ROOM_TABLE26_DEMO, ROOM_TABLE27_DEMO, ROOM_TABLE28_DEMO, nullptr, ROOM_TABLE30_DEMO,
+ ROOM_TABLE31_DEMO, ROOM_TABLE32_DEMO, ROOM_TABLE33_DEMO, ROOM_TABLE34_DEMO, nullptr,
+ nullptr, ROOM_TABLE37_DEMO, ROOM_TABLE38_DEMO, ROOM_TABLE39_DEMO, ROOM_TABLE40_DEMO,
+ nullptr, nullptr, ROOM_TABLE43_DEMO, nullptr, ROOM_TABLE45_DEMO,
+ ROOM_TABLE46_DEMO, ROOM_TABLE47_DEMO, ROOM_TABLE48_DEMO, nullptr, nullptr,
+ ROOM_TABLE51_DEMO, nullptr, nullptr, nullptr, ROOM_TABLE55_DEMO,
+ nullptr, nullptr, ROOM_TABLE58_DEMO, nullptr, nullptr,
+ nullptr, ROOM_TABLE62_DEMO, nullptr, nullptr
+};
+
+const int ROOM_NUMB = 63;
+
+const byte ELAINE[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x41, 0x41, 0x0, 0x1, 0x0, 0xFF, 0x41, 0x0, 0x2,
+ 0x0, 0x41, 0x0, 0x0, 0x0, 0x41, 0x0, 0x3, 0x0, 0x41, 0x0, 0x25, 0x0, 0x41,
+ 0x0, 0x4, 0x0, 0x41, 0x0, 0x26, 0x0, 0x41, 0x0, 0x5, 0x0, 0x41, 0x0, 0x27,
+ 0x0, 0x41, 0x0, 0x6, 0x0, 0x41, 0x0, 0x28, 0x0, 0x41, 0x0, 0x7, 0x0, 0x41,
+ 0x0, 0x29, 0x0, 0x41, 0x0, 0x8, 0x0, 0x41, 0x0, 0x2A, 0x0, 0x41, 0x0, 0x9,
+ 0x0, 0x41, 0x0, 0x2B, 0x0, 0x41, 0x0, 0x0A, 0x0, 0x41, 0x0, 0x2C, 0x0, 0x41,
+ 0x0, 0x0B, 0x0, 0x41, 0x0, 0x2D, 0x0, 0x41, 0x0, 0x0C, 0x0, 0x41, 0x0, 0x2E,
+ 0x0, 0x41, 0x0, 0x0D, 0x0, 0x41, 0x0, 0x2F, 0x0, 0x41, 0x0, 0x0E, 0x0, 0x41,
+ 0x0, 0x30, 0x0, 0x41, 0x0, 0x0F, 0x0, 0x41, 0x0, 0x31, 0x0, 0x41, 0x0, 0x10,
+ 0x0, 0x41, 0x0, 0x32, 0x0, 0x41, 0x0, 0x11, 0x0, 0x41, 0x0, 0x33, 0x0, 0x41,
+ 0x0, 0x12, 0x0, 0x41, 0x0, 0x34, 0x0, 0x41, 0x0, 0x13, 0x0, 0x41, 0x0, 0x35,
+ 0x0, 0x41, 0x0, 0x14, 0x0, 0x41, 0x0, 0x36, 0x0, 0x41, 0x0, 0x15, 0x0, 0x41,
+ 0x0, 0x37, 0x0, 0x41, 0x0, 0x16, 0x0, 0x41, 0x0, 0x38, 0x0, 0x41, 0x0, 0x17,
+ 0x0, 0x41, 0x0, 0x39, 0x0, 0x41, 0x0, 0x18, 0x0, 0x41, 0x0, 0x3A, 0x0, 0x41,
+ 0x0, 0x19, 0x0, 0x41, 0x0, 0x3B, 0x0, 0x41, 0x0, 0x1A, 0x0, 0x41, 0x0, 0x3C,
+ 0x0, 0x41, 0x0, 0x1B, 0x0, 0x41, 0x0, 0x3D, 0x0, 0x41, 0x0, 0x1C, 0x0, 0x41,
+ 0x0, 0x3E, 0x0, 0x41, 0x0, 0x1D, 0x0, 0x41, 0x0, 0x3F, 0x0, 0x41, 0x0, 0x1E,
+ 0x0, 0x41, 0x0, 0x40, 0x0, 0x41, 0x0, 0x1F, 0x0, 0x41, 0x0, 0x41, 0x0, 0x41,
+ 0x0, 0x20, 0x0, 0x41, 0x0, 0x42, 0x0, 0x41, 0x0, 0x21, 0x0, 0x41, 0x0, 0x43,
+ 0x0, 0x41, 0x0, 0x22, 0x0, 0x41, 0x0, 0x44, 0x0, 0x41, 0x0, 0x23, 0x0, 0x41,
+ 0x0, 0x45, 0x0, 0x41, 0x0, 0x24, 0x0, 0x41, 0x0, 0x46, 0x0, 0xFF, 0xFF
+};
+
+const byte LIB[] = {
+ 0x1, 0xFF, 0xFF, 0x42, 0x0, 0x2, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x42, 0x42, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x2,
+ 0x0, 0x42, 0x0, 0x0, 0x0, 0x42, 0x0, 0x3, 0x0, 0x42, 0x0, 0x18, 0x0, 0x42,
+ 0x0, 0x4, 0x0, 0x42, 0x0, 0x19, 0x0, 0x42, 0x0, 0x5, 0x0, 0x42, 0x0, 0x1A,
+ 0x0, 0x42, 0x0, 0x6, 0x0, 0x42, 0x0, 0x1B, 0x0, 0x42, 0x0, 0x7, 0x0, 0x42,
+ 0x0, 0x1C, 0x0, 0x42, 0x0, 0x8, 0x0, 0x42, 0x0, 0x1D, 0x0, 0x42, 0x0, 0x9,
+ 0x0, 0x42, 0x0, 0x1E, 0x0, 0x42, 0x0, 0x0A, 0x0, 0x42, 0x0, 0x1F, 0x0, 0x42,
+ 0x0, 0x0B, 0x0, 0x42, 0x0, 0x20, 0x0, 0x42, 0x0, 0x0C, 0x0, 0x42, 0x0, 0x21,
+ 0x0, 0x42, 0x0, 0x0D, 0x0, 0x42, 0x0, 0x22, 0x0, 0x42, 0x0, 0x0E, 0x0, 0x42,
+ 0x0, 0x23, 0x0, 0x42, 0x0, 0x0F, 0x0, 0x42, 0x0, 0x24, 0x0, 0x42, 0x0, 0x10,
+ 0x0, 0x42, 0x0, 0x25, 0x0, 0x42, 0x0, 0x11, 0x0, 0x42, 0x0, 0x26, 0x0, 0x42,
+ 0x0, 0x12, 0x0, 0x42, 0x0, 0x27, 0x0, 0x42, 0x0, 0x13, 0x0, 0x42, 0x0, 0x28,
+ 0x0, 0x42, 0x0, 0x14, 0x0, 0x42, 0x0, 0x29, 0x0, 0x42, 0x0, 0x15, 0x0, 0x42,
+ 0x0, 0x2A, 0x0, 0x42, 0x0, 0x16, 0x0, 0x42, 0x0, 0x2B, 0x0, 0x42, 0x0, 0x17,
+ 0x0, 0x42, 0x0, 0x2C, 0x0, 0xFF, 0xFF
+};
+
+const byte FLASHBACK[] = {
+ 0x2, 0x1B, 0x0, 0x1C, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x26, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1C,
+ 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0E, 0x0, 0x1C, 0x0, 0x6, 0x0, 0x1C, 0x0, 0x0F,
+ 0x0, 0x1C, 0x0, 0x7, 0x0, 0x1C, 0x0, 0x0C, 0x0, 0x1C, 0x0, 0x8, 0x0, 0x1C,
+ 0x0, 0x0D, 0x0, 0x2, 0x0, 0x1, 0x0, 0x1C, 0x0, 0x10, 0x0, 0x2, 0x0, 0x2, 0x0, 0x1C,
+ 0x0, 0x11, 0x0, 0x1C, 0x0, 0x9, 0x0, 0x1C, 0x0, 0x12, 0x0, 0x1C, 0x0, 0x0A,
+ 0x0, 0x1C, 0x0, 0x13, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x14, 0x0, 0x1C,
+ 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x15, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x16,
+ 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x17, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C,
+ 0x0, 0x18, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x19, 0x0, 0x1C, 0x0, 0x0B,
+ 0x0, 0x1C, 0x0, 0x1A, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x1B, 0x0, 0x1C,
+ 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x1C, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x1D,
+ 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x1E, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C,
+ 0x0, 0x1F, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x20, 0x0, 0x1C, 0x0, 0x0B,
+ 0x0, 0x1C, 0x0, 0x21, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x22, 0x0, 0x1C,
+ 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x23, 0x0, 0x1C, 0x0, 0x0B, 0x0, 0x1C, 0x0, 0x24,
+ 0x0, 0xFF, 0xFF
+};
+
+const byte ALLENDIE[] = {
+ 0x2, 0xFF, 0xFF, 0x49, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x49,
+ 0x0, 0x4, 0x0, 0x62, 0x0, 0x1F, 0x0, 0x49, 0x0, 0x5, 0x0, 0x62, 0x0, 0x3A,
+ 0x0, 0x49, 0x0, 0x6, 0x0, 0x49, 0x0, 0x7, 0x0, 0xFF, 0xFF
+};
+
+const byte OVERBOARD[] = {
+ 0x2, 0xFF, 0xFF, 0x22, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x0, 0x2, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x22, 0x0, 0x0, 0x0, 0x22, 0x0, 0x3, 0x0, 0x22, 0x0, 0x6, 0x0, 0x22,
+ 0x0, 0x4, 0x0, 0x22, 0x0, 0x7, 0x0, 0x22, 0x0, 0x5, 0x0, 0x62, 0x0, 0x1D, 0x0,
+ 0x22, 0x0, 0x5, 0x0, 0x62, 0x0, 0x24, 0x0, 0xFF, 0xFF
+};
+
+const byte PILOT2[] = {
+ 0x0, 0x12, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x46, 0x46, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x46, 0x0, 0x0, 0x0, 0x46, 0x0, 0x2, 0x0, 0x46, 0x0, 0x0A, 0x0, 0x46,
+ 0x0, 0x3, 0x0, 0x46, 0x0, 0x0B, 0x0, 0x46, 0x0, 0x4, 0x0, 0x46, 0x0, 0x0C,
+ 0x0, 0x46, 0x0, 0x5, 0x0, 0x46, 0x0, 0x0D, 0x0, 0x46, 0x0, 0x6, 0x0, 0x46,
+ 0x0, 0x0E, 0x0, 0x46, 0x0, 0x7, 0x0, 0x46, 0x0, 0x0F, 0x0, 0x46, 0x0, 0x8,
+ 0x0, 0x46, 0x0, 0x10, 0x0, 0x46, 0x0, 0x9, 0x0, 0x46, 0x0, 0x11, 0x0, 0x46,
+ 0x0, 0x9, 0x0, 0x62, 0x0, 0x1F, 0x0, 0xFF, 0xFF
+};
+
+const byte TIKAGENT[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x43, 0x43, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x2,
+ 0x0, 0x43, 0x0, 0x0, 0x0, 0x43, 0x0, 0x2, 0x0, 0x43, 0x0, 0x12, 0x0, 0x43,
+ 0x0, 0x3, 0x0, 0x43, 0x0, 0x13, 0x0, 0x43, 0x0, 0x4, 0x0, 0x43, 0x0, 0x14,
+ 0x0, 0x43, 0x0, 0x5, 0x0, 0x43, 0x0, 0x15, 0x0, 0x43, 0x0, 0x6, 0x0, 0x43,
+ 0x0, 0x16, 0x0, 0x43, 0x0, 0x7, 0x0, 0x43, 0x0, 0x17, 0x0, 0x43, 0x0, 0x8,
+ 0x0, 0x43, 0x0, 0x18, 0x0, 0x43, 0x0, 0x9, 0x0, 0x43, 0x0, 0x19, 0x0, 0x43,
+ 0x0, 0x0A, 0x0, 0x43, 0x0, 0x1A, 0x0, 0x43, 0x0, 0x0B, 0x0, 0x43, 0x0, 0x1B,
+ 0x0, 0x43, 0x0, 0x0C, 0x0, 0x43, 0x0, 0x1C, 0x0, 0x43, 0x0, 0x0D, 0x0, 0x43,
+ 0x0, 0x1D, 0x0, 0x43, 0x0, 0x0E, 0x0, 0x43, 0x0, 0x1E, 0x0, 0x43, 0x0, 0x0F,
+ 0x0, 0x43, 0x0, 0x1F, 0x0, 0x43, 0x0, 0x10, 0x0, 0x43, 0x0, 0x20, 0x0, 0x43,
+ 0x0, 0x11, 0x0, 0x43, 0x0, 0x21, 0x0, 0xFF, 0xFF
+};
+
+const byte BARTENDER[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x44, 0x44, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x44, 0x0, 0x0, 0x0, 0x44, 0x0, 0x2, 0x0, 0x44, 0x0, 0x8, 0x0, 0x44, 0x0,
+ 0x3, 0x0, 0x44, 0x0, 0x9, 0x0, 0x44, 0x0, 0x4, 0x0, 0x44, 0x0, 0x0A, 0x0, 0x44,
+ 0x0, 0x5, 0x0, 0x44, 0x0, 0x0B, 0x0, 0x44, 0x0, 0x6, 0x0, 0x44, 0x0, 0x0C,
+ 0x0, 0x44, 0x0, 0x7, 0x0, 0x44, 0x0, 0x0D, 0x0, 0xFF, 0xFF
+};
+
+const byte PILOT1[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x45, 0x45, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x45, 0x0, 0x0, 0x0, 0x45, 0x0, 0x2, 0x0, 0x45, 0x0, 0x3, 0x0, 0xFF, 0xFF
+};
+
+const byte COOK[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x47, 0x47, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF,
+ 0x2, 0x0, 0x47, 0x0, 0x0, 0x0, 0x47, 0x0, 0x2, 0x0, 0x47, 0x0, 0x10, 0x0, 0x47,
+ 0x0, 0x3, 0x0, 0x47, 0x0, 0x11, 0x0, 0x47, 0x0, 0x4, 0x0, 0x47, 0x0, 0x12,
+ 0x0, 0x47, 0x0, 0x5, 0x0, 0x47, 0x0, 0x13, 0x0, 0x47, 0x0, 0x6, 0x0, 0x47,
+ 0x0, 0x14, 0x0, 0x47, 0x0, 0x7, 0x0, 0x47, 0x0, 0x15, 0x0, 0x47, 0x0, 0x8,
+ 0x0, 0x47, 0x0, 0x16, 0x0, 0x47, 0x0, 0x9, 0x0, 0x47, 0x0, 0x17, 0x0, 0x47,
+ 0x0, 0x0A, 0x0, 0x47, 0x0, 0x18, 0x0, 0x47, 0x0, 0x0B, 0x0, 0x47, 0x0, 0x19,
+ 0x0, 0x47, 0x0, 0x0C, 0x0, 0x47, 0x0, 0x1A, 0x0, 0x47, 0x0, 0x0D, 0x0, 0x47,
+ 0x0, 0x1B, 0x0, 0x47, 0x0, 0x0E, 0x0, 0x47, 0x0, 0x1C, 0x0, 0x47, 0x0, 0x0F,
+ 0x0, 0x47, 0x0, 0x1D, 0x0, 0xFF, 0xFF
+};
+
+const byte BEXPLODE[] = {
+ 0x2, 0xFF, 0xFF, 0x28, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x28, 0x28, 0x0, 0x2, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x28, 0x0, 0x0, 0x0, 0x28, 0x0, 0x3, 0x0, 0x28, 0x0, 0x9, 0x0, 0x28,
+ 0x0, 0x4, 0x0, 0x28, 0x0, 0x0A, 0x0, 0x28, 0x0, 0x5, 0x0, 0x28, 0x0, 0x0B,
+ 0x0, 0x28, 0x0, 0x6, 0x0, 0x62, 0x0, 0x23, 0x0, 0x28, 0x0, 0x7, 0x0, 0x62,
+ 0x0, 0x23, 0x0, 0x28, 0x0, 0x8, 0x0, 0x62, 0x0, 0x23, 0x0, 0xFF, 0xFF
+};
+
+const byte THORNICK[] = {
+ 0x2, 0x7, 0x0, 0x7, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0,
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x2, 0x0,
+ 0x7, 0x0, 0x5, 0x0, 0x7, 0x0, 0x3, 0x0, 0x7, 0x0, 0x6, 0x0, 0x7, 0x0, 0x3,
+ 0x0, 0x7, 0x0, 0x7, 0x0, 0x7, 0x0, 0x4, 0x0, 0x7, 0x0, 0x8, 0x0, 0xFF, 0xFF
+};
+
+const byte MAYA[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0x48, 0x48, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x2, 0x0,
+ 0x48, 0x0, 0x0, 0x0, 0x48, 0x0, 0x2, 0x0, 0x48, 0x0, 0x13, 0x0, 0x48,
+ 0x0, 0x3, 0x0, 0x48, 0x0, 0x14, 0x0, 0x48, 0x0, 0x4, 0x0, 0x48, 0x0, 0x15,
+ 0x0, 0x48, 0x0, 0x5, 0x0, 0x48, 0x0, 0x16, 0x0, 0x48, 0x0, 0x6, 0x0, 0x48,
+ 0x0, 0x17, 0x0, 0x48, 0x0, 0x7, 0x0, 0x48, 0x0, 0x18, 0x0, 0x48, 0x0, 0x8,
+ 0x0, 0x48, 0x0, 0x19, 0x0, 0x48, 0x0, 0x9, 0x0, 0x48, 0x0, 0x1A, 0x0, 0x48,
+ 0x0, 0x0A, 0x0, 0x48, 0x0, 0x1B, 0x0, 0x48, 0x0, 0x0B, 0x0, 0x48, 0x0, 0x1C,
+ 0x0, 0x48, 0x0, 0x0C, 0x0, 0x48, 0x0, 0x1D, 0x0, 0x48, 0x0, 0x0D, 0x0, 0x48,
+ 0x0, 0x1E, 0x0, 0x48, 0x0, 0x0E, 0x0, 0x48, 0x0, 0x1F, 0x0, 0x48, 0x0, 0x0F,
+ 0x0, 0x48, 0x0, 0x20, 0x0, 0x48, 0x0, 0x10, 0x0, 0x48, 0x0, 0x21, 0x0, 0x48,
+ 0x0, 0x11, 0x0, 0x48, 0x0, 0x22, 0x0, 0x48, 0x0, 0x12, 0x0, 0x48, 0x0, 0x23,
+ 0x0, 0xFF, 0xFF
+};
+
+const byte CAPTAIN[] = {
+ 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x4A, 0x4A, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF,
+ 0x2, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x4A, 0x0, 0x2, 0x0, 0x4A, 0x0, 0x0E, 0x0, 0x4A,
+ 0x0, 0x3, 0x0, 0x4A, 0x0, 0x0F, 0x0, 0x4A, 0x0, 0x4, 0x0, 0x4A, 0x0, 0x10,
+ 0x0, 0x4A, 0x0, 0x5, 0x0, 0x4A, 0x0, 0x11, 0x0, 0x4A, 0x0, 0x6, 0x0, 0x4A,
+ 0x0, 0x12, 0x0, 0x4A, 0x0, 0x7, 0x0, 0x4A, 0x0, 0x13, 0x0, 0x4A, 0x0, 0x8,
+ 0x0, 0x4A, 0x0, 0x14, 0x0, 0x4A, 0x0, 0x9, 0x0, 0x4A, 0x0, 0x15, 0x0, 0x4A,
+ 0x0, 0x0A, 0x0, 0x4A, 0x0, 0x16, 0x0, 0x4A, 0x0, 0x0B, 0x0, 0x4A, 0x0, 0x17,
+ 0x0, 0x4A, 0x0, 0x0C, 0x0, 0x4A, 0x0, 0x18, 0x0, 0x4A, 0x0, 0x0D, 0x0, 0x4A,
+ 0x0, 0x19, 0x0, 0xFF, 0xFF
+};
+
+const byte ALLEN[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x1E, 0x4C, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x4C, 0x0, 0x0, 0x0, 0x4C, 0x0, 0x2, 0x0, 0x4C, 0x0, 0x3, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte ARCH[] = {
+ 0x1, 0x2B, 0x0, 0x4B, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0x2B, 0x4B, 0x0, 0x40, 0x0, 0xFF, 0x4B, 0x0, 0x41, 0x0,
+ 0x4B, 0x0, 0x0, 0x0, 0x4B, 0x0, 0x2, 0x0, 0x4B, 0x0, 0x4, 0x0, 0x4B, 0x0, 0x3,
+ 0x0, 0x4B, 0x0, 0x5, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x6, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x7, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x8, 0x0, 0x4B,
+ 0x0, 0x3, 0x0, 0x4B, 0x0, 0x9, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x0A, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x0B, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x0C, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x0D, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x0E, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x0F, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x10, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x11, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x12, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x13, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x14, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x15, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x16, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x17, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x18, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x19, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x1A, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x1B, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x1C, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x1D, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x1E, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x1F, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x20, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x21, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x22, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x23, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x24, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x25, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x26, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x27, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x28, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x29, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x2A, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x2B, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x2C, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x2D, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x2E, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x2F, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x30, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x31, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x32, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x33, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x34, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x35, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x36, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x37, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x38, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x39, 0x0, 0x4B, 0x0,
+ 0x3, 0x0, 0x4B, 0x0, 0x3A, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x3B, 0x0,
+ 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x3C, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0,
+ 0x3D, 0x0, 0x4B, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x3E, 0x0, 0x4B, 0x0, 0x3, 0x0,
+ 0x4B, 0x0, 0x3F, 0x0, 0xFF, 0xFF
+};
+
+const byte GUARD1[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x4D, 0x4D, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x4D, 0x0, 0x0, 0x0, 0x4D, 0x0, 0x2, 0x0, 0x4D, 0x0, 0x3, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte MCANOE[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x4E, 0x4E, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x4E, 0x0, 0x0, 0x0, 0x4E, 0x0, 0x2, 0x0, 0x4E, 0x0, 0x3, 0x0,
+ 0xFF, 0xFF
+};
+
+const byte CAMPFIRE[] = {
+ 0x2, 0x35, 0x0, 0x35, 0x0, 0x3, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0x35, 0x35, 0x0, 0x1, 0x0, 0xFF, 0x35, 0x0, 0x2, 0x0, 0x35,
+ 0x0, 0x0, 0x0, 0x35, 0x0, 0x4, 0x0, 0x35, 0x0, 0x18, 0x0, 0x35, 0x0, 0x5, 0x0,
+ 0x35, 0x0, 0x19, 0x0, 0x35, 0x0, 0x6, 0x0, 0x35, 0x0, 0x1A, 0x0, 0x35, 0x0,
+ 0x7, 0x0, 0x35, 0x0, 0x1B, 0x0, 0x35, 0x0, 0x8, 0x0, 0x35, 0x0, 0x1C, 0x0,
+ 0x35, 0x0, 0x9, 0x0, 0x35, 0x0, 0x1D, 0x0, 0x35, 0x0, 0x0A, 0x0, 0x35, 0x0,
+ 0x1E, 0x0, 0x35, 0x0, 0x0B, 0x0, 0x35, 0x0, 0x1F, 0x0, 0x35, 0x0, 0x0C,
+ 0x0, 0x35, 0x0, 0x20, 0x0, 0x35, 0x0, 0x0D, 0x0, 0x35, 0x0, 0x21, 0x0, 0x35,
+ 0x0, 0x0E, 0x0, 0x35, 0x0, 0x22, 0x0, 0x35, 0x0, 0x0F, 0x0, 0x35, 0x0, 0x23,
+ 0x0, 0x35, 0x0, 0x10, 0x0, 0x35, 0x0, 0x24, 0x0, 0x35, 0x0, 0x11, 0x0, 0x35,
+ 0x0, 0x25, 0x0, 0x35, 0x0, 0x12, 0x0, 0x35, 0x0, 0x26, 0x0, 0x35, 0x0, 0x13,
+ 0x0, 0x35, 0x0, 0x27, 0x0, 0x35, 0x0, 0x14, 0x0, 0x35, 0x0, 0x28, 0x0, 0x35,
+ 0x0, 0x15, 0x0, 0x35, 0x0, 0x29, 0x0, 0x35, 0x0, 0x16, 0x0, 0x35, 0x0, 0x2A,
+ 0x0, 0x35, 0x0, 0x17, 0x0, 0x35, 0x0, 0x2B, 0x0, 0xFF, 0xFF
+};
+
+const byte COLONEL[] = {
+ 0x2, 0xFF, 0xFF, 0x0E, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x0E, 0x0E, 0x0, 0x5, 0x0, 0xFF, 0xFF, 0xFF, 0x2,
+ 0x0, 0x4F, 0x0, 0x0, 0x0, 0x4F, 0x0, 0x1, 0x0, 0x4F, 0x0, 0x2, 0x0, 0x0E, 0x0,
+ 0x8, 0x0, 0x4F, 0x0, 0x3, 0x0, 0xFF, 0xFF
+};
+
+const byte SOLDIERS[] = {
+ 0x2, 0xFF, 0xFF, 0x50, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x50,
+ 0x0, 0x2, 0x0, 0x50, 0x0, 0x0, 0x0, 0xFF, 0xFF
+};
+
+const byte JWATER[] = {
+ 0x2, 0xFF, 0xFF, 0x51, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x51, 0x0, 0x0, 0x0, 0x51,
+ 0x0, 0x2, 0x0, 0x51, 0x0, 0x3, 0x0, 0xFF, 0xFF
+};
+
+const byte SHOOT[] = {
+ 0x2, 0xFF, 0xFF, 0x52, 0x0, 0x2, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x38, 0x52, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x52, 0x0, 0x0, 0x0, 0x52, 0x0, 0x3, 0x0, 0x52, 0x0, 0x5, 0x0, 0x52,
+ 0x0, 0x4, 0x0, 0x62, 0x0, 0x1F, 0x0, 0xFF, 0xFF
+};
+
+const byte ADIE[] = {
+ 0x2, 0xFF, 0xFF, 0x53, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x2, 0x0, 0x53, 0x0, 0x0, 0x0, 0x53,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x4, 0x0, 0x53, 0x0, 0x3, 0x0, 0x62, 0x0, 0x4,
+ 0x0, 0x53, 0x0, 0x4, 0x0, 0x62, 0x0, 0x4, 0x0, 0xFF, 0xFF
+};
+
+const byte DYNAMITE[] = {
+ 0x2, 0xFF, 0xFF, 0x54, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x2, 0x0, 0x54, 0x0, 0x0, 0x0, 0x54,
+ 0x0, 0x2, 0x0, 0x62, 0x0, 0x23, 0x0, 0xFF, 0xFF
+};
+
+const byte MAYASHOT[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0, 0x0, 0x0, 0x0, 0x36, 0x55, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF,
+ 0x3, 0x0, 0x55, 0x0, 0x0, 0x0, 0x55, 0x0, 0x2, 0x0, 0x62, 0x0, 0x1F,
+ 0x0, 0xFF, 0xFF
+};
+
+const byte OFFKEV[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0x4D, 0x29, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x29, 0x0, 0x0, 0x0, 0x29, 0x0, 0x2, 0x0, 0x29, 0x0, 0x3, 0x0, 0xFF, 0xFF
+};
+
+const byte VALLEY[] = {
+ 0x2, 0x3A, 0x0, 0x3A, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0x3A, 0x3A, 0x0, 0x2, 0x0, 0xFF, 0xFF, 0xFF, 0x3, 0x0,
+ 0x3A, 0x0, 0x0, 0x0, 0x3A, 0x0, 0x3, 0x0, 0x3A, 0x0, 0x5, 0x0, 0x3A, 0x0,
+ 0x4, 0x0, 0x62, 0x0, 0x27, 0x0, 0xFF, 0xFF
+};
+
+const byte MEANWHILE1[] = {
+ 0x2, 0xFF, 0xFF, 0x0E, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x0E, 0x0E, 0x0, 0x5, 0x0, 0xFF, 0xFF, 0xFF, 0x3,
+ 0x0, 0x0E, 0x0, 0x0, 0x0, 0x0E, 0x0, 0x6, 0x0, 0x0E, 0x0, 0x0A, 0x0, 0x0E,
+ 0x0, 0x7, 0x0, 0x0E, 0x0, 0x0B, 0x0, 0x0E, 0x0, 0x8, 0x0, 0x0E, 0x0, 0x0C,
+ 0x0, 0x0E, 0x0, 0x8, 0x0, 0x0E, 0x0, 0x0D, 0x0, 0x0E, 0x0, 0x8, 0x0, 0x0E,
+ 0x0, 0x0E, 0x0, 0x0E, 0x0, 0x9, 0x0, 0x0E, 0x0, 0x0F, 0x0, 0x0E, 0x0, 0x9,
+ 0x0, 0x0E, 0x0, 0x10, 0x0, 0x0E, 0x0, 0x9, 0x0, 0x0E, 0x0, 0x11, 0x0, 0x0E,
+ 0x0, 0x9, 0x0, 0x0E, 0x0, 0x12, 0x0, 0x0E, 0x0, 0x9, 0x0, 0x62, 0x0, 0x1A,
+ 0x0, 0xFF, 0xFF
+};
+
+const byte MAYATREE[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x30, 0x56, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x56, 0x0, 0x0, 0x0, 0x56, 0x0, 0x2, 0x0, 0x56, 0x0, 0x3, 0x0, 0xFF, 0xFF
+};
+
+const byte LOCO[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x31, 0x57, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x57, 0x0, 0x0, 0x0, 0x57, 0x0, 0x2, 0x0, 0x57, 0x0, 0x3, 0x0, 0xFF, 0xFF
+};
+
+const byte KISS[] = {
+ 0x2, 0xFF, 0xFF, 0x3A, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x5, 0x0, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x0, 0x6, 0x0, 0x40, 0x0, 0x26, 0x0, 0x40,
+ 0x0, 0x7, 0x0, 0x40, 0x0, 0x27, 0x0, 0x40, 0x0, 0x8, 0x0, 0x40, 0x0, 0x28,
+ 0x0, 0x40, 0x0, 0x9, 0x0, 0x62, 0x0, 0x4E, 0x0, 0x40, 0x0, 0x0A, 0x0, 0x40,
+ 0x0, 0x29, 0x0, 0x40, 0x0, 0x0B, 0x0, 0x40, 0x0, 0x2A, 0x0, 0x40, 0x0, 0x0C,
+ 0x0, 0x40, 0x0, 0x2B, 0x0, 0x40, 0x0, 0x0D, 0x0, 0x40, 0x0, 0x2C, 0x0, 0x40,
+ 0x0, 0x0E, 0x0, 0x40, 0x0, 0x2D, 0x0, 0x40, 0x0, 0x0F, 0x0, 0x40, 0x0, 0x2E,
+ 0x0, 0x40, 0x0, 0x10, 0x0, 0x40, 0x0, 0x2F, 0x0, 0x40, 0x0, 0x11, 0x0, 0x40,
+ 0x0, 0x30, 0x0, 0x40, 0x0, 0x12, 0x0, 0x40, 0x0, 0x31, 0x0, 0x40, 0x0, 0x13,
+ 0x0, 0x40, 0x0, 0x32, 0x0, 0x40, 0x0, 0x14, 0x0, 0x40, 0x0, 0x33, 0x0, 0x40,
+ 0x0, 0x15, 0x0, 0x40, 0x0, 0x34, 0x0, 0x40, 0x0, 0x16, 0x0, 0x40, 0x0, 0x35,
+ 0x0, 0x40, 0x0, 0x17, 0x0, 0x40, 0x0, 0x36, 0x0, 0x40, 0x0, 0x18, 0x0, 0x40,
+ 0x0, 0x37, 0x0, 0x40, 0x0, 0x19, 0x0, 0x40, 0x0, 0x38, 0x0, 0x40, 0x0, 0x1A,
+ 0x0, 0x40, 0x0, 0x39, 0x0, 0x40, 0x0, 0x1B, 0x0, 0x40, 0x0, 0x3A, 0x0, 0x40,
+ 0x0, 0x1C, 0x0, 0x40, 0x0, 0x3B, 0x0, 0x40, 0x0, 0x1D, 0x0, 0x40, 0x0, 0x3C,
+ 0x0, 0x40, 0x0, 0x1E, 0x0, 0x40, 0x0, 0x3D, 0x0, 0x40, 0x0, 0x1F, 0x0, 0x40,
+ 0x0, 0x3E, 0x0, 0x40, 0x0, 0x20, 0x0, 0x40, 0x0, 0x3F, 0x0, 0x40, 0x0, 0x21,
+ 0x0, 0x40, 0x0, 0x40, 0x0, 0x40, 0x0, 0x22, 0x0, 0x40, 0x0, 0x41, 0x0, 0x40,
+ 0x0, 0x23, 0x0, 0x40, 0x0, 0x42, 0x0, 0x40, 0x0, 0x24, 0x0, 0x40, 0x0, 0x43,
+ 0x0, 0x40, 0x0, 0x25, 0x0, 0x40, 0x0, 0x44, 0x0, 0x40, 0x0, 0x25, 0x0, 0x40,
+ 0x0, 0x45, 0x0, 0x40, 0x0, 0x25, 0x0, 0x40, 0x0, 0x46, 0x0, 0x40, 0x0, 0x25,
+ 0x0, 0x40, 0x0, 0x47, 0x0, 0xFF, 0xFF
+};
+
+const byte ROBOT[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0x9, 0x58, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0,
+ 0x58, 0x0, 0x0, 0x0, 0x58, 0x0, 0x0, 0x0, 0x58, 0x0, 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte ANTKILL[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0,
+ 0x0, 0x0, 0x3C, 0x59, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x59,
+ 0x0, 0x0, 0x0, 0x59, 0x0, 0x2, 0x0, 0x62, 0x0, 0x0E, 0x0, 0xFF, 0xFF
+};
+
+const byte LOCOHOT[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0,
+ 0x0, 0x0, 0x19, 0x5A, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x5A,
+ 0x0, 0x0, 0x0, 0x5A, 0x0, 0x2, 0x0, 0x62, 0x0, 0x3C, 0x0, 0xFF, 0xFF
+};
+
+const byte CRACK[] = {
+ 0x2, 0x38, 0x0, 0x38, 0x0, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,
+ 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x38,
+ 0x0, 0x0, 0x0, 0x38, 0x0, 0x2, 0x0, 0xFF, 0xFF
+};
+
+const byte LETTER[] = {
+ 0x3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30,
+ 0x0, 0x0, 0x0, 0x30, 0x0, 0x1, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x6, 0x0, 0x30,
+ 0x0, 0x0, 0x0, 0x30, 0x0, 0x7, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x8, 0x0, 0x30,
+ 0x0, 0x0, 0x0, 0x30, 0x0, 0x9, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0A, 0x0,
+ 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0B, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0,
+ 0x0C, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0D, 0x0, 0x30, 0x0, 0x0, 0x0,
+ 0x30, 0x0, 0x0E, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0F, 0x0, 0x30, 0x0,
+ 0x0, 0x0, 0x30, 0x0, 0x10, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x2, 0x0, 0x30,
+ 0x0, 0x0, 0x0, 0x30, 0x0, 0x3, 0x0, 0x30, 0x0, 0x0, 0x0, 0x30, 0x0, 0x4, 0x0, 0x30,
+ 0x0, 0x0, 0x0, 0x30, 0x0, 0x5, 0x0, 0xFF, 0xFF
+};
+
+const byte OVERBOARD_DEMO[] = {
+ 0x02, 0xFF, 0xFF, 0x22, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x02, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0x03, 0x00, 0x22, 0x00, 0x06, 0x00, 0x22, 0x00, 0x04,
+ 0x00, 0x22, 0x00, 0x07, 0x00, 0x22, 0x00, 0x05, 0x00, 0x62,
+ 0x00, 0x1D, 0x00, 0x60, 0x00, 0x00, 0x00, 0x22, 0x00, 0x06,
+ 0x00, 0x60, 0x00, 0x01, 0x00, 0x22, 0x00, 0x07, 0x00, 0xFF,
+ 0xFF
+};
+
+const byte SHORE1[] = {
+ 0x02, 0xFF, 0xFF, 0x55, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+ 0x55, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00, 0x62, 0x00,
+ 0x2E, 0x00, 0x55, 0x00, 0x02, 0x00, 0x62, 0x00, 0x2F, 0x00,
+ 0xFF, 0xFF
+};
+
+const byte CHAP8[] = {
+ 0x02, 0xFF, 0xFF, 0x60, 0x00, 0x03, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x60, 0x00, 0x02, 0x00, 0xFF, 0xFF
+};
+
+const byte *const CHARTBL[] = {
+ ELAINE, LIB, FLASHBACK, ALLENDIE, OVERBOARD, PILOT2, TIKAGENT,
+ BARTENDER, PILOT1, COOK, BEXPLODE, THORNICK, MAYA, CAPTAIN,
+ ALLEN, ARCH, GUARD1, MCANOE, CAMPFIRE, COLONEL, SOLDIERS,
+ JWATER, SHOOT, ADIE, DYNAMITE, MAYASHOT, OFFKEV, VALLEY,
+ MEANWHILE1, MAYATREE, LOCO, KISS, ROBOT, ANTKILL, LOCOHOT,
+ CRACK, LETTER
+};
+
+const byte *const CHARTBL_DEMO[] = {
+ ELAINE, LIB, FLASHBACK, ALLENDIE, OVERBOARD_DEMO, PILOT2, TIKAGENT,
+ BARTENDER, PILOT1, COOK, BEXPLODE, THORNICK, MAYA, CAPTAIN,
+ ALLEN, ARCH, GUARD1, MCANOE, CAMPFIRE, COLONEL, SOLDIERS,
+ JWATER, SHOOT, ADIE, DYNAMITE, SHORE1, CHAP8
+};
+
+const char *const INVENTORY_NAMES[] = {
+ "RAT", "ALCOHOL", "SAFE COMBINATION", "BEAKER", "MICROFILM",
+ "VAULT KEY", "BOLT CUTTERS", "BLOWGUN", "LOVE POTION", "MONEY",
+ "DARTS", "TAPE", "JUNGLE POTION", "MOVIE", "CABINET KEY",
+ "DISPLAY CASE KEY", "FLITCH'S CAR KEYS", "COAT HANGER",
+ "CROWBAR", "COMPASS", "MAP", "LETTER OPENER", "LETTER",
+ "DECODER", "DIPPED DART", "LOADED BLOWGUN", "CARD", "JERRYCAN",
+ "CIGARETTES", "BIKE PUMP", "PARACHUTE", "PESO", "PEPPERS",
+ "MACHETE", "POISON ROOT", "AMMUNITION", "PADDLE", "FISHING NET",
+ "RAT TRAP", "CHEESE", "LOADED TRAP", "KNIFE", "CHOPPED PEPPERS",
+ "LIGHTER", "LADDER", "SMALL POLE", "JEEP KEY", "CHAIN", "ARROW",
+ "FILLED JERRY CAN", "EXPLOSIVES", "GEIGER COUNTER", "VINE",
+ "GOLD NUGGET", "HOLLOW REED", "AMAZON QUEEN KEYS", "FISHING POLE",
+ "HARPOON", "RAG", "BOTTLE OF RUM", "RAG IN BOTTLE", "MOLOTOV COCKTAIL",
+ "JUNGLE PLANT", "LADLE", "WORM", "FISH", "FIREWORKS", "BAITED POLE",
+ "FILLED LADLE", "EMERALD", "SMALL KEY", "SCROLL", "LIT EXPLOSIVES",
+ "LIGHTER", "BROKEN SPEAR", "SHOE LACES", "TORCH", "LACES AND SPEAR",
+ "KNIFE SPEAR", "GARBAGE CAN", "RAFT", "INFLATED RAFT",
+ "JASON'S CAR KEYS", "PESO BILLS", "PLANK"
+};
+
+const int FONT2_INDEX[] = {
+ 62, 2, 6,
+ 0x0000, 0x0019, 0x0021, 0x002e, 0x0041, 0x005a, 0x0073, 0x008c, 0x0093, 0x009b,
+ 0x00a3, 0x00bc, 0x00d5, 0x00dd, 0x00ea, 0x00f1, 0x00fe, 0x010b, 0x0118, 0x0125,
+ 0x0132, 0x013f, 0x014c, 0x0159, 0x0166, 0x0173, 0x0180, 0x0187, 0x018e, 0x01a7,
+ 0x01b4, 0x01cd, 0x01dc, 0x01f5, 0x0208, 0x0215, 0x0222, 0x022f, 0x023c, 0x0249,
+ 0x025c, 0x0269, 0x0276, 0x0285, 0x0292, 0x029f, 0x02b2, 0x02c5, 0x02d2, 0x02df,
+ 0x02ee, 0x02fb, 0x0308, 0x0315, 0x0322, 0x032f, 0x0342, 0x034f, 0x0362, 0x036f,
+ 0x0388, 0x03a1,
+};
+
+const byte FONT2_DATA[] = {
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x00, 0xf0, 0x00, 0x06, 0xf3, 0xc0, 0xc3, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x07, 0x1c, 0x00,
+ 0x67, 0x9e, 0xc0, 0x07, 0x1c, 0x00, 0x67, 0x9e, 0xc0, 0x07,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0xc0, 0x00, 0x3f,
+ 0xfc, 0x00, 0xb2, 0xc0, 0x00, 0x3f, 0xfc, 0x00, 0x02, 0xcb,
+ 0x00, 0x3f, 0xfc, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x60,
+ 0x70, 0x70, 0x60, 0x1c, 0x00, 0x04, 0x60, 0x18, 0x1c, 0x1c,
+ 0x1c, 0x70, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, 0xf0,
+ 0x00, 0x07, 0x00, 0xf0, 0x03, 0xc0, 0x0f, 0x00, 0x3c, 0x00,
+ 0xf0, 0x00, 0x00, 0x00, 0x07, 0x3f, 0xc0, 0x70, 0x70, 0x70,
+ 0x70, 0x70, 0x70, 0x3f, 0xc0, 0x00, 0x00, 0x07, 0x1f, 0x00,
+ 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0xff, 0xf0, 0x00, 0x00,
+ 0x08, 0x2b, 0xf0, 0xb0, 0x2c, 0x00, 0xa0, 0x0a, 0x00, 0xff,
+ 0xfc, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x70, 0x03, 0xc0,
+ 0x00, 0x70, 0xff, 0xc0, 0x00, 0x00, 0x07, 0x0b, 0xc0, 0x2d,
+ 0xc0, 0xb1, 0xc0, 0xaa, 0xa0, 0x01, 0xc0, 0x00, 0x00, 0x07,
+ 0xff, 0xf0, 0x70, 0x00, 0x7f, 0xc0, 0x00, 0xb0, 0xbf, 0xc0,
+ 0x00, 0x00, 0x07, 0x2f, 0xc0, 0x70, 0x00, 0x7f, 0xc0, 0x70,
+ 0x70, 0x3f, 0xc0, 0x00, 0x00, 0x08, 0xff, 0xfc, 0x00, 0xb0,
+ 0x02, 0xc0, 0x02, 0xc0, 0x0b, 0x00, 0x00, 0x00, 0x08, 0x2f,
+ 0xf0, 0xb0, 0x1c, 0x2f, 0xf0, 0xb0, 0x1c, 0x2f, 0xf0, 0x00,
+ 0x00, 0x07, 0x3f, 0xc0, 0x70, 0x70, 0x3f, 0xf0, 0x00, 0x70,
+ 0x3f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0xf0, 0x00, 0xf0, 0xf0,
+ 0x00, 0x03, 0xf0, 0xf0, 0x00, 0xf0, 0x30, 0x00, 0x09, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xff, 0xc0, 0x00, 0x00,
+ 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0xff, 0x00, 0x03, 0xc0, 0x0f, 0x00, 0x3c, 0x00,
+ 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0a, 0x00, 0x40, 0x00, 0x01, 0xf0, 0x00, 0x07, 0x1c,
+ 0x00, 0x1f, 0xff, 0x00, 0x70, 0x01, 0xc0, 0x00, 0x00, 0x00,
+ 0x08, 0x7f, 0xf0, 0x70, 0x1c, 0x7f, 0xf0, 0x70, 0x1c, 0x6a,
+ 0xb0, 0x00, 0x00, 0x08, 0x2f, 0xfc, 0x70, 0x00, 0x70, 0x00,
+ 0x70, 0x00, 0x2a, 0xa8, 0x00, 0x00, 0x08, 0x7f, 0xf0, 0x70,
+ 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x6a, 0xb0, 0x00, 0x00, 0x07,
+ 0x7f, 0xf0, 0x70, 0x00, 0x7f, 0xc0, 0x70, 0x00, 0x6a, 0xa0,
+ 0x00, 0x00, 0x07, 0x7f, 0xf0, 0x70, 0x00, 0x7f, 0xc0, 0x70,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x09, 0x3f, 0xfc, 0x00, 0x70,
+ 0x00, 0x00, 0x70, 0xff, 0x00, 0x70, 0x1c, 0x00, 0x2a, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x70, 0x1c, 0x70, 0x1c, 0x7f,
+ 0xfc, 0x70, 0x1c, 0x70, 0x1c, 0x00, 0x00, 0x07, 0xff, 0xf0,
+ 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0xaa, 0xa0, 0x00, 0x00,
+ 0x08, 0x0f, 0xfc, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x70,
+ 0x70, 0x2a, 0x40, 0x00, 0x00, 0x08, 0x70, 0x2c, 0x72, 0xc0,
+ 0x7f, 0x00, 0x72, 0xc0, 0x70, 0x28, 0x00, 0x00, 0x07, 0x70,
+ 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6a, 0xa0, 0x00,
+ 0x00, 0x0a, 0x70, 0x02, 0xc0, 0x7c, 0x09, 0xc0, 0x77, 0x2d,
+ 0xc0, 0x71, 0xb1, 0xc0, 0x60, 0xc1, 0x80, 0x00, 0x00, 0x00,
+ 0x09, 0x70, 0x07, 0x00, 0x77, 0x07, 0x00, 0x71, 0xc7, 0x00,
+ 0x70, 0x77, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x2f, 0xf0, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x2a, 0xa0,
+ 0x00, 0x00, 0x08, 0x7f, 0xf0, 0x70, 0x1c, 0x7f, 0xf0, 0x70,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x2f, 0xf0, 0x70, 0x1c,
+ 0x70, 0x1c, 0x71, 0xdc, 0x2a, 0xa0, 0x00, 0x1c, 0x00, 0x00,
+ 0x08, 0x7f, 0xf0, 0x70, 0x1c, 0x7f, 0xc0, 0x70, 0x70, 0x60,
+ 0x18, 0x00, 0x00, 0x07, 0x2f, 0xf0, 0x70, 0x00, 0x2f, 0xc0,
+ 0x00, 0xb0, 0xbf, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x0b,
+ 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08,
+ 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0xdc, 0x1f, 0x1c,
+ 0x00, 0x00, 0x08, 0xf0, 0x1c, 0xb0, 0x1c, 0x70, 0xb0, 0x72,
+ 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x0b, 0xf0, 0x00, 0xb0, 0xb0,
+ 0x00, 0x70, 0x70, 0xc0, 0x70, 0x72, 0x72, 0xc0, 0x7c, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0x3c, 0x1c, 0xe0, 0x07,
+ 0xc0, 0x1c, 0x70, 0x70, 0x1c, 0x00, 0x00, 0x09, 0x70, 0x07,
+ 0x00, 0x1c, 0x1c, 0x00, 0x07, 0xf0, 0x00, 0x01, 0xc0, 0x00,
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0xfc, 0x00,
+ 0x70, 0x07, 0x00, 0x1c, 0x00, 0xaa, 0xac, 0x00, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+const int FONT6x6_INDEX[] = {
+ 62, 1, 6,
+ 0x0000, 0x0007, 0x000e, 0x0015, 0x001c, 0x0023, 0x002a, 0x0031, 0x0038, 0x003f,
+ 0x0046, 0x004d, 0x0054, 0x005b, 0x0062, 0x0069, 0x0070, 0x0077, 0x007e, 0x0085,
+ 0x008c, 0x0093, 0x009a, 0x00a1, 0x00a8, 0x00af, 0x00b6, 0x00bd, 0x00c4, 0x00cb,
+ 0x00d2, 0x00d9, 0x00e0, 0x00e7, 0x00ee, 0x00f5, 0x00fc, 0x0103, 0x010a, 0x0111,
+ 0x0118, 0x011f, 0x0126, 0x012d, 0x0134, 0x013b, 0x0142, 0x0149, 0x0150, 0x0157,
+ 0x015e, 0x0165, 0x016c, 0x0173, 0x017a, 0x0181, 0x0188, 0x018f, 0x0196, 0x019d,
+ 0x01a4, 0x01ab,
+};
+
+const byte FONT6x6_DATA[] = {
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x30,
+ 0x30, 0x30, 0x00, 0x30, 0x06, 0xd8, 0xd8, 0x90, 0x00, 0x00,
+ 0x00, 0x06, 0x50, 0xf8, 0x50, 0xf8, 0x50, 0x00, 0x06, 0x78,
+ 0xa0, 0x70, 0x28, 0xf0, 0x20, 0x06, 0xc8, 0xd0, 0x20, 0x58,
+ 0x98, 0x00, 0x06, 0x60, 0xd0, 0x60, 0xe8, 0xd0, 0x68, 0x06,
+ 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x06, 0x30, 0x60, 0x60,
+ 0x60, 0x30, 0x00, 0x07, 0x30, 0x18, 0x18, 0x18, 0x30, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x20,
+ 0xf8, 0x20, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x30,
+ 0x60, 0x06, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x00, 0x06, 0x18, 0x30, 0x60, 0xc0,
+ 0x80, 0x00, 0x06, 0x70, 0x98, 0xa8, 0xc8, 0x70, 0x00, 0x06,
+ 0x10, 0x30, 0x10, 0x10, 0x10, 0x00, 0x06, 0xf0, 0x08, 0x70,
+ 0x80, 0xf8, 0x00, 0x06, 0xf0, 0x08, 0x70, 0x08, 0xf0, 0x00,
+ 0x06, 0x30, 0x50, 0x90, 0xf8, 0x10, 0x00, 0x06, 0xf0, 0x80,
+ 0xf0, 0x08, 0xf0, 0x00, 0x06, 0x70, 0x80, 0xf0, 0x88, 0x70,
+ 0x00, 0x06, 0xf8, 0x08, 0x10, 0x20, 0x20, 0x00, 0x06, 0x70,
+ 0x88, 0x70, 0x88, 0x70, 0x00, 0x06, 0x70, 0x88, 0x78, 0x08,
+ 0x70, 0x00, 0x06, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x06,
+ 0x60, 0x60, 0x00, 0x60, 0x20, 0x40, 0x06, 0x18, 0x30, 0x60,
+ 0x30, 0x18, 0x00, 0x06, 0x00, 0x78, 0x00, 0x78, 0x00, 0x00,
+ 0x06, 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0x06, 0x70, 0x98,
+ 0x30, 0x30, 0x00, 0x30, 0x06, 0x70, 0x88, 0xb8, 0xb0, 0x80,
+ 0x78, 0x06, 0x70, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x06, 0xf0,
+ 0x88, 0xf0, 0x88, 0xf0, 0x00, 0x06, 0x78, 0x80, 0x80, 0x80,
+ 0x78, 0x00, 0x06, 0xf0, 0x88, 0x88, 0x88, 0xf0, 0x00, 0x06,
+ 0xf8, 0x80, 0xf0, 0x80, 0xf8, 0x00, 0x06, 0xf8, 0x80, 0xf0,
+ 0x80, 0x80, 0x00, 0x06, 0x78, 0x80, 0x98, 0x88, 0x78, 0x00,
+ 0x06, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x06, 0x70, 0x20,
+ 0x20, 0x20, 0x70, 0x00, 0x06, 0x08, 0x08, 0x08, 0x88, 0x70,
+ 0x00, 0x06, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x00, 0x06, 0x80,
+ 0x80, 0x80, 0x80, 0xf0, 0x00, 0x06, 0x88, 0xd8, 0xa8, 0x88,
+ 0x88, 0x00, 0x06, 0x88, 0xc8, 0xa8, 0x98, 0x88, 0x00, 0x06,
+ 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x06, 0xf0, 0x88, 0xf0,
+ 0x80, 0x80, 0x00, 0x06, 0x70, 0x88, 0x88, 0x88, 0x70, 0x18,
+ 0x06, 0xf0, 0x88, 0xf0, 0xa0, 0x98, 0x00, 0x06, 0x78, 0x80,
+ 0x70, 0x08, 0xf0, 0x00, 0x06, 0xf8, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x06, 0x88, 0x88, 0x88, 0x88, 0x78, 0x00, 0x06, 0x88,
+ 0x88, 0x88, 0x50, 0x20, 0x00, 0x06, 0x88, 0x88, 0xa8, 0xd8,
+ 0x88, 0x00, 0x06, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x06,
+ 0x88, 0x88, 0x50, 0x20, 0x20, 0x00, 0x06, 0xf8, 0x10, 0x20,
+ 0x40, 0xf8, 0x00, 0x06, 0x78, 0x60, 0x60, 0x60, 0x78, 0x00,
+ 0x06, 0xc0, 0x60, 0x30, 0x18, 0x08, 0x00, 0x06, 0x78, 0x18,
+ 0x18, 0x18, 0x78, 0x00, 0x00, 0x52, 0x41, 0x54, 0x00, 0x41,
+ 0x4c, 0x43, 0x4f, 0x48, 0x4f, 0x4c, 0x00, 0x53, 0x41, 0x46,
+ 0x45, 0x20, 0x43, 0x4f, 0x4d, 0x42, 0x49, 0x4e, 0x41, 0x54,
+ 0x49, 0x4f, 0x4e, 0x00, 0x42, 0x45, 0x41, 0x4b, 0x45, 0x52,
+ 0x00, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x4d,
+ 0x00, 0x56, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x4b, 0x45, 0x59,
+ 0x00, 0x42, 0x4f, 0x4c, 0x54, 0x20, 0x43, 0x55, 0x54, 0x54,
+ 0x45, 0x52, 0x53, 0x00, 0x42, 0x4c, 0x4f, 0x57, 0x47, 0x55,
+ 0x4e, 0x00, 0x4c, 0x4f, 0x56, 0x45, 0x20, 0x50, 0x4f, 0x54,
+ 0x49, 0x4f, 0x4e, 0x00, 0x4d, 0x4f, 0x4e, 0x45, 0x59, 0x00,
+ 0x44, 0x41, 0x52, 0x54, 0x53, 0x00, 0x54, 0x41, 0x50, 0x45,
+ 0x00, 0x4a, 0x55, 0x4e, 0x47, 0x4c, 0x45, 0x20, 0x50, 0x4f,
+ 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x4d, 0x4f, 0x56, 0x49,
+};
+
+const char *const NO_HELP_MESSAGE =
+ "WE ARE UNABLE TO PROVIDE YOU WITH ANY MORE HINTS. YOUR IQ \
+HAS DECREASED SO FAR THAT WE CAN NO LONGER PUT THE HINTS IN TERMS \
+YOU CAN UNDERSTAND.";
+const char *const NO_HINTS_MESSAGE = "THE HELP SYSTEM HAS BEEN TURNED OFF FOR THIS GAME.";
+const char *const RIVER_HIT1 = "YOU HIT THE ROCKS AND THE CANOE BEGINS TO LEAK.";
+const char *const RIVER_HIT2 = "YOU HIT THE ROCKS AND THE CANOE DEVELOPS SERIOUS LEAKS.";
+const char *const BAR_MESSAGE = "YOU ARE TOO BUSY TRYING TO KEEP FROM SINKING TO DO THAT";
+const char *const HELPLVLTXT[3] = {
+ " LEVEL 1 ",
+ " LEVEL 2 ",
+ " LEVEL 3 "
+};
+
+const char *const IQLABELS[9] = {
+ "VEGETABLE",
+ "NEANDERTHAL",
+ "LOBOTOMIZED",
+ "DENSE",
+ "AVERAGE",
+ "INTELLIGENT",
+ "MURPHYITE",
+ "BRILLIANT",
+ "GENIUS"
+};
+
+const byte DEATH_SCREENS[58] = {
+ 0, 1, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 2, 4, 2, 1, 0, 0, 0, 0, 0,
+ 0, 2, 7, 7, 4, 6, 7, 10, 4, 2,
+ 0, 0, 0, 0, 5, 5, 3, 3, 3, 5,
+ 8, 8, 11, 9, 8, 12, 0, 1, 9, 8,
+ 8, 0, 5, 8, 0, 12, 12, 11
+};
+
+const byte DEATH_SCREENS_DEMO[34] = {
+ 1, 2, 1, 1, 1, 1, 1, 1, 4, 1,
+ 3, 4, 2, 4, 2, 1, 1, 1, 1, 1,
+ 1, 4, 2, 4, 2, 4, 2, 4, 4, 4,
+ 1, 1, 1, 1
+};
+
+const char *const DEATH_TEXT[58] = {
+ "SAM SALVADOR SPOTS YOU AND LETS YOU HAVE IT.",
+ "WHILE TAKING A MOONLIGHT SWIM YOU DISCOVER THAT PIRANHA REALLY CAN STRIP FLESH TO THE BONE.",
+ "THE GUARD FILLS YOU FULL OF HOLES BEFORE TOSSING YOU TO THE PIRANHA.",
+ "YOU'RE ONLY ABLE TO SWIM HALFWAY ACROSS THE RIVER BEFORE RUNNING OUT OF AIR. "
+ "YOU MAKE SO MUCH NOISE GASPING FOR BREATH THAT SAM EASILY FINDS YOU AND LEAVES "
+ "YOU IN THE RIVER PERMANENTLY.",
+ "SAM SALVADOR NOTICES SOMEONE HAS BEEN PLAYING WITH THE CARGO. "
+ "HE TRACKS YOU DOWN AND LETS YOU HAVE IT.",
+ "THE GUARD COMES AROUND THE CORNER. HE DECIDES THAT THREE LEAD SLUGS WILL "
+ "TEACH YOU TO BE MORE POLITE.",
+ "THE CAPTAIN IS WAITING OUTSIDE THE DOOR.",
+ "THE CAPTAIN'S RANDOM SHOOTING FINALLY FINDS ITS TARGET.",
+ "THE CRATE OUTSIDE THE WINDOW EXPLODES, DESTROYING THE SHIP. "
+ "UNFORTUNATELY, YOU'RE STILL ABOARD.",
+ "THE DOOR WAS NOT BARRED AND THE CAPTAIN WALKS RIGHT IN AND PARTS YOUR HAIR.",
+
+ "",
+ "YOU RUN OUT ON DECK, THEN REALIZE THAT MAYA IS STILL TIED UP. "
+ "AS YOU TURN TO GO BACK THE BOAT BLOWS UP.",
+ "AFTER YOU FAIL TO PROVE YOUR DIVINITY THE NATIVES EAT YOU FOR LUNCH.",
+ "THIS IS THE GENERIC DEATH SCENE",
+ "YOU ONLY MAKE IT HALFWAY ACROSS THE RIVER BEFORE THE PIRANHA STRIKE.",
+ "WITH NOTHING TO PROTECT HIM FROM THE HAIL OF BULLETS ALLEN IS QUICKLY GUNNED DOWN. "
+ "JASON AND MAYA SOON FOLLOW...",
+ "THE COMBINATION OF THE WIND AND GUNFIRE KNOCK THE CORRUGATED IRON OVER, "
+ "LEAVING YOU WITHOUT PROTECTION.",
+ "WITHOUT SUFFICIENT AMMUNITION, ALLEN IS UNABLE TO HOLD OFF THE ATTACKERS FOR LONG. "
+ "THIS RESULTS IN A SERIOUS CASE OF LEAD POISONING. ADDITIONAL AMMUNITION SHOULD "
+ "HAVE BEEN PURCHASED AT THE RIO BLANCO TRADING POST (CHAPTER 6).",
+ "ALLEN IS A MARVELOUS SHOT, BUT HIS AMMUNITION IS NOT UNLIMITED. "
+ "SOON IT IS ALL OVER.",
+ "THE PILOT FEELS YOU ARE TOO CLOSE AND PULLS THE TRIGGER.",
+
+ "THE PILOT SHOOTS YOU IN THE HEART, THEN TOSSES YOUR LIFELESS BODY OUT THE DOOR.",
+ "THE PLANE CRASHES INTO THE JUNGLE CANOPY AT 200 MPH.",
+ "THE CANOE HITS THE ROCKS AND CAPSIZES, AND THE PIRANHA MAKE YOU THEIR LUNCH GUESTS.",
+ "YOU TAKE THE WRONG BRANCH AND ACCIDENTALLY DISCOVER THE FOURTH TALLEST WATERFALL "
+ "IN SOUTH AMERICA.",
+ "YOU TAKE THE WRONG BRANCH AND DISCOVER A VERY HUNGRY TRIBE OF CANNIBALS.",
+ "YOU TAKE THE WRONG BRANCH AND BECOME LOST IN THE WINDING WATERWAYS. "
+ "YOU WANDER UNTIL YOU STARVE TO DEATH.",
+ "YOU TAKE THE WRONG BRANCH AND BECOME TRAPPED IN THE RAPIDS. "
+ "EVENTUALLY YOU AND MAYA ARE CRUSHED BETWEEN THE ROCKS.",
+ "YOU WAIT AROUND FOR SOME TIME, BUT HANS STROHEIM NEVER SPEAKS TO YOU AGAIN. "
+ "FINALLY YOU RETURN HOME KNOWING YOU HAVE FAILED.",
+ "DECIDING THAT YOU THREATEN HIM AND HIS WORK, HANS STROHEIM HAS THE NATIVES "
+ "IN THE VILLAGE KILL YOU.",
+ "YOU DO NOT GET FAR ENOUGH AWAY BEFORE THE DYNAMITE EXPLODES AND YOU ARE BLOWN "
+ "INTO A THOUSAND PIECES.",
+
+ "YOU ARE STANDING SO CLOSE TO THE ENTRANCE WHEN SANCEZ AND HIS MEN BREAK THROUGH "
+ "THE WALL THAT YOU ARE QUICKLY SPOTTED AND SHOT",
+ "THE AMAZON SENTINELS SPOT YOU AND FILL YOU FULL OF ARROWS.",
+ "SAM MAY BE UGLY, BUT HE'S NOT DEAF. HE HEARS ALL THE NOISE YOU ARE MAKING AND "
+ "CANCELS YOUR BOARDING PASS.",
+ "WITH THE BAR OFF THE DOOR THE CAPTAIN WALTZES IN AND BLOWS YOU AWAY",
+ "THE BEAR WANDERS OFF INTO THE WOODS AND DISTURBS THE TWO LOVEBIRDS. "
+ "WHEN THEY COME OUT THEY FIND YOU AND PUT YOU IN THE BIG HOUSE FOR TWENTY YEARS.",
+ "WHEN YOU DO NOT LEAVE THE SECURITY AREA QUICKLY ENOUGH YOU ARE ARRESTED AND CONVICTED "
+ "AS A COMMIE SPY. YOU EMBARK ON A NEW CAREER STAMPING OUT LICENSE PLATES.",
+ "THE HUNGRY BEAR SPOTS YOU AND DECIDES YOU WILL MAKE A NICE APPETIZER.",
+ "YOU DISTURB THE BEAR'S LUNCH AND HE EATS YOU FOR DESSERT.",
+ "AFTER FAILING TO FIND ANY LUNCH AT THE GARBAGE CAN THE BEAR EATS YOU INSTEAD.",
+ "THE SUSPICIOUS LIBRARIAN CALLS SECURITY AND YOU ARE SENT TO JAIL.",
+
+ "YOU PLUMMET 10,000 FEET TO YOUR DEATH.",
+ "EL LOCO FLIES INTO AN INSANE RAGE AND BEATS YOU TO A BLOODY PULP.",
+ "THE WOMAN WALKS OUT THE DOOR AND NEVER RETURNS. YOU SPEND THE REST OF YOUR LIFE "
+ "IN A FUTILE ATTEMPT TO LOCATE ALLEN.",
+ "YOU SLIP OFF THE PLATFORM AND FALL TO YOUR DEATH.",
+ "YOU SLIP OFF THE PLATFORM AND FALL TO YOUR DEATH.",
+ "YOU COME TOO CLOSE TO THE POWERFUL JAWS OF THE ANT AND HE SNIPS YOU IN TWO BEFORE "
+ "DEVOURING YOU.",
+ "B.O.B. HAS A FLAW IN HIS PROGRAMMING THAT DIRECTS HIM TO SHOOT FIRST AND ASK QUESTIONS LATER.",
+ "THE PLANE SINKS AND THE PIRHANA ATTACK BEFORE YOU EVEN GET OUT THE DOOR.",
+ "MAYA FALLS OFF THE END OF THE BROKEN BRIDGE.",
+ "YOUR WEIGHT IS JUST ENOUGH TO CAUSE THE REMAINING SUPPORT CABLE TO SNAP AND YOU "
+ "FALL TO THE BOTTOM OF THE GORGE.",
+
+ "EVEN WITH REPAIRS THE BRIDGE IS NOT STRONG ENOUGH TO HOLD TWO PEOPLE.",
+ "SANCHEZ AND HIS MEN FIND YOU AND HOLD FIRING SQUAD PRACTICE.",
+ "THE TWO GUARDS ARE DISTURBED IN THEIR LOVE NEST AND COME LOOKING FOR ANYONE ACTING SUSPICIOUS. "
+ "THEY FIND YOU AND SEND YOU UP THE RIVER.",
+ "THE PARACHUTE IS NOT LARGE ENOUGH TO SUPPORT YOU, AND YOU HIT THE TREES AT 140 M.P.H.",
+ "SANCHEZ AND HIS MEN FOLLOW YOU ACROSS THE BRIDGE AND CUT YOU DOWN IN A HAIL OF GUNFIRE",
+ "YOU TRIED TO STAB THE ANT BUT HIS SHELL IS TOO DIFFICULT TO PENETRATE. "
+ "YOU NOTICE A SLIGHT CUT IN THE SHELL UNDERNEATH BUT YOU CAN'T GET TO IT "
+ "AND HE SNIPS YOU INTO DELICIOUS MEATY CHUNKS.",
+ "AFTER THE ANT FINISHES SUCKING ALL OF THE SAP OUT OF THE VINE HE TURNS HIS ATTENTION BACK TO YOU "
+ "AND BITES YOUR HEAD OFF.",
+ "THE CANTINA OWNER NOTICES YOU ARE TRYING TO STEAL OBJECTS FROM THE TABLES. "
+ "TWENTY YEARS LATER YOU ARE RELEASED FROM A SOUTH AMERICAN PRISON."
+};
+
+const char *const DEATH_TEXT_DEMO[34] = {
+ "SAM SALVADOR SPOTS YOU AND LETS YOU HAVE IT.",
+ "WHILE TAKING A MOONLIGHT SWIM YOU DISCOVER THAT PIRANHA REALLY CAN STRIP FLESH TO THE BONE.",
+ "THE GUARD FILLS YOU FULL OF HOLES BEFORE TOSSING YOU TO THE PIRANHA.",
+ "YOU'RE ONLY ABLE TO SWIM HALFWAY ACROSS THE RIVER BEFORE RUNNING OUT OF AIR. YOU MAKE SO MUCH NOISE GASPING FOR BREATH THAT SAM EASILY FINDS YOU AND LEAVES YOU IN THE RIVER PERMANENTLY.",
+ "SAM SALVADOR NOTICES SOMEONE HAS BEEN PLAYING WITH THE CARGO. HE TRACKS YOU DOWN AND LETS YOU HAVE IT.",
+ "THE GUARD COMES AROUND THE CORNER. HE DECIDES THAT THREE LEAD SLUGS WILL TEACH YOU TO BE MORE POLITE.",
+ "THE CAPTAIN IS WAITING OUTSIDE THE DOOR.",
+ "THE CAPTAIN'S RANDOM SHOOTING FINALLY FINDS ITS TARGET.",
+ "THE CRATE OUTSIDE THE WINDOW EXPLODES, DESTROYING THE SHIP. UNFORTUNATELY, YOU'RE STILL ABOARD.",
+ "THE DOOR WAS NOT BARRED AND THE CAPTAIN WALKS RIGHT IN AND PARTS YOUR HAIR.",
+ "",
+ "YOU RUN OUT ON DECK, THEN REALIZE THAT MAYA IS STILL TIED UP. AS YOU TURN TO GO BACK THE BOAT BLOWS UP.",
+ "AFTER YOU FAIL TO PROVE YOUR DIVINITY THE NATIVES EAT YOU FOR LUNCH.",
+ "THIS IS THE GENERIC DEATH SCENE",
+ "YOU ONLY MAKE IT HALFWAY ACROSS THE RIVER BEFORE THE PIRANHA STRIKE.",
+ "WITH NOTHING TO PROTECT HIM FROM THE HAIL OF BULLETS ALLEN IS QUICKLY GUNNED DOWN. JASON AND MAYA SOON FOLLOW...",
+ "THE COMBINATION OF THE WIND AND GUNFIRE KNOCK THE CORRUGATED IRON OVER, LEAVING YOU WITHOUT PROTECTION.",
+ "WITHOUT SUFFICIENT AMMUNITION, ALLEN IS UNABLE TO HOLD OFF THE ATTACKERS FOR LONG. THIS RESULTS IN A SERIOUS CASE OF LEAD POISONING.",
+ "ALLEN IS A MARVELOUS SHOT, BUT HIS AMMUNITION IS NOT UNLIMITED. SOON IT IS ALL OVER.",
+ "THE PILOT FEELS YOU ARE TOO CLOSE AND PULLS THE TRIGGER.",
+ "THE PILOT SHOOTS YOU IN THE HEAD, THEN TOSSES YOUR LIFELESS",
+ "THE PLANE CRASHES INTO THE JUNGLE CANOPY AT 200 MPH.",
+ "THE CANOE HITS THE ROCKS AND CAPSIZES, AND THE PIRANHA MAKE YOU THEIR LUNCH GUESTS.",
+ "YOU ACCIDENTALLY DISCOVER THE FOURTH TALLEST WATERFALL IN SOUTH AMERICA.",
+ "YOU DISCOVER A VERY HUNGRY TRIBE OF CANNIBALS.",
+ "YOU BECOME LOST IN THE WINDING WATERWAYS AND WANDER UNTIL YOU STARVE TO DEATH.",
+ "YOU BECOME TRAPPED IN THE RAPIDS AND ARE CRUSHED BETWEEN THE ROCKS.",
+ "YOU WAIT AROUND FOR SOME TIME, BUT HANS STROHEIM NEVER SPEAKS TO YOU AGAIN. FINALLY YOU RETURN HOME KNOWING YOU HAVE FAILED.",
+ "DECIDING THAT YOU THREATEN HIM AND HIS WORK, HANS STROHEIM HAS THE NATIVES IN THE VILLAGE KILL YOU.",
+ "YOU DO NOT GET FAR ENOUGH AWAY BEFORE THE DYNAMITE EXPLODES AND YOU ARE BLOWN INTO A THOUSAND PIECES.",
+ "STANDING OUT IN THE OPEN YOU ARE EXPOSED TO THE HAIL OF BULLETS FROM SANCHEZ' MEN.",
+ "THE AMAZON SENTINELS SPOT YOU AND FILL YOU FULL OF ARROWS.",
+ "SAM MAY BE UGLY, BUT HE'S NOT DEAF. HE HEARS ALL THE NOISE YOU ARE MAKING AND CANCELS YOUR BOARDING PASS.",
+ "WITH THE BAR OFF THE DOOR THE CAPTAIN WALTZES IN AND BLOWS YOU AWAY"
+};
+
+const int DEATH_CELLS[13][3] = {
+ { 0, 94, 2 },
+ { 0, 94, 3 },
+ { 0, 94, 4 },
+ { 0, 94, 5 },
+ { 0, 94, 6 },
+ { 0, 94, 7 },
+ { 0, 94, 8 },
+ { 0, 94, 9 },
+ { 0, 94, 10 },
+ { 0, 94, 11 },
+ { 0, 94, 12 },
+ { 0, 94, 13 },
+ { 0, 94, 14 }
+};
+
+const int CHAPTER_CELLS[17][3] = {
+ { 1, 96, 18 },
+ { 2, 96, 19 },
+ { 3, 96, 20 },
+ { 4, 96, 21 },
+ { 5, 96, 22 },
+ { 6, 96, 23 },
+ { 7, 96, 24 },
+ { 8, 96, 25 },
+ { 9, 96, 26 },
+ { 10, 96, 27 },
+ { 11, 96, 28 },
+ { 12, 96, 29 },
+ { 13, 96, 30 },
+ { 14, 96, 31 }
+};
+
+const int CHAPTER_TABLE[14][5] = {
+ { 18, 136, 27, 76, 49 },
+ { 16, 134, 27, 53, 74 },
+ { 16, 136, 27, 52, 56 },
+ { 16, 135, 26, 46, 75 },
+ { 16, 135, 27, 54, 66 },
+ { 16, 137, 27, 67, 79 },
+ { 14, 136, 27, 82, 52 },
+ { 15, 136, 26, 65, 73 },
+ { 15, 137, 26, 48, 75 },
+ { 17, 135, 27, 52, 66 },
+ { 15, 135, 27, 62, 65 },
+ { 16, 135, 28, 45, 66 },
+ { 16, 135, 28, 36, 67 },
+ { 15, 135, 27, 34, 63 }
+};
+
+const int CHAPTER_JUMP[14] = {
+ 0, 12, 10, 15, 19, 25, 31, 36, 45, 46, 29, 55, 61, 0
+};
+
+const int COMBO_TABLE[85][4] = {
+ { -1, -1, -1, -1 },
+ { 12, 3, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 24, 25, -1, -1 },
+ { 10, 24, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 8, 24, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 1, 3, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 7, 25, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 80, 81, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 41, 42, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 39, 40, -1, -1 },
+ { 38, 40, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 32, 42, 77, 78 },
+ { -1, -1, -1, -1 },
+ { 60, 61, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 73, 72, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 64, 67, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 59, 60, -1, -1 },
+ { 58, 60, -1, -1 },
+ { 43, 61, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 56, 67, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 50, 72, -1, -1 },
+ { 75, 77, -1, -1 },
+ { 74, 77, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 41, 78, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { 29, 81, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 }
+};
+
+const int ANTWALK[24] = {
+ 0, 3, 0,
+ 1, 5, 0,
+ 2, 4, 0,
+ 3, 2, 0,
+ 4, 4, 0,
+ 5, 3, 0,
+ 6, 4, 0,
+ -1, -1, -1
+};
+
+const int ANTEAT[33] = {
+ 7, 0, -1,
+ 8, 0, -5,
+ 9, 0, -11,
+ 10, 0, 7,
+ 11, 0, -3,
+ 12, 0, 3,
+ 13, 0, -1,
+ 9, 0, -6,
+ 8, 0, 11,
+ 7, 0, 6,
+ -1, -1, -1
+};
+
+const int ANTDIE[21] = {
+ 14, 4, 8,
+ 15, 7, 6,
+ 16, 6, 7,
+ 17, 8, 2,
+ 18, 0, 0,
+ 19, 0, 0,
+ -1, -1, -1
+};
+
+const int PITWALK[27] = {
+ 18, 0, -1,
+ 19, -2, 1,
+ 20, -2, 1,
+ 21, -2, 1,
+ 22, -2, 0,
+ 23, -3, 0,
+ 24, -3, -1,
+ 25, -2, -1,
+ -1, -1, -1
+};
+
+const int PITSTAB[21] = {
+ 14, -2, 0,
+ 15, -4, 0,
+ 16, 3, -13,
+ 16, 0, 0,
+ 15, -3, 13,
+ 14, 4, 0,
+ -1, -1, -1
+};
+
+const int TORCH[12] = {
+ 26, -11, -7,
+ 27, -12, -2,
+ 28, -15, -4,
+ -1, -1, -1
+};
+
+const int SPEAR[3] = {30, -13, 1};
+
+const int OPENING_OBJS[10][4] = {
+ {8, -80, 120, 30},
+ {13, 229, 0, 50},
+ {12, 78, 0, 50},
+ {11, 10, 0, 50},
+ {10, 178, 97, 50},
+ {9, 92, 192, 50},
+ {14, 38, 0, 100},
+ {15, 132, 76, 100},
+ {16, 142, 0, 100},
+ {4, -280, 40, 120},
+};
+
+const byte MAP0[26] = {
+ 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 4, 0,
+ 0, 0, 1, 0, 2, 0, 0, 1, 1, 3, 0, 0,
+ 0, 0xFF
+};
+
+const byte MAP1[27] = {
+ 0, 0, 1, 0, 3, 0, 0, 1, 1, 2, 0, 0,
+ 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 4, 0,
+ 0, 0, 0xFF
+};
+
+const byte MAP2[32] = {
+ 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 1, 0,
+ 3, 0, 0, 1, 0, 4, 0, 0, 1, 1, 2, 0,
+ 0, 1, 0, 1, 0, 0, 0, 0xFF
+};
+
+const byte *const MAPTBL[3] = {MAP0, MAP1, MAP2};
+
+const int DOWNRIVEROBJ[14][4] = {
+ { 3, 77, 0, 40 },
+ { 2, 30, 0, 30 },
+ { 2, 290, 0, 50 },
+ { 1, 210, 0, 70 },
+ { 2, 350, 0, 30 },
+ { 1, 370, 0, 20 },
+ { 2, 480, 0, 60 },
+ { 3, 395, 0, 10 },
+ { 1, 550, 0, 30 },
+ { 2, 620, 0, 50 },
+ { 1, 690, 0, 10 },
+ { 2, 715, 0, 40 },
+ { 1, 770, 0, 30 },
+ { 3, 700, 0, 20 }
+};
+
+RiverStruct RIVER0OBJECTS[46] = {
+ {16, 31, 6400, 0, 4, 12},
+ {16, 31, 6200, 0, 2, 12},
+ {17, 30, 6100, 0, 3, 15},
+ {16, 31, 5970, 0, 7, 12},
+ {17, 30, 5910, 0, 5, 15},
+ {17, 30, 5730, 0, 3, 15},
+ {16, 31, 5700, 0, 7, 12},
+ {-1, 314, 5392, 0, 4, 0},
+ {17, 30, 5155, 0, 1, 15},
+ {16, 31, 5150, 0, 5, 12},
+ {16, 31, 5056, 0, 7, 12},
+ {17, 30, 4900, 0, 2, 15},
+ {17, 30, 4785, 0, 7, 15},
+ {16, 31, 4690, 0, 4, 12},
+ {16, 31, 4660, 0, 1, 12},
+ {17, 30, 4560, 0, 5, 15},
+ {16, 31, 4465, 0, 2, 12},
+ {-1, 314, 4112, 0, 4, 0},
+ {17, 30, 4005, 0, 3, 15},
+ {16, 31, 3865, 0, 6, 12},
+ {17, 30, 3605, 0, 4, 15},
+ {16, 31, 3360, 0, 1, 12},
+ {17, 30, 3105, 0, 0, 15},
+ {16, 31, 3080, 0, 7, 12},
+ {17, 30, 3014, 0, 4, 15},
+ {16, 31, 2992, 0, 3, 12},
+ {16, 31, 2976, 0, 2, 12},
+ {17, 30, 2880, 0, 7, 15},
+ {17, 30, 2860, 0, 0, 15},
+ {-1, 314, 2512, 0, 4, 0},
+ {17, 30, 2270, 0, 4, 15},
+ {16, 31, 2195, 0, 6, 12},
+ {17, 30, 1824, 0, 1, 15},
+ {16, 31, 1776, 0, 4, 12},
+ {17, 30, 1650, 0, 3, 15},
+ {16, 31, 1616, 0, 7, 12},
+ {17, 30, 1585, 0, 2, 15},
+ {-1, 314, 1232, 0, 4, 0},
+ {17, 30, 1190, 0, 2, 15},
+ {16, 31, 1120, 0, 4, 12},
+ {17, 30, 970, 0, 7, 15},
+ {16, 31, 910, 0, 5, 12},
+ {17, 30, 705, 0, 0, 15},
+ {16, 31, 550, 0, 4, 12},
+ {17, 30, 305, 0, 2, 15},
+ {16, 31, 260, 0, 7, 12}
+};
+
+RiverStruct RIVER1OBJECTS[50] = {
+ {16, 31, 6920, 0, 1, 12},
+ {16, 31, 6740, 0, 4, 12},
+ {17, 30, 6699, 0, 1, 15},
+ {16, 31, 6610, 0, 2, 12},
+ {17, 30, 6495, 0, 6, 15},
+ {17, 30, 6385, 0, 4, 15},
+ {16, 31, 6350, 0, 1, 12},
+ {17, 30, 6180, 0, 0, 15},
+ {-1, 314, 6032, 0, 4, 0},
+ {16, 31, 5800, 0, 3, 12},
+ {17, 30, 5790, 0, 6, 15},
+ {16, 31, 5530, 0, 4, 12},
+ {16, 31, 5500, 0, 7, 12},
+ {17, 30, 5495, 0, 1, 15},
+ {17, 30, 5376, 0, 0, 15},
+ {16, 31, 5328, 0, 7, 12},
+ {17, 30, 5248, 0, 2, 15},
+ {16, 31, 5248, 0, 6, 12},
+ {-1, 314, 4752, 0, 4, 0},
+ {17, 30, 4432, 0, 2, 15},
+ {16, 31, 4432, 0, 7, 12},
+ {16, 31, 4384, 0, 2, 12},
+ {17, 30, 4368, 0, 5, 15},
+ {16, 31, 4336, 0, 4, 12},
+ {17, 30, 4185, 0, 1, 15},
+ {16, 31, 4125, 0, 3, 12},
+ {17, 30, 3817, 0, 7, 15},
+ {16, 31, 3612, 0, 4, 12},
+ {16, 31, 3360, 0, 5, 12},
+ {16, 31, 3265, 0, 7, 12},
+ {17, 30, 3200, 0, 1, 15},
+ {17, 30, 3056, 0, 6, 15},
+ {-1, 314, 2832, 0, 4, 0},
+ {16, 31, 2740, 0, 3, 12},
+ {17, 30, 2694, 0, 6, 15},
+ {16, 31, 2455, 0, 0, 12},
+ {17, 30, 2285, 0, 5, 15},
+ {16, 31, 2260, 0, 2, 12},
+ {16, 31, 1904, 0, 5, 12},
+ {17, 30, 1808, 0, 1, 15},
+ {16, 31, 1744, 0, 7, 12},
+ {17, 30, 1696, 0, 4, 15},
+ {16, 31, 1568, 0, 2, 12},
+ {-1, 314, 1232, 0, 4, 0},
+ {17, 30, 970, 0, 4, 15},
+ {16, 31, 910, 0, 7, 12},
+ {17, 30, 705, 0, 0, 15},
+ {16, 31, 550, 0, 6, 12},
+ {17, 30, 305, 0, 3, 15},
+ { 16, 31, 260, 0, 1, 12 }
+};
+
+RiverStruct RIVER2OBJECTS[54] = {
+ {16, 31, 8230, 0, 6, 12},
+ {16, 31, 8115, 0, 7, 12},
+ {17, 30, 7955, 0, 4, 15},
+ {16, 31, 7890, 0, 0, 12},
+ {16, 31, 7616, 0, 2, 12},
+ {17, 30, 7472, 0, 5, 15},
+ {16, 31, 7425, 0, 4, 12},
+ {17, 30, 7360, 0, 1, 15},
+ {16, 31, 7328, 0, 6, 12},
+ {-1, 314, 6992, 0, 4, 0},
+ {16, 31, 6720, 0, 3, 12},
+ {17, 30, 6700, 0, 6, 15},
+ {16, 31, 6518, 0, 2, 12},
+ {17, 30, 6225, 0, 5, 15},
+ {16, 31, 6200, 0, 2, 12},
+ {17, 30, 5990, 0, 1, 15},
+ {16, 31, 5960, 0, 7, 12},
+ {16, 31, 5700, 0, 2, 12},
+ {17, 30, 5650, 0, 4, 15},
+ {16, 31, 5568, 0, 5, 12},
+ {17, 30, 5488, 0, 6, 15},
+ {-1, 314, 5072, 0, 4, 0},
+ {17, 30, 4825, 0, 4, 15},
+ {16, 31, 4782, 0, 2, 12},
+ {17, 30, 4660, 0, 5, 15},
+ {16, 31, 4510, 0, 7, 12},
+ {16, 31, 4495, 0, 1, 12},
+ {17, 30, 4250, 0, 2, 15},
+ {16, 31, 4195, 0, 4, 12},
+ {-1, 314, 3792, 0, 4, 0},
+ {17, 30, 3600, 0, 3, 15},
+ {16, 31, 3470, 0, 5, 12},
+ {16, 31, 3422, 0, 2, 12},
+ {17, 30, 3170, 0, 6, 15},
+ {16, 31, 2960, 0, 4, 12},
+ {17, 30, 2955, 0, 7, 15},
+ {-1, 314, 2512, 0, 4, 0},
+ {17, 30, 2415, 0, 1, 15},
+ {16, 31, 2318, 0, 0, 12},
+ {17, 30, 2275, 0, 2, 15},
+ {16, 31, 2270, 0, 6, 12},
+ {17, 30, 2026, 0, 3, 15},
+ {16, 31, 2000, 0, 0, 12},
+ {16, 31, 1840, 0, 3, 12},
+ {17, 30, 1795, 0, 7, 15},
+ {16, 31, 1634, 0, 5, 12},
+ {17, 30, 1630, 0, 1, 15},
+ {-1, 314, 1232, 0, 4, 0},
+ {17, 30, 970, 0, 2, 15},
+ {16, 31, 910, 0, 5, 12},
+ {17, 30, 705, 0, 0, 15},
+ {16, 31, 550, 0, 4, 12},
+ {17, 30, 305, 0, 3, 15},
+ {16, 31, 260, 0, 6, 12}
+};
+
+RiverStruct *RIVER_OBJECTS[3][2] = {
+ { RIVER0OBJECTS, RIVER0OBJECTS + 46 - 1},
+ { RIVER1OBJECTS, RIVER0OBJECTS + 50 - 1 },
+ { RIVER2OBJECTS, RIVER0OBJECTS + 54 - 1 }
+};
+
+const int HELP1COORDS[2][4] = {
+ { 76, 129, 168, 183 }, { 187, 240, 168, 183 }
+};
+
+const int RIVER1OBJ[23][4] = {
+ { 18, -77, 0, 30 },
+ { 18, -325, 0, 20 },
+ { 18, -450, 0, 15 },
+ { 18, -1250, 0, 25 },
+ { 19, -130, 0, 20 },
+ { 19, -410, 0, 15 },
+ { 19, -710, 0, 25 },
+ { 19, -1510, 0, 20 },
+ { 20, -350, 0, 30 },
+ { 20, -695, 0, 25 },
+ { 20, -990, 0, 20 },
+ { 20, -1300, 0, 25 },
+ { 20, -1600, 0, 30 },
+ { 21, -370, 0, 20 },
+ { 21, -650, 0, 30 },
+ { 21, -1215, 0, 40 },
+ { 21, -1815, 0, 35 },
+ { 22, -380, 0, 25 },
+ { 22, -720, 0, 35 },
+ { 22, -1020, 0, 30 },
+ { 22, -1170, 0, 25 },
+ { 22, -1770, 0, 35 },
+ { 23, -500, 63, 20 }
+};
+
+const int CAST_END_OBJ[26][4] = {
+ { 0, 118, 210, 10 },
+ { 1, 38, 250, 10 },
+ { 2, 38, 280, 10 },
+ { 3, 38, 310, 10 },
+ { 4, 38, 340, 10 },
+ { 5, 38, 370, 10 },
+ { 6, 38, 400, 10 },
+ { 7, 38, 430, 10 },
+ { 8, 38, 460, 10 },
+ { 9, 38, 490, 10 },
+ { 10, 38, 520, 10 },
+ { 11, 38, 550, 10 },
+ { 12, 38, 580, 10 },
+ { 13, 38, 610, 10 },
+ { 14, 38, 640, 10 },
+ { 15, 38, 670, 10 },
+ { 16, 38, 700, 10 },
+ { 17, 38, 730, 10 },
+ { 18, 38, 760, 10 },
+ { 19, 38, 790, 10 },
+ { 20, 95, 820, 10 },
+ { 21, 94, 850, 10 },
+ { 22, 96, 880, 10 },
+ { 23, 114, 910, 10 },
+ { 24, 114, 940, 10 },
+ { 25, 110, 970, 10 }
+};
+
+const int CAST_END_OBJ1[4][4] = {
+ { 0, 40, 1100, 10 },
+ { 2, 11, 1180, 10 },
+ { 1, 154, 1180, 10 },
+ { 3, 103, 1300, 10 }
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/amazon/amazon_resources.h b/engines/access/amazon/amazon_resources.h
new file mode 100644
index 0000000000..a952860bc2
--- /dev/null
+++ b/engines/access/amazon/amazon_resources.h
@@ -0,0 +1,148 @@
+/* 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 ACCESS_AMAZON_RESOURCES_H
+#define ACCESS_AMAZON_RESOURCES_H
+
+#include "common/scummsys.h"
+
+namespace Access {
+
+namespace Amazon {
+
+enum InventoryEnum {
+ INV_BAITED_POLE = 67, INV_TORCH = 76, INV_KNIFE_SPEAR = 78
+};
+
+struct RiverStruct {
+ int _id;
+ int _width;
+ int _riverX;
+ int _xp;
+ int _lane;
+ int _offsetY;
+};
+
+extern const char *const FILENAMES[];
+extern const char *const FILENAMES_DEMO[];
+
+extern const byte *const CURSORS[10];
+
+extern const int TRAVEL_POS[][2];
+
+extern const int OVEROFFR[];
+extern const int OVEROFFL[];
+extern const int OVEROFFU[];
+extern const int OVEROFFD[];
+extern const int OVEROFFURX[];
+extern const int OVEROFFURY[];
+extern const int OVEROFFDRX[];
+extern const int OVEROFFDRY[];
+extern const int OVEROFFULX[];
+extern const int OVEROFFULY[];
+extern const int OVEROFFDLX[];
+extern const int OVEROFFDLY[];
+
+extern const byte *const ROOM_TABLE[];
+extern const char *const ROOM_DESCR[];
+extern const byte *const ROOM_TABLE_DEMO[];
+extern const int ROOM_NUMB;
+
+extern const byte *const CHARTBL[];
+extern const byte *const CHARTBL_DEMO[];
+
+extern const char *const INVENTORY_NAMES[];
+
+extern const int FONT2_INDEX[];
+
+extern const byte FONT2_DATA[];
+
+extern const int FONT6x6_INDEX[];
+
+extern const byte FONT6x6_DATA[];
+
+extern const char *const NO_HELP_MESSAGE;
+extern const char *const NO_HINTS_MESSAGE;
+extern const char *const RIVER_HIT1;
+extern const char *const RIVER_HIT2;
+extern const char *const BAR_MESSAGE;
+extern const char *const HELPLVLTXT[3];
+extern const char *const IQLABELS[9];
+extern const byte DEATH_SCREENS[58];
+extern const byte DEATH_SCREENS_DEMO[34];
+
+extern const char *const DEATH_TEXT[58];
+extern const char *const DEATH_TEXT_DEMO[34];
+
+extern const int DEATH_CELLS[13][3];
+
+extern const int CHAPTER_CELLS[17][3];
+
+extern const int CHAPTER_TABLE[14][5];
+
+extern const int CHAPTER_JUMP[14];
+
+extern const int COMBO_TABLE[85][4];
+
+extern const int ANTWALK[24];
+
+extern const int ANTEAT[33];
+
+extern const int ANTDIE[21];
+
+extern const int PITWALK[27];
+
+extern const int PITSTAB[21];
+
+extern const int TORCH[12];
+
+extern const int SPEAR[3];
+
+extern const int OPENING_OBJS[10][4];
+
+extern const byte MAP0[26];
+extern const byte MAP1[27];
+extern const byte MAP2[32];
+
+extern const byte *const MAPTBL[3];
+
+extern const int DOWNRIVEROBJ[14][4];
+
+extern RiverStruct RIVER0OBJECTS[46];
+extern RiverStruct RIVER1OBJECTS[50];
+extern RiverStruct RIVER2OBJECTS[54];
+extern RiverStruct *RIVER_OBJECTS[3][2];
+enum { RIVER_START = 0, RIVER_END = 1 };
+
+extern const int HELP1COORDS[2][4];
+
+extern const int RIVER1OBJ[23][4];
+
+extern const int CAST_END_OBJ[26][4];
+
+extern const int CAST_END_OBJ1[4][4];
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_AMAZON_RESOURCES_H */
diff --git a/engines/access/amazon/amazon_room.cpp b/engines/access/amazon/amazon_room.cpp
new file mode 100644
index 0000000000..29742f66bd
--- /dev/null
+++ b/engines/access/amazon/amazon_room.cpp
@@ -0,0 +1,241 @@
+/* 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 "access/access.h"
+#include "access/resources.h"
+#include "access/amazon/amazon_game.h"
+#include "access/amazon/amazon_resources.h"
+#include "access/amazon/amazon_room.h"
+
+namespace Access {
+
+namespace Amazon {
+
+AmazonRoom::AmazonRoom(AccessEngine *vm) : Room(vm) {
+ _game = (AmazonEngine *)vm;
+ _antOutFlag = false;
+ _icon = nullptr;
+}
+
+AmazonRoom::~AmazonRoom() {
+}
+
+void AmazonRoom::loadRoom(int roomNumber) {
+ if (_vm->isDemo())
+ loadRoomData(ROOM_TABLE_DEMO[roomNumber]);
+ else
+ loadRoomData(ROOM_TABLE[roomNumber]);
+}
+
+void AmazonRoom::reloadRoom() {
+ loadRoom(_vm->_player->_roomNumber);
+
+ if (_roomFlag != 1) {
+ _vm->_currentMan = _roomFlag;
+ _vm->_currentManOld = _roomFlag;
+ _vm->_manScaleOff = 0;
+
+ switch (_vm->_currentMan) {
+ case 0:
+ _vm->_player->loadSprites("MAN.LZ");
+ break;
+
+ case 2:
+ _vm->_player->loadSprites("JMAN.LZ");
+ break;
+
+ case 3:
+ _vm->_player->loadSprites("OVERHEAD.LZ");
+ _vm->_manScaleOff = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ reloadRoom1();
+}
+
+void AmazonRoom::reloadRoom1() {
+ if (_vm->_player->_roomNumber == 29 || _vm->_player->_roomNumber == 31
+ || _vm->_player->_roomNumber == 42 || _vm->_player->_roomNumber == 44) {
+ Resource *spriteData = _vm->_files->loadFile("MAYA.LZ");
+ _game->_inactive._altSpritesPtr = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+ _vm->_currentCharFlag = false;
+ }
+
+ _selectCommand = -1;
+ _vm->_events->setNormalCursor(CURSOR_CROSSHAIRS);
+ _vm->_mouseMode = 0;
+ _vm->_boxSelect = true;
+ _vm->_player->_playerOff = false;
+
+ _vm->_screen->fadeOut();
+ _vm->_screen->clearScreen();
+ roomSet();
+
+ if (_roomFlag != 1 && (_vm->_player->_roomNumber != 61 || !_antOutFlag)) {
+ _vm->_player->load();
+ _vm->_player->calcManScale();
+ }
+
+ if (_vm->_player->_roomNumber != 20 && _vm->_player->_roomNumber != 24
+ && _vm->_player->_roomNumber != 33 && _vm->_player->_roomNumber != 45) {
+ roomMenu();
+ }
+
+ _vm->_screen->setBufferScan();
+ setupRoom();
+ setWallCodes();
+ buildScreen();
+
+ if (!_vm->_screen->_vesaMode) {
+ _vm->copyBF2Vid();
+ } else if (_vm->_player->_roomNumber != 20 && _vm->_player->_roomNumber != 24
+ && _vm->_player->_roomNumber != 33) {
+ _vm->_screen->setPalette();
+ _vm->copyBF2Vid();
+ }
+
+ // Stop player moving
+ _vm->_player->_playerMove = false;
+ _vm->_player->_frame = 0;
+
+ // Clear any dirty rects from the old scene
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+}
+
+void AmazonRoom::setupRoom() {
+ Room::setupRoom();
+
+ // WORKAROUND: The original engine doesn't handle vertical scrolling rooms
+ Screen &screen = *_vm->_screen;
+ if (screen._vWindowHeight == (_playFieldHeight - 1)) {
+ _vm->_scrollRow = 1;
+ _vm->_scrollY = 0;
+ }
+}
+
+void AmazonRoom::roomSet() {
+ _vm->_numAnimTimers = 0;
+ _vm->_scripts->_sequence = 1000;
+ _vm->_scripts->searchForSequence();
+ _vm->_scripts->executeScript();
+}
+
+void AmazonRoom::roomMenu() {
+ Resource *iconData = _vm->_files->loadFile("ICONS.LZ");
+ SpriteResource *spr = new SpriteResource(_vm, iconData);
+ delete iconData;
+
+ Screen &screen = *_vm->_screen;
+ screen.saveScreen();
+ screen.setDisplayScan();
+ _vm->_destIn = &screen; // TODO: Redundant
+ screen.plotImage(spr, 0, Common::Point(0, 177));
+ screen.plotImage(spr, 1, Common::Point(143, 177));
+
+ screen.restoreScreen();
+ delete spr;
+}
+
+void AmazonRoom::mainAreaClick() {
+ Common::Point &mousePos = _vm->_events->_mousePos;
+ Common::Point pt = _vm->_events->calcRawMouse();
+ Screen &screen = *_vm->_screen;
+ Player &player = *_vm->_player;
+
+ if (_selectCommand == -1) {
+ if (player._roomNumber == 42 || player._roomNumber == 44 ||
+ player._roomNumber == 31 || player._roomNumber == 29) {
+ switch (checkBoxes1(pt)) {
+ case 0:
+ // Make Jason the active player
+ _game->_jasMayaFlag = 0;
+ return;
+ case 1:
+ // Make Maya the active player
+ _game->_jasMayaFlag = 1;
+ return;
+ default:
+ break;
+ }
+ }
+
+ // WORKAROUND: In Amazon room 9, you can't leave the screen to the south due
+ // to not being able to click a Y position that's high enough
+ if (_vm->_scrollRow == 0 && pt.y > 178)
+ pt.y = 200;
+
+ player._moveTo = pt;
+ player._playerMove = true;
+ } else if (mousePos.x >= screen._windowXAdd &&
+ mousePos.x <= (screen._windowXAdd + screen._vWindowBytesWide) &&
+ mousePos.y >= screen._windowYAdd &&
+ mousePos.y <= (screen._windowYAdd + screen._vWindowLinesTall)) {
+ if (checkBoxes1(pt) >= 0) {
+ checkBoxes3();
+ }
+ }
+}
+
+void AmazonRoom::walkCursor() {
+ // WORKAROUND: For scene 29, which is a normal walkable scene, but yet can be
+ // 'exited'. This workaround ensures the scene will only be left if you click
+ // the Exit icon when the cursor is already a walk cursor
+ EventsManager &events = *_vm->_events;
+
+ if (_vm->_events->_middleButton || (_vm->_player->_roomNumber == 29 &&
+ events._normalMouse != CURSOR_CROSSHAIRS)) {
+ events.forceSetCursor(CURSOR_CROSSHAIRS);
+ _selectCommand = -1;
+ _vm->_boxSelect = true;
+ } else {
+ Room::walkCursor();
+ }
+}
+
+void AmazonRoom::init4Quads() {
+ if (!_vm->_screen->_vesaMode)
+ return;
+
+ // CHECKME: in the original, this call of tileScreen uses an useless parameter, "TILES.BLK"
+ _game->tileScreen();
+ _vm->_inventory->refreshInventory();
+ _game->updateSummary(_game->_chapter);
+
+ _vm->_screen->setPanel(0);
+ _vm->_screen->clearScreen();
+}
+
+void AmazonRoom::clearRoom() {
+ _game->freeInactivePlayer();
+ Room::clearRoom();
+}
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/amazon/amazon_room.h b/engines/access/amazon/amazon_room.h
new file mode 100644
index 0000000000..6396f80199
--- /dev/null
+++ b/engines/access/amazon/amazon_room.h
@@ -0,0 +1,72 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_AMAZON_ROOM_H
+#define ACCESS_AMAZON_ROOM_H
+
+#include "common/scummsys.h"
+#include "access/room.h"
+
+namespace Access {
+
+class AccessEngine;
+
+namespace Amazon {
+
+class AmazonEngine;
+
+class AmazonRoom : public Room {
+private:
+ AmazonEngine *_game;
+ bool _antOutFlag;
+ const byte *_icon;
+
+ void roomSet();
+protected:
+ virtual void loadRoom(int roomNumber);
+
+ virtual void reloadRoom();
+
+ virtual void reloadRoom1();
+
+ virtual void setupRoom();
+
+ virtual void mainAreaClick();
+
+ virtual void clearRoom();
+
+ virtual void walkCursor();
+public:
+ AmazonRoom(AccessEngine *vm);
+
+ virtual ~AmazonRoom();
+
+ virtual void init4Quads();
+
+ virtual void roomMenu();
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_AMAZON_ROOM_H */
diff --git a/engines/access/amazon/amazon_scripts.cpp b/engines/access/amazon/amazon_scripts.cpp
new file mode 100644
index 0000000000..633188e4dd
--- /dev/null
+++ b/engines/access/amazon/amazon_scripts.cpp
@@ -0,0 +1,516 @@
+/* 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 "access/access.h"
+#include "access/resources.h"
+#include "access/amazon/amazon_game.h"
+#include "access/amazon/amazon_resources.h"
+#include "access/amazon/amazon_scripts.h"
+
+namespace Access {
+
+namespace Amazon {
+
+AmazonScripts::AmazonScripts(AccessEngine *vm) : Scripts(vm) {
+ _game = (AmazonEngine *)_vm;
+}
+
+void AmazonScripts::cLoop() {
+ searchForSequence();
+ _vm->_images.clear();
+ _vm->_buffer2.copyFrom(_vm->_buffer1);
+ _vm->_oldRects.clear();
+ _vm->_scripts->executeScript();
+ _vm->plotList1();
+ _vm->copyBlocks();
+}
+
+void AmazonScripts::mWhile1() {
+ _vm->_screen->setDisplayScan();
+ _vm->_screen->fadeOut();
+ _vm->_events->hideCursor();
+
+ _vm->_files->loadScreen(14, 0);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_events->showCursor();
+
+ _vm->_screen->setIconPalette();
+ _vm->_screen->forceFadeIn();
+
+ Resource *spriteData = _vm->_files->loadFile(14, 6);
+ _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 2100;
+
+ do {
+ cLoop();
+ _sequence = 2100;
+ } while (_vm->_flags[52] == 1);
+
+ _vm->_buffer1.copyTo(_vm->_screen);
+ _vm->_buffer2.copyTo(&_vm->_buffer1);
+
+ _game->establish(-1, 14);
+
+ spriteData = _vm->_files->loadFile(14, 7);
+ _vm->_objectsTable[1] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_sound->playSound(0);
+ _vm->_screen->setDisplayScan();
+ _vm->_events->hideCursor();
+
+ _vm->_files->loadScreen(14, 1);
+ _vm->_screen->setPalette();
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_events->showCursor();
+
+ _vm->_screen->setIconPalette();
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 2200;
+
+ _vm->_sound->queueSound(0, 14, 15);
+
+ do {
+ cLoop();
+ _sequence = 2200;
+ } while (_vm->_flags[52] == 2);
+
+ _vm->_screen->setDisplayScan();
+ _vm->_events->hideCursor();
+
+ _vm->_files->loadScreen(14, 2);
+ _vm->_screen->setPalette();
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_events->showCursor();
+
+ _vm->_screen->setIconPalette();
+ _vm->freeCells();
+
+ spriteData = _vm->_files->loadFile(14, 8);
+ _vm->_objectsTable[2] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 2300;
+ _vm->_sound->playSound(0);
+
+ do {
+ cLoop();
+ _sequence = 2300;
+ } while (_vm->_flags[52] == 3);
+
+ _vm->freeCells();
+ spriteData = _vm->_files->loadFile(14, 9);
+ _vm->_objectsTable[3] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_screen->setDisplayScan();
+ _vm->_events->hideCursor();
+
+ _vm->_files->loadScreen(14, 3);
+ _vm->_screen->setPalette();
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_events->showCursor();
+
+ _vm->_screen->setIconPalette();
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 2400;
+
+ do {
+ cLoop();
+ _sequence = 2400;
+ } while (_vm->_flags[52] == 4);
+}
+
+void AmazonScripts::mWhile2() {
+ _vm->_screen->setDisplayScan();
+ _vm->_screen->fadeOut();
+ _vm->_events->hideCursor();
+
+ _vm->_files->loadScreen(14, 0);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_events->showCursor();
+
+ _vm->_screen->setIconPalette();
+ _vm->_screen->forceFadeIn();
+
+ Resource *spriteData = _vm->_files->loadFile(14, 6);
+ _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 2100;
+
+ do {
+ cLoop();
+ _sequence = 2100;
+ } while (_vm->_flags[52] == 1);
+
+ _vm->_screen->fadeOut();
+ _vm->freeCells();
+ spriteData = _vm->_files->loadFile(14, 9);
+ _vm->_objectsTable[3] = new SpriteResource(_vm, spriteData);
+ delete spriteData;
+
+ _vm->_screen->setDisplayScan();
+ _vm->_events->hideCursor();
+
+ _vm->_files->loadScreen(14, 3);
+ _vm->_screen->setPalette();
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_events->showCursor();
+
+ _vm->_screen->setIconPalette();
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 2400;
+
+ do {
+ cLoop();
+ _sequence = 2400;
+ } while (_vm->_flags[52] == 4);
+}
+
+void AmazonScripts::mWhile(int param1) {
+ switch(param1) {
+ case 1:
+ mWhile1();
+ break;
+ case 2:
+ _game->_plane->mWhileFly();
+ break;
+ case 3:
+ _game->_plane->mWhileFall();
+ break;
+ case 4:
+ _game->_jungle->mWhileJWalk();
+ break;
+ case 5:
+ _game->_jungle->mWhileDoOpen();
+ break;
+ case 6:
+ _game->_river->mWhileDownRiver();
+ break;
+ case 7:
+ mWhile2();
+ break;
+ case 8:
+ _game->_jungle->mWhileJWalk2();
+ break;
+ default:
+ break;
+ }
+}
+
+void AmazonScripts::loadBackground(int param1, int param2) {
+ _vm->_files->_setPaletteFlag = false;
+ _vm->_files->loadScreen(param1, param2);
+
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+
+ _vm->_screen->forceFadeIn();
+}
+
+void AmazonScripts::loadNSound(int param1, int param2) {
+ Resource *sound = _vm->_files->loadFile(param1, param2);
+ _vm->_sound->_soundTable.push_back(SoundEntry(sound, 1));
+}
+
+void AmazonScripts::setInactive() {
+ _game->_rawInactiveX = _vm->_player->_rawPlayer.x;
+ _game->_rawInactiveY = _vm->_player->_rawPlayer.y;
+ _game->_charSegSwitch = false;
+
+ mWhile(_game->_rawInactiveY);
+}
+
+void AmazonScripts::boatWalls(int param1, int param2) {
+ if (param1 == 1)
+ _vm->_room->_plotter._walls[42] = Common::Rect(96, 27, 96 + 87, 27 + 42);
+ else {
+ _vm->_room->_plotter._walls[39].bottom = _vm->_room->_plotter._walls[41].bottom = 106;
+ _vm->_room->_plotter._walls[40].left = 94;
+ }
+}
+
+void AmazonScripts::plotInactive() {
+ Player &player = *_vm->_player;
+ InactivePlayer &inactive = _game->_inactive;
+
+ if (_game->_charSegSwitch) {
+ _game->_currentCharFlag = true;
+ SWAP(inactive._altSpritesPtr, player._playerSprites);
+ _game->_charSegSwitch = false;
+ } else if (_game->_jasMayaFlag != (_game->_currentCharFlag ? 1 : 0)) {
+ if (player._playerOff) {
+ _game->_jasMayaFlag = (_game->_currentCharFlag ? 1 : 0);
+ } else {
+ _game->_currentCharFlag = (_game->_jasMayaFlag == 1);
+ int tmpX = _game->_rawInactiveX;
+ int tmpY = _game->_rawInactiveY;
+ _game->_rawInactiveX = player._rawPlayer.x;
+ _game->_rawInactiveY = player._rawPlayer.y;
+ player._rawPlayer.x = tmpX;
+ player._rawPlayer.y = tmpY;
+ _game->_inactiveYOff = player._playerOffset.y;
+ player.calcManScale();
+
+ SWAP(inactive._altSpritesPtr, player._playerSprites);
+ _vm->_room->setWallCodes();
+ }
+ }
+
+ _game->_flags[155] = 0;
+ if (_game->_rawInactiveX >= 152 && _game->_rawInactiveX <= 167 &&
+ _game->_rawInactiveY >= 158 && _game->_rawInactiveY <= 173) {
+ _game->_flags[155] = 1;
+ } else {
+ _game->_flags[160] = 0;
+ if (!_game->_jasMayaFlag && _game->_rawInactiveX >= 266 && _game->_rawInactiveX <= 290
+ && _game->_rawInactiveY >= 70 && _game->_rawInactiveY <= 87) {
+ _game->_flags[160] = 1;
+ }
+ }
+
+ inactive._flags &= ~IMGFLAG_UNSCALED;
+ inactive._flags &= ~IMGFLAG_BACKWARDS;
+ inactive._position.x = _game->_rawInactiveX;
+ inactive._position.y = _game->_rawInactiveY - _game->_inactiveYOff;
+ inactive._offsetY = _game->_inactiveYOff;
+ inactive._spritesPtr = inactive._altSpritesPtr;
+
+ _vm->_images.addToList(_game->_inactive);
+}
+
+void AmazonScripts::executeSpecial(int commandIndex, int param1, int param2) {
+ switch (commandIndex) {
+ case 0:
+ warning("TODO: DEMO - RESETAN");
+ break;
+ case 1:
+ _vm->establish(param1, param2);
+ break;
+ case 2:
+ loadBackground(param1, param2);
+ break;
+ case 3:
+ if (_vm->isDemo())
+ warning("TODO: DEMO - LOADCELLSET");
+ else
+ _game->_cast->doCast(param1);
+ break;
+ case 4:
+ if (_vm->isDemo())
+ loadNSound(param1, param2);
+ else
+ setInactive();
+ break;
+ case 5:
+ warning("TODO: DEMO - UNLOADCELLSET");
+ break;
+ case 6:
+ mWhile(param1);
+ break;
+ case 7:
+ warning("TODO: DEMO - ADDMONEY");
+ break;
+ case 8:
+ warning("TODO: DEMO - CHKMONEY");
+ break;
+ case 9:
+ _game->_guard->doGuard();
+ break;
+ case 10:
+ _vm->_midi->newMusic(param1, param2);
+ break;
+ case 11:
+ plotInactive();
+ break;
+ case 13:
+ _game->_river->doRiver();
+ break;
+ case 14:
+ _game->_ant->doAnt();
+ break;
+ case 15:
+ boatWalls(param1, param2);
+ break;
+ default:
+ warning("Unexpected Special code %d - Skipped", commandIndex);
+ }
+}
+
+typedef void(AmazonScripts::*AmazonScriptMethodPtr)();
+
+void AmazonScripts::executeCommand(int commandIndex) {
+ static const AmazonScriptMethodPtr COMMAND_LIST[] = {
+ &AmazonScripts::cmdHelp, &AmazonScripts::cmdCycleBack,
+ &AmazonScripts::cmdChapter, &AmazonScripts::cmdSetHelp,
+ &AmazonScripts::cmdCenterPanel, &AmazonScripts::cmdMainPanel,
+ &AmazonScripts::CMDRETFLASH
+ };
+
+ if (commandIndex >= 73)
+ (this->*COMMAND_LIST[commandIndex - 73])();
+ else
+ Scripts::executeCommand(commandIndex);
+}
+
+void AmazonScripts::cmdHelp() {
+ Common::String helpMessage = readString();
+
+ if (_game->_helpLevel == 0) {
+ _game->_timers.saveTimers();
+ _game->_useItem = 0;
+
+ if (_game->_noHints) {
+ printString(NO_HELP_MESSAGE);
+ return;
+ } else if (_game->_hintLevel == 0) {
+ printString(NO_HINTS_MESSAGE);
+ return;
+ }
+ }
+
+ int level = _game->_hintLevel - 1;
+ if (level < _game->_helpLevel)
+ _game->_moreHelp = 0;
+
+ _game->drawHelp(helpMessage);
+
+ while (!_vm->shouldQuit()) {
+ while (!_vm->shouldQuit() && !_vm->_events->_leftButton)
+ _vm->_events->pollEventsAndWait();
+
+ _vm->_events->debounceLeft();
+
+ static const Common::Rect butn1 = Common::Rect(HELP1COORDS[0][0], HELP1COORDS[0][2], HELP1COORDS[0][1], HELP1COORDS[0][3]);
+ static const Common::Rect butn2 = Common::Rect(HELP1COORDS[1][0], HELP1COORDS[1][2], HELP1COORDS[1][1], HELP1COORDS[1][3]);
+ const Common::Point pt = _vm->_events->_mousePos;
+
+ int choice = -1;
+ if (butn1.contains(pt))
+ choice = 0;
+ else if (butn2.contains(pt))
+ choice = 1;
+
+ if (choice < 0)
+ continue;
+
+ if (choice == 1) {
+ // Done button selected
+ _game->_helpLevel = 0;
+ _game->_moreHelp = 1;
+ _game->_useItem = 0;
+ _vm->_events->hideCursor();
+ if (_vm->_screen->_vesaMode) {
+ _vm->_screen->restoreScreen();
+ _vm->_screen->setPanel(0);
+ } else {
+ _vm->_screen->fadeOut();
+ _vm->_screen->clearBuffer();
+ }
+
+ _vm->_buffer2.copyTo(_vm->_screen);
+ _vm->_screen->restorePalette();
+ _vm->_screen->setPalette();
+ _vm->_events->showCursor();
+
+ delete _vm->_objectsTable[45];
+ _vm->_objectsTable[45] = nullptr;
+ _vm->_timers.restoreTimers();
+ break;
+ } else {
+ // More button selected
+ if ((_game->_moreHelp == 0) || (choice != 0))
+ continue;
+ ++_game->_helpLevel;
+ _game->_useItem = 1;
+ break;
+ }
+ }
+ findNull();
+}
+
+void AmazonScripts::cmdCycleBack() {
+ if (_vm->_startup == -1)
+ _vm->_screen->cyclePaletteBackwards();
+}
+void AmazonScripts::cmdChapter() {
+ if (_vm->isDemo()) {
+ cmdSetHelp();
+ } else {
+ int chapter = _data->readByte();
+ _game->startChapter(chapter);
+ }
+}
+
+void AmazonScripts::cmdSetHelp() {
+ int arrayId = (_data->readUint16LE() & 0xFF) - 1;
+ int helpId = _data->readUint16LE() & 0xFF;
+
+ byte *help = _game->_helpTbl[arrayId];
+ help[helpId] = 1;
+
+ if (_vm->_useItem == 0) {
+ _sequence = 11000;
+ searchForSequence();
+ }
+}
+
+void AmazonScripts::cmdCenterPanel() {
+ if (_vm->_screen->_vesaMode) {
+ _vm->_screen->clearScreen();
+ _vm->_screen->setPanel(3);
+ }
+}
+
+void AmazonScripts::cmdMainPanel() {
+ if (_vm->_screen->_vesaMode) {
+ _vm->_room->init4Quads();
+ _vm->_screen->setPanel(0);
+ }
+}
+
+void AmazonScripts::CMDRETFLASH() {
+ error("TODO CMDRETFLASH");
+}
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/amazon/amazon_scripts.h b/engines/access/amazon/amazon_scripts.h
new file mode 100644
index 0000000000..e10eefb4f5
--- /dev/null
+++ b/engines/access/amazon/amazon_scripts.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_AMAZON_SCRIPTS_H
+#define ACCESS_AMAZON_SCRIPTS_H
+
+#include "common/scummsys.h"
+#include "access/scripts.h"
+
+namespace Access {
+
+namespace Amazon {
+
+class AmazonEngine;
+
+class AmazonScripts : public Scripts {
+private:
+ AmazonEngine *_game;
+protected:
+ virtual void executeSpecial(int commandIndex, int param1, int param2);
+ virtual void executeCommand(int commandIndex);
+
+ void cLoop();
+ void mWhile1();
+ void mWhile2();
+ void mWhile(int param1);
+ void loadBackground(int param1, int param2);
+ void plotInactive();
+ void loadNSound(int param1, int param2);
+ void setInactive();
+ void boatWalls(int param1, int param2);
+
+ void cmdHelp();
+ void cmdCycleBack();
+ void cmdChapter();
+ void cmdSetHelp();
+ void cmdCenterPanel();
+ void cmdMainPanel();
+ void CMDRETFLASH();
+public:
+ AmazonScripts(AccessEngine *vm);
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_AMAZON_SCRIPTS_H */
diff --git a/engines/access/animation.cpp b/engines/access/animation.cpp
new file mode 100644
index 0000000000..548e7db02d
--- /dev/null
+++ b/engines/access/animation.cpp
@@ -0,0 +1,342 @@
+/* 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/endian.h"
+#include "common/memstream.h"
+#include "access/access.h"
+#include "access/animation.h"
+
+namespace Access {
+
+AnimationResource::AnimationResource(AccessEngine *vm, Resource *res) {
+ int count = res->_stream->readUint16LE();
+
+ Common::Array<int> offsets;
+ for (int i = 0; i < count; ++i)
+ offsets.push_back(res->_stream->readUint32LE());
+
+ _animations.reserve(count);
+ for (int i = 0; i < count; ++i) {
+ res->_stream->seek(offsets[i]);
+ Animation *anim = new Animation(vm, res->_stream);
+ _animations.push_back(anim);
+ }
+}
+
+AnimationResource::~AnimationResource() {
+ for (int i = 0; i < (int)_animations.size(); ++i)
+ delete _animations[i];
+}
+
+/*------------------------------------------------------------------------*/
+
+Animation::Animation(AccessEngine *vm, Common::SeekableReadStream *stream) : Manager(vm) {
+ uint32 startOfs = stream->pos();
+
+ _type = stream->readByte();
+ _scaling = stream->readSByte();
+ stream->readByte(); // unk
+ _frameNumber = stream->readByte();
+ _initialTicks = stream->readUint16LE();
+ stream->readUint16LE(); // unk
+ stream->readUint16LE(); // unk
+ _loopCount = stream->readSint16LE();
+ _countdownTicks = stream->readUint16LE();
+ _currentLoopCount = stream->readSint16LE();
+ stream->readUint16LE(); // unk
+
+ Common::Array<uint16> frameOffsets;
+ uint16 ofs;
+ while ((ofs = stream->readUint16LE()) != 0)
+ frameOffsets.push_back(ofs);
+
+ for (int i = 0; i < (int)frameOffsets.size(); i++) {
+ stream->seek(startOfs + frameOffsets[i]);
+
+ AnimationFrame *frame = new AnimationFrame(stream, startOfs);
+ _frames.push_back(frame);
+ }
+}
+
+Animation::~Animation() {
+ for (uint i = 0; i < _frames.size(); ++i)
+ delete _frames[i];
+}
+
+typedef void(Animation::*AnimationMethodPtr)();
+
+void Animation::animate() {
+ static const AnimationMethodPtr METHODS[8] = {
+ &Animation::anim0, &Animation::anim1, &Animation::anim2, &Animation::anim3,
+ &Animation::anim4, &Animation::animNone, &Animation::animNone, &Animation::anim7
+ };
+
+ (this->*METHODS[_type])();
+}
+
+void Animation::anim0() {
+ if (_currentLoopCount != -1) {
+ if (_countdownTicks != 0) {
+ setFrame1(calcFrame());
+ } else {
+ _countdownTicks = _initialTicks;
+ ++_frameNumber;
+ AnimationFrame *frame = calcFrame();
+
+ if (frame == nullptr) {
+ _frameNumber = 0;
+ _currentLoopCount = -1;
+ frame = calcFrame();
+ }
+
+ setFrame(frame);
+ }
+ }
+}
+
+void Animation::anim1() {
+ if (_currentLoopCount == -1 || _countdownTicks != 0) {
+ setFrame1(calcFrame());
+ } else {
+ _countdownTicks = _initialTicks;
+ ++_frameNumber;
+ AnimationFrame *frame = calcFrame();
+
+ if (frame == nullptr) {
+ --_frameNumber;
+ _currentLoopCount = -1;
+ frame = calcFrame();
+ }
+
+ setFrame(frame);
+ }
+}
+
+void Animation::anim2() {
+ if (_countdownTicks != 0) {
+ setFrame1(calcFrame());
+ } else {
+ _countdownTicks = _initialTicks;
+ ++_frameNumber;
+ AnimationFrame *frame = calcFrame();
+
+ if (frame == nullptr) {
+ _frameNumber = 0;
+ frame = calcFrame();
+ }
+
+ setFrame(frame);
+ }
+}
+
+void Animation::anim3() {
+ if (_currentLoopCount != -1) {
+ if (_countdownTicks != 0) {
+ setFrame1(calcFrame());
+ } else {
+ _countdownTicks = _initialTicks;
+ ++_frameNumber;
+ AnimationFrame *frame = calcFrame();
+
+ if (frame == nullptr) {
+ --_currentLoopCount;
+ _frameNumber = 0;
+ frame = calcFrame();
+ }
+
+ setFrame(frame);
+ }
+ }
+}
+
+void Animation::anim4() {
+ if (_currentLoopCount == -1 || _countdownTicks != 0) {
+ setFrame1(calcFrame());
+ } else {
+ _countdownTicks = _initialTicks;
+ ++_frameNumber;
+ AnimationFrame *frame = calcFrame();
+
+ if (frame == nullptr) {
+ if (--_currentLoopCount == -1) {
+ setFrame1(calcFrame());
+ return;
+ } else {
+ _frameNumber = 0;
+ frame = calcFrame();
+ }
+ }
+
+ setFrame(frame);
+ }
+}
+
+void Animation::animNone() {
+ // Empty implementation
+}
+
+void Animation::anim7() {
+ setFrame(calcFrame1());
+}
+
+AnimationFrame *Animation::calcFrame() {
+ return (_frameNumber < (int)_frames.size()) ? _frames[_frameNumber] : nullptr;
+}
+
+AnimationFrame *Animation::calcFrame1() {
+ return _frames[0];
+}
+
+void Animation::setFrame(AnimationFrame *frame) {
+ assert(frame);
+ _countdownTicks += frame->_frameDelay;
+ setFrame1(frame);
+}
+
+void Animation::setFrame1(AnimationFrame *frame) {
+ _vm->_animation->_base.x = frame->_baseX;
+ _vm->_animation->_base.y = frame->_baseY;
+
+ // Loop to add image draw requests for the parts of the frame
+ for (uint i = 0; i < frame->_parts.size(); ++i) {
+ AnimationFramePart *part = frame->_parts[i];
+ ImageEntry ie;
+
+ // Set the flags
+ ie._flags = part->_flags & ~IMGFLAG_UNSCALED;
+ if (_vm->_animation->_frameScale == -1)
+ ie._flags |= IMGFLAG_UNSCALED;
+
+ // Set the other fields
+ ie._spritesPtr = _vm->_objectsTable[part->_spritesIndex];
+ ie._frameNumber = part->_frameIndex;
+ ie._position = part->_position + _vm->_animation->_base;
+ ie._offsetY = part->_offsetY - ie._position.y;
+
+ _vm->_images.addToList(ie);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+AnimationFrame::AnimationFrame(Common::SeekableReadStream *stream, int startOffset) {
+ uint16 nextOffset;
+
+ stream->readByte(); // unk
+ _baseX = stream->readUint16LE();
+ _baseY = stream->readUint16LE();
+ _frameDelay = stream->readUint16LE();
+ nextOffset = stream->readUint16LE();
+
+ while (nextOffset != 0) {
+ stream->seek(startOffset + nextOffset);
+
+ AnimationFramePart *framePart = new AnimationFramePart(stream);
+ _parts.push_back(framePart);
+
+ nextOffset = stream->readUint16LE();
+ }
+}
+
+AnimationFrame::~AnimationFrame() {
+ for (int i = 0; i < (int)_parts.size(); ++i)
+ delete _parts[i];
+}
+
+/*------------------------------------------------------------------------*/
+
+AnimationFramePart::AnimationFramePart(Common::SeekableReadStream *stream) {
+ _flags = stream->readByte();
+ _spritesIndex = stream->readByte();
+ _frameIndex = stream->readByte();
+ _position.x = stream->readUint16LE();
+ _position.y = stream->readUint16LE();
+ _offsetY = stream->readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
+AnimationManager::AnimationManager(AccessEngine *vm) : Manager(vm) {
+ _animation = nullptr;
+ _animStart = nullptr;
+ _frameScale = 0;
+}
+
+AnimationManager::~AnimationManager() {
+ delete _animation;
+}
+
+void AnimationManager::freeAnimationData() {
+ delete _animation;
+ _animation = nullptr;
+ _animStart = nullptr;
+}
+
+void AnimationManager::clearTimers() {
+ _animationTimers.clear();
+}
+
+void AnimationManager::loadAnimations(Resource *res) {
+ _animationTimers.clear();
+ delete _animation;
+ _animation = new AnimationResource(_vm, res);
+}
+
+
+Animation *AnimationManager::setAnimation(int animId) {
+ Animation *anim = findAnimation(animId);
+ if (!anim)
+ return nullptr;
+
+ anim->_countdownTicks = anim->_initialTicks;
+ anim->_frameNumber = 0;
+
+ anim->_currentLoopCount = (anim->_type != 3 && anim->_type != 4) ? 0 :
+ anim->_loopCount;
+ anim->_field10 = 0;
+
+ return anim;
+}
+
+void AnimationManager::setAnimTimer(Animation *anim) {
+ _animationTimers.push_back(anim);
+}
+
+Animation *AnimationManager::findAnimation(int animId) {
+ _animStart = (_animation == nullptr) ? nullptr : _animation->getAnimation(animId);
+ return _animStart;
+}
+
+void AnimationManager::animate(int animId) {
+ Animation *anim = findAnimation(animId);
+ _frameScale = anim->_scaling;
+ anim->animate();
+}
+
+void AnimationManager::updateTimers() {
+ for (uint idx = 0; idx < _animationTimers.size(); ++idx) {
+ if (_animationTimers[idx]->_countdownTicks > 0)
+ _animationTimers[idx]->_countdownTicks--;
+ }
+}
+
+} // End of namespace Access
diff --git a/engines/access/animation.h b/engines/access/animation.h
new file mode 100644
index 0000000000..722f5430ab
--- /dev/null
+++ b/engines/access/animation.h
@@ -0,0 +1,140 @@
+/* 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 ACCESS_ANIMATION_H
+#define ACCESS_ANIMATION_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/memstream.h"
+#include "access/data.h"
+#include "access/files.h"
+
+namespace Access {
+
+class AnimationResource;
+class Animation;
+class AnimationFrame;
+class AnimationFramePart;
+
+class AnimationManager : public Manager {
+private:
+ Common::Array<Animation *> _animationTimers;
+ AnimationResource *_animation;
+public:
+ Animation *_animStart;
+ Common::Point _base;
+ int _frameScale;
+public:
+ AnimationManager(AccessEngine *vm);
+ ~AnimationManager();
+ void freeAnimationData();
+ void loadAnimations(Resource *res);
+
+ Animation *findAnimation(int animId);
+ Animation *setAnimation(int animId);
+
+ void animate(int animId);
+
+ /**
+ * Clear the list of currently active animations
+ */
+ void clearTimers();
+
+ /**
+ * Add an animation to the list of currently animating ones
+ */
+ void setAnimTimer(Animation *anim);
+
+ /**
+ * Update the timing of all currently active animation
+ */
+ void updateTimers();
+};
+
+class AnimationResource {
+private:
+ Common::Array<Animation *> _animations;
+public:
+ AnimationResource(AccessEngine *vm, Resource *res);
+ ~AnimationResource();
+
+ int getCount() { return _animations.size(); }
+ Animation *getAnimation(int idx) { return _animations[idx]; }
+};
+
+class Animation : public Manager {
+private:
+ Common::Array<AnimationFrame *> _frames;
+
+ void anim0();
+ void anim1();
+ void anim2();
+ void anim3();
+ void anim4();
+ void animNone();
+ void anim7();
+
+ AnimationFrame *calcFrame();
+ AnimationFrame *calcFrame1();
+ void setFrame(AnimationFrame *frame);
+ void setFrame1(AnimationFrame *frame);
+public:
+ int _type;
+ int _scaling;
+ int _frameNumber;
+ int _initialTicks;
+ int _loopCount;
+ int _countdownTicks;
+ int _currentLoopCount;
+ int _field10;
+public:
+ Animation(AccessEngine *vm, Common::SeekableReadStream *stream);
+ ~Animation();
+
+ void animate();
+};
+
+class AnimationFrame {
+public:
+ int _baseX, _baseY;
+ int _frameDelay;
+ Common::Array<AnimationFramePart *> _parts;
+public:
+ AnimationFrame(Common::SeekableReadStream *stream, int startOffset);
+ ~AnimationFrame();
+};
+
+class AnimationFramePart {
+public:
+ byte _flags;
+ int _spritesIndex;
+ int _frameIndex;
+ Common::Point _position;
+ int _offsetY;
+public:
+ AnimationFramePart(Common::SeekableReadStream *stream);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_ANIMATION_H */
diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp
new file mode 100644
index 0000000000..38af7add00
--- /dev/null
+++ b/engines/access/asurface.cpp
@@ -0,0 +1,344 @@
+/* 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/algorithm.h"
+#include "common/endian.h"
+#include "common/memstream.h"
+#include "access/access.h"
+#include "access/asurface.h"
+
+namespace Access {
+
+SpriteResource::SpriteResource(AccessEngine *vm, Resource *res) {
+ Common::Array<uint32> offsets;
+ int count = res->_stream->readUint16LE();
+
+ for (int i = 0; i < count; i++)
+ offsets.push_back(res->_stream->readUint32LE());
+ offsets.push_back(res->_size); // For easier calculations of Noctropolis sizes
+
+ // Build up the frames
+ for (int i = 0; i < count; ++i) {
+ res->_stream->seek(offsets[i]);
+ int frameSize = offsets[i + 1] - offsets[i];
+
+ SpriteFrame *frame = new SpriteFrame(vm, res->_stream, frameSize);
+ _frames.push_back(frame);
+ }
+}
+
+SpriteResource::~SpriteResource() {
+ for (uint i = 0; i < _frames.size(); ++i)
+ delete _frames[i];
+}
+
+SpriteFrame::SpriteFrame(AccessEngine *vm, Common::SeekableReadStream *stream, int frameSize) {
+ int xSize = stream->readUint16LE();
+ int ySize = stream->readUint16LE();
+ create(xSize, ySize);
+
+ // Empty surface
+ byte *data = (byte *)getPixels();
+ Common::fill(data, data + w * h, 0);
+
+ // Decode the data
+ for (int y = 0; y < h; ++y) {
+ int offset = stream->readByte();
+ int len = stream->readByte();
+ assert((offset + len) <= w);
+
+ byte *destP = (byte *)getBasePtr(offset, y);
+ stream->read(destP, len);
+ }
+}
+
+SpriteFrame::~SpriteFrame() {
+ free();
+}
+
+/*------------------------------------------------------------------------*/
+
+ImageEntry::ImageEntry() {
+ _frameNumber = 0;
+ _spritesPtr = nullptr;
+ _offsetY = 0;
+ _flags = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+static bool sortImagesY(const ImageEntry &ie1, const ImageEntry &ie2) {
+ int v = (ie1._position.y + ie1._offsetY) - (ie2._position.y + ie2._offsetY);
+ return (v < 0) || (v == 0 && ie1._position.y <= ie2._position.y);
+}
+
+void ImageEntryList::addToList(ImageEntry &ie) {
+ assert(size() < 35);
+ push_back(ie);
+ Common::sort(begin(), end(), sortImagesY);
+}
+
+/*------------------------------------------------------------------------*/
+
+int ASurface::_clipWidth;
+int ASurface::_clipHeight;
+
+ASurface::ASurface() {
+ _leftSkip = _rightSkip = 0;
+ _topSkip = _bottomSkip = 0;
+ _lastBoundsX = _lastBoundsY = 0;
+ _lastBoundsW = _lastBoundsH = 0;
+ _orgX1 = _orgY1 = 0;
+ _orgX2 = _orgY2 = 0;
+ _lColor = 0;
+}
+
+ASurface::~ASurface() {
+ free();
+ _savedBlock.free();
+}
+
+void ASurface::create(uint16 width, uint16 height) {
+ Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+}
+
+void ASurface::clearBuffer() {
+ byte *pSrc = (byte *)getPixels();
+ Common::fill(pSrc, pSrc + w * h, 0);
+}
+
+bool ASurface::clip(Common::Rect &r) {
+ int skip;
+ _leftSkip = _rightSkip = 0;
+ _topSkip = _bottomSkip = 0;
+
+ if (r.left > _clipWidth || r.left < 0) {
+ if (r.left >= 0)
+ return true;
+
+ skip = -r.left;
+ r.setWidth(r.width() - skip);
+ _leftSkip = skip;
+ r.moveTo(0, r.top);
+ }
+
+ int right = r.right - 1;
+ if (right < 0)
+ return true;
+ else if (right > _clipWidth) {
+ skip = right - _clipWidth;
+ r.setWidth(r.width() - skip);
+ _rightSkip = skip;
+ }
+
+ if (r.top > _clipHeight || r.top < 0) {
+ if (r.top >= 0)
+ return true;
+
+ skip = -r.top;
+ r.setHeight(r.height() - skip);
+ _topSkip = skip;
+ r.moveTo(r.left, 0);
+ }
+
+ int bottom = r.bottom - 1;
+ if (bottom < 0)
+ return true;
+ else if (bottom > _clipHeight) {
+ skip = bottom - _clipHeight;
+ _bottomSkip = skip;
+ r.setHeight(r.height() - skip);
+ }
+
+ return false;
+}
+
+void ASurface::plotImage(SpriteResource *sprite, int frameNum, const Common::Point &pt) {
+ SpriteFrame *frame = sprite->getFrame(frameNum);
+ Common::Rect r(pt.x, pt.y, pt.x + frame->w, pt.y + frame->h);
+
+ if (!clip(r)) {
+ _lastBoundsX = r.left;
+ _lastBoundsY = r.top;
+ _lastBoundsW = r.width();
+ _lastBoundsH = r.height();
+
+ plotF(frame, pt);
+ }
+}
+
+void ASurface::transCopyFrom(ASurface *src, const Common::Point &destPos) {
+ if (getPixels() == nullptr)
+ create(w, h);
+
+ for (int yp = 0; yp < src->h; ++yp) {
+ const byte *srcP = (const byte *)src->getBasePtr(0, yp);
+ byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
+
+ for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
+ if (*srcP != 0)
+ *destP = *srcP;
+ }
+ }
+}
+
+void ASurface::transCopyFrom(ASurface *src, const Common::Rect &bounds) {
+ const int SCALE_LIMIT = 0x100;
+ int scaleX = SCALE_LIMIT * bounds.width() / src->w;
+ int scaleY = SCALE_LIMIT * bounds.height() / src->h;
+ int scaleXCtr = 0, scaleYCtr = 0;
+
+ for (int yCtr = 0, destY = bounds.top; yCtr < src->h; ++yCtr) {
+ // Handle skipping lines if Y scaling
+ scaleYCtr += scaleY;
+ if (scaleYCtr < SCALE_LIMIT)
+ continue;
+ scaleYCtr -= SCALE_LIMIT;
+
+ // Handle off-screen lines
+ if (destY >= this->h)
+ break;
+
+ if (destY >= 0) {
+ // Handle drawing the line
+ const byte *pSrc = (const byte *)src->getBasePtr(0, yCtr);
+ byte *pDest = (byte *)getBasePtr(bounds.left, destY);
+ scaleXCtr = 0;
+ int x = bounds.left;
+
+ for (int xCtr = 0; xCtr < src->w; ++xCtr, ++pSrc) {
+ // Handle horizontal scaling
+ scaleXCtr += scaleX;
+ if (scaleXCtr < SCALE_LIMIT)
+ continue;
+ scaleXCtr -= SCALE_LIMIT;
+
+ // Only handle on-screen pixels
+ if (x >= this->w)
+ break;
+ if (x >= 0 && *pSrc != 0)
+ *pDest = *pSrc;
+
+ ++pDest;
+ ++x;
+ }
+ }
+
+ ++destY;
+ }
+}
+
+void ASurface::transCopyFrom(ASurface &src) {
+ copyFrom(src);
+}
+
+void ASurface::copyFrom(Graphics::Surface &src) {
+ for (int y = 0; y < src.h; ++y) {
+ const byte *srcP = (const byte *)src.getBasePtr(0, y);
+ byte *destP = (byte *)getBasePtr(0, y);
+ Common::copy(srcP, srcP + src.w, destP);
+ }
+}
+
+void ASurface::copyBuffer(Graphics::Surface *src) {
+ copyFrom(*src);
+}
+
+void ASurface::plotF(SpriteFrame *frame, const Common::Point &pt) {
+ sPlotF(frame, Common::Rect(pt.x, pt.y, pt.x + frame->w, pt.y + frame->h));
+}
+
+void ASurface::plotB(SpriteFrame *frame, const Common::Point &pt) {
+ sPlotB(frame, Common::Rect(pt.x, pt.y, pt.x + frame->w, pt.y + frame->h));
+}
+
+void ASurface::sPlotF(SpriteFrame *frame, const Common::Rect &bounds) {
+ transCopyFrom(frame, bounds);
+}
+
+void ASurface::sPlotB(SpriteFrame *frame, const Common::Rect &bounds) {
+ ASurface flippedFrame;
+ frame->flipHorizontal(flippedFrame);
+
+ transCopyFrom(&flippedFrame, bounds);
+}
+
+void ASurface::copyBlock(ASurface *src, const Common::Rect &bounds) {
+ copyRectToSurface(*src, bounds.left, bounds.top, bounds);
+}
+
+void ASurface::saveBlock(const Common::Rect &bounds) {
+ _savedBounds = bounds;
+ _savedBounds.clip(Common::Rect(0, 0, this->w, this->h));
+
+ _savedBlock.free();
+ _savedBlock.create(bounds.width(), bounds.height(),
+ Graphics::PixelFormat::createFormatCLUT8());
+ _savedBlock.copyRectToSurface(*this, 0, 0, _savedBounds);
+}
+
+void ASurface::restoreBlock() {
+ if (!_savedBounds.isEmpty()) {
+ copyRectToSurface(_savedBlock, _savedBounds.left, _savedBounds.top,
+ Common::Rect(0, 0, _savedBlock.w, _savedBlock.h));
+
+ _savedBlock.free();
+ _savedBounds = Common::Rect(0, 0, 0, 0);
+ }
+}
+
+void ASurface::drawRect() {
+ Graphics::Surface::fillRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2), _lColor);
+}
+
+void ASurface::flipHorizontal(ASurface &dest) {
+ dest.create(this->w, this->h);
+ for (int y = 0; y < h; ++y) {
+ const byte *pSrc = (const byte *)getBasePtr(this->w - 1, y);
+ byte *pDest = (byte *)dest.getBasePtr(0, y);
+
+ for (int x = 0; x < w; ++x, --pSrc, ++pDest)
+ *pDest = *pSrc;
+ }
+}
+
+void ASurface::moveBufferLeft() {
+ byte *p = (byte *)getPixels();
+ Common::copy(p + TILE_WIDTH, p + (w * h), p);
+}
+
+void ASurface::moveBufferRight() {
+ byte *p = (byte *)getPixels();
+ Common::copy_backward(p, p + (pitch * h) - TILE_WIDTH, p + (pitch * h));
+}
+
+void ASurface::moveBufferUp() {
+ byte *p = (byte *)getPixels();
+ Common::copy(p + (pitch * TILE_HEIGHT), p + (pitch * h), p);
+}
+
+void ASurface::moveBufferDown() {
+ byte *p = (byte *)getPixels();
+ Common::copy_backward(p, p + (pitch * (h - TILE_HEIGHT)), p + (pitch * h));
+}
+
+} // End of namespace Access
diff --git a/engines/access/asurface.h b/engines/access/asurface.h
new file mode 100644
index 0000000000..763e3e629e
--- /dev/null
+++ b/engines/access/asurface.h
@@ -0,0 +1,166 @@
+/* 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 ACCESS_ASURFACE_H
+#define ACCESS_ASURFACE_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/memstream.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "access/data.h"
+
+namespace Access {
+
+class SpriteResource;
+class SpriteFrame;
+
+class ASurface : public Graphics::Surface {
+private:
+ Graphics::Surface _savedBlock;
+
+ void flipHorizontal(ASurface &dest);
+protected:
+ Common::Rect _savedBounds;
+public:
+ int _leftSkip, _rightSkip;
+ int _topSkip, _bottomSkip;
+ int _lastBoundsX, _lastBoundsY;
+ int _lastBoundsW, _lastBoundsH;
+ int _orgX1, _orgY1;
+ int _orgX2, _orgY2;
+ int _lColor;
+
+ Common::Point _printOrg;
+ Common::Point _printStart;
+ int _maxChars;
+public:
+ static int _clipWidth, _clipHeight;
+public:
+ ASurface();
+
+ virtual ~ASurface();
+
+ void create(uint16 width, uint16 height);
+
+ void clearBuffer();
+
+ bool clip(Common::Rect &r);
+
+ void plotImage(SpriteResource *sprite, int frameNum, const Common::Point &pt);
+
+ /**
+ * Scaled draw frame in forward orientation
+ */
+ void sPlotF(SpriteFrame *frame, const Common::Rect &bounds);
+
+ /**
+ * Scaled draw frame in backwards orientation
+ */
+ void sPlotB(SpriteFrame *frame, const Common::Rect &bounds);
+
+ /**
+ * Draw an image full-size in forward orientation
+ */
+ void plotF(SpriteFrame *frame, const Common::Point &pt);
+
+ /**
+ * Draw an image full-size in backwards orientation
+ */
+ void plotB(SpriteFrame *frame, const Common::Point &pt);
+
+ virtual void copyBlock(ASurface *src, const Common::Rect &bounds);
+
+ virtual void restoreBlock();
+
+ virtual void drawRect();
+
+ virtual void transCopyFrom(ASurface *src, const Common::Point &destPos);
+
+ virtual void transCopyFrom(ASurface *src, const Common::Rect &bounds);
+
+ virtual void transCopyFrom(ASurface &src);
+
+ virtual void copyFrom(Graphics::Surface &src);
+
+ virtual void copyBuffer(Graphics::Surface *src);
+
+ virtual void addDirtyRect(const Common::Rect &r) {}
+
+ void copyTo(ASurface *dest) { dest->copyFrom(*this); }
+
+ void saveBlock(const Common::Rect &bounds);
+
+ void moveBufferLeft();
+
+ void moveBufferRight();
+
+ void moveBufferUp();
+
+ void moveBufferDown();
+};
+
+class SpriteFrame : public ASurface {
+public:
+ SpriteFrame(AccessEngine *vm, Common::SeekableReadStream *stream, int frameSize);
+ ~SpriteFrame();
+};
+
+class SpriteResource {
+public:
+ Common::Array<SpriteFrame *> _frames;
+public:
+ SpriteResource(AccessEngine *vm, Resource *res);
+ ~SpriteResource();
+
+ int getCount() { return _frames.size(); }
+
+ SpriteFrame *getFrame(int idx) { return _frames[idx]; }
+};
+
+enum ImageFlag {
+ IMGFLAG_CROPPED = 1,
+ IMGFLAG_BACKWARDS = 2,
+ IMGFLAG_DRAWN = 4,
+ IMGFLAG_UNSCALED = 8
+};
+
+class ImageEntry {
+public:
+ int _frameNumber;
+ SpriteResource *_spritesPtr;
+ int _offsetY;
+ Common::Point _position;
+ int _flags;
+public:
+ ImageEntry();
+};
+
+class ImageEntryList : public Common::Array<ImageEntry> {
+public:
+ void addToList(ImageEntry &ie);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_ASURFACE_H */
diff --git a/engines/access/bubble_box.cpp b/engines/access/bubble_box.cpp
new file mode 100644
index 0000000000..e37a8142e8
--- /dev/null
+++ b/engines/access/bubble_box.cpp
@@ -0,0 +1,282 @@
+/* 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/algorithm.h"
+#include "access/bubble_box.h"
+#include "access/access.h"
+
+namespace Access {
+
+BubbleBox::BubbleBox(AccessEngine *vm) : Manager(vm) {
+ _type = TYPE_2;
+ _bounds = Common::Rect(64, 32, 64 + 130, 32 + 122);
+ _bubbleDisplStr = "";
+ _fieldD = 0;
+ _fieldE = 0;
+ _fieldF = 0;
+ _field10 = 0;
+}
+
+void BubbleBox::load(Common::SeekableReadStream *stream) {
+ _bubbleTitle.clear();
+
+ byte v;
+ while ((v = stream->readByte()) != 0)
+ _bubbleTitle += (char)v;
+
+ _bubbleDisplStr = _bubbleTitle;
+}
+
+void BubbleBox::clearBubbles() {
+ // Loop through the bubble list to restore the screen areas
+ for (uint i = 0; i < _bubbles.size(); ++i) {
+ _vm->_screen->_screenYOff = 0;
+ Common::Rect r = _bubbles[i];
+ r.left -= 2;
+ r.right = MIN(r.right, (int16)_vm->_screen->w);
+
+ _vm->_screen->copyBlock(&_vm->_buffer1, r);
+ }
+
+ // Clear the list
+ _bubbles.clear();
+}
+
+void BubbleBox::placeBubble(const Common::String &msg) {
+ _vm->_screen->_maxChars = 27;
+ placeBubble1(msg);
+}
+
+void BubbleBox::placeBubble1(const Common::String &msg) {
+ _bubbles.clear();
+ _vm->_fonts._charSet._lo = 1;
+ _vm->_fonts._charSet._hi = 8;
+ _vm->_fonts._charFor._lo = 29;
+ _vm->_fonts._charFor._hi = 32;
+
+ calcBubble(msg);
+
+ Common::Rect r = _bubbles[0];
+ r.translate(-2, 0);
+ _vm->_screen->saveBlock(r);
+ printBubble(msg);
+}
+
+void BubbleBox::calcBubble(const Common::String &msg) {
+ // Save points
+ Common::Point printOrg = _vm->_screen->_printOrg;
+ Common::Point printStart = _vm->_screen->_printStart;
+
+ // Figure out maximum width allowed
+ if (_type == TYPE_4) {
+ _vm->_fonts._printMaxX = 110;
+ } else {
+ _vm->_fonts._printMaxX = _vm->_fonts._font2.stringWidth(_bubbleDisplStr);
+ }
+
+ // Start of with a rect with the given starting x and y
+ Common::Rect bounds(printOrg.x - 2, printOrg.y - 10, printOrg.x - 2, printOrg.y - 10);
+
+ // Loop through getting lines
+ Common::String s = msg;
+ Common::String line;
+ int width = 0;
+ bool lastLine;
+ do {
+ lastLine = _vm->_fonts._font2.getLine(s, _vm->_screen->_maxChars * 6, line, width);
+ _vm->_fonts._printMaxX = MAX(width, _vm->_fonts._printMaxX);
+
+ _vm->_screen->_printOrg.y += 6;
+ _vm->_screen->_printOrg.x = _vm->_screen->_printStart.x;
+ } while (!lastLine);
+
+ if (_type == TYPE_4)
+ ++_vm->_screen->_printOrg.y += 6;
+
+ // Determine the width for the area
+ width = (((_vm->_fonts._printMaxX >> 4) + 1) << 4) + 5;
+ if (width >= 24)
+ width += 20 - ((width - 24) % 20);
+ bounds.setWidth(width);
+
+ // Determine the height for area
+ int y = _vm->_screen->_printOrg.y + 6;
+ if (_type == TYPE_4)
+ y += 6;
+ int height = y - bounds.top;
+ bounds.setHeight(height);
+
+ height -= (_type == TYPE_4) ? 30 : 24;
+ if (height >= 0)
+ bounds.setHeight(bounds.height() + 13 - (height % 13));
+
+ // Add the new bounds to the bubbles list
+ _bubbles.push_back(bounds);
+
+ // Restore points
+ _vm->_screen->_printOrg = printOrg;
+ _vm->_screen->_printStart = printStart;
+}
+
+void BubbleBox::printBubble(const Common::String &msg) {
+ drawBubble(_bubbles.size() - 1);
+
+ // Loop through drawing the lines
+ Common::String s = msg;
+ Common::String line;
+ int width = 0;
+ bool lastLine;
+ do {
+ // Get next line
+ Font &font2 = _vm->_fonts._font2;
+ lastLine = font2.getLine(s, _vm->_screen->_maxChars * 6, line, width);
+
+ // Set font colors
+ font2._fontColors[0] = 0;
+ font2._fontColors[1] = 27;
+ font2._fontColors[2] = 28;
+ font2._fontColors[3] = 29;
+
+ int xp = _vm->_screen->_printOrg.x;
+ if (_type == TYPE_4)
+ xp = (_bounds.width() - width) / 2 + _bounds.left - 4;
+
+ // Draw the text
+ font2.drawString(_vm->_screen, line, Common::Point(xp, _vm->_screen->_printOrg.y));
+
+ // Move print position
+ _vm->_screen->_printOrg.y += 6;
+ _vm->_screen->_printOrg.x = _vm->_screen->_printStart.x;
+ } while (!lastLine);
+}
+
+void BubbleBox::drawBubble(int index) {
+ _bounds = _bubbles[index];
+ doBox(0, 0);
+}
+
+void BubbleBox::doBox(int item, int box) {
+ FontManager &fonts = _vm->_fonts;
+ ASurface &screen = *_vm->_screen;
+
+ _startItem = item;
+ _startBox = box;
+
+ // Save state information
+ FontVal charSet = fonts._charSet;
+ FontVal charFor = fonts._charFor;
+ Common::Point printOrg = screen._printOrg;
+ Common::Point printStart = screen._printStart;
+ int charCol = _charCol;
+ int rowOff = _rowOff;
+
+ _vm->_screen->saveScreen();
+ _vm->_screen->setDisplayScan();
+ fonts._charFor._hi = 0xff;
+ fonts._charSet._lo = 1;
+ fonts._charSet._hi = 0;
+
+ if (_type == TYPE_4) {
+ fonts._charFor._lo = 0xFF;
+ error("TODO: filename listing");
+ return;
+ }
+
+ // Get icons data
+ Resource *iconData = _vm->_files->loadFile("ICONS.LZ");
+ SpriteResource *icons = new SpriteResource(_vm, iconData);
+ delete iconData;
+
+ // Set the up boundaries and color to use for the box background
+ _vm->_screen->_orgX1 = _bounds.left - 2;
+ _vm->_screen->_orgY1 = _bounds.top;
+ _vm->_screen->_orgX2 = _bounds.right - 2;
+ _vm->_screen->_orgY2 = _bounds.bottom;
+ _vm->_screen->_lColor = 1;
+
+ int h = _bounds.height() - (_type == TYPE_4 ? 30 : 24);
+ int ySize = (h < 0) ? 0 : (h + 12) / 13;
+ int w = _bounds.width() - 24;
+ int xSize = (w < 0) ? 0 : (w + 19) / 20;
+
+ // Draw a background for the entire area
+ screen.drawRect();
+
+ // Draw images to form the top border
+ int xp, yp;
+ screen.plotImage(icons, 20, Common::Point(screen._orgX1, screen._orgY1));
+ xp = screen._orgX1 + 12;
+ for (int x = 0; x < xSize; ++x, xp += 20)
+ screen.plotImage(icons, 24 + x, Common::Point(xp, screen._orgY1));
+ screen.plotImage(icons, 21, Common::Point(xp, screen._orgY1));
+
+ // Draw images to form the bottom border
+ yp = screen._orgY2 - (_type == TYPE_4 ? 18 : 12);
+ screen.plotImage(icons, (_type == TYPE_4) ? 72 : 22,
+ Common::Point(screen._orgX1, yp));
+ xp = screen._orgX1 + 12;
+ yp += (_type == TYPE_4) ? 4 : 8;
+
+ for (int x = 0; x < xSize; ++x, xp += 20) {
+ screen.plotImage(icons, (_type == TYPE_4 ? 62 : 34) + x,
+ Common::Point(xp, yp));
+ }
+
+ yp = screen._orgY2 - (_type == TYPE_4 ? 18 : 12);
+ screen.plotImage(icons, (_type == TYPE_4) ? 73 : 23, Common::Point(xp, yp));
+
+ if (_type == TYPE_4) {
+ // Further stuff for filename dialog
+ error("TODO: Box type 4");
+ }
+
+ // Draw images to form the sides
+ yp = screen._orgY1 + 12;
+ for (int y = 0; y < ySize; ++y, yp += 13) {
+ screen.plotImage(icons, 44 + y, Common::Point(screen._orgX1, yp));
+ screen.plotImage(icons, 53 + y, Common::Point(screen._orgX2 - 4, yp));
+ }
+
+ // Handle drawing title
+ int titleWidth = _vm->_fonts._font2.stringWidth(_bubbleDisplStr);
+ Font &font2 = _vm->_fonts._font2;
+ font2._fontColors[0] = 0;
+ font2._fontColors[1] = 3;
+ font2._fontColors[2] = 2;
+ font2._fontColors[3] = 1;
+ font2.drawString(_vm->_screen, _bubbleDisplStr, Common::Point(
+ _bounds.left + (_bounds.width() / 2) - (titleWidth / 2), _bounds.top + 1));
+
+ // Restore positional state
+ fonts._charSet = charSet;
+ fonts._charFor = charFor;
+ screen._printOrg = printOrg;
+ screen._printStart = printStart;
+ _charCol = charCol;
+ _rowOff = rowOff;
+ _vm->_screen->restoreScreen();
+
+ // Free icons data
+ delete icons;
+}
+
+} // End of namespace Access
diff --git a/engines/access/bubble_box.h b/engines/access/bubble_box.h
new file mode 100644
index 0000000000..0130344c7e
--- /dev/null
+++ b/engines/access/bubble_box.h
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_BUBBLE_BOX_H
+#define ACCESS_BUBBLE_BOX_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str-array.h"
+#include "common/stream.h"
+#include "common/types.h"
+#include "graphics/surface.h"
+#include "access/data.h"
+
+namespace Access {
+
+class AccessEngine;
+
+enum BoxType { TYPE_2 = 2, TYPE_4 = 4 };
+
+class BubbleBox : public Manager {
+private:
+ int _startItem, _startBox;
+ int _charCol, _rowOff;
+ Common::Point _fileStart;
+public:
+ BoxType _type;
+ Common::Rect _bounds;
+ Common::StringArray _nameIndex;
+ Common::String _bubbleTitle;
+ Common::String _bubbleDisplStr;
+ int _fieldD;
+ int _fieldE;
+ int _fieldF;
+ int _field10;
+
+ Common::Array<Common::Rect> _bubbles;
+public:
+ BubbleBox(AccessEngine *vm);
+
+ void load(Common::SeekableReadStream *stream);
+
+ void clearBubbles();
+
+ void placeBubble(const Common::String &msg);
+ void placeBubble1(const Common::String &msg);
+
+ /**
+ * Calculate the size of a bubble needed to hold a given string
+ */
+ void calcBubble(const Common::String &msg);
+
+ /**
+ * Prints a text bubble and it's contents
+ */
+ void printBubble(const Common::String &msg);
+
+ /*
+ * Draws the background for a text bubble
+ * @param index Index of bounds in _bubbles array
+ */
+ void drawBubble(int index);
+
+ void doBox(int item, int box);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_BUBBLE_BOX_H */
diff --git a/engines/access/char.cpp b/engines/access/char.cpp
new file mode 100644
index 0000000000..5bc6707509
--- /dev/null
+++ b/engines/access/char.cpp
@@ -0,0 +1,162 @@
+/* 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/memstream.h"
+#include "access/access.h"
+#include "access/char.h"
+#include "access/amazon/amazon_resources.h"
+
+namespace Access {
+
+CharEntry::CharEntry(const byte *data) {
+ Common::MemoryReadStream s(data, 999);
+
+ _charFlag = s.readByte();
+ _estabIndex = s.readSint16LE();
+ _screenFile.load(s);
+ _paletteFile.load(s);
+ _startColor = s.readUint16LE();
+ _numColors = s.readUint16LE();
+
+ // Load cells
+ for (byte cell = s.readByte(); cell != 0xff; cell = s.readByte()) {
+ CellIdent ci;
+ ci._cell = cell;
+ ci.load(s);
+
+ _cells.push_back(ci);
+ }
+
+ _animFile.load(s);
+ _scriptFile.load(s);
+
+ for (int16 v = s.readSint16LE(); v != -1; v = s.readSint16LE()) {
+ ExtraCell ec;
+ ec._vid._fileNum = v;
+ ec._vid._subfile = s.readSint16LE();
+ ec._vidSound.load(s);
+
+ _extraCells.push_back(ec);
+ }
+}
+
+CharEntry::CharEntry() {
+ _charFlag = 0;
+ _estabIndex = 0;
+ _startColor = _numColors = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+CharManager::CharManager(AccessEngine *vm) : Manager(vm) {
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ // Setup character list
+ if (_vm->isDemo()) {
+ for (int i = 0; i < 27; ++i)
+ _charTable.push_back(CharEntry(Amazon::CHARTBL_DEMO[i]));
+ } else {
+ for (int i = 0; i < 37; ++i)
+ _charTable.push_back(CharEntry(Amazon::CHARTBL[i]));
+ }
+ break;
+ default:
+ error("Unknown game");
+ }
+
+ _charFlag = 0;
+}
+
+void CharManager::loadChar(int charId) {
+ CharEntry &ce = _charTable[charId];
+ _charFlag = ce._charFlag;
+
+ _vm->_establishFlag = false;
+ if (ce._estabIndex != -1) {
+ _vm->_establishFlag = true;
+ if (!_vm->_establishTable[ce._estabIndex]) {
+ _vm->_establishTable[ce._estabIndex] = true;
+ _vm->establish(0, ce._estabIndex);
+ }
+ }
+
+ if (_charFlag != 0 && _charFlag != 3) {
+ if (!_vm->_establishFlag)
+ _vm->_screen->fadeOut();
+
+ _vm->_files->loadScreen(ce._screenFile._fileNum, ce._screenFile._subfile);
+ _vm->_screen->setIconPalette();
+ _vm->_screen->fadeIn();
+ }
+
+ _vm->_buffer1.copyFrom(*_vm->_screen);
+ _vm->_buffer2.copyFrom(*_vm->_screen);
+ _vm->_screen->setDisplayScan();
+
+ if (_charFlag != 2 && _charFlag != 3) {
+ charMenu();
+ }
+
+ _vm->_screen->_startColor = ce._startColor;
+ _vm->_screen->_numColors = ce._numColors;
+ if (ce._paletteFile._fileNum != -1) {
+ _vm->_screen->loadPalette(ce._paletteFile._fileNum, ce._paletteFile._subfile);
+ }
+ _vm->_screen->setIconPalette();
+ _vm->_screen->setPalette();
+
+ _vm->loadCells(ce._cells);
+ if (ce._animFile._fileNum != -1) {
+ Resource *data = _vm->_files->loadFile(ce._animFile);
+ _vm->_animation->loadAnimations(data);
+ }
+
+ // Load script data
+ _vm->_scripts->freeScriptData();
+ if (ce._scriptFile._fileNum != -1) {
+ Resource *data = _vm->_files->loadFile(ce._scriptFile);
+ _vm->_scripts->setScript(data);
+ }
+
+ // Load extra cells
+ _vm->_extraCells.clear();
+ for (uint i = 0; i < ce._extraCells.size(); ++i)
+ _vm->_extraCells.push_back(ce._extraCells[i]);
+}
+
+void CharManager::charMenu() {
+ Resource *iconData = _vm->_files->loadFile("ICONS.LZ");
+ SpriteResource *spr = new SpriteResource(_vm, iconData);
+ delete iconData;
+
+ Screen &screen = *_vm->_screen;
+ screen.saveScreen();
+ screen.setDisplayScan();
+
+ screen.plotImage(spr, 17, Common::Point(0, 176));
+ screen.plotImage(spr, 18, Common::Point(155, 176));
+
+ screen.restoreScreen();
+ delete spr;
+}
+
+} // End of namespace Access
diff --git a/engines/access/char.h b/engines/access/char.h
new file mode 100644
index 0000000000..e89cdae49f
--- /dev/null
+++ b/engines/access/char.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_CHAR_H
+#define ACCESS_CHAR_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "access/data.h"
+
+namespace Access {
+
+class CharEntry {
+public:
+ int _charFlag;
+ int _estabIndex;
+ FileIdent _screenFile;
+ FileIdent _paletteFile;
+ int _startColor, _numColors;
+ Common::Array<CellIdent> _cells;
+ FileIdent _animFile;
+ FileIdent _scriptFile;
+ Common::Array<ExtraCell> _extraCells;
+public:
+ CharEntry(const byte *data);
+
+ CharEntry();
+};
+
+class CharManager : public Manager {
+private:
+ void charMenu();
+public:
+ Common::Array<CharEntry> _charTable;
+ int _converseMode;
+ int _charFlag;
+
+ // Fields that are included in savegames
+ int _conversation;
+public:
+ CharManager(AccessEngine *vm);
+
+ void loadChar(int charId);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_CHAR_H */
diff --git a/engines/access/configure.engine b/engines/access/configure.engine
new file mode 100644
index 0000000000..b1defce946
--- /dev/null
+++ b/engines/access/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 access "Access" no
diff --git a/engines/access/data.cpp b/engines/access/data.cpp
new file mode 100644
index 0000000000..cf40e81ccb
--- /dev/null
+++ b/engines/access/data.cpp
@@ -0,0 +1,76 @@
+/* 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/algorithm.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/palette.h"
+#include "access/data.h"
+
+namespace Access {
+
+TimerList::TimerList() : Common::Array<TimerEntry>() {
+ _timersSavedFlag = false;
+}
+
+void TimerList::saveTimers() {
+ if (!_timersSavedFlag /* && !_flashbackFlag */) {
+ _savedTimers = *this;
+ _timersSavedFlag = true;
+ }
+}
+
+void TimerList::restoreTimers() {
+ if (_timersSavedFlag /* && !_flashbackFlag */) {
+ clear();
+ *static_cast<Common::Array<TimerEntry> *>(this) = _savedTimers;
+ _timersSavedFlag = false;
+ }
+}
+
+void TimerList::updateTimers() {
+ for (uint i = 0; i < size(); ++i) {
+ TimerEntry &te = (*this)[i];
+ if (te._flag) {
+ if (!--te._timer) {
+ te._timer = te._initTm;
+ te._flag = 0;
+ }
+ }
+ }
+}
+
+void TimerList::synchronize(Common::Serializer &s) {
+ int count = size();
+ s.syncAsUint16LE(count);
+
+ if (!s.isSaving())
+ resize(count);
+
+ for (int i = 0; i < count; ++i) {
+ s.syncAsUint32LE((*this)[i]._initTm);
+ s.syncAsUint32LE((*this)[i]._timer);
+ s.syncAsByte((*this)[i]._flag);
+ }
+}
+
+} // End of namespace Access
diff --git a/engines/access/data.h b/engines/access/data.h
new file mode 100644
index 0000000000..19413ecd7e
--- /dev/null
+++ b/engines/access/data.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 ACCESS_DATA_H
+#define ACCESS_DATA_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "common/types.h"
+#include "graphics/surface.h"
+#include "access/files.h"
+
+namespace Access {
+
+class AccessEngine;
+
+class Manager {
+protected:
+ AccessEngine *_vm;
+public:
+ Manager(AccessEngine *vm) : _vm(vm) {}
+};
+
+struct TimerEntry {
+ int _initTm;
+ int _timer;
+ byte _flag;
+
+ TimerEntry() {
+ _initTm = _timer = 0;
+ _flag = 0;
+ }
+};
+
+class TimerList : public Common::Array<TimerEntry> {
+private:
+ Common::Array<TimerEntry> _savedTimers;
+public:
+ bool _timersSavedFlag;
+public:
+ TimerList();
+
+ /**
+ * Save a copy of all current timers
+ */
+ void saveTimers();
+
+ /**
+ * Resetore the set of previously saved timers
+ */
+ void restoreTimers();
+
+ /**
+ * Update the timer list
+ */
+ void updateTimers();
+
+ /**
+ * Synchronize savegame data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+class ExtraCell {
+public:
+ FileIdent _vid;
+ FileIdent _vidSound;
+};
+
+struct DeathEntry {
+ int _screenId;
+ Common::String _msg;
+};
+
+class DeathList : public Common::Array<DeathEntry> {
+public:
+ Common::Array<CellIdent> _cells;
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_DATA_H */
diff --git a/engines/access/debugger.cpp b/engines/access/debugger.cpp
new file mode 100644
index 0000000000..6cb2bb606c
--- /dev/null
+++ b/engines/access/debugger.cpp
@@ -0,0 +1,164 @@
+/* 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/file.h"
+#include "access/access.h"
+#include "access/debugger.h"
+#include "access/amazon/amazon_game.h"
+
+namespace Access {
+
+static int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+Debugger *Debugger::init(AccessEngine *vm) {
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ return new Amazon::AmazonDebugger(vm);
+ default:
+ return new Debugger(vm);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Debugger::Debugger(AccessEngine *vm) : GUI::Debugger(), _vm(vm) {
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene));
+ registerCmd("cheat", WRAP_METHOD(Debugger, Cmd_Cheat));
+
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ _sceneNumb = Amazon::ROOM_NUMB;
+ _sceneDescr = new Common::String[_sceneNumb];
+ for (int i = 0; i < _sceneNumb; i++)
+ _sceneDescr[i] = Common::String(Amazon::ROOM_DESCR[i]);
+ break;
+ case GType_MartianMemorandum:
+ _sceneNumb = Martian::ROOM_NUMB;
+ _sceneDescr = new Common::String[_sceneNumb];
+ for (int i = 0; i < _sceneNumb; i++)
+ _sceneDescr[i] = Common::String(Martian::ROOM_DESCR[i]);
+ break;
+ default:
+ _sceneDescr = nullptr;
+ _sceneNumb = 0;
+ break;
+ }
+}
+
+Debugger::~Debugger() {
+ delete[] _sceneDescr;
+}
+
+bool Debugger::Cmd_LoadScene(int argc, const char **argv) {
+ switch (argc) {
+ case 1:
+ debugPrintf("Current scene is: %d\n\n", _vm->_player->_roomNumber);
+
+ for (int i = 0; i < _sceneNumb; i++)
+ if (_sceneDescr[i].size())
+ debugPrintf("%d - %s\n", i, _sceneDescr[i].c_str());
+ return true;
+
+ case 2: {
+ int newRoom = strToInt(argv[1]);
+ if (newRoom < 0 || newRoom >= _sceneNumb) {
+ debugPrintf("Invalid Room Number\n");
+ return true;
+ }
+ if (!_sceneDescr[newRoom].size()) {
+ debugPrintf("Unused Room Number\n");
+ return true;
+ }
+
+ _vm->_player->_roomNumber = newRoom;
+
+ _vm->_room->_function = FN_CLEAR1;
+ _vm->freeChar();
+ _vm->_converseMode = 0;
+ _vm->_scripts->_endFlag = true;
+ _vm->_scripts->_returnCode = 0;
+
+ return false;
+ }
+ default:
+ debugPrintf("Current scene is: %d\n", _vm->_player->_roomNumber);
+ debugPrintf("Usage: %s <scene number>\n", argv[0]);
+ return true;
+ }
+}
+
+bool Debugger::Cmd_Cheat(int argc, const char **argv) {
+ if (argc != 1) {
+ debugPrintf("Usage: %s\n", argv[0]);
+ debugPrintf("Switches on/off the cheat mode\n");
+ return true;
+ }
+
+ _vm->_cheatFl = !_vm->_cheatFl;
+ debugPrintf("Cheat is now %s\n", _vm->_cheatFl ? "ON" : "OFF");
+ return true;
+}
+
+/*------------------------------------------------------------------------*/
+
+namespace Amazon {
+
+AmazonDebugger::AmazonDebugger(AccessEngine *vm) : Debugger(vm) {
+ registerCmd("chapter", WRAP_METHOD(AmazonDebugger, Cmd_StartChapter));
+}
+
+bool AmazonDebugger::Cmd_StartChapter(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Usage: %s <chapter number>\n", argv[0]);
+ return true;
+ }
+
+ // Build up a simple one line script to start the given chapter
+ byte *chapterScript = (byte *)malloc(5);
+ chapterScript[0] = SCRIPT_START_BYTE;
+ chapterScript[1] = ROOM_SCRIPT % 256;
+ chapterScript[2] = ROOM_SCRIPT / 256;
+ chapterScript[3] = 0x80 + 75; // cmdChapter
+ chapterScript[4] = strToInt(argv[1]); // chapter number
+ _vm->_scripts->setScript(new Resource(chapterScript, 5), true);
+
+ return false;
+}
+
+} // End of namespace Amazon
+
+} // End of namespace Access
diff --git a/engines/access/debugger.h b/engines/access/debugger.h
new file mode 100644
index 0000000000..f4d8df7634
--- /dev/null
+++ b/engines/access/debugger.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_DEBUGGER_H
+#define ACCESS_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+#include "access/amazon/amazon_resources.h"
+#include "access/martian/martian_resources.h"
+
+namespace Access {
+
+class AccessEngine;
+
+class Debugger : public GUI::Debugger {
+protected:
+ AccessEngine *_vm;
+
+ bool Cmd_LoadScene(int argc, const char **argv);
+ bool Cmd_Cheat(int argc, const char **argv);
+ Common::String *_sceneDescr;
+ int _sceneNumb;
+public:
+ static Debugger *init(AccessEngine *vm);
+public:
+ Debugger(AccessEngine *vm);
+ virtual ~Debugger();
+};
+
+namespace Amazon {
+
+class AmazonDebugger : public Debugger {
+protected:
+ bool Cmd_StartChapter(int argc, const char **argv);
+public:
+ AmazonDebugger(AccessEngine *vm);
+ virtual ~AmazonDebugger() {}
+};
+
+} // End of namespace Amazon
+
+} // End of namespace Access
+
+#endif /* ACCESS_DEBUGGER_H */
diff --git a/engines/access/decompress.cpp b/engines/access/decompress.cpp
new file mode 100644
index 0000000000..62bff87860
--- /dev/null
+++ b/engines/access/decompress.cpp
@@ -0,0 +1,127 @@
+/* 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/debug.h"
+#include "common/endian.h"
+#include "common/util.h"
+
+#include "access/decompress.h"
+
+namespace Access {
+
+void LzwDecompressor::decompress(byte *source, byte *dest) {
+
+ _source = source;
+
+ byte litByte;
+ uint16 copyLength, maxCodeValue, code, nextCode, lastCode, oldCode;
+
+ byte *copyBuf = new byte[8192];
+
+ struct { uint16 code; byte value; } codeTable[8192];
+ memset(codeTable, 0, sizeof(codeTable));
+
+ _codeLength = 9;
+ nextCode = 258;
+ maxCodeValue = 512;
+
+ copyLength = 0;
+ _bitPos = 0;
+
+ while (1) {
+
+ code = getCode();
+
+ if (code == 257)
+ break;
+
+ if (code == 256) {
+ _codeLength = 9;
+ nextCode = 258;
+ maxCodeValue = 512;
+ lastCode = getCode();
+ oldCode = lastCode;
+ litByte = lastCode;
+ *dest++ = litByte;
+ } else {
+ lastCode = code;
+ if (code >= nextCode) {
+ lastCode = oldCode;
+ copyBuf[copyLength++] = litByte;
+ }
+ while (lastCode > 255) {
+ copyBuf[copyLength++] = codeTable[lastCode].value;
+ lastCode = codeTable[lastCode].code;
+ }
+ litByte = lastCode;
+ copyBuf[copyLength++] = lastCode;
+ while (copyLength > 0)
+ *dest++ = copyBuf[--copyLength];
+ codeTable[nextCode].value = lastCode;
+ codeTable[nextCode].code = oldCode;
+ nextCode++;
+ oldCode = code;
+ if (nextCode >= maxCodeValue && _codeLength <= 12) {
+ _codeLength++;
+ maxCodeValue <<= 1;
+ }
+ }
+
+ }
+
+ delete[] copyBuf;
+
+}
+
+uint16 LzwDecompressor::getCode() {
+ const byte bitMasks[9] = {
+ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x0FF
+ };
+ uint16 bits, loCode, hiCode;
+ loCode = (READ_LE_UINT16(_source) >> _bitPos) & 0xFF;
+ _source++;
+ bits = _codeLength - 8;
+ hiCode = (READ_LE_UINT16(_source) >> _bitPos) & bitMasks[bits];
+ _bitPos += bits;
+ if (_bitPos > 8) {
+ _source++;
+ _bitPos -= 8;
+ }
+ return (hiCode << 8) | loCode;
+}
+
+uint32 decompressDBE(byte *source, byte **dest) {
+
+ uint32 destSize = READ_LE_UINT32(source + 4);
+ *dest = new byte[destSize];
+
+ debug(1, "decompressDBE() destSize = %d", destSize);
+
+ LzwDecompressor dec;
+ dec.decompress(source + 16, *dest);
+
+ debug(1, "decompressDBE() ok");
+
+ return destSize;
+}
+
+} // End of namespace Access
diff --git a/engines/access/decompress.h b/engines/access/decompress.h
new file mode 100644
index 0000000000..eea450086b
--- /dev/null
+++ b/engines/access/decompress.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_DECOMPRESS_H
+#define ACCESS_DECOMPRESS_H
+
+#include "common/scummsys.h"
+
+namespace Access {
+
+class LzwDecompressor {
+public:
+ void decompress(byte *source, byte *dest);
+private:
+ byte *_source;
+ byte _codeLength, _bitPos;
+ uint16 getCode();
+};
+
+uint32 decompressDBE(byte *source, byte **dest);
+
+} // End of namespace Access
+
+#endif
diff --git a/engines/access/detection.cpp b/engines/access/detection.cpp
new file mode 100644
index 0000000000..441740c1b2
--- /dev/null
+++ b/engines/access/detection.cpp
@@ -0,0 +1,209 @@
+/* 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 "access/access.h"
+#include "access/amazon/amazon_game.h"
+#include "access/martian/martian_game.h"
+
+#include "base/plugins.h"
+#include "common/savefile.h"
+#include "common/str-array.h"
+#include "common/memstream.h"
+#include "engines/advancedDetector.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/surface.h"
+
+#define MAX_SAVES 99
+
+namespace Access {
+
+struct AccessGameDescription {
+ ADGameDescription desc;
+
+ int gameID;
+ uint32 features;
+};
+
+uint32 AccessEngine::getGameID() const {
+ return _gameDescription->gameID;
+}
+
+uint32 AccessEngine::getGameFeatures() const {
+ return _gameDescription->features;
+}
+
+uint32 AccessEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+bool AccessEngine::isCD() const {
+ return (bool)(_gameDescription->desc.flags & ADGF_CD);
+}
+
+bool AccessEngine::isDemo() const {
+ return (bool)(_gameDescription->desc.flags & ADGF_DEMO);
+}
+
+Common::Language AccessEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+Common::Platform AccessEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
+} // End of namespace Access
+
+static const PlainGameDescriptor AccessGames[] = {
+ {"Access", "Access"},
+ {"amazon", "Amazon: Guardians of Eden"},
+ {"martian", "Martian Memorandum"},
+ {0, 0}
+};
+
+#include "access/detection_tables.h"
+
+class AccessMetaEngine : public AdvancedMetaEngine {
+public:
+ AccessMetaEngine() : AdvancedMetaEngine(Access::gameDescriptions, sizeof(Access::AccessGameDescription), AccessGames) {
+ _maxScanDepth = 3;
+ }
+
+ virtual const char *getName() const {
+ return "Access Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Access Engine (c) 1989-1994 Access Software";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool AccessMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail);
+}
+
+bool Access::AccessEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+bool AccessMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Access::AccessGameDescription *gd = (const Access::AccessGameDescription *)desc;
+ if (gd) {
+ switch (gd->gameID) {
+ case Access::GType_Amazon:
+ *engine = new Access::Amazon::AmazonEngine(syst, gd);
+ break;
+ case Access::GType_MartianMemorandum:
+ *engine = new Access::Martian::MartianEngine(syst, gd);
+ break;
+ default:
+ error("Unknown game");
+ }
+ }
+ return gd != 0;
+}
+
+SaveStateList AccessMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String saveDesc;
+ Common::String pattern = Common::String::format("%s.0??", target);
+ Access::AccessSavegameHeader header;
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ const char *ext = strrchr(file->c_str(), '.');
+ int slot = ext ? atoi(ext + 1) : -1;
+
+ if (slot >= 0 && slot < MAX_SAVES) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+ if (in) {
+ Access::AccessEngine::readSavegameHeader(in, header);
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+
+ header._thumbnail->free();
+ delete header._thumbnail;
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+int AccessMetaEngine::getMaximumSaveSlot() const {
+ return MAX_SAVES;
+}
+
+void AccessMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
+SaveStateDescriptor AccessMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
+
+ if (f) {
+ Access::AccessSavegameHeader header;
+ Access::AccessEngine::readSavegameHeader(f, header);
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header._saveName);
+ desc.setThumbnail(header._thumbnail);
+ desc.setSaveDate(header._year, header._month, header._day);
+ desc.setSaveTime(header._hour, header._minute);
+ desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
+
+ return desc;
+ }
+
+ return SaveStateDescriptor();
+}
+
+
+#if PLUGIN_ENABLED_DYNAMIC(ACCESS)
+ REGISTER_PLUGIN_DYNAMIC(ACCESS, PLUGIN_TYPE_ENGINE, AccessMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(ACCESS, PLUGIN_TYPE_ENGINE, AccessMetaEngine);
+#endif
diff --git a/engines/access/detection_tables.h b/engines/access/detection_tables.h
new file mode 100644
index 0000000000..88a64470c5
--- /dev/null
+++ b/engines/access/detection_tables.h
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+namespace Access {
+
+static const AccessGameDescription gameDescriptions[] = {
+ {
+ // Amazon Guardians of Eden - Floppy English
+ // 3.5" and 5.25" floppies provided by Strangerke had the same md5
+ // Except the sound file. The executable is also identical
+ {
+ "amazon",
+ 0,
+ AD_ENTRY1s("c00.ap", "dcabf69d5a0d911168cb73511ebaead0", 331481),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_Amazon,
+ 0
+ },
+
+ // Amazon Guardians of Eden - Demo English
+ {
+ {
+ "amazon",
+ "Demo",
+ AD_ENTRY1s("c25.ap", "5baba0c052d22157499bfa05cb1ed5b7", 65458),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_DEMO,
+ GUIO1(GUIO_NONE)
+ },
+ GType_Amazon,
+ 0
+ },
+
+ {
+ // Amazon: Guardians of Eden - CD English
+ {
+ "amazon",
+ "CD",
+ AD_ENTRY1s("checksum.crc", "bef85478132fec74cb5d9067f3a37d24", 8),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO1(GUIO_NONE)
+ },
+ GType_Amazon,
+ 0
+ },
+
+ {
+ // Martian Memorandum
+ {
+ "martian",
+ nullptr,
+ AD_ENTRY1s("r00.ap", "af98db5ee7f9ef86c6b1f43187a3691b", 31),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GType_MartianMemorandum,
+ 0
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0 }
+};
+
+} // End of namespace Access
diff --git a/engines/access/events.cpp b/engines/access/events.cpp
new file mode 100644
index 0000000000..0867b09765
--- /dev/null
+++ b/engines/access/events.cpp
@@ -0,0 +1,371 @@
+/* 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 "graphics/cursorman.h"
+#include "common/events.h"
+#include "common/endian.h"
+#include "engines/util.h"
+#include "access/access.h"
+#include "access/events.h"
+#include "access/player.h"
+#include "access/amazon/amazon_resources.h"
+
+#define CURSOR_WIDTH 16
+#define CURSOR_HEIGHT 16
+
+namespace Access {
+
+EventsManager::EventsManager(AccessEngine *vm) : _vm(vm) {
+ _cursorId = CURSOR_NONE;
+ _normalMouse = CURSOR_CROSSHAIRS;
+ _frameCounter = 10;
+ _priorFrameTime = 0;
+ _leftButton = _rightButton = false;
+ _middleButton = false;
+ _wheelUp = _wheelDown = false;
+ _mouseCol = _mouseRow = 0;
+ _cursorExitFlag = false;
+ _vbCount = 0;
+ _keyCode = Common::KEYCODE_INVALID;
+ _priorTimerTime = 0;
+}
+
+EventsManager::~EventsManager() {
+ _invCursor.free();
+}
+
+void EventsManager::forceSetCursor(CursorType cursorId) {
+ setNormalCursor(cursorId);
+ setCursor(cursorId);
+}
+
+void EventsManager::setNormalCursor(CursorType cursorId) {
+ _normalMouse = cursorId;
+}
+
+void EventsManager::setCursor(CursorType cursorId) {
+ if (cursorId == _cursorId)
+ return;
+ _cursorId = cursorId;
+
+ if (cursorId == CURSOR_INVENTORY) {
+ // Set the cursor
+ CursorMan.replaceCursor(_invCursor.getPixels(), _invCursor.w, _invCursor.h,
+ _invCursor.w / 2, _invCursor.h / 2, 0);
+ } else {
+ // Get a pointer to the mouse data to use, and get the cursor hotspot
+ const byte *srcP = Amazon::CURSORS[cursorId];
+ int hotspotX = (int16)READ_LE_UINT16(srcP);
+ int hotspotY = (int16)READ_LE_UINT16(srcP + 2);
+ srcP += 4;
+
+ // Create a surface to build up the cursor on
+ Graphics::Surface cursorSurface;
+ cursorSurface.create(16, 16, Graphics::PixelFormat::createFormatCLUT8());
+ byte *destP = (byte *)cursorSurface.getPixels();
+ Common::fill(destP, destP + CURSOR_WIDTH * CURSOR_HEIGHT, 0);
+
+ // Loop to build up the cursor
+ for (int y = 0; y < CURSOR_HEIGHT; ++y) {
+ destP = (byte *)cursorSurface.getBasePtr(0, y);
+ int width = CURSOR_WIDTH;
+ int skip = *srcP++;
+ int plot = *srcP++;
+ if (skip >= width)
+ break;
+
+ // Skip over pixels
+ destP += skip;
+ width -= skip;
+
+ // Write out the pixels to plot
+ while (plot > 0 && width > 0) {
+ *destP++ = *srcP++;
+ --plot;
+ --width;
+ }
+ }
+
+ // Set the cursor
+ CursorMan.replaceCursor(cursorSurface.getPixels(), CURSOR_WIDTH, CURSOR_HEIGHT,
+ hotspotX, hotspotY, 0);
+
+ // Free the cursor surface
+ cursorSurface.free();
+ }
+}
+
+void EventsManager::setCursorData(Graphics::Surface *src, const Common::Rect &r) {
+ _invCursor.create(r.width(), r.height(), Graphics::PixelFormat::createFormatCLUT8());
+ _invCursor.copyRectToSurface(*src, 0, 0, r);
+}
+
+void EventsManager::showCursor() {
+ CursorMan.showMouse(true);
+}
+
+void EventsManager::hideCursor() {
+ CursorMan.showMouse(false);
+}
+
+bool EventsManager::isCursorVisible() {
+ return CursorMan.isVisible();
+}
+
+void EventsManager::pollEvents(bool skipTimers) {
+ if (checkForNextFrameCounter()) {
+ nextFrame();
+ }
+
+ if (checkForNextTimerUpdate() && !skipTimers)
+ nextTimer();
+
+ _wheelUp = _wheelDown = false;
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ return;
+
+ case Common::EVENT_KEYDOWN:
+ // Check for debugger
+ if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _vm->_debugger->attach();
+ _vm->_debugger->onFrame();
+ } else {
+ keyControl(event.kbd.keycode, true);
+ }
+ return;
+ case Common::EVENT_KEYUP:
+ keyControl(event.kbd.keycode, false);
+ return;
+ case Common::EVENT_MOUSEMOVE:
+ _mousePos = event.mouse;
+ _mouseCol = _mousePos.x / 8;
+ _mouseRow = _mousePos.y / 8;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ _leftButton = true;
+ return;
+ case Common::EVENT_LBUTTONUP:
+ _leftButton = false;
+ return;
+ case Common::EVENT_RBUTTONDOWN:
+ _rightButton = true;
+ return;
+ case Common::EVENT_RBUTTONUP:
+ _rightButton = false;
+ return;
+ case Common::EVENT_MBUTTONDOWN:
+ _middleButton = true;
+ return;
+ case Common::EVENT_MBUTTONUP:
+ _middleButton = false;
+ return;
+ case Common::EVENT_WHEELUP:
+ _wheelUp = true;
+ return;
+ case Common::EVENT_WHEELDOWN:
+ _wheelDown = true;
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+void EventsManager::keyControl(Common::KeyCode keycode, bool isKeyDown) {
+ Player &player = *_vm->_player;
+
+ if (!isKeyDown) {
+ if (player._move != NONE) {
+ _keyCode = Common::KEYCODE_INVALID;
+ player._move = NONE;
+ }
+ return;
+ }
+
+ _keyCode = keycode;
+
+ switch (keycode) {
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ player._move = UP;
+ break;
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ player._move = DOWN;
+ break;
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_KP4:
+ player._move = LEFT;
+ break;
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_KP6:
+ player._move = RIGHT;
+ break;
+ case Common::KEYCODE_KP7:
+ player._move = UPLEFT;
+ break;
+ case Common::KEYCODE_KP9:
+ player._move = UPRIGHT;
+ break;
+ case Common::KEYCODE_KP1:
+ player._move = DOWNLEFT;
+ break;
+ case Common::KEYCODE_KP3:
+ player._move = DOWNRIGHT;
+ break;
+ default:
+ break;
+ }
+}
+
+void EventsManager::pollEventsAndWait() {
+ pollEvents();
+ delay();
+}
+
+bool EventsManager::checkForNextFrameCounter() {
+ // Check for next game frame
+ uint32 milli = g_system->getMillis();
+ if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
+ --_vbCount;
+ ++_frameCounter;
+ _priorFrameTime = milli;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool EventsManager::checkForNextTimerUpdate() {
+ // Check for next timer update
+ uint32 milli = g_system->getMillis();
+ if ((milli - _priorTimerTime) >= GAME_TIMER_TIME) {
+ _priorTimerTime = milli;
+
+ return true;
+ }
+
+ return false;
+}
+
+void EventsManager::nextFrame() {
+ // Give time to the debugger
+ _vm->_debugger->onFrame();
+
+ // TODO: Refactor for dirty rects
+ _vm->_screen->updateScreen();
+}
+
+void EventsManager::nextTimer() {
+ _vm->_animation->updateTimers();
+ _vm->_timers.updateTimers();
+}
+
+void EventsManager::delay(int time) {
+ g_system->delayMillis(time);
+}
+
+void EventsManager::zeroKeys() {
+ _keyCode = Common::KEYCODE_INVALID;
+}
+
+bool EventsManager::getKey(Common::KeyState &key) {
+ if (_keyCode == Common::KEYCODE_INVALID) {
+ return false;
+ } else {
+ key = _keyCode;
+ _keyCode = Common::KEYCODE_INVALID;
+ return true;
+ }
+}
+
+bool EventsManager::isKeyPending() const {
+ return _keyCode != Common::KEYCODE_INVALID;
+}
+
+void EventsManager::debounceLeft() {
+ while (_leftButton && !_vm->shouldQuit()) {
+ pollEventsAndWait();
+ }
+}
+
+void EventsManager::clearEvents() {
+ _leftButton = _rightButton = false;
+ zeroKeys();
+}
+
+void EventsManager::waitKeyMouse() {
+ while (!_vm->shouldQuit() && !isKeyMousePressed()) {
+ pollEvents(true);
+ delay();
+ }
+}
+
+Common::Point EventsManager::calcRawMouse() {
+ Common::Point pt;
+ Screen &screen = *_vm->_screen;
+ pt.x = _mousePos.x - screen._windowXAdd +
+ (_vm->_scrollCol * TILE_WIDTH) + _vm->_scrollX;
+ pt.y = _mousePos.y - screen._screenYOff - screen._windowYAdd +
+ (_vm->_scrollRow * TILE_HEIGHT) + _vm->_scrollY;
+
+ return pt;
+}
+
+int EventsManager::checkMouseBox1(Common::Array<Common::Rect> &rects) {
+ for (uint16 i = 0; i < rects.size(); ++i) {
+ if (rects[i].left == -1)
+ return -1;
+
+ if ((_mousePos.x > rects[i].left) && (_mousePos.x < rects[i].right)
+ && (_mousePos.y > rects[i].top) && (_mousePos.y < rects[i].bottom))
+ return i;
+ }
+
+ return -1;
+}
+
+bool EventsManager::isKeyMousePressed() {
+ bool result = _leftButton || _rightButton || isKeyPending();
+ debounceLeft();
+ zeroKeys();
+
+ return result;
+}
+
+void EventsManager::centerMousePos() {
+ _mousePos = Common::Point(160, 100);
+}
+
+void EventsManager::restrictMouse() {
+ // No implementation in ScummVM
+}
+
+} // End of namespace Access
diff --git a/engines/access/events.h b/engines/access/events.h
new file mode 100644
index 0000000000..b8c5f0ee5e
--- /dev/null
+++ b/engines/access/events.h
@@ -0,0 +1,157 @@
+/* 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 ACCESS_EVENTS_H
+#define ACCESS_EVENTS_H
+
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/stack.h"
+
+namespace Access {
+
+enum CursorType {
+ CURSOR_NONE = -1,
+ CURSOR_ARROW = 0, CURSOR_CROSSHAIRS, CURSOR_2, CURSOR_3, CURSOR_LOOK,
+ CURSOR_USE, CURSOR_TAKE, CURSOR_CLIMB, CURSOR_TALK, CURSOR_HELP,
+ CURSOR_INVENTORY = 99
+};
+
+#define GAME_FRAME_RATE 100
+#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
+#define GAME_TIMER_TIME 15
+
+class AccessEngine;
+
+class EventsManager {
+private:
+ AccessEngine *_vm;
+ uint32 _frameCounter;
+ uint32 _priorFrameTime;
+ uint32 _priorTimerTime;
+ Common::KeyCode _keyCode;
+
+ Graphics::Surface _invCursor;
+ bool checkForNextFrameCounter();
+ bool checkForNextTimerUpdate();
+ void nextFrame();
+ void nextTimer();
+ void keyControl(Common::KeyCode keycode, bool isKeyDown);
+public:
+ CursorType _cursorId;
+ CursorType _normalMouse;
+ bool _leftButton, _rightButton;
+ bool _middleButton;
+ bool _wheelUp, _wheelDown;
+ Common::Point _mousePos;
+ int _mouseCol, _mouseRow;
+ bool _cursorExitFlag;
+ int _vbCount;
+public:
+ /**
+ * Constructor
+ */
+ EventsManager(AccessEngine *vm);
+
+ /**
+ * Destructor
+ */
+ ~EventsManager();
+
+ /**
+ * Return frame counter
+ */
+ uint32 getFrameCounter() { return _frameCounter; }
+
+ /**
+ * Sets the cursor and reset the normal cursor
+ */
+ void forceSetCursor(CursorType cursorId);
+
+ /**
+ * Sets the normal cursor
+ */
+ void setNormalCursor(CursorType cursorId);
+
+ /**
+ * Sets the cursor
+ */
+ void setCursor(CursorType cursorId);
+
+ /**
+ * Set the image for the inventory cursor
+ */
+ void setCursorData(Graphics::Surface *src, const Common::Rect &r);
+
+ /**
+ * Return the current cursor Id
+ */
+ CursorType getCursor() const { return _cursorId; }
+
+ /**
+ * Show the mouse cursor
+ */
+ void showCursor();
+
+ /**
+ * Hide the mouse cursor
+ */
+ void hideCursor();
+
+ /**
+ * Returns if the mouse cursor is visible
+ */
+ bool isCursorVisible();
+
+ void pollEvents(bool skipTimers = false);
+
+ void pollEventsAndWait();
+
+ void zeroKeys();
+
+ bool getKey(Common::KeyState &key);
+
+ bool isKeyPending() const;
+
+ void delay(int time = 5);
+
+ void debounceLeft();
+
+ void clearEvents();
+
+ void waitKeyMouse();
+
+ Common::Point &getMousePos() { return _mousePos; }
+
+ Common::Point calcRawMouse();
+
+ int checkMouseBox1(Common::Array<Common::Rect> &rects);
+
+ bool isKeyMousePressed();
+
+ void centerMousePos();
+ void restrictMouse();
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_EVENTS_H */
diff --git a/engines/access/files.cpp b/engines/access/files.cpp
new file mode 100644
index 0000000000..42a7914638
--- /dev/null
+++ b/engines/access/files.cpp
@@ -0,0 +1,239 @@
+/* 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/substream.h"
+#include "access/files.h"
+#include "access/amazon/amazon_resources.h"
+#include "access/martian/martian_resources.h"
+#include "access/access.h"
+
+namespace Access {
+
+FileIdent::FileIdent() {
+ _fileNum = -1;
+ _subfile = 0;
+}
+
+void FileIdent::load(Common::SeekableReadStream &s) {
+ _fileNum = s.readSint16LE();
+ _subfile = s.readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
+CellIdent::CellIdent(int cell, int fileNum, int subfile) {
+ _cell = cell;
+ _fileNum = fileNum;
+ _subfile = subfile;
+}
+
+/*------------------------------------------------------------------------*/
+
+Resource::Resource() {
+ _stream = nullptr;
+ _size = 0;
+ _data = nullptr;
+}
+
+Resource::~Resource() {
+ delete[] _data;
+ delete _stream;
+}
+
+Resource::Resource(byte *p, int size) {
+ _data = p;
+ _size = size;
+ _stream = new Common::MemoryReadStream(p, size);
+}
+
+byte *Resource::data() {
+ if (_data == nullptr) {
+ _data = new byte[_size];
+ int pos = _stream->pos();
+ _stream->seek(0);
+ _stream->read(_data, _size);
+ _stream->seek(pos);
+ }
+
+ return _data;
+}
+
+/*------------------------------------------------------------------------*/
+
+FileManager::FileManager(AccessEngine *vm) : _vm(vm) {
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ if (_vm->isDemo())
+ _filenames = &Amazon::FILENAMES_DEMO[0];
+ else
+ _filenames = &Amazon::FILENAMES[0];
+ break;
+ case GType_MartianMemorandum:
+ _filenames = &Martian::FILENAMES[0];
+ break;
+ default:
+ error("Unknown game");
+ }
+
+ _fileNumber = -1;
+ _setPaletteFlag = true;
+}
+
+FileManager::~FileManager() {
+}
+
+Resource *FileManager::loadFile(int fileNum, int subfile) {
+ Resource *res = new Resource();
+ setAppended(res, fileNum);
+ gotoAppended(res, subfile);
+
+ handleFile(res);
+ return res;
+}
+
+Resource *FileManager::loadFile(const FileIdent &fileIdent) {
+ return loadFile(fileIdent._fileNum, fileIdent._subfile);
+}
+
+Resource *FileManager::loadFile(const Common::String &filename) {
+ Resource *res = new Resource();
+
+ // Open the file
+ openFile(res, filename);
+
+ // Set up stream for the entire file
+ res->_size = res->_file.size();
+ res->_stream = res->_file.readStream(res->_size);
+
+ handleFile(res);
+ return res;
+}
+
+bool FileManager::existFile(const Common::String &filename) {
+ Common::File f;
+ return f.exists(filename);
+}
+
+void FileManager::openFile(Resource *res, const Common::String &filename) {
+ // Open up the file
+ _fileNumber = -1;
+ if (!res->_file.open(filename))
+ error("Could not open file - %s", filename.c_str());
+}
+
+void FileManager::loadScreen(Graphics::Surface *dest, int fileNum, int subfile) {
+ Resource *res = loadFile(fileNum, subfile);
+ handleScreen(dest, res);
+ delete res;
+}
+
+void FileManager::handleScreen(Graphics::Surface *dest, Resource *res) {
+ _vm->_screen->loadRawPalette(res->_stream);
+ if (_setPaletteFlag)
+ _vm->_screen->setPalette();
+ _setPaletteFlag = true;
+
+ // The remainder of the file after the palette may be separately compressed,
+ // so call handleFile to handle it if it is
+ res->_size -= res->_stream->pos();
+ handleFile(res);
+
+ if (dest != _vm->_screen)
+ dest->w = _vm->_screen->w;
+
+ if (dest->w == dest->pitch) {
+ res->_stream->read((byte *)dest->getPixels(), dest->w * dest->h);
+ } else {
+ for (int y = 0; y < dest->h; ++y) {
+ byte *pDest = (byte *)dest->getBasePtr(0, y);
+ res->_stream->read(pDest, dest->w);
+ }
+ }
+
+ if (dest == _vm->_screen)
+ _vm->_screen->addDirtyRect(Common::Rect(0, 0, dest->w, dest->h));
+}
+
+void FileManager::loadScreen(int fileNum, int subfile) {
+ loadScreen(_vm->_screen, fileNum, subfile);
+}
+
+void FileManager::loadScreen(const Common::String &filename) {
+ Resource *res = loadFile(filename);
+ handleScreen(_vm->_screen, res);
+ delete res;
+}
+
+void FileManager::handleFile(Resource *res) {
+ char header[3];
+ res->_stream->read(&header[0], 3);
+ res->_stream->seek(-3, SEEK_CUR);
+
+ bool isCompressed = !strncmp(header, "DBE", 3);
+
+ // If the data is compressed, uncompress it and replace the stream
+ // in the resource with the decompressed one
+ if (isCompressed) {
+ // Read in the entire compressed data
+ byte *src = new byte[res->_size];
+ res->_stream->read(src, res->_size);
+
+ // Decompress the data
+ res->_size = decompressDBE(src, &res->_data);
+
+ // Replace the default resource stream with a stream for the decompressed data
+ delete res->_stream;
+ res->_file.close();
+ res->_stream = new Common::MemoryReadStream(res->_data, res->_size);
+
+ delete[] src;
+ }
+}
+
+void FileManager::setAppended(Resource *res, int fileNum) {
+ // Open the file for access
+ if (!res->_file.open(_filenames[fileNum]))
+ error("Could not open file %s", _filenames[fileNum]);
+
+ // If a different file has been opened then previously, load its index
+ if (_fileNumber != fileNum) {
+ _fileNumber = fileNum;
+
+ // Read in the file index
+ int count = res->_file.readUint16LE();
+ assert(count <= 100);
+ _fileIndex.resize(count);
+ for (int i = 0; i < count; ++i)
+ _fileIndex[i] = res->_file.readUint32LE();
+ }
+}
+
+void FileManager::gotoAppended(Resource *res, int subfile) {
+ uint32 offset = _fileIndex[subfile];
+ uint32 size = (subfile == (int)_fileIndex.size() - 1) ? res->_file.size() - offset :
+ _fileIndex[subfile + 1] - offset;
+
+ res->_size = size;
+ res->_stream = new Common::SeekableSubReadStream(&res->_file, offset, offset + size);
+}
+
+} // End of namespace Access
diff --git a/engines/access/files.h b/engines/access/files.h
new file mode 100644
index 0000000000..8b1aef0363
--- /dev/null
+++ b/engines/access/files.h
@@ -0,0 +1,142 @@
+/* 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 ACCESS_FILES_H
+#define ACCESS_FILES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "graphics/surface.h"
+#include "access/decompress.h"
+
+namespace Access {
+
+class AccessEngine;
+
+struct FileIdent {
+ int _fileNum;
+ int _subfile;
+
+ FileIdent();
+ FileIdent(int fileNum, int subfile) { _fileNum = fileNum; _subfile = subfile; }
+
+ void load(Common::SeekableReadStream &s);
+};
+
+struct CellIdent : FileIdent {
+ byte _cell;
+
+ CellIdent() {}
+ CellIdent(int cell, int fileNum, int subfile);
+};
+
+class FileManager;
+
+class Resource {
+ friend class FileManager;
+private:
+ Common::File _file;
+ byte *_data;
+public:
+ Common::SeekableReadStream *_stream;
+ int _size;
+
+ Resource();
+ Resource(byte *data, int size);
+ ~Resource();
+ byte *data();
+};
+
+class FileManager {
+private:
+ AccessEngine *_vm;
+ const char * const *_filenames;
+
+ void openFile(Resource *res, const Common::String &filename);
+
+ /**
+ * Handles setting up the resource with a stream for the located resource
+ */
+ void handleFile(Resource *res);
+
+ /**
+ * Handles loading a screen surface and palette with decoded resource
+ */
+ void handleScreen(Graphics::Surface *dest, Resource *res);
+
+ /**
+ * Open up a sub-file container file
+ */
+ void setAppended(Resource *file, int fileNum);
+
+ /**
+ * Open up a sub-file resource within an alrady opened container file.
+ */
+ void gotoAppended(Resource *file, int subfile);
+public:
+ int _fileNumber;
+ Common::Array<uint32> _fileIndex;
+ bool _setPaletteFlag;
+public:
+ FileManager(AccessEngine *vm);
+ ~FileManager();
+
+ /**
+ * Check the existence of a given file
+ */
+ bool existFile(const Common::String &filename);
+
+ /**
+ * Load a given subfile from a container file
+ */
+ Resource *loadFile(int fileNum, int subfile);
+
+ /**
+ * Loads a resource specified by a file identifier
+ */
+ Resource *loadFile(const FileIdent &fileIdent);
+
+ /**
+ * Load a given file by name
+ */
+ Resource *loadFile(const Common::String &filename);
+
+ /**
+ * Load a given scren from a container file
+ */
+ void loadScreen(int fileNum, int subfile);
+
+ /**
+ * Load a given screen by name
+ */
+ void loadScreen(const Common::String &filename);
+
+ /**
+ * Load a screen resource onto a designated surface
+ */
+ void loadScreen(Graphics::Surface *dest, int fileNum, int subfile);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_FILES_H */
diff --git a/engines/access/font.cpp b/engines/access/font.cpp
new file mode 100644
index 0000000000..da8f0b6ec5
--- /dev/null
+++ b/engines/access/font.cpp
@@ -0,0 +1,177 @@
+/* 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 "access/font.h"
+
+namespace Access {
+
+byte Font::_fontColors[4];
+
+Font::Font() {
+}
+
+Font::~Font() {
+ for (uint i = 0; i < _chars.size(); ++i)
+ _chars[i].free();
+}
+
+void Font::load(const int *fontIndex, const byte *fontData) {
+ assert(_chars.size() == 0);
+ int count = fontIndex[0];
+ _bitWidth = fontIndex[1];
+ _height = fontIndex[2];
+
+ _chars.resize(count);
+
+ for (int i = 0; i < count; ++i) {
+ const byte *pData = fontData + fontIndex[i + 3];
+ _chars[i].create(*pData++, _height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int y = 0; y < _height; ++y) {
+ int bitsLeft = 0;
+ byte srcByte = 0;
+ byte pixel;
+
+ byte *pDest = (byte *)_chars[i].getBasePtr(0, y);
+ for (int x = 0; x < _chars[i].w; ++x, ++pDest) {
+ // Get the pixel
+ pixel = 0;
+ for (int pixelCtr = 0; pixelCtr < _bitWidth; ++pixelCtr, --bitsLeft) {
+ // No bits in current byte left, so get next byte
+ if (bitsLeft == 0) {
+ bitsLeft = 8;
+ srcByte = *pData++;
+ }
+
+ pixel = (pixel << 1) | (srcByte >> 7);
+ srcByte <<= 1;
+ }
+
+ // Write out the pixel
+ *pDest = pixel;
+ }
+ }
+ }
+}
+
+int Font::charWidth(char c) {
+ if (c < ' ')
+ return 0;
+
+ return _chars[c - ' '].w;
+}
+
+int Font::stringWidth(const Common::String &msg) {
+ int total = 0;
+
+ for (const char *c = msg.c_str(); *c != '\0'; ++c)
+ total += charWidth(*c);
+
+ return total;
+}
+
+bool Font::getLine(Common::String &s, int maxWidth, Common::String &line, int &width) {
+ assert(maxWidth > 0);
+ width = 0;
+ const char *src = s.c_str();
+ char c;
+
+ while ((c = *src) != '\0') {
+ if (c == '\r') {
+ // End of line, so return calculated line
+ line = Common::String(s.c_str(), src);
+ s = Common::String(src + 1);
+ return false;
+ }
+
+ ++src;
+ width += charWidth(c);
+ if (width < maxWidth)
+ continue;
+
+ // Reached maximum allowed size
+ // If this was the last character of the string, let it go
+ if (*src == '\0') {
+ line = Common::String(s.c_str(), src);
+ s.clear();
+ return true;
+ }
+
+ // Work backwards to find space at the start of the current word
+ // as a point to split the line on
+ while (src >= s.c_str() && *src != ' ') {
+ width -= charWidth(*src);
+ --src;
+ }
+ if (src < s.c_str())
+ error("Could not fit line");
+
+ // Split the line around the space
+ line = Common::String(s.c_str(), src);
+ s = Common::String(src + 1);
+ return false;
+ }
+
+ // Return entire string
+ line = s;
+ s = Common::String();
+ return true;
+}
+
+void Font::drawString(ASurface *s, const Common::String &msg, const Common::Point &pt) {
+ Common::Point currPt = pt;
+ const char *msgP = msg.c_str();
+
+ while (*msgP) {
+ currPt.x += drawChar(s, *msgP, currPt);
+ ++msgP;
+ }
+}
+
+int Font::drawChar(ASurface *s, char c, Common::Point &pt) {
+ Graphics::Surface &ch = _chars[c - ' '];
+
+ s->addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + ch.w, pt.y + ch.h));
+
+ // Loop through the lines of the character
+ for (int y = 0; y < ch.h; ++y) {
+ byte *pSrc = (byte *)ch.getBasePtr(0, y);
+ byte *pDest = (byte *)s->getBasePtr(pt.x, pt.y + y);
+
+ // Loop through the horizontal pixels of the line
+ for (int x = 0; x < ch.w; ++x, ++pSrc, ++pDest) {
+ if (*pSrc != 0)
+ *pDest = _fontColors[*pSrc];
+ }
+ }
+
+ return ch.w;
+}
+
+/*------------------------------------------------------------------------*/
+
+FontManager::FontManager() {
+ _printMaxX = 0;
+ Common::fill(&Font::_fontColors[0], &Font::_fontColors[4], 0);
+}
+
+} // End of namespace Access
diff --git a/engines/access/font.h b/engines/access/font.h
new file mode 100644
index 0000000000..6a812051ca
--- /dev/null
+++ b/engines/access/font.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 ACCESS_FONT_H
+#define ACCESS_FONT_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "access/asurface.h"
+#include "access/data.h"
+
+namespace Access {
+
+struct FontVal {
+public:
+ int _lo, _hi;
+
+ FontVal() { _lo = _hi = 0; }
+};
+
+class Font {
+private:
+ int _bitWidth;
+ int _height;
+ Common::Array<Graphics::Surface> _chars;
+public:
+ static byte _fontColors[4];
+public:
+ Font();
+
+ ~Font();
+
+ /**
+ * Load the given font data
+ */
+ void load(const int *fontIndex, const byte *fontData);
+
+ /**
+ * Get the width of a given character
+ */
+ int charWidth(char c);
+
+ /**
+ * Get the width of a given string
+ */
+ int stringWidth(const Common::String &msg);
+
+ /**
+ * Get a partial string that will fit in a given width
+ * @param s Source string. Modified to remove line
+ * @param maxWidth Maximum width allowed
+ * @param line Output line
+ * @param width Calculated width of returned line
+ * @returns True if last line
+ */
+ bool getLine(Common::String &s, int maxWidth, Common::String &line, int &width);
+
+ /**
+ * Draw a string on a given surface
+ */
+ void drawString(ASurface *s, const Common::String &msg, const Common::Point &pt);
+
+ /**
+ * Draw a character on a given surface
+ */
+ int drawChar(ASurface *s, char c, Common::Point &pt);
+
+};
+
+class FontManager {
+public:
+ FontVal _charSet;
+ FontVal _charFor;
+ int _printMaxX;
+ Font _font1;
+ Font _font2;
+public:
+ FontManager();
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_FONT_H */
diff --git a/engines/access/inventory.cpp b/engines/access/inventory.cpp
new file mode 100644
index 0000000000..8db62a45fc
--- /dev/null
+++ b/engines/access/inventory.cpp
@@ -0,0 +1,535 @@
+/* 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 "access/inventory.h"
+#include "access/access.h"
+#include "access/resources.h"
+#include "access/amazon/amazon_resources.h"
+#include "access/martian/martian_resources.h"
+
+namespace Access {
+
+void InventoryEntry::load(const Common::String &name, const int *data) {
+ _value = ITEM_NOT_FOUND;
+ _name = name;
+ _otherItem1 = *data++;
+ _newItem1 = *data++;
+ _otherItem2 = *data++;
+ _newItem2 = *data;
+}
+
+int InventoryEntry::checkItem(int itemId) {
+ if (_otherItem1 == itemId)
+ return _newItem1;
+ else if (_otherItem2 == itemId)
+ return _newItem2;
+ else
+ return -1;
+}
+
+/*------------------------------------------------------------------------*/
+
+InventoryManager::InventoryManager(AccessEngine *vm) : Manager(vm) {
+ _startInvItem = 0;
+ _startInvBox = 0;
+ _invChangeFlag = true;
+ _invRefreshFlag = false;
+ _invModeFlag = false;
+ _startAboutItem = 0;
+ _startTravelItem = 0;
+ _iconDisplayFlag = true;
+
+ const char *const *names;
+ const int *combineP;
+
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ names = Amazon::INVENTORY_NAMES;
+ combineP = &Amazon::COMBO_TABLE[0][0];
+ _inv.resize(85);
+ break;
+ case GType_MartianMemorandum:
+ names = Martian::INVENTORY_NAMES;
+ combineP = &Martian::COMBO_TABLE[0][0];
+ _inv.resize(54);
+ break;
+ default:
+ error("Unknown game");
+ }
+
+ for (uint i = 0; i < _inv.size(); ++i, combineP += 4) {
+ _inv[i].load(names[i], combineP);
+ }
+
+ for (uint i = 0; i < 26; ++i) {
+ const int *r = INVCOORDS[i];
+ _invCoords.push_back(Common::Rect(r[0], r[2], r[1], r[3]));
+ }
+}
+
+int &InventoryManager::operator[](int idx) {
+ // WORKAROUND: At least in Amazon, some game scripts accidentally do reads
+ // beyond the length of the inventory array
+ static int invalid = 0;
+ return (idx >= (int)_inv.size()) ? invalid : _inv[idx]._value;
+}
+
+int InventoryManager::useItem() {
+ return _vm->_useItem;
+}
+
+void InventoryManager::setUseItem(int itemId) {
+ _vm->_useItem = itemId;
+}
+
+void InventoryManager::refreshInventory() {
+ // The original version was using pre-rendering for the inventory to spare some time.
+ // This is not needed on modern hardware, and it breaks a couple of things.
+ // Therefore it was removed in order to keep the same logic than for the CD version
+ // if (_vm->_screen->_vesaMode) {
+ // _invRefreshFlag = true;
+ // newDisplayInv();
+ // }
+}
+
+int InventoryManager::newDisplayInv() {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ Room &room = *_vm->_room;
+ FileManager &files = *_vm->_files;
+
+ _invModeFlag = true;
+ _vm->_timers.saveTimers();
+
+ if (!room._tile && !_invRefreshFlag) {
+ saveScreens();
+ }
+
+ savedFields();
+ screen.setPanel(1);
+ events._cursorExitFlag = false;
+ getList();
+ initFields();
+
+ files.loadScreen(&_vm->_buffer1, 99, 0);
+ _vm->_buffer1.copyTo(&_vm->_buffer2);
+ _vm->copyBF2Vid();
+
+ // Set cells
+ Common::Array<CellIdent> cells;
+ cells.push_back(CellIdent(99, 99, 1));
+ _vm->loadCells(cells);
+
+ showAllItems();
+
+ if (!_invRefreshFlag) {
+ chooseItem();
+ if (_vm->_useItem != -1) {
+ int savedScale = _vm->_scale;
+ _vm->_scale = 153;
+ _vm->_screen->setScaleTable(_vm->_scale);
+ _vm->_buffer1.clearBuffer();
+
+ SpriteResource *spr = _vm->_objectsTable[99];
+ SpriteFrame *frame = spr->getFrame(_vm->_useItem);
+
+ int w = screen._scaleTable1[46];
+ int h = screen._scaleTable1[35];
+ _vm->_buffer1.sPlotF(frame, Common::Rect(0, 0, w, h));
+ events.setCursorData(&_vm->_buffer1, Common::Rect(0, 0, w, h));
+
+ _vm->_scale = savedScale;
+ screen.setScaleTable(_vm->_scale);
+ }
+ }
+
+ freeInvCells();
+ screen.setPanel(0);
+ events.debounceLeft();
+
+ restoreFields();
+ screen.restorePalette();
+ // The original was testing the vesa mode too.
+ // We removed this check as we don't use pre-rendering
+ if (!_invRefreshFlag) {
+ screen.clearScreen();
+ screen.setPalette();
+ }
+
+ if (!room._tile && !_invRefreshFlag) {
+ restoreScreens();
+ } else {
+ screen.setBufferScan();
+ room.buildScreen();
+
+ // The original was doing a check on the vesa mode at this point.
+ // We don't need it as we don't do inventory pre-rendering
+ screen.fadeOut();
+ _vm->copyBF2Vid();
+ }
+
+ events._cursorExitFlag = false;
+ screen._screenChangeFlag = false;
+ _invModeFlag = false;
+ events.debounceLeft();
+ _vm->_timers.restoreTimers();
+ _vm->_startup = 1;
+
+ int result = 0;
+ if (!_invRefreshFlag) {
+ if (_vm->_useItem == -1) {
+ result = 2;
+ events.forceSetCursor(CURSOR_CROSSHAIRS);
+ } else
+ events.forceSetCursor(CURSOR_INVENTORY);
+ }
+
+ _invRefreshFlag = false;
+ _invChangeFlag = false;
+ return result;
+}
+
+void InventoryManager::savedFields() {
+ Screen &screen = *_vm->_screen;
+ Room &room = *_vm->_room;
+
+ _fields._vWindowHeight = screen._vWindowHeight;
+ _fields._vWindowLinesTall = screen._vWindowLinesTall;
+ _fields._vWindowWidth = screen._vWindowWidth;
+ _fields._vWindowBytesWide = screen._vWindowBytesWide;
+ _fields._playFieldHeight = room._playFieldHeight;
+ _fields._playFieldWidth = room._playFieldWidth;
+ _fields._windowXAdd = screen._windowXAdd;
+ _fields._windowYAdd = screen._windowYAdd;
+ _fields._screenYOff = screen._screenYOff;
+ _fields._scrollX = _vm->_scrollX;
+ _fields._scrollY = _vm->_scrollY;
+ _fields._clipWidth = screen._clipWidth;
+ _fields._clipHeight = screen._clipHeight;
+ _fields._bufferStart = screen._bufferStart;
+ _fields._scrollCol = _vm->_scrollCol;
+ _fields._scrollRow = _vm->_scrollRow;
+}
+
+void InventoryManager::restoreFields() {
+ Screen &screen = *_vm->_screen;
+ Room &room = *_vm->_room;
+
+ screen._vWindowHeight = _fields._vWindowHeight;
+ screen._vWindowLinesTall = _fields._vWindowLinesTall;
+ screen._vWindowWidth = _fields._vWindowWidth;
+ screen._vWindowBytesWide = _fields._vWindowBytesWide;
+ room._playFieldHeight = _fields._playFieldHeight;
+ room._playFieldWidth = _fields._playFieldWidth;
+ screen._windowXAdd = _fields._windowXAdd;
+ screen._windowYAdd = _fields._windowYAdd;
+ screen._screenYOff = _fields._screenYOff;
+ _vm->_scrollX = _fields._scrollX;
+ _vm->_scrollY = _fields._scrollY;
+ screen._clipWidth = _fields._clipWidth;
+ screen._clipHeight = _fields._clipHeight;
+ screen._bufferStart = _fields._bufferStart;
+ _vm->_scrollCol = _fields._scrollCol;
+ _vm->_scrollRow = _fields._scrollRow;
+}
+
+void InventoryManager::initFields() {
+ Screen &screen = *_vm->_screen;
+ Room &room = *_vm->_room;
+
+ screen._vWindowHeight = screen.h;
+ room._playFieldHeight = screen.h;
+ screen._vWindowLinesTall = screen.h;
+ screen._clipHeight = screen.h;
+ room._playFieldWidth = screen.w;
+ screen._vWindowWidth = screen.w;
+ screen._vWindowBytesWide = screen.w;
+ screen._clipWidth = screen.w;
+
+ screen._windowXAdd = 0;
+ screen._windowYAdd = 0;
+ screen._screenYOff = 0;
+ screen._bufferStart.x = 0;
+ screen._bufferStart.y = 0;
+ _vm->_scrollX = _vm->_scrollY = 0;
+
+ _vm->_buffer1.clearBuffer();
+ _vm->_buffer2.clearBuffer();
+ // The original was doing at this point a check on vesa mode
+ // We don't need it as we don't do inventory pre-rendering
+ if (!_invRefreshFlag)
+ screen.clearBuffer();
+
+ screen.savePalette();
+}
+
+void InventoryManager::getList() {
+ _items.clear();
+ _tempLOff.clear();
+
+ for (uint i = 0; i < _inv.size(); ++i) {
+ if (_inv[i]._value == ITEM_IN_INVENTORY) {
+ _items.push_back(i);
+ _tempLOff.push_back(_inv[i]._name);
+ }
+ }
+}
+
+void InventoryManager::showAllItems() {
+ _iconDisplayFlag = true;
+
+ for (uint i = 0; i < _items.size(); ++i)
+ putInvIcon(i, _items[i]);
+}
+
+void InventoryManager::putInvIcon(int itemIndex, int itemId) {
+ SpriteResource *spr = _vm->_objectsTable[99];
+ assert(spr);
+ Common::Point pt((itemIndex % 6) * 46 + 23, (itemIndex / 6) * 35 + 15);
+ _vm->_buffer2.plotImage(spr, itemId, pt);
+
+ if (_iconDisplayFlag) {
+ _vm->_screen->copyBlock(&_vm->_buffer2, Common::Rect(pt.x, pt.y, pt.x + 46, pt.y + 35));
+ }
+}
+
+void InventoryManager::chooseItem() {
+ EventsManager &events = *_vm->_events;
+ _vm->_useItem = -1;
+
+ while (!_vm->shouldQuit()) {
+ // Check for events
+ events.pollEventsAndWait();
+
+ int selIndex;
+ // Poll events and wait for a click on a known area
+ if (!events._leftButton || ((selIndex = coordIndexOf()) == -1))
+ continue;
+
+ if (selIndex > 23) {
+ if (selIndex == 25)
+ _vm->_useItem = -1;
+ break;
+ } else if (selIndex < (int)_items.size() && _items[selIndex] != -1) {
+ _boxNum = selIndex;
+ _vm->copyBF2Vid();
+ combineItems();
+ _vm->copyBF2Vid();
+ outlineIcon(_boxNum);
+ _vm->_useItem = _items[_boxNum];
+ }
+ }
+}
+
+void InventoryManager::freeInvCells() {
+ delete _vm->_objectsTable[99];
+ _vm->_objectsTable[99] = nullptr;
+}
+
+int InventoryManager::coordIndexOf() {
+ const Common::Point pt = _vm->_events->_mousePos;
+
+ for (int i = 0; i < (int)_invCoords.size(); ++i) {
+ if (_invCoords[i].contains(pt))
+ return i;
+ }
+
+ return -1;
+}
+
+void InventoryManager::saveScreens() {
+ _vm->_buffer1.copyTo(&_savedBuffer1);
+ _vm->_screen->copyTo(&_savedScreen);
+ _vm->_newRects.push_back(Common::Rect(0, 0, _savedScreen.w, _savedScreen.h));
+
+}
+
+void InventoryManager::restoreScreens() {
+ _vm->_buffer1.w = _vm->_buffer1.pitch;
+ _savedBuffer1.copyTo(&_vm->_buffer1);
+ _savedScreen.copyTo(_vm->_screen);
+
+ _savedBuffer1.free();
+ _savedScreen.free();
+}
+
+void InventoryManager::outlineIcon(int itemIndex) {
+ Screen &screen = *_vm->_screen;
+ screen.frameRect(_invCoords[itemIndex], 7);
+
+ Common::String s = _tempLOff[itemIndex];
+ Font &font = _vm->_fonts._font2;
+ int strWidth = font.stringWidth(s);
+
+ font._fontColors[0] = 0;
+ font._fontColors[1] = 10;
+ font._fontColors[2] = 11;
+ font._fontColors[3] = 12;
+ font.drawString(&screen, s, Common::Point((screen.w - strWidth) / 2, 184));
+}
+
+void InventoryManager::combineItems() {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ screen._leftSkip = screen._rightSkip = 0;
+ screen._topSkip = screen._bottomSkip = 0;
+ screen._screenYOff = 0;
+
+ Common::Point tempMouse = events._mousePos;
+ Common::Point lastMouse = events._mousePos;
+
+ Common::Rect &inv = _invCoords[_boxNum];
+ Common::Rect r(inv.left, inv.top, inv.left + 46, inv.top + 35);
+ Common::Point tempBox(inv.left, inv.top);
+ Common::Point lastBox(inv.left, inv.top);
+
+ _vm->_buffer2.copyBlock(&_vm->_buffer1, r);
+ SpriteResource *sprites = _vm->_objectsTable[99];
+ int invItem = _items[_boxNum];
+ events.pollEvents();
+
+ // Item drag handling loop if left button is held down
+ while (!_vm->shouldQuit() && events._leftButton) {
+ // Poll for events
+ events.pollEventsAndWait();
+
+ // Check positioning
+ if (lastMouse == events._mousePos)
+ continue;
+
+ lastMouse = events._mousePos;
+ Common::Rect lastRect(lastBox.x, lastBox.y, lastBox.x + 46, lastBox.y + 35);
+ screen.copyBlock(&_vm->_buffer2, lastRect);
+
+ Common::Point newPt;
+ newPt.x = MAX(events._mousePos.x - tempMouse.x + tempBox.x, 0);
+ newPt.y = MAX(events._mousePos.y - tempMouse.y + tempBox.y, 0);
+
+ screen.plotImage(sprites, invItem, newPt);
+ lastBox = newPt;
+ }
+
+ int destBox = events.checkMouseBox1(_invCoords);
+ if (destBox >= 0 && destBox != _boxNum && destBox < (int)_items.size()
+ && _items[destBox] != -1) {
+ int itemA = invItem;
+ int itemB = _items[destBox];
+
+ // Check whether the items can be combined
+ int combinedItem = _inv[itemA].checkItem(itemB);
+ if (combinedItem != -1) {
+ _inv[combinedItem]._value = 1;
+ _inv[itemA]._value = 2;
+ _inv[itemB]._value = 2;
+ _items[_boxNum] = -1;
+ _items[destBox] = combinedItem;
+ _tempLOff[destBox] = _inv[combinedItem]._name;
+ events.hideCursor();
+
+ // Shrink down the first item on top of the second item
+ zoomIcon(itemA, itemB, destBox, true);
+
+ // Shrink down the second item
+ Common::Rect destRect(_invCoords[destBox].left, _invCoords[destBox].top,
+ _invCoords[destBox].left + 46, _invCoords[destBox].top + 35);
+ _vm->_buffer2.copyBlock(&_vm->_buffer1, destRect);
+ screen._screenYOff = 0;
+ zoomIcon(itemB, -1, destBox, true);
+
+ // Exand up the new combined item from nothing to full size
+ zoomIcon(combinedItem, -1, destBox, false);
+
+ _boxNum = destBox;
+ events.showCursor();
+ return;
+ }
+ }
+
+ _iconDisplayFlag = true;
+ putInvIcon(_boxNum, invItem);
+}
+
+void InventoryManager::zoomIcon(int zoomItem, int backItem, int zoomBox, bool shrink) {
+ Screen &screen = *_vm->_screen;
+ screen._screenYOff = 0;
+ SpriteResource *sprites = _vm->_objectsTable[99];
+
+ int oldScale = _vm->_scale;
+ int zoomScale = shrink ? 255 : 1;
+ int zoomInc = shrink ? -1 : 1;
+ Common::Rect boxRect(_invCoords[zoomBox].left, _invCoords[zoomBox].top,
+ _invCoords[zoomBox].left + 46, _invCoords[zoomBox].top + 35);
+
+ while (!_vm->shouldQuit() && zoomScale != 0 && zoomScale != 256) {
+ _vm->_events->pollEventsAndWait();
+
+ _vm->_buffer2.copyBlock(&_vm->_buffer1, boxRect);
+ if (backItem != -1) {
+ _iconDisplayFlag = false;
+ putInvIcon(zoomBox, backItem);
+ }
+
+ _vm->_scale = zoomScale;
+ screen.setScaleTable(zoomScale);
+
+ int xv = screen._scaleTable1[boxRect.width() + 1];
+ if (xv) {
+ int yv = screen._scaleTable1[boxRect.height() + 1];
+ if (yv) {
+ // The zoomed size is positive in both directions, so show zoomed item
+ Common::Rect scaledBox(xv, yv);
+ scaledBox.moveTo(boxRect.left + (boxRect.width() - xv + 1) / 2,
+ boxRect.top + (boxRect.height() - yv + 1) / 2);
+
+ _vm->_buffer2.sPlotF(sprites->getFrame(zoomItem), scaledBox);
+ }
+ }
+
+ screen.copyBlock(&_vm->_buffer2, boxRect);
+
+ zoomScale += zoomInc;
+ }
+
+ if (!shrink) {
+ // Handle the final full-size version
+ _vm->_buffer2.copyBlock(&_vm->_buffer1, boxRect);
+ _vm->_buffer2.plotImage(sprites, zoomItem,
+ Common::Point(boxRect.left, boxRect.top));
+ screen.copyBlock(&_vm->_buffer2, boxRect);
+ }
+
+ _vm->_scale = oldScale;
+ screen.setScaleTable(oldScale);
+}
+
+void InventoryManager::synchronize(Common::Serializer &s) {
+ int count = _inv.size();
+ s.syncAsUint16LE(count);
+
+ if (!s.isSaving())
+ _inv.resize(count);
+
+ for (int i = 0; i < count; ++i)
+ s.syncAsUint16LE(_inv[i]._value);
+}
+
+} // End of namespace Access
diff --git a/engines/access/inventory.h b/engines/access/inventory.h
new file mode 100644
index 0000000000..6a9390eda9
--- /dev/null
+++ b/engines/access/inventory.h
@@ -0,0 +1,140 @@
+/* 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 ACCESS_INVENTORY_H
+#define ACCESS_INVENTORY_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str-array.h"
+#include "access/data.h"
+#include "access/asurface.h"
+
+namespace Access {
+
+enum ItemState {
+ ITEM_NOT_FOUND = 0, ITEM_IN_INVENTORY = 1, ITEM_USED = 2
+};
+
+class InventoryEntry {
+public:
+ Common::String _name;
+ int _value;
+
+ int _otherItem1;
+ int _newItem1;
+ int _otherItem2;
+ int _newItem2;
+
+ void load(const Common::String &name, const int *data);
+
+ int checkItem(int itemId);
+};
+
+class InventoryManager : public Manager {
+ struct SavedFields {
+ int _vWindowHeight;
+ int _vWindowLinesTall;
+ int _vWindowWidth;
+ int _vWindowBytesWide;
+ int _playFieldHeight;
+ int _playFieldWidth;
+ int _windowXAdd;
+ int _windowYAdd;
+ int _screenYOff;
+ int _scrollX;
+ int _scrollY;
+ int _clipWidth;
+ int _clipHeight;
+ Common::Point _bufferStart;
+ int _scrollCol;
+ int _scrollRow;
+ };
+private:
+ Common::Array<int> _items;
+ Common::Array<Common::Rect> _invCoords;
+ ASurface _savedBuffer1;
+ ASurface _savedScreen;
+ SavedFields _fields;
+ bool _iconDisplayFlag;
+ Common::Array<int> _tempLPtr;
+ Common::StringArray _tempLOff;
+ int _boxNum;
+
+ void savedFields();
+
+ void restoreFields();
+
+ void initFields();
+
+ void getList();
+
+ void showAllItems();
+
+ void putInvIcon(int itemIndex, int itemId);
+
+ void chooseItem();
+
+ void freeInvCells();
+
+ int coordIndexOf();
+
+ void saveScreens();
+
+ void restoreScreens();
+
+ void outlineIcon(int itemIndex);
+
+ void combineItems();
+
+ void zoomIcon(int zoomItem, int backItem, int zoomBox, bool shrink);
+public:
+ Common::Array<InventoryEntry> _inv;
+ int _startInvItem;
+ int _startInvBox;
+ bool _invChangeFlag;
+ bool _invRefreshFlag;
+ bool _invModeFlag;
+ int _startAboutItem;
+ int _startTravelItem;
+public:
+ InventoryManager(AccessEngine *vm);
+
+ int &operator[](int idx);
+
+ int useItem();
+ void setUseItem(int itemId);
+
+ void refreshInventory();
+
+ int newDisplayInv();
+
+ /**
+ * Synchronize savegame data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_INVENTORY_H */
diff --git a/engines/access/martian/martian_game.cpp b/engines/access/martian/martian_game.cpp
new file mode 100644
index 0000000000..6392206209
--- /dev/null
+++ b/engines/access/martian/martian_game.cpp
@@ -0,0 +1,168 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "access/resources.h"
+#include "access/martian/martian_game.h"
+#include "access/martian/martian_resources.h"
+#include "access/martian/martian_room.h"
+#include "access/martian/martian_scripts.h"
+#include "access/amazon/amazon_resources.h"
+
+namespace Access {
+
+namespace Martian {
+
+MartianEngine::MartianEngine(OSystem *syst, const AccessGameDescription *gameDesc) : AccessEngine(syst, gameDesc) {
+}
+
+MartianEngine::~MartianEngine() {
+}
+
+void MartianEngine::playGame() {
+ // Do introduction
+ doIntroduction();
+ if (shouldQuit())
+ return;
+
+ // Setup the game
+ setupGame();
+
+ _screen->clearScreen();
+ _screen->setPanel(0);
+ _screen->forceFadeOut();
+
+ _events->showCursor();
+
+ // Setup and execute the room
+ _room = new MartianRoom(this);
+ _scripts = new MartianScripts(this);
+ _room->doRoom();
+}
+
+void MartianEngine::doIntroduction() {
+ _screen->setInitialPalettte();
+ _events->setCursor(CURSOR_ARROW);
+ _events->showCursor();
+ _screen->setPanel(0);
+
+ // TODO: Worry about implementing full intro sequence later
+ return;
+
+ doTitle();
+ if (shouldQuit())
+ return;
+
+ if (!_skipStart) {
+ _screen->setPanel(3);
+ doOpening();
+ if (shouldQuit())
+ return;
+
+ if (!_skipStart) {
+ //doTent();
+ if (shouldQuit())
+ return;
+ }
+ }
+
+ doTitle();
+}
+
+void MartianEngine::doTitle() {
+ /*
+ _screen->setDisplayScan();
+ _destIn = &_buffer2;
+
+ _screen->forceFadeOut();
+ _events->hideCursor();
+
+ _sound->queueSound(0, 98, 30);
+
+ _files->_setPaletteFlag = false;
+ _files->loadScreen(0, 3);
+
+ _buffer2.copyFrom(*_screen);
+ _buffer1.copyFrom(*_screen);
+ _screen->forceFadeIn();
+ _sound->playSound(1);
+
+ Resource *spriteData = _files->loadFile(0, 2);
+ _objectsTable[0] = new SpriteResource(this, spriteData);
+ delete spriteData;
+
+ _sound->playSound(1);
+
+ _files->_setPaletteFlag = false;
+ _files->loadScreen(0, 4);
+ _sound->playSound(1);
+
+ _buffer2.copyFrom(*_screen);
+ _buffer1.copyFrom(*_screen);
+ _sound->playSound(1);
+
+ const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 };
+ for (_pCount = 0; _pCount < 3; ++_pCount) {
+ _buffer2.copyFrom(_buffer1);
+ int id = READ_LE_UINT16(COUNTDOWN + _pCount * 4);
+ int xp = READ_LE_UINT16(COUNTDOWN + _pCount * 4 + 2);
+ _screen->plotImage(_objectsTable[0], id, Common::Point(xp, 71));
+ }
+ // TODO: More to do
+
+ delete _objectsTable[0];
+ */
+}
+
+void MartianEngine::doOpening() {
+ warning("TODO doOpening");
+}
+
+void MartianEngine::setupGame() {
+
+ // Setup timers
+ const int TIMER_DEFAULTS[] = { 4, 10, 8, 1, 1, 1, 1, 2 };
+ for (int i = 0; i < 32; ++i) {
+ TimerEntry te;
+ te._initTm = te._timer = (i < 8) ? TIMER_DEFAULTS[i] : 1;
+ te._flag = 1;
+
+ _timers.push_back(te);
+ }
+
+ // Miscellaneous
+ // TODO: Replace with Martian fonts when located
+ _fonts._font1.load(Amazon::FONT6x6_INDEX, Amazon::FONT6x6_DATA);
+ _fonts._font2.load(Amazon::FONT2_INDEX, Amazon::FONT2_DATA);
+
+ // Set player room and position
+ _player->_roomNumber = 7;
+ _player->_playerX = _player->_rawPlayer.x = TRAVEL_POS[_player->_roomNumber][0];
+ _player->_playerY = _player->_rawPlayer.y = TRAVEL_POS[_player->_roomNumber][1];
+}
+
+void MartianEngine::drawHelp() {
+ error("TODO: drawHelp");
+}
+
+} // End of namespace Martian
+
+} // End of namespace Access
diff --git a/engines/access/martian/martian_game.h b/engines/access/martian/martian_game.h
new file mode 100644
index 0000000000..a83b67a288
--- /dev/null
+++ b/engines/access/martian/martian_game.h
@@ -0,0 +1,76 @@
+/* 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 ACCESS_MARTIAN_GAME_H
+#define ACCESS_MARTIAN_GAME_H
+
+#include "access/access.h"
+
+namespace Access {
+
+namespace Martian {
+
+class MartianEngine : public AccessEngine {
+private:
+ bool _skipStart;
+
+ /**
+ * Do the game introduction
+ */
+ void doIntroduction();
+
+ /**
+ * Do title sequence
+ */
+ void doTitle();
+
+ /**
+ * Do opening sequence
+ */
+ void doOpening();
+
+ /**
+ * Setup variables for the game
+ */
+ void setupGame();
+
+protected:
+ /**
+ * Play the game
+ */
+ virtual void playGame();
+
+ virtual void dead(int deathId) {}
+public:
+ MartianEngine(OSystem *syst, const AccessGameDescription *gameDesc);
+
+ virtual ~MartianEngine();
+
+ void drawHelp();
+ virtual void establish(int esatabIndex, int sub) {};
+};
+
+} // End of namespace Martian
+
+} // End of namespace Access
+
+#endif /* ACCESS_MARTIAN_GAME_H */
diff --git a/engines/access/martian/martian_resources.cpp b/engines/access/martian/martian_resources.cpp
new file mode 100644
index 0000000000..d2b5dfd5d0
--- /dev/null
+++ b/engines/access/martian/martian_resources.cpp
@@ -0,0 +1,722 @@
+/* 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 "access/martian/martian_resources.h"
+#include "access/access.h"
+
+namespace Access {
+
+namespace Martian {
+
+const char *const FILENAMES[] = {
+ "R00.AP", "R01.AP", "R02.AP", "R03.AP", "R04.AP", "R05.AP", "R06.AP", "R07.AP",
+ "R08.AP", "R09.AP", "R10.AP", "R11.AP", "R12.AP", "R13.AP", "R14.AP", "R15.AP",
+ "R16.AP", "R17.AP", "R18.AP", "R19.AP", "R20.AP", "R21.AP", "R22.AP", "R23.AP",
+ "R24.AP", "R25.AP", "R26.AP", "R27.AP", "R28.AP", "R29.AP", "R30.AP", "R31.AP",
+ "R32.AP", "R33.AP", "R34.AP", "R35.AP", "R36.AP", "R37.AP", "R38.AP", "R39.AP",
+ "R40.AP","TITLE.AP","R42.AP","S01.AP", "R44.AP", "R45.AP","SOUND.AP","MUSIC.AP",
+ "DEAD.AP","EST.AP", "W02.AP", "C02.AP", "C05.AP", "C04.AP", "C10.AP", "C03.AP",
+ "C07.AP", "LOVE.AP","CAFE.AP","C08.AP", "C18.AP", "C19.AP", "C21.AP", "C23.AP",
+ "C12.AP", "C16.AP","CAFE1.AP","C05A.AP","C06.AP","C11.AP", "C13.AP", "C20.AP",
+ "C16A.AP","C09.AP", "R45.AP", "R46.AP", "R47.AP", "R48.AP", "R49.AP"
+};
+
+const byte MOUSE0[] = {
+ 0, 0, 0, 0, 0, 2, 0xF7, 5, 0, 3, 0xF7, 0xF7, 5, 0, 3,
+ 0xF7, 0xF7, 5, 0, 4, 0xF7, 0xF7, 0xF7, 5, 0, 4, 0xF7,
+ 0xF7, 0xF7, 5, 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5, 0, 5,
+ 0xF7, 0xF7, 0xF7, 0xF7, 5, 0, 6, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 5, 0, 6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5, 0, 7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 5, 0, 6, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 5, 0, 5, 0xF7, 0xF7, 0xF7, 0xF7, 5,
+ 2, 3, 0xF7, 0xF7, 5, 3, 3, 0xF7, 0xF7, 5, 3, 3, 0xF7,
+ 0xF7, 5, 4, 2, 0xF7, 5
+};
+const byte MOUSE1[] = {
+ 7, 0, 7, 0, 6, 1, 0xF7, 4, 5, 0xFF, 0xFF, 0, 0xFF, 0xFF,
+ 3, 7, 0xFF, 0, 0, 0, 0, 0, 0xFF, 2, 9, 0xFF, 0, 0, 0,
+ 0xF7, 0, 0, 0, 0xFF, 1, 11, 0xFF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFF, 1, 11, 0xFF, 0, 0, 0, 0, 0xF7, 0, 0,
+ 0, 0, 0xFF, 0, 13, 0xF7, 0, 0, 0xF7, 0, 0xF7, 0, 0xF7,
+ 0, 0xF7, 0, 0, 0xF7, 1, 11, 0xFF, 0, 0, 0, 0, 0xF7,
+ 0, 0, 0, 0, 0xFF, 1, 11, 0xFF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFF, 2, 9, 0xFF, 0, 0, 0, 0xF7, 0, 0, 0, 0xFF,
+ 3, 7, 0xFF, 0, 0, 0, 0, 0, 0xFF, 4, 5, 0xFF, 0xFF, 0,
+ 0xFF, 0xFF, 6, 1, 0xF7, 0, 0, 0, 0, 0, 0
+};
+const byte MOUSE2[] = {
+ 8, 0, 8, 0, 0, 0, 0, 0, 7, 2, 4, 5, 7, 2, 4, 5, 7, 2,
+ 4, 5, 7, 2, 4, 5, 7, 2, 4, 5, 2, 12, 4, 4, 4, 4, 4,
+ 0, 4, 4, 4, 4, 4, 5, 7, 2, 4, 5, 7, 2, 4, 5, 7, 2, 4,
+ 5, 7, 2, 4, 5, 7, 2, 4, 5, 0, 0, 0, 0, 0, 0
+};
+const byte MOUSE3[] = {
+ 0, 0, 0, 0, 0, 11, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 0, 12, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 0, 12,
+ 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 5, 0, 12, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 5, 0, 12, 6, 6, 6, 6, 6, 5,
+ 6, 6, 6, 6, 6, 5, 0, 12, 6, 6, 6, 6, 5, 0, 0, 6, 6,
+ 6, 6, 5, 0, 12, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 5,
+ 0, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 0, 12,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 0, 12, 6, 6, 6,
+ 6, 6, 5, 6, 6, 6, 6, 6, 5, 0, 12, 6, 6, 6, 6, 6, 5,
+ 6, 6, 6, 6, 6, 5, 0, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 5, 1, 11, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
+ 0, 0, 0, 0, 0
+};
+const byte *const CURSORS[4] = { MOUSE0, MOUSE1, MOUSE2, MOUSE3 };
+
+const int TRAVEL_POS[][2] = {
+ { -1, 0 },
+ { 228, 117 },
+ { 28, 98 },
+ { 161, 140 },
+ { 160, 116 },
+ { 34, 119 },
+ { 166, 105 },
+ { 260, 126 },
+ { 37, 107 },
+ { 78, 139 },
+ { 0, 0 },
+ { 13, 112 },
+ { 0, 0 },
+ { 16, 122 },
+ { 33, 126 },
+ { 10, 160 },
+ { 150, 102 },
+ { 134, 160 },
+ { 160, 76 },
+ { 0, 0 },
+ { 0, 0 },
+ { 36, 116 },
+ { 214, 113 },
+ { 30, 127 },
+ { 143, 131 },
+ { 163, 103 },
+ { 254, 106 },
+ { 28, 161 },
+ { 11, 164 },
+ { 276, 134 },
+ { 93, 118 },
+ { 22, 150 },
+ { 282, 156 },
+ { 149, 92 },
+ { 0, 0 },
+ { 43, 410 },
+ { 0, 0 },
+ { 10, 136 },
+ { 41, 100 },
+ { 157, 97 },
+ { -1, 5 },
+ { -1, 4 },
+ { -1, 10 },
+ { -1, 7 },
+ { -1, 3 },
+ { -1, 8 },
+ { -1, 6 },
+ { -1, 20 },
+ { -1, 18 },
+ { -1, 19 },
+ { -1, 21 }
+};
+
+const char *const INVENTORY_NAMES[] = {
+ "CAMERA", "LENS", "PHOTOS", "MAIL", "GUN", "CASH", "COMLINK", "AMMO",
+ "LOCKPICK KIT", "EARRING", "RECIEPTS", "PAPER", "LADDER", "BOOTS",
+ "DOCUMENTS", "KNIFE", "DAGGER", "KEYS", "ROCK", "LOG", "SHOVEL",
+ "STONE", "REMOTE CONTROL", "FOOD AND WATER", "DOOR CARD KEY",
+ "FLASHLIGHT", "INTERLOCK KEY", "TOOLS", "REBREATHER", "JET PACK",
+ "ROD", "HCL2", "SAFE CARD KEY", "TUNING FORK", "STONE", "ROSE",
+ "KEY", "NOTE", "ALLEN WRENCH", "HOVER BOARD", "BLUE PRINTS",
+ "LETTER", "MEMORANDUM", "MARKERS", "FILM", "ANDRETTI FILM",
+ "GLASSES", "AMULET", "FACIAL KIT", "CAT FOOD", "MONKEY WRENCH",
+ "BIG DICK CARD", "BRA", "BOLT"
+};
+
+const byte ROOM_TABLE1[] = {
+ 0x00, 0x2f, 0x00, 0x0d, 0x00, 0x30, 0x22, 0x30, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0xff, 0x01, 0x00,
+ 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0xc0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x05, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE2[] = {
+ 0x00, 0x2f, 0x00, 0x0d, 0x00, 0x32, 0x28, 0x25, 0x02, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x03, 0x00, 0xff, 0x02, 0x00,
+ 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0xc8, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x06, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE3[] = {
+ 0x00, 0x2f, 0x00, 0x0f, 0x00, 0x1e, 0x19, 0x24, 0x03, 0x00,
+ 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x00, 0xff, 0x03, 0x00,
+ 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x78, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x05, 0x00,
+ 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x01, 0x00, 0x2e, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE4[] = {
+ 0x00, 0x2f, 0x00, 0x06, 0x00, 0x36, 0x27, 0x32, 0x04, 0x00,
+ 0x00, 0x00, 0x04, 0x04, 0x00, 0x03, 0x00, 0xff, 0x04, 0x00,
+ 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0xc8, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x05, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE5[] = {
+ 0x00, 0x2f, 0x00, 0x00, 0x00, 0x28, 0x19, 0x36, 0x05, 0x00,
+ 0x00, 0x00, 0x05, 0x05, 0x00, 0x03, 0x00, 0xff, 0x05, 0x00,
+ 0x02, 0x00, 0x05, 0x00, 0x01, 0x00, 0xa0, 0x20, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x03, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE6[] = {
+ 0x00, 0x2f, 0x00, 0x07, 0x00, 0x40, 0x36, 0x36, 0x06, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x03, 0x00, 0xff, 0x06, 0x00,
+ 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x13, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x08, 0x00,
+ 0x01, 0x00, 0x2e, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2e, 0x00,
+ 0x07, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE7[] = {
+ 0x00, 0x2f, 0x00, 0x0e, 0x00, 0x40, 0x32, 0x3b, 0x07, 0x00,
+ 0x00, 0x00, 0x07, 0x07, 0x00, 0x03, 0x00, 0xff, 0x07, 0x00,
+ 0x02, 0x00, 0x07, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE8[] = {
+ 0x00, 0x2f, 0x00, 0x0a, 0x00, 0x30, 0x22, 0x46, 0x08, 0x00,
+ 0x00, 0x00, 0x08, 0x08, 0x00, 0x03, 0x00, 0xff, 0x08, 0x00,
+ 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0xc0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff,
+};
+const byte ROOM_TABLE9[] = {
+ 0x00, 0x2f, 0x00, 0x07, 0x00, 0x32, 0x0c, 0x29, 0x09, 0x00,
+ 0x00, 0x00, 0x09, 0x09, 0x00, 0x03, 0x00, 0xff, 0x09, 0x00,
+ 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0xc8, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff,
+};
+const byte ROOM_TABLE11[] = {
+ 0x00, 0x2f, 0x00, 0x00, 0x00, 0x40, 0x3a, 0x22, 0x0b, 0x00,
+ 0x00, 0x00, 0x0b, 0x0b, 0x00, 0x03, 0x00, 0xff, 0x0b, 0x00,
+ 0x02, 0x00, 0x0b, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff,
+};
+const byte ROOM_TABLE13[] = {
+ 0x00, 0x2f, 0x00, 0x0c, 0x00, 0x40, 0x36, 0x2c, 0x0d, 0x00,
+ 0x00, 0x00, 0x0d, 0x0d, 0x00, 0x03, 0x00, 0xff, 0x0d, 0x00,
+ 0x02, 0x00, 0x0d, 0x00, 0x01, 0x00, 0xe6, 0x40, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0x2e, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x2e, 0x00,
+ 0x15, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE14[] = {
+ 0x00, 0x2f, 0x00, 0x05, 0x00, 0x40, 0x3e, 0x33, 0x0e, 0x00,
+ 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x03, 0x00, 0xff, 0x0e, 0x00,
+ 0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0xfe, 0x40, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x09, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0x2e, 0x00, 0x13, 0x00, 0x01, 0x00, 0x2e, 0x00,
+ 0x0a, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE15[] = {
+ 0x00, 0x2f, 0x00, 0x0c, 0x00, 0x28, 0x0c, 0x5e, 0x0f, 0x00,
+ 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x03, 0x00, 0xff, 0x0f, 0x00,
+ 0x02, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xb4, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x11, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE16[] = {
+ 0x00, 0x2f, 0x00, 0x05, 0x00, 0x28, 0x1e, 0x24, 0x10, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x00, 0x03, 0x00, 0xff, 0x10, 0x00,
+ 0x02, 0x00, 0x10, 0x00, 0x01, 0x00, 0xa0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE17[] = {
+ 0x00, 0x2f, 0x00, 0x06, 0x00, 0x28, 0x19, 0x2b, 0x11, 0x00,
+ 0x00, 0x00, 0x11, 0x11, 0x00, 0x03, 0x00, 0xff, 0x11, 0x00,
+ 0x02, 0x00, 0x11, 0x00, 0x01, 0x00, 0xa0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x05, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE18[] = {
+ 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x3c, 0x12, 0x00,
+ 0x00, 0x00, 0x12, 0x12, 0x00, 0x03, 0x00, 0xff, 0x12, 0x00,
+ 0x02, 0x00, 0x12, 0x00, 0x01, 0x00, 0xb1, 0x40, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x05, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE21[] = {
+ 0x00, 0x2f, 0x00, 0x07, 0x00, 0x3c, 0x2a, 0x29, 0x15, 0x00,
+ 0x00, 0x00, 0x15, 0x15, 0x00, 0x03, 0x00, 0xff, 0x15, 0x00,
+ 0x02, 0x00, 0x15, 0x00, 0x01, 0x00, 0xf0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE22[] = {
+ 0x00, 0x2f, 0x00, 0x0a, 0x00, 0x40, 0x2d, 0x27, 0x16, 0x00,
+ 0x00, 0x00, 0x16, 0x16, 0x00, 0x03, 0x00, 0xff, 0x16, 0x00,
+ 0x02, 0x00, 0x16, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x16, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE23[] = {
+ 0x00, 0x2f, 0x00, 0x0a, 0x00, 0x40, 0x38, 0x24, 0x17, 0x00,
+ 0x00, 0x00, 0x17, 0x17, 0x00, 0x03, 0x00, 0xff, 0x17, 0x00,
+ 0x02, 0x00, 0x17, 0x00, 0x01, 0x00, 0xfe, 0x40, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x17, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE24[] = {
+ 0x00, 0x2f, 0x00, 0x06, 0x00, 0x3e, 0x10, 0x62, 0x18, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x03, 0x00, 0xff, 0x18, 0x00,
+ 0x02, 0x00, 0x18, 0x00, 0x01, 0x00, 0xf8, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x16, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE25[] = {
+ 0x00, 0x2f, 0x00, 0x0e, 0x00, 0x3e, 0x37, 0x19, 0x19, 0x00,
+ 0x00, 0x00, 0x19, 0x19, 0x00, 0x03, 0x00, 0xff, 0x19, 0x00,
+ 0x02, 0x00, 0x19, 0x00, 0x01, 0x00, 0xf8, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x10, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE26[] = {
+ 0x00, 0x2f, 0x00, 0x06, 0x00, 0x34, 0x28, 0x28, 0x1a, 0x00,
+ 0x00, 0x00, 0x1a, 0x1a, 0x00, 0x03, 0x00, 0xff, 0x1a, 0x00,
+ 0x02, 0x00, 0x1a, 0x00, 0x01, 0x00, 0xd0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE27[] = {
+ 0x00, 0x2f, 0x00, 0x0f, 0x00, 0x1b, 0x16, 0x18, 0x1b, 0x00,
+ 0x00, 0x00, 0x1b, 0x1b, 0x00, 0x03, 0x00, 0xff, 0x1b, 0x00,
+ 0x02, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x70, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE28[] = {
+ 0x00, 0x2f, 0x00, 0x09, 0x00, 0x25, 0x10, 0x43, 0x1c, 0x00,
+ 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x03, 0x00, 0xff, 0x1c, 0x00,
+ 0x02, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x94, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff,
+};
+const byte ROOM_TABLE29[] = {
+ 0x00, 0x2f, 0x00, 0x0a, 0x00, 0x20, 0x18, 0x56, 0x1d, 0x00,
+ 0x00, 0x00, 0x1d, 0x1d, 0x00, 0x03, 0x00, 0xff, 0x1d, 0x00,
+ 0x02, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x80, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x17, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x10, 0x00,
+ 0x02, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE30[] = {
+ 0x00, 0x2f, 0x00, 0x07, 0x00, 0x3f, 0x1c, 0x27, 0x1e, 0x00,
+ 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x03, 0x00, 0xff, 0x1e, 0x00,
+ 0x02, 0x00, 0x1e, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x1e, 0x00, 0x04, 0x00, 0xff, 0xff, 0x2e, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x15, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE31[] = {
+ 0x00, 0x2f, 0x00, 0x0d, 0x00, 0x32, 0x2e, 0x69, 0x1f, 0x00,
+ 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x03, 0x00, 0xff, 0x1f, 0x00,
+ 0x02, 0x00, 0x1f, 0x00, 0x01, 0x00, 0xc8, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff,
+};
+const byte ROOM_TABLE32[] = {
+ 0x00, 0x2f, 0x00, 0x07, 0x00, 0x40, 0x3b, 0x4b, 0x20, 0x00,
+ 0x00, 0x00, 0x20, 0x20, 0x00, 0x03, 0x00, 0xff, 0x20, 0x00,
+ 0x02, 0x00, 0x20, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x05, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE33[] = {
+ 0x00, 0x2f, 0x00, 0x0b, 0x00, 0x30, 0x10, 0x51, 0x21, 0x00,
+ 0x00, 0x00, 0x21, 0x21, 0x00, 0x03, 0x00, 0xff, 0x21, 0x00,
+ 0x02, 0x00, 0x21, 0x00, 0x01, 0x00, 0xc0, 0x40, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xff, 0xff,
+};
+const byte ROOM_TABLE35[] = {
+ 0x00, 0x2f, 0x00, 0x0f, 0x00, 0x1e, 0x18, 0x25, 0x23, 0x00,
+ 0x00, 0x00, 0x23, 0x23, 0x00, 0x03, 0x00, 0xff, 0x23, 0x00,
+ 0x02, 0x00, 0x23, 0x00, 0x01, 0x00, 0x78, 0x18, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x07, 0x00,
+ 0x01, 0x00, 0x2e, 0x00, 0x16, 0x00, 0x01, 0x00, 0x2e, 0x00,
+ 0x0c, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE37[] = {
+ 0x00, 0x2f, 0x00, 0x0f, 0x00, 0x3f, 0x3a, 0x1a, 0x25, 0x00,
+ 0x00, 0x00, 0x25, 0x25, 0x00, 0x03, 0x00, 0xff, 0x25, 0x00,
+ 0x02, 0x00, 0x25, 0x00, 0x01, 0x00, 0xfe, 0x40, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x0d, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE38[] = {
+ 0x00, 0x2f, 0x00, 0x0d, 0x00, 0x40, 0x32, 0x32, 0x26, 0x00,
+ 0x00, 0x00, 0x26, 0x26, 0x00, 0x03, 0x00, 0xff, 0x26, 0x00,
+ 0x02, 0x00, 0x26, 0x00, 0x01, 0x00, 0xf0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x0b, 0x00, 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE39[] = {
+ 0x00, 0x2f, 0x00, 0x0a, 0x00, 0x3c, 0x10, 0x4c, 0x27, 0x00,
+ 0x00, 0x00, 0x27, 0x27, 0x00, 0x03, 0x00, 0xff, 0x27, 0x00,
+ 0x02, 0x00, 0x27, 0x00, 0x01, 0x00, 0xf0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x2e, 0x00, 0x11, 0x00, 0x01, 0x00, 0x2e, 0x00, 0x0f, 0x00,
+ 0x01, 0x00, 0xff, 0xff,
+};
+const byte ROOM_TABLE47[] = {
+ 0x00, 0x2f, 0x00, 0x06, 0x00, 0x28, 0x1e, 0x32, 0x2b, 0x00,
+ 0x00, 0x00, 0x46, 0x2b, 0x00, 0x03, 0x00, 0xff, 0x2b, 0x00,
+ 0x02, 0x00, 0x2b, 0x00, 0x01, 0x00, 0xf0, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x2b, 0x00, 0x04, 0x00, 0xff, 0xff, 0x2e, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00,
+};
+const byte *const ROOM_TABLE[] = {
+ nullptr, ROOM_TABLE1, ROOM_TABLE2, ROOM_TABLE3, ROOM_TABLE4, ROOM_TABLE5, ROOM_TABLE6,
+ ROOM_TABLE7, ROOM_TABLE8, ROOM_TABLE9, nullptr, ROOM_TABLE11, nullptr, ROOM_TABLE13,
+ ROOM_TABLE14, ROOM_TABLE15, ROOM_TABLE16, ROOM_TABLE17, ROOM_TABLE18, nullptr, nullptr,
+ ROOM_TABLE21, ROOM_TABLE22, ROOM_TABLE23, ROOM_TABLE24, ROOM_TABLE25, ROOM_TABLE26, ROOM_TABLE27,
+ ROOM_TABLE28, ROOM_TABLE29, ROOM_TABLE30, ROOM_TABLE31, ROOM_TABLE32, ROOM_TABLE33, nullptr,
+ ROOM_TABLE35, nullptr, ROOM_TABLE37, ROOM_TABLE38, ROOM_TABLE39, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, ROOM_TABLE47
+};
+
+const char *const ROOM_DESCR[] = {
+ nullptr, "TBD ROOM_TABLE1", "TBD ROOM_TABLE2", "TBD ROOM_TABLE3", "TBD ROOM_TABLE4",
+ "TBD ROOM_TABLE5", "TBD ROOM_TABLE6", "TBD ROOM_TABLE7", "TBD ROOM_TABLE8", "TBD ROOM_TABLE9",
+ nullptr, "TBD ROOM_TABLE11", nullptr, "TBD ROOM_TABLE13", "TBD ROOM_TABLE14",
+ "TBD ROOM_TABLE15", "TBD ROOM_TABLE16", "TBD ROOM_TABLE17", "TBD ROOM_TABLE18", nullptr,
+ nullptr, "TBD ROOM_TABLE21", "TBD ROOM_TABLE22", "TBD ROOM_TABLE23", "TBD ROOM_TABLE24",
+ "TBD ROOM_TABLE25", "TBD ROOM_TABLE26", "TBD ROOM_TABLE27", "TBD ROOM_TABLE28", "TBD ROOM_TABLE29",
+ "TBD ROOM_TABLE30", "TBD ROOM_TABLE31", "TBD ROOM_TABLE32", "TBD ROOM_TABLE33", nullptr,
+ "TBD ROOM_TABLE35", nullptr, "TBD ROOM_TABLE37", "TBD ROOM_TABLE38", "TBD ROOM_TABLE39",
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, "TBD ROOM_TABLE47"
+};
+
+const int ROOM_NUMB = 48;
+
+const byte CHAR_TABLE0[] = {
+ 0x02, 0x31, 0x00, 0x08, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE2[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x32, 0x33, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, 0x00, 0x00, 0x00, 0x33,
+ 0x00, 0x02, 0x00, 0x33, 0x00, 0x0b, 0x00, 0x33, 0x00, 0x03,
+ 0x00, 0x33, 0x00, 0x0c, 0x00, 0x33, 0x00, 0x04, 0x00, 0x33,
+ 0x00, 0x0d, 0x00, 0x33, 0x00, 0x05, 0x00, 0x33, 0x00, 0x0e,
+ 0x00, 0x33, 0x00, 0x06, 0x00, 0x33, 0x00, 0x0f, 0x00, 0x33,
+ 0x00, 0x07, 0x00, 0x33, 0x00, 0x10, 0x00, 0x33, 0x00, 0x08,
+ 0x00, 0x33, 0x00, 0x11, 0x00, 0x33, 0x00, 0x09, 0x00, 0x33,
+ 0x00, 0x12, 0x00, 0x33, 0x00, 0x0a, 0x00, 0x33, 0x00, 0x13,
+ 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE3[] = {
+ 0x02, 0x31, 0x00, 0x03, 0x00, 0x35, 0x00, 0x37, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x4b, 0x37, 0x00, 0x01, 0x00,
+ 0xff, 0x37, 0x00, 0x03, 0x00, 0x37, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE4[] = {
+ 0x01, 0x31, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x35, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x49, 0x35, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x35, 0x00, 0x00, 0x00, 0x35,
+ 0x00, 0x03, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x35, 0x00, 0x04,
+ 0x00, 0x35, 0x00, 0x0d, 0x00, 0x35, 0x00, 0x05, 0x00, 0x35,
+ 0x00, 0x0e, 0x00, 0x35, 0x00, 0x06, 0x00, 0x35, 0x00, 0x0f,
+ 0x00, 0x35, 0x00, 0x07, 0x00, 0x35, 0x00, 0x10, 0x00, 0x35,
+ 0x00, 0x08, 0x00, 0x35, 0x00, 0x11, 0x00, 0x35, 0x00, 0x09,
+ 0x00, 0x35, 0x00, 0x12, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x35,
+ 0x00, 0x13, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x35, 0x00, 0x14,
+ 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE5[] = {
+ 0x01, 0x31, 0x00, 0x08, 0x00, 0x37, 0x00, 0x34, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x48, 0x34, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x34, 0x00, 0x00, 0x00, 0x43,
+ 0x00, 0x00, 0x00, 0x34, 0x00, 0x03, 0x00, 0x43, 0x00, 0x01,
+ 0x00, 0x34, 0x00, 0x04, 0x00, 0x43, 0x00, 0x02, 0x00, 0x34,
+ 0x00, 0x05, 0x00, 0x43, 0x00, 0x03, 0x00, 0x34, 0x00, 0x06,
+ 0x00, 0x43, 0x00, 0x04, 0x00, 0x34, 0x00, 0x07, 0x00, 0x43,
+ 0x00, 0x05, 0x00, 0x34, 0x00, 0x08, 0x00, 0x43, 0x00, 0x06,
+ 0x00, 0x34, 0x00, 0x09, 0x00, 0x43, 0x00, 0x07, 0x00, 0x34,
+ 0x00, 0x0a, 0x00, 0x43, 0x00, 0x08, 0x00, 0x34, 0x00, 0x0b,
+ 0x00, 0x43, 0x00, 0x09, 0x00, 0x34, 0x00, 0x0c, 0x00, 0x43,
+ 0x00, 0x0a, 0x00, 0x34, 0x00, 0x0d, 0x00, 0x43, 0x00, 0x0b,
+ 0x00, 0x34, 0x00, 0x0e, 0x00, 0x43, 0x00, 0x0c, 0x00, 0x34,
+ 0x00, 0x0f, 0x00, 0x43, 0x00, 0x0d, 0x00, 0x34, 0x00, 0x10,
+ 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE6[] = {
+ 0x02, 0x31, 0x00, 0x03, 0x00, 0x38, 0x00, 0x44, 0x00, 0x03,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x4e, 0x44, 0x00, 0x01, 0x00,
+ 0xff, 0x44, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE7[] = {
+ 0x02, 0x31, 0x00, 0x01, 0x00, 0x39, 0x00, 0x38, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x4c, 0x38, 0x00, 0x01, 0x00,
+ 0xff, 0x38, 0x00, 0x03, 0x00, 0x38, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE8[] = {
+ 0x03, 0xff, 0xff, 0xff, 0xff, 0x3a, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x3b, 0x00, 0x01, 0x00,
+ 0xff, 0x3b, 0x00, 0x02, 0x00, 0x3b, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE9[] = {
+ 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x59, 0x4a, 0x00, 0x01, 0x00,
+ 0xff, 0x4a, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE10[] = {
+ 0x01, 0x31, 0x00, 0x0a, 0x00, 0x3c, 0x00, 0x36, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x4a, 0x36, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x36, 0x00, 0x00, 0x00, 0x36,
+ 0x00, 0x03, 0x00, 0x36, 0x00, 0x13, 0x00, 0x36, 0x00, 0x04,
+ 0x00, 0x36, 0x00, 0x14, 0x00, 0x36, 0x00, 0x05, 0x00, 0x36,
+ 0x00, 0x15, 0x00, 0x36, 0x00, 0x06, 0x00, 0x36, 0x00, 0x16,
+ 0x00, 0x36, 0x00, 0x07, 0x00, 0x36, 0x00, 0x17, 0x00, 0x36,
+ 0x00, 0x08, 0x00, 0x36, 0x00, 0x18, 0x00, 0x36, 0x00, 0x09,
+ 0x00, 0x36, 0x00, 0x19, 0x00, 0x36, 0x00, 0x0a, 0x00, 0x36,
+ 0x00, 0x1a, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x1b,
+ 0x00, 0x36, 0x00, 0x0c, 0x00, 0x36, 0x00, 0x1c, 0x00, 0x36,
+ 0x00, 0x0d, 0x00, 0x36, 0x00, 0x1d, 0x00, 0x36, 0x00, 0x0e,
+ 0x00, 0x36, 0x00, 0x1e, 0x00, 0x36, 0x00, 0x0f, 0x00, 0x36,
+ 0x00, 0x1f, 0x00, 0x36, 0x00, 0x10, 0x00, 0x36, 0x00, 0x20,
+ 0x00, 0x36, 0x00, 0x11, 0x00, 0x36, 0x00, 0x21, 0x00, 0x36,
+ 0x00, 0x12, 0x00, 0x36, 0x00, 0x22, 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE11[] = {
+ 0x03, 0xff, 0xff, 0xff, 0xff, 0x3d, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x55, 0x45, 0x00, 0x01, 0x00,
+ 0xff, 0x45, 0x00, 0x02, 0x00, 0x45, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE12[] = {
+ 0x03, 0xff, 0xff, 0xff, 0xff, 0x3e, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0x00, 0x01, 0x00,
+ 0xff, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE13[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x46, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x56, 0x46, 0x00, 0x01, 0x00,
+ 0xff, 0x46, 0x00, 0x03, 0x00, 0x46, 0x00, 0x00, 0x00, 0x46,
+ 0x00, 0x04, 0x00, 0x46, 0x00, 0x0d, 0x00, 0x46, 0x00, 0x05,
+ 0x00, 0x46, 0x00, 0x0e, 0x00, 0x46, 0x00, 0x06, 0x00, 0x46,
+ 0x00, 0x0f, 0x00, 0x46, 0x00, 0x07, 0x00, 0x46, 0x00, 0x10,
+ 0x00, 0x46, 0x00, 0x08, 0x00, 0x46, 0x00, 0x11, 0x00, 0x46,
+ 0x00, 0x09, 0x00, 0x46, 0x00, 0x12, 0x00, 0x46, 0x00, 0x0a,
+ 0x00, 0x46, 0x00, 0x13, 0x00, 0x46, 0x00, 0x0b, 0x00, 0x46,
+ 0x00, 0x14, 0x00, 0x46, 0x00, 0x0c, 0x00, 0x46, 0x00, 0x15,
+ 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE15[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x57, 0x47, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x47, 0x00, 0x03,
+ 0x00, 0x47, 0x00, 0x06, 0x00, 0x47, 0x00, 0x04, 0x00, 0x47,
+ 0x00, 0x07, 0x00, 0xff, 0xff,
+};
+const byte CHAR_TABLE16[] = {
+ 0x03, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x54, 0x41, 0x00, 0x01, 0x00,
+ 0xff, 0x41, 0x00, 0x02, 0x00, 0x41, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE18[] = {
+ 0x02, 0x31, 0x00, 0x07, 0x00, 0x44, 0x00, 0x3c, 0x00, 0x03,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x50, 0x3c, 0x00, 0x01, 0x00,
+ 0xff, 0x3c, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE19[] = {
+ 0x02, 0x31, 0x00, 0x07, 0x00, 0x45, 0x00, 0x3d, 0x00, 0x03,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x51, 0x3d, 0x00, 0x01, 0x00,
+ 0xff, 0x3d, 0x00, 0x02, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE20[] = {
+ 0x02, 0x31, 0x00, 0x02, 0x00, 0x46, 0x00, 0x48, 0x00, 0x02,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x58, 0x48, 0x00, 0x01, 0x00,
+ 0xff, 0x48, 0x00, 0x03, 0x00, 0x48, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE21[] = {
+ 0x02, 0x31, 0x00, 0x07, 0x00, 0x47, 0x00, 0x3e, 0x00, 0x03,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x52, 0x3e, 0x00, 0x01, 0x00,
+ 0xff, 0x3e, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE23[] = {
+ 0x02, 0x31, 0x00, 0x08, 0x00, 0x49, 0x00, 0x3f, 0x00, 0x03,
+ 0x00, 0x80, 0x00, 0xf7, 0x00, 0x53, 0x3f, 0x00, 0x01, 0x00,
+ 0xff, 0x3f, 0x00, 0x02, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff,
+ 0xff,
+};
+const byte CHAR_TABLE24[] = {
+ 0x02, 0x32, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x47, 0x32, 0x00, 0x02, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x32, 0x00, 0x01, 0x00, 0x32,
+ 0x00, 0x03, 0x00, 0x32, 0x00, 0x0a, 0x00, 0x32, 0x00, 0x04,
+ 0x00, 0x32, 0x00, 0x0b, 0x00, 0x32, 0x00, 0x05, 0x00, 0x32,
+ 0x00, 0x0c, 0x00, 0x32, 0x00, 0x06, 0x00, 0x32, 0x00, 0x0d,
+ 0x00, 0x32, 0x00, 0x07, 0x00, 0x32, 0x00, 0x0e, 0x00, 0x32,
+ 0x00, 0x08, 0x00, 0x32, 0x00, 0x0f, 0x00, 0x32, 0x00, 0x09,
+ 0x00, 0x32, 0x00, 0x10, 0x00, 0xff, 0xff
+};
+const byte CHAR_TABLE25[] = {
+ 0x02, 0x39, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF
+};
+const byte CHAR_TABLE26[] = {
+ 0x01, 0x3a, 0x00, 0x01, 0x00, 0x0a, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x3a, 0x00, 0x02, 0x00,
+ 0xff, 0x3a, 0x00, 0x03, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x42,
+ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x04, 0x00, 0x42, 0x00, 0x01,
+ 0x00, 0x3a, 0x00, 0x05, 0x00, 0x42, 0x00, 0x02, 0x00, 0x3a,
+ 0x00, 0x06, 0x00, 0x42, 0x00, 0x03, 0x00, 0x3a, 0x00, 0x07,
+ 0x00, 0x42, 0x00, 0x04, 0x00, 0x3a, 0x00, 0x08, 0x00, 0x42,
+ 0x00, 0x05, 0x00, 0x3a, 0x00, 0x09, 0x00, 0x42, 0x00, 0x06,
+ 0x00, 0x3a, 0x00, 0x0a, 0x00, 0x42, 0x00, 0x07, 0x00, 0x3a,
+ 0x00, 0x0b, 0x00, 0x42, 0x00, 0x08, 0x00, 0x3a, 0x00, 0x0c,
+ 0x00, 0x42, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x0d, 0x00, 0x42,
+ 0x00, 0x0a, 0x00, 0x3a, 0x00, 0x0e, 0x00, 0x42, 0x00, 0x0b,
+ 0x00, 0x3a, 0x00, 0x0f, 0x00, 0x42, 0x00, 0x0c, 0x00, 0x3a,
+ 0x00, 0x10, 0x00, 0x42, 0x00, 0x0d, 0x00, 0x3a, 0x00, 0x11,
+ 0x00, 0x42, 0x00, 0x0e, 0x00, 0x3a, 0x00, 0x12, 0x00, 0x42,
+ 0x00, 0x0f, 0x00, 0x3a, 0x00, 0x13, 0x00, 0x42, 0x00, 0x10,
+ 0x00, 0x3a, 0x00, 0x14, 0x00, 0x42, 0x00, 0x11, 0x00, 0x3a,
+ 0x00, 0x15, 0x00, 0xff, 0xff
+};
+const byte CHAR_TABLE27[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x58, 0x49, 0x00, 0x01, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x49,
+ 0x00, 0x02, 0x00, 0x49, 0x00, 0x0a, 0x00, 0x49, 0x00, 0x03,
+ 0x00, 0x49, 0x00, 0x0b, 0x00, 0x49, 0x00, 0x04, 0x00, 0x49,
+ 0x00, 0x0c, 0x00, 0x49, 0x00, 0x05, 0x00, 0x49, 0x00, 0x0d,
+ 0x00, 0x49, 0x00, 0x06, 0x00, 0x49, 0x00, 0x0e, 0x00, 0x49,
+ 0x00, 0x07, 0x00, 0x49, 0x00, 0x0f, 0x00, 0x49, 0x00, 0x08,
+ 0x00, 0x49, 0x00, 0x10, 0x00, 0x49, 0x00, 0x09, 0x00, 0x49,
+ 0x00, 0x11, 0x00, 0xff, 0xff,
+};
+const byte *const CHAR_TABLE[] = {
+ CHAR_TABLE0, nullptr, CHAR_TABLE2, CHAR_TABLE3, CHAR_TABLE4, CHAR_TABLE5,
+ CHAR_TABLE6, CHAR_TABLE7, CHAR_TABLE8, CHAR_TABLE9, CHAR_TABLE10,
+ CHAR_TABLE11, CHAR_TABLE12, CHAR_TABLE13, nullptr, CHAR_TABLE15,
+ CHAR_TABLE16, nullptr, CHAR_TABLE18, CHAR_TABLE19, CHAR_TABLE20,
+ CHAR_TABLE21, nullptr, CHAR_TABLE23, CHAR_TABLE24, CHAR_TABLE25,
+ CHAR_TABLE26, CHAR_TABLE27
+};
+
+// TODO: Fix that array
+const int COMBO_TABLE[54][4] = {
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 },
+ { -1, -1, -1, -1 }
+};
+
+} // End of namespace Martian
+
+} // End of namespace Access
diff --git a/engines/access/martian/martian_resources.h b/engines/access/martian/martian_resources.h
new file mode 100644
index 0000000000..a52967d42a
--- /dev/null
+++ b/engines/access/martian/martian_resources.h
@@ -0,0 +1,52 @@
+/* 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 ACCESS_MARTIAN_RESOURCES_H
+#define ACCESS_MARTIAN_RESOURCES_H
+
+#include "common/scummsys.h"
+
+namespace Access {
+
+namespace Martian {
+
+extern const char *const FILENAMES[];
+
+extern const byte *const CURSORS[4];
+
+extern const int TRAVEL_POS[][2];
+
+extern const char *const INVENTORY_NAMES[];
+
+extern const byte *const ROOM_TABLE[];
+extern const char *const ROOM_DESCR[];
+extern const int ROOM_NUMB;
+
+extern const byte *const CHAR_TABLE[];
+
+extern const int COMBO_TABLE[54][4];
+
+} // End of namespace Martian
+
+} // End of namespace Access
+
+#endif /* ACCESS_MARTIAN_RESOURCES_H */
diff --git a/engines/access/martian/martian_room.cpp b/engines/access/martian/martian_room.cpp
new file mode 100644
index 0000000000..e9d1b9d8cf
--- /dev/null
+++ b/engines/access/martian/martian_room.cpp
@@ -0,0 +1,141 @@
+/* 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 "access/access.h"
+#include "access/resources.h"
+#include "access/martian/martian_game.h"
+#include "access/martian/martian_resources.h"
+#include "access/martian/martian_room.h"
+
+namespace Access {
+
+namespace Martian {
+
+MartianRoom::MartianRoom(AccessEngine *vm) : Room(vm) {
+ _game = (MartianEngine *)vm;
+}
+
+MartianRoom::~MartianRoom() {
+}
+
+void MartianRoom::loadRoom(int roomNumber) {
+ loadRoomData(ROOM_TABLE[roomNumber]);
+}
+
+void MartianRoom::reloadRoom() {
+ loadRoom(_vm->_player->_roomNumber);
+
+ if (_roomFlag != 1) {
+ _vm->_currentMan = _roomFlag;
+ _vm->_currentManOld = _roomFlag;
+ _vm->_manScaleOff = 0;
+
+ switch (_vm->_currentMan) {
+ case 0:
+ _vm->_player->loadSprites("MAN.LZ");
+ break;
+
+ case 2:
+ _vm->_player->loadSprites("JMAN.LZ");
+ break;
+
+ case 3:
+ _vm->_player->loadSprites("OVERHEAD.LZ");
+ _vm->_manScaleOff = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ reloadRoom1();
+}
+
+void MartianRoom::reloadRoom1() {
+ if (_vm->_player->_roomNumber == 29 || _vm->_player->_roomNumber == 31
+ || _vm->_player->_roomNumber == 42 || _vm->_player->_roomNumber == 44) {
+ //Resource *spriteData = _vm->_files->loadFile("MAYA.LZ");
+ //_vm->_inactive._spritesPtr = new SpriteResource(_vm, spriteData);
+ //delete spriteData;
+ _vm->_currentCharFlag = false;
+ }
+
+ _selectCommand = -1;
+ _vm->_events->setNormalCursor(CURSOR_CROSSHAIRS);
+ _vm->_mouseMode = 0;
+ _vm->_boxSelect = true;
+ _vm->_player->_playerOff = false;
+
+ _vm->_screen->fadeOut();
+ _vm->_screen->clearScreen();
+ roomSet();
+
+ // TODO: Refactor
+
+ _vm->_screen->setBufferScan();
+ setupRoom();
+ setWallCodes();
+ buildScreen();
+
+ if (!_vm->_screen->_vesaMode) {
+ _vm->copyBF2Vid();
+ } else if (_vm->_player->_roomNumber != 20 && _vm->_player->_roomNumber != 24
+ && _vm->_player->_roomNumber != 33) {
+ _vm->_screen->setPalette();
+ _vm->copyBF2Vid();
+ }
+
+ _vm->_player->_frame = 0;
+ _vm->_oldRects.clear();
+ _vm->_newRects.clear();
+}
+
+void MartianRoom::roomSet() {
+ _vm->_numAnimTimers = 0;
+ _vm->_scripts->_sequence = 1000;
+ _vm->_scripts->searchForSequence();
+ _vm->_scripts->executeScript();
+}
+
+void MartianRoom::roomMenu() {
+ Resource *iconData = _vm->_files->loadFile("ICONS.LZ");
+ SpriteResource *spr = new SpriteResource(_vm, iconData);
+ delete iconData;
+
+ _vm->_screen->saveScreen();
+ _vm->_screen->setDisplayScan();
+ _vm->_destIn = _vm->_screen; // TODO: Redundant
+ _vm->_screen->plotImage(spr, 0, Common::Point(0, 177));
+ _vm->_screen->plotImage(spr, 1, Common::Point(143, 177));
+
+ _vm->_screen->restoreScreen();
+ delete spr;
+}
+
+void MartianRoom::mainAreaClick() {
+}
+
+} // End of namespace Martian
+
+} // End of namespace Access
diff --git a/engines/access/martian/martian_room.h b/engines/access/martian/martian_room.h
new file mode 100644
index 0000000000..85529ce8f0
--- /dev/null
+++ b/engines/access/martian/martian_room.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 ACCESS_MARTIAN_ROOM_H
+#define ACCESS_MARTIAN_ROOM_H
+
+#include "common/scummsys.h"
+#include "access/room.h"
+
+namespace Access {
+
+class AccessEngine;
+
+namespace Martian {
+
+class MartianEngine;
+
+class MartianRoom : public Room {
+private:
+ MartianEngine *_game;
+
+ void roomSet();
+protected:
+ virtual void loadRoom(int roomNumber);
+
+ virtual void reloadRoom();
+
+ virtual void reloadRoom1();
+
+ virtual void mainAreaClick();
+public:
+ MartianRoom(AccessEngine *vm);
+
+ virtual ~MartianRoom();
+
+ virtual void loadRoomData(const byte *roomData) { warning("TODO - loadRoomData"); }
+
+ virtual void init4Quads() { }
+
+ virtual void roomMenu();
+};
+
+} // End of namespace Martian
+
+} // End of namespace Access
+
+#endif /* ACCESS_AMAZON_ROOM_H */
diff --git a/engines/access/martian/martian_scripts.cpp b/engines/access/martian/martian_scripts.cpp
new file mode 100644
index 0000000000..0578872092
--- /dev/null
+++ b/engines/access/martian/martian_scripts.cpp
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "access/access.h"
+#include "access/martian/martian_game.h"
+#include "access/martian/martian_resources.h"
+#include "access/martian/martian_scripts.h"
+
+namespace Access {
+
+namespace Martian {
+
+MartianScripts::MartianScripts(AccessEngine *vm) : Scripts(vm) {
+ _game = (MartianEngine *)_vm;
+}
+
+void MartianScripts::executeSpecial(int commandIndex, int param1, int param2) {
+}
+
+typedef void(MartianScripts::*MartianScriptMethodPtr)();
+
+void MartianScripts::executeCommand(int commandIndex) {
+ Scripts::executeCommand(commandIndex);
+}
+
+} // End of namespace Martian
+
+} // End of namespace Access
diff --git a/engines/access/martian/martian_scripts.h b/engines/access/martian/martian_scripts.h
new file mode 100644
index 0000000000..fc7495fc47
--- /dev/null
+++ b/engines/access/martian/martian_scripts.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_MARTIAN_SCRIPTS_H
+#define ACCESS_MARTIAN_SCRIPTS_H
+
+#include "common/scummsys.h"
+#include "access/scripts.h"
+
+namespace Access {
+
+namespace Martian {
+
+class MartianEngine;
+
+class MartianScripts : public Scripts {
+private:
+ MartianEngine *_game;
+protected:
+ virtual void executeSpecial(int commandIndex, int param1, int param2);
+ virtual void executeCommand(int commandIndex);
+public:
+ MartianScripts(AccessEngine *vm);
+};
+
+} // End of namespace Martian
+
+} // End of namespace Access
+
+#endif /* ACCESS_MARTIAN_SCRIPTS_H */
diff --git a/engines/access/module.mk b/engines/access/module.mk
new file mode 100644
index 0000000000..b6961aeca9
--- /dev/null
+++ b/engines/access/module.mk
@@ -0,0 +1,41 @@
+MODULE := engines/access
+
+MODULE_OBJS := \
+ animation.o \
+ asurface.o \
+ access.o \
+ bubble_box.o \
+ char.o \
+ data.o \
+ debugger.o \
+ decompress.o \
+ detection.o \
+ events.o \
+ files.o \
+ font.o \
+ inventory.o \
+ player.o \
+ resources.o \
+ room.o \
+ screen.o \
+ scripts.o \
+ sound.o \
+ video.o \
+ amazon/amazon_game.o \
+ amazon/amazon_logic.o \
+ amazon/amazon_player.o \
+ amazon/amazon_resources.o \
+ amazon/amazon_room.o \
+ amazon/amazon_scripts.o \
+ martian/martian_game.o \
+ martian/martian_resources.o \
+ martian/martian_room.o \
+ martian/martian_scripts.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_ACCESS), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/access/player.cpp b/engines/access/player.cpp
new file mode 100644
index 0000000000..d547aedc1d
--- /dev/null
+++ b/engines/access/player.cpp
@@ -0,0 +1,820 @@
+/* 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/algorithm.h"
+#include "common/textconsole.h"
+#include "access/player.h"
+#include "access/access.h"
+#include "access/resources.h"
+#include "access/amazon/amazon_player.h"
+
+namespace Access {
+
+Player *Player::init(AccessEngine *vm) {
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ return new Amazon::AmazonPlayer(vm);
+ default:
+ return new Player(vm);
+ }
+}
+
+Player::Player(AccessEngine *vm) : Manager(vm), ImageEntry() {
+ Common::fill(&_walkOffRight[0], &_walkOffRight[PLAYER_DATA_COUNT], 0);
+ Common::fill(&_walkOffLeft[0], &_walkOffLeft[PLAYER_DATA_COUNT], 0);
+ Common::fill(&_walkOffUp[0], &_walkOffUp[PLAYER_DATA_COUNT], 0);
+ Common::fill(&_walkOffDown[0], &_walkOffDown[PLAYER_DATA_COUNT], 0);
+
+ _playerSprites = nullptr;
+ _playerSprites1 = nullptr;
+ _manPal1 = nullptr;
+ _frameNumber = 0;
+ _monData = nullptr;
+ _rawTempL = 0;
+ _rawXTemp = 0;
+ _rawYTempL = 0;
+ _rawYTemp = 0;
+ _playerXLow = 0;
+ _playerX = 0;
+ _playerYLow = 0;
+ _playerY = 0;
+ _frame = 0;
+ _playerOff = false;
+ _playerMove = false;
+ _leftDelta = _rightDelta = 0;
+ _upDelta = _downDelta = 0;
+ _scrollConst = 0;
+ _scrollFlag = false;
+ _scrollThreshold = 0;
+ _scrollAmount = 0;
+ _scrollEnd = 0;
+ _roomNumber = 0;
+ _collideFlag = false;
+ _move = NONE;
+ _playerDirection = NONE;
+ _xFlag = _yFlag = 0;
+ _inactiveYOff = 0;
+}
+
+Player::~Player() {
+ delete _playerSprites;
+ delete[] _manPal1;
+}
+
+void Player::load() {
+ _playerOffset.x = _vm->_screen->_scaleTable1[25];
+ _playerOffset.y = _vm->_screen->_scaleTable1[67];
+ _leftDelta = -3;
+ _rightDelta = 33;
+ _upDelta = 5;
+ _downDelta = -10;
+ _scrollConst = 5;
+
+ for (int i = 0; i < PLAYER_DATA_COUNT; ++i) {
+ _walkOffRight[i] = SIDEOFFR[i];
+ _walkOffLeft[i] = SIDEOFFL[i];
+ _walkOffUp[i] = SIDEOFFU[i];
+ _walkOffDown[i] = SIDEOFFD[i];
+ _walkOffUR[i].x = DIAGOFFURX[i];
+ _walkOffUR[i].y = DIAGOFFURY[i];
+ _walkOffDR[i].x = DIAGOFFDRX[i];
+ _walkOffDR[i].y = DIAGOFFDRY[i];
+ _walkOffUL[i].x = DIAGOFFULX[i];
+ _walkOffUL[i].y = DIAGOFFULY[i];
+ _walkOffDL[i].x = DIAGOFFDLX[i];
+ _walkOffDL[i].y = DIAGOFFDLY[i];
+ }
+
+ _sideWalkMin = 0;
+ _sideWalkMax = 7;
+ _upWalkMin = 16;
+ _upWalkMax = 23;
+ _downWalkMin = 8;
+ _downWalkMax = 15;
+ _diagUpWalkMin = 0;
+ _diagUpWalkMax = 7;
+ _diagDownWalkMin = 0;
+ _diagDownWalkMax = 7;
+
+ _playerSprites = _playerSprites1;
+ if (_manPal1) {
+ Common::copy(_manPal1 + 0x270, _manPal1 + 0x270 + 0x60, _vm->_screen->_manPal);
+ } else {
+ Common::fill(_vm->_screen->_manPal, _vm->_screen->_manPal + 0x60, 0);
+ }
+}
+
+void Player::loadSprites(const Common::String &name) {
+ freeSprites();
+
+ Resource *data = _vm->_files->loadFile(name);
+ _playerSprites1 = new SpriteResource(_vm, data);
+ delete data;
+}
+
+void Player::freeSprites() {
+ delete _playerSprites;
+ _playerSprites1 = nullptr;
+ _playerSprites = nullptr;
+}
+
+void Player::removeSprite1() {
+ if (_playerSprites1) {
+ delete _playerSprites1;
+ _playerSprites1 = nullptr;
+ }
+}
+
+void Player::calcManScale() {
+ if (!_vm->_manScaleOff) {
+ _vm->_scale = ((((_rawPlayer.y - _vm->_scaleMaxY + _vm->_scaleN1) *
+ _vm->_scaleT1 + (_vm->_scaleH2 << 8)) & 0xff00) / _vm->_scaleH1 * _vm->_scaleI) >> 8;
+ _vm->_screen->setScaleTable(_vm->_scale);
+
+ _playerOffset.x = _vm->_screen->_scaleTable1[20];
+ _playerOffset.y = _vm->_screen->_scaleTable1[67];
+ _inactiveYOff = _playerOffset.y;
+ }
+}
+
+void Player::walk() {
+ _collideFlag = false;
+ _playerDirection = NONE;
+
+ if (_playerOff)
+ return;
+ else if (_vm->_timers[0]._flag) {
+ plotCom3();
+ return;
+ }
+
+ ++_vm->_timers[0]._flag;
+ switch (_move) {
+ case UP:
+ _playerMove = false;
+ walkUp();
+ break;
+ case DOWN:
+ _playerMove = false;
+ walkDown();
+ break;
+ case LEFT:
+ _playerMove = false;
+ walkLeft();
+ break;
+ case RIGHT:
+ _playerMove = false;
+ walkRight();
+ break;
+ case UPLEFT:
+ _playerMove = false;
+ walkUpLeft();
+ break;
+ case DOWNLEFT:
+ _playerMove = false;
+ walkDownLeft();
+ break;
+ case UPRIGHT:
+ _playerMove = false;
+ walkUpRight();
+ break;
+ case DOWNRIGHT:
+ _playerMove = false;
+ walkDownRight();
+ break;
+ default:
+ checkMove();
+ break;
+ }
+}
+
+void Player::calcPlayer() {
+ Screen &scr = *_vm->_screen;
+ scr._bufferStart.x = (_vm->_scrollCol << 4) + _vm->_scrollX;
+ scr._bufferStart.y = (_vm->_scrollRow << 4) + _vm->_scrollY;
+ _playerX = _rawPlayer.x - scr._bufferStart.x;
+ _playerY = _rawPlayer.y - scr._bufferStart.y;
+}
+
+void Player::walkUp() {
+ if (_frame > _upWalkMax || _frame < _upWalkMin)
+ _frame = _upWalkMin;
+
+ _playerDirection = UP;
+ int walkOff = _walkOffUp[_frame - _upWalkMin];
+ int tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOff];
+ _rawYTempL = (byte)tempL;
+ int yTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOff] -
+ (tempL < 0 ? 1 : 0);
+ _rawYTemp = yTemp;
+ _rawXTemp = _rawPlayer.x;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.y = _rawYTempL;
+
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom
+ //if (_vm->_currentMan != 3 && (_frame == 17 || _frame == 21))
+ // warning("TODO: walkUp - si = 0?");
+
+ if (++_frame > _upWalkMax)
+ _frame = _upWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkDown() {
+ if (_frame > _downWalkMax || _frame < _downWalkMin)
+ _frame = _downWalkMin;
+
+ _playerDirection = DOWN;
+ int walkOff = _walkOffDown[_frame - _downWalkMin];
+ int tempL = _vm->_screen->_scaleTable2[walkOff] + _rawPlayerLow.y;
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _vm->_screen->_scaleTable1[walkOff] + _rawPlayer.y + (tempL >= 0x100 ? 1 : 0);
+ _rawXTemp = _rawPlayer.x;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.y = _rawYTempL;
+
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom
+ //if (_vm->_currentMan != 3 && (_frame == 10 || _frame == 14))
+ // warning("TODO: walkDown - si = 0?");
+
+ if (++_frame > _downWalkMax)
+ _frame = _downWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkLeft() {
+ if (_frame > _sideWalkMax || _frame < _sideWalkMin)
+ _frame = _sideWalkMin;
+
+ _playerDirection = LEFT;
+
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ int walkOffset = _walkOffLeft[_frame - _sideWalkMin];
+ int tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst];
+ }
+ _rawYTemp = _rawPlayer.y;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayerLow.x = _rawTempL;
+ ++_frame;
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkLeft - si = 0?");
+
+ if (_frame > _sideWalkMax)
+ _frame = _sideWalkMin;
+
+ plotCom1();
+ }
+}
+
+void Player::walkRight() {
+ if (_frame > _sideWalkMax || _frame < _sideWalkMin)
+ _frame = _sideWalkMin;
+
+ _playerDirection = RIGHT;
+
+ bool flag = _scrollEnd == 2;
+ if (!flag) {
+ calcPlayer();
+ flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ int walkOffset = _walkOffRight[_frame - _sideWalkMin];
+ int tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst];
+ }
+ _rawYTemp = _rawPlayer.y;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayerLow.x = _rawTempL;
+ ++_frame;
+
+ // Useless check removed
+ if (_frame > _sideWalkMax)
+ _frame = _sideWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkUpLeft() {
+ if (_frame > _diagUpWalkMax || _frame < _diagUpWalkMin)
+ _frame = _diagUpWalkMin;
+
+ _playerDirection = UPLEFT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffUL[_frame - _diagUpWalkMin].x;
+ tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffUL[_frame - _diagUpWalkMin].y;
+ tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ ++_frame;
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkUpLeft - si = 0?");
+
+ if (_frame > _diagUpWalkMax)
+ _frame = _diagUpWalkMin;
+
+ plotCom1();
+ }
+}
+
+void Player::walkDownLeft() {
+ if (_frame > _diagDownWalkMax || _frame < _diagDownWalkMin)
+ _frame = _diagDownWalkMin;
+
+ _playerDirection = DOWNLEFT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffDL[_frame - _sideWalkMin].x;
+ tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffDL[_frame - _diagDownWalkMin].y;
+ tempL = _rawPlayerLow.y + _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ ++_frame;
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkDownLeft - si = 0?");
+
+ if (_frame > _diagDownWalkMax)
+ _frame = _diagDownWalkMin;
+
+ plotCom1();
+ }
+}
+
+void Player::walkUpRight() {
+ if (_frame > _diagUpWalkMax || _frame < _diagUpWalkMin)
+ _frame = _diagUpWalkMin;
+
+ _playerDirection = UPRIGHT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffUR[_frame - _diagUpWalkMin].x;
+ tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffUL[_frame - _diagUpWalkMin].y;
+ tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ ++_frame;
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkUpRight - si = 0?");
+
+ if (_frame > _diagUpWalkMax)
+ _frame = _diagUpWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkDownRight() {
+ if (_frame > _diagDownWalkMax || _frame < _diagDownWalkMin)
+ _frame = _diagDownWalkMin;
+
+ _playerDirection = DOWNRIGHT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 2;
+ if (!flag) {
+ calcPlayer();
+ flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffUR[_frame - _diagDownWalkMin].x;
+ tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffDR[_frame - _diagDownWalkMin].y;
+ tempL = _rawPlayerLow.y + _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkDownRight - si = 0?");
+
+ ++_frame;
+ if (_frame > _diagDownWalkMax)
+ _frame = _diagDownWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::checkMove() {
+ if (_playerMove) {
+ if (_xFlag == 0 && _yFlag == 0) {
+ int xp = (_playerOffset.x / 2) + _rawPlayer.x - _moveTo.x;
+ if (xp < 0)
+ xp = -xp;
+ int yp = _rawPlayer.y - _moveTo.y;
+ if (yp < 0)
+ yp = -yp;
+
+ if (xp >= yp)
+ _xFlag = 1;
+ else
+ _yFlag = 1;
+ }
+
+ if (_yFlag == 1) {
+ int yd = _rawPlayer.y - _moveTo.y;
+ if ((yd >= 0 && yd <= _upDelta) || (yd < 0 && -yd <= _upDelta)) {
+ ++_yFlag;
+ if (_xFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ } else {
+ ++_xFlag;
+ }
+ } else {
+ if (yd >= 0)
+ walkUp();
+ else
+ walkDown();
+
+ if (_collideFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ }
+ } else if (_xFlag == 1) {
+ int xd = (_playerOffset.x / 2) + _rawPlayer.x - _moveTo.x;
+ if ((xd >= 0 && xd <= -_leftDelta) || (xd < 0 && -xd <= -_leftDelta)) {
+ ++_xFlag;
+
+ if (_yFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ } else {
+ if (xd >= 0)
+ walkLeft();
+ else
+ walkRight();
+
+ if (_collideFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ }
+ } else if (!_yFlag) {
+ ++_yFlag;
+ } else {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ }
+
+ plotCom3();
+}
+
+void Player::plotCom(int flags) {
+ _flags &= ~2;
+ _flags &= ~8;
+ _flags |= flags;
+
+ plotCom3();
+}
+
+void Player::plotCom1() {
+ plotCom(2);
+}
+
+void Player::plotCom2() {
+ // WORKAROUND: Amazon has at least one cutscene with the player not properly turned off
+ if (!_playerOff && _spritesPtr != nullptr)
+ _vm->_images.addToList(*this);
+}
+
+void Player::plotCom3() {
+ // Update the base ImageEntry fields for the player
+ _position.x = _rawPlayer.x;
+ _position.y = _rawPlayer.y - _playerOffset.y;
+ _offsetY = _playerOffset.y;
+ _spritesPtr = _playerSprites;
+ _frameNumber = _frame;
+
+ plotCom2();
+}
+
+void Player::checkScrollUp() {
+ if ((_playerDirection == DOWNRIGHT || _playerDirection == DOWNLEFT ||
+ _playerDirection == DOWN) && (_vm->_screen->_clipHeight -
+ _playerY - _scrollThreshold) <= 0) {
+ // Scroll up
+ if (scrollUp()) {
+ _scrollEnd = 4;
+ _vm->_scrollY &= TILE_HEIGHT;
+ _scrollFlag = true;
+ }
+ }
+}
+
+void Player::checkScroll() {
+ _scrollFlag = false;
+ if (_playerDirection == NONE)
+ return;
+
+ if ((_playerDirection == UPLEFT || _playerDirection == DOWNLEFT ||
+ _playerDirection == LEFT) && _playerX <= _scrollThreshold) {
+ // Scroll right
+ if (!scrollRight()) {
+ if (_playerDirection == DOWNLEFT)
+ checkScrollUp();
+
+ return;
+ }
+ } else if ((_playerDirection == UPRIGHT || _playerDirection == DOWNRIGHT ||
+ _playerDirection == RIGHT) && (_vm->_screen->_clipWidth -
+ _playerX - _scrollThreshold) <= 0) {
+ // Scroll left
+ if (!scrollLeft()) {
+ if (_playerDirection == DOWNRIGHT)
+ checkScrollUp();
+
+ return;
+ }
+ }
+
+ if ((_playerDirection == UPRIGHT || _playerDirection == UPLEFT ||
+ _playerDirection == UP) && _playerY <= _scrollThreshold) {
+ scrollDown();
+ } else {
+ checkScrollUp();
+ }
+}
+
+bool Player::scrollUp() {
+ _scrollAmount = -(_vm->_screen->_clipHeight - _playerY - _scrollThreshold);
+ if ((_vm->_scrollRow + _vm->_screen->_vWindowHeight) >=
+ _vm->_room->_playFieldHeight)
+ return true;
+
+ _scrollFlag = true;
+ _vm->_scrollY = _vm->_scrollY + _scrollAmount;
+
+ while (_vm->_scrollY >= TILE_HEIGHT && !_vm->shouldQuit()) {
+ _vm->_scrollY -= TILE_HEIGHT;
+ ++_vm->_scrollRow;
+ _vm->_buffer1.moveBufferUp();
+
+ _vm->_room->buildRow(_vm->_scrollRow + _vm->_screen->_vWindowHeight,
+ _vm->_screen->_vWindowLinesTall);
+
+ if ((_vm->_scrollRow + _vm->_screen->_vWindowHeight) >=
+ _vm->_room->_playFieldHeight)
+ return true;
+
+ if (_vm->_scrollY <= TILE_HEIGHT)
+ return false;
+ }
+
+ return false;
+}
+
+bool Player::scrollDown() {
+ _scrollAmount = -(_playerY - _scrollThreshold);
+ _scrollFlag = true;
+ _vm->_scrollY -= _scrollAmount;
+ if (_vm->_scrollY >= 0)
+ return true;
+
+ do {
+ _vm->_scrollY += TILE_HEIGHT;
+ if (--_vm->_scrollRow < 0)
+ break;
+
+ _vm->_buffer1.moveBufferDown();
+ _vm->_room->buildRow(_vm->_scrollRow, 0);
+
+ if (_vm->_scrollY >= 0)
+ return false;
+ } while (!_vm->shouldQuit());
+
+ _scrollEnd = 3;
+ _vm->_scrollY = 0;
+ _vm->_scrollRow = 0;
+ return true;
+}
+
+bool Player::scrollLeft() {
+ Screen &screen = *_vm->_screen;
+ _scrollAmount = -(_vm->_screen->_clipWidth - _playerX - _scrollThreshold);
+ if ((_vm->_scrollCol + screen._vWindowWidth) == _vm->_room->_playFieldWidth) {
+ _scrollEnd = 2;
+ _vm->_scrollX = 0;
+ _scrollFlag = true;
+ return true;
+ } else {
+ _scrollFlag = true;
+ _vm->_scrollX = _vm->_scrollX + _scrollAmount;
+
+ do {
+ if (_vm->_scrollX < TILE_WIDTH)
+ return true;
+
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth,
+ screen._vWindowBytesWide);
+ } while (!_vm->shouldQuit() && (_vm->_scrollX >= TILE_WIDTH));
+
+ return (_playerDirection == UPRIGHT);
+ }
+}
+
+bool Player::scrollRight() {
+ _scrollAmount = -(_playerX - _scrollThreshold);
+ _scrollFlag = true;
+ _vm->_scrollX -= _scrollAmount;
+
+ if (_vm->_scrollX < 0) {
+ do {
+ _vm->_scrollX += TILE_WIDTH;
+ if (--_vm->_scrollCol < 0) {
+ _scrollEnd = true;
+ _vm->_scrollX = 0;
+ _vm->_scrollCol = 0;
+ return true;
+ }
+
+ _vm->_buffer1.moveBufferRight();
+ _vm->_room->buildColumn(_vm->_scrollCol, 0);
+ } while (!_vm->shouldQuit() && (_vm->_scrollX < 0));
+
+ return false;
+ }
+
+ return true;
+}
+
+void Player::synchronize(Common::Serializer &s) {
+ s.syncAsUint16LE(_roomNumber);
+ s.syncAsSint16LE(_rawPlayerLow.x);
+ s.syncAsSint16LE(_rawPlayer.x);
+ s.syncAsSint16LE(_rawPlayerLow.y);
+ s.syncAsSint16LE(_rawPlayer.y);
+}
+
+} // End of namespace Access
diff --git a/engines/access/player.h b/engines/access/player.h
new file mode 100644
index 0000000000..26caec681f
--- /dev/null
+++ b/engines/access/player.h
@@ -0,0 +1,153 @@
+/* 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 ACCESS_PLAYER_H
+#define ACCESS_PLAYER_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "access/asurface.h"
+#include "access/data.h"
+
+namespace Access {
+
+#define PLAYER_DATA_COUNT 8
+
+enum Direction {
+ NONE = 0,
+ UP = 1,
+ DOWN = 2,
+ LEFT = 3,
+ RIGHT = 4,
+ UPRIGHT = 5,
+ DOWNRIGHT = 6,
+ UPLEFT = 7,
+ DOWNLEFT = 8
+};
+
+class AccessEngine;
+
+class Player : public ImageEntry, public Manager {
+protected:
+ int _leftDelta, _rightDelta;
+ int _upDelta, _downDelta;
+ int _scrollConst;
+ int _sideWalkMin, _sideWalkMax;
+ int _upWalkMin, _upWalkMax;
+ int _downWalkMin, _downWalkMax;
+ int _diagUpWalkMin, _diagUpWalkMax;
+ int _diagDownWalkMin, _diagDownWalkMax;
+ SpriteResource *_playerSprites1;
+ byte *_manPal1;
+ int _scrollEnd;
+ int _inactiveYOff;
+
+ void plotCom(int v1);
+ void plotCom1();
+ void plotCom2();
+ void plotCom3();
+
+ void walkUp();
+ void walkDown();
+ void walkLeft();
+ void walkRight();
+ void walkUpLeft();
+ void walkDownLeft();
+ void walkUpRight();
+ void walkDownRight();
+ void checkScrollUp();
+ bool scrollUp();
+ bool scrollDown();
+ bool scrollLeft();
+ bool scrollRight();
+public:
+ Direction _playerDirection;
+ SpriteResource *_playerSprites;
+ // Fields in original Player structure
+ byte *_monData;
+ int _walkOffRight[PLAYER_DATA_COUNT];
+ int _walkOffLeft[PLAYER_DATA_COUNT];
+ int _walkOffUp[PLAYER_DATA_COUNT];
+ int _walkOffDown[PLAYER_DATA_COUNT];
+ Common::Point _walkOffUR[PLAYER_DATA_COUNT];
+ Common::Point _walkOffDR[PLAYER_DATA_COUNT];
+ Common::Point _walkOffUL[PLAYER_DATA_COUNT];
+ Common::Point _walkOffDL[PLAYER_DATA_COUNT];
+ byte _rawTempL;
+ int _rawXTemp;
+ byte _rawYTempL;
+ int _rawYTemp;
+ Common::Point _playerOffset;
+ int _playerXLow;
+ int _playerX;
+ int _playerYLow;
+ int _playerY;
+ int _frame;
+ int _xFlag, _yFlag;
+ Direction _move;
+
+ // Additional public globals we've added to new Player class
+ bool _playerOff;
+ bool _playerMove;
+ Common::Point _moveTo;
+ bool _collideFlag;
+ bool _scrollFlag;
+ int _scrollThreshold;
+ int _scrollAmount;
+
+ // Additional globals that need to be saved
+ int _roomNumber;
+ Common::Point _rawPlayerLow;
+ Common::Point _rawPlayer;
+public:
+ Player(AccessEngine *vm);
+ virtual ~Player();
+ static Player *init(AccessEngine *vm);
+
+ virtual void load();
+
+ void loadSprites(const Common::String &name);
+
+ void freeSprites();
+
+ void removeSprite1();
+
+ void calcManScale();
+
+ void walk();
+
+ void calcPlayer();
+
+ void checkScroll();
+
+ void checkMove();
+
+ /**
+ * Synchronize savegame data
+ */
+ void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_PLAYER_H */
diff --git a/engines/access/resources.cpp b/engines/access/resources.cpp
new file mode 100644
index 0000000000..4157cdfc0d
--- /dev/null
+++ b/engines/access/resources.cpp
@@ -0,0 +1,109 @@
+/* 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 "access/resources.h"
+#include "access/access.h"
+
+namespace Access {
+
+const byte INITIAL_PALETTE[18 * 3] = {
+ 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff,
+ 0xf0, 0xf0, 0xf0,
+ 0xe0, 0xe0, 0xe0,
+ 0xd0, 0xd0, 0xd0,
+ 0xc0, 0xc0, 0xc0,
+ 0xb0, 0xb0, 0xb0,
+ 0xa0, 0xa0, 0xa0,
+ 0x90, 0x90, 0x90,
+ 0x80, 0x80, 0x80,
+ 0x70, 0x70, 0x70,
+ 0x60, 0x60, 0x60,
+ 0x50, 0x50, 0x50,
+ 0x40, 0x40, 0x40,
+ 0x30, 0x30, 0x30,
+ 0x20, 0x20, 0x20,
+ 0x10, 0x10, 0x10,
+ 0x00, 0x00, 0x00
+};
+
+const int SIDEOFFR[] = { 5, 5, 5, 5, 5, 5, 5, 5, 0 };
+const int SIDEOFFL[] = { 5, 5, 5, 5, 5, 5, 5, 5, 0 };
+const int SIDEOFFU[] = { 2, 2, 2, 2, 2, 2, 2, 2, 0 };
+const int SIDEOFFD[] = { 2, 2, 2, 2, 2, 2, 2, 2, 0 };
+const int DIAGOFFURX[] = { 4, 5, 2, 2, 3, 4, 2, 2, 0 };
+const int DIAGOFFURY[] = { 2, 3, 2, 2, 2, 3, 1, 1, 0 };
+const int DIAGOFFDRX[] = { 4, 5, 4, 3, 5, 4, 5, 1, 0 };
+const int DIAGOFFDRY[] = { 3, 2, 1, 2, 2, 1, 2, 1, 0 };
+const int DIAGOFFULX[] = { 4, 5, 4, 3, 3, 2, 2, 2, 0 };
+const int DIAGOFFULY[] = { 3, 3, 1, 2, 2, 1, 1, 1, 0 };
+const int DIAGOFFDLX[] = { 4, 5, 3, 3, 5, 4, 6, 1, 0 };
+const int DIAGOFFDLY[] = { 2, 2, 1, 2, 3, 1, 2, 1, 0 };
+
+const int RMOUSE[10][2] = {
+ { 0, 35 }, { 0, 0 }, { 36, 70 }, { 71, 106 }, { 107, 141 },
+ { 142, 177 }, { 178, 212 }, { 213, 248 }, { 249, 283 }, { 284, 318 }
+};
+
+const char *const LOOK_MESSAGE = "LOOKING THERE REVEALS NOTHING OF INTEREST.";
+const char *const GET_MESSAGE = "YOU CAN'T TAKE THAT.";
+const char *const OPEN_MESSAGE = "THAT DOESN'T OPEN.";
+const char *const MOVE_MESSAGE = "THAT WON'T MOVE.";
+const char *const USE_MESSAGE = "THAT DOESN'T SEEM TO WORK.";
+const char *const GO_MESSAGE = "YOU CAN'T CLIMB THAT.";
+const char *const HELP_MESSAGE = "THIS OBJECT REQUIRES NO HINTS";
+const char *const TALK_MESSAGE = "THERE SEEMS TO BE NO RESPONSE.";
+const char *const GENERAL_MESSAGES[] = {
+ LOOK_MESSAGE, OPEN_MESSAGE, MOVE_MESSAGE, GET_MESSAGE, USE_MESSAGE,
+ GO_MESSAGE, TALK_MESSAGE, HELP_MESSAGE, HELP_MESSAGE, USE_MESSAGE
+};
+
+const int INVCOORDS[][4] = {
+ { 23, 68, 15, 49 },
+ { 69, 114, 15, 49 },
+ { 115, 160, 15, 49 },
+ { 161, 206, 15, 49 },
+ { 207, 252, 15, 49 },
+ { 253, 298, 15, 49 },
+ { 23, 68, 50, 84 },
+ { 69, 114, 50, 84 },
+ { 115, 160, 50, 84 },
+ { 161, 206, 50, 84 },
+ { 207, 252, 50, 84 },
+ { 253, 298, 50, 84 },
+ { 23, 68, 85, 119 },
+ { 69, 114, 85, 119 },
+ { 115, 160, 85, 119 },
+ { 161, 206, 85, 119 },
+ { 207, 252, 85, 119 },
+ { 253, 298, 85, 119 },
+ { 23, 68, 120, 154 },
+ { 69, 114, 120, 154 },
+ { 115, 160, 120, 154 },
+ { 161, 206, 120, 154 },
+ { 207, 252, 120, 154 },
+ { 253, 298, 120, 154 },
+ { 237, 298, 177, 193 },
+ { 25, 85, 177, 193 }
+};
+
+} // End of namespace Access
diff --git a/engines/access/resources.h b/engines/access/resources.h
new file mode 100644
index 0000000000..8d59b1b1f1
--- /dev/null
+++ b/engines/access/resources.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_RESOURCES_H
+#define ACCESS_RESOURCES_H
+
+#include "common/scummsys.h"
+
+namespace Access {
+
+extern const byte INITIAL_PALETTE[18 * 3];
+
+extern const int SIDEOFFR[];
+extern const int SIDEOFFL[];
+extern const int SIDEOFFU[];
+extern const int SIDEOFFD[];
+extern const int DIAGOFFURX[];
+extern const int DIAGOFFURY[];
+extern const int DIAGOFFDRX[];
+extern const int DIAGOFFDRY[];
+extern const int DIAGOFFULX[];
+extern const int DIAGOFFULY[];
+extern const int DIAGOFFDLX[];
+extern const int DIAGOFFDLY[];
+
+extern const int RMOUSE[10][2];
+
+extern const char *const GENERAL_MESSAGES[];
+
+extern const int INVCOORDS[][4];
+
+} // End of namespace Access
+
+#endif /* ACCESS_RESOURCES_H */
diff --git a/engines/access/room.cpp b/engines/access/room.cpp
new file mode 100644
index 0000000000..f7c2eabd0f
--- /dev/null
+++ b/engines/access/room.cpp
@@ -0,0 +1,833 @@
+/* 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/memstream.h"
+#include "access/access.h"
+#include "access/resources.h"
+#include "access/room.h"
+
+namespace Access {
+
+Room::Room(AccessEngine *vm) : Manager(vm) {
+ _function = FN_NONE;
+ _roomFlag = 0;
+ _playField = nullptr;
+ _playFieldWidth = _playFieldHeight = 0;
+ _matrixSize = 0;
+ _tile = nullptr;
+ _selectCommand = 0;
+ _conFlag = false;
+ _selectCommand = -1;
+}
+
+Room::~Room() {
+ delete[] _playField;
+ delete[] _tile;
+}
+
+void Room::freePlayField() {
+ delete[] _playField;
+ _playField = nullptr;
+}
+
+void Room::freeTileData() {
+ delete[] _tile;
+ _tile = nullptr;
+}
+
+void Room::doRoom() {
+ bool reloadFlag = false;
+
+ while (!_vm->shouldQuit()) {
+ if (!reloadFlag) {
+ _vm->_images.clear();
+ _vm->_newRects.clear();
+ _vm->_oldRects.clear();
+ _vm->_numAnimTimers = 0;
+
+ reloadRoom();
+ }
+
+ reloadFlag = false;
+ _vm->_startup = 8;
+ _function = FN_NONE;
+
+ while (!_vm->shouldQuit()) {
+ _vm->_images.clear();
+ if (_vm->_startup != -1 && --_vm->_startup == 0) {
+ _vm->_events->showCursor();
+ _vm->_screen->fadeIn();
+ }
+
+ // Poll for events
+ _vm->_canSaveLoad = true;
+ _vm->_events->pollEventsAndWait();
+ _vm->_canSaveLoad = false;
+
+ _vm->_player->walk();
+ _vm->_midi->midiRepeat();
+ _vm->_player->checkScroll();
+
+ doCommands();
+ if (_vm->shouldQuitOrRestart())
+ return;
+
+ // DOROOMFLASHBACK jump point
+ if (_function == FN_CLEAR1) {
+ clearRoom();
+ break;
+ } else if (_function == FN_CLEAR2) {
+ clearRoom();
+ return;
+ } else if (_function == FN_RELOAD) {
+ reloadRoom1();
+ reloadFlag = true;
+ break;
+ } else if (_function == FN_BREAK) {
+ break;
+ }
+
+ if (_vm->_player->_scrollFlag) {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ _function = FN_NONE;
+ roomLoop();
+
+ if (_function == FN_CLEAR1) {
+ clearRoom();
+ break;
+ } else {
+ _vm->plotList();
+ _vm->copyRects();
+ _vm->copyBF2Vid();
+ }
+ } else {
+ _vm->copyBF1BF2();
+ _vm->_newRects.clear();
+ _function = FN_NONE;
+
+ roomLoop();
+ if (_vm->shouldQuitOrRestart())
+ return;
+
+ if (_function == FN_CLEAR1) {
+ clearRoom();
+ break;
+ } else {
+ _vm->plotList();
+
+ if (_vm->_events->_mousePos.y < 177)
+ _vm->_events->setCursor(_vm->_events->_normalMouse);
+ else
+ _vm->_events->setCursor(CURSOR_ARROW);
+
+ _vm->copyBlocks();
+ }
+ }
+ }
+ }
+}
+
+void Room::clearRoom() {
+ if (_vm->_midi->_music) {
+ _vm->_midi->stopSong();
+ _vm->_midi->freeMusic();
+ }
+
+ _vm->_sound->freeSounds();
+ _vm->_numAnimTimers = 0;
+
+ _vm->_animation->freeAnimationData();
+ _vm->_scripts->freeScriptData();
+ _vm->freeCells();
+ freePlayField();
+ freeTileData();
+ _vm->_player->freeSprites();
+}
+
+void Room::loadRoomData(const byte *roomData) {
+ RoomInfo roomInfo(roomData, _vm->getGameID(), _vm->isCD(), _vm->isDemo());
+
+ _roomFlag = roomInfo._roomFlag;
+
+ _vm->_establishFlag = false;
+ if (roomInfo._estIndex != -1) {
+ _vm->_establishFlag = true;
+ if (_vm->_establishTable[roomInfo._estIndex] != 1) {
+ _vm->_establishTable[roomInfo._estIndex] = 1;
+ _vm->establish(0, roomInfo._estIndex);
+ }
+ }
+
+ _vm->_midi->freeMusic();
+ if (roomInfo._musicFile._fileNum != -1) {
+ _vm->_midi->loadMusic(roomInfo._musicFile);
+ _vm->_midi->midiPlay();
+ _vm->_midi->setLoop(true);
+ }
+
+ _vm->_scaleH1 = roomInfo._scaleH1;
+ _vm->_scaleH2 = roomInfo._scaleH2;
+ _vm->_scaleN1 = roomInfo._scaleN1;
+ _vm->_scaleT1 = ((_vm->_scaleH1 - _vm->_scaleH2) << 8) / _vm->_scaleN1;
+
+ if (roomInfo._playFieldFile._fileNum != -1) {
+ loadPlayField(roomInfo._playFieldFile._fileNum,
+ roomInfo._playFieldFile._subfile);
+ setupRoom();
+
+ _vm->_scaleMaxY = _playFieldHeight << 4;
+ }
+
+ // Load cells
+ _vm->loadCells(roomInfo._cells);
+
+ // Load script data
+ _vm->_scripts->freeScriptData();
+ if (roomInfo._scriptFile._fileNum != -1) {
+ Resource *newScript = _vm->_files->loadFile(roomInfo._scriptFile);
+ _vm->_scripts->setScript(newScript);
+ }
+
+ // Load animation data
+ _vm->_animation->freeAnimationData();
+ if (roomInfo._animFile._fileNum != -1) {
+ Resource *anim = _vm->_files->loadFile(roomInfo._animFile);
+ _vm->_animation->loadAnimations(anim);
+ delete anim;
+ }
+
+ _vm->_scale = _vm->_scaleI = roomInfo._scaleI;
+ _vm->_screen->setScaleTable(_vm->_scale);
+ _vm->_player->_scrollThreshold = roomInfo._scrollThreshold;
+
+ // Handle loading scene palette data
+ if (roomInfo._paletteFile._fileNum != -1) {
+ _vm->_screen->_startColor = roomInfo._startColor;
+ _vm->_screen->_numColors = roomInfo._numColors;
+ _vm->_screen->loadPalette(roomInfo._paletteFile._fileNum,
+ roomInfo._paletteFile._subfile);
+ }
+
+ // Load extra cells
+ _vm->_extraCells.clear();
+ for (uint i = 0; i < roomInfo._extraCells.size(); ++i)
+ _vm->_extraCells.push_back(roomInfo._extraCells[i]);
+
+ // Load sounds for the scene
+ _vm->_sound->loadSounds(roomInfo._sounds);
+}
+
+void Room::roomLoop() {
+ _vm->_scripts->_sequence = ROOM_SCRIPT;
+ _vm->_scripts->searchForSequence();
+ _vm->_scripts->executeScript();
+}
+
+void Room::setupRoom() {
+ Screen &screen = *_vm->_screen;
+ screen.setScaleTable(_vm->_scale);
+ screen.setBufferScan();
+
+ if (_roomFlag != 2)
+ screen.setIconPalette();
+
+ if (screen._vWindowWidth == _playFieldWidth) {
+ _vm->_scrollX = 0;
+ _vm->_scrollCol = 0;
+ } else {
+ int xv = _vm->_player->_rawPlayer.x / TILE_WIDTH;
+ _vm->_scrollX = _vm->_player->_rawPlayer.x % TILE_WIDTH;
+ _vm->_scrollCol = MAX(xv - (screen._vWindowWidth / 2), 0);
+
+ int sx = _vm->_scrollCol + screen._vWindowWidth - _playFieldWidth;
+ if (sx >= 0) {
+ _vm->_scrollCol -= sx + 1;
+ }
+ }
+
+ if (screen._vWindowHeight == _playFieldHeight) {
+ _vm->_scrollY = 0;
+ _vm->_scrollRow = 0;
+ } else {
+ _vm->_scrollY = _vm->_player->_rawPlayer.y -
+ (_vm->_player->_rawPlayer.y / 16) * 16;
+ int yc = MAX((_vm->_player->_rawPlayer.y >> 4) -
+ (screen._vWindowHeight / 2), 0);
+ _vm->_scrollRow = yc;
+
+ yc = yc + screen._vWindowHeight - _playFieldHeight;
+ if (yc >= 0) {
+ _vm->_scrollRow = _playFieldHeight - screen._vWindowHeight;
+ _vm->_scrollY = 0;
+ }
+ }
+}
+
+void Room::setWallCodes() {
+ _jetFrame.clear();
+ _jetFrame.resize(_plotter._walls.size());
+
+ _vm->_player->_rawXTemp = _vm->_player->_rawPlayer.x;
+ _vm->_player->_rawYTemp = _vm->_player->_rawPlayer.y;
+}
+
+void Room::buildScreen() {
+ int scrollCol = _vm->_scrollCol;
+ int offset = 0;
+
+ // Clear current background buffer
+ _vm->_buffer1.clearBuffer();
+
+ // WORKAROUND: Original's use of '+ 1' would frequently cause memory overruns
+ int w = MIN(_vm->_screen->_vWindowWidth + 1, _playFieldWidth);
+
+ // Loop through drawing each column of tiles forming the background
+ for (int idx = 0; idx < w; offset += TILE_WIDTH, ++idx) {
+ buildColumn(_vm->_scrollCol, offset);
+ ++_vm->_scrollCol;
+ }
+
+ _vm->_scrollCol = scrollCol;
+ _vm->copyBF1BF2();
+}
+
+void Room::buildColumn(int playX, int screenX) {
+ if (playX < 0 || playX >= _playFieldWidth)
+ return;
+
+ const byte *pSrc = _playField + _vm->_scrollRow *
+ _playFieldWidth + playX;
+
+ // WORKAROUND: Original's use of '+ 1' would frequently cause memory overruns
+ int h = MIN(_vm->_screen->_vWindowHeight + 1, _playFieldHeight);
+
+ for (int y = 0; y < h; ++y) {
+ byte *pTile = _tile + (*pSrc << 8);
+ byte *pDest = (byte *)_vm->_buffer1.getBasePtr(screenX, y * TILE_HEIGHT);
+
+ for (int tileY = 0; tileY < TILE_HEIGHT; ++tileY) {
+ Common::copy(pTile, pTile + TILE_WIDTH, pDest);
+ pTile += TILE_WIDTH;
+ pDest += _vm->_buffer1.pitch;
+ }
+
+ pSrc += _playFieldWidth;
+ }
+}
+
+void Room::buildRow(int playY, int screenY) {
+ if (playY < 0 || playY >= _playFieldHeight)
+ return;
+ assert(screenY <= (_vm->_screen->h - TILE_HEIGHT));
+
+ const byte *pSrc = _playField + playY *_playFieldWidth + _vm->_scrollCol;
+
+ // WORKAROUND: Original's use of '+ 1' would frequently cause memory overruns
+ int w = MIN(_vm->_screen->_vWindowWidth + 1, _playFieldWidth);
+
+ for (int x = 0; x < w; ++x) {
+ byte *pTile = _tile + (*pSrc << 8);
+ byte *pDest = (byte *)_vm->_buffer1.getBasePtr(x * TILE_WIDTH, screenY);
+
+ for (int tileY = 0; tileY < TILE_HEIGHT; ++tileY) {
+ Common::copy(pTile, pTile + TILE_WIDTH, pDest);
+ pTile += TILE_WIDTH;
+ pDest += _vm->_buffer1.pitch;
+ }
+
+ ++pSrc;
+ }
+}
+
+void Room::loadPlayField(int fileNum, int subfile) {
+ Resource *playData = _vm->_files->loadFile(fileNum, subfile);
+ byte header[16];
+ playData->_stream->read(&header[0], 16);
+ Screen &screen = *_vm->_screen;
+
+ // Copy the new palette
+ screen.loadRawPalette(playData->_stream);
+
+ // Copy off the tile data
+ _tileSize = (int)header[2] << 8;
+ _tile = new byte[_tileSize];
+ playData->_stream->read(_tile, _tileSize);
+
+ // Copy off the playfield data
+ _matrixSize = header[0] * header[1];
+ _playField = new byte[_matrixSize];
+ playData->_stream->read(_playField, _matrixSize);
+
+ // Load the plotter data
+ int numWalls = READ_LE_UINT16(&header[6]);
+ int numBlocks = header[8];
+ _plotter.load(playData->_stream, numWalls, numBlocks);
+
+ _playFieldWidth = header[0];
+ _playFieldHeight = header[1];
+ screen._vWindowWidth = header[3];
+ screen._vWindowBytesWide = screen._vWindowWidth << 4;
+ screen._bufferBytesWide = screen._vWindowBytesWide + 16;
+ screen._vWindowHeight = header[4];
+ screen._vWindowLinesTall = screen._vWindowHeight << 4;
+
+ _vm->_screen->setBufferScan();
+ delete playData;
+}
+
+/*------------------------------------------------------------------------*/
+
+Plotter::Plotter() {
+ _delta = _blockIn = 0;
+}
+
+void Plotter::load(Common::SeekableReadStream *stream, int wallCount, int blockCount) {
+ // Load the wall count
+ _walls.resize(wallCount);
+
+ for (int i = 0; i < wallCount; ++i)
+ _walls[i].left = stream->readSint16LE();
+ for (int i = 0; i < wallCount; ++i)
+ _walls[i].top = stream->readSint16LE();
+ for (int i = 0; i < wallCount; ++i)
+ _walls[i].right = stream->readSint16LE();
+ for (int i = 0; i < wallCount; ++i)
+ _walls[i].bottom = stream->readSint16LE();
+
+ // Load the block list
+ _blocks.resize(blockCount);
+
+ for (int i = 0; i < blockCount; ++i)
+ _blocks[i].left = stream->readSint16LE();
+ for (int i = 0; i < blockCount; ++i)
+ _blocks[i].top = stream->readSint16LE();
+ for (int i = 0; i < blockCount; ++i)
+ _blocks[i].right = stream->readSint16LE();
+ for (int i = 0; i < blockCount; ++i)
+ _blocks[i].bottom = stream->readSint16LE();
+}
+
+void Room::doCommands() {
+ int commandId = 0;
+ Common::KeyState keyState;
+
+ if (_vm->_startup != -1)
+ return;
+
+ if (_vm->_inventory->_invChangeFlag)
+ _vm->_inventory->refreshInventory();
+
+ if (_vm->_screen->_screenChangeFlag) {
+ _vm->_screen->_screenChangeFlag = false;
+ _vm->_events->_cursorExitFlag = true;
+ executeCommand(7);
+ }
+ else if (_vm->_events->_wheelUp || _vm->_events->_wheelDown) {
+ // Handle scrolling mouse wheel
+ cycleCommand(_vm->_events->_wheelUp ? 1 : -1);
+
+ } else if (_vm->_events->_middleButton) {
+ // Switch back to walking
+ handleCommand(7);
+
+ } else if (_vm->_events->_leftButton) {
+ if (_vm->_events->_mouseRow >= 22) {
+ // Mouse in user interface area
+ for (commandId = 0; commandId < 10; ++commandId) {
+ if (_vm->_events->_mousePos.x >= RMOUSE[commandId][0] &&
+ _vm->_events->_mousePos.x < RMOUSE[commandId][1])
+ break;
+ }
+ if (commandId < 10)
+ handleCommand(commandId);
+
+ } else {
+ // Mouse click in main game area
+ mainAreaClick();
+ }
+ } else if (_vm->_events->getKey(keyState)) {
+ if (keyState.keycode == Common::KEYCODE_F1)
+ handleCommand(keyState.keycode - Common::KEYCODE_F1 + 1);
+ else if (keyState.keycode >= Common::KEYCODE_F2 && keyState.keycode <= Common::KEYCODE_F10)
+ handleCommand(keyState.keycode - Common::KEYCODE_F1);
+ }
+}
+
+void Room::cycleCommand(int incr) {
+ int command = _selectCommand + incr;
+ if (command < -1)
+ command = 6;
+ else if (command == -1)
+ command = 7;
+ else if (command == 1)
+ command = (incr == 1) ? 2 : 0;
+ else if (command == 4)
+ command = (incr == 1) ? 5 : 3;
+
+ handleCommand(command);
+}
+
+void Room::handleCommand(int commandId) {
+ if (commandId == 1)
+ --commandId;
+
+ if (commandId == 9) {
+ _vm->_events->debounceLeft();
+ _vm->_canSaveLoad = true;
+ _vm->openMainMenuDialog();
+ _vm->_canSaveLoad = false;
+ } else if (commandId == _selectCommand) {
+ _vm->_events->debounceLeft();
+ commandOff();
+ } else {
+ _vm->_events->debounceLeft();
+ executeCommand(commandId);
+ }
+}
+
+void Room::executeCommand(int commandId) {
+ EventsManager &events = *_vm->_events;
+ _selectCommand = commandId;
+
+ switch (commandId) {
+ case 0:
+ events.forceSetCursor(CURSOR_LOOK);
+ break;
+ case 2:
+ events.forceSetCursor(CURSOR_USE);
+ break;
+ case 3:
+ events.forceSetCursor(CURSOR_TAKE);
+ break;
+ case 4:
+ events.setCursor(CURSOR_ARROW);
+ if (_vm->_inventory->newDisplayInv() == 2) {
+ commandOff();
+ return;
+ }
+ break;
+ case 5:
+ events.forceSetCursor(CURSOR_CLIMB);
+ break;
+ case 6:
+ events.forceSetCursor(CURSOR_TALK);
+ break;
+ case 7:
+ walkCursor();
+ return;
+ case 8:
+ events.forceSetCursor(CURSOR_HELP);
+ break;
+ default:
+ break;
+ }
+
+ // Draw the default toolbar menu at the bottom of the screen
+ roomMenu();
+ _vm->_screen->saveScreen();
+ _vm->_screen->setDisplayScan();
+
+ // Get the toolbar icons resource
+ Resource *iconData = _vm->_files->loadFile("ICONS.LZ");
+ SpriteResource *spr = new SpriteResource(_vm, iconData);
+ delete iconData;
+
+ // Draw the button as selected
+ _vm->_screen->plotImage(spr, _selectCommand + 2,
+ Common::Point(RMOUSE[_selectCommand][0], 176));
+
+ _vm->_screen->restoreScreen();
+ _vm->_boxSelect = true;
+}
+
+void Room::walkCursor() {
+ EventsManager &events = *_vm->_events;
+
+ events.forceSetCursor(CURSOR_CROSSHAIRS);
+ _vm->_scripts->_sequence = 5000;
+ _vm->_scripts->searchForSequence();
+ roomMenu();
+ _selectCommand = -1;
+
+ _conFlag = true;
+ while (_conFlag && !_vm->shouldQuitOrRestart()) {
+ _conFlag = false;
+ _vm->_scripts->executeScript();
+ }
+
+ _vm->_boxSelect = true;
+}
+
+void Room::commandOff() {
+ _selectCommand = -1;
+ _vm->_events->forceSetCursor(CURSOR_CROSSHAIRS);
+ roomMenu();
+}
+
+int Room::checkBoxes() {
+ return checkBoxes1(_vm->_player->_rawPlayer);
+}
+
+int Room::checkBoxes1(const Common::Point &pt) {
+ return checkBoxes2(pt, 0, _plotter._blocks.size());
+}
+
+int Room::checkBoxes2(const Common::Point &pt, int start, int count) {
+ for (; count > 0; --count, ++start) {
+ if (_plotter._blocks[start].contains(pt)) {
+ _plotter._blockIn = start;
+ return start;
+ }
+ }
+
+ return -1;
+}
+
+void Room::checkBoxes3() {
+ Common::Point pt = _vm->_events->calcRawMouse();
+
+ for (uint start = 0; start < _plotter._blocks.size(); ++start) {
+ if (_plotter._blocks[start].contains(pt)) {
+ _plotter._blockIn = start;
+ if (!(validateBox(start) & 0x80)) {
+ _vm->_events->debounceLeft();
+ _vm->_boxSelect = start;
+
+ _conFlag = true;
+ while (_conFlag && !_vm->shouldQuitOrRestart()) {
+ _conFlag = false;
+ _vm->_scripts->executeScript();
+ }
+
+ _vm->_boxSelect = true;
+ return;
+ }
+ }
+ }
+}
+
+int Room::validateBox(int boxId) {
+ _vm->_scripts->_sequence = boxId;
+ _vm->_scripts->searchForSequence();
+ return _vm->_scripts->executeScript();
+}
+
+void Room::swapOrg() {
+ SWAP<int>(_vm->_screen->_orgX1, _vm->_screen->_orgX2);
+ SWAP<int>(_vm->_screen->_orgY1, _vm->_screen->_orgY2);
+}
+
+int Room::calcLR(int yp) {
+ const Screen &screen = *_vm->_screen;
+
+ int yv = (yp - screen._orgY1) * (screen._orgX2 - screen._orgX1);
+ int yd = screen._orgY2 - screen._orgY1;
+
+ int rem = (yv % yd) << 1;
+ yv /= yd;
+ if (rem >= yd || rem < 0)
+ ++yv;
+
+ return yv + screen._orgX1;
+}
+
+int Room::calcUD(int xp) {
+ const Screen &screen = *_vm->_screen;
+
+ int xv = (xp - screen._orgX1) * (screen._orgY2 - screen._orgY1);
+ int xd = screen._orgX2 - screen._orgX1;
+
+ int rem = (xv % xd) << 1;
+ xv /= xd;
+ if (rem >= xd || rem < 0)
+ ++xv;
+
+ return xv + screen._orgY1;
+}
+
+bool Room::codeWalls() {
+ Screen &screen = *_vm->_screen;
+ Player &player = *_vm->_player;
+
+ if (_plotter._walls.size() == 0)
+ return false;
+
+ for (uint i = 0; i < _plotter._walls.size(); ++i) {
+ Common::Rect &r = _plotter._walls[i];
+ JetFrame &jf = _jetFrame[i];
+
+ jf._wallCode = 0;
+ jf._wallCode1 = 0;
+ screen._orgX1 = r.left;
+ screen._orgY1 = r.top;
+ screen._orgX2 = r.right;
+ screen._orgY2 = r.bottom;
+
+ if (screen._orgY2 != screen._orgY1) {
+ if (screen._orgY2 < screen._orgY1)
+ swapOrg();
+
+ if ((player._rawYTemp >= screen._orgY1) &&
+ (player._rawYTemp <= screen._orgY2)) {
+ jf._wallCode |= (calcLR(player._rawYTemp) - player._rawXTemp) < 0 ? 2 : 1;
+ jf._wallCode1 |= (calcLR(player._rawYTemp) -
+ (player._rawXTemp + player._playerOffset.x)) < 0 ? 2 : 1;
+ }
+ }
+
+ if (screen._orgX2 != screen._orgX1) {
+ if (screen._orgX2 < screen._orgX1)
+ swapOrg();
+
+ if ((player._rawXTemp >= screen._orgX1) &&
+ (player._rawXTemp <= screen._orgX2)) {
+ int y = screen._orgY2;
+ if (y != screen._orgY1)
+ y = calcUD(player._rawXTemp);
+
+ jf._wallCode |= (player._rawYTemp - y) < 0 ? 4 : 8;
+ }
+
+ int x = player._rawXTemp + player._playerOffset.x;
+ if ((x >= screen._orgX1) && (x <= screen._orgX2)) {
+ int y = screen._orgY2;
+ if (screen._orgY2 != screen._orgY1)
+ y = calcUD(player._rawXTemp + player._playerOffset.x);
+
+ jf._wallCode1 |= (player._rawYTemp - y) < 0 ? 4 : 8;
+ }
+ }
+ }
+
+ for (uint i = 0; i < _jetFrame.size(); ++i) {
+ JetFrame &jf = _jetFrame[i];
+ if (checkCode(jf._wallCode, jf._wallCodeOld) ||
+ checkCode(jf._wallCode1, jf._wallCode1Old))
+ return true;
+ }
+
+ // Copy the current wall calculations to the old properties
+ for (uint i = 0; i < _jetFrame.size(); ++i) {
+ JetFrame &jf = _jetFrame[i];
+ jf._wallCodeOld = jf._wallCode;
+ jf._wallCode1Old = jf._wallCode1;
+ }
+
+ return false;
+}
+
+bool Room::checkCode(int v1, int v2) {
+ Player &p = *_vm->_player;
+
+ if (!v1 || !v2 || (v1 == v2))
+ return false;
+
+ if (v1 & 1) {
+ if (v2 & 2) {
+ p._collideFlag = true;
+ return true;
+ }
+ } else if (v1 & 2) {
+ if (v2 & 1) {
+ p._collideFlag = true;
+ return true;
+ }
+ } else if (v1 & 4) {
+ if (v2 & 8) {
+ p._collideFlag = true;
+ return true;
+ }
+ } else if (v1 & 8) {
+ if (v2 & 4) {
+ p._collideFlag = true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------------*/
+
+RoomInfo::RoomInfo(const byte *data, int gameType, bool isCD, bool isDemo) {
+ Common::MemoryReadStream stream(data, 999);
+
+ _roomFlag = stream.readByte();
+
+ if (gameType == GType_Amazon) {
+ if (isCD)
+ _estIndex = stream.readSint16LE();
+ else {
+ _estIndex = -1;
+ if (!isDemo)
+ stream.readSint16LE();
+ }
+ } else
+ _estIndex = -1;
+
+ _musicFile.load(stream);
+ _scaleH1 = stream.readByte();
+ _scaleH2 = stream.readByte();
+ _scaleN1 = stream.readByte();
+ _playFieldFile.load(stream);
+
+ for (byte cell = stream.readByte(); cell != 0xff; cell = stream.readByte()) {
+ CellIdent ci;
+ ci._cell = cell;
+ ci.load(stream);
+
+ _cells.push_back(ci);
+ }
+
+ _scriptFile.load(stream);
+ _animFile.load(stream);
+ _scaleI = stream.readByte();
+ _scrollThreshold = stream.readByte();
+ _paletteFile.load(stream);
+ if (_paletteFile._fileNum == -1) {
+ _startColor = _numColors = 0;
+ } else {
+ _startColor = stream.readUint16LE();
+ _numColors = stream.readUint16LE();
+ }
+
+ for (int16 v = stream.readSint16LE(); v != -1; v = stream.readSint16LE()) {
+ ExtraCell ec;
+ ec._vid._fileNum = v;
+ ec._vid._subfile = stream.readSint16LE();
+
+ _extraCells.push_back(ec);
+ }
+
+ for (int16 fileNum = stream.readSint16LE(); fileNum != -1; fileNum = stream.readSint16LE()) {
+ SoundIdent fi;
+ fi._fileNum = fileNum;
+ fi._subfile = stream.readUint16LE();
+ fi._priority = stream.readUint16LE();
+
+ _sounds.push_back(fi);
+ }
+}
+
+} // End of namespace Access
diff --git a/engines/access/room.h b/engines/access/room.h
new file mode 100644
index 0000000000..44279fa6b1
--- /dev/null
+++ b/engines/access/room.h
@@ -0,0 +1,202 @@
+/* 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 ACCESS_ROOM_H
+#define ACCESS_ROOM_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "access/data.h"
+
+#define TILE_WIDTH 16
+#define TILE_HEIGHT 16
+
+namespace Access {
+
+class Plotter {
+public:
+ Common::Array<Common::Rect> _walls;
+ Common::Array<Common::Rect> _blocks;
+ int _blockIn;
+ int _delta;
+public:
+ Plotter();
+
+ void load(Common::SeekableReadStream *stream, int wallCount, int blockCount);
+};
+
+class JetFrame {
+public:
+ int _wallCode;
+ int _wallCodeOld;
+ int _wallCode1;
+ int _wallCode1Old;
+
+ JetFrame() {
+ _wallCode = _wallCodeOld = 0;
+ _wallCode1 = _wallCode1Old = 0;
+ }
+};
+
+enum Function { FN_NONE = 0, FN_CLEAR1 = 1, FN_CLEAR2 = 2, FN_RELOAD = 3, FN_BREAK = 4 };
+
+class Room : public Manager {
+private:
+ void roomLoop();
+
+ void loadPlayField(int fileNum, int subfile);
+
+ void commandOff();
+
+ void swapOrg();
+ int calcLR(int yp);
+ int calcUD(int xp);
+
+ /**
+ * Cycles forwards or backwards through the list of commands
+ */
+ void cycleCommand(int incr);
+
+ bool checkCode(int v1, int v2);
+protected:
+ void loadRoomData(const byte *roomData);
+
+ /**
+ * Free the playfield data
+ */
+ void freePlayField();
+
+ /**
+ * Free tile data
+ */
+ void freeTileData();
+
+ int checkBoxes();
+ int checkBoxes1(const Common::Point &pt);
+ int checkBoxes2(const Common::Point &pt, int start, int count);
+ void checkBoxes3();
+
+ int validateBox(int boxId);
+
+ /**
+ * Inner handler for switching to a given command mode
+ */
+ void executeCommand(int commandId);
+
+ virtual void reloadRoom() = 0;
+
+ virtual void reloadRoom1() = 0;
+
+ virtual void setupRoom();
+
+ virtual void doCommands();
+
+ virtual void mainAreaClick() = 0;
+
+ virtual void walkCursor();
+public:
+ Plotter _plotter;
+ Common::Array<JetFrame> _jetFrame;
+ Function _function;
+ int _roomFlag;
+ byte *_playField;
+ int _matrixSize;
+ int _playFieldWidth;
+ int _playFieldHeight;
+ byte *_tile;
+ int _tileSize;
+ int _selectCommand;
+ bool _conFlag;
+public:
+ Room(AccessEngine *vm);
+
+ virtual ~Room();
+
+ void doRoom();
+
+ virtual void loadRoom(int roomNumber) = 0;
+
+ virtual void roomMenu() = 0;
+
+ /**
+ * Clear all the data used by the room
+ */
+ virtual void clearRoom();
+
+ /**
+ * Builds up a game screen
+ */
+ void buildScreen();
+
+ /**
+ * Draw a column of a game scene
+ */
+ void buildColumn(int playX, int screenX);
+
+ /**
+ * Draw a row of a game scene
+ */
+ void buildRow(int playY, int screenY);
+
+ virtual void init4Quads() = 0;
+
+ void setWallCodes();
+
+ bool codeWalls();
+
+ /**
+ * Switch to a given command mode
+ */
+ void handleCommand(int commandId);
+};
+
+class RoomInfo {
+public:
+ struct SoundIdent : FileIdent {
+ int _priority;
+ };
+public:
+ int _roomFlag;
+ int _estIndex;
+ FileIdent _musicFile;
+ int _scaleH1;
+ int _scaleH2;
+ int _scaleN1;
+ FileIdent _playFieldFile;
+ Common::Array<CellIdent> _cells;
+ FileIdent _scriptFile;
+ FileIdent _animFile;
+ int _scaleI;
+ int _scrollThreshold;
+ FileIdent _paletteFile;
+ int _startColor;
+ int _numColors;
+ Common::Array<ExtraCell> _extraCells;
+ Common::Array<SoundIdent> _sounds;
+public:
+ RoomInfo(const byte *data, int gameType, bool isCD, bool isDemo);
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_ROOM_H */
diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp
new file mode 100644
index 0000000000..35069ba683
--- /dev/null
+++ b/engines/access/screen.cpp
@@ -0,0 +1,368 @@
+/* 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/algorithm.h"
+#include "common/endian.h"
+#include "common/rect.h"
+#include "common/textconsole.h"
+#include "common/system.h"
+#include "graphics/palette.h"
+#include "access/access.h"
+#include "access/screen.h"
+#include "access/resources.h"
+
+namespace Access {
+
+#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
+
+Screen::Screen(AccessEngine *vm) : _vm(vm) {
+ create(320, 200);
+ Common::fill(&_tempPalette[0], &_tempPalette[PALETTE_SIZE], 0);
+ Common::fill(&_manPal[0], &_manPal[0x60], 0);
+ Common::fill(&_scaleTable1[0], &_scaleTable1[256], 0);
+ Common::fill(&_scaleTable2[0], &_scaleTable2[256], 0);
+ _savedPaletteCount = 0;
+ if (_vm->isCD())
+ _vesaMode = 0;
+ else
+ _vesaMode = 1;
+
+ _vesaCurrentWin = 0;
+ _currentPanel = 0;
+ _hideFlag = true;
+ _startColor = _numColors = 0;
+ _windowXAdd = _windowYAdd = 0;
+ _screenYOff = 0;
+ _screenChangeFlag = false;
+
+ _bufferBytesWide = _vWindowBytesWide = this->w;
+ _vWindowLinesTall = this->h;
+ _clipWidth = _vWindowBytesWide - 1;
+ _clipHeight = _vWindowLinesTall - 1;
+ _startCycle = 0;
+ _cycleStart = 0;
+ _endCycle = 0;
+}
+
+void Screen::clearScreen() {
+ clearBuffer();
+ if (_vesaMode)
+ _vm->_clearSummaryFlag = true;
+
+ addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void Screen::setDisplayScan() {
+ _clipWidth = this->w - 1;
+ _clipHeight = this->h - 1;
+ _windowXAdd = _windowYAdd = 0;
+ _vm->_scrollX = _vm->_scrollY = 0;
+ _vm->_scrollCol = _vm->_scrollRow = 0;
+ _bufferStart.x = _bufferStart.y = 0;
+ _screenYOff = 0;
+}
+
+void Screen::setPanel(int num) {
+ assert(num < 4);
+ _currentPanel = num;
+ _msVirtualOffset = _virtualOffsetsTable[num];
+}
+
+void Screen::updateScreen() {
+ // Merge the dirty rects
+ mergeDirtyRects();
+
+ // Loop through copying dirty areas to the physical screen
+ Common::List<Common::Rect>::iterator i;
+ for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
+ const Common::Rect &r = *i;
+ const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
+ g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top,
+ r.width(), r.height());
+ }
+
+ // Signal the physical screen to update
+ g_system->updateScreen();
+ _dirtyRects.clear();
+}
+
+void Screen::setInitialPalettte() {
+ Common::copy(&INITIAL_PALETTE[0], &INITIAL_PALETTE[18 * 3], _rawPalette);
+ Common::fill(&_rawPalette[18 * 3], &_rawPalette[PALETTE_SIZE], 0);
+
+ g_system->getPaletteManager()->setPalette(INITIAL_PALETTE, 0, 18);
+}
+
+void Screen::loadPalette(int fileNum, int subfile) {
+ Resource *res = _vm->_files->loadFile(fileNum, subfile);
+ byte *palette = res->data();
+ Common::copy(palette, palette + (_numColors * 3), &_rawPalette[_startColor * 3]);
+ delete res;
+}
+
+void Screen::setPalette() {
+ g_system->getPaletteManager()->setPalette(&_rawPalette[0], 0, PALETTE_COUNT);
+}
+
+void Screen::loadRawPalette(Common::SeekableReadStream *stream) {
+ stream->read(&_rawPalette[0], PALETTE_SIZE);
+ for (byte *p = &_rawPalette[0]; p < &_rawPalette[PALETTE_SIZE]; ++p)
+ *p = VGA_COLOR_TRANS(*p);
+}
+
+void Screen::updatePalette() {
+ g_system->getPaletteManager()->setPalette(&_tempPalette[0], 0, PALETTE_COUNT);
+ updateScreen();
+}
+
+void Screen::savePalette() {
+ Common::copy(&_rawPalette[0], &_rawPalette[PALETTE_SIZE],
+ &_savedPalettes[_savedPaletteCount][0]);
+
+ if (++_savedPaletteCount == 2)
+ _savedPaletteCount = 1;
+}
+
+void Screen::restorePalette() {
+ if (--_savedPaletteCount < 0)
+ _savedPaletteCount = 0;
+
+ Common::copy(&_savedPalettes[_savedPaletteCount][0],
+ &_savedPalettes[_savedPaletteCount][PALETTE_SIZE], &_rawPalette[0]);
+}
+
+void Screen::getPalette(byte *pal) {
+ g_system->getPaletteManager()->grabPalette(pal, 0, 256);
+}
+
+void Screen::forceFadeOut() {
+ const int FADE_AMOUNT = 2;
+ bool repeatFlag;
+ byte *srcP;
+ int count;
+
+ do {
+ repeatFlag = false;
+ for (srcP = &_tempPalette[0], count = 0; count < PALETTE_SIZE; ++count, ++srcP) {
+ int v = *srcP;
+ if (v) {
+ repeatFlag = true;
+ *srcP = MAX(*srcP - FADE_AMOUNT, 0);
+ }
+ }
+
+ updatePalette();
+ _vm->_events->pollEventsAndWait();
+ } while (repeatFlag && !_vm->shouldQuit());
+}
+
+void Screen::forceFadeIn() {
+ Common::fill(&_tempPalette[0], &_tempPalette[PALETTE_SIZE], 0);
+
+ const int FADE_AMOUNT = 2;
+ bool repeatFlag;
+ do {
+ repeatFlag = false;
+ const byte *srcP = &_rawPalette[0];
+ byte *destP = &_tempPalette[0];
+
+ for (int idx = 0; idx < PALETTE_SIZE; ++idx, ++srcP, ++destP) {
+ if (*destP != *srcP) {
+ repeatFlag = true;
+ *destP = MAX((int)*destP + FADE_AMOUNT, (int)*srcP);
+ }
+ }
+
+ updatePalette();
+ _vm->_events->pollEventsAndWait();
+ } while (repeatFlag);
+}
+
+void Screen::copyBuffer(const byte *data) {
+ byte *destP = (byte *)getPixels();
+ Common::copy(data, data + (h * w), destP);
+ g_system->copyRectToScreen(destP, w, 0, 0, w, h);
+}
+
+void Screen::setBufferScan() {
+ _clipWidth = _vWindowBytesWide - 1;
+ _windowXAdd = (320 - _clipWidth) >> 1;
+ _clipHeight = _vWindowLinesTall - 1;
+ _windowYAdd = (176 - _clipHeight) >> 1;
+}
+
+void Screen::setScaleTable(int scale) {
+ int total = 0;
+ for (int idx = 0; idx < 256; ++idx) {
+ _scaleTable1[idx] = total >> 8;
+ _scaleTable2[idx] = total & 0xff;
+ total += scale;
+ }
+}
+
+void Screen::saveScreen() {
+ _screenSave._clipWidth = _clipWidth;
+ _screenSave._clipHeight = _clipHeight;
+ _screenSave._windowXAdd = _windowXAdd;
+ _screenSave._windowYAdd = _windowYAdd;
+ _screenSave._scroll.x = _vm->_scrollX;
+ _screenSave._scroll.y = _vm->_scrollY;
+ _screenSave._scrollCol = _vm->_scrollCol;
+ _screenSave._scrollRow = _vm->_scrollRow;
+ _screenSave._bufferStart.x = _bufferStart.x;
+ _screenSave._bufferStart.y = _bufferStart.y;
+ _screenSave._screenYOff = _screenYOff;
+}
+
+void Screen::restoreScreen() {
+ _clipWidth = _screenSave._clipWidth;
+ _clipHeight = _screenSave._clipHeight;
+ _windowXAdd = _screenSave._windowXAdd;
+ _windowYAdd = _screenSave._windowYAdd;
+ _vm->_scrollX = _screenSave._scroll.x;
+ _vm->_scrollY = _screenSave._scroll.y;
+ _vm->_scrollCol = _screenSave._scrollCol;
+ _vm->_scrollRow = _screenSave._scrollRow;
+ _bufferStart.x = _screenSave._bufferStart.x;
+ _bufferStart.y = _screenSave._bufferStart.y;
+ _screenYOff = _screenSave._screenYOff;
+}
+
+void Screen::copyBlock(ASurface *src, const Common::Rect &bounds) {
+ Common::Rect destBounds = bounds;
+ destBounds.translate(_windowXAdd, _windowYAdd + _screenYOff);
+
+ copyRectToSurface(*src, destBounds.left, destBounds.top, bounds);
+ addDirtyRect(destBounds);
+}
+
+void Screen::restoreBlock() {
+ if (!_savedBounds.isEmpty())
+ addDirtyRect(_savedBounds);
+ ASurface::restoreBlock();
+}
+
+void Screen::drawRect() {
+ addDirtyRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2));
+ ASurface::drawRect();
+}
+
+void Screen::transCopyFrom(ASurface *src, const Common::Point &destPos) {
+ addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src->w, destPos.y + src->h));
+ ASurface::transCopyFrom(src, destPos);
+}
+
+void Screen::transCopyFrom(ASurface *src, const Common::Rect &bounds) {
+ addDirtyRect(bounds);
+ ASurface::transCopyFrom(src, bounds);
+}
+
+void Screen::copyFrom(Graphics::Surface &src) {
+ addDirtyRect(Common::Rect(0, 0, src.w, src.h));
+ ASurface::copyFrom(src);
+}
+
+void Screen::copyBuffer(Graphics::Surface *src) {
+ addDirtyRect(Common::Rect(0, 0, src->w, src->h));
+ ASurface::copyBuffer(src);
+}
+
+void Screen::setPaletteCycle(int startCycle, int endCycle, int timer) {
+ _startCycle = _cycleStart = startCycle;
+ _endCycle = endCycle;
+
+ TimerEntry &te = _vm->_timers[6];
+ te._timer = te._initTm = timer;
+ te._flag++;
+}
+
+void Screen::cyclePaletteForward() {
+ cyclePaletteBackwards();
+}
+
+void Screen::cyclePaletteBackwards() {
+ if (!_vm->_timers[6]._flag) {
+ _vm->_timers[6]._flag++;
+ byte *pStart = &_rawPalette[_cycleStart * 3];
+ byte *pEnd = &_rawPalette[_endCycle * 3];
+
+ for (int idx = _startCycle; idx < _endCycle; ++idx) {
+ g_system->getPaletteManager()->setPalette(pStart, idx, 1);
+
+ pStart += 3;
+ if (pStart == pEnd)
+ pStart = &_rawPalette[_cycleStart * 3];
+ }
+
+ if (--_cycleStart <= _startCycle)
+ _cycleStart = _endCycle - 1;
+
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+}
+
+void Screen::addDirtyRect(const Common::Rect &r) {
+ _dirtyRects.push_back(r);
+ assert(r.isValidRect() && r.width() > 0 && r.height() > 0);
+}
+
+void Screen::mergeDirtyRects() {
+ Common::List<Common::Rect>::iterator rOuter, rInner;
+
+ // Ensure dirty rect list has at least two entries
+ rOuter = _dirtyRects.begin();
+ for (int i = 0; i < 2; ++i, ++rOuter) {
+ if (rOuter == _dirtyRects.end())
+ return;
+ }
+
+ // Process the dirty rect list to find any rects to merge
+ for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
+ rInner = rOuter;
+ while (++rInner != _dirtyRects.end()) {
+
+ if ((*rOuter).intersects(*rInner)) {
+ // these two rectangles overlap or
+ // are next to each other - merge them
+
+ unionRectangle(*rOuter, *rOuter, *rInner);
+
+ // remove the inner rect from the list
+ _dirtyRects.erase(rInner);
+
+ // move back to beginning of list
+ rInner = rOuter;
+ }
+ }
+ }
+}
+
+bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
+ destRect = src1;
+ destRect.extend(src2);
+
+ return !destRect.isEmpty();
+}
+
+
+} // End of namespace Access
diff --git a/engines/access/screen.h b/engines/access/screen.h
new file mode 100644
index 0000000000..0fa111c21c
--- /dev/null
+++ b/engines/access/screen.h
@@ -0,0 +1,182 @@
+/* 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 ACCESS_SCREEN_H
+#define ACCESS_SCREEN_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "common/stream.h"
+#include "access/asurface.h"
+
+namespace Access {
+
+class AccessEngine;
+
+#define PALETTE_COUNT 256
+#define PALETTE_SIZE (256 * 3)
+
+struct ScreenSave {
+ int _clipWidth;
+ int _clipHeight;
+ int _windowXAdd;
+ int _windowYAdd;
+ Common::Point _scroll;
+ int _scrollCol;
+ int _scrollRow;
+ Common::Point _bufferStart;
+ int _screenYOff;
+};
+
+class Screen : public ASurface {
+private:
+ AccessEngine *_vm;
+ byte _tempPalette[PALETTE_SIZE];
+ byte _rawPalette[PALETTE_SIZE];
+ byte _savedPalettes[2][PALETTE_SIZE];
+ int _savedPaletteCount;
+ int _vesaCurrentWin;
+ int _currentPanel;
+ Common::Point _msVirtualOffset;
+ Common::Point _virtualOffsetsTable[4];
+ bool _hideFlag;
+ ScreenSave _screenSave;
+ int _startCycle;
+ int _cycleStart;
+ int _endCycle;
+ Common::List<Common::Rect> _dirtyRects;
+
+ void updatePalette();
+
+ void mergeDirtyRects();
+
+ bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+public:
+ int _vesaMode;
+ int _startColor, _numColors;
+ Common::Point _bufferStart;
+ int _windowXAdd, _windowYAdd;
+ int _screenYOff;
+ byte _manPal[0x60];
+ byte _scaleTable1[256];
+ byte _scaleTable2[256];
+ int _vWindowWidth;
+ int _vWindowHeight;
+ int _vWindowBytesWide;
+ int _bufferBytesWide;
+ int _vWindowLinesTall;
+ bool _screenChangeFlag;
+public:
+ virtual void copyBlock(ASurface *src, const Common::Rect &bounds);
+
+ virtual void restoreBlock();
+
+ virtual void drawRect();
+
+ virtual void transCopyFrom(ASurface *src, const Common::Point &destPos);
+
+ virtual void transCopyFrom(ASurface *src, const Common::Rect &bounds);
+
+ virtual void copyFrom(Graphics::Surface &src);
+
+ virtual void copyBuffer(Graphics::Surface *src);
+
+ virtual void addDirtyRect(const Common::Rect &r);
+public:
+ Screen(AccessEngine *vm);
+
+ virtual ~Screen() {}
+
+ void setDisplayScan();
+
+ void setPanel(int num);
+
+ /**
+ * Update the underlying screen
+ */
+ void updateScreen();
+
+ /**
+ * Fade out screen
+ */
+ void forceFadeOut();
+
+ /**
+ * Fade in screen
+ */
+ void forceFadeIn();
+
+ void fadeOut() { forceFadeOut(); }
+ void fadeIn() { forceFadeIn(); }
+ void clearScreen();
+
+ /**
+ * Set the initial palette
+ */
+ void setInitialPalettte();
+
+ /**
+ * Set icon palette
+ */
+ void setIconPalette() {}
+
+ void loadPalette(int fileNum, int subfile);
+
+ void setPalette();
+
+ void loadRawPalette(Common::SeekableReadStream *stream);
+
+ void savePalette();
+
+ void restorePalette();
+
+ void getPalette(byte *pal);
+
+ /**
+ * Copy a buffer to the screen
+ */
+ void copyBuffer(const byte *data);
+
+ void setBufferScan();
+
+ void setScaleTable(int scale);
+
+ /**
+ * Save all the screen display state variables
+ */
+ void saveScreen();
+
+ /**
+ * Restores previously saved screen display state variables
+ */
+ void restoreScreen();
+
+ void setPaletteCycle(int startCycle, int endCycle, int timer);
+
+ void cyclePaletteForward();
+
+ void cyclePaletteBackwards();
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_SCREEN_H */
diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp
new file mode 100644
index 0000000000..2e22d9a2ce
--- /dev/null
+++ b/engines/access/scripts.cpp
@@ -0,0 +1,885 @@
+/* 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 "access/access.h"
+#include "access/resources.h"
+#include "access/scripts.h"
+
+namespace Access {
+
+Scripts::Scripts(AccessEngine *vm) : Manager(vm) {
+ _resource = nullptr;
+ _data = nullptr;
+ _sequence = 0;
+ _endFlag = false;
+ _returnCode = 0;
+ _choice = 0;
+ _choiceStart = 0;
+ _charsOrg = Common::Point(0, 0);
+ _texsOrg = Common::Point(0, 0);
+}
+
+Scripts::~Scripts() {
+ freeScriptData();
+}
+
+void Scripts::setScript(Resource *res, bool restartFlag) {
+ _resource = res;
+ _data = res->_stream;
+ _endFlag = restartFlag;
+}
+
+void Scripts::freeScriptData() {
+ delete _resource;
+ _resource = nullptr;
+ _data = nullptr;
+}
+
+void Scripts::searchForSequence() {
+ assert(_data);
+
+ _data->seek(0);
+ int sequenceId;
+ do {
+ while (_data->readByte() != SCRIPT_START_BYTE) ;
+ sequenceId = _data->readUint16LE();
+ } while (sequenceId != _sequence);
+}
+
+void Scripts::charLoop() {
+ bool endFlag = _endFlag;
+ int pos = _data->pos();
+
+ _sequence = 2000;
+ searchForSequence();
+ _vm->_images.clear();
+ _vm->_buffer2.copyFrom(_vm->_buffer1);
+ _vm->_newRects.clear();
+
+ executeScript();
+ _vm->plotList1();
+ _vm->copyBlocks();
+
+ _data->seek(pos);
+ _endFlag = endFlag;
+}
+
+void Scripts::findNull() {
+ // No implementation required in ScummVM, the strings in the script files are already skipped by the use of readByte()
+}
+
+int Scripts::executeScript() {
+ assert(_data);
+ _endFlag = false;
+ _returnCode = 0;
+
+ do {
+ // Get next command, skipping over script start start if it's being pointed to
+ while ((_scriptCommand = _data->readByte()) == SCRIPT_START_BYTE)
+ _data->skip(2);
+
+ if (_scriptCommand < 0x80)
+ error("Unexpected opcode value %d", _scriptCommand);
+
+ executeCommand(_scriptCommand - 0x80);
+ } while (!_endFlag && !_vm->shouldQuitOrRestart());
+
+ return _returnCode;
+}
+
+typedef void(Scripts::*ScriptMethodPtr)();
+
+void Scripts::executeCommand(int commandIndex) {
+ static const ScriptMethodPtr COMMAND_LIST[] = {
+ &Scripts::cmdObject, &Scripts::cmdEndObject, &Scripts::cmdJumpLook,
+ &Scripts::cmdJumpHelp, &Scripts::cmdJumpGet, &Scripts::cmdJumpMove,
+ &Scripts::cmdJumpUse, &Scripts::cmdJumpTalk, &Scripts::cmdNull,
+ &Scripts::cmdPrint, &Scripts::cmdRetPos, &Scripts::cmdAnim,
+ &Scripts::cmdSetFlag, &Scripts::cmdCheckFlag, &Scripts::cmdGoto,
+ &Scripts::cmdAddScore, &Scripts::cmdSetInventory, &Scripts::cmdCheckInventory,
+ &Scripts::cmdSetTex, &Scripts::cmdNewRoom, &Scripts::cmdConverse,
+ &Scripts::cmdCheckFrame, &Scripts::cmdCheckAnim, &Scripts::cmdSnd,
+ &Scripts::cmdRetNeg, &Scripts::cmdRetPos, &Scripts::cmdCheckLoc,
+ &Scripts::cmdSetAnim, &Scripts::cmdDispInv, &Scripts::cmdSetAbout,
+ &Scripts::cmdSetTimer, &Scripts::cmdCheckTimer, &Scripts::cmdSetTravel,
+ &Scripts::cmdJumpGoto, &Scripts::cmdSetVideo, &Scripts::cmdPlayVideo,
+ &Scripts::cmdPlotImage, &Scripts::cmdSetDisplay, &Scripts::cmdSetBuffer,
+ &Scripts::cmdSetScroll, &Scripts::cmdSaveRect, &Scripts::cmdVideoEnded,
+ &Scripts::cmdSetBufVid, &Scripts::cmdPlayBufVid, &Scripts::cmdRemoveLast,
+ &Scripts::cmdDoTravel, &Scripts::cmdCheckAbout, &Scripts::cmdSpecial,
+ &Scripts::cmdSetCycle, &Scripts::cmdCycle, &Scripts::cmdCharSpeak,
+ &Scripts::cmdTexSpeak, &Scripts::cmdTexChoice, &Scripts::cmdWait,
+ &Scripts::cmdSetConPos, &Scripts::cmdCheckVFrame, &Scripts::cmdJumpChoice,
+ &Scripts::cmdReturnChoice, &Scripts::cmdClearBlock, &Scripts::cmdLoadSound,
+ &Scripts::cmdFreeSound, &Scripts::cmdSetVideoSound, &Scripts::cmdPlayVideoSound,
+ &Scripts::cmdPrintWatch, &Scripts::cmdDispAbout, &Scripts::cmdPushLocation,
+ &Scripts::cmdCheckTravel, &Scripts::cmdBlock, &Scripts::cmdPlayerOff,
+ &Scripts::cmdPlayerOn, &Scripts::cmdDead, &Scripts::cmdFadeOut,
+ &Scripts::cmdEndVideo
+ };
+
+ (this->*COMMAND_LIST[commandIndex])();
+}
+
+void Scripts::cmdObject() {
+ _vm->_bubbleBox->load(_data);
+}
+
+void Scripts::cmdEndObject() {
+ printString(GENERAL_MESSAGES[_vm->_room->_selectCommand]);
+}
+
+void Scripts::cmdJumpLook() {
+ if (_vm->_room->_selectCommand == 0)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdJumpHelp() {
+ if (_vm->_room->_selectCommand == 8)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdJumpGet() {
+ if (_vm->_room->_selectCommand == 3)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdJumpMove() {
+ if (_vm->_room->_selectCommand == 2)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdJumpUse() {
+ if (_vm->_room->_selectCommand == 4)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdJumpTalk() {
+ if (_vm->_room->_selectCommand == 6)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdNull() {
+}
+
+#define PRINT_TIMER 25
+
+void Scripts::cmdPrint() {
+ // Get a text line for display
+ Common::String msg = readString();
+ printString(msg);
+}
+
+void Scripts::printString(const Common::String &msg) {
+ _vm->_screen->_printOrg = Common::Point(20, 42);
+ _vm->_screen->_printStart = Common::Point(20, 42);
+ _vm->_timers[PRINT_TIMER]._timer = 50;
+ _vm->_timers[PRINT_TIMER]._initTm = 50;
+ ++_vm->_timers[PRINT_TIMER]._flag;
+
+ // Display the text in a bubble, and wait for a keypress or mouse click
+ _vm->_bubbleBox->placeBubble(msg);
+ _vm->_events->waitKeyMouse();
+
+ // Wait until the bubble display is expired
+ while (!_vm->shouldQuit() && _vm->_timers[PRINT_TIMER]._flag) {
+ _vm->_events->pollEvents();
+ }
+
+ // Restore the original screen over the text bubble
+ _vm->_screen->restoreBlock();
+}
+
+Common::String Scripts::readString() {
+ Common::String msg;
+ byte c;
+ while ((c = (char)_data->readByte()) != '\0')
+ msg += c;
+
+ return msg;
+}
+
+void Scripts::cmdRetPos() {
+ _endFlag = true;
+ _returnCode = 0;
+}
+
+void Scripts::cmdAnim() {
+ int animId = _data->readByte();
+ _vm->_animation->animate(animId);
+}
+
+void Scripts::cmdSetFlag() {
+ int flagNum = _data->readByte();
+ byte flagVal = _data->readByte();
+ assert(flagNum < 256);
+
+ _vm->_flags[flagNum] = flagVal;
+}
+
+void Scripts::cmdCheckFlag() {
+ int flagNum = _data->readUint16LE();
+ int flagVal = _data->readUint16LE();
+ assert(flagNum < 256);
+
+ if (_vm->_flags[flagNum] == flagVal)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdGoto() {
+ _sequence = _data->readUint16LE();
+ searchForSequence();
+}
+
+void Scripts::cmdAddScore() {
+ if (!_vm->isDemo()) {
+ cmdSetInventory();
+ return;
+ }
+
+ _data->skip(1);
+}
+
+void Scripts::cmdSetInventory() {
+ int itemId = _data->readByte();
+ int itemVal = _data->readByte();
+
+ (*_vm->_inventory)[itemId] = itemVal;
+ _vm->_inventory->_startInvItem = 0;
+ _vm->_inventory->_startInvBox = 0;
+ _vm->_inventory->_invChangeFlag = true;
+}
+
+void Scripts::cmdCheckInventory() {
+ int itemId = _data->readUint16LE();
+ int itemVal = _data->readUint16LE();
+
+ if ((*_vm->_inventory)[itemId] == itemVal)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdSetTex() {
+ _vm->_player->_playerDirection = RIGHT;
+ int posX = _data->readSint16LE() - (_vm->_player->_playerOffset.x / 2);
+ if (posX <= _vm->_player->_rawPlayer.x)
+ _vm->_player->_playerDirection = LEFT;
+
+ _vm->_player->_rawPlayer.x = posX;
+ _vm->_player->checkScroll();
+ bool scrlTemp = _vm->_player->_scrollFlag;
+
+ _vm->_player->_playerDirection = UP;
+ int posY = _data->readSint16LE();
+ if (posY <= _vm->_player->_rawPlayer.y)
+ _vm->_player->_playerDirection = DOWN;
+
+ _vm->_player->_rawPlayer.y = posY;
+ _vm->_player->_frame = 5;
+ _vm->_player->checkScroll();
+
+ _vm->_player->_scrollFlag |= scrlTemp;
+
+ _vm->_player->_position = Common::Point(_vm->_player->_rawPlayer.x, _vm->_player->_rawPlayer.y - _vm->_player->_playerOffset.y);
+ _vm->_player->_offsetY = _vm->_player->_playerOffset.y;
+ _vm->_player->_spritesPtr = _vm->_player->_playerSprites;
+ _vm->_player->_frameNumber = _vm->_player->_frame;
+
+ _vm->_room->setWallCodes();
+}
+
+#define CURRENT_ROOM 0xFF
+
+void Scripts::cmdNewRoom() {
+ int roomNumber = _data->readByte();
+ if (roomNumber != CURRENT_ROOM)
+ _vm->_player->_roomNumber = roomNumber;
+
+ _vm->_room->_function = FN_CLEAR1;
+ _vm->freeChar();
+ _vm->_converseMode = 0;
+ cmdRetPos();
+}
+
+void Scripts::cmdConverse() {
+ _vm->_conversation = _data->readUint16LE();
+ _vm->_room->clearRoom();
+ _vm->freeChar();
+ _vm->_char->loadChar(_vm->_conversation);
+ _vm->_events->setCursor(CURSOR_ARROW);
+
+ _vm->_images.clear();
+ _vm->_oldRects.clear();
+ _sequence = 0;
+ searchForSequence();
+
+ if (_vm->_screen->_vesaMode) {
+ _vm->_converseMode = 1;
+ }
+}
+
+void Scripts::cmdCheckFrame() {
+ int id = _data->readUint16LE();
+ Animation *anim = _vm->_animation->findAnimation(id);
+
+ int frame = _data->readUint16LE();
+ if (anim->_frameNumber == frame)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdCheckAnim() {
+ int id = _data->readUint16LE();
+ Animation *anim = _vm->_animation->findAnimation(id);
+
+ if (anim->_currentLoopCount == -1)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdSnd() {
+ int id = _data->readByte();
+ _vm->_sound->playSound(id);
+}
+
+void Scripts::cmdRetNeg() {
+ _endFlag = true;
+ _returnCode = -1;
+}
+
+void Scripts::cmdCheckLoc() {
+ int minX = _data->readUint16LE();
+ int minY = _data->readUint16LE();
+ int maxX = _data->readUint16LE();
+ int maxY = _data->readUint16LE();
+
+ int curX = _vm->_player->_rawPlayer.x + _vm->_player->_playerOffset.x;
+ int curY = _vm->_player->_rawPlayer.y;
+
+ if ((curX >= minX) && (curX <= maxX) && (curY >= minY) && (curY <= maxY))
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdSetAnim() {
+ int animId = _data->readByte();
+ Animation *anim = _vm->_animation->setAnimation(animId);
+
+ if (anim)
+ _vm->_animation->setAnimTimer(anim);
+}
+
+void Scripts::cmdDispInv() {
+ _vm->_inventory->newDisplayInv();
+}
+
+void Scripts::cmdSetAbout() {
+ if (!_vm->isDemo()) {
+ cmdSetTimer();
+ return;
+ }
+
+ error("TODO: DEMO - cmdSetAbout");
+}
+
+void Scripts::cmdSetTimer() {
+ int idx = _data->readUint16LE();
+ int val = _data->readUint16LE();
+
+ ++_vm->_timers[idx]._flag;
+ _vm->_timers[idx]._timer = val;
+ _vm->_timers[idx]._initTm = val;
+
+ _vm->_events->debounceLeft();
+ _vm->_events->zeroKeys();
+}
+
+void Scripts::cmdCheckTimer() {
+ int idx = _data->readUint16LE();
+
+ _vm->_canSaveLoad = true;
+ _vm->_events->pollEvents();
+ _vm->_canSaveLoad = false;
+
+ // Since the ScummVM debugger can be launched from the above point, we need
+ // to check whether the script needs to be ended here, since some commands,
+ // like the scene command, can change the current script
+ if (_endFlag)
+ return;
+
+ if ((idx == 9) && _vm->_events->isKeyPending()) {
+ _vm->_events->zeroKeys();
+ _vm->_timers[9]._timer = 0;
+ _vm->_timers[9]._flag = 0;
+ }
+
+ int val = _data->readUint16LE() & 0xFF;
+ if (_vm->_timers[idx]._flag == val)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdSetTravel() {
+ if (!_vm->isDemo()) {
+ cmdJumpGoto();
+ return;
+ }
+ error("TODO: DEMO - cmdSetTravel");
+}
+
+void Scripts::cmdJumpGoto() {
+ if (_vm->_room->_selectCommand == 5)
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdSetVideo() {
+ Common::Point pt;
+ pt.x = _data->readSint16LE();
+ pt.y = _data->readSint16LE();
+ int cellIndex = _data->readUint16LE();
+ int rate = _data->readUint16LE();
+
+ _vm->_video->setVideo(_vm->_screen, pt, _vm->_extraCells[cellIndex]._vid, rate);
+}
+
+void Scripts::cmdPlayVideo() {
+ _vm->_video->playVideo();
+}
+
+void Scripts::cmdPlotImage() {
+ _vm->_destIn = _vm->_current;
+
+ int destX = _data->readUint16LE();
+ int destY = _data->readUint16LE();
+ int objId = _data->readUint16LE();
+ int imgId = _data->readUint16LE();
+
+ _vm->_screen->plotImage(_vm->_objectsTable[objId], imgId, Common::Point(destX, destY));
+}
+
+void Scripts::cmdSetDisplay() {
+ _vm->_screen->setDisplayScan();
+ _vm->_current = _vm->_screen;
+}
+
+void Scripts::cmdSetBuffer() {
+ _vm->_current = &_vm->_buffer2;
+}
+
+void Scripts::cmdSetScroll() {
+ _vm->_scrollCol = _data->readUint16LE();
+ _vm->_scrollRow = _data->readUint16LE();
+ _vm->_scrollX = 0;
+ _vm->_scrollY = 0;
+}
+
+void Scripts::cmdSaveRect() {
+ if (!_vm->isDemo()) {
+ cmdVideoEnded();
+ return;
+ }
+ error("TODO: DEMO - cmdSaveRect");
+}
+
+void Scripts::cmdVideoEnded() {
+ _vm->_events->pollEventsAndWait();
+
+ if (_vm->_video->_videoEnd) {
+ cmdGoto();
+ } else {
+ _data->skip(2);
+ }
+}
+
+void Scripts::cmdSetBufVid() {
+ _vm->_vidX = _data->readUint16LE();
+ _vm->_vidY = _data->readUint16LE();
+ int idx = _data->readUint16LE();
+ int rate = _data->readUint16LE();
+
+ _vm->_video->setVideo(&_vm->_vidBuf, Common::Point(0, 0), FileIdent(_vm->_extraCells[idx]._vid._fileNum, _vm->_extraCells[idx]._vid._subfile), rate);
+}
+
+void Scripts::cmdPlayBufVid() {
+ _vm->_video->playVideo();
+ _vm->_video->copyVideo();
+}
+
+void Scripts::cmdRemoveLast() {
+ --_vm->_numAnimTimers;
+}
+
+void Scripts::cmdDoTravel() {
+ if (!_vm->isDemo()) {
+ cmdSpecial();
+ return;
+ }
+ error("TODO: DEMO - cmdDoTravel");
+}
+
+void Scripts::cmdCheckAbout() {
+ if (!_vm->isDemo()) {
+ cmdSpecial();
+ return;
+ }
+ error("TODO: DEMO - cmdCheckAbout");
+}
+
+void Scripts::cmdSpecial() {
+ _specialFunction = _data->readUint16LE();
+ int p1 = _data->readUint16LE();
+ int p2 = _data->readUint16LE();
+
+ if (_specialFunction == 1) {
+ if (_vm->_establishTable[p2] == 1)
+ return;
+
+ _vm->_screen->savePalette();
+ }
+
+ executeSpecial(_specialFunction, p1, p2);
+
+ if (_specialFunction == 1) {
+ _vm->_screen->restorePalette();
+ _vm->_room->_function = FN_RELOAD;
+ }
+}
+
+void Scripts::cmdSetCycle() {
+ int startCycle = _data->readUint16LE();
+ int endCycle = _data->readUint16LE();
+ int timer = _data->readUint16LE();
+ _vm->_screen->setPaletteCycle(startCycle, endCycle, timer);
+}
+
+void Scripts::cmdCycle() {
+ if (_vm->_startup == -1)
+ _vm->_screen->cyclePaletteForward();
+}
+
+void Scripts::cmdCharSpeak() {
+ _vm->_screen->_printOrg = _charsOrg;
+ _vm->_screen->_printStart = _charsOrg;
+
+ byte v;
+ Common::String tmpStr = "";
+ while ((v = _data->readByte()) != 0)
+ tmpStr += (char)v;
+
+ _vm->_bubbleBox->placeBubble(tmpStr);
+ findNull();
+}
+
+void Scripts::cmdTexSpeak() {
+ _vm->_screen->_printOrg = _texsOrg;
+ _vm->_screen->_printStart = _texsOrg;
+ _vm->_screen->_maxChars = 20;
+
+ byte v;
+ Common::String tmpStr = "";
+ while ((v = _data->readByte()) != 0)
+ tmpStr += (char)v;
+
+ _vm->_bubbleBox->_bubbleDisplStr = Common::String("JASON");
+ _vm->_bubbleBox->placeBubble1(tmpStr);
+ findNull();
+}
+
+#define BTN_COUNT 6
+void Scripts::cmdTexChoice() {
+ static const int BTN_RANGES[BTN_COUNT][2] = {
+ { 0, 76 }, { 77, 154 }, { 155, 232 }, { 233, 276 }, { 0, 0 },
+ { 277, 319 }
+ };
+
+ _vm->_oldRects.clear();
+ _choiceStart = _data->pos() - 1;
+ _vm->_fonts._charSet._lo = 1;
+ _vm->_fonts._charSet._hi = 8;
+ _vm->_fonts._charFor._lo = 55;
+ _vm->_fonts._charFor._hi = 255;
+
+ _vm->_screen->_maxChars = 20;
+ _vm->_screen->_printOrg = _texsOrg;
+ _vm->_screen->_printStart = _texsOrg;
+
+ _vm->_bubbleBox->clearBubbles();
+ _vm->_bubbleBox->_bubbleDisplStr = Common::String("RESPONSE 1");
+
+ byte v;
+ Common::String tmpStr = "";
+ while ((v = _data->readByte()) != 0)
+ tmpStr += (char)v;
+
+ _vm->_bubbleBox->calcBubble(tmpStr);
+ _vm->_bubbleBox->printBubble(tmpStr);
+
+ Common::Array<Common::Rect> responseCoords;
+ responseCoords.push_back(_vm->_bubbleBox->_bounds);
+ _vm->_screen->_printOrg.y = _vm->_bubbleBox->_bounds.bottom + 11;
+
+ findNull();
+
+ tmpStr.clear();
+ while ((v = _data->readByte()) != 0)
+ tmpStr += (char)v;
+
+ if (tmpStr.size() != 0) {
+ _vm->_bubbleBox->_bubbleDisplStr = Common::String("RESPONSE 2");
+ _vm->_bubbleBox->calcBubble(tmpStr);
+ _vm->_bubbleBox->printBubble(tmpStr);
+ responseCoords.push_back(_vm->_bubbleBox->_bounds);
+ _vm->_screen->_printOrg.y = _vm->_bubbleBox->_bounds.bottom + 11;
+ }
+
+ findNull();
+
+ bool choice3Fl = false;
+ tmpStr.clear();
+ while ((v = _data->readByte()) != 0)
+ tmpStr += (char)v;
+
+ if (tmpStr.size() != 0) {
+ _vm->_bubbleBox->_bubbleDisplStr = Common::String("RESPONSE 3");
+ _vm->_bubbleBox->calcBubble(tmpStr);
+ _vm->_bubbleBox->printBubble(tmpStr);
+ responseCoords.push_back(_vm->_bubbleBox->_bounds);
+ _vm->_screen->_printOrg.y = _vm->_bubbleBox->_bounds.bottom + 11;
+ }
+
+ findNull();
+
+ int choice = -1;
+ do {
+ _vm->_events->pollEvents();
+ if (_vm->shouldQuit())
+ return;
+
+ charLoop();
+
+ _vm->_bubbleBox->_bubbleDisplStr = _vm->_bubbleBox->_bubbleTitle;
+ if (_vm->_events->_leftButton) {
+ if (_vm->_events->_mouseRow >= 22) {
+ _vm->_events->debounceLeft();
+ int x = _vm->_events->_mousePos.x;
+ for (int i = 0; i < BTN_COUNT; i++) {
+ if ((x >= BTN_RANGES[i][0]) && (x < BTN_RANGES[i][1])) {
+ choice = i;
+ break;
+ }
+ }
+ } else {
+ _vm->_events->debounceLeft();
+ choice = _vm->_events->checkMouseBox1(responseCoords);
+ }
+ }
+ } while ((choice == -1) || ((choice == 2) && choice3Fl));
+
+ _choice = choice + 1;
+ _vm->_bubbleBox->clearBubbles();
+}
+
+void Scripts::cmdWait() {
+ int time = _data->readSint16LE();
+ _vm->_timers[3]._timer = time;
+ _vm->_timers[3]._initTm = time;
+ _vm->_timers[3]._flag++;
+ _vm->_events->zeroKeys();
+
+ while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() &&
+ _vm->_timers[3]._flag) {
+ _vm->_midi->midiRepeat();
+ charLoop();
+
+ _vm->_events->pollEventsAndWait();
+ }
+
+ _vm->_events->debounceLeft();
+ _vm->_events->zeroKeys();
+}
+
+void Scripts::cmdSetConPos() {
+ int x = _data->readSint16LE();
+ int y = _data->readSint16LE();
+ _charsOrg = Common::Point(x, y);
+
+ x = _data->readSint16LE();
+ y = _data->readSint16LE();
+ _texsOrg = Common::Point(x, y);
+}
+
+void Scripts::cmdCheckVFrame() {
+ if (_vm->_video->_videoFrame == _data->readSint16LE())
+ cmdGoto();
+ else
+ _data->skip(2);
+}
+
+void Scripts::cmdJumpChoice() {
+ int val = (_data->readUint16LE() & 0xFF);
+
+ if (val == _choice) {
+ _sequence = _data->readUint16LE();
+ searchForSequence();
+ } else
+ _data->skip(2);
+}
+
+void Scripts::cmdReturnChoice() {
+ _data->seek(_choiceStart);
+}
+
+void Scripts::cmdClearBlock() {
+ _vm->_screen->restoreBlock();
+}
+
+void Scripts::cmdLoadSound() {
+ int idx = _data->readSint16LE();
+
+ _vm->_sound->_soundTable.clear();
+ Resource *sound = _vm->_files->loadFile(_vm->_extraCells[idx]._vidSound);
+ _vm->_sound->_soundTable.push_back(SoundEntry(sound, 1));
+}
+
+void Scripts::cmdFreeSound() {
+ SoundManager &sound = *_vm->_sound;
+
+ if (sound._soundTable.size() > 0 && sound._soundTable[0]._res) {
+ // Keep doing char display loop if playing sound for it
+ do {
+ if (_vm->_flags[236] == 1)
+ charLoop();
+
+ _vm->_events->pollEvents();
+ } while (!_vm->shouldQuit() && sound._playingSound);
+
+ // Free the sounds
+ while (sound._soundTable.size() > 0) {
+ delete sound._soundTable[0]._res;
+ sound._soundTable.remove_at(0);
+ }
+ }
+}
+
+void Scripts::cmdSetVideoSound() {
+ uint32 startPos = _data->pos();
+ _data->skip(4);
+ cmdLoadSound();
+ _data->seek(startPos);
+ cmdSetVideo();
+
+ _vm->_video->_soundFrame = _data->readUint16LE();
+ _vm->_video->_soundFlag = false;
+}
+
+void Scripts::cmdPlayVideoSound() {
+ _vm->_video->playVideo();
+ if (_vm->_video->_soundFrame == _vm->_video->_videoFrame &&
+ !_vm->_video->_soundFlag) {
+ _vm->_sound->playSound(0);
+ _vm->_video->_soundFlag = true;
+ }
+
+ _vm->_events->pollEventsAndWait();
+}
+
+void Scripts::cmdPrintWatch() {
+ if (!_vm->isDemo()) {
+ cmdPushLocation();
+ return;
+ }
+ error("TODO: DEMO - cmdPrintWatch");
+}
+
+void Scripts::cmdDispAbout() {
+ if (!_vm->isDemo()) {
+ cmdPushLocation();
+ return;
+ }
+ error("TODO: DEMO - cmdDispAbout");
+}
+
+void Scripts::cmdPushLocation() {
+ error("TODO cmdPushLocation");
+}
+
+void Scripts::cmdCheckTravel() {
+ if (!_vm->isDemo()) {
+ cmdPushLocation();
+ return;
+ }
+ error("TODO: DEMO - cmdCheckTravel");
+}
+
+void Scripts::cmdBlock() {
+ if (!_vm->isDemo()) {
+ cmdPushLocation();
+ return;
+ }
+ error("TODO: DEMO - cmdBlock");
+}
+
+void Scripts::cmdPlayerOff() {
+ _vm->_player->_playerOff = true;
+}
+
+void Scripts::cmdPlayerOn() {
+ _vm->_player->_playerOff = false;
+}
+
+void Scripts::cmdDead() {
+ int deathId = _data->readByte();
+ _vm->dead(deathId);
+}
+
+void Scripts::cmdFadeOut() {
+ _vm->_screen->forceFadeOut();
+}
+
+void Scripts::cmdEndVideo() {
+ _vm->_video->closeVideo();
+ _vm->_video->_videoEnd = true;
+}
+
+} // End of namespace Access
diff --git a/engines/access/scripts.h b/engines/access/scripts.h
new file mode 100644
index 0000000000..cfadf6d901
--- /dev/null
+++ b/engines/access/scripts.h
@@ -0,0 +1,168 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ACCESS_SCRIPTS_H
+#define ACCESS_SCRIPTS_H
+
+#include "common/scummsys.h"
+#include "common/memstream.h"
+#include "access/data.h"
+
+namespace Access {
+
+class AccessEngine;
+class Scripts;
+
+#define SCRIPT_START_BYTE 0xE0
+#define ROOM_SCRIPT 2000
+
+class Scripts : public Manager {
+private:
+ Resource *_resource;
+ int _specialFunction;
+
+ void charLoop();
+protected:
+ Common::SeekableReadStream *_data;
+
+ virtual void executeSpecial(int commandIndex, int param1, int param2) = 0;
+ virtual void executeCommand(int commandIndex);
+
+ /**
+ * Read a null terminated string from the script
+ */
+ Common::String readString();
+
+ void cmdObject();
+ void cmdEndObject();
+ void cmdJumpLook();
+ void cmdJumpHelp();
+ void cmdJumpGet();
+ void cmdJumpMove();
+ void cmdJumpUse();
+ void cmdJumpTalk();
+ void cmdNull();
+ void cmdPrint();
+ void cmdAnim();
+ void cmdSetFlag();
+ void cmdCheckFlag();
+
+ /**
+ * Jump to another script
+ */
+ void cmdGoto();
+
+ void cmdAddScore();
+ void cmdSetInventory();
+ void cmdCheckInventory();
+ void cmdSetTex();
+ void cmdNewRoom();
+ void cmdConverse();
+ void cmdCheckFrame();
+ void cmdCheckAnim();
+ void cmdSnd();
+ void cmdRetNeg();
+ void cmdCheckLoc();
+ void cmdSetAnim();
+ void cmdDispInv();
+ void cmdSetAbout();
+ void cmdSetTimer();
+ void cmdCheckTimer();
+ void cmdJumpGoto();
+ void cmdSetTravel();
+ void cmdSetVideo();
+ void cmdPlayVideo();
+ void cmdPlotImage();
+ void cmdSetDisplay();
+ void cmdSetBuffer();
+ void cmdSetScroll();
+ void cmdSaveRect();
+ void cmdVideoEnded();
+ void cmdSetBufVid();
+ void cmdPlayBufVid();
+ void cmdRemoveLast();
+ void cmdDoTravel();
+ void cmdCheckAbout();
+ void cmdSpecial();
+ void cmdSetCycle();
+ void cmdCycle();
+ void cmdCharSpeak();
+ void cmdTexSpeak();
+ void cmdTexChoice();
+ void cmdWait();
+ void cmdSetConPos();
+ void cmdCheckVFrame();
+ void cmdJumpChoice();
+ void cmdReturnChoice();
+ void cmdClearBlock();
+ void cmdLoadSound();
+ void cmdSetVideoSound();
+ void cmdPlayVideoSound();
+ void cmdPrintWatch();
+ void cmdDispAbout();
+ void cmdPushLocation();
+ void cmdCheckTravel();
+ void cmdBlock();
+ void cmdPlayerOff();
+ void cmdPlayerOn();
+ void cmdDead();
+ void cmdFadeOut();
+ void cmdEndVideo();
+ void cmdHelp();
+ void cmdCycleBack();
+ void cmdSetHelp();
+public:
+ int _sequence;
+ bool _endFlag;
+ int _returnCode;
+ int _scriptCommand;
+ int _choice;
+ int32 _choiceStart;
+ Common::Point _charsOrg, _texsOrg;
+public:
+ Scripts(AccessEngine *vm);
+
+ virtual ~Scripts();
+
+ void setScript(Resource *data, bool restartFlag = false);
+
+ void freeScriptData();
+
+ void searchForSequence();
+
+ int executeScript();
+
+ void findNull();
+
+ /**
+ * Print a given message to the screen in a bubble box
+ */
+ void printString(const Common::String &msg);
+
+ // Script commands that need to be public
+ void cmdFreeSound();
+ void cmdRetPos();
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_SCRIPTS_H */
diff --git a/engines/access/sound.cpp b/engines/access/sound.cpp
new file mode 100644
index 0000000000..a7d96dac9a
--- /dev/null
+++ b/engines/access/sound.cpp
@@ -0,0 +1,310 @@
+/* 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/algorithm.h"
+#include "audio/mixer.h"
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "audio/decoders/wave.h"
+#include "access/access.h"
+#include "access/sound.h"
+
+namespace Access {
+
+SoundManager::SoundManager(AccessEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
+ _playingSound = false;
+ _isVoice = false;
+}
+
+SoundManager::~SoundManager() {
+ clearSounds();
+}
+
+void SoundManager::clearSounds() {
+ debugC(1, kDebugSound, "clearSounds()");
+
+ for (uint i = 0; i < _soundTable.size(); ++i)
+ delete _soundTable[i]._res;
+ _soundTable.clear();
+}
+
+void SoundManager::queueSound(int idx, int fileNum, int subfile) {
+ debugC(1, kDebugSound, "queueSound(%d, %d, %d)", idx, fileNum, subfile);
+
+ Resource *soundResource;
+
+ if (idx >= (int)_soundTable.size())
+ _soundTable.resize(idx + 1);
+
+ delete _soundTable[idx]._res;
+ soundResource = _vm->_files->loadFile(fileNum, subfile);
+ _soundTable[idx]._res = soundResource;
+ _soundTable[idx]._priority = 1;
+}
+
+Resource *SoundManager::loadSound(int fileNum, int subfile) {
+ debugC(1, kDebugSound, "loadSound(%d, %d)", fileNum, subfile);
+ return _vm->_files->loadFile(fileNum, subfile);
+}
+
+void SoundManager::playSound(int soundIndex) {
+ debugC(1, kDebugSound, "playSound(%d)", soundIndex);
+
+ int priority = _soundTable[soundIndex]._priority;
+ playSound(_soundTable[soundIndex]._res, priority);
+}
+
+void SoundManager::playSound(Resource *res, int priority) {
+ debugC(1, kDebugSound, "playSound");
+
+ byte *resourceData = res->data();
+ Audio::SoundHandle audioHandle;
+ Audio::RewindableAudioStream *audioStream = 0;
+
+ assert(res->_size >= 32);
+
+ // HACK: Simulates queueing for the rare sounds played one after the other
+ while (_mixer->hasActiveChannelOfType(Audio::Mixer::kSFXSoundType))
+ ;
+
+ if (READ_BE_UINT32(resourceData) == MKTAG('R','I','F','F')) {
+ // CD version uses WAVE-files
+ Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(resourceData, res->_size, DisposeAfterUse::NO);
+ audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES);
+
+ } else if (READ_BE_UINT32(resourceData) == MKTAG('S', 'T', 'E', 'V')) {
+ // sound files have a fixed header of 32 bytes in total
+ // header content:
+ // "STEVE" - fixed header
+ // byte - sample rate
+ // 01h mapped internally to 3Ch
+ // 02h mapped internally to 78h
+ // 03h mapped internally to B5h
+ // 04h mapped internally to F1h
+ // byte - unknown
+ // word - actual sample size (should be resource-size - 32)
+ byte internalSampleRate = resourceData[5];
+ int sampleSize = READ_LE_UINT16(resourceData + 7);
+
+ assert( (sampleSize + 32) == res->_size);
+
+ int sampleRate = 0;
+ switch (internalSampleRate) {
+ case 1: // NEG(3Ch) -> C4h time constant
+ sampleRate = 16666;
+ break;
+
+ case 2: // NEG(78h) -> 88h time constant
+ sampleRate = 8334;
+ break;
+
+ case 3: // NEG(B5h) -> 4Bh time constant
+ sampleRate = 5525;
+ break;
+
+ case 4: // NEG(F1h) -> 0Fh time constant
+ sampleRate = 4150;
+ break;
+
+ default:
+ error("Unexpected internal Sample Rate %d", internalSampleRate);
+ return;
+ }
+
+ audioStream = Audio::makeRawStream(resourceData + 32, sampleSize, sampleRate, 0);
+
+ } else
+ error("Unknown format");
+
+ audioHandle = Audio::SoundHandle();
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &audioHandle,
+ audioStream, -1, _mixer->kMaxChannelVolume, 0,
+ DisposeAfterUse::NO);
+
+ /*
+ Audio::QueuingAudioStream *audioStream = Audio::makeQueuingAudioStream(22050, false);
+ audioStream->queueBuffer(data, size, DisposeAfterUse::YES, 0);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, audioStream, -1,
+ Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, false);
+ */
+}
+
+void SoundManager::loadSounds(Common::Array<RoomInfo::SoundIdent> &sounds) {
+ debugC(1, kDebugSound, "loadSounds");
+
+ clearSounds();
+
+ for (uint i = 0; i < sounds.size(); ++i) {
+ Resource *sound = loadSound(sounds[i]._fileNum, sounds[i]._subfile);
+ _soundTable.push_back(SoundEntry(sound, sounds[i]._priority));
+ }
+}
+
+void SoundManager::stopSound() {
+ debugC(3, kDebugSound, "stopSound");
+
+ _mixer->stopHandle(Audio::SoundHandle());
+}
+
+void SoundManager::freeSounds() {
+ debugC(3, kDebugSound, "freeSounds");
+
+ stopSound();
+ clearSounds();
+}
+
+/******************************************************************************************/
+
+MusicManager::MusicManager(AccessEngine *vm) : _vm(vm) {
+ _music = nullptr;
+ _tempMusic = nullptr;
+ _isLooping = false;
+
+ MidiPlayer::createDriver();
+ MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+
+ int retValue = _driver->open();
+ if (retValue == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+MusicManager::~MusicManager() {
+ delete _music;
+ delete _tempMusic;
+}
+
+void MusicManager::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicManager::midiPlay() {
+ debugC(1, kDebugSound, "midiPlay");
+
+ if (_music->_size < 4) {
+ error("midiPlay() wrong music resource size");
+ }
+
+ stop();
+
+ if (READ_BE_UINT32(_music->data()) != MKTAG('F', 'O', 'R', 'M')) {
+ warning("midiPlay() Unexpected signature");
+ _isPlaying = false;
+ } else {
+ _parser = MidiParser::createParser_XMIDI();
+
+ if (!_parser->loadMusic(_music->data(), _music->_size))
+ error("midiPlay() wrong music resource");
+
+ _parser->setTrack(0);
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+ _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
+
+ // Handle music looping
+ _parser->property(MidiParser::mpAutoLoop, _isLooping);
+
+ setVolume(127);
+ _isPlaying = true;
+ }
+}
+
+bool MusicManager::checkMidiDone() {
+ debugC(1, kDebugSound, "checkMidiDone");
+ return (!_isPlaying);
+}
+
+void MusicManager::midiRepeat() {
+ debugC(1, kDebugSound, "midiRepeat");
+
+ if (!_parser)
+ return;
+
+ _isLooping = true;
+ _parser->property(MidiParser::mpAutoLoop, _isLooping);
+ if (!_isPlaying)
+ _parser->setTrack(0);
+}
+
+void MusicManager::stopSong() {
+ debugC(1, kDebugSound, "stopSong");
+
+ stop();
+}
+
+void MusicManager::loadMusic(int fileNum, int subfile) {
+ debugC(1, kDebugSound, "loadMusic(%d, %d)", fileNum, subfile);
+
+ _music = _vm->_files->loadFile(fileNum, subfile);
+}
+
+void MusicManager::loadMusic(FileIdent file) {
+ debugC(1, kDebugSound, "loadMusic(%d, %d)", file._fileNum, file._subfile);
+
+ _music = _vm->_files->loadFile(file);
+}
+
+void MusicManager::newMusic(int musicId, int mode) {
+ debugC(1, kDebugSound, "newMusic(%d, %d)", musicId, mode);
+
+ if (mode == 1) {
+ stopSong();
+ freeMusic();
+ _music = _tempMusic;
+ _tempMusic = nullptr;
+ _isLooping = true;
+ } else {
+ _isLooping = (mode == 2);
+ _tempMusic = _music;
+ stopSong();
+ loadMusic(97, musicId);
+ }
+
+ if (_music)
+ midiPlay();
+}
+
+void MusicManager::freeMusic() {
+ debugC(3, kDebugSound, "freeMusic");
+
+ delete _music;
+ _music = nullptr;
+}
+
+void MusicManager::setLoop(bool loop) {
+ debugC(3, kDebugSound, "setLoop");
+
+ _isLooping = loop;
+ if (_parser)
+ _parser->property(MidiParser::mpAutoLoop, _isLooping);
+}
+} // End of namespace Access
diff --git a/engines/access/sound.h b/engines/access/sound.h
new file mode 100644
index 0000000000..d0f4584fac
--- /dev/null
+++ b/engines/access/sound.h
@@ -0,0 +1,109 @@
+/* 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 ACCESS_SOUND_H
+#define ACCESS_SOUND_H
+
+#include "common/scummsys.h"
+#include "audio/mixer.h"
+#include "access/files.h"
+#include "audio/midiplayer.h"
+#include "audio/midiparser.h"
+
+#define MAX_SOUNDS 20
+
+namespace Access {
+
+class AccessEngine;
+
+struct SoundEntry {
+ Resource *_res;
+ int _priority;
+
+ SoundEntry() { _res = nullptr; _priority = 0; }
+ SoundEntry(Resource *res, int priority) { _res = res; _priority = priority; }
+};
+
+class SoundManager {
+private:
+ AccessEngine *_vm;
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _soundHandle;
+
+ void clearSounds();
+
+ void playSound(Resource *res, int priority);
+public:
+ Common::Array<SoundEntry> _soundTable;
+ bool _playingSound;
+ bool _isVoice;
+public:
+ SoundManager(AccessEngine *vm, Audio::Mixer *mixer);
+ ~SoundManager();
+
+ void queueSound(int idx, int fileNum, int subfile);
+
+ void playSound(int soundIndex);
+
+ Resource *loadSound(int fileNum, int subfile);
+ void loadSounds(Common::Array<RoomInfo::SoundIdent> &sounds);
+
+ void stopSound();
+ void freeSounds();
+};
+
+class MusicManager : public Audio::MidiPlayer {
+private:
+ AccessEngine *_vm;
+
+ Resource *_tempMusic;
+
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+
+public:
+ Resource *_music;
+
+public:
+ MusicManager(AccessEngine *vm);
+ ~MusicManager();
+
+ void midiPlay();
+
+ bool checkMidiDone();
+
+ void midiRepeat();
+
+ void stopSong();
+
+ void newMusic(int musicId, int mode);
+
+ void freeMusic();
+
+ void loadMusic(int fileNum, int subfile);
+ void loadMusic(FileIdent file);
+
+ void setLoop(bool loop);
+};
+} // End of namespace Access
+
+#endif /* ACCESS_SOUND_H*/
diff --git a/engines/access/video.cpp b/engines/access/video.cpp
new file mode 100644
index 0000000000..b7d5652e5b
--- /dev/null
+++ b/engines/access/video.cpp
@@ -0,0 +1,176 @@
+/* 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 "access/video.h"
+#include "access/access.h"
+
+namespace Access {
+
+VideoPlayer::VideoPlayer(AccessEngine *vm) : Manager(vm) {
+ _vidSurface = nullptr;
+ _videoFrame = 0;
+ _soundFlag = false;
+ _soundFrame = 0;
+ _videoData = nullptr;
+}
+
+VideoPlayer::~VideoPlayer() {
+ closeVideo();
+}
+
+
+void VideoPlayer::setVideo(ASurface *vidSurface, const Common::Point &pt, const FileIdent &videoFile, int rate) {
+ _vidSurface = vidSurface;
+ vidSurface->_orgX1 = pt.x;
+ vidSurface->_orgY1 = pt.y;
+ _vm->_timers[31]._timer = rate;
+ _vm->_timers[31]._initTm = rate;
+
+ // Open up video stream
+ _videoData = _vm->_files->loadFile(videoFile);
+
+ // Load in header
+ _header._frameCount = _videoData->_stream->readUint16LE();
+ _header._width = _videoData->_stream->readUint16LE();
+ _header._height = _videoData->_stream->readUint16LE();
+ _videoData->_stream->skip(1);
+ _header._flags = (VideoFlags)_videoData->_stream->readByte();
+
+ _startCoord = (byte *)vidSurface->getBasePtr(pt.x, pt.y);
+ _frameCount = _header._frameCount - 2;
+ _xCount = _header._width;
+ _scanCount = _header._height;
+ _videoFrame = 0;
+ _videoBounds = Common::Rect(pt.x, pt.y, pt.x + _header._width, pt.y + _header._height);
+
+ getFrame();
+
+ if (_header._flags == VIDEOFLAG_BG) {
+ // Draw the background
+ for (int y = 0; y < _scanCount; ++y) {
+ byte *pDest = (byte *)vidSurface->getBasePtr(pt.x, pt.y + y);
+ _videoData->_stream->read(pDest, _xCount);
+ }
+
+ if (vidSurface == _vm->_screen)
+ _vm->_newRects.push_back(Common::Rect(pt.x, pt.y, pt.x + _xCount, pt.y + _scanCount));
+
+ getFrame();
+ }
+
+ _videoEnd = false;
+}
+
+void VideoPlayer::closeVideo() {
+ delete _videoData;
+ _videoData = nullptr;
+}
+
+void VideoPlayer::getFrame() {
+ _frameSize = _videoData->_stream->readUint16LE();
+}
+
+void VideoPlayer::playVideo() {
+ if (_vm->_timers[31]._flag)
+ return;
+ ++_vm->_timers[31]._flag;
+
+ byte *pDest = _startCoord;
+ byte *pLine = _startCoord;
+ uint32 frameEnd = _videoData->_stream->pos() + _frameSize;
+
+ while ((uint32)_videoData->_stream->pos() < frameEnd) {
+ int count = _videoData->_stream->readByte();
+
+ if (count & 0x80) {
+ count &= 0x7f;
+
+ // Skip count number of pixels
+ // Loop across lines if necessary
+ while (count >= (pLine + _xCount - pDest)) {
+ count -= (pLine + _xCount - pDest);
+ pLine += _vidSurface->pitch;
+ pDest = pLine;
+ }
+
+ // Skip any remaining pixels in the new line
+ pDest += count;
+ } else {
+ // Read count number of pixels
+
+ // Load across lines if necessary
+ while (count >= (pLine + _xCount - pDest)) {
+ int lineCount = (pLine + _xCount - pDest);
+ _videoData->_stream->read(pDest, lineCount);
+ count -= lineCount;
+ pLine += _vidSurface->pitch;
+ pDest = pLine;
+ }
+
+ // Load remainder of pixels on line
+ if (count > 0) {
+ _videoData->_stream->read(pDest, count);
+ pDest += count;
+ }
+ }
+ }
+
+ // If the video is playing on the screen surface, add a dirty rect
+ if (_vidSurface == _vm->_screen)
+ _vm->_screen->addDirtyRect(_videoBounds);
+
+ getFrame();
+ if (++_videoFrame == _frameCount) {
+ closeVideo();
+ _videoEnd = true;
+ }
+}
+
+void VideoPlayer::copyVideo() {
+ _vm->_player->calcPlayer();
+
+ // Figure out the dirty rect area for the video frame
+ Common::Rect r = Common::Rect(_vm->_vidX - _vm->_screen->_bufferStart.x,
+ _vm->_vidY - _vm->_screen->_bufferStart.y,
+ _vm->_vidX - _vm->_screen->_bufferStart.x + _header._width,
+ _vm->_vidY - _vm->_screen->_bufferStart.y + _header._height);
+ if (!_vm->_screen->clip(r))
+ return;
+ _vm->_newRects.push_back(r);
+
+ int vh = _header._height;
+ int vw = _header._width;
+ int destIdx = _vm->_vidX - _vm->_screen->_bufferStart.x;
+ int srcIdx = _vm->_screen->_leftSkip;
+ for (int i = 0; i < _vm->_screen->_topSkip; i++)
+ destIdx += 160;
+
+ const byte *srcP = (const byte *)_vm->_vidBuf.getPixels() + srcIdx;
+ byte *destP = (byte *)_vm->_buffer2.getPixels() + destIdx;
+ for (int i = 0; i < vh; i++) {
+ Common::copy(srcP, srcP + vw, destP);
+ srcP += _vm->_vidBuf.pitch;
+ destP += _vm->_buffer2.pitch;
+ }
+}
+
+} // End of namespace Access
diff --git a/engines/access/video.h b/engines/access/video.h
new file mode 100644
index 0000000000..17825db367
--- /dev/null
+++ b/engines/access/video.h
@@ -0,0 +1,82 @@
+/* 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 ACCESS_VIDEO_H
+#define ACCESS_VIDEO_H
+
+#include "common/scummsys.h"
+#include "common/memstream.h"
+#include "access/data.h"
+#include "access/asurface.h"
+#include "access/files.h"
+
+namespace Access {
+
+enum VideoFlags { VIDEOFLAG_NONE = 0, VIDEOFLAG_BG = 1 };
+
+class VideoPlayer : public Manager {
+ struct VideoHeader {
+ int _frameCount;
+ int _width, _height;
+ VideoFlags _flags;
+ };
+private:
+ ASurface *_vidSurface;
+ Resource *_videoData;
+ VideoHeader _header;
+ byte *_startCoord;
+ int _frameCount;
+ int _xCount;
+ int _scanCount;
+ int _frameSize;
+ Common::Rect _videoBounds;
+
+ void getFrame();
+public:
+ int _videoFrame;
+ bool _soundFlag;
+ int _soundFrame;
+ bool _videoEnd;
+public:
+ VideoPlayer(AccessEngine *vm);
+ ~VideoPlayer();
+
+ /**
+ * Start up a video
+ */
+ void setVideo(ASurface *vidSurface, const Common::Point &pt, const FileIdent &videoFile, int rate);
+
+ /**
+ * Decodes a frame of the video
+ */
+ void playVideo();
+
+ void copyVideo();
+ /**
+ * Frees the data for a previously loaded video
+ */
+ void closeVideo();
+};
+
+} // End of namespace Access
+
+#endif /* ACCESS_VIDEO_H */