Esempio n. 1
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: @Override public void readSector(int sectorNumber, byte[] buffer, int offset) throws java.io.IOException
        public override void readSector(int sectorNumber, sbyte[] buffer, int offset)
        {
            int lba = sectorNumber - currentBlock;

            if (table == null)
            {
                Arrays.Fill(buffer, offset, offset + ISectorDevice_Fields.sectorLength, (sbyte)0);
            }
            else if (currentBlock >= 0 && lba >= 0 && lba < blockLBAs)
            {
                Array.Copy(blockBuffer, lba * ISectorDevice_Fields.sectorLength, buffer, offset, ISectorDevice_Fields.sectorLength);
            }
            else
            {
                int block = sectorNumber / blockLBAs;
                lba          = sectorNumber % blockLBAs;
                currentBlock = block * blockLBAs;

                if (table[block].unknown == 0)
                {
                    fileAccess.seek(offsetPsarData + table[block].offset);

                    sbyte[] readBuffer;
                    if (table[block].size < blockSize)
                    {
                        // For compressed blocks, decode into a temporary buffer
                        readBuffer = tempBuffer;
                    }
                    else
                    {
                        readBuffer = blockBuffer;
                    }

                    int readSize = fileAccess.read(readBuffer, 0, table[block].size);
                    if (readSize == table[block].size)
                    {
                        if ((table[block].flags & TableInfo.FLAG_IS_UNCRYPTED) == 0)
                        {
                            AMCTRL.BBCipher_Ctx cipherContext = new AMCTRL.BBCipher_Ctx();
                            amctrl.hleDrmBBCipherInit(cipherContext, 1, 2, hkey, vkey, table[block].offset >> 4);
                            amctrl.hleDrmBBCipherUpdate(cipherContext, readBuffer, table[block].size);
                            amctrl.hleDrmBBCipherFinal(cipherContext);
                        }

                        // Compressed block?
                        if (table[block].size < blockSize)
                        {
                            int lzsize = lzrc_decompress(blockBuffer, blockBuffer.Length, readBuffer, table[block].size);
                            if (lzsize != blockSize)
                            {
                                Console.WriteLine(string.Format("LZRC decompress error: decompressedSized={0:D}, should be {1:D}", lzsize, blockSize));
                            }
                        }

                        Array.Copy(blockBuffer, lba * ISectorDevice_Fields.sectorLength, buffer, offset, ISectorDevice_Fields.sectorLength);
                    }
                }
            }
        }
