public void Read(BinaryReaderBE Reader) { Magic = Reader.ReadBytes(16); ServerId = Reader.ReadBytes(8); Security = Reader.ReadByte(); MTU = Reader.ReadUInt16BE(); }
public void Read(BinaryReaderBE Reader) { Magic = Reader.ReadBytes(16); Address.Read(Reader); MTU = Reader.ReadUInt16BE(); ClientId = Reader.ReadBytes(8); }
public void Parse() { FileStream Stream = File.OpenRead(Path); using (BinaryReaderBE Reader = new BinaryReaderBE(Stream)) { bool IsCorrectEndian = Reader.ReadUInt32() == 0x80371240; if (!IsCorrectEndian) { Reader.Dispose(); Stream.Dispose(); return; } Stream.Position = 0x08; Header.ProgramCounter = BitConverter.ToUInt32(Reader.ReadBytes(8), 0); Stream.Position = 0x20; Header.Name = System.Text.Encoding.Default.GetString(Reader.ReadBytes(20)); Stream.Position = 0x0; using (MemoryStream ms = new MemoryStream()) { Stream.CopyTo(ms); AllData = ms.ToArray(); } HasBeenParsed = true; } Stream.Dispose(); }
public virtual void Load(string filename) { BinaryReaderBE reader = new BinaryReaderBE(File.Open(filename, FileMode.Open)); try { // is it MacBinary? int fork_start = 0; if (MacBinaryHeader(reader.ReadBytes(128))) { fork_start = 128; } reader.BaseStream.Seek(fork_start, SeekOrigin.Begin); // read the header version = reader.ReadInt16(); DataVersion = reader.ReadInt16(); Filename = reader.ReadMacString(maxFilename); checksum = reader.ReadUInt32(); directoryOffset = reader.ReadInt32(); short wadCount = reader.ReadInt16(); applicationSpecificDirectoryDataSize = reader.ReadInt16(); entryHeaderSize = reader.ReadInt16(); directoryEntryBaseSize = reader.ReadInt16(); // sanity check the map if (Version < 2 || entryHeaderSize != 16 || directoryEntryBaseSize != 10) { throw new BadMapException("Only Marathon 2 and higher maps are supported"); } ParentChecksum = reader.ReadUInt32(); reader.ReadBytes(2 * 20); // unused // load the directory reader.BaseStream.Seek(directoryOffset + fork_start, SeekOrigin.Begin); for (int i = 0; i < wadCount; ++i) { DirectoryEntry entry = new DirectoryEntry(); entry.LoadEntry(reader); Directory[entry.Index] = entry; LoadApplicationSpecificDirectoryData(reader, entry.Index); } // load all the wads(!) foreach (KeyValuePair <int, DirectoryEntry> kvp in Directory) { reader.BaseStream.Seek(kvp.Value.Offset + fork_start, SeekOrigin.Begin); kvp.Value.LoadChunks(reader); } } finally { reader.Close(); } }
/// <summary> /// Gets the list of Weather UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetWeatherList() { var weatherLock = new object(); var weatherList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int nameLengthOffset = 6; const int iconNumberOffset = 26; var weatherExData = await _ex.ReadExData(XivEx.weather); var weatherNames = new List <string>(); await Task.Run(() => Parallel.ForEach(weatherExData.Values, (weather) => { var xivUi = new XivUi() { PrimaryCategory = "UI", SecondaryCategory = XivStrings.Weather }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(weather))) { br.BaseStream.Seek(nameLengthOffset, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(iconNumberOffset, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; } if (weatherNames.Contains(xivUi.Name)) { return; } lock (weatherLock) { weatherNames.Add(xivUi.Name); weatherList.Add(xivUi); } })); weatherList.Sort(); return(weatherList); }
public void Read(BinaryReaderBE Reader) { ClientId = Reader.ReadBytes(8); Reader.ReadUInt32(); // Unknown Time = Reader.ReadUInt32BE(); Security = Reader.ReadByte(); }
/// <summary> /// Reads and parses the ExHeader file /// </summary> /// <param name="exFile">The Ex file to use.</param> private void ReadExHeader(XivEx exFile) { OffsetTypeDict = new Dictionary <int, int>(); PageList = new List <int>(); LanguageList = new List <int>(); var exdFolderHash = HashGenerator.GetHash("exd"); var exdFileHash = HashGenerator.GetHash(exFile + ExhExtension); var index = new Index(_gameDirectory); var dat = new Dat(_gameDirectory); var offset = index.GetDataOffset(exdFolderHash, exdFileHash, XivDataFile._0A_Exd); if (offset == 0) { throw new Exception($"Could not find offest for exd/{exFile}{ExhExtension}"); } var exhData = dat.GetType2Data(offset, XivDataFile._0A_Exd); // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(exhData))) { var signature = br.ReadInt32(); var version = br.ReadInt16(); var dataSetChunk = br.ReadInt16(); var dataSetCount = br.ReadInt16(); var pageTableCount = br.ReadInt16(); var langTableCount = br.ReadInt16(); var unknown = br.ReadInt16(); var unknown1 = br.ReadInt32(); var entryCount = br.ReadInt32(); br.ReadBytes(8); for (var i = 0; i < dataSetCount; i++) { var dataType = br.ReadInt16(); var dataOffset = br.ReadInt16(); if (!OffsetTypeDict.ContainsKey(dataOffset)) { OffsetTypeDict.Add(dataOffset, dataType); } } for (var i = 0; i < pageTableCount; i++) { var pageNumber = br.ReadInt32(); var pageSize = br.ReadInt32(); PageList.Add(pageNumber); } for (var i = 0; i < langTableCount; i++) { var langCode = br.ReadInt16(); LanguageList.Add(langCode); } } }
private static String ReadString(BinaryReaderBE Reader) { var length = Reader.ReadInt32(); var strBytes = Reader.ReadBytes(length); return(Encoding.UTF8.GetString(strBytes)); }
public QHFReader(string path) { fs = new FileStream(path, FileMode.Open); br = new BinaryReaderBE(fs, encoding); fs.Position = 4; Size = br.ReadInt32(); fs.Position = 34; MsgCount = br.ReadInt32(); fs.Position = 44; Int16 uinLength = br.ReadInt16(); Uin = encoding.GetString(br.ReadBytes(uinLength)); Int16 nickLength = br.ReadInt16(); Nick = encoding.GetString(br.ReadBytes(nickLength)); }
static void Main(string[] args) { City city = new City(); string filename = args.Length > 0 ? args[0] : "test.sc2"; #if DEBUG // dumb and bad. filename = string.Concat("../../../cities/", filename); #endif var rawStream = new MemoryStream(); using (var fs = File.OpenRead(filename)) { fs.CopyTo(rawStream); rawStream.Position = 0; } var reader = new BinaryReaderBE(rawStream); var iffType = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (iffType != "FORM") { throw new InvalidDataException(string.Format("Incorrect IFF type: {0}, expected FORM", iffType)); } var filesize = reader.ReadInt32(); if (filesize + 8 != reader.BaseStream.Length) { throw new InvalidDataException(string.Format("Incorrect filesize: {0}, expected {1}", filesize, reader.BaseStream.Length - 8)); } var container = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (container != "SCDH") { throw new InvalidDataException(string.Format("Incorrect container: {0}, expected SCDH", container)); } while (reader.BaseStream.Position < reader.BaseStream.Length) { ParseChunk(city, reader); } Console.WriteLine("City name: {0}", city.name); Console.WriteLine("Building count: {0}", buildingCount); }
/// <summary> /// Gets the list of Weather UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public List <XivUi> GetWeatherList() { var weatherList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int nameLengthOffset = 6; const int iconNumberOffest = 26; var ex = new Ex(_gameDirectory, _xivLanguage); var weatherExData = ex.ReadExData(XivEx.weather); var weatherNames = new List <string>(); foreach (var weather in weatherExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Weather }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(weather))) { br.BaseStream.Seek(nameLengthOffset, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(iconNumberOffest, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; } if (weatherNames.Contains(xivUi.Name)) { continue; } weatherNames.Add(xivUi.Name); weatherList.Add(xivUi); } weatherList.Sort(); return(weatherList); }
public void Load(BinaryReaderBE reader) { long start = (int)reader.BaseStream.Position; TotalLength = reader.ReadInt16(); Flags = reader.ReadInt16(); LinesPerPage = reader.ReadInt16(); GroupingCount = reader.ReadInt16(); FontChangeCount = reader.ReadInt16(); Groupings = new List <Grouping>(); FontChanges = new List <FontChange>(); for (int i = 0; i < GroupingCount; ++i) { Grouping grouping = new Grouping(); grouping.Load(reader); Groupings.Add(grouping); } for (int i = 0; i < FontChangeCount; ++i) { FontChange fontChange = new FontChange(); fontChange.Load(reader); FontChanges.Add(fontChange); } int textLength = TotalLength - (int)(reader.BaseStream.Position - start); textBytes = reader.ReadBytes(textLength); if (Flags == 1) { //decode text for (int i = 0; i < textBytes.Length; ++i) { i++; if (textBytes.Length > ++i) { textBytes[i] ^= 0xfe; } if (textBytes.Length > ++i) { textBytes[i] ^= 0xed; } } } Encoding macRoman = Encoding.GetEncoding(10000); Texts = macRoman.GetString(textBytes).Split('\0'); }
public void Load(BinaryReaderBE reader) { Flags = reader.ReadInt32(); Name = reader.ReadMacString(ScriptNameLength); Length = reader.ReadInt32(); byte[] textBytes = reader.ReadBytes(Length); Text = Encoding.UTF8.GetString(textBytes); }
/// <summary> /// Gets the list of online status UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetOnlineStatusList() { var onlineStatusLock = new object(); var onlineStatusList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int iconNumberOffset = 6; const int dataSize = 12; var onlineStatusExData = await _ex.ReadExData(XivEx.onlinestatus); await Task.Run(() => Parallel.ForEach(onlineStatusExData.Values, (onlineStatus) => { var xivUi = new XivUi() { PrimaryCategory = "UI", SecondaryCategory = XivStrings.OnlineStatus }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(onlineStatus))) { br.BaseStream.Seek(iconNumberOffset, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(dataSize, SeekOrigin.Begin); // The size of the online status name string // Size of the entire data chunk - size of the data portion var nameLength = onlineStatus.Length - dataSize; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; } lock (onlineStatusLock) { onlineStatusList.Add(xivUi); } })); onlineStatusList.Sort(); return(onlineStatusList); }
// private short nameLen; public void Load(BinaryReaderBE reader) { reader.ReadBytes(1); // reader.ReadBytes(1); Type = reader.ReadInt16(); // reader.ReadBytes(1); Flags = reader.ReadUInt16(); // long position = reader.BaseStream.Position; // position += 1;//??? // reader.BaseStream.Seek(position, SeekOrigin.Begin); // reader.ReadBytes(1); Name = reader.ReadMacString(33); NoOfViews = reader.ReadInt16(); FramesPerView = reader.ReadInt16(); TickePerFrame = reader.ReadInt16(); KeyFrame = reader.ReadInt16(); TrasferMode = reader.ReadInt16(); TransferModePeriod = reader.ReadInt16(); FirstFrameSound = reader.ReadInt16(); KeyFrameSound = reader.ReadInt16(); LastFrameSound = reader.ReadInt16(); PixelsToWorld = reader.ReadInt16(); LoopFrame = reader.ReadInt16(); // long position = reader.BaseStream.Position; // position += 28;//??? // reader.BaseStream.Seek(position, SeekOrigin.Begin); reader.ReadBytes(28); short nov = NoOfViews; int idxCount = getRealViewCount(nov) * FramesPerView; FrameIndexes = new List <int>(); for (int i = 0; i < idxCount; i++) { short frameIndex = reader.ReadInt16(); FrameIndexes.Add(frameIndex); } }
/// <summary> /// Gets the list of online status UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public List <XivUi> GetOnlineStatusList() { var onlineStatusList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int iconNumberOffset = 6; const int dataSize = 12; var ex = new Ex(_gameDirectory, _xivLanguage); var onlineStatusExData = ex.ReadExData(XivEx.onlinestatus); foreach (var onlineStatus in onlineStatusExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.OnlineStatus }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(onlineStatus))) { br.BaseStream.Seek(iconNumberOffset, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(dataSize, SeekOrigin.Begin); // The size of the online status name string // Size of the entire data chunk - size of the data portion var nameLength = onlineStatus.Length - dataSize; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; } onlineStatusList.Add(xivUi); } onlineStatusList.Sort(); return(onlineStatusList); }
/// <summary> /// Gets the list of available loading screen images /// </summary> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetLoadingImageList() { var loadingImageLock = new object(); var loadingImageList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int dataLength = 4; var loadingImageExData = await _ex.ReadExData(XivEx.loadingimage); await Task.Run(() => Parallel.ForEach(loadingImageExData.Values, (loadingImage) => { var xivUi = new XivUi() { PrimaryCategory = "UI", SecondaryCategory = XivStrings.LoadingScreen, UiPath = "ui/loadingimage" }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(loadingImage))) { br.BaseStream.Seek(dataLength, SeekOrigin.Begin); // The length of the loading image name string // Size of the entire data chunk - size of the data portion var nameLength = loadingImage.Length - dataLength; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); if (name.Equals("")) { return; } xivUi.Name = name; } lock (loadingImageLock) { loadingImageList.Add(xivUi); } })); loadingImageList.Sort(); return(loadingImageList); }
public void Read(BinaryReaderBE Reader) { var lines = Reader.ReadUInt32(); Lines = new ConsoleLine[lines]; for (var i = 0; i < lines; i++) { var consoleLine = new ConsoleLine(); var length = Reader.ReadUInt32(); var unknown = Reader.ReadByte(); var length2 = Reader.ReadUInt32(); var line = Reader.ReadBytes((int)length); consoleLine.Level = Reader.ReadUInt32(); consoleLine.Line = Encoding.UTF8.GetString(line); Lines[i] = consoleLine; } }
/// <summary> /// Gets the list of available loading screen images /// </summary> /// <returns>A list containing XivUi data</returns> public List <XivUi> GetLoadingImageList() { var loadingImageList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int dataLength = 4; var ex = new Ex(_gameDirectory, _xivLanguage); var loadingImageExData = ex.ReadExData(XivEx.loadingimage); foreach (var loadingImage in loadingImageExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.LoadingScreen, UiPath = "ui/loadingimage" }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(loadingImage))) { br.BaseStream.Seek(dataLength, SeekOrigin.Begin); // The length of the loading image name string // Size of the entire data chunk - size of the data portion var nameLength = loadingImage.Length - dataLength; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); if (name.Equals("")) { continue; } xivUi.Name = name; } loadingImageList.Add(xivUi); } loadingImageList.Sort(); return(loadingImageList); }
/// <summary> /// Helper function to obtain the string value from placename_0 /// </summary> /// <param name="data">The uncompressed placename byte data</param> /// <returns>A string containing the place name</returns> private static string GetPlaceName(byte[] data) { // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int nameLengthOffset = 6; const int dataLength = 24; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(data))) { br.BaseStream.Seek(nameLengthOffset, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(dataLength, SeekOrigin.Begin); return(Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", "")); } }
internal void LoadChunks(BinaryReaderBE reader) { long position = reader.BaseStream.Position; int nextOffset; do { uint tag = reader.ReadUInt32(); nextOffset = reader.ReadInt32(); int length = reader.ReadInt32(); reader.ReadInt32(); // offset Chunks[tag] = reader.ReadBytes(length); if (nextOffset > 0) { reader.BaseStream.Seek(position + nextOffset, SeekOrigin.Begin); } } while (nextOffset > 0); }
public bool GetNextMessage(QHFMessage msg) { if (fs.Position >= fs.Length - 24) { return(false); } byte[] msgBytes = null; //Trace.WriteLine("Block start: " + fs.Position); msg.Signature = br.ReadInt16(); if (msg.SignatureMismatch) { if (br.ReadByte() == 1) { // В предыдущем сообщении были ошибки и структура съехала. msg.Signature = 1; } else { // Сдвигаем позицию на исходную для достоверности отладки. fs.Position -= 1; Trace.WriteLine($"{Uin} ({Nick}). Signature mismatch. (sign={msg.Signature})"); return(true); } } var size = br.ReadInt32(); var endOfBlock = size + fs.Position; try { msg.ID = GetNextBlock(); msg.Time = UnixTimeStampToDateTime(GetNextBlock()); msg.IsMy = GetNextBlock() > 0; var msgLength = GetNextBlock(); if (msgLength < 0) { fs.Position -= 4; msgBytes = ReadBytesUntilNextMessage(msg.ID + 1); msgLength = msgBytes.Length; } else { if (msgLength > size) { fs.Position -= 4; msgLength = br.ReadInt16(); if (msgLength > size) { fs.Position -= 2; msgLength = br.ReadByte(); } } msgBytes = br.ReadBytes(msgLength); } msg.Text = encoding.GetString(DecodeBytes(msgBytes)); return(true); } catch (ArgumentException ex) { Trace.WriteLine(ex.Message); if (fs.Position == fs.Length) { msg.Text = "Сообщение потеряно."; } return(true); } }
/// <summary> /// Reads and parses the ExData file /// </summary> /// <remarks> /// This reads the data at each index of the exd file /// It then places the data in a dictionary with format [index, raw data] /// </remarks> /// <param name="exFile"></param> /// <returns>A dictionary containing the Index and Raw Data of the ex file</returns> public async Task <Dictionary <int, byte[]> > ReadExData(XivEx exFile) { var exdNameOffsetDictionary = new Dictionary <long, string>(); var exdDataDictionary = new Dictionary <int, byte[]>(); var errorString = ""; await ReadExHeader(exFile); var language = "_" + _langCode; // Some Ex files are universal and do not have a language code if (LanguageList.Count == 0) { language = ""; } // Each page is a new exd file // A good example is item_[page]_[language].exd // item_0_en.exd, item_500_en.exd, item_1000_en.exd, etc. foreach (var page in PageList) { var exdFile = exFile + "_" + page + language + ExdExtension; var exdFolderHash = HashGenerator.GetHash("exd"); var exdFileHash = HashGenerator.GetHash(exdFile); var offset = await _index.GetDataOffset(exdFolderHash, exdFileHash, XivDataFile._0A_Exd); try { exdNameOffsetDictionary.Add(offset, exdFile); } catch (Exception ex) { var zz = "zz"; throw ex; } } await Task.Run(async() => { foreach (var exdData in exdNameOffsetDictionary) { try { var exData = await _dat.GetType2Data(exdData.Key, XivDataFile._0A_Exd); // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(exData))) { br.ReadBytes(8); var offsetTableSize = br.ReadInt32(); for (var i = 0; i < offsetTableSize; i += 8) { br.BaseStream.Seek(i + 32, SeekOrigin.Begin); var entryNum = br.ReadInt32(); var entryOffset = br.ReadInt32(); br.BaseStream.Seek(entryOffset, SeekOrigin.Begin); var entrySize = br.ReadInt32(); br.ReadBytes(2); if (!exdDataDictionary.ContainsKey(entryNum)) { exdDataDictionary.Add(entryNum, br.ReadBytes(entrySize)); } } } } catch (Exception ex) { errorString += $"File: {exdData.Value}\nError: {ex.Message}\n\n"; } } }); if (!string.IsNullOrEmpty(errorString)) { throw new Exception($"There was an error reading EX data for the following\n\n{errorString}"); } return(exdDataDictionary); }
/// <summary> /// Gets the list of indoor furniture /// </summary> /// <remarks> /// Housing items can be obtained one of two ways /// One: checking the housingfurniture exd for the item index, and going to that item to grab the data /// Two: iterating through the entire item list seeing if the item contains an index to a housing item (offset 112, 4 bytes) /// This method does option one /// </remarks> /// <returns>A list of XivFurniture objects containing indoor furniture item info</returns> private async Task <List <XivFurniture> > GetIndoorFurniture() { var indoorLock = new object(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int itemIndexOffset = 10; const int modelNumberOffset = 12; const int itemCategoryOffset = 14; const int itemNameDataOffset = 14; int itemDataLength = DataLengthByPatch["5.5"]; const int itemIconDataOffset = 136; if (_xivLanguage == XivLanguage.Korean) { itemDataLength = DataLengthByPatch["5.4"]; } else if (_xivLanguage == XivLanguage.Chinese) { itemDataLength = DataLengthByPatch["5.4"]; } var ex = new Ex(_gameDirectory, _xivLanguage); var housingDictionary = await ex.ReadExData(XivEx.housingfurniture); var itemDictionary = await ex.ReadExData(XivEx.item); var furnitureList = new List <XivFurniture>(); await Task.Run(() => Parallel.ForEach(housingDictionary.Values, (housingItem) => { try { var item = new XivFurniture { PrimaryCategory = XivStrings.Housing, SecondaryCategory = XivStrings.Furniture_Indoor, ModelInfo = new XivModelInfo() }; using (var br = new BinaryReaderBE(new MemoryStream(housingItem))) { br.BaseStream.Seek(itemIndexOffset, SeekOrigin.Begin); var itemIndex = br.ReadUInt16(); br.BaseStream.Seek(modelNumberOffset, SeekOrigin.Begin); item.ModelInfo.PrimaryID = br.ReadInt16(); br.BaseStream.Seek(itemCategoryOffset, SeekOrigin.Begin); var housingCategory = br.ReadByte(); using (var br1 = new BinaryReaderBE(new MemoryStream(itemDictionary[itemIndex]))) { br1.BaseStream.Seek(itemNameDataOffset, SeekOrigin.Begin); var nameOffset = br1.ReadInt16(); br1.BaseStream.Seek(itemIconDataOffset, SeekOrigin.Begin); item.IconNumber = br1.ReadUInt16(); var gearNameOffset = itemDataLength + nameOffset; var gearNameLength = itemDictionary[itemIndex].Length - gearNameOffset; br1.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br1.ReadBytes(gearNameLength)).Replace("\0", ""); item.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); } } if (!item.Name.Equals(string.Empty)) { lock (indoorLock) { furnitureList.Add(item); } } } catch (Exception ex) { throw; } })); furnitureList.Sort(); return(furnitureList); }
/// <summary> /// Gets the list of indoor furniture /// </summary> /// <remarks> /// Housing items can be obtained one of two ways /// One: checking the housingfurniture exd for the item index, and going to that item to grab the data /// Two: iterating through the entire item list seeing if the item contains an index to a housing item (offset 112, 4 bytes) /// This method does option two as the item index was removed from the picture exd file in patch 5.2 /// </remarks> /// <returns>A list of XivFurniture objects containing indoor furniture item info</returns> private async Task <List <XivFurniture> > GetPaintings() { var paintingsLock = new object(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch int iconNumberOffset = 0; const int itemNameDataOffset = 14; const int housingIndexOffset = 112; int itemDataLength = DataLengthByPatch["5.5"]; const int itemIconDataOffset = 136; var ex = new Ex(_gameDirectory, _xivLanguage); var pictureDictionary = await ex.ReadExData(XivEx.picture); var itemDictionary = await ex.ReadExData(XivEx.item); if (_xivLanguage == XivLanguage.Korean) { itemDataLength = DataLengthByPatch["5.4"]; } else if (_xivLanguage == XivLanguage.Chinese) { itemDataLength = DataLengthByPatch["5.4"]; } var furnitureList = new List <XivFurniture>(); await Task.Run(() => Parallel.ForEach(itemDictionary.Values, (item) => { var painting = new XivFurniture { PrimaryCategory = XivStrings.Housing, SecondaryCategory = XivStrings.Paintings, ModelInfo = new XivModelInfo() }; using (var br = new BinaryReaderBE(new MemoryStream(item))) { br.BaseStream.Seek(housingIndexOffset, SeekOrigin.Begin); var pictureIndex = br.ReadInt32(); if (pictureIndex == 0 || pictureIndex > (pictureDictionary.Count - 1)) { return; } br.BaseStream.Seek(itemNameDataOffset, SeekOrigin.Begin); var nameOffset = br.ReadInt16(); br.BaseStream.Seek(itemIconDataOffset, SeekOrigin.Begin); painting.IconNumber = br.ReadUInt16(); var gearNameOffset = itemDataLength + nameOffset; var gearNameLength = item.Length - gearNameOffset; br.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br.ReadBytes(gearNameLength)).Replace("\0", ""); painting.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); using (var br1 = new BinaryReaderBE(new MemoryStream(pictureDictionary[pictureIndex]))) { br1.BaseStream.Seek(iconNumberOffset, SeekOrigin.Begin); painting.ModelInfo.PrimaryID = br1.ReadInt32(); } } if (!painting.Name.Equals(string.Empty) && (painting.Name.IndexOf("painting", System.StringComparison.OrdinalIgnoreCase) >= 0)) { lock (paintingsLock) { furnitureList.Add(painting); } } })); furnitureList.Sort(); return(furnitureList); }
/// <summary> /// Gets the list of available map data /// </summary> /// <remarks> /// The map data is obtained from the map exd files /// There may be unlisted maps which this does not check for /// </remarks> /// <returns>A list containing XivUi data</returns> public List <XivUi> GetMapList() { // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int regionMapDataOffset = 12; const int dataLength = 32; var mapList = new List <XivUi>(); var ex = new Ex(_gameDirectory, _xivLanguage); var placeNameData = ex.ReadExData(XivEx.placename); var mapData = ex.ReadExData(XivEx.map); var mapNameList = new List <string>(); // Loops through all available maps in the map exd files // At present only one file exists (map_0) foreach (var map in mapData.Values) { int regionIndex; int mapIndex; var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Maps }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(map))) { br.BaseStream.Seek(regionMapDataOffset, SeekOrigin.Begin); regionIndex = br.ReadInt16(); mapIndex = br.ReadInt16(); if (mapIndex == 0) { continue; } br.BaseStream.Seek(dataLength, SeekOrigin.Begin); // The size of the map path string // Size of the entire data chunk - size of the data portion var mapPathLength = map.Length - dataLength; if (mapPathLength < 4) { continue; } xivUi.UiPath = Encoding.UTF8.GetString(br.ReadBytes(mapPathLength)).Replace("\0", ""); } // Gets the name from the placename exd file var regionName = GetPlaceName(placeNameData[regionIndex]); var mapName = GetPlaceName(placeNameData[mapIndex]); if (mapName.Equals(string.Empty)) { continue; } xivUi.Name = mapName; xivUi.ItemSubCategory = regionName; if (mapNameList.Contains(mapName)) { xivUi.Name = mapName + " " + xivUi.UiPath.Substring(xivUi.UiPath.Length - 2); } mapNameList.Add(mapName); mapList.Add(xivUi); } mapList.Sort(); return(mapList); }
/// <summary> /// Gets the list of status effect UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetStatusList() { var statusLock = new object(); var statusList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int nameLengthDataOffset = 6; var typeDataOffset = 13; var dataLength = 24; if (_xivLanguage != XivLanguage.Korean) { typeDataOffset = 16; dataLength = 28; } var statusExData = await _ex.ReadExData(XivEx.status); await Task.Run(() => Parallel.ForEach(statusExData.Values, (status) => { var xivUi = new XivUi() { PrimaryCategory = "UI", SecondaryCategory = XivStrings.Status }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(status))) { br.BaseStream.Seek(nameLengthDataOffset, SeekOrigin.Begin); var nameLength = br.ReadInt16(); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(typeDataOffset, SeekOrigin.Begin); var type = br.ReadByte(); br.BaseStream.Seek(dataLength, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; if (name.Equals(string.Empty)) { return; } //Status effects have a byte that determines whether the effect is detrimental or beneficial if (type == 1) { xivUi.TertiaryCategory = XivStrings.Beneficial; } else if (type == 2) { xivUi.TertiaryCategory = XivStrings.Detrimental; } else { xivUi.TertiaryCategory = XivStrings.None; xivUi.Name = xivUi.Name + " " + type; } } lock (statusLock) { statusList.Add(xivUi); } })); statusList.Sort(); return(statusList); }
/// <summary> /// Gets the list of status effect UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public List <XivUi> GetStatusList() { var statusList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int nameLengthDataOffset = 6; const int typeDataOffset = 13; const int dataLength = 24; var ex = new Ex(_gameDirectory, _xivLanguage); var statusExData = ex.ReadExData(XivEx.status); foreach (var status in statusExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Status }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(status))) { br.BaseStream.Seek(nameLengthDataOffset, SeekOrigin.Begin); var nameLength = br.ReadInt16(); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(typeDataOffset, SeekOrigin.Begin); var type = br.ReadByte(); br.BaseStream.Seek(dataLength, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; if (name.Equals(string.Empty)) { continue; } //Status effects have a byte that determines whether the effect is detrimental or beneficial if (type == 1) { xivUi.ItemSubCategory = XivStrings.Beneficial; } else if (type == 2) { xivUi.ItemSubCategory = XivStrings.Detrimental; } else { xivUi.ItemSubCategory = XivStrings.None; xivUi.Name = xivUi.Name + " " + type; } } statusList.Add(xivUi); } statusList.Sort(); return(statusList); }
/// <summary> /// Gets the list of action UI elements /// </summary> /// <remarks> /// The actions are obtained from different sources, but is not all inclusive /// There may be some actions that are missing /// </remarks> /// <returns>A list containing XivUi data</returns> public List <XivUi> GetActionList() { var ex = new Ex(_gameDirectory, _xivLanguage); // Data from the action_0 exd var actionExData = ex.ReadExData(XivEx.action); var actionCategoryExData = ex.ReadExData(XivEx.actioncategory); var actionList = new List <XivUi>(); var actionNames = new List <string>(); foreach (var action in actionExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions }; int actionCategory; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(8, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(26, SeekOrigin.Begin); actionCategory = br.ReadByte(); br.BaseStream.Seek(56, SeekOrigin.Begin); var nameLength = action.Length - 56; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); var actionCategoryData = actionCategoryExData[actionCategory]; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(actionCategoryData))) { br.BaseStream.Seek(4, SeekOrigin.Begin); var nameLength = actionCategoryData.Length - 4; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); if (name.Equals(string.Empty)) { xivUi.ItemSubCategory = XivStrings.None; } else { xivUi.ItemSubCategory = name; } } actionList.Add(xivUi); } // Data from generalaction_0 var generalActionExData = ex.ReadExData(XivEx.generalaction); foreach (var action in generalActionExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.General }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(8, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(10, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(20, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from buddyaction_0 var buddyActionExData = ex.ReadExData(XivEx.buddyaction); foreach (var action in buddyActionExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Buddy }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(10, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(20, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from companyaction_0 var companyActionExData = ex.ReadExData(XivEx.companyaction); foreach (var action in companyActionExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Company }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(14, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(20, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from craftaction_100000 var craftActionExData = ex.ReadExData(XivEx.craftaction); foreach (var action in craftActionExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Craft }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(48, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(60, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from eventaction_0 var eventActionExData = ex.ReadExData(XivEx.eventaction); foreach (var action in eventActionExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Event }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(4, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(16, SeekOrigin.Begin); var nameLength = action.Length - 16; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from emote_0 var emoteExData = ex.ReadExData(XivEx.emote); foreach (var action in emoteExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Emote }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(26, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(36, SeekOrigin.Begin); var nameLength = action.Length - 36; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from marker_0 var markerExData = ex.ReadExData(XivEx.marker); foreach (var action in markerExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Marker }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } var nameLength = action.Length - 6; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } // Data from fieldmarker_0 var fieldMarkerExData = ex.ReadExData(XivEx.fieldmarker); foreach (var action in fieldMarkerExData.Values) { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.FieldMarker }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(8, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { continue; } br.BaseStream.Seek(12, SeekOrigin.Begin); var nameLength = action.Length - 12; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { continue; } actionNames.Add(xivUi.Name); actionList.Add(xivUi); } actionList.Sort(); return(actionList); }
public override GameFile[] Unpack() { this.file.BaseStream.Position = this.file.Position; BinaryReaderBE br = new BinaryReaderBE(this.file.BaseStream); // Read header if (br.ReadUInt32() != MagicStamp) { throw new InvalidDataException(); } uint numFiles = br.ReadUInt32(); br.ReadUInt32(); // File size br.ReadUInt32(); // Header + FAT size uint nameSecOffset = br.ReadUInt32(); uint fileSecOffset = br.ReadUInt32(); br.ReadUInt32(); // Unknown, maybe FAT entry or header size? br.ReadUInt32(); // Unknown, maybe MD5 size? br.ReadUInt32(); // Unknown, padding? // Read FAT & name GameFile[] files = new GameFile[numFiles]; for (int i = 0; i < numFiles; i++) { this.file.BaseStream.Position = this.file.Position + 0x20 + i * 0x20; files[i] = new GameFile(this.file.BaseStream); byte[] md5 = br.ReadBytes(0x10); files[i].Position = this.file.Position + fileSecOffset + br.ReadUInt32(); files[i].Size = br.ReadUInt32(); // Get name this.file.BaseStream.Position = this.file.Position + nameSecOffset + br.ReadUInt32(); string relativePath = br.ReadString(); //relativePath = relativePath.Replace('/', '\\'); if (relativePath.Contains("//")) { relativePath = relativePath.Replace("//", ""); } if (relativePath.Contains("/")) { files[i].FileName = relativePath.Substring(relativePath.LastIndexOf('/') + 1); files[i].FilePath = Path.Combine( this.file.FilePath, relativePath.Substring(0, relativePath.LastIndexOf('/'))); } else { files[i].FileName = relativePath; files[i].FilePath = Path.Combine(this.file.FilePath, relativePath); } files[i].Parent = this.file; this.file.AddChild(files[i]); } br = null; return(files); }