private static void SubtractFromInt16AtAddress(MemoryStream ms, Dol dol, uint position, short value)
        {
            ms.Position = dol.MapRamToRom(position);
            short result = (short)(ms.PeekInt16(EndianUtils.Endianness.BigEndian) - value);

            ms.WriteInt16(result, EndianUtils.Endianness.BigEndian);
        }
        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
            }
        }
示例#3
0
        public override void ApplyToDol(Dol dol)
        {
            Address.AssertAbsolute();
            Target.AssertAbsolute();

            dol.WriteUInt32(Address.Value, GenerateInstruction());
        }
        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 IncreaseNoticeBoxBufferSize(MemoryStream ms, Dol dol)
        {
            // default stack space is too small, overflows on the shuttle tutorial message (and possibly elsewhere?)
            // so increase it by a bit
            const short extraBufferSpace = 0x100;

            SubtractFromInt16AtAddress(ms, dol, 0x8029b128 + 2, extraBufferSpace);
            AddToInt16AtAddress(ms, dol, 0x8029b130 + 2, extraBufferSpace);
            AddToInt16AtAddress(ms, dol, 0x8029b134 + 2, extraBufferSpace);
            AddToInt16AtAddress(ms, dol, 0x8029b378 + 2, extraBufferSpace);
            AddToInt16AtAddress(ms, dol, 0x8029b380 + 2, extraBufferSpace);
            AddToInt16AtAddress(ms, dol, 0x8029b388 + 2, extraBufferSpace);
        }
示例#6
0
        public override void ApplyToDol(Dol dol)
        {
            Address.AssertAbsolute();
            if (ValueType == Type.Pointer)
            {
                Value.AssertAbsolute();
            }
            else
            {
                Value.AssertValue();
            }

            if (Original.HasValue)
            {
                bool patchOK = false;
                switch (ValueType)
                {
                case Type.Value8:
                    patchOK = (dol.ReadByte(Address.Value) == Original.Value.Value);
                    break;

                case Type.Value16:
                    patchOK = (dol.ReadUInt16(Address.Value) == Original.Value.Value);
                    break;

                case Type.Value32:
                case Type.Pointer:
                    patchOK = (dol.ReadUInt32(Address.Value) == Original.Value.Value);
                    break;
                }
                if (!patchOK)
                {
                    return;
                }
            }

            switch (ValueType)
            {
            case Type.Value8: dol.WriteByte(Address.Value, (byte)Value.Value); break;

            case Type.Value16: dol.WriteUInt16(Address.Value, (ushort)Value.Value); break;

            case Type.Value32:
            case Type.Pointer: dol.WriteUInt32(Address.Value, Value.Value); break;
            }
        }
        public static void ModifyTextInputForEnglish(MemoryStream ms, Dol dol)
        {
            // characters available in text input are stored in a few long strings that assume all characters are 2-byte Shift-JIS
            // to avoid having to recode the entire menu we also just store them like that even for English characters...

            // some scratchpad notes:
            // function at 0x8024ec8c sets up the text input menu
            // if you break there and modify the u32 at [r4 + 0x54] you can affect what selections are available to the user
            // 0x8007d674 is the strcmp for the checking password chests

            string[] charmaps = new string[12];
            for (int i = 0; i < 12; ++i)
            {
                ms.Position = 0x530068 + i * 0x5b;
                charmaps[i] = ms.ReadShiftJis(0x5a);
            }

            // hiragana -> generic alphanumeric
            // TODO: some of these symbols are not in the font
            string alphanumeric = Util.ConvertToFullwidth("ABCDEFGHIJKLMNOPQRSTUVWXYZ    abcdefghijklmnopqrstuvwxyz    0123456789+-*/=@'\".,!?%&#~¢£¬¦");

            (charmaps[3], charmaps[7]) = ConvertToHalves(alphanumeric);

            // katakana -> password chest limited charset
            string chest = Util.ConvertToFullwidth("abcdefghijklmnopqrstuvwxyz    0123456789".PadRight(90));

            (charmaps[2], charmaps[6]) = ConvertToHalves(chest);

            // latin -> symbols
            // TODO: some of these symbols are not in the font, clearly this table is not actually used originally...
            charmaps[8] = charmaps[10];
            charmaps[9] = charmaps[11];

            for (int i = 0; i < 12; ++i)
            {
                ms.Position = 0x530068 + i * 0x5b;
                ms.WriteShiftJis(charmaps[i], 0x5a);
            }

            // TODO: text entry style 0 (generic) should hide the 2nd (of 3) input field
            // TODO: text entry style 3 (chest pass) should hide the 2nd (of 2) input field

            // allow spaces to be entered mid-string
            ms.Position = dol.MapRamToRom(0x80251374);
            ms.WriteUInt16(0x4800, EndianUtils.Endianness.BigEndian);
        }
示例#8
0
        public override void ApplyToDol(Dol dol)
        {
            Address.AssertAbsolute();
            Target.AssertAbsolute();

            switch (Id)
            {
            case Ids.Rel24:
                long delta = Target - Address;
                uint insn  = dol.ReadUInt32(Address.Value) & 0xFC000003;
                insn |= ((uint)delta & 0x3FFFFFC);
                dol.WriteUInt32(Address.Value, insn);
                break;

            case Ids.Addr32:
                dol.WriteUInt32(Address.Value, Target.Value);
                break;

            case Ids.Addr16Lo:
                dol.WriteUInt16(Address.Value, (ushort)(Target.Value & 0xFFFF));
                break;

            case Ids.Addr16Hi:
                dol.WriteUInt16(Address.Value, (ushort)(Target.Value >> 16));
                break;

            case Ids.Addr16Ha:
                ushort v = (ushort)(Target.Value >> 16);
                if ((Target.Value & 0x8000) == 0x8000)
                {
                    v++;
                }
                dol.WriteUInt16(Address.Value, v);
                break;

            default:
                throw new NotImplementedException("unrecognised relocation type");
            }
        }
示例#9
0
 public override void ApplyToDol(Dol dol)
 {
     throw new NotImplementedException();
 }
示例#10
0
        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);
        }
示例#11
0
 public abstract void ApplyToDol(Dol dol);