From e11afdeab5534158c2005c23084fc278c30b0695 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 30 Apr 2010 11:27:42 +0000 Subject: [PATCH] Added proper names for some of the previous unknown timer fields, and bugfixes for the sequence list methods svn-id: r48875 --- engines/m4/assets.cpp | 2 +- engines/m4/m4.cpp | 1 + engines/m4/m4.h | 3 +- engines/m4/mads_logic.cpp | 12 ++--- engines/m4/mads_logic.h | 2 +- engines/m4/mads_menus.cpp | 2 +- engines/m4/mads_scene.cpp | 18 +------ engines/m4/mads_views.cpp | 111 +++++++++++++++++++++++++++++--------- engines/m4/mads_views.h | 22 ++++---- 9 files changed, 111 insertions(+), 62 deletions(-) diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index fa0ec9af343..e6040199016 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -227,7 +227,7 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre frame.w = spriteStream->readUint16LE(); frame.h = spriteStream->readUint16LE(); if (curFrame == 0) - printf("%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h); + debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h); frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false); _frames.push_back(frame); diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 4411a808ca9..f6130648888 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -115,6 +115,7 @@ MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) : SearchMan.addSubDirectoryMatching(_gameDataDir, "resource"); DebugMan.addDebugChannel(kDebugScript, "script", "Script debug level"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics debug level"); DebugMan.addDebugChannel(kDebugConversations, "conversations", "Conversations debugging"); _resourceManager = NULL; diff --git a/engines/m4/m4.h b/engines/m4/m4.h index f732bdd5591..1f34bd36852 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -113,7 +113,8 @@ enum { enum { kDebugScript = 1 << 0, - kDebugConversations = 2 << 0 + kDebugConversations = 1 << 1, + kDebugGraphics = 1 << 2 }; #define MESSAGE_BASIC 1 diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index a0f72725338..9341dbcd8d2 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -83,16 +83,16 @@ uint16 MadsSceneLogic::startSpriteSequence(uint16 srcSpriteIdx, int v0, int numT spriteFrame->y + (spriteFrame->height() / 2)); return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, - -1, 100, (int)pixel - 1, 1, 1, 0, 0); + -1, 100, (int)pixel - 1, 1, ANIMTYPE_SINGLE_DIRECTION, 0, 0); } -uint16 MadsSceneLogic::startSpriteSequence2(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks) { +uint16 MadsSceneLogic::startCycledSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks) { M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(1); uint8 pixel = *_madsVm->scene()->getWalkSurface()->getBasePtr(spriteFrame->x + (spriteFrame->width() / 2), spriteFrame->y + (spriteFrame->height() / 2)); return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, - -1, 100, (int)pixel - 1, 1, 2, 0, 0); + -1, 100, (int)pixel - 1, 1, ANIMTYPE_CYCLED, 0, 0); } uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks) { @@ -101,7 +101,7 @@ uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, int v0, int num spriteFrame->y + (spriteFrame->height() / 2)); return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, - -1, 100, (int)pixel - 1, -1, 1, 0, 0); + -1, 100, (int)pixel - 1, -1, ANIMTYPE_SINGLE_DIRECTION, 0, 0); } void MadsSceneLogic::activateHotspot(int idx, bool active) { @@ -165,7 +165,7 @@ void MadsSceneLogic::selectScene(int sceneNum) { void MadsSceneLogic::setupScene() { // FIXME: This is the hardcoded logic for Rex scene 101 only const char *animName = formAnimName('A', -1); -warning("anim - %s\n", animName); + // sub_1e754(animName, 3); getSceneSpriteSet(); @@ -189,7 +189,7 @@ void MadsSceneLogic::enterScene() { _madsVm->scene()->_sequenceList.unk2(0, 2, 7, 0x46); - _spriteIndexes[18] = startSpriteSequence2(_spriteIndexes[3], 0, 10, 0, 0, 60); + _spriteIndexes[18] = startCycledSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60); _spriteIndexes[19] = startSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0); _spriteIndexes[20] = startSpriteSequence(_spriteIndexes[5], 0, 10, 0, 2, 0); _spriteIndexes[21] = startSpriteSequence(_spriteIndexes[6], 0, 6, 0, 0, 0); diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h index 88f8c6e9283..5c66da48fd8 100644 --- a/engines/m4/mads_logic.h +++ b/engines/m4/mads_logic.h @@ -36,7 +36,7 @@ private: // Library interface methods uint16 loadSpriteSet(uint16 suffixNum, uint16 sepChar); uint16 startSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks); - uint16 startSpriteSequence2(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks); + uint16 startCycledSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks); uint16 startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks); void activateHotspot(int idx, bool active); void lowRoomsEntrySound(); diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index d3944e2ff4b..802eb4690aa 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -697,7 +697,7 @@ void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) { refreshText(); // Handle the drawing of the various Mads elements - refresh(rects); + refresh(); View::onRefresh(rects, destSurface); } diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 4b6e03b7bcb..39279573ded 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -263,26 +263,10 @@ void MadsScene::setAction(int action, int objectId) { * Draws all the elements of the scene */ void MadsScene::drawElements() { - // Display animations - _spriteSlots.draw(this); - - // Text display - _textDisplay.draw(this); + refresh(); // Copy the user interface surface onto the surface _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height()); - -/* - // 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; - } - }*/ } diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 9fcd89b895c..57dd3523d4e 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -36,14 +36,26 @@ namespace M4 { -static const int INV_ANIM_FRAME_SPEED = 8; +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; //-------------------------------------------------------------------------- +MadsSpriteSlots::MadsSpriteSlots() { + for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) { + MadsSpriteSlot rec; + _entries.push_back(rec); + } + + startIndex = 0; +} + int MadsSpriteSlots::getIndex() { + if (startIndex == SPRITE_SLOTS_SIZE) + error("Run out of sprite slots"); + return startIndex++; } @@ -97,7 +109,7 @@ void MadsSpriteSlots::draw(View *view) { // Sort the list in order of the depth Common::sort(depthList.begin(), depthList.end(), sortHelper); - // Loop through each of the objectes + // Loop through each of the objects DepthList::iterator i; for (i = depthList.begin(); i != depthList.end(); ++i) { DepthEntry &de = *i; @@ -131,6 +143,29 @@ void MadsSpriteSlots::draw(View *view) { } } +/** + * Removes any sprite slots that are no longer needed + */ +void MadsSpriteSlots::cleanUp() { + // Delete any entries that aren't needed + int idx = 0; + while (idx < startIndex) { + if (_entries[idx].spriteId >= 0) { + _entries.remove_at(idx); + --startIndex; + } else { + ++idx; + } + } + + // Original engine sprite slot list was a fixed array, so to keep the engine similiar, for + // now I'm adding in new entries to make up the original fixed total again + while (_entries.size() < SPRITE_SLOTS_SIZE) { + MadsSpriteSlot rec; + _entries.push_back(rec); + } +} + //-------------------------------------------------------------------------- MadsTextDisplay::MadsTextDisplay() { @@ -191,6 +226,18 @@ void MadsTextDisplay::draw(View *view) { } } +/** + * Deactivates any text display entries that are finished + */ +void MadsTextDisplay::cleanUp() { + for (uint idx = 0; idx < _entries.size(); ++idx) { + if (_entries[idx].expire < 0) { + _entries[idx].active = false; + _entries[idx].expire = 0; + } + } +} + //-------------------------------------------------------------------------- /** @@ -341,8 +388,8 @@ bool MadsSequenceList::unk2(int index, int v1, int v2, int v3) { } int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, char field_24, int timeoutTicks, int extraTicks, int numTicks, - int height, int width, char field_12, char scale, char depth, int frameStart, int field_A, int numSprites, - int spriteNum) { + int height, int width, char field_12, char scale, char depth, int frameInc, SpriteAnimType animType, int numSprites, + int frameStart) { // Find a free slot uint timerIndex = 0; @@ -351,22 +398,22 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, char fiel if (timerIndex == _entries.size()) error("TimerList full"); - if (spriteNum <= 0) - spriteNum = 1; + if (frameStart <= 0) + frameStart = 1; if (numSprites == 0) numSprites = _madsVm->scene()->_spriteSlots.getSprite(spriteListIndex).getCount(); - if (spriteNum == numSprites) - frameStart = 0; + if (frameStart == numSprites) + frameInc = 0; // Set the list entry fields _entries[timerIndex].active = true; _entries[timerIndex].spriteListIndex = spriteListIndex; _entries[timerIndex].field_2 = v0; _entries[timerIndex].frameIndex = frameIndex; - _entries[timerIndex].spriteNum = spriteNum; - _entries[timerIndex].numSprites = numSprites; - _entries[timerIndex].field_A = field_A; _entries[timerIndex].frameStart = frameStart; + _entries[timerIndex].numSprites = numSprites; + _entries[timerIndex].animType = animType; + _entries[timerIndex].frameInc = frameInc; _entries[timerIndex].depth = depth; _entries[timerIndex].scale = scale; _entries[timerIndex].field_12 = field_12; @@ -405,7 +452,7 @@ void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) SpriteAsset &sprite = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex); // TODO: Figure out logic for spriteId value based on SPRITE_SLOT.field_0 - spriteSlot.spriteId = (0 /*field 0*/ == 1) ? 0xFFFC : 1; + spriteSlot.spriteId = (0 /*field 0*/ == 1) ? -4 : 1; spriteSlot.timerIndex = timerIndex; spriteSlot.spriteListIndex = timerEntry.spriteListIndex; spriteSlot.frameNumber = ((timerEntry.field_2 == 1) ? 0x8000 : 0) | timerEntry.frameIndex; @@ -416,8 +463,8 @@ void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) spriteSlot.xp = timerEntry.width; spriteSlot.yp = timerEntry.height; } else { - spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex)->x; - spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex)->y; + spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex - 1)->x; + spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex - 1)->y; } } @@ -443,7 +490,7 @@ bool MadsSequenceList::loadSprites(int timerIndex) { if ((timerEntry.field_13 != 0) || (timerEntry.dynamicHotspotIndex >= 0)) { SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex); - M4Sprite *frame = spriteSet.getFrame(timerEntry.frameIndex); + M4Sprite *frame = spriteSet.getFrame(timerEntry.frameIndex - 1); int width = frame->width() * timerEntry.scale / 200; int height = frame->height() * timerEntry.scale / 100; @@ -464,26 +511,32 @@ bool MadsSequenceList::loadSprites(int timerIndex) { } // Frame adjustments - if (timerEntry.numSprites != timerEntry.spriteNum) - timerEntry.frameIndex += timerEntry.frameStart; + if (timerEntry.frameStart != timerEntry.numSprites) + timerEntry.frameIndex += timerEntry.frameInc; - if (timerEntry.frameIndex >= timerEntry.spriteNum) { + if (timerEntry.frameIndex >= timerEntry.frameStart) { if (timerEntry.frameIndex > timerEntry.numSprites) { result = true; - if (timerEntry.field_A != 2) { - timerEntry.frameIndex = timerEntry.spriteNum; + if (timerEntry.animType != ANIMTYPE_CYCLED) { + // Keep index from exceeding maximum allowed + timerEntry.frameIndex = timerEntry.frameStart; } else { + // Switch into reverse timerEntry.frameIndex = timerEntry.numSprites - 1; - timerEntry.frameStart = -1; + timerEntry.frameInc = -1; } } } else { + // Currently in reverse mode result = true; - if (timerEntry.field_A == 2) { - timerEntry.frameIndex = timerEntry.spriteNum + 1; - timerEntry.frameStart = 1; + if (timerEntry.animType == ANIMTYPE_CYCLED) + { + // Switch back to forward direction again + timerEntry.frameIndex = timerEntry.frameStart + 1; + timerEntry.frameInc = 1; } else { + // Otherwise reset back to last sprite for further reverse animating timerEntry.frameIndex = timerEntry.numSprites; } } @@ -511,7 +564,7 @@ bool MadsSequenceList::loadSprites(int timerIndex) { } if (idx >= 0) { - _owner._abortTimers = timerEntry.fld36[idx]; + //_owner._abortTimers = timerEntry.fld36[idx]; // TODO: Figure out word_84208, timerEntry.field_3B[] } @@ -558,12 +611,18 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL _abortTimers2 = 0; } -void MadsView::refresh(RectList *rects) { +void MadsView::refresh() { // Draw any sprites _spriteSlots.draw(_view); // Draw text elements onto the view _textDisplay.draw(_view); + + // Remove any sprite slots that are no longer needed + _spriteSlots.cleanUp(); + + // Deactivate any text display entries that are no longer needed + _textDisplay.cleanUp(); } /*-------------------------------------------------------------------------- diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index a1d07c97f0e..50ce9e1aabc 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -60,12 +60,12 @@ typedef Common::Array > SpriteList; class MadsSpriteSlots { private: - MadsSpriteSlot _entries[SPRITE_SLOTS_SIZE]; + Common::Array _entries; SpriteList _sprites; public: int startIndex; - MadsSpriteSlots() { startIndex = 0; } + MadsSpriteSlots(); MadsSpriteSlot &operator[](int idx) { assert(idx < SPRITE_SLOTS_SIZE); @@ -85,6 +85,7 @@ public: void deleteTimer(int timerIndex); void draw(View *view); + void cleanUp(); }; class MadsTextDisplayEntry { @@ -122,6 +123,7 @@ public: int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font); void clear(); void draw(View *view); + void cleanUp(); }; class ScreenObjectEntry { @@ -191,6 +193,8 @@ public: #define TIMER_ENTRY_SUBSET_MAX 5 +enum SpriteAnimType {ANIMTYPE_SINGLE_DIRECTION = 1, ANIMTYPE_CYCLED = 2}; + struct MadsSequenceEntry { int8 active; int8 spriteListIndex; @@ -198,11 +202,11 @@ struct MadsSequenceEntry { int field_2; int frameIndex; - int spriteNum; - int numSprites; - - int field_A; int frameStart; + int numSprites; + + SpriteAnimType animType; + int frameInc; int depth; int scale; @@ -240,8 +244,8 @@ public: MadsSequenceEntry &operator[](int index) { return _entries[index]; } bool unk2(int index, int v1, int v2, int v3); int add(int spriteListIndex, int v0, int v1, char field_24, int timeoutTicks, int extraTicks, int numTicks, - int height, int width, char field_12, char scale, char depth, int frameStart, int field_A, - int numSprites, int spriteNum); + int height, int width, char field_12, char scale, char depth, int frameInc, SpriteAnimType animType, + int numSprites, int frameStart); void remove(int timerIndex); void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot); bool loadSprites(int timerIndex); @@ -264,7 +268,7 @@ public: public: MadsView(View *view); - void refresh(RectList *rects); + void refresh(); }; #define CHEAT_SEQUENCE_MAX 8