コード例 #1
0
        public override void Construct(BinaryEndianReader br, QbItemType type)
        {
            //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0')));

            _isUnicode = ((type == QbItemType.SectionStringW || type == QbItemType.ArrayStringW || type == QbItemType.StructItemStringW) &&
                          (base.Root.PakFormat.PakFormatType == PakFormatType.PC || base.Root.PakFormat.PakFormatType == PakFormatType.XBox));

            byte[] bytes;

            base.Construct(br, type);

            this.Strings = new string[base.ItemCount];

            _charWidth = !_isUnicode ? 1 : 2;

            if (base.ItemCount != 0)
            {
                //use pointers to read quickly
                if (base.ItemCount > 1)
                {
                    for (int i = 0; i < base.ItemCount - 1; i++)
                    {
                        if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                        {
                            throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));
                        }

                        bytes = br.ReadBytes((int)((base.Pointers[i + 1] - _charWidth) - base.StreamPos(br)));

                        _strings[i] = bytesToString(bytes); //handles unicode

                        if (!_isUnicode ? (br.ReadByte() != 0) : (br.ReadByte() != 0 || br.ReadByte() != 0))
                        {
                            throw new ApplicationException(string.Format("Null byte expected reading string array at 0x{0}", (base.StreamPos(br) - _charWidth).ToString("X").PadLeft(8, '0')));
                        }
                    }

                    if (base.StreamPos(br) != base.Pointers[base.ItemCount - 1]) //pointer test
                    {
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[base.ItemCount - 1]));
                    }
                }


                //use the slow method read the last string
                StringBuilder sb = new StringBuilder();
                //if we have come from an array we must align our position to %4
                int byteAmount = (int)(4 - (base.StreamPos(br) % 4));

                do
                {
                    bytes = br.ReadBytes(byteAmount);
                    sb.Append(bytesToString(bytes));
                    byteAmount = 4;
                }while (!_isUnicode ? (bytes[bytes.Length - 1] != '\0') : (bytes[bytes.Length - 1] != '\0' || bytes[bytes.Length - 2] != '\0'));


                //get text and remove any trailing null bytes
                _strings[base.ItemCount - 1] = sb.ToString().TrimEnd(new char[] { '\0' });
            }
            base.ConstructEnd(br);
        }
コード例 #2
0
ファイル: QbItemString.cs プロジェクト: Nanook/Queen-Bee
        public override void Construct(BinaryEndianReader br, QbItemType type)
        {
            //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0')));

            _isUnicode = ((type == QbItemType.SectionStringW || type == QbItemType.ArrayStringW || type == QbItemType.StructItemStringW) &&
                (base.Root.PakFormat.PakFormatType == PakFormatType.PC || base.Root.PakFormat.PakFormatType == PakFormatType.XBox));

            byte[] bytes;

            base.Construct(br, type);

            this.Strings = new string[base.ItemCount];

            _charWidth = !_isUnicode ? 1 : 2;

            if (base.ItemCount != 0)
            {
                //use pointers to read quickly
                if (base.ItemCount > 1)
                {

                    for (int i = 0; i < base.ItemCount - 1; i++)
                    {
                        if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                            throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));

                        bytes = br.ReadBytes((int)((base.Pointers[i + 1] - _charWidth) - base.StreamPos(br)));

                        _strings[i] = bytesToString(bytes); //handles unicode

                        if (!_isUnicode ? (br.ReadByte() != 0) : (br.ReadByte() != 0 || br.ReadByte() != 0))
                            throw new ApplicationException(string.Format("Null byte expected reading string array at 0x{0}", (base.StreamPos(br) - _charWidth).ToString("X").PadLeft(8, '0')));
                    }

                    if (base.StreamPos(br) != base.Pointers[base.ItemCount - 1]) //pointer test
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[base.ItemCount - 1]));
                }

                //use the slow method read the last string
                StringBuilder sb = new StringBuilder();
                //if we have come from an array we must align our position to %4
                int byteAmount = (int)(4 - (base.StreamPos(br) % 4));

                do
                {
                    bytes = br.ReadBytes(byteAmount);
                    sb.Append(bytesToString(bytes));
                    byteAmount = 4;
                }
                while (!_isUnicode ? (bytes[bytes.Length - 1] != '\0') : (bytes[bytes.Length - 1] != '\0' || bytes[bytes.Length - 2] != '\0'));

                //get text and remove any trailing null bytes
                _strings[base.ItemCount - 1] = sb.ToString().TrimEnd(new char[] { '\0' });
            }
            base.ConstructEnd(br);
        }
