Exemple #1
0
        public CPK(Stream data)
        {
            EndianReader reader   = new EndianReader(data, Endianness.BigEndian);
            EndianReader lereader = new EndianReader(data, Endianness.LittleEndian);

            if (reader.ReadUInt32() != CpkMagic)
            {
                throw new FormatException();
            }

            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; section size; 0x00;
            }
            Header = new UTF(data);

            if (Header.Rows.Count != 1)
            {
                throw new FormatException();
            }

            UTF.Row mainrow = Header.Rows[0];

            long tocoffset  = (long)(mainrow.FindValue("TocOffset") as UTF.LongValue).Value;
            long etocoffset = (long)(mainrow.FindValue("EtocOffset") as UTF.LongValue).Value;
            long itocoffset = (long)(mainrow.FindValue("ItocOffset") as UTF.LongValue).Value;
            //long dpkitocoffset = (long)(mainrow.FindValue("DpkItoc") as UTF.IntValue).Value;
            long contentoffset = (long)(mainrow.FindValue("ContentOffset") as UTF.LongValue).Value;
            uint filecount     = (mainrow.FindValue("Files") as UTF.IntValue).Value;

            UTF.ShortValue version = mainrow.FindValue("Version") as UTF.ShortValue;
            UTF.IntValue   mode    = mainrow.FindValue("Mode") as UTF.IntValue;
            if (version != null)
            {
                Version = version.Value;
            }
            if (mode != null)
            {
                Mode = mode.Value;
            }

            reader.Position = tocoffset;
            if (reader.ReadUInt32() != TocMagic)
            {
                throw new FormatException();
            }
            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; size; 0x00;
            }
            ToC = new UTF(data);

            reader.Position = etocoffset;
            if (reader.ReadUInt32() != ETocMagic)
            {
                throw new FormatException();
            }
            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; size; 0x00;
            }
            EToC = new UTF(data);

            reader.Position = itocoffset;
            if (reader.ReadUInt32() != ITocMagic)
            {
                throw new FormatException();
            }
            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; size; 0x00;
            }
            IToC = new UTF(data);

            Cache = new DelayedStreamCache();

            Root = new DirectoryNode();
            foreach (var filerow in ToC.Rows)
            {
                UTF.StringValue dirnamevalue = filerow.FindValue("DirName") as UTF.StringValue;
                string          dirname      = string.Empty;
                if (dirnamevalue != null)
                {
                    dirname = dirnamevalue.Value;
                }
                long   offset     = (long)(filerow.FindValue("FileOffset") as UTF.LongValue).Value;
                string filename   = (filerow.FindValue("FileName") as UTF.StringValue).Value;
                uint   packedsize = (filerow.FindValue("FileSize") as UTF.IntValue).Value;
                uint   filesize   = packedsize;

                if (Version == 7)                 // ToGf
                {
                    offset += tocoffset;
                }
                else                 // Need to check ToG:Wii's version/mode
                {
                    offset += contentoffset;
                }

                UTF.IntValue filesizevalue = filerow.FindValue("ExtractSize") as UTF.IntValue;
                if (filesizevalue != null)
                {
                    filesize = filesizevalue.Value;
                }
                else                   // If we must, read the uncompressed size from the internal compressed file itself
                {
                    data.Position = offset;
                    EndianReader littlereader = new EndianReader(data, Endianness.LittleEndian);
                    if (littlereader.ReadUInt64() == 0)
                    {
                        filesize = littlereader.ReadUInt32() + 0x100;
                    }
                }

                DirectoryNode dir       = Root.Navigate(dirname, true) as DirectoryNode;
                Stream        substream = new Substream(data, offset, packedsize);
                try {
                    if (filesize > packedsize)
                    {
                        //throw new Exception();
                        Stream compressed = substream;
                        substream = new DelayedStream(delegate() {
                            Stream ret = new TemporaryStream();
                            CpkCompression.Decompress(compressed, ret);
                            ret.Position = 0;
                            return(ret);
                        });
                        Cache.AddStream(substream);
                    }
                    dir.AddChild(new FileNode(filename, filesize, substream));
                } catch {
                    dir.AddChild(new FileNode(filename, packedsize, substream));
                }
            }

            // TODO: EToc: Groups

            // TODO: IToc: Attributes
        }
Exemple #2
0
 public Row(UTF parent, uint size)
 {
     Parent = parent;
     Values = new List <Value>();
     Size   = size;
 }