diff options
Diffstat (limited to 'engines/m4')
-rw-r--r-- | engines/m4/globals.cpp | 6 | ||||
-rw-r--r-- | engines/m4/globals.h | 1 | ||||
-rw-r--r-- | engines/m4/resource.cpp | 28 | ||||
-rw-r--r-- | engines/m4/resource.h | 3 | ||||
-rw-r--r-- | engines/m4/scene.cpp | 164 | ||||
-rw-r--r-- | engines/m4/scene.h | 51 |
6 files changed, 225 insertions, 28 deletions
diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index 856c1bb817..1ce2f24658 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -511,6 +511,10 @@ bool Player::saidAny(const char *word1, const char *word2, const char *word3, /*--------------------------------------------------------------------------*/ MadsObject::MadsObject(Common::SeekableReadStream *stream) { + load(stream); +} + +void MadsObject::load(Common::SeekableReadStream *stream) { // Get the next data block uint8 obj[0x30]; stream->read(obj, 0x30); @@ -519,7 +523,7 @@ MadsObject::MadsObject(Common::SeekableReadStream *stream) { descId = READ_LE_UINT16(&obj[0]); roomNumber = READ_LE_UINT16(&obj[2]); article = (MADSArticles)obj[4]; - vocabCount = obj[5]; + vocabCount = obj[5] & 0x7f; assert(vocabCount <= 3); for (int i = 0; i < vocabCount; ++i) { diff --git a/engines/m4/globals.h b/engines/m4/globals.h index aee0e6fa9c..6349376643 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -174,6 +174,7 @@ class MadsObject { public: MadsObject() {}; MadsObject(Common::SeekableReadStream *stream); + void load(Common::SeekableReadStream *stream); bool isInInventory() const { return roomNumber == PLAYER_INVENTORY; }; uint16 descId; diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp index a1c5290afa..eee1214e7f 100644 --- a/engines/m4/resource.cpp +++ b/engines/m4/resource.cpp @@ -369,6 +369,34 @@ const char *MADSResourceManager::getResourceName(char asciiCh, int prefix, Exten } /** + * Another variation for forming resource names + */ +const char *MADSResourceManager::getResourceName(ResourcePrefixType prefixType, int idx, const char *extension) { + static char resourceName[100]; + + strcpy(resourceName, "*"); + + if (extension) { + switch (prefixType) { + case RESPREFIX_GL: + strcat(resourceName, "GL000"); + break; + case RESPREFIX_SC: + case RESPREFIX_RM: + strcat(resourceName, (prefixType == RESPREFIX_SC) ? "SC" : "RM"); + sprintf(resourceName + 3, "%.3d", idx); + break; + default: + break; + } + + strcat(resourceName, extension); + } + + return &resourceName[0]; +} + +/** * Forms an AA resource name based on the given passed index */ const char *MADSResourceManager::getAAName(int index) { diff --git a/engines/m4/resource.h b/engines/m4/resource.h index 2c6bacced6..b41b1b0799 100644 --- a/engines/m4/resource.h +++ b/engines/m4/resource.h @@ -115,6 +115,8 @@ enum ResourceType {RESTYPE_ROOM, RESTYPE_SC, RESTYPE_TEXT, RESTYPE_QUO, RESTYPE_ enum ExtensionType {EXTTYPE_SS = 1, EXTTYPE_AA = 2, EXTTYPE_DAT = 3, EXTTYPE_HH = 4, EXTTYPE_ART = 5, EXTTYPE_INT = 6, EXTTYPE_NONE = -1}; +enum ResourcePrefixType {RESPREFIX_GL = 1, RESPREFIX_SC = 2, RESPREFIX_RM = 3}; + class MADSResourceManager : public ResourceManager { private: ResourceType getResourceType(const char *resourceName); @@ -126,6 +128,7 @@ public: bool resourceExists(const char *resourceName); static const char *getResourceName(char asciiCh, int prefix, ExtensionType extType, const char *suffix, int index); + static const char *getResourceName(ResourcePrefixType prefixType, int idx, const char *extension); static const char *getAAName(int index); }; diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp index e70b4d4bd8..3729d17437 100644 --- a/engines/m4/scene.cpp +++ b/engines/m4/scene.cpp @@ -59,6 +59,7 @@ Scene::~Scene() { } void Scene::loadScene(int sceneNumber) { + _previousScene = _currentScene; _currentScene = sceneNumber; // Load scene background and set palette @@ -596,29 +597,21 @@ MadsScene::MadsScene(MadsEngine *vm): Scene(vm) { strcpy(_statusText, ""); _interfaceSurface = new MadsInterfaceView(vm); _currentAction = kVerbNone; + _spriteSlotsStart = 0; } -void MadsScene::loadScene(int sceneNumber) { - // Close the menu if it's active - View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU); - if (mainMenu != NULL) { - _vm->_viewManager->deleteView(mainMenu); - } - - // Handle common scene setting - Scene::loadScene(sceneNumber); - - // Signal the script engine what scene is to be active - _sceneLogic.selectScene(sceneNumber); - _sceneLogic.setupScene(); - - // Add the scene if necessary to the list of scenes that have been visited - _vm->globals()->addVisitedScene(sceneNumber); - +/** + * Secondary scene loading code + */ +void MadsScene::loadScene2(int sceneNumber, const char *aaName) { - // Do any scene specific setup - _sceneLogic.enterScene(); + _sceneInfo.load(sceneNumber); +} +/** + * Existing ScummVM code that needs to be eventually replaced with MADS code + */ +void MadsScene::loadSceneTemporary() { /* Existing code that eventually needs to be replaced with the proper MADS code */ // Set system palette entries _vm->_palette->blockRange(0, 7); @@ -626,11 +619,11 @@ void MadsScene::loadScene(int sceneNumber) { {0x00<<2, 0x10<<2, 0x16<<2, 0}}; _vm->_palette->setPalette(&sysColors[0], 4, 3); - _backgroundSurface->loadBackground(sceneNumber, &_palData); + _backgroundSurface->loadBackground(_currentScene, &_palData); _vm->_palette->addRange(_palData); _backgroundSurface->translate(_palData); - if (sceneNumber < 900) { + if (_currentScene < 900) { /*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT, _backgroundSurface->width(), _backgroundSurface->height()), _vm->_palette->BLACK);*/ @@ -644,19 +637,46 @@ void MadsScene::loadScene(int sceneNumber) { } // Don't load other screen resources for system screens - if (sceneNumber >= 900) + if (_currentScene >= 900) return; - loadSceneHotSpotsMads(sceneNumber); + loadSceneHotSpotsMads(_currentScene); // TODO: set walker scaling // TODO: destroy woodscript buffer // Load scene walk path file (*.COD/*.WW?) - loadSceneCodes(sceneNumber); + loadSceneCodes(_currentScene); // Load inverse color table file (*.IPL) - loadSceneInverseColorTable(sceneNumber); + loadSceneInverseColorTable(_currentScene); +} + +void MadsScene::loadScene(int sceneNumber) { + // Close the menu if it's active + View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU); + if (mainMenu != NULL) { + _vm->_viewManager->deleteView(mainMenu); + } + + // Handle common scene setting + Scene::loadScene(sceneNumber); + + // Signal the script engine what scene is to be active + _sceneLogic.selectScene(sceneNumber); + _sceneLogic.setupScene(); + + // Add the scene if necessary to the list of scenes that have been visited + _vm->globals()->addVisitedScene(sceneNumber); + + // Secondary scene load routine + loadScene2(sceneNumber, "*I0.AA"); + + // Do any scene specific setup + _sceneLogic.enterScene(); + + // Existing ScummVM code that needs to be eventually replaced with MADS code + loadSceneTemporary(); // Purge resources _vm->res()->purge(); @@ -774,9 +794,71 @@ void MadsScene::setStatusText(const char *text) { strcpy(_statusText, text); } +/** + * Draws all the elements of the scene + */ +void MadsScene::drawElements() { + + // Display animations + for (int idx = 0; idx < _spriteSlotsStart; ++idx) { + + } + + + // Text display loop + for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { + if (_textDisplay[idx].active && (_textDisplay[idx].field_A >= 0)) { + _textDisplay[idx].font->setColours(0xFF, (_textDisplay[idx].colour2 == 0) ? + _textDisplay[idx].colour1 : _textDisplay[idx].colour2, _textDisplay[idx].colour1); + _textDisplay[idx].font->writeString(this, _textDisplay[idx].message, + _textDisplay[idx].bounds.left, _textDisplay[idx].bounds.top, + width() - _textDisplay[idx].bounds.left, _textDisplay[idx].spacing); + } + } + + // Copy the user interface surface onto the surface + _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height()); + +/* + // At this point, in the original engine, the dirty/changed areas were copied to the screen. At the moment, + // the current M4 engine framework doesn't support dirty areas, but this is being kept in case that ever changes + for (int idx = 0; idx < DIRTY_AREA_SIZE; ++idx) { + if (_dirtyAreas[idx].active && _dirtyAreas[idx].active2 && + (_dirtyAreas[idx].bounds.width() > 0) && (_dirtyAreas[idx].bounds.height() > 0)) { + // Copy changed area to screen + + } + } +*/ + + // Some kind of copying over of slot entries + for (int idx = 0, idx2 = 0; idx < _spriteSlotsStart; ++idx) { + if (_spriteSlots[idx].spriteId >= 0) { + if (idx != idx2) { + // Copy over the slot entry + _spriteSlots[idx2] = _spriteSlots[idx]; + } + ++idx2; + } + } + + // Clear up any now inactive text display entries + for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { + if (_textDisplay[idx].field_A < 0) { + _textDisplay[idx].active = false; + _textDisplay[idx].field_A = 0; + } + } +} + + void MadsScene::update() { + // Copy the bare scene in _backgroundSurface->copyTo(this); + // Draw all the various elements + drawElements(); + // Handle display of any status text if (_statusText[0]) { // Text colors are inverted in Dragonsphere @@ -789,8 +871,6 @@ void MadsScene::update() { _vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0); } - _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height()); - //***DEBUG*** _sceneSprites[0]->getFrame(1)->copyTo(this, 120, 90, 0); } @@ -833,4 +913,34 @@ void MadsScene::loadPlayerSprites(const char *prefix) { error("Couldn't find player sprites"); } +/*--------------------------------------------------------------------------*/ + +void MadsSceneInfo::load(int sceneId) { + const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneId, ".DAT"); + Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr); + MadsPack sceneInfo(rawStream); + Common::SeekableReadStream *stream = sceneInfo.getItemStream(0); + + int resSceneId = stream->readUint16LE(); + assert(resSceneId == sceneId); + + artFileNum = stream->readUint16LE(); + field_4 = stream->readUint16LE(); + width = stream->readUint16LE(); + height = stream->readUint16LE(); + assert((width == 320) && (height == 156)); + + stream->skip(24); + + objectCount = stream->readUint16LE(); + + stream->skip(40); + + for (int i = 0; i < objectCount; ++i) { + objects[i].load(stream); + } + + _vm->_resourceManager->toss(sceneInfoStr); +} + } // End of namespace M4 diff --git a/engines/m4/scene.h b/engines/m4/scene.h index a0a07bce6a..f94ecc0574 100644 --- a/engines/m4/scene.h +++ b/engines/m4/scene.h @@ -29,6 +29,7 @@ class View; #include "m4/assets.h" +#include "m4/font.h" #include "m4/hotspot.h" #include "m4/graphics.h" #include "m4/viewmgr.h" @@ -90,6 +91,7 @@ private: HotSpotList _sceneHotspots; protected: int _currentScene; + int _previousScene; GameInterfaceView *_interfaceSurface; M4Surface *_backgroundSurface; M4Surface *_codeSurface; @@ -161,8 +163,48 @@ public: M4InterfaceView *getInterface() { return (M4InterfaceView *)_interfaceSurface; }; }; +struct SpriteSlot { + int16 spriteId; + int16 scale; + uint16 spriteListIndex; +}; + +struct TextDisplay { + bool active; + int spacing; + Common::Rect bounds; + int16 field_A; + uint8 colour1, colour2; + Font *font; + char message[100]; +}; + +struct DirtyArea { + bool active; + bool active2; + Common::Rect bounds; +}; + +class MadsSceneInfo { +public: + int sceneId; + int artFileNum; + int field_4; + int width; + int height; + + int objectCount; + MadsObject objects[32]; + + void load(int sceneId); +}; + typedef Common::Array<SpriteAsset *> SpriteAssetArray; +#define SPRITE_SLOTS_SIZE 50 +#define TEXT_DISPLAY_SIZE 40 +#define DIRTY_AREA_SIZE 90 + class MadsScene : public Scene { private: MadsEngine *_vm; @@ -170,8 +212,17 @@ private: int _currentAction; char _statusText[100]; MadsSceneLogic _sceneLogic; + MadsSceneInfo _sceneInfo; SpriteAsset *_playerSprites; SpriteAssetArray _sceneSprites; + SpriteSlot _spriteSlots[50]; + TextDisplay _textDisplay[TEXT_DISPLAY_SIZE]; + DirtyArea _dirtyAreas[DIRTY_AREA_SIZE]; + int _spriteSlotsStart; + + void drawElements(); + void loadScene2(int sceneNumber, const char *aaName); + void loadSceneTemporary(); public: char _aaName[100]; public: |