SCUMM: Clean-up and implement remaining messages for v0-1-2-3

This commit is contained in:
AndywinXp 2022-10-11 15:09:07 +02:00 committed by Eugene Sandulenko
parent 13e7c9d4d9
commit 9cb7293de3
4 changed files with 324 additions and 63 deletions

View File

@ -593,7 +593,7 @@ const ResString &InfoDialog::getStaticResString(Common::Language lang, int strin
{3, "ERROR READING %d type %d"}, // As found on the Italian v2 executable...
{4, "PAUSA - Premere SPAZIO per continuare."}, // Original DOS Italian v2
{5, "Sei sicuro di voler ricominciare? (s/n)s"}, // Original DOS Italian v2
{6, "Sei sicuro di voler uscire? (s/n)s"} // Original DOS Italian v2
{6, "Sei sicuro di voler uscire? (s/n)s"} // (matching the previous sentence)
},
{ // Spanish
{1, "Introduce el disco %c y pulsa un bot""\xa2""n para continuar."},
@ -648,12 +648,34 @@ const ResString &InfoDialog::getStaticResString(Common::Language lang, int strin
{0, "Text Display Only"},
{0, "Text Speed Slow ========== Fast"},
{0, "Roland Volume Low ========= High"},
{0, "Heap %dK"}
{0, "Heap %dK"},
// Snap scroll messages
{0, "Snap Scroll On"}, // v2
{0, "Snap Scroll Off"},
{0, "Screen reposition instantly"}, // v3
{0, "Screen reposition by Scrolling"},
{0, "Horizontal Screen Snap"}, // v4
{0, "Horizontal Screen Scroll"},
// Miscellaneous input messages
{0, "Recalibrating Joystick"},
{0, "Mouse Mode"},
{0, "Mouse On"},
{0, "Mouse Off"},
{0, "Joystick On"},
{0, "Joystick Off"},
{0, "Sounds On"},
{0, "Sounds Off"},
// V1-2 graphic modes
{0, "VGA Graphics"},
{0, "EGA Graphics"},
{0, "CGA Graphics"},
{0, "Hercules Graphics"},
{0, "TANDY Graphics"}
};
if (stringno + 1 >= ARRAYSIZE(strMap1)) {
stringno -= ARRAYSIZE(strMap1) - 1;
assert(stringno + 1 < ARRAYSIZE(strMap2));
assert(stringno < ARRAYSIZE(strMap2));
return strMap2[stringno];
}
@ -683,6 +705,20 @@ const ResString &InfoDialog::getStaticResString(Common::Language lang, int strin
break;
}
// Special case for ZAK v2 ITA, which has a different string both for the pause
// message and for the restart message.
// If it can be verified that other languages have different strings for this game
// we can refactor strMap1 to contain both a MM string and a ZAK string; but with
// currently only one language doing this, it seems overkill...
if (_vm->_game.version == 2 && _vm->_game.id == GID_ZAK && langIndex == 3) {
if (stringno == 3) {
static const ResString altStr = {4, "PAUSE - Premere SPACE per continuare."};
return altStr;
} else if (stringno == 4) {
static const ResString altStr = {5, "Sei sicuro che vuoi ricominciare? (s/n)s"};
return altStr;
}
}
return strMap1[langIndex][stringno];
}

View File

