Ejemplo n.º 1
0
        public LevelSettings(NitroOverlay ovl)
        {
            QuestionMarks  = (byte)(ovl.Read8(0x78) & 0xf);
            Background     = (byte)(ovl.Read8(0x78) >> 4);
            ObjectBanks    = new uint[8];
            ObjectBanks[0] = ovl.Read8(0x54);
            ObjectBanks[1] = ovl.Read8(0x55);
            ObjectBanks[2] = ovl.Read8(0x56);
            ObjectBanks[3] = ovl.Read8(0x57);
            ObjectBanks[4] = ovl.Read8(0x58);
            ObjectBanks[5] = ovl.Read8(0x59);
            ObjectBanks[6] = ovl.Read8(0x5A);
            ObjectBanks[7] = ovl.Read32(0x5C);

            BMDFileID         = ovl.Read16(0x68);
            KCLFileID         = ovl.Read16(0x6A);
            MinimapTsetFileID = ovl.Read16(0x6C);
            MinimapPalFileID  = ovl.Read16(0x6E);

            MusicBytes    = new byte[3];
            MusicBytes[0] = ovl.Read8(0x7C);
            MusicBytes[1] = ovl.Read8(0x7D);
            MusicBytes[2] = ovl.Read8(0x7E);

            MinimapCoordinateScale = ovl.Read16(0x76);
            CameraStartZoomedOut   = ovl.Read8(0x75);

            LevelFormatVersion        = (byte)(ovl.Read8(0x7F) & 0x0F);
            OverlayInitialiserVersion = (byte)(ovl.Read8(0x7F) >> 4);
        }
Ejemplo n.º 2
0
        private void copyCLPS(int sourceLevel)
        {
            NitroOverlay otherOVL = new NitroOverlay(Program.m_ROM, Program.m_ROM.GetLevelOverlayID(sourceLevel));

            uint   other_clps_addr = otherOVL.ReadPointer(0x60);
            ushort other_clps_num  = otherOVL.Read16(other_clps_addr + 0x06);
            uint   other_clps_size = (uint)(8 + (other_clps_num * 8));

            uint   clps_addr = _owner.m_Overlay.ReadPointer(0x60);
            ushort clps_num  = _owner.m_Overlay.Read16(clps_addr + 0x06);
            uint   clps_size = (uint)(8 + (clps_num * 8));

            byte[] CLPS_data = otherOVL.ReadBlock(other_clps_addr, other_clps_size);

            // Make or remove room for other CLPS table
            if (clps_size < other_clps_size)
            {
                AddSpace(clps_addr + clps_size, other_clps_size - clps_size);
            }
            else if (clps_size > other_clps_size)
            {
                RemoveSpace(clps_addr + clps_size - (clps_size - other_clps_size), clps_size - other_clps_size);
            }

            // Write CLPS table from overlay
            _owner.m_Overlay.WriteBlock(clps_addr, CLPS_data);

            loadCLPSData();
        }
Ejemplo n.º 3
0
        private void btnDecompressOverlay_Click(object sender, EventArgs e)
        {
            uint         ovlID = uint.Parse(m_SelectedOverlay.Substring(8));
            NitroOverlay ovl   = new NitroOverlay(Program.m_ROM, ovlID);

            ovl.SaveChanges();
        }
Ejemplo n.º 4
0
        public DoorObject(NitroOverlay ovl, uint offset, int num, int layer)
            : base(ovl, offset, layer)
        {
            m_UniqueID = (uint)(0x20000000 | num);
            m_Type = 9;

            ID = 0;
            Position.X = (float)((short)m_Overlay.Read16(m_Offset + 0x0)) / 1000f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000f;
            YRotation = ((float)((short)m_Overlay.Read16(m_Offset + 0x6)) / 4096f) * 22.5f;

            DoorType = m_Overlay.Read8(m_Offset + 0xA);
            if (DoorType > 0x17) DoorType = 0x17;

            InAreaID = m_Overlay.Read8(m_Offset + 0x9);
            OutAreaID = InAreaID >> 4;
            InAreaID &= 0xF;

            PlaneSizeX = m_Overlay.Read8(m_Offset + 0x8);
            PlaneSizeY = PlaneSizeX >> 4;
            PlaneSizeX &= 0xF;

            m_Renderer = InitialiseRenderer();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 5
0
        public void LoadTables()
        {
            m_FileTable = new ushort[m_FileTableLength];

            NitroOverlay ovl0 = new NitroOverlay(this, 0);

            for (uint i = 0; i < m_FileTableLength; i++)
            {
                if (ovl0.Read32(m_FileTableOffset + (i * 4)) != 0 || m_Version != Version.EUR)
                {
                    uint   str_offset = ovl0.ReadPointer(m_FileTableOffset + (i * 4));
                    string fname      = ovl0.ReadString(str_offset, 0);
                    m_FileTable[i] = GetFileIDFromName(fname);
                    m_FileEntries[GetFileIDFromName(fname)].InternalID = (ushort)i;
                }
                else
                {
                    m_FileTable[i] = 0xffff;
                }
            }

            m_FileStream.Position = m_LevelOvlIDTableOffset;
            m_LevelOvlIDTable     = new uint[52];
            for (uint i = 0; i < 52; i++)
            {
                m_LevelOvlIDTable[i] = m_BinReader.ReadUInt32();
            }
        }
Ejemplo n.º 6
0
        public Level(int levelID, NitroOverlay overlay)
        {
            m_LevelID = levelID;
            m_Overlay = overlay;

            m_LevelSettings = new LevelSettings(m_Overlay);
            if (m_LevelSettings.LevelFormatVersion > k_LevelFormatVersion)
            {
                throw new InvalidDataException("This level was added by a later version of SM64DSe and cannot be read");
            }

            LoadCLPS(m_Overlay);

            // read object lists

            m_NumAreas = m_Overlay.Read8(0x74);
            uint objlistptr = m_Overlay.ReadPointer(0x70);

            m_LevelObjects = new Dictionary <uint, LevelObject>();
            m_TexAnims     = new List <LevelTexAnim>(8);
            for (int i = 0; i < 8; ++i)
            {
                m_TexAnims.Add(new LevelTexAnim(m_Overlay, i, m_NumAreas, m_LevelSettings.LevelFormatVersion));
            }

            m_DynLibIDs = new List <ushort>();
            if (DoesLevelUseDynamicLibs())
            {
                uint dlDataOffset = m_Overlay.Read32(0x30);
                uint numDLs       = m_Overlay.Read16(dlDataOffset);
                m_DynLibIDs = new List <ushort>((int)numDLs);
                for (uint i = 0; i < numDLs; ++i)
                {
                    m_DynLibIDs.Add(m_Overlay.Read16(dlDataOffset + 2 * i + 2));
                }
            }

            ReadObjectTable(m_Overlay, m_Overlay.ReadPointer(0x64), 0);
            m_MinimapIndices = new byte[k_MaxNumAreas];
            for (byte a = 0; a < m_NumAreas; a++)
            {
                // read object tables
                uint addr = (uint)(objlistptr + (a * 12));
                if (m_Overlay.Read32(addr) != 0)
                {
                    ReadObjectTable(m_Overlay, m_Overlay.ReadPointer(addr), a);
                }

                // texture animations, have already been read
                addr += 4;

                addr += 4;
                m_MinimapIndices[a] = m_Overlay.Read8(addr);
            }

            m_ObjAvailable = new Dictionary <ushort, bool>();
            DetermineAvailableObjects();
        }
Ejemplo n.º 7
0
        private void btnKCLEditor_Click(object sender, EventArgs e)
        {
            uint          ovlID   = Program.m_ROM.GetLevelOverlayID(lbxLevels.SelectedIndex);
            NitroOverlay  curOvl  = new NitroOverlay(Program.m_ROM, ovlID);
            NitroFile     curKCL  = Program.m_ROM.GetFileFromInternalID(curOvl.Read16((uint)(0x6A)));
            KCLEditorForm kclForm = new KCLEditorForm(curKCL);

            kclForm.Show();
        }
Ejemplo n.º 8
0
        public void RemovePatch(NitroROM rom)
        {
            List <AddressDataPair> addressDataPairs = null;

            switch (rom.m_Version)
            {
            case NitroROM.Version.EUR:
                addressDataPairs = m_EURRestoreData;
                break;

            case NitroROM.Version.USA_v1:
                addressDataPairs = m_USv1RestoreData;
                break;

            case NitroROM.Version.USA_v2:
                addressDataPairs = m_USv2RestoreData;
                break;

            case NitroROM.Version.JAP:
                addressDataPairs = m_JAPRestoreData;
                break;
            }

            INitroROMBlock fileToPatch = null;

            if (m_FileToPatch != null)
            {
                fileToPatch = Program.m_ROM.GetFileFromName(m_FileToPatch);
            }
            else if (m_OverlayID != null)
            {
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(m_OverlayID));
            }

            foreach (AddressDataPair addressDataPair in addressDataPairs)
            {
                for (int i = 0; i < addressDataPair.m_Data.Length; i++)
                {
                    if (fileToPatch == null)
                    {
                        rom.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                    }
                    else
                    {
                        fileToPatch.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                    }
                }
            }

            if (fileToPatch != null)
            {
                fileToPatch.SaveChanges();
            }
        }
Ejemplo n.º 9
0
        public static void DecompressOverlaysWithinGame()
        {
            if (CheckAllOverlaysDecompressed())
            {
                return;
            }

            for (int i = 0; i < 155; i++)
            {
                NitroOverlay overlay = new NitroOverlay(Program.m_ROM, (uint)i);
                // Overlay is decompressed when initialised above automatically if needed, just need to save changes
                overlay.SaveChanges();
            }
        }
Ejemplo n.º 10
0
        public static List <AddressDataPair> GenerateRestoreData(List <AddressDataPair> patchData, string fileName = null, string overlayID = null)
        {
            List <AddressDataPair> restoreDataList = new List <AddressDataPair>();

            INitroROMBlock fileToPatch = null;

            if (fileName != null)
            {
                fileToPatch = Program.m_ROM.GetFileFromName(fileName);
            }
            else if (overlayID != null)
            {
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(overlayID));
            }

            foreach (AddressDataPair addressDataPair in patchData)
            {
                AddressDataPair restoreData = new AddressDataPair();
                restoreData.m_Address = addressDataPair.m_Address;

                List <byte> data = new List <byte>();
                for (int i = 0; i < addressDataPair.m_Data.Length; i++)
                {
                    if (fileToPatch == null)
                    {
                        if (Program.m_IsROMFolder)
                        {
                            Program.m_ROM.arm9R.BaseStream.Position = addressDataPair.m_Address + (uint)i - Program.m_ROM.headerSize;
                            data.Add(Program.m_ROM.arm9R.ReadByte());
                        }
                        else
                        {
                            data.Add(Program.m_ROM.Read8(addressDataPair.m_Address + (uint)i));
                        }
                    }
                    else
                    {
                        data.Add(fileToPatch.Read8(addressDataPair.m_Address + (uint)i));
                    }
                }
                restoreData.m_Data = data.ToArray();

                restoreDataList.Add(restoreData);
            }

            return(restoreDataList);
        }
Ejemplo n.º 11
0
        private void LoadCLPS(NitroOverlay ovl)
        {
            uint clpsAddr  = ovl.ReadPointer(0x60);
            int  numCLPSes = ovl.Read16(clpsAddr + 0x06);

            m_CLPS = new CLPS();

            clpsAddr += 8;
            for (int i = 0; i < numCLPSes; ++i)
            {
                CLPS.Entry clps = new CLPS.Entry();
                clps.flags  = ovl.Read32(clpsAddr);
                clps.flags |= (ulong)ovl.Read32(clpsAddr + 4) << 32;
                m_CLPS.Add(clps);
                clpsAddr += 8;
            }
        }
Ejemplo n.º 12
0
        private void btnEditCollisionMap_Click(object sender, EventArgs e)
        {
            uint         overlayID      = Program.m_ROM.GetLevelOverlayID(lbxLevels.SelectedIndex);
            NitroOverlay currentOverlay = new NitroOverlay(Program.m_ROM, overlayID);
            NitroFile    currentKCL     = Program.m_ROM.GetFileFromInternalID(currentOverlay.Read16((uint)(0x6A)));

            if (!Properties.Settings.Default.UseSimpleModelAndCollisionMapImporters)
            {
                ModelAndCollisionMapEditor kclForm =
                    new ModelAndCollisionMapEditor(null, currentKCL.m_Name, 1f, ModelAndCollisionMapEditor.StartMode.CollisionMap);
                kclForm.Show();
            }
            else
            {
                KCLEditorForm kclForm = new KCLEditorForm(currentKCL);
                kclForm.Show();
            }
        }
Ejemplo n.º 13
0
 private void mnitDumpAllOvls_Click(object sender, EventArgs e)
 {
     if (Program.m_ROM == null)
     {
         return;
     }
     for (int i = 0; i < 155; i++)
     {
         NitroOverlay overlay  = new NitroOverlay(Program.m_ROM, (uint)i);
         string       filename = "DecompressedOverlays/overlay_" + i.ToString("0000") + ".bin";
         string       dir      = "DecompressedOverlays";
         if (!Directory.Exists(dir))
         {
             Directory.CreateDirectory(dir);
         }
         System.IO.File.WriteAllBytes(filename, overlay.m_Data);
     }
     slStatusLabel.Text = "All overlays have been successfully dumped.";
 }
Ejemplo n.º 14
0
        private void CopyCLPS(int sourceLevel)
        {
            NitroOverlay otherOVL = new NitroOverlay(Program.m_ROM, Program.m_ROM.GetLevelOverlayID(sourceLevel));

            uint   other_clps_addr = otherOVL.ReadPointer(0x60);
            ushort other_clps_num  = otherOVL.Read16(other_clps_addr + 0x06);
            uint   other_clps_size = (uint)(8 + (other_clps_num * 8));

            m_CLPS = new CLPS();
            for (int i = 0; i < other_clps_num; ++i)
            {
                ulong flags = otherOVL.Read32((uint)(other_clps_addr + 8 + 8 * i + 0));
                flags |= (ulong)otherOVL.Read32((uint)(other_clps_addr + 8 + 8 * i + 4)) << 32;
                CLPS.Entry clps = new CLPS.Entry();
                clps.flags = flags;
                m_CLPS.Add(clps);
            }

            LoadCLPSData();
        }
Ejemplo n.º 15
0
        public void LoadTables()
        {
            m_FileTable = new ushort[m_FileTableLength];

            NitroOverlay ovl0 = new NitroOverlay(this, 0);

            for (uint i = 0; i < m_FileTableLength; i++)
            {
                uint   str_offset = ovl0.ReadPointer(m_FileTableOffset + (i * 4));
                string fname      = ovl0.ReadString(str_offset, 0);
                m_FileTable[i] = GetFileIDFromName(fname);
            }

            m_FileStream.Position = m_LevelOvlIDTableOffset;
            m_LevelOvlIDTable     = new uint[52];
            for (uint i = 0; i < 52; i++)
            {
                m_LevelOvlIDTable[i] = m_BinReader.ReadUInt32();
            }
        }
Ejemplo n.º 16
0
        private void btnReplaceOverlay_Click(object sender, EventArgs e)
        {
            if (m_SelectedOverlay == null)
            {
                return;
            }

            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            uint         ovlID = uint.Parse(m_SelectedOverlay.Substring(8));
            NitroOverlay ovl   = new NitroOverlay(Program.m_ROM, ovlID);

            ovl.Clear();
            ovl.WriteBlock(0, System.IO.File.ReadAllBytes(ofd.FileName));
            ovl.SaveChanges();
        }
