public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback) { ThingList TL = new ThingList(); if (ProgressCallback != null) ProgressCallback(I18N.GetText("FTM:ScanningFile"), 0); Graphic G = new Graphic(); while (BR.BaseStream.Position < BR.BaseStream.Length) { long Pos = BR.BaseStream.Position; // Save Position (G.Read() will advance it an unknown amount) if (G.Read(BR)) { TL.Add(G); G = new Graphic(); if (ProgressCallback != null) ProgressCallback(null, (double) (BR.BaseStream.Position + 1) / BR.BaseStream.Length); } else { BR.BaseStream.Seek(Pos + 1, SeekOrigin.Begin); if (ProgressCallback != null && (BR.BaseStream.Position == BR.BaseStream.Length || (BR.BaseStream.Position % 1024) == 0)) ProgressCallback(null, (double) (BR.BaseStream.Position + 1) / BR.BaseStream.Length); } } G = null; return TL; }
protected override void LoadField(string Field, System.Xml.XmlElement Node) { switch (Field) { // "Simple" Fields case "activation-time": this.ActivationTime_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "casting-time": this.CastingTime_ = (byte)this.LoadUnsignedIntegerField(Node); break; case "damage": this.Damage_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "delay": this.Delay_ = (short)this.LoadSignedIntegerField(Node); break; case "description": this.Description_ = this.LoadTextField(Node); break; case "dps": this.DPS_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "element": this.Element_ = (Element)this.LoadHexField(Node); break; case "element-charge": this.ElementCharge_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "flags": this.Flags_ = (ItemFlags)this.LoadHexField(Node); break; case "id": this.ID_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "iLevel:": this.iLevel_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "instinct-cost:": this.iLevel_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "jobs": this.Jobs_ = (Job)this.LoadHexField(Node); break; case "jug-size": this.JugSize_ = (byte)this.LoadUnsignedIntegerField(Node); break; case "level": this.Level_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "log-name-plural": this.LogNamePlural_ = this.LoadTextField(Node); break; case "log-name-singular": this.LogNameSingular_ = this.LoadTextField(Node); break; case "max-charges": this.MaxCharges_ = (byte)this.LoadUnsignedIntegerField(Node); break; case "name": this.Name_ = this.LoadTextField(Node); break; case "puppet-slot": this.PuppetSlot_ = (PuppetSlot)this.LoadHexField(Node); break; case "races": this.Races_ = (Race)this.LoadHexField(Node); break; case "resource-id": this.ResourceID_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "reuse-delay": this.ReuseDelay_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "superior-level": this.SuperiorLevel_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "shield-size": this.ShieldSize_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "skill": this.Skill_ = (Skill)this.LoadHexField(Node); break; case "slots": this.Slots_ = (EquipmentSlot)this.LoadHexField(Node); break; case "stack-size": this.StackSize_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "storage-slots": this.StorageSlots_ = (int)this.LoadSignedIntegerField(Node); break; case "type": this.Type_ = (ItemType)this.LoadHexField(Node); break; case "unknown-1": this.Unknown1_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "unknown-2": this.Unknown2_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "unknown-3": this.Unknown3_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "unknown-4": this.Unknown4_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "use-delay": this.UseDelay_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "valid-targets": this.ValidTargets_ = (ValidTarget)this.LoadHexField(Node); break; // Sub-Things case "icon": if (this.Icon_ == null) { this.Icon_ = new Graphic(); } this.LoadThingField(Node, this.Icon_); break; } }
public bool Read(BinaryReader BR, Type T) { this.Clear(); try { byte[] ItemBytes = BR.ReadBytes(0xC00); FFXIEncryption.Rotate(ItemBytes, 5); BR = new BinaryReader(new MemoryStream(ItemBytes, false)); BR.BaseStream.Seek(0x280, SeekOrigin.Begin); Graphic G = new Graphic(); int GraphicSize = BR.ReadInt32(); if (GraphicSize < 0 || !G.Read(BR) || BR.BaseStream.Position != 0x280 + 4 + GraphicSize) { BR.Close(); return false; } this.Icon_ = G; BR.BaseStream.Seek(0, SeekOrigin.Begin); } catch { return false; } // Common Fields (14 bytes) this.ID_ = BR.ReadUInt32(); this.Flags_ = (ItemFlags)BR.ReadUInt16(); this.StackSize_ = BR.ReadUInt16(); // 0xe0ff for Currency, which kinda suggests this is really 2 separate bytes this.Type_ = (ItemType)BR.ReadUInt16(); this.ResourceID_ = BR.ReadUInt16(); this.ValidTargets_ = (ValidTarget)BR.ReadUInt16(); // Extra Fields (22/30/10/6/2 bytes for Armor/Weapon/Puppet/Item/UsableItem) if (T == Type.Armor || T == Type.Weapon) { this.Level_ = BR.ReadUInt16(); this.Slots_ = (EquipmentSlot)BR.ReadUInt16(); this.Races_ = (Race)BR.ReadUInt16(); this.Jobs_ = (Job)BR.ReadUInt32(); this.SuperiorLevel_ = BR.ReadUInt16(); if (T == Type.Armor) { this.ShieldSize_ = BR.ReadUInt16(); } else { // Weapon this.Unknown4_ = BR.ReadUInt16(); this.Damage_ = BR.ReadUInt16(); this.Delay_ = BR.ReadInt16(); this.DPS_ = BR.ReadUInt16(); this.Skill_ = (Skill)BR.ReadByte(); this.JugSize_ = BR.ReadByte(); this.Unknown1_ = BR.ReadUInt32(); } this.MaxCharges_ = BR.ReadByte(); this.CastingTime_ = BR.ReadByte(); this.UseDelay_ = BR.ReadUInt16(); this.ReuseDelay_ = BR.ReadUInt32(); this.Unknown2_ = BR.ReadUInt16(); this.iLevel_ = BR.ReadUInt16(); this.Unknown3_ = BR.ReadUInt32(); } else if (T == Type.PuppetItem) { this.PuppetSlot_ = (PuppetSlot)BR.ReadUInt16(); this.ElementCharge_ = BR.ReadUInt32(); this.Unknown3_ = BR.ReadUInt32(); } else if (T == Type.Instinct) { BR.ReadUInt32(); BR.ReadUInt32(); BR.ReadUInt16(); this.InstinctCost_ = BR.ReadUInt16(); BR.ReadUInt16(); BR.ReadUInt32(); BR.ReadUInt32(); BR.ReadUInt32(); } else if (T == Type.Item) { switch (this.Type_.Value) { case ItemType.Flowerpot: case ItemType.Furnishing: case ItemType.Mannequin: this.Element_ = (Element)BR.ReadUInt16(); this.StorageSlots_ = BR.ReadInt32(); this.Unknown3_ = BR.ReadUInt32(); break; default: this.Unknown2_ = BR.ReadUInt16(); this.Unknown3_ = BR.ReadUInt32(); this.Unknown3_ = BR.ReadUInt32(); break; } } else if (T == Type.UsableItem) { this.ActivationTime_ = BR.ReadUInt16(); this.Unknown1_ = BR.ReadUInt32(); this.Unknown3_ = BR.ReadUInt32(); this.Unknown4_ = BR.ReadUInt32(); } else if (T == Type.Currency) { this.Unknown2_ = BR.ReadUInt16(); } else if (T == Type.Slip) { this.Unknown1_ = BR.ReadUInt16(); for (int counter = 0; counter < 17; counter++) { BR.ReadUInt32(); } } else if (T == Type.Monipulator) { this.Unknown1_ = BR.ReadUInt16(); for (int counter = 0; counter < 24; counter++) { BR.ReadInt32(); } } // Next Up: Strings (variable size) long StringBase = BR.BaseStream.Position; uint StringCount = BR.ReadUInt32(); if (StringCount > 9) { // Sanity check, for safety - 0 strings is fine for now this.Clear(); return false; } FFXIEncoding E = new FFXIEncoding(); string[] Strings = new string[StringCount]; for (byte i = 0; i < StringCount; ++i) { long Offset = StringBase + BR.ReadUInt32(); uint Flag = BR.ReadUInt32(); if (Offset < 0 || Offset + 0x20 > 0x280 || (Flag != 0 && Flag != 1)) { this.Clear(); return false; } // Flag seems to be 1 if the offset is not actually an offset. Could just be padding to make StringCount unique per language, or it could be an indication // of the pronoun to use (a/an/the/...). The latter makes sense because of the increased number of such flags for french and german. if (Flag == 0) { BR.BaseStream.Position = Offset; Strings[i] = this.ReadString(BR, E); if (Strings[i] == null) { this.Clear(); return false; } BR.BaseStream.Position = StringBase + 4 + 8 * (i + 1); } } // Assign the strings to the proper fields switch (StringCount) { case 1: this.Name_ = Strings[0]; break; case 2: // Japanese this.Name_ = Strings[0]; this.Description_ = Strings[1]; break; case 5: // English this.Name_ = Strings[0]; // unused: Strings[1] this.LogNameSingular_ = Strings[2]; this.LogNamePlural_ = Strings[3]; this.Description_ = Strings[4]; break; case 6: // French this.Name_ = Strings[0]; // unused: Strings[1] // unused: Strings[2] this.LogNameSingular_ = Strings[3]; this.LogNamePlural_ = Strings[4]; this.Description_ = Strings[5]; break; case 9: // German this.Name_ = Strings[0]; // unused: Strings[1] // unused: Strings[2] // unused: Strings[3] this.LogNameSingular_ = Strings[4]; // unused: Strings[5] // unused: Strings[6] this.LogNamePlural_ = Strings[7]; this.Description_ = Strings[8]; break; } BR.Close(); return true; }
public override void Clear() { if (this.Icon_ != null) { this.Icon_.Clear(); } this.ID_ = null; this.Flags_ = null; this.StackSize_ = null; this.Type_ = null; this.ResourceID_ = null; this.ValidTargets_ = null; this.Name_ = null; this.Description_ = null; this.LogNameSingular_ = null; this.LogNamePlural_ = null; this.Element_ = null; this.StorageSlots_ = null; this.ActivationTime_ = null; this.Level_ = null; this.Slots_ = null; this.Races_ = null; this.Jobs_ = null; this.SuperiorLevel_ = null; this.ShieldSize_ = null; this.Damage_ = null; this.Delay_ = null; this.DPS_ = null; this.Skill_ = null; this.JugSize_ = null; this.iLevel_ = null; this.MaxCharges_ = null; this.CastingTime_ = null; this.UseDelay_ = null; this.ReuseDelay_ = null; this.PuppetSlot_ = null; this.ElementCharge_ = null; this.InstinctCost_ = null; this.Icon_ = null; this.Unknown1_ = null; this.Unknown2_ = null; this.Unknown3_ = null; this.Unknown4_ = null; }
protected override void LoadField(string Field, System.Xml.XmlElement Node) { switch (Field) { case "description": this.Description_ = this.LoadTextField(Node); break; case "id": this.ID_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "unknown-1": this.Unknown1_ = (ushort)this.LoadUnsignedIntegerField(Node); break; case "unknown-2": this.Unknown2_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "unknown-3": this.Unknown3_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "unknown-4": this.Unknown4_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "unknown-5": this.Unknown5_ = (uint)this.LoadUnsignedIntegerField(Node); break; case "icon": if (this.Icon_ == null) { this.Icon_ = new Graphic(); } this.LoadThingField(Node, this.Icon_); break; } }
// Block Layout: // 000-003 U32 Index // 004-007 U32 Unknown // 008-00b U32 Unknown // 00c-00f U32 Unknown // 010-013 U32 Unknown // 014-02b Unknown // 02c-0ab TXT Description // 0ac-27f Unknown // 280-281 U16 Icon Size // 282-bff IMG Icon (+ padding) public bool Read(BinaryReader BR) { this.Clear(); try { byte[] Bytes = BR.ReadBytes(0x280); byte[] IconBytes = BR.ReadBytes(0x980); if (!FFXIEncryption.DecodeDataBlock(Bytes)) { return false; } if (IconBytes[0x97f] != 0xff) { return false; } { // Verify that the icon info is valid Graphic StatusIcon = new Graphic(); BinaryReader IconBR = new BinaryReader(new MemoryStream(IconBytes, false)); int IconSize = IconBR.ReadInt32(); if (IconSize > 0 && IconSize <= 0x97b) { if (!StatusIcon.Read(IconBR) || IconBR.BaseStream.Position != 4 + IconSize) { IconBR.Close(); return false; } } IconBR.Close(); if (StatusIcon == null) { return false; } this.Icon_ = StatusIcon; } BR = new BinaryReader(new MemoryStream(Bytes, false)); } catch { return false; } FFXIEncoding E = new FFXIEncoding(); this.ID_ = BR.ReadUInt16(); this.Unknown1_ = BR.ReadUInt16(); this.Unknown2_ = BR.ReadUInt32(); this.Unknown3_ = BR.ReadUInt32(); this.Unknown4_ = BR.ReadUInt32(); this.Unknown4_ = BR.ReadUInt32(); BR.ReadBytes(0x18); this.Description_ = E.GetString(BR.ReadBytes(128)).TrimEnd('\0'); BR.Close(); return true; }