@ -262,7 +262,7 @@ Common::KeyState ScummEngine::showBannerAndPause(int bannerId, int32 waitTime, c
return ks;
}
Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int32 waitTime, bool drawOnSentenceLine) {
Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int color, int32 waitTime, bool drawOnSentenceLine) {
Common::Rect sentenceline;
// Pause the engine
@ -321,28 +321,49 @@ Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int32 waitTi
drawString(2, (byte *)string);
drawDirtyScreenParts();
} else {
_string[0].xpos = 0;
_string[0].ypos = 0;
_string[0].right = _screenWidth - 1;
_string[0].center = false;
_string[0].overhead = false;
byte tmpColor = _string[0].color;
byte tmpAct = _actorToPrintStrFor;
_string[0].color = color;
_actorToPrintStrFor = 0xFF;
actorTalk((const byte *)msg);
_actorToPrintStrFor = tmpAct;
_string[0].color = tmpColor;
}
Common::KeyState ks = Common::KEYCODE_INVALID;
bool leftBtnPressed = false, rightBtnPressed = false;
// Wait until the engine receives a new Keyboard or Mouse input,
// unless we have specified a positive waitTime: in that case, the banner
// will stay on screen until an input has been received or until the time-out.
Common::KeyState ks = Common::KEYCODE_INVALID;
bool leftBtnPressed = false, rightBtnPressed = false;
if (waitTime) {
ScummEngine::drawDirtyScreenParts();
waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
stopTalk();
}
setBuiltinCursor(0);
restoreBackground(sentenceline);
// Restore the sentence which was being displayed before
// (MANIAC v1 doesn't do this)
if (!(_game.id == GID_MANIAC && _game.version <= 1))
drawSentence();
if (drawOnSentenceLine) {
setBuiltinCursor(0);
restoreBackground(sentenceline);
// Restore the sentence which was being displayed before
// (MANIAC v1 doesn't do this)
if (!(_game.id == GID_MANIAC && _game.version <= 1))
drawSentence();
}
// Finally, resume the engine, clear the input state, and restore the charset.
pt.clear();
clearClickedStatus();;
clearClickedStatus();
return ks;
}
@ -1396,7 +1417,7 @@ void ScummEngine::queryQuit(bool returnToLauncher) {
} else if (_game.version == 4) {
ks = showOldStyleBannerAndPause(msgLabelPtr, 12, -1);
} else {
ks = printMessageAndPause(msgLabelPtr, -1, true);
ks = printMessageAndPause(msgLabelPtr, 0, -1, true);
}
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
@ -1429,10 +1450,13 @@ void ScummEngine::queryRestart() {
// "Are you sure you want to restart? (Y/N)"
Common::KeyState ks;
if (_game.version > 4)
if (_game.version > 4) {
ks = showBannerAndPause(0, -1, msgLabelPtr);
else
} else if (_game.version == 3) {
ks = showOldStyleBannerAndPause(msgLabelPtr, 12, -1);
} else {
ks = printMessageAndPause(msgLabelPtr, 4, -1, false);
}
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
@ -3120,23 +3144,31 @@ void ScummEngine::drawGUIText(const char *buttonString, Common::Rect *clipRect,
void ScummEngine::getSliderString(int stringId, int value, char *sliderString, int size) {
char *ptrToChar;
char tempStr[256];
if (_game.version > 2) {
Common::strlcpy(tempStr, getGUIString(stringId), sizeof(tempStr));
convertMessageToString((const byte *)tempStr, (byte *)sliderString, size);
Common::strlcpy(tempStr, getGUIString(stringId), sizeof(tempStr));
convertMessageToString((const byte *)tempStr, (byte *)sliderString, size);
ptrToChar = strchr(sliderString, '=');
ptrToChar = strchr(sliderString, '=');
if (!ptrToChar) {
ptrToChar = strstr(sliderString, "xxx");
}
if (!ptrToChar) {
ptrToChar = strstr(sliderString, "xxx");
}
if (ptrToChar) {
if (ptrToChar) {
if (stringId == gsTextSpeedSlider) {
memset(ptrToChar, '\v', 10);
ptrToChar[9 - value] = '\f';
} else {
memset(ptrToChar, '\v', 9);
ptrToChar[value / 15] = '\f';
}
}
} else {
if (stringId == gsTextSpeedSlider) {
memset(ptrToChar, '\v', 10);
ptrToChar[9 - value] = '\f';
} else {
memset(ptrToChar, '\v', 9);
ptrToChar[value / 15] = '\f';
Common::strlcpy(tempStr, getGUIString(stringId), sizeof(tempStr));
// Format the string with the arguments...
Common::sprintf_s(sliderString, size, tempStr, value);
}
}
}
@ -3321,13 +3353,83 @@ const char *ScummEngine::getGUIString(int stringId) {
resStringId = 24;
break;
case gsTextSpeedSlider:
resStringId = 25;
if (_game.version <= 2) {
return "TextRate %d";
} else {
resStringId = 25;
}
break;
case gsMusicVolumeSlider:
resStringId = 26;
break;
case gsHeap:
resStringId = 28;
resStringId = 27;
break;
case gsSnapOn:
switch (_game.version) {
case 2:
resStringId = 28;
break;
case 3:
resStringId = 30;
break;
default:
resStringId = 32;
}
break;
case gsSnapOff:
switch (_game.version) {
case 2:
resStringId = 29;
break;
case 3:
resStringId = 31;
break;
default:
resStringId = 33;
}
break;
case gsRecalJoystick:
resStringId = 34;
break;
case gsMouseMode:
resStringId = 35;
break;
case gsMouseOn:
resStringId = 36;
break;
case gsMouseOff:
resStringId = 37;
break;
case gsJoystickOn:
resStringId = 38;
break;
case gsJoystickOff:
resStringId = 39;
break;
case gsSoundsOn:
resStringId = 40;
break;
case gsSoundsOff:
resStringId = 41;
break;
case gsVGAMode:
resStringId = 42;
break;
case gsEGAMode:
resStringId = 43;
break;
case gsCGAMode:
resStringId = 44;
break;
case gsHerculesMode:
resStringId = 45;
break;
case gsTandyMode:
resStringId = 46;
break;
default:
break;

View File

@ -922,11 +922,12 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
_cursor.state = oldCursorState;
return;
} else if (_game.version <= 2 && lastKeyHit.keycode == Common::KEYCODE_SPACE) {
printMessageAndPause(getGUIString(gsPause), -1, true);
printMessageAndPause(getGUIString(gsPause), 0, -1, true);
return;
}
if ((VAR_RESTART_KEY != 0xFF && (lastKeyHit.ascii == VAR(VAR_RESTART_KEY))) ||
(_game.version == 2 && (lastKeyHit.keycode == Common::KEYCODE_F8)) ||
((_game.id == GID_CMI && !(_game.features & GF_DEMO))
&& lastKeyHit.keycode == Common::KEYCODE_F8 && lastKeyHit.hasFlags(0))) {
queryRestart();
@ -989,7 +990,6 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
return;
Common::KeyState ks = lastKeyHit;
pt = pauseEngine();
do {
@ -1008,10 +1008,11 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
setTalkSpeed(_defaultTextSpeed);
getSliderString(gsTextSpeedSlider, VAR(VAR_CHARINC), sliderString, sizeof(sliderString));
if (_game.version > 4)
if (_game.version > 4) {
showBannerAndPause(0, 0, sliderString);
else
} else if (_game.version == 4) {
showOldStyleBannerAndPause(sliderString, 9, 0);
}
ks = Common::KEYCODE_INVALID;
bool leftBtnPressed = false, rightBtnPressed = false;
@ -1024,12 +1025,37 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
if (_game.version <= 2 && (lastKeyHit.ascii == '+' || lastKeyHit.ascii == '-' ||
lastKeyHit.ascii == '>' || lastKeyHit.ascii == '<')) {
Common::KeyState ks = lastKeyHit;
byte textSpeedColor;
if (ks.ascii == '+' || ks.ascii == '>') {
textSpeedColor = _game.version <= 1 ? 7 : 14;
if (_defaultTextSpeed > 0)
_defaultTextSpeed -= 1;
} else {
textSpeedColor = _game.version <= 1 ? 2 : 4;
if (_defaultTextSpeed < 9)
_defaultTextSpeed += 1;
}
setTalkSpeed(_defaultTextSpeed);
ConfMan.setInt("original_gui_text_speed", _defaultTextSpeed);
getSliderString(gsTextSpeedSlider, 9 - _defaultTextSpeed + 1, sliderString, sizeof(sliderString));
printMessageAndPause(sliderString, textSpeedColor, 0, false);
return;
}
if (_game.version > 4 && lastKeyHit.keycode == Common::KEYCODE_k && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
showBannerAndPause(0, 120, getGUIString(gsHeap), _res->getHeapSize() / 1024);
return;
}
// NOTE: For consistency we enable the quit message even for sub v3 games which don't have it.
if ((lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_CTRL)) ||
(lastKeyHit.keycode == Common::KEYCODE_x && lastKeyHit.hasFlags(Common::KBD_ALT))) {
Common::Event event;
@ -1045,16 +1071,23 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
}
if (snapScrollKeyEnabled) {
if ((_game.version <= 3 && lastKeyHit.keycode == Common::KEYCODE_i && lastKeyHit.hasFlags(Common::KBD_ALT)) ||
if ((_game.version == 2 && lastKeyHit.keycode == Common::KEYCODE_s && lastKeyHit.hasFlags(Common::KBD_SHIFT)) ||
(_game.version == 3 && lastKeyHit.keycode == Common::KEYCODE_i && lastKeyHit.hasFlags(Common::KBD_ALT)) ||
(_game.version == 4 && lastKeyHit.keycode == Common::KEYCODE_r && lastKeyHit.hasFlags(Common::KBD_CTRL))) {
const char *msgSnap = _game.version == 4 ? "Horizontal Screen Snap" : "Screen reposition instantly";
const char *msgScroll = _game.version == 4 ? "Horizontal Screen Scroll" : "Screen reposition by Scrolling";
_snapScroll ^= 1;
if (_snapScroll) {
showOldStyleBannerAndPause(msgSnap, 9, 90);
} else {
showOldStyleBannerAndPause(msgScroll, 9, 90);
if (_game.version < 3) {
if (_snapScroll) {
printMessageAndPause(getGUIString(gsSnapOn), 2, 0, false);
} else {
printMessageAndPause(getGUIString(gsSnapOff), 14, 0, false);
}
} else {
if (_snapScroll) {
showBannerAndPause(0, 90, getGUIString(gsSnapOn));
} else {
showBannerAndPause(0, 90, getGUIString(gsSnapOff));
}
}
if (VAR_CAMERA_FAST_X != 0xFF)
@ -1062,31 +1095,102 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
return;
}
}
// The following ones serve no purpose whatsoever, but just for the sake of completeness...
// Also, these were originally mapped with the CTRL flag, but they would clash with other
// internal ScummVM commands, so they are instead available with the SHIFT flag.
if (lastKeyHit.keycode == Common::KEYCODE_j && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
showOldStyleBannerAndPause("Recalibrating Joystick", 2, 90);
return;
}
if (lastKeyHit.keycode == Common::KEYCODE_m && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
showOldStyleBannerAndPause("Mouse Mode", 2, 90);
return;
}
if (lastKeyHit.keycode == Common::KEYCODE_s && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
_internalSpeakerSoundsAreOn ^= 1;
if (_internalSpeakerSoundsAreOn) {
showOldStyleBannerAndPause("Sounds On", 9, 90);
// The following ones serve no purpose whatsoever, but just for the sake of completeness...
// Also, some of these were originally mapped with the CTRL flag, but they would clash with other
// internal ScummVM commands, so they are instead available with the SHIFT flag.
if (_game.version < 7) {
if (_game.version >= 4 && lastKeyHit.keycode == Common::KEYCODE_j && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
if (_game.version == 4) {
showOldStyleBannerAndPause(getGUIString(gsRecalJoystick), 2, 90);
} else {
showOldStyleBannerAndPause("Sounds Off", 9, 90);
showBannerAndPause(0, 90, getGUIString(gsRecalJoystick));
}
return;
}
if (_game.version >= 4 && lastKeyHit.keycode == Common::KEYCODE_m && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
if (_game.version == 4) {
showOldStyleBannerAndPause(getGUIString(gsMouseMode), 2, 90);
} else {
showBannerAndPause(0, 90, getGUIString(gsMouseMode));
}
return;
}
if (_game.version < 3) {
if (lastKeyHit.keycode == Common::KEYCODE_m && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
_guiMouseFlag ^= 1;
if (_guiMouseFlag) {
printMessageAndPause(getGUIString(gsMouseOn), _game.version <= 1 ? 5 : 2, 0, false);
} else {
printMessageAndPause(getGUIString(gsMouseOff), _game.version <= 1 ? 2 : 4, 0, false);
}
return;
}
return;
if (lastKeyHit.keycode == Common::KEYCODE_j && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
_guiJoystickFlag ^= 1;
if (_guiJoystickFlag) {
printMessageAndPause(getGUIString(gsJoystickOn), _game.version <= 1 ? 5 : 2, 0, false);
} else {
printMessageAndPause(getGUIString(gsJoystickOff), _game.version <= 1 ? 2 : 4, 0, false);
}
return;
}
if (lastKeyHit.keycode == Common::KEYCODE_F6) {
_internalSpeakerSoundsAreOn ^= 1;
if (_internalSpeakerSoundsAreOn) {
printMessageAndPause(getGUIString(gsSoundsOn), _game.version <= 1 ? 5 : 2, 0, false);
} else {
printMessageAndPause(getGUIString(gsSoundsOff), _game.version <= 1 ? 2 : 4, 0, false);
}
return;
}
}
if ((_game.version > 2 && _game.version < 5)) {
if (lastKeyHit.keycode == Common::KEYCODE_s && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
_internalSpeakerSoundsAreOn ^= 1;
if (_internalSpeakerSoundsAreOn) {
showOldStyleBannerAndPause(getGUIString(gsSoundsOn), 9, 90);
} else {
showOldStyleBannerAndPause(getGUIString(gsSoundsOff), 9, 90);
}
return;
}
}
// Graphic mode toggles for v1-2... maybe one day they'll actually do something :-)
if (_game.version == 1 || _game.version == 2) {
// VGA/MCGA mode
if (lastKeyHit.keycode == Common::KEYCODE_v && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
printMessageAndPause(getGUIString(gsVGAMode), _game.version <= 1 ? 5 : 2, 0, false);
}
// EGA mode
if (lastKeyHit.keycode == Common::KEYCODE_e && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
printMessageAndPause(getGUIString(gsEGAMode), _game.version <= 1 ? 5 : 2, 0, false);
}
// CGA mode
if (lastKeyHit.keycode == Common::KEYCODE_c && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
printMessageAndPause(getGUIString(gsCGAMode), _game.version <= 1 ? 5 : 2, 0, false);
}
// Hercules mode
if (lastKeyHit.keycode == Common::KEYCODE_h && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
printMessageAndPause(getGUIString(gsHerculesMode), _game.version <= 1 ? 5 : 2, 0, false);
}
// Tandy 16-color mode
if (lastKeyHit.keycode == Common::KEYCODE_t && lastKeyHit.hasFlags(Common::KBD_SHIFT)) {
printMessageAndPause(getGUIString(gsTandyMode), _game.version <= 1 ? 5 : 2, 0, false);
}
}
}
}

View File

@ -429,7 +429,22 @@ enum GUIString {
gsTextSpeed = 37,
gsDisplayText = 38,
gsSpooledMusic = 39,
gsInsertSaveDisk = 40
gsInsertSaveDisk = 40,
gsSnapOn = 41,
gsSnapOff = 42,
gsRecalJoystick = 43,
gsMouseMode = 44,
gsMouseOn = 45,
gsMouseOff = 46,
gsJoystickOn = 47,
gsJoystickOff = 48,
gsSoundsOn = 49,
gsSoundsOff = 50,
gsVGAMode = 51,
gsEGAMode = 52,
gsCGAMode = 53,
gsHerculesMode = 54,
gsTandyMode = 55
};
struct InternalGUIControl {
@ -636,7 +651,11 @@ protected:
int _saveScriptParam = 0;
int _guiCursorAnimCounter = 0;
int _v5VoiceMode = 0;
// Fake flags just for sub v5 GUIs
int _internalSpeakerSoundsAreOn = 1;
int _guiMouseFlag = 1;
int _guiJoystickFlag = 1;
Graphics::Surface _savegameThumbnail;
byte *_tempTextSurface = nullptr;
@ -658,7 +677,7 @@ protected:
void initBanners();
Common::KeyState showBannerAndPause(int bannerId, int32 waitTime, const char *msg, ...);
Common::KeyState showOldStyleBannerAndPause(const char *msg, int color, int32 waitTime);
Common::KeyState printMessageAndPause(const char *msg, int32 waitTime, bool drawOnSentenceLine);
Common::KeyState printMessageAndPause(const char *msg, int color, int32 waitTime, bool drawOnSentenceLine);
void clearBanner();
void setBannerColors(int bannerId, byte r, byte g, byte b);