Example #1
0
        public void Load(byte[] data, RpfFileEntry entry)
        {
            //adapted from libertyV code


            //MemoryStream ms = new MemoryStream(data);
            Name      = entry.Name;
            FileEntry = entry;
            Data      = data;

            if ((data == null) || (data.Length < 8))
            {
                ErrorMessage = "Data null or too short!";
                return; //nothing to do, not enough data...
            }

            Endianess endianess = Endianess.LittleEndian;

            Magic = BitConverter.ToUInt32(data, 0);
            if (Magic != 0x54414441 && Magic != 0x41444154)
            {
                if (data.Length % 4 == 0)
                {
                    Decrypt_RSXXTEA(data, GTA5Keys.PC_AWC_KEY);
                    Magic = BitConverter.ToUInt32(data, 0);
                }
                else
                {
                    ErrorMessage = "Corrupted data!";
                }
            }

            switch (Magic)
            {
            default:
                ErrorMessage = "Unexpected Magic 0x" + Magic.ToString("X");
                return;

            case 0x54414441:
                endianess = Endianess.LittleEndian;
                break;

            case 0x41444154:
                endianess = Endianess.BigEndian;
                break;
            }

            using (MemoryStream ms = new MemoryStream(data))
            {
                DataReader r = new DataReader(ms, endianess);

                Magic       = r.ReadUInt32();
                Version     = r.ReadUInt16();
                Flags       = r.ReadUInt16();
                StreamCount = r.ReadInt32();
                InfoOffset  = r.ReadInt32();


                //notes from libertyV:
                // first bit - means that there are unknown word for each stream after this header
                // second bit - I think that it means that not all the tags are in the start of the file, but all the tags of a stream are near the data tag
                // third bit - Multi channel audio

                if ((Flags >> 8) != 0xFF)
                {
                    ErrorMessage = "Flags 0 not supported!";
                    return;
                }
                if ((Flags & 0xF8) != 0)
                {
                    //ErrorMessage = "Flags 1 not supported!";
                    //return;
                }

                MultiChannel = ((Flags & 4) == 4);


                var flag0     = ((Flags & 1) == 1);
                var infoStart = 16 + (flag0 ? (StreamCount * 2) : 0);

                ms.Position = infoStart;

                List <AwcStreamInfo>             infos    = new List <AwcStreamInfo>();
                Dictionary <uint, AwcStreamInfo> infoDict = new Dictionary <uint, AwcStreamInfo>();
                List <uint>     audioIds = new List <uint>();
                List <AwcAudio> audios   = new List <AwcAudio>();

                for (int i = 0; i < StreamCount; i++)
                {
                    var info = new AwcStreamInfo(r);
                    infos.Add(info);
                    infoDict[info.Id] = info;
                }
                for (int i = 0; i < StreamCount; i++)
                {
                    var info = infos[i];
                    for (int j = 0; j < info.TagCount; j++)
                    {
                        var chunk = new AwcChunkInfo(r);
                        info.Chunks[chunk.Tag] = chunk;
                    }
                }

                StreamInfos = infos.ToArray();



                byte hformat = 0xFA; // 250  0x6061D4FA & 0xFF; //JenkHash.GenHash("format");
                byte hdata   = 0x55; // 85  0x5EB5E655 & 0xFF; //JenkHash.GenHash("data");
                byte hycd    = 0x5C; // 92  YCD resource chunk... lip sync anims?
                byte hunk    = 0x36; // 54  unk chunk? small number of bytes (2+)



                if (MultiChannel)
                {
                    AwcStreamInfo stream0 = null;
                    if (!infoDict.TryGetValue(0, out stream0))
                    {
                        ErrorMessage = "Couldn't find MultiChannel stream0";
                        return;
                    }

                    AwcChunkInfo chunk72 = null;
                    if (!stream0.Chunks.TryGetValue(72, out chunk72))
                    {
                        ErrorMessage = "Couldn't find MultiChannel chunk72";
                        return;
                    }

                    ms.Position = chunk72.Offset;

                    AwcChannelChunkInfo chanInfo = new AwcChannelChunkInfo(r);
                    if (chanInfo.ChannelCount != StreamCount - 1)
                    {
                        ErrorMessage = "Channel Count did not match Stream Count";
                        return;
                    }

                    List <AwcChannelChunkItemInfo> chunkItems = new List <AwcChannelChunkItemInfo>();
                    for (int i = 0; i < chanInfo.ChannelCount; i++)
                    {
                        var itemInfo = new AwcChannelChunkItemInfo(r);
                        chunkItems.Add(itemInfo);
                        audioIds.Add(infos[i + 1].Id);
                    }

                    //AudioStreams.Add(new MultiChannelAudio(new ChunkStream(this.Stream, streamsChunks[0][Tag("data")]), channelsInfoHeader, streamsInfo, header.BigEndian));

                    AwcChunkInfo cdata = null;
                    if (!stream0.Chunks.TryGetValue(hdata, out cdata))
                    {
                        ErrorMessage = "Couldn't find Stream 0 data chunk";
                        return;
                    }

                    ms.Position = cdata.Offset;
                    var lastPos = cdata.Offset + cdata.Size;
                    //int chunkSize = 0x800;
                    uint bigChunkSize = chanInfo.ChunkSize;
                    var  chanCount    = chanInfo.ChannelCount;

                    MultiChannelData = r.ReadBytes(cdata.Size);
                    ms.Position      = cdata.Offset;

                    //var d = data;//temporary

                    ////this doesn't seem to work :(
                    //while (ms.Position < lastPos)
                    //{
                    //    uint totalChunks = 0;
                    //    var startPos = ms.Position;
                    //    var curPos = startPos;
                    //    //byte[] chunkdata = r.ReadBytes(chunkSize);
                    //    //ms.Position = startPos;
                    //    AwcChannelChunkHeader[] chanHeaders = new AwcChannelChunkHeader[chanCount];
                    //    for (int i = 0; i < chanCount; i++)
                    //    {
                    //        var chanHeader = new AwcChannelChunkHeader(r);
                    //        chanHeaders[i] = chanHeader;
                    //        totalChunks += chanHeader.ChunkCount;
                    //    }
                    //    int headerSize = (int)(totalChunks * 4 + chanInfo.ChannelCount * AwcChannelChunkHeader.Size);
                    //    headerSize += (((-headerSize) % chunkSize) + chunkSize) % chunkSize; //todo: simplify this!
                    //    curPos += headerSize;
                    //    AwcChannelChunk[] chanChunks = new AwcChannelChunk[chanCount];
                    //    for (int i = 0; i < chanCount; i++)
                    //    {
                    //        var chanChunk = new AwcChannelChunk(r, chanHeaders[i], chunkItems[i]);
                    //        chanChunks[i] = chanChunk;
                    //        curPos += chanChunk.TotalDataSize;
                    //    }
                    //    if (curPos - startPos > chanInfo.ChunkSize)
                    //    {
                    //        ErrorMessage = "Chunk was bigger than the chunk size";
                    //        break;
                    //    }
                    //    if ((totalChunks == 0) || ((startPos + chanInfo.ChunkSize) > lastPos))
                    //    {
                    //        ErrorMessage = "Unable to read chunk";
                    //        break;
                    //    }
                    //    var newPos = startPos + bigChunkSize;
                    //    if (newPos >= lastPos) break;
                    //    ms.Position = newPos;
                    //}
                }
                else
                {
                    for (int i = 0; i < StreamCount; i++)
                    {
                        var info = infos[i];

                        AwcChunkInfo cformat = null;
                        if (!info.Chunks.TryGetValue(hformat, out cformat))
                        {
                            ErrorMessage = "Couldn't find Stream " + i.ToString() + " format chunk";
                            continue;
                        }

                        AwcChunkInfo cdata = null;
                        if (!info.Chunks.TryGetValue(hdata, out cdata))
                        {
                            ErrorMessage = "Couldn't find Stream " + i.ToString() + " data chunk";
                            continue;
                        }

                        AwcChunkInfo         cycd = null;
                        AwcAudioAnimClipDict oycd = null;
                        if (info.Chunks.TryGetValue(hycd, out cycd))
                        {
                            ms.Position = cycd.Offset;
                            oycd        = new AwcAudioAnimClipDict(r, cycd);
                        }

                        AwcChunkInfo cunk = null;
                        AwcAudioUnk  ounk = null;
                        if (info.Chunks.TryGetValue(hunk, out cunk))
                        {
                            ms.Position = cunk.Offset;
                            ounk        = new AwcAudioUnk(r, cunk);
                        }


                        ms.Position = cformat.Offset;
                        AwcFormatChunk formatChunk = new AwcFormatChunk(r);

                        ms.Position = cdata.Offset;
                        AwcAudio audio = new AwcAudio(r, info, formatChunk, cdata);

                        audio.ClipDict = oycd;
                        audio.UnkData  = ounk;

                        audios.Add(audio);
                        audioIds.Add(info.Id);
                    }
                }


                Audios   = audios.ToArray();
                AudioIds = audioIds.ToArray();
            }
        }
