protected virtual void DecodeMask(int x, int y, int width, int height, int stripnr, IList <ZPlane> zPlanes, bool transpStrip, DrawBitmaps flags) { var zplaneCount = IsZBufferEnabled ? NumZBuffer : 0; if (flags.HasFlag(DrawBitmaps.DrawMaskOnAll)) { // Sam & Max uses dbDrawMaskOnAll for things like the inventory // box and the speech icons. While these objects only have one // mask, it should be applied to all the Z-planes in the room, // i.e. they should mask every actor. // // This flag used to be called dbDrawMaskOnBoth, and all it // would do was to mask Z-plane 0. (Z-plane 1 would also be // masked, because what is now the else-clause used to be run // always.) While this seems to be the only way there is to // mask Z-plane 0, this wasn't good enough since actors in // Z-planes >= 2 would not be masked. // // The flag is also used by The Dig and Full Throttle, but I // don't know what for. At the time of writing, these games // are still too unstable for me to investigate. var offs = zPlanes[0].StripOffsets[stripnr]; using (var zplanePtr = new MemoryStream(zPlanes[0].Data)) { zplanePtr.Seek(offs.Value, SeekOrigin.Begin); for (var i = 0; i < zplaneCount; i++) { var mask_ptr = GetMaskBuffer(x, y, i); if (transpStrip && (flags.HasFlag(DrawBitmaps.AllowMaskOr))) { DecompressMaskImgOr(mask_ptr, zplanePtr, height); } else { DecompressMaskImg(mask_ptr, zplanePtr, height); } } } } else { for (var i = 1; i < zplaneCount; i++) { var offs = i <= zPlanes.Count ? zPlanes[i - 1].StripOffsets[stripnr] : null; var mask_ptr = GetMaskBuffer(x, y, i); if (offs.HasValue) { using (var zplanePtr = new MemoryStream(zPlanes[i - 1].Data)) { zplanePtr.Seek(offs.Value, SeekOrigin.Begin); if (transpStrip && flags.HasFlag(DrawBitmaps.AllowMaskOr)) { DecompressMaskImgOr(mask_ptr, zplanePtr, height); } else { DecompressMaskImg(mask_ptr, zplanePtr, height); } } } else if (!(transpStrip && flags.HasFlag(DrawBitmaps.AllowMaskOr))) { for (var h = 0; h < height; h++) { mask_ptr.OffsetY(1); mask_ptr.Write(0); } } } } }
protected virtual void DecodeMask(int x, int y, int width, int height, int stripnr, IList<ZPlane> zPlanes, bool transpStrip, DrawBitmaps flags) { var zplaneCount = IsZBufferEnabled ? NumZBuffer : 0; if (flags.HasFlag(DrawBitmaps.DrawMaskOnAll)) { // Sam & Max uses dbDrawMaskOnAll for things like the inventory // box and the speech icons. While these objects only have one // mask, it should be applied to all the Z-planes in the room, // i.e. they should mask every actor. // // This flag used to be called dbDrawMaskOnBoth, and all it // would do was to mask Z-plane 0. (Z-plane 1 would also be // masked, because what is now the else-clause used to be run // always.) While this seems to be the only way there is to // mask Z-plane 0, this wasn't good enough since actors in // Z-planes >= 2 would not be masked. // // The flag is also used by The Dig and Full Throttle, but I // don't know what for. At the time of writing, these games // are still too unstable for me to investigate. var offs = zPlanes[0].StripOffsets[stripnr]; using (var zplanePtr = new MemoryStream(zPlanes[0].Data)) { zplanePtr.Seek(offs.Value, SeekOrigin.Begin); for (var i = 0; i < zplaneCount; i++) { var mask_ptr = GetMaskBuffer(x, y, i); if (transpStrip && (flags.HasFlag(DrawBitmaps.AllowMaskOr))) DecompressMaskImgOr(mask_ptr, zplanePtr, height); else DecompressMaskImg(mask_ptr, zplanePtr, height); } } } else { for (var i = 1; i < zplaneCount; i++) { var offs = i <= zPlanes.Count ? zPlanes[i - 1].StripOffsets[stripnr] : null; var mask_ptr = GetMaskBuffer(x, y, i); if (offs.HasValue) { using (var zplanePtr = new MemoryStream(zPlanes[i - 1].Data)) { zplanePtr.Seek(offs.Value, SeekOrigin.Begin); if (transpStrip && flags.HasFlag(DrawBitmaps.AllowMaskOr)) { DecompressMaskImgOr(mask_ptr, zplanePtr, height); } else { DecompressMaskImg(mask_ptr, zplanePtr, height); } } } else if (!(transpStrip && flags.HasFlag(DrawBitmaps.AllowMaskOr))) { for (var h = 0; h < height; h++) { mask_ptr.OffsetY(1); mask_ptr.Write(0); } } } } }
public void DrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags, bool isLightOn) { var x = p.X; var y = p.Y; if ((_vm.TownsPaletteFlags & 2) != 0) { int cx = (x - _vm.ScreenStartStrip) << 3; Gdi.Fill(_vm.TextSurface, new Rect(cx * _vm.TextSurfaceMultiplier, y * _vm.TextSurfaceMultiplier, (cx + width - 1) * _vm.TextSurfaceMultiplier, (y + height - 1) * _vm.TextSurfaceMultiplier), 0); } _objectMode = flags.HasFlag(DrawBitmaps.ObjectMode); PrepareDrawBitmap(img, vs, p, width, height, stripnr, numstrip); int sx = x - vs.XStart / 8; if (sx < 0) { numstrip -= -sx; x += -sx; stripnr += -sx; sx = 0; } // Compute the number of strips we have to iterate over. // TODO/FIXME: The computation of its initial value looks very fishy. // It was added as a kind of hack to fix some corner cases, but it compares // the room width to the virtual screen width; but the former should always // be bigger than the latter (except for MM NES, maybe)... strange int limit = Math.Max(roomWidth, vs.Width) / 8 - x; if (limit > numstrip) { limit = numstrip; } if (limit > NumStrips - sx) { limit = NumStrips - sx; } for (int k = 0; k < limit; ++k, ++stripnr, ++sx, ++x) { if (y < vs.TDirty[sx]) { vs.TDirty[sx] = y; } if (y + height > vs.BDirty[sx]) { vs.BDirty[sx] = y + height; } // In the case of a double buffered virtual screen, we draw to // the backbuffer, otherwise to the primary surface memory. var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0]; var navDst = new PixelNavigator(surface); navDst.GoTo(x * 8, y); bool transpStrip; using (var smapReader = new BinaryReader(new MemoryStream(img.Data))) { transpStrip = DrawStrip(navDst, width, height, stripnr, smapReader); } // COMI and HE games only uses flag value if (game.Version == 8) { transpStrip = true; } if (vs.HasTwoBuffers) { var navFrontBuf = new PixelNavigator(vs.Surfaces[0]); navFrontBuf.GoTo(x * 8, y); if (isLightOn) { Copy8Col(navFrontBuf, navDst, height); } else { Clear8Col(navFrontBuf, height); } } DecodeMask(x, y, width, height, stripnr, img.ZPlanes, transpStrip, flags); } }
public void DrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags, bool isLightOn) { var x = p.X; var y = p.Y; if ((_vm.TownsPaletteFlags & 2) != 0) { int cx = (x - _vm.ScreenStartStrip) << 3; Gdi.Fill(_vm.TextSurface, new Rect(cx * _vm.TextSurfaceMultiplier, y * _vm.TextSurfaceMultiplier, (cx + width - 1) * _vm.TextSurfaceMultiplier, (y + height - 1) * _vm.TextSurfaceMultiplier), 0); } _objectMode = flags.HasFlag(DrawBitmaps.ObjectMode); PrepareDrawBitmap(img, vs, p, width, height, stripnr, numstrip); int sx = x - vs.XStart / 8; if (sx < 0) { numstrip -= -sx; x += -sx; stripnr += -sx; sx = 0; } // Compute the number of strips we have to iterate over. // TODO/FIXME: The computation of its initial value looks very fishy. // It was added as a kind of hack to fix some corner cases, but it compares // the room width to the virtual screen width; but the former should always // be bigger than the latter (except for MM NES, maybe)... strange int limit = Math.Max(roomWidth, vs.Width) / 8 - x; if (limit > numstrip) limit = numstrip; if (limit > NumStrips - sx) limit = NumStrips - sx; for (int k = 0; k < limit; ++k, ++stripnr, ++sx, ++x) { if (y < vs.TDirty[sx]) vs.TDirty[sx] = y; if (y + height > vs.BDirty[sx]) vs.BDirty[sx] = y + height; // In the case of a double buffered virtual screen, we draw to // the backbuffer, otherwise to the primary surface memory. var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0]; var navDst = new PixelNavigator(surface); navDst.GoTo(x * 8, y); bool transpStrip; using (var smapReader = new BinaryReader(new MemoryStream(img.Data))) { transpStrip = DrawStrip(navDst, width, height, stripnr, smapReader); } // COMI and HE games only uses flag value if (game.Version == 8) transpStrip = true; if (vs.HasTwoBuffers) { var navFrontBuf = new PixelNavigator(vs.Surfaces[0]); navFrontBuf.GoTo(x * 8, y); if (isLightOn) Copy8Col(navFrontBuf, navDst, height); else Clear8Col(navFrontBuf, height); } DecodeMask(x, y, width, height, stripnr, img.ZPlanes, transpStrip, flags); } }