aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorWalter van Niftrik2009-05-12 11:28:15 +0000
committerWalter van Niftrik2009-05-12 11:28:15 +0000
commit7f587a9d6b97930e1ebff2c966a2c72e69bfd729 (patch)
tree6292ee75b595ee6c7d8ad6f5b3e34b5b4f415865 /engines/sci/engine
parent4aedfc75f8f6ca7b9d03fa2bb66f43bf50a240d1 (diff)
downloadscummvm-rg350-7f587a9d6b97930e1ebff2c966a2c72e69bfd729.tar.gz
scummvm-rg350-7f587a9d6b97930e1ebff2c966a2c72e69bfd729.tar.bz2
scummvm-rg350-7f587a9d6b97930e1ebff2c966a2c72e69bfd729.zip
SCI: Message: Added resource-internal recursion (currently untested).
svn-id: r40478
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/kstring.cpp24
-rw-r--r--engines/sci/engine/message.cpp146
-rw-r--r--engines/sci/engine/message.h17
3 files changed, 110 insertions, 77 deletions
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 0de81724b4..21ca298d18 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -727,9 +727,6 @@ reg_t kGetFarText(EngineState *s, int funct_nr, int argc, reg_t *argv) {
static MessageState state;
reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- if (!state.isInitialized())
- message_state_initialize(s->resmgr, &state);
-
MessageTuple tuple;
switch (UKPV(0)) {
@@ -738,9 +735,6 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
case 3:
case 4:
case 5:
- if (!state.loadRes(UKPV(1)))
- return NULL_REG;
-
tuple.noun = UKPV(2);
tuple.verb = UKPV(3);
tuple.cond = UKPV(4);
@@ -749,7 +743,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
switch (UKPV(0)) {
case 0 :
- if (state.getMessage(&tuple)) {
+ if (state.loadRes(s->resmgr, UKPV(1), true) && state.getMessage(&tuple)) {
char *buffer = NULL;
if ((argc == 7) && (argv[6] != NULL_REG))
@@ -759,6 +753,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if (buffer)
state.getText(buffer);
+
// Talker id
return make_reg(0, talker);
} else {
@@ -783,6 +778,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if (buffer)
state.getText(buffer);
+
// Talker id
return make_reg(0, talker);
} else {
@@ -796,11 +792,14 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return NULL_REG;
}
- case 2:
- if (state.getMessage(&tuple))
- return make_reg(0, state.getLength() + 1);
+ case 2: {
+ MessageState tempState;
+
+ if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.getMessage(&tuple))
+ return make_reg(0, tempState.getLength() + 1);
else
return NULL_REG;
+ }
default:
warning("kMessage subfunction %i invoked (not implemented)", UKPV(0));
}
@@ -809,9 +808,6 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
reg_t kGetMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- if (!state.isInitialized())
- message_state_initialize(s->resmgr, &state);
-
MessageTuple tuple;
tuple.noun = UKPV(0);
int module = UKPV(1);
@@ -819,7 +815,7 @@ reg_t kGetMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
tuple.cond = 0;
tuple.seq = 0;
- if (state.loadRes(module) && state.getMessage(&tuple)) {
+ if (state.loadRes(s->resmgr, module, true) && state.getMessage(&tuple)) {
int len = state.getLength();
char *buffer = kernel_dereference_char_pointer(s, argv[3], len + 1);
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index e838c05506..3e06ee419a 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -28,13 +28,6 @@
namespace Sci {
-void MessageState::initIndexRecordCursor() {
- _engineCursor.resource_beginning = _currentResource->data;
- _engineCursor.index_record = _indexRecords;
- _engineCursor.index = 0;
- _lastMessage.seq = 0;
-}
-
void MessageState::parse(IndexRecordCursor *cursor, MessageTuple *t) {
t->noun = *(cursor->index_record + 0);
t->verb = *(cursor->index_record + 1);
@@ -47,39 +40,93 @@ void MessageState::parse(IndexRecordCursor *cursor, MessageTuple *t) {
}
}
-int MessageState::getMessage(MessageTuple *t) {
- MessageTuple looking_at;
+void MessageState::parseRef(IndexRecordCursor *cursor, MessageTuple *t) {
+ if (_version == 2101) {
+ t->noun = 0;
+ t->verb = 0;
+ t->cond = 0;
+ } else {
+ t->noun = *(cursor->index_record + 7);
+ t->verb = *(cursor->index_record + 8);
+ t->cond = *(cursor->index_record + 9);
+ }
+ t->seq = 1;
+}
+
+void MessageState::initCursor() {
+ _engineCursor.index_record = _indexRecords;
+ _engineCursor.index = 0;
+ _engineCursor.nextSeq = 0;
+}
- initIndexRecordCursor();
- _lastMessage.seq = t->seq - 1;
+void MessageState::advanceCursor(bool increaseSeq) {
+ _engineCursor.index_record += ((_version == 2101) ? 4 : 11);
+ _engineCursor.index++;
- while (_engineCursor.index != _recordCount) {
+ if (increaseSeq)
+ _engineCursor.nextSeq++;
+}
+
+int MessageState::getMessage(MessageTuple *t) {
+ // Reset the cursor
+ initCursor();
+ _engineCursor.nextSeq = t->seq;
+
+ // Do a linear search for the message
+ while (1) {
+ MessageTuple looking_at;
parse(&_engineCursor, &looking_at);
+
if (t->noun == looking_at.noun &&
t->verb == looking_at.verb &&
t->cond == looking_at.cond &&
t->seq == looking_at.seq)
- return 1;
+ break;
- _engineCursor.index_record += ((_version == 2101) ? 4 : 11);
- _engineCursor.index++;
- }
+ advanceCursor(false);
- // FIXME: Recursion not handled yet
+ // Message tuple is not present
+ if (_engineCursor.index == _recordCount)
+ return 0;
+ }
- return 0;
+ return getNext();
}
int MessageState::getNext() {
- if (_engineCursor.index == _recordCount)
- return 0;
-
- MessageTuple mesg;
- parse(&_engineCursor, &mesg);
+ if (_engineCursor.index != _recordCount) {
+ MessageTuple mesg;
+ parse(&_engineCursor, &mesg);
+ MessageTuple ref;
+ parseRef(&_engineCursor, &ref);
+
+ if (_engineCursor.nextSeq == mesg.seq) {
+ // We found the right sequence number, check for recursion
+
+ if (ref.noun != 0) {
+ // Recursion, advance the current cursor and load the reference
+ advanceCursor(true);
+
+ if (getMessage(&ref))
+ return getNext();
+ else {
+ // Reference not found
+ return 0;
+ }
+ } else {
+ // No recursion, we are done
+ return 1;
+ }
+ }
+ }
- if (_lastMessage.seq == mesg.seq - 1)
- return 1;
+ // We either ran out of records, or found an incorrect sequence number. Go to previous stack frame.
+ if (!_cursorStack.empty()) {
+ _engineCursor = _cursorStack.pop();
+ return getNext();
+ }
+ // Stack is empty, no message available
return 0;
}
@@ -89,60 +136,47 @@ int MessageState::getTalker() {
void MessageState::getText(char *buffer) {
int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
- char *stringptr = (char *)_engineCursor.resource_beginning + offset;
- parse(&_engineCursor, &_lastMessage);
+ char *stringptr = (char *)_currentResource->data + offset;
strcpy(buffer, stringptr);
- _engineCursor.index_record += ((_version == 2101) ? 4 : 11);
- _engineCursor.index++;
+ advanceCursor(true);
}
int MessageState::getLength() {
int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
- char *stringptr = (char *)_engineCursor.resource_beginning + offset;
+ char *stringptr = (char *)_currentResource->data + offset;
return strlen(stringptr);
}
-int MessageState::loadRes(int module) {
+int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) {
if (_module == module)
return 1;
// Unlock old resource
- if (_module != -1)
- _resmgr->unlockResource(_currentResource, _module, kResourceTypeMessage);
+ if (_module != -1) {
+ resmgr->unlockResource(_currentResource, _module, kResourceTypeMessage);
+ _module = -1;
+ }
- _module = module;
- _currentResource = _resmgr->findResource(kResourceTypeMessage, module, 1);
+ _currentResource = resmgr->findResource(kResourceTypeMessage, module, lock);
if (_currentResource == NULL || _currentResource->data == NULL) {
- sciprintf("Message subsystem: Failed to load %d.MSG\n", module);
- _module = -1;
+ warning("Message subsystem: failed to load %d.msg", module);
return 0;
}
+ if (lock)
+ _module = module;
+
+ _version = READ_LE_UINT16(_currentResource->data);
+
int offs = (_version == 2101) ? 0 : 4;
_recordCount = READ_LE_UINT16(_currentResource->data + 4 + offs);
_indexRecords = _currentResource->data + 6 + offs;
- initIndexRecordCursor();
- return 1;
-}
-
-void MessageState::initialize(ResourceManager *resmgr) {
- _module = -1;
- _resmgr = resmgr;
- _currentResource = NULL;
- _recordCount = 0;
- _initialized = 1;
-}
-
-void message_state_initialize(ResourceManager *resmgr, MessageState *state) {
- Resource *tester = resmgr->findResource(kResourceTypeMessage, 0, 0);
+ _cursorStack.clear();
+ initCursor();
- if (tester) {
- int version = READ_LE_UINT16(tester->data);
- state->initialize(resmgr);
- state->setVersion(version);
- }
+ return 1;
}
} // End of namespace Sci
diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h
index 5a8924f4b5..e8f0662440 100644
--- a/engines/sci/engine/message.h
+++ b/engines/sci/engine/message.h
@@ -27,6 +27,7 @@
#define SCI_ENGINE_MESSAGE_H
#include "sci/scicore/resource.h"
+#include "common/stack.h"
namespace Sci {
@@ -40,38 +41,40 @@ struct MessageTuple {
struct IndexRecordCursor {
byte *index_record;
int index;
- byte *resource_beginning;
+ int nextSeq;
};
+typedef Common::Stack<IndexRecordCursor> CursorStack;
+
class MessageState {
public:
+ MessageState() : _module(-1) { }
int getMessage(MessageTuple *t);
int getNext();
int getTalker();
int getLength();
void getText(char *buffer);
- int loadRes(int module);
+ int loadRes(ResourceManager *resmgr, int module, bool lock);
int isInitialized() { return _initialized; }
void initialize(ResourceManager *resmgr);
void setVersion(int version) { _version = version; }
private:
- void initIndexRecordCursor();
void parse(IndexRecordCursor *cursor, MessageTuple *t);
+ void parseRef(IndexRecordCursor *cursor, MessageTuple *t);
+ void initCursor();
+ void advanceCursor(bool increaseSeq);
int _initialized;
- ResourceManager *_resmgr;
Resource *_currentResource;
int _module;
int _recordCount;
byte *_indexRecords;
+ CursorStack _cursorStack;
IndexRecordCursor _engineCursor;
- MessageTuple _lastMessage;
int _version;
};
-void message_state_initialize(ResourceManager *resmgr, MessageState *state);
-
} // End of namespace Sci
#endif // SCI_ENGINE_MESSAGE_H