diff options
-rw-r--r-- | engines/m4/font.h | 6 | ||||
-rw-r--r-- | engines/m4/mads_logic.cpp | 5 | ||||
-rw-r--r-- | engines/m4/mads_scene.cpp | 42 | ||||
-rw-r--r-- | engines/m4/mads_scene.h | 21 | ||||
-rw-r--r-- | engines/m4/mads_views.cpp | 215 | ||||
-rw-r--r-- | engines/m4/mads_views.h | 71 |
6 files changed, 248 insertions, 112 deletions
diff --git a/engines/m4/font.h b/engines/m4/font.h index d675cb6d47..e64f80b70d 100644 --- a/engines/m4/font.h +++ b/engines/m4/font.h @@ -61,6 +61,12 @@ class Font { public: Font(MadsM4Engine *vm); ~Font(); + + Font *getFont(const char *filename) { + // TODO: Proper separation of font instances + setFont(filename); + return this; + } void setFont(const char *filename); void setColor(uint8 color); void setColors(uint8 alt1, uint8 alt2, uint8 foreground); diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 24d225a2a6..9d6c4e169b 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -164,7 +164,8 @@ 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); + const char *animName = formAnimName('A', -1); + warning("anim - %s", animName); // sub_1e754(animName, 3); @@ -187,7 +188,7 @@ void MadsSceneLogic::enterScene() { _spriteIndexes[16] = startSpriteSequence(_spriteIndexes[1], 0, 4, 0, 1, 0); _spriteIndexes[17] = startSpriteSequence(_spriteIndexes[2], 0, 4, 0, 1, 0); - _madsVm->scene()->_sequenceList.unk2(0, 2, 7, 0x46); + _madsVm->scene()->_sequenceList.addSubEntry(0, SM_FRAME_INDEX, 7, 70); _spriteIndexes[18] = startCycledSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60); _spriteIndexes[19] = startSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0); diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 39279573de..efb495e823 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -57,6 +57,12 @@ MadsScene::~MadsScene() { * Secondary scene loading code */ void MadsScene::loadScene2(const char *aaName) { + // TODO: Completely finish + + _spriteSlots.clear(); + _sequenceList.clear(); + _kernelMessages.clear(); + // Load up the properties for the scene _sceneResources.load(_currentScene); @@ -652,42 +658,6 @@ void MadsSceneResources::load(int sId) { * Adds a new entry to the timed on-screen text display list */ /* -int MadsScreenText::addTimed(const Common::Point &destPos, uint fontColours, uint flags, int vUnknown, uint32 timeout, const char *message) { - // Find a free slot - int idx = 0; - while ((idx < TIMED_TEXT_SIZE) && ((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0)) - ++idx; - if (idx == TIMED_TEXT_SIZE) { - if (vUnknown == 0) - return -1; - - error("Ran out of timed text display slots"); - } - - // Set up the entry values - _timedText[idx].flags = flags | TEXTFLAG_ACTIVE; - strcpy(_timedText[idx].message, message); - _timedText[idx].colour1 = fontColours & 0xff; - _timedText[idx].colour2 = fontColours >> 8; - _timedText[idx].position.x = destPos.x; - _timedText[idx].position.y = destPos.y; - _timedText[idx].textDisplayIndex = -1; - _timedText[idx].timeout = timeout; - _timedText[idx].frameTimer = g_system->getMillis(); - _timedText[idx].field_1C = vUnknown; - _timedText[idx].field_1D = 0; // word_84206 - - // Copy the current action noun list - for (int i = 0; i < 3; ++i) - _timedText[idx].actionNouns[i] = _madsVm->scene()->actionNouns[i]; - - if (flags & TEXTFLAG_2) { - warning("word_844b8 and dword_845a0 not yet implemented"); - } - - return idx; -} - void MadsScreenText::draw(M4Surface *surface) { } diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index 43a90b621f..f7625bb761 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -66,27 +66,6 @@ public: void load(int sceneId); }; -#define TIMED_TEXT_SIZE 10 -#define TEXT_4A_SIZE 30 - -enum TalkTextFlags {TEXTFLAG_2 = 2, TEXTFLAG_4 = 4, TEXTFLAG_8 = 8, TEXTFLAG_40 = 0x40, - TEXTFLAG_ACTIVE = 0x80}; - -struct TimedText { - uint8 flags; - int colour1; - int colour2; - Common::Point position; - int textDisplayIndex; - int timerIndex; - uint32 timeout; - uint32 frameTimer; - bool field_1C; - uint8 field_1D; - uint16 actionNouns[3]; - char message[100]; -}; - enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6}; enum MAdsActionMode2 {ACTMODE2_0 = 0, ACTMODE2_2 = 2, ACTMODE2_5 = 5}; diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 57dd3523d4..a99976338b 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -240,6 +240,108 @@ void MadsTextDisplay::cleanUp() { //-------------------------------------------------------------------------- +MadsKernelMessageList::MadsKernelMessageList(MadsView &owner): _owner(owner) { + for (int i = 0; i < TIMED_TEXT_SIZE; ++i) { + MadsKernelMessageListEntry rec; + _entries.push_back(rec); + } + + _owner._textSpacing = -1; + _talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS); +} + +void MadsKernelMessageList::clear() { + for (uint i = 0; i < _entries.size(); ++i) + _entries[i].flags = 0; + + _owner._textSpacing = -1; + _talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS); +} + +int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 v2, uint32 timeout, char *msg) { + // Find a free slot + uint idx = 0; + while ((idx < _entries.size()) && ((_entries[idx].flags & KMSG_ACTIVE) != 0)) + ++idx; + if (idx == _entries.size()) { + if (v2 == 0) + return -1; + + error("MadsKernelList overflow"); + } + + MadsKernelMessageListEntry &rec = _entries[idx]; + rec.msg = msg; + rec.flags = flags | KMSG_ACTIVE; + rec.colour1 = fontColour & 0xff; + rec.colour2 = fontColour >> 8; + rec.position = pt; + rec.textDisplayIndex = -1; + rec.timeout = timeout; + rec.frameTimer = _madsVm->_currentTimer; + rec.field_1C = v2; + rec.abortMode = _owner._abortTimersMode2; + + for (int i = 0; i < 3; ++i) + rec.actionNouns[i] = _madsVm->scene()->actionNouns[i]; + + if (flags & KMSG_2) + rec.frameTimer = _owner._ticksAmount + _owner._newTimeout; + + return idx; +} + +void MadsKernelMessageList::unk1(int msgIndex, int v1, int v2) { + if (msgIndex < 0) + return; + + _entries[msgIndex].flags |= (v2 == 0) ? KMSG_8 : (KMSG_8 | KMSG_1); + _entries[msgIndex].msgOffset = 0; + _entries[msgIndex].field_E = v1; + _entries[msgIndex].frameTimer2 = _madsVm->_currentTimer; + + const char *msgP = _entries[msgIndex].msg; + _entries[msgIndex].asciiChar = *msgP; + _entries[msgIndex].asciiChar2 = *(msgP + 1); + + if (_entries[msgIndex].flags & KMSG_2) + _entries[msgIndex].frameTimer2 = _owner._ticksAmount + _owner._newTimeout; + + _entries[msgIndex].frameTimer = _entries[msgIndex].frameTimer2; +} + +void MadsKernelMessageList::setSeqIndex(int msgIndex, int seqIndex) { + if (msgIndex >= 0) { + _entries[msgIndex].flags |= KMSG_4; + _entries[msgIndex].sequenceIndex = seqIndex; + } +} + +void MadsKernelMessageList::remove(int msgIndex) { + MadsKernelMessageListEntry &rec = _entries[msgIndex]; + + if (rec.flags & KMSG_ACTIVE) { + if (rec.flags & KMSG_8) { + *(rec.msg + rec.msgOffset) = rec.asciiChar; + *(rec.msg + rec.msgOffset + 1) = rec.asciiChar2; + } + + if (rec.textDisplayIndex >= 0) + _owner._textDisplay.expire(rec.textDisplayIndex); + + rec.flags &= ~KMSG_ACTIVE; + } +} + +void MadsKernelMessageList::reset() { + for (uint i = 0; i < _entries.size(); ++i) + remove(i); + + // sub_20454 +} + +//-------------------------------------------------------------------------- + /** * Clears the entries list */ @@ -375,14 +477,21 @@ MadsSequenceList::MadsSequenceList(MadsView &owner): _owner(owner) { } } -bool MadsSequenceList::unk2(int index, int v1, int v2, int v3) { - if (_entries[index].len27 >= TIMER_ENTRY_SUBSET_MAX) +void MadsSequenceList::clear() { + for (uint i = 0; i < _entries.size(); ++i) { + _entries[i].active = 0; + _entries[i].dynamicHotspotIndex = -1; + } +} + +bool MadsSequenceList::addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal) { + if (_entries[index].entries.count >= TIMER_ENTRY_SUBSET_MAX) return true; - int subIndex = _entries[index].len27++; - _entries[index].fld27[subIndex] = v1; - _entries[index].fld2C[subIndex] = v2; - _entries[index].fld36[subIndex] = v3; + int subIndex = _entries[index].entries.count++; + _entries[index].entries.mode[subIndex] = mode; + _entries[index].entries.frameIndex[subIndex] = frameIndex; + _entries[index].entries.abortVal[subIndex] = abortVal; return false; } @@ -428,8 +537,8 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, char fiel _entries[timerIndex].field_25 = 0; _entries[timerIndex].field_13 = 0; _entries[timerIndex].dynamicHotspotIndex = -1; - _entries[timerIndex].len27 = 0; - _entries[timerIndex].field_3B = 0; //word_84206 + _entries[timerIndex].entries.count = 0; + _entries[timerIndex].abortMode = _owner._abortTimersMode2; for (int i = 0; i < 3; ++i) _entries[timerIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i]; @@ -469,37 +578,37 @@ void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) } bool MadsSequenceList::loadSprites(int timerIndex) { - MadsSequenceEntry &timerEntry = _entries[timerIndex]; + MadsSequenceEntry &seqEntry = _entries[timerIndex]; int slotIndex; bool result = false; int idx = -1; _owner._spriteSlots.deleteTimer(timerIndex); - if (timerEntry.field_25 != 0) { + if (seqEntry.field_25 != 0) { remove(timerIndex); return false; } - if (timerEntry.spriteListIndex == -1) { - timerEntry.field_25 = -1; + if (seqEntry.spriteListIndex == -1) { + seqEntry.field_25 = -1; } else if ((slotIndex = _owner._spriteSlots.getIndex()) >= 0) { MadsSpriteSlot &spriteSlot = _owner._spriteSlots[slotIndex]; setSpriteSlot(timerIndex, spriteSlot); int x2 = 0, y2 = 0; - if ((timerEntry.field_13 != 0) || (timerEntry.dynamicHotspotIndex >= 0)) { - SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex); - M4Sprite *frame = spriteSet.getFrame(timerEntry.frameIndex - 1); - int width = frame->width() * timerEntry.scale / 200; - int height = frame->height() * timerEntry.scale / 100; + if ((seqEntry.field_13 != 0) || (seqEntry.dynamicHotspotIndex >= 0)) { + SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex); + M4Sprite *frame = spriteSet.getFrame(seqEntry.frameIndex - 1); + int width = frame->width() * seqEntry.scale / 200; + int height = frame->height() * seqEntry.scale / 100; warning("frame size %d x %d", width, height); // TODO: Missing stuff here, and I'm not certain about the dynamic hotspot stuff below - if (timerEntry.dynamicHotspotIndex >= 0) { - DynamicHotspot &dynHotspot = _owner._dynamicHotspots[timerEntry.dynamicHotspotIndex]; + if (seqEntry.dynamicHotspotIndex >= 0) { + DynamicHotspot &dynHotspot = _owner._dynamicHotspots[seqEntry.dynamicHotspotIndex]; dynHotspot.bounds.left = MAX(x2 - width, 0); dynHotspot.bounds.right = MAX(x2 - width, 319) - dynHotspot.bounds.left + 1; @@ -511,62 +620,70 @@ bool MadsSequenceList::loadSprites(int timerIndex) { } // Frame adjustments - if (timerEntry.frameStart != timerEntry.numSprites) - timerEntry.frameIndex += timerEntry.frameInc; + if (seqEntry.frameStart != seqEntry.numSprites) + seqEntry.frameIndex += seqEntry.frameInc; - if (timerEntry.frameIndex >= timerEntry.frameStart) { - if (timerEntry.frameIndex > timerEntry.numSprites) { + if (seqEntry.frameIndex >= seqEntry.frameStart) { + if (seqEntry.frameIndex > seqEntry.numSprites) { result = true; - if (timerEntry.animType != ANIMTYPE_CYCLED) { + if (seqEntry.animType != ANIMTYPE_CYCLED) { // Keep index from exceeding maximum allowed - timerEntry.frameIndex = timerEntry.frameStart; + seqEntry.frameIndex = seqEntry.frameStart; } else { // Switch into reverse - timerEntry.frameIndex = timerEntry.numSprites - 1; - timerEntry.frameInc = -1; + seqEntry.frameIndex = seqEntry.numSprites - 1; + seqEntry.frameInc = -1; } } } else { // Currently in reverse mode result = true; - if (timerEntry.animType == ANIMTYPE_CYCLED) + if (seqEntry.animType == ANIMTYPE_CYCLED) { // Switch back to forward direction again - timerEntry.frameIndex = timerEntry.frameStart + 1; - timerEntry.frameInc = 1; + seqEntry.frameIndex = seqEntry.frameStart + 1; + seqEntry.frameInc = 1; } else { // Otherwise reset back to last sprite for further reverse animating - timerEntry.frameIndex = timerEntry.numSprites; + seqEntry.frameIndex = seqEntry.numSprites; } } - if (result && (timerEntry.field_24 != 0)) { - if (--timerEntry.field_24 != 0) - timerEntry.field_25 = -1; + if (result && (seqEntry.field_24 != 0)) { + if (--seqEntry.field_24 != 0) + seqEntry.field_25 = -1; } } else { // Out of sprite slots - timerEntry.field_25 = -1; + seqEntry.field_25 = -1; } - if (timerEntry.len27 > 0) { - for (int i = 0; i <= timerEntry.len27; ++i) { - if ((!timerEntry.fld27[i] && (timerEntry.field_25 != 0)) || - ((timerEntry.fld27[i] == 1) && result)) { + if (seqEntry.entries.count > 0) { + for (int i = 0; i <= seqEntry.entries.count; ++i) { + switch (seqEntry.entries.mode[i]) { + case SM_0: + case SM_1: + if (((seqEntry.entries.mode[i] == SM_0) && (seqEntry.field_25 != 0)) || + ((seqEntry.entries.mode[i] == SM_1) && result)) idx = i; - } else if (timerEntry.fld27[i] > 1) { - int v = timerEntry.fld2C[i]; - if ((v == timerEntry.frameIndex) || (v == 0)) + break; + + case SM_FRAME_INDEX: { + int v = seqEntry.entries.frameIndex[i]; + if ((v == seqEntry.frameIndex) || (v == 0)) idx = i; } + + default: + break; + } } } if (idx >= 0) { - //_owner._abortTimers = timerEntry.fld36[idx]; - - // TODO: Figure out word_84208, timerEntry.field_3B[] + _owner._abortTimers = seqEntry.entries.abortVal[idx]; + _owner._abortTimersMode = seqEntry.abortMode; } return result; @@ -606,9 +723,15 @@ void MadsSequenceList::delay(uint32 v1, uint32 v2) { //-------------------------------------------------------------------------- -MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this) { +MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this), + _kernelMessages(*this) { + _textSpacing = -1; + _ticksAmount = 3; + _newTimeout = 0; _abortTimers = 0; _abortTimers2 = 0; + _abortTimersMode = ABORTMODE_0; + _abortTimersMode2 = ABORTMODE_0; } void MadsView::refresh() { diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 50ce9e1aab..37c797b931 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -40,6 +40,8 @@ namespace M4 { class MadsView; +enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2}; + class MadsSpriteSlot { public: int spriteId; @@ -126,6 +128,48 @@ public: void cleanUp(); }; +#define TIMED_TEXT_SIZE 10 +#define TEXT_4A_SIZE 30 + +enum KernelMessageFlags {KMSG_1 = 1, KMSG_2 = 2, KMSG_4 = 4, KMSG_8 = 8, KMSG_40 = 0x40, KMSG_ACTIVE = 0x80}; + +class MadsKernelMessageListEntry { +public: + uint8 flags; + int sequenceIndex; + char asciiChar; + char asciiChar2; + int colour1; + int colour2; + Common::Point position; + int textDisplayIndex; + int msgOffset; + int field_E; + uint32 frameTimer2; + uint32 frameTimer; + uint32 timeout; + bool field_1C; + AbortTimerMode abortMode; + uint16 actionNouns[3]; + char *msg; +}; + +class MadsKernelMessageList { +private: + MadsView &_owner; + Common::Array<MadsKernelMessageListEntry> _entries; + Font *_talkFont; +public: + MadsKernelMessageList(MadsView &owner); + + void clear(); + int add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 v2, uint32 timeout, char *msg); + void unk1(int msgIndex, int v1, int v2); + void setSeqIndex(int msgIndex, int seqIndex); + void remove(int msgIndex); + void reset(); +}; + class ScreenObjectEntry { public: Common::Rect bounds; @@ -191,9 +235,18 @@ public: void reset(); }; +enum SpriteAnimType {ANIMTYPE_SINGLE_DIRECTION = 1, ANIMTYPE_CYCLED = 2}; + +enum SequenceSubEntryMode {SM_0 = 0, SM_1 = 1, SM_FRAME_INDEX = 2}; + #define TIMER_ENTRY_SUBSET_MAX 5 -enum SpriteAnimType {ANIMTYPE_SINGLE_DIRECTION = 1, ANIMTYPE_CYCLED = 2}; +struct MadsSequenceSubEntries { + int count; + SequenceSubEntryMode mode[TIMER_ENTRY_SUBSET_MAX]; + int16 frameIndex[TIMER_ENTRY_SUBSET_MAX]; + int8 abortVal[TIMER_ENTRY_SUBSET_MAX]; +}; struct MadsSequenceEntry { int8 active; @@ -220,11 +273,8 @@ struct MadsSequenceEntry { int field_24; int field_25; - int len27; - int8 fld27[TIMER_ENTRY_SUBSET_MAX]; - int16 fld2C[TIMER_ENTRY_SUBSET_MAX]; - int8 fld36[TIMER_ENTRY_SUBSET_MAX]; - int field_3B; + MadsSequenceSubEntries entries; + AbortTimerMode abortMode; uint16 actionNouns[3]; int numTicks; @@ -242,7 +292,8 @@ public: MadsSequenceList(MadsView &owner); MadsSequenceEntry &operator[](int index) { return _entries[index]; } - bool unk2(int index, int v1, int v2, int v3); + void clear(); + bool addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal); 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 frameInc, SpriteAnimType animType, int numSprites, int frameStart); @@ -259,12 +310,18 @@ private: public: MadsSpriteSlots _spriteSlots; MadsTextDisplay _textDisplay; + MadsKernelMessageList _kernelMessages; ScreenObjects _screenObjects; MadsDynamicHotspots _dynamicHotspots; MadsSequenceList _sequenceList; + int _textSpacing; + int _ticksAmount; + uint32 _newTimeout; int _abortTimers; int8 _abortTimers2; + AbortTimerMode _abortTimersMode; + AbortTimerMode _abortTimersMode2; public: MadsView(View *view); |