protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);

            // --- Update Table Addr ---
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801cca98), SeekOrigin.Begin);
            // mulli r0,r3,0x38 ->  mulli r0,r3,0x04
            stream.Write(PowerPcAsm.mulli(0, 3, 0x04));
            // r3 <- 0x80428e50 ->  r3 <- tableAddr
            stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            stream.Seek(0x4, SeekOrigin.Current);
            // lwz r3,0x10(r3)  ->  lwz r3,0x0(r3)
            stream.Write(PowerPcAsm.lwz(3, 0, 3));

            // --- ASM hack: Use the rule set from map instead of from global setting ---
            var ruleSetFromMapRoutine = allocate(writeRuleSetFromMapRoutine(addressMapper, (VAVAddr)0), "writeRuleSetFromMapRoutine");

            stream.Seek(addressMapper.toFileAddress(ruleSetFromMapRoutine), SeekOrigin.Begin);
            stream.Write(writeRuleSetFromMapRoutine(addressMapper, ruleSetFromMapRoutine)); // re-write the routine again since now we know where it is located in the main dol

            var virtualPos = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8007e13c);

            stream.Seek(addressMapper.toFileAddress(virtualPos), SeekOrigin.Begin);
            // lha r3,0x3c(r30)  -> bl ruleSetFromMapRoutine
            stream.Write(PowerPcAsm.bl(virtualPos, ruleSetFromMapRoutine));
            // cmpwi r23,0x0     -> lha r3,0x3c(r30)
            stream.Write(PowerPcAsm.lha(3, 0x3c, 30));
            // lha r0,0x28(r30)  -> cmpwi r23,0x0
            stream.Write(PowerPcAsm.cmpwi(23, 0x0));
            // stw r25,0x53f4(r29) -> lha r0,0x28(r30)
            stream.Write(PowerPcAsm.lha(0, 0x28, 30));
        }
Beispiel #2
0
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);

            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x804363b8), SeekOrigin.Begin); stream.Write(Encoding.ASCII.GetBytes("NAME"));
            // Store the pointer to the table to some unused address. The game does not use the internal name, but CSMM uses it for the name of the map descriptor file.
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x804363bc), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(5, v.upper16Bit)); stream.Write(PowerPcAsm.addi(5, 5, v.lower16Bit));
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);

            // --- Game::GetMapFrbName ---
            // mulli r3,r3,0x38  ->  mulli r3,r3,0x10
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccab0), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(3, 3, 0x10));
            // r5 <- 0x80428e50  ->  r5 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccab4), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(5, v.upper16Bit)); stream.Seek(0x4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(5, 5, v.lower16Bit));
            // lwz r3,0x18(r3)   ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccac8), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));

            // --- Game::GetMapMapNum ---
            // mulli r0,r3,0x38  ->  mulli r0,r3,0x10
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccad0), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 3, 0x10));
            // r4 <- 0x80428e50  ->  r4 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccad4), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(4, v.upper16Bit)); stream.Seek(0x4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(4, 4, v.lower16Bit));
            // lwz r0,0x18(r4)   ->  lwz r0,0x0(r4)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccae4), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x0, 4));
            // lwz r0,0x1c(r4)   ->  lwz r0,0x4(r4)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccaf0), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x4, 4));
            // lwz r0,0x20(r4)   ->  lwz r0,0x8(r4)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb00), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x8, 4));
            // lwz r0,0x24(r4)   ->  lwz r0,0xc(r4)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb10), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0xc, 4));
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x802bb120);
            var returnAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x802bb124);

            var uploadSimulatedButtonPress = allocate(writeUploadSimulatedButtonPress(addressMapper, (VAVAddr)0, returnAddr), "UploadSimulatedButtonPress");

            stream.Seek(addressMapper.toFileAddress(uploadSimulatedButtonPress), SeekOrigin.Begin);
            stream.Write(writeUploadSimulatedButtonPress(addressMapper, uploadSimulatedButtonPress, returnAddr)); // re-write the routine again since now we know where it is located in the main dol
            // lwz r0,0x4(r3)                                                             -> b uploadSimulatedButtonPress
            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); stream.Write(PowerPcAsm.b(hijackAddr, uploadSimulatedButtonPress));
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);

            // --- Update Table Addr ---
            // mulli r0,r3,0x38 ->  mulli r0,r3,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801cca6c), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 3, 0x04));
            // r3 <- 0x80428e50 ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801cca70), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
        }
        protected override void readAsm(EndianBinaryReader stream, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)(0x80173bf8 + 2)), SeekOrigin.Begin);
            var easyPracticeBoard = stream.ReadInt16();

            stream.Seek(addressMapper.toFileAddress((BSVAddr)(0x80173c04 + 2)), SeekOrigin.Begin);
            var standardPracticeBoard = stream.ReadInt16();

            mapDescriptors[easyPracticeBoard].IsPracticeBoard     = true;
            mapDescriptors[easyPracticeBoard].MapSet              = 0;
            mapDescriptors[standardPracticeBoard].IsPracticeBoard = true;
            mapDescriptors[standardPracticeBoard].MapSet          = 1;
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);

            // --- Game::GetMapSwitchParam ---
            // mulli r0,r3,0x38  ->  mulli r0,r3,0x4
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb28), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 3, 0x4));
            // r3 <- 0x80428e50  ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb2c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // lwz r3,0x28(r3)   ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb38), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            short tableRowCount           = (short)mapDescriptors.Count;
            var   mapDescriptionTableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)mapDescriptionTableAddr);
            // HACK: Expand the description message ID table
            // subi r3,r3,0x15                                     -> nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021214c), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r3,0x12                                       -> cmpwi r3,tableRowCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212158), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(3, tableRowCount));
            // r4 <- 0x80436bc0                                    -> r4 <- mapDescriptionTableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212164), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(4, v.upper16Bit)); stream.Seek(4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(4, 4, v.lower16Bit));
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            short easyPracticeBoard     = -1;
            short standardPracticeBoard = -1;
            var   validation            = MapDescriptor.getPracticeBoards(mapDescriptors, out easyPracticeBoard, out standardPracticeBoard);

            if (!validation.Passed)
            {
                throw new ArgumentException(validation.GetMessage("\n"));
            }
            // li r0,0x29                                                                 -> li r0,easyPracticeBoard
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80173bf8), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(0, easyPracticeBoard));
            // li r0,0x14                                                                 -> li r0,standardPracticeBoard
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80173c04), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(0, standardPracticeBoard));
        }
Beispiel #10
0
        protected override void readAsm(EndianBinaryReader stream, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper)
        {
            var isVanilla = readIsVanilla(stream, addressMapper);
            var rowCount  = readTableRowCount(stream, addressMapper, isVanilla);

            if (rowCount != -1 && rowCount != mapDescriptors.Count)
            {
                if (isVanilla)
                {
                    // in vanilla all kinds of strange stuff is there. E.g.
                    // - there are 42 venture card tables but 48 maps.
                    // - there are 48 maps but the ids get mapped to different values (e.g. easy map yoshi island index is 21 but mapped to 18 in some tables and in other tables mapped to 0)
                    //     so we cant really figure out the real amount of maps unless doing some complex logic
                }
                else
                {
                    // should not happen as with the hacks that we apply we streamline the tables and total map count so that they should always map
                    throw new ApplicationException("The amount of rows of the table in the main.dol is " + rowCount + " but the mapDescriptor count is " + mapDescriptors.Count);
                }
            }
            var addr = readTableAddr(stream, addressMapper, isVanilla);

            if (addr != VAVAddr.NullAddress)
            {
                stream.Seek(addressMapper.toFileAddress(addr), SeekOrigin.Begin);
            }
            readAsm(stream, mapDescriptors, addressMapper, isVanilla);
        }
 private void readRotationOriginPoints(VAVAddr address, EndianBinaryReader s, MapDescriptor mapDescriptor, AddressMapper addressMapper)
 {
     mapDescriptor.SwitchRotationOriginPoints.Clear();
     // Special case handling: in the original game these values are initialized at run time only. So we need to hardcode them:
     if (address == addressMapper.toVersionAgnosticAddress((BSVAddr)0x806b8df0)) // magmageddon
     {
         // no points
     }
     else if (address == addressMapper.toVersionAgnosticAddress((BSVAddr)0x8047d598)) // collosus
     {
         mapDescriptor.SwitchRotationOriginPoints[0] = new OriginPoint(-288, -32);
         mapDescriptor.SwitchRotationOriginPoints[1] = new OriginPoint(288, -32);
     }
     else if (address == addressMapper.toVersionAgnosticAddress((BSVAddr)0x8047d5b4)) // observatory
     {
         mapDescriptor.SwitchRotationOriginPoints[0] = new OriginPoint(0, 0);
     }
     else if (addressMapper.canConvertToFileAddress(address))
     {
         s.Seek(addressMapper.toFileAddress(address), SeekOrigin.Begin);
         var originPointCount = s.ReadUInt32();
         for (int i = 0; i < originPointCount; i++)
         {
             OriginPoint point = new OriginPoint();
             point.X = s.ReadSingle();
             var z = s.ReadSingle(); // ignore Z value
             point.Y = s.ReadSingle();
             mapDescriptor.SwitchRotationOriginPoints[i] = point;
         }
     }
 }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            // hardcoded virtual address for the parameter table on how the Miis are being animated to play baseball in the background
            var bgSequenceMarioStadium = addressMapper.toVersionAgnosticAddress((BSVAddr)0x80428968);
            var tableAddr = writeTable(mapDescriptors, bgSequenceMarioStadium);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);

            // --- Update Table Addr ---
            // mulli r0,r3,0x38 ->  mulli r0,r3,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb70), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 3, 0x04));
            // r3 <- 0x80428e50 ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb74), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // lwz r3,0x34(r3)   ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb80), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));
        }
Beispiel #13
0
        protected override Int16 readTableRowCount(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8007e104), SeekOrigin.Begin);
            var opcode = stream.ReadUInt32();

            return((Int16)(PowerPcAsm.getOpcodeParameter(opcode) + 1));
        }
Beispiel #14
0
        protected override bool readIsVanilla(EndianBinaryReader stream, AddressMapper addressMapper)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x804363b8), SeekOrigin.Begin);
            var bytes = stream.ReadBytes(4);

            return(!new ByteArrayComparer().Equals(bytes, Encoding.ASCII.GetBytes("NAME")));
        }
Beispiel #15
0
        protected override bool readIsVanilla(EndianBinaryReader stream, AddressMapper addressMapper)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8007e130), SeekOrigin.Begin);
            var opcode = stream.ReadUInt32();

            return(opcode == PowerPcAsm.li(5, 0));
        }
        protected override VAVAddr readTableAddr(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d170), SeekOrigin.Begin);
            var lis_opcode  = stream.ReadUInt32();
            var addi_opcode = stream.ReadUInt32();

            return((VAVAddr)PowerPcAsm.make32bitValueFromPair(lis_opcode, addi_opcode));
        }
Beispiel #17
0
        protected override bool readIsVanilla(EndianBinaryReader stream, AddressMapper addressMapper)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801cca50), SeekOrigin.Begin);
            var opcode = stream.ReadUInt32();

            // mulli r0,r3,0x38
            return(opcode == PowerPcAsm.mulli(0, 3, 0x38));
        }
        protected override bool readIsVanilla(EndianBinaryReader stream, AddressMapper addressMapper)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021214c), SeekOrigin.Begin);
            var opcode = stream.ReadUInt32();

            // subi r3,r3,0x15
            return(opcode == PowerPcAsm.subi(3, 3, 0x15));
        }
        protected override bool readIsVanilla(EndianBinaryReader stream, AddressMapper addressMapper)
        {
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021210c), SeekOrigin.Begin);
            var opcode = stream.ReadUInt32();

            // mulli r4,r0,0x24
            return(opcode == PowerPcAsm.mulli(4, 0, 0x24));
        }
Beispiel #20
0
        private AddressMapper setupAddressMapper(EndianBinaryReader stream, List <AddressSection> fileMappingSections, IProgress <ProgressInfo> progress)
        {
            var addressMapper = new AddressMapper(fileMappingSections);

            // find out the version we are dealing with

            // Boom Street: 8007a314: lwz r0,-0x547c(r13)
            stream.Seek(addressMapper.toFileAddress((VAVAddr)0x8007a314), SeekOrigin.Begin);
            if (stream.ReadUInt32() == PowerPcAsm.lwz(0, -0x547c, 13))
            {
                progress?.Report("Detected game: Boom Street");
                // boom street address mapper is a no-op, since the ASM hacks use the boom street virtual addresses
                var versionMappingSections = new List <AddressSection> {
                    AddressSection.identity()
                };
                addressMapper.setVersionMappingSections(versionMappingSections);
            }
            else
            {
                // Fortune Street: 8007a2c0: lwz r0,-0x547c(r13)
                stream.Seek(addressMapper.toFileAddress((VAVAddr)0x8007a2c0), SeekOrigin.Begin);
                if (stream.ReadUInt32() == PowerPcAsm.lwz(0, -0x547c, 13))
                {
                    progress?.Report("Detected game: Fortune Street");

                    var versionMappingSections = new List <AddressSection>();
                    // add mappings to translate boom street virtual addresses to fortune street virtual addresses
                    versionMappingSections.Add(new AddressSection(0x80000100, 0x8007a283, 0x0, ".text, .data0, .data1 and beginning of .text1 until InitSoftLanguage"));
                    versionMappingSections.Add(new AddressSection(0x8007a2f4, 0x80268717, 0x54, "continuation of .text1 until AIRegisterDMACallback"));
                    versionMappingSections.Add(new AddressSection(0x80268720, 0x8040d97b, 0x50, "continuation of .text1"));
                    versionMappingSections.Add(new AddressSection(0x8040d980, 0x8041027f, 0x40, ".data2, .data3 and beginning of .data4 until Boom Street / Fortune Street strings"));
                    versionMappingSections.Add(new AddressSection(0x804105f0, 0x8044ebe7, 0x188, "continuation of .data4"));
                    versionMappingSections.Add(new AddressSection(0x8044ec00, 0x804ac804, 0x1A0, ".data5"));
                    versionMappingSections.Add(new AddressSection(0x804ac880, 0x8081f013, 0x200, ".uninitialized0, .data6, .uninitialized1, .data7, .uninitialized2"));

                    addressMapper.setVersionMappingSections(versionMappingSections);
                }
                else
                {
                    // unsupported version
                    throw new ApplicationException("Only Boom Street (ST7P01) and Fortune Street (ST7E01) are supported.");
                }
            }
            return(addressMapper);
        }
 protected override short readTableRowCount(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla)
 {
     if (isVanilla)
     {
         return(-1);
     }
     stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020F45E), SeekOrigin.Begin);
     return(stream.ReadInt16());
 }
 private void readLoopingModeConfig(VAVAddr address, EndianBinaryReader s, MapDescriptor mapDescriptor, AddressMapper addressMapper)
 {
     if (addressMapper.canConvertToFileAddress(address))
     {
         s.Seek(addressMapper.toFileAddress(address), SeekOrigin.Begin);
         mapDescriptor.LoopingModeRadius              = s.ReadSingle();
         mapDescriptor.LoopingModeHorizontalPadding   = s.ReadSingle();
         mapDescriptor.LoopingModeVerticalSquareCount = s.ReadSingle();
     }
 }
Beispiel #23
0
        /// <summary>
        /// Hijack the LoadBoard() routine. Intercept the moment when the (now compressed) ventureCardTable is passed on to the InitChanceBoard() routine.
        /// Call the decompressVentureCardTable routine and pass the resulting decompressed ventureCardTable (located at ventureCardDecompressedTableAddr) to the InitChanceBoard() routine instead.
        /// </summary>
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableRowCount = mapDescriptors.Count;
            var ventureCardCompressedTableAddr = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)ventureCardCompressedTableAddr);

            // Allocate working memory space for a single uncompressed venture card table which is passed on for the game to use. We will use it to store the result of decompressing a compressed venture card table
            var ventureCardDecompressedTableAddr  = allocate(new byte[130], "VentureCardReservedMemoryForDecompressedTable");
            var ventureCardDecompressTableRoutine = allocate(writeSubroutine(ventureCardDecompressedTableAddr), "DecompressVentureCardSubroutine");

            // cmplwi r24,0x29                                     -> cmplwi r24,ventureCardTableCount-1
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8007e104), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmplwi(24, (UInt16)(tableRowCount - 1)));
            // mulli r0,r24,0x82                                   -> mulli r0,r24,0x10
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8007e11c), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 24, 0x10));
            // r4 <- 0x80410648                                    -> r4 <- ventureCardCompressedTableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8007e120), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(4, v.upper16Bit)); stream.Seek(4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(4, 4, v.lower16Bit));
            // li r5,0x0                                           -> bl ventureCardDecompressTableRoutine
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8007e130), SeekOrigin.Begin); stream.Write(PowerPcAsm.bl((UInt32)addressMapper.toVersionAgnosticAddress((BSVAddr)0x8007e130), (UInt32)ventureCardDecompressTableRoutine));
        }
        protected override VAVAddr readTableAddr(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla)
        {
            if (isVanilla)
            {
                return(VAVAddr.NullAddress);
            }
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020f458), SeekOrigin.Begin);
            var addr = (VAVAddr)stream.ReadUInt32();

            return(addr);
        }
 /// <summary>
 /// This method writes 0x00 to all remaining free space in the main.dol. The reason we do this
 /// is so that we can fail-fast if one of the determined free-space locations turn out to be used
 /// after all (the main.dol will probably crash in that case or have some other strange behavior).
 /// If we do not do this, then this might turn into a heisenbug where some rare users experience this
 /// bug and others do not, making it harder to find the root cause.
 /// </summary>
 /// <param name="stream"></param>
 /// <param name="addressMapper"></param>
 public void nullTheFreeSpace(EndianBinaryWriter stream, AddressMapper addressMapper)
 {
     byte[] nullBytes;
     foreach (var entry in remainingFreeSpaceBlocks)
     {
         var start         = entry.Value;
         var end           = entry.Key;
         var freeSpaceSize = end - start;
         stream.Seek(addressMapper.toFileAddress(start), SeekOrigin.Begin);
         nullBytes = new byte[freeSpaceSize];
         stream.Write(nullBytes);
     }
 }
Beispiel #26
0
        public List <MapDescriptor> readMainDol(EndianBinaryReader stream, IProgress <ProgressInfo> progress)
        {
            // GetMapCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801cca30), SeekOrigin.Begin);
            UInt32 opcode = stream.ReadUInt32();
            var    count  = (Int16)(PowerPcAsm.getOpcodeParameter(opcode));

            List <MapDescriptor> mapDescriptors = new List <MapDescriptor>();

            for (int i = 0; i < count; i++)
            {
                MapDescriptor mapDescriptor = new MapDescriptor();
                mapDescriptors.Add(mapDescriptor);
            }

            foreach (var patch in patches)
            {
                patch.read(stream, addressMapper, mapDescriptors, progress);
            }

            return(mapDescriptors);
        }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableRowCount = mapDescriptors.Count;
            var tableAddr     = writeTable(mapDescriptors);

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)tableAddr);
            // --- IsMapClear(int mapId,int normalMode,UserIndex userIndex) ---

            /*
             * // subi r31,r3,0x15                                   ->  nop
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80210434), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
             * // cmpwi r31,0x12                                     ->  cmpwi r31,tableElementsCount
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80210440), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(31, (short)(tableRowCount)));
             * // subi r29,r31,0x15                                  ->  nop
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80210504), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
             * // cmpwi r29,0x12                                     ->  cmpwi r29,tableElementsCount
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80210510), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(29, (short)(tableRowCount)));
             * // li r0,0x15                                         ->  nop
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80210598), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
             */
            // mulli r0,r0,0x24                                   ->  mulli r0,r0,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x802105a4), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 0, 0x04));
            // r3 <- 804363c8                                     ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x802105a8), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Seek(0x4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // mulli r0,r29,0x24                                  ->  mulli r0,r29,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x802105c4), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 29, 0x04));
            // lwz r4,0x18(r3)                                    ->  lwz r4,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x802105d8), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(4, 0x0, 3));

            // --- GetMapClearRank(int mapId,int normalMode) ---

            /*
             * // subi r31,r3,0x15                                   ->  nop
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212074), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
             * // cmpwi r31,0x12                                     ->  cmpwi r31,tableElementsCount
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212080), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(31, (short)(tableRowCount)));
             * // li r0,0x15                                         ->  nop
             * stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212100), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
             */
            // mulli r4,r0,0x24                                   ->  mulli r4,r0,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021210c), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(4, 0, 0x04));
            // r3 <- 804363c8                                     ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212110), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // mulli r0,r31,0x24                                  ->  mulli r0,r31,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212118), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 31, 0x04));
            // lwz r3,0x18(r3)                                    ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021212c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));
        }
Beispiel #28
0
        protected string resolveAddressToString(VAVAddr virtualAddress, EndianBinaryReader stream, AddressMapper addressMapper)
        {
            if (virtualAddress == VAVAddr.NullAddress)
            {
                return(null);
            }
            int fileAddress = addressMapper.toFileAddress(virtualAddress);
            var pos         = stream.BaseStream.Position;

            stream.Seek(fileAddress, SeekOrigin.Begin);
            byte[] buff = stream.ReadBytes(64);
            stream.BaseStream.Seek(pos, SeekOrigin.Begin);
            return(HexUtil.byteArrayToString(buff));
        }
        protected string resolveAddressAddressToString(VAVAddr virtualAddressAddress, EndianBinaryReader stream, AddressMapper addressMapper)
        {
            if (virtualAddressAddress == VAVAddr.NullAddress)
            {
                return(null);
            }
            int fileAddress = addressMapper.toFileAddress(virtualAddressAddress);
            var pos         = stream.BaseStream.Position;

            stream.Seek(fileAddress, SeekOrigin.Begin);
            VAVAddr virtualAddress = (VAVAddr)stream.ReadUInt32();

            stream.BaseStream.Seek(pos, SeekOrigin.Begin);
            return(resolveAddressToString(virtualAddress, stream, addressMapper));
        }
        public VAVAddr allocateUnusedSpace(byte[] bytes, EndianBinaryWriter stream, AddressMapper fileMapper, IProgress <ProgressInfo> progress, string purpose)
        {
            if (!string.IsNullOrEmpty(purpose))
            {
                purpose = " for " + purpose;
            }
            startedAllocating = true;
            string str = HexUtil.byteArrayToStringOrHex(bytes);

            if (reuseValues.ContainsKey(bytes))
            {
                progress?.Report(new ProgressInfo("Reuse " + str + " at " + reuseValues[bytes].ToString() + purpose, true));
                return(reuseValues[bytes]);
            }
            else
            {
                VAVAddr end   = findSuitableFreeSpaceBlock(bytes.Length);
                VAVAddr start = remainingFreeSpaceBlocks[end];
                VAVAddr addr  = start;

                VAVAddr newStartPos = start + bytes.Length;
                while (newStartPos % 4 != 0)
                {
                    newStartPos++;
                }
                if (newStartPos > end)
                {
                    newStartPos = end;
                }
                remainingFreeSpaceBlocks[end] = newStartPos;

                stream.Seek(fileMapper.toFileAddress(addr), SeekOrigin.Begin);
                stream.Write(bytes);
                byte[] fillUpToAlign = new byte[(int)(newStartPos - addr - bytes.Length)];
                stream.Write(fillUpToAlign);

                reuseValues.Add(bytes, addr);
                progress?.Report(new ProgressInfo("Allocate " + str + " (" + bytes.Length + " bytes) at " + addr.ToString() + purpose, true));
                return(addr);
            }
        }