/// <summary> /// Read an HTEX file into memory. /// </summary> /// <param name="input">A readable stream of an HTEX file.</param> public HTEX(Stream input) { using (var br = new BinaryReaderX(input)) { // Packet Header _packetHeader = br.ReadType <PacketHeaderX>(); // HTSF Packet Header _htsfPacketHeader = br.ReadType <PacketHeaderX>(); // HTSF Header _htsfHeader = br.ReadType <HtsfHeader>(); var bytes = br.ReadBytes(_htsfPacketHeader.DataSize - Common.PacketHeaderXSize); ImageStream = new MemoryStream(bytes); //if (input is FileStream stream && !File.Exists(Path.ChangeExtension(stream.Name, "gim"))) // File.WriteAllBytes(Path.ChangeExtension(stream.Name, "gim"), bytes); // Footers _htsfFooter = br.ReadType <PacketHeaderX>(); _htexFooter = br.ReadType <PacketHeaderX>(); } }
/// <summary> /// Read an MXEN file into memory. /// </summary> /// <param name="input">A readable stream of an MXEN file.</param> public MXEN(Stream input) { using (var br = new BinaryReaderX(input)) { // Packet Header _packetHeader = br.ReadType <PacketHeaderX>(); // MXEC Packet Header _mxecPacketHeader = br.ReadType <PacketHeaderX>(); // Rolling XOR Encryption Stream ss; if (_mxecPacketHeader.Flags3 == 0x0C) { var bytes = br.ReadBytes(_mxecPacketHeader.DataSize); var b = _xorKey = bytes[0]; ss = new MemoryStream { Capacity = _mxecPacketHeader.DataSize }; using (var bw = new BinaryWriterX(ss, true)) { bw.Write((byte)0x01); for (var i = 1; i < bytes.Length; i++) { var bs = bytes[i]; bw.Write((byte)(bs ^ b)); b = bs; } } ss.Position = 0; } else { ss = new SubStream(input, br.BaseStream.Position, _mxecPacketHeader.DataSize); } // Table1 Binary Reader var bbr = new BinaryReaderX(ss); // MXEC Header _mxecHeader = bbr.ReadType <MXECHeader>(); // Unsupported Tables if (_mxecHeader.Table2Offset > 0) { throw new Exception("Table2 is not supported by this plugin."); } if (_mxecHeader.Table4Offset > 0) { throw new Exception("Table4 is not supported by this plugin."); } if (_mxecHeader.Table6Offset > 0) { throw new Exception("Table6 is not supported by this plugin."); } // Table1 Metadata _table1Metadata = bbr.ReadMultiple <Table1Metadata>(_mxecHeader.Table1Count); _table1Objects = new List <Table1Object>(); // Table1 foreach (var metadata in _table1Metadata) { var obj = new Table1Object { Metadata = metadata }; _table1Objects.Add(obj); bbr.BaseStream.Position = metadata.TypeOffset - Common.PacketHeaderXSize; obj.Type = bbr.ReadCStringSJIS(); bbr.BaseStream.Position = metadata.DataOffset - Common.PacketHeaderXSize; obj.Data = bbr.ReadBytes(metadata.DataSize); } bbr.SeekAlignment(); // Text var textStart = bbr.BaseStream.Position; var textEnd = _mxecPacketHeader.DataSize; _textEntries = new List <Table1TextEntry>(); while (true) { var entry = new Table1TextEntry { Offset = (int)bbr.BaseStream.Position }; var text = bbr.ReadCStringSJIS(); if (text == "" && _textEntries.Count > 0) { break; } entry.Text = text; _textEntries.Add(entry); if (bbr.BaseStream.Position >= textEnd) { break; } } bbr.SeekAlignment(); _editableTexts = new Dictionary <int, string>(); foreach (var entry in _table1Objects) { entry.TypeIndex = _textEntries.IndexOf(_textEntries.FirstOrDefault(t => t.Offset == entry.Metadata.TypeOffset - Common.PacketHeaderXSize)); for (var i = 0; i < entry.Data.Length / 4; i++) { var val = BitConverter.ToInt32(entry.Data, i * 4) - Common.PacketHeaderXSize; if (val >= textStart && val <= textEnd) { var index = _textEntries.IndexOf(_textEntries.FirstOrDefault(t => t.Offset == val)); if (index <= -1) { continue; } entry.Texts.Add(new Table1ObjectText { DataOffset = i * 4, TextIndex = index }); if (!_editableTexts.ContainsKey(val)) { _editableTexts.Add(val, entry.Type); } else if (!_editableTexts[val].Contains(entry.Type)) { _editableTexts[val] += ", " + entry.Type; } } } } var id = 1; foreach (var entry in _textEntries) { if (!_editableTexts.ContainsKey(entry.Offset)) { continue; } entry.ID = id; Entries.Add(new TextEntry { Name = entry.ID.ToString(), EditedText = entry.Text, Notes = _editableTexts[entry.Offset] }); id++; } // Reset Stream br.BaseStream.Position = Common.PacketHeaderXSize * 2 + _mxecPacketHeader.DataSize; // POF0 _pof0 = br.ReadType <PacketHeaderX>(); _pof0Data = br.ReadBytes(_pof0.DataSize); // ENRS _enrs = br.ReadType <PacketHeaderX>(); _enrsData = br.ReadBytes(_enrs.DataSize); // CCRS _ccrs = br.ReadType <PacketHeaderX>(); _ccrsData = br.ReadBytes(_ccrs.DataSize); // Footers _ccrsFooter = br.ReadType <PacketHeaderX>(); _mxecFooter = br.ReadType <PacketHeaderX>(); _mxenFooter = br.ReadType <PacketHeaderX>(); } }
/// <summary> /// Read an MTPA file into memory. /// </summary> /// <param name="input">A readable stream of an MTPA file.</param> public MTPA(Stream input) { using (var br = new BinaryReaderX(input)) { // Packet Header _packetHeader = br.ReadType <PacketHeaderX>(); // MTPA Header _mtpaHeader = br.ReadType <MTPAHeader>(); var metadataSize = _mtpaHeader.MetadataSize; // Unknown MTPA Data _mtpaHeaderData = br.ReadMultiple <int>(_mtpaHeader.MetadataSize); // Text Metadata Pointers _mtpaTextMetadataPointers = br.ReadMultiple <int>(_mtpaHeader.PointerCount); // Text Metadata if (metadataSize == 2) { _mtpaTextMetadata = br.ReadMultiple <TextMetadata>(_mtpaHeader.MetadataCount).ToList <ITextMetadata>(); } else if (metadataSize == 4) { _mtpaTextMetadata = br.ReadMultiple <TextMetadataX>(_mtpaHeader.MetadataCount).ToList <ITextMetadata>(); } // Text var textStart = (int)br.BaseStream.Position; var textEnd = _packetHeader.DataSize + _packetHeader.HeaderSize; for (var i = 0; i < _mtpaHeader.MetadataCount; i++) { var offset = textStart; var unused = false; offset += _mtpaTextMetadata[i].Offset; br.BaseStream.Position = offset; var length = br.ReadROTnInt32(); if (length == 0) { var currentOffset = _mtpaTextMetadata[i].Offset; unused = true; if (i != _mtpaHeader.MetadataCount - 1) { length = _mtpaTextMetadata[i + 1].Offset - currentOffset - 4; } else { length = textEnd - currentOffset - 4; } } var str = br.ReadROTnBytes(length); Entries.Add(new TextEntry { Name = _mtpaTextMetadata[i].ID.ToString(), EditedText = Encoding.GetEncoding("shift-jis").GetString(str).Trim('\0'), Notes = unused ? "Text length was set to zero. This line might be unused." : string.Empty }); } br.BaseStream.Position = textEnd; // ENRS _enrs = br.ReadType <PacketHeaderX>(); if (br.BaseStream.Position + _enrs.DataSize + Common.PacketHeaderXSize * 2 <= br.BaseStream.Length) { _enrsData = br.ReadBytes(_enrs.DataSize); _enrsFooter = br.ReadType <PacketHeaderX>(); } else { br.BaseStream.Position = br.BaseStream.Length - Common.PacketHeaderXSize; } // MTPA Footer _mtpaFooter = br.ReadType <PacketHeaderX>(); } }