aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Montoir2007-04-15 20:36:44 +0000
committerGregory Montoir2007-04-15 20:36:44 +0000
commit642fa67da9c271244de373431166f23449ec8543 (patch)
treedbd138e5ebd40f8fa55ed67c049e6e8f0b6eea4a
parentf8067d54e53084c9fd7ef848fd855967d0641465 (diff)
downloadscummvm-rg350-642fa67da9c271244de373431166f23449ec8543.tar.gz
scummvm-rg350-642fa67da9c271244de373431166f23449ec8543.tar.bz2
scummvm-rg350-642fa67da9c271244de373431166f23449ec8543.zip
Added code for decodeParseString.SO_PRINT_WRAP and rewrote the CHARSET_1 function in order to match the original V8 interpreter. This should fix bugs #1036707 and #1662610 (subtitles word wrapping issues).
svn-id: r26516
-rw-r--r--engines/scumm/actor.cpp9
-rw-r--r--engines/scumm/charset.cpp38
-rw-r--r--engines/scumm/charset.h1
-rw-r--r--engines/scumm/intern.h1
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script_v8.cpp5
-rw-r--r--engines/scumm/scumm.h3
-rw-r--r--engines/scumm/string.cpp163
9 files changed, 216 insertions, 8 deletions
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index af5726a273..f104f7bb8b 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -1850,6 +1850,7 @@ void ScummEngine::resetV1ActorTalkColor() {
#ifndef DISABLE_SCUMM_7_8
void ScummEngine_v7::actorTalk(const byte *msg) {
Actor *a;
+ bool stringWrap;
convertMessageToString(msg, _charsetBuffer, sizeof(_charsetBuffer));
@@ -1882,9 +1883,15 @@ void ScummEngine_v7::actorTalk(const byte *msg) {
if (_game.version == 7)
VAR(VAR_HAVE_MSG) = 0xFF;
_haveActorSpeechMsg = true;
+ if (_game.version == 8) {
+ stringWrap = _string[0].wrapping;
+ _string[0].wrapping = true;
+ }
CHARSET_1();
- if (_game.version == 8)
+ if (_game.version == 8) {
VAR(VAR_HAVE_MSG) = (_string[0].no_talk_anim) ? 2 : 1;
+ _string[0].wrapping = stringWrap;
+ }
}
#endif
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 654a7fd6c3..92642faaa5 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -348,6 +348,44 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {
return width;
}
+int CharsetRenderer::getStringHeight(const byte *text) {
+ int pos = 0;
+ int height = 0;
+ byte chr;
+ int oldID = getCurID();
+
+ while ((chr = text[pos++]) != 0) {
+ if (chr == '\n' || chr == '\r')
+ break;
+ if (chr == '@')
+ continue;
+ if (chr == 255 || (_vm->_game.version <= 6 && chr == 254)) {
+ chr = text[pos++];
+ if (chr == 3) { // 'WAIT'
+ height += getFontHeight();
+ break;
+ }
+ if (chr == 10 || chr == 21 || chr == 12 || chr == 13) {
+ pos += 2;
+ continue;
+ }
+ if (chr == 9 || chr == 1 || chr == 2) { // 'Newline'
+ height += getFontHeight();
+ continue;
+ }
+ if (chr == 14) {
+ int set = text[pos] | (text[pos + 1] << 8);
+ pos += 2;
+ setCurID(set);
+ continue;
+ }
+ }
+ }
+
+ setCurID(oldID);
+ return height + getFontHeight();
+}
+
void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
int lastspace = -1;
int curw = 1;
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 5039d31573..476b57b86e 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -73,6 +73,7 @@ public:
virtual void drawChar(int chr, const Graphics::Surface &s, int x, int y) {}
int getStringWidth(int a, const byte *str);
+ int getStringHeight(const byte *text);
void addLinebreaks(int a, byte *str, int pos, int maxwidth);
void translateColor();
diff --git a/engines/scumm/intern.h b/engines/scumm/intern.h
index 796867a116..3d3a07a2ed 100644
--- a/engines/scumm/intern.h
+++ b/engines/scumm/intern.h
@@ -972,6 +972,7 @@ protected:
virtual const char *getOpcodeDesc(byte i);
virtual void printString(int m, const byte *msg);
+ virtual void CHARSET_1();
virtual void scummLoop_handleSaveLoad();
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 7df428529a..6d8798a1e7 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -834,6 +834,8 @@ void ScummEngine::saveOrLoad(Serializer *s) {
MKLINE(StringTab, _default.overhead, sleByte, VER(8)),
MKLINE(StringTab, no_talk_anim, sleByte, VER(8)),
MKLINE(StringTab, _default.no_talk_anim, sleByte, VER(8)),
+ MKLINE(StringTab, wrapping, sleByte, VER(71)),
+ MKLINE(StringTab, _default.wrapping, sleByte, VER(71)),
MKEND()
};
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index e98704bc2b..dbbf9a8a09 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -47,7 +47,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 70
+#define CURRENT_VER 71
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp
index 17b494250e..011c41856a 100644
--- a/engines/scumm/script_v8.cpp
+++ b/engines/scumm/script_v8.cpp
@@ -488,7 +488,7 @@ void ScummEngine_v8::decodeParseString(int m, int n) {
_string[m].charset = pop();
break;
case 0xCE: // SO_PRINT_LEFT
- _string[m].center = false;
+ _string[m].wrapping = false;
_string[m].overhead = false;
break;
case 0xCF: // SO_PRINT_OVERHEAD
@@ -503,7 +503,8 @@ void ScummEngine_v8::decodeParseString(int m, int n) {
_scriptPointer += resStrLen(_scriptPointer) + 1;
break;
case 0xD2: // SO_PRINT_WRAP Set print wordwrap
- //debug(0, "decodeParseString: SO_PRINT_WRAP");
+ _string[m].wrapping = true;
+ _string[m].overhead = false;
break;
default:
error("decodeParseString: default case 0x%x", b);
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 90cb14de1f..76b36fe935 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -243,6 +243,7 @@ struct StringSlot {
bool center;
bool overhead;
bool no_talk_anim;
+ bool wrapping;
};
struct StringTab : StringSlot {
@@ -1169,7 +1170,7 @@ protected:
virtual void printString(int m, const byte *msg);
virtual bool handleNextCharsetCode(Actor *a, int *c);
- void CHARSET_1();
+ virtual void CHARSET_1();
void drawString(int a, const byte *msg);
void debugMessage(const byte *msg);
void showMessageDialog(const byte *msg);
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 432cd7f1c9..90f227d0b3 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -437,7 +437,7 @@ void ScummEngine::CHARSET_1() {
if (getTalkingActor() != 0xFF)
a = derefActorSafe(getTalkingActor(), "CHARSET_1");
- if (a && _string[0].overhead != 0) {
+ if (a && _string[0].overhead) {
int s;
_string[0].xpos = a->getPos().x - virtscr[0].xstart;
@@ -490,8 +490,7 @@ void ScummEngine::CHARSET_1() {
return;
if ((_game.version <= 6 && _haveMsg == 1) ||
- (_game.version == 7 && _haveMsg != 1) ||
- (_game.version == 8 && VAR(VAR_HAVE_MSG))) {
+ (_game.version == 7 && _haveMsg != 1)) {
if (_game.heversion >= 60) {
if (_sound->isSoundRunning(1) == 0)
@@ -644,6 +643,164 @@ void ScummEngine::CHARSET_1() {
#endif
}
+#ifndef DISABLE_SCUMM_7_8
+void ScummEngine_v8::CHARSET_1() {
+ byte subtitleBuffer[2048];
+ byte *subtitleLine = subtitleBuffer;
+ Common::Point subtitlePos;
+
+ processSubtitleQueue();
+
+ if (!_haveMsg)
+ return;
+
+ Actor *a = NULL;
+ if (getTalkingActor() != 0xFF)
+ a = derefActorSafe(getTalkingActor(), "CHARSET_1");
+
+ StringTab saveStr = _string[0];
+ if (a && _string[0].overhead) {
+ int s;
+
+ _string[0].xpos = a->getPos().x - virtscr[0].xstart;
+ s = a->_scalex * a->_talkPosX / 255;
+ _string[0].xpos += (a->_talkPosX - s) / 2 + s;
+
+ _string[0].ypos = a->getPos().y - a->getElevation() - _screenTop;
+ s = a->_scaley * a->_talkPosY / 255;
+ _string[0].ypos += (a->_talkPosY - s) / 2 + s;
+ }
+
+ _charset->setColor(_charsetColor);
+
+ if (a && a->_charset)
+ _charset->setCurID(a->_charset);
+ else
+ _charset->setCurID(_string[0].charset);
+
+ if (_talkDelay)
+ return;
+
+ if (VAR(VAR_HAVE_MSG)) {
+ if ((_sound->_sfxMode & 2) == 0) {
+ stopTalk();
+ }
+ return;
+ }
+
+ if (a && !_string[0].no_talk_anim) {
+ a->runActorTalkScript(a->_talkStartFrame);
+ }
+
+ if (!_keepText) {
+ clearSubtitleQueue();
+ _nextLeft = _string[0].xpos;
+ _nextTop = _string[0].ypos + _screenTop;
+ }
+
+ _charset->_disableOffsX = _charset->_firstChar = !_keepText;
+
+ _talkDelay = VAR(VAR_DEFAULT_TALK_DELAY);
+ for (int i = _charsetBufPos; _charsetBuffer[i]; ++i) {
+ _talkDelay += VAR(VAR_CHARINC);
+ }
+
+ if (_string[0].wrapping) {
+ _charset->addLinebreaks(0, _charsetBuffer, _charsetBufPos, _screenWidth - 20);
+
+ struct { int pos, w; } substring[10];
+ int count = 0;
+ int maxLineWidth = 0;
+ int lastPos = 0;
+ int code = 0;
+ while (handleNextCharsetCode(a, &code)) {
+ if (code == 13 || code == 0) {
+ *subtitleLine++ = '\0';
+ assert(count < 10);
+ substring[count].w = _charset->getStringWidth(0, subtitleBuffer + lastPos);
+ if (maxLineWidth < substring[count].w) {
+ maxLineWidth = substring[count].w;
+ }
+ substring[count].pos = lastPos;
+ ++count;
+ lastPos = subtitleLine - subtitleBuffer;
+ } else {
+ *subtitleLine++ = code;
+ *subtitleLine = '\0';
+ }
+ if (code == 0) {
+ break;
+ }
+ }
+
+ int h = count * _charset->getFontHeight();
+ h += _charset->getFontHeight() / 2;
+ subtitlePos.y = _string[0].ypos;
+ if (subtitlePos.y + h > _screenHeight - 10) {
+ subtitlePos.y = _screenHeight - 10 - h;
+ }
+ if (subtitlePos.y < 10) {
+ subtitlePos.y = 10;
+ }
+
+ for (int i = 0; i < count; ++i) {
+ subtitlePos.x = _string[0].xpos;
+ if (_string[0].center) {
+ if (subtitlePos.x + maxLineWidth / 2 > _screenWidth - 10) {
+ subtitlePos.x = _screenWidth - 10 - maxLineWidth / 2;
+ }
+ if (subtitlePos.x - maxLineWidth / 2 < 10) {
+ subtitlePos.x = 10 + maxLineWidth / 2;
+ }
+ subtitlePos.x -= substring[i].w / 2;
+ } else {
+ if (subtitlePos.x + maxLineWidth > _screenWidth - 10) {
+ subtitlePos.x = _screenWidth - 10 - maxLineWidth;
+ }
+ if (subtitlePos.x - maxLineWidth < 10) {
+ subtitlePos.x = 10;
+ }
+ }
+ if (subtitlePos.y < _screenHeight - 10) {
+ ((ScummEngine_v7 *)this)->addSubtitleToQueue(subtitleBuffer + substring[i].pos, subtitlePos, _charsetColor, _charset->getCurID());
+ }
+ subtitlePos.y += _charset->getFontHeight();
+ }
+ } else {
+ int code = 0;
+ subtitlePos.y = _string[0].ypos;
+ if (subtitlePos.y < 10) {
+ subtitlePos.y = 10;
+ }
+ while (handleNextCharsetCode(a, &code)) {
+ if (code == 13 || code == 0) {
+ subtitlePos.x = _string[0].xpos;
+ if (_string[0].center) {
+ subtitlePos.x -= _charset->getStringWidth(0, subtitleBuffer) / 2;
+ }
+ if (subtitlePos.x < 10) {
+ subtitlePos.x = 10;
+ }
+ if (subtitlePos.y < _screenHeight - 10) {
+ ((ScummEngine_v7 *)this)->addSubtitleToQueue(subtitleBuffer, subtitlePos, _charsetColor, _charset->getCurID());
+ subtitlePos.y += _charset->getFontHeight();
+ }
+ subtitleLine = subtitleBuffer;
+ } else {
+ *subtitleLine++ = code;
+ }
+ *subtitleLine = '\0';
+ if (code == 0) {
+ break;
+ }
+ }
+ }
+ _haveMsg = 2;
+ _keepText = false;
+ _string[0] = saveStr;
+}
+#endif
+
void ScummEngine::drawString(int a, const byte *msg) {
byte buf[270];
byte *space;