aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/array.h73
-rw-r--r--dists/macosx/scummvm_appcast.xml10
-rw-r--r--engines/agi/graphics.cpp6
-rw-r--r--engines/scumm/he/logic/moonbase_logic.cpp25
-rw-r--r--engines/scumm/he/moonbase/ai_main.cpp4
-rw-r--r--engines/scumm/he/moonbase/ai_main.h2
-rw-r--r--engines/scumm/he/moonbase/ai_tree.cpp53
-rw-r--r--engines/scumm/he/moonbase/ai_tree.h13
8 files changed, 143 insertions, 43 deletions
diff --git a/common/array.h b/common/array.h
index db1a62ba34..869d79b68b 100644
--- a/common/array.h
+++ b/common/array.h
@@ -361,6 +361,79 @@ protected:
};
+/**
+ * Double linked list with sorted nodes.
+ */
+template<class T>
+class SortedArray : public Array<T> {
+public:
+ typedef T *iterator;
+ typedef uint size_type;
+
+ SortedArray(int (*comparator)(const void *, const void *)) {
+ _comparator = comparator;
+ }
+
+ /**
+ * Inserts element at the sorted position.
+ */
+ void insert(const T &element) {
+ T *where = (T *)bsearchMin(element, this->front(), this->_size, sizeof(T), _comparator);
+ insert(where, element);
+ }
+
+ T &operator[](size_type idx) {
+ error("Operation not allowed with SortedArray");
+ }
+
+ void insert_at(size_type idx, const T &element) {
+ error("Operation not allowed with SortedArray");
+ }
+
+ void insert_at(size_type idx, const Array<T> &array) {
+ error("Operation not allowed with SortedArray");
+ }
+
+ void insert(iterator pos, const T &element) {
+ error("Operation not allowed with SortedArray");
+ }
+
+ void push_back(const T &element) {
+ error("Operation not allowed with SortedArray");
+ }
+
+ void push_back(const Array<T> &array) {
+ error("Operation not allowed with SortedArray");
+ }
+
+private:
+ // Based on code Copyright (C) 2008-2009 Ksplice, Inc.
+ // Author: Tim Abbott <tabbott@ksplice.com>
+ // Licensed under GPLv2+
+ void *bsearchMin(const void *key, const void *base, uint num, uint size,
+ int (*cmp)(const void *key, const void *elt)) {
+ uint start = 0, end = num;
+ int result;
+
+ while (start < end) {
+ uint mid = start + (end - start) / 2;
+
+ result = cmp(key, (byte *)base + mid * size);
+ if (result < 0)
+ end = mid;
+ else if (result > 0)
+ start = mid + 1;
+ else
+ return (void *)((byte *)base + mid * size);
+ }
+
+ return (void *)((byte *)base + start * size);
+ }
+
+private:
+ int (*_comparator)(const void *, const void *);
+};
+
} // End of namespace Common
#endif
diff --git a/dists/macosx/scummvm_appcast.xml b/dists/macosx/scummvm_appcast.xml
index 3d47c94bbc..35fbc54908 100644
--- a/dists/macosx/scummvm_appcast.xml
+++ b/dists/macosx/scummvm_appcast.xml
@@ -6,6 +6,16 @@
<description>Most recent changes with links to updates.</description>
<language>en</language>
<item>
+ <title>Version 1.8.1</title>
+ <sparkle:releaseNotesLink>
+ https://scummvm.org/frs/scummvm/1.8.1/ReleaseNotes
+ </sparkle:releaseNotesLink>
+ <pubDate>Wed, 25 May 2016 19:26:00 +0000</pubDate>
+ <enclosure url="https://www.scummvm.org/frs/scummvm/1.8.1/scummvm-1.8.1-macosx.dmg"
+ sparkle:version="1.8.1" length="15791070" type="application/octet-stream"
+ sparkle:dsaSignature="MC0CFQDF0u/pGH51pMPzCbsv07eCNxuGDQIUdrKWVTznbF69fzuzIieR4Lc0U2Y=" />
+ </item>
+ <item>
<title>Version 1.8.0</title>
<sparkle:releaseNotesLink>
https://scummvm.org/frs/scummvm/1.8.0/ReleaseNotes
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 6d3563a451..c7d643d6a0 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -1178,13 +1178,17 @@ void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte
#define SHAKE_HORIZONTAL_PIXELS 4
// Sierra used some EGA port trickery to do it, we have to do it by copying pixels around
+//
+// Shaking locations:
+// - Fanmade "Enclosure" right during the intro
+// - Space Quest 2 almost right at the start when getting captured (after walking into the space ship)
void GfxMgr::shakeScreen(int16 repeatCount) {
int shakeNr, shakeCount;
uint8 *blackSpace;
int16 shakeHorizontalPixels = SHAKE_HORIZONTAL_PIXELS * (2 + _displayWidthMulAdjust);
int16 shakeVerticalPixels = SHAKE_VERTICAL_PIXELS * (1 + _displayHeightMulAdjust);
- if ((blackSpace = (uint8 *)calloc(shakeVerticalPixels * _displayScreenWidth, 1)) == NULL)
+ if ((blackSpace = (uint8 *)calloc(shakeHorizontalPixels * _displayScreenWidth, 1)) == NULL)
return;
shakeCount = repeatCount * 8; // effectively 4 shakes per repeat
diff --git a/engines/scumm/he/logic/moonbase_logic.cpp b/engines/scumm/he/logic/moonbase_logic.cpp
index a32356614f..d5100cef71 100644
--- a/engines/scumm/he/logic/moonbase_logic.cpp
+++ b/engines/scumm/he/logic/moonbase_logic.cpp
@@ -23,6 +23,7 @@
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/he/moonbase/moonbase.h"
+#include "scumm/he/moonbase/ai_main.h"
namespace Scumm {
@@ -48,7 +49,7 @@ private:
int op_set_fow_image(int op, int numArgs, int32 *args);
void op_ai_test_kludge(int op, int numArgs, int32 *args);
- void op_ai_master_control_program(int op, int numArgs, int32 *args);
+ int op_ai_master_control_program(int op, int numArgs, int32 *args);
void op_ai_reset(int op, int numArgs, int32 *args);
void op_ai_set_type(int op, int numArgs, int32 *args);
void op_ai_clean_up(int op, int numArgs, int32 *args);
@@ -137,14 +138,12 @@ int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) {
break;
case OP_SET_FOW_IMAGE:
return op_set_fow_image(op, numArgs, args);
- break;
case OP_AI_TEST_KLUDGE:
op_ai_test_kludge(op, numArgs, args);
break;
case OP_AI_MASTER_CONTROL_PROGRAM:
- op_ai_master_control_program(op, numArgs, args);
- break;
+ return op_ai_master_control_program(op, numArgs, args);
case OP_AI_RESET:
op_ai_reset(op, numArgs, args);
break;
@@ -226,24 +225,24 @@ void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) {
LogicHE::dispatch(op, numArgs, args);
}
-void LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) {
- warning("STUB: op_ai_master_control_program()");
- LogicHE::dispatch(op, numArgs, args);
+int LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) {
+ warning("op_ai_master_control_program()");
+ return masterControlProgram(numArgs, args);
}
void LogicHEmoonbase::op_ai_reset(int op, int numArgs, int32 *args) {
- warning("STUB: op_ai_reset)");
- LogicHE::dispatch(op, numArgs, args);
+ warning("op_ai_reset())");
+ resetAI(_vm);
}
void LogicHEmoonbase::op_ai_set_type(int op, int numArgs, int32 *args) {
- warning("STUB: op_ai_set_type()");
- LogicHE::dispatch(op, numArgs, args);
+ warning("op_ai_set_type()");
+ setAIType(numArgs, args);
}
void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) {
- warning("STUB: op_ai_clean_up()");
- LogicHE::dispatch(op, numArgs, args);
+ warning("op_ai_clean_up()");
+ cleanUpAI();
}
LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) {
diff --git a/engines/scumm/he/moonbase/ai_main.cpp b/engines/scumm/he/moonbase/ai_main.cpp
index 1a191a1328..6844d2f7dd 100644
--- a/engines/scumm/he/moonbase/ai_main.cpp
+++ b/engines/scumm/he/moonbase/ai_main.cpp
@@ -168,7 +168,9 @@ const int *MCP_params;
Common::Array<int> lastXCoord[5];
Common::Array<int> lastYCoord[5];
-void resetAI() {
+void resetAI(ScummEngine_v90he *vm) {
+ _vm = vm;
+
AIstate = STATE_CHOOSE_BEHAVIOR;
warning("----------------------> Resetting AI");
diff --git a/engines/scumm/he/moonbase/ai_main.h b/engines/scumm/he/moonbase/ai_main.h
index 4937eced0f..7b5ad3ca40 100644
--- a/engines/scumm/he/moonbase/ai_main.h
+++ b/engines/scumm/he/moonbase/ai_main.h
@@ -86,7 +86,7 @@ enum {
static int energyHogType = 0;
-void resetAI();
+void resetAI(ScummEngine_v90he *vm);
void cleanUpAI();
void setAIType(const int paramCount, const int *params);
int masterControlProgram(const int paramCount, const int *params);
diff --git a/engines/scumm/he/moonbase/ai_tree.cpp b/engines/scumm/he/moonbase/ai_tree.cpp
index efbf3e3a99..7bd44f6644 100644
--- a/engines/scumm/he/moonbase/ai_tree.cpp
+++ b/engines/scumm/he/moonbase/ai_tree.cpp
@@ -25,10 +25,16 @@
namespace Scumm {
+static int compareTreeNodes(const void *a, const void *b) {
+ return ((const TreeNode *)a)->value - ((const TreeNode *)b)->value;
+}
+
Tree::Tree() {
pBaseNode = new Node;
_maxDepth = MAX_DEPTH;
_maxNodes = MAX_NODES;
+
+ _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
}
Tree::Tree(IContainedObject *contents) {
@@ -36,6 +42,8 @@ Tree::Tree(IContainedObject *contents) {
pBaseNode->setContainedObject(contents);
_maxDepth = MAX_DEPTH;
_maxNodes = MAX_NODES;
+
+ _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
}
Tree::Tree(IContainedObject *contents, int maxDepth) {
@@ -43,6 +51,8 @@ Tree::Tree(IContainedObject *contents, int maxDepth) {
pBaseNode->setContainedObject(contents);
_maxDepth = maxDepth;
_maxNodes = MAX_NODES;
+
+ _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
}
Tree::Tree(IContainedObject *contents, int maxDepth, int maxNodes) {
@@ -50,6 +60,8 @@ Tree::Tree(IContainedObject *contents, int maxDepth, int maxNodes) {
pBaseNode->setContainedObject(contents);
_maxDepth = maxDepth;
_maxNodes = maxNodes;
+
+ _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
}
void Tree::duplicateTree(Node *sourceNode, Node *destNode) {
@@ -68,6 +80,7 @@ Tree::Tree(const Tree *sourceTree) {
pBaseNode = new Node(sourceTree->getBaseNode());
_maxDepth = sourceTree->getMaxDepth();
_maxNodes = sourceTree->getMaxNodes();
+ _currentMap = new Common::SortedArray<TreeNode *>(compareTreeNodes);
duplicateTree(sourceTree->getBaseNode(), pBaseNode);
}
@@ -80,7 +93,6 @@ Tree::~Tree() {
while (pNodeItr != NULL) {
// If any children are left, move to one of them
if (!(pNodeItr->getChildren().empty())) {
- //int size = (pNodeItr->getChildren()).size();
pNodeItr = pNodeItr->popChild();
} else {
// Delete this node, and move up to the parent for further processing
@@ -90,13 +102,12 @@ Tree::~Tree() {
pTemp = NULL;
}
}
-}
+ delete _currentMap;
+}
Node *Tree::aStarSearch() {
- return NULL;
-#if 0
- fnpMMap mmfpOpen;
+ Common::SortedArray<TreeNode *> mmfpOpen(compareTreeNodes);
Node *currentNode = NULL;
float currentT;
@@ -106,24 +117,24 @@ Node *Tree::aStarSearch() {
float temp = pBaseNode->getContainedObject()->calcT();
if (static_cast<int>(temp) != SUCCESS) {
-
- mmfpOpen.insert(fnpMMap::value_type(pBaseNode->getObjectT(), pBaseNode));
+ mmfpOpen.insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode));
while (mmfpOpen.size() && (retNode == NULL)) {
- currentNode = mmfpOpen.begin()->second;
+ currentNode = mmfpOpen.front()->node;
mmfpOpen.erase(mmfpOpen.begin());
if ((currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes)) {
// Generate nodes
- int numChildren = currentNode->generateChildren();
Common::Array<Node *> vChildren = currentNode->getChildren();
for (Common::Array<Node *>::iterator i = vChildren.begin(); i != vChildren.end(); i++) {
IContainedObject *pTemp = (*i)->getContainedObject();
currentT = pTemp->calcT();
- if (currentT == SUCCESS) retNode = *i;
- else mmfpOpen.insert(fnpMMap::value_type(currentT, (*i)));
+ if (currentT == SUCCESS)
+ retNode = *i;
+ else
+ mmfpOpen.insert(new TreeNode(currentT, (*i)));
}
} else {
retNode = currentNode;
@@ -134,7 +145,6 @@ Node *Tree::aStarSearch() {
}
return retNode;
-#endif
}
@@ -146,8 +156,7 @@ Node *Tree::aStarSearch_singlePassInit() {
float temp = pBaseNode->getContainedObject()->calcT();
if (static_cast<int>(temp) != SUCCESS) {
- //_currentMap.insert(fnpMMap::value_type(pBaseNode->getObjectT(), pBaseNode));
- //assert(_currentMap.size());
+ _currentMap->insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode));
} else {
retNode = pBaseNode;
}
@@ -157,10 +166,9 @@ Node *Tree::aStarSearch_singlePassInit() {
Node *Tree::aStarSearch_singlePass(Node **currentNode) {
currentNode = NULL;
+ float currentT;
Node *retNode = NULL;
-#if 0
- float currentT;
static int maxTime = 0;
if (currentChildIndex == 1) {
@@ -168,13 +176,13 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) {
}
if (currentChildIndex) {
- if (!(_currentMap.size())) {
+ if (!(_currentMap->size())) {
retNode = _currentNode;
return retNode;
}
- _currentNode = _currentMap.begin()->second;
- _currentMap.erase(_currentMap.begin());
+ _currentNode = _currentMap->front()->node;
+ _currentMap->erase(_currentMap->begin());
}
if ((_currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes) && ((!maxTime) || (getTimerValue(3) < maxTime))) {
@@ -184,7 +192,7 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) {
if (currentChildIndex) {
Common::Array<Node *> vChildren = _currentNode->getChildren();
- if (!vChildren.size() && !_currentMap.size()) {
+ if (!vChildren.size() && !_currentMap->size()) {
currentChildIndex = 0;
retNode = _currentNode;
}
@@ -197,11 +205,11 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) {
retNode = *i;
i = vChildren.end() - 1;
} else {
- _currentMap.insert(fnpMMap::value_type(currentT, (*i)));
+ _currentMap->insert(new TreeNode(currentT, (*i)));
}
}
- if (!(_currentMap.size()) && (currentT != SUCCESS)) {
+ if (!(_currentMap->size()) && (currentT != SUCCESS)) {
assert(_currentNode != NULL);
retNode = _currentNode;
}
@@ -209,7 +217,6 @@ Node *Tree::aStarSearch_singlePass(Node **currentNode) {
} else {
retNode = _currentNode;
}
-#endif
return retNode;
}
diff --git a/engines/scumm/he/moonbase/ai_tree.h b/engines/scumm/he/moonbase/ai_tree.h
index 1097665a7a..908786ad9a 100644
--- a/engines/scumm/he/moonbase/ai_tree.h
+++ b/engines/scumm/he/moonbase/ai_tree.h
@@ -23,16 +23,21 @@
#ifndef SCUMM_HE_MOONBASE_AI_TREE_H
#define SCUMM_HE_MOONBASE_AI_TREE_H
-#include "common/hash-str.h"
+#include "common/array.h"
#include "scumm/he/moonbase/ai_node.h"
namespace Scumm {
-//typedef std::multimap< float, Node *, std::less<float> > fnpMMap;
-
const int MAX_DEPTH = 100;
const int MAX_NODES = 1000000;
+struct TreeNode {
+ float value;
+ Node *node;
+
+ TreeNode(float v, Node *n) { value = v; node = n; }
+};
+
class Tree {
private:
Node *pBaseNode;
@@ -42,7 +47,7 @@ private:
int currentChildIndex;
- Common::StringMap _currentMap;
+ Common::SortedArray<TreeNode *> *_currentMap;
Node *_currentNode;
public: