aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/bbvs/bbvs.cpp33
-rw-r--r--engines/sci/engine/kgraphics32.cpp37
-rw-r--r--engines/sci/graphics/celobj32.cpp123
-rw-r--r--engines/wage/design.cpp10
-rw-r--r--engines/wage/detection_tables.h1
5 files changed, 128 insertions, 76 deletions
diff --git a/engines/bbvs/bbvs.cpp b/engines/bbvs/bbvs.cpp
index d40d5e482f..6ae663479d 100644
--- a/engines/bbvs/bbvs.cpp
+++ b/engines/bbvs/bbvs.cpp
@@ -137,6 +137,21 @@ BbvsEngine::~BbvsEngine() {
}
void BbvsEngine::newGame() {
+ memset(_easterEggInput, 0, sizeof(_easterEggInput));
+ _gameTicks = 0;
+ _playVideoNumber = 0;
+ memset(_inventoryItemStatus, 0, sizeof(_inventoryItemStatus));
+ memset(_gameVars, 0, sizeof(_gameVars));
+ memset(_sceneVisited, 0, sizeof(_sceneVisited));
+
+ _mouseX = 160;
+ _mouseY = 120;
+ _mouseButtons = 0;
+
+ _currVerbNum = kVerbLook;
+ _currTalkObjectIndex = -1;
+ _currSceneNum = 0;
+
_currInventoryItem = -1;
_newSceneNum = 32;
}
@@ -162,24 +177,10 @@ Common::Error BbvsEngine::run() {
_sound = new SoundMan();
allocSnapshot();
- memset(_easterEggInput, 0, sizeof(_easterEggInput));
- _gameTicks = 0;
- _playVideoNumber = 0;
- _bootSaveSlot = -1;
-
- memset(_inventoryItemStatus, 0, sizeof(_inventoryItemStatus));
- memset(_gameVars, 0, sizeof(_gameVars));
- memset(_sceneVisited, 0, sizeof(_sceneVisited));
-
- _mouseX = 160;
- _mouseY = 120;
- _mouseButtons = 0;
+ newGame();
- _currVerbNum = kVerbLook;
- _currInventoryItem = -1;
- _currTalkObjectIndex = -1;
- _currSceneNum = 0;
+ _bootSaveSlot = -1;
_newSceneNum = 31;
if (ConfMan.hasKey("save_slot"))
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 6e45944150..b4d8a07eee 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -330,24 +330,27 @@ reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
// Used by Shivers 1, room 23601 to determine what blocks on the red door puzzle board
// are occupied by pieces already
- switch (argv[0].toUint16()) { // subops 0 - 4
- // 0 - return the view
- // 1 - return the loop
- // 2, 3 - nop
- case 4: {
- GuiResourceId viewId = argv[1].toSint16();
- int16 loopNo = argv[2].toSint16();
- int16 celNo = argv[3].toSint16();
- int16 x = argv[4].toUint16();
- int16 y = argv[5].toUint16();
- byte color = g_sci->_gfxCache->kernelViewGetColorAtCoordinate(viewId, loopNo, celNo, x, y);
- return make_reg(0, color);
- }
- default: {
- kStub(s, argc, argv);
- return s->r_acc;
- }
+ CelObjView view(argv[1].toUint16(), argv[2].toSint16(), argv[3].toSint16());
+
+ int16 result = 0;
+
+ switch (argv[0].toUint16()) {
+ case 0:
+ result = view._displace.x;
+ break;
+ case 1:
+ result = view._displace.y;
+ break;
+ case 2:
+ case 3:
+ // null operation
+ break;
+ case 4:
+ result = view.readPixel(argv[4].toSint16(), argv[5].toSint16(), view._mirrorX);
+ break;
}
+
+ return make_reg(0, result);
}
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index acf499308a..e9833c517b 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -109,25 +109,42 @@ void CelObj::deinit() {
template<bool FLIP, typename READER>
struct SCALER_NoScale {
+#ifndef NDEBUG
+ const byte *_rowEdge;
+#endif
const byte *_row;
READER _reader;
const int16 _lastIndex;
+ const int16 _sourceX;
+ const int16 _sourceY;
- SCALER_NoScale(const CelObj &celObj, const int16 maxWidth) :
+ SCALER_NoScale(const CelObj &celObj, const int16 maxWidth, const Common::Point &scaledPosition) :
_reader(celObj, FLIP ? celObj._width : maxWidth),
- _lastIndex(celObj._width - 1) {}
+ _lastIndex(celObj._width - 1),
+ _sourceX(scaledPosition.x),
+ _sourceY(scaledPosition.y) {}
- inline void setSource(const int16 x, const int16 targetY, const int16 scaledPosY) {
- _row = _reader.getRow(targetY - scaledPosY);
+ inline void setTarget(const int16 x, const int16 y) {
+ _row = _reader.getRow(y - _sourceY);
if (FLIP) {
- _row += _lastIndex - x;
+#ifndef NDEBUG
+ _rowEdge = _row - 1;
+#endif
+ _row += _lastIndex - (x - _sourceX);
+ assert(_row > _rowEdge);
} else {
- _row += x;
+#ifndef NDEBUG
+ _rowEdge = _row + _lastIndex + 1;
+#endif
+ _row += x - _sourceX;
+ assert(_row < _rowEdge);
}
}
inline byte read() {
+ assert(_row != _rowEdge);
+
if (FLIP) {
return *_row--;
} else {
@@ -138,58 +155,96 @@ struct SCALER_NoScale {
template<bool FLIP, typename READER>
struct SCALER_Scale {
+#ifndef NDEBUG
+ int16 _maxX;
+#endif
const byte *_row;
READER _reader;
- const CelScalerTable *_table;
int16 _x;
- const uint16 _lastIndex;
+ static int16 _valuesX[1024];
+ static int16 _valuesY[1024];
- SCALER_Scale(const CelObj &celObj, const int16 maxWidth, const Ratio scaleX, const Ratio scaleY) :
+ SCALER_Scale(const CelObj &celObj, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio scaleX, const Ratio scaleY) :
+#ifndef NDEBUG
+ _maxX(targetRect.right - 1),
+#endif
// The maximum width of the scaled object may not be as
// wide as the source data it requires if downscaling,
// so just always make the reader decompress an entire
// line of source data when scaling
- _reader(celObj, celObj._width),
- _table(CelObj::_scaler->getScalerTable(scaleX, scaleY)),
- _lastIndex(maxWidth - 1) {}
-
- inline void setSource(const int16 x, const int16 targetY, const int16 scaledPosY) {
- // look up both targetY + scaledPosY in here, only subtract afterwards
- // otherwise y won't be correct all the time when uneven scaling is used (for example 5:12)
- int16 y = _table->valuesY[targetY] - _table->valuesY[scaledPosY];
- _row = _reader.getRow(y);
+ _reader(celObj, celObj._width) {
+ // In order for scaling ratios to apply equally across objects that
+ // start at different positions on the screen, the pixels that are
+ // read from the source bitmap must all use the same pattern of
+ // division. In other words, cels must follow the same scaling pattern
+ // as if they were drawn starting at an even multiple of the scaling
+ // ratio, even if they were not.
+ //
+ // To get the correct source pixel when reading out through the scaler,
+ // the engine creates a lookup table for each axis that translates
+ // directly from target positions to the indexes of source pixels using
+ // the global cadence for the given scaling ratio.
+
+ const CelScalerTable *table = CelObj::_scaler->getScalerTable(scaleX, scaleY);
+
+ const int16 unscaledX = (scaledPosition.x / scaleX).toInt();
if (FLIP) {
- _x = _lastIndex - x;
+ int lastIndex = celObj._width - 1;
+ for (int16 x = targetRect.left; x < targetRect.right; ++x) {
+ _valuesX[x] = lastIndex - (table->valuesX[x] - unscaledX);
+ }
} else {
- _x = x;
+ for (int16 x = targetRect.left; x < targetRect.right; ++x) {
+ _valuesX[x] = table->valuesX[x] - unscaledX;
+ }
+ }
+
+ const int16 unscaledY = (scaledPosition.y / scaleY).toInt();
+ for (int16 y = targetRect.top; y < targetRect.bottom; ++y) {
+ _valuesY[y] = table->valuesY[y] - unscaledY;
}
}
+ inline void setTarget(const int16 x, const int16 y) {
+ _row = _reader.getRow(_valuesY[y]);
+ _x = x;
+ assert(_x >= 0 && _x <= _maxX);
+ }
+
inline byte read() {
- if (FLIP) {
- return _row[_table->valuesX[_x--]];
- } else {
- return _row[_table->valuesX[_x++]];
- }
+ assert(_x >= 0 && _x <= _maxX);
+ return _row[_valuesX[_x++]];
}
};
+template<bool FLIP, typename READER>
+int16 SCALER_Scale<FLIP, READER>::_valuesX[1024];
+template<bool FLIP, typename READER>
+int16 SCALER_Scale<FLIP, READER>::_valuesY[1024];
+
#pragma mark -
#pragma mark CelObj - Resource readers
struct READER_Uncompressed {
private:
+#ifndef NDEBUG
+ const int16 _sourceHeight;
+#endif
byte *_pixels;
const int16 _sourceWidth;
public:
READER_Uncompressed(const CelObj &celObj, const int16) :
+#ifndef NDEBUG
+ _sourceHeight(celObj._height),
+#endif
_sourceWidth(celObj._width) {
byte *resource = celObj.getResPointer();
_pixels = resource + READ_SCI11ENDIAN_UINT32(resource + celObj._celHeaderOffset + 24);
}
inline const byte *getRow(const int16 y) const {
+ assert(y >= 0 && y < _sourceHeight);
return _pixels + y * _sourceWidth;
}
};
@@ -213,7 +268,7 @@ public:
_sourceHeight(celObj._height),
_transparentColor(celObj._transparentColor),
_maxWidth(maxWidth) {
- assert(_maxWidth <= celObj._width);
+ assert(maxWidth <= celObj._width);
byte *celHeader = _resource + celObj._celHeaderOffset;
_dataOffset = READ_SCI11ENDIAN_UINT32(celHeader + 24);
@@ -222,6 +277,7 @@ public:
}
inline const byte *getRow(const int16 y) {
+ assert(y >= 0 && y < _sourceHeight);
if (y != _y) {
// compressed data segment for row
byte *row = _resource + _dataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + y * 4);
@@ -230,7 +286,7 @@ public:
byte *literal = _resource + _uncompressedDataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + _sourceHeight * 4 + y * 4);
uint8 length;
- for (int i = 0; i < _maxWidth; i += length) {
+ for (int16 i = 0; i < _maxWidth; i += length) {
byte controlByte = *row++;
length = controlByte;
@@ -577,18 +633,15 @@ struct RENDERER {
_skipColor(skipColor) {}
inline void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- const int16 sourceX = targetRect.left - scaledPosition.x;
- //const int16 sourceY = targetRect.top - scaledPosition.y;
-
byte *targetPixel = (byte *)target.getPixels() + target.screenWidth * targetRect.top + targetRect.left;
const int16 skipStride = target.screenWidth - targetRect.width();
const int16 targetWidth = targetRect.width();
const int16 targetHeight = targetRect.height();
- for (int y = 0; y < targetHeight; ++y) {
- _scaler.setSource(sourceX, targetRect.top + y, scaledPosition.y);
+ for (int16 y = 0; y < targetHeight; ++y) {
+ _scaler.setTarget(targetRect.left, targetRect.top + y);
- for (int x = 0; x < targetWidth; ++x) {
+ for (int16 x = 0; x < targetWidth; ++x) {
_mapper.draw(targetPixel++, _scaler.read(), _skipColor);
}
@@ -601,7 +654,7 @@ template<typename MAPPER, typename SCALER>
void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
MAPPER mapper;
- SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width());
+ SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width(), scaledPosition);
RENDERER<MAPPER, SCALER> renderer(mapper, scaler, _transparentColor);
renderer.draw(target, targetRect, scaledPosition);
}
@@ -610,7 +663,7 @@ template<typename MAPPER, typename SCALER>
void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio &scaleX, const Ratio &scaleY) const {
MAPPER mapper;
- SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width(), scaleX, scaleY);
+ SCALER scaler(*this, targetRect, scaledPosition, scaleX, scaleY);
RENDERER<MAPPER, SCALER> renderer(mapper, scaler, _transparentColor);
renderer.draw(target, targetRect, scaledPosition);
}
diff --git a/engines/wage/design.cpp b/engines/wage/design.cpp
index 220acae05a..907a1ec435 100644
--- a/engines/wage/design.cpp
+++ b/engines/wage/design.cpp
@@ -87,16 +87,14 @@ void Design::paint(Graphics::Surface *surface, Patterns &patterns, int x, int y)
bool needRender = false;
if (_surface == NULL) {
- //_boundsCalculationMode = true;
+ _boundsCalculationMode = true;
_bounds->debugPrint(4, "Internal bounds:");
- //_bounds->left = _bounds->top = 10000;
- //_bounds->right =_bounds->bottom = -10000;
- //render(patterns);
+ render(patterns);
_boundsCalculationMode = false;
if (_bounds->right == -10000) {
_bounds->left = _bounds->top = _bounds->right = _bounds->bottom = 0;
}
- //_bounds->debugPrint(4, "Calculated bounds:");
+ _bounds->debugPrint(4, "Calculated bounds:");
_surface = new Graphics::Surface;
_surface->create(_bounds->width(), _bounds->height(), Graphics::PixelFormat::createFormatCLUT8());
@@ -201,9 +199,7 @@ bool Design::isPointOpaque(int x, int y) {
}
void Design::adjustBounds(int16 x, int16 y) {
- _bounds->left = MIN(x, _bounds->left);
_bounds->right = MAX(x, _bounds->right);
- _bounds->top = MIN(y, _bounds->top);
_bounds->bottom = MAX(y, _bounds->bottom);
}
diff --git a/engines/wage/detection_tables.h b/engines/wage/detection_tables.h
index 18ba8970ed..7e22b2f090 100644
--- a/engines/wage/detection_tables.h
+++ b/engines/wage/detection_tables.h
@@ -74,7 +74,6 @@ static const ADGameDescription gameDescriptions[] = {
// ??? problems with dog bitmap?
FANGAMEN("Space Adventure", "SpaceAdventure", "f9f3f1c419f56955f7966355b34ea5c8", 155356),
FANGAME("Star Trek", "44aaef4806578700429de5aaf95c266e", 53320),
- // Crash in bitmap drawing on the first scene
FANGAME("Strange Disappearance", "d81f2d03a1e863f04fb1e3a5495b720e", 772282),
FANGAME("Time Bomb", "4b0e1a1fbaaa4930accd0f9f0e1519c7", 64564),
FANGAMEN("The Hotel Caper", "The Hotel Caper V1.0", "595117cbed33e8de1ab3714b33880205", 231969),