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 GetTriangleMap(ROM realRom, Region region, int maxDLLength, List <ScrollObject> scrolls, out TriangleMap map, out SortedRegionList vertexData) { TriangleMapParseState state = new TriangleMapParseState(scrolls); DisplayListRegion dlRegion = (DisplayListRegion)region; 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(); // Check map validity // There are 2 possible ways to mess up scroll // 'Too much' - scroll is performing too much scrolling, 1st warn detect, 2nd falsing, 3rd can fix such scroll if scrolls are done properly // 'Not enough' - scroll is not scrolling the whole texture, 2nd warn may be able to detect that, no fix yet but 'stretch' the scroll should work // I assume there is no scrolls that do not correspond to no texture, such case will leave weird things :) // Currently ScrollingTextures cannot be longed so it is impossible to fix 'Not enough' :( List <ScrollingTextureDescription> brokenTextures = new List <ScrollingTextureDescription>(); { // Not enough HashSet <TextureDescription> scrollingTds = new HashSet <TextureDescription>(map.map.Keys.Where(k => k.scroll != null)); foreach (TextureDescription td in scrollingTds) { var stds = map.map.Keys.Where(k => k.Equals(td)).ToList(); if (stds.Count() > 1) { int a = 0; } } // Check if scroll 'fits' foreach (ScrollingTextureDescription std in map.map.Keys) { if (std.scroll == null) { continue; } if (!std.vertexRegions.Equals(std.scrollRegions)) { brokenTextures.Add(std); } } } foreach (ScrollingTextureDescription brokenTd in brokenTextures) { if (brokenTd.omitScrollCheck) { continue; } // Figure out the way to "heal", either drop scroll or extend it // If scroll does not start at the same place, just drop it, such solution may backfire if 2 scrolls intersect bool shouldDrop = brokenTd.scrollRegions.RegionList.First().Key != brokenTd.vertexRegions.RegionList.First().Key; if (shouldDrop) { // Find if texture without scroll exists, if it does, merge tris in it, otherwise drop the scroll List <ScrollingTextureDescription> similarTextures = map.map.Keys.Where(k => k.scroll == null).Where(k => TextureDescription.Equals(brokenTd, k)).ToList(); if (similarTextures.Count() != 0) { ScrollingTextureDescription stdNoScroll = similarTextures[0]; List <Triangle> tris = map.map[brokenTd]; map.map.Remove(brokenTd); map.map[stdNoScroll].AddRange(tris); } else { state.td.scroll = null; } } else { // Find if texture without scroll exists, if it does, merge tris from it (make it scroll) List <ScrollingTextureDescription> similarTextures = map.map.Keys.Where(k => k.scroll == null).Where(k => TextureDescription.Equals(brokenTd, k)).ToList(); foreach (ScrollingTextureDescription similarStd in similarTextures) { List <Triangle> tris = map.map[similarStd]; map.map.Remove(similarStd); map.map[brokenTd].AddRange(tris); } } } vertexData = state.vertexBytes; }
static DisplayList() { Type t = typeof(DisplayList); for (int i = 0x00; i < 0xFF; i++) { parser[i] = RegionParse_common; string name = "RegionParse_cmd" + string.Format("{0:X2}", i); MethodInfo info = t.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); if (info == null) { continue; } RegionParseCmd cmd = Delegate.CreateDelegate(typeof(RegionParseCmd), info) as RegionParseCmd; if (cmd == null) { continue; } parser[i] = cmd; } for (int i = 0; i < 0xFF; i++) { fixParser[i] = FixParse_common; string name = "FixParse_cmd" + string.Format("{0:X2}", i); MethodInfo info = t.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); if (info == null) { continue; } FixParseCmd cmd = Delegate.CreateDelegate(typeof(FixParseCmd), info) as FixParseCmd; if (cmd == null) { continue; } fixParser[i] = cmd; } for (int i = 0; i < 0xFF; i++) { optimizeParser[i] = OptimizeParse_common; string name = "OptimizeParse_cmd" + string.Format("{0:X2}", i); MethodInfo info = t.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); if (info == null) { continue; } OptimizeParserCmd cmd = Delegate.CreateDelegate(typeof(OptimizeParserCmd), info) as OptimizeParserCmd; if (cmd == null) { continue; } optimizeParser[i] = cmd; } for (int i = 0; i < 0xFF; i++) { visualMapParser[i] = VisualMapParse_common; string name = "VisualMapParse_cmd" + string.Format("{0:X2}", i); MethodInfo info = t.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); if (info == null) { continue; } VisualMapParserCmd cmd = Delegate.CreateDelegate(typeof(VisualMapParserCmd), info) as VisualMapParserCmd; if (cmd == null) { continue; } visualMapParser[i] = cmd; } for (int i = 0; i < 0xFF; i++) { triangleMapParser[i] = TriangleMapParse_common; string name = "TriangleMapParse_cmd" + string.Format("{0:X2}", i); MethodInfo info = t.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); if (info == null) { continue; } TriangleMapParserCmd cmd = Delegate.CreateDelegate(typeof(TriangleMapParserCmd), info) as TriangleMapParserCmd; if (cmd == null) { continue; } triangleMapParser[i] = cmd; } }