private static DWordTexture ConvertTexture(WordTexture t) { var ret = new DWordTexture(new uint[256][]); for (var y = 0; y < 256; y++) { ret.Pixels[y] = new uint[256]; for (var x = 0; x < 256; x++) { var color = t.Pixels[y][x]; uint val = 0; if ((color & 0x8000) != 0) { val = (uint)( ((color & 0x00007c00) >> 7) | (((color & 0x000003e0) >> 2) << 8) | ((color & 0x0000001f) << 3 << 16) | 0xff000000); } ret.Pixels[y][x] = val; } } return ret; }
public void GenTexAndPalettesIfEmpty() { if (EngineVersion == Engine.TR2) return; // TR2 already has 8-bit, 16-bit and 32-bit tex and palette if ((Texture16 ?? new WordTexture[0]).Length == 0) { // Generate 16-bit textures Texture16 = new WordTexture[Textures.Length]; for (var i = 0; i < Texture16.Length; i++) { Texture16[i] = new WordTexture(new ushort[256][]); for (var y = 0; y < 256; y++) { Texture16[i].Pixels[y] = new ushort[256]; for (var x = 0; x < 256; x++) { Texture16[i].Pixels[y][x] = new ByteColor(Textures[i].Pixels[y][x]).ToUInt16(); } } } } if (WriteGameVersion < TRGame.TR4 && (Equals(Palette, default(Palette)) || (Texture8 ?? new ByteTexture[0]).Length == 0)) { unsafe { Texture8 = new ByteTexture[Textures.Length]; var bigBmp = new Bitmap(Textures.Length * 256, 256, PixelFormat.Format32bppArgb); for (var bi = 0; bi < Textures.Length; bi++) { var bt = Textures[bi]; var bmp = new Bitmap(256, 256, PixelFormat.Format32bppArgb); var bmpData = bmp.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); var scan0 = (uint*)bmpData.Scan0; for (var y = 0; y < 256; y++) { var scanline = bt.Pixels[y]; fixed (uint* ptr = scanline) { for (var i = 0; i < 256; i++) scan0[y * 256 + i] = (ptr[i] & 0xff00ff00) | ((ptr[i] & 0x00ff0000) >> 16) | ((ptr[i] & 0x000000ff) << 16); } } bmp.UnlockBits(bmpData); using (var gr = Graphics.FromImage(bigBmp)) gr.DrawImage(bmp, new Rectangle(bi * 256, 0, 256, 256), 0, 0, 256, 256, GraphicsUnit.Pixel); } var bmp8 = bigBmp.Clone(new Rectangle(0, 0, bigBmp.Width, 256), PixelFormat.Format8bppIndexed); Palette = new Palette() { Colour = bmp8.Palette.Entries.Select(x => (ByteColor)x).ToArray().Resize(256) }; for (var i = 0; i < Textures.Length; i++) { Texture8[i] = new ByteTexture(new byte[256][]); for (var y = 0; y < 256; y++) { Texture8[i].Pixels[y] = new byte[256]; for (var x = 0; x < 256; x++) { Texture8[i].Pixels[y][x] = (byte)Array.IndexOf(bmp8.Palette.Entries, bmp8.GetPixel(i * 256 + x, y)); } } } //Gen8bitPaletteFrom32bitTex(Textures); // Generate 8-bit textures /*for (var i = 0; i < Textures.Length; i++) { var tex = Textures[i]; Texture8[i] = new ByteTexture(new byte[256][]); for (var y = 0; y < 256; y++) { Texture8[i].Pixels[y] = new byte[256]; for (var x = 0; x < 256; x++) { Texture8[i].Pixels[y][x] = (byte) Helper.closestColor1(Palette.Colour, new ByteColor(tex.Pixels[y][x])); } } }*/ } } if (WriteEngineVersion < Engine.TR4 && Equals(Palette16, default(Palette))) { Palette16 = new Palette {Colour = Palette.Colour.Select(x => new ByteColor(x.R, x.G, x.B, 0xFF)).ToArray()}; } }
private void Load_TR4() { var version = reader.ReadUInt32(); if (!version.IsAnyOf((uint)0x00345254, (uint)0x63345254, 0xFFFFFFF0)) throw new ArgumentException("Load_TR4: Wrong level version"); Texture16 = new WordTexture[0]; var numRoomTextiles = reader.ReadUInt16(); var numObjTextiles = reader.ReadUInt16(); var numBumpTextiles = reader.ReadUInt16(); var numMiscTextiles = 2; var numTextiles = numRoomTextiles + numObjTextiles + numBumpTextiles + numMiscTextiles; var uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR4: Textiles32 uncompSize == 0", nameof(uncompSize)); var compSize = reader.ReadUInt32(); if (compSize > 0) { var compBuffer = reader.ReadBytes((int) compSize); var newsrc_ = Helper.Decompress(compBuffer); Textures = newsrc_.ReadArray(numTextiles - numMiscTextiles, () => DWordTexture.Read(newsrc_)); } uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR4: Textiles16 uncompSize == 0", nameof(uncompSize)); compSize = reader.ReadUInt32(); if (compSize > 0) { if (Textures.Length == 0) { var compBuffer = reader.ReadBytes((int) compSize); var newsrc_ = Helper.Decompress(compBuffer); Texture16 = newsrc_.ReadArray(numTextiles - numMiscTextiles, () => WordTexture.Read(newsrc_)); } else { reader.BaseStream.Position += compSize; } } uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR4: Textiles32d uncompSize == 0", nameof(uncompSize)); compSize = reader.ReadUInt32(); if (compSize > 0) { if (Textures.Length == 0) { // 262144 = 256*256*4 if (uncompSize / 262144 > 2) Cerr.Write("Load_TR4: NumMiscTextiles > 2"); Array.Resize(ref Textures, numTextiles); var compBuffer = reader.ReadBytes((int) compSize); var newsrc_ = Helper.Decompress(compBuffer); Textures = Textures.AddArray(newsrc_.ReadArray(numMiscTextiles, () => DWordTexture.Read(newsrc_))); } else { reader.BaseStream.Position += compSize; } } uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR4: Packed geometry uncompSize == 0", nameof(uncompSize)); compSize = reader.ReadUInt32(); if (compSize == 0) throw new ArgumentException("Load_TR4: Packed geometry", nameof(compSize)); var compBuffer_ = reader.ReadBytes((int) compSize); var newsrc = Helper.Decompress(compBuffer_); var unused = newsrc.ReadUInt32(); if (unused != 0) Cerr.Write("Load_TR4: unused: Expected 0, Found " + unused.ToString("X8")); var numRooms = newsrc.ReadUInt16(); Rooms = newsrc.ReadArray(numRooms, () => Room.Read(newsrc, Engine.TR4)); var numFloorData = newsrc.ReadUInt32(); FloorData = newsrc.ReadUInt16Array(numFloorData); var tmpr = reader; reader = newsrc; ReadMeshData(); reader = tmpr; var numAnimations = newsrc.ReadUInt32(); Animations = newsrc.ReadArray(numAnimations, () => Animation.Read(newsrc, Engine.TR4)); var numStateChanges = newsrc.ReadUInt32(); StateChanges = newsrc.ReadArray(numStateChanges, () => StateChange.Read(newsrc)); var numAnimDispatches = newsrc.ReadUInt32(); AnimDispatches = newsrc.ReadArray(numAnimDispatches, () => AnimDispatch.Read(newsrc)); var numAnimCommands = newsrc.ReadUInt32(); AnimCommands = newsrc.ReadInt16Array(numAnimCommands); var numMeshTreeData = newsrc.ReadUInt32(); MeshTreeData = newsrc.ReadUInt32Array(numMeshTreeData); tmpr = reader; reader = newsrc; ReadFrameMoveableData(); reader = tmpr; var numStaticMeshes = newsrc.ReadUInt32(); StaticMeshes = newsrc.ReadArray(numStaticMeshes, () => StaticMesh.Read(newsrc)); var spr1 = (char)newsrc.ReadSByte(); var spr2 = (char)newsrc.ReadSByte(); var spr3 = (char)newsrc.ReadSByte(); var spr = "" + spr1 + spr2 + spr3; if(spr != "SPR") throw new ArgumentException("Load_TR4: Expected 'SPR', Found '" + spr + "'", nameof(spr)); var numSpriteTextures = newsrc.ReadUInt32(); SpriteTextures = newsrc.ReadArray(numSpriteTextures, () => SpriteTexture.Read(newsrc, Engine.TR4)); var numSpriteSequences = newsrc.ReadUInt32(); SpriteSequences = newsrc.ReadArray(numSpriteSequences, () => SpriteSequence.Read(newsrc)); var numCameras = newsrc.ReadUInt32(); Cameras = newsrc.ReadArray(numCameras, () => Camera.Read(newsrc)); var numFlybyCameras = newsrc.ReadUInt32(); FlybyCameras = newsrc.ReadArray(numFlybyCameras, () => FlybyCamera.Read(newsrc)); var numSoundSources = newsrc.ReadUInt32(); SoundSources = newsrc.ReadArray(numSoundSources, () => SoundSource.Read(newsrc)); var numBoxes = newsrc.ReadUInt32(); Boxes = newsrc.ReadArray(numBoxes, () => Box.Read(newsrc, Engine.TR2)); var numOverlaps = newsrc.ReadUInt32(); Overlaps = newsrc.ReadUInt16Array(numOverlaps); Zones = newsrc.ReadArray(numBoxes, () => Zone.Read(newsrc, Engine.TR2)); var numAnimatedTextures = newsrc.ReadUInt32(); AnimatedTextures = newsrc.ReadUInt16Array(numAnimatedTextures); AnimatedTexturesUVCount = newsrc.ReadByte(); var tex1 = (char)newsrc.ReadSByte(); var tex2 = (char)newsrc.ReadSByte(); var tex3 = (char)newsrc.ReadSByte(); var tex = "" + tex1 + tex2 + tex3; if (tex != "TEX") throw new ArgumentException("Load_TR4: Expected 'TEX', Found '" + tex + "'", nameof(tex)); var numObjectTextures = newsrc.ReadUInt32(); ObjectTextures = newsrc.ReadArray(numObjectTextures, () => ObjectTexture.Read(newsrc, Engine.TR4)); var numItems = newsrc.ReadUInt32(); Items = newsrc.ReadArray(numItems, () => Item.Read(newsrc, Engine.TR4)); var numAiObjects = newsrc.ReadUInt32(); AIObjects = newsrc.ReadArray(numAiObjects, () => AIObject.Read(newsrc)); var numDemoData = newsrc.ReadUInt16(); DemoData = newsrc.ReadBytes(numDemoData); SoundMap = newsrc.ReadInt16Array(Constants.TR_AUDIO_MAP_SIZE_TR4); var numSoundDetails = newsrc.ReadUInt32(); SoundDetails = newsrc.ReadArray(numSoundDetails, () => Loader.SoundDetails.Read(newsrc, Engine.TR3)); var numSampleIndices = newsrc.ReadUInt32(); SampleIndices = newsrc.ReadUInt32Array(numSampleIndices); var numSamples = reader.ReadUInt32(); if(numSamples > 0) { SamplesCount = (int) numSamples; SamplesData = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); } if (Textures.Length == 0) { Textures = new DWordTexture[Texture16.Length]; for (uint i = 0; i < Texture16.Length; i++) { Textures[i] = ConvertTexture(Texture16[i]); } } }
/// <summary> /// Reads a <see cref="WordTexture"/> /// </summary> /// <param name="br">The <see cref="BinaryReader"/> used to read the <see cref="WordTexture"/></param> /// <returns>A <see cref="WordTexture"/></returns> public static WordTexture Read(BinaryReader br) { var ret = new WordTexture { Pixels = new ushort[256][] }; for (var i = 0; i < 256; i++) { ret.Pixels[i] = br.ReadUInt16Array(256); } return ret; }
private void Load_TR5() { var version = reader.ReadUInt32(); if (version != 0x00345254) throw new ArgumentException("Load_TR5: Wrong level version"); var numRoomTextiles = reader.ReadUInt16(); var numObjTextiles = reader.ReadUInt16(); var numBumpTextiles = reader.ReadUInt16(); var numMiscTextiles = 3; var numTextiles = numRoomTextiles + numObjTextiles + numBumpTextiles + numMiscTextiles; var uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR5: Textiles32 uncompSize == 0", nameof(uncompSize)); var compSize = reader.ReadUInt32(); if (compSize > 0) { var compBuffer = reader.ReadBytes((int)compSize); var newsrc = Helper.Decompress(compBuffer); Textures = newsrc.ReadArray(numTextiles - numMiscTextiles, () => DWordTexture.Read(newsrc)); } uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR5: Textiles16 uncompSize == 0", nameof(uncompSize)); compSize = reader.ReadUInt32(); Texture16 = new WordTexture[0]; if (compSize > 0) { if (Textures.Length == 0) { var compBuffer = reader.ReadBytes((int)compSize); var newsrc = Helper.Decompress(compBuffer); Texture16 = newsrc.ReadArray(numTextiles - numMiscTextiles, () => WordTexture.Read(newsrc)); } else { reader.BaseStream.Position += compSize; } } uncompSize = reader.ReadUInt32(); if (uncompSize == 0) throw new ArgumentException("Load_TR5: Textiles32d uncompSize == 0", nameof(uncompSize)); compSize = reader.ReadUInt32(); if (compSize > 0) { // 262144 = Width * Height * Depth // = 256 * 256 * 4 if (uncompSize / 262144 > 3) Cerr.Write("Load_TR5: NumMiscTextiles > 3"); var compBuffer = reader.ReadBytes((int) compSize); var newsrc = Helper.Decompress(compBuffer); var t = newsrc.ReadArray(numMiscTextiles, () => DWordTexture.Read(newsrc)); Textures = Textures.AddArray(t); } LaraType = (LaraType) reader.ReadUInt16(); WeatherType = (WeatherType) reader.ReadUInt16(); var flags = reader.ReadUInt32Array(7); // 28 bytes zero padding for (var i = 0; i < flags.Length; i++) { if (flags[i] != 0) Cerr.Write("Load_TR5: flags[" + (i + 1) + "]: Expected 0, Found 0x" + flags[i].ToString("X8")); } var levelUncompSize = reader.ReadUInt32(); var levelCompSize = reader.ReadUInt32(); var unused = reader.ReadUInt32(); if(unused != 0) Cerr.Write("Load_TR5: unused: Expected 0, Found " + unused.ToString("X8")); var numRooms = reader.ReadUInt32(); Rooms = reader.ReadArray(numRooms, () => Room.Read(reader, Engine.TR5)); var numFloorData = reader.ReadUInt32(); FloorData = reader.ReadUInt16Array(numFloorData); ReadMeshData(); var numAnimations = reader.ReadUInt32(); Animations = reader.ReadArray(numAnimations, () => Animation.Read(reader, Engine.TR4)); var numStateChanges = reader.ReadUInt32(); StateChanges = reader.ReadArray(numStateChanges, () => StateChange.Read(reader)); var numAnimDispatches = reader.ReadUInt32(); AnimDispatches = reader.ReadArray(numAnimDispatches, () => AnimDispatch.Read(reader)); var numAnimCommands = reader.ReadUInt32(); AnimCommands = reader.ReadInt16Array(numAnimCommands); var numMeshTreeData = reader.ReadUInt32(); MeshTreeData = reader.ReadUInt32Array(numMeshTreeData); ReadFrameMoveableData(); var numStaticMeshes = reader.ReadUInt32(); StaticMeshes = reader.ReadArray(numStaticMeshes, () => StaticMesh.Read(reader)); var spr1 = (char) reader.ReadSByte(); var spr2 = (char) reader.ReadSByte(); var spr3 = (char) reader.ReadSByte(); var spr4 = (char) reader.ReadSByte(); var spr = "" + spr1 + spr2 + spr3 + spr4; if (spr != "SPR\0") throw new ArgumentException("Load_TR5: Expected 'SPR', Found '" + spr + "'", nameof(spr)); var numSpriteTextures = reader.ReadUInt32(); SpriteTextures = reader.ReadArray(numSpriteTextures, () => SpriteTexture.Read(reader, Engine.TR4)); var numSpriteSequences = reader.ReadUInt32(); SpriteSequences = reader.ReadArray(numSpriteSequences, () => SpriteSequence.Read(reader)); var numCameras = reader.ReadUInt32(); Cameras = reader.ReadArray(numCameras, () => Camera.Read(reader)); var numFlybyCameras = reader.ReadUInt32(); FlybyCameras = reader.ReadArray(numFlybyCameras, () => FlybyCamera.Read(reader)); var numSoundSources = reader.ReadUInt32(); SoundSources = reader.ReadArray(numSoundSources, () => SoundSource.Read(reader)); var numBoxes = reader.ReadUInt32(); Boxes = reader.ReadArray(numBoxes, () => Box.Read(reader, Engine.TR2)); var numOverlaps = reader.ReadUInt32(); Overlaps = reader.ReadUInt16Array(numOverlaps); Zones = reader.ReadArray(numBoxes, () => Zone.Read(reader, Engine.TR2)); var numAnimatedTextures = reader.ReadUInt32(); AnimatedTextures = reader.ReadUInt16Array(numAnimatedTextures); AnimatedTexturesUVCount = reader.ReadByte(); var tex1 = (char)reader.ReadSByte(); var tex2 = (char)reader.ReadSByte(); var tex3 = (char)reader.ReadSByte(); var tex4 = (char) reader.ReadSByte(); var tex = "" + tex1 + tex2 + tex3 + tex4; if (tex != "TEX\0") throw new ArgumentException("Load_TR5: Expected 'TEX', Found '" + tex + "'", nameof(tex)); var numObjectTextures = reader.ReadUInt32(); ObjectTextures = reader.ReadArray(numObjectTextures, () => ObjectTexture.Read(reader, Engine.TR5)); var numItems = reader.ReadUInt32(); Items = reader.ReadArray(numItems, () => Item.Read(reader, Engine.TR4)); var numAiObjects = reader.ReadUInt32(); AIObjects = reader.ReadArray(numAiObjects, () => AIObject.Read(reader)); var numDemoData = reader.ReadUInt16(); DemoData = reader.ReadBytes(numDemoData); SoundMap = reader.ReadInt16Array(Constants.TR_AUDIO_MAP_SIZE_TR5); var numSoundDetails = reader.ReadUInt32(); SoundDetails = reader.ReadArray(numSoundDetails, () => Loader.SoundDetails.Read(reader, Engine.TR3)); var numSampleIndices = reader.ReadUInt32(); SampleIndices = reader.ReadUInt32Array(numSampleIndices); reader.BaseStream.Position += 6; var numSamples = reader.ReadUInt32(); if (numSamples > 0) { SamplesCount = (int)numSamples; SamplesData = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); } if (Textures.Length == 0) { Textures = new DWordTexture[Texture16.Length]; for (uint i = 0; i < Texture16.Length; i++) { Textures[i] = ConvertTexture(Texture16[i]); } } }