Beispiel #1
0
        public static void DecryptNgxRom(string inPath, string outPath)
        {
            File.Copy(inPath, outPath, true);
            using (var fs = File.Open(outPath, FileMode.Open, FileAccess.ReadWrite))
            {
                BinaryReader br = new BinaryReader(fs);
                fs.Seek(-8, SeekOrigin.End);
                int    unencryptedStart = br.ReadInt32() ^ 0x12345678;
                int    unencryptedEnd   = br.ReadInt32() ^ 0x12345678;
                int    keyLength;
                byte[] keyData = GetNgxRomKey(br, unencryptedStart, unencryptedEnd, out keyLength);

                BurnCacheHeader header = null;
                CryptNgxRom(fs, ref header, keyData, keyLength);

                // Swap sprite and text blocks
                BinaryWriter bw = new BinaryWriter(fs);
                fs.Seek(header.Blocks[1].Offset, SeekOrigin.Begin);
                byte[] textBlock   = br.ReadBytes((int)header.GetLength(1));
                byte[] spriteBlock = br.ReadBytes((int)header.GetLength(2));
                fs.Seek(header.Blocks[1].Offset, SeekOrigin.Begin);
                bw.Write(spriteBlock);
                header.Blocks[2].Offset = (uint)fs.Position;
                bw.Write(textBlock);

                // Update header
                fs.Seek(0, SeekOrigin.Begin);
                header.Write(bw);

                fs.SetLength(fs.Length - 8);
            }
        }
Beispiel #2
0
        static void CryptNgxRom(Stream fs, ref BurnCacheHeader header, byte[] keyData, int keyLength)
        {
            BinaryReader br = new BinaryReader(fs);
            BinaryWriter bw = new BinaryWriter(fs);

            // Crypt cache header
            fs.Seek(0, SeekOrigin.Begin);
            byte[] cacheHeader = br.ReadBytes(0x100);
            for (int i = 0; i < cacheHeader.Length; ++i)
            {
                cacheHeader[i] ^= keyData[i % keyLength];
            }

            fs.Seek(0, SeekOrigin.Begin);
            bw.Write(cacheHeader);

            if (header == null)
            {
                using (MemoryStream ms = new MemoryStream(cacheHeader))
                {
                    BinaryReader hbr = new BinaryReader(ms);
                    header = new BurnCacheHeader();
                    header.Read(hbr);
                }
            }

            // Encryption map (key index -> cache block)
            Dictionary <int, int> encryptionMap = new Dictionary <int, int>
            {
                { 1, 0 },    // Code
                { 2, 3 },    // PCM A
                { 3, 4 },    // PCM B
                { 4, 5 },    // Sprite Attr
                { 5, 6 }     // Text Attr
            };

            foreach (var pair in encryptionMap)
            {
                CryptNeoGeoBlock(fs, header.Blocks[pair.Value].Offset, header.GetLength(pair.Value), keyData,
                                 pair.Key * ROM_KEY_OFFSET_MULTIPLE, keyLength);
            }
        }