private TBFHeader ReadTexture(Reader reader, TBFHeader h = null) { if (h == null) { h = new TBFHeader(); h.offset = (uint)reader.BaseStream.Position; } h.signature = reader.ReadUInt32(); h.flags = reader.ReadUInt32(); h.width = reader.ReadUInt32(); h.height = reader.ReadUInt32(); switch (h.TypeNumber) { case 0x1: { Color[] palette = ReadPalette(reader, 16, h.HasAlpha); byte[] texData = reader.ReadBytes((int)(h.height * h.width / 2)); if (Settings.s.game == Settings.Game.R3) { ezSwizzle s = new ezSwizzle(); s.writeTexPSMCT32(0, (int)h.width / 128, 0, 0, (int)h.width / 2, (int)h.height / 4, texData); texData = new byte[h.height * h.width]; s.readTexPSMT4_mod(0, (int)h.width / 64, 0, 0, (int)h.width, (int)h.height, ref texData); } else { texData = texData.SelectMany(b => new byte[] { (byte)(b & 0xF), (byte)(b >> 4) }).ToArray(); } //Util.ByteArrayToFile(MapLoader.Loader.gameDataBinFolder + "/textures/lol_" + h.width + "_" + h.height +".bin", texData); h.texture = CreateTexture(palette, texData, h.width, h.height); } break; case 0x2: { Color[] palette = ReadPalette(reader, 256, h.HasAlpha); byte[] texData = reader.ReadBytes((int)(h.height * h.width)); if (Settings.s.game == Settings.Game.R3) { ezSwizzle s = new ezSwizzle(); s.writeTexPSMCT32(0, (int)h.width / 128, 0, 0, (int)h.width / 2, (int)h.height / 2, texData); texData = new byte[h.height * h.width]; s.readTexPSMT8(0, (int)h.width / 64, 0, 0, (int)h.width, (int)h.height, ref texData); } h.texture = CreateTexture(palette, texData, h.width, h.height); } break; case 0: // Do nothing, this is empty if (h.width != 0 || h.height != 0) { throw new InvalidDataException(path + " - " + string.Format("{0:X8}", h.offset) + " - Type 0, but width & height aren't 0!"); } break; // Rayman 3 supports types 3 and 4 as well default: throw new InvalidDataException(path + " - " + string.Format("{0:X8}", h.offset) + " - Unknown type: " + h.TypeNumber); } return(h); }
public TBF(string path, bool hasNames = false) { this.path = path; Stream tbf = FileSystem.GetFileReadStream(path); using (Reader reader = new Reader(tbf, Settings.s.IsLittleEndian)) { if (hasNames) // for example, TXC file in Rayman M/Arena { Count = reader.ReadUInt32(); headers = new TBFHeader[Count]; for (uint i = 0; i < Count; i++) { TBFHeader h = new TBFHeader(); uint len = reader.ReadUInt32(); h.name = reader.ReadString((int)len); h.offset = reader.ReadUInt32(); headers[i] = h; } for (uint i = 0; i < Count; i++) { reader.BaseStream.Position = headers[i].offset; ReadTexture(reader, h: headers[i]); } } else { List <Texture2D> textures = new List <Texture2D>(); List <TBFHeader> headers = new List <TBFHeader>(); while (reader.BaseStream.Position < reader.BaseStream.Length) { TBFHeader h = ReadTexture(reader); headers.Add(h); } Count = (uint)headers.Count; this.textures = headers.Select(h => h.texture).ToArray(); this.headers = headers.ToArray(); } } }