示例#1
0
        public GT3DemoVol(string file)
        {
            volFile = new FileStream(file, FileMode.Open, FileAccess.Read);
            byte[] intArray = new byte[4];
            volFile.Seek(8, SeekOrigin.Begin);
            volFile.Read(intArray, 0, 4);
            uint headerSize = BitConverter.ToUInt32(intArray, 0);

            volFile.Seek(0, SeekOrigin.Begin);
            byte[] header = new byte[headerSize];
            volFile.Read(header, 0, (int)headerSize);
            Debug.Assert((header[0] == 'R') && (header[1] == 'o') && (header[2] == 'F') && (header[3] == 'S'));

            MemoryStream ms = new MemoryStream(header, false);

            ms.Seek(0xc, SeekOrigin.Begin);
            BinaryReader br            = new BinaryReader(ms, Encoding.UTF8);
            uint         rootEntryData = br.ReadUInt32();

            if ((rootEntryData & Flags.Directory) != Flags.Directory)
            {
                Console.Error.WriteLine("{0} is an invalid VOL", file);
                volFile.Close();
                return;
            }
            uint nameOffset = (rootEntryData & Flags.TurnOffFlags);

            rootVolEntry             = new VolEntryInfo();
            rootVolEntry.size        = 0;
            rootVolEntry.fileAddress = 0xc;
            rootVolEntry.name        = ReadNullTermName(br, nameOffset);
            rootVolEntry.children    = ParseDirectory(br);
        }
示例#2
0
        public GT3Vol(string file)
        {
            volFile = new FileStream(file, FileMode.Open, FileAccess.Read);
            byte[] magic = new byte[4];
            volFile.Read(magic, 0, magic.Length);
            // if this is a demo vol
            if ((magic[0] == 'R') && (magic[1] == 'o') && (magic[2] == 'F') && (magic[3] == 'S'))
            {
                isDemoVol      = true;
                compressedFlag = 0x2;
                directoryFlag  = 0x1;
            }
            // this is 'RoFS' but bitwise not-ted
            else if ((magic[0] == 0xAD) && (magic[1] == 0x90) && (magic[2] == 0xB9) && (magic[3] == 0xAC))
            {
                isDemoVol      = false;
                compressedFlag = 0x02000000;
                directoryFlag  = 0x01000000;
            }
            else
            {
                volFile.Close();
                throw new FileLoadException("This isn't a GT3 VOL");
            }
            allFlags     = compressedFlag | directoryFlag;
            turnOffFlags = ~allFlags;

            byte[] intArray = new byte[4];
            volFile.Seek(8, SeekOrigin.Begin);
            volFile.Read(intArray, 0, 4);
            uint headerSize = BitConverter.ToUInt32(intArray, 0);

            volFile.Seek(0, SeekOrigin.Begin);
            byte[] header = new byte[headerSize];
            volFile.Read(header, 0, (int)headerSize);
            MemoryStream ms = new MemoryStream(header, false);
            BinaryReader br = new BinaryReader(ms);

            br.BaseStream.Seek(0xc, SeekOrigin.Begin);
            if (!isDemoVol)
            {
                //volFile.Read(intArray, 0, 4);
                //uint namesOffset = BitConverter.ToUInt32(intArray, 0) + 1;
                uint namesOffset = br.ReadUInt32();

                uint namesSize = headerSize - namesOffset;
                for (uint i = namesOffset; i < headerSize; ++i)
                {
                    header[i] = (byte)~header[i];
                }
                br.BaseStream.Seek(0x14, SeekOrigin.Begin);
            }

            uint rootEntryData = br.ReadUInt32();

            if ((rootEntryData & directoryFlag) != directoryFlag)
            {
                Console.Error.WriteLine("{0} is an invalid VOL", file);
                volFile.Close();
                throw new FileLoadException("Don't recognize this type of GT3.VOL");
            }
            uint nameOffset = rootEntryData & turnOffFlags;

            rootVolEntry             = new VolEntryInfo();
            rootVolEntry.size        = 0;
            rootVolEntry.fileAddress = isDemoVol ? 0xcu : 0x14u;
            rootVolEntry.name        = ReadNullTermName(br, nameOffset);
            rootVolEntry.children    = ParseDirectory(br);
        }
示例#3
0
        private List <VolEntryInfo> ParseDirectory(BinaryReader br)
        {
            int numEntries = br.ReadInt32();
            List <VolEntryInfo> entryInfo = new List <VolEntryInfo>(numEntries);
            long currentFileOffset        = br.BaseStream.Position;

            for (int i = 0; i < numEntries; ++i)
            {
                uint entryOffset  = (uint)br.BaseStream.Position;
                uint entry        = br.ReadUInt32();
                uint entryFlag    = entry & allFlags;
                uint entryPointer = entry & turnOffFlags;
                // directory entries are offsets to data about the entries
                // the flags for directories etc are in this data, not the entries themselves
                Debug.Assert(entryFlag == 0);
                // parent entry
                if (entryPointer < currentFileOffset)
                {
                    continue;
                }
                uint         offsetValue    = GetValueAtOffset(br, entryPointer);
                uint         offsetFlag     = offsetValue & allFlags;
                uint         offsetPosition = offsetValue & turnOffFlags;
                string       entryName      = ReadNullTermName(br, offsetPosition);
                VolEntryInfo volEntry       = new VolEntryInfo();
                volEntry.children        = null;
                volEntry.name            = entryName;
                volEntry.isCompressed    = false;
                volEntry.entryAddress    = entryOffset;
                volEntry.fileInfoAddress = entryPointer;
                if (offsetFlag == directoryFlag)
                {
                    volEntry.size = 0;
                    long preParsePos = br.BaseStream.Position;
                    br.BaseStream.Seek(entryPointer + 4, SeekOrigin.Begin);
                    volEntry.children = ParseDirectory(br);
                    br.BaseStream.Seek(preParsePos, SeekOrigin.Begin);
                }
                else if (offsetFlag == compressedFlag) // compressed file (gzip)
                {
                    // high byte 2 = gzip compressed file (lower 3 bytes, name offset)
                    //  first entry = file data offset
                    //  second entry = decompressed size
                    //  third entry = compressed size (ie the size of the data in the vol)
                    volEntry.isCompressed = true;
                    long preParsePos = br.BaseStream.Position;
                    br.BaseStream.Seek(entryPointer + 4, SeekOrigin.Begin);
                    uint dataOffset = br.ReadUInt32() * 0x800;
                    volEntry.fileAddress = dataOffset;
                    br.ReadUInt32(); // decompressed size, not needed
                    volEntry.size = br.ReadUInt32();
                    br.BaseStream.Seek(preParsePos, SeekOrigin.Begin);
                }
                else // entry
                {
                    Debug.Assert(offsetFlag == 0);
                    long preParsePos = br.BaseStream.Position;
                    br.BaseStream.Seek(entryPointer + 4, SeekOrigin.Begin);
                    uint dataOffset = br.ReadUInt32() * 0x800;
                    volEntry.fileAddress = dataOffset;
                    volEntry.size        = br.ReadUInt32();
                    if (isDemoVol)
                    {
                        // the demo has 4 entries for both compressed and normal files
                        br.ReadUInt32();
                    }
                    br.BaseStream.Seek(preParsePos, SeekOrigin.Begin);
                }
                entryInfo.Add(volEntry);
            }
            return(entryInfo);
        }
示例#4
0
        private List <VolEntryInfo> ParseDirectory(BinaryReader br)
        {
            int numEntries = br.ReadInt32();
            List <VolEntryInfo> entryInfo = new List <VolEntryInfo>(numEntries);
            long currentFileOffset        = br.BaseStream.Position;

            for (int i = 0; i < numEntries; ++i)
            {
                uint entryOffset  = (uint)br.BaseStream.Position;
                uint entry        = br.ReadUInt32();
                uint entryFlag    = (entry & Flags.AllFlags);
                uint entryPointer = entry & ~Flags.TurnOffFlags;
                // directory entries are offsets to data about the entries
                // the flags for directories etc are in this data, not the entries themselves
                Debug.Assert(entryFlag == 0);
                // parent entry
                if (entryPointer < currentFileOffset)
                {
                    continue;
                }
                uint         offsetValue    = GetValueAtOffset(br, entryPointer);
                uint         offsetFlag     = offsetValue & Flags.AllFlags;
                uint         offsetPosition = offsetValue & Flags.TurnOffFlags;
                string       entryName      = ReadNullTermName(br, offsetPosition);
                VolEntryInfo volEntry       = new VolEntryInfo();
                volEntry.children        = null;
                volEntry.name            = entryName;
                volEntry.isCompressed    = false;
                volEntry.entryAddress    = entryOffset;
                volEntry.fileInfoAddress = entryPointer;
                switch (offsetFlag)
                {
                case 1:     // directory
                {
                    volEntry.size = 0;
                    long preParsePos = br.BaseStream.Position;
                    br.BaseStream.Seek(entryPointer + 4, SeekOrigin.Begin);
                    volEntry.children = ParseDirectory(br);
                    br.BaseStream.Seek(preParsePos, SeekOrigin.Begin);
                }
                break;

                case 2:     // compressed file (gzip)
                case 0:     // uncompressed file
                {
                    // files -
                    //  first entry = file data offset
                    //  second entry = decompressed size
                    //  third entry = compressed size (ie the size of the data in the vol)
                    volEntry.isCompressed = (offsetFlag == 2);
                    long preParsePos = br.BaseStream.Position;
                    br.BaseStream.Seek(entryPointer + 4, SeekOrigin.Begin);
                    uint dataOffset = br.ReadUInt32() * 0x800;
                    volEntry.fileAddress = dataOffset;
                    br.ReadUInt32();         // decompressed size, not needed
                    volEntry.size = br.ReadUInt32();
                    br.BaseStream.Seek(preParsePos, SeekOrigin.Begin);
                }
                break;

                default:
                {
                    Debug.Assert(false);
                }
                break;
                }
                entryInfo.Add(volEntry);
            }
            return(entryInfo);
        }