[Scummvm-git-logs] scummvm master -> 3eaebb47e29a1c286c16fdb900079e9841a968ba
antoniou79
noreply at scummvm.org
Tue May 16 12:18:10 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3eaebb47e2 BLADERUNNER: Custom beta cursors for exits and esper
Commit: 3eaebb47e29a1c286c16fdb900079e9841a968ba
https://github.com/scummvm/scummvm/commit/3eaebb47e29a1c286c16fdb900079e9841a968ba
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-05-16T15:16:23+03:00
Commit Message:
BLADERUNNER: Custom beta cursors for exits and esper
Also fixes for the beta combat cursors (color and hotspot / target center)
Changed paths:
engines/bladerunner/debugger.cpp
engines/bladerunner/mouse.cpp
engines/bladerunner/mouse.h
engines/bladerunner/shape.cpp
engines/bladerunner/shape.h
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
index 9170dc45205..c3b235a3f98 100644
--- a/engines/bladerunner/debugger.cpp
+++ b/engines/bladerunner/debugger.cpp
@@ -1899,7 +1899,7 @@ bool Debugger::cmdRegion(int argc, const char **argv) {
/**
* click: Toggle showing mouse click info in the text console (not the debugger window)
-* beta: Toggle beta crosshairs for aiming in combat mode
+* beta: Toggle beta crosshairs for aiming in combat mode, exit cursors (custom) and ESPER edge cursors (custom)
* add0: Toggle semi-transparent hotspot cursor (additive draw mode 0)
* add1: Toggle semi-transparent hotspot cursor (additive draw mode 1)
*/
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 44d98eea9aa..5a9ef497b81 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -80,6 +80,7 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 0;
_hotspotY = 0;
break;
+
case 1:
// normal cursor over hotspot (not exit) (green rotating)
// animating: 8 frames (4-11)
@@ -96,36 +97,58 @@ void Mouse::setCursor(int cursor) {
}
}
break;
+
case 2:
- // exit cursor (upwards/North)
+ // static exit cursor (upwards/North)
_frame = 12;
_hotspotX = 12;
_hotspotY = 0;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::ESPER_UP);
+ } else {
+ _drawModeBitFlags &= ~(MouseDrawFlags::CUSTOM | MouseDrawFlags::ESPER_UP);
+ }
break;
+
case 3:
- // exit cursor (right/East)
+ // static exit cursor (right/East)
_frame = 15;
_hotspotX = 23;
_hotspotY = 12;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::ESPER_RIGHT);
+ } else {
+ _drawModeBitFlags &= ~(MouseDrawFlags::CUSTOM | MouseDrawFlags::ESPER_RIGHT);
+ }
break;
+
case 4:
- // exit cursor (downwards/South)
+ // static exit cursor (downwards/South)
_frame = 13;
_hotspotX = 12;
_hotspotY = 23;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::ESPER_DOWN);
+ }
break;
+
case 5:
- // exit cursor (left/West)
+ // static exit cursor (left/West)
_frame = 14;
_hotspotX = 0;
_hotspotY = 12;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::ESPER_LEFT);
+ }
break;
+
case 6:
// combat cursor, simple bullets (normal / no target)
_frame = 16;
_hotspotX = 19;
_hotspotY = 19;
break;
+
case 7:
// combat cursor, simple bullets (hot target)
// animating: 8 frames (17-24)
@@ -133,12 +156,14 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 19;
_hotspotY = 19;
break;
+
case 8:
// combat cursor, advanced bullets (normal / no target)
_frame = 25;
_hotspotX = 19;
_hotspotY = 19;
break;
+
case 9:
// combat cursor, advanced bullets (hot target)
// animating: 8 frames (26-33)
@@ -146,12 +171,14 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 19;
_hotspotY = 19;
break;
+
case 10:
// combat cursor, best bullets (normal / no target)
_frame = 34;
_hotspotX = 19;
_hotspotY = 19;
break;
+
case 11:
// combat cursor, best bullets (hot target)
// animating: 8 frames (35-42)
@@ -159,6 +186,7 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 19;
_hotspotY = 19;
break;
+
case 12:
// exit cursor (upwards/North)
// resets animCounter too (as opposed to _cursor == 2)
@@ -167,7 +195,11 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 12;
_hotspotY = 0;
_animCounter = 0;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::EXIT_UP);
+ }
break;
+
case 13:
// exit cursor (right/East)
// resets animCounter too (as opposed to _cursor == 3)
@@ -176,7 +208,11 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 23;
_hotspotY = 12;
_animCounter = 0;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::EXIT_RIGHT);
+ }
break;
+
case 14:
// exit cursor (downwards/South)
// resets animCounter too (as opposed to _cursor == 4)
@@ -185,7 +221,11 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 12;
_hotspotY = 23;
_animCounter = 0;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::EXIT_DOWN);
+ }
break;
+
case 15:
// exit cursor (left/West)
// resets animCounter too (as opposed to _cursor == 5)
@@ -194,11 +234,21 @@ void Mouse::setCursor(int cursor) {
_hotspotX = 0;
_hotspotY = 12;
_animCounter = 0;
+ if (_vm->_debugger->_useBetaCrosshairsCursor) {
+ _drawModeBitFlags |= (MouseDrawFlags::CUSTOM | MouseDrawFlags::EXIT_LEFT);
+ }
break;
+
case 16:
+ // (beta version) combat cursor (inactive)
+ _drawModeBitFlags &= ~(0x01 << _vm->_settings->getAmmoType());
+ _drawModeBitFlags &= ~(MouseDrawFlags::SPECIAL);
#if !BLADERUNNER_ORIGINAL_BUGS
_frame = 0;
+ _hotspotX = 11;
+ _hotspotY = 11;
break;
+
case 17:
#endif
// (beta version) combat cursor (white or flashing white/blue)
@@ -214,9 +264,13 @@ void Mouse::setCursor(int cursor) {
// So:
// id 16: inactive (beta) combat crosshairs
// id 17: active (beta) combat crosshairs
+ _drawModeBitFlags |= (0x01 << _vm->_settings->getAmmoType());
+ _drawModeBitFlags |= MouseDrawFlags::SPECIAL;
_frame = 1;
_hotspotX = 11;
_hotspotY = 11;
+ break;
+
default:
break;
}
@@ -230,7 +284,7 @@ void Mouse::getXY(int *x, int *y) const {
void Mouse::setMouseJitterUp() {
switch (_vm->_settings->getDifficulty()) {
default:
- // fallthrough intended
+ // fall through intended
case kGameDifficultyEasy:
_randomCountdownX = 2;
_randomX = _vm->_rnd.getRandomNumberRng(0, 6) - 3;
@@ -254,7 +308,7 @@ void Mouse::setMouseJitterUp() {
void Mouse::setMouseJitterDown() {
switch (_vm->_settings->getDifficulty()) {
default:
- // fallthrough intended
+ // fall through intended
case kGameDifficultyEasy:
_randomCountdownY = 2;
_randomX = _vm->_rnd.getRandomNumberRng(0, 6) - 3;
@@ -332,59 +386,114 @@ void Mouse::updateCursorFrame() {
switch (_cursor) {
case 0:
break;
+
case 1:
if (++_frame > 11)
_frame = 4;
break;
+
case 2:
+ // fall through
case 3:
+ // fall through
case 4:
+ // fall through
case 5:
+ // fall through
+ // 2,3,4,5 are case for "static" exit arrows, used in ESPER
case 6:
+ // 6 is combat cursor, simple bullets (normal / no target)
break;
+
case 7:
if (++_frame > 24)
_frame = 17;
break;
+
case 8:
break;
+
case 9:
if (++_frame > 33)
_frame = 26;
break;
+
case 10:
break;
+
case 11:
if (++_frame > 42)
_frame = 35;
break;
+
case 12:
- if (++_animCounter >= 4) {
- _animCounter = 0;
+ if ((_drawModeBitFlags & Mouse::MouseDrawFlags::CUSTOM)
+ && (_drawModeBitFlags & Mouse::MouseDrawFlags::EXIT_UP)) {
+ // use the 3 least significant bits in place of "frame" index
+ _drawModeBitFlags +=1;
+ if ((_drawModeBitFlags & 0x7) == 0x7) {
+ _drawModeBitFlags &= ~0x7;
+ }
+ } else {
+ if (++_animCounter >= 4) {
+ _animCounter = 0;
+ }
+ _hotspotY = -offset[_animCounter];
}
- _hotspotY = -offset[_animCounter];
break;
+
case 13:
- if (++_animCounter >= 4) {
- _animCounter = 0;
+ if ((_drawModeBitFlags & Mouse::MouseDrawFlags::CUSTOM)
+ && (_drawModeBitFlags & Mouse::MouseDrawFlags::EXIT_RIGHT)) {
+ // use the 3 least significant bits in place of "frame" index
+ _drawModeBitFlags +=1;
+ if ((_drawModeBitFlags & 0x7) == 0x7) {
+ _drawModeBitFlags &= ~0x7;
+ }
+ } else {
+ if (++_animCounter >= 4) {
+ _animCounter = 0;
+ }
+ _hotspotX = 23 + offset[_animCounter];
}
- _hotspotX = 23 + offset[_animCounter];
break;
+
case 14:
- if (++_animCounter >= 4) {
- _animCounter = 0;
+ if ((_drawModeBitFlags & Mouse::MouseDrawFlags::CUSTOM)
+ && (_drawModeBitFlags & Mouse::MouseDrawFlags::EXIT_DOWN)) {
+ // use the 3 least significant bits in place of "frame" index
+ _drawModeBitFlags +=1;
+ if ((_drawModeBitFlags & 0x7) == 0x7) {
+ _drawModeBitFlags &= ~0x7;
+ }
+ } else {
+ if (++_animCounter >= 4) {
+ _animCounter = 0;
+ }
+ _hotspotY = 23 + offset[_animCounter];
}
- _hotspotY = 23 + offset[_animCounter];
break;
+
case 15:
- if (++_animCounter >= 4) {
- _animCounter = 0;
+ if ((_drawModeBitFlags & Mouse::MouseDrawFlags::CUSTOM)
+ && (_drawModeBitFlags & Mouse::MouseDrawFlags::EXIT_LEFT)) {
+ // use the 3 least significant bits in place of "frame" index
+ _drawModeBitFlags +=1;
+ if ((_drawModeBitFlags & 0x7) == 0x7) {
+ _drawModeBitFlags &= ~0x7;
+ }
+ } else {
+ if (++_animCounter >= 4) {
+ _animCounter = 0;
+ }
+ _hotspotX = -offset[_animCounter];
}
- _hotspotX = -offset[_animCounter];
break;
+
case 16:
#if !BLADERUNNER_ORIGINAL_BUGS
break;
+
case 17:
#endif
if (++_frame > 2)
@@ -397,6 +506,7 @@ void Mouse::updateCursorFrame() {
_frame = 1;
#endif
break;
+
default:
break;
}
@@ -431,15 +541,19 @@ void Mouse::tick(int x, int y) {
case 0:
cursorId = 12;
break;
+
case 1:
cursorId = 13;
break;
+
case 2:
cursorId = 14;
break;
+
case 3:
cursorId = 15;
break;
+
default:
break;
}
@@ -476,19 +590,20 @@ void Mouse::tick(int x, int y) {
if (actorId >= 0 || itemId >= 0 || isObject) {
if (_vm->_debugger->_useBetaCrosshairsCursor) {
cursorId = 17;
- _drawModeBitFlags |= (0x01 << _vm->_settings->getAmmoType());
- _drawModeBitFlags |= MouseDrawFlags::SPECIAL;
} else {
switch (_vm->_settings->getAmmoType()) {
case 0:
cursorId = 7;
break;
+
case 1:
cursorId = 9;
break;
+
case 2:
cursorId = 11;
break;
+
default:
break;
}
@@ -499,19 +614,20 @@ void Mouse::tick(int x, int y) {
} else {
if (_vm->_debugger->_useBetaCrosshairsCursor) {
cursorId = 16;
- _drawModeBitFlags &= ~(0x01 << _vm->_settings->getAmmoType());
- _drawModeBitFlags &= ~(MouseDrawFlags::SPECIAL);
} else {
switch (_vm->_settings->getAmmoType()) {
case 0:
cursorId = 6;
break;
+
case 1:
cursorId = 8;
break;
+
case 2:
cursorId = 10;
break;
+
default:
break;
}
diff --git a/engines/bladerunner/mouse.h b/engines/bladerunner/mouse.h
index 0324f2da484..a8dddf0c68c 100644
--- a/engines/bladerunner/mouse.h
+++ b/engines/bladerunner/mouse.h
@@ -50,7 +50,7 @@ class Mouse {
int _randomX;
int _randomY;
- uint8 _drawModeBitFlags; // replaces the additive bool with a set of bit flags (including flags for additive mode)
+ uint16 _drawModeBitFlags; // replaces the additive bool with a set of bit flags (including flags for additive mode)
public:
Mouse(BladeRunnerEngine *vm);
@@ -76,12 +76,21 @@ public:
Vector3 getXYZ(int x, int y) const;
typedef enum mouseDrawFlags {
- REDCROSSHAIRS = 0x01,
- YELLOWCROSSHAIRS = 0x02,
- BLUECROSSHAIRS = 0x04,
- SPECIAL = 0x08,
- ADDITIVE_MODE0 = 0x10,
- ADDITIVE_MODE1 = 0x20
+ REDCROSSHAIRS = 0x0001,
+ YELLOWCROSSHAIRS = 0x0002,
+ BLUECROSSHAIRS = 0x0004,
+ SPECIAL = 0x0008,
+ ADDITIVE_MODE0 = 0x0010,
+ ADDITIVE_MODE1 = 0x0020,
+ CUSTOM = 0x0040,
+ EXIT_UP = 0x0080,
+ EXIT_DOWN = 0x0100,
+ EXIT_LEFT = 0x0200,
+ EXIT_RIGHT = 0x0400,
+ ESPER_UP = 0x0800,
+ ESPER_DOWN = 0x1000,
+ ESPER_LEFT = 0x2000,
+ ESPER_RIGHT = 0x4000
} MouseDrawFlags;
};
diff --git a/engines/bladerunner/shape.cpp b/engines/bladerunner/shape.cpp
index 5ae26d5a3b6..1c3646ed1b2 100644
--- a/engines/bladerunner/shape.cpp
+++ b/engines/bladerunner/shape.cpp
@@ -61,7 +61,155 @@ Shape::~Shape() {
delete[] _data;
}
-void Shape::draw(Graphics::Surface &surface, int x, int y, uint8 drawModeBitFlags) const {
+void Shape::drawFilledTriangleAux(Graphics::Surface &surface, const int &dst_x, const int &dst_y, int x1, int y1, int x2, int y2, int x3, int y3, uint32 colorRGB) const {
+ // Code used is based on the Bresenham-like algorithm as described in:
+ // https://mcejp.github.io/2020/11/06/bresenham.html
+ // http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html
+
+ const Vector2 triangleV1 = Vector2(x1, y1);
+ const Vector2 triangleV2 = Vector2(x2, y2); // (V2, V3) should be the flat side, so either x2 == x3 or y2 == y3
+ const Vector2 triangleV3 = Vector2(x3, y3);
+
+ // vTmp1 will be moving along the "left" side of the triangle, and vTmp2 along the "right" side.
+ Vector2 vTmp1 = triangleV1;
+ Vector2 vTmp2 = triangleV1;
+
+ bool swappedDx1WithDy1 = false;
+ bool swappedDx2WithDy2 = false;
+
+ int dx1 = abs(triangleV2.x - triangleV1.x);
+ int dy1 = abs(triangleV2.y - triangleV1.y);
+
+ if (dy1 > dx1) {
+ SWAP(dy1, dx1);
+ swappedDx1WithDy1 = true;
+ }
+
+ int dx2 = abs(triangleV3.x - triangleV1.x);
+ int dy2 = abs(triangleV3.y - triangleV1.y);
+
+ if (dy2 > dx2) {
+ SWAP(dy2, dx2);
+ swappedDx2WithDy2 = true;
+ }
+
+ int signx1 = (triangleV2.x - triangleV1.x) > 0 ? 1: -1;
+ if (triangleV2.x == triangleV1.x) {
+ signx1 = 0;
+ }
+
+ int signx2 = (triangleV3.x - triangleV1.x) > 0 ? 1: -1;
+ if (triangleV3.x == triangleV1.x) {
+ signx2 = 0;
+ }
+
+ int signy1 = (triangleV2.y - triangleV1.y) > 0 ? 1: -1;
+ if (triangleV2.y == triangleV1.y) {
+ signy1 = 0;
+ }
+
+ int signy2 = (triangleV3.y - triangleV1.y) > 0 ? 1: -1;
+ if (triangleV3.y == triangleV1.y) {
+ signy2 = 0;
+ }
+
+ int e1 = 2 * dy1 - dx1;
+ int e2 = 2 * dy2 - dx2;
+
+ for (int i = 0; i <= dx1; ++i) {
+ // dx1 here may be dy1 (if they swapped above). It is whichever was the largest of the two.
+ // We loop over each pixel of "horizontal" (triangle filling) line
+ // check if paint goes from left endpoint of "horizontal" (triangle filling) line to right or other way round
+ int leftEndPoint, rightEndPoint;
+
+ if (triangleV2.y == triangleV3.y) {
+ if (vTmp1.x < vTmp2.x) {
+ leftEndPoint = ceil(vTmp1.x);
+ rightEndPoint = int(vTmp2.x);
+ } else {
+ leftEndPoint = ceil(vTmp2.x);
+ rightEndPoint = int(vTmp1.x);
+ }
+ } else {
+ if (vTmp1.y < vTmp2.y) {
+ leftEndPoint = ceil(vTmp1.y);
+ rightEndPoint = int(vTmp2.y);
+ } else {
+ leftEndPoint = ceil(vTmp2.y);
+ rightEndPoint = int(vTmp1.y);
+ }
+ }
+
+ void *dstPtr;
+ for (int xPos = leftEndPoint; xPos <= rightEndPoint; ++xPos) {
+ if (triangleV2.y == triangleV3.y) {
+ dstPtr = surface.getBasePtr(CLIP(dst_x + xPos, 0, surface.w - 1), CLIP(dst_y + (int)ceil(vTmp1.y), 0, surface.h - 1));
+ } else {
+ dstPtr = surface.getBasePtr(CLIP(dst_x + (int)ceil(vTmp1.x), 0, surface.w - 1), CLIP(dst_y + xPos, 0, surface.h - 1));
+ }
+ drawPixel(surface, dstPtr, colorRGB);
+ }
+
+ while (e1 >= 0) {
+ if (swappedDx1WithDy1) {
+ vTmp1.x += signx1;
+ } else {
+ vTmp1.y += signy1;
+ }
+ e1 = e1 - 2 * dx1;
+ }
+
+ if (swappedDx1WithDy1) {
+ vTmp1.y += signy1;
+ } else {
+ vTmp1.x += signx1;
+ }
+ e1 = e1 + 2 * dy1;
+
+ // Here we've rendered the next point on the "left" edge triangle line.
+ // We now do the same for the "right" edge triangle line, until we are on
+ // the same y-value as on the "left" edge triangle line.
+ if (triangleV2.y == triangleV3.y) {
+ while (vTmp2.y != vTmp1.y) {
+ while (e2 >= 0) {
+ if (swappedDx2WithDy2) {
+ vTmp2.x += signx2;
+ } else {
+ vTmp2.y += signy2;
+ }
+ e2 = e2 - 2 * dx2;
+ }
+
+ if (swappedDx2WithDy2) {
+ vTmp2.y += signy2;
+ } else {
+ vTmp2.x += signx2;
+ }
+ e2 = e2 + 2 * dy2;
+ }
+ } else {
+ while (vTmp2.x != vTmp1.x) {
+ while (e2 >= 0) {
+ if (swappedDx2WithDy2) {
+ vTmp2.x += signx2;
+ } else {
+ vTmp2.y += signy2;
+ }
+ e2 = e2 - 2 * dx2;
+ }
+
+ if (swappedDx2WithDy2) {
+ vTmp2.y += signy2;
+ } else {
+ vTmp2.x += signx2;
+ }
+ e2 = e2 + 2 * dy2;
+ }
+ }
+ }
+}
+
+void Shape::draw(Graphics::Surface &surface, int x, int y, uint16 drawModeBitFlags) const {
int src_x = CLIP(-x, 0, _width);
int src_y = CLIP(-y, 0, _height);
@@ -77,66 +225,138 @@ void Shape::draw(Graphics::Surface &surface, int x, int y, uint8 drawModeBitFlag
return;
}
- const uint8 *src_p = _data + 2 * (src_y * _width + src_x);
-
- uint16 shpColor = 0;
- uint32 surfaceColorRGBPrev = 0;
- uint32 newSurfaceColorRGB = 0;
- uint8 a, r, g, b;
- uint8 rPrev, gPrev, bPrev;
- uint16 rgb16bitPrev = 0;
- uint16 rgb16bitAdd = 0;
- for (int yi = 0; yi != rect_h; ++yi) {
- for (int xi = 0; xi != rect_w; ++xi) {
- shpColor = READ_LE_UINT16(src_p);
- src_p += 2;
-
- getGameDataColor(shpColor, a, r, g, b);
-
- if (!a) {
- // Ignore the alpha in the output as it is inversed in the input
- void *dstPtr = surface.getBasePtr(CLIP(dst_x + xi, 0, surface.w - 1), CLIP(dst_y + yi, 0, surface.h - 1));
- if (drawModeBitFlags & Mouse::MouseDrawFlags::SPECIAL) {
- // It seems that the additive mode was supposed to be used only for cursor shapes
- // From testing, the only cursor shape that seems to work with it is the green rotating cursor
- // We add extra code here to cover the cases of the beta crosshairs cursor
- // being drawn a different color based on bullet power
- // The code for creating the specific color is custom.
- if (drawModeBitFlags & Mouse::MouseDrawFlags::REDCROSSHAIRS) {
- newSurfaceColorRGB = surface.format.RGBToColor((b & 0x8B) | (g >> 1), 0, 0);
- } else if (drawModeBitFlags & Mouse::MouseDrawFlags::YELLOWCROSSHAIRS) {
- newSurfaceColorRGB = surface.format.RGBToColor(b & 0xDF, (b & 0xA5) | (g >> 1), 0);
- } else if (drawModeBitFlags & Mouse::MouseDrawFlags::BLUECROSSHAIRS) {
- newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
- } else {
- // Additive modes
- getPixel(surface, dstPtr, surfaceColorRGBPrev);
- if (drawModeBitFlags & Mouse::MouseDrawFlags::ADDITIVE_MODE0) {
- // This code makes the cursor semi-transparent
- // but it may not be what the disassembly of the original was going for.
- newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
- newSurfaceColorRGB = (((uint16)surfaceColorRGBPrev >> 1) & 0xFBEF)
- + (((uint16)newSurfaceColorRGB >> 1) & 0xFBEF);
- } else if (drawModeBitFlags & Mouse::MouseDrawFlags::ADDITIVE_MODE1) {
- // This code may be closer to what the disassembly of the original was doing
- // for additive draw mode but it doesn't look well.
- surface.format.colorToRGB(surfaceColorRGBPrev, rPrev, gPrev, bPrev);
- rgb16bitPrev = ( ((uint16)(rPrev >> 3) << 10)
- | ((uint16)(gPrev >> 3) << 5)
- | ((uint16)(bPrev >> 3)));
- rgb16bitAdd = (((uint16)rgb16bitPrev >> 1) & 0xFBEF)
- + ((shpColor >> 1) & 0xFBEF);
- getGameDataColor(rgb16bitAdd, a, r, g, b);
+ if (drawModeBitFlags & Mouse::MouseDrawFlags::CUSTOM) {
+ // for both scene exit cursors and static ESPER edge cursors
+ // we choose 25x25px -- odd dimensions chosen so that pixel 12 is the absolute middle (with edges 0-24)
+ rect_w = MIN(CLIP(25 + x, 0, 25), surface.w - x);
+ rect_h = MIN(CLIP(25 + y, 0, 25), surface.h - y);
+
+ const uint32 exitDemoShapeColors[3] = { surface.format.RGBToColor(255, 255, 143),
+ surface.format.RGBToColor(228, 108, 10),
+ surface.format.RGBToColor(140, 0, 37) };
+
+ const uint32 esperExitDemoShapeColor = surface.format.RGBToColor(230, 230, 230); // For ESPER arrows
+ Common::Rect tailRect;
+
+ // We mask out the irrelevant bitflags and exploit the fact
+ // that these exit cursor bitflags do not combine,
+ // so only one of them can be set at any time.
+ switch (drawModeBitFlags & ~0x007F) {
+ case Mouse::MouseDrawFlags::EXIT_RIGHT:
+ // 6 px h, 6 px w
+ drawFilledTriangleAux(surface, dst_x, dst_y, 24, 12, 18, 6, 18, 18, exitDemoShapeColors[ (drawModeBitFlags & 0x7)/2 % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 16, 12, 10, 6, 10, 18, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 1) % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 8, 12, 2, 6, 2, 18, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 2) % 3]);
+ break;
+
+ case Mouse::MouseDrawFlags::EXIT_LEFT:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 0, 12, 6, 6, 6, 18, exitDemoShapeColors[ (drawModeBitFlags & 0x7)/2 % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 8, 12, 14, 6, 14, 18, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 1) % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 16, 12, 22, 6, 22, 18, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 2) % 3]);
+ break;
+
+ case Mouse::MouseDrawFlags::EXIT_UP:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 0, 6, 6, 18, 6, exitDemoShapeColors[ (drawModeBitFlags & 0x7)/2 % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 8, 6, 14, 18, 14, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 1) % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 16, 6, 22, 18, 22, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 2) % 3]);
+ break;
+
+ case Mouse::MouseDrawFlags::EXIT_DOWN:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 24, 6, 18, 18, 18, exitDemoShapeColors[ (drawModeBitFlags & 0x7)/2 % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 16, 6, 10, 18, 10, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 1) % 3]);
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 8, 6, 2, 18, 2, exitDemoShapeColors[((drawModeBitFlags & 0x7)/2 + 2) % 3]);
+ break;
+
+ case Mouse::MouseDrawFlags::ESPER_RIGHT:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 24, 12, 12, 0, 12, 24, esperExitDemoShapeColor);
+ tailRect = Common::Rect(dst_x + 4, dst_y + 6, dst_x + 12, dst_y + 18);
+ surface.fillRect(tailRect, esperExitDemoShapeColor);
+ break;
+
+ case Mouse::MouseDrawFlags::ESPER_LEFT:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 0, 12, 12, 0, 12, 24, esperExitDemoShapeColor);
+ tailRect = Common::Rect(dst_x + 12, dst_y + 6, dst_x + 20, dst_y + 18);
+ surface.fillRect(tailRect, esperExitDemoShapeColor);
+ break;
+
+ case Mouse::MouseDrawFlags::ESPER_UP:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 0, 0, 12, 24, 12, esperExitDemoShapeColor);
+ tailRect = Common::Rect(dst_x + 6, dst_y + 12, dst_x + 18, dst_y + 20);
+ surface.fillRect(tailRect, esperExitDemoShapeColor);
+ break;
+
+ case Mouse::MouseDrawFlags::ESPER_DOWN:
+ drawFilledTriangleAux(surface, dst_x, dst_y, 12, 24, 0, 12, 24, 12, esperExitDemoShapeColor);
+ tailRect = Common::Rect(dst_x + 6, dst_y + 4, dst_x + 18, dst_y + 12);
+ surface.fillRect(tailRect, esperExitDemoShapeColor);
+ break;
+
+ default:
+ debug("Unsupported custom shape %d", drawModeBitFlags &~ 0xEF);
+ break;
+ }
+ } else {
+ const uint8 *src_p = _data + 2 * (src_y * _width + src_x);
+
+ uint16 shpColor = 0;
+ uint32 surfaceColorRGBPrev = 0;
+ uint32 newSurfaceColorRGB = 0;
+ uint8 a, r, g, b;
+ uint8 rPrev, gPrev, bPrev;
+ uint16 rgb16bitPrev = 0;
+ uint16 rgb16bitAdd = 0;
+ for (int yi = 0; yi != rect_h; ++yi) {
+ for (int xi = 0; xi != rect_w; ++xi) {
+ shpColor = READ_LE_UINT16(src_p);
+ src_p += 2;
+
+ getGameDataColor(shpColor, a, r, g, b);
+
+ if (!a) {
+ // Ignore the alpha in the output as it is inversed in the input
+ void *dstPtr = surface.getBasePtr(CLIP(dst_x + xi, 0, surface.w - 1), CLIP(dst_y + yi, 0, surface.h - 1));
+ if (drawModeBitFlags & Mouse::MouseDrawFlags::SPECIAL) {
+ // It seems that the additive mode was supposed to be used only for cursor shapes
+ // From testing, the only cursor shape that seems to work with it is the green rotating cursor
+ // We add extra code here to cover the cases of the beta crosshairs cursor
+ // being drawn a different color based on bullet power
+ // The code for creating the specific color is custom.
+ if (drawModeBitFlags & Mouse::MouseDrawFlags::REDCROSSHAIRS) {
+ newSurfaceColorRGB = surface.format.RGBToColor((b & 0x8B) | (g >> 1), 0, 0);
+ } else if (drawModeBitFlags & Mouse::MouseDrawFlags::YELLOWCROSSHAIRS) {
+ newSurfaceColorRGB = surface.format.RGBToColor(b & 0xDF, (b & 0xA5) | (g >> 1), 0);
+ } else if (drawModeBitFlags & Mouse::MouseDrawFlags::BLUECROSSHAIRS) {
newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
+ } else {
+ // Additive modes
+ getPixel(surface, dstPtr, surfaceColorRGBPrev);
+ if (drawModeBitFlags & Mouse::MouseDrawFlags::ADDITIVE_MODE0) {
+ // This code makes the cursor semi-transparent
+ // but it may not be what the disassembly of the original was going for.
+ newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
+ newSurfaceColorRGB = (((uint16)surfaceColorRGBPrev >> 1) & 0xFBEF)
+ + (((uint16)newSurfaceColorRGB >> 1) & 0xFBEF);
+ } else if (drawModeBitFlags & Mouse::MouseDrawFlags::ADDITIVE_MODE1) {
+ // This code may be closer to what the disassembly of the original was doing
+ // for additive draw mode but it doesn't look well.
+ surface.format.colorToRGB(surfaceColorRGBPrev, rPrev, gPrev, bPrev);
+ rgb16bitPrev = ( ((uint16)(rPrev >> 3) << 10)
+ | ((uint16)(gPrev >> 3) << 5)
+ | ((uint16)(bPrev >> 3)));
+ rgb16bitAdd = (((uint16)rgb16bitPrev >> 1) & 0xFBEF)
+ + ((shpColor >> 1) & 0xFBEF);
+ getGameDataColor(rgb16bitAdd, a, r, g, b);
+ newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
+ }
}
+ } else {
+ newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
}
- } else {
- newSurfaceColorRGB = surface.format.RGBToColor(r, g, b);
+ drawPixel(surface, dstPtr, newSurfaceColorRGB);
}
- drawPixel(surface, dstPtr, newSurfaceColorRGB);
}
+ src_p += 2 * (_width - rect_w);
}
- src_p += 2 * (_width - rect_w);
}
}
diff --git a/engines/bladerunner/shape.h b/engines/bladerunner/shape.h
index cb9249f856d..bebca4c72b4 100644
--- a/engines/bladerunner/shape.h
+++ b/engines/bladerunner/shape.h
@@ -47,10 +47,12 @@ class Shape {
bool load(Common::SeekableReadStream *stream);
+ void drawFilledTriangleAux(Graphics::Surface &surface, const int &dst_x, const int &dst_y, int x1, int y1, int x2, int y2, int x3, int y3, uint32 colorRGB) const;
+
public:
~Shape();
- void draw(Graphics::Surface &surface, int x, int y, uint8 drawModeBitFlags = 0) const;
+ void draw(Graphics::Surface &surface, int x, int y, uint16 drawModeBitFlags = 0) const;
int getWidth() const { return _width; }
int getHeight() const { return _height; }
More information about the Scummvm-git-logs
mailing list