diff options
Diffstat (limited to 'engines/m4')
-rw-r--r-- | engines/m4/animation.cpp | 28 | ||||
-rw-r--r-- | engines/m4/animation.h | 5 | ||||
-rw-r--r-- | engines/m4/console.cpp | 8 | ||||
-rw-r--r-- | engines/m4/graphics.cpp | 26 | ||||
-rw-r--r-- | engines/m4/graphics.h | 14 | ||||
-rw-r--r-- | engines/m4/mads_scene.cpp | 552 | ||||
-rw-r--r-- | engines/m4/mads_scene.h | 67 | ||||
-rw-r--r-- | engines/m4/mads_views.cpp | 445 | ||||
-rw-r--r-- | engines/m4/mads_views.h | 62 |
9 files changed, 647 insertions, 560 deletions
diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 9c31cd35d7..412f514e5b 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -26,6 +26,7 @@ #include "m4/assets.h" #include "m4/animation.h" #include "m4/compression.h" +#include "m4/mads_scene.h" namespace M4 { @@ -44,7 +45,7 @@ MadsAnimation::~MadsAnimation() { delete _font; } -void MadsAnimation::load(const Common::String &filename) { +void MadsAnimation::load(const Common::String &filename, uint16 flags, M4Surface *walkSurface, M4Surface *sceneSurface) { MadsPack anim(filename.c_str(), _vm); bool madsRes = filename[0] == '*'; char buffer[20]; @@ -64,7 +65,6 @@ void MadsAnimation::load(const Common::String &filename) { animStream->skip(2); _animMode = animStream->readUint16LE(); - assert(_animMode != 4); _roomNumber = animStream->readUint16LE(); _field12 = animStream->readUint16LE() != 0; animStream->skip(4); @@ -74,7 +74,7 @@ void MadsAnimation::load(const Common::String &filename) { animStream->skip(10); animStream->read(buffer, 13); - _field24 = Common::String(buffer, 13); + _infoFilename = Common::String(buffer, 13); for (int i = 0; i < 10; ++i) { animStream->read(buffer, 13); @@ -93,8 +93,10 @@ void MadsAnimation::load(const Common::String &filename) { animStream->read(buffer, 13); Common::String fontResource(buffer, 13); - // TODO: Based on a weird usage of a flags word, a secondary method gets called here. - // Figure out secondary method, and when/if it's called + if (_animMode == 4) + flags |= 0x4000; + if (flags & 0x100) + loadInterface(walkSurface, sceneSurface); // Initialise the reference list for (int i = 0; i < spriteListCount; ++i) @@ -416,12 +418,24 @@ void MadsAnimation::load1(int frameNumber) { if (proc1(spriteSet, pt, frameNumber)) error("proc1 failure"); - - } bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) { return 0; } +void MadsAnimation::loadInterface(M4Surface *walkSurface, M4Surface *sceneSurface) { + walkSurface->madsloadInterface(0); + + + /* TODO - implement properly + if (_animMode > 2) { + warning("Mode1"); + } else { + MadsSceneResources sceneResources; + sceneResources.load(_roomNumber, _infoFilename.c_str(), 0, walkSurface, sceneSurface); + } + */ +} + } // End of namespace M4 diff --git a/engines/m4/animation.h b/engines/m4/animation.h index a5f3ea3085..cb68b27853 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -83,7 +83,7 @@ private: int _spriteListIndex; int _scrollX; int _scrollY; - Common::String _field24; + Common::String _infoFilename; Common::String _spriteSetNames[10]; Common::String _lbmFilename; Common::String _spritesFilename; @@ -104,11 +104,12 @@ private: void load1(int frameNumber); bool proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber); + void loadInterface(M4Surface *walkSurface, M4Surface *sceneSurface); public: MadsAnimation(MadsM4Engine *vm, MadsView *view); virtual ~MadsAnimation(); - virtual void load(const Common::String &filename); + virtual void load(const Common::String &filename, uint16 flags, M4Surface *walkSurface, M4Surface *sceneSurface); virtual void start(); virtual bool update(); virtual void stop(); diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index d568584d30..ccb1c8c182 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -375,10 +375,10 @@ bool MadsConsole::cmdPlayAnimation(int argc, const char **argv) { _vm->_viewManager->moveToFront(view); if (argc == 3 && atoi(argv[2]) == 1) - _madsVm->scene()->_sceneAnimation.loadFullScreen(resourceName); - else - _madsVm->scene()->_sceneAnimation.load(resourceName); - _madsVm->scene()->_sceneAnimation.start(); + _madsVm->_palette->deleteAllRanges(); + + _madsVm->scene()->_sceneAnimation->load(resourceName, 0, NULL, NULL); + _madsVm->scene()->_sceneAnimation->start(); view->restore(0, 0, view->width(), view->height()); return false; diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 6666814289..edabcd8b22 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -69,6 +69,13 @@ void RGBList::setRange(int start, int count, const RGB8 *src) { #define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2) +M4Surface::~M4Surface() { + if (_rgbList) { + _madsVm->_palette->deleteRange(_rgbList); + delete _rgbList; + } +} + void M4Surface::loadCodesM4(Common::SeekableReadStream *source) { if (!source) { free(); @@ -472,9 +479,18 @@ void M4Surface::loadBackground(int sceneNumber, RGBList **palData) { if (_vm->getGameType() == GType_RexNebular) { // Load Rex Nebular screen + bool hasPalette = palData != NULL; + if (!hasPalette) + palData = &_rgbList; + sprintf(resourceName, "rm%d.art", sceneNumber); stream = _vm->_resourceManager->get(resourceName); rexLoadBackground(stream, palData); + + if (!hasPalette) { + _vm->_palette->addRange(_rgbList); + this->translate(_rgbList); + } } else { // Loads M4 game scene if (palData) @@ -717,6 +733,10 @@ void M4Surface::madsloadInterface(int index, RGBList **palData) { MadsPack intFile(resourceName, _vm); RGB8 *palette = new RGB8[16]; + bool hasPalette = palData != NULL; + if (!hasPalette) + palData = &_rgbList; + // Chunk 0, palette Common::SeekableReadStream *intStream = intFile.getItemStream(0); @@ -736,6 +756,12 @@ void M4Surface::madsloadInterface(int index, RGBList **palData) { create(320, 44, 1); intStream->read(pixels, 320 * 44); delete intStream; + + if (!hasPalette) { + // Translate the interface palette + _vm->_palette->addRange(_rgbList); + this->translate(_rgbList); + } } void M4Surface::scrollX(int xAmount) { diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index c140140f97..97fdfc0d6c 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -35,6 +35,12 @@ namespace M4 { +#define MADS_SURFACE_WIDTH 320 +#define MADS_SURFACE_HEIGHT 156 +#define MADS_SCREEN_HEIGHT 200 +#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2) + + struct BGR8 { uint8 b, g, r; }; @@ -89,19 +95,23 @@ class M4Surface : protected Graphics::Surface { private: byte _color; bool _isScreen; + RGBList *_rgbList; void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL); void madsLoadBackground(int roomNumber, RGBList **palData = NULL); void m4LoadBackground(Common::SeekableReadStream *source); public: M4Surface(bool isScreen = false) { - create(g_system->getWidth(), g_system->getHeight(), 1); + create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, 1); _isScreen = isScreen; + _rgbList = NULL; } M4Surface(int width_, int height_) { create(width_, height_, 1); _isScreen = false; + _rgbList = NULL; } + virtual ~M4Surface(); // loads a .COD file into the M4Surface // TODO: maybe move this to the rail system? check where it makes sense @@ -112,7 +122,7 @@ public: // loads the specified background void loadBackground(int sceneNumber, RGBList **palData = NULL); void loadBackgroundRiddle(const char *sceneName); - void madsloadInterface(int index, RGBList **palData); + void madsloadInterface(int index, RGBList **palData = NULL); void setColor(byte value) { _color = value; } void setColour(byte value) { _color = value; } diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 60e480e6fb..b69c8bd116 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -40,6 +40,13 @@ namespace M4 { +static const int INV_ANIM_FRAME_SPEED = 2; +static const int INVENTORY_X = 160; +static const int INVENTORY_Y = 159; +static const int SCROLLER_DELAY = 200; + +//-------------------------------------------------------------------------- + MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResources), MadsView(this) { _vm = vm; @@ -66,10 +73,17 @@ void MadsScene::loadScene2(const char *aaName) { _kernelMessages.clear(); // Load up the properties for the scene - _sceneResources.load(_currentScene); + _sceneResources.load(_currentScene, 0/*word_83546*/, NULL, _walkSurface, _backgroundSurface); // Load scene walk paths loadSceneCodes(_currentScene); + + // Initialise the scene animation + uint16 flags = 0x4100; + if (_madsVm->globals()->_config.textWindowStill) + flags |= 0x200; + + _sceneAnimation->load(aaName, flags, _interfaceSurface, NULL); } /** @@ -83,22 +97,7 @@ void MadsScene::loadSceneTemporary() { {0x00<<2, 0x10<<2, 0x16<<2, 0}}; _vm->_palette->setPalette(&sysColors[0], 4, 3); - _backgroundSurface->loadBackground(_currentScene, &_palData); - _vm->_palette->addRange(_palData); - _backgroundSurface->translate(_palData); - - if (_currentScene < 900) { - _interfaceSurface->madsloadInterface(0, &_interfacePal); - _vm->_palette->addRange(_interfacePal); - _interfaceSurface->translate(_interfacePal); - _backgroundSurface->copyFrom(_interfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44); - - _interfaceSurface->initialise(); - } - - // Don't load other screen resources for system screens - if (_currentScene >= 900) - return; + _interfaceSurface->initialise(); loadSceneHotspots(_currentScene); @@ -185,15 +184,6 @@ void MadsScene::loadSceneCodes(int sceneNumber, int index) { sceneS = walkData.getItemStream(0); _walkSurface->loadCodesMads(sceneS); _vm->res()->toss(filename); - } else if (_vm->getGameType() == GType_RexNebular) { - // For Rex Nebular, the walk areas are part of the scene info - byte *destP = _walkSurface->getBasePtr(0, 0); - const byte *srcP = _sceneResources.walkData; - byte runLength; - while ((runLength = *srcP++) != 0) { - Common::set_to(destP, destP + runLength, *srcP++); - destP += runLength; - } } } @@ -614,45 +604,531 @@ void MadsAction::set() { /*--------------------------------------------------------------------------*/ -void MadsSceneResources::load(int sId) { - const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sId, ".DAT"); - Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr); +void MadsSceneResources::load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface) { + char buffer[80]; + const char *sceneName; + + // TODO: Initialise spriteSet / xp_list + + if (sceneId > 0) { + sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneId, ".DAT"); + } else { + strcat(buffer, "*"); + strcat(buffer, resName); + sceneName = buffer; // TODO: Check whether this needs to be converted to 'HAG form' + } + + Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneName); MadsPack sceneInfo(rawStream); + // Chunk 0: // Basic scene info Common::SeekableReadStream *stream = sceneInfo.getItemStream(0); int resSceneId = stream->readUint16LE(); - assert(resSceneId == sId); - + assert(resSceneId == sceneId); artFileNum = stream->readUint16LE(); - field_4 = stream->readUint16LE(); + dialogStyle = stream->readUint16LE(); width = stream->readUint16LE(); height = stream->readUint16LE(); assert((width == 320) && (height == 156)); stream->skip(24); - objectCount = stream->readUint16LE(); + int objectCount = stream->readUint16LE(); stream->skip(40); + // Load in any scene objects for (int i = 0; i < objectCount; ++i) { - objects[i].load(stream); + MadsObject rec; + rec.load(stream); + objects.push_back(rec); + } + for (int i = 0; i < 20 - objectCount; ++i) + stream->skip(48); + + int setCount = stream->readUint16LE(); + stream->readUint16LE(); + for (int i = 0; i < setCount; ++i) { + char buffer[64]; + Common::String s(buffer, 64); + setNames.push_back(s); + } + + // Initialise a copy of the surfaces if they weren't provided + bool dsFlag = false, ssFlag = false; + int gfxSize = width * height; + if (!surface) { + surface = new M4Surface(width, height); + ssFlag = true; + } + int walkSize = gfxSize; + if (dialogStyle == 2) { + width >>= 2; + walkSize = width * height; + } + if (!depthSurface) { + depthSurface = new M4Surface(width, height); + dsFlag = true; } // For Rex Nebular, read in the scene's compressed walk surface information if (_vm->getGameType() == GType_RexNebular) { - delete walkData; - + assert(depthSurface); stream = sceneInfo.getItemStream(1); - walkData = (byte *)malloc(stream->size()); + byte *walkData = (byte *)malloc(stream->size()); stream->read(walkData, stream->size()); + + // For Rex Nebular, the walk areas are part of the scene info + byte *destP = depthSurface->getBasePtr(0, 0); + const byte *srcP = walkData; + byte runLength; + while ((runLength = *srcP++) != 0) { + Common::set_to(destP, destP + runLength, *srcP++); + destP += runLength; + } + + delete walkData; + delete stream; } - _vm->_resourceManager->toss(sceneInfoStr); + _vm->_resourceManager->toss(sceneName); + + // Load the surface artwork + surface->loadBackground(sceneId); + + // Final cleanup + if (ssFlag) + delete surface; + if (dsFlag) + delete depthSurface; } + /*--------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------- + * MadsInterfaceView handles the user interface section at the bottom of + * game screens in MADS games + *-------------------------------------------------------------------------- + */ + +MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): GameInterfaceView(vm, + Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) { + _screenType = VIEWID_INTERFACE; + _highlightedElement = -1; + _topIndex = 0; + _selectedObject = -1; + _cheatKeyCtr = 0; + + _objectSprites = NULL; + _objectPalData = NULL; + + /* Set up the rect list for screen elements */ + // Actions + for (int i = 0; i < 10; ++i) + _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2, + ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2); + + // Scroller elements (up arrow, scroller, down arrow) + _screenObjects.addRect(73, 160, 82, 167); + _screenObjects.addRect(73, 168, 82, 190); + _screenObjects.addRect(73, 191, 82, 198); + + // Inventory object names + for (int i = 0; i < 5; ++i) + _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8); + + // Full rectangle area for all vocab actions + for (int i = 0; i < 5; ++i) + _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8); +} + +MadsInterfaceView::~MadsInterfaceView() { + delete _objectSprites; +} + +void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) { + switch (newMode) { + case ITEM_NORMAL: + _vm->_font->current()->setColours(4, 4, 0xff); + break; + case ITEM_HIGHLIGHTED: + _vm->_font->current()->setColours(5, 5, 0xff); + break; + case ITEM_SELECTED: + _vm->_font->current()->setColours(6, 6, 0xff); + break; + } +} + +void MadsInterfaceView::initialise() { + // Build up the inventory list + _inventoryList.clear(); + + for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) { + MadsObject *obj = _madsVm->globals()->getObject(i); + if (obj->roomNumber == PLAYER_INVENTORY) + _inventoryList.push_back(i); + } + + // If the inventory has at least one object, select it + if (_inventoryList.size() > 0) + setSelectedObject(_inventoryList[0]); +} + +void MadsInterfaceView::setSelectedObject(int objectNumber) { + char resName[80]; + + // Load inventory resource + if (_objectSprites) { + _vm->_palette->deleteRange(_objectPalData); + delete _objectSprites; + } + + // Check to make sure the object is in the inventory, and also visible on-screen + int idx = _inventoryList.indexOf(objectNumber); + if (idx == -1) { + // Object wasn't found, so return + _selectedObject = -1; + return; + } + + // Found the object + if (idx < _topIndex) + _topIndex = idx; + else if (idx >= (_topIndex + 5)) + _topIndex = MAX(0, idx - 4); + + _selectedObject = objectNumber; + sprintf(resName, "*OB%.3dI.SS", objectNumber); + + Common::SeekableReadStream *data = _vm->res()->get(resName); + _objectSprites = new SpriteAsset(_vm, data, data->size(), resName); + _vm->res()->toss(resName); + + // Slot it into available palette space + _objectPalData = _objectSprites->getRgbList(); + _vm->_palette->addRange(_objectPalData); + _objectSprites->translate(_objectPalData, true); + + _objectFrameNumber = 0; +} + +void MadsInterfaceView::addObjectToInventory(int objectNumber) { + if (_inventoryList.indexOf(objectNumber) == -1) { + _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY; + _inventoryList.push_back(objectNumber); + } + + setSelectedObject(objectNumber); +} + +void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { + _vm->_font->setFont(FONT_INTERFACE_MADS); + char buffer[100]; + + // Check to see if any dialog is currently active + bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL; + + // Highlighting logic for action list + int actionIndex = 0; + for (int x = 0; x < 2; ++x) { + for (int y = 0; y < 5; ++y, ++actionIndex) { + // Determine the font colour depending on whether an item is selected. Note that the first action, + // 'Look', is always 'selected', even when another action is clicked on + setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED : + ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL)); + + // Get the verb action and capitalise it + const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex); + strcpy(buffer, verbStr); + if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; + + // Display the verb + const Common::Rect r(_screenObjects[actionIndex]); + _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); + } + } + + // Check for highlighting of the scrollbar controls + if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) { + // Highlight the control's borders + const Common::Rect r(_screenObjects[_highlightedElement]); + destSurface->frameRect(r, 5); + } + + // Draw the horizontal line in the scroller representing the current top selected + const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]); + int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1); + destSurface->setColor(4); + destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP); + + // List inventory items + for (uint i = 0; i < 5; ++i) { + if ((_topIndex + i) >= _inventoryList.size()) + break; + + const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject( + _inventoryList[_topIndex + i])->descId); + strcpy(buffer, descStr); + if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; + + const Common::Rect r(_screenObjects[INVLIST_START + i]); + + // Set the highlighting of the inventory item + if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED); + else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED); + else setFontMode(ITEM_NORMAL); + + // Write out it's description + _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); + } + + // Handle the display of any currently selected object + if (_objectSprites) { + // Display object sprite. Note that the frame number isn't used directly, because it would result + // in too fast an animation + M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); + spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); + + if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) { + // If objects need to be animated, move to the next frame + if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED)) + _objectFrameNumber = 0; + } + + // List the vocab actions for the currently selected object + MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); + int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); + + for (int i = 0; i < obj->vocabCount; ++i) { + const Common::Rect r(_screenObjects[VOCAB_START + i]); + + // Get the vocab description and capitalise it + const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId); + strcpy(buffer, descStr); + if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; + + // Set the highlighting and display the entry + setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL); + _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); + } + } +} + +bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { + MadsAction &act = _madsVm->scene()->getAction(); + + // If the mouse isn't being held down, then reset the repeated scroll timer + if (eventType != MEVENT_LEFT_HOLD) + _nextScrollerTicks = 0; + + // Handle various event types + switch (eventType) { + case MEVENT_MOVE: + // If the cursor isn't in "wait mode", don't do any processing + if (_vm->_mouse->getCursorNum() == CURSOR_WAIT) + return true; + + // Ensure the cursor is the standard arrow + _vm->_mouse->setCursorNum(CURSOR_ARROW); + + // Check if any interface element is currently highlighted + _highlightedElement = _screenObjects.find(Common::Point(x, y)); + + return true; + + case MEVENT_LEFT_CLICK: + // Left mouse click + { + // Check if an inventory object was selected + if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) { + // Ensure there is an inventory item listed in that cell + uint idx = _highlightedElement - INVLIST_START; + if ((_topIndex + idx) < _inventoryList.size()) { + // Set the selected object + setSelectedObject(_inventoryList[_topIndex + idx]); + } + } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) { + // A standard action was selected + int verbId = kVerbLook + (_highlightedElement - ACTIONS_START); + warning("Selected action #%d", verbId); + + } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) { + // A vocab action was selected + MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); + int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); + if (vocabIndex >= 0) { + act._actionMode = ACTMODE_OBJECT; + act._actionMode2 = ACTMODE2_2; + act._flags1 = obj->vocabList[1].flags1; + act._flags2 = obj->vocabList[1].flags2; + + act._currentHotspot = _selectedObject; + act._articleNumber = act._flags2; + } + } + } + return true; + + case MEVENT_LEFT_HOLD: + // Left mouse hold + // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down + if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) { + if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) { + // Handle scroll up/down action + _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY; + + if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0)) + --_topIndex; + if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1))) + ++_topIndex; + } + } + return true; + + case MEVENT_LEFT_DRAG: + // Left mouse drag + // Handle the the the scroller area that can be dragged to adjust the top displayed index + if (_highlightedElement == SCROLL_SCROLLER) { + // Calculate the new top index based on the Y position + const Common::Rect r(_screenObjects[SCROLL_SCROLLER]); + _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5), + 0, (int)_inventoryList.size() - 1); + } + return true; + + case KEVENT_KEY: + if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) + handleCheatKey(param1); + handleKeypress(param1); + return true; + + default: + break; + } + + return false; +} + +bool MadsInterfaceView::handleCheatKey(int32 keycode) { + switch (keycode) { + case Common::KEYCODE_SPACE: + // TODO: Move player to current destination + return true; + + case Common::KEYCODE_t | (Common::KEYCODE_LALT): + case Common::KEYCODE_t | (Common::KEYCODE_RALT): + { + // Teleport to room + //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE); + + + return true; + } + + default: + break; + } + + return false; +} + +const char *CHEAT_SEQUENCE = "widepipe"; + +bool MadsInterfaceView::handleKeypress(int32 keycode) { + int flags = keycode >> 24; + int kc = keycode & 0xffff; + + // Capitalise the letter if necessary + if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) { + if ((flags & Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) { + ++_cheatKeyCtr; + if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) + Dialog::display(_vm, 22, cheatingEnabledDesc); + return true; + } else { + _cheatKeyCtr = 0; + } + } + + // Handle the various keys + if ((keycode == Common::KEYCODE_ESCAPE) || (keycode == Common::KEYCODE_F1)) { + // Game menu + _madsVm->globals()->dialogType = DIALOG_GAME_MENU; + leaveScene(); + return false; + } else if (flags & Common::KBD_CTRL) { + // Handling of the different control key combinations + switch (kc) { + case Common::KEYCODE_i: + // Mouse to inventory + warning("TODO: Mouse to inventory"); + break; + + case Common::KEYCODE_k: + // Toggle hotspots + warning("TODO: Toggle hotspots"); + break; + + case Common::KEYCODE_p: + // Player stats + warning("TODO: Player stats"); + break; + + case Common::KEYCODE_q: + // Quit game + break; + + case Common::KEYCODE_s: + // Activate sound + warning("TODO: Activate sound"); + break; + + case Common::KEYCODE_u: + // Rotate player + warning("TODO: Rotate player"); + break; + + case Common::KEYCODE_v: { + // Release version + Dialog *dlg = new Dialog(_vm, GameReleaseInfoStr, GameReleaseTitleStr); + _vm->_viewManager->addView(dlg); + _vm->_viewManager->moveToFront(dlg); + return false; + } + + default: + break; + } + } else if ((flags & Common::KBD_ALT) && (kc == Common::KEYCODE_q)) { + // Quit Game + + } else { + // Standard keypresses + switch (kc) { + case Common::KEYCODE_F2: + // Save game + _madsVm->globals()->dialogType = DIALOG_SAVE; + leaveScene(); + break; + case Common::KEYCODE_F3: + // Restore game + _madsVm->globals()->dialogType = DIALOG_RESTORE; + leaveScene(); + break; + } + } +//DIALOG_OPTIONS + return false; +} + +void MadsInterfaceView::leaveScene() { + // Close the scene + View *view = _madsVm->_viewManager->getView(VIEWID_SCENE); + _madsVm->_viewManager->deleteView(view); +} + } // End of namespace M4 diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index c8a0da3aea..e3e4c3c084 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -33,27 +33,24 @@ namespace M4 { #define INTERFACE_HEIGHT 106 - +class MadsInterfaceView; class MadsSceneResources: public SceneResources { public: int sceneId; int artFileNum; - int field_4; + int dialogStyle; int width; int height; - - int objectCount; - MadsObject objects[32]; + Common::Array<MadsObject> objects; + Common::Array<Common::String> setNames; - int walkSize; - byte *walkData; Common::Point playerPos; int playerDir; - MadsSceneResources() { walkSize = 0; walkData = NULL; playerDir = 0; } - ~MadsSceneResources() { delete walkData; } - void load(int sceneId); + MadsSceneResources() { playerDir = 0; } + ~MadsSceneResources() {} + void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface); }; enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6}; @@ -137,6 +134,56 @@ public: void setStatusText(const char *text) {}//***DEPRECATED*** }; +#define CHEAT_SEQUENCE_MAX 8 + +class IntegerList : public Common::Array<int> { +public: + int indexOf(int v) { + for (uint i = 0; i < size(); ++i) + if (operator [](i) == v) + return i; + return -1; + } +}; + +enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; + +enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12, + INVLIST_START = 13, VOCAB_START = 18}; + +class MadsInterfaceView : public GameInterfaceView { +private: + IntegerList _inventoryList; + RectList _screenObjects; + int _highlightedElement; + int _topIndex; + uint32 _nextScrollerTicks; + int _cheatKeyCtr; + + // Object display fields + int _selectedObject; + SpriteAsset *_objectSprites; + RGBList *_objectPalData; + int _objectFrameNumber; + + void setFontMode(InterfaceFontMode newMode); + bool handleCheatKey(int32 keycode); + bool handleKeypress(int32 keycode); + void leaveScene(); +public: + MadsInterfaceView(MadsM4Engine *vm); + ~MadsInterfaceView(); + + virtual void initialise(); + virtual void setSelectedObject(int objectNumber); + virtual void addObjectToInventory(int objectNumber); + int getSelectedObject() { return _selectedObject; } + int getInventoryObject(int objectIndex) { return _inventoryList[objectIndex]; } + + void onRefresh(RectList *rects, M4Surface *destSurface); + bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); +}; + } // End of namespace M4 #endif diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index f4f43c48f1..79ca2c51b7 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -37,13 +37,6 @@ namespace M4 { -static const int INV_ANIM_FRAME_SPEED = 2; -static const int INVENTORY_X = 160; -static const int INVENTORY_Y = 159; -static const int SCROLLER_DELAY = 200; - -//-------------------------------------------------------------------------- - bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const { return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) && (xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale); @@ -1149,17 +1142,11 @@ Animation::Animation(MadsM4Engine *vm): _vm(vm) { Animation::~Animation() { } -void Animation::loadFullScreen(const Common::String &filename) { - _vm->_palette->deleteAllRanges(); - load(filename); -} - //-------------------------------------------------------------------------- MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this), - _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this), - // FIXME: There's probably a cleaner way to do this, and I don't think the destructor is ever called - _sceneAnimation(*new MadsAnimation(_vm, this)) { + _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) { + _textSpacing = -1; _ticksAmount = 3; _newTimeout = 0; @@ -1170,6 +1157,11 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL _depthSurface = NULL; _bgSurface = NULL; + _sceneAnimation = new MadsAnimation(_vm, this); +} + +MadsView::~MadsView() { + delete _sceneAnimation; } void MadsView::refresh() { @@ -1203,427 +1195,4 @@ void MadsView::refresh() { _textDisplay.cleanUp(); } -/*-------------------------------------------------------------------------- - * MadsInterfaceView handles the user interface section at the bottom of - * game screens in MADS games - *-------------------------------------------------------------------------- - */ - -MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): GameInterfaceView(vm, - Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) { - _screenType = VIEWID_INTERFACE; - _highlightedElement = -1; - _topIndex = 0; - _selectedObject = -1; - _cheatKeyCtr = 0; - - _objectSprites = NULL; - _objectPalData = NULL; - - /* Set up the rect list for screen elements */ - // Actions - for (int i = 0; i < 10; ++i) - _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2, - ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2); - - // Scroller elements (up arrow, scroller, down arrow) - _screenObjects.addRect(73, 160, 82, 167); - _screenObjects.addRect(73, 168, 82, 190); - _screenObjects.addRect(73, 191, 82, 198); - - // Inventory object names - for (int i = 0; i < 5; ++i) - _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8); - - // Full rectangle area for all vocab actions - for (int i = 0; i < 5; ++i) - _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8); -} - -MadsInterfaceView::~MadsInterfaceView() { - delete _objectSprites; -} - -void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) { - switch (newMode) { - case ITEM_NORMAL: - _vm->_font->current()->setColours(4, 4, 0xff); - break; - case ITEM_HIGHLIGHTED: - _vm->_font->current()->setColours(5, 5, 0xff); - break; - case ITEM_SELECTED: - _vm->_font->current()->setColours(6, 6, 0xff); - break; - } -} - -void MadsInterfaceView::initialise() { - // Build up the inventory list - _inventoryList.clear(); - - for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) { - MadsObject *obj = _madsVm->globals()->getObject(i); - if (obj->roomNumber == PLAYER_INVENTORY) - _inventoryList.push_back(i); - } - - // If the inventory has at least one object, select it - if (_inventoryList.size() > 0) - setSelectedObject(_inventoryList[0]); -} - -void MadsInterfaceView::setSelectedObject(int objectNumber) { - char resName[80]; - - // Load inventory resource - if (_objectSprites) { - _vm->_palette->deleteRange(_objectPalData); - delete _objectSprites; - } - - // Check to make sure the object is in the inventory, and also visible on-screen - int idx = _inventoryList.indexOf(objectNumber); - if (idx == -1) { - // Object wasn't found, so return - _selectedObject = -1; - return; - } - - // Found the object - if (idx < _topIndex) - _topIndex = idx; - else if (idx >= (_topIndex + 5)) - _topIndex = MAX(0, idx - 4); - - _selectedObject = objectNumber; - sprintf(resName, "*OB%.3dI.SS", objectNumber); - - Common::SeekableReadStream *data = _vm->res()->get(resName); - _objectSprites = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - _objectPalData = _objectSprites->getRgbList(); - _vm->_palette->addRange(_objectPalData); - _objectSprites->translate(_objectPalData, true); - - _objectFrameNumber = 0; -} - -void MadsInterfaceView::addObjectToInventory(int objectNumber) { - if (_inventoryList.indexOf(objectNumber) == -1) { - _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY; - _inventoryList.push_back(objectNumber); - } - - setSelectedObject(objectNumber); -} - -void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { - _vm->_font->setFont(FONT_INTERFACE_MADS); - char buffer[100]; - - // Check to see if any dialog is currently active - bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL; - - // Highlighting logic for action list - int actionIndex = 0; - for (int x = 0; x < 2; ++x) { - for (int y = 0; y < 5; ++y, ++actionIndex) { - // Determine the font colour depending on whether an item is selected. Note that the first action, - // 'Look', is always 'selected', even when another action is clicked on - setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED : - ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL)); - - // Get the verb action and capitalise it - const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex); - strcpy(buffer, verbStr); - if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; - - // Display the verb - const Common::Rect r(_screenObjects[actionIndex]); - _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); - } - } - - // Check for highlighting of the scrollbar controls - if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) { - // Highlight the control's borders - const Common::Rect r(_screenObjects[_highlightedElement]); - destSurface->frameRect(r, 5); - } - - // Draw the horizontal line in the scroller representing the current top selected - const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]); - int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1); - destSurface->setColor(4); - destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP); - - // List inventory items - for (uint i = 0; i < 5; ++i) { - if ((_topIndex + i) >= _inventoryList.size()) - break; - - const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject( - _inventoryList[_topIndex + i])->descId); - strcpy(buffer, descStr); - if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; - - const Common::Rect r(_screenObjects[INVLIST_START + i]); - - // Set the highlighting of the inventory item - if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED); - else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED); - else setFontMode(ITEM_NORMAL); - - // Write out it's description - _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); - } - - // Handle the display of any currently selected object - if (_objectSprites) { - // Display object sprite. Note that the frame number isn't used directly, because it would result - // in too fast an animation - M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); - spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); - - if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) { - // If objects need to be animated, move to the next frame - if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED)) - _objectFrameNumber = 0; - } - - // List the vocab actions for the currently selected object - MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); - int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); - - for (int i = 0; i < obj->vocabCount; ++i) { - const Common::Rect r(_screenObjects[VOCAB_START + i]); - - // Get the vocab description and capitalise it - const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId); - strcpy(buffer, descStr); - if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; - - // Set the highlighting and display the entry - setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL); - _vm->_font->current()->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); - } - } -} - -bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - MadsAction &act = _madsVm->scene()->getAction(); - - // If the mouse isn't being held down, then reset the repeated scroll timer - if (eventType != MEVENT_LEFT_HOLD) - _nextScrollerTicks = 0; - - // Handle various event types - switch (eventType) { - case MEVENT_MOVE: - // If the cursor isn't in "wait mode", don't do any processing - if (_vm->_mouse->getCursorNum() == CURSOR_WAIT) - return true; - - // Ensure the cursor is the standard arrow - _vm->_mouse->setCursorNum(CURSOR_ARROW); - - // Check if any interface element is currently highlighted - _highlightedElement = _screenObjects.find(Common::Point(x, y)); - - return true; - - case MEVENT_LEFT_CLICK: - // Left mouse click - { - // Check if an inventory object was selected - if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) { - // Ensure there is an inventory item listed in that cell - uint idx = _highlightedElement - INVLIST_START; - if ((_topIndex + idx) < _inventoryList.size()) { - // Set the selected object - setSelectedObject(_inventoryList[_topIndex + idx]); - } - } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) { - // A standard action was selected - int verbId = kVerbLook + (_highlightedElement - ACTIONS_START); - warning("Selected action #%d", verbId); - - } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) { - // A vocab action was selected - MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); - int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); - if (vocabIndex >= 0) { - act._actionMode = ACTMODE_OBJECT; - act._actionMode2 = ACTMODE2_2; - act._flags1 = obj->vocabList[1].flags1; - act._flags2 = obj->vocabList[1].flags2; - - act._currentHotspot = _selectedObject; - act._articleNumber = act._flags2; - } - } - } - return true; - - case MEVENT_LEFT_HOLD: - // Left mouse hold - // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down - if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) { - if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) { - // Handle scroll up/down action - _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY; - - if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0)) - --_topIndex; - if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1))) - ++_topIndex; - } - } - return true; - - case MEVENT_LEFT_DRAG: - // Left mouse drag - // Handle the the the scroller area that can be dragged to adjust the top displayed index - if (_highlightedElement == SCROLL_SCROLLER) { - // Calculate the new top index based on the Y position - const Common::Rect r(_screenObjects[SCROLL_SCROLLER]); - _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5), - 0, (int)_inventoryList.size() - 1); - } - return true; - - case KEVENT_KEY: - if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) - handleCheatKey(param1); - handleKeypress(param1); - return true; - - default: - break; - } - - return false; -} - -bool MadsInterfaceView::handleCheatKey(int32 keycode) { - switch (keycode) { - case Common::KEYCODE_SPACE: - // TODO: Move player to current destination - return true; - - case Common::KEYCODE_t | (Common::KEYCODE_LALT): - case Common::KEYCODE_t | (Common::KEYCODE_RALT): - { - // Teleport to room - //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE); - - - return true; - } - - default: - break; - } - - return false; -} - -const char *CHEAT_SEQUENCE = "widepipe"; - -bool MadsInterfaceView::handleKeypress(int32 keycode) { - int flags = keycode >> 24; - int kc = keycode & 0xffff; - - // Capitalise the letter if necessary - if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) { - if ((flags & Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) { - ++_cheatKeyCtr; - if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) - Dialog::display(_vm, 22, cheatingEnabledDesc); - return true; - } else { - _cheatKeyCtr = 0; - } - } - - // Handle the various keys - if ((keycode == Common::KEYCODE_ESCAPE) || (keycode == Common::KEYCODE_F1)) { - // Game menu - _madsVm->globals()->dialogType = DIALOG_GAME_MENU; - leaveScene(); - return false; - } else if (flags & Common::KBD_CTRL) { - // Handling of the different control key combinations - switch (kc) { - case Common::KEYCODE_i: - // Mouse to inventory - warning("TODO: Mouse to inventory"); - break; - - case Common::KEYCODE_k: - // Toggle hotspots - warning("TODO: Toggle hotspots"); - break; - - case Common::KEYCODE_p: - // Player stats - warning("TODO: Player stats"); - break; - - case Common::KEYCODE_q: - // Quit game - break; - - case Common::KEYCODE_s: - // Activate sound - warning("TODO: Activate sound"); - break; - - case Common::KEYCODE_u: - // Rotate player - warning("TODO: Rotate player"); - break; - - case Common::KEYCODE_v: { - // Release version - Dialog *dlg = new Dialog(_vm, GameReleaseInfoStr, GameReleaseTitleStr); - _vm->_viewManager->addView(dlg); - _vm->_viewManager->moveToFront(dlg); - return false; - } - - default: - break; - } - } else if ((flags & Common::KBD_ALT) && (kc == Common::KEYCODE_q)) { - // Quit Game - - } else { - // Standard keypresses - switch (kc) { - case Common::KEYCODE_F2: - // Save game - _madsVm->globals()->dialogType = DIALOG_SAVE; - leaveScene(); - break; - case Common::KEYCODE_F3: - // Restore game - _madsVm->globals()->dialogType = DIALOG_RESTORE; - leaveScene(); - break; - } - } -//DIALOG_OPTIONS - return false; -} - -void MadsInterfaceView::leaveScene() { - // Close the scene - View *view = _madsVm->_viewManager->getView(VIEWID_SCENE); - _madsVm->_viewManager->deleteView(view); -} - } // End of namespace M4 diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 6f264312d1..31b8cd891f 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -34,11 +34,6 @@ namespace M4 { -#define MADS_SURFACE_WIDTH 320 -#define MADS_SURFACE_HEIGHT 156 -#define MADS_SCREEN_HEIGHT 200 -#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2) - class MadsView; enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2}; @@ -372,9 +367,7 @@ protected: public: Animation(MadsM4Engine *vm); virtual ~Animation(); - void loadFullScreen(const Common::String &filename); - - virtual void load(const Common::String &filename) = 0; + virtual void load(const Common::String &filename, uint16 flags, M4Surface *walkSurface, M4Surface *sceneSurface) = 0; virtual void start() = 0; virtual bool update() = 0; virtual void stop() = 0; @@ -386,7 +379,7 @@ class MadsView { private: View *_view; public: - Animation &_sceneAnimation; + Animation *_sceneAnimation; MadsSpriteSlots _spriteSlots; MadsTextDisplay _textDisplay; MadsKernelMessageList _kernelMessages; @@ -408,60 +401,11 @@ public: M4Surface *_bgSurface; public: MadsView(View *view); + ~MadsView(); void refresh(); }; -#define CHEAT_SEQUENCE_MAX 8 - -class IntegerList : public Common::Array<int> { -public: - int indexOf(int v) { - for (uint i = 0; i < size(); ++i) - if (operator [](i) == v) - return i; - return -1; - } -}; - -enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; - -enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12, - INVLIST_START = 13, VOCAB_START = 18}; - -class MadsInterfaceView : public GameInterfaceView { -private: - IntegerList _inventoryList; - RectList _screenObjects; - int _highlightedElement; - int _topIndex; - uint32 _nextScrollerTicks; - int _cheatKeyCtr; - - // Object display fields - int _selectedObject; - SpriteAsset *_objectSprites; - RGBList *_objectPalData; - int _objectFrameNumber; - - void setFontMode(InterfaceFontMode newMode); - bool handleCheatKey(int32 keycode); - bool handleKeypress(int32 keycode); - void leaveScene(); -public: - MadsInterfaceView(MadsM4Engine *vm); - ~MadsInterfaceView(); - - virtual void initialise(); - virtual void setSelectedObject(int objectNumber); - virtual void addObjectToInventory(int objectNumber); - int getSelectedObject() { return _selectedObject; } - int getInventoryObject(int objectIndex) { return _inventoryList[objectIndex]; } - - void onRefresh(RectList *rects, M4Surface *destSurface); - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - } #endif |