SCUMM: Maniac V0: Implement 'simulator' for CPU lag (as the original engine occasionally ran at less than 60Hz). Fix call to 'getClosestPtOnBox', whcih was being passed X * V12_X_MULTIPLIER and Y * V12_Y_MULTIPLIER, but the box coordinates, where not
This commit is contained in:
parent
44000ba826
commit
67071b42bc
8 changed files with 102 additions and 40 deletions
|
@ -272,23 +272,23 @@ void Actor_v0::walkBoxQueueReset() {
|
|||
_walkboxHistory.clear();
|
||||
_walkboxQueueIndex = 0;
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE( _walkboxQueue ); ++i) {
|
||||
for (uint i = 0; i < ARRAYSIZE(_walkboxQueue); ++i) {
|
||||
_walkboxQueue[i] = kInvalidBox;
|
||||
}
|
||||
}
|
||||
|
||||
bool Actor_v0::walkBoxQueueAdd(int box) {
|
||||
|
||||
if (_walkboxQueueIndex == ARRAYSIZE( _walkboxQueue ))
|
||||
if (_walkboxQueueIndex == ARRAYSIZE(_walkboxQueue))
|
||||
return false;
|
||||
|
||||
_walkboxQueue[_walkboxQueueIndex++] = box ;
|
||||
_walkboxHistory.push_back( box );
|
||||
_walkboxQueue[_walkboxQueueIndex++] = box;
|
||||
_walkboxHistory.push_back(box);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Actor_v0::walkboxQueueReverse() {
|
||||
int j = ARRAYSIZE( _walkboxQueue ) - 1;
|
||||
int j = ARRAYSIZE(_walkboxQueue) - 1;
|
||||
|
||||
while (_walkboxQueue[j] == kInvalidBox && j >= 1)
|
||||
--j;
|
||||
|
@ -328,21 +328,21 @@ bool Actor_v0::walkBoxQueuePrepare() {
|
|||
// Build a series of walkboxes from our current position, to the target
|
||||
do {
|
||||
// Add the current box to the queue
|
||||
if (!walkBoxQueueAdd( BoxFound ))
|
||||
if (!walkBoxQueueAdd(BoxFound))
|
||||
return false;
|
||||
|
||||
// Loop until we find a walkbox which hasn't been tested
|
||||
while (_walkboxQueueIndex > 0) {
|
||||
|
||||
// Check if the dest box is a direct neighbour
|
||||
if ((BoxFound = _vm->getNextBox( BoxFound, _walkdata.destbox )) == kInvalidBox) {
|
||||
if ((BoxFound = _vm->getNextBox(BoxFound, _walkdata.destbox)) == kInvalidBox) {
|
||||
|
||||
// Its not, start hunting through this boxes immediate connections
|
||||
byte* boxm = _vm->getBoxConnectionBase( _walkboxQueue[_walkboxQueueIndex - 1] );
|
||||
byte* boxm = _vm->getBoxConnectionBase(_walkboxQueue[_walkboxQueueIndex - 1]);
|
||||
|
||||
// Attempt to find one, which we havn't already used
|
||||
for (; *boxm != kInvalidBox; ++boxm) {
|
||||
if (walkBoxQueueFind( *boxm ) != true)
|
||||
if (walkBoxQueueFind(*boxm) != true)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -357,7 +357,7 @@ bool Actor_v0::walkBoxQueuePrepare() {
|
|||
|
||||
_newWalkBoxEntered = true;
|
||||
|
||||
walkBoxQueueAdd( BoxFound );
|
||||
walkBoxQueueAdd(BoxFound);
|
||||
|
||||
walkboxQueueReverse();
|
||||
return true;
|
||||
|
@ -750,7 +750,7 @@ void Actor::startWalkActor(int destX, int destY, int dir) {
|
|||
_walkdata.curbox = _walkbox;
|
||||
|
||||
if (_vm->_game.version == 0) {
|
||||
((Actor_v0*)this)->walkBoxQueuePrepare();
|
||||
((Actor_v0 *)this)->walkBoxQueuePrepare();
|
||||
|
||||
} else if (_vm->_game.version <= 2) {
|
||||
_moving = (_moving & ~(MF_LAST_LEG | MF_IN_LEG)) | MF_NEW_LEG;
|
||||
|
@ -1507,9 +1507,9 @@ void Actor::putActor(int dstX, int dstY, int newRoom) {
|
|||
|
||||
if (_vm->_game.version == 0) {
|
||||
|
||||
((Actor_v0*)this)->_newWalkBoxEntered = false;
|
||||
((Actor_v0*)this)->_CurrentWalkTo = _pos;
|
||||
((Actor_v0*)this)->_NewWalkTo = _pos;
|
||||
((Actor_v0 *)this)->_newWalkBoxEntered = false;
|
||||
((Actor_v0 *)this)->_CurrentWalkTo = _pos;
|
||||
((Actor_v0 *)this)->_NewWalkTo = _pos;
|
||||
|
||||
// V0 always sets the actor to face the camera upon entering a room
|
||||
setDirection(oldDirToNewDir(2));
|
||||
|
@ -2512,7 +2512,7 @@ void Actor_v0::limbFrameCheck(int limb) {
|
|||
void Actor_v0::animateCostume() {
|
||||
speakCheck();
|
||||
|
||||
byte count = _vm->_costumeLoader->increaseAnims( this );
|
||||
byte count = _vm->_costumeLoader->increaseAnims(this);
|
||||
|
||||
if (count) {
|
||||
_vm->_V0Delay._actorLimbRedrawDrawCount += count;
|
||||
|
@ -3430,7 +3430,7 @@ void Actor_v0::actorSetWalkTo() {
|
|||
|
||||
_newWalkBoxEntered = false;
|
||||
|
||||
int nextBox = ((ScummEngine_v0*)_vm)->walkboxFindTarget(this, _walkdata.destbox, _walkdata.dest);
|
||||
int nextBox = ((ScummEngine_v0 *)_vm)->walkboxFindTarget(this, _walkdata.destbox, _walkdata.dest);
|
||||
if (nextBox != kInvalidBox) {
|
||||
_walkdata.curbox = nextBox;
|
||||
}
|
||||
|
@ -3471,22 +3471,27 @@ void Actor_v0::saveLoadWithSerializer(Serializer *ser) {
|
|||
|
||||
ser->saveLoadEntries(this, actorEntries);
|
||||
|
||||
// When loading, we need to ensure the limbs are restarted
|
||||
if (ser->isLoading()) {
|
||||
if (_costCommand != 0xFF ) {
|
||||
|
||||
// valid costume command?
|
||||
if (_costCommand != 0xFF) {
|
||||
|
||||
// Do we have a walkbox queue?
|
||||
if (_walkboxQueueIndex < 1) {
|
||||
|
||||
_costCommand = 0xFF;
|
||||
setDirection( _facing );
|
||||
|
||||
// Standing Still
|
||||
setDirection(_facing);
|
||||
speakCheck();
|
||||
}
|
||||
else {
|
||||
//_costCommandNew = _costCommand;
|
||||
//_costCommand = 0xFF;
|
||||
//animateActor( _costCommandNew );
|
||||
|
||||
} else {
|
||||
// Force limb direction update
|
||||
_facing = 0;
|
||||
directionUpdate();
|
||||
animateActor( newDirToOldDir( _facing ) );
|
||||
|
||||
// Begin walking
|
||||
animateActor(newDirToOldDir(_facing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3633,7 +3638,7 @@ void Actor::saveLoadWithSerializer(Serializer *ser) {
|
|||
_walkdata.point3.y >>= V12_Y_SHIFT;
|
||||
}
|
||||
|
||||
setDirection( _facing );
|
||||
setDirection(_facing);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -387,8 +387,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
bool walkBoxQueueAdd( int box );
|
||||
bool walkBoxQueueFind( int box );
|
||||
bool walkBoxQueueAdd(int box);
|
||||
bool walkBoxQueueFind(int box);
|
||||
void walkboxQueueReverse();
|
||||
|
||||
public:
|
||||
|
|
|
@ -692,14 +692,14 @@ byte *ScummEngine::getBoxMatrixBaseAddr() {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
byte *ScummEngine::getBoxConnectionBase( int box ) {
|
||||
byte *ScummEngine::getBoxConnectionBase(int box) {
|
||||
byte *boxm = getBoxMatrixBaseAddr();
|
||||
|
||||
int boxIndex = 0;
|
||||
|
||||
for (; boxIndex != box; ++boxIndex) {
|
||||
|
||||
while ( *boxm != 0xFF) {
|
||||
while (*boxm != 0xFF) {
|
||||
++boxm;
|
||||
}
|
||||
|
||||
|
@ -736,7 +736,7 @@ int ScummEngine::getNextBox(byte from, byte to) {
|
|||
|
||||
if (_game.version == 0) {
|
||||
|
||||
boxm = getBoxConnectionBase( from );
|
||||
boxm = getBoxConnectionBase(from);
|
||||
|
||||
for (; *boxm != 0xFF; ++boxm) {
|
||||
if (*boxm == to)
|
||||
|
@ -1173,7 +1173,7 @@ bool ScummEngine::areBoxesNeighbors(int box1nr, int box2nr) {
|
|||
}
|
||||
|
||||
byte ScummEngine_v0::walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest) {
|
||||
Actor_v0 *Actor = (Actor_v0*)a;
|
||||
Actor_v0 *Actor = (Actor_v0 *)a;
|
||||
byte nextBox = kOldInvalidBox;
|
||||
|
||||
// Do we have a walkbox queue to process
|
||||
|
@ -1195,7 +1195,7 @@ byte ScummEngine_v0::walkboxFindTarget(Actor *a, int destbox, Common::Point walk
|
|||
// Next box reached
|
||||
if (nextBox != Actor::kInvalidBox && nextBox != a->_walkbox) {
|
||||
|
||||
getClosestPtOnBox(getBoxCoordinates(nextBox), a->getPos().x, a->getPos().y, Actor->_NewWalkTo.x, Actor->_NewWalkTo.y);
|
||||
getClosestPtOnBox(getBoxCoordinates(nextBox), a->getRealPos().x, a->getRealPos().y, Actor->_NewWalkTo.x, Actor->_NewWalkTo.y);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
|
@ -3797,7 +3797,7 @@ void ScummEngine::fadeOut(int effect) {
|
|||
|
||||
// V0 wipes the text area before fading out
|
||||
if (_game.version == 0) {
|
||||
updateDirtyScreen( kTextVirtScreen );
|
||||
updateDirtyScreen(kTextVirtScreen);
|
||||
}
|
||||
|
||||
// TheDig can disable fadeIn(), and may call fadeOut() several times
|
||||
|
|
|
@ -1126,6 +1126,7 @@ void ScummEngine_v80he::clearDrawQueues() {
|
|||
*/
|
||||
void ScummEngine::markObjectRectAsDirty(int obj) {
|
||||
int i, strip;
|
||||
++_V0Delay._objectRedrawCount;
|
||||
|
||||
for (i = 1; i < _numLocalObjects; i++) {
|
||||
if (_objs[i].obj_nr == (uint16)obj) {
|
||||
|
@ -1133,6 +1134,7 @@ void ScummEngine::markObjectRectAsDirty(int obj) {
|
|||
const int minStrip = MAX(_screenStartStrip, _objs[i].x_pos / 8);
|
||||
const int maxStrip = MIN(_screenEndStrip+1, _objs[i].x_pos / 8 + _objs[i].width / 8);
|
||||
for (strip = minStrip; strip < maxStrip; strip++) {
|
||||
++_V0Delay._objectStripRedrawCount;
|
||||
setGfxUsageBit(strip, USAGE_BIT_DIRTY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -733,10 +733,39 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
|
|||
VAR_IS_SOUND_RUNNING = 0xFF;
|
||||
VAR_ACTIVE_VERB = 0xFF;
|
||||
|
||||
DelayReset();
|
||||
|
||||
if (strcmp(dr.fp.pattern, "maniacdemo.d64") == 0 )
|
||||
_game.features |= GF_DEMO;
|
||||
}
|
||||
|
||||
void ScummEngine_v0::DelayReset() {
|
||||
_V0Delay._screenScroll = false;
|
||||
_V0Delay._objectRedrawCount = 0;
|
||||
_V0Delay._objectStripRedrawCount = 0;
|
||||
_V0Delay._actorRedrawCount = 0;
|
||||
_V0Delay._actorLimbRedrawDrawCount = 0;
|
||||
}
|
||||
|
||||
int ScummEngine_v0::DelayCalculateDelta() {
|
||||
float Time = 0;
|
||||
|
||||
// These values are made up, based on trial/error with visual inspection against WinVice
|
||||
// If anyone feels inclined, the routines in the original engine could be profiled
|
||||
// and these values changed accordindly.
|
||||
Time += _V0Delay._objectRedrawCount * 7;
|
||||
Time += _V0Delay._objectStripRedrawCount * 0.6;
|
||||
Time += _V0Delay._actorRedrawCount * 2.0;
|
||||
Time += _V0Delay._actorLimbRedrawDrawCount * 0.3;
|
||||
|
||||
if (_V0Delay._screenScroll)
|
||||
Time += 3.6f;
|
||||
|
||||
DelayReset();
|
||||
|
||||
return roundf(Time);
|
||||
}
|
||||
|
||||
ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)
|
||||
: ScummEngine(syst, dr) {
|
||||
_blastObjectQueuePos = 0;
|
||||
|
@ -2079,13 +2108,24 @@ Common::Error ScummEngine::go() {
|
|||
if (delta < 1) // Ensure we don't get into an endless loop
|
||||
delta = 1; // by not decreasing sleepers.
|
||||
|
||||
// WORKAROUND: walking speed in the original v0/v1 interpreter
|
||||
// WORKAROUND: Unfortunately the MOS 6502 wasn't always fast enough for MM
|
||||
// a number of situations can lead to the engine running at less than 60 ticks per second, without this drop
|
||||
// - A single kid is able to escape via the Dungeon Door (after pushing the brick)
|
||||
// - During the intro, calls to 'SetState08' are made for the lights on the mansion, with a 'breakHere'
|
||||
// in between each, the reduction in ticks then occurs while affected stripes are being redrawn.
|
||||
// The music buildup is then out of sync with the text "A Lucasfilm Games Production".
|
||||
// Each call to 'breakHere' has been replaced with calls to 'Delay' in the V1/V2 versions of the game
|
||||
if (_game.version == 0) {
|
||||
delta += ((ScummEngine_v0 *)this)->DelayCalculateDelta();
|
||||
}
|
||||
|
||||
// WORKAROUND: walking speed in the original v1 interpreter
|
||||
// is sometimes slower (e.g. during scrolling) than in ScummVM.
|
||||
// This is important for the door-closing action in the dungeon,
|
||||
// otherwise (delta < 6) a single kid is able to escape.
|
||||
if ((_game.version == 0 && isScriptRunning(132)) ||
|
||||
(_game.version == 1 && isScriptRunning(137)))
|
||||
if (_game.version == 1 && isScriptRunning(137)) {
|
||||
delta = 6;
|
||||
}
|
||||
|
||||
// Wait...
|
||||
waitForTimer(delta * 1000 / 60 - diff);
|
||||
|
@ -2452,6 +2492,8 @@ void ScummEngine_v8::scummLoop_handleSaveLoad() {
|
|||
|
||||
void ScummEngine::scummLoop_handleDrawing() {
|
||||
if (camera._cur != camera._last || _bgNeedsRedraw || _fullRedraw) {
|
||||
_V0Delay._screenScroll = true;
|
||||
|
||||
redrawBGAreas();
|
||||
}
|
||||
|
||||
|
|
|
@ -298,7 +298,14 @@ struct StringTab : StringSlot {
|
|||
}
|
||||
};
|
||||
|
||||
struct ScummEngine_v0_Delays {
|
||||
bool _screenScroll;
|
||||
uint _objectRedrawCount;
|
||||
uint _objectStripRedrawCount;
|
||||
uint _actorRedrawCount;
|
||||
uint _actorLimbRedrawDrawCount;
|
||||
|
||||
};
|
||||
|
||||
enum WhereIsObject {
|
||||
WIO_NOT_FOUND = -1,
|
||||
|
@ -1097,6 +1104,8 @@ public:
|
|||
// Indy4 Amiga specific
|
||||
byte *_verbPalette;
|
||||
|
||||
ScummEngine_v0_Delays _V0Delay;
|
||||
|
||||
protected:
|
||||
int _shadowPaletteSize;
|
||||
byte _currentPalette[3 * 256];
|
||||
|
@ -1131,7 +1140,7 @@ public:
|
|||
|
||||
byte getNumBoxes();
|
||||
byte *getBoxMatrixBaseAddr();
|
||||
byte *getBoxConnectionBase( int box );
|
||||
byte *getBoxConnectionBase(int box);
|
||||
|
||||
int getNextBox(byte from, byte to);
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ public:
|
|||
|
||||
byte walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest);
|
||||
|
||||
/* Delay calculation */
|
||||
void DelayReset();
|
||||
int DelayCalculateDelta();
|
||||
|
||||
protected:
|
||||
virtual void resetRoomObject(ObjectData *od, const byte *room, const byte *searchptr = NULL);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue