get rid of getStringLen and use the more powerful resStrLen instead; moved resStrLen from common/ to scumm/, where it belongs; enhanced resStrLen to suport V8; fixed translateText to support embeded vars (in strings I mean) - it may still not be fully correct but at least is better now; rewrote o6_arrayOps to parallel the V8 version - needs testing
svn-id: r6215
This commit is contained in:
parent
319facc9c3
commit
ae5b30df3d
9 changed files with 82 additions and 168 deletions
|
@ -133,31 +133,6 @@ void hexdump(const byte * data, int len)
|
|||
printf("|\n");
|
||||
}
|
||||
|
||||
//
|
||||
// Given a pointer to a Scumm resource, this function returns the length
|
||||
// of the (string) data in that resource. To do so it understands certain
|
||||
// special chars starting with FF. The reason for this function is that
|
||||
// sometimes resource data will contain 0 bytes, thus we can't just use strlen.
|
||||
//
|
||||
int resStrLen(const char *src)
|
||||
{
|
||||
int num = 0;
|
||||
byte chr;
|
||||
while ((chr = *src++) != 0) {
|
||||
num++;
|
||||
if (chr == 255) {
|
||||
chr = *src++;
|
||||
num++;
|
||||
|
||||
if (chr != 1 && chr != 2 && chr != 3 && chr != 8) {
|
||||
src += 2;
|
||||
num += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
RandomSource::RandomSource(uint32 seed)
|
||||
{
|
||||
_randSeed = seed;
|
||||
|
|
|
@ -47,10 +47,6 @@ void ClearBlendCache(byte *palette, int weight);
|
|||
*/
|
||||
void hexdump(const byte * data, int len);
|
||||
|
||||
// Resource string length
|
||||
int resStrLen(const char *src);
|
||||
|
||||
|
||||
class RandomSource {
|
||||
private:
|
||||
uint32 _randSeed;
|
||||
|
|
|
@ -1477,7 +1477,7 @@ void Scumm::loadPtrToResource(int type, int resindex, byte *source)
|
|||
|
||||
nukeResource(type, resindex);
|
||||
|
||||
len = getStringLen(source);
|
||||
len = resStrLen(source) + 1;
|
||||
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
|
|
@ -1097,33 +1097,43 @@ int Scumm::getArrayId()
|
|||
return -1;
|
||||
}
|
||||
|
||||
void Scumm::copyString(byte *dst, byte *src, int len)
|
||||
void Scumm::copyScriptString(byte *dst)
|
||||
{
|
||||
if (!src) {
|
||||
while (--len >= 0)
|
||||
int len = resStrLen(_scriptPointer) + 1;
|
||||
while (len--)
|
||||
*dst++ = fetchScriptByte();
|
||||
} else {
|
||||
while (--len >= 0)
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
int Scumm::getStringLen(byte *ptr)
|
||||
//
|
||||
// Given a pointer to a Scumm string, this function returns the total byte length
|
||||
// of the string data in that resource. To do so it has to understand certain
|
||||
// special characters embedded into the string. The reason for this function is that
|
||||
// sometimes this embedded data contains zero bytes, thus we can't just use strlen.
|
||||
//
|
||||
int Scumm::resStrLen(const byte *src) const
|
||||
{
|
||||
int len;
|
||||
byte c;
|
||||
if (!ptr)
|
||||
ptr = _scriptPointer;
|
||||
len = 0;
|
||||
do {
|
||||
c = *ptr++;
|
||||
if (!c)
|
||||
break;
|
||||
len++;
|
||||
if (c == 0xFF)
|
||||
ptr += 3, len += 3;
|
||||
} while (1);
|
||||
return len + 1;
|
||||
int num = 0;
|
||||
byte chr;
|
||||
if (src == NULL)
|
||||
src = _scriptPointer;
|
||||
while ((chr = *src++) != 0) {
|
||||
num++;
|
||||
if (chr == 255) {
|
||||
chr = *src++;
|
||||
num++;
|
||||
|
||||
if (chr != 1 && chr != 2 && chr != 3 && chr != 8) {
|
||||
if (_features & GF_AFTER_V8) {
|
||||
src += 4;
|
||||
num += 4;
|
||||
} else {
|
||||
src += 2;
|
||||
num += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
void Scumm::exitCutscene()
|
||||
|
|
|
@ -1827,7 +1827,7 @@ void Scumm_v5::o5_roomOps()
|
|||
if (out) {
|
||||
byte *ptr;
|
||||
ptr = getResourceAddress(rtString, a);
|
||||
fwrite(ptr, getStringLen(ptr) + 1, 1, out);
|
||||
fwrite(ptr, resStrLen(ptr) + 1, 1, out);
|
||||
fclose(out);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1952,54 +1952,46 @@ void Scumm_v6::o6_getVerbEntrypoint()
|
|||
push(getVerbEntrypoint(v, e));
|
||||
}
|
||||
|
||||
void Scumm::arrayop_1(int a, byte *ptr)
|
||||
{
|
||||
ArrayHeader *ah;
|
||||
int r;
|
||||
int len = getStringLen(ptr);
|
||||
|
||||
r = defineArray(a, 4, 0, len);
|
||||
ah = (ArrayHeader *)getResourceAddress(rtString, r);
|
||||
copyString(ah->data, ptr, len);
|
||||
}
|
||||
|
||||
void Scumm_v6::o6_arrayOps()
|
||||
{
|
||||
int a, b, c, d, num;
|
||||
byte subOp = fetchScriptByte();
|
||||
int array = fetchScriptWord();
|
||||
int b, c, d, len;
|
||||
ArrayHeader *ah;
|
||||
int list[128];
|
||||
|
||||
switch (fetchScriptByte()) {
|
||||
switch (subOp) {
|
||||
case 205:
|
||||
a = fetchScriptWord();
|
||||
pop();
|
||||
arrayop_1(a, NULL);
|
||||
b = pop();
|
||||
len = resStrLen(_scriptPointer);
|
||||
c = defineArray(array, 4, 0, len + 1);
|
||||
ah = (ArrayHeader *)getResourceAddress(rtString, c);
|
||||
copyScriptString(ah->data + b);
|
||||
break;
|
||||
case 208:
|
||||
a = fetchScriptWord();
|
||||
b = pop();
|
||||
c = pop();
|
||||
d = readVar(a);
|
||||
d = readVar(array);
|
||||
if (d == 0) {
|
||||
defineArray(a, 5, 0, b + c);
|
||||
defineArray(array, 5, 0, b + c);
|
||||
}
|
||||
while (c--) {
|
||||
writeArray(a, 0, b + c, pop());
|
||||
writeArray(array, 0, b + c, pop());
|
||||
}
|
||||
break;
|
||||
case 212:
|
||||
a = fetchScriptWord();
|
||||
b = pop();
|
||||
num = getStackList(list, sizeof(list) / sizeof(list[0]));
|
||||
d = readVar(a);
|
||||
len = getStackList(list, sizeof(list) / sizeof(list[0]));
|
||||
d = readVar(array);
|
||||
if (d == 0)
|
||||
error("Must DIM a two dimensional array before assigning");
|
||||
c = pop();
|
||||
while (--num >= 0) {
|
||||
writeArray(a, c, b + num, list[num]);
|
||||
while (--len >= 0) {
|
||||
writeArray(array, c, b + len, list[len]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("o6_arrayOps: default case");
|
||||
error("o6_arrayOps: default case %d (array %d)", subOp, array);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2015,7 +2007,6 @@ void Scumm_v6::o6_saveRestoreVerbs()
|
|||
byte subOp = fetchScriptByte();
|
||||
if (_features & GF_AFTER_V8) {
|
||||
subOp = (subOp - 141) + 0xB4;
|
||||
printf("o8_saveRestoreVerbs:%d\n", (int)subOp);
|
||||
}
|
||||
|
||||
switch (subOp) {
|
||||
|
@ -2112,7 +2103,6 @@ void Scumm_v6::o6_wait()
|
|||
|
||||
return;
|
||||
case 171:
|
||||
printf("wait for sentence");
|
||||
if (_sentenceNum) {
|
||||
if (_sentence[_sentenceNum - 1].freezeCount && !isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]))
|
||||
return;
|
||||
|
@ -2290,8 +2280,9 @@ void Scumm_v6::o6_talkActor()
|
|||
char pointer[20];
|
||||
int i, j;
|
||||
|
||||
_scriptPointer += resStrLen((char*)_scriptPointer) + 1;
|
||||
_scriptPointer += resStrLen(_scriptPointer) + 1;
|
||||
translateText(_messagePtr, _transText);
|
||||
|
||||
for (i = 0, j = 0; (_messagePtr[i] != '/' || j == 0) && j < 19; i++) {
|
||||
if (_messagePtr[i] != '/')
|
||||
pointer[j++] = _messagePtr[i];
|
||||
|
@ -2934,7 +2925,7 @@ void Scumm_v6::decodeParseString(int m, int n)
|
|||
char pointer[20];
|
||||
int i, j;
|
||||
|
||||
_scriptPointer += resStrLen((char*)_scriptPointer)+ 1;
|
||||
_scriptPointer += resStrLen(_scriptPointer)+ 1;
|
||||
translateText(_messagePtr, _transText);
|
||||
for (i = 0, j = 0; (_messagePtr[i] != '/' || j == 0) && j < 19; i++) {
|
||||
if (_messagePtr[i] != '/')
|
||||
|
|
|
@ -512,16 +512,14 @@ void Scumm_v8::decodeParseString(int m, int n)
|
|||
case 0xD0: // SO_PRINT_MUMBLE
|
||||
error("decodeParseString: SO_PRINT_MUMBLE");
|
||||
break;
|
||||
case 0xD1: {
|
||||
|
||||
#if 1
|
||||
case 0xD1:
|
||||
_messagePtr = _scriptPointer;
|
||||
|
||||
if (_messagePtr[0] == '/') {
|
||||
char pointer[20];
|
||||
int i, j;
|
||||
|
||||
_scriptPointer += resStrLen((char*)_scriptPointer)+ 1;
|
||||
_scriptPointer += resStrLen(_scriptPointer) + 1;
|
||||
translateText(_messagePtr, _transText);
|
||||
for (i = 0, j = 0; (_messagePtr[i] != '/' || j == 0) && j < 19; i++) {
|
||||
if (_messagePtr[i] != '/')
|
||||
|
@ -569,61 +567,7 @@ void Scumm_v8::decodeParseString(int m, int n)
|
|||
_scriptPointer = _messagePtr;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
char buffer[1024];
|
||||
_messagePtr = _scriptPointer;
|
||||
|
||||
if (_messagePtr[0] == '/') {
|
||||
char pointer[20];
|
||||
int i, j;
|
||||
|
||||
// Skip over the string
|
||||
_scriptPointer += resStrLen((char*)_scriptPointer) + 1;
|
||||
|
||||
translateText(_messagePtr, _transText);
|
||||
for (i = 0, j = 0; (_messagePtr[i] != '/' || j == 0) && j < 19; i++) {
|
||||
if (_messagePtr[i] != '/')
|
||||
pointer[j++] = _messagePtr[i];
|
||||
}
|
||||
pointer[j] = 0;
|
||||
|
||||
// Stop any talking that's still going on
|
||||
if (_sound->_talkChannel > -1)
|
||||
_mixer->stop(_sound->_talkChannel);
|
||||
|
||||
// FIXME: no 'digvoice.bun' in COMI
|
||||
_sound->_talkChannel = _sound->playBundleSound(pointer);
|
||||
|
||||
_messagePtr = _transText;
|
||||
_msgPtrToAdd = (byte *)buffer;
|
||||
_messagePtr = addMessageToStack(_messagePtr);
|
||||
} else {
|
||||
_msgPtrToAdd = (byte *)buffer;
|
||||
_scriptPointer = _messagePtr = addMessageToStack(_messagePtr);
|
||||
}
|
||||
|
||||
if (_fr[_string[m].charset] == NULL) // FIXME: Put this elsewhere?
|
||||
loadCharset(_string[m].charset);
|
||||
|
||||
if (_fr[_string[m].charset] != NULL) {
|
||||
int x = _string[m].xpos;
|
||||
// HACK - center mode. I call this a hack because we really should
|
||||
// not duplicate all the string code from string.cpp. Rather, maybe
|
||||
// abstract away the code in string.cpp from using the 'charset'
|
||||
// fonts, and allow it to work both with old and new fonts. To this
|
||||
// end, we should seperate the parts of Charset/_charset which are
|
||||
// for bookkeeping (like x_pos, center mode etc.) and those that are
|
||||
// for rendering. Then let the old (think printCharOld), medium (printChar),
|
||||
// new (NUT) style renderers be subclasses of a common base class (which
|
||||
// defines the API). This will clean up the code, and allow us to reuse
|
||||
// the string logic in string.cpp.
|
||||
if (_string[m].center)
|
||||
x -= _fr[_string[m].charset]->getStringWidth(buffer) / 2;
|
||||
_fr[_string[m].charset]->drawString(buffer, x, _string[m].ypos, _string[m].color, 0);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 0xD2: // SO_PRINT_WRAP Set print wordwrap
|
||||
error("decodeParseString: SO_PRINT_MUMBLE");
|
||||
break;
|
||||
|
@ -746,23 +690,18 @@ void Scumm_v8::o8_arrayOps()
|
|||
byte subOp = fetchScriptByte();
|
||||
int array = fetchScriptWord();
|
||||
int b, c, d, len;
|
||||
ArrayHeader *ah;
|
||||
int list[128];
|
||||
|
||||
switch (subOp) {
|
||||
case 0x14: // SO_ASSIGN_STRING
|
||||
{
|
||||
int idx = pop();
|
||||
ArrayHeader *ah;
|
||||
int r;
|
||||
len = getStringLen(NULL);
|
||||
|
||||
r = defineArray(array, 4, 0, len);
|
||||
ah = (ArrayHeader *)getResourceAddress(rtString, r);
|
||||
copyString(ah->data + idx, NULL, len);
|
||||
}
|
||||
b = pop();
|
||||
len = resStrLen(_scriptPointer);
|
||||
c = defineArray(array, 4, 0, len + 1);
|
||||
ah = (ArrayHeader *)getResourceAddress(rtString, c);
|
||||
copyScriptString(ah->data + b);
|
||||
break;
|
||||
case 0x15: // SO_ASSIGN_SCUMMVAR_LIST
|
||||
// TODO / FIXME: is this right?
|
||||
b = pop();
|
||||
c = pop();
|
||||
d = readVar(array);
|
||||
|
@ -774,7 +713,6 @@ void Scumm_v8::o8_arrayOps()
|
|||
}
|
||||
break;
|
||||
case 0x16: // SO_ASSIGN_2DIM_LIST
|
||||
// TODO / FIXME: is this right?
|
||||
b = pop();
|
||||
len = getStackList(list, sizeof(list) / sizeof(list[0]));
|
||||
d = readVar(array);
|
||||
|
@ -1333,7 +1271,7 @@ void Scumm_v8::o8_system()
|
|||
|
||||
void Scumm_v8::o8_startVideo()
|
||||
{
|
||||
int len = resStrLen((char*)_scriptPointer);
|
||||
int len = resStrLen(_scriptPointer);
|
||||
|
||||
warning("o8_startVideo(%s/%s)", getGameDataPath(), (char*)_scriptPointer);
|
||||
|
||||
|
@ -1528,7 +1466,7 @@ void Scumm_v8::o8_getObjectImageHeight()
|
|||
void Scumm_v8::o8_getStringWidth()
|
||||
{
|
||||
int charset = pop();
|
||||
int len = resStrLen((char*)_scriptPointer);
|
||||
int len = resStrLen(_scriptPointer);
|
||||
int oldID = _charset->getCurID();
|
||||
int width;
|
||||
|
||||
|
|
|
@ -457,7 +457,6 @@ public:
|
|||
virtual void writeVar(uint var, int value);
|
||||
void runHook(int i);
|
||||
bool isScriptInUse(int script);
|
||||
int getStringLen(byte *ptr);
|
||||
|
||||
void freezeScripts(int scr);
|
||||
void unfreezeScripts();
|
||||
|
@ -476,8 +475,8 @@ public:
|
|||
void decreaseScriptDelay(int amount);
|
||||
bool isScriptRunning(int script);
|
||||
bool isRoomScriptRunning(int script);
|
||||
void arrayop_1(int a, byte *ptr);
|
||||
void copyString(byte *dst, byte *src, int len);
|
||||
void copyScriptString(byte *dst);
|
||||
int resStrLen(const byte *src) const;
|
||||
void doSentence(int c, int b, int a);
|
||||
void setStringVars(int i);
|
||||
|
||||
|
|
|
@ -494,7 +494,7 @@ void Scumm::drawString(int a)
|
|||
}
|
||||
|
||||
for (i = 0; (chr = buf[i++]) != 0;) {
|
||||
if (chr == 254 || chr == 255) {
|
||||
if (chr == 0xFE || chr == 0xFF) {
|
||||
chr = buf[i++];
|
||||
switch (chr) {
|
||||
case 9:
|
||||
|
@ -650,6 +650,11 @@ byte *Scumm::addMessageToStack(byte *msg)
|
|||
*_msgPtrToAdd++ = chr;
|
||||
*_msgPtrToAdd++ = ptr[num++];
|
||||
*_msgPtrToAdd++ = ptr[num++];
|
||||
if (_features & GF_AFTER_V8) {
|
||||
// FIXME - is this right?!?
|
||||
*_msgPtrToAdd++ = ptr[num++];
|
||||
*_msgPtrToAdd++ = ptr[num++];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debug(2, "addMessageToStack(): string escape sequence %d unknown", chr);
|
||||
|
@ -808,11 +813,11 @@ void Scumm::translateText(byte *text, byte *trans_buff) {
|
|||
// skip translation if flag 'h' exist
|
||||
if (*(buf + pos) == 'h') {
|
||||
pos += 3;
|
||||
char *pointer = strchr((char*)text + 1, '/');
|
||||
byte *pointer = (byte *)strchr((char*)text + 1, '/');
|
||||
if (pointer != NULL)
|
||||
strcpy((char *)trans_buff, pointer + 1);
|
||||
memcpy(trans_buff, pointer + 1, resStrLen(pointer + 1) + 1);
|
||||
else
|
||||
strcpy((char *)trans_buff, "");
|
||||
trans_buff[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -868,14 +873,14 @@ void Scumm::translateText(byte *text, byte *trans_buff) {
|
|||
}
|
||||
|
||||
if (text[0] == '/') {
|
||||
char *pointer = strchr((char*)text + 1, '/');
|
||||
byte *pointer = (byte *)strchr((char*)text + 1, '/');
|
||||
if (pointer != NULL)
|
||||
strcpy((char *)trans_buff, pointer + 1);
|
||||
memcpy(trans_buff, pointer + 1, resStrLen(pointer + 1) + 1);
|
||||
else
|
||||
strcpy((char *)trans_buff, "");
|
||||
|
||||
trans_buff[0] = '\0';
|
||||
return;
|
||||
}
|
||||
strcpy((char *)trans_buff, (char *)text);
|
||||
|
||||
memcpy(trans_buff, text, resStrLen(text) + 1);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue