aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorMartin Kiewitz2016-02-28 15:50:25 +0100
committerMartin Kiewitz2016-02-28 15:50:25 +0100
commite6466b20fa510187aaa277756a86ebc71ebf96b8 (patch)
treef9bf90e15c1ed585e821c0c18e90592781c84c4f /engines
parentaded46f08b476ee1caccc070b8495cafe7094b47 (diff)
downloadscummvm-rg350-e6466b20fa510187aaa277756a86ebc71ebf96b8.tar.gz
scummvm-rg350-e6466b20fa510187aaa277756a86ebc71ebf96b8.tar.bz2
scummvm-rg350-e6466b20fa510187aaa277756a86ebc71ebf96b8.zip
AGI: Add optional "pause, when entering commands" feature
Shows a prompt window and pauses the game (just like original AGI did, but original AGI only did it in Hercules rendering mode).
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/detection.cpp10
-rw-r--r--engines/agi/detection_tables.h7
-rw-r--r--engines/agi/systemui.cpp43
-rw-r--r--engines/agi/systemui.h4
-rw-r--r--engines/agi/text.cpp96
-rw-r--r--engines/agi/text.h4
-rw-r--r--engines/agi/words.cpp2
-rw-r--r--engines/agi/words.h2
8 files changed, 147 insertions, 21 deletions
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 308489ad0b..7127584ba0 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -181,6 +181,16 @@ static const ADExtraGuiOptionsMap optionsList[] = {
}
},
+ {
+ GAMEOPTION_COMMAND_PROMPT_WINDOW,
+ {
+ _s("Pause, when entering commands"),
+ _s("Shows a command prompt window and pauses the game (like in SCI) instead of a real-time prompt."),
+ "commandpromptwindow",
+ false
+ }
+ },
+
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 87da0c2c01..0938e9d4d6 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -26,11 +26,12 @@ namespace Agi {
#define GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE GUIO_GAMEOPTIONS2
#define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3
#define GAMEOPTION_USE_HERCULES_FONT GUIO_GAMEOPTIONS4
+#define GAMEOPTION_COMMAND_PROMPT_WINDOW GUIO_GAMEOPTIONS5
// TODO: properly implement GAMEOPTIONs
-#define GAMEOPTIONS_DEFAULT GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE,GAMEOPTION_USE_HERCULES_FONT)
-#define GAMEOPTIONS_AMIGA GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,GAMEOPTION_USE_HERCULES_FONT)
-#define GAMEOPTIONS_FANMADE_MOUSE GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_USE_HERCULES_FONT)
+#define GAMEOPTIONS_DEFAULT GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW)
+#define GAMEOPTIONS_AMIGA GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW)
+#define GAMEOPTIONS_FANMADE_MOUSE GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW)
#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp,guioptions) { \
{ \
diff --git a/engines/agi/systemui.cpp b/engines/agi/systemui.cpp
index 7aa26131c9..aeb1ded4a2 100644
--- a/engines/agi/systemui.cpp
+++ b/engines/agi/systemui.cpp
@@ -44,6 +44,8 @@ SystemUI::SystemUI(AgiEngine *vm, GfxMgr *gfx, TextMgr *text) {
_textStatusSoundOn = "Sound:on";
_textStatusSoundOff = "Sound:off";
+ _textEnterCommand = "Enter input\n\n";
+
_textPause = " Game paused.\nPress Enter to continue.";
_textPauseButton = nullptr;
@@ -214,6 +216,47 @@ const char *SystemUI::getInventoryTextReturnToGame() {
return _textInventoryReturnToGame;
}
+bool SystemUI::askForCommand(Common::String &commandText) {
+ // Let user enter the command (this was originally only available for Hercules rendering, we allow it everywhere)
+ bool previousEditState = _text->inputGetEditStatus();
+ byte previousEditCursor = _text->inputGetCursorChar();
+
+ _text->drawMessageBox(_textEnterCommand, 0, 36, true);
+
+ _text->inputEditOn();
+
+ _text->charPos_Push();
+ _text->charAttrib_Push();
+
+ _text->charPos_SetInsideWindow(2, 0);
+ _text->charAttrib_Set(15, 0);
+ _text->clearBlockInsideWindow(2, 0, 36, 0); // input line is supposed to be black
+ _text->inputSetCursorChar('_');
+
+ _text->stringSet(commandText.c_str()); // Set current command text (may be a command recall)
+
+ _vm->cycleInnerLoopActive(CYCLE_INNERLOOP_GETSTRING);
+ _text->stringEdit(35); // only allow up to 35 characters
+
+ _text->charAttrib_Pop();
+ _text->charPos_Pop();
+ _text->inputSetCursorChar(previousEditCursor);
+ if (!previousEditState) {
+ _text->inputEditOff();
+ }
+
+ _text->closeWindow();
+
+ if (!_text->stringWasEntered()) {
+ // User cancelled? exit now
+ return false;
+ }
+
+ commandText.clear();
+ commandText += (char *)_text->_inputString;
+ return true;
+}
+
int16 SystemUI::figureOutAutomaticSaveGameSlot(const char *automaticSaveDescription) {
int16 matchedGameSlotId = -1;
int16 freshGameSlotId = -1;
diff --git a/engines/agi/systemui.h b/engines/agi/systemui.h
index ffb1238ebe..283de8794c 100644
--- a/engines/agi/systemui.h
+++ b/engines/agi/systemui.h
@@ -77,6 +77,8 @@ public:
const char *getInventoryTextSelectItems();
const char *getInventoryTextReturnToGame();
+ bool askForCommand(Common::String &commandText);
+
int16 figureOutAutomaticSaveGameSlot(const char *automaticSaveDescription);
int16 figureOutAutomaticRestoreGameSlot(const char *automaticSaveDescription);
@@ -130,6 +132,8 @@ private:
const char *_textStatusSoundOn;
const char *_textStatusSoundOff;
+ const char *_textEnterCommand;
+
const char *_textPause;
const char *_textPauseButton;
const char *_textRestart;
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index 18254d88f8..0cacce2421 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/config-manager.h"
#include "agi/agi.h"
#include "agi/sprite.h" // for commit_both()
#include "agi/graphics.h"
@@ -74,6 +75,12 @@ TextMgr::TextMgr(AgiEngine *vm, Words *words, GfxMgr *gfx) {
configureScreen(2);
_messageBoxCancelled = false;
+
+ _optionCommandPromptWindow = false;
+
+ if (ConfMan.getBool("commandpromptwindow")) {
+ _optionCommandPromptWindow = true;
+ }
}
TextMgr::~TextMgr() {
@@ -671,6 +678,30 @@ void TextMgr::promptKeyPress(uint16 newKey) {
int16 maxChars = 0;
int16 scriptsInputLen = _vm->getVar(VM_VAR_MAX_INPUT_CHARACTERS);
+ bool acceptableInput = false;
+
+ // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.)
+ // In text-mode this sort of worked at least with the DOS interpreter
+ // but as soon as invalid characters were used in graphics mode they weren't properly shown
+ switch (_vm->getLanguage()) {
+ case Common::RU_RUS:
+ if (newKey >= 0x20)
+ acceptableInput = true;
+ break;
+ default:
+ if ((newKey >= 0x20) && (newKey <= 0x7f))
+ acceptableInput = true;
+ break;
+ }
+
+ if (_optionCommandPromptWindow) {
+ // Forward to command prompt window, using last command
+ if (acceptableInput) {
+ promptCommandWindow(false, newKey);
+ }
+ return;
+ }
+
if (_messageState.dialogue_Open) {
maxChars = TEXT_STRING_MAX_SIZE - 4;
} else {
@@ -715,22 +746,6 @@ void TextMgr::promptKeyPress(uint16 newKey) {
}
default:
if (maxChars > _promptCursorPos) {
- bool acceptableInput = false;
-
- // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.)
- // In text-mode this sort of worked at least with the DOS interpreter
- // but as soon as invalid characters were used in graphics mode they weren't properly shown
- switch (_vm->getLanguage()) {
- case Common::RU_RUS:
- if (newKey >= 0x20)
- acceptableInput = true;
- break;
- default:
- if ((newKey >= 0x20) && (newKey <= 0x7f))
- acceptableInput = true;
- break;
- }
-
if (acceptableInput) {
_prompt[_promptCursorPos] = newKey;
_promptCursorPos++;
@@ -747,6 +762,11 @@ void TextMgr::promptKeyPress(uint16 newKey) {
}
void TextMgr::promptCancelLine() {
+ if (_optionCommandPromptWindow) {
+ // Abort, in case command prompt window is active
+ return;
+ }
+
while (_promptCursorPos) {
promptKeyPress(0x08); // Backspace until prompt is empty
}
@@ -755,6 +775,12 @@ void TextMgr::promptCancelLine() {
void TextMgr::promptEchoLine() {
int16 previousLen = strlen((char *)_promptPrevious);
+ if (_optionCommandPromptWindow) {
+ // Forward to command prompt window, using last command
+ promptCommandWindow(true, 0);
+ return;
+ }
+
if (_promptCursorPos < previousLen) {
inputEditOn();
@@ -771,6 +797,11 @@ void TextMgr::promptRedraw() {
char *textPtr = nullptr;
if (_promptEnabled) {
+ if (_optionCommandPromptWindow) {
+ // Abort, in case command prompt window is active
+ return;
+ }
+
inputEditOn();
clearLine(_promptRow, _textAttrib.background);
charPos_Set(_promptRow, 0);
@@ -788,6 +819,10 @@ void TextMgr::promptRedraw() {
// for AGI1
void TextMgr::promptClear() {
+ if (_optionCommandPromptWindow) {
+ // Abort, in case command prompt window is active
+ return;
+ }
clearLine(_promptRow, _textAttrib.background);
}
@@ -797,6 +832,35 @@ void TextMgr::promptRememberForAutoComplete(bool entered) {
#endif
}
+void TextMgr::promptCommandWindow(bool recallLastCommand, uint16 newKey) {
+ Common::String commandText;
+
+ if (recallLastCommand) {
+ commandText += Common::String((char *)_promptPrevious);
+ }
+ if (newKey) {
+ if (newKey != ' ') {
+ // Only add char, when it's not a space.
+ // Original AGI did not filter space, but it makes no sense to start with a space.
+ // Space would get filtered anyway during dictionary parsing.
+ commandText += newKey;
+ }
+ }
+
+ if (_systemUI->askForCommand(commandText)) {
+ if (commandText.size()) {
+ // Something actually was entered?
+ strncpy((char *)&_prompt, commandText.c_str(), sizeof(_prompt));
+ promptRememberForAutoComplete(true);
+ memcpy(&_promptPrevious, &_prompt, sizeof(_prompt));
+ // parse text
+ _vm->_words->parseUsingDictionary((char *)&_prompt);
+
+ _prompt[0] = 0;
+ }
+ }
+}
+
bool TextMgr::stringWasEntered() {
return _inputStringEntered;
}
diff --git a/engines/agi/text.h b/engines/agi/text.h
index 7e9228e30a..f0aeab7762 100644
--- a/engines/agi/text.h
+++ b/engines/agi/text.h
@@ -163,6 +163,8 @@ public:
bool _inputEditEnabled;
byte _inputCursorChar;
+ bool _optionCommandPromptWindow;
+
bool _promptEnabled;
int16 _promptRow;
int16 _promptCursorPos;
@@ -189,6 +191,8 @@ public:
void promptClear(); // for AGI1
void promptRememberForAutoComplete(bool entered = false); // for auto-completion
+ void promptCommandWindow(bool recallLastCommand, uint16 newKey);
+
int16 _inputStringRow;
int16 _inputStringColumn;
bool _inputStringEntered;
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 32fa4cbff4..7072f003c2 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -293,7 +293,7 @@ int16 Words::findWordInDictionary(const Common::String &userInputLowcased, uint1
return wordId;
}
-void Words::parseUsingDictionary(char *rawUserInput) {
+void Words::parseUsingDictionary(const char *rawUserInput) {
Common::String userInput;
Common::String userInputLowcased;
const char *userInputPtr = nullptr;
diff --git a/engines/agi/words.h b/engines/agi/words.h
index c7bf4829c3..96dafae275 100644
--- a/engines/agi/words.h
+++ b/engines/agi/words.h
@@ -57,7 +57,7 @@ public:
void unloadDictionary();
void clearEgoWords();
- void parseUsingDictionary(char *rawUserInput);
+ void parseUsingDictionary(const char *rawUserInput);
private:
void cleanUpInput(const char *userInput, Common::String &cleanInput);