private static void TriangleMapParse_cmd04(ROM rom, TriangleMap map, TriangleMapParseState state) { state.vertexLoadCmd = (UInt64)rom.Read64(); byte vertexDesc = rom.Read8(1); byte vertexCount = (byte)(((vertexDesc & 0xF0) >> 4) + 1); byte vertexOffset = (byte)((vertexDesc & 0x0F)); Int32 vertexSegmentedAddress = rom.Read32(4); state.segmentedVertexBufferAddress = vertexSegmentedAddress; Int32 romPtr = rom.GetROMAddress(vertexSegmentedAddress); if (romPtr == -1) { throw new ArgumentException("Invalid segmented address!"); } rom.PushOffset(romPtr); for (int vertex = vertexOffset; vertex < vertexCount; vertex++) { Int64 lo = rom.Read64(); Int64 hi = rom.Read64(8); state.vbuf[vertex] = new Vertex((UInt64)lo, (UInt64)hi); state.vbufRomStart[vertex] = rom.offset; state.scrollBuf[vertex] = FindMatchingScroll(state.scrolls, vertexSegmentedAddress, state.td); rom.AddOffset(0x10); vertexSegmentedAddress += 0x10; } rom.PopOffset(); }
private static void TriangleMapParse_cmdBB(ROM rom, TriangleMap map, TriangleMapParseState state) { if ((UInt64)rom.Read64() == 0xBB000000FFFFFFFF) { state.state = VisualMapParseStateCmd.Footer; } TriangleMapParse_common(rom, map, state); }
private static void TriangleMapParse_cmdFD(ROM rom, TriangleMap map, TriangleMapParseState state) { UInt64 fdCmd = state.td.GetTextureCMD(); if (state.state != VisualMapParseStateCmd.Texture) { state.state = VisualMapParseStateCmd.Texture; state.td = new ScrollingTextureDescription(); if (state.envColorCmd != null) { state.td.Add(state.envColorCmd.GetValueOrDefault(), 0 /*FIXME*/); } } TriangleMapParse_common(rom, map, state); }
private static void TriangleMapParse_cmdFB(ROM rom, TriangleMap map, TriangleMapParseState state) { // Some importers have the only EnvColor func for everything lmfao if (rom.Read8(8) != 0xFD) { goto fini; } state.state = VisualMapParseStateCmd.Texture; state.envColorCmd = (ulong)rom.Read64(); state.td = new ScrollingTextureDescription(); fini: TriangleMapParse_common(rom, map, state); }
private static void TriangleMapParse_cmdBF(ROM rom, TriangleMap map, TriangleMapParseState state) { state.isHeader = false; state.state = VisualMapParseStateCmd.Footer; byte v0index = (byte)(rom.Read8(5) / 0xA); byte v1index = (byte)(rom.Read8(6) / 0xA); byte v2index = (byte)(rom.Read8(7) / 0xA); state.vertexBytes.AddRegion(state.vbufRomStart[v0index], 0x10); state.vertexBytes.AddRegion(state.vbufRomStart[v1index], 0x10); state.vertexBytes.AddRegion(state.vbufRomStart[v2index], 0x10); // This assumes all scrolls are scrolling at the same speed which is usually true :3 if (state.scrollBuf[v0index] != state.scrollBuf[v1index] || state.scrollBuf[v0index] != state.scrollBuf[v2index] || state.scrollBuf[v1index] != state.scrollBuf[v2index]) { throw new Exception("Vertices are scrolling at different scrolls"); } Scroll scroll = state.scrollBuf[v0index]; if ((scroll == null && state.td.scroll != null) || (scroll != null && !scroll.Equals(state.td.scroll))) { ScrollingTextureDescription oldTd = state.td; state.td = new ScrollingTextureDescription(); state.td.AddRange(oldTd); state.td.scroll = scroll; if (scroll is EditorScroll editorScroll) { state.td.RegisterScroll(editorScroll); } if (scroll is TextureScroll) { state.td.omitScrollCheck = true; } } state.td.RegisterVertex(state.segmentedVertexBufferAddress + v0index * 0x10); state.td.RegisterVertex(state.segmentedVertexBufferAddress + v1index * 0x10); state.td.RegisterVertex(state.segmentedVertexBufferAddress + v2index * 0x10); map.AddTriangle(state.td, state.vbuf[v0index], state.vbuf[v1index], state.vbuf[v2index]); }
private static void TriangleMapParse_common(ROM rom, TriangleMap map, TriangleMapParseState state) { switch (state.state) { case VisualMapParseStateCmd.Header: map.AddHeaderCmd((UInt64)rom.Read64()); break; case VisualMapParseStateCmd.Texture: state.td.Add((UInt64)rom.Read64(), rom.GetSegmentedAddress(rom.offset)); break; case VisualMapParseStateCmd.Footer: map.AddFooterCmd((UInt64)rom.Read64()); break; } }
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); }
private static void TriangleMapParse_cmdF2(ROM rom, TriangleMap map, TriangleMapParseState state) { TriangleMapParse_common(rom, map, state); state.state = state.isHeader ? VisualMapParseStateCmd.Header : VisualMapParseStateCmd.Footer; // Case for fog }
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; }