コード例 #3
0
ファイル: WiiIso.cs プロジェクト: Nanook/TheGHOST
        public static void BuildPartition(string partitionBinFilename,
                                          string mainDolFilename,
                                          string appLoaderImgFilename,
                                          string bi2BinFilename,
                                          string bootBinFilename,
                                          string sourceDirectory,
                                          string partitionFilename,
                                          bool deleteWhileBuilding)
        {
            ulong totalSize = 0;

            BinaryEndianReader brFst = null;
            BinaryEndianWriter bwFst = new BinaryEndianWriter(new MemoryStream());
            BinaryEndianWriter bwStr = new BinaryEndianWriter(new MemoryStream());
            BinaryEndianWriter bwBootBin = null;
            BinaryEndianWriter bwPartitionBin = null;
            BinaryEndianWriter bwB12Bin = null;

            try
            {

                DirectoryInfo inputFolder = new DirectoryInfo(sourceDirectory);

                //DateTime n = DateTime.Now;
                uint fileCount = recurseFiles(true, inputFolder, bwFst, bwStr, ref totalSize, 0, null, 0, deleteWhileBuilding);
                //System.Diagnostics.Debug.WriteLine((DateTime.Now - n).Ticks);

                // get the file sizes we need - apploader and main.dol
                FileInfo appLoaderImg = new FileInfo(appLoaderImgFilename);
                FileInfo mainDol = new FileInfo(mainDolFilename);

                // now calculate the relative offsets
                uint pad1Size = 0x100 - (((uint)appLoaderImg.Length + 0x2440) % 0x100);
                uint pad2Size = 0x100 - ((uint)mainDol.Length % 0x100);

                // just a pad out for no real reason :)
                uint pad3Size = 0x2000;

                uint mainDolOffset = 0x2440 + (uint)appLoaderImg.Length + pad1Size;
                uint fstOffset = mainDolOffset + pad2Size + (uint)mainDol.Length;

                // modify the data size in partition.bin
                // read in partition.bin
                bwPartitionBin = new BinaryEndianWriter(new MemoryStream(File.ReadAllBytes(partitionBinFilename)));

                // now Actual size = scaled up by sizes
                totalSize += pad1Size + 0x2440 + pad2Size + pad3Size + (uint)mainDol.Length + (uint)appLoaderImg.Length;

                ulong dataSize = (totalSize / 0x7c00) * 0x8000;
                if (dataSize % 0x7c00 != 0)
                    dataSize += 0x8000;

                bwPartitionBin.Seek(0x2BC, SeekOrigin.Begin);
                bwPartitionBin.Write((uint)dataSize >> 2, EndianType.Big);

                // generate a boot.bin
                bwBootBin = new BinaryEndianWriter(new MemoryStream(File.ReadAllBytes(bootBinFilename)));
                // now the size offsets
                bwBootBin.Seek(0x420, SeekOrigin.Begin);
                bwBootBin.Write(mainDolOffset >> 2, EndianType.Big);
                bwBootBin.Write(fstOffset >> 2, EndianType.Big);
                bwBootBin.Write((uint)(bwFst.BaseStream.Length + bwStr.BaseStream.Length) >> 2, EndianType.Big);
                bwBootBin.Write((uint)(bwFst.BaseStream.Length + bwStr.BaseStream.Length) >> 2, EndianType.Big);

                // calculate what we need to modify the FST entries by
                ulong dataOffset = 0x2440 + pad1Size + (uint)appLoaderImg.Length + (uint)mainDol.Length + pad2Size + (uint)bwFst.BaseStream.Length + (uint)bwStr.BaseStream.Length + pad3Size;
                dataOffset = (dataOffset >> 2);

                // modify the fst.bin to include all the correct offsets
                brFst = new BinaryEndianReader(bwFst.BaseStream);
                brFst.BaseStream.Seek(8, SeekOrigin.Begin);
                uint fstEntries = brFst.ReadUInt32(EndianType.Big);

                for (int i = 1; i < fstEntries; i++) //1 as we've already skipped the root
                {
                    if (brFst.ReadByte() == 0) //file
                    {
                        brFst.BaseStream.Seek(3, SeekOrigin.Current); //skip the rest of the uint
                        uint temp = brFst.ReadUInt32(EndianType.Big);
                        bwFst.BaseStream.Seek(-4, SeekOrigin.Current); //THE STREAMS ARE THE SAME (be careful of bugs when the position moves)
                        bwFst.Write((uint)dataOffset + temp, EndianType.Big);
                        brFst.BaseStream.Seek(4, SeekOrigin.Current); //skip the rest of the file
                    }
                    else
                        brFst.BaseStream.Seek(0xc - 1, SeekOrigin.Current); //skip the rest of the directory
                }

                using (FileStream fs = new FileStream(partitionFilename, FileMode.Create))
                {
                    copyStream(bwPartitionBin.BaseStream, fs, 4);

                    copyStream(bwBootBin.BaseStream, fs, 4);

                    copyStream(bi2BinFilename, fs, 4);

                    copyStream(appLoaderImgFilename, fs, 4);

                    fs.Write(new byte[pad1Size], 0, (int)pad1Size);

                    copyStream(mainDolFilename, fs, 4);

                    fs.Write(new byte[pad2Size], 0, (int)pad2Size);

                    copyStream(bwFst.BaseStream, fs, 4);

                    copyStream(bwStr.BaseStream, fs, 4);

                    fs.Write(new byte[pad3Size], 0, (int)pad3Size);

                    //copy all the files to the end of the partition
                    totalSize = dataOffset; //will give the offsets the correct value (not that it matters here heh)
                    bwFst.BaseStream.Seek(0, SeekOrigin.Begin);
                    bwStr.BaseStream.Seek(0, SeekOrigin.Begin);
                    recurseFiles(true, inputFolder, bwFst, bwStr, ref totalSize, 0, fs, (ulong)fs.Position - dataOffset, deleteWhileBuilding);

                    if (deleteWhileBuilding)
                    {
                        try
                        {
                            inputFolder.Delete(true);
                        }
                        catch
                        {
                        }
                    }
                }

            }
            finally
            {
                if (brFst != null)
                    brFst.Close();
                bwFst.Close();
                bwStr.Close();
                if (bwBootBin != null)
                    bwBootBin.Close();
                if (bwPartitionBin != null)
                    bwPartitionBin.Close();
                if (bwB12Bin != null)
                    bwB12Bin.Close();
            }
        }