SCUMM: Implement basic support for v0-3 GUI

This commit is contained in:
AndywinXp 2022-10-03 22:52:00 +02:00 committed by Eugene Sandulenko
parent 17a2ce8c5a
commit 13e7c9d4d9
12 changed files with 356 additions and 152 deletions

View File

@ -91,6 +91,32 @@ static const byte default_v6_cursor[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x0F,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
static const byte c64_dos_snail_cursor[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x0F,0x0F,0xFF,0xFF,0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x0F,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x0F,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0x0F,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0x0F,0x0F,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,
0xFF,0xFF,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,
0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,
0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0xFF,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,0x0F,0x0F,
// Blank pixels...
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
#ifdef ENABLE_SCUMM_7_8
static const byte default_v7_cursor[] = {
0x01,0x01,0x01,0x01, 0x00,0x0F,0x00, 0x01,0x01,0x01,0x01,
@ -809,6 +835,24 @@ void ScummEngine_v2::setBuiltinCursor(int idx) {
updateCursor();
}
void ScummEngine_v2::setSnailCursor() {
memcpy(_grabbedCursor, c64_dos_snail_cursor, sizeof(c64_dos_snail_cursor));
if (_game.version == 0) {
for (int i = 0; i < sizeof(c64_dos_snail_cursor); i++) {
if (_grabbedCursor[i] == 0x0F)
_grabbedCursor[i] = 0x01;
}
}
_cursor.width = 24;
_cursor.height = 21;
_cursor.hotspotX = 11;
_cursor.hotspotY = 10;
updateCursor();
}
void ScummEngine_v5::resetCursors() {
static const uint16 default_cursor_images[4][16] = {
/* cross-hair */

View File

@ -429,8 +429,8 @@ void InfoDialog::reflowLayout() {
_text->setSize(_w, _h);
}
const char *InfoDialog::getPlainEngineString(int stringno) {
const char *result;
const char *InfoDialog::getPlainEngineString(int stringno, bool forceHardcodedString) {
const char *result = nullptr;
if (stringno == 0)
return nullptr;
@ -450,7 +450,8 @@ const char *InfoDialog::getPlainEngineString(int stringno) {
result = string_map_table_v6[stringno - 1].string;
}
} else if (_vm->_game.version >= 3) {
result = (const char *)_vm->getStringAddress(getStaticResString(_vm->_language, stringno - 1).num);
if (!forceHardcodedString)
result = (const char *)_vm->getStringAddress(getStaticResString(_vm->_language, stringno - 1).num);
if (!result) {
result = getStaticResString(_vm->_language, stringno - 1).string;
@ -587,12 +588,12 @@ const ResString &InfoDialog::getStaticResString(Common::Language lang, int strin
{6, "Wollen Sie wirklich beenden? (j/n)j"} // (matching the previous sentence)
},
{ // Italian
{1, "Inserisci il disco %c e premi un pulsante per continuare."},
{2, "Impossibile trovare %s, (%c%d) Premere un pulsante."},
{3, "Errore nella lettura del disco %c, (%c%d) Premere un pulsante."},
{4, "Gioco in pausa. Premi SPAZIO per continuare."},
{5, "Sei sicuro di voler ricominciare? (S/N)S"},
{6, "Sei sicuro di voler uscire? (S/N)S"}
{1, "Inserisci il Disk n. Premi ENTER."}, // Original DOS Italian v2
{2, "Non trovato il file nn.lfl. Premi ENTER."}, // Original DOS Italian v2
{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
},
{ // Spanish
{1, "Introduce el disco %c y pulsa un bot""\xa2""n para continuar."},

View File

@ -96,7 +96,7 @@ public:
}
void reflowLayout() override;
const char *getPlainEngineString(int stringno);
const char *getPlainEngineString(int stringno, bool forceHardcodedString = false);
protected:
// Query a string from the resources

View File

@ -20,6 +20,7 @@
*/
#include "scumm/scumm.h"
#include "scumm/scumm_v2.h"
#include "scumm/scumm_v4.h"
#include "scumm/scumm_v6.h"
#include "scumm/scumm_v8.h"
@ -261,6 +262,91 @@ Common::KeyState ScummEngine::showBannerAndPause(int bannerId, int32 waitTime, c
return ks;
}
Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int32 waitTime, bool drawOnSentenceLine) {
Common::Rect sentenceline;
// Pause the engine
PauseToken pt = pauseEngine();
if (drawOnSentenceLine) {
setSnailCursor();
_string[2].charset = 1;
_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
_string[2].xpos = 0;
_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
if (_game.platform == Common::kPlatformNES) {
_string[2].xpos = 16;
_string[2].color = 0;
} else if (_game.platform == Common::kPlatformC64) {
_string[2].color = 16;
} else {
_string[2].color = 13;
}
byte string[80];
const char *ptr = msg;
int i = 0, len = 0;
// Maximum length of printable characters
int maxChars = (_game.platform == Common::kPlatformNES) ? 60 : 40;
while (*ptr) {
if (*ptr != '@')
len++;
if (len > maxChars) {
break;
}
string[i++] = *ptr++;
if (_game.platform == Common::kPlatformNES && len == 30) {
string[i++] = 0xFF;
string[i++] = 8;
}
}
string[i] = 0;
if (_game.platform == Common::kPlatformNES) {
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 16;
sentenceline.left = 16;
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
} else {
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
sentenceline.left = 0;
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
}
restoreBackground(sentenceline);
drawString(2, (byte *)string);
drawDirtyScreenParts();
} else {
}
// 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) {
waitForBannerInput(waitTime, ks, leftBtnPressed, rightBtnPressed);
}
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();;
return ks;
}
Common::KeyState ScummEngine::showOldStyleBannerAndPause(const char *msg, int color, int32 waitTime) {
// LOOM VGA uses the new style GUI
if (_game.version == 4 && _game.id == GID_LOOM) {
@ -291,10 +377,9 @@ Common::KeyState ScummEngine::showOldStyleBannerAndPause(const char *msg, int co
// Pause the engine
PauseToken pt = pauseEngine();
// Backup the current charsetId, since we're going to switch
// to charsetId == 1...
// Backup the current charsetId...
int oldId = _charset->getCurID();
_charset->setCurID(1);
_charset->setCurID(_game.version > 3 ? 1 : 0);
// Take all the necessary measurements for the box which
// will contain the string...
@ -304,14 +389,35 @@ Common::KeyState ScummEngine::showOldStyleBannerAndPause(const char *msg, int co
bannerMsgWidth = 100;
startingPointY = 80;
bannerSaveYStart = startingPointY - 2;
bannerSaveYStart = startingPointY - (_game.version == 4 ? 2 : _virtscr[kMainVirtScreen].topline);
// Save the pixels which will be overwritten by the banner,
// so that we can restore them later...
if (!_bannerMem) {
int rowSize = _screenWidth + 8;
_bannerMemSize = (bannerMsgHeight + 2) * (_screenWidth + 8);
int rowSize = _screenWidth + (_game.version == 4 ? 8 : 0);
// FM-Towns games draw the banner on the text surface, so let's save that
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && !_textSurfBannerMem) {
rowSize *= _textSurfaceMultiplier;
bannerSaveYStart *= _textSurfaceMultiplier;
_textSurfBannerMemSize = bannerMsgHeight * rowSize * _textSurfaceMultiplier;
_textSurfBannerMem = (byte *)malloc(_textSurfBannerMemSize * sizeof(byte));
if (_textSurfBannerMem) {
memcpy(
_textSurfBannerMem,
&((byte *)_textSurface.getBasePtr(0, _screenTop * _textSurfaceMultiplier))[rowSize * bannerSaveYStart],
_textSurfBannerMemSize);
}
// We're going to use these same values for saving the
// virtual screen surface, so let's un-multiply them...
rowSize /= _textSurfaceMultiplier;
bannerSaveYStart /= _textSurfaceMultiplier;
}
#endif
_bannerMemSize = (bannerMsgHeight + 2) * (rowSize);
_bannerMem = (byte *)malloc(_bannerMemSize * sizeof(byte));
if (_bannerMem) {
memcpy(
@ -362,7 +468,7 @@ void ScummEngine::clearBanner() {
// Restore the GFX content which was under the banner,
// and then mark that part of the screen as dirty.
if (_bannerMem) {
int rowSize = _screenWidth + 8;
int rowSize = _screenWidth + (_game.version >= 4 ? 8 : 0);
// Don't manually clear the banner if a SMUSH movie is playing,
// as that will cause some rare small glitches. The SMUSH player
// will take care of that for us automatically when updating the
@ -371,12 +477,14 @@ void ScummEngine::clearBanner() {
int startingPointY;
if (_game.version == 8) {
startingPointY = _screenHeight / 2 - 10;
} else if (_game.version < 4) {
startingPointY = 80;
} else if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformFMTowns) {
startingPointY = 78;
} else {
startingPointY = ((_game.version < 7) ? 80 - 2 : _screenHeight / 2 - 10);
}
startingPointY -= (_game.version >= 4 ? 0 : _virtscr[kMainVirtScreen].topline);
// FM-Towns games draw the banners on the text surface, so restore both surfaces...
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && _textSurfBannerMem) {
@ -393,6 +501,7 @@ void ScummEngine::clearBanner() {
startingPointY /= _textSurfaceMultiplier;
}
#endif
memcpy(
&_virtscr[kMainVirtScreen].getPixels(0, _screenTop)[rowSize * startingPointY],
_bannerMem,
@ -1138,7 +1247,7 @@ void ScummEngine::saveSurfacesPreGUI() {
// so the last line is being drawn on the verb surface; to address this, we
// save and restore that too.
if (_game.version < 4 || _game.version > 6)
if (_game.version < 3 || _game.version > 6)
return;
_tempTextSurface = (byte *)malloc(_textSurface.pitch * _textSurface.h * sizeof(byte));
@ -1181,7 +1290,7 @@ void ScummEngine::saveSurfacesPreGUI() {
void ScummEngine::restoreSurfacesPostGUI() {
if (_game.version < 4 || _game.version > 6)
if (_game.version < 3 || _game.version > 6)
return;
if (_tempTextSurface) {
@ -1282,10 +1391,13 @@ void ScummEngine::queryQuit(bool returnToLauncher) {
// "Are you sure you want to quit? (Y/N)"
Common::KeyState ks;
if (_game.version > 4)
if (_game.version > 4) {
ks = showBannerAndPause(0, -1, msgLabelPtr);
else
} else if (_game.version == 4) {
ks = showOldStyleBannerAndPause(msgLabelPtr, 12, -1);
} else {
ks = printMessageAndPause(msgLabelPtr, -1, true);
}
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
@ -2999,7 +3111,7 @@ void ScummEngine::drawGUIText(const char *buttonString, Common::Rect *clipRect,
_string[5].right = clipRect ? clipRect->right : _screenWidth - 1;
_string[5].center = centerFlag;
_string[5].color = textColor;
_string[5].charset = 1;
_string[5].charset = _game.version > 3 ? 1 : 0;
drawString(5, (const byte *)buttonString);
_string[5].right = tmpRight;
@ -3222,7 +3334,7 @@ const char *ScummEngine::getGUIString(int stringId) {
}
if (resStringId > 0)
return d.getPlainEngineString(resStringId);
return d.getPlainEngineString(resStringId, (_game.id == GID_INDY3) && stringId == gsQuitPrompt);
else
return _emptyMsg;
}

View File

@ -121,7 +121,7 @@ void ScummEngine::parseEvent(Common::Event event) {
_fastMode ^= 1;
} else if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_g) {
_fastMode ^= 2;
} else if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_s) {
} else if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.hasFlags(Common::KBD_ALT) && event.kbd.keycode == Common::KEYCODE_s) {
_res->resourceStats();
} else if (event.kbd.hasFlags(Common::KBD_ALT) && event.kbd.keycode == Common::KEYCODE_x) {
if (_game.version < 8) {
@ -195,6 +195,7 @@ void ScummEngine::parseEvent(Common::Event event) {
_leftBtnPressed |= msClicked|msDown;
else if (event.type == Common::EVENT_RBUTTONDOWN)
_rightBtnPressed |= msClicked|msDown;
_mouse.x = event.mouse.x;
_mouse.y = event.mouse.y;
@ -582,7 +583,7 @@ void ScummEngine::waitForBannerInput(int32 waitTime, Common::KeyState &ks, bool
while (!validKey && !leftBtnClicked && !rightBtnClicked && !(handeleMouseWheel && _mouseWheelFlag)) {
waitForTimer(1); // Allow the engine to update the screen and fetch new inputs...
if (_game.version < 7 && (_guiCursorAnimCounter++ & 16)) {
if (_game.version > 2 && _game.version < 7 && (_guiCursorAnimCounter++ & 16)) {
_guiCursorAnimCounter = 0;
animateCursor();
}
@ -794,6 +795,18 @@ void ScummEngine_v6::processKeyboard(Common::KeyState lastKeyHit) {
}
void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
if (isUsingOriginalGUI()) {
if (lastKeyHit.keycode == Common::KEYCODE_F5) {
prepareSavegame();
if (_game.id == GID_MANIAC && _game.version == 0) {
runScript(2, 0, 0, nullptr);
}
if (_game.id == GID_MANIAC && _game.platform == Common::kPlatformNES) {
runScript(163, 0, 0, nullptr);
}
}
}
// RETURN is used to skip cutscenes in the Commodore 64 version of Zak McKracken
if (_game.id == GID_ZAK &&_game.platform == Common::kPlatformC64 && lastKeyHit.keycode == Common::KEYCODE_RETURN && lastKeyHit.hasFlags(0)) {
lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE);
@ -823,13 +836,15 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
ScummEngine::processKeyboard(lastKeyHit);
// On Alt-F5 prepare savegame for the original save/load dialog.
if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
prepareSavegame();
if (_game.id == GID_MANIAC && _game.version == 0) {
runScript(2, 0, 0, nullptr);
}
if (_game.id == GID_MANIAC &&_game.platform == Common::kPlatformNES) {
runScript(163, 0, 0, nullptr);
if (!isUsingOriginalGUI()) {
if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
prepareSavegame();
if (_game.id == GID_MANIAC && _game.version == 0) {
runScript(2, 0, 0, nullptr);
}
if (_game.id == GID_MANIAC && _game.platform == Common::kPlatformNES) {
runScript(163, 0, 0, nullptr);
}
}
}
@ -844,25 +859,33 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
}
void ScummEngine_v3::processKeyboard(Common::KeyState lastKeyHit) {
if (isUsingOriginalGUI()) {
if (lastKeyHit.keycode == Common::KEYCODE_F5) {
prepareSavegame();
}
}
// Fall back to default behavior
ScummEngine::processKeyboard(lastKeyHit);
// On Alt-F5 prepare savegame for the original save/load dialog.
if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
prepareSavegame();
}
if (!isUsingOriginalGUI()) {
// On Alt-F5 prepare savegame for the original save/load dialog.
if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(Common::KBD_ALT)) {
prepareSavegame();
}
// 'i' brings up an IQ dialog in Indy3 (disabled in save/load dialog for input)
if (lastKeyHit.ascii == 'i' && _game.id == GID_INDY3 && _currentRoom != 14) {
// SCUMM var 244 is the episode score
// and var 245 is the series score
char text[50];
// 'i' brings up an IQ dialog in Indy3 (disabled in save/load dialog for input)
if (lastKeyHit.ascii == 'i' && _game.id == GID_INDY3 && _currentRoom != 14) {
// SCUMM var 244 is the episode score
// and var 245 is the series score
char text[50];
updateIQPoints();
updateIQPoints();
Common::sprintf_s(text, "IQ Points: Episode = %d, Series = %d", _scummVars[244], _scummVars[245]);
Indy3IQPointsDialog indy3IQPointsDialog(this, text);
runDialog(indy3IQPointsDialog);
Common::sprintf_s(text, "IQ Points: Episode = %d, Series = %d", _scummVars[244], _scummVars[245]);
Indy3IQPointsDialog indy3IQPointsDialog(this, text);
runDialog(indy3IQPointsDialog);
}
}
}
@ -898,6 +921,9 @@ 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);
return;
}
if ((VAR_RESTART_KEY != 0xFF && (lastKeyHit.ascii == VAR(VAR_RESTART_KEY))) ||
@ -1013,18 +1039,22 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
}
if (VAR_MAINMENU_KEY != 0xFF && (lastKeyHit.ascii == VAR(VAR_MAINMENU_KEY) && lastKeyHit.hasFlags(0))
&& _game.platform != Common::kPlatformFMTowns) {
&& _game.platform != Common::kPlatformFMTowns && _game.version > 3) {
showMainMenu();
return;
}
if (_game.version == 4) {
if (lastKeyHit.keycode == Common::KEYCODE_r && lastKeyHit.hasFlags(Common::KBD_CTRL)) {
if (snapScrollKeyEnabled) {
if ((_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("Horizontal Screen Snap", 9, 90);
showOldStyleBannerAndPause(msgSnap, 9, 90);
} else {
showOldStyleBannerAndPause("Horizontal Screen Scroll", 9, 90);
showOldStyleBannerAndPause(msgScroll, 9, 90);
}
if (VAR_CAMERA_FAST_X != 0xFF)
@ -1066,7 +1096,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (_game.id == GID_CMI)
mainmenuKeyEnabled = true;
if (mainmenuKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0))) {
if (mainmenuKeyEnabled && !isUsingOriginalGUI() && (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.hasFlags(0))) {
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, nullptr);
@ -1078,10 +1108,10 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (VAR_SAVELOAD_SCRIPT2 != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, nullptr);
} else if (restartKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F8 && lastKeyHit.hasFlags(0))) {
} else if (restartKeyEnabled && !isUsingOriginalGUI() && (lastKeyHit.keycode == Common::KEYCODE_F8 && lastKeyHit.hasFlags(0))) {
confirmRestartDialog();
} else if (pauseKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_SPACE && lastKeyHit.hasFlags(0))) {
} else if (pauseKeyEnabled && !isUsingOriginalGUI() && (lastKeyHit.keycode == Common::KEYCODE_SPACE && lastKeyHit.hasFlags(0))) {
pauseGame();
} else if (talkstopKeyEnabled && lastKeyHit.ascii == '.') {
@ -1095,7 +1125,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
// VAR_CUTSCENEEXIT_KEY doesn't exist in SCUMM0
if (VAR_CUTSCENEEXIT_KEY != 0xFF)
_mouseAndKeyboardStat = VAR(VAR_CUTSCENEEXIT_KEY);
} else if (snapScrollKeyEnabled && lastKeyHit.keycode == Common::KEYCODE_r &&
} else if (snapScrollKeyEnabled && !isUsingOriginalGUI() && lastKeyHit.keycode == Common::KEYCODE_r &&
lastKeyHit.hasFlags(Common::KBD_CTRL)) {
_snapScroll ^= 1;
if (_snapScroll) {

View File

@ -1051,99 +1051,7 @@ void ScummEngine_v2::drawPreposition(int index) {
}
void ScummEngine_v2::o2_drawSentence() {
Common::Rect sentenceline;
const byte *temp;
int slot = getVerbSlot(VAR(VAR_SENTENCE_VERB), 0);
if (!((_userState & USERSTATE_IFACE_SENTENCE) ||
(_game.platform == Common::kPlatformNES && (_userState & USERSTATE_IFACE_ALL))))
return;
if (getResourceAddress(rtVerb, slot))
_sentenceBuf = (char *)getResourceAddress(rtVerb, slot);
else
return;
if (VAR(VAR_SENTENCE_OBJECT1) > 0) {
temp = getObjOrActorName(VAR(VAR_SENTENCE_OBJECT1));
if (temp) {
_sentenceBuf += " ";
_sentenceBuf += (const char *)temp;
}
// For V1 games, the engine must compute the preposition.
// In all other Scumm versions, this is done by the sentence script.
if ((_game.id == GID_MANIAC && _game.version == 1 && !(_game.platform == Common::kPlatformNES)) && (VAR(VAR_SENTENCE_PREPOSITION) == 0)) {
if (_verbs[slot].prep == 0xFF) {
byte *ptr = getOBCDFromObject(VAR(VAR_SENTENCE_OBJECT1));
assert(ptr);
VAR(VAR_SENTENCE_PREPOSITION) = (*(ptr + 12) >> 5);
} else
VAR(VAR_SENTENCE_PREPOSITION) = _verbs[slot].prep;
}
}
if (0 < VAR(VAR_SENTENCE_PREPOSITION) && VAR(VAR_SENTENCE_PREPOSITION) <= 4) {
drawPreposition(VAR(VAR_SENTENCE_PREPOSITION));
}
if (VAR(VAR_SENTENCE_OBJECT2) > 0) {
temp = getObjOrActorName(VAR(VAR_SENTENCE_OBJECT2));
if (temp) {
_sentenceBuf += " ";
_sentenceBuf += (const char *)temp;
}
}
_string[2].charset = 1;
_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
_string[2].xpos = 0;
_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
if (_game.platform == Common::kPlatformNES) {
_string[2].xpos = 16;
_string[2].color = 0;
} else if (_game.platform == Common::kPlatformC64) {
_string[2].color = 16;
} else {
_string[2].color = 13;
}
byte string[80];
const char *ptr = _sentenceBuf.c_str();
int i = 0, len = 0;
// Maximum length of printable characters
int maxChars = (_game.platform == Common::kPlatformNES) ? 60 : 40;
while (*ptr) {
if (*ptr != '@')
len++;
if (len > maxChars) {
break;
}
string[i++] = *ptr++;
if (_game.platform == Common::kPlatformNES && len == 30) {
string[i++] = 0xFF;
string[i++] = 8;
}
}
string[i] = 0;
if (_game.platform == Common::kPlatformNES) {
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 16;
sentenceline.left = 16;
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
} else {
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
sentenceline.left = 0;
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
}
restoreBackground(sentenceline);
drawString(2, (byte *)string);
drawSentence();
}
void ScummEngine_v2::o2_ifClassOfIs() {

View File

@ -408,12 +408,14 @@ void ScummEngine_v4::o4_saveLoadGame() {
}
break;
case 0x40: // load
_lastLoadedRoom = -1;
if (loadState(slot, false))
result = 3; // sucess
else
result = 5; // failed to load
break;
case 0x80: // save
_lastLoadedRoom = -1;
if (_game.version <= 3) {
char name[32];
if (_game.version <= 2) {

View File

@ -2596,7 +2596,8 @@ load_game:
_res->increaseExpireCounter();
animateCursor();
if (!isUsingOriginalGUI() || ((_game.version >= 3) || !isPaused()))
animateCursor();
/* show or hide mouse */
CursorMan.showMouse(_cursor.state > 0);
@ -3146,7 +3147,7 @@ bool ScummEngine::isUsingOriginalGUI() {
if (_game.heversion != 0)
return false;
if (_game.version > 3)
if (_game.version >= 0)
return _useOriginalGUI;
return false;

View File

@ -653,9 +653,13 @@ protected:
int _curCursorHotspotX = 0;
int _curCursorHotspotY = 0;
virtual void setSnailCursor() {}
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);
void clearBanner();
void setBannerColors(int bannerId, byte r, byte g, byte b);
virtual int getBannerColor(int bannerId);
@ -1201,6 +1205,8 @@ protected:
bool _doEffect = false;
bool _snapScroll = false;
virtual void setBuiltinCursor(int index) {}
public:
bool isLightOn() const;
@ -1478,6 +1484,7 @@ protected:
virtual void printString(int m, const byte *msg);
virtual bool handleNextCharsetCode(Actor *a, int *c);
virtual void drawSentence() {}
virtual void CHARSET_1();
bool newLine();
void drawString(int a, const byte *msg);

View File

@ -92,6 +92,7 @@ protected:
void clearStateCommon(byte type);
void stopScriptCommon(int script);
void drawSentence() override;
void resetSentence() override;
void setUserState(byte state);
@ -104,6 +105,7 @@ protected:
void initNESMouseOver();
void setBuiltinCursor(int index) override;
void setSnailCursor() override;
void drawPreposition(int index);

View File

@ -82,7 +82,7 @@ protected:
void animateCursor() override;
virtual void setBuiltinCursor(int index);
void setBuiltinCursor(int index) override;
void redefineBuiltinCursorFromChar(int index, int chr);
void redefineBuiltinCursorHotspot(int index, int x, int y);

View File

@ -36,6 +36,7 @@
#endif
#include "scumm/resource.h"
#include "scumm/scumm.h"
#include "scumm/scumm_v2.h"
#include "scumm/scumm_v6.h"
#include "scumm/scumm_v7.h"
#include "scumm/verbs.h"
@ -706,6 +707,102 @@ void ScummEngine::fakeBidiString(byte *ltext, bool ignoreVerb, int ltextSize) co
free(stack);
}
void ScummEngine_v2::drawSentence() {
Common::Rect sentenceline;
const byte *temp;
int slot = getVerbSlot(VAR(VAR_SENTENCE_VERB), 0);
if (!((_userState & USERSTATE_IFACE_SENTENCE) ||
(_game.platform == Common::kPlatformNES && (_userState & USERSTATE_IFACE_ALL))))
return;
if (getResourceAddress(rtVerb, slot))
_sentenceBuf = (char *)getResourceAddress(rtVerb, slot);
else
return;
if (VAR(VAR_SENTENCE_OBJECT1) > 0) {
temp = getObjOrActorName(VAR(VAR_SENTENCE_OBJECT1));
if (temp) {
_sentenceBuf += " ";
_sentenceBuf += (const char *)temp;
}
// For V1 games, the engine must compute the preposition.
// In all other Scumm versions, this is done by the sentence script.
if ((_game.id == GID_MANIAC && _game.version == 1 && !(_game.platform == Common::kPlatformNES)) && (VAR(VAR_SENTENCE_PREPOSITION) == 0)) {
if (_verbs[slot].prep == 0xFF) {
byte *ptr = getOBCDFromObject(VAR(VAR_SENTENCE_OBJECT1));
assert(ptr);
VAR(VAR_SENTENCE_PREPOSITION) = (*(ptr + 12) >> 5);
} else
VAR(VAR_SENTENCE_PREPOSITION) = _verbs[slot].prep;
}
}
if (0 < VAR(VAR_SENTENCE_PREPOSITION) && VAR(VAR_SENTENCE_PREPOSITION) <= 4) {
drawPreposition(VAR(VAR_SENTENCE_PREPOSITION));
}
if (VAR(VAR_SENTENCE_OBJECT2) > 0) {
temp = getObjOrActorName(VAR(VAR_SENTENCE_OBJECT2));
if (temp) {
_sentenceBuf += " ";
_sentenceBuf += (const char *)temp;
}
}
_string[2].charset = 1;
_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
_string[2].xpos = 0;
_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
if (_game.platform == Common::kPlatformNES) {
_string[2].xpos = 16;
_string[2].color = 0;
} else if (_game.platform == Common::kPlatformC64) {
_string[2].color = 16;
} else {
_string[2].color = 13;
}
byte string[80];
const char *ptr = _sentenceBuf.c_str();
int i = 0, len = 0;
// Maximum length of printable characters
int maxChars = (_game.platform == Common::kPlatformNES) ? 60 : 40;
while (*ptr) {
if (*ptr != '@')
len++;
if (len > maxChars) {
break;
}
string[i++] = *ptr++;
if (_game.platform == Common::kPlatformNES && len == 30) {
string[i++] = 0xFF;
string[i++] = 8;
}
}
string[i] = 0;
if (_game.platform == Common::kPlatformNES) {
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 16;
sentenceline.left = 16;
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
} else {
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
sentenceline.left = 0;
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
}
restoreBackground(sentenceline);
drawString(2, (byte *)string);
}
void ScummEngine::CHARSET_1() {
Actor *a;
if (_game.heversion >= 70 && _haveMsg == 3) {