Esempio n. 2
0
        public PBPFileSectorDevice(RandomAccessFile fileAccess) : base(fileAccess)
        {
            try
            {
                int magic   = endianSwap32(fileAccess.readInt());
                int version = endianSwap32(fileAccess.readInt());
                offsetParamSFO = endianSwap32(fileAccess.readInt());
                offsetIcon0    = endianSwap32(fileAccess.readInt());
                offsetIcon1    = endianSwap32(fileAccess.readInt());
                offsetPic0     = endianSwap32(fileAccess.readInt());
                offsetPic1     = endianSwap32(fileAccess.readInt());
                offsetSnd0     = endianSwap32(fileAccess.readInt());
                offsetPspData  = endianSwap32(fileAccess.readInt());
                offsetPsarData = endianSwap32(fileAccess.readInt());
                if (magic != 0x50425000)
                {
                    throw new IOException(string.Format("Invalid PBP header 0x{0:X8}", magic));
                }
                if (version != 0x00010000 && version != 0x00000100 && version != 0x00010001)
                {
                    throw new IOException(string.Format("Invalid PBP version 0x{0:X8}", version));
                }
                fileAccess.seek(offsetPsarData);
                sbyte[] header   = new sbyte[256];
                int     readSize = fileAccess.read(header);
                if (readSize != header.Length)
                {
                    int psarDataLength = (int)(fileAccess.Length() - offsetPsarData);
                    if (psarDataLength != 0 && psarDataLength != 16)
                    {
                        throw new IOException(string.Format("Invalid PBP header"));
                    }
                }
                else if (header[0] == (sbyte)'N' && header[1] == (sbyte)'P' && header[2] == (sbyte)'U' && header[3] == (sbyte)'M' && header[4] == (sbyte)'D' && header[5] == (sbyte)'I' && header[6] == (sbyte)'M' && header[7] == (sbyte)'G')
                {
                    CryptoEngine cryptoEngine = new CryptoEngine();
                    amctrl = cryptoEngine.AMCTRLEngine;

                    AMCTRL.BBMac_Ctx    macContext    = new AMCTRL.BBMac_Ctx();
                    AMCTRL.BBCipher_Ctx cipherContext = new AMCTRL.BBCipher_Ctx();

                    // getKey
                    amctrl.hleDrmBBMacInit(macContext, 3);
                    amctrl.hleDrmBBMacUpdate(macContext, header, 0xC0);
                    sbyte[] macKeyC0 = new sbyte[16];
                    Array.Copy(header, 0xC0, macKeyC0, 0, macKeyC0.Length);
                    vkey = amctrl.GetKeyFromBBMac(macContext, macKeyC0);

                    // decrypt NP header
                    sbyte[] cipherData = new sbyte[0x60];
                    Array.Copy(header, 0x40, cipherData, 0, cipherData.Length);
                    Array.Copy(header, 0xA0, hkey, 0, hkey.Length);
                    amctrl.hleDrmBBCipherInit(cipherContext, 1, 2, hkey, vkey);
                    amctrl.hleDrmBBCipherUpdate(cipherContext, cipherData, cipherData.Length);
                    amctrl.hleDrmBBCipherFinal(cipherContext);

                    int lbaStart = Utilities.readUnaligned32(cipherData, 0x14);
                    int lbaEnd   = Utilities.readUnaligned32(cipherData, 0x24);
                    numSectors = lbaEnd + 1;
                    lbaSize    = numSectors - lbaStart;
                    blockLBAs  = Utilities.readUnaligned32(header, 0x0C);
                    blockSize  = blockLBAs * ISectorDevice_Fields.sectorLength;
                    numBlocks  = (lbaSize + blockLBAs - 1) / blockLBAs;

                    blockBuffer = new sbyte[blockSize];
                    tempBuffer  = new sbyte[blockSize];

                    table = new TableInfo[numBlocks];

                    int tableOffset = Utilities.readUnaligned32(cipherData, 0x2C);
                    fileAccess.seek(offsetPsarData + tableOffset);
                    sbyte[] tableBytes = new sbyte[numBlocks * 32];
                    readSize = fileAccess.read(tableBytes);
                    if (readSize != tableBytes.Length)
                    {
                        Console.WriteLine(string.Format("Could not read table with size {0:D} (readSize={1:D})", tableBytes.Length, readSize));
                    }

                    IntBuffer tableInts = ByteBuffer.wrap(tableBytes).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
                    for (int i = 0; i < numBlocks; i++)
                    {
                        int p0 = tableInts.get();
                        int p1 = tableInts.get();
                        int p2 = tableInts.get();
                        int p3 = tableInts.get();
                        int p4 = tableInts.get();
                        int p5 = tableInts.get();
                        int p6 = tableInts.get();
                        int p7 = tableInts.get();
                        int k0 = p0 ^ p1;
                        int k1 = p1 ^ p2;
                        int k2 = p0 ^ p3;
                        int k3 = p2 ^ p3;

                        TableInfo tableInfo = new TableInfo();
                        Array.Copy(tableBytes, i * 32, tableInfo.mac, 0, tableInfo.mac.Length);
                        tableInfo.offset  = p4 ^ k3;
                        tableInfo.size    = p5 ^ k1;
                        tableInfo.flags   = p6 ^ k2;
                        tableInfo.unknown = p7 ^ k0;
                        table[i]          = tableInfo;
                    }

                    currentBlock = -1;
                }
            }
            catch (IOException e)
            {
                Console.WriteLine("Reading PBP", e);
            }
        }