aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Hesse2011-01-17 13:37:14 +0000
committerSven Hesse2011-01-17 13:37:14 +0000
commitdb13af5337e06472c82684cbf362598598d158d3 (patch)
treecfc6fec7fe251bb8591c321127aeca8f4da9f249
parent6c6d85908fd475eb6c32031f3fdfa16bd5bae3d9 (diff)
downloadscummvm-rg350-db13af5337e06472c82684cbf362598598d158d3.tar.gz
scummvm-rg350-db13af5337e06472c82684cbf362598598d158d3.tar.bz2
scummvm-rg350-db13af5337e06472c82684cbf362598598d158d3.zip
GOB: Make the variable stack endianness-independent
Since Urban Runner casts int16s to uint32 before pushing them onto the stack and after popping assumes it's little endian, we have explicitely preserve the variable space endianness while pushing/popping. svn-id: r55277
-rw-r--r--engines/gob/inter.cpp5
-rw-r--r--engines/gob/inter.h3
-rw-r--r--engines/gob/inter_v2.cpp32
-rw-r--r--engines/gob/variables.cpp61
-rw-r--r--engines/gob/variables.h17
5 files changed, 88 insertions, 30 deletions
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 8db42b217c..06bf9a216f 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -39,7 +39,7 @@
namespace Gob {
-Inter::Inter(GobEngine *vm) : _vm(vm) {
+Inter::Inter(GobEngine *vm) : _vm(vm), _varStack(600) {
_terminate = 0;
_break = false;
@@ -55,9 +55,6 @@ Inter::Inter(GobEngine *vm) : _vm(vm) {
_soundEndTimeKey = 0;
_soundStopVal = 0;
- memset(_varStack, 0, 300);
- _varStackPos = 0;
-
_noBusyWait = false;
_variables = 0;
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 4554a0783b..c3567ce7ce 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -129,8 +129,7 @@ protected:
int16 _animPalHighIndex[8];
int16 _animPalDir[8];
- byte _varStack[300];
- int16 _varStackPos;
+ VariableStack _varStack;
// The busy-wait detection in o1_keyFunc breaks fast scrolling in Ween
bool _noBusyWait;
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 1707e614ce..3e8a4903ca 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -609,21 +609,15 @@ void Inter_v2::o2_switchTotSub() {
}
void Inter_v2::o2_pushVars() {
- byte count;
- int16 varOff;
-
- count = _vm->_game->_script->readByte();
- for (int i = 0; i < count; i++, _varStackPos++) {
+ uint8 count = _vm->_game->_script->readByte();
+ for (int i = 0; i < count; i++) {
if ((_vm->_game->_script->peekByte() == 25) ||
(_vm->_game->_script->peekByte() == 28)) {
- varOff = _vm->_game->_script->readVarIndex();
+ int16 varOff = _vm->_game->_script->readVarIndex();
_vm->_game->_script->skip(1);
- _variables->copyTo(varOff, _varStack + _varStackPos, _vm->_global->_inter_animDataSize * 4);
-
- _varStackPos += _vm->_global->_inter_animDataSize * 4;
- _varStack[_varStackPos] = _vm->_global->_inter_animDataSize * 4;
+ _varStack.pushData(*_variables, varOff, _vm->_global->_inter_animDataSize * 4);
} else {
int16 value;
@@ -631,27 +625,17 @@ void Inter_v2::o2_pushVars() {
if (_vm->_game->_script->evalExpr(&value) != 20)
value = 0;
- uint32 value32 = ((uint16) value);
-
- memcpy(_varStack + _varStackPos, &value32, 4);
- _varStackPos += 4;
- _varStack[_varStackPos] = 4;
+ _varStack.pushInt((uint16)value);
}
}
}
void Inter_v2::o2_popVars() {
- byte count;
- int16 varOff;
- int16 size;
-
- count = _vm->_game->_script->readByte();
+ uint8 count = _vm->_game->_script->readByte();
for (int i = 0; i < count; i++) {
- varOff = _vm->_game->_script->readVarIndex();
- size = _varStack[--_varStackPos];
+ int16 varOff = _vm->_game->_script->readVarIndex();
- _varStackPos -= size;
- _variables->copyFrom(varOff, _varStack + _varStackPos, size);
+ _varStack.pop(*_variables, varOff);
}
}
diff --git a/engines/gob/variables.cpp b/engines/gob/variables.cpp
index 4f6bad52f0..7f7ddb023d 100644
--- a/engines/gob/variables.cpp
+++ b/engines/gob/variables.cpp
@@ -286,4 +286,65 @@ VariableReference &VariableReference::operator*=(uint32 value) {
return (*this = (*this * value));
}
+
+VariableStack::VariableStack(uint32 size) : _size(size), _position(0) {
+ _stack = new byte[_size];
+
+ memset(_stack, 0, _size);
+}
+
+VariableStack::~VariableStack() {
+ delete[] _stack;
+}
+
+void VariableStack::pushData(const Variables &vars, uint32 offset, uint32 size) {
+ // Sanity checks
+ assert(size < 256);
+ assert((_position + size) < _size);
+
+ vars.copyTo(offset, _stack + _position, size);
+
+ _position += size;
+ _stack[_position++] = size;
+ _stack[_position++] = 0;
+}
+
+void VariableStack::pushInt(uint32 value) {
+ // Sanity check
+ assert((_position + 4) < _size);
+
+ memcpy(_stack + _position, &value, 4);
+
+ _position += 4;
+ _stack[_position++] = 4;
+ _stack[_position++] = 1;
+}
+
+void VariableStack::pop(Variables &vars, uint32 offset) {
+ // Sanity check
+ assert(_position >= 2);
+
+ bool isInt = _stack[--_position] == 1;
+ uint32 size = _stack[--_position];
+
+ // Sanity check
+ assert(_position >= size);
+
+ _position -= size;
+
+ if (isInt) {
+ // If it's an int, explicitely call the int variable writing method,
+ // to make sure the variable space endianness is preserved.
+
+ assert(size == 4);
+
+ uint32 value;
+ memcpy(&value, _stack + _position, 4);
+
+ vars.writeOff32(offset, value);
+ } else
+ // Otherwise, use do a raw copy
+ vars.copyFrom(offset, _stack + _position, size);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/variables.h b/engines/gob/variables.h
index c3724bc118..d092a8bc4c 100644
--- a/engines/gob/variables.h
+++ b/engines/gob/variables.h
@@ -148,6 +148,23 @@ private:
Variables::Type _type;
};
+class VariableStack {
+public:
+ VariableStack(uint32 size);
+ ~VariableStack();
+
+ void pushData(const Variables &vars, uint32 offset, uint32 size);
+ void pushInt(uint32 value);
+
+ void pop(Variables &vars, uint32 offset);
+
+private:
+ byte *_stack;
+
+ uint32 _size;
+ uint32 _position;
+};
+
} // End of namespace Gob
#endif // GOB_VARIABLES_H