mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 21:59:17 +00:00
ddf3336bc1
svn-id: r41374
1585 lines
30 KiB
C++
1585 lines
30 KiB
C++
/* 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$
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include "agos/agos.h"
|
|
#include "agos/intern.h"
|
|
|
|
using Common::File;
|
|
|
|
namespace AGOS {
|
|
|
|
void AGOSEngine::uncompressText(byte *ptr) {
|
|
byte a;
|
|
while (1) {
|
|
if (_awaitTwoByteToken != 0)
|
|
a = _awaitTwoByteToken;
|
|
else
|
|
a = *ptr++;
|
|
if (a == 0)
|
|
return;
|
|
ptr = uncompressToken(a, ptr);
|
|
if (ptr == 0)
|
|
return;
|
|
}
|
|
}
|
|
|
|
byte *AGOSEngine::uncompressToken(byte a, byte *ptr) {
|
|
byte *ptr1 = 0;
|
|
byte *ptr2 = 0;
|
|
byte b;
|
|
int count1 = 0;
|
|
|
|
if (a == 0xFF || a == 0xFE || a == 0xFD) {
|
|
if (a == 0xFF)
|
|
ptr2 = _twoByteTokenStrings;
|
|
if (a == 0xFE)
|
|
ptr2 = _secondTwoByteTokenStrings;
|
|
if (a == 0xFD)
|
|
ptr2 = _thirdTwoByteTokenStrings;
|
|
_awaitTwoByteToken = a;
|
|
b = a;
|
|
a = *ptr++;
|
|
if (a == 0) /* Need to return such that next byte */
|
|
return 0; /* is used as two byte token */
|
|
|
|
_awaitTwoByteToken = 0;
|
|
ptr1 = _twoByteTokens;
|
|
while (*ptr1 != a) {
|
|
ptr1++;
|
|
count1++;
|
|
if (*ptr1 == 0) { /* If was not a two byte token */
|
|
count1 = 0; /* then was a byte token. */
|
|
ptr1 = _byteTokens;
|
|
while (*ptr1 != a) {
|
|
ptr1++;
|
|
count1++;
|
|
}
|
|
ptr1 = _byteTokenStrings; /* Find it */
|
|
while (count1--) {
|
|
while (*ptr1++)
|
|
;
|
|
}
|
|
ptr1 = uncompressToken(b, ptr1); /* Try this one as a two byte token */
|
|
uncompressText(ptr1); /* Uncompress rest of this token */
|
|
return ptr;
|
|
}
|
|
}
|
|
while (count1--) {
|
|
while (*ptr2++)
|
|
;
|
|
}
|
|
uncompressText(ptr2);
|
|
} else {
|
|
ptr1 = _byteTokens;
|
|
while (*ptr1 != a) {
|
|
ptr1++;
|
|
count1++;
|
|
if (*ptr1 == 0) {
|
|
_textBuffer[_textCount++] = a; /* Not a byte token */
|
|
return ptr; /* must be real character */
|
|
}
|
|
}
|
|
ptr1 = _byteTokenStrings;
|
|
while (count1--) { /* Is a byte token so count */
|
|
while (*ptr1++) /* to start of token */
|
|
;
|
|
}
|
|
uncompressText(ptr1); /* and do it */
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
const byte *AGOSEngine::getStringPtrByID(uint16 stringId, bool upperCase) {
|
|
const byte *stringPtr;
|
|
byte *dst;
|
|
|
|
_freeStringSlot ^= 1;
|
|
dst = _stringReturnBuffer[_freeStringSlot];
|
|
|
|
if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformAtariST) {
|
|
byte *ptr = _stringTabPtr[stringId];
|
|
_textCount = 0;
|
|
_awaitTwoByteToken = 0;
|
|
uncompressText(ptr);
|
|
_textBuffer[_textCount] = 0;
|
|
strcpy((char *)dst, (const char *)_textBuffer);
|
|
} else {
|
|
if (stringId < 0x8000) {
|
|
stringPtr = _stringTabPtr[stringId];
|
|
} else {
|
|
stringPtr = getLocalStringByID(stringId);
|
|
}
|
|
strcpy((char *)dst, (const char *)stringPtr);
|
|
}
|
|
|
|
if (upperCase && *dst) {
|
|
if (islower(*dst))
|
|
*dst = toupper(*dst);
|
|
}
|
|
|
|
return dst;
|
|
}
|
|
|
|
const byte *AGOSEngine::getLocalStringByID(uint16 stringId) {
|
|
if (stringId < _stringIdLocalMin || stringId >= _stringIdLocalMax) {
|
|
loadTextIntoMem(stringId);
|
|
}
|
|
return _localStringtable[stringId - _stringIdLocalMin];
|
|
}
|
|
|
|
TextLocation *AGOSEngine::getTextLocation(uint a) {
|
|
switch (a) {
|
|
case 1:
|
|
return &_textLocation1;
|
|
case 2:
|
|
return &_textLocation2;
|
|
case 101:
|
|
return &_textLocation3;
|
|
case 102:
|
|
return &_textLocation4;
|
|
default:
|
|
error("getTextLocation: Invalid text location %d", a);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void AGOSEngine::allocateStringTable(int num) {
|
|
_stringTabPtr = (byte **)calloc(num, sizeof(byte *));
|
|
_stringTabPos = 0;
|
|
_stringTabSize = num;
|
|
}
|
|
|
|
void AGOSEngine::setupStringTable(byte *mem, int num) {
|
|
int i = 0;
|
|
|
|
if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformAtariST) {
|
|
int ct1;
|
|
|
|
_twoByteTokens = mem;
|
|
while (*mem++) {
|
|
i++;
|
|
}
|
|
_twoByteTokenStrings = mem;
|
|
ct1 = i;
|
|
while (*mem++) {
|
|
while (*mem++)
|
|
;
|
|
i--;
|
|
if ((i == 0) && (ct1 != 0)) {
|
|
_secondTwoByteTokenStrings = mem;
|
|
i = ct1;
|
|
ct1 = 0;
|
|
}
|
|
if (i == 0)
|
|
_thirdTwoByteTokenStrings = mem;
|
|
}
|
|
_byteTokens = mem;
|
|
while (*mem++)
|
|
;
|
|
_byteTokenStrings = mem;
|
|
while (*mem++) {
|
|
while (*mem++)
|
|
;
|
|
}
|
|
i = 0;
|
|
l1: _stringTabPtr[i++] = mem;
|
|
num--;
|
|
if (!num) {
|
|
_stringTabPos = i;
|
|
return;
|
|
}
|
|
while (*mem++)
|
|
;
|
|
goto l1;
|
|
} else {
|
|
for (;;) {
|
|
_stringTabPtr[i++] = mem;
|
|
if (--num == 0)
|
|
break;
|
|
for (; *mem; mem++)
|
|
;
|
|
mem++;
|
|
}
|
|
|
|
_stringTabPos = i;
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::setupLocalStringTable(byte *mem, int num) {
|
|
int i = 0;
|
|
for (;;) {
|
|
_localStringtable[i++] = mem;
|
|
if (--num == 0)
|
|
break;
|
|
for (; *mem; mem++)
|
|
;
|
|
mem++;
|
|
}
|
|
}
|
|
|
|
uint AGOSEngine::loadTextFile(const char *filename, byte *dst) {
|
|
if (getFeatures() & GF_OLD_BUNDLE)
|
|
return loadTextFile_simon1(filename, dst);
|
|
else
|
|
return loadTextFile_gme(filename, dst);
|
|
}
|
|
|
|
uint AGOSEngine::loadTextFile_simon1(const char *filename, byte *dst) {
|
|
File fo;
|
|
fo.open(filename);
|
|
uint32 size;
|
|
|
|
if (fo.isOpen() == false)
|
|
error("loadTextFile: Can't open '%s'", filename);
|
|
|
|
size = fo.size();
|
|
|
|
if (fo.read(dst, size) != size)
|
|
error("loadTextFile: fread failed");
|
|
fo.close();
|
|
|
|
return size;
|
|
}
|
|
|
|
uint AGOSEngine::loadTextFile_gme(const char *filename, byte *dst) {
|
|
uint res;
|
|
uint32 offs;
|
|
uint32 size;
|
|
|
|
res = atoi(filename + 4) + _textIndexBase - 1;
|
|
offs = _gameOffsetsPtr[res];
|
|
size = _gameOffsetsPtr[res + 1] - offs;
|
|
|
|
readGameFile(dst, offs, size);
|
|
|
|
return size;
|
|
}
|
|
|
|
void AGOSEngine::loadTextIntoMem(uint16 stringId) {
|
|
byte *p;
|
|
char filename[30];
|
|
int i;
|
|
uint16 baseMin = 0x8000, baseMax, size;
|
|
|
|
_tablesHeapPtr = _tablesheapPtrNew;
|
|
_tablesHeapCurPos = _tablesHeapCurPosNew;
|
|
|
|
p = _strippedTxtMem;
|
|
|
|
// get filename
|
|
while (*p) {
|
|
for (i = 0; *p; p++, i++)
|
|
filename[i] = *p;
|
|
filename[i] = 0;
|
|
p++;
|
|
|
|
if (getPlatform() == Common::kPlatformAcorn) {
|
|
sprintf(filename, "%s.DAT", filename);
|
|
}
|
|
|
|
baseMax = (p[0] * 256) | p[1];
|
|
p += 2;
|
|
|
|
if (stringId < baseMax) {
|
|
_stringIdLocalMin = baseMin;
|
|
_stringIdLocalMax = baseMax;
|
|
|
|
_localStringtable = (byte **)_tablesHeapPtr;
|
|
|
|
size = (baseMax - baseMin + 1) * sizeof(byte *);
|
|
_tablesHeapPtr += size;
|
|
_tablesHeapCurPos += size;
|
|
|
|
size = loadTextFile(filename, _tablesHeapPtr);
|
|
|
|
setupLocalStringTable(_tablesHeapPtr, baseMax - baseMin + 1);
|
|
|
|
_tablesHeapPtr += size;
|
|
_tablesHeapCurPos += size;
|
|
|
|
if (_tablesHeapCurPos > _tablesHeapSize) {
|
|
error("loadTextIntoMem: Out of table memory");
|
|
}
|
|
return;
|
|
}
|
|
|
|
baseMin = baseMax;
|
|
}
|
|
|
|
error("loadTextIntoMem: didn't find %d", stringId);
|
|
}
|
|
|
|
static const byte polish_charWidth[226] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 6, 2, 8, 7, 6,10, 8, 2,
|
|
4, 4, 7, 6, 3, 4, 2, 3, 6, 4,
|
|
6, 6, 7, 6, 6, 6, 6, 6, 2, 8,
|
|
6, 9, 7, 6, 6, 8, 7, 8, 8, 7,
|
|
6, 9, 8, 2, 6, 7, 6,10, 8, 9,
|
|
7, 9, 7, 7, 8, 8, 8,12, 8, 8,
|
|
7, 6, 7, 6, 4, 7, 7, 7, 7, 6,
|
|
7, 7, 4, 7, 6, 2, 3, 6, 2,10,
|
|
6, 7, 7, 7, 5, 6, 4, 6, 6,10,
|
|
6, 6, 6, 0, 0, 0, 0, 0, 8, 6,
|
|
7, 7, 7, 7, 7, 6, 7, 7, 7, 4,
|
|
4, 3, 8, 8, 7, 0, 0, 7, 7, 7,
|
|
6, 6, 6, 9, 8, 0, 0, 0, 0, 0,
|
|
7, 3, 7, 6, 6, 8, 0, 0, 6, 0,
|
|
0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 7
|
|
};
|
|
|
|
static const byte charWidth[226] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 6, 2, 4, 8, 6,10, 9, 2,
|
|
4, 4, 6, 6, 3, 4, 2, 3, 6, 4,
|
|
6, 6, 7, 6, 6, 6, 6, 6, 2, 3,
|
|
7, 7, 7, 6,11, 8, 7, 8, 8, 7,
|
|
6, 9, 8, 2, 6, 7, 6,10, 8, 9,
|
|
7, 9, 7, 7, 8, 8, 8,12, 8, 8,
|
|
7, 3, 3, 3, 6, 8, 3, 7, 7, 6,
|
|
7, 7, 4, 7, 6, 2, 3, 6, 2,10,
|
|
6, 7, 7, 7, 5, 6, 4, 7, 7,10,
|
|
6, 6, 6, 0, 0, 0, 0, 0, 8, 6,
|
|
7, 7, 7, 7, 7, 6, 7, 7, 7, 4,
|
|
4, 3, 8, 8, 7, 0, 0, 7, 7, 7,
|
|
6, 6, 6, 9, 8, 0, 0, 0, 0, 0,
|
|
7, 3, 7, 6, 6, 8, 0, 6, 0, 0,
|
|
0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 7
|
|
};
|
|
|
|
const char *AGOSEngine::getPixelLength(const char *string, uint16 maxWidth, uint16 &pixels) {
|
|
pixels = 0;
|
|
|
|
while (*string != 0) {
|
|
byte chr = *string;
|
|
uint8 len = (_language == Common::PL_POL) ? polish_charWidth[chr] : charWidth[chr];
|
|
if ((pixels + len) > maxWidth)
|
|
break;
|
|
pixels += len;
|
|
string++;
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
bool AGOSEngine::printTextOf(uint a, uint x, uint y) {
|
|
const byte *stringPtr;
|
|
uint16 pixels, w;
|
|
|
|
if (getGameType() == GType_SIMON2) {
|
|
if (getBitFlag(79)) {
|
|
Subroutine *sub;
|
|
_variableArray[84] = a;
|
|
sub = getSubroutineByID(5003);
|
|
if (sub != NULL)
|
|
startSubroutineEx(sub);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (a >= _numTextBoxes)
|
|
return false;
|
|
|
|
|
|
stringPtr = getStringPtrByID(_shortText[a]);
|
|
if (getGameType() == GType_FF) {
|
|
getPixelLength((const char *)stringPtr, 400, pixels);
|
|
w = pixels + 1;
|
|
x -= w / 2;
|
|
printScreenText(6, 0, (const char *)stringPtr, x, y, w);
|
|
} else {
|
|
showActionString(stringPtr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AGOSEngine::printNameOf(Item *item, uint x, uint y) {
|
|
SubObject *subObject;
|
|
const byte *stringPtr;
|
|
uint16 pixels, w;
|
|
|
|
if (item == 0 || item == _dummyItem2 || item == _dummyItem3)
|
|
return false;
|
|
|
|
subObject = (SubObject *)findChildOfType(item, kObjectType);
|
|
if (subObject == NULL)
|
|
return false;
|
|
|
|
stringPtr = getStringPtrByID(subObject->objectName);
|
|
if (getGameType() == GType_FF) {
|
|
getPixelLength((const char *)stringPtr, 400, pixels);
|
|
w = pixels + 1;
|
|
x -= w / 2;
|
|
printScreenText(6, 0, (const char *)stringPtr, x, y, w);
|
|
} else {
|
|
showActionString(stringPtr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *string, int16 x, int16 y, int16 width) {
|
|
char convertedString[320];
|
|
char *convertedString2 = convertedString;
|
|
int16 height, talkDelay;
|
|
int stringLength = strlen(string);
|
|
int padding, lettersPerRow, lettersPerRowJustified;
|
|
const int textHeight = 10;
|
|
|
|
height = textHeight;
|
|
lettersPerRow = width / 6;
|
|
lettersPerRowJustified = stringLength / (stringLength / lettersPerRow + 1) + 1;
|
|
|
|
talkDelay = (stringLength + 3) / 3;
|
|
if (getGameType() == GType_SIMON1 && (getFeatures() & GF_TALKIE)) {
|
|
if (_variableArray[141] == 0)
|
|
_variableArray[141] = 9;
|
|
_variableArray[85] = _variableArray[141] * talkDelay;
|
|
} else {
|
|
if (_variableArray[86] == 0)
|
|
talkDelay /= 2;
|
|
if (_variableArray[86] == 2)
|
|
talkDelay *= 2;
|
|
_variableArray[85] = talkDelay * 5;
|
|
}
|
|
|
|
assert(stringLength > 0);
|
|
|
|
while (stringLength > 0) {
|
|
int pos = 0;
|
|
if (stringLength > lettersPerRow) {
|
|
int removeLastWord = 0;
|
|
if (lettersPerRow > lettersPerRowJustified) {
|
|
pos = lettersPerRowJustified;
|
|
while (string[pos] != ' ')
|
|
pos++;
|
|
if (pos > lettersPerRow)
|
|
removeLastWord = 1;
|
|
}
|
|
if (lettersPerRow <= lettersPerRowJustified || removeLastWord) {
|
|
pos = lettersPerRow;
|
|
while (string[pos] != ' ' && pos > 0)
|
|
pos--;
|
|
}
|
|
height += textHeight;
|
|
y -= textHeight;
|
|
} else
|
|
pos = stringLength;
|
|
padding = (lettersPerRow - pos) % 2 ?
|
|
(lettersPerRow - pos) / 2 + 1 : (lettersPerRow - pos) / 2;
|
|
while (padding--)
|
|
*convertedString2++ = ' ';
|
|
stringLength -= pos;
|
|
while (pos--)
|
|
*convertedString2++ = *string++;
|
|
*convertedString2++ = '\n';
|
|
string++; // skip space
|
|
stringLength--; // skip space
|
|
}
|
|
*(convertedString2 - 1) = '\0';
|
|
|
|
if (getGameType() == GType_SIMON1)
|
|
stopAnimate(vgaSpriteId + 199);
|
|
else
|
|
stopAnimateSimon2(2, vgaSpriteId);
|
|
|
|
if (getPlatform() == Common::kPlatformAmiga) {
|
|
color = color * 3 + 1;
|
|
renderStringAmiga(vgaSpriteId, color, width, height, convertedString);
|
|
} else {
|
|
color = color * 3 + 192;
|
|
renderString(vgaSpriteId, color, width, height, convertedString);
|
|
}
|
|
|
|
uint16 windowNum = (!getBitFlag(133)) ? 3 : 4;
|
|
if (getGameType() == GType_SIMON1 && (getFeatures() & GF_DEMO))
|
|
windowNum = 4;
|
|
|
|
x /= 8;
|
|
if (y < 2)
|
|
y = 2;
|
|
|
|
if (getGameType() == GType_SIMON1) {
|
|
uint16 id = 199 + vgaSpriteId;
|
|
animate(windowNum, id / 100, id, x, y, 12);
|
|
} else {
|
|
animate(windowNum, 2, vgaSpriteId, x, y, 12);
|
|
}
|
|
}
|
|
|
|
// The Feeble Files specific
|
|
void AGOSEngine_Feeble::printScreenText(uint vgaSpriteId, uint color, const char *string, int16 x, int16 y, int16 width) {
|
|
char convertedString[320];
|
|
char *convertedString2 = convertedString;
|
|
const char *string2 = string;
|
|
int16 height, talkDelay;
|
|
int stringLength = strlen(string);
|
|
int lettersPerRow, lettersPerRowJustified;
|
|
const int textHeight = 15;
|
|
|
|
height = textHeight;
|
|
lettersPerRow = width / 6;
|
|
lettersPerRowJustified = stringLength / (stringLength / lettersPerRow + 1) + 1;
|
|
|
|
talkDelay = (stringLength + 3) / 3;
|
|
if (_variableArray[86] == 0)
|
|
talkDelay /= 2;
|
|
if (_variableArray[86] == 2)
|
|
talkDelay *= 2;
|
|
_variableArray[85] = talkDelay * 5;
|
|
|
|
assert(stringLength > 0);
|
|
|
|
uint16 b, pixels, spaces;
|
|
|
|
while (1) {
|
|
string2 = getPixelLength(string, width, pixels);
|
|
if (*string2 == 0) {
|
|
spaces = (width - pixels) / 12;
|
|
if (spaces != 0)
|
|
spaces--;
|
|
while (spaces) {
|
|
*convertedString2++ = ' ';
|
|
spaces--;
|
|
}
|
|
strcpy(convertedString2, string);
|
|
break;
|
|
}
|
|
while (*string2 != ' ') {
|
|
byte chr = *string2;
|
|
pixels -= (_language == Common::PL_POL) ? polish_charWidth[chr] : charWidth[chr];
|
|
string2--;
|
|
}
|
|
spaces = (width - pixels) / 12;
|
|
if (spaces != 0)
|
|
spaces--;
|
|
while (spaces) {
|
|
*convertedString2++ = ' ';
|
|
spaces--;
|
|
}
|
|
b = string2 - string;
|
|
strncpy(convertedString2, string, b);
|
|
convertedString2 += b;
|
|
*convertedString2++ = '\n';
|
|
height += textHeight;
|
|
y -= textHeight;
|
|
if (y < 2)
|
|
y = 2;
|
|
string = string2;
|
|
}
|
|
|
|
stopAnimateSimon2(2, vgaSpriteId);
|
|
|
|
renderString(1, color, width, height, convertedString);
|
|
|
|
animate(4, 2, vgaSpriteId, x, y, 12);
|
|
}
|
|
|
|
void AGOSEngine_Feeble::printInteractText(uint16 num, const char *string) {
|
|
char convertedString[320];
|
|
char *convertedString2 = convertedString;
|
|
const char *string2 = string;
|
|
uint16 height = 15;
|
|
uint16 w = 0xFFFF;
|
|
uint16 b, pixels, x;
|
|
|
|
// It doesn't really matter what 'w' is to begin with, as long as it's
|
|
// something that cannot be generated by getPixelLength(). The original
|
|
// used 620, which was a potential problem.
|
|
|
|
while (1) {
|
|
string2 = getPixelLength(string, 620, pixels);
|
|
if (*string2 == 0x00) {
|
|
if (w == 0xFFFF)
|
|
w = pixels;
|
|
strcpy(convertedString2, string);
|
|
break;
|
|
}
|
|
while (*string2 != ' ') {
|
|
byte chr = *string2;
|
|
pixels -= (_language == Common::PL_POL) ? polish_charWidth[chr] : charWidth[chr];
|
|
string2--;
|
|
}
|
|
if (w == 0xFFFF)
|
|
w = pixels;
|
|
b = string2 - string;
|
|
strncpy(convertedString2, string, b);
|
|
convertedString2 += b;
|
|
*convertedString2++ = '\n';
|
|
height += 15;
|
|
string = string2;
|
|
}
|
|
|
|
// ScrollX
|
|
x = _variableArray[251];
|
|
x += 20;
|
|
|
|
if (num == 1)
|
|
_interactY = 385;
|
|
|
|
// Returned values for box definition
|
|
_variableArray[51] = x;
|
|
_variableArray[52] = _interactY;
|
|
_variableArray[53] = w;
|
|
_variableArray[54] = height;
|
|
|
|
stopAnimateSimon2(2, num + 6);
|
|
renderString(num, 0, w, height, convertedString);
|
|
animate(4, 2, num + 6, x, _interactY, 12);
|
|
|
|
_interactY += height;
|
|
}
|
|
|
|
void AGOSEngine_Feeble::sendInteractText(uint16 num, const char *fmt, ...) {
|
|
va_list arglist;
|
|
char string[256];
|
|
|
|
va_start(arglist, fmt);
|
|
vsprintf(string, fmt, arglist);
|
|
va_end(arglist);
|
|
|
|
printInteractText(num, string);
|
|
}
|
|
|
|
// Waxworks specific
|
|
uint16 AGOSEngine_Waxworks::getBoxSize() {
|
|
int x;
|
|
switch (_boxLineCount) {
|
|
case 1: x = _lineCounts[0];
|
|
if (x <= 26)
|
|
return 1;
|
|
if (x <= 64)
|
|
if (checkFit(_linePtrs[0], 32, 2))
|
|
return 2;
|
|
if (x <= 111)
|
|
if (checkFit(_linePtrs[0], 37, 3))
|
|
return 3;
|
|
if (x <= 168)
|
|
if (checkFit(_linePtrs[0], 42, 4))
|
|
return 4;
|
|
if (x <= 240)
|
|
if (checkFit(_linePtrs[0], 48, 5))
|
|
return 5;
|
|
return 6;
|
|
case 2: if (_lineCounts[0] <= 32) {
|
|
if (_lineCounts[1] <= 32)
|
|
return 2;
|
|
if (_lineCounts[1] <= 74)
|
|
if (checkFit(_linePtrs[1], 37, 2))
|
|
return 3;
|
|
if (_lineCounts[1] <= 126)
|
|
if (checkFit(_linePtrs[1], 42, 3))
|
|
return 4;
|
|
if (_lineCounts[1] <= 172)
|
|
if (checkFit(_linePtrs[1], 48, 4))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[0] <= 74) && (checkFit(_linePtrs[0], 37, 2))) {
|
|
if (_lineCounts[1] <= 37)
|
|
return 3;
|
|
if (_lineCounts[1] <= 84)
|
|
if (checkFit(_linePtrs[1], 42, 2))
|
|
return 4;
|
|
if (_lineCounts[1] <= 144)
|
|
if (checkFit(_linePtrs[1], 48, 3))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[0] <= 126) && (checkFit(_linePtrs[0], 42, 3))) {
|
|
if (_lineCounts[1] <= 42)
|
|
return 4;
|
|
if (_lineCounts[1] <= 84)
|
|
if (checkFit(_linePtrs[1], 48, 2))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[0] <= 192) && (checkFit(_linePtrs[0], 48, 4))) {
|
|
if (_lineCounts[1] <= 48)
|
|
return 5;
|
|
return 6;
|
|
}
|
|
return 6;
|
|
case 3: if (_lineCounts[0] <= 37) {
|
|
if (_lineCounts[1] <= 37) {
|
|
if (_lineCounts[2] <= 37)
|
|
return 3;
|
|
if (_lineCounts[2] <= 84)
|
|
if (checkFit(_linePtrs[2], 42, 2))
|
|
return 4;
|
|
if (_lineCounts[2] <= 144)
|
|
if (checkFit(_linePtrs[2], 48, 3))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[1] <= 84) && (checkFit(_linePtrs[1], 42, 2))) {
|
|
if (_lineCounts[2] <= 42)
|
|
return 4;
|
|
if (_lineCounts[2] <= 96)
|
|
if (checkFit(_linePtrs[2], 48, 2))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[1] <= 144) && (checkFit(_linePtrs[1], 48, 3))) {
|
|
if (_lineCounts[2] <= 48)
|
|
return 5;
|
|
return 6;
|
|
}
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[0] <= 84) && (checkFit(_linePtrs[0], 42, 2))) {
|
|
if (_lineCounts[1] <= 42) {
|
|
if (_lineCounts[2] <= 42)
|
|
return 4;
|
|
if (_lineCounts[2] <= 96)
|
|
if (checkFit(_linePtrs[2], 48, 2))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[1] <= 96) && (checkFit(_linePtrs[1], 48, 2))) {
|
|
if (_lineCounts[2] <= 48)
|
|
return 5;
|
|
return 6;
|
|
}
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[0] <= 96) && (checkFit(_linePtrs[0], 48, 3))) {
|
|
if (_lineCounts[1] <= 48) {
|
|
if (_lineCounts[2] <= 48)
|
|
return 5;
|
|
}
|
|
return 6;
|
|
}
|
|
return 6;
|
|
case 4: if (_lineCounts[0] <= 42) {
|
|
if (_lineCounts[1] <= 42) {
|
|
if (_lineCounts[2] <= 42) {
|
|
if (_lineCounts[3] <= 42)
|
|
return 4;
|
|
if (_lineCounts[3] <= 96)
|
|
if (checkFit(_linePtrs[3], 48, 2))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[2] <= 96) && (checkFit(_linePtrs[2], 48, 2)))
|
|
if (_lineCounts[3] <= 48)
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[1] <= 96) && (checkFit(_linePtrs[1], 48, 2)))
|
|
if ((_lineCounts[2] <= 48) && (_lineCounts[3] <= 48))
|
|
return 5;
|
|
return 6;
|
|
}
|
|
if ((_lineCounts[0] <= 96) && (checkFit(_linePtrs[0], 48, 2)))
|
|
if ((_lineCounts[1] <= 48) && (_lineCounts[2] <= 48) && (_lineCounts[3] <= 48))
|
|
return 5;
|
|
return 6;
|
|
case 5: if ((_lineCounts[0] > 48) || (_lineCounts[1] > 48) || (_lineCounts[2] > 48)
|
|
|| (_lineCounts[3] > 48) || (_lineCounts[4] > 48))
|
|
return 6;
|
|
else
|
|
return 5;
|
|
default:
|
|
return 6;
|
|
}
|
|
}
|
|
|
|
|
|
uint16 AGOSEngine_Waxworks::checkFit(char *ptr, int width, int lines) {
|
|
int countw = 0;
|
|
int countl = 0;
|
|
char *x = NULL;
|
|
while (*ptr) {
|
|
if (*ptr == '\n')
|
|
return 1;
|
|
if (countw == width) {
|
|
countl++;
|
|
countw = 0;
|
|
ptr = x;
|
|
}
|
|
if (*ptr == ' ') {
|
|
x = ptr;
|
|
x++;
|
|
}
|
|
countw++;
|
|
if (countl == lines)
|
|
return 0;
|
|
ptr++;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void AGOSEngine_Waxworks::boxTextMessage(const char *x) {
|
|
sprintf(_boxBufferPtr, "%s\n", x);
|
|
_lineCounts[_boxLineCount] += strlen(x);
|
|
_boxBufferPtr += strlen(x) + 1;
|
|
_boxLineCount++;
|
|
_linePtrs[_boxLineCount] = _boxBufferPtr;
|
|
_boxCR = 1;
|
|
}
|
|
|
|
void AGOSEngine_Waxworks::boxTextMsg(const char *x) {
|
|
sprintf(_boxBufferPtr, "%s", x);
|
|
_lineCounts[_boxLineCount] += strlen(x);
|
|
_boxBufferPtr += strlen(x);
|
|
_boxCR = 0;
|
|
}
|
|
|
|
void AGOSEngine_Waxworks::printBox() {
|
|
uint16 BoxSize;
|
|
|
|
*_boxBufferPtr = 0;
|
|
_linePtrs[0] = _boxBuffer;
|
|
if (_boxCR == 0)
|
|
_boxLineCount++;
|
|
stopAnimate(105);
|
|
BoxSize = getBoxSize();
|
|
_variableArray[53] = BoxSize;
|
|
animate(3, 1, 100, 0, 0, 0);
|
|
changeWindow(5);
|
|
|
|
switch (BoxSize) {
|
|
case 1: _textWindow->x = 10;
|
|
_textWindow->y = 163;
|
|
_textWindow->width = 20;
|
|
_textWindow->height = 1;
|
|
_textWindow->textMaxLength = 26;
|
|
break;
|
|
case 2: _textWindow->x = 8;
|
|
_textWindow->y = 160;
|
|
_textWindow->width = 24;
|
|
_textWindow->height = 2;
|
|
_textWindow->textMaxLength = 32;
|
|
break;
|
|
case 3: _textWindow->x = 6;
|
|
_textWindow->y = 156;
|
|
_textWindow->width = 28;
|
|
_textWindow->height = 3;
|
|
_textWindow->textMaxLength = 37;
|
|
break;
|
|
case 4: _textWindow->x = 4;
|
|
_textWindow->y = 153;
|
|
_textWindow->width = 32;
|
|
_textWindow->height = 4;
|
|
_textWindow->textMaxLength = 42;
|
|
break;
|
|
case 5: _textWindow->x = 2;
|
|
_textWindow->y = 150;
|
|
_textWindow->width = 36;
|
|
_textWindow->height = 5;
|
|
_textWindow->textMaxLength = 48;
|
|
break;
|
|
default:_textWindow->x = 1;
|
|
_textWindow->y = 147;
|
|
_textWindow->width = 38;
|
|
_textWindow->height = 6;
|
|
_textWindow->textMaxLength = 50;
|
|
break;
|
|
}
|
|
_textWindow->textColumn = 0;
|
|
_textWindow->textRow = 0;
|
|
_textWindow->textColumnOffset = 0;
|
|
_textWindow->textLength = 0;
|
|
justifyStart();
|
|
waitForSync(99);
|
|
_boxBufferPtr = _boxBuffer;
|
|
while (*_boxBufferPtr)
|
|
justifyOutPut(*_boxBufferPtr++);
|
|
_boxLineCount = 0;
|
|
_boxBufferPtr = _boxBuffer;
|
|
_lineCounts[0] = 0;
|
|
_lineCounts[1] = 0;
|
|
_lineCounts[2] = 0;
|
|
_lineCounts[3] = 0;
|
|
_lineCounts[4] = 0;
|
|
_lineCounts[5] = 0;
|
|
changeWindow(0);
|
|
}
|
|
|
|
#ifdef ENABLE_PN
|
|
// Personal Nightmare specific
|
|
uint32 AGOSEngine_PN::ftext(uint32 base, int n) {
|
|
uint32 b = base;
|
|
int ct = n;
|
|
while (ct) {
|
|
while(_textBase[b++])
|
|
;
|
|
ct--;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
char *AGOSEngine_PN::unctok(char *c, int n) {
|
|
int x;
|
|
uint8 *tokbase;
|
|
tokbase = _textBase + getlong(30);
|
|
x = n;
|
|
while (x-=(*tokbase++ > 127))
|
|
;
|
|
while (*tokbase < 128)
|
|
*c++=*tokbase++;
|
|
*c++ = *tokbase & 127;
|
|
*c = 0;
|
|
return c;
|
|
}
|
|
|
|
void AGOSEngine_PN::uncomstr(char *c, uint32 x) {
|
|
if (x > _textBaseSize)
|
|
error("UNCOMSTR: TBASE over-run");
|
|
while (_textBase[x]) {
|
|
if (_textBase[x] < 244) {
|
|
c = unctok(c, _textBase[x]);
|
|
} else {
|
|
c = unctok(c, (_textBase[x] - 244) * 254 + _textBase[x + 1] - 1);
|
|
x++;
|
|
}
|
|
x++;
|
|
}
|
|
*c++ = 13;
|
|
*c = 0;
|
|
}
|
|
|
|
static const char *objectNames[30] = {
|
|
"\0",
|
|
"Take \0",
|
|
"Inventory\r",
|
|
"Open \0",
|
|
"Close \0",
|
|
"Lock \0",
|
|
"Unlock \0",
|
|
"Examine \0",
|
|
"Look in \0",
|
|
"Exits \r",
|
|
"Look\r",
|
|
"Wait\r",
|
|
"Pause\r",
|
|
"\0",
|
|
"Save\r",
|
|
"Restore\r",
|
|
"\0",
|
|
"N\r",
|
|
"NE\r",
|
|
"E\r",
|
|
"SE\r",
|
|
"S\r",
|
|
"SW\r",
|
|
"W\r",
|
|
"NW\r",
|
|
"INVENTORY\r",
|
|
"ROOM DESCRIPTION\r",
|
|
"x\r",
|
|
"MORE\r",
|
|
"CLOSE\r"
|
|
};
|
|
|
|
void AGOSEngine_PN::getObjectName(char *v, uint16 x) {
|
|
if (x & 0x8000) {
|
|
x &= ~0x8000;
|
|
if (x > getptr(51))
|
|
error("getObjectName: Object %d out of range", x);
|
|
uncomstr(v, ftext(getlong(27), x * _dataBase[47]));
|
|
} else {
|
|
assert(x < 30);
|
|
strcpy(v, objectNames[x]);
|
|
}
|
|
}
|
|
|
|
void AGOSEngine_PN::pcl(const char *s) {
|
|
strcat(_sb, s);
|
|
if (strchr(s, '\n') == 0) {
|
|
for (char *str = _sb; *str; str++)
|
|
windowPutChar(_windowArray[_curWindow], *str);
|
|
strcpy(_sb, "");
|
|
}
|
|
}
|
|
|
|
void AGOSEngine_PN::pcf(uint8 ch) {
|
|
int ct = 0;
|
|
if (ch == '[')
|
|
ch = '\n';
|
|
if (ch == 0)
|
|
return; /* Trap any C EOS chrs */
|
|
if (ch == 255) {
|
|
_bp = 0;
|
|
_xofs = 0;
|
|
return; /* pcf(255) initialises the routine */
|
|
} /* pcf(254) flushes its working _buffer */
|
|
if (ch != 254) {
|
|
if ((ch != 32) || (_bp + _xofs != 50))
|
|
_buffer[_bp++] = ch;
|
|
}
|
|
if ((ch != 254) && (!isspace(ch)) && (_bp < 60))
|
|
return;
|
|
/* We know have a case of needing to print the text */
|
|
if (_bp + _xofs > 50) {
|
|
pcl("\n");
|
|
if (_buffer[0] == ' ')
|
|
ct = 1; /* Skip initial space */
|
|
/* Note ' ' will give a single start of line space */
|
|
_xofs = 0;
|
|
}
|
|
_buffer[_bp] = 0;
|
|
pcl(_buffer + ct);
|
|
_xofs += _bp;
|
|
_bp = 0;
|
|
if (ch == '\n')
|
|
_xofs = 0; /* At Newline! */
|
|
}
|
|
|
|
void AGOSEngine_PN::patok(int n) {
|
|
int x;
|
|
uint8 *tokbase;
|
|
tokbase = _textBase + getlong(30);
|
|
x = n;
|
|
while (x -= (*tokbase++ > 127))
|
|
;
|
|
while (*tokbase < 128)
|
|
pcf(*tokbase++);
|
|
pcf((uint8)(*tokbase & 127));
|
|
}
|
|
|
|
void AGOSEngine_PN::pmesd(int n) {
|
|
ptext(ftext(getlong(24), n));
|
|
}
|
|
|
|
void AGOSEngine_PN::plocd(int n, int m) {
|
|
if (n > getptr(53))
|
|
error("Location out of range");
|
|
ptext(ftext(getlong(21), n * _dataBase[48] + m));
|
|
}
|
|
|
|
void AGOSEngine_PN::pobjd(int n, int m) {
|
|
if (n > getptr(51))
|
|
error("Object out of range");
|
|
ptext(ftext(getlong(27), n * _dataBase[47] + m));
|
|
}
|
|
|
|
void AGOSEngine_PN::ptext(uint32 tptr) {
|
|
if (tptr > _textBaseSize)
|
|
error("ptext: attempt to print beyond end of TBASE");
|
|
|
|
while (_textBase[tptr]) {
|
|
if (_textBase[tptr] < 244) {
|
|
patok(_textBase[tptr++]);
|
|
} else {
|
|
patok((_textBase[tptr] - 244) * 254 + _textBase[tptr + 1] - 1);
|
|
tptr += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
const uint8 characters[11][80] = {
|
|
// PETERMASON
|
|
{
|
|
118, 225,
|
|
91, 118,
|
|
94, 124,
|
|
236, 161,
|
|
241, 166,
|
|
168, 4,
|
|
138, 46,
|
|
139, 46,
|
|
249, 50,
|
|
38, 56,
|
|
80, 59,
|
|
149, 69,
|
|
37, 77,
|
|
93, 93,
|
|
86, 95,
|
|
0,
|
|
0,
|
|
58, 130,
|
|
62, 178,
|
|
83, 95,
|
|
0,
|
|
121, 58,
|
|
122, 59,
|
|
126, 60,
|
|
124, 61,
|
|
240, 62,
|
|
123, 63,
|
|
0
|
|
},
|
|
// JBLANDFORD
|
|
{
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
},
|
|
// SBLANDFORD
|
|
{
|
|
120, 223,
|
|
94, 126,
|
|
112, 134,
|
|
45, 152,
|
|
241, 166,
|
|
168, 3,
|
|
150, 26,
|
|
220, 29,
|
|
138, 42,
|
|
139, 47,
|
|
249, 50,
|
|
38, 56,
|
|
230, 64,
|
|
37, 77,
|
|
93, 94,
|
|
86, 96,
|
|
0,
|
|
0,
|
|
58, 129,
|
|
59, 112,
|
|
83, 96,
|
|
81, 106,
|
|
62, 169,
|
|
0,
|
|
121, 54,
|
|
122, 55,
|
|
119, 56,
|
|
118, 57,
|
|
0
|
|
},
|
|
// MRJONES
|
|
{
|
|
121, 218,
|
|
91, 118,
|
|
253, 121,
|
|
154, 138,
|
|
235, 173,
|
|
236, 161,
|
|
241, 165,
|
|
168, 0,
|
|
150, 21,
|
|
36, 33,
|
|
138, 42,
|
|
249, 50,
|
|
80, 60,
|
|
4, 60,
|
|
37, 78,
|
|
68, 33,
|
|
93, 92,
|
|
101, 109,
|
|
0,
|
|
36, 35,
|
|
68, 90,
|
|
0,
|
|
58, 128,
|
|
59, 111,
|
|
62, 182,
|
|
0,
|
|
122, 13,
|
|
126, 14,
|
|
124, 15,
|
|
240, 16,
|
|
120, 17,
|
|
119, 18,
|
|
118, 19,
|
|
52, 20,
|
|
125, 21,
|
|
127, 22,
|
|
123, 23,
|
|
117, 24,
|
|
0
|
|
},
|
|
// MRSJONES
|
|
{
|
|
122, 219,
|
|
91, 119,
|
|
253, 123,
|
|
112, 136,
|
|
154, 137,
|
|
95, 142,
|
|
45, 152,
|
|
109, 155,
|
|
235, 160,
|
|
168, 1,
|
|
151, 13,
|
|
145, 15,
|
|
150, 22,
|
|
220, 28,
|
|
36, 33,
|
|
138, 43,
|
|
13, 51,
|
|
80, 59,
|
|
230, 64,
|
|
149, 69,
|
|
86, 100,
|
|
0,
|
|
36, 36,
|
|
0,
|
|
58, 127,
|
|
62, 179,
|
|
83, 100,
|
|
81, 102,
|
|
0,
|
|
121, 25,
|
|
126, 26,
|
|
124, 27,
|
|
120, 28,
|
|
119, 29,
|
|
118, 30,
|
|
52, 31,
|
|
125, 32,
|
|
127, 33,
|
|
123, 34,
|
|
117, 35,
|
|
0
|
|
},
|
|
// MRROBERTS
|
|
{
|
|
123, 229,
|
|
91, 117,
|
|
253, 120,
|
|
94, 125,
|
|
112, 134,
|
|
109, 156,
|
|
235, 172,
|
|
236, 162,
|
|
241, 165,
|
|
168, 3,
|
|
36, 33,
|
|
249, 50,
|
|
38, 56,
|
|
80, 58,
|
|
37, 75,
|
|
34, 81,
|
|
68, 33,
|
|
101, 109,
|
|
0,
|
|
36, 40,
|
|
68, 88,
|
|
0,
|
|
59, 111,
|
|
62, 181,
|
|
0,
|
|
0
|
|
},
|
|
// POSTMISTRESS
|
|
{
|
|
124, 221,
|
|
91, 119,
|
|
253, 122,
|
|
112, 136,
|
|
95, 142,
|
|
130, 149,
|
|
109, 155,
|
|
235, 176,
|
|
220, 29,
|
|
36, 33,
|
|
138, 43,
|
|
13, 51,
|
|
80, 57,
|
|
149, 68,
|
|
37, 73,
|
|
34, 33,
|
|
68, 33,
|
|
86, 100,
|
|
0,
|
|
36, 39,
|
|
34, 80,
|
|
68, 86,
|
|
0,
|
|
58, 130,
|
|
62, 181,
|
|
83, 100,
|
|
81, 103,
|
|
0,
|
|
121, 41,
|
|
122, 42,
|
|
126, 43,
|
|
240, 44,
|
|
120, 45,
|
|
119, 46,
|
|
118, 47,
|
|
52, 48,
|
|
123, 49,
|
|
83, 50,
|
|
117, 51,
|
|
0
|
|
},
|
|
// MWILLIAMS
|
|
{
|
|
125, 227,
|
|
94, 124,
|
|
95, 141,
|
|
241, 166,
|
|
168, 4,
|
|
150, 26,
|
|
38, 54,
|
|
4, 60,
|
|
230, 65,
|
|
149, 68,
|
|
37, 76,
|
|
101, 109,
|
|
0,
|
|
230, 63,
|
|
0,
|
|
59, 112,
|
|
62, 183,
|
|
0,
|
|
240, 71,
|
|
120, 72,
|
|
118, 73,
|
|
52, 74,
|
|
117, 75,
|
|
0
|
|
},
|
|
// TONY
|
|
{
|
|
126, 220,
|
|
95, 143,
|
|
130, 149,
|
|
45, 153,
|
|
109, 154,
|
|
235, 158,
|
|
241, 166,
|
|
168, 2,
|
|
145, 15,
|
|
150, 24,
|
|
220, 20,
|
|
36, 20,
|
|
4, 60,
|
|
37, 79,
|
|
86, 97,
|
|
0,
|
|
150, 23,
|
|
220, 27,
|
|
36, 34,
|
|
0,
|
|
83, 97,
|
|
0,
|
|
121, 36,
|
|
122, 37,
|
|
124, 38,
|
|
240, 39,
|
|
52, 40,
|
|
0
|
|
},
|
|
// PIG
|
|
{
|
|
127, 228,
|
|
112, 133,
|
|
45, 153,
|
|
235, 157,
|
|
236, 163,
|
|
241, 165,
|
|
36, 33,
|
|
80, 58,
|
|
34, 81,
|
|
68, 33,
|
|
86, 98,
|
|
0,
|
|
36, 37,
|
|
68, 90,
|
|
0,
|
|
62, 184,
|
|
83, 98,
|
|
0,
|
|
121, 76,
|
|
122, 77,
|
|
126, 78,
|
|
124, 79,
|
|
240, 80,
|
|
120, 81,
|
|
118, 82,
|
|
52, 83,
|
|
125, 84,
|
|
123, 85,
|
|
83, 86,
|
|
117, 87,
|
|
0
|
|
},
|
|
// JUDY
|
|
{
|
|
0,
|
|
0,
|
|
0,
|
|
240, 52,
|
|
117, 53,
|
|
0
|
|
}
|
|
};
|
|
|
|
void AGOSEngine_PN::getResponse(uint16 charNum, uint16 objNum, uint16 &msgNum1, uint16 &msgNum2) {
|
|
const uint8 *ptr;
|
|
uint16 num;
|
|
|
|
msgNum1 = 0;
|
|
msgNum2 = 0;
|
|
|
|
if (charNum == 83)
|
|
charNum += 45;
|
|
|
|
if (charNum < 118 || charNum > 128) {
|
|
return;
|
|
}
|
|
|
|
ptr = characters[charNum - 118];
|
|
|
|
while ((num = *ptr++) != 0) {
|
|
if (num == objNum) {
|
|
msgNum1 = *ptr++;
|
|
msgNum1 += 400;
|
|
|
|
while ((num = *ptr++) != 0)
|
|
ptr++;
|
|
break;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
while ((num = *ptr++) != 0) {
|
|
if (num == objNum) {
|
|
msgNum2 = *ptr++;
|
|
msgNum2 += 400;
|
|
|
|
if (msgNum1 == 569)
|
|
msgNum1 += 400;
|
|
if (msgNum2 == 0)
|
|
msgNum2 = msgNum1;
|
|
return;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
if (objNum >= 200)
|
|
msgNum1 = 0;
|
|
|
|
objNum -= 200;
|
|
while ((num = *ptr++) != 0) {
|
|
if (num == objNum) {
|
|
msgNum1 = *ptr++;
|
|
msgNum1 += 400;
|
|
|
|
if (msgNum1 == 569)
|
|
msgNum1 += 400;
|
|
if (msgNum2 == 0)
|
|
msgNum2 = msgNum1;
|
|
return;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
objNum += 200;
|
|
while ((num = *ptr++) != 0) {
|
|
if (num == objNum) {
|
|
msgNum1 = *ptr++;
|
|
msgNum1 += 200;
|
|
|
|
if (msgNum1 == 569)
|
|
msgNum1 += 400;
|
|
if (msgNum2 == 0)
|
|
msgNum2 = msgNum1;
|
|
return;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
if (msgNum1 == 569)
|
|
msgNum1 += 400;
|
|
if (msgNum2 == 0)
|
|
msgNum2 = msgNum1;
|
|
}
|
|
|
|
char *AGOSEngine_PN::getMessage(char *msg, uint16 num) {
|
|
char *origPtr, *strPtr1 = msg;
|
|
uint8 count;
|
|
|
|
getObjectName(strPtr1, num);
|
|
if (!(num & 0x8000)) {
|
|
return msg;
|
|
}
|
|
|
|
if (strPtr1[0] == 0x41 || strPtr1[0] == 0x61) {
|
|
if (strPtr1[1] != 0x20)
|
|
strPtr1 += 2;
|
|
} else if (strPtr1[0] == 0x54 || strPtr1[0] == 0x74) {
|
|
if (strPtr1[1] == 0x68 &&
|
|
strPtr1[2] == 0x65 &&
|
|
strPtr1[3] == 0x20)
|
|
strPtr1 += 4;
|
|
}
|
|
|
|
origPtr = strPtr1;
|
|
while (*strPtr1 != 13)
|
|
strPtr1++;
|
|
|
|
strPtr1[0] = 32;
|
|
strPtr1[1] = 13;
|
|
strPtr1[2] = 0;
|
|
|
|
if (_videoLockOut & 0x10) {
|
|
strPtr1 = origPtr;
|
|
count = 6;
|
|
while (*strPtr1) {
|
|
if (*strPtr1 == 32) {
|
|
count = 6;
|
|
} else {
|
|
count--;
|
|
if (count == 0) {
|
|
char *tmpPtr = strPtr1;
|
|
char *strPtr2 = strPtr1;
|
|
|
|
while (*strPtr2 != 0 && *strPtr2 != 32)
|
|
strPtr2++;
|
|
|
|
while (*strPtr2) {
|
|
*strPtr1++ = *strPtr2++;
|
|
}
|
|
*strPtr1++ = *strPtr2++;
|
|
|
|
strPtr1 = tmpPtr;
|
|
count = 6;
|
|
}
|
|
}
|
|
strPtr1++;
|
|
}
|
|
}
|
|
|
|
return origPtr;
|
|
}
|
|
#endif
|
|
|
|
} // End of namespace AGOS
|