diff options
author | Walter van Niftrik | 2009-05-12 11:28:15 +0000 |
---|---|---|
committer | Walter van Niftrik | 2009-05-12 11:28:15 +0000 |
commit | 7f587a9d6b97930e1ebff2c966a2c72e69bfd729 (patch) | |
tree | 6292ee75b595ee6c7d8ad6f5b3e34b5b4f415865 /engines/sci/engine | |
parent | 4aedfc75f8f6ca7b9d03fa2bb66f43bf50a240d1 (diff) | |
download | scummvm-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.cpp | 24 | ||||
-rw-r--r-- | engines/sci/engine/message.cpp | 146 | ||||
-rw-r--r-- | engines/sci/engine/message.h | 17 |
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 |