aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2010-05-24 12:12:27 +0000
committerPaul Gilbert2010-05-24 12:12:27 +0000
commit6bda3e15db6baaa3af3d479e86dad2dd4f95084f (patch)
tree030bffb63865244c80e6a900ce734bebf146555a
parent55e29af78a52a13269d9905c6410e70f56b5920d (diff)
downloadscummvm-rg350-6bda3e15db6baaa3af3d479e86dad2dd4f95084f.tar.gz
scummvm-rg350-6bda3e15db6baaa3af3d479e86dad2dd4f95084f.tar.bz2
scummvm-rg350-6bda3e15db6baaa3af3d479e86dad2dd4f95084f.zip
Implemented the bulk of the logic for displaying timed on-screen messages
svn-id: r49180
-rw-r--r--engines/m4/mads_logic.cpp11
-rw-r--r--engines/m4/mads_logic.h1
-rw-r--r--engines/m4/mads_scene.cpp54
-rw-r--r--engines/m4/mads_views.cpp152
-rw-r--r--engines/m4/mads_views.h21
5 files changed, 167 insertions, 72 deletions
diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp
index 1fe5f4beb3..ee65d3be5c 100644
--- a/engines/m4/mads_logic.cpp
+++ b/engines/m4/mads_logic.cpp
@@ -245,4 +245,15 @@ void MadsSceneLogic::doAction() {
}
+void MadsSceneLogic::sceneStep() {
+ // FIXME: Temporary code to display a message on-screen
+ static bool tempBool = false;
+ if (!tempBool) {
+ tempBool = true;
+
+ _madsVm->scene()->_kernelMessages.add(Common::Point(63, 100), 0x1110, 0, 0, 240,
+ _madsVm->globals()->getQuote(49));
+ }
+}
+
}
diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h
index a589556a21..774ed016a6 100644
--- a/engines/m4/mads_logic.h
+++ b/engines/m4/mads_logic.h
@@ -54,6 +54,7 @@ public:
void setupScene();
void enterScene();
void doAction();
+ void sceneStep();
};
}
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index 4f28cdc6da..1b8e44b581 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -302,7 +302,9 @@ void MadsScene::update() {
}
void MadsScene::updateState() {
+ _sceneLogic.sceneStep();
_sequenceList.tick();
+ _kernelMessages.update();
}
int MadsScene::loadSceneSpriteSet(const char *setName) {
@@ -653,56 +655,4 @@ void MadsSceneResources::load(int sId) {
/*--------------------------------------------------------------------------*/
-/**
- * Adds a new entry to the timed on-screen text display list
- */
-/*
-void MadsScreenText::draw(M4Surface *surface) {
-}
-
-void MadsScreenText::timedDisplay() {
- for (int idx = 0; !_abortTimedText && (idx < OLD_TEXT_DISPLAY_SIZE); ++idx) {
- if (((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0) &&
- (_timedText[idx].frameTimer <= g_system->getMillis()))
- // Add the specified entry
- addTimedText(&_timedText[idx]);
- }
-}
-
-void MadsScreenText::addTimedText(TimedText *entry) {
- if ((entry->flags & TEXTFLAG_40) != 0) {
- this->setActive2(entry->textDisplayIndex);
- entry->flags &= 0x7F;
- return;
- }
-
- if ((entry->flags & TEXTFLAG_8) == 0)
- // FIXME: Adjust timeouts for ScumVM's milli counter
- entry->timeout -= 3;
-
- if ((entry->flags & TEXTFLAG_4) != 0) {
- Text4A &rec = _text4A[entry->unk4AIndex];
- if ((rec.field25 != 0) || (rec.active == 0))
- entry->timeout = 0;
- }
-
- if ((entry->timeout == 0) && !_abortTimedText) {
- entry->flags |= TEXTFLAG_40;
-
- if (entry->field_1C) {
- _abortTimedText = entry->field_1C;
- //word_84208 = entry->field_1D;
-
- if (entry->field_1D != 1) {
- // Restore the action list
- for (int i = 0; i < 3; ++i)
- _madsVm->scene()->actionNouns[i] = entry->actionNouns[i];
- }
- }
- }
-
- // TODO: code from 'loc_244ec' onwards
-}
-*/
-
} // End of namespace M4
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index e82a9976a5..7a71509041 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -324,12 +324,13 @@ void MadsTextDisplay::cleanUp() {
MadsKernelMessageList::MadsKernelMessageList(MadsView &owner): _owner(owner) {
for (int i = 0; i < TIMED_TEXT_SIZE; ++i) {
- MadsKernelMessageListEntry rec;
+ MadsKernelMessageEntry rec;
_entries.push_back(rec);
}
_owner._textSpacing = -1;
_talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS);
+ word_8469E = 0;
}
void MadsKernelMessageList::clear() {
@@ -352,8 +353,8 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f
error("MadsKernelList overflow");
}
- MadsKernelMessageListEntry &rec = _entries[idx];
- rec.msg = msg;
+ MadsKernelMessageEntry &rec = _entries[idx];
+ strcpy(rec.msg, msg);
rec.flags = flags | KMSG_ACTIVE;
rec.colour1 = fontColour & 0xff;
rec.colour2 = fontColour >> 8;
@@ -378,13 +379,13 @@ int MadsKernelMessageList::addQuote(int quoteId, int v2, uint32 timeout) {
return add(Common::Point(0, 0), 0x1110, KMSG_2 | KMSG_20, v2, timeout, quoteStr);
}
-void MadsKernelMessageList::unk1(int msgIndex, int v1, int v2) {
+void MadsKernelMessageList::unk1(int msgIndex, int numTicks, 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].numTicks = numTicks;
_entries[msgIndex].frameTimer2 = _madsVm->_currentTimer;
const char *msgP = _entries[msgIndex].msg;
@@ -405,7 +406,7 @@ void MadsKernelMessageList::setSeqIndex(int msgIndex, int seqIndex) {
}
void MadsKernelMessageList::remove(int msgIndex) {
- MadsKernelMessageListEntry &rec = _entries[msgIndex];
+ MadsKernelMessageEntry &rec = _entries[msgIndex];
if (rec.flags & KMSG_ACTIVE) {
if (rec.flags & KMSG_8) {
@@ -427,6 +428,135 @@ void MadsKernelMessageList::reset() {
// sub_20454
}
+void MadsKernelMessageList::update() {
+ uint32 currentTimer = _madsVm->_currentTimer;
+
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (((_entries[i].flags & KMSG_ACTIVE) != 0) && (currentTimer >= _entries[i].frameTimer))
+ processText(i);
+ }
+}
+
+void MadsKernelMessageList::processText(int msgIndex) {
+ MadsKernelMessageEntry &msg = _entries[msgIndex];
+ uint32 currentTimer = _madsVm->_currentTimer;
+ bool flag = false;
+
+ if ((msg.flags & KMSG_40) != 0) {
+ _owner._textDisplay.expire(msg.textDisplayIndex);
+ msg.flags &= !KMSG_ACTIVE;
+ return;
+ }
+
+ if ((msg.flags & KMSG_8) == 0) {
+ msg.timeout -= 3;
+ }
+
+ if (msg.flags & KMSG_4) {
+ MadsSequenceEntry &seqEntry = _owner._sequenceList[msg.sequenceIndex];
+ if (seqEntry.doneFlag || !seqEntry.active)
+ msg.timeout = 0;
+ }
+
+ if ((msg.timeout <= 0) && (_owner._abortTimers == 0)) {
+ msg.flags |= KMSG_40;
+ if (msg.field_1C != 0) {
+ _owner._abortTimers = msg.field_1C;
+ _owner._abortTimersMode = msg.abortMode;
+
+ if (_owner._abortTimersMode != ABORTMODE_1) {
+ for (int i = 0; i < 3; ++i)
+ _madsVm->scene()->actionNouns[i] = msg.actionNouns[i];
+ }
+ }
+ }
+
+ msg.frameTimer = currentTimer + 3;
+ int x1 = 0, y1 = 0;
+
+ if (msg.flags & KMSG_4) {
+ MadsSequenceEntry &seqEntry = _owner._sequenceList[msg.sequenceIndex];
+ if (seqEntry.field_12) {
+ SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex);
+ M4Sprite *frame = spriteSet.getFrame(seqEntry.frameIndex - 1);
+ x1 = frame->bounds().left;
+ y1 = frame->bounds().top;
+ } else {
+ x1 = seqEntry.msgPos.x;
+ y1 = seqEntry.msgPos.y;
+ }
+ }
+
+ if (msg.flags & KMSG_2) {
+ if (word_8469E != 0) {
+ // TODO: Figure out various flags
+ } else {
+ x1 = 160;
+ y1 = 78;
+ }
+ }
+
+ x1 += msg.position.x;
+ y1 += msg.position.y;
+
+ if ((msg.flags & KMSG_8) && (msg.frameTimer >= currentTimer)) {
+ msg.msg[msg.msgOffset] = msg.asciiChar;
+ char *msgP = &msg.msg[++msg.msgOffset];
+ *msgP = msg.asciiChar2;
+
+ msg.asciiChar = *msgP;
+ msg.asciiChar2 = *(msgP + 1);
+
+ if (!msg.asciiChar) {
+ *msgP = '\0';
+ msg.flags &= ~KMSG_8;
+ } else if (msg.flags & KMSG_1) {
+ *msgP = '"';
+ *(msgP + 1) = '\0';
+ }
+
+ msg.frameTimer = msg.frameTimer2 = currentTimer + msg.numTicks;
+ flag = true;
+ }
+
+ int strWidth = _talkFont->getWidth(msg.msg, _owner._textSpacing);
+
+ if (msg.flags & KMSG_30) {
+ x1 -= (msg.flags & KMSG_20) ? strWidth / 2 : strWidth;
+ }
+
+ // Make sure text appears entirely on-screen
+ int x2 = x1 + strWidth;
+ if (x2 > MADS_SURFACE_WIDTH)
+ x1 -= x2 - MADS_SURFACE_WIDTH;
+ if (x1 > (MADS_SURFACE_WIDTH - 1))
+ x1 = MADS_SURFACE_WIDTH - 1;
+ if (x1 < 0)
+ x1 = 0;
+
+ if (y1 > (MADS_SURFACE_HEIGHT - 1))
+ y1 = MADS_SURFACE_HEIGHT - 1;
+ if (y1 < 0)
+ y1 = 0;
+
+ if (msg.textDisplayIndex >= 0) {
+ MadsTextDisplayEntry textEntry = _owner._textDisplay[msg.textDisplayIndex];
+
+ if (flag || (textEntry.bounds.left != x1) || (textEntry.bounds.top != y1)) {
+ // Mark the associated text entry as deleted, so it can be re-created
+ _owner._textDisplay.expire(msg.textDisplayIndex);
+ msg.textDisplayIndex = -1;
+ }
+ }
+
+ if (msg.textDisplayIndex < 0) {
+ // Need to create a new text display entry for this message
+ int idx = _owner._textDisplay.add(x1, y1, msg.colour1 | (msg.colour2 << 8), _owner._textSpacing, msg.msg, _talkFont);
+ if (idx >= 0)
+ msg.textDisplayIndex = idx;
+ }
+}
+
//--------------------------------------------------------------------------
/**
@@ -725,7 +855,7 @@ bool MadsSequenceList::addSubEntry(int index, SequenceSubEntryMode mode, int fra
}
int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks,
- int height, int width, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType, int numSprites,
+ int msgX, int msgY, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType, int numSprites,
int frameStart) {
// Find a free slot
@@ -754,8 +884,8 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int trigg
_entries[timerIndex].depth = depth;
_entries[timerIndex].scale = scale;
_entries[timerIndex].field_12 = field_12;
- _entries[timerIndex].width = width;
- _entries[timerIndex].height = height;
+ _entries[timerIndex].msgPos.x = msgX;
+ _entries[timerIndex].msgPos.y = msgY;
_entries[timerIndex].numTicks = numTicks;
_entries[timerIndex].extraTicks = extraTicks;
@@ -796,8 +926,8 @@ void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot)
spriteSlot.scale = timerEntry.scale;
if (timerEntry.field_12 == 0) {
- spriteSlot.xp = timerEntry.width;
- spriteSlot.yp = timerEntry.height;
+ spriteSlot.xp = timerEntry.msgPos.x;
+ spriteSlot.yp = timerEntry.msgPos.y;
} else {
spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex - 1)->x;
spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex - 1)->y;
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index 3b64cc77f2..52388a99e0 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -139,9 +139,10 @@ public:
#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_20 = 0x20, KMSG_40 = 0x40, KMSG_ACTIVE = 0x80};
+enum KernelMessageFlags {KMSG_1 = 1, KMSG_2 = 2, KMSG_4 = 4, KMSG_8 = 8, KMSG_20 = 0x20, KMSG_30 = 0x30,
+ KMSG_40 = 0x40, KMSG_ACTIVE = 0x80};
-class MadsKernelMessageListEntry {
+class MadsKernelMessageEntry {
public:
uint8 flags;
int sequenceIndex;
@@ -152,22 +153,24 @@ public:
Common::Point position;
int textDisplayIndex;
int msgOffset;
- int field_E;
+ int numTicks;
uint32 frameTimer2;
uint32 frameTimer;
uint32 timeout;
bool field_1C;
AbortTimerMode abortMode;
uint16 actionNouns[3];
- const char *msg;
+ char msg[100];
};
class MadsKernelMessageList {
private:
MadsView &_owner;
- Common::Array<MadsKernelMessageListEntry> _entries;
+ Common::Array<MadsKernelMessageEntry> _entries;
Font *_talkFont;
public:
+ int word_8469E;
+public:
MadsKernelMessageList(MadsView &owner);
void clear();
@@ -177,6 +180,8 @@ public:
void setSeqIndex(int msgIndex, int seqIndex);
void remove(int msgIndex);
void reset();
+ void update();
+ void processText(int msgIndex);
};
class ScreenObjectEntry {
@@ -311,9 +316,7 @@ struct MadsSequenceEntry {
int field_12;
int field_13;
- int width;
- int height;
-
+ Common::Point msgPos;
int triggerCountdown;
bool doneFlag;
MadsSequenceSubEntries entries;
@@ -338,7 +341,7 @@ public:
void clear();
bool addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal);
int add(int spriteListIndex, int v0, int v1, int triggerCountdown, int delayTicks, int extraTicks, int numTicks,
- int height, int width, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType,
+ int msgX, int msgY, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType,
int numSprites, int frameStart);
void remove(int timerIndex);
void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot);