unsafe void ReadStaticTexture(int index, out Texture2DInfo texture) { texture = null; // get a reader inside Art.Mul var r = _fileIndex.Seek(index, out int length, out int extra, out bool patched); if (r == null) { return; } r.ReadInt(); // don't need this, see Art.mul file format. // get the dimensions of the texture var width = r.ReadShort(); var height = r.ReadShort(); if (width <= 0 || height <= 0) { return; } // read the texture data! var lookups = r.ReadUShorts(height); var fileData = r.ReadUShorts(length - lookups.Length * 2 - 8); Metrics.ReportDataRead(sizeof(ushort) * (fileData.Length + lookups.Length + 2)); var pixels = new byte[width * height * 4]; fixed(byte *pData = pixels) { uint *dataRef = (uint *)pData; int i; for (int y = 0; y < height; y++, dataRef += width) { i = lookups[y]; uint *start = dataRef; int count, offset; while (((offset = fileData[i++]) + (count = fileData[i++])) != 0) { start += offset; uint *end = start + count; while (start < end) { uint color = ConvertUtils.FromBGR555(fileData[i++]); * start++ = color; } } } } texture = new Texture2DInfo(width, height, TextureFormat.BGRA32, false, pixels); _staticPicking.Set(index, width, height, pixels); return; }
public unsafe Texture2DInfo GetGumpTexture(int textureID, bool replaceMask080808 = false) { if (textureID < 0) { return(null); } if (_textureCache[textureID] == null) { var reader = _fileIndex.Seek(textureID, out int length, out int extra, out bool patched); if (reader == null) { return(null); } var width = (extra >> 16) & 0xFFFF; var height = extra & 0xFFFF; if (width == 0 || height == 0) { return(null); } var shortsToRead = length - (height * 2); if (reader.Stream.Length - reader.Position < (shortsToRead * 2)) { Utils.Error($"Could not read gump {textureID:X4}: not enough data. Gump texture file truncated?"); return(null); } var lookups = reader.ReadInts(height); var metrics_dataread_start = (int)reader.Position; var fileData = reader.ReadUShorts(shortsToRead); var pixels = new byte[width * height * 4]; fixed(byte *line = &pixels[0]) fixed(ushort *data = &fileData[0]) for (int y = 0; y < height; ++y) { ushort *dataRef = data + (lookups[y] - height) * 2; uint * cur = (uint *)line + (y * width); uint * end = cur + width; while (cur < end) { uint color = ConvertUtils.FromBGR555(*dataRef++, false); uint *next = cur + *dataRef++; if (color == 0) { cur = next; } else { color |= 0xFF000000; while (cur < next) { *cur++ = color; } } } } Metrics.ReportDataRead(length); //if (replaceMask080808) // for (var i = 0; i < pixels.Length; i++) // if (pixels[i] == 0x8421) // pixels[i] = 0xFC1F; var texture = new Texture2DInfo(width, height, TextureFormat.BGRA32, false, pixels); //: SurfaceFormat.Bgra5551 _textureCache[textureID] = texture; _picking.Set(textureID, width, height, pixels); } return(_textureCache[textureID]); }
public unsafe AnimationFrame(int uniqueAnimationIndex, object graphics, ushort[] palette, BinaryFileReader reader, SittingTransformation sitting) { _animationIndex = uniqueAnimationIndex; int xCenter = reader.ReadShort(); int yCenter = reader.ReadShort(); int width = reader.ReadUShort(); int height = reader.ReadUShort(); // Fix for animations with no pixels. if (width == 0 || height == 0) { Texture = null; return; } if (sitting == SittingTransformation.StandSouth) { xCenter += 8; width += 8; height += 4; } var data = new byte[width * height * 4]; // for sitting: // somewhere around the waist of a typical mobile animation, we take twelve rows of pixels, // discard every third, and shift every remaining row (total of eight) one pixel to the left // or right (depending on orientation), for a total skew of eight pixels. fixed(byte *pData = data) { ushort *dataRef = (ushort *)pData; var dataRead = 0; int header; while ((header = reader.ReadInt()) != 0x7FFF7FFF) { header ^= DoubleXor; var x = ((header >> 22) & 0x3FF) + xCenter - 0x200; var y = ((header >> 12) & 0x3FF) + yCenter + height - 0x200; if (sitting == SittingTransformation.StandSouth) { const int skew_start = -17; const int skew_end = skew_start - 16; var iy = y - height - yCenter; if (iy > skew_start) { // pixels below the skew x -= 8; y -= 4; } else if (iy > skew_end) { // pixels within the skew if ((iy - skew_end) % 4 == 0) { reader.Position += (header & 0xFFF); continue; } x -= (iy - skew_end) / 2; y -= (iy - skew_end) / 4; } } ushort *cur = dataRef + y * width + x; ushort *end = cur + (header & 0xFFF); var filecounter = 0; var filedata = reader.ReadBytes(header & 0xFFF); while (cur < end) { *cur++ = palette[filedata[filecounter++]]; } dataRead += header & 0xFFF; } Metrics.ReportDataRead(dataRead); } Center = new Vector2Int(xCenter, yCenter); Texture = new Texture2DInfo(width, height, TextureFormat.BGRA32, false, data); _picking.Set(_animationIndex, width, height, data); }