private static byte GetDataShiftSize(IList <byte> Data, int Offset, int Size) { if (Size < 13) { return(0); } // This is the heuristic that ffxitool uses to determine the shift size - it makes absolutely no // sense to me, but it works; I suppose the author of ffxitool reverse engineered what FFXI does. int BitCount = FFXIEncryption.CountBits(Data[Offset + 2]) - FFXIEncryption.CountBits(Data[Offset + 11]) + FFXIEncryption.CountBits(Data[Offset + 12]); switch (Math.Abs(BitCount) % 5) { case 0: return(7); case 1: return(1); case 2: return(6); case 3: return(2); case 4: return(5); } return(0); }
public static bool Rotate(IList <byte> Data, int Offset, int Size, byte ShiftSize) { if (ShiftSize < 1 || ShiftSize > 8) { return(false); } for (int i = 0; i < Size; ++i) { Data[Offset + i] = FFXIEncryption.Rotate(Data[Offset + i], ShiftSize); } return(true); }
public static string ReadEncodedString(BinaryReader BR, Encoding E) { List <byte> LineBytes = new List <byte>(); // It's NUL-terminated, BUT we need at least two bytes to determine the shift size - for example, a single space becomes "10 00". do { LineBytes.Add(BR.ReadByte()); } while (LineBytes.Count < 2 || (byte)LineBytes[LineBytes.Count - 1] != 0); FFXIEncryption.DecodeTextBlock(LineBytes); return(E.GetString(LineBytes.ToArray()).TrimEnd('\0')); }
public static bool DecodeDataBlockMask(IList <byte> Data) { byte save3 = Data[2]; byte save12 = Data[11]; byte save13 = Data[12]; bool returnvalue = FFXIEncryption.DecodeDataBlock(Data, 0, Data.Count); Data[2] = save3; Data[11] = save12; Data[12] = save13; return(returnvalue); }
public static string GetKeyItemName(byte Language, ushort ID) { #if false // FIXME: Not updated to new DAT file format BinaryReader BR = FFXIResourceManager.OpenDATFile(82); // JP = 80 if (BR != null) { if (Encoding.ASCII.GetString(BR.ReadBytes(4)) == "menu" && BR.ReadUInt32() == 0x101) { BR.BaseStream.Position = 0x20; while (BR.BaseStream.Position < BR.BaseStream.Length) { long Offset = BR.BaseStream.Position; string ShortName = Encoding.ASCII.GetString(BR.ReadBytes(4)); uint SizeInfo = BR.ReadUInt32(); if (BR.ReadUInt64() != 0) { break; } if (ShortName == "sc_i") { BR.BaseStream.Position += 0x14; uint EntryCount = BR.ReadUInt32(); for (uint i = 0; i < EntryCount; ++i) { if (BR.ReadUInt32() == ID) { BR.BaseStream.Position += 4; BR.BaseStream.Position = Offset + 0x10 + BR.ReadUInt32(); return(FFXIEncryption.ReadEncodedString(BR, FFXIResourceManager.E)); } BR.BaseStream.Position += 16; } } // Skip to next one BR.BaseStream.Position = Offset + ((SizeInfo & 0xFFFFFF80) >> 3); } } BR.Close(); } return(null); #else return(String.Format("Key Item #{0}", ID)); #endif }
public static string GetSpellName(ushort ID) { #if false // FIXME: Not updated to new DAT file format BinaryReader BR = FFXIResourceManager.OpenDATFile(86); if (BR != null) { if ((ID + 1) * 0x400 <= BR.BaseStream.Length) { BR.BaseStream.Position = ID * 0x400; byte[] SpellData = BR.ReadBytes(0x400); BR.Close(); if (FFXIEncryption.DecodeDataBlock(SpellData)) { return(FFXIResourceManager.E.GetString(SpellData, 0x3d, 20).TrimEnd('\0')); } } BR.Close(); } return(null); #else return(String.Format("Spell #{0}", ID)); #endif }
public static bool Rotate(IList <byte> Data, byte ShiftSize) { return(FFXIEncryption.Rotate(Data, 0, Data.Count, ShiftSize)); }
public static bool DecodeDataBlock(IList <byte> Data, int Offset, int Size) { return(FFXIEncryption.Rotate(Data, Offset, Size, FFXIEncryption.GetDataShiftSize(Data, Offset, Size))); }
public static bool DecodeDataBlock(IList <byte> Data) { return(FFXIEncryption.DecodeDataBlock(Data, 0, Data.Count)); }