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); }
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)); }
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(); }
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(); }
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); }
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); }
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(); }
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); }
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)); }