internal static Bitmap LoadRawBitmap(Stream inputStream) { using (var r = new BinaryFileReader(inputStream)) { var header = r.ReadT <BitmapHeader>(0x10); var frameCount = header.FrameCount; var frameOffsets = r.ReadTArray <BitmapFrameOffset>(frameCount * 0x08, frameCount); var frames = new Texture2DInfo[frameCount]; for (var i = 0; i < frameCount; i++) { r.Position = frameOffsets[i].Offset; var frame = r.ReadT <BitmapFrame>(0x14); var frameHeight = (int)frame.height; var sizeOfFrame = 0x14 + frameHeight * 0x04; var frameDataSize = (int)(frameHeight * frame.width); var bitsPerPixel = (int)((frameOffsets[i].Size - sizeOfFrame) / frameDataSize); var offsets = r.ReadTArray <uint>(frameHeight * 0x04, frameHeight); // Offset to the data for each row relative to the start of the resource. if (offsets[0] == 0xCDCDCDCD) //: unknownFrame { continue; } r.Position = frameOffsets[i].Offset + offsets[0]; var rawData = r.ReadBytes(frameDataSize * bitsPerPixel); frames[i] = bitsPerPixel == 1 ? new Texture2DInfo((int)frame.width, (int)frame.height, UnityEngine.TextureFormat.RGBA32, false, rawData).From8BitPallet(GetGlobal8BitPallet(), UnityEngine.TextureFormat.RGBA32) : new Texture2DInfo((int)frame.width, (int)frame.height, UnityEngine.TextureFormat.RGBA32, false, rawData).FromABGR555(); } return(new Bitmap { Header = header, Frames = frames, }); } }
public VTEXField(BinaryFileReader r, int dataSize, GameFormat format) { if (format == GameFormat.TES3) { TextureIndicesT3 = r.ReadTArray <ushort>(dataSize, dataSize >> 1); TextureIndicesT4 = null; return; } TextureIndicesT3 = null; TextureIndicesT4 = r.ReadTArray <uint>(dataSize, dataSize >> 2); }
public sbyte[] HeightData; // HeightData public VHGTField(BinaryFileReader r, int dataSize) { ReferenceHeight = r.ReadSingle(); var count = dataSize - 4 - 3; HeightData = r.ReadTArray <sbyte>(count, count); //HeightData = new sbyte[count]; //for (var i = 0; i < HeightData.Length; i++) HeightData[i] = r.ReadSByte(); r.Skip(3); // Unused }
public RNAMField(BinaryFileReader r, int dataSize) { GridX = r.ReadInt16(); GridY = r.ReadInt16(); var referenceCount = r.ReadUInt32(); var referenceSize = dataSize - 8; Assert(referenceSize >> 3 == referenceCount); GridReferences = r.ReadTArray <Reference>(referenceSize, referenceSize >> 3); }
public static void ReadNonfixed(BinaryFileReader r, Header header, RecordGroup group) { var world = int.Parse(header.Label); // header r.Skip(4 * 5); var width = r.ReadUInt32(); var height = r.ReadUInt32(); r.Skip(4); var indexSize = (int)(width * height); var indices = r.ReadTArray <uint>(indexSize * 4, indexSize); r.Skip(4); // pages var page = r.ReadT <Page>(28); r.Skip(4 * 7); var entities = new Entity[page.EntityCount]; for (var i = 0; i < entities.Length; i++) { entities[i] = r.ReadT <Entity>(64); } }
public Vector3Int GridId; // => new Vector3Int(INTV.CellX, INTV.CellY, 0); public override bool CreateField(BinaryFileReader r, GameFormat format, string type, int dataSize) { switch (type) { case "DATA": DATA = r.ReadT <IN32Field>(dataSize); return(true); case "VNML": VNML = new VNMLField(r, dataSize); return(true); case "VHGT": VHGT = new VHGTField(r, dataSize); return(true); case "VCLR": VCLR = new VNMLField(r, dataSize); return(true); case "VTEX": VTEX = new VTEXField(r, dataSize, format); return(true); // TES3 case "INTV": INTV = r.ReadT <CORDField>(dataSize); return(true); case "WNAM": WNAM = new WNAMField(r, dataSize); return(true); // TES4 case "BTXT": var btxt = r.ReadT <BTXTField>(dataSize); BTXTs[btxt.Quadrant] = btxt; return(true); case "ATXT": if (ATXTs == null) { ATXTs = new ATXTGroup[4]; } var atxt = r.ReadT <BTXTField>(dataSize); _lastATXT = ATXTs[atxt.Quadrant] = new ATXTGroup { ATXT = atxt }; return(true); case "VTXT": _lastATXT.VTXTs = r.ReadTArray <VTXTField>(dataSize, dataSize >> 3); return(true); default: return(false); } }
public static void ReadFixed(BinaryFileReader r, Header header, RecordGroup group) { var world = int.Parse(header.Label); var head = r.ReadT <Head>(32); var indexSize = (int)(head.Width * head.Height); // These are either 0 or a number in the form nnnn001h, where nnnn is a number that may be a page index. This may be in [x + y * width] order, but that doesn't seem to corroborate with where objects are located in the maps var indices = r.ReadTArray <uint>(indexSize * 4, indexSize); const int POINT_STRIDE = 32; var pages = new Page[head.PageSize / 4096]; for (var i = 0; i < pages.Length; i++) { var page = pages[i] = new Page(); r.Skip(4 * 0x3); page.BaseX = r.ReadUInt32(); page.BaseY = r.ReadUInt32(); r.Skip(4 * 0x13); page.FixedObjects = r.ReadTArray <FixedObject>(0x18 * 166, 166); r.Skip(0x10); } var data = new Data { Width = head.Width, Height = head.Height, Indices = indices, Pages = pages, }; group.Tag = data; // transform const int CELL_STRIDE = 64; var records = new List <Record>(); for (var y = 0; y < data.Height; y += 2) { for (var x = 0; x < data.Width; x += 2) { //var vhgt = new ushort[CELL_STRIDE * CELL_STRIDE]; //var vtex = new ushort[CELL_STRIDE * CELL_STRIDE]; //var vtexf = new byte[CELL_STRIDE * CELL_STRIDE]; //for (var sy = 0; sy < 2; sy++) // for (var sx = 0; sx < 2; sx++) // { // var index = indices[x + sx + ((y + sy) * data.Width)]; // if (index >= chunks.Length) // continue; // var chunk = chunks[index]; // var offset = (sx * POINT_STRIDE) + (sy * POINT_STRIDE * CELL_STRIDE); // for (var i = 0; i < POINT_STRIDE; i++) // { // Buffer.BlockCopy(chunk.VHGT, i * POINT_STRIDE * 2, vhgt, offset + (i * CELL_STRIDE * 2), POINT_STRIDE * 2); // Buffer.BlockCopy(chunk.VTEX, i * POINT_STRIDE * 2, vtex, offset + (i * CELL_STRIDE * 2), POINT_STRIDE * 2); // Buffer.BlockCopy(chunk.VTEXF, i * POINT_STRIDE, vtexf, offset + (i * CELL_STRIDE), POINT_STRIDE); // } // } records.Add(new CELLRecord { GridId = new Vector3Int(x / 2, y / 2, world), }); } } // insert group.CELLsById = records.ToDictionary(x => ((CELLRecord)x).GridId, x => (CELLRecord)x); group.Records.AddRange(records); }
public Byte3[] Vertexs; // XYZ 8 bit floats public VNMLField(BinaryFileReader r, int dataSize) { Vertexs = r.ReadTArray <Byte3>(dataSize, dataSize / 3); //Vertexs = new Vector3Int8[dataSize / 3]; //for (var i = 0; i < Vertexs.Length; i++) Vertexs[i] = new Vector3Int8 { X = r.ReadByte(), Y = r.ReadByte(), Z = r.ReadByte() }; }
public static void ReadTerrain(BinaryFileReader r, Header header, RecordGroup group) { var world = int.Parse(header.Label); var data = new Data { Width = r.ReadUInt32(), Height = r.ReadUInt32(), Name = r.ReadASCIIString(0x80, ASCIIFormat.ZeroTerminated), WaterLevel = r.ReadUInt32(), WaveAmplitude = r.ReadUInt32(), Flags = r.ReadUInt32(), }; var chunkCount = (int)r.ReadUInt32(); var widthHeight = (int)(data.Width * data.Height); var indices = data.Indices = r.ReadTArray <ushort>(widthHeight << 1, widthHeight); var chunks = data.Chunks = new Chunk[chunkCount]; const int POINT_STRIDE = 16; for (var i = 0; i < chunks.Length; i++) { var points = r.ReadTArray <uint>(POINT_STRIDE * POINT_STRIDE * 4, POINT_STRIDE * POINT_STRIDE); chunks[i] = new Chunk { VHGT = points.Select(x => (ushort)(x & 0xFFF)).ToArray(), VTEXF = points.Select(x => (byte)((x >> 16) & 0x1F)).ToArray(), VTEX = points.Select(x => (ushort)((x >> 22) & 0x3FF)).ToArray(), //: sky, >> 21? }; } group.Tag = data; // transform //const int LAND_STRIDE = 64; //var records = new List<Record>(); //var VHGTs = new Dictionary<int, ushort[]>(); //for (var i = 0; i < POINT_STRIDE; i++) // VHGTs.Add(i, Enumerable.Repeat((ushort)(i * 10), POINT_STRIDE * POINT_STRIDE).ToArray()); //for (var y = 0; y < data.Height; y += 4) // for (var x = 0; x < data.Width; x += 4) // { // var vhgt = new ushort[LAND_STRIDE * LAND_STRIDE]; // var vtex = new ushort[LAND_STRIDE * LAND_STRIDE]; // var vtexf = new byte[LAND_STRIDE * LAND_STRIDE]; // for (var sy = 0; sy < 4; sy++) // for (var sx = 0; sx < 4; sx++) // { // var offset = ((sx * POINT_STRIDE) + (sy * POINT_STRIDE * LAND_STRIDE)) << 1; // for (var i = 0; i < POINT_STRIDE; i++) // { // Buffer.BlockCopy(VHGTs[i], i * POINT_STRIDE << 1, vhgt, offset + (i * LAND_STRIDE << 1), POINT_STRIDE << 1); // } // } // records.Add(new LANDRecord // { // VHGT = vhgt, // VTEX = vtex, // VTEXF = vtexf, // GridId = new Vector3Int(x / 4, y / 4, world), // }); // } // transform const int LAND_STRIDE = 64; var records = new List <Record>(); for (var y = 0; y < data.Height; y += 4) { for (var x = 0; x < data.Width; x += 4) { var vhgt = new ushort[LAND_STRIDE * LAND_STRIDE]; var vtex = new ushort[LAND_STRIDE * LAND_STRIDE]; var vtexf = new byte[LAND_STRIDE * LAND_STRIDE]; for (var sy = 0; sy < 4; sy++) { for (var sx = 0; sx < 4; sx++) { var index = indices[x + sx + ((y + sy) * data.Width)]; if (index >= chunks.Length) { continue; } var chunk = chunks[index]; var offset = ((sx * POINT_STRIDE) + (sy * POINT_STRIDE * LAND_STRIDE)) << 1; for (var i = 0; i < POINT_STRIDE; i++) { Buffer.BlockCopy(chunk.VHGT, i * POINT_STRIDE << 1, vhgt, offset + (i * LAND_STRIDE << 1), POINT_STRIDE << 1); Buffer.BlockCopy(chunk.VTEX, i * POINT_STRIDE << 1, vtex, offset + (i * LAND_STRIDE << 1), POINT_STRIDE << 1); //Buffer.BlockCopy(chunk.VTEXF, i * POINT_STRIDE, vtexf, offset + (i * LAND_STRIDE), POINT_STRIDE); } } } records.Add(new LANDRecord { VHGT = vhgt, VTEX = vtex, VTEXF = vtexf, GridId = new Vector3Int(x / 4, y / 4, world), }); } } // insert group.LANDsById = records.ToDictionary(x => ((LANDRecord)x).GridId, x => (LANDRecord)x); group.Records.AddRange(records); }