aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorMatthew Hoops2011-04-27 10:08:40 -0400
committerMatthew Hoops2011-04-27 10:15:28 -0400
commitf584f2f3120c33492ba0309bde33a1b4c473c1e1 (patch)
treead1a072d9fe14843e876b13c50d38bb51507abfc /engines/scumm
parent27e4a1dee524fb4979a3ba2430b6c82d486be853 (diff)
downloadscummvm-rg350-f584f2f3120c33492ba0309bde33a1b4c473c1e1.tar.gz
scummvm-rg350-f584f2f3120c33492ba0309bde33a1b4c473c1e1.tar.bz2
scummvm-rg350-f584f2f3120c33492ba0309bde33a1b4c473c1e1.zip
SCUMM: Implement soccer u32 opcodes 1013, 1019, 1020, and 1021
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/he/logic_he.cpp154
-rw-r--r--engines/scumm/he/logic_he.h32
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 {