Example #1
0
        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)0x801ccb58), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 3, 0x04));
            // r3 <- 0x80428e50 ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb5c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // lwz r3,0x30(r3)  ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x801ccb68), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));
        }
        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));
        }
        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));
        }
        private List <UInt32> writeRuleSetFromMapRoutine(AddressMapper addressMapper, VAVAddr routineStartAddress)
        {
            var Game_GetRuleFlag = addressMapper.toVersionAgnosticAddress((BSVAddr)0x801cca98);

            // precondition: r24 is mapId
            // precondition: r25 is global rule set which we are gonna use to store the linkreturn
            var asm = new List <UInt32>();

            asm.Add(PowerPcAsm.mflr(25));
            asm.Add(PowerPcAsm.mr(3, 24));                                             // r3 <- r24
            asm.Add(PowerPcAsm.bl(routineStartAddress, asm.Count, Game_GetRuleFlag));  // r3 <- bl Game_GetRuleFlag(r3)
            asm.Add(PowerPcAsm.stw(3, 0x53f4, 29));                                    // gameRule <- r3
            asm.Add(PowerPcAsm.mtlr(25));
            asm.Add(PowerPcAsm.blr());                                                 // return
            return(asm);
        }
        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));
        }
Example #6
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);
        }
        private List <UInt32> writeSubroutineInitMapIdsForMapIcons(AddressMapper addressMapper, VAVAddr entryAddr)
        {
            var JUtility_memset = addressMapper.toVersionAgnosticAddress((BSVAddr)0x80004714);
            // precondition: r3 is newly created map icon array
            //               r16 is the amount of map ids in the array (size / 4)
            //               r24 is unused
            // postcondition: r24 is the map icon array
            var asm = new List <UInt32>();

            asm.Add(PowerPcAsm.mflr(24));                                     // save the link register
            asm.Add(PowerPcAsm.li(4, -1));                                    // fill with 0xff
            asm.Add(PowerPcAsm.rlwinm(5, 16, 0x3, 0x0, 0x1d));                // get the size of the array
            asm.Add(PowerPcAsm.bl(entryAddr, asm.Count, JUtility_memset));    // call JUtility_memset(array*, 0xff, array.size)
            asm.Add(PowerPcAsm.mtlr(24));                                     // restore the link register
            asm.Add(PowerPcAsm.mr(24, 3));                                    // move array* to r24
            asm.Add(PowerPcAsm.blr());                                        // return
            return(asm);
        }
Example #8
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));
        }
        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);
            }
        }
        private List <UInt32> writeUploadSimulatedButtonPress(AddressMapper addressMapper, VAVAddr routineStartAddress, VAVAddr returnAddr)
        {
            var asm = new List <UInt32>();
            // 0x804363b4 (4 bytes): force simulated button press
            var forceSimulatedButtonPress = PowerPcAsm.make16bitValuePair((UInt32)addressMapper.toVersionAgnosticAddress((BSVAddr)0x804363b4));
            var pressedButtonsBitArray    = PowerPcAsm.make16bitValuePair((UInt32)addressMapper.toVersionAgnosticAddress((BSVAddr)0x8078C880));

            asm.Add(PowerPcAsm.lis(6, forceSimulatedButtonPress.upper16Bit));                // \
            asm.Add(PowerPcAsm.addi(6, 6, forceSimulatedButtonPress.lower16Bit));            // / r6 <- &forceSimulatedButtonPress
            asm.Add(PowerPcAsm.lis(7, pressedButtonsBitArray.upper16Bit));                   // \
            asm.Add(PowerPcAsm.addi(7, 7, pressedButtonsBitArray.lower16Bit));               // / r7 <- &pressedButtonsBitArray
            asm.Add(PowerPcAsm.lwz(0, 0x0, 6));                                              // r0 <- forceSimulatedButtonPress
            asm.Add(PowerPcAsm.cmpwi(0, 0x0));                                               // if (forceSimulatedButtonPress != 0)
            asm.Add(PowerPcAsm.beq(4));                                                      // {
            asm.Add(PowerPcAsm.stw(0, 0x0, 7));                                              //   pressedButtonsBitArray <- forceSimulatedButtonPress
            asm.Add(PowerPcAsm.li(0, 0x0));                                                  //   \ 
            asm.Add(PowerPcAsm.stw(0, 0x0, 6));                                              //   / forceSimulatedButtonPress <- 0
                                                                                             // }
            asm.Add(PowerPcAsm.lwz(0, 0x4, 3));                                              // *replaced opcode*
            asm.Add(PowerPcAsm.b(routineStartAddress, asm.Count, returnAddr));               // return

            return(asm);
        }
Example #11
0
        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);

            // subi r30,r30,0x15                                  ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d2b0), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r30,0x12                                     ->  cmpwi r30,tableElementsCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d2bc), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(30, (short)(tableRowCount)));
            // li r0,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d334), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r5,r0,0x24                                   ->  mulli r5,r0,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d340), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(5, 0, 0x04));
            // r4 <- 804363c8                                     ->  r4 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d344), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(4, v.upper16Bit)); stream.Seek(0x4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(4, 4, v.lower16Bit));
            // mulli r0,r30,0x24                                  ->  mulli r0,r30,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d350), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 30, 0x04));
            // lwz r0,0x4(r4)                                     ->  lwz r0,0x4(r4)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d35c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x0, 4));

            // subi r31,r3,0x15                                   ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211f90), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r31,0x12                                     ->  cmpwi r31,tableElementsCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211f9c), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(31, (short)(tableRowCount)));
            // li r3,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212014), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r4,r3,0x24                                   ->  mulli r4,r3,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212020), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(4, 3, 0x04));
            // r3 <- 804363c8                                     ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212024), 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)0x8021202c), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 31, 0x04));
            // lwz r3,0x4(r3)                                     ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80212040), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));
        }
        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);

            // subi r3,r3,0x15                                    ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020cec8), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r3,0x12                                      ->  cmpwi r3,tableElementsCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020ced4), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(3, (short)(tableRowCount)));
            // li r0,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020cf68), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r0,r3,0x24                                   ->  mulli r0,r3,0x0c
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020cee0), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 3, 0x0c));
            // r3 <- 804363c8                                     ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020cee4), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Seek(0x4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // mulli r3,r0,0x24                                  ->  mulli r3,r0,0x0c
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020cf74), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(3, 0, 0x0c));
            // lwz r0,0xc(r3)                                     ->  lwz r0,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020cf8c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x0, 3));

            // subi r4,r4,0x15                                   ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211af4), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r4,0x12                                     ->  cmpwi r4,tableElementsCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211b00), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(4, (short)(tableRowCount)));
            // li r3,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211b94), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r0,r4,0x24                                   ->  mulli r0,r4,0x0c
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211b0c), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 4, 0x0c));
            // r4 <- 804363c8                                     ->  r4 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211b10), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(4, v.upper16Bit)); stream.Seek(0x4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(4, 4, v.lower16Bit));
            // mulli r3,r3,0x24                                  ->  mulli r3,r3,0x0c
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211ba0), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(3, 3, 0x0c));
            // lwz r0,0xc(r3)                                     ->  lwz r0,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211bb8), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x0, 3));
        }
Example #13
0
        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);

            // subi r30,r30,0x15                                  ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d1c4), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r30,0x12                                     ->  cmpwi r30,tableElementsCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d1d0), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(30, (short)(tableRowCount)));
            // li r0,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d248), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r4,r0,0x24                                   ->  mulli r4,r0,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d254), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(4, 0, 0x04));
            // r3 <- 804363c8                                     ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d258), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, v.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, v.lower16Bit));
            // mulli r0,r30,0x24                                  ->  mulli r0,r30,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d260), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 30, 0x04));
            // lwz r0,0x8(r3)                                     ->  lwz r0,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020d26c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(0, 0x0, 3));

            // subi r31,r3,0x15                                   ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211ce4), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r31,0x12                                     ->  cmpwi r31,tableElementsCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211cf0), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(31, (short)(tableRowCount)));
            // li r3,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211d68), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r4,r3,0x24                                   ->  mulli r4,r3,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211d74), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(4, 3, 0x04));
            // r3 <- 804363c8                                     ->  r3 <- tableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211d78), 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)0x80211d80), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 31, 0x04));
            // lwz r3,0x8(r3)                                     ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211d94), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));
        }
        private List <UInt32> writeGetDescriptionForCustomSquareRoutine(AddressMapper addressMapper, VAVAddr routineStartAddress)
        {
            var asm = new List <UInt32>();
            var gameUiTextGetString  = addressMapper.toVersionAgnosticAddress((BSVAddr)0x800f78dc);
            var gameUiTextGetCardMsg = addressMapper.toVersionAgnosticAddress((BSVAddr)0x800f837c);
            var gameBoard            = PowerPcAsm.make16bitValuePair((UInt32)addressMapper.toVersionAgnosticAddress((BSVAddr)0x8054d018));

            asm.Add(PowerPcAsm.lis(7, gameBoard.upper16Bit));                                //
            asm.Add(PowerPcAsm.addi(7, 7, gameBoard.lower16Bit));                            // r7 <- start of gameboard table containing all squares
            asm.Add(PowerPcAsm.mulli(8, 24, 0x54));                                          // r8 <- squareId * 0x54 (the size of each square)
            asm.Add(PowerPcAsm.add(6, 7, 8));                                                // r6 <- the current square
            asm.Add(PowerPcAsm.lbz(8, 0x4d, 6));                                             // r8 <- square.squareType
            asm.Add(PowerPcAsm.cmpwi(8, 0x2e));                                              // if(square.squareType == 0x2e)
            asm.Add(PowerPcAsm.bne(3));                                                      // {
            asm.Add(PowerPcAsm.lbz(4, 0x18, 6));                                             //   r4 <- square.district_color
            asm.Add(PowerPcAsm.b(routineStartAddress, asm.Count, gameUiTextGetCardMsg));     //   goto Game::uitext::get_card_message(r4)
                                                                                             // }
            asm.Add(PowerPcAsm.li(6, 0x0));                                                  // \
            asm.Add(PowerPcAsm.li(7, 0x0));                                                  // | No message arguments
            asm.Add(PowerPcAsm.li(8, 0x0));                                                  // /
            asm.Add(PowerPcAsm.b(routineStartAddress, asm.Count, gameUiTextGetString));      // goto Game::uitext::get_string(r4, 0, 0, 0)

            return(asm);
        }
Example #15
0
 public MainDol(EndianBinaryReader stream, List <AddressSection> fileMappingSections, IProgress <ProgressInfo> progress)
 {
     this.addressMapper    = setupAddressMapper(stream, fileMappingSections, progress);
     this.freeSpaceManager = setupFreeSpaceManager(addressMapper);
     this.patches          = setupPatches();
 }
 protected override void readAsm(EndianBinaryReader s, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
 {
     if (isVanilla)
     {
         s.Seek(0x0, SeekOrigin.Current); // offset
     }
     foreach (var mapDescriptor in mapDescriptors)
     {
         mapDescriptor.TargetAmount = s.ReadUInt32();
         if (isVanilla)
         {
             // in vanilla main.dol the table has other stuff in it like initial cash and tour opponents of the map
             // this we need to skip to go the next target amount in the table
             s.Seek(0x24 - 0x4, SeekOrigin.Current);
         }
     }
 }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var mapIcons = writeIconStrings(mapDescriptors);
            Dictionary <string, VAVAddr> iconTableMap;
            VAVAddr iconTableAddr       = writeIconTable(mapIcons, out iconTableMap);
            VAVAddr mapIconPointerTable = writeMapIconPointerTable(mapDescriptors, iconTableMap);
            ushort  iconCount           = (ushort)iconTableMap.Count;
            short   tableRowCount       = (short)mapDescriptors.Count;

            PowerPcAsm.Pair16Bit v = PowerPcAsm.make16bitValuePair((UInt32)iconTableAddr);
            PowerPcAsm.Pair16Bit w = PowerPcAsm.make16bitValuePair((UInt32)mapIconPointerTable);
            // note: To add custom icons, the following files need to be editted as well:
            // - ui_menu_19_00a.brlyt within game_sequence.arc and within game_sequence_wifi.arc
            // - ui_menu_19_00a_Tag_*.brlan within game_sequence.arc and within game_sequence_wifi.arc

            // custom map icon hack (change it that way that it will call the GetMapDifficulty routine instead of the GetMapOrigin routine
            // the GetMapDifficulty routine is mostly unused by the game and we repurpose it to return the pointer to the pointer of the string of the map icon instead
            // then we go through all map icon pointer pointers and check if it is the same as the one retrieved. If it is then we make it visible, otherwise we set the visibility to false.
            var GetMapDifficulty = addressMapper.toVersionAgnosticAddress((BSVAddr)0x80211da4);

            // bl GetMapOrigin                                     -> bl GetMapDifficulty
            var offset = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e77c);

            stream.Seek(addressMapper.toFileAddress(offset), SeekOrigin.Begin); stream.Write(PowerPcAsm.bl(offset, GetMapDifficulty));
            // cmpw r28,r30                                        -> cmpw r29,r30
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e790), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpw(29, 30));
            // cmplwi r28,0x12                                     -> cmplwi r28,iconCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e7c0), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmplwi(28, iconCount));
            // bl GetMapOrigin                                     -> bl GetMapDifficulty
            offset = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e8a4);
            stream.Seek(addressMapper.toFileAddress(offset), SeekOrigin.Begin); stream.Write(PowerPcAsm.bl(offset, GetMapDifficulty));
            // cmpw r29,r28                                        -> cmpw r30,r28
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e8b8), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpw(30, 28));
            // cmplwi r29,0x12                                     -> cmplwi r29,iconCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e8e8), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmplwi(29, iconCount));
            // bl GetMapOrigin                                     -> bl GetMapDifficulty
            offset = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e824);
            stream.Seek(addressMapper.toFileAddress(offset), SeekOrigin.Begin); stream.Write(PowerPcAsm.bl(offset, GetMapDifficulty));
            // cmplwi r28,0x12                                     -> cmplwi r28,iconCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e84c), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmplwi(28, iconCount));
            // r29 <- 0x8047f5c0                                   -> r29 <- iconTableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e780), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(29, v.upper16Bit)); stream.Seek(4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(29, 29, v.lower16Bit));
            // r30 <- 0x8047f5c0                                   -> r30 <- iconTableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e8a8), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(30, v.upper16Bit)); stream.Seek(4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(30, 30, v.lower16Bit));
            // r30 <- 0x8047f5c0                                   -> r30 <- iconTableAddr
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e828), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(30, v.upper16Bit)); stream.Seek(4, SeekOrigin.Current); stream.Write(PowerPcAsm.addi(30, 30, v.lower16Bit));
            // mr r3,r28                                           -> mr r3,r26
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e94c), SeekOrigin.Begin); stream.Write(PowerPcAsm.mr(3, 26));
            // mr r3,r28                                           -> mr r3,r26
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021e968), SeekOrigin.Begin); stream.Write(PowerPcAsm.mr(3, 26));

            // Modify the GetMapDifficulty routine to retrieve the current map icon addr addr
            // subi r31,r3,0x15                                   ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211dc8), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // cmpwi r31,0x12                                     ->  cmpwi r31,tableRowCount
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211dd4), SeekOrigin.Begin); stream.Write(PowerPcAsm.cmpwi(31, tableRowCount));
            // li r3,0x15                                         ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211e4c), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // mulli r4,r3,0x24                                   ->  mulli r4,r3,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211e58), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(4, 3, 0x04));
            // r3 <- 804363c8                                     ->  r3 <- mapIconPointerTable
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211e5c), SeekOrigin.Begin); stream.Write(PowerPcAsm.lis(3, w.upper16Bit)); stream.Write(PowerPcAsm.addi(3, 3, w.lower16Bit));
            // mulli r0,r31,0x24                                  ->  mulli r0,r31,0x04
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211e64), SeekOrigin.Begin); stream.Write(PowerPcAsm.mulli(0, 31, 0x04));
            // lwz r3,0x1c(r3)                                    ->  lwz r3,0x0(r3)
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80211e78), SeekOrigin.Begin); stream.Write(PowerPcAsm.lwz(3, 0x0, 3));

            // --- Hack to make icons invisible which do not have a map ---
            // -- Init Maps in the map array with -1 --
            var subroutineInitMapIdsForMapIcons = allocate(writeSubroutineInitMapIdsForMapIcons(addressMapper, VAVAddr.NullAddress), "SubroutineInitMapIdsForMapIcons");

            stream.Seek(addressMapper.toFileAddress(subroutineInitMapIdsForMapIcons), SeekOrigin.Begin);
            stream.Write(writeSubroutineInitMapIdsForMapIcons(addressMapper, subroutineInitMapIdsForMapIcons)); // re-write the routine again since now we know where it is located in the main dol
            // increase the array size
            // rlwinm r3,r16,0x2,0x0,0x1d                            -> r3,r16,0x3,0x0,0x1d
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80187794), SeekOrigin.Begin); stream.Write(PowerPcAsm.rlwinm(3, 16, 0x3, 0x0, 0x1d));
            var hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8018779c);

            // cmpwi r3,0x0                                          ->  bl subroutineInitMapIdsForMapIcons
            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); stream.Write(PowerPcAsm.bl(hijackAddr, subroutineInitMapIdsForMapIcons));
            // mr r24,r3                                             ->  cmpwi r3,0x0
            stream.Write(PowerPcAsm.cmpwi(3, 0));
            // increase the array size
            // rlwinm r3,r16,0x2,0x0,0x1d                            -> r3,r16,0x3,0x0,0x1d
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80187aa4), SeekOrigin.Begin); stream.Write(PowerPcAsm.rlwinm(3, 16, 0x3, 0x0, 0x1d));
            hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x80187aac);
            // cmpwi r3,0x0                                          ->  bl subroutineInitMapIdsForMapIcons
            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); stream.Write(PowerPcAsm.bl(hijackAddr, subroutineInitMapIdsForMapIcons));
            // mr r24,r3                                             ->  cmpwi r3,0x0
            stream.Write(PowerPcAsm.cmpwi(3, 0));
            // -- if a map id is -1, make the map icon invisible --
            hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e73c);
            var returnContinueAddr                  = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e740);
            var returnMakeInvisibleAddr             = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e808);
            var subroutineMakeNoneMapIconsInvisible = allocate(writeSubroutineMakeNoneMapIconsInvisible(addressMapper, VAVAddr.NullAddress, returnContinueAddr, returnMakeInvisibleAddr), "SubroutineMakeNoneMapIconsInvisibleMultiplayer");

            stream.Seek(addressMapper.toFileAddress(subroutineMakeNoneMapIconsInvisible), SeekOrigin.Begin);
            stream.Write(writeSubroutineMakeNoneMapIconsInvisible(addressMapper, subroutineMakeNoneMapIconsInvisible, returnContinueAddr, returnMakeInvisibleAddr)); // re-write the routine again since now we know where it is located in the main dol
            // lwz r0,0x184(r3)                                      ->  b subroutineMakeNoneMapIconsInvisible
            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); stream.Write(PowerPcAsm.b(hijackAddr, subroutineMakeNoneMapIconsInvisible));

            // -- if the map id is -1, do not check if it has been unlocked or not ---
            hijackAddr         = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e570);
            returnContinueAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e574);
            var returnSkipMapUnlockedCheck = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8021e5a8);
            var subroutineWriteSubroutineSkipMapUnlockCheck = allocate(writeSubroutineSkipMapUnlockCheck(addressMapper, VAVAddr.NullAddress, returnContinueAddr, returnSkipMapUnlockedCheck), "SubroutineWriteSubroutineSkipMapUnlockCheck");

            stream.Seek(addressMapper.toFileAddress(subroutineWriteSubroutineSkipMapUnlockCheck), SeekOrigin.Begin);
            stream.Write(writeSubroutineSkipMapUnlockCheck(addressMapper, subroutineWriteSubroutineSkipMapUnlockCheck, returnContinueAddr, returnSkipMapUnlockedCheck)); // re-write the routine again since now we know where it is located in the main dol
            // or r3,r26,r26                                      ->  b subroutineWriteSubroutineSkipMapUnlockCheck
            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin); stream.Write(PowerPcAsm.b(hijackAddr, subroutineWriteSubroutineSkipMapUnlockCheck));

            // --- Various Map UI Fixes ---
            // -- if the map index is over the map array size, do not loop around to the first map index again --
            // ble 0x80187e1c                                        ->  b 0x80187e1c
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80187dfc), SeekOrigin.Begin); stream.Write(PowerPcAsm.b(8));
            // -- fix map selection going out of bounds in tour mode --
            // bne 0x80188258                                        ->  nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80188230), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
        }
        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));
        }
 protected override void readAsm(EndianBinaryReader s, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
 {
     foreach (MapDescriptor mapDescriptor in mapDescriptors)
     {
         if (isVanilla)
         {
             // in vanilla there is a mapping of bgXXX to p_bg_XXX which we will assume here without actually reading what is inside the main.dol
             if (mapDescriptor.UnlockID < 18)
             {
                 var number = Regex.Match(mapDescriptor.Background, @"\d+").Value;
                 mapDescriptor.MapIcon = "p_bg_" + number;
             }
         }
         else
         {
             mapDescriptor.MapIcon = resolveAddressAddressToString((VAVAddr)s.ReadUInt32(), s, addressMapper);
         }
     }
 }
Example #20
0
 protected abstract VAVAddr readTableAddr(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla);
 protected override void readAsm(EndianBinaryReader s, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
 {
     if (isVanilla)
     {
         readVanillaTable(s, mapDescriptors);
     }
     else
     {
         foreach (MapDescriptor mapDescriptor in mapDescriptors)
         {
             mapDescriptor.Desc_MSG_ID = s.ReadUInt32();
         }
     }
 }
        protected override void writeAsm(EndianBinaryWriter stream, AddressMapper addressMapper, List <MapDescriptor> mapDescriptors)
        {
            var tableAddr = writeTable(mapDescriptors);

            // --- Game::GameSequenceDataAdapter::GetNumMapsInZone ---
            var subroutineGetNumMapsInZone = allocate(writeSubroutineGetNumMapsInZone(mapDescriptors), "SubroutineGetNumMapsInZone");
            var hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8020f3ac);

            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin);
            // li r3,0x6 ->  b subroutineGetNumMapsInZone
            stream.Write(PowerPcAsm.b(hijackAddr, subroutineGetNumMapsInZone));

            // --- Game::GameSequenceDataAdapter::GetMapsInZone ---
            hijackAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8020f454);
            var returnAddr = addressMapper.toVersionAgnosticAddress((BSVAddr)0x8020f554);
            var subroutineGetMapsInZone = allocate(writeSubroutineGetMapsInZone(addressMapper, mapDescriptors, tableAddr, VAVAddr.NullAddress, returnAddr), "SubroutineGetMapsInZone");

            stream.Seek(addressMapper.toFileAddress(subroutineGetMapsInZone), SeekOrigin.Begin);
            stream.Write(writeSubroutineGetMapsInZone(addressMapper, mapDescriptors, tableAddr, subroutineGetMapsInZone, returnAddr)); // re-write the routine again since now we know where it is located in the main dol
            stream.Seek(addressMapper.toFileAddress(hijackAddr), SeekOrigin.Begin);
            // cmpwi r29,0x0 ->  b subroutineGetMapsInZone
            stream.Write(PowerPcAsm.b(hijackAddr, subroutineGetMapsInZone));

            // --- Write Table Meta Information ---
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020f458), SeekOrigin.Begin);
            stream.Write((uint)tableAddr);
            stream.Write((short)0);
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8020F45E), SeekOrigin.Begin);
            stream.Write((short)mapDescriptors.Count);

            // --- Fix Wifi Map Selection ---
            // bl GameSequenceDataAdapter::GetMapOrigin(r3)                               -> nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80185ac4), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // or r31,r3,r3                                                               -> or r31,r4,r4
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80185ac8), SeekOrigin.Begin); stream.Write(PowerPcAsm.or(31, 4, 4));
            // li r5,0x1                                                                  -> li r5,0x2
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80185b10), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(5, 2));
            // bl GameSequenceDataAdapter::GetMapOrigin(r3)                               -> nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8024b1b8), SeekOrigin.Begin); stream.Write(PowerPcAsm.nop());
            // bl GameSequenceDataAdapter::GetMapOrigin(r3)                               -> nop
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x802498a8), SeekOrigin.Begin);
            for (int i = 0; i < 8; i++)
            {
                stream.Write(PowerPcAsm.nop());
            }
            // --- Default selected map button in wifi ---
            // since Standard Mode is selected on default, we use this mapset to find the standard map
            // TODO need asm hack to determine currently selected MapSet and use rather use that ID
            short defaultMap = 0;

            for (short i = 0; i < mapDescriptors.Count; i++)
            {
                var mapDescriptor = mapDescriptors[i];
                if (mapDescriptor.MapSet == 1 && mapDescriptor.Zone == 0 && mapDescriptor.Order == 0)
                {
                    defaultMap = i;
                }
            }
            // 0x9 = Castle Trodain
            // li r3,0x9                                                                  -> li r3,0x9
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8024afc8), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(3, defaultMap));
            // TODO 0x13 is some special handling map id. Need to check what is going on with it
            // li r3,0x13                                                                 -> li r3,0x13
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x80243ae4), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(5, 0x13));
            // --- Fix out of array bounds error when opening tour mode and viewing the zones and having more than 6 maps in a zone ---
            // bl Game::GameSequenceDataAdapter::GetNumMapsInZone    -> li r3,0x6
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021f880), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(3, 0x6));
            // bl Game::GameSequenceDataAdapter::GetNumMapsInZone    -> li r3,0x6
            stream.Seek(addressMapper.toFileAddress((BSVAddr)0x8021ff4c), SeekOrigin.Begin); stream.Write(PowerPcAsm.li(3, 0x6));
        }
 protected override void readAsm(EndianBinaryReader stream, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
 {
     if (isVanilla)
     {
         setVanillaMapSetZoneOrder(mapDescriptors);
     }
     else
     {
         for (int i = 0; i < mapDescriptors.Count; i++)
         {
             var mapDescriptor = mapDescriptors[i];
             mapDescriptor.MapSet = stream.ReadSByte();
             mapDescriptor.Zone   = stream.ReadSByte();
             if (mapDescriptor.Zone == 0)
             {
                 mapDescriptor.Zone = 1;
             }
             else if (mapDescriptor.Zone == 1)
             {
                 mapDescriptor.Zone = 0;
             }
             mapDescriptor.Order = stream.ReadSByte();
         }
     }
 }
Example #24
0
 protected override Int16 readTableRowCount(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla)
 {
     return(-1);
 }
Example #25
0
 protected override void readAsm(EndianBinaryReader s, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
 {
     if (isVanilla)
     {
         s.Seek(0x4, SeekOrigin.Current); // offset
     }
     foreach (var mapDescriptor in mapDescriptors)
     {
         mapDescriptor.BGMID = s.ReadUInt32();
         if (isVanilla)
         {
             // in vanilla main.dol the table has other stuff in it like bgm id, map frb files, etc.
             // this we need to skip to go the next target amount in the table
             s.Seek(0x38 - 0x04, SeekOrigin.Current);
         }
     }
 }
        protected override void readAsm(EndianBinaryReader s, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
        {
            if (isVanilla)
            {
                s.Seek(0x28, SeekOrigin.Current); // offset
            }
            foreach (var mapDescriptor in mapDescriptors)
            {
                var address = (VAVAddr)s.ReadUInt32();
                var pos     = s.BaseStream.Position;
                readRotationOriginPoints(address, s, mapDescriptor, addressMapper);
                s.BaseStream.Seek(pos, SeekOrigin.Begin);

                if (isVanilla)
                {
                    // in vanilla main.dol the table has other stuff in it like bgm id, map frb files, etc.
                    // this we need to skip to go the next target amount in the table
                    s.Seek(0x38 - 0x4, SeekOrigin.Current);
                }
            }
        }
Example #27
0
 /// <summary>
 /// In vanilla the venture card table uses a wasteful format of having an array of 130 bytes for each map:
 /// 1 byte for each venture card id, the last two bytes are unused.
 /// The hacked compressed venture card table uses only 16 bytes for each map
 /// </summary>
 /// <param name="s"></param>
 /// <param name="mapDescriptors"></param>
 /// <param name="isVanilla"></param>
 protected override void readAsm(EndianBinaryReader s, List <MapDescriptor> mapDescriptors, AddressMapper addressMapper, bool isVanilla)
 {
     if (isVanilla)
     {
         readVanillaVentureCardTable(s, mapDescriptors);
     }
     else
     {
         readCompressedVentureCardTable(s, mapDescriptors);
     }
 }
Example #28
0
 protected abstract bool readIsVanilla(EndianBinaryReader stream, AddressMapper addressMapper);
 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;
         }
     }
 }
Example #30
0
 protected abstract Int16 readTableRowCount(EndianBinaryReader stream, AddressMapper addressMapper, bool isVanilla);