mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-17 14:09:59 +00:00
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:
parent
5e75092dec
commit
c84d1ada32
@ -1360,10 +1360,13 @@ void ScummEngine_v7::actorTalk(const byte *msg) {
|
|||||||
}
|
}
|
||||||
_charsetBufPos = 0;
|
_charsetBufPos = 0;
|
||||||
_talkDelay = 0;
|
_talkDelay = 0;
|
||||||
_haveMsg = 0xFF;
|
_haveMsg = 1;
|
||||||
if (_version == 7)
|
if (_version == 7)
|
||||||
VAR(VAR_HAVE_MSG) = 0xFF;
|
VAR(VAR_HAVE_MSG) = 0xFF;
|
||||||
|
_haveActorSpeechMsg = true;
|
||||||
CHARSET_1();
|
CHARSET_1();
|
||||||
|
if (_version == 8)
|
||||||
|
VAR(VAR_HAVE_MSG) = (_string[0].no_talk_anim) ? 2 : 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1428,6 +1431,7 @@ void ScummEngine::actorTalk(const byte *msg) {
|
|||||||
VAR(VAR_HAVE_MSG) = 0xFF;
|
VAR(VAR_HAVE_MSG) = 0xFF;
|
||||||
if (VAR_CHARCOUNT != 0xFF)
|
if (VAR_CHARCOUNT != 0xFF)
|
||||||
VAR(VAR_CHARCOUNT) = 0;
|
VAR(VAR_CHARCOUNT) = 0;
|
||||||
|
_haveActorSpeechMsg = true;
|
||||||
CHARSET_1();
|
CHARSET_1();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1474,8 +1478,14 @@ void ScummEngine::stopTalk() {
|
|||||||
if (_version == 8)
|
if (_version == 8)
|
||||||
VAR(VAR_HAVE_MSG) = 0;
|
VAR(VAR_HAVE_MSG) = 0;
|
||||||
_keepText = false;
|
_keepText = false;
|
||||||
|
if (_version >= 7) {
|
||||||
|
#ifndef DISABLE_SCUMM_7_8
|
||||||
|
((ScummEngine_v7 *)this)->clearSubtitleQueue();
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
_charset->restoreCharsetBg();
|
_charset->restoreCharsetBg();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Actor::setActorCostume(int c) {
|
void Actor::setActorCostume(int c) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -516,6 +516,13 @@ protected:
|
|||||||
|
|
||||||
int _smushFrameRate;
|
int _smushFrameRate;
|
||||||
|
|
||||||
|
struct TextObject {
|
||||||
|
int16 xpos, ypos;
|
||||||
|
byte color;
|
||||||
|
byte charset;
|
||||||
|
byte text[256];
|
||||||
|
};
|
||||||
|
|
||||||
/** BlastObjects to draw */
|
/** BlastObjects to draw */
|
||||||
struct BlastObject {
|
struct BlastObject {
|
||||||
uint16 number;
|
uint16 number;
|
||||||
@ -528,13 +535,9 @@ protected:
|
|||||||
int _blastObjectQueuePos;
|
int _blastObjectQueuePos;
|
||||||
BlastObject _blastObjectQueue[128];
|
BlastObject _blastObjectQueue[128];
|
||||||
|
|
||||||
struct BlastText {
|
struct BlastText : TextObject {
|
||||||
int16 xpos, ypos;
|
|
||||||
Common::Rect rect;
|
Common::Rect rect;
|
||||||
byte color;
|
|
||||||
byte charset;
|
|
||||||
bool center;
|
bool center;
|
||||||
byte text[256];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int _blastTextQueuePos;
|
int _blastTextQueuePos;
|
||||||
@ -1004,6 +1007,8 @@ protected:
|
|||||||
int findObject(int x, int y, int num, int *args);
|
int findObject(int x, int y, int num, int *args);
|
||||||
int getSoundResourceSize(int id);
|
int getSoundResourceSize(int id);
|
||||||
|
|
||||||
|
virtual bool handleNextCharsetCode(Actor *a, int *c);
|
||||||
|
|
||||||
/* HE version 72 script opcodes */
|
/* HE version 72 script opcodes */
|
||||||
void o72_pushDWord();
|
void o72_pushDWord();
|
||||||
void o72_getScriptString();
|
void o72_getScriptString();
|
||||||
@ -1338,6 +1343,17 @@ public:
|
|||||||
int _languageIndexSize;
|
int _languageIndexSize;
|
||||||
char _lastStringTag[12+1];
|
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:
|
protected:
|
||||||
virtual void setupScummVars();
|
virtual void setupScummVars();
|
||||||
virtual void initScummVars();
|
virtual void initScummVars();
|
||||||
|
@ -730,6 +730,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
|
|||||||
MKLINE(ScummEngine, _charsetBufPos, sleInt16, VER(10)),
|
MKLINE(ScummEngine, _charsetBufPos, sleInt16, VER(10)),
|
||||||
|
|
||||||
MKLINE(ScummEngine, _haveMsg, sleByte, VER(8)),
|
MKLINE(ScummEngine, _haveMsg, sleByte, VER(8)),
|
||||||
|
MKLINE(ScummEngine, _haveActorSpeechMsg, sleByte, VER(61)),
|
||||||
MKLINE(ScummEngine, _useTalkAnims, sleByte, VER(8)),
|
MKLINE(ScummEngine, _useTalkAnims, sleByte, VER(8)),
|
||||||
|
|
||||||
MKLINE(ScummEngine, _talkDelay, sleInt16, VER(8)),
|
MKLINE(ScummEngine, _talkDelay, sleInt16, VER(8)),
|
||||||
@ -952,6 +953,13 @@ void ScummEngine::saveOrLoad(Serializer *s) {
|
|||||||
_system->warpMouse(_mouse.x, _mouse.y);
|
_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
|
// Save/load actors
|
||||||
//
|
//
|
||||||
@ -1190,8 +1198,25 @@ void ScummEngine_v5::saveOrLoad(Serializer *s) {
|
|||||||
void ScummEngine_v7::saveOrLoad(Serializer *s) {
|
void ScummEngine_v7::saveOrLoad(Serializer *s) {
|
||||||
ScummEngine::saveOrLoad(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);
|
_imuseDigital->saveOrLoad(s);
|
||||||
|
|
||||||
|
s->saveLoadArrayOf(_subtitleQueue, ARRAYSIZE(_subtitleQueue), sizeof(_subtitleQueue[0]), subtitleQueueEntries);
|
||||||
|
s->saveLoadEntries(this, V7Entries);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ namespace Scumm {
|
|||||||
* only saves/loads those which are valid for the version of the savegame
|
* only saves/loads those which are valid for the version of the savegame
|
||||||
* which is being loaded/saved currently.
|
* 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
|
* An auxillary macro, used to specify savegame versions. We use this instead
|
||||||
|
@ -1128,6 +1128,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
|
|||||||
_palDirtyMin = 0;
|
_palDirtyMin = 0;
|
||||||
_palDirtyMax = 0;
|
_palDirtyMax = 0;
|
||||||
_haveMsg = 0;
|
_haveMsg = 0;
|
||||||
|
_haveActorSpeechMsg = false;
|
||||||
_useTalkAnims = false;
|
_useTalkAnims = false;
|
||||||
_defaultTalkDelay = 0;
|
_defaultTalkDelay = 0;
|
||||||
_midiDriver = MD_NULL;
|
_midiDriver = MD_NULL;
|
||||||
@ -1585,6 +1586,7 @@ ScummEngine_v7::ScummEngine_v7(GameDetector *detector, OSystem *syst, const Scum
|
|||||||
_existLanguageFile = false;
|
_existLanguageFile = false;
|
||||||
_languageBuffer = NULL;
|
_languageBuffer = NULL;
|
||||||
_languageIndex = NULL;
|
_languageIndex = NULL;
|
||||||
|
clearSubtitleQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScummEngine_v7::~ScummEngine_v7() {
|
ScummEngine_v7::~ScummEngine_v7() {
|
||||||
@ -1939,6 +1941,7 @@ void ScummEngine::scummInit() {
|
|||||||
|
|
||||||
_charsetBufPos = 0;
|
_charsetBufPos = 0;
|
||||||
_haveMsg = 0;
|
_haveMsg = 0;
|
||||||
|
_haveActorSpeechMsg = false;
|
||||||
|
|
||||||
_varwatch = -1;
|
_varwatch = -1;
|
||||||
_screenStartStrip = 0;
|
_screenStartStrip = 0;
|
||||||
@ -2296,7 +2299,7 @@ int ScummEngine::scummLoop(int delta) {
|
|||||||
VAR(VAR_CAMERA_POS_X) = camera._cur.x;
|
VAR(VAR_CAMERA_POS_X) = camera._cur.x;
|
||||||
}
|
}
|
||||||
if (_version <= 7)
|
if (_version <= 7)
|
||||||
VAR(VAR_HAVE_MSG) = (_haveMsg == 0xFE) ? 0xFF : _haveMsg;
|
VAR(VAR_HAVE_MSG) = _haveMsg;
|
||||||
|
|
||||||
if (_platform == Common::kPlatformC64 && _gameId == GID_MANIAC) {
|
if (_platform == Common::kPlatformC64 && _gameId == GID_MANIAC) {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -1093,6 +1093,7 @@ protected:
|
|||||||
byte *_palManipIntermediatePal;
|
byte *_palManipIntermediatePal;
|
||||||
|
|
||||||
byte _haveMsg;
|
byte _haveMsg;
|
||||||
|
bool _haveActorSpeechMsg;
|
||||||
bool _useTalkAnims;
|
bool _useTalkAnims;
|
||||||
uint16 _defaultTalkDelay;
|
uint16 _defaultTalkDelay;
|
||||||
int _tempMusic;
|
int _tempMusic;
|
||||||
@ -1161,6 +1162,7 @@ protected:
|
|||||||
|
|
||||||
void printString(int m, const byte *msg);
|
void printString(int m, const byte *msg);
|
||||||
|
|
||||||
|
virtual bool handleNextCharsetCode(Actor *a, int *c);
|
||||||
void CHARSET_1();
|
void CHARSET_1();
|
||||||
void drawString(int a, const byte *msg);
|
void drawString(int a, const byte *msg);
|
||||||
void debugMessage(const byte *msg);
|
void debugMessage(const byte *msg);
|
||||||
|
440
scumm/string.cpp
440
scumm/string.cpp
@ -95,17 +95,212 @@ void ScummEngine::showMessageDialog(const byte *msg) {
|
|||||||
VAR(VAR_KEYPRESS) = runDialog(dialog);
|
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_a = 0;
|
||||||
uint32 talk_sound_b = 0;
|
uint32 talk_sound_b = 0;
|
||||||
int i, t, c;
|
int i, color, frme, c, oldy;
|
||||||
int frme;
|
bool endLoop = false;
|
||||||
Actor *a;
|
byte *buffer = _charsetBuffer + _charsetBufPos;
|
||||||
byte *buffer;
|
while (!endLoop) {
|
||||||
int code = (_heversion >= 80) ? 127 : 64;
|
c = *buffer++;
|
||||||
char value[32];
|
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)
|
if (!_haveMsg)
|
||||||
return;
|
return;
|
||||||
@ -166,13 +361,12 @@ void ScummEngine::CHARSET_1() {
|
|||||||
_charset->setCurID(_string[0].charset);
|
_charset->setCurID(_string[0].charset);
|
||||||
|
|
||||||
if (_version >= 5)
|
if (_version >= 5)
|
||||||
for (i = 0; i < 4; i++)
|
memcpy(_charsetColorMap, _charsetData[_charset->getCurID()], 4);
|
||||||
_charsetColorMap[i] = _charsetData[_charset->getCurID()][i];
|
|
||||||
|
|
||||||
if (_talkDelay)
|
if (_talkDelay)
|
||||||
return;
|
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)
|
if ((_sound->_sfxMode & 2) == 0)
|
||||||
stopTalk();
|
stopTalk();
|
||||||
return;
|
return;
|
||||||
@ -183,15 +377,19 @@ void ScummEngine::CHARSET_1() {
|
|||||||
_useTalkAnims = true;
|
_useTalkAnims = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always set to 60
|
_talkDelay = (VAR_DEFAULT_TALK_DELAY != 0xFF) ? VAR(VAR_DEFAULT_TALK_DELAY) : 60;
|
||||||
if (_version <= 6)
|
|
||||||
_talkDelay = 60;
|
|
||||||
else
|
|
||||||
_talkDelay = VAR(VAR_DEFAULT_TALK_DELAY);
|
|
||||||
|
|
||||||
if (!_keepText) {
|
if (!_keepText) {
|
||||||
|
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();
|
_charset->restoreCharsetBg();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t = _charset->_right - _string[0].xpos - 1;
|
t = _charset->_right - _string[0].xpos - 1;
|
||||||
if (_charset->_center) {
|
if (_charset->_center) {
|
||||||
@ -200,25 +398,21 @@ void ScummEngine::CHARSET_1() {
|
|||||||
t *= 2;
|
t *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = _charsetBuffer + _charsetBufPos;
|
|
||||||
|
|
||||||
if (_version > 3)
|
if (_version > 3)
|
||||||
_charset->addLinebreaks(0, buffer, 0, t);
|
_charset->addLinebreaks(0, _charsetBuffer + _charsetBufPos, 0, t);
|
||||||
|
|
||||||
if (_charset->_center) {
|
if (_charset->_center) {
|
||||||
_charset->_nextLeft -= _charset->getStringWidth(0, buffer) / 2;
|
_charset->_nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2;
|
||||||
if (_charset->_nextLeft < 0)
|
if (_charset->_nextLeft < 0)
|
||||||
_charset->_nextLeft = 0;
|
_charset->_nextLeft = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_charset->_disableOffsX = _charset->_firstChar = !_keepText;
|
_charset->_disableOffsX = _charset->_firstChar = !_keepText;
|
||||||
|
|
||||||
do {
|
while (handleNextCharsetCode(a, &c)) {
|
||||||
c = *buffer++;
|
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
// End of text reached, set _haveMsg to 1 so that the text will be
|
// End of text reached, set _haveMsg accordingly
|
||||||
// removed next time CHARSET_1 is called.
|
_haveMsg = (_version >= 7) ? 2 : 1;
|
||||||
_haveMsg = 1;
|
|
||||||
_keepText = false;
|
_keepText = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -233,9 +427,16 @@ void ScummEngine::CHARSET_1() {
|
|||||||
if (c == 13) {
|
if (c == 13) {
|
||||||
newLine:;
|
newLine:;
|
||||||
_charset->_nextLeft = _string[0].xpos;
|
_charset->_nextLeft = _string[0].xpos;
|
||||||
if (_charset->_center) {
|
#ifndef DISABLE_SCUMM_7_8
|
||||||
_charset->_nextLeft -= _charset->getStringWidth(0, buffer) / 2;
|
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) {
|
if (_platform == Common::kPlatformC64 && _gameId == GID_MANIAC) {
|
||||||
break;
|
break;
|
||||||
} else if (!(_platform == Common::kPlatformFMTowns) && _string[0].height) {
|
} else if (!(_platform == Common::kPlatformFMTowns) && _string[0].height) {
|
||||||
@ -250,188 +451,44 @@ void ScummEngine::CHARSET_1() {
|
|||||||
continue;
|
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);
|
|
||||||
}
|
|
||||||
} 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->_left = _charset->_nextLeft;
|
||||||
_charset->_top = _charset->_nextTop;
|
_charset->_top = _charset->_nextTop;
|
||||||
if (c & 0x80 && _useCJKMode)
|
if (_version >= 7) {
|
||||||
if (_language == Common::JA_JPN && !checkSJISCode(c)) {
|
#ifndef DISABLE_SCUMM_7_8
|
||||||
c = 0x20; //not in S-JIS
|
if (subtitleLine == subtitleBuffer) {
|
||||||
|
subtitlePos.x = _charset->_left;
|
||||||
|
subtitlePos.y = _charset->_top;
|
||||||
|
}
|
||||||
|
*subtitleLine++ = c;
|
||||||
|
*subtitleLine = '\0';
|
||||||
|
#endif
|
||||||
} else {
|
} 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_version <= 3) {
|
if (_version <= 3) {
|
||||||
_charset->printChar(c);
|
_charset->printChar(c);
|
||||||
} else {
|
} else {
|
||||||
if (_features & GF_HE_NOSUBTITLES) {
|
if (_features & GF_HE_NOSUBTITLES) {
|
||||||
// HE games which use sprites for subtitles
|
// 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)) {
|
} else if (_heversion >= 60 && !ConfMan.getBool("subtitles") && _sound->isSoundRunning(1)) {
|
||||||
// Special case for HE games
|
// Special case for HE games
|
||||||
} else if ((_gameId == GID_LOOM256) && !ConfMan.getBool("subtitles") && (_sound->pollCD())) {
|
} else if ((_gameId == GID_LOOM256) && !ConfMan.getBool("subtitles") && (_sound->pollCD())) {
|
||||||
// Special case for loomcd, since it only uses CD audio.for sound
|
// 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
|
// Subtitles are turned off, and there is a voice version
|
||||||
// of this message -> don't print it.
|
// of this message -> don't print it.
|
||||||
} else {
|
} else {
|
||||||
_charset->printChar(c);
|
_charset->printChar(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cmi_pos_hack) {
|
|
||||||
cmi_pos_hack = false;
|
|
||||||
_charset->_top -= 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
_charset->_nextLeft = _charset->_left;
|
_charset->_nextLeft = _charset->_left;
|
||||||
_charset->_nextTop = _charset->_top;
|
_charset->_nextTop = _charset->_top;
|
||||||
|
}
|
||||||
|
|
||||||
if (_version <= 2) {
|
if (_version <= 2) {
|
||||||
_talkDelay += _defaultTalkDelay;
|
_talkDelay += _defaultTalkDelay;
|
||||||
VAR(VAR_CHARCOUNT)++;
|
VAR(VAR_CHARCOUNT)++;
|
||||||
} else
|
} else {
|
||||||
_talkDelay += (int)VAR(VAR_CHARINC);
|
_talkDelay += (int)VAR(VAR_CHARINC);
|
||||||
|
}
|
||||||
// Handle line overflow for V3
|
// Handle line overflow for V3
|
||||||
if (_version == 3 && _charset->_nextLeft > _screenWidth) {
|
if (_version == 3 && _charset->_nextLeft > _screenWidth) {
|
||||||
_charset->_nextLeft = _screenWidth;
|
_charset->_nextLeft = _screenWidth;
|
||||||
@ -441,13 +498,12 @@ loc_avoid_ks_fe:
|
|||||||
goto newLine;
|
goto newLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (c != 2 && c != 3);
|
|
||||||
|
|
||||||
_charsetBufPos = buffer - _charsetBuffer;
|
#ifndef DISABLE_SCUMM_7_8
|
||||||
|
if (_version >= 7 && subtitleLine != subtitleBuffer) {
|
||||||
// TODO Verify this is correct spot
|
((ScummEngine_v7 *)this)->addSubtitleToQueue(subtitleBuffer, subtitlePos, _charsetColor, _charset->getCurID());
|
||||||
if (_version == 8)
|
}
|
||||||
VAR(VAR_HAVE_MSG) = (_string[0].no_talk_anim) ? 2 : 1;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScummEngine::drawString(int a, const byte *msg) {
|
void ScummEngine::drawString(int a, const byte *msg) {
|
||||||
@ -859,7 +915,7 @@ void ScummEngine_v6::removeBlastTexts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_SCUMM_7_8
|
#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 *i1 = (const ScummEngine_v7::LangIndexNode *) p1;
|
||||||
const ScummEngine_v7::LangIndexNode *i2 = (const ScummEngine_v7::LangIndexNode *) p2;
|
const ScummEngine_v7::LangIndexNode *i2 = (const ScummEngine_v7::LangIndexNode *) p2;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user