aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorEugene Sandulenko2016-06-14 19:28:00 +0200
committerEugene Sandulenko2016-06-14 19:28:29 +0200
commit6928ddba1574dcbe87c06f3774968ae8f3fc02ea (patch)
treeb605d96ca458289b337bba1a7efa72ca4251dda8 /engines
parentdf02215957ebf220a35995deef9cb745af8f9aac (diff)
downloadscummvm-rg350-6928ddba1574dcbe87c06f3774968ae8f3fc02ea.tar.gz
scummvm-rg350-6928ddba1574dcbe87c06f3774968ae8f3fc02ea.tar.bz2
scummvm-rg350-6928ddba1574dcbe87c06f3774968ae8f3fc02ea.zip
SCUMM HE: Initial Moonbase distortion code
Diffstat (limited to 'engines')
-rw-r--r--engines/scumm/he/moonbase/distortion.cpp236
-rw-r--r--engines/scumm/he/moonbase/moonbase.h2
-rw-r--r--engines/scumm/module.mk1
3 files changed, 239 insertions, 0 deletions
diff --git a/engines/scumm/he/moonbase/distortion.cpp b/engines/scumm/he/moonbase/distortion.cpp
new file mode 100644
index 0000000000..121a19400b
--- /dev/null
+++ b/engines/scumm/he/moonbase/distortion.cpp
@@ -0,0 +1,236 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "scumm/he/intern_he.h"
+#include "engines/scumm/he/moonbase/moonbase.h"
+
+namespace Scumm {
+
+enum {
+ kHalfRange = (0x1f / 2),
+ kBptHeaderSize = 8,
+
+ kReflectionClipped = 0,
+ kNotClipped = 1,
+ kSpecializedNotClipped = 2
+};
+
+void blitCore(
+ Graphics::Surface *dstBitmap,
+ const int x, const int y,
+ const Graphics::Surface *distortionBitmap,
+ const Common::Rect *optionalclipRectPtr,
+ int transferOp,
+ const Graphics::Surface *srcBitmap,
+ int offset_x, int offset_y,
+ Common::Rect *srcClipRect
+) {
+ Common::Rect clipRect(dstBitmap->w, dstBitmap->h);
+
+ if (optionalclipRectPtr)
+ if (!clipRect.intersects(*optionalclipRectPtr))
+ return;
+
+ clipRect.clip(*optionalclipRectPtr);
+
+ Common::Rect distortionRect(distortionBitmap->w, distortionBitmap->h);
+ Common::Rect dstRect(x, y, x + distortionRect.width(), y + distortionRect.height());
+
+ if (!dstRect.intersects(clipRect))
+ return;
+
+ dstRect.clip(clipRect);
+
+ distortionRect.moveTo(dstRect.left - x, dstRect.top - y);
+
+ byte *distortionPtr = (byte *)distortionBitmap->getBasePtr(distortionRect.left, distortionRect.top);
+ byte *dstPtr = (byte *)dstBitmap->getBasePtr(dstRect.left, dstRect.top);
+ int cw = dstRect.width();
+ int ch = dstRect.height();
+ int idx = dstRect.left;
+ int dy = dstRect.top;
+
+ int baseX, baseY;
+ byte *srcData = (byte *)srcBitmap->getBasePtr(0, 0);
+ int srcPitch = srcBitmap->pitch;
+
+ switch (transferOp) {
+ case kReflectionClipped:
+ case kNotClipped:
+ baseX = offset_x - kHalfRange;
+ baseY = offset_y - kHalfRange;
+ break;
+
+ case kSpecializedNotClipped:
+ default:
+ baseX = 0;
+ baseY = 0;
+ }
+
+ while (--ch >= 0) {
+ uint16 *d = (uint16 *)dstPtr;
+ uint16 *is = (uint16 *)distortionPtr;
+ int dx = idx;
+
+ for (int i = cw; --i >= 0;) {
+ uint16 p = READ_LE_UINT16(is);
+ int sx = baseX + dx + (p >> 5) & 0x1f; // G color
+ int sy = baseY + dy + p & 0x1f; // B color;
+
+ if (transferOp == kReflectionClipped) {
+ if (sx < srcClipRect->left)
+ sx -= (srcClipRect->left - sx);
+
+ if (sx > srcClipRect->right)
+ sx -= (sx - srcClipRect->right);
+
+ sx = MAX<int>(srcClipRect->left, MIN<int>(sx, srcClipRect->right));
+
+ if (sy < srcClipRect->top)
+ sy -= (srcClipRect->top - sy);
+
+ if (sy > srcClipRect->bottom)
+ sy -= (sy - srcClipRect->bottom);
+
+ sy = MAX<int>(srcClipRect->top, MIN<int>(sy, srcClipRect->bottom));
+ }
+
+ *d = *((uint16 *)(srcData + sy * srcPitch + sx * 2));
+
+ ++d;
+ ++is;
+ ++dx;
+ }
+
+ dstPtr += dstBitmap->pitch;
+ distortionPtr += distortionBitmap->pitch;
+
+ ++dy;
+ }
+}
+
+void distortionBlit(
+ Graphics::Surface *dstBitmap,
+ Graphics::Surface *srcBitmap,
+ Graphics::Surface *distortionBitmap,
+ const int dst_x, const int dst_y,
+ const int src_x, const int src_y,
+ const int l_reach, const int r_reach, const int t_reach, const int b_reach,
+ const Common::Rect &srcClipRect, const Common::Rect &dstClipRect
+) {
+ Common::Rect srcReach((src_x - l_reach), (src_y - t_reach), (src_x + r_reach), (src_y + b_reach));
+ Common::Rect srcLimits(srcBitmap->w, srcBitmap->h);
+
+ if (!srcLimits.intersects(srcClipRect))
+ return;
+
+ srcLimits.clip(srcClipRect);
+
+ if (!srcReach.intersects(srcLimits))
+ return;
+
+ srcReach.clip(srcLimits);
+
+ if (srcLimits.contains(srcReach)) {
+ if (srcBitmap->pitch == 1280) {
+ blitCore(dstBitmap, dst_x, dst_y, distortionBitmap, &dstClipRect, kSpecializedNotClipped, srcBitmap, (dst_x - src_x), (dst_y - src_y), 0);
+ } else {
+ blitCore(dstBitmap, dst_x, dst_y, distortionBitmap, &dstClipRect, kNotClipped, srcBitmap, (dst_x - src_x), (dst_y - src_y), 0);
+ }
+ } else {
+ blitCore(dstBitmap, dst_x, dst_y, distortionBitmap, &dstClipRect, kReflectionClipped, srcBitmap, (dst_x - src_x), (dst_y - src_y), &srcLimits);
+ }
+}
+
+void Moonbase::blitDistortion(byte *bufferData, const int bufferWidth, const int bufferHeight, const int bufferPitch,
+ const Common::Rect *optionalClippingRect, byte *dataStream, const int x, const int y, byte *altSourceBuffer) {
+ byte *sourcePixels = (altSourceBuffer) ? altSourceBuffer : bufferData;
+ Common::Rect dstLimitsRect(bufferWidth, bufferHeight);
+ Common::Rect clippedDstRect = dstLimitsRect;
+
+ if (optionalClippingRect) {
+ if (!dstLimitsRect.intersects(*optionalClippingRect))
+ return;
+ dstLimitsRect.clip(*optionalClippingRect);
+ } else {
+ clippedDstRect = dstLimitsRect;
+ }
+
+ int w = READ_LE_UINT16(dataStream + kBptHeaderSize + 0);
+ int h = READ_LE_UINT16(dataStream + kBptHeaderSize + 2);
+ Common::Rect srcLimitsRect(w, h);
+ Common::Rect clippedSrcRect = srcLimitsRect;
+ Common::Rect dstOperation(x, y, x + clippedSrcRect.width(), y + clippedSrcRect.height());
+
+ if (!clippedDstRect.intersects(dstOperation))
+ return;
+
+ clippedDstRect.clip(dstOperation);
+
+ int subBlockCount = READ_LE_UINT16(dataStream + kBptHeaderSize + 4);
+ byte *subBlockStream = dataStream + kBptHeaderSize + READ_LE_UINT16(dataStream) + 2;
+ int cx1 = clippedDstRect.left;
+ int cy1 = clippedDstRect.top;
+ int cx2 = clippedDstRect.right - 1;
+ int cy2 = clippedDstRect.bottom - 1;
+
+ for (int i = 0; i < subBlockCount; i++) {
+ byte *blockData = subBlockStream;
+ uint32 blockSize = READ_LE_UINT32(blockData); blockData += 4;
+ subBlockStream += blockSize;
+ int xOffset = READ_LE_UINT16(blockData); blockData += 2;
+ int yOffset = READ_LE_UINT16(blockData); blockData += 2;
+ int width = READ_LE_UINT16(blockData); blockData += 2;
+ int height = READ_LE_UINT16(blockData); blockData += 2;
+ int l_Reach = READ_LE_UINT16(blockData); blockData += 2;
+ int r_Reach = READ_LE_UINT16(blockData); blockData += 2;
+ int t_Reach = READ_LE_UINT16(blockData); blockData += 2;
+ int b_Reach = READ_LE_UINT16(blockData); blockData += 2;
+ int distortionPitch = ((width * 2 + 7) / 8); // 2 for 555
+
+ if (width == 0 && height == 0)
+ continue;
+
+ Graphics::Surface mappedDstBitmap;
+ mappedDstBitmap.init(bufferWidth, bufferHeight, bufferPitch, bufferData, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+
+ Graphics::Surface mappedSrcBitmap;
+ mappedSrcBitmap.init(bufferWidth, bufferHeight, bufferPitch, sourcePixels, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+
+ Graphics::Surface mappedDistortionBitmap;
+ mappedDistortionBitmap.init(width, height, distortionPitch, blockData, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+
+ Common::Rect srcClipRect(cx1, cy1, cx2, cy2);
+ Common::Rect dstClipRect(cx1, cy1, cx2, cy2);
+
+ distortionBlit(
+ &mappedDstBitmap,
+ &mappedSrcBitmap,
+ &mappedDistortionBitmap,
+ (x + xOffset), (y + yOffset),
+ (x + xOffset), (y + yOffset),
+ l_Reach, r_Reach, t_Reach, b_Reach,
+ srcClipRect, dstClipRect);
+ }
+}
+
+}
diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h
index 1d87eed7d9..71c03cb007 100644
--- a/engines/scumm/he/moonbase/moonbase.h
+++ b/engines/scumm/he/moonbase/moonbase.h
@@ -42,6 +42,8 @@ public:
void blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox,
uint8 *wizd, int srcx, int srcy, int rawROP, int paramROP);
+ void blitDistortion(byte *bufferData, const int bufferWidth, const int bufferHeight, const int bufferPitch,
+ const Common::Rect *optionalClippingRect, byte *dataStream, const int x, const int y, byte *altSourceBuffer);
// FOW Stuff
bool isFOW(int resNum, int state, uint32 conditionBits) {
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 04611ba1b1..85ff1aa4cd 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -147,6 +147,7 @@ MODULE_OBJS += \
he/moonbase/ai_tree.o \
he/moonbase/ai_types.o \
he/moonbase/ai_weapon.o \
+ he/moonbase/distortion.o \
he/moonbase/moonbase.o \
he/moonbase/moonbase_fow.o
endif