diff options
-rw-r--r-- | engines/mads/animation.cpp | 242 | ||||
-rw-r--r-- | engines/mads/animation.h | 83 | ||||
-rw-r--r-- | engines/mads/font.cpp | 6 | ||||
-rw-r--r-- | engines/mads/font.h | 5 | ||||
-rw-r--r-- | engines/mads/graphics.h | 1 | ||||
-rw-r--r-- | engines/mads/scene.cpp | 1 | ||||
-rw-r--r-- | engines/mads/scene.h | 3 | ||||
-rw-r--r-- | engines/mads/scene_data.cpp | 35 | ||||
-rw-r--r-- | engines/mads/scene_data.h | 8 | ||||
-rw-r--r-- | engines/mads/sound.cpp | 4 | ||||
-rw-r--r-- | engines/mads/sound.h | 5 |
11 files changed, 384 insertions, 9 deletions
diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index f5144c3c49..dd62e7b0f0 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -21,17 +21,255 @@ */ #include "mads/animation.h" +#include "mads/compression.h" + +#define FILENAME_SIZE 64 namespace MADS { + +AAHeader::AAHeader(Common::SeekableReadStream *f) { + _spriteListCount = f->readUint16LE(); + _miscEntriesCount = f->readUint16LE(); + _frameEntriesCount = f->readUint16LE(); + _messagesCount = f->readUint16LE(); + f->skip(1); + _flags = f->readByte(); + + f->skip(2); + _animMode = f->readUint16LE(); + _roomNumber = f->readUint16LE(); + f->skip(2); + _field12 = f->readUint16LE() != 0; + _spriteListIndex = f->readUint16LE(); + _scrollPosition.x = f->readSint16LE(); + _scrollPosition.y = f->readSint16LE(); + _scrollTicks = f->readUint16LE(); + f->skip(8); + + char buffer[FILENAME_SIZE]; + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _interfaceFile = Common::String(buffer); + + for (int i = 0; i < 10; ++i) { + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _spriteSetNames[i] = Common::String(buffer); + } + + f->skip(81); + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _lbmFilename = Common::String(buffer); + + f->skip(365); + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _spritesFilename = Common::String(buffer); + + f->skip(48); + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _soundName = Common::String(buffer); + + f->skip(13); + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _dsrName = Common::String(buffer); + + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + Common::String fontResource(buffer); +} + +/*------------------------------------------------------------------------*/ + +void AnimMessage::load(Common::SeekableReadStream *f) { + _soundId = f->readSint16LE(); + + char buffer[64]; + f->read(&buffer[0], 64); + _msg = Common::String(buffer); + f->skip(4); + _pos.x = f->readSint16LE(); + _pos.y = f->readSint16LE(); + _flags = f->readUint16LE(); + _rgb1[0] = f->readByte() << 2; + _rgb1[1] = f->readByte() << 2; + _rgb1[2] = f->readByte() << 2; + _rgb2[0] = f->readByte() << 2; + _rgb2[1] = f->readByte() << 2; + _rgb2[2] = f->readByte() << 2; + f->skip(2); // Space for kernelMsgIndex + _kernelMsgIndex = -1; + f->skip(6); + _startFrame = f->readUint16LE(); + _endFrame = f->readUint16LE(); + f->skip(2); +} + +void AnimFrameEntry::load(Common::SeekableReadStream *f) { + _frameNumber = f->readUint16LE(); + _seqIndex = f->readByte(); + _spriteSlot._spritesIndex = f->readByte(); + _spriteSlot._frameNumber = f->readUint16LE(); + _spriteSlot._position.x = f->readSint16LE(); + _spriteSlot._position.y = f->readSint16LE(); + _spriteSlot._depth = f->readSByte(); + _spriteSlot._scale = (int8)f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +void AnimMiscEntry::load(Common::SeekableReadStream *f) { + _soundId = f->readByte(); + _msgIndex = f->readSByte(); + _numTicks = f->readUint16LE(); + _posAdjust.x = f->readSint16LE(); + _posAdjust.y = f->readSint16LE(); + _scrollPos.x = f->readSint16LE(); + _scrollPos.y = f->readSint16LE(); +} + +/*------------------------------------------------------------------------*/ Animation *Animation::init(MADSEngine *vm, Scene *scene) { return new Animation(vm, scene); } -void Animation::load(MSurface *sceneSurface, MSurface *interfaceSurface, int sceneId, - int flags, byte *palette, SceneInfo *sceneInfo) { +void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface, + const Common::String &resName, int flags, Common::Array<RGB4> *palAnimData, + SceneInfo *sceneInfo) { + Common::String resourceName = resName; + if (!resourceName.contains(".")) + resourceName += ".AA"; + + File f(resourceName); + MadsPack madsPack(&f); + Common::SeekableReadStream *stream = madsPack.getItemStream(0); + AAHeader aaHeader(stream); + delete stream; + + if (aaHeader._animMode == 4) + flags |= 0x4000; + + if (flags & 0x100) { + loadInterface(interfaceSurface, depthSurface, aaHeader, flags, palAnimData, sceneInfo); + } + if (flags & 0x200) { + // No data + aaHeader._messagesCount = 0; + aaHeader._frameEntriesCount = 0; + aaHeader._miscEntriesCount = 0; + } + + // Initialize the reference list + for (int i = 0; i < aaHeader._spriteListCount; ++i) + _spriteListIndexes.push_back(-1); + + if (aaHeader._messagesCount > 0) { + // Chunk 2: Following is a list of any messages for the animation + Common::SeekableReadStream *msgStream = madsPack.getItemStream(1); + + for (int i = 0; i < aaHeader._messagesCount; ++i) { + AnimMessage rec; + rec.load(msgStream); + _messages.push_back(rec); + } + + delete msgStream; + } + + if (aaHeader._frameEntriesCount > 0) { + // Chunk 3: animation frame info + Common::SeekableReadStream *frameStream = madsPack.getItemStream(2); + + for (int i = 0; i < aaHeader._frameEntriesCount; i++) { + AnimFrameEntry rec; + rec.load(frameStream); + _frameEntries.push_back(rec); + } + + delete frameStream; + } + + if (aaHeader._miscEntriesCount > 0) { + // Chunk 4: Misc Data + Common::SeekableReadStream *miscStream = madsPack.getItemStream(3); + + for (int i = 0; i < aaHeader._miscEntriesCount; ++i) { + AnimMiscEntry rec; + rec.load(miscStream); + _miscEntries.push_back(rec); + } + + delete miscStream; + } + /* + // If the animation specifies a font, then load it for access + if (_flags & ANIM_CUSTOM_FONT) { + Common::String fontName; + if (madsRes) + fontName += "*"; + fontName += fontResource; + + if (fontName != "") + _font = _vm->_font->getFont(fontName.c_str()); + else + warning("Attempted to set a font with an empty name"); + } + + // If a speech file is specified, then load it + if (!_dsrName.empty()) + _vm->_sound->loadDSRFile(_dsrName.c_str()); + + // Load all the sprite sets for the animation + for (int i = 0; i < spriteListCount; ++i) { + if (_field12 && (i == _spriteListIndex)) + // Skip over field, since it's manually loaded + continue; + + _spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str()); + } + + + if (_field12) { + Common::String resName; + if (madsRes) + resName += "*"; + resName += _spriteSetNames[_spriteListIndex]; + + _spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str()); + } + */ + f.close(); } +void Animation::loadInterface(InterfaceSurface &interfaceSurface, MSurface &depthSurface, + AAHeader &header, int flags, Common::Array<RGB4> *palAnimData, SceneInfo *sceneInfo) { + _scene->_depthStyle = 0; + if (header._animMode <= 2) { + sceneInfo->load(header._roomNumber, flags, header._interfaceFile, 0, depthSurface, interfaceSurface); + _scene->_depthStyle = sceneInfo->_depthStyle == 2 ? 1 : 0; + if (palAnimData) { + palAnimData->clear(); + for (uint i = 0; i < sceneInfo->_palAnimData.size(); ++i) + palAnimData->push_back(sceneInfo->_palAnimData[i]); + } + } + else if (header._animMode == 4) { + // Load a scene interface + Common::String resourceName = "*" + header._interfaceFile; + interfaceSurface.load(_vm, resourceName); + + if (palAnimData) + palAnimData->clear(); + } + else { + // Original has useless code here + } +} + } // End of namespace MADS diff --git a/engines/mads/animation.h b/engines/mads/animation.h index cc46143b32..1e542da590 100644 --- a/engines/mads/animation.h +++ b/engines/mads/animation.h @@ -31,23 +31,102 @@ namespace MADS { +enum AnimFlag { ANIM_CUSTOM_FONT = 0x20 }; + class MADSEngine; class Scene; +class AnimMessage { +public: + int16 _soundId; + Common::String _msg; + Common::Point _pos; + byte _rgb1[3], _rgb2[3]; + int _flags; + int _startFrame, _endFrame; + int _kernelMsgIndex; + + /** + * Loads data for the message from a stream + */ + void load(Common::SeekableReadStream *f); +}; + +class AnimFrameEntry { +public: + int _frameNumber; + int _seqIndex; + SpriteSlotSubset _spriteSlot; + + /** + * Loads data for the record + */ + void load(Common::SeekableReadStream *f); +}; + +class AnimMiscEntry { +public: + int _soundId; + int _msgIndex; + int _numTicks; + Common::Point _posAdjust; + Common::Point _scrollPos; + + /** + * Loads data for the record + */ + void load(Common::SeekableReadStream *f); +}; + +class AAHeader { +public: + int _spriteListCount; + int _miscEntriesCount; + int _frameEntriesCount; + int _messagesCount; + byte _flags; + int _animMode; + int _roomNumber; + int _field12; + int _spriteListIndex; + Common::Point _scrollPosition; + uint32 _scrollTicks; + Common::String _interfaceFile; + Common::StringArray _spriteSetNames; + Common::String _lbmFilename; + Common::String _spritesFilename; + Common::String _soundName; + Common::String _dsrName; + Common::String _fontResource; + + /** + * Loads the data for a animation file header + */ + AAHeader(Common::SeekableReadStream *f); +}; + class Animation { private: MADSEngine *_vm; Scene *_scene; + + void loadInterface(InterfaceSurface &interfaceSurface, MSurface &depthSurface, + AAHeader &header, int flags, Common::Array<RGB4> *palAnimData, SceneInfo *sceneInfo); protected: Animation(MADSEngine *vm, Scene *scene) : _vm(vm), _scene(scene) {} public: static Animation *init(MADSEngine *vm, Scene *scene); public: + Common::Array<int> _spriteListIndexes; + Common::Array<AnimMessage> _messages; + Common::Array<AnimFrameEntry> _frameEntries; + Common::Array<AnimMiscEntry> _miscEntries; +public: /** * Loads animation data */ - void load(MSurface *sceneSurface, MSurface *interfaceSurface, int sceneId, int flags, - byte *palette, SceneInfo *sceneInfo); + void load(MSurface &depthSurface, InterfaceSurface &interfaceSurface, const Common::String &resName, + int flags, Common::Array<RGB4> *palAnimData, SceneInfo *sceneInfo); }; } // End of namespace MADS diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp index 52541500c9..10d51fbbc0 100644 --- a/engines/mads/font.cpp +++ b/engines/mads/font.cpp @@ -205,4 +205,10 @@ int Font::getBpp(int charWidth) { return 1; } +Font *Font::getFont(const Common::String &fontName) { + Font *font = new Font(_vm); + font->setFont(fontName); + return font; +} + } // End of namespace MADS diff --git a/engines/mads/font.h b/engines/mads/font.h index 3deb3f4d2d..c642831952 100644 --- a/engines/mads/font.h +++ b/engines/mads/font.h @@ -68,6 +68,11 @@ public: int writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, int width = 0, int spaceWidth = -1) { return write(surface, msg, pt, width, spaceWidth, _fontColors); } + + /** + * Returns a new Font instance using the specified font name + */ + Font *getFont(const Common::String &fontName); }; } // End of namespace MADS diff --git a/engines/mads/graphics.h b/engines/mads/graphics.h index 87cd8be3c9..cadbbc8e8e 100644 --- a/engines/mads/graphics.h +++ b/engines/mads/graphics.h @@ -29,7 +29,6 @@ namespace MADS { #define MADS_SCREEN_WIDTH 320 #define MADS_SCREEN_HEIGHT 200 -#define MADS_INTERFACE_HEIGHT 44 } // End of namespace MADS diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index eaa1cab7fa..e6c02b89e0 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -37,6 +37,7 @@ Scene::Scene(MADSEngine *vm): _vm(vm), _spriteSlots(vm) { _sceneInfo = nullptr; _animFlag = false; _animVal1 = 0; + _depthStyle = 0; _verbList.push_back(VerbInit(VERB_LOOK, 2, 0)); _verbList.push_back(VerbInit(VERB_TAKE, 2, 0)); diff --git a/engines/mads/scene.h b/engines/mads/scene.h index 7a7959e917..2c5880a405 100644 --- a/engines/mads/scene.h +++ b/engines/mads/scene.h @@ -80,7 +80,7 @@ public: SceneInfo *_sceneInfo; MSurface _backgroundSurface; MSurface _depthSurface; - MSurface _interfaceSurface; + InterfaceSurface _interfaceSurface; bool _animFlag; int _animVal1; int _animCount; @@ -89,6 +89,7 @@ public: SceneNodeList _nodes; Common::StringArray _vocabStrings; Animation *_animation; + int _depthStyle; /** * Constructor diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index 07a2ae856d..cec3e457a0 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -24,6 +24,7 @@ #include "mads/scene_data.h" #include "mads/mads.h" #include "mads/compression.h" +#include "mads/graphics.h" #include "mads/resources.h" #include "mads/nebular/nebular_scenes.h" @@ -214,6 +215,34 @@ void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) { /*------------------------------------------------------------------------*/ +void InterfaceSurface::load(MADSEngine *vm, const Common::String &resName) { + File f(resName); + MadsPack madsPack(&f); + + // Load in the palette + Common::SeekableReadStream *palStream = madsPack.getItemStream(0); + + RGB4 *gamePalP = &vm->_palette->_gamePalette[0]; + byte *palP = &vm->_palette->_mainPalette[0]; + + for (int i = 0; i < 16; ++i, gamePalP++, palP += 3) { + palP[0] = palStream->readByte(); + palP[1] = palStream->readByte(); + palP[2] = palStream->readByte(); + gamePalP->r |= 1; + palStream->skip(3); + } + delete palStream; + + // set the size for the interface + setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT); + Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1); + pixelsStream->read(getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT); + delete pixelsStream; +} + +/*------------------------------------------------------------------------*/ + SceneInfo *SceneInfo::init(MADSEngine *vm) { if (vm->getGameID() == GType_RexNebular) { return new SceneInfoNebular(vm); @@ -356,7 +385,7 @@ void SceneInfo::load(int sceneId, int v1, const Common::String &resName, artFile.close(); Common::Array<SpriteAsset *> spriteSets; - Common::Array<int> xpList; + Common::Array<int> indexList; if (flags & 1) { for (uint i = 0; i < setNames.size(); ++i) { @@ -367,11 +396,11 @@ void SceneInfo::load(int sceneId, int v1, const Common::String &resName, SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags); spriteSets.push_back(sprites); - xpList.push_back(-1); // TODO:: sprites->_field6 + indexList.push_back(-1); // TODO:: sprites->_field6 } } - warning("TODO: sub_201E4(xpList, namesCount, &pal data2"); + warning("TODO: sub_201E4(indexList, namesCount, &pal data2"); for (uint i = 0; i < spriteInfo.size(); ++i) { SpriteInfo &si = spriteInfo[i]; diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h index c646215bbf..23eee3403f 100644 --- a/engines/mads/scene_data.h +++ b/engines/mads/scene_data.h @@ -54,6 +54,9 @@ enum MadsActionMode { ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, AC enum MadsActionMode2 { ACTMODE2_0 = 0, ACTMODE2_2 = 2, ACTMODE2_4 = 4, ACTMODE2_5 = 5 }; enum AbortTimerMode { ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2 }; +#define MADS_INTERFACE_HEIGHT 44 +#define MADS_SCENE_HEIGHT (MADS_SCREEN_HEIGHT - MADS_INTERFACE_HEIGHT) + #define DEPTH_BANDS_SIZE 15 #define MAX_ROUTE_NODES 22 @@ -294,6 +297,11 @@ public: }; typedef Common::Array<SceneNode> SceneNodeList; +class InterfaceSurface : public MSurface { +public: + void load(MADSEngine *vm, const Common::String &resName); +}; + /** * Handles general data for a given scene */ diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp index ea0239076b..ae338461ec 100644 --- a/engines/mads/sound.cpp +++ b/engines/mads/sound.cpp @@ -90,6 +90,10 @@ void SoundManager::startQueuedCommands() { } } +void SoundManager::loadDSRFile(const Common::String &filename) { + error("TODO: SoundManager::loadDSRFile"); +} + void SoundManager::command(int commandId, int param) { if (_newSoundsPaused) { if (_queuedCommands.size() < 8) diff --git a/engines/mads/sound.h b/engines/mads/sound.h index 0fd9ac1095..1fe322d6fb 100644 --- a/engines/mads/sound.h +++ b/engines/mads/sound.h @@ -77,6 +77,11 @@ public: */ void startQueuedCommands(); + /** + * Loads a DSR resource + */ + void loadDSRFile(const Common::String &filename); + //@{ /** * Executes a command on the sound driver |