From 8c9420a8349b0cdb93dcace36c2bd5f93e03476f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 23 Feb 2014 19:33:26 -0500 Subject: [PATCH] MADS: Added game initialisation code --- engines/mads/dialogs.cpp | 9 +- engines/mads/events.cpp | 18 +++- engines/mads/events.h | 10 ++ engines/mads/game.cpp | 125 ++++++++++++++++++++++- engines/mads/game.h | 112 +++++++++++++++++++- engines/mads/module.mk | 1 + engines/mads/nebular/game_nebular.cpp | 142 +++++++++++++++++++++++++- engines/mads/nebular/game_nebular.h | 28 ++++- engines/mads/scene.cpp | 37 +++++++ engines/mads/scene.h | 44 ++++++++ 10 files changed, 513 insertions(+), 13 deletions(-) create mode 100644 engines/mads/scene.cpp create mode 100644 engines/mads/scene.h diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp index c6049c3c1a5..34a0b86abc9 100644 --- a/engines/mads/dialogs.cpp +++ b/engines/mads/dialogs.cpp @@ -285,15 +285,16 @@ void TextDialog::draw() { } void TextDialog::drawWithInput() { - int innerWidth = _innerWidth; - int lineHeight = _vm->_font->getHeight() + 1; - int xp = _position.x + 5; + //int innerWidth = _innerWidth; + //int lineHeight = _vm->_font->getHeight() + 1; + //int xp = _position.x + 5; // Draw the content of the dialog drawContent(Common::Rect(_position.x + 2, _position.y + 2, _position.x + _width - 2, _position.y + _height - 2), 0, TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2); - + + error("TODO: drawWithInput"); } void TextDialog::restorePalette() { diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index 89d15607141..23d2e72eebd 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -42,7 +42,7 @@ EventsManager::EventsManager(MADSEngine *vm) { } EventsManager::~EventsManager() { - delete _cursorSprites; + freeCursors(); } void EventsManager::loadCursors(const Common::String &spritesName) { @@ -68,8 +68,22 @@ void EventsManager::hideCursor() { CursorMan.showMouse(false); } -void EventsManager::changeCursor() { +void EventsManager::resetCursor() { + CursorType cursorId = (CursorType)MIN(_cursorSprites->getCount(), (int)CURSOR_WAIT); + _newCursorId = cursorId; + if (_cursorId != _newCursorId) { + changeCursor(); + _cursorId = _newCursorId; + } +} +void EventsManager::changeCursor() { + warning("TODO: changeCursor"); +} + +void EventsManager::freeCursors() { + delete _cursorSprites; + _cursorSprites = nullptr; } void EventsManager::pollEvents() { diff --git a/engines/mads/events.h b/engines/mads/events.h index 4705e6258f3..01f48170d46 100644 --- a/engines/mads/events.h +++ b/engines/mads/events.h @@ -92,6 +92,16 @@ public: */ void hideCursor(); + /** + * Resets the cursor, if necessary + */ + void resetCursor(); + + /** + * Free currently loaded cursors + */ + void freeCursors(); + /** * Poll any pending events */ diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 774ec98eb4e..aa0d1dcac67 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -26,6 +26,7 @@ #include "mads/nebular/game_nebular.h" #include "mads/graphics.h" #include "mads/msurface.h" +#include "mads/resources.h" namespace MADS { @@ -38,15 +39,66 @@ Game *Game::init(MADSEngine *vm) { Game::Game(MADSEngine *vm): _vm(vm), _surface(nullptr) { _sectionNumber = _priorSectionNumber = 0; + _difficultyLevel = DIFFICULTY_HARD; + _saveSlot = -1; + _statusFlag = 0; + _sectionHandler = nullptr; } Game::~Game() { delete _surface; + delete _sectionHandler; } void Game::run() { - if (!checkCopyProtection()) - return; + int protectionResult = checkCopyProtection(); + switch (protectionResult) { + case 1: + // Copy protection failed + _scene._nextSceneId = 804; + initialiseGlobals(); + _globalFlags[5] = 0xFFFF; + _saveSlot = -1; + break; + case 2: + _statusFlag = 0; + break; + default: + break; + } + + if (_saveSlot == -1 && protectionResult != -1 && protectionResult != -2) { + initSection(_scene._sectionNum); + _statusFlag = _scene._sectionNum != 1; + _pendingDialog = DIALOG_DIFFICULTY; + + showDialog(); + _pendingDialog = DIALOG_NONE; + + _vm->_events->freeCursors(); + _scene._priorSectionNum = 0; + _scene._priorSceneId = 0; + _scene._sectionNum2 = -1; + _scene._currentSceneId = -1; + } + + if (protectionResult != 1 && protectionResult != 2) { + initialiseGlobals(); + + if (_saveSlot != -1) { + warning("TODO: loadGame(\"REX.SAV\", 210)"); + _statusFlag = false; + } + } + + if (_statusFlag) + gameLoop(); +} + +void Game::gameLoop() { + setSectionHandler(); + + // TODO: More stuff } void Game::initSection(int sectionNumber) { @@ -61,4 +113,73 @@ void Game::initSection(int sectionNumber) { CURSOR_ARROW : CURSOR_WAIT); } +void Game::loadObjects() { + File f("*OBJECTS.DAT"); + + // Get the total numer of inventory objects + int count = f.readUint16LE(); + _objects.reserve(count); + + // Read in each object + for (int i = 0; i < count; ++i) { + InventoryObject obj; + obj.load(f); + _objects.push_back(obj); + + // If it's for the player's inventory, add the index to the inventory list + if (obj._roomNumber == PLAYER_INVENTORY) { + _inventoryList.push_back(i); + assert(_inventoryList.size() <= 32); + } + } +} + +void Game::setObjectData(int objIndex, int id, const byte *p) { + // TODO: This whole method seems weird. Check it out more thoroughly once + // more of the engine is implemented + for (int i = 0; i < (int)_objects.size(); ++i) { + InventoryObject &obj = _objects[i]; + if (obj._vocabList[0]._actionFlags1 <= i) + break; + + if (obj._mutilateString[6 + i] == id) { + _objects[objIndex]._objFolder = p; + } + } +} + +void Game::setObjectRoom(int objectId, int roomNumber) { + warning("TODO: setObjectRoom"); +} + +void Game::loadResourceSequence(const Common::String prefix, int v) { + warning("TODO: loadResourceSequence"); +} + +/*------------------------------------------------------------------------*/ + +void InventoryObject::load(Common::SeekableReadStream &f) { + _descId = f.readUint16LE(); + _roomNumber = f.readUint16LE(); + _article = f.readByte(); + _vocabCount = f.readByte(); + + for (int i = 0; i < 3; ++i) { + _vocabList[i]._actionFlags1 = f.readByte(); + _vocabList[i]._actionFlags2 = f.readByte(); + _vocabList[i]._vocabId = f.readByte(); + } + + f.skip(4); // field12 + f.read(&_mutilateString[0], 10); + f.skip(16); +} + +/*------------------------------------------------------------------------*/ + +Player::Player() { + _direction = 8; + _newDirection = 8; +} + } // End of namespace MADS diff --git a/engines/mads/game.h b/engines/mads/game.h index bb15a8e35b0..9dd7ca0ace7 100644 --- a/engines/mads/game.h +++ b/engines/mads/game.h @@ -24,28 +24,136 @@ #define MADS_GAME_H #include "common/scummsys.h" +#include "mads/scene.h" namespace MADS { class MADSEngine; +enum { + PLAYER_INVENTORY = 2 +}; + +enum Difficulty { + DIFFICULTY_HARD = 1, DIFFICULTY_MEDIUM = 2, DIFFICULTY_EASY = 3 +}; + +enum DialogId { + DIALOG_NONE = 0, DIALOG_GAME_MENU = 1, DIALOG_SAVE = 2, DIALOG_RESTORE = 3, + DIALOG_OPTIONS = 4, DIALOG_DIFFICULTY = 5, DIALOG_ERROR = 6 +}; + +class InventoryObject { +public: + int _descId; + int _roomNumber; + int _article; + int _vocabCount; + struct { + int _actionFlags1; + int _actionFlags2; + int _vocabId; + } _vocabList[3]; + char _mutilateString[10]; // ??? + const byte *_objFolder; // ??? + + /** + * Loads the data for a given object + */ + void load(Common::SeekableReadStream &f); +}; + +class Player { +public: + int _direction; + int _newDirection; +public: + Player(); +}; + +class SectionHandler { +protected: + MADSEngine *_vm; +public: + SectionHandler(MADSEngine *vm): _vm(vm) {} + + virtual void loadSection() = 0; + virtual void sectionPtr2() = 0; + virtual void sectionPtr3() = 0; +}; + class Game { +private: + /** + * Main game loop + */ + void gameLoop(); protected: MADSEngine *_vm; MSurface *_surface; + Difficulty _difficultyLevel; + Common::Array _globalFlags; + Common::Array _objects; + Common::Array _inventoryList; + Player _player; + Scene _scene; + int _saveSlot; + int _statusFlag; + DialogId _pendingDialog; + SectionHandler *_sectionHandler; + + /** + * Constructor + */ Game(MADSEngine *vm); /** - * Perform any copy protection check + * Loads the game's object list */ - virtual bool checkCopyProtection() = 0; + void loadObjects(); + + /** + * Set the associated data? pointer with an inventory object + */ + void setObjectData(int objIndex, int id, const byte *p); + + /** + * Sets the room number + */ + void setObjectRoom(int objectId, int roomNumber); /** * Initialises the current section number of the game */ void initSection(int sectionNumber); + void loadResourceSequence(const Common::String prefix, int v); + + //@{ + /** @name Virtual Method list */ + + /** + * Perform any copy protection check + */ + virtual int checkCopyProtection() = 0; + + /** + * Initialises global variables for a new game + */ + virtual void initialiseGlobals() = 0; + + /** + * Show a game dialog + */ + virtual void showDialog() = 0; + + /** + * Set up the section handler specific to each section + */ + virtual void setSectionHandler() = 0; + //@} + public: static Game *init(MADSEngine *vm); public: diff --git a/engines/mads/module.mk b/engines/mads/module.mk index 0b5f4c7b489..9219d04fdc9 100644 --- a/engines/mads/module.mk +++ b/engines/mads/module.mk @@ -18,6 +18,7 @@ MODULE_OBJS := \ msurface.o \ palette.o \ resources.o \ + scene.o \ sound.o \ user_interface.o diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index bf52af37333..2e27eaea0f3 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -37,15 +37,153 @@ GameNebular::GameNebular(MADSEngine *vm): Game(vm) { _surface =MSurface::init(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT - MADS_INTERFACE_HEIGHT); } -bool GameNebular::checkCopyProtection() { +int GameNebular::checkCopyProtection() { if (!ConfMan.getBool("copy_protection")) return true; + /* DEBUG: Disabled for now CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); dlg->show(); delete dlg; + */ - return false; + // DEBUG: Return that copy protection failed + return 1; +} + +void GameNebular::initialiseGlobals() { + // Allocate globals space + _globalFlags.resize(210); + for (int i = 0; i < 210; ++i) + _globalFlags[i] = 0; + + // Set specific values needed by the game + _globalFlags[4] = 8; + _globalFlags[33] = 1; + _globalFlags[10] = 0xFFFF; + _globalFlags[13] = 0xFFFF; + _globalFlags[15] = 0xFFFF; + _globalFlags[19] = 0xFFFF; + _globalFlags[20] = 0xFFFF; + _globalFlags[21] = 0xFFFF; + _globalFlags[95] = 0xFFFF; + + setObjectData(3, 17, nullptr); + + // Put the values 0 through 3 in a random order in global slots 83 to 86 + for (int i = 0; i < 4;) { + int randomVal = _vm->getRandomNumber(3); + _globalFlags[83 + i] = randomVal; + + bool flag = false; + for (int idx2 = 0; idx2 < i; ++idx2) { + if (_globalFlags[83 + idx2] == randomVal) + flag = true; + } + + if (!flag) + ++i; + } + + // Put the values 0 through 3 in a random order in global slots 87 to 90 + for (int i = 0; i < 4;) { + int randomVal = _vm->getRandomNumber(3); + _globalFlags[87 + i] = randomVal; + + bool flag = false; + for (int idx2 = 0; idx2 < i; ++idx2) { + if (_globalFlags[87 + idx2] == randomVal) + flag = true; + } + + if (!flag) + ++i; + } + + _globalFlags[120] = 501; + _globalFlags[121] = 0xFFFF; + _globalFlags[55] = 0xFFFF; + _globalFlags[119] = 1; + _globalFlags[134] = 4; + + // Fill out the globals 200 to 209 with unique random values less than 10000 + for (int i = 0; i < 10; ++i) { + int randomVal = _vm->getRandomNumber(9999); + _globalFlags[200 + i] = randomVal; + + bool flag = false; + for (int idx2 = 0; idx2 < i; ++idx2) { + if (_globalFlags[200 + idx2] == randomVal) + flag = true; + } + + if (!flag) + ++i; + } + + // Difficulty level control + switch (_difficultyLevel) { + case DIFFICULTY_HARD: + _globalFlags[35] = 0; + setObjectRoom(9, 1); + setObjectRoom(50, 1); + _globalFlags[137] = 5; + _globalFlags[136] = 0; + break; + case DIFFICULTY_MEDIUM: + _globalFlags[35] = 0; + setObjectRoom(8, 1); + _globalFlags[137] = 0xFFFF; + _globalFlags[136] = 6; + break; + case DIFFICULTY_EASY: + _globalFlags[35] = 2; + setObjectRoom(8, 1); + setObjectRoom(27, 1); + break; + default: + break; + } + + _player._direction = 8; + _player._newDirection = 8; + + loadResourceSequence("RXM", 1); + loadResourceSequence("ROX", 1); +} + +void GameNebular::showDialog() { + warning("TODO: showDialog"); +} + +void GameNebular::setSectionHandler() { + delete _sectionHandler; + + switch (_scene._sectionNum) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + case 6: + _sectionHandler = new Section6Handler(_vm); + break; + case 7: + _sectionHandler = new Section7Handler(_vm); + break; + default: + break; + } } } // End of namespace Nebular diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h index b0f088f8912..b7f47aa9cd0 100644 --- a/engines/mads/nebular/game_nebular.h +++ b/engines/mads/nebular/game_nebular.h @@ -35,9 +35,35 @@ class GameNebular: public Game { protected: GameNebular(MADSEngine *vm); - virtual bool checkCopyProtection(); + virtual int checkCopyProtection(); + + virtual void initialiseGlobals(); + + virtual void showDialog(); + + virtual void setSectionHandler(); }; + +class Section1Handler: public SectionHandler { +public: + Section1Handler(MADSEngine *vm): SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void loadSection() {} + virtual void sectionPtr2() {} + virtual void sectionPtr3() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; +typedef Section1Handler Section6Handler; +typedef Section1Handler Section7Handler; + + } // End of namespace Nebular } // End of namespace MADS diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp new file mode 100644 index 00000000000..f6bbf32e405 --- /dev/null +++ b/engines/mads/scene.cpp @@ -0,0 +1,37 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "mads/scene.h" + +namespace MADS { + +Scene::Scene() { + _sectionNum = 1; + _sectionNum2 = -1; + _priorSectionNum = 0; + _priorSceneId = 0; + _nextSceneId = 0; + _currentSceneId = 0; +} + +} // End of namespace MADS diff --git a/engines/mads/scene.h b/engines/mads/scene.h new file mode 100644 index 00000000000..a5359a98956 --- /dev/null +++ b/engines/mads/scene.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef MADS_SCENE_H +#define MADS_SCENE_H + +#include "common/scummsys.h" + +namespace MADS { + +class Scene { +public: + int _priorSectionNum; + int _sectionNum; + int _sectionNum2; + int _priorSceneId; + int _nextSceneId; + int _currentSceneId; + + Scene(); +}; + +} // End of namespace MADS + +#endif /* MADS_SCENE_H */