Example #2
0
        public void Load(byte[] data, RpfFileEntry entry)
        {
            //adapted from libertyV code


            //MemoryStream ms = new MemoryStream(data);
            Name      = entry.Name;
            FileEntry = entry;
            Data      = data;

            if ((data == null) || (data.Length < 8))
            {
                ErrorMessage = "Data null or too short!";
                return; //nothing to do, not enough data...
            }

            Magic = BitConverter.ToUInt32(data, 0);

            Endianess endianess = Endianess.LittleEndian;

            switch (Magic)
            {
            default:
                ErrorMessage = "Unexpected Magic 0x" + Magic.ToString("X");
                return;

            case 0x54414441:
                endianess = Endianess.LittleEndian;
                break;

            case 0x41444154:
                endianess = Endianess.BigEndian;
                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);

                Magic       = r.ReadUInt32();
                Version     = r.ReadUInt16();
                Flags       = r.ReadUInt16();
                StreamCount = r.ReadInt32();
                InfoOffset  = r.ReadInt32();


                //notes from libertyV:
                // first bit - means that there are unknown word for each stream after this header
                // second bit - I think that it means that not all the tags are in the start of the file, but all the tags of a stream are near the data tag
                // third bit - Multi channel audio

                if ((Flags >> 8) != 0xFF)
                {
                    ErrorMessage = "Flags 0 not supported!";
                    return;
                }
                if ((Flags & 0xF8) != 0)
                {
                    //ErrorMessage = "Flags 1 not supported!";
                    //return;
                }

                MultiChannel = ((Flags & 4) == 4);


                var flag0     = ((Flags & 1) == 1);
                var infoStart = 16 + (flag0 ? (StreamCount * 2) : 0);

                ms.Position = infoStart;

                List <AwcStreamInfo>             infos    = new List <AwcStreamInfo>();
                Dictionary <uint, AwcStreamInfo> infoDict = new Dictionary <uint, AwcStreamInfo>();
                List <uint>     audioIds = new List <uint>();
                List <AwcAudio> audios   = new List <AwcAudio>();

                for (int i = 0; i < StreamCount; i++)
                {
                    var info = new AwcStreamInfo(r);
                    infos.Add(info);
                    infoDict[info.Id] = info;
                }
                for (int i = 0; i < StreamCount; i++)
                {
                    var info = infos[i];
                    for (int j = 0; j < info.TagCount; j++)
                    {
                        var chunk = new AwcChunkInfo(r);
                        info.Chunks[chunk.Tag] = chunk;
                    }
                }

                StreamInfos = infos.ToArray();



                byte hformat = 0xFA; // 250  0x6061D4FA & 0xFF; //JenkHash.GenHash("format");
                byte hdata   = 0x55; // 85  0x5EB5E655 & 0xFF; //JenkHash.GenHash("data");
                byte hycd    = 0x5C; // 92  YCD resource chunk... lip sync anims?
                byte hunk    = 0x36; // 54  unk chunk? small number of bytes (2+)



                if (MultiChannel)
                {
                    AwcStreamInfo stream0 = null;
                    if (!infoDict.TryGetValue(0, out stream0))
                    {
                        ErrorMessage = "Couldn't find MultiChannel stream0";
                        return;
                    }

                    AwcChunkInfo chunk72 = null;
                    if (!stream0.Chunks.TryGetValue(72, out chunk72))
                    {
                        ErrorMessage = "Couldn't find MultiChannel chunk72";
                        return;
                    }

                    ms.Position = chunk72.Offset;

                    AwcChannelChunkInfo chanInfo = new AwcChannelChunkInfo(r);
                    if (chanInfo.ChannelCount != StreamCount - 1)
                    {
                        ErrorMessage = "Channel Count did not match Stream Count";
                        return;
                    }

                    List <AwcChannelChunkItemInfo> chunkItems = new List <AwcChannelChunkItemInfo>();
                    for (int i = 0; i < chanInfo.ChannelCount; i++)
                    {
                        var itemInfo = new AwcChannelChunkItemInfo(r);
                        chunkItems.Add(itemInfo);
                        audioIds.Add(infos[i + 1].Id);
                    }

                    //AudioStreams.Add(new MultiChannelAudio(new ChunkStream(this.Stream, streamsChunks[0][Tag("data")]), channelsInfoHeader, streamsInfo, header.BigEndian));

                    AwcChunkInfo cdata = null;
                    if (!stream0.Chunks.TryGetValue(hdata, out cdata))
                    {
                        ErrorMessage = "Couldn't find Stream 0 data chunk";
                        return;
                    }

                    ms.Position = cdata.Offset;
                    var lastPos = cdata.Offset + cdata.Size;
                    //int chunkSize = 0x800;
                    uint bigChunkSize = chanInfo.ChunkSize;
                    var  chanCount    = chanInfo.ChannelCount;

                    MultiChannelData = r.ReadBytes(cdata.Size);
                    ms.Position      = cdata.Offset;

                    //var d = data;//temporary

                    ////this doesn't seem to work :(
                    //while (ms.Position < lastPos)
                    //{
                    //    uint totalChunks = 0;
                    //    var startPos = ms.Position;
                    //    var curPos = startPos;
                    //    //byte[] chunkdata = r.ReadBytes(chunkSize);
                    //    //ms.Position = startPos;
                    //    AwcChannelChunkHeader[] chanHeaders = new AwcChannelChunkHeader[chanCount];
                    //    for (int i = 0; i < chanCount; i++)
                    //    {
                    //        var chanHeader = new AwcChannelChunkHeader(r);
                    //        chanHeaders[i] = chanHeader;
                    //        totalChunks += chanHeader.ChunkCount;
                    //    }
                    //    int headerSize = (int)(totalChunks * 4 + chanInfo.ChannelCount * AwcChannelChunkHeader.Size);
                    //    headerSize += (((-headerSize) % chunkSize) + chunkSize) % chunkSize; //todo: simplify this!
                    //    curPos += headerSize;
                    //    AwcChannelChunk[] chanChunks = new AwcChannelChunk[chanCount];
                    //    for (int i = 0; i < chanCount; i++)
                    //    {
                    //        var chanChunk = new AwcChannelChunk(r, chanHeaders[i], chunkItems[i]);
                    //        chanChunks[i] = chanChunk;
                    //        curPos += chanChunk.TotalDataSize;
                    //    }
                    //    if (curPos - startPos > chanInfo.ChunkSize)
                    //    {
                    //        ErrorMessage = "Chunk was bigger than the chunk size";
                    //        break;
                    //    }
                    //    if ((totalChunks == 0) || ((startPos + chanInfo.ChunkSize) > lastPos))
                    //    {
                    //        ErrorMessage = "Unable to read chunk";
                    //        break;
                    //    }
                    //    var newPos = startPos + bigChunkSize;
                    //    if (newPos >= lastPos) break;
                    //    ms.Position = newPos;
                    //}
                }
                else
                {
                    for (int i = 0; i < StreamCount; i++)
                    {
                        var info = infos[i];

                        AwcChunkInfo cformat = null;
                        if (!info.Chunks.TryGetValue(hformat, out cformat))
                        {
                            ErrorMessage = "Couldn't find Stream " + i.ToString() + " format chunk";
                            continue;
                        }

                        AwcChunkInfo cdata = null;
                        if (!info.Chunks.TryGetValue(hdata, out cdata))
                        {
                            ErrorMessage = "Couldn't find Stream " + i.ToString() + " data chunk";
                            continue;
                        }

                        AwcChunkInfo         cycd = null;
                        AwcAudioAnimClipDict oycd = null;
                        if (info.Chunks.TryGetValue(hycd, out cycd))
                        {
                            ms.Position = cycd.Offset;
                            oycd        = new AwcAudioAnimClipDict(r, cycd);
                        }

                        AwcChunkInfo cunk = null;
                        AwcAudioUnk  ounk = null;
                        if (info.Chunks.TryGetValue(hunk, out cunk))
                        {
                            ms.Position = cunk.Offset;
                            ounk        = new AwcAudioUnk(r, cunk);
                        }


                        ms.Position = cformat.Offset;
                        AwcFormatChunk formatChunk = new AwcFormatChunk(r);

                        ms.Position = cdata.Offset;
                        AwcAudio audio = new AwcAudio(r, info, formatChunk, cdata);

                        audio.ClipDict = oycd;
                        audio.UnkData  = ounk;

                        audios.Add(audio);
                        audioIds.Add(info.Id);
                    }
                }


                Audios   = audios.ToArray();
                AudioIds = audioIds.ToArray();
            }
        }