Ejemplo n.º 1
0
        public byte[] GetArm9()
        {
            if (!_arm9Open)
            {
                _arm9Open = true;
                int    arm9_offset = ReadFromFile(BaseRom, 0x20, 4);
                int    arm9_size   = ReadFromFile(BaseRom, 0x2C, 4);
                byte[] arm9        = new byte[arm9_size];
                BaseRom.Seek(arm9_offset);
                BaseRom.ReadFully(arm9);
                // footer check
                int nitrocode = ReadFromFile(BaseRom, 4);

                if (nitrocode == unchecked ((int)0xDEC0_0621))
                {
                    // found a footer
                    _arm9Footer = new byte[12];
                    WriteToByteArr(_arm9Footer, 0, 4, unchecked ((int)0xDEC00621));
                    BaseRom.Read(_arm9Footer, 4, 8);
                    _arm9HasFooter = true;
                }
                else
                {
                    _arm9HasFooter = false;
                }
                // Any extras?
                while ((ReadFromByteArr(arm9, arm9.Length - 12, 4) == unchecked ((int)0xDEC00621)) || ((ReadFromByteArr(arm9, arm9.Length - 12, 4) == 0 && ReadFromByteArr(arm9, arm9.Length - 8, 4) == 0 && ReadFromByteArr(arm9, arm9.Length - 4, 4) == 0)))
                {
                    if (!_arm9HasFooter)
                    {
                        _arm9HasFooter = true;
                        _arm9Footer    = new byte[0];
                    }
                    byte[] newfooter = new byte[_arm9Footer.Length + 12];
                    Array.Copy(arm9, arm9.Length - 12, newfooter, 0, 12);
                    Array.Copy(_arm9Footer, 0, newfooter, 12, _arm9Footer.Length);
                    _arm9Footer = newfooter;
                    byte[] newarm9 = new byte[arm9.Length - 12];
                    Array.Copy(arm9, 0, newarm9, 0, arm9.Length - 12);
                    arm9 = newarm9;
                }
                // Compression?
                _arm9Compressed = false;
                _arm9Szoffset   = 0;
                if (((int)arm9[arm9.Length - 5]) >= 0x08 && ((int)arm9[arm9.Length - 5]) <= 0x0B)
                {
                    int compSize = ReadFromByteArr(arm9, arm9.Length - 8, 3);
                    if (compSize > (arm9.Length * 9 / 10) && compSize < (arm9.Length * 11 / 10))
                    {
                        _arm9Compressed = true;
                        byte[] compLength = new byte[3];
                        WriteToByteArr(compLength, 0, 3, arm9.Length);
                        IList <int> foundOffsets = RomFunctions.Search(arm9, compLength);
                        if (foundOffsets.Count == 1)
                        {
                            _arm9Szmode   = 1;
                            _arm9Szoffset = foundOffsets[0];
                        }
                        else
                        {
                            byte[] compLength2 = new byte[3];
                            WriteToByteArr(compLength2, 0, 3, arm9.Length + 0x4000);
                            IList <int> foundOffsets2 = RomFunctions.Search(arm9, compLength2);
                            if (foundOffsets2.Count == 1)
                            {
                                _arm9Szmode   = 2;
                                _arm9Szoffset = foundOffsets2[0];
                            }
                        }
                    }
                }

                if (_arm9Compressed)
                {
                    arm9 = BlzCoder.Decode(arm9, "arm9.bin");
                }


                _arm9Ramstored = arm9;
                byte[] newcopy = new byte[arm9.Length];
                Array.Copy(arm9, 0, newcopy, 0, arm9.Length);
                return(newcopy);
            }
            else
            {
                byte[] newcopy = new byte[_arm9Ramstored.Length];
                Array.Copy(_arm9Ramstored, 0, newcopy, 0, _arm9Ramstored.Length);
                return(newcopy);
            }
        }
