SCUMM: GUI: Fix pre-v7 text rendering over GUI
This commit is contained in:
parent
194555c3a7
commit
025d25a1f1
3 changed files with 92 additions and 8 deletions
|
@ -1255,7 +1255,8 @@ void ScummEngine::restoreCharsetBg() {
|
||||||
_nextLeft = _string[0].xpos;
|
_nextLeft = _string[0].xpos;
|
||||||
_nextTop = _string[0].ypos + _screenTop;
|
_nextTop = _string[0].ypos + _screenTop;
|
||||||
|
|
||||||
if (_charset->_hasMask) {
|
if (_charset->_hasMask || _postGUICharMask) {
|
||||||
|
_postGUICharMask = false;
|
||||||
_charset->_hasMask = false;
|
_charset->_hasMask = false;
|
||||||
_charset->_str.left = -1;
|
_charset->_str.left = -1;
|
||||||
_charset->_left = -1;
|
_charset->_left = -1;
|
||||||
|
|
|
@ -103,6 +103,12 @@ Common::KeyState ScummEngine::showBannerAndPause(int bannerId, int32 waitTime, c
|
||||||
convertMessageToString((const byte *)getGUIString(gsYesKey), (byte *)localizedY, sizeof(localizedY));
|
convertMessageToString((const byte *)getGUIString(gsYesKey), (byte *)localizedY, sizeof(localizedY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backup the text surface...
|
||||||
|
if (_game.version < 7) {
|
||||||
|
saveTextSurfacePreGUI();
|
||||||
|
restoreCharsetBg();
|
||||||
|
}
|
||||||
|
|
||||||
// Pause the engine
|
// Pause the engine
|
||||||
PauseToken pt = pauseEngine();
|
PauseToken pt = pauseEngine();
|
||||||
|
|
||||||
|
@ -209,6 +215,12 @@ Common::KeyState ScummEngine::showBannerAndPause(int bannerId, int32 waitTime, c
|
||||||
clearBanner();
|
clearBanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore the text surface...
|
||||||
|
if (_game.version < 7) {
|
||||||
|
restoreTextSurfacePostGUI();
|
||||||
|
_completeScreenRedraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, resume the engine, clear the input state, and restore the charset.
|
// Finally, resume the engine, clear the input state, and restore the charset.
|
||||||
pt.clear();
|
pt.clear();
|
||||||
clearClickedStatus();
|
clearClickedStatus();
|
||||||
|
@ -928,6 +940,50 @@ int ScummEngine::getBannerColor(int bannerId) {
|
||||||
return (int)arrAddr[bannerId];
|
return (int)arrAddr[bannerId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScummEngine::saveTextSurfacePreGUI() {
|
||||||
|
if (_game.version < 4 || _game.version > 6)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_tempTextSurface = (byte *)malloc(_textSurface.w * _textSurface.h * sizeof(byte));
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
uint32 curPix;
|
||||||
|
for (int i = 0; i < _textSurface.h; i++) {
|
||||||
|
for (int j = 0; j < _textSurface.w; j++) {
|
||||||
|
x = j;
|
||||||
|
y = i;
|
||||||
|
curPix = _textSurface.getPixel(x, y);
|
||||||
|
_tempTextSurface[j + i * _textSurface.w] = curPix;
|
||||||
|
if (curPix != 0xFD)
|
||||||
|
_virtscr[kMainVirtScreen].setPixel(_virtscr[kMainVirtScreen].xstart + x, y, curPix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScummEngine::restoreTextSurfacePostGUI() {
|
||||||
|
if (_game.version < 4 || _game.version > 6)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
uint32 curPix;
|
||||||
|
for (int i = 0; i < _textSurface.h; i++) {
|
||||||
|
for (int j = 0; j < _textSurface.w; j++) {
|
||||||
|
x = j;
|
||||||
|
y = i;
|
||||||
|
curPix = _tempTextSurface[j + i * _textSurface.w];
|
||||||
|
_textSurface.setPixel(x, y, curPix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal the restoreCharsetBg() function that there's text
|
||||||
|
// on the text surface, so it gets deleted the next time another
|
||||||
|
// text is displayed...
|
||||||
|
_postGUICharMask = true;
|
||||||
|
|
||||||
|
free(_tempTextSurface);
|
||||||
|
_tempTextSurface = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ScummEngine::toggleVoiceMode() {
|
void ScummEngine::toggleVoiceMode() {
|
||||||
if (VAR_VOICE_MODE != 0xFF) {
|
if (VAR_VOICE_MODE != 0xFF) {
|
||||||
VAR(VAR_VOICE_MODE) = (VAR(VAR_VOICE_MODE) != 1) ? 1 : 0;
|
VAR(VAR_VOICE_MODE) = (VAR(VAR_VOICE_MODE) != 1) ? 1 : 0;
|
||||||
|
@ -1069,13 +1125,15 @@ bool ScummEngine::canWriteGame(int slotId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScummEngine::userWriteLabelRoutine(Common::KeyState &ks, bool &leftMsClicked, bool &rightMsClicked) {
|
bool ScummEngine::userWriteLabelRoutine(Common::KeyState &ks, bool &leftMsClicked, bool &rightMsClicked) {
|
||||||
|
bool hasLoadedState = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
waitForTimer(1);
|
waitForTimer(1);
|
||||||
waitForBannerInput(-1, ks, leftMsClicked, rightMsClicked);
|
waitForBannerInput(-1, ks, leftMsClicked, rightMsClicked);
|
||||||
rightMsClicked = false;
|
rightMsClicked = false;
|
||||||
if (ks.keycode == Common::KEYCODE_RETURN) {
|
if (ks.keycode == Common::KEYCODE_RETURN) {
|
||||||
clearClickedStatus();
|
clearClickedStatus();
|
||||||
executeMainMenuOperation(GUI_CTRL_OK_BUTTON, -1);
|
executeMainMenuOperation(GUI_CTRL_OK_BUTTON, -1, hasLoadedState);
|
||||||
return true;
|
return true;
|
||||||
} else if (leftMsClicked) {
|
} else if (leftMsClicked) {
|
||||||
clearClickedStatus();
|
clearClickedStatus();
|
||||||
|
@ -1153,6 +1211,7 @@ void ScummEngine::showMainMenu() {
|
||||||
bool leftMsClicked = false, rightMsClicked = false;
|
bool leftMsClicked = false, rightMsClicked = false;
|
||||||
int clickedControl = -1;
|
int clickedControl = -1;
|
||||||
int curMouseX, curMouseY;
|
int curMouseX, curMouseY;
|
||||||
|
bool hasLoadedState = false;
|
||||||
|
|
||||||
Common::KeyState ks;
|
Common::KeyState ks;
|
||||||
|
|
||||||
|
@ -1171,6 +1230,19 @@ void ScummEngine::showMainMenu() {
|
||||||
_saveSound = 1;
|
_saveSound = 1;
|
||||||
setShake(0);
|
setShake(0);
|
||||||
|
|
||||||
|
if (_game.version < 7) {
|
||||||
|
// Below version 7, we draw texts on a separate surface which is then composited
|
||||||
|
// on top of the main one during ScummEngine::drawDirtyScreenParts().
|
||||||
|
// This results in texts overlapping on top of the menu; let's simulate the end result
|
||||||
|
// of the original by copying the text surface over the main one just before showing
|
||||||
|
// the menu...
|
||||||
|
saveTextSurfacePreGUI();
|
||||||
|
|
||||||
|
// V6 games should call for stopTalk() instead, but that's a bit too drastic;
|
||||||
|
// this ensures that we can at least hear the speech after the menu is closed.
|
||||||
|
restoreCharsetBg();
|
||||||
|
}
|
||||||
|
|
||||||
_menuPage = GUI_PAGE_MAIN;
|
_menuPage = GUI_PAGE_MAIN;
|
||||||
setUpMainMenuControls();
|
setUpMainMenuControls();
|
||||||
drawMainMenuControls();
|
drawMainMenuControls();
|
||||||
|
@ -1226,7 +1298,7 @@ void ScummEngine::showMainMenu() {
|
||||||
drawInternalGUIControl(clickedControl, 0);
|
drawInternalGUIControl(clickedControl, 0);
|
||||||
|
|
||||||
// Execute the operation pertaining the clicked control
|
// Execute the operation pertaining the clicked control
|
||||||
if (executeMainMenuOperation(clickedControl, curMouseX))
|
if (executeMainMenuOperation(clickedControl, curMouseX, hasLoadedState))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1240,7 +1312,7 @@ void ScummEngine::showMainMenu() {
|
||||||
_system->updateScreen();
|
_system->updateScreen();
|
||||||
|
|
||||||
if (_menuPage == GUI_PAGE_LOAD) {
|
if (_menuPage == GUI_PAGE_LOAD) {
|
||||||
if (executeMainMenuOperation(GUI_CTRL_OK_BUTTON, curMouseX))
|
if (executeMainMenuOperation(GUI_CTRL_OK_BUTTON, curMouseX, hasLoadedState))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1282,12 +1354,15 @@ void ScummEngine::showMainMenu() {
|
||||||
if (_game.version == 7)
|
if (_game.version == 7)
|
||||||
CHARSET_1();
|
CHARSET_1();
|
||||||
|
|
||||||
|
if (_game.version < 7 && !hasLoadedState && !_quitByButton)
|
||||||
|
restoreTextSurfacePostGUI();
|
||||||
|
|
||||||
// Resume the engine
|
// Resume the engine
|
||||||
pt.clear();
|
pt.clear();
|
||||||
clearClickedStatus();
|
clearClickedStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScummEngine::executeMainMenuOperation(int op, int mouseX) {
|
bool ScummEngine::executeMainMenuOperation(int op, int mouseX, bool &hasLoadedState) {
|
||||||
char saveScreenTitle[512];
|
char saveScreenTitle[512];
|
||||||
char formattedString[512];
|
char formattedString[512];
|
||||||
|
|
||||||
|
@ -1312,7 +1387,6 @@ bool ScummEngine::executeMainMenuOperation(int op, int mouseX) {
|
||||||
return true;
|
return true;
|
||||||
case GUI_CTRL_QUIT_BUTTON:
|
case GUI_CTRL_QUIT_BUTTON:
|
||||||
queryQuit();
|
queryQuit();
|
||||||
_quitByButton = shouldQuit();
|
|
||||||
return true;
|
return true;
|
||||||
case GUI_CTRL_OK_BUTTON:
|
case GUI_CTRL_OK_BUTTON:
|
||||||
if (_menuPage == GUI_PAGE_SAVE) {
|
if (_menuPage == GUI_PAGE_SAVE) {
|
||||||
|
@ -1386,7 +1460,13 @@ bool ScummEngine::executeMainMenuOperation(int op, int mouseX) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_game.version < 7) {
|
||||||
|
_postGUICharMask = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (loadState(_mainMenuSavegameLabel + _curDisplayedSaveSlotPage * 9, false)) {
|
if (loadState(_mainMenuSavegameLabel + _curDisplayedSaveSlotPage * 9, false)) {
|
||||||
|
hasLoadedState = true;
|
||||||
|
|
||||||
if (!_spooledMusicIsToBeEnabled)
|
if (!_spooledMusicIsToBeEnabled)
|
||||||
_imuseDigital->diMUSEDisableSpooledMusic();
|
_imuseDigital->diMUSEDisableSpooledMusic();
|
||||||
|
|
||||||
|
|
|
@ -635,6 +635,8 @@ protected:
|
||||||
int _spooledMusicIsToBeEnabled = 1;
|
int _spooledMusicIsToBeEnabled = 1;
|
||||||
int _saveScriptParam = 0;
|
int _saveScriptParam = 0;
|
||||||
Graphics::Surface _savegameThumbnail;
|
Graphics::Surface _savegameThumbnail;
|
||||||
|
byte *_tempTextSurface;
|
||||||
|
bool _postGUICharMask = false;
|
||||||
|
|
||||||
// Saved cursor pre and post GUI
|
// Saved cursor pre and post GUI
|
||||||
byte *_curGrabbedCursor = nullptr;
|
byte *_curGrabbedCursor = nullptr;
|
||||||
|
@ -681,14 +683,15 @@ protected:
|
||||||
void drawMainMenuControls();
|
void drawMainMenuControls();
|
||||||
void updateMainMenuControls();
|
void updateMainMenuControls();
|
||||||
void drawMainMenuTitle(const char *title);
|
void drawMainMenuTitle(const char *title);
|
||||||
bool executeMainMenuOperation(int op, int mouseX);
|
bool executeMainMenuOperation(int op, int mouseX, bool &hasLoadedState);
|
||||||
bool shouldHighlightLabelAndWait(int clickedControl);
|
bool shouldHighlightLabelAndWait(int clickedControl);
|
||||||
void fillSavegameLabels();
|
void fillSavegameLabels();
|
||||||
bool canWriteGame(int slotId);
|
bool canWriteGame(int slotId);
|
||||||
bool userWriteLabelRoutine(Common::KeyState &ks, bool &leftMsClicked, bool &rightMsClicked);
|
bool userWriteLabelRoutine(Common::KeyState &ks, bool &leftMsClicked, bool &rightMsClicked);
|
||||||
void saveCursorPreMenu();
|
void saveCursorPreMenu();
|
||||||
void restoreCursorPostMenu();
|
void restoreCursorPostMenu();
|
||||||
|
void saveTextSurfacePreGUI();
|
||||||
|
void restoreTextSurfacePostGUI();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
char displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4);
|
char displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue