Beispiel #1
0
        public static void RebuildTriangleMap(ROM realRom, Region region, int maxDLLength, TriangleMap map, SortedRegionList vertexData, ScrollFactory factory)
        {
            ROM fakeRom = (ROM)realRom.Clone();

            // bzero
            fakeRom.PushOffset(region.romStart);
            {
                do
                {
                    fakeRom.Write64(0x0101010101010101);
                    fakeRom.AddOffset(8);
                } while (fakeRom.offset < region.romStart + region.length);
            }
            fakeRom.PopOffset();

            fakeRom.offset = region.romStart;
            int triangleMapLength = map.MakeF3D(fakeRom, vertexData, factory);

            if (triangleMapLength > maxDLLength)
            {
                throw new OutOfMemoryException("No memory for DL available :(");
            }

            realRom.TransferFrom(fakeRom);

            realRom.offset = fakeRom.offset;
            region.length  = realRom.offset - region.romStart;
            region.data    = new byte[region.length];
            realRom.ReadData(region.romStart, region.length, region.data);
        }
Beispiel #2
0
        private void splitROM_Click(object sender, EventArgs e)
        {
            GC.Collect();
            dataGridView1.Rows.Clear();
            //object[] row = { "aaaa", true, false, "old", "new", false };
            //dataGridView1.Rows.Add(row);
            //return;

            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.Filter = "ROM File|*.z64";
            openFileDialog1.Title  = "Select a ROM";

            if (openFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK)
            {
                return;
            }

            path = openFileDialog1.FileName;
            path = Path.GetFullPath(path);

            rom = new ROM(File.ReadAllBytes(path));
            for (int i = 0; i <= 30; i++)
            {
                try
                {
                    int offset = LevelInfo.GetLevelScriptEntryPoint(i);

                    List <Region> regions = new List <Region>();

                    // 1st pass : find out where regions are
                    LevelScript.PerformRegionParse(rom, regions, offset, out Dictionary <int, List <ScrollObject> > scrolls);

                    // Fill in data from rom
                    foreach (Region region in regions)
                    {
                        region.data = new byte[region.length];
                        rom.ReadData(region.romStart, region.length, region.data);
                    }

                    foreach (Region region in regions)
                    {
                        if (region.state == RegionState.DisplayList)
                        {
                            DisplayListRegion dlRegion = (DisplayListRegion)region;
                            scrolls.TryGetValue(1, out List <ScrollObject> areaScrolls);
                            if (areaScrolls == null)
                            {
                                areaScrolls = new List <ScrollObject>();
                            }

                            object[] row = { dlRegion, true, region.romStart.ToString("X"), i, dlRegion.isFogEnabled, dlRegion.isEnvcolorEnabled, new CombinerCommand(dlRegion.FCcmdfirst), CombinerCommand.GetNewCombiner(dlRegion), rom.segments.Clone(), areaScrolls };
                            dataGridView1.Rows.Add(row);
                        }
                    }
                }
                catch (Exception) { }
            }
            dataGridView1.Sort(new RowComparer(SortOrder.Ascending));
        }
Beispiel #3
0
        public static void PerformVisualMapRebuild(ROM realRom, Region region, int maxDLLength)
        {
            // This is fake rom but it works anyways, just more convenient
            // Want to be safe with overwriting the whole display list
            ROM fakeRom = new ROM(region.data);
            VisualMapParseState state = new VisualMapParseState();

            DisplayListRegion dlRegion = (DisplayListRegion)region;
            VisualMap         map      = new VisualMap();

            byte curCmdIndex;

            do
            {
                curCmdIndex = fakeRom.Read8();
                VisualMapParserCmd func = visualMapParser[curCmdIndex];
                func(fakeRom, map, state);
                fakeRom.AddOffset(8);
            }while (fakeRom.offset < region.length);

            ROM visualMapROM    = new ROM(new byte[maxDLLength]);
            int visualMapLength = map.MakeF3D(visualMapROM);


            // Now write data to real rom + trimming
            // bzero
            fakeRom.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                do
                {
                    realRom.Write64(0x0101010101010101);
                    realRom.AddOffset(8);
                    fakeRom.AddOffset(8);
                } while (fakeRom.offset < region.length);
            }
            realRom.PopOffset();

            visualMapROM.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                int start = region.romStart;
                do
                {
                    Int64 cmd = visualMapROM.Read64();
                    visualMapROM.AddOffset(8);

                    realRom.Write64((ulong)cmd);
                    realRom.AddOffset(8);
                } while (visualMapROM.offset < visualMapLength);

                region.length = realRom.offset - start;
                region.data   = new byte[region.length];
                realRom.ReadData(region.romStart, region.length, region.data);
            }
            realRom.PopOffset();
        }
