mirror of
https://wiilab.wiimart.org/wiimart/WiiMart-Patcher
synced 2025-09-03 20:11:19 +02:00
Add vWii support
However, this appears to be broken on a vWii itself, and needs some tweaks. These will be determined at a later date. However, the changes are extremely large, so this commit is being made.
This commit is contained in:
parent
c7bb2cc646
commit
d721238346
@ -4,30 +4,53 @@ package main
|
||||
// See docs/patch_overwrite_ios.md for more information.
|
||||
var OverwriteIOSPatch = PatchSet{
|
||||
Patch{
|
||||
Name: "Clear extraneous textinput::EventObserver functions",
|
||||
AtOffset: 20336,
|
||||
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,
|
||||
padding, padding, padding,
|
||||
// Function: textinput::EventObserver::onCommand
|
||||
BLR(),
|
||||
padding,
|
||||
padding,
|
||||
padding,
|
||||
padding, padding, padding,
|
||||
// Function: textinput::EventObserver::onInput
|
||||
BLR(),
|
||||
padding,
|
||||
padding,
|
||||
padding,
|
||||
padding, padding, padding,
|
||||
}.toBytes(),
|
||||
|
||||
// We wish to clear extraneous blrs so that our custom overwriteIOSMemory
|
||||
// function does not somehow conflict. We only preserve onSE.
|
||||
After: emptyBytes(48),
|
||||
// function does not somehow conflict.
|
||||
// We only preserve onSE, which is this immediate BLR.
|
||||
After: append(Instructions{
|
||||
BLR(),
|
||||
}.toBytes(), emptyBytes(108)...),
|
||||
},
|
||||
Patch{
|
||||
Name: "Repair textinput::EventObserver vtable",
|
||||
@ -38,13 +61,19 @@ var OverwriteIOSPatch = PatchSet{
|
||||
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, 0x44, 0x20,
|
||||
0x80, 0x01, 0x44, 0x20,
|
||||
0x80, 0x01, 0x44, 0x20,
|
||||
0x80, 0x01, 0x44, 0x20,
|
||||
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,
|
||||
},
|
||||
},
|
||||
Patch{
|
||||
@ -52,55 +81,154 @@ var OverwriteIOSPatch = PatchSet{
|
||||
AtOffset: 3097888,
|
||||
|
||||
Before: []byte{
|
||||
0x80, 0x01, 0x44, 0x50, // onSE
|
||||
0x80, 0x01, 0x84, 0xE0, // ipl::keyboard::EventObserver::onCommand - not patched
|
||||
0x80, 0x01, 0x44, 0x30, // onCommand
|
||||
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, 0x44, 0x20, // doNothing
|
||||
0x80, 0x01, 0x84, 0xE0, // ipl::keyboard::EventObserver::onCommand - not patched
|
||||
0x80, 0x01, 0x44, 0x20, // doNothing
|
||||
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
|
||||
},
|
||||
},
|
||||
Patch{
|
||||
Name: "Insert patch table",
|
||||
AtOffset: 3205088,
|
||||
|
||||
Before: emptyBytes(40),
|
||||
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 0xd3a73ad4.
|
||||
0xd3, 0xa7, 0x3a, 0xd4,
|
||||
// 0x20004770 is equivalent in ARM THUMB to:
|
||||
// mov r0, #0x0
|
||||
// bx lr
|
||||
0x20, 0x00, 0x47, 0x70,
|
||||
|
||||
//////////////////////////
|
||||
// PATCH #3 - vWii only //
|
||||
//////////////////////////
|
||||
// Patch location:
|
||||
// We want to write at 0x20102100, aka "ES_AddTicket".
|
||||
// (To us, this is mapped at 0x939f2100.)
|
||||
0x93, 0x9f, 0x21, 0x00,
|
||||
// The original code has a few conditionals preventing system title usage.
|
||||
// We simply branch off past these.
|
||||
// 0x681a2a01 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, 0x2a, 0x01,
|
||||
|
||||
//////////////////////////
|
||||
// PATCH #4 - vWii only //
|
||||
//////////////////////////
|
||||
// We want to write to 0x20103240, aka "ES_AddTitleStart".
|
||||
// (For us, this is 0x939f3240.)
|
||||
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
|
||||
// mov r8, r8 ; recommended THUMB nop
|
||||
0xe0, 0x08, 0x46, 0xc0,
|
||||
|
||||
//////////////////////////
|
||||
// PATCH #5 - vWii only //
|
||||
//////////////////////////
|
||||
// Lastly, we want to write to 0x20103564, aka "ES_AddContentStart".
|
||||
// (We utilize memory cache and write at 0x939f3564.)
|
||||
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
|
||||
// mov r8, r8 ; recommended THUMB nop
|
||||
0xe0, 0x0c, 0x46, 0xc0,
|
||||
},
|
||||
},
|
||||
Patch{
|
||||
Name: "Insert overwriteIOSMemory",
|
||||
AtOffset: 20328,
|
||||
AtOffset: 20276,
|
||||
|
||||
// This area should be cleared.
|
||||
Before: emptyBytes(48),
|
||||
// This area should be cleared in the patch
|
||||
// "Clear extraneous functions".
|
||||
Before: emptyBytes(108),
|
||||
After: Instructions{
|
||||
// We want r9 to store the location of MEM_PROT at 0x0d8b420a.
|
||||
// For us, this is mapped to 0xcd8b420a.
|
||||
LIS(R9, 0xcd8b),
|
||||
ORI(R9, R9, 0x420a),
|
||||
// Our patch table is available at 0x803126e0.
|
||||
LIS(R8, 0x8031),
|
||||
ORI(R8, R8, 0x26e0),
|
||||
|
||||
// We want to write 0x2 and unlock everything.
|
||||
LI(R10, 0x02),
|
||||
|
||||
// Write!
|
||||
// Load address/value pair for MEM_PROT
|
||||
LWZ(R9, 0x0, R8),
|
||||
LWZ(R10, 0x4, R8),
|
||||
// Apply lower half
|
||||
STH(R10, 0x0, R9),
|
||||
// Flush memory
|
||||
EIEIO(),
|
||||
|
||||
// Location of IOSC_VerifyPublicKeySign
|
||||
LIS(R9, 0xd3a7),
|
||||
ORI(R9, R9, 0x3ad4),
|
||||
// Load address/value pair for IOSC_VerifyPublicKeySign
|
||||
LWZ(R9, 0x8, R8),
|
||||
LWZ(R10, 0xc, R8),
|
||||
|
||||
// Write our custom THUMB.
|
||||
// 0x20004770 is equivalent to:
|
||||
// mov r0, #0x0
|
||||
// bx lr
|
||||
LIS(R10, 0x2000),
|
||||
ORI(R10, R10, 0x4770),
|
||||
|
||||
// Write!
|
||||
// Apply!
|
||||
STW(R10, 0x0, R9),
|
||||
// Possibly clear cache
|
||||
// TODO(spotlightishere): Is this needed?
|
||||
// dcbi 0, r10
|
||||
Instruction{0x7C, 0x00, 0x53, 0xAC},
|
||||
// And finish.
|
||||
|
||||
// The remainder of our patches will determine if we are on a Wii U.
|
||||
// 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.)
|
||||
LIS(R9, 0xcd80),
|
||||
ORI(R9, R9, 0x05a0),
|
||||
LWZ(R9, 0, R9),
|
||||
|
||||
// Shift this value 16 bits to the right
|
||||
// in order to compare its higher value.
|
||||
// srawi r9, r9, 16
|
||||
Instruction{0x7d, 0x29, 0x86, 0x70},
|
||||
CMPWI(R9, 0xCAFE),
|
||||
// If we're not a Wii U, carry on until the end.
|
||||
// bne (last blr)
|
||||
ORI(R0, R0, 0),
|
||||
//Instruction{0x40, 0x82, 0x00, 0x28},
|
||||
|
||||
// Apply ES_AddTicket
|
||||
LWZ(R9, 0x10, R8),
|
||||
LWZ(R10, 0x14, R8),
|
||||
STW(R10, 0x0, R9),
|
||||
|
||||
// Apply ES_AddTicket
|
||||
LWZ(R9, 0x18, R8),
|
||||
LWZ(R10, 0x1c, R8),
|
||||
STW(R10, 0x0, R9),
|
||||
|
||||
// Apply ES_AddTicket
|
||||
LWZ(R9, 0x20, R8),
|
||||
LWZ(R10, 0x24, R8),
|
||||
STW(R10, 0x0, R9),
|
||||
|
||||
// We're finished patching!
|
||||
BLR(),
|
||||
|
||||
BLR(), BLR(), BLR(),
|
||||
}.toBytes(),
|
||||
},
|
||||
Patch{
|
||||
@ -118,7 +246,7 @@ var OverwriteIOSPatch = PatchSet{
|
||||
After: Instructions{
|
||||
LWZ(R0, 0x14, R1),
|
||||
// bl overwriteIOSMemory @ 0x80014428
|
||||
Instruction{0x4B, 0xDB, 0xB1, 0x01},
|
||||
Instruction{0x4b, 0xdb, 0xb0, 0xcd},
|
||||
MTSPR(),
|
||||
ADDI(R1, R1, 0x10),
|
||||
BLR(),
|
||||
|
@ -35,6 +35,12 @@ func BLR() Instruction {
|
||||
return [4]byte{0x4E, 0x80, 0x00, 0x20}
|
||||
}
|
||||
|
||||
// CRXOR represents a common use of CRXOR on PowerPC.
|
||||
// TODO: actually implement
|
||||
func CRXOR() Instruction {
|
||||
return [4]byte{0x4c, 0xc6, 0x31, 0x82}
|
||||
}
|
||||
|
||||
// ADDI represents the addi PowerPC instruction.
|
||||
func ADDI(rT Register, rA Register, value uint16) Instruction {
|
||||
return EncodeInstrDForm(14, rT, rA, value)
|
||||
@ -46,6 +52,7 @@ func LI(rT Register, value uint16) Instruction {
|
||||
}
|
||||
|
||||
// SUBI represents the subi mnemonic on PowerPC.
|
||||
// TODO: handle negative values properly?
|
||||
func SUBI(rT Register, rA Register, value uint16) Instruction {
|
||||
return ADDI(rT, 0, -value)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user