aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/hugo/display.cpp22
-rw-r--r--engines/hugo/display.h19
-rw-r--r--engines/hugo/hugo.cpp182
-rw-r--r--engines/hugo/hugo.h32
-rw-r--r--engines/hugo/inventory.h4
-rw-r--r--engines/hugo/object.cpp175
-rw-r--r--engines/hugo/object.h17
-rw-r--r--engines/hugo/object_v1d.cpp18
-rw-r--r--engines/hugo/object_v1w.cpp18
-rw-r--r--engines/hugo/object_v2d.cpp18
-rw-r--r--engines/hugo/object_v3d.cpp18
-rw-r--r--engines/hugo/route.cpp11
-rw-r--r--engines/hugo/route.h9
13 files changed, 265 insertions, 278 deletions
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp
index 09e04a96e1..4d6303305d 100644
--- a/engines/hugo/display.cpp
+++ b/engines/hugo/display.cpp
@@ -199,14 +199,14 @@ void Screen::setBackgroundColor(const uint16 color) {
overlayState_t Screen::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) {
debugC(4, kDebugDisplay, "findOvl()");
- for (; y < seq_p->lines; y++) { // Each line in object
- image_pt ovb_p = _vm->getBaseBoundaryOverlay() + ((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits
- if (*ovb_p & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set
- return FG; // Found a bit - must be foreground
+ for (; y < seq_p->lines; y++) { // Each line in object
+ byte ovb = _vm->_object->getBaseBoundary((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits
+ if (ovb & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set
+ return kOvlForeground; // Found a bit - must be foreground
dst_p += kXPix;
}
- return BG; // No bits set, must be background
+ return kOvlBackground; // No bits set, must be background
}
/**
@@ -218,19 +218,17 @@ void Screen::displayFrame(const int sx, const int sy, seq_t *seq, const bool for
image_pt image = seq->imagePtr; // Ptr to object image data
image_pt subFrontBuffer = &_frontBuffer[sy * kXPix + sx]; // Ptr to offset in _frontBuffer
- image_pt overlay = &_vm->getFirstOverlay()[(sy * kXPix + sx) >> 3]; // Ptr to overlay data
int16 frontBufferwrap = kXPix - seq->x2 - 1; // Wraps dest_p after each line
int16 imageWrap = seq->bytesPerLine8 - seq->x2 - 1;
-
- overlayState_t overlayState = UNDEF; // Overlay state of object
+ overlayState_t overlayState = kOvlUndef; // Overlay state of object
for (uint16 y = 0; y < seq->lines; y++) { // Each line in object
for (uint16 x = 0; x <= seq->x2; x++) {
if (*image) { // Non-transparent
- overlay = _vm->getFirstOverlay() + ((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits
- if (*overlay & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
- if (overlayState == UNDEF) // Overlay defined yet?
+ byte ovlBound = _vm->_object->getFirstOverlay((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits
+ if (ovlBound & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
+ if (overlayState == kOvlUndef) // Overlay defined yet?
overlayState = findOvl(seq, subFrontBuffer, y);// No, find it.
- if (foreFl || overlayState == FG) // Object foreground
+ if (foreFl || overlayState == kOvlForeground) // Object foreground
*subFrontBuffer = *image; // Copy pixel
} else { // No overlay
*subFrontBuffer = *image; // Copy pixel
diff --git a/engines/hugo/display.h b/engines/hugo/display.h
index 29d7bb7722..05a9546243 100644
--- a/engines/hugo/display.h
+++ b/engines/hugo/display.h
@@ -34,13 +34,7 @@
#define HUGO_DISPLAY_H
namespace Hugo {
-enum overlayState_t {UNDEF, FG, BG}; // Overlay state
-
-static const int kShapeSize = 24;
-static const int kFontLength = 128; // Number of chars in font
-static const int kFontSize = 1200; // Max size of font data
-static const int kNumFonts = 3; // Number of dib fonts
-static const int kCenter = -1; // Used to center text in x
+enum overlayState_t {kOvlUndef, kOvlForeground, kOvlBackground}; // Overlay state
struct rect_t { // Rectangle used in Display list
int16 x; // Position in dib
@@ -49,6 +43,8 @@ struct rect_t { // Rectangle used in Display
int16 dy; // height
};
+static const int kCenter = -1; // Used to center text in x
+
/**
* A black and white Windows-style arrow cursor (12x20).
* 0 = Black (#000000 in 24-bit RGB).
@@ -56,7 +52,6 @@ struct rect_t { // Rectangle used in Display
* 15 = White (#FFFFFF in 24-bit RGB).
* This cursor comes from Mohawk engine.
*/
-
static const byte stdMouseCursor[] = {
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 15, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -79,8 +74,6 @@ static const byte stdMouseCursor[] = {
1, 1, 1, 1, 1, 1, 1, 0, 15, 15, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1
};
-static const byte stdMouseCursorHeight = 20;
-static const byte stdMouseCursorWidth = 12;
class Screen {
public:
@@ -145,6 +138,12 @@ protected:
static const int kRectListSize = 16; // Size of add/restore rect lists
static const int kBlitListSize = kRectListSize * 2; // Size of dirty rect blit list
+ static const int kShapeSize = 24;
+ static const int kFontLength = 128; // Number of chars in font
+ static const int kFontSize = 1200; // Max size of font data
+ static const int kNumFonts = 3; // Number of dib fonts
+ static const byte stdMouseCursorHeight = 20;
+ static const byte stdMouseCursorWidth = 12;
inline bool isInX(const int16 x, const rect_t *rect) const;
inline bool isInY(const int16 y, const rect_t *rect) const;
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index e97cfbbd85..dec3ab59d3 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -50,11 +50,6 @@ namespace Hugo {
HugoEngine *HugoEngine::s_Engine = 0;
-overlay_t HugoEngine::_boundary;
-overlay_t HugoEngine::_overlay;
-overlay_t HugoEngine::_ovlBase;
-overlay_t HugoEngine::_objBound;
-
maze_t _maze; // Default to not in maze
hugo_boot_t _boot; // Boot info structure file
@@ -855,147 +850,14 @@ void HugoEngine::readScreenFiles(const int screenNum) {
_file->readBackground(screenNum); // Scenery file
memcpy(_screen->getBackBuffer(), _screen->getFrontBuffer(), sizeof(_screen->getFrontBuffer())); // Make a copy
- _file->readOverlay(screenNum, _boundary, kOvlBoundary); // Boundary file
- _file->readOverlay(screenNum, _overlay, kOvlOverlay); // Overlay file
- _file->readOverlay(screenNum, _ovlBase, kOvlBase); // Overlay base file
+ _file->readOverlay(screenNum, _object->_boundary, kOvlBoundary); // Boundary file
+ _file->readOverlay(screenNum, _object->_overlay, kOvlOverlay); // Overlay file
+ _file->readOverlay(screenNum, _object->_ovlBase, kOvlBase); // Overlay base file
// Suppress a boundary used in H3 DOS in 'Crash' screen, which blocks
// pathfinding and is useless.
if ((screenNum == 0) && (_gameVariant == kGameVariantH3Dos))
- clearScreenBoundary(50, 311, 152);
-}
-
-/**
-* Return maximum allowed movement (from zero to vx) such that object does
-* not cross a boundary (either background or another object)
-*/
-int HugoEngine::deltaX(const int x1, const int x2, const int vx, int y) const {
-// Explanation of algorithm: The boundaries are drawn as contiguous
-// lines 1 pixel wide. Since DX,DY are not necessarily 1, we must
-// detect boundary crossing. If vx positive, examine each pixel from
-// x1 old to x2 new, else x2 old to x1 new, both at the y2 line.
-// If vx zero, no need to check. If vy non-zero then examine each
-// pixel on the line segment x1 to x2 from y old to y new.
-// Fix from Hugo I v1.5:
-// Note the diff is munged in the return statement to cater for a special
-// cases arising from differences in image widths from one sequence to
-// another. The problem occurs reversing direction at a wall where the
-// new image intersects before the object can move away. This is cured
-// by comparing the intersection with half the object width pos. If the
-// intersection is in the other half wrt the intended direction, use the
-// desired vx, else use the computed delta. i.e. believe the desired vx
-
- debugC(3, kDebugEngine, "deltaX(%d, %d, %d, %d)", x1, x2, vx, y);
-
- if (vx == 0)
- return 0; // Object stationary
-
- y *= kCompLineSize; // Offset into boundary file
- if (vx > 0) {
- // Moving to right
- for (int i = x1 >> 3; i <= (x2 + vx) >> 3; i++) {// Search by byte
- int b = Utils::firstBit((byte)(_boundary[y + i] | _objBound[y + i]));
- if (b < 8) { // b is index or 8
- // Compute x of boundary and test if intersection
- b += i << 3;
- if ((b >= x1) && (b <= x2 + vx))
- return (b < x1 + ((x2 - x1) >> 1)) ? vx : b - x2 - 1; // return dx
- }
- }
- } else {
- // Moving to left
- for (int i = x2 >> 3; i >= (x1 + vx) >> 3; i--) {// Search by byte
- int b = Utils::lastBit((byte)(_boundary[y + i] | _objBound[y + i]));
- if (b < 8) { // b is index or 8
- // Compute x of boundary and test if intersection
- b += i << 3;
- if ((b >= x1 + vx) && (b <= x2))
- return (b > x1 + ((x2 - x1) >> 1)) ? vx : b - x1 + 1; // return dx
- }
- }
- }
- return vx;
-}
-
-/**
-* Similar to Delta_x, but for movement in y direction. Special case of
-* bytes at end of line segment; must only count boundary bits falling on
-* line segment.
-*/
-int HugoEngine::deltaY(const int x1, const int x2, const int vy, const int y) const {
- debugC(3, kDebugEngine, "deltaY(%d, %d, %d, %d)", x1, x2, vy, y);
-
- if (vy == 0)
- return 0; // Object stationary
-
- int inc = (vy > 0) ? 1 : -1;
- for (int j = y + inc; j != (y + vy + inc); j += inc) { //Search by byte
- for (int i = x1 >> 3; i <= x2 >> 3; i++) {
- int b = _boundary[j * kCompLineSize + i] | _objBound[j * kCompLineSize + i];
- if (b != 0) { // Any bit set
- // Make sure boundary bits fall on line segment
- if (i == (x2 >> 3)) // Adjust right end
- b &= 0xff << ((i << 3) + 7 - x2);
- else if (i == (x1 >> 3)) // Adjust left end
- b &= 0xff >> (x1 - (i << 3));
- if (b)
- return j - y - inc;
- }
- }
- }
- return vy;
-}
-
-/**
-* Store a horizontal line segment in the object boundary file
-*/
-void HugoEngine::storeBoundary(const int x1, const int x2, const int y) {
- debugC(5, kDebugEngine, "storeBoundary(%d, %d, %d)", x1, x2, y);
-
- for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line
- byte *b = &_objBound[y * kCompLineSize + i];// get boundary byte
- if (i == x2 >> 3) // Adjust right end
- *b |= 0xff << ((i << 3) + 7 - x2);
- else if (i == x1 >> 3) // Adjust left end
- *b |= 0xff >> (x1 - (i << 3));
- else
- *b = 0xff;
- }
-}
-
-/**
-* Clear a horizontal line segment in the object boundary file
-*/
-void HugoEngine::clearBoundary(const int x1, const int x2, const int y) {
- debugC(5, kDebugEngine, "clearBoundary(%d, %d, %d)", x1, x2, y);
-
- for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line
- byte *b = &_objBound[y * kCompLineSize + i];// get boundary byte
- if (i == x2 >> 3) // Adjust right end
- *b &= ~(0xff << ((i << 3) + 7 - x2));
- else if (i == x1 >> 3) // Adjust left end
- *b &= ~(0xff >> (x1 - (i << 3)));
- else
- *b = 0;
- }
-}
-
-/**
-* Clear a horizontal line segment in the screen boundary file
-* Used to fix some data issues
-*/
-void HugoEngine::clearScreenBoundary(const int x1, const int x2, const int y) {
- debugC(5, kDebugEngine, "clearScreenBoundary(%d, %d, %d)", x1, x2, y);
-
- for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line
- byte *b = &_boundary[y * kCompLineSize + i];// get boundary byte
- if (i == x2 >> 3) // Adjust right end
- *b &= ~(0xff << ((i << 3) + 7 - x2));
- else if (i == x1 >> 3) // Adjust left end
- *b &= ~(0xff >> (x1 - (i << 3)));
- else
- *b = 0;
- }
+ _object->clearScreenBoundary(50, 311, 152);
}
/**
@@ -1040,42 +902,6 @@ void HugoEngine::setNewScreen(const int screenNum) {
}
/**
-* An object has collided with a boundary. See if any actions are required
-*/
-void HugoEngine::boundaryCollision(object_t *obj) {
- debugC(1, kDebugEngine, "boundaryCollision");
-
- if (obj == _hero) {
- // Hotspots only relevant to HERO
- int x;
- if (obj->vx > 0)
- x = obj->x + obj->currImagePtr->x2;
- else
- x = obj->x + obj->currImagePtr->x1;
- int y = obj->y + obj->currImagePtr->y2;
-
- for (int i = 0; _hotspots[i].screenIndex >= 0; i++) {
- hotspot_t *hotspot = &_hotspots[i];
- if (hotspot->screenIndex == obj->screenIndex)
- if ((x >= hotspot->x1) && (x <= hotspot->x2) && (y >= hotspot->y1) && (y <= hotspot->y2)) {
- _scheduler->insertActionList(hotspot->actIndex);
- break;
- }
- }
- } else {
- // Check whether an object collided with HERO
- int dx = _hero->x + _hero->currImagePtr->x1 - obj->x - obj->currImagePtr->x1;
- int dy = _hero->y + _hero->currImagePtr->y2 - obj->y - obj->currImagePtr->y2;
- // If object's radius is infinity, use a closer value
- int8 radius = obj->radius;
- if (radius < 0)
- radius = kStepDx * 2;
- if ((abs(dx) <= radius) && (abs(dy) <= radius))
- _scheduler->insertActionList(obj->actIndex);
- }
-}
-
-/**
* Add up all the object values and all the bonus points
*/
void HugoEngine::calcMaxScore() {
diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h
index ea67927e11..3799e32e32 100644
--- a/engines/hugo/hugo.h
+++ b/engines/hugo/hugo.h
@@ -141,11 +141,6 @@ enum istate_t {kInventoryOff, kInventoryUp, kInventoryDown, kInventoryActive};
enum vstate_t {kViewIdle, kViewIntroInit, kViewIntro, kViewPlay, kViewInvent, kViewExit};
/**
-* Purpose of an automatic route
-*/
-enum go_t {kRouteSpace, kRouteExit, kRouteLook, kRouteGet};
-
-/**
* Enumerate whether object is foreground, background or 'floating'
* If floating, HERO can collide with it and fore/back ground is determined
* by relative y-coord of object base. This is the general case.
@@ -305,37 +300,18 @@ public:
char *useBG(const char *name);
- int deltaX(const int x1, const int x2, const int vx, int y) const;
- int deltaY(const int x1, const int x2, const int vy, const int y) const;
-
int8 getTPS() const;
void initGame(const HugoGameDescription *gd);
void initGamePart(const HugoGameDescription *gd);
- void boundaryCollision(object_t *obj);
- void clearBoundary(const int x1, const int x2, const int y);
- void clearScreenBoundary(const int x1, const int x2, const int y);
void endGame();
void initStatus();
void readScreenFiles(const int screen);
void screenActions(const int screen);
void setNewScreen(const int screen);
void shutdown();
- void storeBoundary(const int x1, const int x2, const int y);
void syncSoundSettings();
- overlay_t &getBoundaryOverlay() {
- return _boundary;
- }
- overlay_t &getObjectBoundaryOverlay() {
- return _objBound;
- }
- overlay_t &getBaseBoundaryOverlay() {
- return _ovlBase;
- }
- overlay_t &getFirstOverlay() {
- return _overlay;
- }
status_t &getGameStatus() {
return _status;
}
@@ -407,14 +383,6 @@ private:
// foreground stationary objects and baselines for those objects (used to
// determine foreground/background wrt moving objects)
-// Vinterstum: These shouldn't be static, but we get weird pathfinding issues (and Valgrind warnings) without.
-// Needs more investigation. Alignment issues?
-
- static overlay_t _boundary; // Boundary overlay file
- static overlay_t _overlay; // First overlay file
- static overlay_t _ovlBase; // First overlay base file
- static overlay_t _objBound; // Boundary file marks object baselines
-
GameType _gameType;
Common::Platform _platform;
bool _packedFl;
diff --git a/engines/hugo/inventory.h b/engines/hugo/inventory.h
index f4263de5c4..84bc29ea1b 100644
--- a/engines/hugo/inventory.h
+++ b/engines/hugo/inventory.h
@@ -44,9 +44,9 @@ public:
InventoryHandler(HugoEngine *vm);
void setInventoryObjId(int16 objId) { _inventoryObjId = objId; }
- int16 getInventoryObjId() { return _inventoryObjId; }
void setInventoryState(istate_t state) { _inventoryState = state; }
- istate_t getInventoryState() { return _inventoryState; }
+ int16 getInventoryObjId() const { return _inventoryObjId; }
+ istate_t getInventoryState() const { return _inventoryState; }
int16 processInventory(const invact_t action, ...);
void runInventory();
diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp
index 5f79bc0d5a..5db53fdd79 100644
--- a/engines/hugo/object.cpp
+++ b/engines/hugo/object.cpp
@@ -50,6 +50,10 @@ namespace Hugo {
ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm), _objects(0) {
_numObj = 0;
_objCount = 0;
+ memset(_objBound, '\0', sizeof(overlay_t));
+ memset(_boundary, '\0', sizeof(overlay_t));
+ memset(_overlay, '\0', sizeof(overlay_t));
+ memset(_ovlBase, '\0', sizeof(overlay_t));
}
ObjectHandler::~ObjectHandler() {
@@ -591,7 +595,176 @@ void ObjectHandler::readObjectImages() {
bool ObjectHandler::checkBoundary(int16 x, int16 y) {
// Check if Boundary bit set
- return (_vm->getBoundaryOverlay()[y * kCompLineSize + x / 8] & (0x80 >> x % 8)) != 0;
+ return (_boundary[y * kCompLineSize + x / 8] & (0x80 >> x % 8)) != 0;
+}
+
+/**
+* Return maximum allowed movement (from zero to vx) such that object does
+* not cross a boundary (either background or another object)
+*/
+int ObjectHandler::deltaX(const int x1, const int x2, const int vx, int y) const {
+// Explanation of algorithm: The boundaries are drawn as contiguous
+// lines 1 pixel wide. Since DX,DY are not necessarily 1, we must
+// detect boundary crossing. If vx positive, examine each pixel from
+// x1 old to x2 new, else x2 old to x1 new, both at the y2 line.
+// If vx zero, no need to check. If vy non-zero then examine each
+// pixel on the line segment x1 to x2 from y old to y new.
+// Fix from Hugo I v1.5:
+// Note the diff is munged in the return statement to cater for a special
+// cases arising from differences in image widths from one sequence to
+// another. The problem occurs reversing direction at a wall where the
+// new image intersects before the object can move away. This is cured
+// by comparing the intersection with half the object width pos. If the
+// intersection is in the other half wrt the intended direction, use the
+// desired vx, else use the computed delta. i.e. believe the desired vx
+
+ debugC(3, kDebugEngine, "deltaX(%d, %d, %d, %d)", x1, x2, vx, y);
+
+ if (vx == 0)
+ return 0; // Object stationary
+
+ y *= kCompLineSize; // Offset into boundary file
+ if (vx > 0) {
+ // Moving to right
+ for (int i = x1 >> 3; i <= (x2 + vx) >> 3; i++) {// Search by byte
+ int b = Utils::firstBit((byte)(_boundary[y + i] | _objBound[y + i]));
+ if (b < 8) { // b is index or 8
+ // Compute x of boundary and test if intersection
+ b += i << 3;
+ if ((b >= x1) && (b <= x2 + vx))
+ return (b < x1 + ((x2 - x1) >> 1)) ? vx : b - x2 - 1; // return dx
+ }
+ }
+ } else {
+ // Moving to left
+ for (int i = x2 >> 3; i >= (x1 + vx) >> 3; i--) {// Search by byte
+ int b = Utils::lastBit((byte)(_boundary[y + i] | _objBound[y + i]));
+ if (b < 8) { // b is index or 8
+ // Compute x of boundary and test if intersection
+ b += i << 3;
+ if ((b >= x1 + vx) && (b <= x2))
+ return (b > x1 + ((x2 - x1) >> 1)) ? vx : b - x1 + 1; // return dx
+ }
+ }
+ }
+ return vx;
+}
+
+/**
+* Similar to Delta_x, but for movement in y direction. Special case of
+* bytes at end of line segment; must only count boundary bits falling on
+* line segment.
+*/
+int ObjectHandler::deltaY(const int x1, const int x2, const int vy, const int y) const {
+ debugC(3, kDebugEngine, "deltaY(%d, %d, %d, %d)", x1, x2, vy, y);
+
+ if (vy == 0)
+ return 0; // Object stationary
+
+ int inc = (vy > 0) ? 1 : -1;
+ for (int j = y + inc; j != (y + vy + inc); j += inc) { //Search by byte
+ for (int i = x1 >> 3; i <= x2 >> 3; i++) {
+ int b = _boundary[j * kCompLineSize + i] | _objBound[j * kCompLineSize + i];
+ if (b != 0) { // Any bit set
+ // Make sure boundary bits fall on line segment
+ if (i == (x2 >> 3)) // Adjust right end
+ b &= 0xff << ((i << 3) + 7 - x2);
+ else if (i == (x1 >> 3)) // Adjust left end
+ b &= 0xff >> (x1 - (i << 3));
+ if (b)
+ return j - y - inc;
+ }
+ }
+ }
+ return vy;
+}
+
+/**
+* Store a horizontal line segment in the object boundary file
+*/
+void ObjectHandler::storeBoundary(const int x1, const int x2, const int y) {
+ debugC(5, kDebugEngine, "storeBoundary(%d, %d, %d)", x1, x2, y);
+
+ for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line
+ byte *b = &_objBound[y * kCompLineSize + i];// get boundary byte
+ if (i == x2 >> 3) // Adjust right end
+ *b |= 0xff << ((i << 3) + 7 - x2);
+ else if (i == x1 >> 3) // Adjust left end
+ *b |= 0xff >> (x1 - (i << 3));
+ else
+ *b = 0xff;
+ }
+}
+
+/**
+* Clear a horizontal line segment in the object boundary file
+*/
+void ObjectHandler::clearBoundary(const int x1, const int x2, const int y) {
+ debugC(5, kDebugEngine, "clearBoundary(%d, %d, %d)", x1, x2, y);
+
+ for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line
+ byte *b = &_objBound[y * kCompLineSize + i];// get boundary byte
+ if (i == x2 >> 3) // Adjust right end
+ *b &= ~(0xff << ((i << 3) + 7 - x2));
+ else if (i == x1 >> 3) // Adjust left end
+ *b &= ~(0xff >> (x1 - (i << 3)));
+ else
+ *b = 0;
+ }
+}
+
+/**
+* Clear a horizontal line segment in the screen boundary file
+* Used to fix some data issues
+*/
+void ObjectHandler::clearScreenBoundary(const int x1, const int x2, const int y) {
+ debugC(5, kDebugEngine, "clearScreenBoundary(%d, %d, %d)", x1, x2, y);
+
+ for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line
+ byte *b = &_boundary[y * kCompLineSize + i];// get boundary byte
+ if (i == x2 >> 3) // Adjust right end
+ *b &= ~(0xff << ((i << 3) + 7 - x2));
+ else if (i == x1 >> 3) // Adjust left end
+ *b &= ~(0xff >> (x1 - (i << 3)));
+ else
+ *b = 0;
+ }
+}
+
+/**
+* An object has collided with a boundary. See if any actions are required
+*/
+void ObjectHandler::boundaryCollision(object_t *obj) {
+ debugC(1, kDebugEngine, "boundaryCollision");
+
+ if (obj == _vm->_hero) {
+ // Hotspots only relevant to HERO
+ int x;
+ if (obj->vx > 0)
+ x = obj->x + obj->currImagePtr->x2;
+ else
+ x = obj->x + obj->currImagePtr->x1;
+ int y = obj->y + obj->currImagePtr->y2;
+
+ for (int i = 0; _vm->_hotspots[i].screenIndex >= 0; i++) {
+ hotspot_t *hotspot = &_vm->_hotspots[i];
+ if (hotspot->screenIndex == obj->screenIndex)
+ if ((x >= hotspot->x1) && (x <= hotspot->x2) && (y >= hotspot->y1) && (y <= hotspot->y2)) {
+ _vm->_scheduler->insertActionList(hotspot->actIndex);
+ break;
+ }
+ }
+ } else {
+ // Check whether an object collided with HERO
+ int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - obj->currImagePtr->x1;
+ int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - obj->currImagePtr->y2;
+ // If object's radius is infinity, use a closer value
+ int8 radius = obj->radius;
+ if (radius < 0)
+ radius = kStepDx * 2;
+ if ((abs(dx) <= radius) && (abs(dy) <= radius))
+ _vm->_scheduler->insertActionList(obj->actIndex);
+ }
}
} // End of namespace Hugo
diff --git a/engines/hugo/object.h b/engines/hugo/object.h
index 736be20ef1..ce94c79103 100644
--- a/engines/hugo/object.h
+++ b/engines/hugo/object.h
@@ -42,9 +42,26 @@ public:
ObjectHandler(HugoEngine *vm);
virtual ~ObjectHandler();
+ overlay_t _objBound;
+ overlay_t _boundary; // Boundary overlay file
+ overlay_t _overlay; // First overlay file
+ overlay_t _ovlBase; // First overlay base file
+
object_t *_objects;
uint16 _numObj;
+ byte getBoundaryOverlay(uint16 index) const { return _boundary[index]; }
+ byte getObjectBoundary(uint16 index) const { return _objBound[index]; }
+ byte getBaseBoundary(uint16 index) const { return _ovlBase[index]; }
+ byte getFirstOverlay(uint16 index) const { return _overlay[index]; }
+
+ int deltaX(const int x1, const int x2, const int vx, int y) const;
+ int deltaY(const int x1, const int x2, const int vy, const int y) const;
+ void boundaryCollision(object_t *obj);
+ void clearBoundary(const int x1, const int x2, const int y);
+ void clearScreenBoundary(const int x1, const int x2, const int y);
+ void storeBoundary(const int x1, const int x2, const int y);
+
virtual void homeIn(const int objIndex1, const int objIndex2, const int8 objDx, const int8 objDy) = 0;
virtual void moveObjects() = 0;
virtual void updateImages() = 0;
diff --git a/engines/hugo/object_v1d.cpp b/engines/hugo/object_v1d.cpp
index f2cac5c658..64def1435a 100644
--- a/engines/hugo/object_v1d.cpp
+++ b/engines/hugo/object_v1d.cpp
@@ -224,7 +224,7 @@ void ObjectHandler_v1d::moveObjects() {
obj->cycling = kCycleForward;
} else {
obj->cycling = kCycleNotCycling;
- _vm->boundaryCollision(obj); // Must have got hero!
+ boundaryCollision(obj); // Must have got hero!
}
obj->oldvx = obj->vx;
obj->oldvy = obj->vy;
@@ -267,7 +267,7 @@ void ObjectHandler_v1d::moveObjects() {
}
// Store boundaries
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
+ storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
}
}
@@ -287,25 +287,25 @@ void ObjectHandler_v1d::moveObjects() {
int y2 = obj->y + currImage->y2; // Bottom edge
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(x1, x2, y2); // Clear our own boundary
+ clearBoundary(x1, x2, y2); // Clear our own boundary
// Allowable motion wrt boundary
- int dx = _vm->deltaX(x1, x2, obj->vx, y2);
+ int dx = deltaX(x1, x2, obj->vx, y2);
if (dx != obj->vx) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vx = 0;
}
- int dy = _vm->deltaY(x1, x2, obj->vy, y2);
+ int dy = deltaY(x1, x2, obj->vy, y2);
if (dy != obj->vy) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vy = 0;
}
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary
+ storeBoundary(x1, x2, y2); // Re-store our own boundary
obj->x += dx; // Update object position
obj->y += dy;
@@ -330,7 +330,7 @@ void ObjectHandler_v1d::moveObjects() {
object_t *obj = &_objects[i]; // Get pointer to object
seq_t *currImage = obj->currImagePtr; // Get ptr to current image
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
+ clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
}
// If maze mode is enabled, do special maze processing
diff --git a/engines/hugo/object_v1w.cpp b/engines/hugo/object_v1w.cpp
index 465427b840..0e3efbb98b 100644
--- a/engines/hugo/object_v1w.cpp
+++ b/engines/hugo/object_v1w.cpp
@@ -236,7 +236,7 @@ void ObjectHandler_v1w::moveObjects() {
obj->cycling = kCycleForward;
} else {
obj->cycling = kCycleNotCycling;
- _vm->boundaryCollision(obj); // Must have got hero!
+ boundaryCollision(obj); // Must have got hero!
}
obj->oldvx = obj->vx;
obj->oldvy = obj->vy;
@@ -277,7 +277,7 @@ void ObjectHandler_v1w::moveObjects() {
}
// Store boundaries
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
+ storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
}
}
@@ -297,25 +297,25 @@ void ObjectHandler_v1w::moveObjects() {
int y2 = obj->y + currImage->y2; // Bottom edge
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(x1, x2, y2); // Clear our own boundary
+ clearBoundary(x1, x2, y2); // Clear our own boundary
// Allowable motion wrt boundary
- int dx = _vm->deltaX(x1, x2, obj->vx, y2);
+ int dx = deltaX(x1, x2, obj->vx, y2);
if (dx != obj->vx) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vx = 0;
}
- int dy = _vm->deltaY(x1, x2, obj->vy, y2);
+ int dy = deltaY(x1, x2, obj->vy, y2);
if (dy != obj->vy) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vy = 0;
}
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary
+ storeBoundary(x1, x2, y2); // Re-store our own boundary
obj->x += dx; // Update object position
obj->y += dy;
@@ -340,7 +340,7 @@ void ObjectHandler_v1w::moveObjects() {
object_t *obj = &_objects[i]; // Get pointer to object
seq_t *currImage = obj->currImagePtr; // Get ptr to current image
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
+ clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
}
// If maze mode is enabled, do special maze processing
diff --git a/engines/hugo/object_v2d.cpp b/engines/hugo/object_v2d.cpp
index 17adae846a..7a4e5ce9a2 100644
--- a/engines/hugo/object_v2d.cpp
+++ b/engines/hugo/object_v2d.cpp
@@ -239,7 +239,7 @@ void ObjectHandler_v2d::moveObjects() {
obj->cycling = kCycleForward;
} else {
obj->cycling = kCycleNotCycling;
- _vm->boundaryCollision(obj); // Must have got hero!
+ boundaryCollision(obj); // Must have got hero!
}
obj->oldvx = obj->vx;
obj->oldvy = obj->vy;
@@ -280,7 +280,7 @@ void ObjectHandler_v2d::moveObjects() {
}
// Store boundaries
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
+ storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
}
}
@@ -300,25 +300,25 @@ void ObjectHandler_v2d::moveObjects() {
int y2 = obj->y + currImage->y2; // Bottom edge
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(x1, x2, y2); // Clear our own boundary
+ clearBoundary(x1, x2, y2); // Clear our own boundary
// Allowable motion wrt boundary
- int dx = _vm->deltaX(x1, x2, obj->vx, y2);
+ int dx = deltaX(x1, x2, obj->vx, y2);
if (dx != obj->vx) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vx = 0;
}
- int dy = _vm->deltaY(x1, x2, obj->vy, y2);
+ int dy = deltaY(x1, x2, obj->vy, y2);
if (dy != obj->vy) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vy = 0;
}
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary
+ storeBoundary(x1, x2, y2); // Re-store our own boundary
obj->x += dx; // Update object position
obj->y += dy;
@@ -343,7 +343,7 @@ void ObjectHandler_v2d::moveObjects() {
object_t *obj = &_objects[i]; // Get pointer to object
seq_t *currImage = obj->currImagePtr; // Get ptr to current image
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
+ clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
}
// If maze mode is enabled, do special maze processing
diff --git a/engines/hugo/object_v3d.cpp b/engines/hugo/object_v3d.cpp
index e80a18bd5a..b9d7bcc261 100644
--- a/engines/hugo/object_v3d.cpp
+++ b/engines/hugo/object_v3d.cpp
@@ -120,7 +120,7 @@ void ObjectHandler_v3d::moveObjects() {
obj->cycling = kCycleForward;
} else {
obj->cycling = kCycleNotCycling;
- _vm->boundaryCollision(obj); // Must have got hero!
+ boundaryCollision(obj); // Must have got hero!
}
obj->oldvx = obj->vx;
obj->oldvy = obj->vy;
@@ -162,7 +162,7 @@ void ObjectHandler_v3d::moveObjects() {
}
// Store boundaries
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
+ storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
}
}
@@ -182,25 +182,25 @@ void ObjectHandler_v3d::moveObjects() {
int y2 = obj->y + currImage->y2; // Bottom edge
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(x1, x2, y2); // Clear our own boundary
+ clearBoundary(x1, x2, y2); // Clear our own boundary
// Allowable motion wrt boundary
- int dx = _vm->deltaX(x1, x2, obj->vx, y2);
+ int dx = deltaX(x1, x2, obj->vx, y2);
if (dx != obj->vx) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vx = 0;
}
- int dy = _vm->deltaY(x1, x2, obj->vy, y2);
+ int dy = deltaY(x1, x2, obj->vy, y2);
if (dy != obj->vy) {
// An object boundary collision!
- _vm->boundaryCollision(obj);
+ boundaryCollision(obj);
obj->vy = 0;
}
if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary
+ storeBoundary(x1, x2, y2); // Re-store our own boundary
obj->x += dx; // Update object position
obj->y += dy;
@@ -225,7 +225,7 @@ void ObjectHandler_v3d::moveObjects() {
object_t *obj = &_objects[i]; // Get pointer to object
seq_t *currImage = obj->currImagePtr; // Get ptr to current image
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
+ clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
}
// If maze mode is enabled, do special maze processing
diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp
index 5f86591512..ad74acf4bf 100644
--- a/engines/hugo/route.cpp
+++ b/engines/hugo/route.cpp
@@ -329,21 +329,22 @@ bool Route::findRoute(const int16 cx, const int16 cy) {
int i;
for (i = 1, obj = &_vm->_object->_objects[i]; i < _vm->_object->_numObj; i++, obj++) {
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling != kCycleInvisible) && (obj->priority == kPriorityFloating))
- _vm->storeBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
+ _vm->_object->storeBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
}
// Combine objbound and boundary bitmaps to local byte map
- for (int16 y = 0; y < kYPix; y++) {
- for (int16 x = 0; x < kCompLineSize; x++) {
+ for (uint16 y = 0; y < kYPix; y++) {
+ for (uint16 x = 0; x < kCompLineSize; x++) {
+ uint16 boundIdx = y * kCompLineSize + x;
for (i = 0; i < 8; i++)
- _boundaryMap[y][x * 8 + i] = ((_vm->getObjectBoundaryOverlay()[y * kCompLineSize + x] | _vm->getBoundaryOverlay()[y * kCompLineSize + x]) & (0x80 >> i)) ? kMapBound : 0;
+ _boundaryMap[y][x * 8 + i] = ((_vm->_object->getObjectBoundary(boundIdx) | _vm->_object->getBoundaryOverlay(boundIdx)) & (0x80 >> i)) ? kMapBound : 0;
}
}
// Clear all object baselines from objbound
for (i = 0, obj = _vm->_object->_objects; i < _vm->_object->_numObj; i++, obj++) {
if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling != kCycleInvisible) && (obj->priority == kPriorityFloating))
- _vm->clearBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
+ _vm->_object->clearBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2);
}
// Search from hero to destination
diff --git a/engines/hugo/route.h b/engines/hugo/route.h
index f9c80642db..ca5d03d910 100644
--- a/engines/hugo/route.h
+++ b/engines/hugo/route.h
@@ -35,6 +35,11 @@
namespace Hugo {
+/**
+* Purpose of an automatic route
+*/
+enum go_t {kRouteSpace, kRouteExit, kRouteLook, kRouteGet};
+
struct Point {
int x;
int y;
@@ -49,8 +54,8 @@ class Route {
public:
Route(HugoEngine *vm);
- void resetRoute() {_routeIndex = -1; }
- int16 getRouteIndex() {return _routeIndex; }
+ void resetRoute() {_routeIndex = -1; }
+ int16 getRouteIndex() const {return _routeIndex; }
void processRoute();
bool startRoute(const go_t go_for, const int16 id, int16 cx, int16 cy);