Beispiel #4
0
        public static void PerformRegionOptimize(ROM realRom, Region region, FixConfig config)
        {
            // This is fake rom but it works anyways, just more convenient
            // Want to be safe with overwriting the whole display list
            ROM fakeRom = new ROM(region.data);
            RegionOptimizeState state = new RegionOptimizeState(config);

            DisplayListRegion dlRegion = (DisplayListRegion)region;

            byte curCmdIndex;

            do
            {
                curCmdIndex = fakeRom.Read8();
                OptimizeParserCmd func = optimizeParser[curCmdIndex];
                func(fakeRom, dlRegion, state);
                fakeRom.AddOffset(8);
            }while (fakeRom.offset < region.length);

            // Now write data to real rom + trimming
            // bzero
            fakeRom.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                do
                {
                    realRom.Write64(0x0101010101010101);
                    realRom.AddOffset(8);
                    fakeRom.AddOffset(8);
                } while (fakeRom.offset < region.length);
            }
            realRom.PopOffset();

            fakeRom.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                int start = region.romStart;
                do
                {
                    Int64 cmd = fakeRom.Read64();
                    fakeRom.AddOffset(8);

                    if (config.trimNOPs && cmd == 0 && dlRegion.isUnusedTrimmingAllowed)
                    {
                        continue;
                    }

                    realRom.Write64((ulong)cmd);
                    realRom.AddOffset(8);
                } while (fakeRom.offset < region.length);

                region.length = realRom.offset - start;
                region.data   = new byte[region.length];
                realRom.ReadData(region.romStart, region.length, region.data);
            }
            realRom.PopOffset();
        }
Beispiel #5
0
        public static void PerformTriangleMapRebuild(ROM realRom, Region region, int maxDLLength, List <ScrollObject> scrolls)
        {
            TriangleMapParseState state    = new TriangleMapParseState(scrolls);
            DisplayListRegion     dlRegion = (DisplayListRegion)region;
            TriangleMap           map      = new TriangleMap();

            realRom.PushOffset(region.romStart);
            byte curCmdIndex;

            do
            {
                curCmdIndex = realRom.Read8();
                TriangleMapParserCmd func = triangleMapParser[curCmdIndex];
                func(realRom, map, state);
                realRom.AddOffset(8);
            }while (realRom.offset < region.romStart + region.length);
            realRom.PopOffset();

            ROM fakeRom = (ROM)realRom.Clone();

            // bzero
            fakeRom.PushOffset(region.romStart);
            {
                do
                {
                    fakeRom.Write64(0x0101010101010101);
                    fakeRom.AddOffset(8);
                } while (fakeRom.offset < region.romStart + region.length);
            }
            fakeRom.PopOffset();

            fakeRom.offset = region.romStart;
            int triangleMapLength = map.MakeF3D(fakeRom, state.vertexBytes, new ScrollFactory(scrolls));

            if (triangleMapLength > maxDLLength)
            {
                throw new OutOfMemoryException("No memory for DL available :(");
            }

            realRom.TransferFrom(fakeRom);

            realRom.offset = fakeRom.offset;
            region.length  = realRom.offset - region.romStart;
            region.data    = new byte[region.length];
            realRom.ReadData(region.romStart, region.length, region.data);
        }
Beispiel #6
0
        public static void PerformRegionFix(ROM rom, Region region, FixConfig config)
        {
            RegionFixState    state    = new RegionFixState(config);
            DisplayListRegion dlRegion = (DisplayListRegion)region;

            rom.PushOffset(region.romStart);
            byte curCmdIndex;

            do
            {
                curCmdIndex = rom.Read8();
                FixParseCmd func = fixParser[curCmdIndex];
                func(rom, dlRegion, state);
                rom.AddOffset(8);
            }while (rom.offset < region.romStart + region.length);
            rom.PopOffset();
            rom.ReadData(region.romStart, region.length, region.data);
        }
Beispiel #7
0
        public static void Trim(Region region, bool addObjects)
        {
            ROM rom = new ROM(region.data);

            MemoryStream trimmedObject = new MemoryStream();

            while (rom.offset < region.length)
            {
                byte curCmdIndex = rom.Read8();
                byte curCmdSize  = rom.Read8(1);

                if (curCmdIndex == 0x24)
                {
                    byte acts = rom.Read8(2);
                    if (acts == 0)
                    {
                        goto fini;
                    }
                }


                byte[] data = new byte[curCmdSize];
                rom.ReadData(rom.offset, curCmdSize, data);
                trimmedObject.Write(data, 0, curCmdSize);

fini:
                rom.AddOffset(curCmdSize);
            }

            if (addObjects)
            {
                trimmedObject.Write(emptyObject, 0, emptyObject.Count());
                trimmedObject.Write(emptyObject, 0, emptyObject.Count());
                trimmedObject.Write(emptyObject, 0, emptyObject.Count());
                trimmedObject.Write(emptyObject, 0, emptyObject.Count());
                trimmedObject.Write(emptyObject, 0, emptyObject.Count());
            }

            region.data   = trimmedObject.ToArray();
            region.length = (int)trimmedObject.Length;

            trimmedObject.Dispose();
        }
Beispiel #8
0
        private void button2_Click(object sender, EventArgs e)
        {
            List <Region> regions = new List <Region>();

            if (!Int32.TryParse(textBoxF3DPtr.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int offset))
            {
                MessageBox.Show("Custom DL", "Invalid ptr", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!Int32.TryParse(textBoxSegNum.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int segment))
            {
                MessageBox.Show("Custom DL", "Invalid segment", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!Int32.TryParse(textBoxROMAddr.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int addr))
            {
                MessageBox.Show("Custom DL", "Invalid rom addr", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            rom.SetSegment(segment, new SegmentDescriptor(addr, 0x00400000));
            DisplayList.FixConfig config = new DisplayList.FixConfig(checkBoxNerfFog.Checked, checkBoxOptimizeVertex.Checked, checkBoxTrimNops.Checked, checkBoxCombiners.Checked, checkBoxOtherMode.Checked, checkBoxNoFog.Checked);

            DisplayList.PerformRegionParse(rom, regions, offset, int.Parse(textBoxLayer.Text));
            foreach (Region region in regions)
            {
                if (region.state != RegionState.DisplayList)
                {
                    continue;
                }

                DisplayListRegion dlRegion = (DisplayListRegion)region;
                region.data = new byte[region.length];
                rom.ReadData(region.romStart, region.length, region.data);

                int maxDLLength = dlRegion.length;
                DisplayList.PerformRegionFix(rom, dlRegion, config);
                if (checkBoxOptimizeVertex.Checked)
                {
                    DisplayList.PerformRegionOptimize(rom, dlRegion, config);
                }

                if (checkBoxGroupByTexture.Checked)
                {
                    if (checkBoxRebuildVertices.Checked)
                    {
                        DisplayList.PerformTriangleMapRebuild(rom, dlRegion, maxDLLength, new List <ScrollObject>());
                    }
                    else
                    {
                        DisplayList.PerformVisualMapRebuild(rom, dlRegion, maxDLLength);
                    }
                }

                DisplayList.PerformRegionOptimize(rom, dlRegion, config);
            }

            File.WriteAllBytes(path, rom.rom);

            rom.SetSegment(segment, null);
            MessageBox.Show(String.Format("Ptr was fixed successfully"), "f3d fix", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
Beispiel #9
0
        private void splitROM_Click(object sender, EventArgs e)
        {
            GC.Collect();

            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.Filter = "ROM File|*.z64";
            openFileDialog1.Title  = "Select a ROM";

            if (openFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK)
            {
                return;
            }

            string path = openFileDialog1.FileName;

            path = Path.GetFullPath(path);

            ROM rom    = new ROM(File.ReadAllBytes(path));
            int offset = Convert.ToInt32(addressTextBox.Text, 16);

            if (offset == 0)
            {
                MessageBox.Show("Failed to parse address, input correct address", "Level Split", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List <Region> regions = new List <Region>();

            // 1st pass : find out where regions are
            LevelScript.PerformRegionParse(rom, regions, offset, checkBoxOldScrolls.Checked);

            foreach (Region region in regions)
            {
                Console.WriteLine(GetTab(region.state) + "Region {0:x} {1:x} {2:x}", region.romStart, region.romStart + region.length, region.state.ToString());
            }

            // 2nd pass : with known regions, relocate data
            // GraphicsData position independent
            // Collision    position independent
            // DisplayList to 0E000000 of GraphicsData
            // GeoLayout   to 0E000000 of DisplayList
            // AreaHeader  to 19000000 of GeoLayout
            // ObjectsLoad to 19000000 of GeoLayout
            // AreaFooter  to 0E000000 of Collision
            StaticRelocationTable table = new StaticRelocationTable();

            foreach (Region region in regions)
            {
                RelocationUnit unit = new RelocationUnit(region, rom, isFromStatic: false);
                table.AddUnit(unit);
            }

            // Fill in data from rom
            foreach (Region region in regions)
            {
                region.data = new byte[region.length];
                rom.ReadData(region.romStart, region.length, region.data);
            }

            SortedSet <int> areasTrimmed = new SortedSet <int>();

            // Trim AreaData if flag is checked
            foreach (Region region in regions)
            {
                if (region.state != RegionState.AreaData && region.state != RegionState.AreaScrolls)
                {
                    continue;
                }

                ObjectsTrimmer.Trim(region, !areasTrimmed.Contains(region.area));
                areasTrimmed.Add(region.area);
            }

            // Relocate!
            foreach (Region region in regions)
            {
                try
                {
                    region.Relocate(table);
                }
                catch (ArgumentException)
                {
                    string answer = String.Format("Region relocation failed for {0}", region.state);
                    if (region.area != -1)
                    {
                        answer += String.Format(", area {0}", region.area);
                    }
                    if (region.model != -1)
                    {
                        answer += String.Format(", model {0}", region.model);
                    }
                    answer += ", region might be broken";

                    MessageBox.Show(answer, "Level Split", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }

            Dictionary <RegionState, int> dictionary = new Dictionary <RegionState, int>();

            foreach (RegionState state in (RegionState[])Enum.GetValues(typeof(RegionState)))
            {
                dictionary[state] = 0;
            }

            string dirPostfix            = addressTextBox.Text;
            int    levelScriptEntryPoint = Convert.ToInt32(addressTextBox.Text, 16);

            if (LevelInfo.IsValidLevelScriptEntry(levelScriptEntryPoint))
            {
                dirPostfix = (LevelInfo.GetLevel(levelScriptEntryPoint) + 1).ToString();
            }

            string dirname = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path), dirPostfix);

            if (deleteFolderCheckbox.Checked)
            {
                if (Directory.Exists(dirname))
                {
                    DialogResult result = MessageBox.Show(String.Format("Path {0} already exists! Delete it anyways?", dirname), "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                    if (result == DialogResult.OK)
                    {
                        Directory.Delete(dirname, true);
                    }
                    else
                    {
                        return;
                    }
                }
            }

            Directory.CreateDirectory(dirname);
            SortedSet <string> truncatedFiles = new SortedSet <string>();

            foreach (Region region in regions)
            {
                switch (region.state)
                {
                case RegionState.LevelHeader:
                    if (!levelHeaderCheckbox.Checked)
                    {
                        continue;
                    }
                    break;

                case RegionState.LevelFooter:
                    if (!levelFooterCheckbox.Checked)
                    {
                        continue;
                    }
                    break;

                case RegionState.ModelsLoader:
                    if (!modelsDescriptorCheckbox.Checked)
                    {
                        continue;
                    }
                    break;

                case RegionState.AreaHeader:
                    if (!areaHeaderCheckbox.Checked)
                    {
                        continue;
                    }
                    break;

                case RegionState.AreaData:
                case RegionState.AreaScrolls:
                    if (!areaObjectsDataCheckbox.Checked)
                    {
                        continue;
                    }
                    break;

                case RegionState.AreaFooter:
                    if (!areaFooterCheckbox.Checked)
                    {
                        continue;
                    }
                    break;

                case RegionState.GeoLayout:
                case RegionState.DisplayList:
                case RegionState.GraphicsData:
                    if (region.area != -1)
                    {
                        if (!areaGraphicsCheckBox.Checked)
                        {
                            continue;
                        }
                    }
                    else if (region.model != -1)
                    {
                        if (!modelsGraphicsCheckbox.Checked)
                        {
                            continue;
                        }
                    }
                    break;

                case RegionState.Collision:
                    if (!levelCollisionCheckbox.Checked)
                    {
                        continue;
                    }
                    break;
                }

                string regionPath = null;
                try
                {
                    regionPath = PathComposer.ComposeName(dirname, region.state, region.area, region.model, region.number);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(String.Format("Failed to compose path for {0}, reason: {1}", region.state, ex.Message), "Level Split", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                if (regionPath == null)
                {
                    continue;
                }

                Directory.CreateDirectory(Path.GetDirectoryName(regionPath));

                //if (deleteFolderCheckbox.Checked && File.Exists(regionPath))
                //    throw new Exception("Such region was written already!");

                if (!truncatedFiles.Contains(regionPath))
                {
                    File.Delete(regionPath);
                    truncatedFiles.Add(regionPath);
                }
                else
                {
                    if (region.state != RegionState.ModelsLoader &&
                        region.state != RegionState.AreaData &&
                        region.state != RegionState.AreaScrolls)
                    {
                        MessageBox.Show(String.Format("Appending data from region {0}, this might be bug", region.state), "Level Split", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                }

                using (var stream = new FileStream(regionPath, FileMode.Append))
                    stream.Write(region.data, 0, region.data.Length);
            }

            MessageBox.Show(String.Format("ROM was splitted successfully at {0}", dirname), "Level Split", MessageBoxButtons.OK, MessageBoxIcon.Information);
            splittedPathTextBox.Text = dirname;
            //regions.Sort((x, y) => x.start.CompareTo(y.start));
        }