diff options
author | Eugene Sandulenko | 2016-06-14 19:28:00 +0200 |
---|---|---|
committer | Eugene Sandulenko | 2016-06-14 19:28:29 +0200 |
commit | 6928ddba1574dcbe87c06f3774968ae8f3fc02ea (patch) | |
tree | b605d96ca458289b337bba1a7efa72ca4251dda8 /engines | |
parent | df02215957ebf220a35995deef9cb745af8f9aac (diff) | |
download | scummvm-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.cpp | 236 | ||||
-rw-r--r-- | engines/scumm/he/moonbase/moonbase.h | 2 | ||||
-rw-r--r-- | engines/scumm/module.mk | 1 |
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 |