[Scummvm-git-logs] scummvm master -> 4353765c3289b62d2fdc19e53945a0c34fea3418
AndywinXp
noreply at scummvm.org
Sat Jul 6 19:12:15 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
4353765c32 SCUMM: HE: Relabel and clean-up arrays subsystem
Commit: 4353765c3289b62d2fdc19e53945a0c34fea3418
https://github.com/scummvm/scummvm/commit/4353765c3289b62d2fdc19e53945a0c34fea3418
Author: AndywinXp (andywinxp at gmail.com)
Date: 2024-07-06T21:12:04+02:00
Commit Message:
SCUMM: HE: Relabel and clean-up arrays subsystem
I wanted to do this for a very long time. This is helping me
debugging some very hard to understand remaining bugs
on some SCUMM HE games.
I tested this for several hours with several games,
including Moonbase and some Backyard games
ensuring there were no obvious regressions.
Changed paths:
engines/scumm/he/intern_he.h
engines/scumm/he/logic/football.cpp
engines/scumm/he/net/net_lobby.cpp
engines/scumm/he/net/net_main.cpp
engines/scumm/he/script_v100he.cpp
engines/scumm/he/script_v60he.cpp
engines/scumm/he/script_v72he.cpp
engines/scumm/he/script_v80he.cpp
engines/scumm/he/script_v90he.cpp
engines/scumm/resource.cpp
engines/scumm/script_v6.cpp
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index e798e971bbe..0dddfd84cb1 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -35,6 +35,8 @@ class SeekableWriteStream;
namespace Scumm {
+#define MAGIC_ARRAY_NUMBER 0x33539000
+
class ActorHE;
class ResExtractor;
#ifdef ENABLE_HE
@@ -383,12 +385,12 @@ protected:
#include "common/pack-start.h" // START STRUCT PACKING
struct ArrayHeader {
- int32 type; //0
- int32 dim1start; //4
- int32 dim1end; //8
- int32 dim2start; //0C
- int32 dim2end; //10
- byte data[1]; //14
+ int32 type;
+ int32 acrossMin;
+ int32 acrossMax;
+ int32 downMin;
+ int32 downMax;
+ byte data[1];
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
@@ -421,17 +423,22 @@ protected:
void redrawBGAreas() override;
void checkExecVerbs() override;
- byte *defineArray(int array, int type, int dim2start, int dim2end, int dim1start, int dim1end, bool newArray = false, int *newid = NULL);
+ byte *defineArray(int array, int type, int downMin, int downMax, int acrossMin, int acrossMax, bool newArray = false, int *newid = NULL);
int readArray(int array, int idx2, int idx1) override;
void writeArray(int array, int idx2, int idx1, int value) override;
void redimArray(int arrayId, int newDim2start, int newDim2end,
int newDim1start, int newDim1end, int type);
- void checkArrayLimits(int array, int dim2start, int dim2end, int dim1start, int dim1end);
+ void checkArrayLimits(int array, int downMin, int downMax, int acrossMin, int acrossMax);
void copyArray(int array1, int a1_dim2start, int a1_dim2end, int a1_dim1start, int a1_dim1end,
int array2, int a2_dim2start, int a2_dim2end, int a2_dim1start, int a2_dim1end);
- void copyArrayHelper(ArrayHeader *ah, int idx2, int idx1, int len1, byte **data, int *size, int *num);
+ void getArrayDataPtrAndDataSize(ArrayHeader *ah, int idx2, int idx1, int len1, byte **data, int *size, int *num);
int readFileToArray(int slot, int32 size);
void writeFileFromArray(int slot, int32 resID);
+ void arrayBlockOperation(
+ int dstVariable, int dstDownMin, int dstDownMax, int dstAcrossMin, int dstAcrossMax,
+ int a2Variable, int a2DownMin, int a2DownMax, int a2AcrossMin, int a2AcrossMax,
+ int a1Variable, int a1DownMin, int a1DownMax, int a1AcrossMin, int a1AcrossMax,
+ int (*op)(int a2, int a1));
void decodeParseString(int a, int b) override;
void decodeScriptString(byte *dst, bool scriptString = false);
@@ -709,8 +716,8 @@ protected:
bool heAuxProcessFileRelativeBlock(HEAnimAuxData *auxInfoPtr, const byte *dataBlockPtr);
bool heAuxProcessDisplacedBlock(HEAnimAuxData *auxInfoPtr, const byte *displacedBlockPtr);
- void getArrayDim(int array, int *dim2start, int *dim2end, int *dim1start, int *dim1end);
- void sortArray(int array, int dim2start, int dim2end, int dim1start, int dim1end, int sortOrder);
+ void getArrayDim(int array, int *downMin, int *downMax, int *acrossMin, int *acrossMax);
+ void sortArray(int array, int downMin, int downMax, int acrossMin, int acrossMax, int sortOrder);
public:
int getGroupSpriteArray(int spriteGroupId);
diff --git a/engines/scumm/he/logic/football.cpp b/engines/scumm/he/logic/football.cpp
index b5c897efcf9..0b31d4a4220 100644
--- a/engines/scumm/he/logic/football.cpp
+++ b/engines/scumm/he/logic/football.cpp
@@ -623,7 +623,7 @@ int LogicHEfootball2002::getPlaybookFiles(int32 *args) {
// Get the pattern and then skip over the directory prefix ("*\" or "*:")
// Also prepend the target name
Common::String targetName = _vm->getTargetName();
- Common::String basePattern = ((const char *)_vm->getStringAddress(args[0] & ~0x33539000) + 2);
+ Common::String basePattern = ((const char *)_vm->getStringAddress(args[0] & ~MAGIC_ARRAY_NUMBER) + 2);
Common::String pattern = targetName + '-' + basePattern;
// Prepare a buffer to hold the file names
diff --git a/engines/scumm/he/net/net_lobby.cpp b/engines/scumm/he/net/net_lobby.cpp
index 0782274fd02..dd79a1a98af 100644
--- a/engines/scumm/he/net/net_lobby.cpp
+++ b/engines/scumm/he/net/net_lobby.cpp
@@ -608,9 +608,9 @@ void Lobby::sendGameResults(int userId, int arrayIndex, int lastFlag) {
setProfileRequest.setVal("cmd", new Common::JSONValue("game_results"));
setProfileRequest.setVal("user", new Common::JSONValue((long long int)userId));
- ScummEngine_v90he::ArrayHeader *ah = (ScummEngine_v90he::ArrayHeader *)_vm->getResourceAddress(rtString, arrayIndex & ~0x33539000);
- int32 size = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
- (FROM_LE_32(ah->dim2end) - FROM_LE_32(ah->dim2start) + 1);
+ ScummEngine_v90he::ArrayHeader *ah = (ScummEngine_v90he::ArrayHeader *)_vm->getResourceAddress(rtString, arrayIndex & ~MAGIC_ARRAY_NUMBER);
+ int32 size = (FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1) *
+ (FROM_LE_32(ah->downMax) - FROM_LE_32(ah->downMin) + 1);
Common::JSONArray arrayData;
for (int i = 0; i < size; i++) {
diff --git a/engines/scumm/he/net/net_main.cpp b/engines/scumm/he/net/net_main.cpp
index 785efba95bc..23c68e388db 100644
--- a/engines/scumm/he/net/net_main.cpp
+++ b/engines/scumm/he/net/net_main.cpp
@@ -836,16 +836,16 @@ int Net::remoteSendData(int typeOfSend, int sendTypeParam, int type, Common::Str
}
void Net::remoteSendArray(int typeOfSend, int sendTypeParam, int priority, int arrayIndex) {
- debugC(DEBUG_NETWORK, "Net::remoteSendArray(%d, %d, %d, %d)", typeOfSend, sendTypeParam, priority, arrayIndex & ~0x33539000); // PN_RemoteSendArrayCommand
+ debugC(DEBUG_NETWORK, "Net::remoteSendArray(%d, %d, %d, %d)", typeOfSend, sendTypeParam, priority, arrayIndex & ~MAGIC_ARRAY_NUMBER); // PN_RemoteSendArrayCommand
- ScummEngine_v90he::ArrayHeader *ah = (ScummEngine_v90he::ArrayHeader *)_vm->getResourceAddress(rtString, arrayIndex & ~0x33539000);
+ ScummEngine_v90he::ArrayHeader *ah = (ScummEngine_v90he::ArrayHeader *)_vm->getResourceAddress(rtString, arrayIndex & ~MAGIC_ARRAY_NUMBER);
Common::String jsonData = Common::String::format(
"\"type\":%d,\"dim1start\":%d,\"dim1end\":%d,\"dim2start\":%d,\"dim2end\":%d,\"data\":[",
- ah->type, ah->dim1start, ah->dim1end, ah->dim2start, ah->dim2end);
+ ah->type, ah->acrossMin, ah->acrossMax, ah->downMin, ah->downMax);
- int32 size = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
- (FROM_LE_32(ah->dim2end) - FROM_LE_32(ah->dim2start) + 1);
+ int32 size = (FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1) *
+ (FROM_LE_32(ah->downMax) - FROM_LE_32(ah->downMin) + 1);
for (int i = 0; i < size; i++) {
int32 data;
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index 46705ad98fc..29e28bb40ed 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -551,7 +551,7 @@ void ScummEngine_v100he::o100_actorOps() {
void ScummEngine_v100he::o100_arrayOps() {
byte *data;
byte string[1024];
- int dim1end, dim1start, dim2end, dim2start;
+ int acrossMax, acrossMin, downMax, downMin;
int id, len, b, c, list[128];
int offs, tmp, tmp2;
uint tmp3, type;
@@ -597,26 +597,26 @@ void ScummEngine_v100he::o100_arrayOps() {
break;
case SO_COMPLEX_ARRAY_ASSIGNMENT:
len = getStackList(list, ARRAYSIZE(list));
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
id = readVar(array);
if (id == 0) {
- defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
+ defineArray(array, kDwordArray, downMin, downMax, acrossMin, acrossMax);
}
- checkArrayLimits(array, dim2start, dim2end, dim1start, dim1end);
+ checkArrayLimits(array, downMin, downMax, acrossMin, acrossMax);
tmp2 = 0;
- while (dim2start <= dim2end) {
- tmp = dim1start;
- while (tmp <= dim1end) {
- writeArray(array, dim2start, tmp, list[tmp2++]);
+ while (downMin <= downMax) {
+ tmp = acrossMin;
+ while (tmp <= acrossMax) {
+ writeArray(array, downMin, tmp, list[tmp2++]);
if (tmp2 == len)
tmp2 = 0;
tmp++;
}
- dim2start++;
+ downMin++;
}
break;
case SO_COMPLEX_ARRAY_COPY_OPERATION:
@@ -650,10 +650,10 @@ void ScummEngine_v100he::o100_arrayOps() {
int a2_dim1start = pop();
int a2_dim2end = pop();
int a2_dim2start = pop();
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
debug(0, "Complex: %d = %d[%d to %d][%d to %d] %c %d[%d to %d][%d to %d]", array,
array1, a1_dim1start, a1_dim2end, a1_dim1start, a1_dim2end,
@@ -664,21 +664,21 @@ void ScummEngine_v100he::o100_arrayOps() {
int a11_num = a1_dim1end - a1_dim1start + 1;
int a22_num = a2_dim2end - a2_dim2start + 1;
int a21_num = a2_dim1end - a2_dim1start + 1;
- int d12_num = dim2end - dim2start + 1;
- int d11_num = dim1end - dim1start + 1;
+ int d12_num = downMax - downMin + 1;
+ int d11_num = acrossMax - acrossMin + 1;
id = readVar(array);
if (id == 0) {
- defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
+ defineArray(array, kDwordArray, downMin, downMax, acrossMin, acrossMax);
}
if (a12_num != a22_num || a12_num != d12_num || a11_num != a21_num || a11_num != d11_num) {
error("Operation size mismatch (%d vs %d)(%d vs %d)", a12_num, a22_num, a11_num, a21_num);
}
- for (; a1_dim2start <= a1_dim2end; ++a1_dim2start, ++a2_dim2start, ++dim2start) {
+ for (; a1_dim2start <= a1_dim2end; ++a1_dim2start, ++a2_dim2start, ++downMin) {
int a2dim1 = a2_dim1start;
int a1dim1 = a1_dim1start;
- int dim1 = dim1start;
+ int dim1 = acrossMin;
for (; a1dim1 <= a1_dim1end; ++a1dim1, ++a2dim1, ++dim1) {
int val1 = readArray(array1, a1_dim2start, a1dim1);
int val2 = readArray(array2, a2_dim2start, a2dim1);
@@ -703,7 +703,7 @@ void ScummEngine_v100he::o100_arrayOps() {
default:
error("o100_arrayOps: case 132 unknown type %d)", type);
}
- writeArray(array, dim2start, dim1, res);
+ writeArray(array, downMin, dim1, res);
}
}
break;
@@ -711,23 +711,23 @@ void ScummEngine_v100he::o100_arrayOps() {
case SO_RANGE_ARRAY_ASSIGNMENT:
b = pop();
c = pop();
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
id = readVar(array);
if (id == 0) {
- defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
+ defineArray(array, kDwordArray, downMin, downMax, acrossMin, acrossMax);
}
- checkArrayLimits(array, dim2start, dim2end, dim1start, dim1end);
+ checkArrayLimits(array, downMin, downMax, acrossMin, acrossMax);
offs = (b >= c) ? 1 : -1;
tmp2 = c;
tmp3 = ABS(c - b) + 1;
- while (dim2start <= dim2end) {
- tmp = dim1start;
- while (tmp <= dim1end) {
- writeArray(array, dim2start, tmp, tmp2);
+ while (downMin <= downMax) {
+ tmp = acrossMin;
+ while (tmp <= acrossMax) {
+ writeArray(array, downMin, tmp, tmp2);
if (--tmp3 == 0) {
tmp2 = c;
tmp3 = ABS(c - b) + 1;
@@ -736,7 +736,7 @@ void ScummEngine_v100he::o100_arrayOps() {
}
tmp++;
}
- dim2start++;
+ downMin++;
}
break;
default:
@@ -777,7 +777,7 @@ void ScummEngine_v100he::o100_createSound() {
}
void ScummEngine_v100he::o100_dim2dimArray() {
- int data, dim1end, dim2end;
+ int data, acrossMax, downMax;
byte subOp = fetchScriptByte();
@@ -804,9 +804,9 @@ void ScummEngine_v100he::o100_dim2dimArray() {
error("o100_dim2dimArray: default case %d", subOp);
}
- dim1end = pop();
- dim2end = pop();
- defineArray(fetchScriptWord(), data, 0, dim2end, 0, dim1end);
+ acrossMax = pop();
+ downMax = pop();
+ defineArray(fetchScriptWord(), data, 0, downMax, 0, acrossMax);
}
void ScummEngine_v100he::o100_dimArray() {
@@ -1420,7 +1420,7 @@ void ScummEngine_v100he::o100_wizImageOps() {
}
void ScummEngine_v100he::o100_dim2dim2Array() {
- int data, dim1start, dim1end, dim2start, dim2end;
+ int data, acrossMin, acrossMax, downMin, downMax;
byte subOp = fetchScriptByte();
@@ -1448,18 +1448,18 @@ void ScummEngine_v100he::o100_dim2dim2Array() {
}
if (pop() == 2) {
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
} else {
- dim2end = pop();
- dim2start = pop();
- dim1end = pop();
- dim1start = pop();
+ downMax = pop();
+ downMin = pop();
+ acrossMax = pop();
+ acrossMin = pop();
}
- defineArray(fetchScriptWord(), data, dim2start, dim2end, dim1start, dim1end);
+ defineArray(fetchScriptWord(), data, downMin, downMax, acrossMin, acrossMax);
}
void ScummEngine_v100he::o100_redim2dimArray() {
diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp
index 1b4bcc8065e..9a4541011e7 100644
--- a/engines/scumm/he/script_v60he.cpp
+++ b/engines/scumm/he/script_v60he.cpp
@@ -1035,7 +1035,7 @@ void ScummEngine_v60he::o60_soundOps() {
void ScummEngine_v60he::localizeArray(int slot, byte scriptSlot) {
if (_game.heversion >= 80)
- slot &= ~0x33539000;
+ slot &= ~MAGIC_ARRAY_NUMBER;
if (slot >= _numArray)
error("o60_localizeArrayToScript(%d): array slot out of range", slot);
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 59ef476d085..a443d568a27 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -101,14 +101,14 @@ void ScummEngine_v72he::setupOpcodes() {
static const int arrayDataSizes[] = { 0, 1, 4, 8, 8, 16, 32 };
-byte *ScummEngine_v72he::defineArray(int array, int type, int dim2start, int dim2end,
- int dim1start, int dim1end, bool newArray, int *newid) {
- int id;
+byte *ScummEngine_v72he::defineArray(int array, int type, int downMin, int downMax,
+ int acrossMin, int acrossMax, bool newArray, int *newid) {
+ int arrayPtr;
int size;
ArrayHeader *ah;
- assert(dim2start >= 0 && dim2start <= dim2end);
- assert(dim1start >= 0 && dim1start <= dim1end);
+ assert(downMin >= 0 && downMin <= downMax);
+ assert(acrossMin >= 0 && acrossMin <= acrossMax);
assert(0 <= type && type <= 6);
@@ -118,45 +118,37 @@ byte *ScummEngine_v72he::defineArray(int array, int type, int dim2start, int dim
if (!newArray)
nukeArray(array);
- id = findFreeArrayId();
+ arrayPtr = findFreeArrayId();
- if (newid != NULL)
- *newid = id;
+ if (newid)
+ *newid = arrayPtr;
- debug(9, "defineArray (array %d, dim2start %d, dim2end %d dim1start %d dim1end %d", id, dim2start, dim2end, dim1start, dim1end);
+ debug(9, "defineArray (array %d, downMin %d, downMax %d acrossMin %d acrossMax %d", arrayPtr, downMin, downMax, acrossMin, acrossMax);
if (!newArray && (array & 0x80000000)) {
error("Can't define bit variable as array pointer");
}
- size = arrayDataSizes[type];
-
- if (_game.heversion >= 80)
- id |= 0x33539000;
-
if (!newArray)
- writeVar(array, id);
+ writeVar(array, (_game.heversion >= 80 ? (arrayPtr | MAGIC_ARRAY_NUMBER) : arrayPtr));
- if (_game.heversion >= 80)
- id &= ~0x33539000;
+ size = ((downMax - downMin + 1) * (acrossMax - acrossMin + 1) * arrayDataSizes[type]) / 8;
- size *= dim2end - dim2start + 1;
- size *= dim1end - dim1start + 1;
- size >>= 3;
-
- ah = (ArrayHeader *)_res->createResource(rtString, id, size + sizeof(ArrayHeader));
+ ah = (ArrayHeader *)_res->createResource(rtString,
+ (_game.heversion >= 80 ? (arrayPtr & ~MAGIC_ARRAY_NUMBER) : arrayPtr),
+ size + sizeof(ArrayHeader));
ah->type = TO_LE_32(type);
- ah->dim1start = TO_LE_32(dim1start);
- ah->dim1end = TO_LE_32(dim1end);
- ah->dim2start = TO_LE_32(dim2start);
- ah->dim2end = TO_LE_32(dim2end);
+ ah->acrossMin = TO_LE_32(acrossMin);
+ ah->acrossMax = TO_LE_32(acrossMax);
+ ah->downMin = TO_LE_32(downMin);
+ ah->downMax = TO_LE_32(downMax);
return ah->data;
}
int ScummEngine_v72he::readArray(int array, int idx2, int idx1) {
- debug(9, "readArray (array %d, idx2 %d, idx1 %d)", readVar(array), idx2, idx1);
+ debug(9, "readArray (array %d, down %d, aMin %d)", readVar(array), idx2, idx1);
if (readVar(array) == 0)
error("readArray: Reference to zeroed array pointer");
@@ -166,11 +158,11 @@ int ScummEngine_v72he::readArray(int array, int idx2, int idx1) {
if (!ah)
error("readArray: invalid array %d (%d)", array, readVar(array));
- if (idx2 < (int)FROM_LE_32(ah->dim2start) || idx2 > (int)FROM_LE_32(ah->dim2end) ||
- idx1 < (int)FROM_LE_32(ah->dim1start) || idx1 > (int)FROM_LE_32(ah->dim1end)) {
+ if (idx2 < (int)FROM_LE_32(ah->downMin) || idx2 > (int)FROM_LE_32(ah->downMax) ||
+ idx1 < (int)FROM_LE_32(ah->acrossMin) || idx1 > (int)FROM_LE_32(ah->acrossMax)) {
error("readArray: array %d out of bounds: [%d, %d] exceeds [%d..%d, %d..%d]",
- array, idx1, idx2, FROM_LE_32(ah->dim1start), FROM_LE_32(ah->dim1end),
- FROM_LE_32(ah->dim2start), FROM_LE_32(ah->dim2end));
+ array, idx1, idx2, FROM_LE_32(ah->acrossMin), FROM_LE_32(ah->acrossMax),
+ FROM_LE_32(ah->downMin), FROM_LE_32(ah->downMax));
}
#if defined(USE_ENET) && defined(USE_LIBCURL)
@@ -198,8 +190,8 @@ int ScummEngine_v72he::readArray(int array, int idx2, int idx1) {
}
#endif
- const int offset = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
- (idx2 - FROM_LE_32(ah->dim2start)) + (idx1 - FROM_LE_32(ah->dim1start));
+ const int offset = (FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1) *
+ (idx2 - FROM_LE_32(ah->downMin)) + (idx1 - FROM_LE_32(ah->acrossMin));
switch (FROM_LE_32(ah->type)) {
case kByteArray:
@@ -220,7 +212,7 @@ int ScummEngine_v72he::readArray(int array, int idx2, int idx1) {
}
void ScummEngine_v72he::writeArray(int array, int idx2, int idx1, int value) {
- debug(9, "writeArray (array %d, idx2 %d, idx1 %d, value %d)", readVar(array), idx2, idx1, value);
+ debug(9, "writeArray (array %d, down %d, aMin %d, value %d)", readVar(array), idx2, idx1, value);
if (readVar(array) == 0)
error("writeArray: Reference to zeroed array pointer");
@@ -230,15 +222,15 @@ void ScummEngine_v72he::writeArray(int array, int idx2, int idx1, int value) {
if (!ah)
error("writeArray: Invalid array (%d) reference", readVar(array));
- if (idx2 < (int)FROM_LE_32(ah->dim2start) || idx2 > (int)FROM_LE_32(ah->dim2end) ||
- idx1 < (int)FROM_LE_32(ah->dim1start) || idx1 > (int)FROM_LE_32(ah->dim1end)) {
+ if (idx2 < (int)FROM_LE_32(ah->downMin) || idx2 > (int)FROM_LE_32(ah->downMax) ||
+ idx1 < (int)FROM_LE_32(ah->acrossMin) || idx1 > (int)FROM_LE_32(ah->acrossMax)) {
error("writeArray: array %d out of bounds: [%d, %d] exceeds [%d..%d, %d..%d]",
- array, idx1, idx2, FROM_LE_32(ah->dim1start), FROM_LE_32(ah->dim1end),
- FROM_LE_32(ah->dim2start), FROM_LE_32(ah->dim2end));
+ array, idx1, idx2, FROM_LE_32(ah->acrossMin), FROM_LE_32(ah->acrossMax),
+ FROM_LE_32(ah->downMin), FROM_LE_32(ah->downMax));
}
- const int offset = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
- (idx2 - FROM_LE_32(ah->dim2start)) - FROM_LE_32(ah->dim1start) + idx1;
+ const int offset = (FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1) *
+ (idx2 - FROM_LE_32(ah->downMin)) - FROM_LE_32(ah->acrossMin) + idx1;
switch (FROM_LE_32(ah->type)) {
case kByteArray:
@@ -299,6 +291,68 @@ void ScummEngine_v72he::readArrayFromIndexFile() {
}
}
+void ScummEngine_v72he::arrayBlockOperation(
+ int dstVariable, int dstDownMin, int dstDownMax, int dstAcrossMin, int dstAcrossMax,
+ int a2Variable, int a2DownMin, int a2DownMax, int a2AcrossMin, int a2AcrossMax,
+ int a1Variable, int a1DownMin, int a1DownMax, int a1AcrossMin, int a1AcrossMax,
+ int (*op)(int a2, int a1)) {
+ int downCount, acrossCount;
+ int dstD, dstA, a1D, a1A, a2D, a2A;
+ int dstDIndex, dstAIndex;
+ int a1DIndex, a1AIndex;
+ int a2DIndex, a2AIndex;
+
+ checkArrayLimits(dstVariable, dstDownMin, dstDownMax, dstAcrossMin, dstAcrossMax);
+ checkArrayLimits(a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax);
+ checkArrayLimits(a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax);
+
+ dstD = ((dstDownMax - dstDownMin) + 1);
+ dstA = ((dstAcrossMax - dstAcrossMin) + 1);
+ a1D = ((a1DownMax - a1DownMin) + 1);
+ a1A = ((a1AcrossMax - a1AcrossMin) + 1);
+ a2D = ((a2DownMax - a2DownMin) + 1);
+ a2A = ((a2AcrossMax - a2AcrossMin) + 1);
+
+ if (((dstD != a1D) || (a1D != a2D)) || ((dstA != a1A) || (a1A != a2A))) {
+
+ debug("ScummEngine_v72he::arrayBlockOperation(): "
+ "{%8d}[ %4d to %4d ][ %4d to %4d ] = "
+ "({%8d}[ %4d to %4d ][ %4d to %4d ] <?> "
+ "{%8d}[ %4d to %4d ][ %4d to %4d ] <%d>)\n",
+ dstVariable, dstDownMin, dstDownMax, dstAcrossMin, dstAcrossMax,
+ a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax,
+ a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax);
+
+ error("Invalid ranges for array block math operation");
+ }
+
+ acrossCount = dstA;
+ downCount = dstD;
+
+ dstDIndex = dstDownMin;
+ a1DIndex = a1DownMin;
+ a2DIndex = a2DownMin;
+
+ for (int downCounter = 0; downCounter < downCount; downCounter++) {
+ dstAIndex = dstAcrossMin;
+ a1AIndex = a1AcrossMin;
+ a2AIndex = a2AcrossMin;
+
+ for (int acrossCounter = 0; acrossCounter < acrossCount; acrossCounter++) {
+ writeArray(dstVariable, dstDIndex, dstAIndex,
+ (*op)(readArray(a2Variable, a2DIndex, a2AIndex), readArray(a1Variable, a1DIndex, a1AIndex)));
+
+ dstAIndex++;
+ a1AIndex++;
+ a2AIndex++;
+ }
+
+ dstDIndex++;
+ a1DIndex++;
+ a2DIndex++;
+ }
+}
+
void ScummEngine_v72he::copyScriptString(byte *dst, int dstSize) {
byte string[1024];
byte chr;
@@ -648,7 +702,7 @@ void ScummEngine_v72he::o72_printWizImage() {
void ScummEngine_v72he::o72_getArrayDimSize() {
byte subOp = fetchScriptByte();
- int32 val1, val2;
+ int32 maxValue, minValue;
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(fetchScriptWord()));
if (!ah) {
push(0);
@@ -658,26 +712,26 @@ void ScummEngine_v72he::o72_getArrayDimSize() {
switch (subOp) {
case SO_NONE:
case SO_NIBBLE:
- val1 = FROM_LE_32(ah->dim1end);
- val2 = FROM_LE_32(ah->dim1start);
- push(val1 - val2 + 1);
+ maxValue = FROM_LE_32(ah->acrossMax);
+ minValue = FROM_LE_32(ah->acrossMin);
+ push(maxValue - minValue + 1);
break;
case SO_BIT:
- val1 = FROM_LE_32(ah->dim2end);
- val2 = FROM_LE_32(ah->dim2start);
- push(val1 - val2 + 1);
+ maxValue = FROM_LE_32(ah->downMax);
+ minValue = FROM_LE_32(ah->downMin);
+ push(maxValue - minValue + 1);
break;
case SO_BYTE:
- push(FROM_LE_32(ah->dim1start));
+ push(FROM_LE_32(ah->acrossMin));
break;
case SO_INT:
- push(FROM_LE_32(ah->dim1end));
+ push(FROM_LE_32(ah->acrossMax));
break;
case SO_DWORD:
- push(FROM_LE_32(ah->dim2start));
+ push(FROM_LE_32(ah->downMin));
break;
case SO_STRING:
- push(FROM_LE_32(ah->dim2end));
+ push(FROM_LE_32(ah->downMax));
break;
default:
error("o72_getArrayDimSize: default case %d", subOp);
@@ -1142,13 +1196,31 @@ void ScummEngine_v72he::o72_findObject() {
push(r);
}
+static int arrayBlockSubOp(int a2, int a1) {
+ return (a2 - a1);
+}
+
+static int arrayBlockAddOp(int a2, int a1) {
+ return (a2 + a1);
+}
+
+static int arrayBlockBANDOp(int a2, int a1) {
+ return (a2 & a1);
+}
+
+static int arrayBlockBOROp(int a2, int a1) {
+ return (a2 | a1);
+}
+
+static int arrayBlockBXOROp(int a2, int a1) {
+ return (a2 ^ a1);
+}
+
void ScummEngine_v72he::o72_arrayOps() {
byte *data;
byte string[1024];
- int dim1end, dim1start, dim2end, dim2start;
+ int acrossMax, acrossMin, downMax, downMin;
int id, len, b, c, list[128];
- int offs, tmp, tmp2;
- uint tmp3, type;
byte subOp = fetchScriptByte();
int array = fetchScriptWord();
@@ -1163,150 +1235,185 @@ void ScummEngine_v72he::o72_arrayOps() {
break;
case SO_COMPLEX_ARRAY_ASSIGNMENT:
- len = getStackList(list, ARRAYSIZE(list));
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
- id = readVar(array);
- if (id == 0) {
- defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
- }
- checkArrayLimits(array, dim2start, dim2end, dim1start, dim1end);
-
- tmp2 = 0;
- while (dim2start <= dim2end) {
- tmp = dim1start;
- while (tmp <= dim1end) {
- writeArray(array, dim2start, tmp, list[tmp2++]);
- if (tmp2 == len)
- tmp2 = 0;
- tmp++;
+ {
+ len = getStackList(list, ARRAYSIZE(list));
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
+ id = readVar(array);
+
+ if (id == 0) {
+ defineArray(array, kDwordArray, downMin, downMax, acrossMin, acrossMax);
+ }
+
+ checkArrayLimits(array, downMin, downMax, acrossMin, acrossMax);
+
+ int *currPtr = list;
+ int countDown = len;
+
+ for (int downCounter = downMin; downCounter <= downMax; downCounter++) {
+ for (int acrossCounter = acrossMin; acrossCounter <= acrossMax; acrossCounter++) {
+ writeArray(array, downCounter, acrossCounter, *currPtr++);
+
+ if (!--countDown) {
+ countDown = len;
+ currPtr = list;
+ }
+ }
}
- dim2start++;
}
+
break;
case SO_COMPLEX_ARRAY_COPY_OPERATION:
{
- int a2_dim1end = pop();
- int a2_dim1start = pop();
- int a2_dim2end = pop();
- int a2_dim2start = pop();
- int array2 = fetchScriptWord();
- int a1_dim1end = pop();
- int a1_dim1start = pop();
- int a1_dim2end = pop();
- int a1_dim2start = pop();
- if (a1_dim1end - a1_dim1start != a2_dim1end - a2_dim1start || a2_dim2end - a2_dim2start != a1_dim2end - a1_dim2start) {
- error("Source and dest ranges size are mismatched");
+ int srcAcrossMax = pop();
+ int srcAcrossMin = pop();
+ int srcDownMax = pop();
+ int srcDownMin = pop();
+ int srcVariable = fetchScriptWord();
+ int dstAcrossMax = pop();
+ int dstAcrossMin = pop();
+ int dstDownMax = pop();
+ int dstDownMin = pop();
+
+ if (dstAcrossMax - dstAcrossMin != srcAcrossMax - srcAcrossMin || srcDownMax - srcDownMin != dstDownMax - dstDownMin) {
+ error("Source and dest ranges dataOffsetPtr are mismatched");
}
- copyArray(array, a1_dim2start, a1_dim2end, a1_dim1start, a1_dim1end, array2, a2_dim2start, a2_dim2end, a2_dim1start, a2_dim1end);
+
+ copyArray(array, dstDownMin, dstDownMax, dstAcrossMin, dstAcrossMax, srcVariable, srcDownMin, srcDownMax, srcAcrossMin, srcAcrossMax);
}
+
break;
case SO_RANGE_ARRAY_ASSIGNMENT:
- b = pop();
- c = pop();
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
- id = readVar(array);
- if (id == 0) {
- defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
- }
- checkArrayLimits(array, dim2start, dim2end, dim1start, dim1end);
-
- offs = (b >= c) ? 1 : -1;
- tmp2 = c;
- tmp3 = ABS(c - b) + 1;
- while (dim2start <= dim2end) {
- tmp = dim1start;
- while (tmp <= dim1end) {
- writeArray(array, dim2start, tmp, tmp2);
- if (--tmp3 == 0) {
- tmp2 = c;
- tmp3 = ABS(c - b) + 1;
- } else {
- tmp2 += offs;
+ {
+ int rangeEnd = pop();
+ int rangeStart = pop();
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
+ id = readVar(array);
+
+ if (id == 0) {
+ defineArray(array, kDwordArray, downMin, downMax, acrossMin, acrossMax);
+ }
+
+ checkArrayLimits(array, downMin, downMax, acrossMin, acrossMax);
+
+ int value = rangeStart;
+ int count = ABS(rangeStart - rangeEnd) + 1;
+ int stepValue = (rangeStart <= rangeEnd) ? 1 : -1;
+ int countDown = count;
+
+ for (int downCounter = downMin; downCounter <= downMax; downCounter++) {
+ for (int acrossCounter = acrossMin; acrossCounter <= acrossMax; acrossCounter++) {
+ writeArray(array, downCounter, acrossCounter, value);
+
+ if (!--countDown) {
+ value = rangeStart;
+ countDown = count;
+ } else {
+ value += stepValue;
+ }
}
- tmp++;
}
- dim2start++;
}
+
break;
case SO_COMPLEX_ARRAY_MATH_OPERATION:
- {
- // Used by script 84 (Send end of play info) in Backyard Football during online play.
- int array2 = fetchScriptWord();
- int array1 = fetchScriptWord();
- type = pop();
- int a1_dim1end = pop();
- int a1_dim1start = pop();
- int a1_dim2end = pop();
- int a1_dim2start = pop();
- int a2_dim1end = pop();
- int a2_dim1start = pop();
- int a2_dim2end = pop();
- int a2_dim2start = pop();
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
-
- debug(0, "Complex: %d = %d[%d to %d][%d to %d] %c %d[%d to %d][%d to %d]", array,
- array1, a1_dim1start, a1_dim2end, a1_dim1start, a1_dim2end,
- " +-&|^"[type],
- array2, a2_dim1start, a2_dim2end, a2_dim1start, a2_dim2end);
-
- int a12_num = a1_dim2end - a1_dim2start + 1;
- int a11_num = a1_dim1end - a1_dim1start + 1;
- int a22_num = a2_dim2end - a2_dim2start + 1;
- int a21_num = a2_dim1end - a2_dim1start + 1;
- int d12_num = dim2end - dim2start + 1;
- int d11_num = dim1end - dim1start + 1;
-
- id = readVar(array);
- if (id == 0) {
- defineArray(array, kDwordArray, dim2start, dim2end, dim1start, dim1end);
- }
- if (a12_num != a22_num || a12_num != d12_num || a11_num != a21_num || a11_num != d11_num) {
- error("Operation size mismatch (%d vs %d)(%d vs %d)", a12_num, a22_num, a11_num, a21_num);
- }
+ {
+ // Used by script 84 (Send end of play info) in Backyard Football during online play.
+ int a2Variable = fetchScriptWord();
+ int a1Variable = fetchScriptWord();
+ int mathOperationType = pop();
+
+ int a1AcrossMax = pop();
+ int a1AcrossMin = pop();
+ int a1DownMax = pop();
+ int a1DownMin = pop();
+
+ int a2AcrossMax = pop();
+ int a2AcrossMin = pop();
+ int a2DownMax = pop();
+ int a2DownMin = pop();
+
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
+
+ debug(0, "Complex: %d = %d[%d to %d][%d to %d] %c %d[%d to %d][%d to %d]", array,
+ a1Variable, a1AcrossMin, a1DownMax, a1AcrossMin, a1DownMax,
+ " +-&|^"[mathOperationType],
+ a2Variable, a2AcrossMin, a2DownMax, a2AcrossMin, a2DownMax);
+
+ int dstD = downMax - downMin + 1;
+ int dstA = acrossMax - acrossMin + 1;
+
+ int a1D = a1DownMax - a1DownMin + 1;
+ int a1A = a1AcrossMax - a1AcrossMin + 1;
+ int a2D = a2DownMax - a2DownMin + 1;
+ int a2A = a2AcrossMax - a2AcrossMin + 1;
+
+ id = readVar(array);
+ if (id == 0) {
+ defineArray(array, kDwordArray, downMin, downMax, acrossMin, acrossMax);
+ }
- for (; a1_dim2start <= a1_dim2end; ++a1_dim2start, ++a2_dim2start, ++dim2start) {
- int a2dim1 = a2_dim1start;
- int a1dim1 = a1_dim1start;
- int dim1 = dim1start;
- for (; a1dim1 <= a1_dim1end; ++a1dim1, ++a2dim1, ++dim1) {
- int val1 = readArray(array1, a1_dim2start, a1dim1);
- int val2 = readArray(array2, a2_dim2start, a2dim1);
- int res;
-
- switch (type) {
- case 1: // Addition
- res = val2 + val1;
- break;
- case 2: // Subtraction
- res = val2 - val1;
- break;
- case 3: // Binary AND
- res = val2 & val1;
- break;
- case 4: // Binary OR
- res = val2 | val1;
- break;
- case 5: // Binary XOR
- res = val2 ^ val1;
- break;
- default:
- error("o72_arrayOps: case 138 unknown type %d)", type);
- }
- writeArray(array, dim2start, dim1, res);
- }
- }
+ if (a1D != a2D || a1D != dstD || a1A != a2A || a1A != dstA) {
+ error("Operation dataOffsetPtr mismatch (%d vs %d)(%d vs %d)", a1D, a2D, a1A, a2A);
+ }
+
+ switch (mathOperationType) {
+ case 1: // Addition
+ arrayBlockOperation(
+ array, downMin, downMax, acrossMin, acrossMax,
+ a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax,
+ a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax,
+ arrayBlockAddOp);
+ break;
+
+ case 2: // Subtraction
+ arrayBlockOperation(
+ array, downMin, downMax, acrossMin, acrossMax,
+ a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax,
+ a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax,
+ arrayBlockSubOp);
+ break;
+
+ case 3: // Binary AND
+ arrayBlockOperation(
+ array, downMin, downMax, acrossMin, acrossMax,
+ a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax,
+ a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax,
+ arrayBlockBANDOp);
+ break;
+
+ case 4: // Binary OR
+ arrayBlockOperation(
+ array, downMin, downMax, acrossMin, acrossMax,
+ a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax,
+ a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax,
+ arrayBlockBOROp);
+ break;
+
+ case 5: // Binary BXOR
+ arrayBlockOperation(
+ array, downMin, downMax, acrossMin, acrossMax,
+ a2Variable, a2DownMin, a2DownMax, a2AcrossMin, a2AcrossMax,
+ a1Variable, a1DownMin, a1DownMax, a1AcrossMin, a1AcrossMax,
+ arrayBlockBXOROp);
+ break;
+
+ default:
+ error("Invalid array math operation (%d)", mathOperationType);
break;
}
- case SO_FORMATTED_STRING: // SO_FORMATTED_STRING
+
+ break;
+ }
+ case SO_FORMATTED_STRING:
decodeScriptString(string);
len = resStrLen(string);
data = defineArray(array, kStringArray, 0, 0, 0, len);
@@ -1440,7 +1547,7 @@ void ScummEngine_v72he::o72_dimArray() {
void ScummEngine_v72he::o72_dim2dimArray() {
- int data, dim1end, dim2end;
+ int data, acrossMax, downMax;
byte subOp = fetchScriptByte();
@@ -1467,9 +1574,9 @@ void ScummEngine_v72he::o72_dim2dimArray() {
error("o72_dim2dimArray: default case %d", subOp);
}
- dim1end = pop();
- dim2end = pop();
- defineArray(fetchScriptWord(), data, 0, dim2end, 0, dim1end);
+ acrossMax = pop();
+ downMax = pop();
+ defineArray(fetchScriptWord(), data, 0, downMax, 0, acrossMax);
}
void ScummEngine_v72he::o72_traceStatus() {
@@ -1633,8 +1740,8 @@ void ScummEngine_v72he::o72_readFile() {
void ScummEngine_v72he::writeFileFromArray(int slot, int32 resID) {
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resID);
- int32 size = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
- (FROM_LE_32(ah->dim2end) - FROM_LE_32(ah->dim2start) + 1);
+ int32 size = (FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1) *
+ (FROM_LE_32(ah->downMax) - FROM_LE_32(ah->downMin) + 1);
if (slot != -1) {
_hOutFileTable[slot]->write(ah->data, size);
@@ -1762,7 +1869,7 @@ void ScummEngine_v72he::o72_getPixel() {
void ScummEngine_v72he::o72_pickVarRandom() {
int num;
int args[100];
- int32 dim1end;
+ int32 acrossMax;
num = getStackList(args, ARRAYSIZE(args));
int value = fetchScriptWord();
@@ -1785,11 +1892,11 @@ void ScummEngine_v72he::o72_pickVarRandom() {
num = readArray(value, 0, 0);
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(value));
- dim1end = FROM_LE_32(ah->dim1end);
+ acrossMax = FROM_LE_32(ah->acrossMax);
- if (dim1end < num) {
+ if (acrossMax < num) {
int32 var_2 = readArray(value, 0, num - 1);
- shuffleArray(value, 1, dim1end);
+ shuffleArray(value, 1, acrossMax);
if (readArray(value, 0, 1) == var_2) {
num = 2;
} else {
@@ -1826,134 +1933,170 @@ void ScummEngine_v72he::o72_redimArray() {
void ScummEngine_v72he::redimArray(int arrayId, int newDim2start, int newDim2end,
int newDim1start, int newDim1end, int type) {
int newSize, oldSize;
-
- if (readVar(arrayId) == 0)
+ int rawArray = readVar(arrayId);
+ if (rawArray == 0)
error("redimArray: Reference to zeroed array pointer");
- ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(arrayId));
+ if (_game.heversion >= 80) {
+ if ((rawArray & MAGIC_ARRAY_NUMBER) != MAGIC_ARRAY_NUMBER) {
+ error("redimArray: Illegal array pointer not having magic number (%d,%d)", arrayId, rawArray);
+ }
+
+ rawArray &= ~MAGIC_ARRAY_NUMBER;
+ }
+
+ ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, rawArray);
if (!ah)
- error("redimArray: Invalid array (%d) reference", readVar(arrayId));
+ error("redimArray: Invalid array (%d) reference", rawArray);
- newSize = arrayDataSizes[type];
- oldSize = arrayDataSizes[FROM_LE_32(ah->type)];
+ newSize = arrayDataSizes[type] / 8;
+ oldSize = arrayDataSizes[FROM_LE_32(ah->type)] / 8;
newSize *= (newDim1end - newDim1start + 1) * (newDim2end - newDim2start + 1);
- oldSize *= (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
- (FROM_LE_32(ah->dim2end) - FROM_LE_32(ah->dim2start) + 1);
-
- newSize >>= 3;
- oldSize >>= 3;
+ oldSize *= (FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1) *
+ (FROM_LE_32(ah->downMax) - FROM_LE_32(ah->downMin) + 1);
if (newSize != oldSize)
- error("redimArray: array %d redim mismatch", readVar(arrayId));
+ error("redimArray: array %d redim mismatch", rawArray);
ah->type = TO_LE_32(type);
- ah->dim1start = TO_LE_32(newDim1start);
- ah->dim1end = TO_LE_32(newDim1end);
- ah->dim2start = TO_LE_32(newDim2start);
- ah->dim2end = TO_LE_32(newDim2end);
+ ah->acrossMin = TO_LE_32(newDim1start);
+ ah->acrossMax = TO_LE_32(newDim1end);
+ ah->downMin = TO_LE_32(newDim2start);
+ ah->downMax = TO_LE_32(newDim2end);
}
-void ScummEngine_v72he::checkArrayLimits(int array, int dim2start, int dim2end, int dim1start, int dim1end) {
- if (dim1end < dim1start) {
- error("Across max %d smaller than min %d", dim1end, dim1start);
+void ScummEngine_v72he::checkArrayLimits(int array, int downMin, int downMax, int acrossMin, int acrossMax) {
+ if (acrossMax < acrossMin) {
+ error("Across max %d smaller than min %d", acrossMax, acrossMin);
}
- if (dim2end < dim2start) {
- error("Down max %d smaller than min %d", dim2end, dim2start);
+
+ if (downMax < downMin) {
+ error("Down max %d smaller than min %d", downMax, downMin);
}
+
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array));
assert(ah);
- if ((int)FROM_LE_32(ah->dim2start) > dim2start || (int)FROM_LE_32(ah->dim2end) < dim2end || (int)FROM_LE_32(ah->dim1start) > dim1start || (int)FROM_LE_32(ah->dim1end) < dim1end) {
- error("Invalid array access (%d,%d,%d,%d) limit (%d,%d,%d,%d)", dim2start, dim2end, dim1start, dim1end, FROM_LE_32(ah->dim2start), FROM_LE_32(ah->dim2end), FROM_LE_32(ah->dim1start), FROM_LE_32(ah->dim1end));
- }
-}
-
-void ScummEngine_v72he::copyArray(int array1, int a1_dim2start, int a1_dim2end, int a1_dim1start, int a1_dim1end,
- int array2, int a2_dim2start, int a2_dim2end, int a2_dim1start, int a2_dim1end)
-{
- byte *dst, *src;
- int dstPitch, srcPitch;
- int rowSize;
- checkArrayLimits(array1, a1_dim2start, a1_dim2end, a1_dim1start, a1_dim1end);
- checkArrayLimits(array2, a2_dim2start, a2_dim2end, a2_dim1start, a2_dim1end);
- int a12_num = a1_dim2end - a1_dim2start + 1;
- int a11_num = a1_dim1end - a1_dim1start + 1;
- int a22_num = a2_dim2end - a2_dim2start + 1;
- int a21_num = a2_dim1end - a2_dim1start + 1;
- if (a22_num != a12_num || a21_num != a11_num) {
- error("Operation size mismatch (%d vs %d)(%d vs %d)", a12_num, a22_num, a11_num, a21_num);
- }
-
- if (array1 != array2) {
- ArrayHeader *ah1 = (ArrayHeader *)getResourceAddress(rtString, readVar(array1));
- assert(ah1);
- ArrayHeader *ah2 = (ArrayHeader *)getResourceAddress(rtString, readVar(array2));
- assert(ah2);
- if (FROM_LE_32(ah1->type) == FROM_LE_32(ah2->type)) {
- copyArrayHelper(ah1, a1_dim2start, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize);
- copyArrayHelper(ah2, a2_dim2start, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize);
- for (; a1_dim2start <= a1_dim2end; ++a1_dim2start) {
- memcpy(dst, src, rowSize);
- dst += dstPitch;
- src += srcPitch;
+ if ((int)FROM_LE_32(ah->downMin) > downMin || (int)FROM_LE_32(ah->downMax) < downMax || (int)FROM_LE_32(ah->acrossMin) > acrossMin || (int)FROM_LE_32(ah->acrossMax) < acrossMax) {
+ error("Invalid array access (%d,%d,%d,%d) limit (%d,%d,%d,%d)", downMin, downMax, acrossMin, acrossMax, FROM_LE_32(ah->downMin), FROM_LE_32(ah->downMax), FROM_LE_32(ah->acrossMin), FROM_LE_32(ah->acrossMax));
+ }
+}
+
+void ScummEngine_v72he::copyArray(int dstVariable, int dstDownMin, int dstDownMax, int dstAcrossMin, int dstAcrossMax,
+ int srcVariable, int srcDownMin, int srcDownMax, int srcAcrossMin, int srcAcrossMax) {
+ byte *dstPtr, *srcPtr;
+ int dstOffset, srcOffset;
+ int dataSize;
+
+ checkArrayLimits(dstVariable, dstDownMin, dstDownMax, dstAcrossMin, dstAcrossMax);
+ checkArrayLimits(srcVariable, srcDownMin, srcDownMax, srcAcrossMin, srcAcrossMax);
+
+ int dstDownCount = dstDownMax - dstDownMin + 1;
+ int dstAcrossCount = dstAcrossMax - dstAcrossMin + 1;
+ int srcDownCount = srcDownMax - srcDownMin + 1;
+ int srcAcrossCount = srcAcrossMax - srcAcrossMin + 1;
+
+ if (srcDownCount != dstDownCount || srcAcrossCount != dstAcrossCount) {
+ error("Operation dataOffsetPtr mismatch (%d vs %d)(%d vs %d)", dstDownCount, srcDownCount, dstAcrossCount, srcAcrossCount);
+ }
+
+ if (dstVariable != srcVariable) {
+ ArrayHeader *dstArray = (ArrayHeader *)getResourceAddress(rtString, readVar(dstVariable));
+ assert(dstArray);
+ ArrayHeader *srcArray = (ArrayHeader *)getResourceAddress(rtString, readVar(srcVariable));
+ assert(srcArray);
+
+ if (FROM_LE_32(dstArray->type) == FROM_LE_32(srcArray->type)) {
+ getArrayDataPtrAndDataSize(dstArray, dstDownMin, dstAcrossMin, dstAcrossMax, &dstPtr, &dstOffset, &dataSize);
+ getArrayDataPtrAndDataSize(srcArray, srcDownMin, srcAcrossMin, srcAcrossMax, &srcPtr, &srcOffset, &dataSize);
+
+ for (int dstDownCounter = dstDownMin; dstDownCounter <= dstDownMax; dstDownCounter++) {
+ memcpy(dstPtr, srcPtr, dataSize);
+ dstPtr += dstOffset;
+ srcPtr += srcOffset;
}
} else {
- for (; a1_dim2start <= a1_dim2end; ++a1_dim2start, ++a2_dim2start) {
- int a2dim1 = a2_dim1start;
- int a1dim1 = a1_dim1start;
- for (; a1dim1 <= a1_dim1end; ++a1dim1, ++a2dim1) {
- int val = readArray(array2, a2_dim2start, a2dim1);
- writeArray(array1, a1_dim2start, a1dim1, val);
+ int srcDownIndex = srcDownMin;
+
+ for (int dstDownCounter = dstDownMin; dstDownCounter <= dstDownMax; dstDownCounter++) {
+ int srcAcrossIndex = srcAcrossMin;
+
+ for (int dstAcrossCounter = dstAcrossMin; dstAcrossCounter <= dstAcrossMax; dstAcrossCounter++) {
+ writeArray(dstVariable, dstDownMin, dstAcrossCounter,
+ readArray(srcVariable, srcDownMin, srcAcrossIndex++));
}
+
+ srcDownIndex++;
}
}
} else {
- if (a2_dim2start != a1_dim2start || a2_dim1start != a1_dim1start) {
- ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array1));
- assert(ah);
- if (a2_dim2start > a1_dim2start) {
- copyArrayHelper(ah, a1_dim2start, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize);
- copyArrayHelper(ah, a2_dim2start, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize);
+ if (srcDownMin != dstDownMin || srcAcrossMin != dstAcrossMin) {
+ int dstArray = readVar(dstVariable);
+
+ ArrayHeader *dstArrayPtr = (ArrayHeader *)getResourceAddress(rtString, dstArray & ~MAGIC_ARRAY_NUMBER);
+ ArrayHeader *srcArrayPtr = dstArrayPtr;
+
+ if (!dstArrayPtr) {
+ error("Missing array (%d,%d,4) reference", (dstArray & ~MAGIC_ARRAY_NUMBER), dstArray);
+ }
+
+ bool useMemcpy = false;
+
+ // Calculate the check for overlap or flipped reads on src and dst pointers
+ // and setup the copy operation variables...
+ if ((dstDownMin < srcDownMin) || (_game.heversion > 99 || _isHE995)) {
+ useMemcpy = true;
+
+ getArrayDataPtrAndDataSize(dstArrayPtr, dstDownMin, dstAcrossMin, dstAcrossMax, &dstPtr, &dstOffset, &dataSize);
+ getArrayDataPtrAndDataSize(srcArrayPtr, srcDownMin, srcAcrossMin, srcAcrossMax, &srcPtr, &srcOffset, &dataSize);
} else {
- // start at the end, so we copy backwards (in case the indices overlap)
- copyArrayHelper(ah, a1_dim2end, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize);
- copyArrayHelper(ah, a2_dim2end, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize);
- dstPitch = -dstPitch;
- srcPitch = -srcPitch;
+ getArrayDataPtrAndDataSize(dstArrayPtr, dstDownMax, dstAcrossMin, dstAcrossMax, &dstPtr, &dstOffset, &dataSize);
+ getArrayDataPtrAndDataSize(srcArrayPtr, srcDownMax, srcAcrossMin, srcAcrossMax, &srcPtr, &srcOffset, &dataSize);
+
+ useMemcpy = (dstAcrossMin <= srcAcrossMin);
}
- for (; a1_dim2start <= a1_dim2end; ++a1_dim2start) {
- memcpy(dst, src, rowSize);
- dst += dstPitch;
- src += srcPitch;
+
+ if (useMemcpy) {
+ for (int dstDownCounter = dstDownMin; dstDownCounter <= dstDownMax; dstDownCounter++) {
+ memcpy(dstPtr, srcPtr, dataSize);
+ dstPtr += dstOffset;
+ srcPtr += srcOffset;
+ }
+ } else {
+ for (int dstDownCounter = dstDownMin; dstDownCounter <= dstDownMax; dstDownCounter++) {
+ memmove(dstPtr, srcPtr, dataSize);
+ dstPtr += dstOffset;
+ srcPtr += srcOffset;
+ }
}
}
}
}
-void ScummEngine_v72he::copyArrayHelper(ArrayHeader *ah, int idx2, int idx1, int len1, byte **data, int *size, int *num) {
- const int pitch = FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1;
- const int offset = pitch * (idx2 - FROM_LE_32(ah->dim2start)) + idx1 - FROM_LE_32(ah->dim1start);
+void ScummEngine_v72he::getArrayDataPtrAndDataSize(ArrayHeader *headerPtr, int down, int aMin, int aMax, byte **ptrPtr, int *dataOffsetPtr, int *dataSizePtr) {
+ const int acrossCount = FROM_LE_32(headerPtr->acrossMax) - FROM_LE_32(headerPtr->acrossMin) + 1;
+ const int index = acrossCount * (down - FROM_LE_32(headerPtr->downMin)) + aMin - FROM_LE_32(headerPtr->acrossMin);
- switch (FROM_LE_32(ah->type)) {
+ switch (FROM_LE_32(headerPtr->type)) {
case kByteArray:
case kStringArray:
- *num = len1 - idx1 + 1;
- *size = pitch;
- *data = ah->data + offset;
+ *dataSizePtr = aMax - aMin + 1;
+ *dataOffsetPtr = acrossCount;
+ *ptrPtr = headerPtr->data + index;
break;
case kIntArray:
- *num = (len1 - idx1) * 2 + 2;
- *size = pitch * 2;
- *data = ah->data + offset * 2;
+ *dataSizePtr = (aMax - aMin) * 2 + 2;
+ *dataOffsetPtr = acrossCount * 2;
+ *ptrPtr = headerPtr->data + index * 2;
break;
case kDwordArray:
- *num = (len1 - idx1) * 4 + 4;
- *size = pitch * 4;
- *data = ah->data + offset * 4;
+ *dataSizePtr = (aMax - aMin) * 4 + 4;
+ *dataOffsetPtr = acrossCount * 4;
+ *ptrPtr = headerPtr->data + index * 4;
break;
default:
- error("Invalid array type %d", FROM_LE_32(ah->type));
+ error("Invalid array type %d", FROM_LE_32(headerPtr->type));
}
}
diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp
index b10fac58e76..d4ca3db057e 100644
--- a/engines/scumm/he/script_v80he.cpp
+++ b/engines/scumm/he/script_v80he.cpp
@@ -500,7 +500,7 @@ void ScummEngine_v80he::o80_drawLine() {
void ScummEngine_v80he::o80_pickVarRandom() {
int num;
int args[100];
- int32 dim1end;
+ int32 acrossMax;
num = getStackList(args, ARRAYSIZE(args));
int value = fetchScriptWord();
@@ -528,13 +528,13 @@ void ScummEngine_v80he::o80_pickVarRandom() {
num = readArray(value, 0, 0);
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(value));
- dim1end = FROM_LE_32(ah->dim1end);
+ acrossMax = FROM_LE_32(ah->acrossMax);
- if (dim1end < num) {
+ if (acrossMax < num) {
int32 var_2 = readArray(value, 0, num - 1);
- shuffleArray(value, 1, dim1end);
+ shuffleArray(value, 1, acrossMax);
num = 1;
- if (readArray(value, 0, 1) == var_2 && dim1end >= 3) {
+ if (readArray(value, 0, 1) == var_2 && acrossMax >= 3) {
int32 tmp = readArray(value, 0, 2);
writeArray(value, 0, num, tmp);
writeArray(value, 0, 2, var_2);
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index aca2931ce6f..8cafde5677d 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -1826,7 +1826,7 @@ void ScummEngine_v90he::o90_cond() {
}
void ScummEngine_v90he::o90_dim2dim2Array() {
- int data, dim1start, dim1end, dim2start, dim2end;
+ int data, acrossMin, acrossMax, downMin, downMax;
byte subOp = fetchScriptByte();
@@ -1854,18 +1854,18 @@ void ScummEngine_v90he::o90_dim2dim2Array() {
}
if (pop() == 2) {
- dim1end = pop();
- dim1start = pop();
- dim2end = pop();
- dim2start = pop();
+ acrossMax = pop();
+ acrossMin = pop();
+ downMax = pop();
+ downMin = pop();
} else {
- dim2end = pop();
- dim2start = pop();
- dim1end = pop();
- dim1start = pop();
+ downMax = pop();
+ downMin = pop();
+ acrossMax = pop();
+ acrossMin = pop();
}
- defineArray(fetchScriptWord(), data, dim2start, dim2end, dim1start, dim1end);
+ defineArray(fetchScriptWord(), data, downMin, downMax, acrossMin, acrossMax);
}
void ScummEngine_v90he::o90_redim2dimArray() {
@@ -2032,20 +2032,20 @@ void ScummEngine_v90he::o90_getLinesIntersectionPoint() {
push(0);
}
-void ScummEngine_v90he::getArrayDim(int array, int *dim2start, int *dim2end, int *dim1start, int *dim1end) {
+void ScummEngine_v90he::getArrayDim(int array, int *downMin, int *downMax, int *acrossMin, int *acrossMax) {
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array));
assert(ah);
- if (dim2start && *dim2start == -1) {
- *dim2start = FROM_LE_32(ah->dim2start);
+ if (downMin && *downMin == -1) {
+ *downMin = FROM_LE_32(ah->downMin);
}
- if (dim2end && *dim2end == -1) {
- *dim2end = FROM_LE_32(ah->dim2end);
+ if (downMax && *downMax == -1) {
+ *downMax = FROM_LE_32(ah->downMax);
}
- if (dim1start && *dim1start == -1) {
- *dim1start = FROM_LE_32(ah->dim1start);
+ if (acrossMin && *acrossMin == -1) {
+ *acrossMin = FROM_LE_32(ah->acrossMin);
}
- if (dim1end && *dim1end == -1) {
- *dim1end = FROM_LE_32(ah->dim1end);
+ if (acrossMax && *acrossMax == -1) {
+ *acrossMax = FROM_LE_32(ah->acrossMax);
}
}
@@ -2091,21 +2091,21 @@ static int compareDwordArrayReverse(const void *a, const void *b) {
/**
* Sort a row range in a two-dimensional array by the value in a given column.
*
- * We sort the data in the row range [dim2start..dim2end], according to the value
- * in column dim1start == dim1end.
+ * We sort the data in the row range [downMin..downMax], according to the value
+ * in column acrossMin == acrossMax.
*/
-void ScummEngine_v90he::sortArray(int array, int dim2start, int dim2end, int dim1start, int dim1end, int sortOrder) {
- debug(9, "sortArray(%d, [%d,%d,%d,%d], %d)", array, dim2start, dim2end, dim1start, dim1end, sortOrder);
+void ScummEngine_v90he::sortArray(int array, int downMin, int downMax, int acrossMin, int acrossMax, int sortOrder) {
+ debug(9, "sortArray(%d, [%d,%d,%d,%d], %d)", array, downMin, downMax, acrossMin, acrossMax, sortOrder);
- assert(dim1start == dim1end);
- checkArrayLimits(array, dim2start, dim2end, dim1start, dim1end);
+ assert(acrossMin == acrossMax);
+ checkArrayLimits(array, downMin, downMax, acrossMin, acrossMax);
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array));
assert(ah);
- const int num = dim2end - dim2start + 1; // number of rows to sort
- const int pitch = FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1; // length of a row = number of columns in it
- const int offset = pitch * (dim2start - FROM_LE_32(ah->dim2start)); // memory offset to the first row to be sorted
- sortArrayOffset = dim1start - FROM_LE_32(ah->dim1start); // offset to the column by which we sort
+ const int num = downMax - downMin + 1; // number of rows to sort
+ const int pitch = FROM_LE_32(ah->acrossMax) - FROM_LE_32(ah->acrossMin) + 1; // length of a row = number of columns in it
+ const int offset = pitch * (downMin - FROM_LE_32(ah->downMin)); // memory offset to the first row to be sorted
+ sortArrayOffset = acrossMin - FROM_LE_32(ah->acrossMin); // offset to the column by which we sort
// Now we just have to invoke qsort on the appropriate row range. We
// need to pass sortArrayOffset as an implicit parameter to the
@@ -2154,12 +2154,12 @@ void ScummEngine_v90he::o90_sortArray() {
{
int array = fetchScriptWord();
int sortOrder = pop();
- int dim1end = pop();
- int dim1start = pop();
- int dim2end = pop();
- int dim2start = pop();
- getArrayDim(array, &dim2start, &dim2end, &dim1start, &dim1end);
- sortArray(array, dim2start, dim2end, dim1start, dim1end, sortOrder);
+ int acrossMax = pop();
+ int acrossMin = pop();
+ int downMax = pop();
+ int downMin = pop();
+ getArrayDim(array, &downMin, &downMax, &acrossMin, &acrossMax);
+ sortArray(array, downMin, downMax, acrossMin, acrossMax, sortOrder);
}
break;
default:
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index bfabde42494..b37902dedb1 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -763,7 +763,7 @@ byte *ScummEngine::getResourceAddress(ResType type, ResId idx) {
byte *ptr;
if (_game.heversion >= 80 && type == rtString)
- idx &= ~0x33539000;
+ idx &= ~MAGIC_ARRAY_NUMBER;
if (!_res->validateResource("getResourceAddress", type, idx))
return nullptr;
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index b4918bd5259..778f00d276b 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -25,6 +25,7 @@
#include "scumm/actor.h"
#include "scumm/charset.h"
#include "scumm/file.h"
+#include "scumm/he/intern_he.h"
#include "scumm/imuse/imuse.h"
#include "scumm/imuse_digi/dimuse_engine.h"
#include "scumm/insane/insane.h"
@@ -345,7 +346,7 @@ void ScummEngine_v6::nukeArray(int a) {
data = readVar(a);
if (_game.heversion >= 80)
- data &= ~0x33539000;
+ data &= ~MAGIC_ARRAY_NUMBER;
if (data)
_res->nukeResource(rtString, data);
@@ -3505,15 +3506,21 @@ void ScummEngine_v6::o6_findAllObjects() {
push(readVar(0));
}
-void ScummEngine_v6::shuffleArray(int num, int minIdx, int maxIdx) {
+void ScummEngine_v6::shuffleArray(int num, int minIdx, int maxIdx) {
+ int rand1, rand2;
int range = maxIdx - minIdx;
int count = range * 2;
-
+
// Shuffle the array 'num'
while (count--) {
// Determine two random elements...
- int rand1 = _rnd.getRandomNumber(range) + minIdx;
- int rand2 = _rnd.getRandomNumber(range) + minIdx;
+ if (_game.heversion >= 72) {
+ rand1 = VAR(VAR_RANDOM_NR) = _rnd.getRandomNumberRng(minIdx, maxIdx);
+ rand2 = VAR(VAR_RANDOM_NR) = _rnd.getRandomNumberRng(minIdx, maxIdx);
+ } else {
+ rand1 = _rnd.getRandomNumber(range) + minIdx;
+ rand2 = _rnd.getRandomNumber(range) + minIdx;
+ }
// ...and swap them
int val1 = readArray(num, 0, rand1);
More information about the Scummvm-git-logs
mailing list