[Scummvm-git-logs] scummvm master -> f0a14d295e1d06b9576509780646698534ae7898
mduggan
noreply at scummvm.org
Tue Sep 23 10:04:18 UTC 2025
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
8a2cba2b63 ACCESS: Remove redundant debug message
d4da7f3a23 ACCESS: small const correctness fixes
41e4007633 ACCESS: Add myself to engine credits
8fb83ad151 ACCESS: Implement MM duct section
28a3a81347 NEWS: Mention Martian Memorandum support
f0a14d295e ACCESS: Mark MM as ready for testing
Commit: 8a2cba2b6354cb52ba03e1a3896b6793dcd33d5f
https://github.com/scummvm/scummvm/commit/8a2cba2b6354cb52ba03e1a3896b6793dcd33d5f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-09-23T14:15:25+10:00
Commit Message:
ACCESS: Remove redundant debug message
Changed paths:
engines/access/bubble_box.cpp
diff --git a/engines/access/bubble_box.cpp b/engines/access/bubble_box.cpp
index 494570c3ce8..749fbb7a46b 100644
--- a/engines/access/bubble_box.cpp
+++ b/engines/access/bubble_box.cpp
@@ -336,9 +336,6 @@ void BubbleBox::doBox(int item, int box) {
void BubbleBox::setCursorPos(int posX, int posY) {
Common::Point newPt = Common::Point(posX * 8, posY * 8 + _rowOff);
_vm->_screen->_printStart = _vm->_screen->_printOrg = newPt;
- // This function (at 0x6803) calculates something from a lookup table, but
- // never does anything with it.
- debug("Skipping call to setCursorPos");
}
void BubbleBox::printString(Common::String msg) {
Commit: d4da7f3a236788ccb07c24029d415cc67ebac2e7
https://github.com/scummvm/scummvm/commit/d4da7f3a236788ccb07c24029d415cc67ebac2e7
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-09-23T14:16:11+10:00
Commit Message:
ACCESS: small const correctness fixes
Changed paths:
engines/access/asurface.cpp
engines/access/asurface.h
engines/access/screen.cpp
engines/access/screen.h
diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp
index f01a5542a60..3224b82bef4 100644
--- a/engines/access/asurface.cpp
+++ b/engines/access/asurface.cpp
@@ -163,7 +163,7 @@ void BaseSurface::sPlotB(const SpriteFrame *frame, const Common::Rect &bounds) {
transBlitFrom(*frame, Common::Rect(0, 0, frame->w, frame->h), bounds, TRANSPARENCY, true);
}
-void BaseSurface::copyBlock(BaseSurface *src, const Common::Rect &bounds) {
+void BaseSurface::copyBlock(const BaseSurface *src, const Common::Rect &bounds) {
copyRectToSurface(*src, bounds.left, bounds.top, bounds);
}
diff --git a/engines/access/asurface.h b/engines/access/asurface.h
index 81ead365387..d11e7c936a8 100644
--- a/engines/access/asurface.h
+++ b/engines/access/asurface.h
@@ -90,7 +90,7 @@ public:
*/
void plotB(const SpriteFrame *frame, const Common::Point &pt);
- virtual void copyBlock(BaseSurface *src, const Common::Rect &bounds);
+ virtual void copyBlock(const BaseSurface *src, const Common::Rect &bounds);
virtual void restoreBlock();
diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp
index fbd799369d5..139200ba5ce 100644
--- a/engines/access/screen.cpp
+++ b/engines/access/screen.cpp
@@ -282,7 +282,7 @@ void Screen::restoreScreen() {
_screenYOff = _screenSave._screenYOff;
}
-void Screen::copyBlock(BaseSurface *src, const Common::Rect &bounds) {
+void Screen::copyBlock(const BaseSurface *src, const Common::Rect &bounds) {
Common::Rect destBounds = bounds;
destBounds.translate(_windowXAdd, _windowYAdd + _screenYOff);
diff --git a/engines/access/screen.h b/engines/access/screen.h
index 31341a862af..735db92d88d 100644
--- a/engines/access/screen.h
+++ b/engines/access/screen.h
@@ -86,7 +86,7 @@ public:
*/
void update() override;
- void copyBlock(BaseSurface *src, const Common::Rect &bounds) override;
+ void copyBlock(const BaseSurface *src, const Common::Rect &bounds) override;
void restoreBlock() override;
Commit: 41e40076335002297aeb1d64f51dee1c101dce29
https://github.com/scummvm/scummvm/commit/41e40076335002297aeb1d64f51dee1c101dce29
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-09-23T14:19:26+10:00
Commit Message:
ACCESS: Add myself to engine credits
Changed paths:
engines/access/credits.pl
diff --git a/engines/access/credits.pl b/engines/access/credits.pl
index bfb19a57267..f0b826ba875 100644
--- a/engines/access/credits.pl
+++ b/engines/access/credits.pl
@@ -1,4 +1,5 @@
begin_section("Access");
add_person("Arnaud Boutonné", "Strangerke", "");
add_person("Paul Gilbert", "dreammaster", "");
+ add_person("Matthew Duggan", "stauff", "");
end_section();
Commit: 8fb83ad151beadcf127a5384353abf92bd8f846c
https://github.com/scummvm/scummvm/commit/8fb83ad151beadcf127a5384353abf92bd8f846c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-09-23T19:47:07+10:00
Commit Message:
ACCESS: Implement MM duct section
Changed paths:
A engines/access/martian/martian_duct.cpp
A engines/access/martian/martian_duct.h
R engines/access/martian/martian_tunnel.cpp
R engines/access/martian/martian_tunnel.h
engines/access/events.cpp
engines/access/events.h
engines/access/martian/martian_resources.cpp
engines/access/martian/martian_resources.h
engines/access/martian/martian_scripts.cpp
engines/access/martian/martian_scripts.h
engines/access/module.mk
engines/access/room.cpp
diff --git a/engines/access/events.cpp b/engines/access/events.cpp
index 0196e66a257..e68505420a2 100644
--- a/engines/access/events.cpp
+++ b/engines/access/events.cpp
@@ -130,6 +130,12 @@ bool EventsManager::isCursorVisible() {
return CursorMan.isVisible();
}
+void EventsManager::delayUntilNextFrame() {
+ while (!checkForNextFrameCounter())
+ delay();
+ nextFrame();
+}
+
void EventsManager::pollEvents(bool skipTimers) {
if (checkForNextFrameCounter()) {
nextFrame();
@@ -312,6 +318,7 @@ bool EventsManager::getAction(Common::CustomEventType &action) {
}
}
+
bool EventsManager::isKeyActionPending() const {
return (_keyCode != Common::KEYCODE_INVALID || _action != kActionNone);
}
diff --git a/engines/access/events.h b/engines/access/events.h
index f02a1773dbe..c99a6b5f547 100644
--- a/engines/access/events.h
+++ b/engines/access/events.h
@@ -131,10 +131,16 @@ public:
bool getAction(Common::CustomEventType &action);
+ Common::CustomEventType peekAction() const { return _action; }
+
+ Common::KeyCode peekKeyCode() const { return _keyCode; }
+
bool isKeyActionPending() const;
void delay(int time = 5);
+ void delayUntilNextFrame();
+
void debounceLeft();
void clearEvents();
diff --git a/engines/access/martian/martian_duct.cpp b/engines/access/martian/martian_duct.cpp
new file mode 100644
index 00000000000..9d7679728b5
--- /dev/null
+++ b/engines/access/martian/martian_duct.cpp
@@ -0,0 +1,1286 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "access/martian/martian_duct.h"
+#include "access/martian/martian_game.h"
+#include "access/martian/martian_resources.h"
+
+namespace Access {
+
+namespace Martian {
+
+MartianDuct::MartianDuct(MartianEngine *vm) : _vm(vm), _stopMoveLoop(false), _playerX(0), _preYOffset(0), _playerY(0), _moveAngle(kMoveAngleNorth), _drawDistX(100), _drawDistY(500), _threshold1(50), _crawlFrame(0), _xOffset(160), _yOffset(160), _xScale(100), _yScale(160), _moveIntent(kMoveIntentNone), _primArrayIdx(0), _mapLoc(0), _nextPlayerX(0), _nextPlayerY(0) {
+ ARRAYCLEAR(_matrix[0]);
+ ARRAYCLEAR(_matrix[1]);
+ ARRAYCLEAR(_matrix[2]);
+ ARRAYCLEAR(_tempPoints);
+}
+
+MartianDuct::~MartianDuct() {
+}
+
+void MartianDuct::duct2() {
+ _playerX = 550;
+ _preYOffset = 10;
+ _playerY = 850;
+ doDuct();
+}
+
+void MartianDuct::duct4() {
+ _playerX = 2750;
+ _preYOffset = 10;
+ _playerY = 1050;
+ doDuct();
+}
+
+void MartianDuct::doDuct() {
+ _vm->_screen->forceFadeOut();
+
+ _vm->_screen->_windowXAdd = 0;
+ _vm->_screen->_windowYAdd = 0;
+ _vm->_screen->_screenYOff = 0;
+
+ _vm->_events->hideCursor();
+ _vm->_files->loadScreen(20, 0);
+ Resource *res = _vm->_files->loadFile(20, 1);
+ _vm->_objectsTable[20] = new SpriteResource(_vm, res);
+ if (_vm->_inventory->_inv[40]._value == ITEM_IN_INVENTORY) {
+ // Show map if we have it.
+ _vm->_screen->plotImage(_vm->_objectsTable[20], 8, Common::Point(140, 10));
+ }
+ _vm->_events->showCursor();
+ _vm->_screen->forceFadeIn();
+ _crawlFrame = 0;
+ _xOffset = 160;
+ _yOffset = 100;
+ _xScale = 160;
+ _yScale = 100;
+ // The game initialises some drawing window here but it makes no difference
+ _moveAngle = kMoveAngleNorth;
+ // game has Y and Z angles X fraction part which is always 0
+ _drawDistX = 100;
+ _drawDistY = 500;
+ _threshold1 = 50;
+
+ drawArrowSprites();
+ drawArrowSprites2();
+ _vm->_room->_function = FN_NONE;
+
+ // FIXME: Quick HACK: skip this part
+ //g_system->displayMessageOnOSD(Common::U32String("Duct section not implemented yet!"));
+ //_vm->_flags[0x62] = 1;
+ //_vm->_flags[0x55] = 1;
+ //_vm->_room->_function = FN_CLEAR1;
+ // END HACK
+
+ while (!_vm->shouldQuit()) {
+ clearWorkScreenArea();
+ updateMatrix();
+ applyMatrixToMapData();
+ // Draw duct panels
+ updatePrimsAndDraw();
+ // Draw tex over the top
+ _vm->_buffer2.plotImage(_vm->_objectsTable[20], _crawlFrame, Common::Point(140, 94));
+ copyBufBlockToScreen();
+ if (_vm->_room->_function != FN_NONE)
+ break;
+ do {
+ waitForMoveUpdate();
+ } while (!_stopMoveLoop && !_vm->shouldQuitOrRestart());
+ }
+
+ delete _vm->_objectsTable[20];
+ _vm->_objectsTable[20] = nullptr;
+}
+
+void MartianDuct::drawArrowSprites() {
+ int x;
+ int y;
+ int frame;
+
+ _vm->_events->hideCursor();
+ _vm->_screen->plotImage(_vm->_objectsTable[20], 7, Common::Point(4, 0x50));
+ if (_moveAngle == kMoveAngleNorth) { // (highlight up arrow)
+ x = 0x11;
+ y = 0x50;
+ frame = 9;
+ } else if (_moveAngle == kMoveAngleEast) { // highlight right arrow
+ x = 0x19;
+ y = 0x57;
+ frame = 12;
+ } else if (_moveAngle == kMoveAngleSouth) { // highlight down arrow
+ x = 0xe;
+ y = 0x5d;
+ frame = 11;
+ } else { // West or west2 (left arrow)
+ x = 4;
+ y = 0x57;
+ frame = 10;
+ }
+ _vm->_screen->plotImage(_vm->_objectsTable[20], frame, Common::Point(x, y));
+ _vm->_events->showCursor();
+}
+
+void MartianDuct::drawArrowSprites2() {
+ _vm->_events->hideCursor();
+ _vm->_screen->plotImage(_vm->_objectsTable[20], 14, Common::Point(16, 0x58));
+ if (_mapLoc > 3 && _mapLoc < 13) {
+ _vm->_screen->plotImage(_vm->_objectsTable[20], 13, Common::Point(17, 0x59));
+ }
+ _vm->_events->showCursor();
+}
+
+void MartianDuct::clearWorkScreenArea() {
+ _vm->_buffer2.fillRect(Common::Rect(100, 60, 220, 140), 0);
+ // For testing, clear the whole buffer:
+ //_vm->_buffer2.fillRect(Common::Rect(320, 200), 0);
+}
+
+void MartianDuct::copyBufBlockToScreen() {
+ // Start from row 60, 100 across. 100 px by 80 rows.
+ _vm->_screen->copyBlock(&_vm->_buffer2, Common::Rect(100, 60, 220, 140));
+ // For testing, copy everything:
+ //_vm->_screen->copyBuffer(&_vm->_buffer2);
+}
+
+void MartianDuct::updateMatrix() {
+ // The original does a full fixed-point matrix calculation here, but
+ // half the values are always 1 or 0 so it's much simpler than that.
+ float moveAngleRad = (float)(_moveAngle / 256.0f) * 2.0f * M_PI;
+ float cosVal = cos(moveAngleRad);
+ float sinVal = sin(moveAngleRad);
+
+ // 3D rotation through Y axis. We never rotate through the others.
+ _matrix[0][0] = cosVal;
+ _matrix[0][1] = 0.0f;
+ _matrix[0][2] = sinVal;
+ _matrix[1][0] = 0.0f;
+ _matrix[1][1] = 1.0f;
+ _matrix[1][2] = 0.0f;
+ _matrix[2][0] = -sinVal;
+ _matrix[2][1] = 0.0f;
+ _matrix[2][2] = cosVal;
+}
+
+void MartianDuct::applyMatrixToMapData() {
+ int16 shapeDataIndex;
+ _renderShapes.clear();
+ _renderPoints.clear();
+
+ for (const DuctMapPoint *pMapData = DUCT_MAP_DATA; shapeDataIndex = pMapData->shapeType, shapeDataIndex != -1; pMapData++) {
+ // The original sets the actual drawing x/y here but then uses them
+ // as inputs to the next step so we don't need to set them here.
+ const int16 blockX = pMapData->x;
+ const int16 blockY = pMapData->y;
+ if (abs(blockX + _threshold1 - _playerX) < _drawDistX && abs(blockY + _threshold1 - _playerY) < _drawDistY) {
+ const DuctShape *ptr = DUCT_SHAPE_DATA[shapeDataIndex];
+ const uint startPointNum = _renderPoints.size();
+ const Point3 *pPoint = ptr->points;
+ // The data is the point list followed by the other data.
+ for (int i = 0; i < ptr->numPts; i++) {
+ int16 x = pPoint->x + blockX - _playerX;
+ int16 y = pPoint->y - _preYOffset;
+ int16 z = pPoint->z + blockY - _playerY;
+ pPoint++;
+ doMatrixMulAndAddPoint(x, y, z);
+ }
+
+ const uint16 *dataPtr = ptr->data;
+ for (int j = 0; j < ptr->array2Len; j++) {
+ RenderShape shapeData;
+ // Input struct is byte,ignored,int16,[array of int16]
+ shapeData._col = (byte)dataPtr[0];
+ const int dataCount = dataPtr[1];
+ dataPtr += 2;
+ for (int i = 0; i < dataCount; i++) {
+ shapeData._pointIdxs.push_back(*dataPtr + startPointNum);
+ dataPtr++;
+ }
+ _renderShapes.push_back(shapeData);
+ }
+ }
+ }
+}
+
+void MartianDuct::updatePrimsAndDraw() {
+ int16 shapeZDepth[256];
+ int shapeIndexes[256];
+
+ for (uint i = 0; i < _renderShapes.size(); i++)
+ shapeZDepth[i] = INT16_MIN;
+
+ for (uint shpNum = 0; shpNum < _renderShapes.size(); shpNum++) {
+ const Point3 &pt0 = _renderPoints[_renderShapes[shpNum]._pointIdxs[0]];
+ const Point3 &pt2 = _renderPoints[_renderShapes[shpNum]._pointIdxs[2]];
+ int16 zDepth = ((int)pt0.z + pt2.z) / 2;
+ uint insertPoint = 0;
+ uint i = _renderShapes.size();
+ while (zDepth <= shapeZDepth[insertPoint] && i > 0) {
+ insertPoint++;
+ i--;
+ }
+
+ if (i == 0)
+ continue;
+
+ for (uint j = _renderShapes.size(); j > insertPoint; j--) {
+ shapeZDepth[j] = shapeZDepth[j - 1];
+ shapeIndexes[j] = shapeIndexes[j - 1];
+ }
+
+ shapeZDepth[insertPoint] = zDepth;
+ shapeIndexes[insertPoint] = shpNum;
+ }
+
+ //debug("**** Begin frame ****");
+ for (uint shapeNum = 0; shapeNum < _renderShapes.size(); shapeNum++) {
+ int shapeIdx = shapeIndexes[shapeNum];
+ _vm->_buffer2._lColor = _renderShapes[shapeIdx]._col;
+ int numPoints = _renderShapes[shapeIdx]._pointIdxs.size();
+ _primX1Array.clear();
+ _primY1Array.clear();
+ _primZ1Array.clear();
+ _primX2Array.clear();
+ _primY2Array.clear();
+ _primZ2Array.clear();
+ // Link up the points in order to make a polygon.
+ int ptIdx;
+ for (int pointNum = 0; pointNum < numPoints - 1; pointNum++) {
+ ptIdx = _renderShapes[shapeIdx]._pointIdxs[pointNum];
+ _primX1Array.push_back(_renderPoints[ptIdx].x);
+ _primY1Array.push_back(_renderPoints[ptIdx].y);
+ _primZ1Array.push_back(_renderPoints[ptIdx].z);
+ ptIdx = _renderShapes[shapeIdx]._pointIdxs[pointNum + 1];
+ _primX2Array.push_back(_renderPoints[ptIdx].x);
+ _primY2Array.push_back(_renderPoints[ptIdx].y);
+ _primZ2Array.push_back(_renderPoints[ptIdx].z);
+ }
+ ptIdx = _renderShapes[shapeIdx]._pointIdxs[numPoints - 1];
+ _primX1Array.push_back(_renderPoints[ptIdx].x);
+ _primY1Array.push_back(_renderPoints[ptIdx].y);
+ _primZ1Array.push_back(_renderPoints[ptIdx].z);
+ ptIdx = _renderShapes[shapeIdx]._pointIdxs[0];
+ _primX2Array.push_back(_renderPoints[ptIdx].x);
+ _primY2Array.push_back(_renderPoints[ptIdx].y);
+ _primZ2Array.push_back(_renderPoints[ptIdx].z);
+
+ assert(_primX1Array.size() == (uint)numPoints);
+
+ bool shouldDraw = !doPrimArrayUpdates(numPoints);
+
+ if (!shouldDraw)
+ continue;
+
+ /*
+ debug("** shape %d [%d] color %d ** ", shapeNum, shapeIdx, _vm->_buffer2._lColor);
+ debugN("XYs: ");
+ for (int i = 0; i < numPoints; i++) {
+ int16 x = _primX1Array[i];
+ int16 y = _primY1Array[i];
+ debugN("(%d %d), ", x, y);
+ }
+ debug(".");
+
+ debugN("RBs: ");
+ for (int i = 0; i < numPoints; i++) {
+ int16 x = _primX2Array[i];
+ int16 y = _primY2Array[i];
+ debugN("(%d %d), ", x, y);
+ }
+ debug(".");
+ */
+
+ doDraw(numPoints);
+ }
+ //debug("**** End frame ****");
+}
+
+
+#define POLY_DRAW_CODE 1
+
+
+void MartianDuct::doDraw(int numPoints) {
+
+#if POLY_DRAW_CODE
+ //
+ // This code is not as efficient as the original game, but it's
+ // easier to understand.
+ //
+ // We have a set of line segments in the _prim**Array arrays and want
+ // to draw the polygons that they form, but they are not necessarily
+ // in order or handedness. First remove null segments, then sort the
+ // remaining ones by connecting up the start and end points. Since they
+ // are all simple shapes this works fine.
+ //
+
+ // First remove null lines (same start and end)
+ for (int i = 0; i < numPoints; i++) {
+ if (_primX1Array[i] == _primX2Array[i] && _primY1Array[i] == _primY2Array[i]) {
+ _primX1Array.remove_at(i);
+ _primY1Array.remove_at(i);
+ _primX2Array.remove_at(i);
+ _primY2Array.remove_at(i);
+ numPoints--;
+ i--;
+ continue;
+ }
+ }
+
+ // Sort the line segments
+ Common::Array<int> x1s;
+ Common::Array<int> y1s;
+ Common::Array<int> x2s;
+ Common::Array<int> y2s;
+
+ x1s.push_back(_primX1Array.remove_at(0));
+ y1s.push_back(_primY1Array.remove_at(0));
+ x2s.push_back(_primX2Array.remove_at(0));
+ y2s.push_back(_primY2Array.remove_at(0));
+ int pointsToAdd = numPoints - 1;
+ while (pointsToAdd > 0) {
+ // Find the next line segment to add, could be in either direction.
+ for (int i = 0; i < pointsToAdd; i++) {
+ if (_primX1Array[i] == x2s.back() && _primY1Array[i] == y2s.back()) {
+ x1s.push_back(_primX1Array.remove_at(i));
+ y1s.push_back(_primY1Array.remove_at(i));
+ x2s.push_back(_primX2Array.remove_at(i));
+ y2s.push_back(_primY2Array.remove_at(i));
+ pointsToAdd--;
+ break;
+ } else if (_primX2Array[i] == x2s.back() && _primY2Array[i] == y2s.back()) {
+ x1s.push_back(_primX2Array.remove_at(i));
+ y1s.push_back(_primY2Array.remove_at(i));
+ x2s.push_back(_primX1Array.remove_at(i));
+ y2s.push_back(_primY1Array.remove_at(i));
+ pointsToAdd--;
+ break;
+ }
+ }
+ }
+
+ // Complete the shape to join up to the start again.
+ x1s.push_back(x1s[0]);
+ y1s.push_back(y1s[0]);
+
+ _vm->_buffer2.drawPolygonScan(x1s.data(), y1s.data(), x1s.size(), Common::Rect(320, 200), _vm->_buffer2._lColor);
+
+#else
+
+ int16 maxYVal = 0;
+ int16 minYVal = 0xff;
+ int i = 0;
+
+ // Count of line segments and x1/x2 pairs for each row
+ byte segmentCount[202];
+ int16 segmentCoords[200][16];
+
+ ARRAYCLEAR(segmentCount);
+ for (int y = 0; y < 200; y++)
+ ARRAYCLEAR(segmentCoords[y]);
+
+ do {
+ int16 primitiveX = _primXArray[i];
+ int16 primitiveY = _primYArray[i];
+ int16 primitiveB = _primY2Array[i];
+ int16 primitiveR = _primX2Array[i];
+
+ maxYVal = MAX(maxYVal, primitiveY);
+ maxYVal = MAX(maxYVal, primitiveB);
+ minYVal = MIN(minYVal, primitiveY);
+ minYVal = MIN(minYVal, primitiveB);
+
+ if (primitiveR < primitiveX) {
+ // Flip X and Y
+ SWAP(primitiveX, primitiveR);
+ SWAP(primitiveY, primitiveB);
+ }
+ const int16 width = primitiveR - primitiveX;
+ int16 x = primitiveX;
+ int16 _lastPrimIdx = i;
+
+ if (width == 0) {
+ if (primitiveY != primitiveB) {
+ if (primitiveB <= primitiveY)
+ SWAP(primitiveY, primitiveB);
+
+ int16 y = primitiveY;
+ do {
+ //byte bVar6 = (byte)array_a344[y * 0x10];
+ //*(int16 *)CONCAT11((char)((uint)(array_a344[y * 0x10] >> 8) + CARRY1(bVar6, byteData_bc44[y]),
+ // bVar6 + byteData_bc44[y]) = primitiveX;
+ segmentCoords[y][segmentCount[y]] = primitiveX;
+ segmentCoords[y][segmentCount[y] + 1] = primitiveX;
+ segmentCount[y]++;
+ y++;
+ } while (y != primitiveB);
+ }
+ } else {
+ const int height = primitiveB - primitiveY;
+ if (height < 0) {
+ if (-height < width) {
+ i = -width / 2;
+ int16 y = primitiveY;
+ while (true) {
+ do {
+ x++;
+ i -= height;
+ } while (i < 0);
+ int16 nextY = y - 1;
+ if (nextY == primitiveB)
+ break;
+ //byte bVar6 = (byte)array_a344[nextY * 0x10];
+ //*(int16 *)CONCAT11((char)((uint)(array_a344[nextY * 0x10] >> 8) +
+ // CARRY1(bVar6,byteData_bc44[y]),
+ // bVar6 + byteData_bc44[nextY]) = x;
+ segmentCoords[y][segmentCount[y]] = primitiveX;
+ segmentCoords[y][segmentCount[y] + 1] = x;
+ segmentCount[y]++;
+ i -= width;
+ y = nextY;
+ }
+ } else {
+ i = height / 2;
+ int16 y = primitiveY;
+ int16 nextY;
+ while (nextY = y - 1, nextY != primitiveB) {
+ //byte bVar6 = (byte)array_a344[nextY * 0x10];
+ //*(int16 *)CONCAT11((char)((uint)(array_a344[nextY * 0x10] >> 8) +
+ // CARRY1(bVar6,byteData_bc44[primitiveY]),
+ // bVar6 + byteData_bc44[primitiveY]) = x;
+ segmentCount[-y]++;
+ i += width;
+ y = nextY;
+ if (-1 < i) {
+ x++;
+ i += height;
+ }
+ }
+ }
+
+ SWAP(primitiveX, primitiveR);
+ SWAP(primitiveY, primitiveB);
+ //byte bVar6 = (byte)array_a344[primitiveY * 0x10];
+ //*(int16 *)CONCAT11((char)((uint)(array_a344[primitiveY * 0x10] >> 8) +
+ // CARRY1(bVar6,byteData_bc44[primitiveY]),
+ // bVar6 + byteData_bc44[primitiveY]) = primitiveX;
+ segmentCount[primitiveY]++;
+ } else if (height != 0 && height < width) {
+ i = -width / 2;
+ int16 y = primitiveY;
+ while (true) {
+ do {
+ x++;
+ i += height;
+ } while (i < 0);
+ //byte bVar6 = (byte)array_a344[y * 0x10];
+ //*(int16 *)CONCAT11((char)((uint)(array_a344[y * 0x10] >> 8) +
+ // CARRY1(bVar6,byteData_bc44[y]),
+ // bVar6 + byteData_bc44[y]) = x;
+ segmentCount[y]++;
+ y++;
+ if (y == primitiveB)
+ break;
+ i -= width;
+ }
+ } else if (height != 0) {
+ i = -height / 2;
+ int16 y = primitiveY;
+ while (true) {
+ //byte bVar6 = (byte)array_a344[y * 0x10];
+ //*(int16 *)CONCAT11((char)((uint)(array_a344[y * 0x10] >> 8) +
+ // CARRY1(bVar6,byteData_bc44[y]),
+ // bVar6 + byteData_bc44[y]) = x;
+ segmentCount[y]++;
+ y++;
+ if (y == primitiveB)
+ break;
+ i += width;
+ if (-1 < i) {
+ x++;
+ i -= height;
+ }
+ }
+ }
+ }
+ i = _lastPrimIdx + 1;
+ } while (i != numPoints);
+
+ segmentCount[200] = segmentCount[36];
+ for (int16 y = minYVal; y <= maxYVal; y++) {
+ if (segmentCount[y] == 0)
+ continue;
+
+ int16 *lineData = segmentCoords[y];
+ /*
+ CHECK ME: This probably is supposed to swap incorrect left/right vals, but seems
+ to just check values against themselves?
+ const int16 numSegs = segmentCount[y];
+ int16 right = 0;
+ int16 left = 0;
+ do {
+ const int16 tmpy = lineData[right];
+ if (tmpy < lineData[left]) {
+ lineData[right] = lineData[left];
+ lineData[left] = tmpy;
+ }
+ right++;
+ } while ((right != numSegs) || (right = left + 1, left = right, right != numSegs));
+ */
+ for (int16 segNum = 0; segNum < segmentCount[y]; segNum++) {
+ const int16 x2 = *(lineData + 1);
+ const int16 x1 = *lineData;
+ lineData += 2;
+ byte *pdest = (byte *)_vm->_buffer2.getBasePtr(x1, y);
+ for (i = 0; i < (x2 - x1) + 1; i++) {
+ *pdest = _vm->_buffer2._lColor;
+ pdest++;
+ }
+ }
+ segmentCount[y] = 0;
+ }
+#endif
+}
+
+void MartianDuct::doMatrixMulAndAddPoint(int16 x, int16 y, int16 z) {
+ Point3 pt;
+ pt.x = _matrix[0][0] * x + _matrix[1][0] * y + _matrix[2][0] * z;
+ pt.y = _matrix[0][1] * x + _matrix[1][1] * y + _matrix[2][1] * z;
+ pt.z = _matrix[0][2] * x + _matrix[1][2] * y + _matrix[2][2] * z;
+ _renderPoints.push_back(pt);
+}
+
+bool MartianDuct::doPrimArrayUpdates(int &numPoints) {
+ if (checkAndUpdatePrimArray1(numPoints))
+ return true;
+ if (checkAndUpdatePrimArray2(numPoints))
+ return true;
+ if (checkAndUpdatePrimArray3(numPoints))
+ return true;
+ if (checkAndUpdatePrimArray4(numPoints))
+ return true;
+ if (checkAndUpdatePrimArray5(numPoints))
+ return true;
+
+ assert(numPoints > 0);
+ for (int16 idx = 0; idx < numPoints; idx++) {
+ Point3 pt1, pt2;
+ getPointValuesFromArray(idx, pt1, pt2);
+ // The original changes the drawing primitive coordinates here
+ // but we only need them to store so we use a temp rect instead.
+ const Common::Rect r = calcFinalLineSegment(pt1, pt2);
+ _primX1Array[idx] = r.left;
+ _primY1Array[idx] = r.top;
+ _primX2Array[idx] = r.right;
+ _primY2Array[idx] = r.bottom;
+ }
+ return false;
+}
+
+void MartianDuct::getPointValuesFromArray(int idx, Point3 &pt1, Point3 &pt2) const {
+ pt1.x = _primX1Array[idx];
+ pt1.y = _primY1Array[idx];
+ pt1.z = _primZ1Array[idx];
+ pt2.x = _primX2Array[idx];
+ pt2.y = _primY2Array[idx];
+ pt2.z = _primZ2Array[idx];
+}
+
+Common::Rect MartianDuct::calcFinalLineSegment(const Point3 &pt1, const Point3 &pt2) const {
+ Common::Rect result;
+ result.left = _xOffset + ((int)pt1.x * _xScale) / pt1.z;
+ result.top = _yOffset - ((int)pt1.y * _yScale) / pt1.z;
+ result.right = _xOffset + ((int)pt2.x * _xScale) / pt2.z;
+ result.bottom = _yOffset - ((int)pt2.y * _yScale) / pt2.z;
+ return result;
+}
+
+bool MartianDuct::checkAndUpdatePrimArrayForFlag(int &numPoints, DuctFlags flag, int divmulNum) {
+ _primArrayIdx = 0;
+ int tempCount = 0;
+ for (int idx = 0; idx < numPoints; idx++) {
+ Point3 pt1, pt2;
+ DuctFlags xyflags;
+ DuctFlags rbflags;
+ getPointValuesFromArray(idx, pt1, pt2);
+ getXYandRBFlags(xyflags, rbflags, pt1, pt2);
+ if (xyflags == kDuctFlagNone && rbflags == kDuctFlagNone) {
+ storeLastValsToPrimArray(pt1, pt2); // increments _primArrayIdx
+ } else if (((xyflags | rbflags) & flag) == kDuctFlagNone) {
+ storeLastValsToPrimArray(pt1, pt2);
+ } else if ((xyflags & rbflags & flag) == kDuctFlagNone) {
+ if ((rbflags & flag) == kDuctFlagNone) {
+ // Implicitly xyflags & flag != none
+ assert((xyflags & flag) != kDuctFlagNone);
+ SWAP(pt1, pt2);
+ }
+ switch (divmulNum) {
+ case 1: pt2 = divmul1(pt1, pt2); break;
+ case 2: pt2 = divmul2(pt1, pt2); break;
+ case 3: pt2 = divmul3(pt1, pt2); break;
+ case 4: pt2 = divmul4(pt1, pt2); break;
+ case 5: pt2 = divmul5(pt1, pt2); break;
+ default: error("Invalid divmul num");
+ }
+ _tempPoints[tempCount] = pt2;
+ tempCount++;
+ storeLastValsToPrimArray(pt1, pt2);
+ }
+ }
+ numPoints = addPointsToMainPrimArray(tempCount);
+ return numPoints == 0;
+}
+
+bool MartianDuct::checkAndUpdatePrimArray1(int &numPoints) {
+ return checkAndUpdatePrimArrayForFlag(numPoints, kDuctFlagZLessThan2, 1);
+}
+
+bool MartianDuct::checkAndUpdatePrimArray2(int &numPoints) {
+ return checkAndUpdatePrimArrayForFlag(numPoints, kDuctFlagXLessThanNegZ, 2);
+}
+
+bool MartianDuct::checkAndUpdatePrimArray3(int &numPoints) {
+ return checkAndUpdatePrimArrayForFlag(numPoints, kDuctFlagZLessThanY, 3);
+}
+
+bool MartianDuct::checkAndUpdatePrimArray4(int &numPoints) {
+ return checkAndUpdatePrimArrayForFlag(numPoints, kDuctFlagZLessThanX, 4);
+}
+
+bool MartianDuct::checkAndUpdatePrimArray5(int &numPoints) {
+ return checkAndUpdatePrimArrayForFlag(numPoints, kDuctFlagYLessThanNegZ, 5);
+}
+
+//
+// For these functions the original uses some fixed-point stuff, but replaced
+// it with float to be much cleaner.
+//
+Point3 MartianDuct::divmul1(const Point3 &pt1, const Point3 &pt2) {
+ // called for kDuctFlagXLessThanNegZ
+ Point3 out;
+ out.z = 2;
+ float tmp = (2.0f - pt1.z) / (pt2.z - pt1.z);
+ out.x = (int)round((pt2.x - pt1.x) * tmp + pt1.x);
+ out.y = (int)round((pt2.y - pt1.y) * tmp + pt1.y);
+ return out;
+}
+
+Point3 MartianDuct::divmul2(const Point3 &pt1, const Point3 &pt2) {
+ // called for kDuctFlagXLessThanNegZ
+ Point3 out;
+ float tmp = (pt1.z + pt1.x * 2.0f) / ((pt1.x - pt2.x) * 2 - pt2.z + pt1.z);
+ out.z = (int)round((pt2.z - pt1.z) * tmp + pt1.z);
+ out.x = -(out.z / 2);
+ out.y = (int)round((pt2.y - pt1.y) * tmp + pt1.y);
+ return out;
+}
+
+Point3 MartianDuct::divmul3(const Point3 &pt1, const Point3 &pt2) {
+ // called for kDuctFlagZLessThanY
+ Point3 out;
+ float tmp = (pt1.z - pt1.y * 2.0f) / ((pt2.y - pt1.y) * 2 - pt2.z + pt1.z);
+ out.y = (int)round((pt2.z - pt1.z) * tmp + pt1.z);
+ out.z = out.y;
+ out.x = (int)round((pt2.x - pt1.x) * tmp + pt1.x);
+ return out;
+}
+
+Point3 MartianDuct::divmul4(const Point3 &pt1, const Point3 &pt2) {
+ // called for kDuctFlagZLessThanX
+ Point3 out;
+ float tmp = (pt1.z - pt1.x * 2.0f) / ((pt2.x - pt1.x) * 2 - pt2.z + pt1.z);
+ out.z = (int)round((pt2.z - pt1.z) * tmp + pt1.z);
+ out.x = out.z / 2;
+ out.y = (int)round((pt2.y - pt1.y) * tmp + pt1.y);
+ return out;
+}
+
+Point3 MartianDuct::divmul5(const Point3 &pt1, const Point3 &pt2) {
+ // called for kDuctFlagYLessThanNegZ
+ Point3 out;
+ float tmp = (pt1.z + pt1.y * 2.0f) / ((pt1.y - pt2.y) * 2 - pt2.z + pt1.z);
+ out.z = (int)round((pt2.z - pt1.z) * tmp + pt1.z);
+ out.y = -(out.z / 2);
+ out.x = (int)round((pt2.x - pt1.x) * tmp + pt1.x);
+ return out;
+}
+
+
+void MartianDuct::getXYandRBFlags(DuctFlags &xyflags, DuctFlags &rbflags, const Point3 &pt1, const Point3 &pt2) {
+ xyflags = getComparisonFlags(pt1.x * 2, pt1.y * 2, pt1.z);
+ rbflags = getComparisonFlags(pt2.x * 2, pt2.y * 2, pt2.z);
+}
+
+int MartianDuct::addPointsToMainPrimArray(int tempCount) {
+ int dstIdx = _primArrayIdx;
+ // Resize arrays if we need to.
+ if (dstIdx + tempCount > (int)_primX1Array.size()) {
+ _primX1Array.resize(dstIdx + tempCount);
+ _primY1Array.resize(dstIdx + tempCount);
+ _primZ1Array.resize(dstIdx + tempCount);
+ _primX2Array.resize(dstIdx + tempCount);
+ _primY2Array.resize(dstIdx + tempCount);
+ _primZ2Array.resize(dstIdx + tempCount);
+ }
+
+ for (int srcidx = 0; srcidx < tempCount; srcidx += 2) {
+ _primX1Array[dstIdx] = _tempPoints[srcidx].x;
+ _primY1Array[dstIdx] = _tempPoints[srcidx].y;
+ _primZ1Array[dstIdx] = _tempPoints[srcidx].z;
+ _primX2Array[dstIdx] = _tempPoints[srcidx + 1].x;
+ _primY2Array[dstIdx] = _tempPoints[srcidx + 1].y;
+ _primZ2Array[dstIdx] = _tempPoints[srcidx + 1].z;
+ dstIdx++;
+ }
+
+ return dstIdx;
+}
+
+DuctFlags MartianDuct::getComparisonFlags(int16 x, int16 y, int16 z) {
+ enum DuctFlags flags = kDuctFlagNone;
+ if (z < 2)
+ flags = kDuctFlagZLessThan2;
+
+ if (z < y)
+ flags = (DuctFlags)(flags | kDuctFlagZLessThanY);
+
+ if (z < x)
+ flags = (DuctFlags)(flags | kDuctFlagZLessThanX);
+
+ if (x < -z)
+ flags = (DuctFlags)(flags | kDuctFlagXLessThanNegZ);
+
+ if (y < -z)
+ flags = (DuctFlags)(flags | kDuctFlagYLessThanNegZ);
+
+ return flags;
+}
+
+void MartianDuct::waitForMoveUpdate() {
+ // Holding down Insert and O together skips the duct in the original.
+ // Simplify to just accept O.
+ if (_vm->_events->peekKeyCode() == Common::KEYCODE_o) {
+ _vm->_room->_function = FN_CLEAR1;
+ _vm->_flags[0x55] = 1;
+ _vm->_flags[0x62] = 1;
+ _stopMoveLoop = true;
+ return;
+ }
+
+ _stopMoveLoop = false;
+ // Wait for next frame.
+ // Frame rate is set as 100fps, but we really want more like 30.
+ _vm->_events->delayUntilNextFrame();
+ _vm->_events->delayUntilNextFrame();
+ _vm->_events->delayUntilNextFrame();
+ _vm->_events->pollEvents();
+ Common::CustomEventType action = _vm->_events->peekAction();
+
+ Common::Array<Common::Rect> btnCoords;
+ for (int i = 0; Martian::DUCT_ARROW_BUTTON_RANGE[i][0] != -1; i += 2) {
+ // DUCT_ARROW_BUTTON_RANGE is min/max X, min/max Y
+ btnCoords.push_back(Common::Rect(
+ Martian::DUCT_ARROW_BUTTON_RANGE[i][0],
+ Martian::DUCT_ARROW_BUTTON_RANGE[i + 1][0],
+ Martian::DUCT_ARROW_BUTTON_RANGE[i][1],
+ Martian::DUCT_ARROW_BUTTON_RANGE[i + 1][1]));
+ }
+
+ // Note: buttons are 0 = up, 1 = left, 2 = down, 3 = right
+ int hitButton = -1;
+ if (_vm->_events->_leftButton)
+ hitButton = _vm->_events->checkMouseBox1(btnCoords);
+
+ if (action == kActionMoveUp || hitButton == 0) {
+ _moveIntent = kMoveIntentUp;
+ drawArrowSprites2();
+ if (updateMapLocation()) {
+ checkFinished();
+ return;
+ }
+ drawArrowSprites2();
+ if (_moveAngle == kMoveAngleNorth) {
+ _playerY += 7;
+ } else if (_moveAngle == kMoveAngleSouth) {
+ _playerY -= 7;
+ } else if (_moveAngle == kMoveAngleEast) {
+ _playerX += 7;
+ } else if (_moveAngle == kMoveAngleWest) {
+ _playerX -= 7;
+ } else {
+ checkFinished();
+ return;
+ }
+ _stopMoveLoop = true;
+ _crawlFrame++;
+ if (_crawlFrame == 7)
+ _crawlFrame = 0;
+
+ checkFinished();
+ return;
+ } else if (action == kActionMoveDown || hitButton == 2) {
+ _moveIntent = kMoveIntentDown;
+ drawArrowSprites2();
+ if (updateMapLocation()) {
+ checkFinished();
+ return;
+ }
+
+ drawArrowSprites2();
+ if (_moveAngle == kMoveAngleNorth) {
+ _playerY -= 7;
+ } else if (_moveAngle == kMoveAngleSouth) {
+ _playerY += 7;
+ } else if (_moveAngle == kMoveAngleEast) {
+ _playerX -= 7;
+ } else if (_moveAngle == kMoveAngleWest) {
+ _playerX += 7;
+ } else {
+ checkFinished();
+ return;
+ }
+ _stopMoveLoop = true;
+ _crawlFrame--;
+ if (_crawlFrame < 0)
+ _crawlFrame = 6;
+
+ checkFinished();
+ return;
+ } else if (action == kActionMoveLeft || hitButton == 1) {
+ _moveIntent = kMoveIntentLeft;
+ // Action handled, clear it
+ _vm->_events->getAction(action);
+ updateMapLocation();
+ } else if (action == kActionMoveRight || hitButton == 3) {
+ _moveIntent = kMoveIntentRight;
+ // Action handled, clear it
+ _vm->_events->getAction(action);
+ updateMapLocation();
+ } else {
+ checkFinished();
+ return;
+ }
+
+ _moveAngle = (MoveAngle)(_moveAngle & 0xff);
+ drawArrowSprites();
+ drawArrowSprites2();
+ _drawDistX = 200;
+ _drawDistY = 500;
+ if (_moveAngle != kMoveAngleNorth && _moveAngle != kMoveAngleSouth) {
+ _drawDistX = 500;
+ _drawDistY = 200;
+ }
+ _stopMoveLoop = true;
+}
+
+void MartianDuct::checkFinished() {
+ // Check the player position against the exits
+ if (abs(_playerX - 2650) < 50 && abs(_playerY - 1050) < 50) {
+ _vm->_flags[98] = 0;
+ _vm->_room->_function = FN_CLEAR1;
+ }
+ else if (abs(_playerX - 550) < 50 && abs(_playerY - 750) < 50) {
+ // Finished!
+ _vm->_flags[98] = 1;
+ _vm->_flags[85] = 1;
+ _vm->_room->_function = FN_CLEAR1;
+ }
+}
+
+bool MartianDuct::updateMapLocation() {
+ uint16 blk = _threshold1 * 2;
+ _nextPlayerX = (_playerX / blk) * blk + _threshold1;
+ _nextPlayerY = (_playerY / blk) * blk + _threshold1;
+ const DuctMapPoint *mapPt = DUCT_MAP_DATA;
+ do {
+ const int16 pyType = mapPt->ptType;
+ if (pyType == -1)
+ return true;
+
+ if (pyType != 0xff) {
+ _mapLoc = pyType;
+
+ int16 thresh = _threshold1;
+ if (pyType == 6 || pyType == 10)
+ thresh = -_threshold1;
+
+ if (abs((mapPt->x + thresh) - _nextPlayerX) <= _threshold1) {
+ thresh = _threshold1;
+ if (pyType == 8)
+ thresh = -_threshold1;
+
+ if (abs((mapPt->y + thresh) - _nextPlayerY) <= _threshold1) {
+ switch (pyType) {
+ case 0: return checkMove0();
+ case 1: return checkMove1();
+ case 2: return checkMove2();
+ case 3: return checkMove3();
+ case 4: return checkMove4();
+ case 5: return checkMove5();
+ case 6: return checkMove6();
+ case 7: return checkMove7();
+ case 8: return checkMove8();
+ case 9: return checkMove9();
+ case 10: return checkMove10();
+ case 11: return checkMove11();
+ case 12: return checkMove12();
+ case 13: return checkMove13_14();
+ case 14: return checkMove13_14();
+ default: error("Unexpected point type in duct map data %d", pyType); return false;
+ }
+ }
+ }
+ }
+ mapPt++;
+ } while( true );
+
+}
+
+void MartianDuct::storeLastValsToPrimArray(const Point3 &pt1, const Point3 &pt2) {
+ _primX1Array[_primArrayIdx] = pt1.x;
+ _primY1Array[_primArrayIdx] = pt1.y;
+ _primZ1Array[_primArrayIdx] = pt1.z;
+ _primX2Array[_primArrayIdx] = pt2.x;
+ _primY2Array[_primArrayIdx] = pt2.y;
+ _primZ2Array[_primArrayIdx] = pt2.z;
+ _primArrayIdx++;
+}
+
+bool MartianDuct::checkMove0() {
+ if (_moveIntent == kMoveIntentRight || _moveIntent == kMoveIntentLeft) {
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleSouth);
+ return false;
+ }
+
+ if (_moveIntent == kMoveIntentUp) {
+ if (_moveAngle == kMoveAngleWest)
+ return true;
+
+ } else if (_moveIntent == kMoveIntentDown && _moveAngle == kMoveAngleEast) {
+ return true;
+ }
+ return false;
+}
+
+bool MartianDuct::checkMove1() {
+ if ((_moveIntent == kMoveIntentRight) || (_moveIntent == kMoveIntentLeft)) {
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleSouth);
+ return false;
+ }
+
+ if (_moveIntent == kMoveIntentUp) {
+ if (_moveAngle == kMoveAngleEast)
+ return true;
+ } else if (_moveIntent == kMoveIntentDown && _moveAngle == kMoveAngleWest) {
+ return true;
+ }
+ return false;
+}
+
+bool MartianDuct::checkMove2() {
+ if (_moveIntent == kMoveIntentRight || _moveIntent == kMoveIntentLeft) {
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleSouth);
+ return false;
+ }
+ if (_moveIntent == kMoveIntentUp) {
+ if (_moveAngle == kMoveAngleSouth)
+ return true;
+ } else if (_moveIntent == kMoveIntentDown && _moveAngle == kMoveAngleNorth) {
+ return true;
+ }
+ return false;
+}
+
+bool MartianDuct::checkMove3() {
+ if (_moveIntent == kMoveIntentRight || _moveIntent == kMoveIntentLeft) {
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleSouth);
+ return false;
+ }
+ if (_moveIntent == kMoveIntentUp) {
+ if (_moveAngle == kMoveAngleNorth)
+ return true;
+
+ } else if (_moveIntent == kMoveIntentDown && _moveAngle == kMoveAngleSouth) {
+ return true;
+ }
+ return false;
+}
+
+bool MartianDuct::checkMove4() {
+ if (_moveIntent == kMoveIntentRight) {
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft)
+ return false;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove5() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle == kMoveAngleSouth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleWest;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleEast)
+ return false;
+
+ return true;
+ }
+ if (_moveAngle == kMoveAngleNorth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove6() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle == kMoveAngleNorth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleEast;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleWest)
+ return false;
+
+ return true;
+ }
+ if (_moveAngle == kMoveAngleSouth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove7() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle == kMoveAngleEast)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ }
+ else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleSouth;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleNorth)
+ return false;
+
+ return true;
+ }
+ if (_moveAngle == kMoveAngleWest)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove8() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle == kMoveAngleWest)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleNorth;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleSouth)
+ return false;
+
+ return true;
+ }
+
+ if (_moveAngle == kMoveAngleEast)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove9() {
+ if (_moveIntent == kMoveIntentRight) {
+ if ((_moveAngle != kMoveAngleNorth) && (_moveAngle != kMoveAngleEast)) {
+ return true;
+ }
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleWest || _moveAngle == kMoveAngleNorth;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleEast)
+ return _moveAngle == kMoveAngleSouth;
+
+ return true;
+ }
+ if (_moveAngle != kMoveAngleWest && _moveAngle != kMoveAngleSouth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove10() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle != kMoveAngleEast && _moveAngle != kMoveAngleSouth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleEast || _moveAngle == kMoveAngleNorth;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleWest)
+ return _moveAngle == kMoveAngleSouth;
+
+ return true;
+ }
+ if (_moveAngle != kMoveAngleNorth && _moveAngle != kMoveAngleWest)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove11() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle != kMoveAngleWest && _moveAngle != kMoveAngleNorth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleWest || _moveAngle == kMoveAngleSouth;
+
+ if (_moveIntent != kMoveIntentDown) {
+ return true;
+ }
+ if (_moveAngle != kMoveAngleNorth) {
+ return _moveAngle == kMoveAngleEast;
+ }
+ return true;
+ }
+ if (_moveAngle != kMoveAngleSouth && _moveAngle != kMoveAngleEast)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove12() {
+ if (_moveIntent == kMoveIntentRight) {
+ if (_moveAngle != kMoveAngleSouth && _moveAngle != kMoveAngleWest)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleEast);
+ } else {
+ if (_moveIntent != kMoveIntentLeft) {
+ if (_moveIntent == kMoveIntentUp)
+ return _moveAngle == kMoveAngleEast || _moveAngle == kMoveAngleSouth;
+
+ if (_moveIntent != kMoveIntentDown)
+ return true;
+
+ if (_moveAngle != kMoveAngleNorth)
+ return _moveAngle == kMoveAngleWest;
+
+ return true;
+ }
+ if (_moveAngle != kMoveAngleEast && _moveAngle != kMoveAngleNorth)
+ return true;
+
+ _moveAngle = (MoveAngle)(_moveAngle - kMoveAngleEast);
+ }
+ _playerY = _nextPlayerY;
+ _playerX = _nextPlayerX;
+ return false;
+}
+
+bool MartianDuct::checkMove13_14() {
+ if (_moveIntent != kMoveIntentRight && _moveIntent != kMoveIntentLeft)
+ return false;
+
+ _moveAngle = (MoveAngle)(_moveAngle + kMoveAngleSouth);
+ return false;
+}
+
+
+
+}
+
+} // end namespace Access
diff --git a/engines/access/martian/martian_duct.h b/engines/access/martian/martian_duct.h
new file mode 100644
index 00000000000..c4e0cb70c80
--- /dev/null
+++ b/engines/access/martian/martian_duct.h
@@ -0,0 +1,172 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ACCESS_MARTIAN_MARTIAN_DUCT_H
+#define ACCESS_MARTIAN_MARTIAN_DUCT_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/events.h"
+
+#include "access/martian/martian_resources.h" // For Point3 .. move it?
+
+namespace Access {
+
+namespace Martian {
+
+enum MoveIntent {
+ kMoveIntentNone,
+ kMoveIntentUp,
+ kMoveIntentLeft,
+ kMoveIntentDown,
+ kMoveIntentRight,
+};
+
+// Move angles - in the original these are indexes into sin/cos lookup tables.
+// Add Invalid to ensure at least 2-byte length.
+enum MoveAngle {
+ kMoveAngleNorth = 0,
+ kMoveAngleEast = 0x40,
+ kMoveAngleSouth = 0x80,
+ kMoveAngleWest = 0xC0,
+ kMoveAngleInvalid = 0xffff,
+};
+
+enum DuctFlags {
+ kDuctFlagNone = 0,
+ kDuctFlagZLessThanX = 1,
+ kDuctFlagXLessThanNegZ = 2,
+ kDuctFlagYLessThanNegZ = 4,
+ kDuctFlagZLessThanY = 8,
+ kDuctFlagZLessThan2 = 16,
+};
+
+struct RenderShape {
+ byte _col;
+ Common::Array<uint16> _pointIdxs;
+};
+
+class MartianEngine;
+
+class MartianDuct {
+public:
+ MartianDuct(MartianEngine *vm);
+ ~MartianDuct();
+
+ void duct2();
+ void duct4();
+
+private:
+ void doDuct();
+ void drawArrowSprites();
+ void drawArrowSprites2();
+ void clearWorkScreenArea();
+ void copyBufBlockToScreen();
+ void waitForMoveUpdate();
+ void storeLastValsToPrimArray(const Point3 &pt1, const Point3 &pt2);
+ void updatePlayerPos();
+ void updateMatrix();
+ void applyMatrixToMapData();
+ void updatePrimsAndDraw();
+ bool updateMapLocation();
+ void checkFinished();
+ void doMatrixMulAndAddPoint(int16 x, int16 y, int16 z);
+ bool doPrimArrayUpdates(int &tempIdx);
+ void doDraw(int counter);
+
+ void getPointValuesFromArray(int offset, Point3 &pt1, Point3 &pt2) const;
+ Common::Rect calcFinalLineSegment(const Point3 &pt1, const Point3 &pt2) const;
+
+ bool checkAndUpdatePrimArray1(int &offset);
+ bool checkAndUpdatePrimArray2(int &offset);
+ bool checkAndUpdatePrimArray3(int &offset);
+ bool checkAndUpdatePrimArray4(int &offset);
+ bool checkAndUpdatePrimArray5(int &offset);
+ bool checkAndUpdatePrimArrayForFlag(int &offset, DuctFlags flag, int divmulNum);
+
+ static Point3 divmul1(const Point3 &pt1, const Point3 &pt2);
+ static Point3 divmul2(const Point3 &pt1, const Point3 &pt2);
+ static Point3 divmul3(const Point3 &pt1, const Point3 &pt2);
+ static Point3 divmul4(const Point3 &pt1, const Point3 &pt2);
+ static Point3 divmul5(const Point3 &pt1, const Point3 &pt2);
+
+ bool checkMove0();
+ bool checkMove1();
+ bool checkMove2();
+ bool checkMove3();
+ bool checkMove4();
+ bool checkMove5();
+ bool checkMove6();
+ bool checkMove7();
+ bool checkMove8();
+ bool checkMove9();
+ bool checkMove10();
+ bool checkMove11();
+ bool checkMove12();
+ bool checkMove13_14();
+
+ void getXYandRBFlags(DuctFlags &xyflags, DuctFlags &rbflags, const Point3 &pt1, const Point3 &pt2);
+ int addPointsToMainPrimArray(int tempCount);
+ static DuctFlags getComparisonFlags(int16 x, int16 y, int16 z);
+
+ MartianEngine *_vm;
+ int16 _playerX;
+ int16 _preYOffset;
+ int16 _playerY;
+
+ int16 _nextPlayerX;
+ int16 _nextPlayerY;
+ int16 _xOffset;
+ int16 _yOffset;
+ int16 _xScale;
+ int16 _yScale;
+ uint16 _mapLoc;
+ MoveAngle _moveAngle;
+ int16 _crawlFrame;
+ bool _stopMoveLoop;
+ int16 _threshold1;
+ int16 _drawDistX;
+ int16 _drawDistY;
+ MoveIntent _moveIntent;
+
+ // NOTE: Original uses fixed point sin/cos with a lookup table.
+ float _matrix[3][3];
+
+ int16 _primArrayIdx;
+
+ Common::Array<Point3> _renderPoints;
+ Common::Array<RenderShape> _renderShapes;
+
+ Common::Array<int16> _primX1Array;
+ Common::Array<int16> _primY1Array;
+ Common::Array<int16> _primZ1Array;
+ Common::Array<int16> _primX2Array;
+ Common::Array<int16> _primY2Array;
+ Common::Array<int16> _primZ2Array;
+ Point3 _tempPoints[32];
+};
+
+}
+
+} // end namespace Access
+
+#endif // ACCESS_MARTIAN_MARTIAN_DUCT_H
diff --git a/engines/access/martian/martian_resources.cpp b/engines/access/martian/martian_resources.cpp
index 1eaee751437..2be75baacb7 100644
--- a/engines/access/martian/martian_resources.cpp
+++ b/engines/access/martian/martian_resources.cpp
@@ -142,7 +142,7 @@ const byte CAN_TRAVEL_MATRIX[] = {
1
};
-const int PICTURERANGE[][2] = {
+const int16 PICTURE_RANGE[][2] = {
// { min X, max X}, {min Y, max Y}
{ 20, 30 }, { 82, 87 },
{ 20, 30 }, { 105, 110 },
@@ -153,6 +153,505 @@ const int PICTURERANGE[][2] = {
{ -1, -1 }
};
+const int16 DUCT_ARROW_BUTTON_RANGE[][2] = {
+// { min X, max X}, {min Y, max Y}
+ { 12, 23 }, { 80, 87 }, // up button
+ { 4, 15 }, { 87, 93 }, // left button
+ { 14, 26 }, { 93, 104 },// down button
+ { 25, 36 }, { 87, 93 }, // right button
+ { -1, -1 }
+};
+
+const DuctMapPoint DUCT_MAP_DATA[] = {
+ // type //shapetype // x // y
+ { 0x0, 0xB, 0x0, 0x4B0, },
+ { 0xD, 0x10, 0x64, 0x4B0, },
+ { 0xA, 0xD, 0x12C, 0x4B0, },
+ { 0xE, 0xA, 0xC8, 0x44C, },
+ { 0xE, 0xF, 0xC8, 0x3E8, },
+ { 0x5, 0xD, 0xC8, 0x384, },
+ { 0xE, 0xA, 0xC8, 0x320, },
+ { 0xC, 0xC, 0xC8, 0x2BC, },
+ { 0xD, 0xB, 0x64, 0x2BC, },
+ { 0x0, 0x10, 0x0, 0x2BC, },
+ { 0xD, 0xB, 0x12C, 0x384, },
+ { 0xD, 0x10, 0x190, 0x384, },
+ { 0x3, 0xA, 0x1F4, 0x514, },
+ { 0xE, 0xF, 0x1F4, 0x4B0, },
+ { 0xE, 0xA, 0x1F4, 0x44C, },
+ { 0xE, 0xF, 0x1F4, 0x3E8, },
+ { 0xFF, 0xD, 0x0, 0x4B0, },
+ { 0xE, 0xA, 0x1F4, 0x320, },
+ { 0x2, 0xF, 0x1F4, 0x2BC, },
+ { 0xD, 0xB, 0x258, 0x384, },
+ { 0xD, 0x10, 0x2BC, 0x384, },
+ { 0xD, 0xB, 0x320, 0x384, },
+ { 0xD, 0x10, 0x384, 0x384, },
+ { 0x1, 0xB, 0x578, 0x514, },
+ { 0xD, 0x10, 0x514, 0x514, },
+ { 0xD, 0xB, 0x4B0, 0x514, },
+ { 0xD, 0x10, 0x44C, 0x514, },
+ { 0x9, 0xD, 0x3E8, 0x514, },
+ { 0xE, 0xA, 0x3E8, 0x4B0, },
+ { 0xE, 0xF, 0x3E8, 0x44C, },
+ { 0xE, 0xA, 0x3E8, 0x3E8, },
+ { 0xFF, 0xD, 0x0, 0x2BC, },
+ { 0xE, 0xA, 0x3E8, 0x320, },
+ { 0xE, 0xF, 0x3E8, 0x2BC, },
+ { 0xE, 0xA, 0x3E8, 0x258, },
+ { 0x5, 0xD, 0x3E8, 0x1F4, },
+ { 0xE, 0xA, 0x3E8, 0x190, },
+ { 0xE, 0xF, 0x3E8, 0x12C, },
+ { 0xE, 0xA, 0x3E8, 0xC8, },
+ { 0xB, 0xD, 0x3E8, 0x64, },
+ { 0xD, 0xB, 0x44C, 0x64, },
+ { 0x8, 0xC, 0x4B0, 0xC8, },
+ { 0x2, 0xA, 0x4B0, 0x0, },
+ { 0xD, 0xB, 0x514, 0x64, },
+ { 0xD, 0x10, 0x578, 0x64, },
+ { 0xD, 0xB, 0x5DC, 0x64, },
+ { 0xD, 0x10, 0x640, 0x64, },
+ { 0x8, 0xC, 0x6A4, 0xC8, },
+ { 0xC, 0xA, 0x6A4, 0x0, },
+ { 0xD, 0xB, 0x708, 0x64, },
+ { 0xD, 0x10, 0x76C, 0x64, },
+ { 0x7, 0xC, 0x7D0, 0x64, },
+ { 0xD, 0xB, 0x834, 0x64, },
+ { 0x8, 0xC, 0x898, 0xC8, },
+ { 0x2, 0xA, 0x898, 0x0, },
+ { 0xD, 0xC, 0x8FC, 0x64, },
+ { 0x7, 0xB, 0x960, 0x64, },
+ { 0xD, 0x10, 0x9C4, 0x64, },
+ { 0xD, 0xB, 0xA28, 0x64, },
+ { 0x1, 0x10, 0xA8C, 0x64, },
+ { 0xE, 0xA, 0x960, 0xC8, },
+ { 0x9, 0xD, 0x960, 0x12C, },
+ { 0xD, 0xB, 0x9C4, 0x12C, },
+ { 0xD, 0x10, 0xA28, 0x12C, },
+ { 0xD, 0xB, 0xA8C, 0x12C, },
+ { 0x1, 0x10, 0x8F0, 0x17C, },
+ { 0xE, 0xA, 0x7D0, 0xC8, },
+ { 0x6, 0xD, 0x834, 0x12C, },
+ { 0xD, 0xA, 0x76C, 0x12C, },
+ { 0x0, 0xF, 0x708, 0x12C, },
+ { 0xE, 0xA, 0x7D0, 0x190, },
+ { 0x9, 0xD, 0x7D0, 0x1F4, },
+ { 0xD, 0xB, 0x834, 0x1F4, },
+ { 0xD, 0x10, 0x898, 0x1F4, },
+ { 0xD, 0xB, 0x8FC, 0x1F4, },
+ { 0xD, 0x10, 0x960, 0x1F4, },
+ { 0xD, 0xB, 0x9C4, 0x1F4, },
+ { 0xD, 0x10, 0xA28, 0x1F4, },
+ { 0xC, 0xC, 0xA8C, 0x1F4, },
+ { 0xE, 0xA, 0xA8C, 0x258, },
+ { 0xE, 0xF, 0xA8C, 0x2BC, },
+ { 0xE, 0xA, 0xA8C, 0x320, },
+ { 0xE, 0xF, 0xA8C, 0x384, },
+ { 0xA, 0xD, 0xAF0, 0x3E8, },
+ { 0xD, 0xB, 0xA28, 0x3E8, },
+ { 0xD, 0x10, 0x44C, 0x1F4, },
+ { 0xD, 0xB, 0x4B0, 0x1F4, },
+ { 0xD, 0x10, 0x514, 0x1F4, },
+ { 0x8, 0xC, 0x578, 0x258, },
+ { 0xE, 0xA, 0x578, 0x190, },
+ { 0x2, 0xF, 0x578, 0x12C, },
+ { 0xD, 0xB, 0x5DC, 0x1F4, },
+ { 0x7, 0xC, 0x640, 0x1F4, },
+ { 0xD, 0xB, 0x6A4, 0x1F4, },
+ { 0x1, 0x10, 0x708, 0x1F4, },
+ { 0xE, 0xA, 0x640, 0x258, },
+ { 0xE, 0xF, 0x640, 0x2BC, },
+ { 0xE, 0xA, 0x640, 0x320, },
+ { 0xD, 0xB, 0x44C, 0x384, },
+ { 0xD, 0x10, 0x4B0, 0x384, },
+ { 0x7, 0xC, 0x514, 0x384, },
+ { 0xE, 0xA, 0x514, 0x3E8, },
+ { 0x3, 0xF, 0x514, 0x44C, },
+ { 0xD, 0xB, 0x578, 0x384, },
+ { 0xD, 0x10, 0x5DC, 0x384, },
+ { 0xFF, 0xC, 0x3E8, 0x578, },
+ { 0xE, 0xB, 0x640, 0x3E8, },
+ { 0xE, 0x10, 0x640, 0x44C, },
+ { 0xE, 0xB, 0x640, 0x4B0, },
+ { 0x3, 0x10, 0x640, 0x514, },
+ { 0xD, 0xB, 0x6A4, 0x384, },
+ { 0x1, 0x10, 0x708, 0x384, },
+ { 0xFF, 0xC, 0x1F4, 0x578, },
+ { 0xFF, 0xC, 0xC8, 0x514, },
+ { 0xFF, 0xD, 0x12C, 0x2BC, },
+ { 0xFF, 0xD, 0x5DC, 0x514, },
+ { 0xFF, 0xC, 0x3E8, 0x64, },
+ { 0xFF, 0xD, 0xAF0, 0x64, },
+ { 0xFF, 0xC, 0x960, 0x190, },
+ { 0xFF, 0xD, 0x708, 0x12C, },
+ { 0xFF, 0xC, 0x7D0, 0x258, },
+ { 0xFF, 0xD, 0xAF0, 0x1F4, },
+ { 0xFF, 0xC, 0xA8C, 0x44C, },
+ { 0xFF, 0xC, 0x578, 0x12C, },
+ { 0xFF, 0xD, 0x76C, 0x1F4, },
+ { 0xFF, 0xC, 0x514, 0x4B0, },
+ { 0xFF, 0xC, 0x640, 0x578, },
+ { 0xFF, 0xD, 0x76C, 0x384, },
+ { 0x4, 0xE, 0x1F4, 0x384, },
+ { 0x4, 0xE, 0x3E8, 0x384, },
+ { 0x4, 0xE, 0x640, 0x384, },
+ { 0xFF, 0xE, 0xC8, 0x384, },
+ { 0xFF, 0xE, 0xC8, 0x2BC, },
+ { 0xFF, 0xE, 0xC8, 0x4B0, },
+ { 0xFF, 0xE, 0x3E8, 0x514, },
+ { 0xFF, 0xE, 0x3E8, 0x64, },
+ { 0xFF, 0xE, 0x514, 0x384, },
+ { 0xFF, 0xE, 0x4B0, 0x0, },
+ { 0xFF, 0xE, 0x578, 0x1F4, },
+ { 0xFF, 0xE, 0x640, 0x1F4, },
+ { 0xFF, 0xE, 0x6A4, 0x0, },
+ { 0xFF, 0xE, 0x7D0, 0x12C, },
+ { 0xFF, 0xE, 0x7D0, 0x1F4, },
+ { 0xFF, 0xE, 0x898, 0x0, },
+ { 0xFF, 0xE, 0x960, 0x64, },
+ { 0xFF, 0xE, 0x960, 0x12C, },
+ { 0xFF, 0xE, 0xA8C, 0x1F4, },
+ { 0xFF, 0xE, 0xA8C, 0x3E8, },
+ { 0xFF, 0xE, 0x3E8, 0x1F4, },
+ { -1, -1, -1, -1, },
+};
+
+static const Point3 DUCT_SHAPE_0_POINTS[] = {
+ { 0, 300, 0 }, { 0, 100, 0 },
+ { 100, 400, 0 }, { 100, 0, 0 },
+ { 300, 400, 0 }, { 300, 0, 0 },
+ { 400, 300, 0 }, { 400, 100, 0 },
+ { 0, 300, 500 }, { 0, 100, 500 },
+ { 100, 400, 500 }, { 100, 0, 500 },
+ { 300, 400, 500 }, { 300, 0, 500 },
+ { 400, 300, 500 }, { 400, 100, 500 },
+};
+static const Point3 DUCT_SHAPE_1_POINTS[] = {
+ { 0, 300, 400 }, { 0, 100, 400 },
+ { 0, 400, 300 }, { 0, 0, 300 },
+ { 0, 400, 100 }, { 0, 0, 100 },
+ { 0, 300, 0 }, { 0, 100, 0 },
+ { 500, 300, 400 }, { 500, 100, 400 },
+ { 500, 400, 300 }, { 500, 0, 300 },
+ { 500, 400, 100 }, { 500, 0, 100 },
+ { 500, 300, 0 }, { 500, 100, 0 },
+};
+static const Point3 DUCT_SHAPE_2_POINTS[] = {
+ { 0, 300, 500 }, { 0, 100, 500 },
+ { 100, 400, 500 }, { 100, 0, 500 },
+ { 300, 400, 500 }, { 300, 0, 500 },
+ { 400, 300, 500 }, { 400, 100, 500 },
+ { 40, 300, 300 }, { 40, 100, 300 },
+ { 130, 400, 340 }, { 130, 0, 340 },
+ { 320, 400, 400 }, { 320, 0, 400 },
+ { 410, 300, 450 }, { 410, 100, 450 },
+ { 170, 300, 120 }, { 170, 100, 120 },
+ { 230, 400, 200 }, { 230, 0, 200 },
+ { 380, 400, 340 }, { 380, 0, 340 },
+ { 440, 300, 420 }, { 440, 100, 420 },
+ { 330, 300, 20 }, { 330, 100, 20 },
+ { 360, 400, 120 }, { 360, 0, 120 },
+ { 500, 300, 400 }, { 500, 100, 400 },
+ { 500, 400, 300 }, { 500, 0, 300 },
+ { 500, 400, 100 }, { 500, 0, 100 },
+ { 500, 300, 0 }, { 500, 100, 0 },
+};
+static const Point3 DUCT_SHAPE_3_POINTS[] = {
+ { 500, 300, 500 }, { 500, 100, 500 },
+ { 400, 400, 500 }, { 400, 0, 500 },
+ { 200, 400, 500 }, { 200, 0, 500 },
+ { 100, 300, 500 }, { 100, 100, 500 },
+ { 460, 300, 300 }, { 460, 100, 300 },
+ { 370, 400, 340 }, { 370, 0, 340 },
+ { 180, 400, 400 }, { 180, 0, 400 },
+ { 90, 300, 450 }, { 90, 100, 450 },
+ { 330, 300, 120 }, { 330, 100, 120 },
+ { 270, 400, 200 }, { 270, 0, 200 },
+ { 120, 400, 340 }, { 120, 0, 340 },
+ { 60, 300, 420 }, { 60, 100, 420 },
+ { 170, 300, 20 }, { 170, 100, 20 },
+ { 140, 400, 120 }, { 140, 0, 120 },
+ { 0, 300, 400 }, { 0, 100, 400 },
+ { 0, 400, 300 }, { 0, 0, 300 },
+ { 0, 400, 100 }, { 0, 0, 100 },
+ { 0, 300, 0 }, { 0, 100, 0 },
+};
+static const Point3 DUCT_SHAPE_4_POINTS[] = {
+ { 0, 300, 500 }, { 0, 100, 500 },
+ { 0, 400, 400 }, { 0, 0, 400 },
+ { 0, 400, 200 }, { 0, 0, 200 },
+ { 0, 300, 100 }, { 0, 100, 100 },
+ { 170, 300, 480 }, { 170, 100, 480 },
+ { 140, 400, 380 }, { 140, 0, 380 },
+ { 120, 400, 160 }, { 120, 0, 160 },
+ { 60, 300, 80 }, { 60, 100, 80 },
+ { 330, 300, 380 }, { 330, 100, 380 },
+ { 270, 400, 300 }, { 270, 0, 300 },
+ { 180, 400, 200 }, { 180, 0, 200 },
+ { 90, 300, 50 }, { 90, 100, 50 },
+ { 460, 300, 200 }, { 460, 100, 200 },
+ { 370, 400, 160 }, { 370, 0, 160 },
+ { 100, 300, 0 }, { 100, 100, 0 },
+ { 200, 400, 0 }, { 200, 0, 0 },
+ { 400, 400, 0 }, { 400, 0, 0 },
+ { 500, 300, 0 }, { 500, 100, 0 },
+};
+static const Point3 DUCT_SHAPE_5_6_POINTS[] = {
+ { 500, 300, 500 }, { 500, 100, 500 },
+ { 500, 400, 400 }, { 500, 0, 400 },
+ { 500, 400, 200 }, { 500, 0, 200 },
+ { 500, 300, 100 }, { 500, 100, 100 },
+ { 330, 300, 480 }, { 330, 100, 480 },
+ { 360, 400, 380 }, { 360, 0, 380 },
+ { 380, 400, 160 }, { 380, 0, 160 },
+ { 440, 300, 80 }, { 440, 100, 80 },
+ { 170, 300, 380 }, { 170, 100, 380 },
+ { 230, 400, 300 }, { 230, 0, 300 },
+ { 320, 400, 200 }, { 320, 0, 200 },
+ { 410, 300, 50 }, { 410, 100, 50 },
+ { 40, 300, 200 }, { 40, 100, 200 },
+ { 130, 400, 160 }, { 130, 0, 160 },
+ { 400, 300, 0 }, { 400, 100, 0 },
+ { 300, 400, 0 }, { 300, 0, 0 },
+ { 100, 400, 0 }, { 100, 0, 0 },
+ { 0, 300, 0 }, { 0, 100, 0 },
+};
+static const Point3 DUCT_SHAPE_7_POINTS[] = {
+ { 0, 300, 0 }, { 0, 100, 0 },
+ { 100, 400, 0 }, { 100, 0, 0 },
+ { 300, 400, 0 }, { 300, 0, 0 },
+ { 400, 300, 0 }, { 400, 100, 0 },
+ { 0, 300, 500 }, { 0, 100, 500 },
+ { 100, 400, 500 }, { 100, 0, 500 },
+ { 300, 400, 500 }, { 300, 0, 500 },
+ { 400, 300, 500 }, { 400, 100, 500 },
+};
+static const Point3 DUCT_SHAPE_8_9_POINTS[] = {
+ { 0, 300, 400 }, { 0, 100, 400 },
+ { 0, 400, 300 }, { 0, 0, 300 },
+ { 0, 400, 100 }, { 0, 0, 100 },
+ { 0, 300, 0 }, { 0, 100, 0 },
+ { 0, 300, 400 }, { 0, 100, 400 },
+ { 0, 400, 300 }, { 0, 0, 300 },
+ { 0, 400, 100 }, { 0, 0, 100 },
+ { 0, 300, 0 }, { 0, 100, 0 },
+};
+static const Point3 DUCT_SHAPE_10_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 0, 100, 100 }, { 0, 0, 100 },
+ { 100, 100, 100 }, { 100, 0, 100 },
+ { 100, 100, 0 }, { 100, 0, 0 },
+};
+static const Point3 DUCT_SHAPE_11_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 0, 100, 100 }, { 0, 0, 100 },
+ { 100, 100, 100 }, { 100, 0, 100 },
+ { 100, 100, 0 }, { 100, 0, 0 },
+};
+static const Point3 DUCT_SHAPE_12_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 100, 100, 0 }, { 100, 0, 0 },
+};
+static const Point3 DUCT_SHAPE_13_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 0, 100, 100 }, { 0, 0, 100 },
+};
+static const Point3 DUCT_SHAPE_14_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 0, 100, 100 }, { 0, 0, 100 },
+ { 100, 100, 100 }, { 100, 0, 100 },
+ { 100, 100, 0 }, { 100, 0, 0 },
+};
+static const Point3 DUCT_SHAPE_15_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 0, 100, 100 }, { 0, 0, 100 },
+ { 100, 100, 100 }, { 100, 0, 100 },
+ { 100, 100, 0 }, { 100, 0, 0 },
+};
+static const Point3 DUCT_SHAPE_16_POINTS[] = {
+ { 0, 100, 0 }, { 0, 0, 0 },
+ { 0, 100, 100 }, { 0, 0, 100 },
+ { 100, 100, 100 }, { 100, 0, 100 },
+ { 100, 100, 0 }, { 100, 0, 0 },
+};
+
+static const uint16 DUCT_SHAPE_0_DATA[] = {
+ 1, 4, 8, 0xA, 2, 0, 2, 4, 1, 9, 8, 0, 3, 4, 0xB, 3,
+ 1, 9, 4, 4, 0xC, 0xA, 2, 4, 5, 4, 0xD, 0xB, 3, 5, 6, 4,
+ 0xE, 0xC, 4, 6, 7, 4, 0xF, 0xE, 6, 7, 8, 4, 0xF, 0xD, 5, 7
+};
+static const uint16 DUCT_SHAPE_1_DATA[] = {
+ 1, 4, 8, 0xA, 2, 0, 2, 4, 1, 9, 8, 0, 3, 4, 0xB, 3, 1, 9,
+ 4, 4, 0xC, 0xA, 2, 4, 5, 4, 0xD, 0xB, 3, 5, 6, 4, 0xE, 0xC,
+ 4, 6, 7, 4, 0xF, 0xE, 6, 7, 8, 4, 0xF, 0xD, 5, 7
+};
+static const uint16 DUCT_SHAPE_2_DATA[] = {
+ 0x1, 0x4, 0x8, 0xA, 0x2, 0x0, 0x2, 0x4, 0x9, 0xB, 0x3, 0x1,
+ 0x3, 0x4, 0x8, 0x9, 0x1, 0x0, 0x4, 0x4, 0x10, 0x12, 0xA, 0x8,
+ 0x5, 0x4, 0x11, 0x13, 0xB, 0x9, 0x6, 0x4, 0x11, 0x10, 0x8, 0x9,
+ 0x7, 0x4, 0x18, 0x1A, 0x12, 0x10, 0x8, 0x4, 0x19, 0x1B, 0x13, 0x11,
+ 0x1, 0x4, 0x19, 0x18, 0x10, 0x11, 0x2, 0x4, 0x22, 0x20, 0x1A, 0x18,
+ 0x3, 0x4, 0x23, 0x21, 0x1B, 0x19, 0x4, 0x4, 0x23, 0x22, 0x18, 0x19,
+ 0x5, 0x9, 0x2, 0xA, 0x12, 0x1A, 0x20, 0x1E, 0x14, 0xC, 0x4, 0x6,
+ 0x9, 0x3, 0xB, 0x13, 0x1B, 0x21, 0x1F, 0x15, 0xD, 0x5, 0x7, 0x4,
+ 0x1C, 0x16, 0x14, 0x1E, 0x8, 0x4, 0x1F, 0x1D, 0x17, 0x15, 0x1, 0x4,
+ 0x1D, 0x1C, 0x16, 0x17, 0x2, 0x4, 0xC, 0x14, 0x16, 0xE, 0x3, 0x4,
+ 0xD, 0x15, 0x17, 0xF, 0x4, 0x4, 0x17, 0x16, 0xE, 0xF, 0x5, 0x4,
+ 0x4, 0xC, 0xE, 0x6, 0x6, 0x4, 0xD, 0xF, 0x7, 0x5, 0x7, 0x4,
+ 0xF, 0xE, 0x6, 0x7
+};
+static const uint16 DUCT_SHAPE_3_DATA[] = {
+ 0x1, 0x4, 0x8, 0xA, 0x2, 0x0, 0x2, 0x4, 0x9, 0xB, 0x3, 0x1,
+ 0x3, 0x4, 0x8, 0x9, 0x1, 0x0, 0x4, 0x4, 0x10, 0x12, 0xA, 0x8,
+ 0x5, 0x4, 0x11, 0x13, 0xB, 0x9, 0x6, 0x4, 0x11, 0x10, 0x8, 0x9,
+ 0x7, 0x4, 0x18, 0x1A, 0x12, 0x10, 0x8, 0x4, 0x19, 0x1B, 0x13, 0x11,
+ 0x1, 0x4, 0x19, 0x18, 0x10, 0x11, 0x2, 0x4, 0x22, 0x20, 0x1A, 0x18,
+ 0x3, 0x4, 0x23, 0x21, 0x1B, 0x19, 0x4, 0x4, 0x23, 0x22, 0x18, 0x19,
+ 0x5, 0x9, 0x2, 0xA, 0x12, 0x1A, 0x20, 0x1E, 0x14, 0xC, 0x4, 0x6,
+ 0x9, 0x3, 0xB, 0x13, 0x1B, 0x21, 0x1F, 0x15, 0xD, 0x5, 0x7, 0x4,
+ 0x1C, 0x16, 0x14, 0x1E, 0x8, 0x4, 0x1F, 0x1D, 0x17, 0x15, 0x1, 0x4,
+ 0x1D, 0x1C, 0x16, 0x17, 0x2, 0x4, 0xC, 0x14, 0x16, 0xE, 0x3, 0x4,
+ 0xD, 0x15, 0x17, 0xF, 0x4, 0x4, 0x17, 0x16, 0xE, 0xF, 0x5, 0x4,
+ 0x4, 0xC, 0xE, 0x6, 0x6, 0x4, 0xD, 0xF, 0x7, 0x5, 0x7, 0x4,
+ 0xF, 0xE, 0x6, 0x7
+};
+static const uint16 DUCT_SHAPE_4_DATA[] = {
+ 0x1, 0x4, 0x8, 0xA, 0x2, 0x0, 0x2, 0x4, 0x9, 0xB, 0x3, 0x1,
+ 0x3, 0x4, 0x8, 0x9, 0x1, 0x0, 0x4, 0x4, 0x10, 0x12, 0xA, 0x8,
+ 0x5, 0x4, 0x11, 0x13, 0xB, 0x9, 0x6, 0x4, 0x11, 0x10, 0x8, 0x9,
+ 0x7, 0x4, 0x18, 0x1A, 0x12, 0x10, 0x8, 0x4, 0x19, 0x1B, 0x13, 0x11,
+ 0x1, 0x4, 0x19, 0x18, 0x10, 0x11, 0x2, 0x4, 0x22, 0x20, 0x1A, 0x18,
+ 0x3, 0x4, 0x23, 0x21, 0x1B, 0x19, 0x4, 0x4, 0x23, 0x22, 0x18, 0x19,
+ 0x5, 0x9, 0x2, 0xA, 0x12, 0x1A, 0x20, 0x1E, 0x14, 0xC, 0x4, 0x6,
+ 0x9, 0x3, 0xB, 0x13, 0x1B, 0x21, 0x1F, 0x15, 0xD, 0x5, 0x7, 0x4,
+ 0x1C, 0x16, 0x14, 0x1E, 0x8, 0x4, 0x1F, 0x1D, 0x17, 0x15, 0x1, 0x4,
+ 0x1D, 0x1C, 0x16, 0x17, 0x2, 0x4, 0xC, 0x14, 0x16, 0xE, 0x3, 0x4,
+ 0xD, 0x15, 0x17, 0xF, 0x4, 0x4, 0x17, 0x16, 0xE, 0xF, 0x5, 0x4,
+ 0x4, 0xC, 0xE, 0x6, 0x6, 0x4, 0xD, 0xF, 0x7, 0x5, 0x7, 0x4,
+ 0xF, 0xE, 0x6, 0x7
+};
+static const uint16 DUCT_SHAPE_5_6_DATA[] = {
+ 0x1, 0x4, 0x8, 0xA, 0x2, 0x0, 0x2, 0x4, 0x9, 0xB, 0x3, 0x1,
+ 0x3, 0x4, 0x8, 0x9, 0x1, 0x0, 0x4, 0x4, 0x10, 0x12, 0xA, 0x8,
+ 0x5, 0x4, 0x11, 0x13, 0xB, 0x9, 0x6, 0x4, 0x11, 0x10, 0x8, 0x9,
+ 0x7, 0x4, 0x18, 0x1A, 0x12, 0x10, 0x8, 0x4, 0x19, 0x1B, 0x13, 0x11,
+ 0x1, 0x4, 0x19, 0x18, 0x10, 0x11, 0x2, 0x4, 0x22, 0x20, 0x1A, 0x18,
+ 0x3, 0x4, 0x23, 0x21, 0x1B, 0x19, 0x4, 0x4, 0x23, 0x22, 0x18, 0x19,
+ 0x5, 0x9, 0x2, 0xA, 0x12, 0x1A, 0x20, 0x1E, 0x14, 0xC, 0x4, 0x6,
+ 0x9, 0x3, 0xB, 0x13, 0x1B, 0x21, 0x1F, 0x15, 0xD, 0x5, 0x7, 0x4,
+ 0x1C, 0x16, 0x14, 0x1E, 0x8, 0x4, 0x1F, 0x1D, 0x17, 0x15, 0x1, 0x4,
+ 0x1D, 0x1C, 0x16, 0x17, 0x2, 0x4, 0xC, 0x14, 0x16, 0xE, 0x3, 0x4,
+ 0xD, 0x15, 0x17, 0xF, 0x4, 0x4, 0x17, 0x16, 0xE, 0xF, 0x5, 0x4,
+ 0x4, 0xC, 0xE, 0x6, 0x6, 0x4, 0xD, 0xF, 0x7, 0x5, 0x7, 0x4,
+ 0xF, 0xE, 0x6, 0x7
+};
+static const uint16 DUCT_SHAPE_7_DATA[] = {
+ 0x2, 0x4, 0x8, 0xA, 0x2, 0x0, 0x3, 0x4, 0x1, 0x9, 0x8, 0x0,
+ 0x4, 0x4, 0xB, 0x3, 0x1, 0x9, 0x5, 0x4, 0xC, 0xA, 0x2, 0x4,
+ 0x6, 0x4, 0xD, 0xB, 0x3, 0x5, 0x7, 0x4, 0xE, 0xC, 0x4, 0x6,
+ 0x8, 0x4, 0xF, 0xE, 0x6, 0x7, 0x1, 0x4, 0xF, 0xD, 0x5, 0x7
+};
+static const uint16 DUCT_SHAPE_8_9_DATA[] = {
+ 0x2, 0x4, 0x8, 0xA, 0x2, 0x0, 0x3, 0x4, 0x1, 0x9, 0x8, 0x0,
+ 0x4, 0x4, 0xB, 0x3, 0x1, 0x9, 0x5, 0x4, 0xC, 0xA, 0x2, 0x4,
+ 0x6, 0x4, 0xD, 0xB, 0x3, 0x5, 0x7, 0x4, 0xE, 0xC, 0x4, 0x6,
+ 0x8, 0x4, 0xF, 0xE, 0x6, 0x7, 0x1, 0x4, 0xF, 0xD, 0x5, 0x7
+};
+static const uint16 DUCT_SHAPE_10_DATA[] = {
+ 5, 4, 0, 2, 3, 1, 3, 4, 0, 6, 4, 2,
+ 4, 4, 1, 7, 5, 3, 6, 4, 6, 7, 5, 4
+};
+static const uint16 DUCT_SHAPE_11_DATA[] = {
+ 3, 4, 0, 6, 4, 2, 4, 4, 1, 7, 5, 3,
+ 5, 4, 0, 6, 7, 1, 6, 4, 2, 4, 5, 3
+};
+static const uint16 DUCT_SHAPE_12_DATA[] = {
+ 7, 4, 0, 1, 3, 2
+};
+static const uint16 DUCT_SHAPE_13_DATA[] = {
+ 7, 4, 0, 1, 3, 2
+};
+static const uint16 DUCT_SHAPE_14_DATA[] = {
+ 1, 4, 0, 6, 4, 2, 2, 4, 1, 7, 5, 3
+};
+static const uint16 DUCT_SHAPE_15_DATA[] = {
+ 6, 4, 0, 2, 3, 1, 4, 4, 0, 6, 4, 2,
+ 3, 4, 1, 7, 5, 3, 5, 4, 6, 7, 5, 4
+};
+static const uint16 DUCT_SHAPE_16_DATA[] = {
+ 4, 4, 0, 6, 4, 2, 3, 4, 1, 7, 5, 3,
+ 6, 4, 0, 6, 7, 1, 5, 4, 2, 4, 5, 3
+};
+
+static const DuctShape DUCT_SHAPE_0[] = {
+ 16, 8, DUCT_SHAPE_0_POINTS, DUCT_SHAPE_0_DATA
+};
+
+static const DuctShape DUCT_SHAPE_1[] = {
+ 16, 8, DUCT_SHAPE_1_POINTS, DUCT_SHAPE_1_DATA
+};
+
+static const DuctShape DUCT_SHAPE_2[] = {
+ 36, 23, DUCT_SHAPE_2_POINTS, DUCT_SHAPE_2_DATA
+};
+
+static const DuctShape DUCT_SHAPE_3[] = {
+ 36, 23, DUCT_SHAPE_3_POINTS, DUCT_SHAPE_3_DATA
+};
+
+static const DuctShape DUCT_SHAPE_4[] = {
+ 36, 23, DUCT_SHAPE_4_POINTS, DUCT_SHAPE_4_DATA
+};
+
+static const DuctShape DUCT_SHAPE_5_6[] = {
+ 36, 23, DUCT_SHAPE_5_6_POINTS, DUCT_SHAPE_5_6_DATA
+};
+
+static const DuctShape DUCT_SHAPE_7[] = {
+ 16, 8, DUCT_SHAPE_7_POINTS, DUCT_SHAPE_7_DATA
+};
+
+static const DuctShape DUCT_SHAPE_8_9[] = {
+ 16, 8, DUCT_SHAPE_8_9_POINTS, DUCT_SHAPE_8_9_DATA
+};
+
+static const DuctShape DUCT_SHAPE_10[] = {
+ 8, 4, DUCT_SHAPE_10_POINTS, DUCT_SHAPE_10_DATA
+};
+
+static const DuctShape DUCT_SHAPE_11[] = {
+ 8, 4, DUCT_SHAPE_11_POINTS, DUCT_SHAPE_11_DATA
+};
+
+static const DuctShape DUCT_SHAPE_12[] = {
+ 4, 1, DUCT_SHAPE_12_POINTS, DUCT_SHAPE_12_DATA
+};
+
+static const DuctShape DUCT_SHAPE_13[] = {
+ 4, 1, DUCT_SHAPE_13_POINTS, DUCT_SHAPE_13_DATA
+};
+
+static const DuctShape DUCT_SHAPE_14[] = {
+ 8, 2, DUCT_SHAPE_14_POINTS, DUCT_SHAPE_14_DATA
+};
+
+static const DuctShape DUCT_SHAPE_15[] = {
+ 8, 4, DUCT_SHAPE_15_POINTS, DUCT_SHAPE_15_DATA
+};
+
+static const DuctShape DUCT_SHAPE_16[] = {
+ 8, 4, DUCT_SHAPE_16_POINTS, DUCT_SHAPE_16_DATA
+};
+
+
+const DuctShape *DUCT_SHAPE_DATA[17] {
+ DUCT_SHAPE_0, DUCT_SHAPE_1, DUCT_SHAPE_2, DUCT_SHAPE_3,
+ DUCT_SHAPE_4, DUCT_SHAPE_5_6, DUCT_SHAPE_5_6, DUCT_SHAPE_7,
+ DUCT_SHAPE_8_9, DUCT_SHAPE_8_9, DUCT_SHAPE_10, DUCT_SHAPE_11,
+ DUCT_SHAPE_12, DUCT_SHAPE_13, DUCT_SHAPE_14, DUCT_SHAPE_15,
+ DUCT_SHAPE_16
+};
+
static const byte FONT1_WIDTHS[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
diff --git a/engines/access/martian/martian_resources.h b/engines/access/martian/martian_resources.h
index 30bd8ef6138..1d280b8a4e8 100644
--- a/engines/access/martian/martian_resources.h
+++ b/engines/access/martian/martian_resources.h
@@ -50,7 +50,33 @@ extern const char *const TRAVDATA[];
extern const char *const SPEC7MESSAGE;
extern const byte CAN_TRAVEL_MATRIX[];
-extern const int PICTURERANGE[][2];
+extern const int16 PICTURE_RANGE[][2];
+extern const int16 DUCT_ARROW_BUTTON_RANGE[][2];
+
+struct DuctMapPoint {
+ int16 ptType;
+ int16 shapeType;
+ int16 x;
+ int16 y;
+};
+
+extern const DuctMapPoint DUCT_MAP_DATA[];
+
+
+struct Point3 {
+ int16 x;
+ int16 y;
+ int16 z;
+};
+
+struct DuctShape {
+ int16 numPts;
+ int16 array2Len;
+ const Point3 *points;
+ const uint16 *data;
+};
+
+extern const DuctShape *DUCT_SHAPE_DATA[];
class MartianResources : public Resources {
protected:
diff --git a/engines/access/martian/martian_scripts.cpp b/engines/access/martian/martian_scripts.cpp
index f36a852ff3a..41b67874f4a 100644
--- a/engines/access/martian/martian_scripts.cpp
+++ b/engines/access/martian/martian_scripts.cpp
@@ -23,7 +23,7 @@
#include "access/access.h"
#include "access/martian/martian_game.h"
#include "access/martian/martian_resources.h"
-#include "access/martian/martian_tunnel.h"
+#include "access/martian/martian_duct.h"
#include "access/martian/martian_scripts.h"
namespace Access {
@@ -32,11 +32,11 @@ namespace Martian {
MartianScripts::MartianScripts(AccessEngine *vm) : Scripts(vm) {
_game = (MartianEngine *)_vm;
- _tunnel = new MartianTunnel(_game);
+ _duct = new MartianDuct(_game);
}
MartianScripts::~MartianScripts() {
- delete _tunnel;
+ delete _duct;
}
void MartianScripts::cmdSpecial0() {
@@ -113,7 +113,7 @@ void MartianScripts::cmdSpecial1(int param1, int param2) {
}
void MartianScripts::cmdSpecial2() {
- _tunnel->tunnel2();
+ _duct->duct2();
};
void MartianScripts::cmdSpecial3() {
@@ -128,7 +128,7 @@ void MartianScripts::cmdSpecial3() {
}
void MartianScripts::cmdSpecial4() {
- _tunnel->tunnel4();
+ _duct->duct4();
}
void MartianScripts::doIntro(int param1) {
diff --git a/engines/access/martian/martian_scripts.h b/engines/access/martian/martian_scripts.h
index f31f77f7db8..a1f9f495db5 100644
--- a/engines/access/martian/martian_scripts.h
+++ b/engines/access/martian/martian_scripts.h
@@ -30,12 +30,12 @@ namespace Access {
namespace Martian {
class MartianEngine;
-class MartianTunnel;
+class MartianDuct;
class MartianScripts : public Scripts {
private:
MartianEngine *_game;
- MartianTunnel *_tunnel;
+ MartianDuct *_duct;
void cmdSpecial0();
void cmdSpecial1(int param1, int param2);
diff --git a/engines/access/martian/martian_tunnel.cpp b/engines/access/martian/martian_tunnel.cpp
deleted file mode 100644
index 67376039555..00000000000
--- a/engines/access/martian/martian_tunnel.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "access/martian/martian_tunnel.h"
-#include "access/martian/martian_game.h"
-
-namespace Access {
-
-namespace Martian {
-
-MartianTunnel::MartianTunnel(MartianEngine *vm) : _vm(vm), _tunnelParam_ca42(0), _tunnelParam_ca44(0), _tunnelParam_ca46(0), _tunnelMoveFlag(0) {
-}
-
-MartianTunnel::~MartianTunnel() {
-}
-
-void MartianTunnel::tunnel2() {
- _tunnelParam_ca42 = 0x226;
- _tunnelParam_ca44 = 10;
- _tunnelParam_ca46 = 0x352;
- doTunnel();
-}
-
-void MartianTunnel::tunnel4() {
- _tunnelParam_ca42 = 0xabe;
- _tunnelParam_ca44 = 10;
- _tunnelParam_ca46 = 0x41a;
- doTunnel();
-}
-
-void MartianTunnel::doTunnel() {
- _vm->_screen->forceFadeOut();
- _vm->_events->hideCursor();
- _vm->_files->loadScreen(20, 0);
- Resource *res = _vm->_files->loadFile(20, 1);
- _vm->_objectsTable[20] = new SpriteResource(_vm, res);
- if (_vm->_inventory->_inv[40]._value == ITEM_IN_INVENTORY) {
- _vm->_screen->plotImage(_vm->_objectsTable[20], 8, Common::Point(140, 10));
- }
- _vm->_events->showCursor();
- _vm->_screen->forceFadeIn();
- _crawlFrame = 0;
- _tunnelMoveFlag = 0;
-
- warning("***TODO***: Init all the other tunnel variables here");
-
- drawArrowSprites();
- drawArrowSprites2();
- _vm->_room->_function = FN_NONE;
-
- /*
- while (true) {
- clearWorkScreenArea();
- tunnel_17f5c();
- tunnel_1888a();
- tunnel_18985();
- _vm->_buffer2.plotImage(_vm->_objectsTable[20], _crawlFrame, Common::Point(140, 94));
- copyBufBlockToScreen();
- if (_vm->_room->_function != FN_NONE)
- break;
- do {
- tunnel_doloop_18c65();
- } while (_tunnelStopLoop_ca27 == 0);
- }
- */
- // FIXME: Quick hack skip this part
- g_system->displayMessageOnOSD(Common::U32String("Duct tunnel section not implemented yet!"));
- _vm->_flags[0x62] = 1;
- _vm->_flags[0x55] = 1;
- _vm->_room->_function = FN_CLEAR1;
-
-
-
- delete _vm->_objectsTable[20];
- _vm->_objectsTable[20] = nullptr;
-}
-
-void MartianTunnel::drawArrowSprites() {
- int x;
- int y;
- int frame;
-
- _vm->_events->hideCursor();
- _vm->_screen->plotImage(_vm->_objectsTable[20], 7, Common::Point(4, 0x50));
- if (_tunnelMoveFlag == 0) {
- x = 0x11;
- y = 0x50;
- frame = 9;
- } else if (_tunnelMoveFlag == 0x40) {
- x = 0x19;
- y = 0x57;
- frame = 12;
- } else if (_tunnelMoveFlag == 0x80) {
- x = 0xe;
- y = 0x5d;
- frame = 11;
- } else {
- x = 4;
- y = 0x57;
- frame = 10;
- }
- _vm->_screen->plotImage(_vm->_objectsTable[20], frame, Common::Point(x, y));
- _vm->_events->showCursor();
-}
-
-void MartianTunnel::drawArrowSprites2() {
- _vm->_events->hideCursor();
- _vm->_screen->plotImage(_vm->_objectsTable[20], 14, Common::Point(16, 0x58));
- if ((3 < _tunnel_ca20) && (_tunnel_ca20 < 0xd)) {
- _vm->_screen->plotImage(_vm->_objectsTable[20], 13, Common::Point(17, 0x59));
- }
- _vm->_events->showCursor();
-}
-
-void MartianTunnel::clearWorkScreenArea() {
- _vm->_buffer2.fillRect(Common::Rect(100, 60, 220, 140), 0);
-}
-
-void MartianTunnel::copyBufBlockToScreen() {
- _vm->_screen->copyBlock(&_vm->_buffer2, Common::Rect(100, 60, 220, 140));
-}
-
-}
-
-} // end namespace Access
diff --git a/engines/access/martian/martian_tunnel.h b/engines/access/martian/martian_tunnel.h
deleted file mode 100644
index 81f77cf186c..00000000000
--- a/engines/access/martian/martian_tunnel.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef ACCESS_MARTIAN_MARTIAN_TUNNEL_H
-#define ACCESS_MARTIAN_MARTIAN_TUNNEL_H
-
-#include "common/scummsys.h"
-
-namespace Access {
-
-namespace Martian {
-
-class MartianEngine;
-
-class MartianTunnel {
-public:
- MartianTunnel(MartianEngine *vm);
- ~MartianTunnel();
-
- void tunnel2();
- void tunnel4();
-
-private:
- void doTunnel();
- void drawArrowSprites();
- void drawArrowSprites2();
- void clearWorkScreenArea();
- void copyBufBlockToScreen();
- void tunnel_doloop_8c65();
- void tunnel_17f5c();
- void tunnel_1888a();
- void tunnel_18985();
-
- MartianEngine *_vm;
- int16 _tunnelParam_ca42;
- int16 _tunnelParam_ca44;
- int16 _tunnelParam_ca46;
- uint16 _tunnel_ca20;
- byte _tunnelMoveFlag;
- int16 _crawlFrame;
- byte _tunnelStopLoop_ca27;
-};
-
-}
-
-} // end namespace Access
-
-#endif // ACCESS_MARTIAN_MARTIAN_TUNNEL_H
diff --git a/engines/access/module.mk b/engines/access/module.mk
index 6e26737b96a..cf861d4d48f 100644
--- a/engines/access/module.mk
+++ b/engines/access/module.mk
@@ -30,7 +30,7 @@ MODULE_OBJS := \
martian/martian_game.o \
martian/martian_player.o \
martian/martian_resources.o \
- martian/martian_tunnel.o \
+ martian/martian_duct.o \
martian/martian_room.o \
martian/martian_scripts.o \
martian/midiparser_bemd.o \
diff --git a/engines/access/room.cpp b/engines/access/room.cpp
index b1a6e1bc8b7..c93c9253b66 100644
--- a/engines/access/room.cpp
+++ b/engines/access/room.cpp
@@ -91,10 +91,10 @@ void Room::takePicture() {
}
Common::Array<Common::Rect> pictureCoords;
- for (int i = 0; Martian::PICTURERANGE[i][0] != -1; i += 2) {
- // PICTURERANGE is min/max X, min/max Y
- pictureCoords.push_back(Common::Rect(Martian::PICTURERANGE[i][0], Martian::PICTURERANGE[i + 1][0],
- Martian::PICTURERANGE[i][1], Martian::PICTURERANGE[i + 1][1]));
+ for (int i = 0; Martian::PICTURE_RANGE[i][0] != -1; i += 2) {
+ // PICTURE_RANGE is min/max X, min/max Y
+ pictureCoords.push_back(Common::Rect(Martian::PICTURE_RANGE[i][0], Martian::PICTURE_RANGE[i + 1][0],
+ Martian::PICTURE_RANGE[i][1], Martian::PICTURE_RANGE[i + 1][1]));
}
int result = _vm->_events->checkMouseBox1(pictureCoords);
Commit: 28a3a8134748bac7bf2c5f7e9ced01b416404493
https://github.com/scummvm/scummvm/commit/28a3a8134748bac7bf2c5f7e9ced01b416404493
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-09-23T20:02:04+10:00
Commit Message:
NEWS: Mention Martian Memorandum support
Changed paths:
NEWS.md
diff --git a/NEWS.md b/NEWS.md
index f0c4abc353a..5fe925a680d 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -26,9 +26,11 @@ For a more comprehensive changelog of the latest experimental code, see:
- Added support for Adibou 2: Nature & Sciences.
- Added support for WAGE-based game. More than 160 titles so far.
- Added support for Penumbra: Overture.
+ - Added support for Tex Murphy: Martian Memorandum
Access:
- Added keymapper support.
+ - Fixed foodstep sounds.
ADL:
- Added Text-to-Speech support.
Commit: f0a14d295e1d06b9576509780646698534ae7898
https://github.com/scummvm/scummvm/commit/f0a14d295e1d06b9576509780646698534ae7898
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2025-09-23T20:02:15+10:00
Commit Message:
ACCESS: Mark MM as ready for testing
Changed paths:
engines/access/detection_tables.h
diff --git a/engines/access/detection_tables.h b/engines/access/detection_tables.h
index 4a8d35fcdfc..f20427c6725 100644
--- a/engines/access/detection_tables.h
+++ b/engines/access/detection_tables.h
@@ -93,7 +93,7 @@ static const AccessGameDescription gameDescriptions[] = {
AD_ENTRY1s("r01.ap", "c081daca9b0cfd710157cf946e343df6", 39352),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_TESTING,
GUIO1(GUIO_NONE)
},
kGameMartianMemorandum,
More information about the Scummvm-git-logs
mailing list