mirror of
https://wiilab.wiimart.org/wiimart/WiiMart-Patcher
synced 2025-09-02 19:41:13 +02:00

The PowerPC instruction encoder and patching logic is now available at https://github.com/wii-tools/powerpc.
283 lines
8.0 KiB
Go
283 lines
8.0 KiB
Go
package main
|
|
|
|
import (
|
|
. "github.com/wii-tools/powerpc"
|
|
)
|
|
|
|
// OverwriteIOSPatch effectively nullifies IOSC_VerifyPublicKeySign.
|
|
// See docs/patch_overwrite_ios.md for more information.
|
|
var OverwriteIOSPatch = PatchSet{
|
|
Name: "Overwrite IOS Syscall for ES",
|
|
Patches: []Patch{
|
|
{
|
|
Name: "Clear extraneous functions",
|
|
AtOffset: 20272,
|
|
|
|
Before: Instructions{
|
|
// Function: textinput::EventObserver::onOutOfLength
|
|
LIS(R3, 0x802f),
|
|
ADDI(R3, R3, 0x7ac4),
|
|
CRXOR(),
|
|
// b printf
|
|
Instruction{0x48, 0x2a, 0x8b, 0x78},
|
|
|
|
// Function: textinput::EventObserver::onCancel
|
|
LIS(R3, 0x802f),
|
|
ADDI(R3, R3, 0x7ab8),
|
|
CRXOR(),
|
|
// b printf
|
|
Instruction{0x48, 0x2a, 0x8b, 0x68},
|
|
|
|
// Function: textinput::EventObserver::onOK
|
|
// subi r3, r3, 0x7fe0
|
|
Instruction{0x38, 0x6d, 0x80, 0x20},
|
|
CRXOR(),
|
|
// b printf
|
|
Instruction{0x48, 0x2a, 0x8b, 0x5c},
|
|
|
|
Padding,
|
|
|
|
// Function: textinput::EventObserver::onSE
|
|
BLR(),
|
|
Padding, Padding, Padding,
|
|
// Function: textinput::EventObserver::onEvent
|
|
BLR(),
|
|
Padding, Padding, Padding,
|
|
// Function: textinput::EventObserver::onCommand
|
|
BLR(),
|
|
Padding, Padding, Padding,
|
|
// Function: textinput::EventObserver::onInput
|
|
BLR(),
|
|
Padding, Padding, Padding,
|
|
}.Bytes(),
|
|
|
|
// We wish to clear extraneous blrs so that our custom overwriteIOSMemory
|
|
// function does not somehow conflict.
|
|
// We only preserve onSE, which is this immediate BLR.
|
|
After: append(Instructions{
|
|
BLR(),
|
|
}.Bytes(), EmptyBytes(108)...),
|
|
},
|
|
{
|
|
Name: "Repair textinput::EventObserver vtable",
|
|
AtOffset: 3095452,
|
|
|
|
Before: []byte{
|
|
0x80, 0x01, 0x44, 0x50, // onSE
|
|
0x80, 0x01, 0x44, 0x40, // onEvent
|
|
0x80, 0x01, 0x44, 0x30, // onCommand
|
|
0x80, 0x01, 0x44, 0x20, // onInput
|
|
0x80, 0x01, 0x44, 0x10, // onOK
|
|
0x80, 0x01, 0x44, 0x00, // onCancel
|
|
0x80, 0x01, 0x43, 0xf0, // onOutOfLength
|
|
},
|
|
After: []byte{
|
|
// These are all pointers to our so-called doNothing.
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
0x80, 0x01, 0x43, 0xf0,
|
|
},
|
|
},
|
|
{
|
|
Name: "Repair ipl::keyboard::EventObserver vtable",
|
|
AtOffset: 3097888,
|
|
|
|
Before: []byte{
|
|
0x80, 0x01, 0x44, 0x50, // textinput::EventObserver::onSE
|
|
0x80, 0x01, 0x84, 0xE0, // onCommand - not patched
|
|
0x80, 0x01, 0x44, 0x30, // textinput::EventObserver::onCommand
|
|
0x80, 0x01, 0x85, 0x20, // onSE - not patching
|
|
0x80, 0x01, 0x87, 0x40, // onOK - not patching
|
|
0x80, 0x01, 0x87, 0x60, // onCancel - not patching
|
|
0x80, 0x01, 0x43, 0xF0, // textinput::EventObserver::onOutOfLength
|
|
},
|
|
After: []byte{
|
|
0x80, 0x01, 0x43, 0xf0, // textinput::EventObserver::doNothing
|
|
0x80, 0x01, 0x84, 0xE0, // onCommand - not patched
|
|
0x80, 0x01, 0x43, 0xf0, // textinput::EventObserver::doNothing
|
|
0x80, 0x01, 0x85, 0x20, // onSE - not patching
|
|
0x80, 0x01, 0x87, 0x40, // onOK - not patching
|
|
0x80, 0x01, 0x87, 0x60, // onCancel - not patching
|
|
0x80, 0x01, 0x43, 0xf0, // textinput::EventObserver::doNothing
|
|
},
|
|
},
|
|
{
|
|
Name: "Insert patch table",
|
|
AtOffset: 3205088,
|
|
|
|
Before: EmptyBytes(52),
|
|
After: []byte{
|
|
//////////////
|
|
// PATCH #1 //
|
|
//////////////
|
|
// We want to write to MEM_PROT at 0x0d8b420a.
|
|
// For us, this is mapped to 0xcd8b420a.
|
|
0xcd, 0x8b, 0x42, 0x0a,
|
|
// We are going to write the value 0x2 to unlock everything.
|
|
0x00, 0x00, 0x00, 0x02,
|
|
|
|
//////////////
|
|
// PATCH #2 //
|
|
//////////////
|
|
// We want to write to IOSC_VerifyPublicKeySign at 0x13a73ad4.
|
|
// For us, this is mapped to 0x92a73ad4.
|
|
0x93, 0xa7, 0x3a, 0xd4,
|
|
// 0x20004770 is equivalent in ARM THUMB to:
|
|
// mov r0, #0x0
|
|
// bx lr
|
|
0x20, 0x00, 0x47, 0x70,
|
|
|
|
// Not a patch! This is here so we have shorter assembly.
|
|
// 0xcd8005a0 is the location of LT_CHIPREVID.
|
|
0xcd, 0x80, 0x05, 0xa0,
|
|
// We're attempting to compare 0xcafe.
|
|
0x00, 0x00, 0xca, 0xfe,
|
|
|
|
//////////////////////////
|
|
// PATCH #3 - vWii only //
|
|
//////////////////////////
|
|
// Patch location:
|
|
// We want to write at 0x20102100, aka "ES_AddTicket".
|
|
// We use the address mapped to PowerPC.
|
|
0x93, 0x9f, 0x21, 0x00,
|
|
// The original code has a few conditionals preventing system title usage.
|
|
// We simply branch off past these.
|
|
// 0x681ae008 is equivalent in ARM THUMB to:
|
|
// ldr r2,[r3,#0x0] ; original code we wish to preserve
|
|
// ; so we can write 32 bits
|
|
// b +0x14 ; branch past conditionals
|
|
0x68, 0x1a, 0xe0, 0x08,
|
|
|
|
//////////////////////////
|
|
// PATCH #4 - vWii only //
|
|
//////////////////////////
|
|
// We want to write to 0x20103240, aka "ES_AddTitleStart".
|
|
// We use the address mapped to PowerPC.
|
|
0x93, 0x9f, 0x32, 0x40,
|
|
// The original code has a few conditionals preventing system title usage.
|
|
// 0xe00846c0 is equivalent in ARM THUMB to:
|
|
// b +0x8 ; branch past conditionals
|
|
// add sp,#0x0 ; recommended THUMB nop
|
|
0xe0, 0x08, 0xb0, 0x00,
|
|
|
|
//////////////////////////
|
|
// PATCH #5 - vWii only //
|
|
//////////////////////////
|
|
// Lastly, we want to write to 0x20103564, aka "ES_AddContentStart".
|
|
// We use the address mapped to PowerPC.
|
|
0x93, 0x9f, 0x35, 0x64,
|
|
// The original code has a few conditionals preventing system title usage.
|
|
// We simply branch off past these.
|
|
// 0xe00c46c0 is equivalent in ARM THUMB to:
|
|
// b +0xc ; branch past conditionals
|
|
// add sp,#0x0 ; recommended THUMB nop
|
|
0xe0, 0x0c, 0xb0, 0x00,
|
|
|
|
// This is additionally not a patch!
|
|
// We use this to store our ideal MEM2 mapping.
|
|
0x93, 0x00, 0x01, 0xff,
|
|
},
|
|
},
|
|
{
|
|
Name: "Insert overwriteIOSMemory",
|
|
AtOffset: 20276,
|
|
|
|
// This area should be cleared in the patch
|
|
// "Clear extraneous functions".
|
|
Before: EmptyBytes(108),
|
|
After: Instructions{
|
|
// Our patch table is available at 0x803126e0.
|
|
LIS(R8, 0x8031),
|
|
ORI(R8, R8, 0x26e0),
|
|
|
|
// Load address/value pair for MEM_PROT
|
|
LWZ(R9, 0x0, R8),
|
|
LWZ(R10, 0x4, R8),
|
|
// Apply lower half
|
|
STH(R10, 0x0, R9),
|
|
|
|
// Load a better mapping for upper MEM2.
|
|
LWZ(R9, 0x30, R8),
|
|
// mtspr DBAT7U, r9
|
|
Instruction{0x7d, 0x3e, 0x8b, 0xa6},
|
|
|
|
// Load address/value pair for IOSC_VerifyPublicKeySign
|
|
LWZ(R9, 0x8, R8),
|
|
LWZ(R10, 0xc, R8),
|
|
// Apply!
|
|
STW(R10, 0x0, R9),
|
|
|
|
// The remainder of our patches are for a Wii U. We must detect such.
|
|
// Even in vWii mode, 0x0d8005a0 (LT_CHIPREVID) will have its upper
|
|
// 16 bits set to 0xCAFE. We can compare against this.
|
|
// See also: https://wiiubrew.org/wiki/Hardware/Latte_registers
|
|
// (However, we must access the cached version at 0xcd8005a0.)
|
|
LWZ(R9, 0x10, R8),
|
|
LWZ(R9, 0, R9),
|
|
// sync 0
|
|
SYNC(),
|
|
|
|
// Shift this value 16 bits to the right
|
|
// in order to compare its higher value.
|
|
// rlwinm r9, r9, 0x10, 0x10, 0x1f
|
|
Instruction{0x55, 0x29, 0x84, 0x3e},
|
|
|
|
// Load 0xcafe, our comparison value
|
|
LWZ(R10, 0x14, R8),
|
|
|
|
// Compare!
|
|
// cmpw r9, r10
|
|
Instruction{0x7c, 0x09, 0x50, 0x00},
|
|
|
|
// If we're not a Wii U, carry on until the end.
|
|
// bne (last blr)
|
|
Instruction{0x40, 0x82, 0x00, 0x28},
|
|
|
|
// Apply ES_AddTicket
|
|
LWZ(R9, 0x18, R8),
|
|
LWZ(R10, 0x1c, R8),
|
|
STW(R10, 0x0, R9),
|
|
|
|
// Apply ES_AddTitleStart
|
|
LWZ(R9, 0x20, R8),
|
|
LWZ(R10, 0x24, R8),
|
|
STW(R10, 0x0, R9),
|
|
|
|
// Apply ES_AddContentStart
|
|
LWZ(R9, 0x28, R8),
|
|
LWZ(R10, 0x2c, R8),
|
|
STW(R10, 0x0, R9),
|
|
|
|
// We're finished patching!
|
|
BLR(),
|
|
}.Bytes(),
|
|
},
|
|
{
|
|
Name: "Do not require input for exception handler",
|
|
AtOffset: 32032,
|
|
Before: Instructions{
|
|
STWU(R1, R1, 0xFC10),
|
|
}.Bytes(),
|
|
After: Instructions{
|
|
BLR(),
|
|
}.Bytes(),
|
|
},
|
|
{
|
|
Name: "Modify ipl::Exception::__ct",
|
|
AtOffset: 31904,
|
|
|
|
Before: Instructions{
|
|
BLR(),
|
|
}.Bytes(),
|
|
After: Instructions{
|
|
// b overwriteIOSMemory
|
|
Instruction{0x42, 0x80, 0xd2, 0x94},
|
|
}.Bytes(),
|
|
},
|
|
},
|
|
}
|