Example #1
0
        public static void PerformVisualMapRebuild(ROM realRom, Region region, int maxDLLength)
        {
            // This is fake rom but it works anyways, just more convenient
            // Want to be safe with overwriting the whole display list
            ROM fakeRom = new ROM(region.data);
            VisualMapParseState state = new VisualMapParseState();

            DisplayListRegion dlRegion = (DisplayListRegion)region;
            VisualMap         map      = new VisualMap();

            byte curCmdIndex;

            do
            {
                curCmdIndex = fakeRom.Read8();
                VisualMapParserCmd func = visualMapParser[curCmdIndex];
                func(fakeRom, map, state);
                fakeRom.AddOffset(8);
            }while (fakeRom.offset < region.length);

            ROM visualMapROM    = new ROM(new byte[maxDLLength]);
            int visualMapLength = map.MakeF3D(visualMapROM);


            // Now write data to real rom + trimming
            // bzero
            fakeRom.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                do
                {
                    realRom.Write64(0x0101010101010101);
                    realRom.AddOffset(8);
                    fakeRom.AddOffset(8);
                } while (fakeRom.offset < region.length);
            }
            realRom.PopOffset();

            visualMapROM.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                int start = region.romStart;
                do
                {
                    Int64 cmd = visualMapROM.Read64();
                    visualMapROM.AddOffset(8);

                    realRom.Write64((ulong)cmd);
                    realRom.AddOffset(8);
                } while (visualMapROM.offset < visualMapLength);

                region.length = realRom.offset - start;
                region.data   = new byte[region.length];
                realRom.ReadData(region.romStart, region.length, region.data);
            }
            realRom.PopOffset();
        }
Example #2
0
        public static void PerformRegionOptimize(ROM realRom, Region region, FixConfig config)
        {
            // This is fake rom but it works anyways, just more convenient
            // Want to be safe with overwriting the whole display list
            ROM fakeRom = new ROM(region.data);
            RegionOptimizeState state = new RegionOptimizeState(config);

            DisplayListRegion dlRegion = (DisplayListRegion)region;

            byte curCmdIndex;

            do
            {
                curCmdIndex = fakeRom.Read8();
                OptimizeParserCmd func = optimizeParser[curCmdIndex];
                func(fakeRom, dlRegion, state);
                fakeRom.AddOffset(8);
            }while (fakeRom.offset < region.length);

            // Now write data to real rom + trimming
            // bzero
            fakeRom.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                do
                {
                    realRom.Write64(0x0101010101010101);
                    realRom.AddOffset(8);
                    fakeRom.AddOffset(8);
                } while (fakeRom.offset < region.length);
            }
            realRom.PopOffset();

            fakeRom.offset = 0;
            realRom.PushOffset(region.romStart);
            {
                int start = region.romStart;
                do
                {
                    Int64 cmd = fakeRom.Read64();
                    fakeRom.AddOffset(8);

                    if (config.trimNOPs && cmd == 0 && dlRegion.isUnusedTrimmingAllowed)
                    {
                        continue;
                    }

                    realRom.Write64((ulong)cmd);
                    realRom.AddOffset(8);
                } while (fakeRom.offset < region.length);

                region.length = realRom.offset - start;
                region.data   = new byte[region.length];
                realRom.ReadData(region.romStart, region.length, region.data);
            }
            realRom.PopOffset();
        }
Example #3
0
        public static void PerformRegionParse(ROM rom, List <Region> regions, int offset)
        {
            rom.PushOffset(offset);
            try
            {
                int cmd = 0;
                do
                {
                    if (rom.Read8() != 0x00)
                    {
                        throw new ArgumentException("invalid instruction");
                    }

                    cmd = rom.Read8(1);
                    if (cmd >= 0x40 && cmd <= 0x44)
                    {
                        parser[cmd - 0x40](rom, regions);
                    }
                    else
                    {
                        RegionParse_common(rom, regions);
                    }
                }while (cmd != 0x42);

                Region region = new DynamicRegion(offset, rom.offset - offset, RegionState.Collision);
                regions.Add(region);
            }
            finally
            {
                rom.PopOffset();
            }
        }
Example #4
0
        public static void RebuildTriangleMap(ROM realRom, Region region, int maxDLLength, TriangleMap map, SortedRegionList vertexData, ScrollFactory factory)
        {
            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, vertexData, factory);

            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);
        }
Example #5
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();
        }
Example #6
0
 public override void WriteScroll(ROM rom)
 {
     rom.PushOffset(romOffset);
     rom.Write8(acts, 0x02);
     rom.Write16(X, 0x04);
     rom.Write16(Y, 0x06);
     rom.Write32(segmentedAddress, 0x10);
     rom.Write32(behavior, 0x14);
     rom.PopOffset();
 }
Example #7
0
        private static void OptimizeParse_cmdFD(ROM rom, DisplayListRegion region, RegionOptimizeState state)
        {
            if (state.prevFDcmdAddr != 0)
            {
                rom.PushOffset(state.prevFDcmdAddr);
                rom.Write64(0);
                rom.PopOffset();
            }

            state.prevFDcmdAddr = rom.offset;
        }
Example #8
0
 public override void WriteScroll(ROM rom)
 {
     rom.PushOffset(romOffset);
     rom.Write8(acts, 0x02);
     rom.Write16(X, 0x04);
     rom.Write16(Y, 0x06);
     rom.Write16(Z, 0x08);
     rom.Write16(BParam, 0x10);
     rom.Write16(BParam2, 0x12);
     rom.Write32(behavior, 0x14);
     rom.PopOffset();
 }
Example #9
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);
        }
Example #10
0
        public static void PerformRegionFix(ROM rom, Region region, FixConfig config)
        {
            RegionFixState    state    = new RegionFixState(config);
            DisplayListRegion dlRegion = (DisplayListRegion)region;

            rom.PushOffset(region.romStart);
            byte curCmdIndex;

            do
            {
                curCmdIndex = rom.Read8();
                FixParseCmd func = fixParser[curCmdIndex];
                func(rom, dlRegion, state);
                rom.AddOffset(8);
            }while (rom.offset < region.romStart + region.length);
            rom.PopOffset();
            rom.ReadData(region.romStart, region.length, region.data);
        }
Example #11
0
        public static void PerformHeaderParse(ROM rom, int offset)
        {
            rom.PushOffset(offset);

            RegionParseState state = new RegionParseState();

            state.start = rom.offset;

            byte curCmdIndex;
            int  stepCounter = 0;

            do
            {
                curCmdIndex = rom.Read8();
                byte curCmdSize = rom.Read8(1);

                if (curCmdSize == 0)
                {
                    throw new ArgumentException("cmd size is 0, loop detected");
                }

                if (curCmdIndex == 0x00)
                {
                    HeaderParse_cmd00(rom);
                }

                if (curCmdIndex == 0x17)
                {
                    HeaderParse_cmd17(rom);
                }

                rom.AddOffset(curCmdSize);
                stepCounter++;

                if (stepCounter > 100)
                {
                    throw new ArgumentException("Bank 0x19 && 0x0E loader was not detected");
                }
            }while (rom.GetSegmentDescriptor(0x0E) == null || rom.GetSegmentDescriptor(0x19) == null);

            rom.PopOffset();
        }
Example #12
0
        public static void PerformRegionParse(ROM rom, List <Region> regions, int offset, bool isOldScrollBehaviour)
        {
            rom.PushOffset(offset);

            RegionParseState state = new RegionParseState
            {
                start = rom.offset,
                isOldBehaviourChecked = isOldScrollBehaviour
            };

            byte curCmdIndex;

            do
            {
                curCmdIndex = rom.Read8();
                byte curCmdSize = rom.Read8(1);

                if (curCmdSize == 0)
                {
                    throw new ArgumentException("cmd size is 0, loop detected");
                }

                RegionParseCmd func = regionParser[curCmdIndex];
                if (func != RegionParse_common)
                {
                    RegionParse_common(rom, regions, state);
                }

                func(rom, regions, state);

                if (curCmdIndex != 0x7)
                {
                    rom.AddOffset(curCmdSize);
                }
            }while (curCmdIndex != terminateCmd);

            rom.PopOffset();
        }
Example #13
0
        public static void PerformRegionParse(ROM rom, List <Region> regions, int offset, out Dictionary <int, List <ScrollObject> > scrolls)
        {
            rom.PushOffset(offset);

            RegionParseState state = new RegionParseState();

            state.start = rom.offset;

            byte curCmdIndex;

            do
            {
                curCmdIndex = rom.Read8();
                byte curCmdSize = rom.Read8(1);

                if (curCmdSize == 0)
                {
                    throw new ArgumentException("cmd size is 0, loop detected");
                }

                RegionParseCmd func = regionParser[curCmdIndex];
                if (func != RegionParse_common)
                {
                    RegionParse_common(rom, regions, state);
                }

                func(rom, regions, state);

                if (curCmdIndex != 0x7)
                {
                    rom.AddOffset(curCmdSize);
                }
            }while (curCmdIndex != terminateCmd);

            rom.PopOffset();
            scrolls = state.scrolls;
        }
Example #14
0
        static RegionParseState PerformRegionParseInternal(ROM rom, List <Region> regions, int offset, int layer)
        {
            RegionParseState state = new RegionParseState();

            rom.PushOffset(offset);
            try
            {
                int cmd = 0;
                do
                {
                    cmd = rom.Read8();
                    parser[cmd](rom, regions, state);
                    rom.AddOffset(8);
                }while (cmd != 0xB8);

                Region           region;
                SortedRegionList graphicsData = new SortedRegionList();

                foreach (KeyValuePair <int, int> lightRegion in state.lightData.RegionList)
                {
                    //region = new Region(lightRegion.Key, lightRegion.Value, RegionState.LightData);
                    graphicsData.AddRegion(lightRegion.Key, lightRegion.Value);
                    //regions.Add(region);
                }

                // kostul
                if (state.lightData.RegionList.Count == 0)
                {
                    graphicsData.AddRegion(rom.GetROMAddress(0x0E000000), 0x10);
                }

                foreach (KeyValuePair <int, int> textureRegion in state.textureData.RegionList)
                {
                    //region = new Region(textureRegion.Key, textureRegion.Value, RegionState.TextureInfo);
                    graphicsData.AddRegion(textureRegion.Key, textureRegion.Value);
                    //regions.Add(region);
                }

                foreach (KeyValuePair <int, int> vertexRegion in state.vertexData.RegionList)
                {
                    //region = new Region(vertexRegion.Key, vertexRegion.Value, RegionState.VertexInfo);
                    graphicsData.AddRegion(vertexRegion.Key, vertexRegion.Value);
                    //regions.Add(region);
                }

                int count = 0;
                foreach (KeyValuePair <int, int> notFixedRegion in graphicsData.RegionList)
                {
                    region        = new DynamicRegion(notFixedRegion.Key, notFixedRegion.Value, RegionState.GraphicsData);
                    region.number = count++;
                    regions.Add(region);
                }


                region = new DisplayListRegion(offset, rom.offset - offset, state.isFogEnabled, state.isEnvColorEnabled, state.FCCount, state.B9cmdfirst, layer);
                regions.Add(region);
            }
            finally
            {
                rom.PopOffset();
            }
            return(state);
        }
Example #15
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;
        }
Example #16
0
        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();
            }
        }
Example #17
0
 public void Disable(ROM rom)
 {
     rom.PushOffset(romOffset);
     rom.Write8(0, 0x02);
     rom.PopOffset();
 }