private static void CutRegion(ROM rom, List <Region> regions, RegionParseState state, int regionEnd, RegionState newState) { // Trim 0x1008000000000000 commands from beginning int regionStart = state.start; if (rom.PRead64(regionStart) == 0x1008000000000000) { regionStart += 8; } if (regionStart == regionEnd) { return; } Region region = new LevelScriptRegion(regionStart, regionEnd - regionStart, state.regionState); region.area = state.area; regions.Add(region); state.regionState = newState; state.start = regionEnd; }
private void button1_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; } LevelScript.PerformHeaderParse(rom, offset); SegmentDescriptor segmentDescriptor0E = rom.GetSegmentDescriptor(0x0E); SegmentDescriptor segmentDescriptor19 = rom.GetSegmentDescriptor(0x19); DataBuilder segment0E = new DataBuilder(segmentDescriptor0E.start, segmentDescriptor0E.length); DataBuilder segment19 = new DataBuilder(segmentDescriptor19.start, segmentDescriptor19.length); string dirname = splittedPathTextBox.Text; // Fill in area relocation table + geolayouts KeyRelocationTable areaGraphicsDescrRelocationTable = new KeyRelocationTable(); KeyRelocationTable areaGraphicsDataRelocationTable = new KeyRelocationTable(); KeyRelocationTable areaCollisionRelocationTable = new KeyRelocationTable(); for (int area = 1; area <= 8; area++) { if (!PathComposer.IsRegionFileExists(dirname, RegionState.GraphicsData, area: area)) { continue; } // Area graphics ParseGraphics(dirname, segment0E, segment19, rom, out RelocationUnit descrUnit, out RelocationUnit dataUnit, area: area); areaGraphicsDescrRelocationTable.AddUnit(area, descrUnit); areaGraphicsDataRelocationTable.AddUnit(area, dataUnit); // Area collision DynamicRegion collision = new DynamicRegion(dirname, RegionState.Collision, area: area); // No relocation needed segment0E.AddRegion(collision); segment0E.RoundOffset(); RelocationUnit collisionRelocationUnit = new RelocationUnit(collision, rom, isFromStatic: true); areaCollisionRelocationTable.AddUnit(area, collisionRelocationUnit); } // Fill in model relocation table + geolayouts KeyRelocationTable modelRelocationTable = new KeyRelocationTable(); for (int model = 0x00; model < 0xFF; model++) { if (!PathComposer.IsRegionFileExists(dirname, RegionState.GraphicsData, model: model)) { continue; } ParseGraphics(dirname, segment0E, segment19, rom, out RelocationUnit descrUnit, out RelocationUnit graphicsUnit, model: model); modelRelocationTable.AddUnit(model, descrUnit); } // As everything is prepared, we can finally start building level! LevelScriptRegion levelHeader = new LevelScriptRegion(dirname, RegionState.LevelHeader); LevelScript.FixLoadAddresses(rom, levelHeader); segment19.AddRegion(levelHeader); int levelScriptSegmentedAddressStart = rom.GetSegmentedAddress(levelHeader.romStart); LevelScriptRegion modelsLoader = new LevelScriptRegion(dirname, RegionState.ModelsLoader); modelsLoader.Relocate(modelRelocationTable); segment19.AddRegion(modelsLoader); for (sbyte area = 0; area < 8; area++) { if (!PathComposer.IsRegionFileExists(dirname, RegionState.GraphicsData, area: area)) { continue; } // Area header initializes graphics LevelScriptRegion areaHeader = new LevelScriptRegion(dirname, RegionState.AreaHeader, area: area); LevelScript.PerformRegionRelocation(areaHeader, areaGraphicsDescrRelocationTable, area); segment19.AddRegion(areaHeader); LevelScriptRegion areaData = new LevelScriptRegion(dirname, RegionState.AreaData, area: area); // No relocation needed segment19.AddRegion(areaData); if (PathComposer.IsRegionFileExists(dirname, RegionState.AreaScrolls, area: area)) { LevelScriptRegion scrollsData = new LevelScriptRegion(dirname, RegionState.AreaScrolls, area: area); LevelScript.PerformRegionRelocation(scrollsData, areaGraphicsDataRelocationTable, area); segment19.AddRegion(scrollsData); } // Area footer initializes collision LevelScriptRegion areaFooter = new LevelScriptRegion(dirname, RegionState.AreaFooter, area: area); LevelScript.PerformRegionRelocation(areaFooter, areaCollisionRelocationTable, area); segment19.AddRegion(areaFooter); } LevelScriptRegion levelFooter = new LevelScriptRegion(dirname, RegionState.LevelFooter); // no relocation needed segment19.AddRegion(levelFooter); // At this point we know that all data fit in rom // So just write all that in rom using (Stream stream = new FileStream(path, FileMode.Open)) { stream.Seek(segmentDescriptor0E.start, SeekOrigin.Begin); stream.Write(segment0E.Data, 0, segment0E.Offset); stream.Seek(segmentDescriptor19.start, SeekOrigin.Begin); stream.Write(segment19.Data, 0, segment19.Offset); // Also start of level script moved so write that thing too int endianData = IPAddress.HostToNetworkOrder(levelScriptSegmentedAddressStart); byte[] convertedData = BitConverter.GetBytes(endianData); stream.Seek(rom.levelScriptEntryOffset, SeekOrigin.Begin); stream.Write(convertedData, 0, 4); } MessageBox.Show(String.Format("ROM was build successfully from {0}", dirname), "Level Split", MessageBoxButtons.OK, MessageBoxIcon.Information); }