Ejemplo n.º 2
0
        public void SaveTo(Stream fNew)
        {
            var copyBuffer = new byte[256 * 1024];
            var headersize = ReadFromFile(BaseRom, 0x84, 4);

            BaseRom.Seek(0, SeekOrigin.Begin);
            Copy(BaseRom, fNew, copyBuffer, headersize);

            var arm9Offset    = (int)(fNew.Position + Arm9Align) & ~Arm9Align;
            var oldArm9Offset = ReadFromFile(BaseRom, 0x20, 4);
            var arm9Size      = ReadFromFile(BaseRom, 0x2C, 4);

            if (_arm9Open && _arm9Changed)
            {
                var newArm9 = GetArm9();

                if (!_arm9Compressed)
                {
                    newArm9 = BlzCoder.Encode(newArm9, true, "arm9.bin");
                    if (_arm9Szoffset > 0)
                    {
                        var newValue = _arm9Szmode == 1 ? newArm9.Length : newArm9.Length + 0x4000;
                        WriteToByteArr(newArm9, _arm9Szoffset, 3, newValue);
                    }
                }

                arm9Size = newArm9.Length;
                fNew.Seek(arm9Offset, SeekOrigin.Begin);
                fNew.Write(newArm9, 0, newArm9.Length);

                if (_arm9HasFooter)
                {
                    fNew.Write(newArm9, 0, newArm9.Length);
                }
            }
            else
            {
                BaseRom.Seek(oldArm9Offset, SeekOrigin.Begin);
                fNew.Seek(arm9Offset, SeekOrigin.Begin);
                Copy(BaseRom, fNew, copyBuffer, arm9Size + 12);
            }

            var arm9OvlOffset = (int)fNew.Position;
            var arm9OvlSize   = _arm9Overlays.Length * 32;
            var arm7Offset    = (arm9OvlOffset + arm9OvlSize + Arm7Align) & ~Arm7Align;
            var oldArm7Offset = ReadFromFile(BaseRom, 0x30, 4);
            var arm7Size      = ReadFromFile(BaseRom, 0x3C, 4);

            BaseRom.Seek(oldArm7Offset, SeekOrigin.Begin);
            fNew.Seek(arm7Offset, SeekOrigin.Begin);
            Copy(BaseRom, fNew, copyBuffer, arm7Size);

            var arm7OvlOffset    = (int)fNew.Position;
            var oldArm7OvlOffset = ReadFromFile(BaseRom, 0x58, 4);
            var arm7OvlSize      = ReadFromFile(BaseRom, 0x5C, 4);

            BaseRom.Seek(oldArm7OvlOffset, SeekOrigin.Begin);

            fNew.Seek(arm7OvlOffset, SeekOrigin.Begin);
            Copy(BaseRom, fNew, copyBuffer, arm7OvlSize);

            var bannerOffset    = (int)(fNew.Position + BannerAlign) & ~BannerAlign;
            var oldBannerOffset = ReadFromFile(BaseRom, 0x68, 4);
            var bannerSize      = 0x840;

            BaseRom.Seek(oldBannerOffset, SeekOrigin.Begin);
            fNew.Seek(bannerOffset, SeekOrigin.Begin);
            Copy(BaseRom, fNew, copyBuffer, bannerSize);

            var fntOffset    = (int)(fNew.Position + FntAlign) & ~FntAlign;
            var oldFntOffset = ReadFromFile(BaseRom, 0x40, 4);
            var fntSize      = ReadFromFile(BaseRom, 0x44, 4);

            BaseRom.Seek(oldFntOffset, SeekOrigin.Begin);
            fNew.Seek(fntOffset, SeekOrigin.Begin);
            Copy(BaseRom, fNew, copyBuffer, fntSize);

            var fatOffset  = (int)(fNew.Position + FatAlign) & ~FatAlign;
            var fatSize    = _fat.Length;
            var newfat     = new byte[_fat.Length];
            var y9Table    = new byte[_arm9Overlays.Length * 32];
            var baseOffset = fatOffset + fatSize;
            var filecount  = _fat.Length / 8;

            for (var fid = 0; fid < filecount; fid++)
            {
                var offsetOfFile = (baseOffset + FileAlign) & ~FileAlign;
                var fileLen      = 0;
                var copiedCustom = false;
                if (_filesById.ContainsKey(fid))
                {
                    var customContents = _filesById[fid].GetWithoutLoad();

                    if (customContents != null)
                    {
                        fNew.Seek(offsetOfFile, SeekOrigin.Begin);
                        fNew.Write(customContents, 0, customContents.Length);

                        copiedCustom = true;
                        fileLen      = customContents.Length;
                    }
                }
                if (_arm9OverlaysByFileId.ContainsKey(fid))
                {
                    var entry          = _arm9OverlaysByFileId[fid];
                    var overlayId      = entry.OverlayId;
                    var customContents = entry.GetOverrideContents();

                    if (customContents != null)
                    {
                        fNew.Seek(offsetOfFile, SeekOrigin.Begin);
                        fNew.Write(customContents, 0, customContents.Length);

                        copiedCustom = true;
                        fileLen      = customContents.Length;
                    }


                    WriteToByteArr(y9Table, overlayId * 32, 4, overlayId);
                    WriteToByteArr(y9Table, overlayId * 32 + 4, 4, entry.RamAddress);
                    WriteToByteArr(y9Table, overlayId * 32 + 8, 4, entry.RamSize);
                    WriteToByteArr(y9Table, overlayId * 32 + 12, 4, entry.BssSize);
                    WriteToByteArr(y9Table, overlayId * 32 + 16, 4, entry.StaticStart);
                    WriteToByteArr(y9Table, overlayId * 32 + 20, 4, entry.StaticEnd);
                    WriteToByteArr(y9Table, overlayId * 32 + 24, 4, fid);
                    WriteToByteArr(y9Table, overlayId * 32 + 28, 3, entry.CompressedSize);
                    WriteToByteArr(y9Table, overlayId * 32 + 31, 1, entry.CompressFlag);
                }
                if (!copiedCustom)
                {
                    var fileStarts = ReadFromByteArr(_fat, fid * 8, 4);
                    var fileEnds   = ReadFromByteArr(_fat, fid * 8 + 4, 4);
                    fileLen = fileEnds - fileStarts;
                    BaseRom.Seek(fileStarts, SeekOrigin.Begin);
                    fNew.Seek(offsetOfFile, SeekOrigin.Begin);
                    Copy(BaseRom, fNew, copyBuffer, fileLen);
                }

                WriteToByteArr(newfat, fid * 8, 4, offsetOfFile);
                WriteToByteArr(newfat, fid * 8 + 4, 4, offsetOfFile + fileLen);
                baseOffset = offsetOfFile + fileLen;
            }

            fNew.Seek(fatOffset, SeekOrigin.Begin);
            fNew.Write(newfat, 0, newfat.Length);
            fNew.Seek(arm9OvlOffset, SeekOrigin.Begin);
            fNew.Write(y9Table, 0, y9Table.Length);

            var newfilesize = baseOffset;

            newfilesize = (newfilesize + 3) & ~3;

            var applicationEndOffset = newfilesize;

            if (newfilesize != baseOffset)
            {
                fNew.Seek(newfilesize - 1, SeekOrigin.Begin);
                fNew.WriteByte(0);
            }

            newfilesize |= newfilesize >> 16;
            newfilesize |= newfilesize >> 8;
            newfilesize |= newfilesize >> 4;
            newfilesize |= newfilesize >> 2;
            newfilesize |= newfilesize >> 1;
            newfilesize++;

            if (newfilesize <= 128 * 1024)
            {
                newfilesize = 128 * 1024;
            }

            var devcap = -18;
            var x      = newfilesize;

            while (x != 0)
            {
                x >>= 1;
                devcap++;
            }

            var devicecap = devcap < 0 ? 0 : devcap;

            WriteToFile(fNew, 0x20, 4, arm9Offset);
            WriteToFile(fNew, 0x2C, 4, arm9Size);
            WriteToFile(fNew, 0x30, 4, arm7Offset);
            WriteToFile(fNew, 0x3C, 4, arm7Size);
            WriteToFile(fNew, 0x40, 4, fntOffset);
            WriteToFile(fNew, 0x48, 4, fatOffset);
            WriteToFile(fNew, 0x50, 4, arm9OvlOffset);
            WriteToFile(fNew, 0x58, 4, arm7OvlOffset);
            WriteToFile(fNew, 0x68, 4, bannerOffset);
            WriteToFile(fNew, 0x80, 4, applicationEndOffset);
            WriteToFile(fNew, 0x14, 1, devicecap);
            fNew.Seek(0, SeekOrigin.Begin);

            var headerForCrc = new byte[0x15E];

            fNew.Read(headerForCrc, 0, headerForCrc.Length);

            var crc = Crc16.Calculate(headerForCrc, 0, 0x15E);

            WriteToFile(fNew, 0x15E, 2, crc & 0xFFFF);
        }