To match the original v7/v8 interpreters, use BlastTexts to display the subtitles. This allows to fix the bug #1092993. As this is quite an important change, regressions may appear. You've been warned :)

svn-id: r19398
This commit is contained in:
Gregory Montoir 2005-11-02 21:47:44 +00:00
parent 5e75092dec
commit c84d1ada32
7 changed files with 328 additions and 216 deletions

View File

@ -1360,10 +1360,13 @@ void ScummEngine_v7::actorTalk(const byte *msg) {
}
_charsetBufPos = 0;
_talkDelay = 0;
_haveMsg = 0xFF;
_haveMsg = 1;
if (_version == 7)
VAR(VAR_HAVE_MSG) = 0xFF;
_haveActorSpeechMsg = true;
CHARSET_1();
if (_version == 8)
VAR(VAR_HAVE_MSG) = (_string[0].no_talk_anim) ? 2 : 1;
}
#endif
@ -1428,6 +1431,7 @@ void ScummEngine::actorTalk(const byte *msg) {
VAR(VAR_HAVE_MSG) = 0xFF;
if (VAR_CHARCOUNT != 0xFF)
VAR(VAR_CHARCOUNT) = 0;
_haveActorSpeechMsg = true;
CHARSET_1();
}
@ -1474,7 +1478,13 @@ void ScummEngine::stopTalk() {
if (_version == 8)
VAR(VAR_HAVE_MSG) = 0;
_keepText = false;
_charset->restoreCharsetBg();
if (_version >= 7) {
#ifndef DISABLE_SCUMM_7_8
((ScummEngine_v7 *)this)->clearSubtitleQueue();
#endif
} else {
_charset->restoreCharsetBg();
}
}
void Actor::setActorCostume(int c) {

View File

@ -516,6 +516,13 @@ protected:
int _smushFrameRate;
struct TextObject {
int16 xpos, ypos;
byte color;
byte charset;
byte text[256];
};
/** BlastObjects to draw */
struct BlastObject {
uint16 number;
@ -528,13 +535,9 @@ protected:
int _blastObjectQueuePos;
BlastObject _blastObjectQueue[128];
struct BlastText {
int16 xpos, ypos;
struct BlastText : TextObject {
Common::Rect rect;
byte color;
byte charset;
bool center;
byte text[256];
};
int _blastTextQueuePos;
@ -1004,6 +1007,8 @@ protected:
int findObject(int x, int y, int num, int *args);
int getSoundResourceSize(int id);
virtual bool handleNextCharsetCode(Actor *a, int *c);
/* HE version 72 script opcodes */
void o72_pushDWord();
void o72_getScriptString();
@ -1338,6 +1343,17 @@ public:
int _languageIndexSize;
char _lastStringTag[12+1];
struct SubtitleText : TextObject {
bool actorSpeechMsg;
};
int _subtitleQueuePos;
SubtitleText _subtitleQueue[20];
void processSubtitleQueue();
void addSubtitleToQueue(const byte *text, const Common::Point &pos, byte color, byte charset);
void clearSubtitleQueue();
protected:
virtual void setupScummVars();
virtual void initScummVars();

View File

@ -730,6 +730,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
MKLINE(ScummEngine, _charsetBufPos, sleInt16, VER(10)),
MKLINE(ScummEngine, _haveMsg, sleByte, VER(8)),
MKLINE(ScummEngine, _haveActorSpeechMsg, sleByte, VER(61)),
MKLINE(ScummEngine, _useTalkAnims, sleByte, VER(8)),
MKLINE(ScummEngine, _talkDelay, sleInt16, VER(8)),
@ -952,6 +953,13 @@ void ScummEngine::saveOrLoad(Serializer *s) {
_system->warpMouse(_mouse.x, _mouse.y);
}
// Before V61, we re-used the _haveMsg flag to handle "alternative" speech
// sound files (see charset code 10).
if (s->isLoading() && s->getVersion() < VER(61)) {
_haveActorSpeechMsg = (_haveMsg != 0xFE);
_haveMsg = 0xFF;
}
//
// Save/load actors
//
@ -1190,8 +1198,25 @@ void ScummEngine_v5::saveOrLoad(Serializer *s) {
void ScummEngine_v7::saveOrLoad(Serializer *s) {
ScummEngine::saveOrLoad(s);
assert(_imuseDigital);
const SaveLoadEntry subtitleQueueEntries[] = {
MKARRAY(SubtitleText, text[0], sleByte, 256, VER(61)),
MKLINE(SubtitleText, charset, sleByte, VER(61)),
MKLINE(SubtitleText, color, sleByte, VER(61)),
MKLINE(SubtitleText, xpos, sleInt16, VER(61)),
MKLINE(SubtitleText, ypos, sleInt16, VER(61)),
MKLINE(SubtitleText, actorSpeechMsg, sleByte, VER(61)),
MKEND()
};
const SaveLoadEntry V7Entries[] = {
MKLINE(ScummEngine_v7, _subtitleQueuePos, sleInt32, VER(61)),
MKEND()
};
_imuseDigital->saveOrLoad(s);
s->saveLoadArrayOf(_subtitleQueue, ARRAYSIZE(_subtitleQueue), sizeof(_subtitleQueue[0]), subtitleQueueEntries);
s->saveLoadEntries(this, V7Entries);
}
#endif

View File

@ -45,7 +45,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
#define CURRENT_VER 60
#define CURRENT_VER 61
/**
* An auxillary macro, used to specify savegame versions. We use this instead

View File

@ -1128,6 +1128,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
_palDirtyMin = 0;
_palDirtyMax = 0;
_haveMsg = 0;
_haveActorSpeechMsg = false;
_useTalkAnims = false;
_defaultTalkDelay = 0;
_midiDriver = MD_NULL;
@ -1585,6 +1586,7 @@ ScummEngine_v7::ScummEngine_v7(GameDetector *detector, OSystem *syst, const Scum
_existLanguageFile = false;
_languageBuffer = NULL;
_languageIndex = NULL;
clearSubtitleQueue();
}
ScummEngine_v7::~ScummEngine_v7() {
@ -1939,6 +1941,7 @@ void ScummEngine::scummInit() {
_charsetBufPos = 0;
_haveMsg = 0;
_haveActorSpeechMsg = false;
_varwatch = -1;
_screenStartStrip = 0;
@ -2296,7 +2299,7 @@ int ScummEngine::scummLoop(int delta) {
VAR(VAR_CAMERA_POS_X) = camera._cur.x;
}
if (_version <= 7)
VAR(VAR_HAVE_MSG) = (_haveMsg == 0xFE) ? 0xFF : _haveMsg;
VAR(VAR_HAVE_MSG) = _haveMsg;
if (_platform == Common::kPlatformC64 && _gameId == GID_MANIAC) {
// TODO

View File

@ -1093,6 +1093,7 @@ protected:
byte *_palManipIntermediatePal;
byte _haveMsg;
bool _haveActorSpeechMsg;
bool _useTalkAnims;
uint16 _defaultTalkDelay;
int _tempMusic;
@ -1161,6 +1162,7 @@ protected:
void printString(int m, const byte *msg);
virtual bool handleNextCharsetCode(Actor *a, int *c);
void CHARSET_1();
void drawString(int a, const byte *msg);
void debugMessage(const byte *msg);

View File

@ -95,17 +95,212 @@ void ScummEngine::showMessageDialog(const byte *msg) {
VAR(VAR_KEYPRESS) = runDialog(dialog);
}
void ScummEngine::CHARSET_1() {
#ifndef DISABLE_SCUMM_7_8
void ScummEngine_v7::processSubtitleQueue() {
for (int i = 0; i < _subtitleQueuePos; ++i) {
SubtitleText *st = &_subtitleQueue[i];
if (!ConfMan.getBool("subtitles") || VAR(VAR_VOICE_MODE) == 0)
// subtitles are disabled, don't display the text
continue;
if (!ConfMan.getBool("subtitles") && (!st->actorSpeechMsg || _mixer->isSoundHandleActive(_sound->_talkChannelHandle)))
// no subtitles and there's a speech variant of the message, don't display the text
continue;
enqueueText(st->text, st->xpos, st->ypos, st->color, st->charset, false);
}
}
void ScummEngine_v7::addSubtitleToQueue(const byte *text, const Common::Point &pos, byte color, byte charset) {
if (text[0] && strcmp((const char *)text, " ") != 0) {
assert(_subtitleQueuePos < ARRAYSIZE(_subtitleQueue));
SubtitleText *st = &_subtitleQueue[_subtitleQueuePos];
int i = 0;
while (1) {
st->text[i] = text[i];
if (!text[i])
break;
++i;
}
st->xpos = pos.x;
st->ypos = pos.y;
st->color = color;
st->charset = charset;
st->actorSpeechMsg = _haveActorSpeechMsg;
++_subtitleQueuePos;
}
}
void ScummEngine_v7::clearSubtitleQueue() {
memset(_subtitleQueue, 0, sizeof(_subtitleQueue));
_subtitleQueuePos = 0;
}
#endif
bool ScummEngine::handleNextCharsetCode(Actor *a, int *code) {
uint32 talk_sound_a = 0;
uint32 talk_sound_b = 0;
int i, t, c;
int frme;
Actor *a;
byte *buffer;
int code = (_heversion >= 80) ? 127 : 64;
char value[32];
int i, color, frme, c, oldy;
bool endLoop = false;
byte *buffer = _charsetBuffer + _charsetBufPos;
while (!endLoop) {
c = *buffer++;
if (!(c == 0xFF || (_version <= 6 && c == 0xFE))) {
break;
}
c = *buffer++;
switch (c) {
case 1:
c = 13; // new line
endLoop = true;
break;
case 2:
_haveMsg = 0;
_keepText = true;
endLoop = true;
break;
case 3:
_haveMsg = (_version >= 7) ? 1 : 0xFF;
_keepText = false;
endLoop = true;
break;
case 8:
// Ignore this code here. Occurs e.g. in MI2 when you
// talk to the carpenter on scabb island. It works like
// code 1 (=newline) in verb texts, but is ignored in
// spoken text (i.e. here). Used for very long verb
// sentences.
break;
case 9:
frme = buffer[0] | (buffer[1] << 8);
buffer += 2;
if (a)
a->startAnimActor(frme);
break;
case 10:
// Note the similarity to the code in debugMessage()
talk_sound_a = buffer[0] | (buffer[1] << 8) | (buffer[4] << 16) | (buffer[5] << 24);
talk_sound_b = buffer[8] | (buffer[9] << 8) | (buffer[12] << 16) | (buffer[13] << 24);
buffer += 14;
if (_heversion >= 60) {
_sound->startHETalkSound(talk_sound_a);
} else {
_sound->talkSound(talk_sound_a, talk_sound_b, 2);
}
_haveActorSpeechMsg = false;
break;
case 12:
color = buffer[0] | (buffer[1] << 8);
buffer += 2;
if (color == 0xFF)
_charset->setColor(_charsetColor);
else
_charset->setColor(color);
break;
case 13:
debug(0, "handleNextCharsetCode: Unknown opcode 13 %d", READ_LE_UINT16(buffer));
buffer += 2;
break;
case 14:
oldy = _charset->getFontHeight();
_charset->setCurID(*buffer++);
buffer += 2;
for (i = 0; i < 4; i++)
_charsetColorMap[i] = _charsetData[_charset->getCurID()][i];
_charset->_nextTop -= _charset->getFontHeight() - oldy;
break;
default:
error("handleNextCharsetCode: invalid code %d", c);
}
}
_charsetBufPos = buffer - _charsetBuffer;
*code = c;
return (c != 2 && c != 3);
}
bool cmi_pos_hack = false;
#ifndef DISABLE_HE
bool ScummEngine_v72he::handleNextCharsetCode(Actor *a, int *code) {
const int charsetCode = (_heversion >= 80) ? 127 : 64;
uint32 talk_sound_a = 0;
uint32 talk_sound_b = 0;
int i, c;
char value[32];
byte *buffer = _charsetBuffer + _charsetBufPos;
do {
c = *buffer++;
if (c != charsetCode) {
break;
}
c = *buffer++;
switch (c) {
case 84:
i = 0;
memset(value, 0, 32);
c = *buffer++;
while (c != 44) {
value[i] = c;
c = *buffer++;
i++;
}
value[i] = 0;
talk_sound_a = atoi(value);
i = 0;
memset(value, 0, 32);
c = *buffer++;
while (c != charsetCode) {
value[i] = c;
c = *buffer++;
i++;
}
value[i] = 0;
talk_sound_b = atoi(value);
_sound->startHETalkSound(talk_sound_a);
break;
case 104:
_haveMsg = 0;
_keepText = true;
break;
case 110:
c = 13; // new line
break;
case 116:
i = 0;
memset(value, 0, 32);
c = *buffer++;
while (c != charsetCode) {
value[i] = c;
c = *buffer++;
i++;
}
value[i] = 0;
talk_sound_a = atoi(value);
talk_sound_b = 0;
_sound->startHETalkSound(talk_sound_a);
break;
case 119:
_haveMsg = 0xFF;
_keepText = false;
break;
default:
error("handleNextCharsetCode: invalid code %d", c);
}
} while (c != 13);
_charsetBufPos = buffer - _charsetBuffer;
*code = c;
return true;
}
#endif
void ScummEngine::CHARSET_1() {
Actor *a;
int t, c = 0;
#ifndef DISABLE_SCUMM_7_8
byte subtitleBuffer[200];
byte *subtitleLine = subtitleBuffer;
Common::Point subtitlePos;
if (_version >= 7) {
((ScummEngine_v7 *)this)->processSubtitleQueue();
}
#endif
if (!_haveMsg)
return;
@ -166,13 +361,12 @@ void ScummEngine::CHARSET_1() {
_charset->setCurID(_string[0].charset);
if (_version >= 5)
for (i = 0; i < 4; i++)
_charsetColorMap[i] = _charsetData[_charset->getCurID()][i];
memcpy(_charsetColorMap, _charsetData[_charset->getCurID()], 4);
if (_talkDelay)
return;
if ((_version <= 7 && _haveMsg == 1) || (_version == 8 && VAR(VAR_HAVE_MSG))) {
if ((_version <= 6 && _haveMsg == 1) || (_version == 7 && _haveMsg != 1) || (_version == 8 && VAR(VAR_HAVE_MSG))) {
if ((_sound->_sfxMode & 2) == 0)
stopTalk();
return;
@ -183,14 +377,18 @@ void ScummEngine::CHARSET_1() {
_useTalkAnims = true;
}
// Always set to 60
if (_version <= 6)
_talkDelay = 60;
else
_talkDelay = VAR(VAR_DEFAULT_TALK_DELAY);
_talkDelay = (VAR_DEFAULT_TALK_DELAY != 0xFF) ? VAR(VAR_DEFAULT_TALK_DELAY) : 60;
if (!_keepText) {
_charset->restoreCharsetBg();
if (_version >= 7) {
#ifndef DISABLE_SCUMM_7_8
((ScummEngine_v7 *)this)->clearSubtitleQueue();
_charset->_nextLeft = _string[0].xpos;
_charset->_nextTop = _string[0].ypos;
#endif
} else {
_charset->restoreCharsetBg();
}
}
t = _charset->_right - _string[0].xpos - 1;
@ -200,25 +398,21 @@ void ScummEngine::CHARSET_1() {
t *= 2;
}
buffer = _charsetBuffer + _charsetBufPos;
if (_version > 3)
_charset->addLinebreaks(0, buffer, 0, t);
_charset->addLinebreaks(0, _charsetBuffer + _charsetBufPos, 0, t);
if (_charset->_center) {
_charset->_nextLeft -= _charset->getStringWidth(0, buffer) / 2;
_charset->_nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2;
if (_charset->_nextLeft < 0)
_charset->_nextLeft = 0;
}
_charset->_disableOffsX = _charset->_firstChar = !_keepText;
do {
c = *buffer++;
while (handleNextCharsetCode(a, &c)) {
if (c == 0) {
// End of text reached, set _haveMsg to 1 so that the text will be
// removed next time CHARSET_1 is called.
_haveMsg = 1;
// End of text reached, set _haveMsg accordingly
_haveMsg = (_version >= 7) ? 2 : 1;
_keepText = false;
break;
}
@ -233,9 +427,16 @@ void ScummEngine::CHARSET_1() {
if (c == 13) {
newLine:;
_charset->_nextLeft = _string[0].xpos;
if (_charset->_center) {
_charset->_nextLeft -= _charset->getStringWidth(0, buffer) / 2;
#ifndef DISABLE_SCUMM_7_8
if (_version >= 7 && subtitleLine != subtitleBuffer) {
((ScummEngine_v7 *)this)->addSubtitleToQueue(subtitleBuffer, subtitlePos, _charsetColor, _charset->getCurID());
subtitleLine = subtitleBuffer;
}
#endif
if (_charset->_center) {
_charset->_nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2;
}
if (_platform == Common::kPlatformC64 && _gameId == GID_MANIAC) {
break;
} else if (!(_platform == Common::kPlatformFMTowns) && _string[0].height) {
@ -250,204 +451,59 @@ void ScummEngine::CHARSET_1() {
continue;
}
if (_heversion >= 72 && c == code) {
c = *buffer++;
switch (c) {
case 84:
i = 0;
memset(value, 0, 32);
c = *buffer++;
while (c != 44) {
value[i] = c;
c = *buffer++;
i++;
}
value[i] = 0;
talk_sound_a = atoi(value);
i = 0;
memset(value, 0, 32);
c = *buffer++;
while (c != code) {
value[i] = c;
c = *buffer++;
i++;
}
value[i] = 0;
talk_sound_b = atoi(value);
_sound->startHETalkSound(talk_sound_a);
break;
case 104:
_haveMsg = 0;
_keepText = true;
break;
case 110:
goto newLine;
case 116:
i = 0;
memset(value, 0, 32);
c = *buffer++;
while (c != code) {
value[i] = c;
c = *buffer++;
i++;
}
value[i] = 0;
talk_sound_a = atoi(value);
talk_sound_b = 0;
_sound->startHETalkSound(talk_sound_a);
break;
case 119:
if (_haveMsg != 0xFE)
_haveMsg = 0xFF;
_keepText = false;
break;
default:
error("CHARSET_1: invalid code %d", c);
_charset->_left = _charset->_nextLeft;
_charset->_top = _charset->_nextTop;
if (_version >= 7) {
#ifndef DISABLE_SCUMM_7_8
if (subtitleLine == subtitleBuffer) {
subtitlePos.x = _charset->_left;
subtitlePos.y = _charset->_top;
}
} else if (c == 0xFE || c == 0xFF) {
// WORKAROUND to avoid korean code 0xfe treated as charset message code.
if (c == 0xFE && checkKSCode(*(buffer + 1), c) && _useCJKMode) {
goto loc_avoid_ks_fe;
}
c = *buffer++;
switch (c) {
case 1:
goto newLine;
case 2:
_haveMsg = 0;
_keepText = true;
break;
case 3:
if (_haveMsg != 0xFE)
_haveMsg = 0xFF;
_keepText = false;
break;
case 8:
// Ignore this code here. Occurs e.g. in MI2 when you
// talk to the carpenter on scabb island. It works like
// code 1 (=newline) in verb texts, but is ignored in
// spoken text (i.e. here). Used for very long verb
// sentences.
break;
case 9:
frme = *buffer++;
frme |= *buffer++ << 8;
if (a)
a->startAnimActor(frme);
break;
case 10:
// Note the similarity to the code in debugMessage()
talk_sound_a = buffer[0] | (buffer[1] << 8) | (buffer[4] << 16) | (buffer[5] << 24);
talk_sound_b = buffer[8] | (buffer[9] << 8) | (buffer[12] << 16) | (buffer[13] << 24);
buffer += 14;
if (_heversion >= 60) {
_sound->startHETalkSound(talk_sound_a);
} else {
_sound->talkSound(talk_sound_a, talk_sound_b, 2);
}
// Set flag that speech variant exist of this msg.
// This is actually a hack added by ScummVM; the original did
// subtitle hiding in some other way. I am not sure exactly
// how, though.
// FIXME: This is actually a rather ugly hack, and we should consider
// replacing it with something better; problem is that _haveMsg is saved,
// so we need to cope with old save games if we ever change this.
// And BTW Fingolfin was responsible for this silly bad hack. Stupid me! :-).
if (_haveMsg == 0xFF)
_haveMsg = 0xFE;
break;
case 12:
int color;
color = *buffer++;
color |= *buffer++ << 8;
if (color == 0xFF)
_charset->setColor(_charsetColor);
else
_charset->setColor(color);
break;
case 13:
debug(0, "CHARSET_1: Unknown opcode 13 %d", READ_LE_UINT16(buffer));
buffer += 2;
break;
case 14: {
int oldy = _charset->getFontHeight();
_charset->setCurID(*buffer++);
buffer += 2;
for (i = 0; i < 4; i++)
_charsetColorMap[i] = _charsetData[_charset->getCurID()][i];
_charset->_nextTop -= _charset->getFontHeight() - oldy;
break;
}
default:
error("CHARSET_1: invalid code %d", c);
}
} else {
loc_avoid_ks_fe:
_charset->_left = _charset->_nextLeft;
_charset->_top = _charset->_nextTop;
if (c & 0x80 && _useCJKMode)
if (_language == Common::JA_JPN && !checkSJISCode(c)) {
c = 0x20; //not in S-JIS
} else {
c += *buffer++ * 256; //LE
if (_gameId == GID_CMI) { //HACK: This fixes korean text position in COMI (off by 6 pixel)
cmi_pos_hack = true;
_charset->_top += 6;
}
}
*subtitleLine++ = c;
*subtitleLine = '\0';
#endif
} else {
if (_version <= 3) {
_charset->printChar(c);
} else {
if (_features & GF_HE_NOSUBTITLES) {
// HE games which use sprites for subtitles
} else if ((_imuseDigital && _sound->isSoundRunning(kTalkSoundID)) && (!ConfMan.getBool("subtitles") || VAR(VAR_VOICE_MODE) == 0)) {
// Special case for games using imuse digital.for sound
} else if (_heversion >= 60 && !ConfMan.getBool("subtitles") && _sound->isSoundRunning(1)) {
// Special case for HE games
} else if ((_gameId == GID_LOOM256) && !ConfMan.getBool("subtitles") && (_sound->pollCD())) {
// Special case for loomcd, since it only uses CD audio.for sound
} else if (!ConfMan.getBool("subtitles") && (_haveMsg == 0xFE || _mixer->isSoundHandleActive(_sound->_talkChannelHandle))) {
} else if (!ConfMan.getBool("subtitles") && (!_haveActorSpeechMsg || _mixer->isSoundHandleActive(_sound->_talkChannelHandle))) {
// Subtitles are turned off, and there is a voice version
// of this message -> don't print it.
} else {
_charset->printChar(c);
}
}
if (cmi_pos_hack) {
cmi_pos_hack = false;
_charset->_top -= 6;
}
_charset->_nextLeft = _charset->_left;
_charset->_nextTop = _charset->_top;
if (_version <= 2) {
_talkDelay += _defaultTalkDelay;
VAR(VAR_CHARCOUNT)++;
} else
_talkDelay += (int)VAR(VAR_CHARINC);
// Handle line overflow for V3
if (_version == 3 && _charset->_nextLeft > _screenWidth) {
_charset->_nextLeft = _screenWidth;
}
// Handle line breaks for V1-V2
if (_version <= 2 && _charset->_nextLeft > _screenWidth) {
goto newLine;
}
}
} while (c != 2 && c != 3);
_charsetBufPos = buffer - _charsetBuffer;
if (_version <= 2) {
_talkDelay += _defaultTalkDelay;
VAR(VAR_CHARCOUNT)++;
} else {
_talkDelay += (int)VAR(VAR_CHARINC);
}
// Handle line overflow for V3
if (_version == 3 && _charset->_nextLeft > _screenWidth) {
_charset->_nextLeft = _screenWidth;
}
// Handle line breaks for V1-V2
if (_version <= 2 && _charset->_nextLeft > _screenWidth) {
goto newLine;
}
}
// TODO Verify this is correct spot
if (_version == 8)
VAR(VAR_HAVE_MSG) = (_string[0].no_talk_anim) ? 2 : 1;
#ifndef DISABLE_SCUMM_7_8
if (_version >= 7 && subtitleLine != subtitleBuffer) {
((ScummEngine_v7 *)this)->addSubtitleToQueue(subtitleBuffer, subtitlePos, _charsetColor, _charset->getCurID());
}
#endif
}
void ScummEngine::drawString(int a, const byte *msg) {
@ -859,7 +915,7 @@ void ScummEngine_v6::removeBlastTexts() {
}
#ifndef DISABLE_SCUMM_7_8
int indexCompare(const void *p1, const void *p2) {
static int indexCompare(const void *p1, const void *p2) {
const ScummEngine_v7::LangIndexNode *i1 = (const ScummEngine_v7::LangIndexNode *) p1;
const ScummEngine_v7::LangIndexNode *i2 = (const ScummEngine_v7::LangIndexNode *) p2;