public static void FixDualizeResultMessages(MemoryStream ms, Dol dol, ReservedMemchunk memoryAreaSprintfStringDualizeResult, ReservedMemchunk memoryAreaSprintfStringNewDualizeResult) { var be = EndianUtils.Endianness.BigEndian; // adjust sprintf parameters for dualize result { uint address = memoryAreaSprintfStringDualizeResult.AddressRam; var imm = GenerateHighLowImmediatesFor32BitLoad(address); ms.Position = dol.MapRamToRom(0x8027bc58); ms.WriteUInt32(0x3c800000u | (imm.high & 0xffffu), be); // lis r4, imm.high ms.WriteUInt32(AssembleMR(5, 3), be); // mr r5,r3 ms.WriteUInt32(0x38840000u | (imm.low & 0xffffu), be); // addi r4, r4, imm.low ms.Position += 4; ms.WriteUInt32(0x60000000, be); // nop ms.WriteUInt32((ms.PeekUInt32(be) & 0xfc1fffff) | (6 << 21), be); // replace target register with r6 } // adjust sprintf parameters for dualize result { uint address = memoryAreaSprintfStringNewDualizeResult.AddressRam; var imm = GenerateHighLowImmediatesFor32BitLoad(address); ms.Position = dol.MapRamToRom(0x8027bc1c); ms.WriteUInt32(0x3c800000u | (imm.high & 0xffffu), be); // lis r4, imm.high ms.WriteUInt32(AssembleMR(9, 3), be); // mr r9,r3 ms.WriteUInt32(0x38840000u | (imm.low & 0xffffu), be); // addi r4, r4, imm.low ms.WriteUInt32(AssembleMR(5, 30), be); // mr r5,r30 ms.Position += 8; ms.WriteUInt32(0x60000000, be); // nop } }
public static void FixRequestRewardMesssages(MemoryStream ms, Dol dol, ReservedMemchunk memoryAreaSprintfStringItemReward, ReservedMemchunk memoryAreaSprintfStringGaldReward, ReservedMemchunk memoryAreaSprintfStringNotEnough) { var be = EndianUtils.Endianness.BigEndian; // function at 80290d44 builds these // adjust sprintf for message with item reward { uint addressSprintfStringItemReward = memoryAreaSprintfStringItemReward.AddressRam; var imm = GenerateHighLowImmediatesFor32BitLoad(addressSprintfStringItemReward); ms.Position = dol.MapRamToRom(0x80291118); ms.WriteUInt32((ms.PeekUInt32(be) & 0xfc1fffff) | (9 << 21), be); // replace target register with r9 ms.WriteUInt32(0x3c800000u | (imm.high & 0xffffu), be); // lis r4, imm.high ms.WriteUInt32(0x60000000, be); // nop ms.WriteUInt32(0x38840000u | (imm.low & 0xffffu), be); // addi r4, r4, imm.low ms.WriteUInt32(AssembleMR(5, 27), be); // mr r5,r27 ms.Position += 4; ms.WriteUInt32(0x60000000, be); // nop ms.WriteUInt32(AssembleMR(8, 29), be); // mr r8,r29 ms.WriteUInt32(0x60000000, be); // nop ms.Position += 4; ms.Position += 4; ms.Position += 4; ms.WriteUInt32(0x60000000, be); // nop } // adjust sprintf parameters for message with gald reward { uint addressSprintfStringGaldReward = memoryAreaSprintfStringGaldReward.AddressRam; var imm = GenerateHighLowImmediatesFor32BitLoad(addressSprintfStringGaldReward); ms.Position = dol.MapRamToRom(0x8029106c); ms.WriteUInt32(0x60000000, be); // nop ms.WriteUInt32(0x3c800000u | (imm.high & 0xffffu), be); // lis r4, imm.high ms.WriteUInt32(0x38840000u | (imm.low & 0xffffu), be); // addi r4, r4, imm.low ms.WriteUInt32(AssembleMR(5, 24), be); // mr r5,r24 ms.Position += 8; ms.WriteUInt32((ms.PeekUInt32(be) & 0xfc1fffff) | (9 << 21), be); // replace target register with r9 ms.WriteUInt32(AssembleMR(8, 28), be); // mr r8,r28 ms.WriteUInt32(AssembleMR(10, 27), be); // mr r10,r27 ms.Position += 4; ms.WriteUInt32(0x60000000, be); // nop } // adjust sprintf parameters for message when you don't have the necessary items { uint address = memoryAreaSprintfStringNotEnough.AddressRam; var imm = GenerateHighLowImmediatesFor32BitLoad(address); ms.Position = dol.MapRamToRom(0x80290e6c); ms.WriteUInt32(0x3c800000u | (imm.high & 0xffffu), be); // lis r4, imm.high ms.Position += 4; ms.WriteUInt32(0x38840000u | (imm.low & 0xffffu), be); // addi r4, r4, imm.low ms.Position += 20; ms.WriteUInt32(0x60000000, be); // nop } }
public static void ApplyFontTexPointerFix(MemoryStream ms, Dol dol, ReservedMemchunk chunk) { // code snippet for actually repointing // looks at all pointers that start with bitpattern 1110 (0xE) and readjusts them to actually point at the allocated memory // input: // - r3: address of first pointer to fix // - r4: amount of pointers to fix // - r5: bytes to increment per iteration to get to the next pointer // - r6: address font texture has been allocated at uint repointingEntryPoint = chunk.AddressRam; ms.Position = chunk.AddressRom; ms.WriteUInt32(0x7c8903a6u.ToEndian(EndianUtils.Endianness.BigEndian)); // mtctr r4 ms.WriteUInt32(0x3d00e000u.ToEndian(EndianUtils.Endianness.BigEndian)); // lis r8, 0xE000 ms.WriteUInt32(0x81430000u.ToEndian(EndianUtils.Endianness.BigEndian)); // lwz r10, 0 (r3) ms.WriteUInt32(0x55490006u.ToEndian(EndianUtils.Endianness.BigEndian)); // rlwinm r9, r10, 0, 0, 3 (f0000000) ms.WriteUInt32(0x7f894000u.ToEndian(EndianUtils.Endianness.BigEndian)); // cmpw cr7, r9, r8 ms.WriteUInt32(0x40be0010u.ToEndian(EndianUtils.Endianness.BigEndian)); // bne+ cr7 --> add r3, r3, r5 ms.WriteUInt32(0x554a013eu.ToEndian(EndianUtils.Endianness.BigEndian)); // rlwinm r10, r10, 0, 4, 31, (0fffffff) ms.WriteUInt32(0x7d4a3214u.ToEndian(EndianUtils.Endianness.BigEndian)); // add r10, r10, r6 ms.WriteUInt32(0x91430000u.ToEndian(EndianUtils.Endianness.BigEndian)); // stw r10, 0 (r3) ms.WriteUInt32(0x7c632a14u.ToEndian(EndianUtils.Endianness.BigEndian)); // add r3, r3, r5 ms.WriteUInt32(0x4200ffe0u.ToEndian(EndianUtils.Endianness.BigEndian)); // bdnz+ --> lwz r10, 0 (r3) ms.WriteUInt32(0x4e800020u.ToEndian(EndianUtils.Endianness.BigEndian)); // blr uint pointerFixCodeEntryPoint = dol.MapRomToRam((uint)ms.Position); ms.WriteUInt32(0x9421ffb0u.ToEndian(EndianUtils.Endianness.BigEndian)); // stwu sp, -0x50 (sp) ms.WriteUInt32(0x7c0802a6u.ToEndian(EndianUtils.Endianness.BigEndian)); // mflr r0 ms.WriteUInt32(0x91010014u.ToEndian(EndianUtils.Endianness.BigEndian)); // stw r8, 0x0014 (sp) ms.WriteUInt32(0x91210018u.ToEndian(EndianUtils.Endianness.BigEndian)); // stw r9, 0x0018 (sp) ms.WriteUInt32(0x9141001Cu.ToEndian(EndianUtils.Endianness.BigEndian)); // stw r10, 0x001C (sp) foreach (var data in GetChunksForTexPointersFix(dol)) { var imm = GenerateHighLowImmediatesFor32BitLoad(data.where); ms.WriteUInt32((0x3c600000u | (imm.high & 0xffffu)).ToEndian(EndianUtils.Endianness.BigEndian)); // lis r3, imm.high ms.WriteUInt32((0x38630000u | (imm.low & 0xffffu)).ToEndian(EndianUtils.Endianness.BigEndian)); // addi r3, r3, imm.low ms.WriteUInt32((0x38800000u | (data.count & 0xffffu)).ToEndian(EndianUtils.Endianness.BigEndian)); // li r4, data.count ms.WriteUInt32((0x38a00000u | (data.skip & 0xffffu)).ToEndian(EndianUtils.Endianness.BigEndian)); // li r5, data.skip ms.WriteUInt32(0x80de0954u.ToEndian(EndianUtils.Endianness.BigEndian)); // lwz r6, 0x0954 (r30) uint here = dol.MapRomToRam((uint)ms.Position); uint diff = repointingEntryPoint - here; ms.WriteUInt32((0x48000001u | (diff & 0x3fffffcu)).ToEndian(EndianUtils.Endianness.BigEndian)); // bl --> repointingEntryPoint } ms.WriteUInt32(0x8141001Cu.ToEndian(EndianUtils.Endianness.BigEndian)); // lwz r10, 0x001C (sp) ms.WriteUInt32(0x81210018u.ToEndian(EndianUtils.Endianness.BigEndian)); // lwz r9, 0x0018 (sp) ms.WriteUInt32(0x81010014u.ToEndian(EndianUtils.Endianness.BigEndian)); // lwz r8, 0x0014 (sp) ms.WriteUInt32(0x7c0803a6u.ToEndian(EndianUtils.Endianness.BigEndian)); // mtlr r0 ms.WriteUInt32(0x38210050u.ToEndian(EndianUtils.Endianness.BigEndian)); // addi sp, sp, 0x50 long fixupPos = ms.Position; ms.WriteUInt32(0u); // placeholder for the instruction we overwrite to jump to our code ms.WriteUInt32(0x4e800020u.ToEndian(EndianUtils.Endianness.BigEndian)); // blr // and finally, actually hook code ms.Position = dol.MapRamToRom(0x8006be48u); // right after font texture is loaded into memory uint replacedInstruction = ms.PeekUInt32(); { uint here = dol.MapRomToRam((uint)ms.Position); uint diff = pointerFixCodeEntryPoint - here; ms.WriteUInt32((0x48000001u | (diff & 0x3fffffcu)).ToEndian(EndianUtils.Endianness.BigEndian)); // bl --> pointerFixCodeEntryPoint } ms.Position = fixupPos; ms.WriteUInt32(replacedInstruction); }