mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-05 01:38:36 +00:00
AGI: Add heuristic to detect delay loops within scripts
And in that case poll events, delay for a few milliseconds and update screen. This somewhat worked before the graphics rewrite because of a timer hack. This one tries to detect actual inner loops. Happens in at least Police Quest 1 when playing poker.
This commit is contained in:
parent
dcbcbb2120
commit
7b75936f56
@ -401,6 +401,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
|
||||
|
||||
setupOpcodes();
|
||||
_game._curLogic = NULL;
|
||||
_instructionCounter = 0;
|
||||
resetGetVarSecondsHeuristic();
|
||||
|
||||
_lastSaveTime = 0;
|
||||
|
||||
|
@ -862,6 +862,12 @@ public:
|
||||
int testIfCode(int);
|
||||
void executeAgiCommand(uint8, uint8 *);
|
||||
|
||||
private:
|
||||
void resetGetVarSecondsHeuristic();
|
||||
uint32 _instructionCounter; /**< counts every instruction, that got executed, can wrap around */
|
||||
uint32 _getVarSecondsHeuristicLastInstructionCounter; /**< last time VM_VAR_SECONDS were read */
|
||||
uint16 _getVarSecondsHeuristicCounter; /**< how many times heuristic was triggered */
|
||||
|
||||
public:
|
||||
// Some submethods of testIfCode
|
||||
void skipInstruction(byte op);
|
||||
@ -955,6 +961,8 @@ private:
|
||||
public:
|
||||
void redrawScreen();
|
||||
|
||||
void getVarSecondsTrigger();
|
||||
|
||||
void inGameTimerReset(uint32 newPlayTime = 0);
|
||||
void inGameTimerResetPassedCycles();
|
||||
void inGameTimerPause();
|
||||
|
@ -142,6 +142,9 @@ void AgiEngine::interpretCycle() {
|
||||
oldScore = getVar(VM_VAR_SCORE);
|
||||
oldSound = getFlag(VM_FLAG_SOUND_ON);
|
||||
|
||||
// Reset script heuristic here
|
||||
resetGetVarSecondsHeuristic();
|
||||
|
||||
_game.exitAllLogics = false;
|
||||
while (runLogic(0) == 0 && !(shouldQuit() || _restartGame)) {
|
||||
setVar(VM_VAR_WORD_NOT_FOUND, 0);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "agi/agi.h"
|
||||
#include "agi/graphics.h"
|
||||
|
||||
namespace Agi {
|
||||
|
||||
@ -61,6 +62,8 @@ void AgiEngine::setVar(int16 varNr, byte newValue) {
|
||||
byte AgiEngine::getVar(int16 varNr) {
|
||||
switch (varNr) {
|
||||
case VM_VAR_SECONDS:
|
||||
getVarSecondsTrigger();
|
||||
// is supposed to fall through
|
||||
case VM_VAR_MINUTES:
|
||||
case VM_VAR_HOURS:
|
||||
case VM_VAR_DAYS:
|
||||
@ -135,6 +138,35 @@ void AgiEngine::setVolumeViaSystemSetting() {
|
||||
_game.vars[VM_VAR_VOLUME] = internalVolume;
|
||||
}
|
||||
|
||||
void AgiEngine::resetGetVarSecondsHeuristic() {
|
||||
_getVarSecondsHeuristicLastInstructionCounter = 0;
|
||||
_getVarSecondsHeuristicCounter = 0;
|
||||
}
|
||||
|
||||
// Called, when the scripts read VM_VAR_SECONDS
|
||||
void AgiEngine::getVarSecondsTrigger() {
|
||||
uint32 counterDifference = _instructionCounter - _getVarSecondsHeuristicLastInstructionCounter;
|
||||
|
||||
if (counterDifference <= 3) {
|
||||
// Seconds were read within 3 instructions
|
||||
_getVarSecondsHeuristicCounter++;
|
||||
if (_getVarSecondsHeuristicCounter > 20) {
|
||||
// More than 20 times in a row? This really seems to be an inner loop waiting for seconds to change
|
||||
// This happens in at least:
|
||||
// Police Quest 1 - Poker game
|
||||
|
||||
// Wait a few milliseconds, get events and update screen
|
||||
// We MUST NOT process AGI events in here
|
||||
wait(10);
|
||||
processScummVMEvents();
|
||||
_gfx->updateScreen();
|
||||
|
||||
_getVarSecondsHeuristicCounter = 0;
|
||||
}
|
||||
}
|
||||
_getVarSecondsHeuristicLastInstructionCounter = _instructionCounter;
|
||||
}
|
||||
|
||||
// In-Game timer, used for timer VM Variables
|
||||
void AgiEngine::inGameTimerReset(uint32 newPlayTime) {
|
||||
_lastUsedPlayTimeInCycles = newPlayTime / 50;
|
||||
|
@ -2327,6 +2327,9 @@ int AgiEngine::runLogic(int16 logicNr) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Just a counter for every instruction, that got executed
|
||||
_instructionCounter++;
|
||||
|
||||
_game.execStack.back().curIP = state->_curLogic->cIP;
|
||||
|
||||
char st[101];
|
||||
|
Loading…
x
Reference in New Issue
Block a user