diff --git a/GameFiles/FileTypes/AwcFile.cs b/GameFiles/FileTypes/AwcFile.cs index 8a8d42b..c39649b 100644 --- a/GameFiles/FileTypes/AwcFile.cs +++ b/GameFiles/FileTypes/AwcFile.cs @@ -30,6 +30,28 @@ namespace CodeWalker.GameFiles public uint[] AudioIds { get; set; } public AwcAudio[] Audios { get; set; } + public void Decrypt_RSXXTEA(ref byte[] data, uint[] key) + { + // Rockstar's modified version of XXTEA + uint[] blocks = new uint[data.Length / 4]; + Buffer.BlockCopy(data, 0, blocks, 0, data.Length); + + int block_count = blocks.Length; + uint a, b = blocks[0], i; + + i = (uint)(0x9E3779B9 * (6 + 52 / block_count)); + do + { + for (int block_index = block_count - 1; block_index >= 0; --block_index) + { + a = blocks[(block_index > 0 ? block_index : block_count) - 1]; + b = blocks[block_index] -= (a >> 5 ^ b << 2) + (b >> 3 ^ a << 4) ^ (i ^ b) + (key[block_index & 3 ^ (i >> 2 & 3)] ^ a ^ 0x7B3A207F); + } + i -= 0x9E3779B9; + } while (i != 0); + + Buffer.BlockCopy(blocks, 0, data, 0, data.Length); + } public void Load(byte[] data, RpfFileEntry entry) { @@ -48,9 +70,19 @@ namespace CodeWalker.GameFiles return; //nothing to do, not enough data... } - Magic = BitConverter.ToUInt32(data, 0); - Endianess endianess = Endianess.LittleEndian; + + Magic = BitConverter.ToUInt32(data, 0); + if (Magic != 0x54414441 && Magic != 0x41444154) + { + if (data.Length % 4 == 0) + { + Decrypt_RSXXTEA(ref data, GTA5Keys.PC_AWC_KEY); + Magic = BitConverter.ToUInt32(data, 0); + } else + ErrorMessage = "Corrupted data!"; + } + switch (Magic) { default: @@ -64,44 +96,6 @@ namespace CodeWalker.GameFiles break; } - - /* francium - Today at 6:11 PM -IDA decompiler code from a function that seems to be called around audio loading if not ADAT: - if ( a3 ) - { - v3 = *a1; - v4 = -a2; - v5 = (unsigned int)(-a2 - 1); - v6 = 0x9E3779B9 * (52 / -a2 + 6); - do - { - LODWORD(v7) = -a2 - 1; - v8 = (v6 >> 2) & 3; - if ( -a2 != 1 ) - { - v9 = (unsigned int)v5; - v10 = &a1[v5]; - do - { - v7 = (unsigned int)(v7 - 1); - v11 = v9--; - *v10 -= ((v6 ^ v3) + (a1[v7] ^ *(_DWORD *)(a3 + 4 * (v8 ^ (unsigned __int64)(v11 & 3))) ^ 0x7B3A207F)) ^ ((4 * v3 ^ (a1[v7] >> 5)) + ((v3 >> 3) ^ 16 * a1[v7])); - v3 = *v10; - --v10; - } - while ( (_DWORD)v7 ); - } - result = (v6 ^ v3) + (a1[v4 - 1] ^ *(_DWORD *)(a3 + 4 * (v8 ^ (unsigned __int64)(v7 & 3))) ^ 0x7B3A207F); - *a1 -= result ^ ((4 * v3 ^ (a1[v4 - 1] >> 5)) + ((v3 >> 3) ^ 16 * a1[v4 - 1])); - v3 = *a1; - v6 += 0x61C88647; - } - while ( v6 ); - } - */ - - - using (MemoryStream ms = new MemoryStream(data)) { DataReader r = new DataReader(ms, endianess); diff --git a/GameFiles/Utils/GTAKeys.cs b/GameFiles/Utils/GTAKeys.cs index 311a7c9..d7ceff6 100644 --- a/GameFiles/Utils/GTAKeys.cs +++ b/GameFiles/Utils/GTAKeys.cs @@ -64,7 +64,7 @@ namespace CodeWalker.GameFiles public static byte[] PC_LUT; // 256 - public static byte[] PC_AWC_KEY; // 16 + public static uint[] PC_AWC_KEY; // 16 @@ -302,12 +302,12 @@ namespace CodeWalker.GameFiles byte[] b1 = new byte[27472]; byte[] b2 = new byte[278528]; byte[] b3 = new byte[256]; - byte[] b4 = new byte[16]; + uint[] b4 = new uint[4]; int bp = 0; Buffer.BlockCopy(b, bp, b1, 0, b1.Length); bp += b1.Length; // 27472 Buffer.BlockCopy(b, bp, b2, 0, b2.Length); bp += b2.Length; // 278528 Buffer.BlockCopy(b, bp, b3, 0, b3.Length); bp += b3.Length; // 256 - Buffer.BlockCopy(b, bp, b4, 0, b4.Length); bp += b4.Length; // 16 + Buffer.BlockCopy(b, bp, b4, 0, b4.Length * 4); bp += b4.Length; // 16 PC_NG_KEYS = CryptoIO.ReadNgKeys(b1); PC_NG_DECRYPT_TABLES = CryptoIO.ReadNgTables(b2);