Ejemplo n.º 17
0
        public TpSrcObject(NitroOverlay ovl, uint offset, int num, int layer)
            : base(ovl, offset, layer)
        {
            m_UniqueID = (uint)(0x20000000 | num);
            m_Type = 6;

            Position.X = (float)((short)m_Overlay.Read16(m_Offset)) / 1000.0f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000.0f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000.0f;
            YRotation = 0.0f;

            Parameters = new ushort[2];
            Parameters[0] = m_Overlay.Read8(m_Offset + 0x6);
            Parameters[1] = m_Overlay.Read8(m_Offset + 0x07);

            m_Renderer = InitialiseRenderer();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 18
0
        private void ReadObjectTable(NitroOverlay ovl, uint offset, int area)
        {
            uint subtbl_num    = ovl.Read32(offset);
            uint subtbl_offset = ovl.ReadPointer(offset + 0x4);

            for (uint st = 0; st < subtbl_num; st++)
            {
                uint curoffset = subtbl_offset + (st * 8);

                byte flags          = ovl.Read8(curoffset);
                byte entries_num    = ovl.Read8(curoffset + 0x1);
                uint entries_offset = ovl.ReadPointer(curoffset + 0x4);

                byte type  = (byte)(flags & 0x1F);
                byte layer = (byte)(flags >> 5);

                if (type == 11)
                {
                    m_MinimapFileIDs = new ushort[entries_num];
                }

                for (byte e = 0; e < entries_num; ++e)
                {
                    LevelObject    obj;
                    INitroROMBlock objData = new INitroROMBlock();
                    objData.m_Data = ovl.ReadBlock((uint)(entries_offset + e * k_LevelObjTypeSizes[type]), (uint)k_LevelObjTypeSizes[type]);
                    switch (type)
                    {
                    case 0:
                        obj = new StandardObject(objData, m_LevelObjects.Count, layer, area);
                        break;

                    case 1:
                        obj = new EntranceObject(objData, m_LevelObjects.Count, layer, m_EntranceID++);
                        break;

                    case 2:     // Path Node
                        obj = new PathPointObject(objData, m_LevelObjects.Count, m_PathNodeID++);
                        break;

                    case 3:     // Path
                        obj = new PathObject(objData, m_LevelObjects.Count, (ushort)m_PathID++);
                        break;

                    case 4:
                        obj = new ViewObject(objData, m_LevelObjects.Count, m_ViewID++);
                        break;

                    case 5:
                        obj = new SimpleObject(objData, m_LevelObjects.Count, layer, area);
                        break;

                    case 6:
                        obj = new TpSrcObject(objData, m_LevelObjects.Count, layer);
                        break;

                    case 7:
                        obj = new TpDstObject(objData, m_LevelObjects.Count, layer);
                        break;

                    case 8:
                        // Fog
                        obj = new FogObject(objData, m_LevelObjects.Count, layer, area);
                        break;

                    case 9:
                        obj = new DoorObject(objData, m_LevelObjects.Count, layer);
                        break;

                    case 10:
                        obj = new ExitObject(objData, m_LevelObjects.Count, layer);
                        break;

                    case 11:
                        obj = new MinimapTileIDObject(objData, m_LevelObjects.Count, layer, m_MinimapTileIDNum++);
                        // This is still used by Minimap Editor
                        m_MinimapFileIDs[e] = ovl.Read16((uint)(entries_offset + (e * 2)));
                        break;

                    case 12:
                        // per-area minimap scale factors
                        obj = new MinimapScaleObject(objData, m_LevelObjects.Count, layer, area);
                        break;

                    case 14:
                        // ??? Unknown
                        obj = new Type14Object(objData, m_LevelObjects.Count, layer, area);
                        break;

                    default:
                        throw new InvalidDataException("Bad object type: " + type);
                    }

                    m_LevelObjects.Add(obj.m_UniqueID, obj);
                }
            }
        }
Ejemplo n.º 19
0
        public void DumpObjectInfo()
        {
            uint actorptrtable = 0x8000 + 0x88864;

            Program.m_ROM.BeginRW();

            Stream fs = File.Create("objinfo.php");
            StreamWriter wr = new StreamWriter(fs);

            wr.Write("<?php\n$objinfo = array\n(\n");

            for (int i = 0; i < 0x146; i++)
            {
                wr.Write("\tarray\n\t(\n");

                wr.Write(String.Format("\t\t'id' => 0x{0:X4},\n", i));
                wr.Write("\t\t'internalname' => '" + ObjectDatabase.m_ObjectInfo[i].m_InternalName + "',\n");

                uint actorid = ObjectDatabase.m_ObjectInfo[i].m_ActorID;
                uint actoraddr = Program.m_ROM.Read32(actorptrtable + (uint)(actorid * 4));

                wr.Write(String.Format("\t\t'actorid' => 0x{0:X4},\n", actorid));

                if (actoraddr < 0x021111A0)
                    wr.Write("\t\t'requirement' => 'none',\n");
                else
                {
                    uint minovl = 0, maxovl = 0, bank = 0, bankbase = 0;
                    if ((actoraddr >= 0x021111A0) && (actoraddr < 0x02115EE0))
                    { minovl = 8; maxovl = 59; bank = 7; bankbase = 1;  }
                    else if ((actoraddr >= 0x02115EE0) && (actoraddr < 0x0211F000))
                    { minovl = 0x3E; maxovl = 0x42; bank = 0; bankbase = 1;  }
                    else if ((actoraddr >= 0x0211F000) && (actoraddr < 0x02123740))
                    { minovl = 0x46; maxovl = 0x4A; bank = 1; bankbase = 2; }
                    else if ((actoraddr >= 0x02123740) && (actoraddr < 0x02129020))
                    { minovl = 0x4D; maxovl = 0x51; bank = 2; bankbase = 1; }
                    else if ((actoraddr >= 0x02129020) && (actoraddr < 0x02130F00))
                    { minovl = 0x54; maxovl = 0x55; bank = 3; bankbase = 1; }
                    else if ((actoraddr >= 0x02130F00) && (actoraddr < 0x02135700))
                    { minovl = 0x59; maxovl = 0x5C; bank = 4; bankbase = 1; }
                    else if ((actoraddr >= 0x02135700) && (actoraddr < 0x02140D80))
                    { minovl = 0x5E; maxovl = 0x61; bank = 5; bankbase = 1; }
                    else if ((actoraddr >= 0x02140D80) && (actoraddr < 0x0214EAA0))
                    { minovl = 0x64; maxovl = 0x64; bank = 6; bankbase = 1; }

                    uint curovl = minovl;
                    do
                    {
                        NitroOverlay theovl = new NitroOverlay(Program.m_ROM, curovl);

                        uint testval = 0xFFFFFFFF;
                        try { testval = (uint)theovl.Read16(actoraddr - theovl.GetRAMAddr() + 4); }
                        catch {}

                        if (testval == actorid)
                        {
                            wr.Write(String.Format("\t\t'requirement' => 'bank{0}={1}',\n", bank, curovl - minovl + bankbase));

                            break;
                        }

                        curovl++;
                    }
                    while (curovl <= maxovl);
                }

                wr.Write("\t\t0\n\t), \n");
                if ((i % 64) == 0) wr.Flush();
            }

            wr.Write("\t0\n);\n?>\n");
            wr.Flush();

            fs.Close();
            Program.m_ROM.EndRW();
        }
Ejemplo n.º 20
0
        public EntranceObject(NitroOverlay ovl, uint offset, int num, int layer, int id)
            : base(ovl, offset, layer)
        {
            m_UniqueID = (uint)(0x20000000 | num);
            m_EntranceID = id;
            m_Type = 1;

            ID = 0;
            Position.X = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000.0f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000.0f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x6)) / 1000.0f;
            YRotation = ((float)((short)m_Overlay.Read16(m_Offset + 0xA)) / 4096f) * 22.5f;

            Parameters = new ushort[5];
            Parameters[0] = m_Overlay.Read16(m_Offset + 0x0);
            Parameters[1] = m_Overlay.Read16(m_Offset + 0x8);
            Parameters[2] = m_Overlay.Read16(m_Offset + 0xC);
            Parameters[3] = m_Overlay.Read16(m_Offset + 0xE);

            m_Renderer = InitialiseRenderer();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 21
0
        private void btnCompile_Click(object sender, EventArgs e)
        {
            if (!Patcher.PatchMaker.PatchToSupportBigASMHacks())
            {
                return;
            }

            //code and patcher borrowed from NSMBe and edited.
            System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(txtFolder.Text);
            uint addr = 0x02400000;

            if (btnOverlay.Checked)
            {
                addr = new NitroOverlay(Program.m_ROM, uint.Parse(txtOverlayId.Text)).GetRAMAddr();
            }
            else if (btnInjection.Checked)
            {
            }
            else if (!btnDynamicLibrary.Checked)
            {
                addr = uint.Parse(txtOffset.Text, System.Globalization.NumberStyles.HexNumber);
            }
            Patcher.PatchMaker pm = new Patcher.PatchMaker(dir, addr);

            byte[] ret = null;
            if (btnDynamicLibrary.Checked)
            {
                ret = pm.makeDynamicLibrary();
            }
            else if (btnOverlay.Checked)
            {
                pm.compilePatch();
                pm.makeOverlay(uint.Parse(txtOverlayId.Text));
                return;
            }
            else if (btnInjection.Checked)
            {
                //TODO.
            }
            else
            {
                pm.compilePatch();
                ret = pm.generatePatch();
            }
            if (ret == null)
            {
                return;
            }
            bool isOut = btnExternal.Checked;

            if (isOut)
            {
                string file = txtOutput.Text;
                if (txtOutput.Text == "")
                {
                    return;
                }
                System.IO.File.WriteAllBytes(file, ret);
            }
            else
            {
                if (txtInput.Text != "")
                {
                    var file = Program.m_ROM.GetFileFromName(txtInput.Text);
                    file.m_Data = ret;
                    file.SaveChanges();
                }
            }
        }
Ejemplo n.º 22
0
        /*
         * This method takes the first Address and Data from the patch and tests if the current values in the
         * ROM match the values of the patch - if they match the patch is already applied. This doesn't test
         * all values to speed things up.
         */
        public bool CheckIsApplied(NitroROM rom)
        {
            if (m_DecompressAllOverlays && Helper.CheckAllOverlaysDecompressed() == false)
            {
                m_IsApplied = false;
                return false;
            }

            INitroROMBlock fileToPatch = null;
            if (m_FileToPatch != null)
                fileToPatch = Program.m_ROM.GetFileFromName(m_FileToPatch);
            else if (m_OverlayID != null)
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(m_OverlayID));

            AddressDataPair testAddressDataPair = null;

            switch (rom.m_Version)
            {
                case NitroROM.Version.EUR:
                    testAddressDataPair = (m_EURPatch.Count == 0) ? null : m_EURPatch.ElementAt(0);
                    break;
                case NitroROM.Version.USA_v1:
                    testAddressDataPair = (m_USv1Patch.Count == 0) ? null : m_USv1Patch.ElementAt(0);
                    break;
                case NitroROM.Version.USA_v2:
                    testAddressDataPair = (m_USv2Patch.Count == 0) ? null : m_USv2Patch.ElementAt(0);
                    break;
                case NitroROM.Version.JAP:
                    testAddressDataPair = (m_JAPPatch.Count == 0) ? null : m_JAPPatch.ElementAt(0);
                    break;
            }

            if (testAddressDataPair == null || testAddressDataPair.m_Data == null || testAddressDataPair.m_Data.Length == 0)
            {
                m_IsApplied = false;
                return false;
            }

            for (int i = 0; i < testAddressDataPair.m_Data.Length; i++)
            {
                if (fileToPatch == null && rom.Read8(testAddressDataPair.m_Address + (uint)i) != testAddressDataPair.m_Data[i])
                {
                    m_IsApplied = false;
                    return false;
                }
                else if (fileToPatch != null && fileToPatch.Read8(testAddressDataPair.m_Address + (uint)i) != testAddressDataPair.m_Data[i])
                {
                    m_IsApplied = false;
                    return false;
                }
            }

            //If it reaches here, the patch has already been applied
            m_IsApplied = true;
            return true;
        }
Ejemplo n.º 23
0
        private void btnReplaceOverlay_Click(object sender, EventArgs e)
        {
            if (m_SelectedOverlay == null || m_SelectedOverlay.Equals(""))
                return;

            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == DialogResult.Cancel)
                return;

            uint ovlID = uint.Parse(m_SelectedOverlay.Substring(8));
            NitroOverlay ovl = new NitroOverlay(Program.m_ROM, ovlID);
            ovl.Clear();
            ovl.WriteBlock(0, System.IO.File.ReadAllBytes(ofd.FileName));
            ovl.SaveChanges();
        }
Ejemplo n.º 24
0
 private void btnKCLEditor_Click(object sender, EventArgs e)
 {
     uint ovlID = Program.m_ROM.GetLevelOverlayID(lbxLevels.SelectedIndex);
     NitroOverlay curOvl = new NitroOverlay(Program.m_ROM, ovlID);
     NitroFile curKCL = Program.m_ROM.GetFileFromInternalID(curOvl.Read16((uint)(0x6A)));
     KCLEditorForm kclForm = new KCLEditorForm(curKCL);
     kclForm.Show();
 }
Ejemplo n.º 25
0
        public void DumpObjectInfo()
        {
            uint actorptrtable = 0x8000 + 0x88864;

            Program.m_ROM.BeginRW();

            Stream       fs = File.Create("objinfo.php");
            StreamWriter wr = new StreamWriter(fs);

            wr.Write("<?php\n$objinfo = array\n(\n");

            for (int i = 0; i < 0x146; i++)
            {
                wr.Write("\tarray\n\t(\n");

                wr.Write(String.Format("\t\t'id' => 0x{0:X4},\n", i));
                wr.Write("\t\t'internalname' => '" + ObjectDatabase.m_ObjectInfo[i].m_InternalName + "',\n");

                uint actorid   = ObjectDatabase.m_ObjectInfo[i].m_ActorID;
                uint actoraddr = Program.m_ROM.Read32(actorptrtable + (uint)(actorid * 4));

                wr.Write(String.Format("\t\t'actorid' => 0x{0:X4},\n", actorid));

                if (actoraddr < 0x021111A0)
                {
                    wr.Write("\t\t'requirement' => 'none',\n");
                }
                else
                {
                    uint minovl = 0, maxovl = 0, bank = 0, bankbase = 0;
                    if ((actoraddr >= 0x021111A0) && (actoraddr < 0x02115EE0))
                    {
                        minovl = 8; maxovl = 59; bank = 7; bankbase = 1;
                    }
                    else if ((actoraddr >= 0x02115EE0) && (actoraddr < 0x0211F000))
                    {
                        minovl = 0x3E; maxovl = 0x42; bank = 0; bankbase = 1;
                    }
                    else if ((actoraddr >= 0x0211F000) && (actoraddr < 0x02123740))
                    {
                        minovl = 0x46; maxovl = 0x4A; bank = 1; bankbase = 2;
                    }
                    else if ((actoraddr >= 0x02123740) && (actoraddr < 0x02129020))
                    {
                        minovl = 0x4D; maxovl = 0x51; bank = 2; bankbase = 1;
                    }
                    else if ((actoraddr >= 0x02129020) && (actoraddr < 0x02130F00))
                    {
                        minovl = 0x54; maxovl = 0x55; bank = 3; bankbase = 1;
                    }
                    else if ((actoraddr >= 0x02130F00) && (actoraddr < 0x02135700))
                    {
                        minovl = 0x59; maxovl = 0x5C; bank = 4; bankbase = 1;
                    }
                    else if ((actoraddr >= 0x02135700) && (actoraddr < 0x02140D80))
                    {
                        minovl = 0x5E; maxovl = 0x61; bank = 5; bankbase = 1;
                    }
                    else if ((actoraddr >= 0x02140D80) && (actoraddr < 0x0214EAA0))
                    {
                        minovl = 0x64; maxovl = 0x64; bank = 6; bankbase = 1;
                    }

                    uint curovl = minovl;
                    do
                    {
                        NitroOverlay theovl = new NitroOverlay(Program.m_ROM, curovl);

                        uint testval = 0xFFFFFFFF;
                        try { testval = (uint)theovl.Read16(actoraddr - theovl.GetRAMAddr() + 4); }
                        catch {}

                        if (testval == actorid)
                        {
                            wr.Write(String.Format("\t\t'requirement' => 'bank{0}={1}',\n", bank, curovl - minovl + bankbase));

                            break;
                        }

                        curovl++;
                    }while (curovl <= maxovl);
                }

                wr.Write("\t\t0\n\t), \n");
                if ((i % 64) == 0)
                {
                    wr.Flush();
                }
            }

            wr.Write("\t0\n);\n?>\n");
            wr.Flush();

            fs.Close();
            Program.m_ROM.EndRW();
        }
