public static void PerformRegionParse(ROM rom, List <Region> regions, int offset) { rom.PushOffset(offset); try { List <Region> displayListRegions = new List <Region>(); int cmd; do { cmd = rom.Read8(); int cmdSize = cmdSizeTable[cmd]; if (cmdSize == 0) { throw new ArgumentException("Loop detected"); } parser[cmd](rom, displayListRegions); if (cmdSize != 0xFF) { rom.AddOffset(cmdSize); } } while (cmd != 0x01); // !!! : Group together all display list information in geolayout MergedRegionList compoundGraphicsData = new MergedRegionList(); List <Region> otherRegions = new List <Region>(); int count = 0; // Merge together vertex, texture, light descriptions // Enumerate display lists foreach (Region reg in displayListRegions) { switch (reg.state) { case RegionState.GraphicsData: compoundGraphicsData.AddRegion(reg.romStart, reg.length); break; case RegionState.DisplayList: reg.number = count++; otherRegions.Add(reg); break; default: // Passthrough region that we do not need to compound otherRegions.Add(reg); break; } } Region graphicsRegion = new DynamicRegion(compoundGraphicsData.start, compoundGraphicsData.length, RegionState.GraphicsData); regions.Add(graphicsRegion); regions.AddRange(otherRegions); Region region = new GeoLayoutRegion(offset, rom.offset - offset); regions.Add(region); } finally { rom.PopOffset(); } }
private void ParseGraphics(string dirname, DataBuilder segment0E, DataBuilder segmentGeoLayouts, ROM rom, out RelocationUnit unit, out RelocationUnit graphicsDataUnit, int area = -1, int model = -1) { RelocationUnit retValue = null; RelocationUnit graphicsUnit = null; segmentGeoLayouts.Backup(); segment0E.Backup(); try { DynamicRegion graphicsDataRegion = new DynamicRegion(dirname, RegionState.GraphicsData, area, model); // no relocation needed for dynamic region segment0E.AddRegion(graphicsDataRegion); segment0E.RoundOffset(); // Display lists needs to be relocated with static graphics relocation table StaticRelocationTable graphicsRelocationTable = new StaticRelocationTable(); graphicsUnit = new RelocationUnit(graphicsDataRegion, rom, isFromStatic: true); graphicsRelocationTable.AddUnit(graphicsUnit); // Geolayouts needs to be relocated with queued display lists, will be filled during relocation with graphicsRelocationTable QueueRelocationTable dispRelocationTable = new QueueRelocationTable(); RelocationUnit dispRelocationUnit = null; for (int dispNumber = 0; dispNumber < 0xFF; dispNumber++) { if (!PathComposer.IsRegionFileExists(dirname, RegionState.DisplayList, area, model, dispNumber)) { break; } DisplayListRegion dispRegion = new DisplayListRegion(dirname, area, model, dispNumber); DisplayList.PerformRegionRelocation(dispRegion, graphicsRelocationTable); segment0E.AddRegion(dispRegion); segment0E.RoundOffset(); dispRelocationUnit = new RelocationUnit(dispRegion, rom, isFromStatic: true); dispRelocationTable.AddUnit(dispRelocationUnit); } // Not even one disp relocation unit, sounds like a bug if (dispRelocationUnit == null) { throw new IOException("No display lists found!"); } // Geolayout might or might not exist for model, check if it exists and if needed, relocate it if (PathComposer.IsRegionFileExists(dirname, RegionState.GeoLayout, area, model)) { // Load geolayout and relocate it with display lists GeoLayoutRegion modelGeoLayoutRegion = new GeoLayoutRegion(dirname, area, model); GeoLayout.PerformRegionRelocation(modelGeoLayoutRegion, dispRelocationTable); segmentGeoLayouts.AddRegion(modelGeoLayoutRegion); segmentGeoLayouts.RoundOffset(); // Finalize with returning geolayout for model retValue = new RelocationUnit(modelGeoLayoutRegion, rom, isFromStatic: true); } else { // Return display list only, there should be only one, if more, it is undefinied behaviour :3 retValue = dispRelocationUnit; } } catch (Exception ex) { MessageBox.Show(String.Format("Failed to load model {0}, reason : '{1}'", model, ex.Message), "Level Combiner", MessageBoxButtons.OK, MessageBoxIcon.Error); segment0E.Restore(); segmentGeoLayouts.Restore(); } unit = retValue; graphicsDataUnit = graphicsUnit; }