2009-02-17 15:02:16 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 08:34:13 +00:00
|
|
|
#include "sci/engine/message.h"
|
2009-02-21 19:54:15 +00:00
|
|
|
#include "sci/tools.h"
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 10:23:36 +00:00
|
|
|
namespace Sci {
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
MessageTuple MessageState::getTuple() {
|
|
|
|
MessageTuple t;
|
|
|
|
|
|
|
|
t.noun = *(_engineCursor.index_record + 0);
|
|
|
|
t.verb = *(_engineCursor.index_record + 1);
|
2009-05-10 13:15:14 +00:00
|
|
|
if (_version == 2101) {
|
2009-05-13 19:03:12 +00:00
|
|
|
t.cond = 0;
|
|
|
|
t.seq = 1;
|
2009-05-10 13:15:14 +00:00
|
|
|
} else {
|
2009-05-13 19:03:12 +00:00
|
|
|
t.cond = *(_engineCursor.index_record + 2);
|
|
|
|
t.seq = *(_engineCursor.index_record + 3);
|
2009-05-10 13:15:14 +00:00
|
|
|
}
|
2009-05-13 19:03:12 +00:00
|
|
|
|
|
|
|
return t;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
MessageTuple MessageState::getRefTuple() {
|
|
|
|
MessageTuple t;
|
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
if (_version == 2101) {
|
2009-05-13 19:03:12 +00:00
|
|
|
t.noun = 0;
|
|
|
|
t.verb = 0;
|
|
|
|
t.cond = 0;
|
2009-05-12 11:28:15 +00:00
|
|
|
} else {
|
2009-05-13 19:03:12 +00:00
|
|
|
t.noun = *(_engineCursor.index_record + 7);
|
|
|
|
t.verb = *(_engineCursor.index_record + 8);
|
|
|
|
t.cond = *(_engineCursor.index_record + 9);
|
2009-05-12 11:28:15 +00:00
|
|
|
}
|
2009-05-13 19:03:12 +00:00
|
|
|
t.seq = 1;
|
|
|
|
|
|
|
|
return t;
|
2009-05-12 11:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MessageState::initCursor() {
|
|
|
|
_engineCursor.index_record = _indexRecords;
|
|
|
|
_engineCursor.index = 0;
|
|
|
|
_engineCursor.nextSeq = 0;
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
void MessageState::advanceCursor(bool increaseSeq) {
|
|
|
|
_engineCursor.index_record += ((_version == 2101) ? 4 : 11);
|
|
|
|
_engineCursor.index++;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
if (increaseSeq)
|
|
|
|
_engineCursor.nextSeq++;
|
|
|
|
}
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
int MessageState::findTuple(MessageTuple &t) {
|
|
|
|
if (_module == -1)
|
|
|
|
return 0;
|
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
// Reset the cursor
|
|
|
|
initCursor();
|
2009-05-13 19:03:12 +00:00
|
|
|
_engineCursor.nextSeq = t.seq;
|
2009-05-12 11:28:15 +00:00
|
|
|
|
|
|
|
// Do a linear search for the message
|
|
|
|
while (1) {
|
2009-05-13 19:03:12 +00:00
|
|
|
MessageTuple looking_at = getTuple();
|
2009-05-12 11:28:15 +00:00
|
|
|
|
2009-05-20 17:53:31 +00:00
|
|
|
if (t.noun == looking_at.noun &&
|
|
|
|
t.verb == looking_at.verb &&
|
|
|
|
t.cond == looking_at.cond &&
|
2009-05-13 19:03:12 +00:00
|
|
|
t.seq == looking_at.seq)
|
2009-05-12 11:28:15 +00:00
|
|
|
break;
|
2009-05-10 22:25:43 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
advanceCursor(false);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
// Message tuple is not present
|
|
|
|
if (_engineCursor.index == _recordCount)
|
|
|
|
return 0;
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
return 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
int MessageState::getMessage() {
|
|
|
|
if (_module == -1)
|
|
|
|
return 0;
|
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
if (_engineCursor.index != _recordCount) {
|
2009-05-13 19:03:12 +00:00
|
|
|
MessageTuple mesg = getTuple();
|
|
|
|
MessageTuple ref = getRefTuple();
|
2009-05-12 11:28:15 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
if (findTuple(ref))
|
|
|
|
return getMessage();
|
2009-05-12 11:28:15 +00:00
|
|
|
else {
|
|
|
|
// Reference not found
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// No recursion, we are done
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-10 22:25:43 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
// We either ran out of records, or found an incorrect sequence number. Go to previous stack frame.
|
|
|
|
if (!_cursorStack.empty()) {
|
|
|
|
_engineCursor = _cursorStack.pop();
|
2009-05-13 19:03:12 +00:00
|
|
|
return getMessage();
|
2009-05-12 11:28:15 +00:00
|
|
|
}
|
2009-05-10 22:25:43 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
// Stack is empty, no message available
|
2009-05-10 22:25:43 +00:00
|
|
|
return 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-01 00:18:30 +00:00
|
|
|
int MessageState::getTalker() {
|
2009-05-10 14:57:27 +00:00
|
|
|
return (_version == 2101) ? -1 : *(_engineCursor.index_record + 4);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
MessageTuple &MessageState::getLastTuple() {
|
|
|
|
return _lastReturned;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MessageState::getLastModule() {
|
|
|
|
return _lastReturnedModule;
|
|
|
|
}
|
|
|
|
|
2009-06-04 14:29:20 +00:00
|
|
|
Common::String MessageState::getText() {
|
|
|
|
char *str = (char *)_currentResource->data + READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
|
|
|
|
|
|
|
|
Common::String strippedStr;
|
|
|
|
Common::String skippedSubstr;
|
|
|
|
bool skipping = false;
|
|
|
|
|
|
|
|
for (uint i = 0; i < strlen(str); i++) {
|
|
|
|
if (skipping) {
|
|
|
|
// Skip stage direction
|
|
|
|
skippedSubstr += str[i];
|
|
|
|
|
|
|
|
// Hopefully these locale-dependant functions are good enough
|
|
|
|
if (islower(str[i]) || isdigit(str[i])) {
|
|
|
|
// Lowercase or digit found, this is not a stage direction
|
|
|
|
strippedStr += skippedSubstr;
|
|
|
|
skipping = false;
|
|
|
|
} else if (str[i] == ')') {
|
|
|
|
// End of stage direction, skip trailing white space
|
|
|
|
while ((i + 1 < strlen(str)) && isspace(str[i + 1]))
|
|
|
|
i++;
|
|
|
|
skipping = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (str[i] == '(') {
|
|
|
|
// Start skipping stage direction
|
|
|
|
skippedSubstr = str[i];
|
|
|
|
skipping = true;
|
|
|
|
} else if (str[i] == '\\') {
|
|
|
|
// Escape sequence
|
|
|
|
if ((i + 2 < strlen(str)) && isdigit(str[i + 1]) && isdigit(str[i + 2])) {
|
|
|
|
// Hex escape sequence
|
|
|
|
char hexStr[3];
|
|
|
|
|
|
|
|
hexStr[0] = str[++i];
|
|
|
|
hexStr[1] = str[++i];
|
|
|
|
hexStr[2] = 0;
|
|
|
|
|
|
|
|
char *endptr;
|
|
|
|
int hexNr = strtol(hexStr, &endptr, 16);
|
|
|
|
if (*endptr == 0)
|
|
|
|
strippedStr += hexNr;
|
|
|
|
} else if (i + 1 < strlen(str)) {
|
|
|
|
// Literal escape sequence
|
|
|
|
strippedStr += str[++i];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
strippedStr += str[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return strippedStr;
|
2009-05-13 19:03:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MessageState::gotoNext() {
|
|
|
|
_lastReturned = getTuple();
|
|
|
|
_lastReturnedModule = _module;
|
2009-05-12 11:28:15 +00:00
|
|
|
advanceCursor(true);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-01 00:18:30 +00:00
|
|
|
int MessageState::getLength() {
|
2009-05-10 13:47:38 +00:00
|
|
|
int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
|
2009-05-12 11:28:15 +00:00
|
|
|
char *stringptr = (char *)_currentResource->data + offset;
|
2009-05-10 13:47:38 +00:00
|
|
|
return strlen(stringptr);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) {
|
2009-05-13 19:03:12 +00:00
|
|
|
if (_locked) {
|
|
|
|
// We already have a locked resource
|
|
|
|
if (_module == module) {
|
|
|
|
// If it's the same resource, we are done
|
|
|
|
return 1;
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
// Otherwise, free the old resource
|
2009-06-07 19:15:55 +00:00
|
|
|
resmgr->unlockResource(_currentResource);
|
2009-05-13 19:03:12 +00:00
|
|
|
_locked = false;
|
2009-05-12 11:28:15 +00:00
|
|
|
}
|
2009-05-08 16:21:51 +00:00
|
|
|
|
2009-06-07 19:15:55 +00:00
|
|
|
_currentResource = resmgr->findResource(ResourceId(kResourceTypeMessage, module), lock);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-10 13:15:14 +00:00
|
|
|
if (_currentResource == NULL || _currentResource->data == NULL) {
|
2009-05-13 19:03:12 +00:00
|
|
|
warning("Message: failed to load %d.msg", module);
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-13 19:03:12 +00:00
|
|
|
_module = module;
|
|
|
|
_locked = lock;
|
2009-05-12 11:28:15 +00:00
|
|
|
|
|
|
|
_version = READ_LE_UINT16(_currentResource->data);
|
|
|
|
|
2009-05-10 14:57:27 +00:00
|
|
|
int offs = (_version == 2101) ? 0 : 4;
|
|
|
|
_recordCount = READ_LE_UINT16(_currentResource->data + 4 + offs);
|
|
|
|
_indexRecords = _currentResource->data + 6 + offs;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
_cursorStack.clear();
|
|
|
|
initCursor();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-12 11:28:15 +00:00
|
|
|
return 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-21 10:23:36 +00:00
|
|
|
|
|
|
|
} // End of namespace Sci
|