static void DecompressMaskImgOr(PixelNavigator dst, Stream src, int height) { byte b, c; while (height != 0) { b = (byte)src.ReadByte(); if ((b & 0x80) != 0) { b &= 0x7F; c = (byte)src.ReadByte(); do { dst.Write((byte)(dst.Read() | c)); dst.OffsetY(1); --height; } while ((--b != 0) && (height != 0)); } else { do { dst.Write((byte)(dst.Read() | src.ReadByte())); dst.OffsetY(1); --height; } while ((--b != 0) && (height != 0)); } } }
static void DecompressMaskImg(PixelNavigator dst, Stream src, int height) { while (height != 0) { var b = (byte)src.ReadByte(); if ((b & 0x80) != 0) { b &= 0x7F; var c = (byte)src.ReadByte(); do { dst.Write(c); dst.OffsetY(1); --height; } while (--b != 0 && height != 0); } else { do { dst.Write((byte)src.ReadByte()); dst.OffsetY(1); --height; } while (--b != 0 && height != 0); } } }
void DrawStripV1Background(PixelNavigator navDst, int stripnr, int height) { int charIdx; height /= 8; for (int y = 0; y < height; y++) { _v1.Colors[3] = (byte)(_v1.ColorMap[y + stripnr * height] & 7); // Check for room color change in V1 zak if (RoomPalette[0] == 255) { _v1.Colors[2] = RoomPalette[2]; _v1.Colors[1] = RoomPalette[1]; } charIdx = _v1.PicMap[y + stripnr * height] * 8; for (int i = 0; i < 8; i++) { byte c = _v1.CharMap[charIdx + i]; var color = _v1.Colors[(c >> 6) & 3]; navDst.Write(0, color); navDst.Write(1, color); color = _v1.Colors[(c >> 4) & 3]; navDst.Write(2, color); navDst.Write(3, color); color = _v1.Colors[(c >> 2) & 3]; navDst.Write(4, color); navDst.Write(5, color); color = _v1.Colors[(c >> 0) & 3]; navDst.Write(6, color); navDst.Write(7, color); navDst.OffsetY(1); } } }
void DrawStripRaw(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck) { int x; if (game.Features.HasFlag(GameFeatures.Old256)) { int h = height; x = 8; while (true) { navDst.Write(RoomPalette[src.ReadByte()]); if (!NextRow(ref navDst, ref x, ref h, height)) { return; } } } do { for (x = 0; x < 8; x++) { int color = src.ReadByte(); if (!transpCheck || color != TransparentColor) { navDst.OffsetX(x); WriteRoomColor(navDst, color); navDst.OffsetX(-x); } } navDst.OffsetY(1); } while ((--height) != 0); }
void DrawStripV1Object(PixelNavigator navDst, int stripnr, int width, int height) { int charIdx; height /= 8; width /= 8; for (var y = 0; y < height; y++) { _v1.Colors[3] = (byte)(objectMap[(y + height) * width + stripnr] & 7); charIdx = objectMap[y * width + stripnr] * 8; for (var i = 0; i < 8; i++) { byte c = _v1.CharMap[charIdx + i]; var color = _v1.Colors[(c >> 6) & 3]; navDst.Write(0, color); navDst.Write(1, color); color = _v1.Colors[(c >> 4) & 3]; navDst.Write(2, color); navDst.Write(3, color); color = _v1.Colors[(c >> 2) & 3]; navDst.Write(4, color); navDst.Write(5, color); color = _v1.Colors[(c >> 0) & 3]; navDst.Write(6, color); navDst.Write(7, color); navDst.OffsetY(1); } } }
void DrawStripV1Mask(PixelNavigator navDst, int stripnr, int width, int height) { int maskIdx; height /= 8; width /= 8; for (var y = 0; y < height; y++) { if (_objectMode) { maskIdx = objectMap[(y + 2 * height) * width + stripnr] * 8; } else { maskIdx = _v1.MaskMap[y + stripnr * height] * 8; } for (var i = 0; i < 8; i++) { byte c = _v1.MaskChar[maskIdx + i]; // V1/V0 masks are inverted compared to what ScummVM expects navDst.Write((byte)(c ^ 0xFF)); navDst.OffsetY(1); } } }
public void DrawChar(PixelNavigator dst, char c, int x, int y, byte color) { var width = Math.Min((int)_chars[c].Width, dst.Width - x); var height = Math.Min((int)_chars[c].Height, dst.Height - y); var src = UnpackChar(c); var srcPitch = _chars[c].Width; var srcPos = 0; var minX = x < 0 ? -x : 0; var minY = y < 0 ? -y : 0; if (height <= 0 || width <= 0) { return; } if (minY != 0) { srcPos += minY * srcPitch; dst.OffsetY(minY); } for (int ty = minY; ty < height; ty++) { for (int tx = minX; tx < width; tx++) { if (src[srcPos + tx] != _chars[c].Transparency) { if (src[srcPos + tx] == 1) { dst.Write(tx, color); } else { dst.Write(tx, src[srcPos + tx]); } } } srcPos += srcPitch; dst.OffsetY(1); } }
static bool NextRow(ref PixelNavigator navDst, ref int x, ref int y, int height) { navDst.OffsetY(1); if (--y == 0) { if ((--x) == 0) { return(false); } navDst.Offset(1, -height); y = height; } return(true); }
void DrawStripBasicV(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck) { byte color = src.ReadByte(); uint bits = src.ReadByte(); byte cl = 8; int inc = -1; int x = 8; do { int h = height; do { FillBits(ref cl, ref bits, src); if (!transpCheck || color != transparentColor) { WriteRoomColor(navDst, color); } navDst.OffsetY(1); if (!ReadBit(ref cl, ref bits)) { } else if (!ReadBit(ref cl, ref bits)) { FillBits(ref cl, ref bits, src); color = (byte)(bits & decompMask); bits >>= decompShr; cl -= decompShr; inc = -1; } else if (!ReadBit(ref cl, ref bits)) { color = (byte)(color + inc); } else { inc = -inc; color = (byte)(color + inc); } } while ((--h) != 0); navDst.Offset(1, -height); } while ((--x) != 0); }
void UnkDecode11(PixelNavigator navDst, BinaryReader src, int height) { int i; int buffer = 0, mask = 128; int inc = 1; int color = src.ReadByte(); int x = 8; do { int h = height; do { navDst.Write(RoomPalette[color]); navDst.OffsetY(1); for (i = 0; i < 3; i++) { if (!ReadBit256(src, ref mask, ref buffer)) { break; } } switch (i) { case 1: inc = -inc; color -= inc; break; case 2: color -= inc; break; case 3: inc = 1; color = ReadNBits(src, 8, ref mask, ref buffer); break; } } while ((--h) != 0); navDst.Offset(1, -height); } while ((--x) != 0); }
protected virtual void DrawBits1(Surface surface, int x, int y, BinaryReader src, int drawTop, int width, int height) { var dst = new PixelNavigator(surface); dst.GoTo(x, y); byte bits = 0; byte col = Color; //int pitch = surface.Pitch - width * surface.BytesPerPixel; var dst2 = new PixelNavigator(dst); dst2.OffsetY(1); for (y = 0; y < height && y + drawTop < surface.Height; y++) { for (x = 0; x < width; x++) { if ((x % 8) == 0) { bits = src.ReadByte(); } if ((bits & ScummHelper.RevBitMask(x % 8)) != 0 && y + drawTop >= 0) { if (_shadowMode) { dst.OffsetX(1); dst.Write(_shadowColor); dst2.Write(_shadowColor); dst2.OffsetX(1); dst2.Write(_shadowColor); } dst.Write(col); } dst.OffsetX(1); dst2.OffsetX(1); } dst.OffsetX(surface.Width - width); dst2.OffsetX(surface.Width - width); } }
void Akos16Decompress(PixelNavigator dest, int srcPos, int t_width, int t_height, int dir, int numskip_before, int numskip_after, byte transparency, int maskLeft, int maskTop, int zBuf) { var tmp_buf = _akos16.Buffer; var tmp_pos = 0; var maskbit = (byte)ScummHelper.RevBitMask(maskLeft & 7); if (dir < 0) { dest.OffsetX(-(t_width - 1)); tmp_pos += (t_width - 1); } Akos16SetupBitReader(srcPos); if (numskip_before != 0) { Akos16SkipData(numskip_before); } var maskptr = _vm.GetMaskBuffer(maskLeft, maskTop, zBuf); Debug.Assert(t_height > 0); Debug.Assert(t_width > 0); while ((t_height--) != 0) { Akos16DecodeLine(tmp_buf, tmp_pos, t_width, dir); BompDrawData.BompApplyMask(_akos16.Buffer, 0, maskptr, maskbit, t_width, transparency); BompDrawData.BompApplyShadow(ShadowMode, ShadowTable, _akos16.Buffer, 0, dest, t_width, transparency); if (numskip_after != 0) { Akos16SkipData(numskip_after); } dest.OffsetY(1); maskptr.OffsetY(1); } }
protected override void DrawBits1(Surface dest, int x, int y, BinaryReader src, int drawTop, int width, int height) { if (_sjisCurChar != 0) { // Debug.Assert(Vm._cjkFont); // Vm._cjkFont.drawChar(dest, _sjisCurChar, x, y, _color, _shadowColor); return; } bool scale2x = ((dest == Vm.TextSurface) && (Vm.TextSurfaceMultiplier == 2) /*&& !(_sjisCurChar >= 256 && Vm.UseCJKMode)*/); byte bits = 0; var col = Color; var bpp = Surface.GetBytesPerPixel(dest.PixelFormat); int pitch = dest.Pitch - width * bpp; var dst = new PixelNavigator(dest); dst.GoTo(x, y); var dst2 = new PixelNavigator(dst); dst2.OffsetY(1); var dst3 = new PixelNavigator(dst2); var dst4 = new PixelNavigator(dst2); if (scale2x) { dst3.OffsetY(1); dst4.OffsetY(1); pitch <<= 1; } for (y = 0; y < height && y + drawTop < dest.Height; y++) { for (x = 0; x < width; x++) { if ((x % 8) == 0) { bits = src.ReadByte(); } if (((bits & ScummHelper.RevBitMask(x % 8)) != 0) && y + drawTop >= 0) { if (bpp == 2) { if (_enableShadow) { dst.WriteUInt16(2, Vm._16BitPalette[_shadowColor]); dst.WriteUInt16(2 + dest.Pitch, Vm._16BitPalette[_shadowColor]); } dst.WriteUInt16(Vm._16BitPalette[Color]); } else { if (_enableShadow) { if (scale2x) { dst.Write(2, _shadowColor); dst.Write(3, _shadowColor); dst2.Write(2, _shadowColor); dst2.Write(3, _shadowColor); dst3.Write(0, _shadowColor); dst3.Write(1, _shadowColor); dst4.Write(0, _shadowColor); dst4.Write(0, _shadowColor); } else { dst2.Write(_shadowColor); dst.Write(1, _shadowColor); } } dst.Write(col); if (scale2x) { dst.Write(1, col); dst2.Write(0, col); dst2.Write(1, col); } } } dst.OffsetX(1); dst2.OffsetX(1); if (scale2x) { dst.OffsetX(1); dst2.OffsetX(1); dst3.OffsetX(1); dst4.OffsetX(1); } } dst.OffsetX(pitch / dst.BytesByPixel); dst2.OffsetX(pitch / dst2.BytesByPixel); dst3.OffsetX(pitch / dst3.BytesByPixel); dst4.OffsetX(pitch / dst4.BytesByPixel); } }
void Proc3(Codec1 v1) { int y = v1.Y; _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin); var dst = new PixelNavigator(v1.DestPtr); var len = v1.RepLen; uint color = v1.RepColor; var height = (uint)_height; var scaleIndexY = _scaleIndexY; var maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); var mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); bool ehmerde = (len != 0); do { if (!ehmerde) { len = _loaded.CostumeReader.ReadByte(); color = (uint)(len >> v1.Shr); len &= v1.Mask; if (len == 0) { len = _loaded.CostumeReader.ReadByte(); } } do { if (!ehmerde) { if (ScaleY == 255 || v1.Scaletable[scaleIndexY++] < ScaleY) { var masked = (y < 0 || y >= _h) || (v1.X < 0 || v1.X >= _w) || ((mask.Read() & maskbit) != 0); if (color != 0 && !masked) { byte pcolor; if ((ShadowMode & 0x20) != 0) { pcolor = ShadowTable[dst.Read()]; } else { pcolor = (byte)_palette[color]; if (pcolor == 13 && ShadowTable != null) { pcolor = ShadowTable[dst.Read()]; } } dst.Write(pcolor); } dst.OffsetY(1); mask.OffsetY(1); y++; } if ((--height) == 0) { if ((--v1.SkipWidth) == 0) { return; } height = (uint)_height; y = v1.Y; scaleIndexY = _scaleIndexY; if (ScaleX == 255 || v1.Scaletable[_scaleIndexX] < ScaleX) { v1.X += v1.ScaleXStep; if (v1.X < 0 || v1.X >= _w) { return; } maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); v1.DestPtr.OffsetX(v1.ScaleXStep); } _scaleIndexX = (byte)(_scaleIndexX + v1.ScaleXStep); dst = new PixelNavigator(v1.DestPtr); mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); } } ehmerde = false; } while ((--len) != 0); } while (true); }
void DrawStripRaw(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck) { int x; if (game.Features.HasFlag(GameFeatures.Old256)) { int h = height; x = 8; while (true) { navDst.Write(RoomPalette[src.ReadByte()]); if (!NextRow(ref navDst, ref x, ref h, height)) return; } } do { for (x = 0; x < 8; x++) { int color = src.ReadByte(); if (!transpCheck || color != TransparentColor) { navDst.OffsetX(x); WriteRoomColor(navDst, color); navDst.OffsetX(-x); } } navDst.OffsetY(1); } while ((--height) != 0); }
protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip) { var ptr = img.Data; // // Since V3, all graphics data was encoded in strips, which is very efficient // for redrawing only parts of the screen. However, V2 is different: here // the whole graphics are encoded as one big chunk. That makes it rather // difficult to draw only parts of a room/object. We handle the V2 graphics // differently from all other (newer) graphic formats for this reason. // var table = (_objectMode ? null : _roomStrips); int left = (stripnr * 8); int right = left + (numstrip * 8); PixelNavigator navDst; var srcOffset = 0; byte color, data = 0; int run; bool dither = false; byte[] dither_table = new byte[128]; var ditherOffset = 0; int theX, theY, maxX; var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0]; navDst = new PixelNavigator(surface); navDst.GoTo(p.X * 8, p.Y); var mask_ptr = GetMaskBuffer(p.X, p.Y, 1); if (table != null) { run = table.run[stripnr]; color = (byte)table.color[stripnr]; srcOffset = table.offsets[stripnr]; theX = left; maxX = right; } else { run = 1; color = 0; srcOffset = 0; theX = 0; maxX = width; } // Decode and draw the image data. Debug.Assert(height <= 128); for (; theX < maxX; theX++) { ditherOffset = 0; for (theY = 0; theY < height; theY++) { if (--run == 0) { data = ptr[srcOffset++]; if ((data & 0x80) != 0) { run = data & 0x7f; dither = true; } else { run = data >> 4; dither = false; } color = RoomPalette[data & 0x0f]; if (run == 0) { run = ptr[srcOffset++]; } } if (!dither) { dither_table[ditherOffset] = color; } if (left <= theX && theX < right) { navDst.Write(dither_table[ditherOffset++]); navDst.OffsetY(1); } } if (left <= theX && theX < right) { navDst.Offset(1, -height); } } // Draw mask (zplane) data theY = 0; if (table != null) { srcOffset = table.zoffsets[stripnr]; run = table.zrun[stripnr]; theX = left; } else { run = ptr[srcOffset++]; theX = 0; } while (theX < right) { byte runFlag = (byte)(run & 0x80); if (runFlag != 0) { run &= 0x7f; data = ptr[srcOffset++]; } do { if (runFlag == 0) data = ptr[srcOffset++]; if (left <= theX) { mask_ptr.Write(data); mask_ptr.OffsetY(1); } theY++; if (theY >= height) { if (left <= theX) { mask_ptr.Offset(1, -height); } theY = 0; theX += 8; if (theX >= right) break; } } while ((--run) != 0); run = ptr[srcOffset++]; } }
void Proc3(Codec1 v1) { int y = v1.Y; _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin); var dst = new PixelNavigator(v1.DestPtr); var len = v1.RepLen; uint color = v1.RepColor; var height = (uint)_height; var scaleIndexY = _scaleIndexY; var maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); var mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); bool ehmerde = (len != 0); do { if (!ehmerde) { len = _loaded.CostumeReader.ReadByte(); color = (uint)(len >> v1.Shr); len &= v1.Mask; if (len == 0) len = _loaded.CostumeReader.ReadByte(); } do { if (!ehmerde) { if (ScaleY == 255 || v1.Scaletable[scaleIndexY++] < ScaleY) { var masked = (y < 0 || y >= _h) || (v1.X < 0 || v1.X >= _w) || ((mask.Read() & maskbit) != 0); if (color != 0 && !masked) { byte pcolor; if ((ShadowMode & 0x20) != 0) { pcolor = ShadowTable[dst.Read()]; } else { pcolor = (byte)_palette[color]; if (pcolor == 13 && ShadowTable != null) pcolor = ShadowTable[dst.Read()]; } dst.Write(pcolor); } dst.OffsetY(1); mask.OffsetY(1); y++; } if ((--height) == 0) { if ((--v1.SkipWidth) == 0) return; height = (uint)_height; y = v1.Y; scaleIndexY = _scaleIndexY; if (ScaleX == 255 || v1.Scaletable[_scaleIndexX] < ScaleX) { v1.X += v1.ScaleXStep; if (v1.X < 0 || v1.X >= _w) return; maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); v1.DestPtr.OffsetX(v1.ScaleXStep); } _scaleIndexX = (byte)(_scaleIndexX + v1.ScaleXStep); dst = new PixelNavigator(v1.DestPtr); mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); } } ehmerde = false; } while ((--len) != 0); } while (true); }
public void DrawBomp() { Rect clip; byte skip_y_bits = 0x80; byte skip_y_new = 0; byte[] bomp_scaling_x = new byte[64]; byte[] bomp_scaling_y = new byte[64]; if (X < 0) { clip.Left = -X; } else { clip.Left = 0; } if (Y < 0) { clip.Top = -Y; } else { clip.Top = 0; } clip.Right = Width; if (clip.Right > Dst.Width - X) { clip.Right = Dst.Width - X; } clip.Bottom = Height; if (clip.Bottom > Dst.Height - Y) { clip.Bottom = Dst.Height - Y; } var src = Src; var pn = new PixelNavigator(Dst); pn.GoTo(X + clip.Left, Y); var maskbit = ScummHelper.RevBitMask((X + clip.Left) & 7); PixelNavigator maskPtr = new PixelNavigator(); // Mask against any additionally imposed mask if (MaskPtr.HasValue) { maskPtr = MaskPtr.Value; maskPtr.GoTo((X + clip.Left) / 8, Y); } var scalingYPtr = 0; // Setup vertical scaling if (ScaleY != 255) { var scaleBottom = SetupBompScale(bomp_scaling_y, Height, ScaleY); skip_y_new = bomp_scaling_y[scalingYPtr++]; skip_y_bits = 0x80; if (clip.Bottom > scaleBottom) { clip.Bottom = scaleBottom; } } // Setup horizontal scaling if (ScaleX != 255) { var scaleRight = SetupBompScale(bomp_scaling_x, Width, ScaleX); if (clip.Right > scaleRight) { clip.Right = scaleRight; } } var width = clip.Right - clip.Left; if (width <= 0) return; int pos_y = 0; var line_buffer = new byte[1024]; byte tmp; using (var br = new BinaryReader(new MemoryStream(src))) { // Loop over all lines while (pos_y < clip.Bottom) { br.ReadUInt16(); // Decode a single (bomp encoded) line, reversed if we are in mirror mode if (Mirror) BompDecodeLineReverse(br, line_buffer, 0, Width); else // Decode a single (bomp encoded) line BompDecodeLine(br, line_buffer, 0, Width); // If vertical scaling is enabled, do it if (ScaleY != 255) { // A bit set means we should skip this line... tmp = (byte)(skip_y_new & skip_y_bits); // Advance the scale-skip bit mask, if it's 0, get the next scale-skip byte skip_y_bits /= 2; if (skip_y_bits == 0) { skip_y_bits = 0x80; skip_y_new = bomp_scaling_y[scalingYPtr++]; } // Skip the current line if the above check tells us to if (tmp != 0) continue; } // Perform horizontal scaling if (ScaleX != 255) { BompScaleFuncX(line_buffer, bomp_scaling_x, 0, 0x80, Width); } // The first clip.top lines are to be clipped, i.e. not drawn if (clip.Top > 0) { clip.Top--; } else { // Replace the parts of the line which are masked with the transparency color if (MaskPtr.HasValue) BompApplyMask(line_buffer, clip.Left, maskPtr, (byte)maskbit, width, 255); // Apply custom color map, if available if (ActorPalette != null) BompApplyActorPalette(ActorPalette, line_buffer, clip.Left, width); // Finally, draw the decoded, scaled, masked and recolored line onto // the target surface, using the specified shadow mode BompApplyShadow(ShadowMode, ShadowPalette, line_buffer, clip.Left, pn, width, 255); } // Advance to the next line pos_y++; if (MaskPtr.HasValue) { maskPtr.OffsetY(1); } pn.OffsetY(1); } } }
protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip) { var ptr = img.Data; // // Since V3, all graphics data was encoded in strips, which is very efficient // for redrawing only parts of the screen. However, V2 is different: here // the whole graphics are encoded as one big chunk. That makes it rather // difficult to draw only parts of a room/object. We handle the V2 graphics // differently from all other (newer) graphic formats for this reason. // var table = (_objectMode ? null : _roomStrips); int left = (stripnr * 8); int right = left + (numstrip * 8); PixelNavigator navDst; var srcOffset = 0; byte color, data = 0; int run; bool dither = false; byte[] dither_table = new byte[128]; var ditherOffset = 0; int theX, theY, maxX; var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0]; navDst = new PixelNavigator(surface); navDst.GoTo(p.X * 8, p.Y); var mask_ptr = GetMaskBuffer(p.X, p.Y, 1); if (table != null) { run = table.run[stripnr]; color = (byte)table.color[stripnr]; srcOffset = table.offsets[stripnr]; theX = left; maxX = right; } else { run = 1; color = 0; srcOffset = 0; theX = 0; maxX = width; } // Decode and draw the image data. Debug.Assert(height <= 128); for (; theX < maxX; theX++) { ditherOffset = 0; for (theY = 0; theY < height; theY++) { if (--run == 0) { data = ptr[srcOffset++]; if ((data & 0x80) != 0) { run = data & 0x7f; dither = true; } else { run = data >> 4; dither = false; } color = RoomPalette[data & 0x0f]; if (run == 0) { run = ptr[srcOffset++]; } } if (!dither) { dither_table[ditherOffset] = color; } if (left <= theX && theX < right) { navDst.Write(dither_table[ditherOffset++]); navDst.OffsetY(1); } } if (left <= theX && theX < right) { navDst.Offset(1, -height); } } // Draw mask (zplane) data theY = 0; if (table != null) { srcOffset = table.zoffsets[stripnr]; run = table.zrun[stripnr]; theX = left; } else { run = ptr[srcOffset++]; theX = 0; } while (theX < right) { byte runFlag = (byte)(run & 0x80); if (runFlag != 0) { run &= 0x7f; data = ptr[srcOffset++]; } do { if (runFlag == 0) { data = ptr[srcOffset++]; } if (left <= theX) { mask_ptr.Write(data); mask_ptr.OffsetY(1); } theY++; if (theY >= height) { if (left <= theX) { mask_ptr.Offset(1, -height); } theY = 0; theX += 8; if (theX >= right) { break; } } } while ((--run) != 0); run = ptr[srcOffset++]; } }
void DrawStripV1Mask(PixelNavigator navDst, int stripnr, int width, int height) { int maskIdx; height /= 8; width /= 8; for (var y = 0; y < height; y++) { if (_objectMode) maskIdx = objectMap[(y + 2 * height) * width + stripnr] * 8; else maskIdx = _v1.MaskMap[y + stripnr * height] * 8; for (var i = 0; i < 8; i++) { byte c = _v1.MaskChar[maskIdx + i]; // V1/V0 masks are inverted compared to what ScummVM expects navDst.Write((byte)(c ^ 0xFF)); navDst.OffsetY(1); } } }
public static void Fill(Surface surface, Rect r, int color) { r = new Rect(r.Left, r.Top, r.Right, r.Bottom); r.Clip(surface.Width, surface.Height); if (!r.IsValid) { return; } int width = r.Width; int lineLen = width; int height = r.Height; bool useMemset = true; var bpp = Surface.GetBytesPerPixel(surface.PixelFormat); if (bpp == 2) { lineLen *= 2; if ((ushort)color != ((color & 0xff) | (color & 0xff) << 8)) { useMemset = false; } } else if (bpp == 4) { useMemset = false; } else if (bpp != 1) { throw new InvalidOperationException("Surface::fillRect: bytesPerPixel must be 1, 2, or 4"); } if (useMemset) { var pn = new PixelNavigator(surface); pn.GoTo(r.Left, r.Top); for (int i = 0; i < height; i++) { pn.Set((byte)color, lineLen); pn.OffsetY(1); } } else { if (bpp == 2) { var pn = new PixelNavigator(surface); pn.GoTo(r.Left, r.Top); for (int i = 0; i < height; i++) { pn.Set((ushort)color, lineLen); pn.OffsetX(surface.Width); } } else { var pn = new PixelNavigator(surface); pn.GoTo(r.Left, r.Top); for (int i = 0; i < height; i++) { pn.Set((uint)color, lineLen); pn.OffsetX(surface.Width / 2); } } } }
public static void Fill(Surface surface, Rect r, int color) { r = new Rect(r.Left, r.Top, r.Right, r.Bottom); r.Clip(surface.Width, surface.Height); if (!r.IsValid) return; int width = r.Width; int lineLen = width; int height = r.Height; bool useMemset = true; var bpp = Surface.GetBytesPerPixel(surface.PixelFormat); if (bpp == 2) { lineLen *= 2; if ((ushort)color != ((color & 0xff) | (color & 0xff) << 8)) useMemset = false; } else if (bpp == 4) { useMemset = false; } else if (bpp != 1) { throw new InvalidOperationException("Surface::fillRect: bytesPerPixel must be 1, 2, or 4"); } if (useMemset) { var pn = new PixelNavigator(surface); pn.GoTo(r.Left, r.Top); for (int i = 0; i < height; i++) { pn.Set((byte)color, lineLen); pn.OffsetY(1); } } else { if (bpp == 2) { var pn = new PixelNavigator(surface); pn.GoTo(r.Left, r.Top); for (int i = 0; i < height; i++) { pn.Set((ushort)color, lineLen); pn.OffsetX(surface.Width); } } else { var pn = new PixelNavigator(surface); pn.GoTo(r.Left, r.Top); for (int i = 0; i < height; i++) { pn.Set((uint)color, lineLen); pn.OffsetX(surface.Width / 2); } } } }
void Proc3Amiga(Codec1 v1) { byte len; int color; bool masked; var mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); var dst = new PixelNavigator(v1.DestPtr); byte height = (byte)_height; byte width = (byte)_width; _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin); var maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); var y = v1.Y; var oldXpos = v1.X; var oldScaleIndexX = _scaleIndexX; // Indy4 Amiga always uses the room map to match colors to the currently // setup palette in the actor code in the original, thus we need to do this // mapping over here too. var amigaMap = (_vm.Game.Platform == Platform.Amiga && _vm.Game.GameId == GameId.Indy4) ? _vm.Gdi.RoomPalette : null; do { len = _loaded.CostumeReader.ReadByte(); color = len >> v1.Shr; len &= v1.Mask; if (len == 0) { len = _loaded.CostumeReader.ReadByte(); } do { if (ScaleY == 255 || v1.Scaletable[_scaleIndexY] < ScaleY) { masked = (y < 0 || y >= _h) || (v1.X < 0 || v1.X >= _w) || ((mask.Read() & maskbit) != 0); if (color != 0 && !masked) { byte pcolor; if (amigaMap != null) { pcolor = amigaMap[_palette[color]]; } else { pcolor = (byte)_palette[color]; } dst.Write(pcolor); } if (ScaleX == 255 || v1.Scaletable[_scaleIndexX] < ScaleX) { v1.X += v1.ScaleXStep; dst.OffsetX(v1.ScaleXStep); maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); } _scaleIndexX += (byte)v1.ScaleXStep; mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); } if (--width == 0) { if (--height == 0) { return; } if (y >= _h) { return; } if (v1.X != oldXpos) { dst.Offset(-(v1.X - oldXpos), 1); mask = new PixelNavigator(v1.MaskPtr); mask.OffsetY(1); v1.MaskPtr = mask; mask.OffsetX(oldXpos / 8); maskbit = (byte)ScummHelper.RevBitMask(oldXpos & 7); y++; } width = (byte)_width; v1.X = oldXpos; _scaleIndexX = oldScaleIndexX; _scaleIndexY++; } } while (--len != 0); } while (true); }
protected override void DrawBitsN(Surface s, PixelNavigator dst, IList<byte> src, int srcPos, byte bpp, int drawTop, int width, int height) { // if (_sjisCurChar) // { // assert(Vm._cjkFont); // Vm._cjkFont.drawChar(Vm._textSurface, _sjisCurChar, _left * Vm._textSurfaceMultiplier, (_top - Vm._screenTop) * Vm._textSurfaceMultiplier, Vm._townsCharsetColorMap[1], _shadowColor); // return; // } bool scale2x = (Vm.TextSurfaceMultiplier == 2); dst = new PixelNavigator(Vm.TextSurface); dst.GoTo(Left * Vm.TextSurfaceMultiplier, (Top - Vm.ScreenTop) * Vm.TextSurfaceMultiplier); int y, x; int color; byte numbits, bits; int pitch = Vm.TextSurface.Pitch - width; Debug.Assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8); bits = src[srcPos++]; numbits = 8; var cmap = Vm.CharsetColorMap; var dst2 = new PixelNavigator(dst); if (Vm.Game.Platform == Platform.FMTowns) cmap = Vm.TownsCharsetColorMap; if (scale2x) { dst2.OffsetY(1); pitch <<= 1; } for (y = 0; y < height && y + drawTop < Vm.TextSurface.Height; y++) { for (x = 0; x < width; x++) { color = (bits >> (8 - bpp)) & 0xFF; if (color != 0 && y + drawTop >= 0) { dst.Write(cmap[color]); if (scale2x) { dst.Write(1, dst.Read()); dst2.Write(dst.Read()); dst2.Write(1, dst.Read()); } } dst.OffsetX(1); if (scale2x) { dst.OffsetX(1); dst2.OffsetX(2); } bits <<= bpp; numbits -= bpp; if (numbits == 0) { bits = src[srcPos++]; numbits = 8; } } dst.OffsetX(pitch / dst.BytesByPixel); dst2.OffsetX(pitch / dst2.BytesByPixel); } }
static bool NextRow(ref PixelNavigator navDst, ref int x, ref int y, int height) { navDst.OffsetY(1); if (--y == 0) { if ((--x) == 0) return false; navDst.Offset(1, -height); y = height; } return true; }
protected override void DrawBitsN(Surface s, PixelNavigator dst, IList <byte> src, int srcPos, byte bpp, int drawTop, int width, int height) { // if (_sjisCurChar) // { // assert(Vm._cjkFont); // Vm._cjkFont.drawChar(Vm._textSurface, _sjisCurChar, _left * Vm._textSurfaceMultiplier, (_top - Vm._screenTop) * Vm._textSurfaceMultiplier, Vm._townsCharsetColorMap[1], _shadowColor); // return; // } bool scale2x = (Vm.TextSurfaceMultiplier == 2); dst = new PixelNavigator(Vm.TextSurface); dst.GoTo(Left * Vm.TextSurfaceMultiplier, (Top - Vm.ScreenTop) * Vm.TextSurfaceMultiplier); int y, x; int color; byte numbits, bits; int pitch = Vm.TextSurface.Pitch - width; Debug.Assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8); bits = src[srcPos++]; numbits = 8; var cmap = Vm.CharsetColorMap; var dst2 = new PixelNavigator(dst); if (Vm.Game.Platform == Platform.FMTowns) { cmap = Vm.TownsCharsetColorMap; } if (scale2x) { dst2.OffsetY(1); pitch <<= 1; } for (y = 0; y < height && y + drawTop < Vm.TextSurface.Height; y++) { for (x = 0; x < width; x++) { color = (bits >> (8 - bpp)) & 0xFF; if (color != 0 && y + drawTop >= 0) { dst.Write(cmap[color]); if (scale2x) { dst.Write(1, dst.Read()); dst2.Write(dst.Read()); dst2.Write(1, dst.Read()); } } dst.OffsetX(1); if (scale2x) { dst.OffsetX(1); dst2.OffsetX(2); } bits <<= bpp; numbits -= bpp; if (numbits == 0) { bits = src[srcPos++]; numbits = 8; } } dst.OffsetX(pitch / dst.BytesByPixel); dst2.OffsetX(pitch / dst2.BytesByPixel); } }
void UnkDecode11(PixelNavigator navDst, BinaryReader src, int height) { int i; int buffer = 0, mask = 128; int inc = 1; int color = src.ReadByte(); int x = 8; do { int h = height; do { navDst.Write(RoomPalette[color]); navDst.OffsetY(1); for (i = 0; i < 3; i++) { if (!ReadBit256(src, ref mask, ref buffer)) break; } switch (i) { case 1: inc = -inc; color -= inc; break; case 2: color -= inc; break; case 3: inc = 1; color = ReadNBits(src, 8, ref mask, ref buffer); break; } } while ((--h) != 0); navDst.Offset(1, -height); } while ((--x) != 0); }
void Proc3Amiga(Codec1 v1) { byte len; int color; bool masked; var mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); var dst = new PixelNavigator(v1.DestPtr); byte height = (byte)_height; byte width = (byte)_width; _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin); var maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); var y = v1.Y; var oldXpos = v1.X; var oldScaleIndexX = _scaleIndexX; // Indy4 Amiga always uses the room map to match colors to the currently // setup palette in the actor code in the original, thus we need to do this // mapping over here too. var amigaMap = (_vm.Game.Platform == Platform.Amiga && _vm.Game.GameId == GameId.Indy4) ? _vm.Gdi.RoomPalette : null; do { len = _loaded.CostumeReader.ReadByte(); color = len >> v1.Shr; len &= v1.Mask; if (len == 0) len = _loaded.CostumeReader.ReadByte(); do { if (ScaleY == 255 || v1.Scaletable[_scaleIndexY] < ScaleY) { masked = (y < 0 || y >= _h) || (v1.X < 0 || v1.X >= _w) || ((mask.Read() & maskbit) != 0); if (color != 0 && !masked) { byte pcolor; if (amigaMap != null) pcolor = amigaMap[_palette[color]]; else pcolor = (byte)_palette[color]; dst.Write(pcolor); } if (ScaleX == 255 || v1.Scaletable[_scaleIndexX] < ScaleX) { v1.X += v1.ScaleXStep; dst.OffsetX(v1.ScaleXStep); maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7); } _scaleIndexX += (byte)v1.ScaleXStep; mask = new PixelNavigator(v1.MaskPtr); mask.OffsetX(v1.X / 8); } if (--width == 0) { if (--height == 0) return; if (y >= _h) return; if (v1.X != oldXpos) { dst.Offset(-(v1.X - oldXpos), 1); mask = new PixelNavigator(v1.MaskPtr); mask.OffsetY(1); v1.MaskPtr = mask; mask.OffsetX(oldXpos / 8); maskbit = (byte)ScummHelper.RevBitMask(oldXpos & 7); y++; } width = (byte)_width; v1.X = oldXpos; _scaleIndexX = oldScaleIndexX; _scaleIndexY++; } } while (--len != 0); } while (true); }
protected void TownsDrawStripToScreen(VirtScreen vs, int dstX, int dstY, int srcX, int srcY, int width, int height) { if (width <= 0 || height <= 0) return; int m = _textSurfaceMultiplier; var src1 = new PixelNavigator(vs.Surfaces[0]); src1.GoTo(vs.XStart + srcX, srcY); var src2 = new PixelNavigator(_textSurface); src2.GoTo(srcX * m, (srcY + vs.TopLine - ScreenTop) * m); var dst1 = new PixelNavigator(_townsScreen.GetLayerPixels(0, dstX, dstY).Value); var dst2 = new PixelNavigator(_townsScreen.GetLayerPixels(1, dstX * m, dstY * m).Value); int dp1 = _townsScreen.GetLayerPitch(0) - width * _townsScreen.GetLayerBpp(0); int dp2 = _townsScreen.GetLayerPitch(1) - width * m * _townsScreen.GetLayerBpp(1); int sp1 = vs.Pitch - (width * Surface.GetBytesPerPixel(vs.PixelFormat)); int sp2 = _textSurface.Pitch - width * m; if (vs == MainVirtScreen || Game.GameId == GameId.Indy3 || Game.GameId == GameId.Zak) { for (int h = 0; h < height; ++h) { if (Surface.GetBytesPerPixel(_gfxManager.PixelFormat) == 2) { for (int w = 0; w < width; ++w) { dst1.WriteUInt16(_16BitPalette[src1.Read()]); src1.OffsetX(1); dst1.OffsetX(1); } src1.OffsetX(sp1 / src1.BytesByPixel); dst1.OffsetX(dp1 / dst1.BytesByPixel); } else { for (int i = 0; i < width; i++) { dst1.Write(src1.Read()); dst1.OffsetX(1); src1.OffsetX(1); } } for (int sH = 0; sH < m; ++sH) { for (int i = 0; i < width * m; i++) { dst2.Write(src2.Read()); src2.OffsetX(1); dst2.OffsetX(1); } src2.OffsetX(_textSurface.Width - (width * m)); dst2.OffsetX(dst2.Width - (width * m)); } } } else { dst1 = new PixelNavigator(dst2); for (int h = 0; h < height; ++h) { for (int w = 0; w < width; ++w) { var t = (src1.Read()) & 0x0f; src1.OffsetX(1); for (int i = 0; i < m; i++) { dst1.Write((byte)((t << 4) | t)); dst1.OffsetX(1); } } dst1 = new PixelNavigator(dst2); var src3 = new PixelNavigator(src2); if (m == 2) { dst2.OffsetY(1); src3.OffsetY(1); } for (int w = 0; w < width * m; ++w) { dst2.Write((byte)(src3.Read() | dst1.Read() & _townsLayer2Mask[src3.Read()])); dst2.OffsetX(1); dst1.Write((byte)(src2.Read() | dst1.Read() & _townsLayer2Mask[src2.Read()])); src2.OffsetX(1); src3.OffsetX(1); dst1.OffsetX(1); } src1.OffsetX(sp1 / src1.BytesByPixel); src2 = new PixelNavigator(src3); src2.OffsetX(sp2 / src2.BytesByPixel); dst1 = new PixelNavigator(dst2); dst1.OffsetX(dp2 / dst1.BytesByPixel); dst2.OffsetX(dp2 / dst2.BytesByPixel); } } _townsScreen.AddDirtyRect(dstX * m, dstY * m, width * m, height * m); }
protected override void DrawBits1(Surface dest, int x, int y, BinaryReader src, int drawTop, int width, int height) { if (_sjisCurChar != 0) { // Debug.Assert(Vm._cjkFont); // Vm._cjkFont.drawChar(dest, _sjisCurChar, x, y, _color, _shadowColor); return; } bool scale2x = ((dest == Vm.TextSurface) && (Vm.TextSurfaceMultiplier == 2) /*&& !(_sjisCurChar >= 256 && Vm.UseCJKMode)*/); byte bits = 0; var col = Color; var bpp = Surface.GetBytesPerPixel(dest.PixelFormat); int pitch = dest.Pitch - width * bpp; var dst = new PixelNavigator(dest); dst.GoTo(x, y); var dst2 = new PixelNavigator(dst); dst2.OffsetY(1); var dst3 = new PixelNavigator(dst2); var dst4 = new PixelNavigator(dst2); if (scale2x) { dst3.OffsetY(1); dst4.OffsetY(1); pitch <<= 1; } for (y = 0; y < height && y + drawTop < dest.Height; y++) { for (x = 0; x < width; x++) { if ((x % 8) == 0) bits = src.ReadByte(); if (((bits & ScummHelper.RevBitMask(x % 8)) != 0) && y + drawTop >= 0) { if (bpp == 2) { if (_enableShadow) { dst.WriteUInt16(2, Vm._16BitPalette[_shadowColor]); dst.WriteUInt16(2 + dest.Pitch, Vm._16BitPalette[_shadowColor]); } dst.WriteUInt16(Vm._16BitPalette[Color]); } else { if (_enableShadow) { if (scale2x) { dst.Write(2, _shadowColor); dst.Write(3, _shadowColor); dst2.Write(2, _shadowColor); dst2.Write(3, _shadowColor); dst3.Write(0, _shadowColor); dst3.Write(1, _shadowColor); dst4.Write(0, _shadowColor); dst4.Write(0, _shadowColor); } else { dst2.Write(_shadowColor); dst.Write(1, _shadowColor); } } dst.Write(col); if (scale2x) { dst.Write(1, col); dst2.Write(0, col); dst2.Write(1, col); } } } dst.OffsetX(1); dst2.OffsetX(1); if (scale2x) { dst.OffsetX(1); dst2.OffsetX(1); dst3.OffsetX(1); dst4.OffsetX(1); } } dst.OffsetX(pitch / dst.BytesByPixel); dst2.OffsetX(pitch / dst2.BytesByPixel); dst3.OffsetX(pitch / dst3.BytesByPixel); dst4.OffsetX(pitch / dst4.BytesByPixel); } }
public void DrawBomp() { Rect clip; byte skip_y_bits = 0x80; byte skip_y_new = 0; byte[] bomp_scaling_x = new byte[64]; byte[] bomp_scaling_y = new byte[64]; if (X < 0) { clip.Left = -X; } else { clip.Left = 0; } if (Y < 0) { clip.Top = -Y; } else { clip.Top = 0; } clip.Right = Width; if (clip.Right > Dst.Width - X) { clip.Right = Dst.Width - X; } clip.Bottom = Height; if (clip.Bottom > Dst.Height - Y) { clip.Bottom = Dst.Height - Y; } var src = Src; var pn = new PixelNavigator(Dst); pn.GoTo(X + clip.Left, Y); var maskbit = ScummHelper.RevBitMask((X + clip.Left) & 7); PixelNavigator maskPtr = new PixelNavigator(); // Mask against any additionally imposed mask if (MaskPtr.HasValue) { maskPtr = MaskPtr.Value; maskPtr.GoTo((X + clip.Left) / 8, Y); } var scalingYPtr = 0; // Setup vertical scaling if (ScaleY != 255) { var scaleBottom = SetupBompScale(bomp_scaling_y, Height, ScaleY); skip_y_new = bomp_scaling_y[scalingYPtr++]; skip_y_bits = 0x80; if (clip.Bottom > scaleBottom) { clip.Bottom = scaleBottom; } } // Setup horizontal scaling if (ScaleX != 255) { var scaleRight = SetupBompScale(bomp_scaling_x, Width, ScaleX); if (clip.Right > scaleRight) { clip.Right = scaleRight; } } var width = clip.Right - clip.Left; if (width <= 0) { return; } int pos_y = 0; var line_buffer = new byte[1024]; byte tmp; using (var br = new BinaryReader(new MemoryStream(src))) { // Loop over all lines while (pos_y < clip.Bottom) { br.ReadUInt16(); // Decode a single (bomp encoded) line, reversed if we are in mirror mode if (Mirror) { BompDecodeLineReverse(br, line_buffer, 0, Width); } else { // Decode a single (bomp encoded) line BompDecodeLine(br, line_buffer, 0, Width); } // If vertical scaling is enabled, do it if (ScaleY != 255) { // A bit set means we should skip this line... tmp = (byte)(skip_y_new & skip_y_bits); // Advance the scale-skip bit mask, if it's 0, get the next scale-skip byte skip_y_bits /= 2; if (skip_y_bits == 0) { skip_y_bits = 0x80; skip_y_new = bomp_scaling_y[scalingYPtr++]; } // Skip the current line if the above check tells us to if (tmp != 0) { continue; } } // Perform horizontal scaling if (ScaleX != 255) { BompScaleFuncX(line_buffer, bomp_scaling_x, 0, 0x80, Width); } // The first clip.top lines are to be clipped, i.e. not drawn if (clip.Top > 0) { clip.Top--; } else { // Replace the parts of the line which are masked with the transparency color if (MaskPtr.HasValue) { BompApplyMask(line_buffer, clip.Left, maskPtr, (byte)maskbit, width, 255); } // Apply custom color map, if available if (ActorPalette != null) { BompApplyActorPalette(ActorPalette, line_buffer, clip.Left, width); } // Finally, draw the decoded, scaled, masked and recolored line onto // the target surface, using the specified shadow mode BompApplyShadow(ShadowMode, ShadowPalette, line_buffer, clip.Left, pn, width, 255); } // Advance to the next line pos_y++; if (MaskPtr.HasValue) { maskPtr.OffsetY(1); } pn.OffsetY(1); } } }
protected virtual void DrawBits1(Surface surface, int x, int y, BinaryReader src, int drawTop, int width, int height) { var dst = new PixelNavigator(surface); dst.GoTo(x, y); byte bits = 0; byte col = Color; //int pitch = surface.Pitch - width * surface.BytesPerPixel; var dst2 = new PixelNavigator(dst); dst2.OffsetY(1); for (y = 0; y < height && y + drawTop < surface.Height; y++) { for (x = 0; x < width; x++) { if ((x % 8) == 0) bits = src.ReadByte(); if ((bits & ScummHelper.RevBitMask(x % 8)) != 0 && y + drawTop >= 0) { if (_shadowMode) { dst.OffsetX(1); dst.Write(_shadowColor); dst2.Write(_shadowColor); dst2.OffsetX(1); dst2.Write(_shadowColor); } dst.Write(col); } dst.OffsetX(1); dst2.OffsetX(1); } dst.OffsetX(surface.Width - width); dst2.OffsetX(surface.Width - width); } }