Ejemplo n.º 26
0
        public MinimapTileIDObject(NitroOverlay ovl, uint offset, int num, int layer, int id)
            : base(ovl, offset, layer)
        {
            m_Type = 11;
            m_MinimapTileIDNum = id;
            m_UniqueID = (uint)(0x50000000 | num);

            Parameters = new ushort[2];
            Parameters[0] = m_Overlay.Read16(m_Offset);

            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 27
0
        public void ApplyPatch(NitroROM rom)
        {
            Program.m_ROM.BeginRW();
            List <AddressDataPair> addressDataPairs = null;

            switch (rom.m_Version)
            {
            case NitroROM.Version.EUR:
                addressDataPairs = m_EURPatch;
                m_EURRestoreData = GenerateRestoreData(m_EURPatch);
                break;

            case NitroROM.Version.USA_v1:
                addressDataPairs  = m_USv1Patch;
                m_USv1RestoreData = GenerateRestoreData(m_USv1Patch);
                break;

            case NitroROM.Version.USA_v2:
                addressDataPairs  = m_USv2Patch;
                m_USv2RestoreData = GenerateRestoreData(m_USv2Patch);
                break;

            case NitroROM.Version.JAP:
                addressDataPairs = m_JAPPatch;
                m_JAPRestoreData = GenerateRestoreData(m_JAPPatch);
                break;
            }

            if (m_DecompressAllOverlays)
            {
                Helper.DecompressOverlaysWithinGame();
            }

            if (m_FileToPatch != null)
            {
                NitroFile myFile = Program.m_ROM.GetFileFromName(m_FileToPatch);

                foreach (AddressDataPair addressDataPair in addressDataPairs)
                {
                    for (int i = 0; i < addressDataPair.m_Data.Length; i++)
                    {
                        myFile.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                    }
                }

                Program.m_ROM.EndRW();
                myFile.SaveChanges();
                return;
            }

            INitroROMBlock fileToPatch = null;

            if (m_FileToPatch != null)
            {
                fileToPatch = Program.m_ROM.GetFileFromName(m_FileToPatch);
            }
            else if (m_OverlayID != null)
            {
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(m_OverlayID));
            }

            foreach (AddressDataPair addressDataPair in addressDataPairs)
            {
                for (int i = 0; i < addressDataPair.m_Data.Length; i++)
                {
                    if (fileToPatch == null)
                    {
                        if (Program.m_IsROMFolder)
                        {
                            Program.m_ROM.arm9W.BaseStream.Position = addressDataPair.m_Address + (uint)i - Program.m_ROM.headerSize;
                            Program.m_ROM.arm9W.Write(addressDataPair.m_Data[i]);
                        }
                        else
                        {
                            rom.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                        }
                    }
                    else
                    {
                        fileToPatch.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                    }
                }
            }

            Program.m_ROM.EndRW();

            if (fileToPatch != null)
            {
                fileToPatch.SaveChanges();
            }
        }
Ejemplo n.º 28
0
        /*
         * This method takes the first Address and Data from the patch and tests if the current values in the
         * ROM match the values of the patch - if they match the patch is already applied. This doesn't test
         * all values to speed things up.
         */
        public bool CheckIsApplied(NitroROM rom)
        {
            if (m_DecompressAllOverlays && Helper.CheckAllOverlaysDecompressed() == false)
            {
                m_IsApplied = false;
                return(false);
            }

            INitroROMBlock fileToPatch = null;

            if (m_FileToPatch != null)
            {
                fileToPatch = Program.m_ROM.GetFileFromName(m_FileToPatch);
            }
            else if (m_OverlayID != null)
            {
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(m_OverlayID));
            }

            AddressDataPair testAddressDataPair = null;

            switch (rom.m_Version)
            {
            case NitroROM.Version.EUR:
                testAddressDataPair = (m_EURPatch.Count == 0) ? null : m_EURPatch.ElementAt(0);
                break;

            case NitroROM.Version.USA_v1:
                testAddressDataPair = (m_USv1Patch.Count == 0) ? null : m_USv1Patch.ElementAt(0);
                break;

            case NitroROM.Version.USA_v2:
                testAddressDataPair = (m_USv2Patch.Count == 0) ? null : m_USv2Patch.ElementAt(0);
                break;

            case NitroROM.Version.JAP:
                testAddressDataPair = (m_JAPPatch.Count == 0) ? null : m_JAPPatch.ElementAt(0);
                break;
            }

            if (testAddressDataPair == null || testAddressDataPair.m_Data == null || testAddressDataPair.m_Data.Length == 0)
            {
                m_IsApplied = false;
                return(false);
            }

            for (int i = 0; i < testAddressDataPair.m_Data.Length; i++)
            {
                if (fileToPatch == null)
                {
                    if (Program.m_IsROMFolder)
                    {
                        Program.m_ROM.arm9R.BaseStream.Position = testAddressDataPair.m_Address + (uint)i - Program.m_ROM.headerSize;
                        if (Program.m_ROM.arm9R.ReadByte() != testAddressDataPair.m_Data[i])
                        {
                            m_IsApplied = false;
                            return(false);
                        }
                    }
                    else
                    {
                        if (rom.Read8(testAddressDataPair.m_Address + (uint)i) != testAddressDataPair.m_Data[i])
                        {
                            m_IsApplied = false;
                            return(false);
                        }
                    }
                }
                else if (fileToPatch != null && fileToPatch.Read8(testAddressDataPair.m_Address + (uint)i) != testAddressDataPair.m_Data[i])
                {
                    m_IsApplied = false;
                    return(false);
                }
            }

            //If it reaches here, the patch has already been applied
            m_IsApplied = true;
            return(true);
        }
Ejemplo n.º 29
0
        public FogObject(NitroOverlay ovl, uint offset, int num, int layer, int area)
            : base(ovl, offset, layer)
        {
            m_Area = area;
            m_Type = 8;
            m_UniqueID = (uint)(0x50000000 | num);

            Parameters = new ushort[6];
            Parameters[0] = m_Overlay.Read8(m_Offset);
            Parameters[1] = m_Overlay.Read8(m_Offset + 1);
            Parameters[2] = m_Overlay.Read8(m_Offset + 2);
            Parameters[3] = m_Overlay.Read8(m_Offset + 3);
            Parameters[4] = m_Overlay.Read16(m_Offset + 4);
            Parameters[5] = m_Overlay.Read16(m_Offset + 6);

            //m_Renderer = new ColorCubeRenderer(Color.FromArgb(255, 255, 0), Color.FromArgb(Parameters[1], Parameters[2], Parameters[3]), true);
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 30
0
        public LevelSettings(NitroOverlay ovl)
        {
            m_Overlay = ovl;
            Background = (byte)(m_Overlay.Read8(0x78) >> 4);
            ObjectBanks = new uint[8];
            ObjectBanks[0] = m_Overlay.Read8(0x54);
            ObjectBanks[1] = m_Overlay.Read8(0x55);
            ObjectBanks[2] = m_Overlay.Read8(0x56);
            ObjectBanks[3] = m_Overlay.Read8(0x57);
            ObjectBanks[4] = m_Overlay.Read8(0x58);
            ObjectBanks[5] = m_Overlay.Read8(0x59);
            ObjectBanks[6] = m_Overlay.Read8(0x5A);
            ObjectBanks[7] = m_Overlay.Read32(0x5C);

            BMDFileID = m_Overlay.Read16(0x68);
            KCLFileID = m_Overlay.Read16(0x6A);
            MinimapTsetFileID = m_Overlay.Read16(0x6C);
            MinimapPalFileID = m_Overlay.Read16(0x6E);

            MusicBytes = new byte[3];
            MusicBytes[0] = m_Overlay.Read8(0x7C);
            MusicBytes[1] = m_Overlay.Read8(0x7D);
            MusicBytes[2] = m_Overlay.Read8(0x7E);

            MinimapCoordinateScale = m_Overlay.Read16(0x76);
            CameraStartZoomedOut = m_Overlay.Read8(0x75);
        }
Ejemplo n.º 31
0
 private void mnitDumpAllOvls_Click(object sender, EventArgs e)
 {
     if (Program.m_ROM == null)
         return;
     for (int i = 0; i < 155; i++)
     {
         NitroOverlay overlay = new NitroOverlay(Program.m_ROM, (uint)i);
         string filename = "DecompressedOverlays/overlay_" + i.ToString("0000") + ".bin";
         string dir = "DecompressedOverlays";
         if (!Directory.Exists(dir))
             Directory.CreateDirectory(dir);
         System.IO.File.WriteAllBytes(filename, overlay.m_Data);
     }
     slStatusLabel.Text = "All overlays have been successfully dumped.";
 }
Ejemplo n.º 32
0
        public void RemovePatch(NitroROM rom)
        {
            List<AddressDataPair> addressDataPairs = null;

            switch (rom.m_Version)
            {
                case NitroROM.Version.EUR:
                    addressDataPairs = m_EURRestoreData;
                    break;
                case NitroROM.Version.USA_v1:
                    addressDataPairs = m_USv1RestoreData;
                    break;
                case NitroROM.Version.USA_v2:
                    addressDataPairs = m_USv2RestoreData;
                    break;
                case NitroROM.Version.JAP:
                    addressDataPairs = m_JAPRestoreData;
                    break;
            }

            INitroROMBlock fileToPatch = null;
            if (m_FileToPatch != null)
                fileToPatch = Program.m_ROM.GetFileFromName(m_FileToPatch);
            else if (m_OverlayID != null)
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(m_OverlayID));

            foreach (AddressDataPair addressDataPair in addressDataPairs)
            {
                for (int i = 0; i < addressDataPair.m_Data.Length; i++)
                {
                    if (fileToPatch == null)
                    {
                        rom.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                    }
                    else
                    {
                        fileToPatch.Write8(addressDataPair.m_Address + (uint)i, addressDataPair.m_Data[i]);
                    }
                }
            }

            if (fileToPatch != null)
                fileToPatch.SaveChanges();
        }
Ejemplo n.º 33
0
 private void btnDecompressOverlay_Click(object sender, EventArgs e)
 {
     uint ovlID = uint.Parse(m_SelectedOverlay.Substring(8));
     NitroOverlay ovl = new NitroOverlay(Program.m_ROM, ovlID);
     ovl.SaveChanges();
 }
