Пример #1
0
        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();
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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]);
        }
Пример #6
0
        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;
            }
        }
Пример #7
0
        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);
        }
Пример #8
0
 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
 }
Пример #9
0
        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;
        }