diff options
-rw-r--r-- | engines/scumm/he/logic_he.cpp | 154 | ||||
-rw-r--r-- | engines/scumm/he/logic_he.h | 32 |
2 files changed, 151 insertions, 35 deletions
diff --git a/engines/scumm/he/logic_he.cpp b/engines/scumm/he/logic_he.cpp index 33647634d3..70931b19b6 100644 --- a/engines/scumm/he/logic_he.cpp +++ b/engines/scumm/he/logic_he.cpp @@ -823,12 +823,18 @@ int LogicHEsoccer::versionID() { } LogicHEsoccer::LogicHEsoccer(ScummEngine_v90he *vm) : LogicHE(vm) { - _userData = (byte *)calloc(6921, 1); // Allocate user data - _userDataD = (double *)_userData; + _userDataD = (double *)calloc(1732, sizeof(double)); + _intArray1 = 0; + _intArray2 = 0; + _intArraysAllocated = false; + _array1013 = 0; + _array1013Allocated = false; } LogicHEsoccer::~LogicHEsoccer() { - free(_userData); + free(_userDataD); + op_1020(); // clear int arrays + delete[] _array1013; } int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) { @@ -864,10 +870,18 @@ int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) { res = op_1013(args[0], args[1], args[2]); break; + case 1019: + res = op_1019(args); + break; + case 1020: res = op_1020(); break; + case 1021: + res = op_1021(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + break; + case 8221968: // Someone had a fun and used his birthday as opcode number res = getFromArray(args[0], args[1], args[2]); @@ -882,7 +896,7 @@ int32 LogicHEsoccer::dispatch(int op, int numArgs, int32 *args) { } void LogicHEsoccer::beforeBootScript() { - if (_userData[6869]) + if (_intArraysAllocated) op_1020(); _userDataD[530] = 0; @@ -890,7 +904,7 @@ void LogicHEsoccer::beforeBootScript() { void LogicHEsoccer::initOnce() { // The original sets some paths here that we don't need to worry about - _userData[6881] = 0; + _array1013Allocated = false; _userDataD[530] = 0; } @@ -968,11 +982,11 @@ int LogicHEsoccer::op_1006(int32 a1, int32 a2, int32 a3, int32 a4) { } int LogicHEsoccer::op_1007(int32 *args) { - // TODO: Used when the HE logo is shown + // Used when the HE logo is shown // This initializes the _userDataD fields that are used in op_1006/op_1011 + _intArraysAllocated = false; double v14 = (double)args[0] * 0.01; - _userData[6873] = 0; double v13 = (double)args[2] * 0.01; _userDataD[524] = v14; double v12 = atan2(v13, v14); @@ -990,25 +1004,20 @@ int LogicHEsoccer::op_1007(int32 *args) { _userDataD[523] = _userDataD[527] / _userDataD[519]; _userDataD[518] = v13; - *((uint32 *)_userData[6857]) = 0; - memset(_userData + 2737, 0, 4 * 1024); - for (int i = 0; i < 146; i++) - _userDataD[538 + i] = 0; - _userData[2736] = 0; + // Clear both byte arrays + memset(_byteArray1, 0, 4096); + memset(_byteArray2, 0, 585); - if (*((uint32 *)_userData[6885]) == 0 ) + if (_array1013Allocated == 0 ) op_1013(4, args[8], args[9]); return 1; } -#if 0 -// TODO: Used by several opcodes // Returns the square root of the sum of the squares of the arguments -static inline double fsqrtSquare(double a1, double a2, double a3) { +static inline double sqrtSquare(double a1, double a2, double a3) { return sqrt(a1 * a1 + a2 * a2 + a3 * a3); -} -#endif +} int LogicHEsoccer::op_1008(int32 *args) { // TODO: Used during a match (kicking?) @@ -1164,6 +1173,7 @@ void LogicHEsoccer::op_1011_sub(int32 a1, int32 a2, int32 a3, int32 a4) { int LogicHEsoccer::op_1012(int32 *args) { // Used after op_1019 // This function activates startOfFrame() to call op_1011 + // (Possibly field parameters?) _userDataD[530] = (args[0] != 0) ? 1 : 0; _userDataD[531] = args[1]; @@ -1176,8 +1186,6 @@ int LogicHEsoccer::op_1012(int32 *args) { return 1; } -#if 0 -// TODO: Used by op_1013 // Some strange power operation, ignores negative exponents static inline double u32Pow(float a1, int a2) { if (a2 < 0) @@ -1190,34 +1198,126 @@ static inline double u32Pow(float a1, int a2) { return v4; } -#endif + +int LogicHEsoccer::op_sub5(int a1, int a2, int a3) { + byte *v9 = _array1013 + 44 * a2; + + *((uint32 *)v9 + 4) = a3; + *((uint32 *)v9) = a2; + + if (a1 > 2) { + // Casual observation: 585 is also the size of _byteArray2 + *((uint32 *)v9 + 40) = 8 * a2 - 585; + for (int i = 0; i < 8; i++) + *((uint32 *)v9 + 4 * i + 8) = 0xffffffff; + } else { + for (int i = 0; i < 8; i++) + *((uint32 *)v9 + 4 * i + 8) = op_sub5(a1 + 1, i + 8 * a2 + 1, a2); + } + + return a2; +} int LogicHEsoccer::op_1013(int32 a1, int32 a2, int32 a3) { - // TODO: Called by op_1007 + // Creates _array1013 for *some* purpose + // _array1013Temp is used again op_1014 for some reason... + // Seems to be used in op_1015 + + int v4 = (int)((1.0 - u32Pow(8.0, 4)) / -7.0); + + _array1013 = new byte[v4 * 44]; + memset(_array1013, 0, v4 * 44); + _array1013Allocated = true; + memset(_array1013Temp, 0, 44); + + for (int i = 0; i < 8; i++) + _array1013Temp[i + 2] = op_sub5(1, i + 1, 0); + + // Yes, this is not endian-safe, but should not matter since we're + // not saving/loading the data anywhere + memcpy(_array1013, _array1013Temp, 44); return 1; } -int LogicHEsoccer::op_1014(int32 *args) { +int LogicHEsoccer::op_1014(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7, int32 a8, int32 a9, int32 a10, int32 a11, int32 a12, int32 a13, int32 a14) { // TODO: Used many times during a match + // And called from op_1008! return 1; } int LogicHEsoccer::op_1019(int32 *args) { - // TODO: Used at the beginning of a match + // Used at the beginning of a match + // Initializes some arrays. Player positions? + + // These two arrays are used in op_1014 and op_1015 + for (int i = 0; i < 4096; i++) + _byteArray1[i] = getFromArray(args[1], 0, i); + + for (int i = 0; i < 585; i++) + _byteArray2[i] = getFromArray(args[0], 0, i); + + // Deallocate the two integer arrays + if (_intArraysAllocated) + op_1020(); + + // Reallocate them + _intArray1 = new uint32[1008]; + _intArray2 = new uint32[168]; + _intArraysAllocated = true; + + memset(_intArray1, 0, 4 * 4); + memset(_intArray2, 0, 24 * 4); + + // These two arrays are used in op_1015 + for (int i = 0; i < 42; i++) { + for (int j = 0; j < 24; j++) + _intArray1[j + 24 * i] = getFromArray(args[3], 0, j + 24 * i); + + for (int j = 0; j < 4; j++) + _intArray2[j + 4 * i] = getFromArray(args[2], 0, j + 4 * i); + } return 1; } int LogicHEsoccer::op_1020() { - // TODO: Called by several other opcodes. Possibly "stop play"? + // Deallocate integer arrays + // The arrays can be allocated in op_1015 or op_1019 + + delete[] _intArray1; _intArray1 = 0; + delete[] _intArray2; _intArray2 = 0; + _intArraysAllocated = false; return 1; } -int LogicHEsoccer::op_1021(int32 *args) { - // TODO: Used during a match (ball movement?) +int LogicHEsoccer::op_1021(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7) { + // Used during a match (ball movement?) + // Also called from op_1008 + + int v10; + if (a4 && a5) + v10 = (int)(((double)a2 - (double)a5 * (double)a1 / (double)a4) * -1.0 * (double)a4 / (double)a5); + else + v10 = a1; + + int v9; + if (a6 && a5) + v9 = (int)(((double)a2 - (double)a5 * (double)a3 / (double)a6) * -1.0 * (double)a6 / (double)a5); + else + v9 = a3; + + // The final argument chooses whether to store the results for op_1008 or + // store them in SCUMM variables. + if (a7) { + _var1021[0] = v10; + _var1021[1] = v9; + } else { + writeScummVar(108, v10); + writeScummVar(109, v9); + } return 1; } diff --git a/engines/scumm/he/logic_he.h b/engines/scumm/he/logic_he.h index c2ea2b8ec6..d097d37e75 100644 --- a/engines/scumm/he/logic_he.h +++ b/engines/scumm/he/logic_he.h @@ -111,7 +111,6 @@ private: class LogicHEsoccer : public LogicHE { private: - byte *_userData; double *_userDataD; public: @@ -130,21 +129,38 @@ private: int op_1002(int32 *args); int op_1003(int32 *args); int op_1004(int32 *args); - // op_1006 can be called from other opcodes! int op_1006(int32 a1, int32 a2, int32 a3, int32 a4); int op_1007(int32 *args); int op_1008(int32 *args); - // op_1011 can be called from other opcodes! int op_1011(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5); - void op_1011_sub(int32 a1, int32 a2, int32 a3, int32 a4); int op_1012(int32 *args); - // op_1013 can be called from other opcodes! int op_1013(int32 a1, int32 a2, int32 a3); - int op_1014(int32 *args); + int op_1014(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7, int32 a8, int32 a9, int32 a10, int32 a11, int32 a12, int32 a13, int32 a14); int op_1019(int32 *args); - // op_1020 can be called from other opcodes! int op_1020(); - int op_1021(int32 *args); + int op_1021(int32 a1, int32 a2, int32 a3, int32 a4, int32 a5, int32 a6, int32 a7); + + // Two integer arrays are used between some functions + // Originally, these pointers were in _userData, but we keep them separate + // Also, doing it that would break things on non 32-bit systems... + bool _intArraysAllocated; + uint32 *_intArray1, *_intArray2; + + // op_1007 allocates some arrays + // they're then filled by op_1019 + byte _byteArray1[4096], _byteArray2[585]; + + // op_1011 has a subfunction + void op_1011_sub(int32 a1, int32 a2, int32 a3, int32 a4); + + // op_1013 creates some array, purpose unknown + bool _array1013Allocated; + byte *_array1013; + uint32 _array1013Temp[11]; + int op_sub5(int a1, int a2, int a3); + + // op_1021 can (optionally) set two variables for use in op_1008 + uint32 _var1021[2]; }; class LogicHEbaseball2001 : public LogicHE { |