Ejemplo n.º 34
0
        private void importPatchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog o = new OpenFileDialog();

            o.Filter           = "SM64DSe Patch|*.sp";
            o.RestoreDirectory = true;
            if (o.ShowDialog() == DialogResult.OK)
            {
                //Each line.
                var    s        = File.ReadAllLines(o.FileName);
                string basePath = Path.GetDirectoryName(o.FileName) + "/";
                foreach (var l in s)
                {
                    //Get parameters.
                    string t = l;
                    if (t.Contains("#"))
                    {
                        t = t.Substring(0, t.IndexOf('#'));
                    }
                    var p = t.Split(' ');
                    if (p.Length == 0)
                    {
                        continue;
                    }

                    //Switch command.
                    switch (p[0].ToLower())
                    {
                    //Replace file.
                    case "replace":
                        if (ushort.TryParse(p[1], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out _))
                        {
                            Program.m_ROM.ReinsertFile(Program.m_ROM.GetFileIDFromInternalID(ushort.Parse(p[1], NumberStyles.HexNumber, CultureInfo.CurrentCulture)), File.ReadAllBytes(basePath + p[2]));
                        }
                        else
                        {
                            Program.m_ROM.ReinsertFile(Program.m_ROM.GetFileIDFromName(p[1]), File.ReadAllBytes(basePath + p[2]));
                        }
                        break;

                    //Replace ARM9.
                    case "replace_arm9":
                        var r = Program.m_ROM;
                        r.BeginRW(true);
                        uint   arm9addr = r.Read32(0x20);
                        uint   arm9size = r.Read32(0x2C);
                        byte[] newArm9  = File.ReadAllBytes(basePath + p[1]);
                        if (newArm9.Length > arm9size)
                        {
                            r.MakeRoom(arm9addr + arm9size, (uint)(newArm9.Length - arm9size));
                            r.AutoFix(0xFFFF, arm9addr + arm9size, (int)(newArm9.Length - arm9size));
                        }
                        r.Write32(0x2C, (uint)newArm9.Length);
                        r.WriteBlock(arm9addr, newArm9);
                        r.EndRW(true);
                        r.LoadROM(r.m_Path);
                        break;

                    //Replace overlay.
                    case "replace_overlay":
                        NitroOverlay n2 = new NitroOverlay(Program.m_ROM, uint.Parse(p[1]));
                        n2.m_Data = File.ReadAllBytes(basePath + p[2]);
                        n2.SaveChanges();
                        break;

                    //Rename file.
                    case "rename":
                        if (Program.m_ROM.m_Version != NitroROM.Version.EUR)
                        {
                            MessageBox.Show("This is for EUR ROMs only!");
                            continue;
                        }
                        Program.m_ROM.StartFilesystemEdit();
                        ushort fileIdFromName;
                        if (ushort.TryParse(p[1], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out _))
                        {
                            fileIdFromName = Program.m_ROM.GetFileIDFromInternalID(ushort.Parse(p[1], NumberStyles.HexNumber, CultureInfo.CurrentCulture));
                        }
                        else
                        {
                            fileIdFromName = Program.m_ROM.GetFileIDFromName(p[1]);
                        }
                        string filename = Program.m_ROM.m_FileEntries[fileIdFromName].FullName;
                        string newName  = p[2];
                        int    length   = filename.LastIndexOf('/') + 1;
                        string str1     = filename.Substring(0, length) + newName;
                        Program.m_ROM.m_FileEntries[fileIdFromName].Name     = newName;
                        Program.m_ROM.m_FileEntries[fileIdFromName].FullName = str1;
                        Program.m_ROM.SaveFilesystem();
                        this.tvFileList.Nodes.Clear();
                        ROMFileSelect.LoadFileList(this.tvFileList);
                        this.tvARM9Overlays.Nodes.Clear();
                        ROMFileSelect.LoadOverlayList(this.tvARM9Overlays);
                        break;

                    //Import level XML.
                    case "import_xml":
                        Level lv = new Level(int.Parse(p[1]));
                        try { LevelDataXML_Importer.ImportLevel(lv, basePath + p[2], true); }
                        catch (InvalidDataException ex) { MessageBox.Show(ex.Message); }
                        catch (Exception ex) { new ExceptionMessageBox("Error parsing level, changes have not been saved", ex).ShowDialog(); }
                        Program.m_ROM.LoadROM(Program.m_ROM.m_Path);
                        break;

                    //Add overlay.
                    case "add_overlay":
                        if (Program.m_ROM.m_Version != NitroROM.Version.EUR)
                        {
                            MessageBox.Show("This is for EUR ROMs only!");
                            continue;
                        }
                        OverlayEditor oe = new OverlayEditor();
                        oe.AddOverlay(oe.Overlays.Count);
                        var ov          = oe.Overlays[oe.Overlays.Count - 1];
                        var overlayFile = File.ReadAllBytes(basePath + p[6]);
                        ov.ID              = (uint)(oe.Overlays.Count - 1);
                        ov.RAMAddress      = uint.Parse(p[1], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov.RAMSize         = (uint)overlayFile.Length;
                        ov.BSSSize         = uint.Parse(p[4], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov.StaticInitStart = uint.Parse(p[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov.StaticInitEnd   = uint.Parse(p[3], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov.Flags           = uint.Parse(p[5], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        oe.Overlays[oe.Overlays.Count - 1] = ov;
                        oe.saveChangesButton_Click(null, new EventArgs());
                        oe.closeButton_Click(null, new EventArgs());
                        NitroOverlay n = new NitroOverlay(Program.m_ROM, (uint)(oe.Overlays.Count - 1));
                        n.m_Data = overlayFile;
                        n.SaveChanges();
                        this.tvFileList.Nodes.Clear();
                        ROMFileSelect.LoadFileList(this.tvFileList);
                        this.tvARM9Overlays.Nodes.Clear();
                        ROMFileSelect.LoadOverlayList(this.tvARM9Overlays);
                        break;

                    //Edit overlay.
                    case "edit_overlay":
                        if (Program.m_ROM.m_Version != NitroROM.Version.EUR)
                        {
                            MessageBox.Show("This is for EUR ROMs only!");
                            continue;
                        }
                        Program.m_ROM.StartFilesystemEdit();
                        var ov2 = Program.m_ROM.m_OverlayEntries[int.Parse(p[1])];
                        ov2.RAMAddress      = uint.Parse(p[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov2.BSSSize         = uint.Parse(p[5], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov2.StaticInitStart = uint.Parse(p[3], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov2.StaticInitEnd   = uint.Parse(p[4], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        ov2.Flags           = uint.Parse(p[6], NumberStyles.HexNumber, CultureInfo.CurrentCulture);
                        Program.m_ROM.m_OverlayEntries[int.Parse(p[1])] = ov2;
                        Program.m_ROM.SaveFilesystem();
                        break;

                    //Delete overlay.
                    case "delete_overlay":
                        if (Program.m_ROM.m_Version != NitroROM.Version.EUR)
                        {
                            MessageBox.Show("This is for EUR ROMs only!");
                            continue;
                        }
                        OverlayEditor oe2 = new OverlayEditor();
                        oe2.DeleteOverlay(int.Parse(p[1]));
                        oe2.saveChangesButton_Click(null, new EventArgs());
                        oe2.closeButton_Click(null, new EventArgs());
                        break;
                    }
                }
            }
        }
Ejemplo n.º 35
0
        public ExitObject(NitroOverlay ovl, uint offset, int num, int layer)
            : base(ovl, offset, layer)
        {
            m_UniqueID = (uint)(0x20000000 | num);
            m_Type = 10;

            Position.X = (float)((short)m_Overlay.Read16(m_Offset)) / 1000.0f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000.0f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000.0f;
            YRotation = ((float)((short)m_Overlay.Read16(m_Offset + 0x8)) / 4096f) * 22.5f;

            LevelID = m_Overlay.Read8(m_Offset + 0xA);
            EntranceID = m_Overlay.Read8(m_Offset + 0xB);
            Param1 = m_Overlay.Read16(m_Offset + 0x6);
            Param2 = m_Overlay.Read16(m_Offset + 0xC);

            m_Renderer = InitialiseRenderer();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 36
0
        private void dLPatchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Program.m_ROM.m_Version != NitroROM.Version.EUR)
            {
                MessageBox.Show("This is for EUR roms only!");
            }
            else
            {
                bool autorw = Program.m_ROM.CanRW();
                if (!autorw)
                {
                    Program.m_ROM.BeginRW();
                }
                if (Program.m_ROM.Read32(0x6590) != 0) //the patch makes this not 0
                {
                    if (!autorw)
                    {
                        Program.m_ROM.EndRW();
                    }
                    MessageBox.Show("Rom has already been patched!");
                    return;
                }
                if (!autorw)
                {
                    Program.m_ROM.EndRW();
                }

                if (MessageBox.Show("This will patch the ROM. " +
                                    "Continue with the patch?", "Table Shifting Patch", MessageBoxButtons.YesNo) == DialogResult.No)
                {
                    return;
                }

                if (!autorw)
                {
                    Program.m_ROM.BeginRW();
                }
                NitroOverlay ov2 = new NitroOverlay(Program.m_ROM, 2);

                //Move the ACTOR_SPAWN_TABLE so it can expand
                Program.m_ROM.WriteBlock(0x6590, Program.m_ROM.ReadBlock(0x90864, 0x61c));
                Program.m_ROM.WriteBlock(0x90864, new byte[0x61c]);

                //Adjust pointers
                Program.m_ROM.Write32(0x1a198, 0x02006590);

                //Move the OBJ_TO_ACTOR_TABLE so it can expand
                Program.m_ROM.WriteBlock(0x4b00, ov2.ReadBlock(0x0210cbf4 - ov2.GetRAMAddr(), 0x28c));
                ov2.WriteBlock(0x0210cbf4 - ov2.GetRAMAddr(), new byte[0x28c]);

                //Adjust pointers
                ov2.Write32(0x020fe890 - ov2.GetRAMAddr(), 0x02004b00);
                ov2.Write32(0x020fe958 - ov2.GetRAMAddr(), 0x02004b00);
                ov2.Write32(0x020fea44 - ov2.GetRAMAddr(), 0x02004b00);

                //Add the dynamic library loading and cleanup code
                Program.m_ROM.WriteBlock(0x90864, Properties.Resources.dynamic_library_loader);

                //Add the hooks (by replacing LoadObjBankOverlays())
                Program.m_ROM.WriteBlock(0x2df70, Properties.Resources.static_overlay_loader);

                if (!autorw)
                {
                    Program.m_ROM.EndRW();
                }
                ov2.SaveChanges();
            }
        }
Ejemplo n.º 37
0
        public NitroROM(string path)
        {
            m_Path  = path;
            m_CanRW = false;

            BeginRW();

            m_FileStream.Position = 0x00;
            char[] gametitle = m_BinReader.ReadChars(12);
            if (new string(gametitle) != "S.MARIO64DS\0")
            {
                EndRW();
                throw new Exception("This file isn't a Super Mario 64 DS ROM.");
            }

            m_FileStream.Position = 0x0C;
            uint gamecode = m_BinReader.ReadUInt32();

            m_FileStream.Position = 0x1E;
            byte romversion = m_BinReader.ReadByte();

            switch (gamecode)
            {
            case 0x454D5341:     // ASME / USA
                if (romversion == 0x01)
                {
                    m_Version = Version.USA_v2;

                    m_LevelOvlIDTableOffset = 0x742B4;
                    m_FileTableOffset       = 0x11244;
                    m_FileTableLength       = 1824;
                }
                else
                {
                    m_Version = Version.USA_v1;

                    m_LevelOvlIDTableOffset = 0x73594;
                    m_FileTableOffset       = 0x1123C;
                    m_FileTableLength       = 1824;
                }
                break;

            case 0x4A4D5341: // ASMJ / JAP
                m_Version = Version.JAP;

                m_LevelOvlIDTableOffset = 0x73B38;
                m_FileTableOffset       = 0x1123C;
                m_FileTableLength       = 1824;
                break;

            case 0x504D5341:     // ASMP / EUR
                m_Version = Version.EUR;

                m_LevelOvlIDTableOffset = 0x758C8;
                m_FileTableOffset       = 0x13098;
                m_FileTableLength       = 2058;
                break;

            default:
                m_Version = Version.UNK;
                EndRW();
                throw new Exception("Unknown ROM version. Tell Mega-Mario about it.");
            }

            m_FileStream.Position = 0x28;
            ARM9RAMAddress        = m_BinReader.ReadUInt32();

            m_FileStream.Position  = 0x30;
            ARM7Offset             = m_BinReader.ReadUInt32();
            m_FileStream.Position += 0x04;
            ARM7RAMAddress         = m_BinReader.ReadUInt32();
            ARM7Size = m_BinReader.ReadUInt32();

            m_FileStream.Position = 0x40;
            FNTOffset             = m_BinReader.ReadUInt32();
            FNTSize   = m_BinReader.ReadUInt32();
            FATOffset = m_BinReader.ReadUInt32();
            FATSize   = m_BinReader.ReadUInt32();
            OVTOffset = m_BinReader.ReadUInt32();
            OVTSize   = m_BinReader.ReadUInt32();
            // no need to bother about ARM7 overlays... there's none in SM64DS

            m_FileStream.Position = 0x80;
            m_UsedSize            = m_BinReader.ReadUInt32();
            //m_UsedSize += ROM_END_MARGIN;

            m_FileStream.Position = FNTOffset + 6;
            ushort numdirs  = m_BinReader.ReadUInt16();
            ushort numfiles = (ushort)(FATSize / 8);

            m_DirEntries  = new DirEntry[numdirs];
            m_FileEntries = new FileEntry[numfiles];

            m_FileStream.Position = FATOffset;
            for (ushort f = 0; f < numfiles; f++)
            {
                uint start = m_BinReader.ReadUInt32();
                uint end   = m_BinReader.ReadUInt32();

                FileEntry fe;
                fe.ID            = f;
                fe.InternalID    = 0xFFFF;
                fe.ParentID      = 0;
                fe.Offset        = start;
                fe.Size          = end - start;
                fe.Name          = fe.FullName = "";
                fe.Data          = null;
                m_FileEntries[f] = fe;
            }

            DirEntry root;

            root.ID         = 0xF000;
            root.ParentID   = 0;
            root.Name       = root.FullName = "";
            m_DirEntries[0] = root;

            uint tableoffset = FNTOffset;

            for (ushort d = 0; d < numdirs; d++)
            {
                m_FileStream.Position = tableoffset;
                uint   subtableoffset = FNTOffset + m_BinReader.ReadUInt32();
                ushort first_fileid   = m_BinReader.ReadUInt16();
                ushort cur_fileid     = first_fileid;

                m_FileStream.Position = subtableoffset;
                for (;;)
                {
                    byte type_len = m_BinReader.ReadByte();

                    if (type_len == 0x00)
                    {
                        break;
                    }
                    else if (type_len > 0x80)
                    {
                        DirEntry dir;

                        dir.Name     = new string(m_BinReader.ReadChars(type_len & 0x7F));
                        dir.ID       = m_BinReader.ReadUInt16();
                        dir.ParentID = (ushort)(d + 0xF000);
                        dir.FullName = "";

                        m_DirEntries[dir.ID - 0xF000] = dir;
                    }
                    else if (type_len < 0x80)
                    {
                        char[] _name = m_BinReader.ReadChars(type_len & 0x7F);

                        m_FileEntries[cur_fileid].ParentID = (ushort)(d + 0xF000);
                        m_FileEntries[cur_fileid].Name     = new string(_name);
                        cur_fileid++;
                    }
                }

                tableoffset += 8;
            }

            for (int i = 0; i < m_DirEntries.Length; i++)
            {
                if (m_DirEntries[i].ParentID > 0xF000)
                {
                    m_DirEntries[i].FullName = m_DirEntries[m_DirEntries[i].ParentID - 0xF000].FullName + "/" + m_DirEntries[i].Name;
                }
                else
                {
                    m_DirEntries[i].FullName = m_DirEntries[i].Name;
                }
            }

            for (int i = 0; i < m_FileEntries.Length; i++)
            {
                if (m_FileEntries[i].ParentID > 0xF000)
                {
                    m_FileEntries[i].FullName = m_DirEntries[m_FileEntries[i].ParentID - 0xF000].FullName + "/" + m_FileEntries[i].Name;
                }
                else
                {
                    m_FileEntries[i].FullName = m_FileEntries[i].Name;
                }
            }

            uint numoverlays = OVTSize / 0x20;

            m_OverlayEntries = new OverlayEntry[numoverlays];

            for (uint i = 0; i < numoverlays; i++)
            {
                m_FileStream.Position = OVTOffset + (i * 0x20);
                OverlayEntry oe;

                oe.EntryOffset               = (uint)m_FileStream.Position;
                oe.ID                        = m_BinReader.ReadUInt32();
                oe.RAMAddress                = m_BinReader.ReadUInt32();
                oe.RAMSize                   = m_BinReader.ReadUInt32();
                oe.BSSSize                   = m_BinReader.ReadUInt32();
                oe.StaticInitStart           = this.m_BinReader.ReadUInt32();
                oe.StaticInitEnd             = this.m_BinReader.ReadUInt32();
                oe.FileID                    = (ushort)this.m_BinReader.ReadUInt32();
                oe.Flags                     = this.m_BinReader.ReadUInt32();
                m_OverlayEntries[(int)oe.ID] = oe;
            }

            if (m_Version == Version.EUR)
            {
                //screw the l that looks like a 1
                //            \/
                NitroOverlay ov0 = new NitroOverlay(this, 0);
                //And of course, fix those hardcoded values
                //Who expected a new object to be inserted, anyway?
                m_FileTableOffset = ov0.ReadPointer(0xA4);
                m_FileTableLength = ov0.Read32(0x9C);
            }

            EndRW();

            UpdateStrings();
        }
Ejemplo n.º 38
0
        public void LoadTables()
        {
            m_FileTable = new ushort[m_FileTableLength];

            NitroOverlay ovl0 = new NitroOverlay(this, 0);
            for (uint i = 0; i < m_FileTableLength; i++)
            {
                uint str_offset = ovl0.ReadPointer(m_FileTableOffset + (i*4));
                string fname = ovl0.ReadString(str_offset, 0);
                m_FileTable[i] = GetFileIDFromName(fname);
            }

            m_FileStream.Position = m_LevelOvlIDTableOffset;
            m_LevelOvlIDTable = new uint[52];
            for (uint i = 0; i < 52; i++)
                m_LevelOvlIDTable[i] = m_BinReader.ReadUInt32();
        }
Ejemplo n.º 39
0
        public SimpleObject(NitroOverlay ovl, uint offset, int num, int layer, int area)
            : base(ovl, offset, layer)
        {
            m_Area = area;
            m_UniqueID = (uint)(0x10000000 | num);
            m_Type = 5;

            ushort idparam = m_Overlay.Read16(m_Offset);
            ID = (ushort)(idparam & 0x1FF);
            Position.X = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x6)) / 1000f;
            YRotation = 0.0f;

            Parameters = new ushort[1];
            Parameters[0] = (ushort)(idparam >> 9);

            m_Renderer = InitialiseRenderer();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 40
0
        public LevelTexAnim(NitroOverlay ovl, uint tbloffset, uint offset, int num, int area)
        {
            m_Overlay = ovl;
            // Address of the animation data
            m_Offset = offset;
            m_UniqueID = (uint)num;
            m_Area = area;
            // Address of the texture animation data header for this texture animation
            m_TexAnimHeaderOffset = tbloffset;

            // Addresses at which the scale, rotation and translation data for this texture animation starts
            m_ScaleTblOffset = m_Overlay.ReadPointer(tbloffset + 0x4) + (uint)(m_Overlay.Read16(m_Offset + 0xE) * 4);
            m_RotTblOffset = m_Overlay.ReadPointer(tbloffset + 0x8) + (uint)(m_Overlay.Read16(m_Offset + 0x12) * 2);
            m_TransTblOffset = m_Overlay.ReadPointer(tbloffset + 0xC) + (uint)(m_Overlay.Read16(m_Offset + 0x16) * 4);

            // Addresses of the shared scale, rotation and translation tables
            m_BaseScaleTblAddr = m_Overlay.ReadPointer(tbloffset + 0x4);
            m_BaseRotTblAddr = m_Overlay.ReadPointer(tbloffset + 0x8);
            m_BaseTransTblAddr = m_Overlay.ReadPointer(tbloffset + 0xC);

            m_MatNameOffset = m_Overlay.ReadPointer(m_Offset + 0x4);
        }
Ejemplo n.º 41
0
        public MinimapScaleObject(NitroOverlay ovl, uint offset, int num, int layer, int area)
            : base(ovl, offset, layer)
        {
            m_Type = 12;
            m_Area = area;
            m_UniqueID = (uint)(0x50000000 | num);

            Parameters = new ushort[1];
            Parameters[0] = m_Overlay.Read16(m_Offset);

            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 42
0
        public Type14Object(NitroOverlay ovl, uint offset, int num, int layer, int area)
            : base(ovl, offset, layer)
        {
            m_Area = area;
            m_Type = 14;
            m_UniqueID = (uint)(0x50000000 | num);

            Parameters = new ushort[4];
            Parameters[0] = m_Overlay.Read8(m_Offset);
            Parameters[1] = m_Overlay.Read8(m_Offset + 1);
            Parameters[2] = m_Overlay.Read8(m_Offset + 2);
            Parameters[3] = m_Overlay.Read8(m_Offset + 3);

            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 43
0
        private void Patch_v4(BackgroundWorker lazyman)
        {
            uint lvl_start = 0;

            // Music table address
            uint music_tbl_addr = 0;
            // Store locations of the music bytes (music table address, +1, +2) - update to point to within overlay
            uint music_tbl_byte_1_addr = 0, music_tbl_byte_2_addr = 0, music_tbl_byte_3_addr = 0;
            // Locations at which offsets into the music table are calculated
            uint music_byte_1_offset = 0, music_byte_2_offset = 0, music_byte_3_offset = 0;

            switch (m_Version)
            {
            case Version.EUR:
                music_tbl_addr        = 0x75768;
                music_byte_1_offset   = 0x2de28;
                music_byte_2_offset   = 0x2d184;
                music_byte_3_offset   = 0x2d360;
                music_tbl_byte_1_addr = 0x2de60;
                music_tbl_byte_2_addr = 0x2d608;
                music_tbl_byte_3_addr = 0x2d644;

                lvl_start = 34925216;
                break;

            case Version.JAP:
                music_tbl_addr        = 0x739d8;
                music_byte_1_offset   = 0x2cd80;
                music_byte_2_offset   = 0x2c32c;
                music_byte_3_offset   = 0x2c508;
                music_tbl_byte_1_addr = 0x2cdb8;
                music_tbl_byte_2_addr = 0x2c7b0;
                music_tbl_byte_3_addr = 0x2c7ec;

                lvl_start = 34878592;
                break;

            case Version.USA_v1:
                music_tbl_addr        = 0x73434;
                music_byte_1_offset   = 0x2caa8;
                music_byte_2_offset   = 0x2c058;
                music_byte_3_offset   = 0x2c234;
                music_tbl_byte_1_addr = 0x2cae0;
                music_tbl_byte_2_addr = 0x2c4d8;
                music_tbl_byte_3_addr = 0x2c514;

                lvl_start = 34880416;
                break;

            case Version.USA_v2:
                music_tbl_addr        = 0x74154;
                music_byte_1_offset   = 0x2cdbc;
                music_byte_2_offset   = 0x2c368;
                music_byte_3_offset   = 0x2c544;
                music_tbl_byte_1_addr = 0x2cdf4;
                music_tbl_byte_2_addr = 0x2c7ec;
                music_tbl_byte_3_addr = 0x2c828;

                lvl_start = 34887456;
                break;
            }

            // Copy level music data
            for (int i = 0; i < 52; i++)
            {
                NitroOverlay ovl = new NitroOverlay(this, (uint)(103 + i));

                m_FileStream.Position = music_tbl_addr + (i * 3);
                ovl.Write8(0x7C + 0, m_BinReader.ReadByte());
                ovl.Write8(0x7C + 1, m_BinReader.ReadByte());
                ovl.Write8(0x7C + 2, m_BinReader.ReadByte());

                ovl.SaveChanges();
            }

            // Patch music code to load from overlays
            m_FileStream.Position = music_byte_1_offset;   // Offset into table generated
            m_BinWriter.Write((uint)0xe3a03000);           //MOV R3, #0    ;Set offset to 0
            m_FileStream.Position = music_tbl_byte_1_addr; // Stores location of music table byte 1
            m_BinWriter.Write((uint)(lvl_start + 0x7C));   // Write location in overlay of music data
            m_FileStream.Position = music_byte_2_offset;
            m_BinWriter.Write((uint)0xe3a02001);           //MOV R2, #1    ;Set offset to 1
            m_FileStream.Position = music_tbl_byte_2_addr;
            m_BinWriter.Write((uint)(lvl_start + 0x7C));
            m_FileStream.Position = music_byte_3_offset;
            m_BinWriter.Write((uint)0xe3a01002);//MOV R1, #2    ;Set offset to 0
            m_FileStream.Position = music_tbl_byte_3_addr;
            m_BinWriter.Write((uint)(lvl_start + 0x7C));

            lazyman.ReportProgress(499);
        }
Ejemplo n.º 44
0
        private void Patch_v2(BackgroundWorker lazyman)
        {
            lazyman.ReportProgress(200);

            uint levelptr_table = 0, objbank_table = 0;
            uint mempatch1 = 0, mempatch2 = 0;
            byte[] loadercode = null;
            uint lvl_ovlid_table = 0;
            uint unload_patch = 0, unload_branchop = 0;
            uint[] ovltable_addr_patch = new uint[4];
            uint[] ovltable_size_patch = new uint[4];
            uint lvlload_addr_patch = 0, lvlload_code_patch = 0;
            uint objbank_addr_patch = 0, objbank_code_patch = 0;

            switch (m_Version)
            {
            case Version.EUR:
                levelptr_table = 0x92208;
                objbank_table = 0x75998;
                mempatch1 = 0x18B60;
                mempatch2 = 0x58DE0;
                loadercode = Properties.Resources.level_ovl_init_EUR;
                lvl_ovlid_table = 0x758C8;
                unload_patch = 0x2DE80;
                unload_branchop = ARM_BL(0x0202DE80, 0x0214EAD8);
                ovltable_addr_patch[0] = 0x17E90; ovltable_addr_patch[1] = 0x17F30;
                ovltable_addr_patch[2] = 0x17FCC; ovltable_addr_patch[3] = 0x180FC;
                ovltable_size_patch[0] = 0x17E80; ovltable_size_patch[1] = 0x17ED0;
                ovltable_size_patch[2] = 0x17F70; ovltable_size_patch[3] = 0x180C4;
                lvlload_addr_patch = 0x2D62C;
                lvlload_code_patch = 0x2D288;
                objbank_addr_patch = 0x2E074;
                objbank_code_patch = 0x2DFAC;
                break;

            case Version.JAP:
                levelptr_table = 0x902B8;
                objbank_table = 0x73C08;
                mempatch1 = 0x57368;
                mempatch2 = 0xFFFFFFFF;
                loadercode = Properties.Resources.level_ovl_init_JAP;
                lvl_ovlid_table = 0x73B38;
                unload_patch = 0x2CDD8;
                unload_branchop = ARM_BL(0x0202CDD8, 0x021434B8);
                ovltable_addr_patch[0] = 0x17DE4; ovltable_addr_patch[1] = 0x17E84;
                ovltable_addr_patch[2] = 0x17F20; ovltable_addr_patch[3] = 0x18050;
                ovltable_size_patch[0] = 0x17DD4; ovltable_size_patch[1] = 0x17E24;
                ovltable_size_patch[2] = 0x17EC4; ovltable_size_patch[3] = 0x18018;
                lvlload_addr_patch = 0x2C7D4;
                lvlload_code_patch = 0x2C430;
                objbank_addr_patch = 0x2CFCC;
                objbank_code_patch = 0x2CF04;
                break;

            case Version.USA_v1:
                levelptr_table = 0x8FDB0;
                objbank_table = 0x73664;
                mempatch1 = 0x56EB8;
                mempatch2 = 0xFFFFFFFF;
                loadercode = Properties.Resources.level_ovl_init_USAv1;
                lvl_ovlid_table = 0x73594;
                unload_patch = 0x2CB00;
                unload_branchop = ARM_BL(0x0202CB00, 0x02143BD8);
                ovltable_addr_patch[0] = 0x17D70; ovltable_addr_patch[1] = 0x17E10;
                ovltable_addr_patch[2] = 0x17EAC; ovltable_addr_patch[3] = 0x17FDC;
                ovltable_size_patch[0] = 0x17D60; ovltable_size_patch[1] = 0x17DB0;
                ovltable_size_patch[2] = 0x17E50; ovltable_size_patch[3] = 0x17FA4;
                lvlload_addr_patch = 0x2C4FC;
                lvlload_code_patch = 0x2C15C;
                objbank_addr_patch = 0x2CCF4;
                objbank_code_patch = 0x2CC2C;
                break;

            case Version.USA_v2:
                levelptr_table = 0x90ACC;
                objbank_table = 0x74384;
                mempatch1 = 0x18A44;
                mempatch2 = 0x57B30;
                loadercode = Properties.Resources.level_ovl_init_USAv2;
                lvl_ovlid_table = 0x742B4;
                unload_patch = 0x2CE14;
                unload_branchop = ARM_BL(0x0202CE14, 0x02145758);
                ovltable_addr_patch[0] = 0x17DE4; ovltable_addr_patch[1] = 0x17E84;
                ovltable_addr_patch[2] = 0x17F20; ovltable_addr_patch[3] = 0x18050;
                ovltable_size_patch[0] = 0x17DD4; ovltable_size_patch[1] = 0x17E24;
                ovltable_size_patch[2] = 0x17EC4; ovltable_size_patch[3] = 0x18018;
                lvlload_addr_patch = 0x2C810;
                lvlload_code_patch = 0x2C46C;
                objbank_addr_patch = 0x2D008;
                objbank_code_patch = 0x2CF40;
                break;
            }

            // tweak the root heap start address to gain more overlay space :)
            m_FileStream.Position = mempatch1;
            uint lvl_start = m_BinReader.ReadUInt32();

            uint lvl_end = lvl_start + LEVEL_OVERLAY_SIZE;
            m_FileStream.Position = mempatch1;
            m_BinWriter.Write(lvl_end);
            if (mempatch2 != 0xFFFFFFFF)
            {
                m_FileStream.Position = mempatch2;
                m_BinWriter.Write(lvl_end);
            }

            // patch level overlay unloading
            m_FileStream.Position = unload_patch;
            m_BinWriter.Write(unload_branchop);

            // patch more stuff
            foreach (uint addr in ovltable_addr_patch)
            {
                m_FileStream.Position = addr;
                m_BinWriter.Write((uint)(0x02000000 + levelptr_table));
            }
            foreach (uint addr in ovltable_size_patch)
            {
                m_FileStream.Position = addr;
                uint op = m_BinReader.ReadUInt32();
                op = (op & 0xFFFFFF00) | 0x0D;
                m_FileStream.Position = addr;
                m_BinWriter.Write(op);
            }

            lazyman.ReportProgress(201);

            // for each level, create a new overlay with the loader code and level data
            uint dataoffset = (uint)((loadercode.Length + 3) & ~3);

            for (int i = 0; i < 52; i++)
            {
                uint overlayid = AddOverlay(lvl_start);

                m_FileStream.Position = lvl_ovlid_table + (i*4);
                uint old_overlayid = m_BinReader.ReadUInt32();

                m_FileStream.Position = lvl_ovlid_table + (i*4);
                m_BinWriter.Write(overlayid);

                NitroOverlay ovl = new NitroOverlay(this, overlayid);
                ovl.SetInitializer(lvl_start, 4);
                ovl.WriteBlock(0, loadercode);

                // write the object bank settings
                m_FileStream.Position = objbank_table + (i * 7);
                byte[] objbanks = m_BinReader.ReadBytes(7);
                ovl.WriteBlock(dataoffset, objbanks);

                ovl.Write8(dataoffset + 0x7, 0x00);
                ovl.Write32(dataoffset + 0x8, (uint)(i + 1));

                // copy level data
                {
                    NitroOverlay oldovl = new NitroOverlay(this, old_overlayid);
                    uint oldbase = oldovl.GetRAMAddr();

                    m_FileStream.Position = levelptr_table + (i*4);
                    uint header_offset = m_BinReader.ReadUInt32() - oldbase;

                    uint curoffset = dataoffset + 0x40;

                    // CLPS (collision behaviors) chunk
                    {
                        uint clps_addr = oldovl.ReadPointer(header_offset);
                        ushort clps_num = oldovl.Read16(clps_addr + 0x06);
                        uint clps_size = (uint)(8 + (clps_num * 8));
                        byte[] clps = oldovl.ReadBlock(clps_addr, clps_size);
                        ovl.WriteBlock(curoffset, clps);

                        ovl.WritePointer(dataoffset + 0x0C, curoffset);
                        curoffset += clps_size;
                    }

                    // misc objects table list
                    {
                        uint tables_addr = oldovl.ReadPointer(header_offset + 0x4);
                        ushort tables_num = oldovl.Read16(tables_addr);
                        tables_addr = oldovl.ReadPointer(tables_addr + 0x4);

                        ovl.WritePointer(dataoffset + 0x10, curoffset);
                        ovl.Write16(curoffset, tables_num);
                        ovl.WritePointer(curoffset + 0x04, curoffset + 0x8);
                        curoffset += 0x8;

                        uint objdata_offset = (uint)(curoffset + (tables_num * 8));
                        for (ushort t = 0; t < tables_num; t++)
                        {
                            uint tbl_part1 = oldovl.Read32(tables_addr);
                            uint tbl_addr = oldovl.ReadPointer(tables_addr + 0x4);

                            ovl.Write32(curoffset, tbl_part1);
                            ovl.WritePointer(curoffset + 0x4, objdata_offset);

                            tables_addr += 8;
                            curoffset += 8;

                            byte tbltype = (byte)(tbl_part1 & 0x1F);
                            byte numentries = (byte)((tbl_part1 >> 8) & 0xFF);

                            if ((tbltype == 13) || (tbltype > 14))
                                throw new Exception(String.Format("Wrong object table type {0} (0x{0:X2}) in level data", tbltype));

                            int[] datasizes = {16, 16, 6, 6, 14, 8, 8, 8, 8, 12, 14, 2, 2, 0, 4};
                            int datasize = numentries * datasizes[tbltype];

                            byte[] data = oldovl.ReadBlock(tbl_addr, (uint)datasize);
                            ovl.WriteBlock(objdata_offset, data);

                            objdata_offset += (uint)((datasize + 3) & ~3);
                        }

                        curoffset = objdata_offset;
                    }

                    // main object table lists
                    // and that stuff about texture scrolling
                    {
                        uint tlists_addr = oldovl.ReadPointer(header_offset + 0x10);
                        byte tlists_num = oldovl.Read8(header_offset + 0x14);

                        uint tlists_new_addr = curoffset;
                        curoffset += (uint)(tlists_num * 12);

                        ovl.WritePointer(dataoffset + 0x1C, tlists_new_addr);
                        ovl.Write8(dataoffset + 0x20, tlists_num);

                        for (byte tl = 0; tl < tlists_num; tl++)
                        {
                            uint tables_addr = oldovl.ReadPointer(tlists_addr);
                            uint texanm_addr = oldovl.ReadPointer(tlists_addr + 0x4);

                            if (tables_addr != 0xFFFFFFFF)
                            {
                                ovl.WritePointer(tlists_new_addr, curoffset);

                                ushort tables_num = oldovl.Read16(tables_addr);
                                tables_addr = oldovl.ReadPointer(tables_addr + 0x4);

                                ovl.Write16(curoffset, tables_num);
                                ovl.WritePointer(curoffset + 0x04, curoffset + 0x8);
                                curoffset += 0x8;

                                uint objdata_offset = (uint)(curoffset + (tables_num * 8));
                                for (ushort t = 0; t < tables_num; t++)
                                {
                                    uint tbl_part1 = oldovl.Read32(tables_addr);
                                    uint tbl_addr = oldovl.ReadPointer(tables_addr + 0x4);

                                    ovl.Write32(curoffset, tbl_part1);
                                    ovl.WritePointer(curoffset + 0x4, objdata_offset);

                                    tables_addr += 8;
                                    curoffset += 8;

                                    byte tbltype = (byte)(tbl_part1 & 0x1F);
                                    byte numentries = (byte)((tbl_part1 >> 8) & 0xFF);

                                    if ((tbltype == 13) || (tbltype > 14))
                                        throw new Exception(String.Format("Wrong object table type {0} (0x{0:X2}) in level data", tbltype));

                                    int[] datasizes = { 16, 16, 6, 6, 14, 8, 8, 8, 8, 12, 14, 2, 2, 0, 4 };
                                    int datasize = numentries * datasizes[tbltype];

                                    byte[] data = oldovl.ReadBlock(tbl_addr, (uint)datasize);
                                    ovl.WriteBlock(objdata_offset, data);

                                    objdata_offset += (uint)((datasize + 3) & ~3);
                                }

                                curoffset = objdata_offset;
                            }
                            else
                                ovl.Write32(tlists_new_addr, 0);

                            if (texanm_addr != 0xFFFFFFFF)//If not null
                            {
                                ovl.WritePointer(tlists_new_addr + 0x4, curoffset);

                                uint texanm_new_addr = curoffset;
                                curoffset += 0x18;

                                uint textures_addr = oldovl.ReadPointer(texanm_addr + 0x14);
                                uint numscale = 0, numrot = 0, numtrans = 0;
                                uint numtextures = oldovl.Read32(texanm_addr + 0x10);

                                ovl.Write32(texanm_new_addr, oldovl.Read32(texanm_addr));
                                ovl.Write32(texanm_new_addr + 0x10, numtextures);

                                uint textures_new_addr = curoffset;
                                curoffset += (numtextures * 0x1C);

                                ovl.WritePointer(texanm_new_addr + 0x14, textures_new_addr);
                                for (uint t = 0; t < numtextures; t++)
                                {
                                    uint tex_old_addr = textures_addr + (t * 0x1C);
                                    uint tex_new_addr = textures_new_addr + (t * 0x1C);

                                    ushort tex_scalenum = oldovl.Read16(tex_old_addr + 0x0C);
                                    ushort tex_scalestart = oldovl.Read16(tex_old_addr + 0x0E);
                                    ushort tex_rotnum = oldovl.Read16(tex_old_addr + 0x10);
                                    ushort tex_rotstart = oldovl.Read16(tex_old_addr + 0x12);
                                    ushort tex_transnum = oldovl.Read16(tex_old_addr + 0x14);
                                    ushort tex_transstart = oldovl.Read16(tex_old_addr + 0x16);

                                    if ((tex_scalestart + tex_scalenum) > numscale)
                                        numscale = (uint)(tex_scalestart + tex_scalenum);
                                    if ((tex_rotstart + tex_rotnum) > numrot)
                                        numrot = (uint)(tex_rotstart + tex_rotnum);
                                    if ((tex_transstart + tex_transnum) > numtrans)
                                        numtrans = (uint)(tex_transstart + tex_transnum);

                                    ovl.Write32(tex_new_addr, oldovl.Read32(tex_old_addr));
                                    ovl.WritePointer(tex_new_addr + 0x4, curoffset);
                                    ovl.Write32(tex_new_addr + 0x8, oldovl.Read32(tex_old_addr + 0x8));
                                    ovl.Write16(tex_new_addr + 0xC, tex_scalenum);
                                    ovl.Write16(tex_new_addr + 0xE, tex_scalestart);
                                    ovl.Write16(tex_new_addr + 0x10, tex_rotnum);
                                    ovl.Write16(tex_new_addr + 0x12, tex_rotstart);
                                    ovl.Write16(tex_new_addr + 0x14, tex_transnum);
                                    ovl.Write16(tex_new_addr + 0x16, tex_transstart);
                                    ovl.Write32(tex_new_addr + 0x18, oldovl.Read32(tex_old_addr + 0x18));

                                    string tex_matname = oldovl.ReadString(oldovl.ReadPointer(tex_old_addr + 0x4), 0);
                                    ovl.WriteString(curoffset, tex_matname, 0);
                                    curoffset += (uint)((tex_matname.Length + 3) & ~3);
                                }

                                uint scale_addr = oldovl.ReadPointer(texanm_addr + 0x4);
                                ovl.WritePointer(texanm_new_addr + 0x4, curoffset);
                                for (uint v = 0; v < numscale; v++)
                                {
                                    ovl.Write32(curoffset, oldovl.Read32(scale_addr + (v * 4)));
                                    curoffset += 4;
                                }

                                uint rot_addr = oldovl.ReadPointer(texanm_addr + 0x8);
                                ovl.WritePointer(texanm_new_addr + 0x8, curoffset);
                                for (uint v = 0; v < numrot; v++)
                                {
                                    ovl.Write16(curoffset, oldovl.Read16(rot_addr + (v * 2)));
                                    curoffset += 2;
                                }
                                curoffset = (uint)((curoffset + 3) & ~3);

                                uint trans_addr = oldovl.ReadPointer(texanm_addr + 0xC);
                                ovl.WritePointer(texanm_new_addr + 0xC, curoffset);
                                for (uint v = 0; v < numtrans; v++)
                                {
                                    ovl.Write32(curoffset, oldovl.Read32(trans_addr + (v * 4)));
                                    curoffset += 4;
                                }
                            }
                            else
                                ovl.Write32(tlists_new_addr + 0x4, 0);

                            ovl.Write32(tlists_new_addr + 0x8, oldovl.Read32(tlists_addr + 0x8));
                            tlists_new_addr += 12;
                            tlists_addr += 12;
                        }
                    }

                    // misc header pieces
                    ovl.Write32(dataoffset + 0x14, oldovl.Read32(header_offset + 0x8));
                    ovl.Write32(dataoffset + 0x18, oldovl.Read32(header_offset + 0xC));
                    ovl.Write16(dataoffset + 0x22, oldovl.Read16(header_offset + 0x16));
                    ovl.Write8(dataoffset + 0x24, oldovl.Read8(header_offset + 0x18));
                }

                ovl.SaveChanges();
                lazyman.ReportProgress(201 + (int)((98f / 54f) * i));
            }

            // fix the level loader as to load from the new overlays
            m_FileStream.Position = lvlload_addr_patch;
            m_BinWriter.Write((uint)(lvl_start + dataoffset + 0xC));

            m_FileStream.Position = lvlload_code_patch;
            m_BinWriter.Write((uint)0xE1A00000);

            // refill the old level header address table
            // to adapt it to its new usages
            m_FileStream.Position = levelptr_table;
            for (uint i = 0; i < 13; i++)
            {
                m_BinWriter.Write((uint)0xFFFFFFFF);
                m_BinWriter.Write((uint)0x00000000);
                m_BinWriter.Write((uint)0x00000000);
            }
            m_BinWriter.Write((uint)0x00000000);
            m_BinWriter.Write((uint)0x00000000);

            // fix the object banks thingy
            m_FileStream.Position = objbank_addr_patch;
            m_BinWriter.Write((uint)(levelptr_table + 0x0200009C));

            m_FileStream.Position = objbank_code_patch;
            m_BinWriter.Write((uint)0xE1A07001);

            // phew! what a goddamn long thing
            lazyman.ReportProgress(299);
        }
Ejemplo n.º 45
0
        public PathObject(NitroOverlay ovl, uint offset, int num)
            : base(ovl, offset, 0)
        {
            m_UniqueID = (uint)(0x30000000 | num);
            m_Type = 3;

            Parameters = new ushort[5];
            Parameters[0] = m_Overlay.Read16(m_Offset);
            Parameters[1] = (ushort)m_Overlay.Read8(m_Offset + 0x2);
            Parameters[2] = (ushort)m_Overlay.Read8(m_Offset + 0x3);
            Parameters[3] = (ushort)m_Overlay.Read8(m_Offset + 0x4);
            Parameters[4] = (ushort)m_Overlay.Read8(m_Offset + 0x5);

            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 46
0
        //private Hashtable m_PParams;
        public StandardObject(NitroOverlay ovl, uint offset, int num, int layer, int area)
            : base(ovl, offset, layer)
        {
            m_Area = area;
            m_UniqueID = (uint)(0x10000000 | num);
            m_Type = 0;

            ID = m_Overlay.Read16(m_Offset);
            Position.X = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x6)) / 1000f;
            YRotation = ((float)((short)m_Overlay.Read16(m_Offset + 0xA)) / 4096f) * 22.5f;

            Parameters = new ushort[3];
            Parameters[0] = m_Overlay.Read16(m_Offset + 0xE);
            Parameters[1] = m_Overlay.Read16(m_Offset + 0x8);
            Parameters[2] = m_Overlay.Read16(m_Offset + 0xC);

            m_Renderer = InitialiseRenderer();
            // m_PParams = new Hashtable();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }
Ejemplo n.º 47
0
        private void Patch_v4(BackgroundWorker lazyman)
        {
            uint lvl_start = 0;

            // Music table address
            uint music_tbl_addr = 0;
            // Store locations of the music bytes (music table address, +1, +2) - update to point to within overlay
            uint music_tbl_byte_1_addr = 0, music_tbl_byte_2_addr = 0, music_tbl_byte_3_addr = 0;
            // Locations at which offsets into the music table are calculated
            uint music_byte_1_offset = 0, music_byte_2_offset = 0, music_byte_3_offset = 0;

            switch (m_Version)
            {
                case Version.EUR:
                    music_tbl_addr = 0x75768;
                    music_byte_1_offset = 0x2de28;
                    music_byte_2_offset = 0x2d184;
                    music_byte_3_offset = 0x2d360;
                    music_tbl_byte_1_addr = 0x2de60;
                    music_tbl_byte_2_addr = 0x2d608;
                    music_tbl_byte_3_addr = 0x2d644;

                    lvl_start = 34925216;
                    break;

                case Version.JAP:
                    music_tbl_addr = 0x739d8;
                    music_byte_1_offset = 0x2cd80;
                    music_byte_2_offset = 0x2c32c;
                    music_byte_3_offset = 0x2c508;
                    music_tbl_byte_1_addr = 0x2cdb8;
                    music_tbl_byte_2_addr = 0x2c7b0;
                    music_tbl_byte_3_addr = 0x2c7ec;

                    lvl_start = 34878592;
                    break;

                case Version.USA_v1:
                    music_tbl_addr = 0x73434;
                    music_byte_1_offset = 0x2caa8;
                    music_byte_2_offset = 0x2c058;
                    music_byte_3_offset = 0x2c234;
                    music_tbl_byte_1_addr = 0x2cae0;
                    music_tbl_byte_2_addr = 0x2c4d8;
                    music_tbl_byte_3_addr = 0x2c514;

                    lvl_start = 34880416;
                    break;

                case Version.USA_v2:
                    music_tbl_addr = 0x74154;
                    music_byte_1_offset = 0x2cdbc;
                    music_byte_2_offset = 0x2c368;
                    music_byte_3_offset = 0x2c544;
                    music_tbl_byte_1_addr = 0x2cdf4;
                    music_tbl_byte_2_addr = 0x2c7ec;
                    music_tbl_byte_3_addr = 0x2c828;

                    lvl_start = 34887456;
                    break;
            }

            // Copy level music data
            for (int i = 0; i < 52; i++)
            {
                NitroOverlay ovl = new NitroOverlay(this, (uint)(103 + i));

                m_FileStream.Position = music_tbl_addr + (i * 3);
                ovl.Write8(0x7C + 0, m_BinReader.ReadByte());
                ovl.Write8(0x7C + 1, m_BinReader.ReadByte());
                ovl.Write8(0x7C + 2, m_BinReader.ReadByte());

                ovl.SaveChanges();
            }

            // Patch music code to load from overlays
            m_FileStream.Position = music_byte_1_offset;// Offset into table generated
            m_BinWriter.Write((uint)0xe3a03000);//MOV R3, #0    ;Set offset to 0
            m_FileStream.Position = music_tbl_byte_1_addr;// Stores location of music table byte 1
            m_BinWriter.Write((uint)(lvl_start + 0x7C));// Write location in overlay of music data
            m_FileStream.Position = music_byte_2_offset;
            m_BinWriter.Write((uint)0xe3a02001);//MOV R2, #1    ;Set offset to 1
            m_FileStream.Position = music_tbl_byte_2_addr;
            m_BinWriter.Write((uint)(lvl_start + 0x7C));
            m_FileStream.Position = music_byte_3_offset;
            m_BinWriter.Write((uint)0xe3a01002);//MOV R1, #2    ;Set offset to 0
            m_FileStream.Position = music_tbl_byte_3_addr;
            m_BinWriter.Write((uint)(lvl_start + 0x7C));

            lazyman.ReportProgress(499);
        }
Ejemplo n.º 48
0
        private void Patch_v2(BackgroundWorker lazyman)
        {
            lazyman.ReportProgress(200);

            uint levelptr_table = 0, objbank_table = 0;
            uint mempatch1 = 0, mempatch2 = 0;

            byte[] loadercode = null;
            uint   lvl_ovlid_table = 0;
            uint   unload_patch = 0, unload_branchop = 0;

            uint[] ovltable_addr_patch = new uint[4];
            uint[] ovltable_size_patch = new uint[4];
            uint   lvlload_addr_patch = 0, lvlload_code_patch = 0;
            uint   objbank_addr_patch = 0, objbank_code_patch = 0;

            switch (m_Version)
            {
            case Version.EUR:
                levelptr_table         = 0x92208;
                objbank_table          = 0x75998;
                mempatch1              = 0x18B60;
                mempatch2              = 0x58DE0;
                loadercode             = Properties.Resources.level_ovl_init_EUR;
                lvl_ovlid_table        = 0x758C8;
                unload_patch           = 0x2DE80;
                unload_branchop        = ARM_BL(0x0202DE80, 0x0214EAD8);
                ovltable_addr_patch[0] = 0x17E90; ovltable_addr_patch[1] = 0x17F30;
                ovltable_addr_patch[2] = 0x17FCC; ovltable_addr_patch[3] = 0x180FC;
                ovltable_size_patch[0] = 0x17E80; ovltable_size_patch[1] = 0x17ED0;
                ovltable_size_patch[2] = 0x17F70; ovltable_size_patch[3] = 0x180C4;
                lvlload_addr_patch     = 0x2D62C;
                lvlload_code_patch     = 0x2D288;
                objbank_addr_patch     = 0x2E074;
                objbank_code_patch     = 0x2DFAC;
                break;

            case Version.JAP:
                levelptr_table         = 0x902B8;
                objbank_table          = 0x73C08;
                mempatch1              = 0x57368;
                mempatch2              = 0xFFFFFFFF;
                loadercode             = Properties.Resources.level_ovl_init_JAP;
                lvl_ovlid_table        = 0x73B38;
                unload_patch           = 0x2CDD8;
                unload_branchop        = ARM_BL(0x0202CDD8, 0x021434B8);
                ovltable_addr_patch[0] = 0x17DE4; ovltable_addr_patch[1] = 0x17E84;
                ovltable_addr_patch[2] = 0x17F20; ovltable_addr_patch[3] = 0x18050;
                ovltable_size_patch[0] = 0x17DD4; ovltable_size_patch[1] = 0x17E24;
                ovltable_size_patch[2] = 0x17EC4; ovltable_size_patch[3] = 0x18018;
                lvlload_addr_patch     = 0x2C7D4;
                lvlload_code_patch     = 0x2C430;
                objbank_addr_patch     = 0x2CFCC;
                objbank_code_patch     = 0x2CF04;
                break;

            case Version.USA_v1:
                levelptr_table         = 0x8FDB0;
                objbank_table          = 0x73664;
                mempatch1              = 0x56EB8;
                mempatch2              = 0xFFFFFFFF;
                loadercode             = Properties.Resources.level_ovl_init_USAv1;
                lvl_ovlid_table        = 0x73594;
                unload_patch           = 0x2CB00;
                unload_branchop        = ARM_BL(0x0202CB00, 0x02143BD8);
                ovltable_addr_patch[0] = 0x17D70; ovltable_addr_patch[1] = 0x17E10;
                ovltable_addr_patch[2] = 0x17EAC; ovltable_addr_patch[3] = 0x17FDC;
                ovltable_size_patch[0] = 0x17D60; ovltable_size_patch[1] = 0x17DB0;
                ovltable_size_patch[2] = 0x17E50; ovltable_size_patch[3] = 0x17FA4;
                lvlload_addr_patch     = 0x2C4FC;
                lvlload_code_patch     = 0x2C15C;
                objbank_addr_patch     = 0x2CCF4;
                objbank_code_patch     = 0x2CC2C;
                break;

            case Version.USA_v2:
                levelptr_table         = 0x90ACC;
                objbank_table          = 0x74384;
                mempatch1              = 0x18A44;
                mempatch2              = 0x57B30;
                loadercode             = Properties.Resources.level_ovl_init_USAv2;
                lvl_ovlid_table        = 0x742B4;
                unload_patch           = 0x2CE14;
                unload_branchop        = ARM_BL(0x0202CE14, 0x02145758);
                ovltable_addr_patch[0] = 0x17DE4; ovltable_addr_patch[1] = 0x17E84;
                ovltable_addr_patch[2] = 0x17F20; ovltable_addr_patch[3] = 0x18050;
                ovltable_size_patch[0] = 0x17DD4; ovltable_size_patch[1] = 0x17E24;
                ovltable_size_patch[2] = 0x17EC4; ovltable_size_patch[3] = 0x18018;
                lvlload_addr_patch     = 0x2C810;
                lvlload_code_patch     = 0x2C46C;
                objbank_addr_patch     = 0x2D008;
                objbank_code_patch     = 0x2CF40;
                break;
            }

            // tweak the root heap start address to gain more overlay space :)
            m_FileStream.Position = mempatch1;
            uint lvl_start = m_BinReader.ReadUInt32();

            uint lvl_end = lvl_start + LEVEL_OVERLAY_SIZE;

            m_FileStream.Position = mempatch1;
            m_BinWriter.Write(lvl_end);
            if (mempatch2 != 0xFFFFFFFF)
            {
                m_FileStream.Position = mempatch2;
                m_BinWriter.Write(lvl_end);
            }

            // patch level overlay unloading
            m_FileStream.Position = unload_patch;
            m_BinWriter.Write(unload_branchop);

            // patch more stuff
            foreach (uint addr in ovltable_addr_patch)
            {
                m_FileStream.Position = addr;
                m_BinWriter.Write((uint)(0x02000000 + levelptr_table));
            }
            foreach (uint addr in ovltable_size_patch)
            {
                m_FileStream.Position = addr;
                uint op = m_BinReader.ReadUInt32();
                op = (op & 0xFFFFFF00) | 0x0D;
                m_FileStream.Position = addr;
                m_BinWriter.Write(op);
            }

            lazyman.ReportProgress(201);

            // for each level, create a new overlay with the loader code and level data
            uint dataoffset = (uint)((loadercode.Length + 3) & ~3);

            for (int i = 0; i < 52; i++)
            {
                uint overlayid = AddOverlay(lvl_start);

                m_FileStream.Position = lvl_ovlid_table + (i * 4);
                uint old_overlayid = m_BinReader.ReadUInt32();

                m_FileStream.Position = lvl_ovlid_table + (i * 4);
                m_BinWriter.Write(overlayid);

                NitroOverlay ovl = new NitroOverlay(this, overlayid);
                ovl.SetInitializer(lvl_start, 4);
                ovl.WriteBlock(0, loadercode);

                // write the object bank settings
                m_FileStream.Position = objbank_table + (i * 7);
                byte[] objbanks = m_BinReader.ReadBytes(7);
                ovl.WriteBlock(dataoffset, objbanks);

                ovl.Write8(dataoffset + 0x7, 0x00);
                ovl.Write32(dataoffset + 0x8, (uint)(i + 1));

                // copy level data
                {
                    NitroOverlay oldovl  = new NitroOverlay(this, old_overlayid);
                    uint         oldbase = oldovl.GetRAMAddr();

                    m_FileStream.Position = levelptr_table + (i * 4);
                    uint header_offset = m_BinReader.ReadUInt32() - oldbase;

                    uint curoffset = dataoffset + 0x40;

                    // CLPS (collision behaviors) chunk
                    {
                        uint   clps_addr = oldovl.ReadPointer(header_offset);
                        ushort clps_num  = oldovl.Read16(clps_addr + 0x06);
                        uint   clps_size = (uint)(8 + (clps_num * 8));
                        byte[] clps      = oldovl.ReadBlock(clps_addr, clps_size);
                        ovl.WriteBlock(curoffset, clps);

                        ovl.WritePointer(dataoffset + 0x0C, curoffset);
                        curoffset += clps_size;
                    }

                    // misc objects table list
                    {
                        uint   tables_addr = oldovl.ReadPointer(header_offset + 0x4);
                        ushort tables_num  = oldovl.Read16(tables_addr);
                        tables_addr = oldovl.ReadPointer(tables_addr + 0x4);

                        ovl.WritePointer(dataoffset + 0x10, curoffset);
                        ovl.Write16(curoffset, tables_num);
                        ovl.WritePointer(curoffset + 0x04, curoffset + 0x8);
                        curoffset += 0x8;

                        uint objdata_offset = (uint)(curoffset + (tables_num * 8));
                        for (ushort t = 0; t < tables_num; t++)
                        {
                            uint tbl_part1 = oldovl.Read32(tables_addr);
                            uint tbl_addr  = oldovl.ReadPointer(tables_addr + 0x4);

                            ovl.Write32(curoffset, tbl_part1);
                            ovl.WritePointer(curoffset + 0x4, objdata_offset);

                            tables_addr += 8;
                            curoffset   += 8;

                            byte tbltype    = (byte)(tbl_part1 & 0x1F);
                            byte numentries = (byte)((tbl_part1 >> 8) & 0xFF);

                            if ((tbltype == 13) || (tbltype > 14))
                            {
                                throw new Exception(String.Format("Wrong object table type {0} (0x{0:X2}) in level data", tbltype));
                            }

                            int[] datasizes = { 16, 16, 6, 6, 14, 8, 8, 8, 8, 12, 14, 2, 2, 0, 4 };
                            int   datasize  = numentries * datasizes[tbltype];

                            byte[] data = oldovl.ReadBlock(tbl_addr, (uint)datasize);
                            ovl.WriteBlock(objdata_offset, data);

                            objdata_offset += (uint)((datasize + 3) & ~3);
                        }

                        curoffset = objdata_offset;
                    }

                    // main object table lists
                    // and that stuff about texture scrolling
                    {
                        uint tlists_addr = oldovl.ReadPointer(header_offset + 0x10);
                        byte tlists_num  = oldovl.Read8(header_offset + 0x14);

                        uint tlists_new_addr = curoffset;
                        curoffset += (uint)(tlists_num * 12);

                        ovl.WritePointer(dataoffset + 0x1C, tlists_new_addr);
                        ovl.Write8(dataoffset + 0x20, tlists_num);

                        for (byte tl = 0; tl < tlists_num; tl++)
                        {
                            uint tables_addr = oldovl.ReadPointer(tlists_addr);
                            uint texanm_addr = oldovl.ReadPointer(tlists_addr + 0x4);

                            if (tables_addr != 0xFFFFFFFF)
                            {
                                ovl.WritePointer(tlists_new_addr, curoffset);

                                ushort tables_num = oldovl.Read16(tables_addr);
                                tables_addr = oldovl.ReadPointer(tables_addr + 0x4);

                                ovl.Write16(curoffset, tables_num);
                                ovl.WritePointer(curoffset + 0x04, curoffset + 0x8);
                                curoffset += 0x8;

                                uint objdata_offset = (uint)(curoffset + (tables_num * 8));
                                for (ushort t = 0; t < tables_num; t++)
                                {
                                    uint tbl_part1 = oldovl.Read32(tables_addr);
                                    uint tbl_addr  = oldovl.ReadPointer(tables_addr + 0x4);

                                    ovl.Write32(curoffset, tbl_part1);
                                    ovl.WritePointer(curoffset + 0x4, objdata_offset);

                                    tables_addr += 8;
                                    curoffset   += 8;

                                    byte tbltype    = (byte)(tbl_part1 & 0x1F);
                                    byte numentries = (byte)((tbl_part1 >> 8) & 0xFF);

                                    if ((tbltype == 13) || (tbltype > 14))
                                    {
                                        throw new Exception(String.Format("Wrong object table type {0} (0x{0:X2}) in level data", tbltype));
                                    }

                                    int[] datasizes = { 16, 16, 6, 6, 14, 8, 8, 8, 8, 12, 14, 2, 2, 0, 4 };
                                    int   datasize  = numentries * datasizes[tbltype];

                                    byte[] data = oldovl.ReadBlock(tbl_addr, (uint)datasize);
                                    ovl.WriteBlock(objdata_offset, data);

                                    objdata_offset += (uint)((datasize + 3) & ~3);
                                }

                                curoffset = objdata_offset;
                            }
                            else
                            {
                                ovl.Write32(tlists_new_addr, 0);
                            }

                            if (texanm_addr != 0xFFFFFFFF)//If not null
                            {
                                ovl.WritePointer(tlists_new_addr + 0x4, curoffset);

                                uint texanm_new_addr = curoffset;
                                curoffset += 0x18;

                                uint textures_addr = oldovl.ReadPointer(texanm_addr + 0x14);
                                uint numscale = 0, numrot = 0, numtrans = 0;
                                uint numtextures = oldovl.Read32(texanm_addr + 0x10);

                                ovl.Write32(texanm_new_addr, oldovl.Read32(texanm_addr));
                                ovl.Write32(texanm_new_addr + 0x10, numtextures);

                                uint textures_new_addr = curoffset;
                                curoffset += (numtextures * 0x1C);

                                ovl.WritePointer(texanm_new_addr + 0x14, textures_new_addr);
                                for (uint t = 0; t < numtextures; t++)
                                {
                                    uint tex_old_addr = textures_addr + (t * 0x1C);
                                    uint tex_new_addr = textures_new_addr + (t * 0x1C);

                                    ushort tex_scalenum   = oldovl.Read16(tex_old_addr + 0x0C);
                                    ushort tex_scalestart = oldovl.Read16(tex_old_addr + 0x0E);
                                    ushort tex_rotnum     = oldovl.Read16(tex_old_addr + 0x10);
                                    ushort tex_rotstart   = oldovl.Read16(tex_old_addr + 0x12);
                                    ushort tex_transnum   = oldovl.Read16(tex_old_addr + 0x14);
                                    ushort tex_transstart = oldovl.Read16(tex_old_addr + 0x16);

                                    if ((tex_scalestart + tex_scalenum) > numscale)
                                    {
                                        numscale = (uint)(tex_scalestart + tex_scalenum);
                                    }
                                    if ((tex_rotstart + tex_rotnum) > numrot)
                                    {
                                        numrot = (uint)(tex_rotstart + tex_rotnum);
                                    }
                                    if ((tex_transstart + tex_transnum) > numtrans)
                                    {
                                        numtrans = (uint)(tex_transstart + tex_transnum);
                                    }

                                    ovl.Write32(tex_new_addr, oldovl.Read32(tex_old_addr));
                                    ovl.WritePointer(tex_new_addr + 0x4, curoffset);
                                    ovl.Write32(tex_new_addr + 0x8, oldovl.Read32(tex_old_addr + 0x8));
                                    ovl.Write16(tex_new_addr + 0xC, tex_scalenum);
                                    ovl.Write16(tex_new_addr + 0xE, tex_scalestart);
                                    ovl.Write16(tex_new_addr + 0x10, tex_rotnum);
                                    ovl.Write16(tex_new_addr + 0x12, tex_rotstart);
                                    ovl.Write16(tex_new_addr + 0x14, tex_transnum);
                                    ovl.Write16(tex_new_addr + 0x16, tex_transstart);
                                    ovl.Write32(tex_new_addr + 0x18, oldovl.Read32(tex_old_addr + 0x18));

                                    string tex_matname = oldovl.ReadString(oldovl.ReadPointer(tex_old_addr + 0x4), 0);
                                    ovl.WriteString(curoffset, tex_matname, 0);
                                    curoffset += (uint)((tex_matname.Length + 3) & ~3);
                                }

                                uint scale_addr = oldovl.ReadPointer(texanm_addr + 0x4);
                                ovl.WritePointer(texanm_new_addr + 0x4, curoffset);
                                for (uint v = 0; v < numscale; v++)
                                {
                                    ovl.Write32(curoffset, oldovl.Read32(scale_addr + (v * 4)));
                                    curoffset += 4;
                                }

                                uint rot_addr = oldovl.ReadPointer(texanm_addr + 0x8);
                                ovl.WritePointer(texanm_new_addr + 0x8, curoffset);
                                for (uint v = 0; v < numrot; v++)
                                {
                                    ovl.Write16(curoffset, oldovl.Read16(rot_addr + (v * 2)));
                                    curoffset += 2;
                                }
                                curoffset = (uint)((curoffset + 3) & ~3);

                                uint trans_addr = oldovl.ReadPointer(texanm_addr + 0xC);
                                ovl.WritePointer(texanm_new_addr + 0xC, curoffset);
                                for (uint v = 0; v < numtrans; v++)
                                {
                                    ovl.Write32(curoffset, oldovl.Read32(trans_addr + (v * 4)));
                                    curoffset += 4;
                                }
                            }
                            else
                            {
                                ovl.Write32(tlists_new_addr + 0x4, 0);
                            }

                            ovl.Write32(tlists_new_addr + 0x8, oldovl.Read32(tlists_addr + 0x8));
                            tlists_new_addr += 12;
                            tlists_addr     += 12;
                        }
                    }

                    // misc header pieces
                    ovl.Write32(dataoffset + 0x14, oldovl.Read32(header_offset + 0x8));
                    ovl.Write32(dataoffset + 0x18, oldovl.Read32(header_offset + 0xC));
                    ovl.Write16(dataoffset + 0x22, oldovl.Read16(header_offset + 0x16));
                    ovl.Write8(dataoffset + 0x24, oldovl.Read8(header_offset + 0x18));
                }

                ovl.SaveChanges();
                lazyman.ReportProgress(201 + (int)((98f / 54f) * i));
            }

            // fix the level loader as to load from the new overlays
            m_FileStream.Position = lvlload_addr_patch;
            m_BinWriter.Write((uint)(lvl_start + dataoffset + 0xC));

            m_FileStream.Position = lvlload_code_patch;
            m_BinWriter.Write((uint)0xE1A00000);

            // refill the old level header address table
            // to adapt it to its new usages
            m_FileStream.Position = levelptr_table;
            for (uint i = 0; i < 13; i++)
            {
                m_BinWriter.Write((uint)0xFFFFFFFF);
                m_BinWriter.Write((uint)0x00000000);
                m_BinWriter.Write((uint)0x00000000);
            }
            m_BinWriter.Write((uint)0x00000000);
            m_BinWriter.Write((uint)0x00000000);

            // fix the object banks thingy
            m_FileStream.Position = objbank_addr_patch;
            m_BinWriter.Write((uint)(levelptr_table + 0x0200009C));

            m_FileStream.Position = objbank_code_patch;
            m_BinWriter.Write((uint)0xE1A07001);

            // phew! what a goddamn long thing
            lazyman.ReportProgress(299);
        }
Ejemplo n.º 49
0
        public static List<AddressDataPair> GenerateRestoreData(List<AddressDataPair> patchData, string fileName = null, string overlayID = null)
        {
            List<AddressDataPair> restoreDataList = new List<AddressDataPair>();

            INitroROMBlock fileToPatch = null;
            if (fileName != null)
                fileToPatch = Program.m_ROM.GetFileFromName(fileName);
            else if (overlayID != null)
                fileToPatch = new NitroOverlay(Program.m_ROM, uint.Parse(overlayID));

            foreach (AddressDataPair addressDataPair in patchData)
            {
                AddressDataPair restoreData = new AddressDataPair();
                restoreData.m_Address = addressDataPair.m_Address;

                List<byte> data = new List<byte>();
                for (int i = 0; i < addressDataPair.m_Data.Length; i++)
                {
                    if (fileToPatch == null)
                        data.Add(Program.m_ROM.Read8(addressDataPair.m_Address + (uint)i));
                    else
                        data.Add(fileToPatch.Read8(addressDataPair.m_Address + (uint)i));
                }
                restoreData.m_Data = data.ToArray();

                restoreDataList.Add(restoreData);
            }

            return restoreDataList;
        }
Ejemplo n.º 50
0
        public void SaveFilesystem()
        {
            MemoryStream memoryStream       = new MemoryStream();
            BinaryWriter binWriter          = new BinaryWriter((Stream)memoryStream, Encoding.ASCII);
            List <NitroROM.FileEntry> list1 = ((IEnumerable <NitroROM.FileEntry>) this.m_FileEntries).ToList <NitroROM.FileEntry>();

            list1.RemoveAll((Predicate <NitroROM.FileEntry>)(x => x.Name == ""));
            list1.Sort((Comparison <NitroROM.FileEntry>)((x, y) =>
            {
                if ((int)x.ParentID > (int)y.ParentID)
                {
                    return(1);
                }
                return((int)x.ParentID >= (int)y.ParentID ? string.Compare(x.Name, y.Name) : -1);
            }));
            this.m_BinReader.BaseStream.Position = 0L;
            binWriter.Write(this.m_BinReader.ReadBytes(16384));
            this.m_BinReader.BaseStream.Position = 44L;
            int count = this.m_BinReader.ReadInt32();

            this.m_BinReader.BaseStream.Position = 16384L;
            binWriter.Write(this.m_BinReader.ReadBytes(count));
            int position1 = (int)binWriter.BaseStream.Position;

            binWriter.BaseStream.Position = 48L;
            binWriter.Write(position1);
            this.m_BinReader.BaseStream.Position = 48L;
            int num1 = this.m_BinReader.ReadInt32();

            binWriter.BaseStream.Position        = (long)position1;
            this.m_BinReader.BaseStream.Position = (long)num1;
            binWriter.Write(this.m_BinReader.ReadBytes(150308));
            int[] numArray1 = new int[this.m_OverlayEntries.Length + list1.Count];
            int[] numArray2 = new int[this.m_OverlayEntries.Length + list1.Count];
            numArray1[0] = (int)binWriter.BaseStream.Position;
            int          length       = list1.Max <NitroROM.FileEntry>((Func <NitroROM.FileEntry, int>)(x => x.InternalID != ushort.MaxValue ? (int)x.InternalID : 0)) + 1;
            NitroOverlay nitroOverlay = new NitroOverlay(this, 0U);
            int          position2    = (int)binWriter.BaseStream.Position;

            binWriter.Write(nitroOverlay.ReadBlock(0U, 156U));
            binWriter.Write(length);
            binWriter.Write(nitroOverlay.Read32(160U));
            binWriter.Write(uint.MaxValue);
            binWriter.Write(nitroOverlay.ReadBlock(168U, 24U));
            int[] numArray3 = new int[length];
            for (int index = 0; index < list1.Count; ++index)
            {
                if (list1[index].InternalID != ushort.MaxValue)
                {
                    numArray3[(int)list1[index].InternalID] = (int)binWriter.BaseStream.Position - position2 + 34251808;
                    binWriter.Write((list1[index].FullName + "\0").ToCharArray());
                    Helper.AlignWriter(binWriter, 4U);
                }
            }
            Helper.WritePosAndRestore(binWriter, (uint)(position2 + 164), (uint)(34251808 - position2));
            foreach (int num2 in numArray3)
            {
                binWriter.Write(num2);
            }
            numArray2[0] = (int)binWriter.BaseStream.Position;
            for (int index = 1; index < this.m_OverlayEntries.Length; ++index)
            {
                numArray1[index] = (int)binWriter.BaseStream.Position;
                NitroROM.FileEntry fileEntry = this.m_FileEntries[(int)this.m_OverlayEntries[index].FileID];
                if (fileEntry.Data != null)
                {
                    binWriter.Write(fileEntry.Data);
                }
                else
                {
                    this.m_BinReader.BaseStream.Position = (long)fileEntry.Offset;
                    binWriter.Write(this.m_BinReader.ReadBytes((int)fileEntry.Size));
                }
                numArray2[index] = (int)binWriter.BaseStream.Position;
                Helper.AlignWriter(binWriter, 4U);
            }
            Helper.WritePosAndRestore(binWriter, 80U, 0U);
            for (int index = 0; index < this.m_OverlayEntries.Length; ++index)
            {
                binWriter.Write(index);
                binWriter.Write(this.m_OverlayEntries[index].RAMAddress);
                binWriter.Write(this.m_OverlayEntries[index].RAMSize);
                binWriter.Write(this.m_OverlayEntries[index].BSSSize);
                binWriter.Write(this.m_OverlayEntries[index].StaticInitStart);
                binWriter.Write(this.m_OverlayEntries[index].StaticInitEnd);
                binWriter.Write(index);
                binWriter.Write((uint)((long)this.m_OverlayEntries[index].Flags & (long)~(index == 0 ? 16777216 : 0)));
            }
            for (int index = 0; index < list1.Count; ++index)
            {
                numArray1[index + this.m_OverlayEntries.Length] = (int)binWriter.BaseStream.Position;
                if (list1[index].Data != null)
                {
                    binWriter.Write(list1[index].Data);
                    NitroROM.FileEntry fileEntry = list1[index];
                    fileEntry.Data = (byte[])null;
                    list1[index]   = fileEntry;
                }
                else
                {
                    this.m_BinReader.BaseStream.Position = (long)list1[index].Offset;
                    binWriter.Write(this.m_BinReader.ReadBytes((int)list1[index].Size));
                }
                numArray2[index + this.m_OverlayEntries.Length] = (int)binWriter.BaseStream.Position;
                Helper.AlignWriter(binWriter, 4U);
            }
            int position3 = (int)binWriter.BaseStream.Position;

            binWriter.Write(new byte[8 * this.m_DirEntries.Length]);
            int[] numArray4 = new int[this.m_DirEntries.Length];
            List <NitroROM.DirEntry> list2 = ((IEnumerable <NitroROM.DirEntry>) this.m_DirEntries).ToList <NitroROM.DirEntry>();

            list2.RemoveAt(0);
            list2.Sort((Comparison <NitroROM.DirEntry>)((x, y) =>
            {
                if ((int)x.ParentID > (int)y.ParentID)
                {
                    return(1);
                }
                return((int)x.ParentID >= (int)y.ParentID ? string.Compare(x.Name, y.Name) : -1);
            }));
            int index1 = 0;
            int index2 = 0;

            for (int index3 = 0; index3 < this.m_DirEntries.Length; ++index3)
            {
                numArray4[index3] = (int)binWriter.BaseStream.Position - position3;
                for (; index1 < list1.Count && (int)list1[index1].ParentID == index3 + 61440; ++index1)
                {
                    binWriter.Write((byte)list1[index1].Name.Length);
                    binWriter.Write(list1[index1].Name.ToCharArray());
                }
                for (; index2 < list2.Count && (int)list2[index2].ParentID == index3 + 61440; ++index2)
                {
                    binWriter.Write((byte)(list2[index2].Name.Length + 128));
                    binWriter.Write(list2[index2].Name.ToCharArray());
                    binWriter.Write(list2[index2].ID);
                }
                binWriter.Write((byte)0);
            }
            Helper.AlignWriter(binWriter, 4U);
            int position4 = (int)binWriter.BaseStream.Position;

            binWriter.BaseStream.Position = (long)position3;
            int index4 = 0;

            for (int index3 = 0; index3 < this.m_DirEntries.Length; ++index3)
            {
                binWriter.Write(numArray4[index3]);
                binWriter.Write((ushort)(index4 + this.m_OverlayEntries.Length));
                if (index3 == 0)
                {
                    binWriter.Write((ushort)this.m_DirEntries.Length);
                }
                else
                {
                    binWriter.Write(this.m_DirEntries[index3].ParentID);
                }
                while (index4 < list1.Count && (int)list1[index4].ParentID == index3 + 61440)
                {
                    ++index4;
                }
            }
            binWriter.BaseStream.Position = (long)position4;
            for (int index3 = 0; index3 < numArray1.Length; ++index3)
            {
                binWriter.Write(numArray1[index3]);
                binWriter.Write(numArray2[index3]);
            }
            int position5 = (int)binWriter.BaseStream.Position;

            binWriter.BaseStream.Position = 64L;
            binWriter.Write(position3);
            binWriter.Write(position4 - position3);
            binWriter.Write(position4);
            binWriter.Write(position5 - position4);
            binWriter.BaseStream.Position = 20L;
            byte num3 = 0;
            int  num4 = position5;

            while (num4 > 131072)
            {
                num4 >>= 1;
                ++num3;
            }
            binWriter.Write(num3);
            binWriter.BaseStream.Position = 128L;
            binWriter.Write(position5);
            this.m_FileStream.Close();
            this.m_FileStream = (Stream)memoryStream;
            this.m_BinReader  = new BinaryReader(this.m_FileStream, Encoding.ASCII);
            this.m_BinWriter  = binWriter;
            this.FixCRC16();
            this.AllowEmptySpaceInOv0();
            this.m_BinWriter.BaseStream.SetLength((long)position5);
            this.EndRW(true);
            this.LoadROM(this.m_Path);
        }
Ejemplo n.º 51
0
        public LevelObject(NitroOverlay ovl, uint offset, int layer)
        {
            m_Overlay = ovl;
            m_Offset = offset;
            m_Layer = layer;
            m_Area = 0;

            //m_TestMatrix = new Matrix4(1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f);
        }
Ejemplo n.º 52
0
        private void copyCLPS(int sourceLevel)
        {
            NitroOverlay otherOVL = new NitroOverlay(Program.m_ROM, Program.m_ROM.GetLevelOverlayID(sourceLevel));

            uint other_clps_addr = otherOVL.ReadPointer(0x60);
            ushort other_clps_num = otherOVL.Read16(other_clps_addr + 0x06);
            uint other_clps_size = (uint)(8 + (other_clps_num * 8));

            uint clps_addr = _owner.m_Overlay.ReadPointer(0x60);
            ushort clps_num = _owner.m_Overlay.Read16(clps_addr + 0x06);
            uint clps_size = (uint)(8 + (clps_num * 8));

            byte[] CLPS_data = otherOVL.ReadBlock(other_clps_addr, other_clps_size);

            // Make or remove room for other CLPS table
            if (clps_size < other_clps_size)
            {
                AddSpace(clps_addr + clps_size, other_clps_size - clps_size);
            }
            else if (clps_size > other_clps_size)
            {
                RemoveSpace(clps_addr + clps_size - (clps_size - other_clps_size), clps_size - other_clps_size);
            }

            // Write CLPS table from overlay
            _owner.m_Overlay.WriteBlock(clps_addr, CLPS_data);

            loadCLPSData();
        }
Ejemplo n.º 53
0
        public PathPointObject(NitroOverlay ovl, uint offset, int num, int nodeID)
            : base(ovl, offset, 0)
        {
            m_UniqueID = (uint)(0x30000000 | num);
            m_Type = 2;
            m_NodeID = nodeID;

            Position.X = (float)((short)m_Overlay.Read16(m_Offset)) / 1000f;
            Position.Y = (float)((short)m_Overlay.Read16(m_Offset + 0x2)) / 1000f;
            Position.Z = (float)((short)m_Overlay.Read16(m_Offset + 0x4)) / 1000f;

            m_Renderer = InitialiseRenderer();
            m_Properties = new PropertyTable();
            GenerateProperties();
        }