aboutsummaryrefslogtreecommitdiff
path: root/engines/m4
diff options
context:
space:
mode:
Diffstat (limited to 'engines/m4')
-rw-r--r--engines/m4/animation.cpp28
-rw-r--r--engines/m4/animation.h5
-rw-r--r--engines/m4/console.cpp8
-rw-r--r--engines/m4/graphics.cpp26
-rw-r--r--engines/m4/graphics.h14
-rw-r--r--engines/m4/mads_scene.cpp552
-rw-r--r--engines/m4/mads_scene.h67
-rw-r--r--engines/m4/mads_views.cpp445
-rw-r--r--engines/m4/mads_views.h62
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