mirror of
https://github.com/Maschell/hid_to_vpad.git
synced 2024-12-04 19:44:13 +01:00
Splitted the function patcher
- Now the actual patcher and the functions to be patched are splitted into seperate files. - Using now the same method to copy the kerneldata (no manual dbat setting setting needed anymore) - Some code cleanup
This commit is contained in:
parent
c702ac015f
commit
d2c4435a31
@ -51,18 +51,6 @@ extern "C" {
|
|||||||
#define EXIT_HBL_EXIT 0xFFFFFFFE
|
#define EXIT_HBL_EXIT 0xFFFFFFFE
|
||||||
#define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD
|
#define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD
|
||||||
|
|
||||||
#define RESTORE_INSTR_MAGIC 0xC001C0DE
|
|
||||||
#define RESTORE_INSTR_ADDR ((restore_instructions_t*)(MEM_BASE + 0x1600))
|
|
||||||
|
|
||||||
typedef struct _restore_instructions_t {
|
|
||||||
unsigned int magic;
|
|
||||||
unsigned int instr_count;
|
|
||||||
struct {
|
|
||||||
unsigned int addr;
|
|
||||||
unsigned int instr;
|
|
||||||
} data[0];
|
|
||||||
} restore_instructions_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 4c496011da4937e9b518961f374d7f0693874bf1
|
Subproject commit 4e38178c16f49e44900db0279494c8f1e605df54
|
@ -47,44 +47,3 @@ void SetupKernelCallback(void)
|
|||||||
KernelSetupSyscalls();
|
KernelSetupSyscalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelSetDBATs(bat_table_t * table)
|
|
||||||
{
|
|
||||||
KernelSetDBATsInternal(table,0xC0001FFF,0x30000012);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* physical_address is the physical address*/
|
|
||||||
void KernelSetDBATsForDynamicFuction(bat_table_t * table, unsigned int physical_address)
|
|
||||||
{
|
|
||||||
KernelSetDBATsInternal(table,(physical_address & 0xFFFC0000) | 0x0F,(physical_address & 0xFFFC0000) | 0x32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KernelSetDBATsInternal(bat_table_t * table, unsigned int high_address, unsigned int low_address)
|
|
||||||
{
|
|
||||||
SC0x36_KernelReadDBATs(table);
|
|
||||||
bat_table_t bat_table_copy = *table;
|
|
||||||
|
|
||||||
// try to use a free slot
|
|
||||||
int iUse;
|
|
||||||
for(iUse = 0; iUse < 7; iUse++)
|
|
||||||
{
|
|
||||||
// skip position 5 as it is our main DBAT for our code data
|
|
||||||
if(iUse == 5)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(bat_table_copy.bat[iUse].h == 0 || bat_table_copy.bat[iUse].l == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bat_table_copy.bat[iUse].h = high_address;
|
|
||||||
bat_table_copy.bat[iUse].l = low_address;
|
|
||||||
|
|
||||||
SC0x37_KernelWriteDBATs(&bat_table_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KernelRestoreDBATs(bat_table_t * table)
|
|
||||||
{
|
|
||||||
SC0x37_KernelWriteDBATs(table);
|
|
||||||
}
|
|
||||||
|
@ -8,14 +8,9 @@ extern "C" {
|
|||||||
#include "common/kernel_defs.h"
|
#include "common/kernel_defs.h"
|
||||||
#include "syscalls.h"
|
#include "syscalls.h"
|
||||||
|
|
||||||
extern ReducedCosAppXmlInfo cosAppXmlInfoStruct;
|
|
||||||
|
|
||||||
void SetupKernelCallback(void);
|
void SetupKernelCallback(void);
|
||||||
|
|
||||||
void KernelRestoreDBATs(bat_table_t * table);
|
extern ReducedCosAppXmlInfo cosAppXmlInfoStruct;
|
||||||
void KernelSetDBATs(bat_table_t * table);
|
|
||||||
void KernelSetDBATsForDynamicFuction(bat_table_t * table, unsigned int physical_address);
|
|
||||||
void KernelSetDBATsInternal(bat_table_t * table, unsigned int high_address, unsigned int low_address);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -12,64 +12,83 @@ static unsigned int origPrepareTitleInstr __attribute__((section(".data"))) = 0;
|
|||||||
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)
|
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Setup a DBAT access for our 0xC0800000 area and our 0xBC000000 area which hold our variables like GAME_LAUNCHED and our BSS/rodata section
|
* Setup a DBAT access with cache inhibited to write through and read directly from memory
|
||||||
*/
|
*/
|
||||||
register int dbatu0, dbatl0, dbatu1, dbatl1;
|
unsigned int dbatu0, dbatl0, dbatu1, dbatl1;
|
||||||
// save the original DBAT value
|
// save the original DBAT value
|
||||||
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
|
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
|
||||||
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
|
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
|
||||||
asm volatile("mfdbatu %0, 1" : "=r" (dbatu1));
|
asm volatile("mfdbatu %0, 1" : "=r" (dbatu1));
|
||||||
asm volatile("mfdbatl %0, 1" : "=r" (dbatl1));
|
asm volatile("mfdbatl %0, 1" : "=r" (dbatl1));
|
||||||
|
|
||||||
// write our own DBATs into the array
|
unsigned int target_dbatu0 = 0;
|
||||||
if( ((addr & 0xFFF00000) == 0xFFF00000) || ((src & 0xFFF00000) == 0xFFF00000) )
|
unsigned int target_dbatl0 = 0;
|
||||||
{
|
unsigned int target_dbatu1 = 0;
|
||||||
// setup kernel code access
|
unsigned int target_dbatl1 = 0;
|
||||||
unsigned int dbatu = 0;
|
|
||||||
unsigned int dbatl = 0;
|
|
||||||
|
|
||||||
if((src & 0xFFF00000) == 0xFFF00000) {
|
|
||||||
dbatu = (src & 0xFFF00000) | 0x02;
|
|
||||||
dbatl = (src & 0xFFF00000) | 0x32;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dbatu = (addr & 0xFFF00000) | 0x02;
|
|
||||||
dbatl = (addr & 0xFFF00000) | 0x32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ((addr & 0xFFF00000) != (dbatu0 & 0xFFF00000)) && ((src & 0xFFF00000) != (dbatu0 & 0xFFF00000)) )
|
|
||||||
{
|
|
||||||
asm volatile("mtdbatu 0, %0" : : "r" (dbatu));
|
|
||||||
asm volatile("mtdbatl 0, %0" : : "r" (dbatl));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm volatile("mtdbatu 1, %0" : : "r" (dbatu));
|
|
||||||
asm volatile("mtdbatl 1, %0" : : "r" (dbatl));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm volatile("mtdbatu 0, %0" : : "r" (0xC0001FFF));
|
|
||||||
asm volatile("mtdbatl 0, %0" : : "r" (0x30000012));
|
|
||||||
asm volatile("mtdbatu 1, %0" : : "r" (0xB0801FFF));
|
|
||||||
asm volatile("mtdbatl 1, %0" : : "r" (0x20800012));
|
|
||||||
}
|
|
||||||
asm volatile("eieio; isync");
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char *src_p = (unsigned char*)src;
|
|
||||||
unsigned char *dst_p = (unsigned char*)addr;
|
unsigned char *dst_p = (unsigned char*)addr;
|
||||||
|
unsigned char *src_p = (unsigned char*)src;
|
||||||
|
|
||||||
|
// we only need DBAT modification for addresses out of our own DBAT range
|
||||||
|
// as our own DBAT is available everywhere for user and supervisor
|
||||||
|
// since our own DBAT is on DBAT5 position we don't collide here
|
||||||
|
if(addr < 0x00800000 || addr >= 0x01000000)
|
||||||
|
{
|
||||||
|
target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F;
|
||||||
|
target_dbatl0 = (addr & 0xFFF00000) | 0x32;
|
||||||
|
asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0));
|
||||||
|
asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0));
|
||||||
|
dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000);
|
||||||
|
}
|
||||||
|
if(src < 0x00800000 || src >= 0x01000000)
|
||||||
|
{
|
||||||
|
target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F;
|
||||||
|
target_dbatl1 = (src & 0xFFF00000) | 0x32;
|
||||||
|
|
||||||
|
asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1));
|
||||||
|
asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1));
|
||||||
|
src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for(i = 0; i < len; i++)
|
for(i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
dst_p[i] = src_p[i];
|
// if we are on the edge to next chunk
|
||||||
|
if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000)))
|
||||||
|
{
|
||||||
|
target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F;
|
||||||
|
target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32;
|
||||||
|
dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000);
|
||||||
|
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0));
|
||||||
|
asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0));
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
}
|
||||||
|
if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000)))
|
||||||
|
{
|
||||||
|
target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F;
|
||||||
|
target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32;
|
||||||
|
src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000);
|
||||||
|
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1));
|
||||||
|
asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1));
|
||||||
|
asm volatile("eieio; isync");
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst_p = *src_p;
|
||||||
|
|
||||||
|
++dst_p;
|
||||||
|
++src_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore original DBAT value
|
* Restore original DBAT value
|
||||||
*/
|
*/
|
||||||
|
asm volatile("eieio; isync");
|
||||||
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
|
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
|
||||||
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
|
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
|
||||||
asm volatile("mtdbatu 1, %0" : : "r" (dbatu1));
|
asm volatile("mtdbatu 1, %0" : : "r" (dbatu1));
|
||||||
@ -143,8 +162,35 @@ static void KernelWriteDBATs(bat_table_t * table)
|
|||||||
asm volatile("eieio; isync");
|
asm volatile("eieio; isync");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read a 32-bit word with kernel permissions */
|
||||||
|
uint32_t __attribute__ ((noinline)) kern_read(const void *addr)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
asm volatile (
|
||||||
|
"li 3,1\n"
|
||||||
|
"li 4,0\n"
|
||||||
|
"li 5,0\n"
|
||||||
|
"li 6,0\n"
|
||||||
|
"li 7,0\n"
|
||||||
|
"lis 8,1\n"
|
||||||
|
"mr 9,%1\n"
|
||||||
|
"li 0,0x3400\n"
|
||||||
|
"mr %0,1\n"
|
||||||
|
"sc\n"
|
||||||
|
"nop\n"
|
||||||
|
"mr 1,%0\n"
|
||||||
|
"mr %0,3\n"
|
||||||
|
: "=r"(result)
|
||||||
|
: "b"(addr)
|
||||||
|
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
|
||||||
|
"11", "12"
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write a 32-bit word with kernel permissions */
|
/* Write a 32-bit word with kernel permissions */
|
||||||
static void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
|
void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
|
||||||
{
|
{
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"li 3,1\n"
|
"li 3,1\n"
|
||||||
@ -195,9 +241,10 @@ void KernelSetupSyscalls(void)
|
|||||||
|
|
||||||
//! write our hook to the
|
//! write our hook to the
|
||||||
u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003;
|
u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003;
|
||||||
|
DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook));
|
||||||
|
|
||||||
SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4);
|
SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4);
|
||||||
SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&addr_my_PrepareTitle_hook, 4);
|
SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#ifndef __SYSCALLS_H_
|
#ifndef __SYSCALLS_H_
|
||||||
#define __SYSCALLS_H_
|
#define __SYSCALLS_H_
|
||||||
|
|
||||||
@ -15,6 +16,8 @@ void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len
|
|||||||
void SC0x36_KernelReadDBATs(bat_table_t * table);
|
void SC0x36_KernelReadDBATs(bat_table_t * table);
|
||||||
void SC0x37_KernelWriteDBATs(bat_table_t * table);
|
void SC0x37_KernelWriteDBATs(bat_table_t * table);
|
||||||
|
|
||||||
|
uint32_t __attribute__ ((noinline)) kern_read(const void *addr);
|
||||||
|
void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
13
src/main.cpp
13
src/main.cpp
@ -4,6 +4,8 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "common/common.h"
|
||||||
|
|
||||||
#include "dynamic_libs/os_functions.h"
|
#include "dynamic_libs/os_functions.h"
|
||||||
#include "dynamic_libs/gx2_functions.h"
|
#include "dynamic_libs/gx2_functions.h"
|
||||||
#include "dynamic_libs/syshid_functions.h"
|
#include "dynamic_libs/syshid_functions.h"
|
||||||
@ -13,7 +15,8 @@
|
|||||||
#include "controller_patcher/controller_patcher.h"
|
#include "controller_patcher/controller_patcher.h"
|
||||||
#include "controller_patcher/config_reader.h"
|
#include "controller_patcher/config_reader.h"
|
||||||
#include "controller_patcher/cp_retain_vars.h"
|
#include "controller_patcher/cp_retain_vars.h"
|
||||||
#include "patcher/function_hooks.h"
|
#include "utils/function_patcher.h"
|
||||||
|
#include "patcher/hid_controller_patcher.h"
|
||||||
#include "kernel/kernel_functions.h"
|
#include "kernel/kernel_functions.h"
|
||||||
#include "video/CursorDrawer.h"
|
#include "video/CursorDrawer.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
@ -67,7 +70,7 @@ extern "C" int Menu_Main(void)
|
|||||||
//! Patching functions *
|
//! Patching functions *
|
||||||
//!*******************************************************************
|
//!*******************************************************************
|
||||||
log_print("Patching functions\n");
|
log_print("Patching functions\n");
|
||||||
PatchMethodHooks();
|
ApplyPatches();
|
||||||
|
|
||||||
if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0)
|
if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0)
|
||||||
{
|
{
|
||||||
@ -83,10 +86,12 @@ extern "C" int Menu_Main(void)
|
|||||||
deInit();
|
deInit();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
void ApplyPatches(){
|
||||||
|
PatchInvidualMethodHooks(method_hooks_hid_controller, method_hooks_size_hid_controller, method_calls_hid_controller);
|
||||||
|
}
|
||||||
void deInit(){
|
void deInit(){
|
||||||
CursorDrawer::destroyInstance();
|
CursorDrawer::destroyInstance();
|
||||||
RestoreInstructions();
|
RestoreInvidualInstructions(method_hooks_hid_controller,method_hooks_size_hid_controller);
|
||||||
deinit_config_controller();
|
deinit_config_controller();
|
||||||
log_deinit();
|
log_deinit();
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ extern "C" {
|
|||||||
int Menu_Main(void);
|
int Menu_Main(void);
|
||||||
void SplashScreen(int time);
|
void SplashScreen(int time);
|
||||||
void deInit(void);
|
void deInit(void);
|
||||||
|
void ApplyPatches(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
60
src/patcher/hid_controller_function_patcher.cpp
Normal file
60
src/patcher/hid_controller_function_patcher.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "hid_controller_patcher.h"
|
||||||
|
#include "video/CursorDrawer.h"
|
||||||
|
#include "controller_patcher/cp_retain_vars.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
|
||||||
|
DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target){
|
||||||
|
if(gHIDCurrentDevice & gHID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {
|
||||||
|
CursorDrawer::draw(gHID_Mouse.pad_data[0].data[0].X, gHID_Mouse.pad_data[0].data[0].Y);
|
||||||
|
}
|
||||||
|
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL(void, _Exit, void){
|
||||||
|
CursorDrawer::destroyInstance();
|
||||||
|
real__Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
|
||||||
|
int result = real_VPADRead(chan, buffer, buffer_size, error);
|
||||||
|
|
||||||
|
if(gHIDAttached){
|
||||||
|
setControllerDataFromHID(buffer,HID_ALL_CONNECTED_DEVICES);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gButtonRemappingConfigDone){
|
||||||
|
buttonRemapping(buffer);
|
||||||
|
if (HID_DEBUG) printButtons(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks_magic_t method_hooks_hid_controller[] __attribute__((section(".data"))) = {
|
||||||
|
MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION),
|
||||||
|
MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION),
|
||||||
|
MAKE_MAGIC(_Exit, LIB_CORE_INIT, STATIC_FUNCTION),
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 method_hooks_size_hid_controller __attribute__((section(".data"))) = sizeof(method_hooks_hid_controller) / sizeof(hooks_magic_t);
|
||||||
|
|
||||||
|
//! buffer to store our instructions needed for our replacements
|
||||||
|
volatile unsigned int method_calls_hid_controller[sizeof(method_hooks_hid_controller) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data")));
|
||||||
|
|
@ -15,20 +15,21 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef _FUNCTION_HOOKS_H_
|
#ifndef _HID_CONTROLLER_FUNCTION_PATCHER_H
|
||||||
#define _FUNCTION_HOOKS_H_
|
#define _HID_CONTROLLER_FUNCTION_PATCHER_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void PatchMethodHooks(void);
|
#include "utils/function_patcher.h"
|
||||||
void RestoreInstructions(void);
|
|
||||||
unsigned int GetAddressOfFunction(const char * functionName,unsigned int library);
|
extern hooks_magic_t method_hooks_hid_controller[];
|
||||||
int isDynamicFunction(unsigned int physicalAddress);
|
extern u32 method_hooks_size_hid_controller;
|
||||||
|
extern volatile unsigned int method_calls_hid_controller[];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _FS_H */
|
#endif /* _HID_CONTROLLER_FUNCTION_PATCHER_H */
|
@ -15,99 +15,33 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gctypes.h>
|
#include <gctypes.h>
|
||||||
#include "function_hooks.h"
|
#include "function_patcher.h"
|
||||||
#include "controller_patcher/cp_retain_vars.h"
|
|
||||||
#include "dynamic_libs/aoc_functions.h"
|
|
||||||
#include "dynamic_libs/ax_functions.h"
|
|
||||||
#include "dynamic_libs/fs_functions.h"
|
|
||||||
#include "dynamic_libs/gx2_functions.h"
|
|
||||||
#include "dynamic_libs/os_functions.h"
|
|
||||||
#include "dynamic_libs/padscore_functions.h"
|
|
||||||
#include "dynamic_libs/socket_functions.h"
|
|
||||||
#include "dynamic_libs/sys_functions.h"
|
|
||||||
#include "dynamic_libs/vpad_functions.h"
|
|
||||||
#include "dynamic_libs/acp_functions.h"
|
|
||||||
#include "dynamic_libs/syshid_functions.h"
|
|
||||||
#include "kernel/kernel_functions.h"
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "video/CursorDrawer.h"
|
#include "common/kernel_defs.h"
|
||||||
|
#include "kernel/kernel_functions.h"
|
||||||
|
|
||||||
#define LIB_CODE_RW_BASE_OFFSET 0xC1000000
|
#define LIB_CODE_RW_BASE_OFFSET 0xC1000000
|
||||||
#define CODE_RW_BASE_OFFSET 0x00000000
|
#define CODE_RW_BASE_OFFSET 0x00000000
|
||||||
#define DEBUG_LOG_DYN 0
|
#define DEBUG_LOG_DYN 0
|
||||||
|
|
||||||
#define USE_EXTRA_LOG_FUNCTIONS 0
|
|
||||||
|
|
||||||
#define DECL(res, name, ...) \
|
|
||||||
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \
|
|
||||||
res my_ ## name(__VA_ARGS__)
|
|
||||||
|
|
||||||
DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target){
|
|
||||||
if(gHIDCurrentDevice & gHID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {
|
|
||||||
CursorDrawer::draw(gHID_Mouse.pad_data[0].data[0].X, gHID_Mouse.pad_data[0].data[0].Y);
|
|
||||||
}
|
|
||||||
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL(void, _Exit, void){
|
|
||||||
CursorDrawer::destroyInstance();
|
|
||||||
real__Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
|
|
||||||
int result = real_VPADRead(chan, buffer, buffer_size, error);
|
|
||||||
if(gHIDAttached){
|
|
||||||
setControllerDataFromHID(buffer,HID_ALL_CONNECTED_DEVICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(gButtonRemappingConfigDone){
|
|
||||||
buttonRemapping(buffer);
|
|
||||||
if (HID_DEBUG) printButtons(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* *****************************************************************************
|
|
||||||
* Creates function pointer array
|
|
||||||
* ****************************************************************************/
|
|
||||||
#define MAKE_MAGIC(x, lib,functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0}
|
|
||||||
|
|
||||||
static struct hooks_magic_t {
|
|
||||||
const unsigned int replaceAddr;
|
|
||||||
const unsigned int replaceCall;
|
|
||||||
const unsigned int library;
|
|
||||||
const char functionName[50];
|
|
||||||
unsigned int realAddr;
|
|
||||||
unsigned int restoreInstruction;
|
|
||||||
unsigned char functionType;
|
|
||||||
unsigned char alreadyPatched;
|
|
||||||
} method_hooks[] = {
|
|
||||||
// Common FS functions
|
|
||||||
MAKE_MAGIC(VPADRead, LIB_VPAD,STATIC_FUNCTION),
|
|
||||||
MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2,STATIC_FUNCTION),
|
|
||||||
MAKE_MAGIC(_Exit, LIB_CORE_INIT,STATIC_FUNCTION),
|
|
||||||
};
|
|
||||||
|
|
||||||
//! buffer to store our 7 instructions needed for our replacements
|
|
||||||
//! the code will be placed in the address of that buffer - CODE_RW_BASE_OFFSET
|
|
||||||
//! avoid this buffer to be placed in BSS and reset on start up
|
|
||||||
volatile unsigned int dynamic_method_calls[sizeof(method_hooks) / sizeof(struct hooks_magic_t) * 7] __attribute__((section(".data")));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic.
|
* Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic.
|
||||||
* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok.
|
* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. Orignal code by Chadderz.
|
||||||
*/
|
*/
|
||||||
void PatchMethodHooks(void)
|
void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int hook_information_size, volatile unsigned int dynamic_method_calls[])
|
||||||
{
|
{
|
||||||
|
log_printf("Patching %d given functions\n",hook_information_size);
|
||||||
/* Patch branches to it. */
|
/* Patch branches to it. */
|
||||||
volatile unsigned int *space = &dynamic_method_calls[0];
|
volatile unsigned int *space = &dynamic_method_calls[0];
|
||||||
|
|
||||||
int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t);
|
int method_hooks_count = hook_information_size;
|
||||||
|
|
||||||
u32 skip_instr = 1;
|
u32 skip_instr = 1;
|
||||||
u32 my_instr_len = 6;
|
u32 my_instr_len = 6;
|
||||||
@ -118,10 +52,10 @@ void PatchMethodHooks(void)
|
|||||||
log_printf("Patching %s ...",method_hooks[i].functionName);
|
log_printf("Patching %s ...",method_hooks[i].functionName);
|
||||||
if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){
|
if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){
|
||||||
if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){
|
if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){
|
||||||
log_printf(" The function %s is a dynamic function. Please fix that <3 ... ", method_hooks[i].functionName);
|
log_printf("The function %s is a dynamic function. Please fix that <3\n", method_hooks[i].functionName);
|
||||||
method_hooks[i].functionType = DYNAMIC_FUNCTION;
|
method_hooks[i].functionType = DYNAMIC_FUNCTION;
|
||||||
}else{
|
}else{
|
||||||
log_printf(" skipped. Its already patched\n", method_hooks[i].functionName);
|
log_printf("Skipping %s, its already patched\n", method_hooks[i].functionName);
|
||||||
space += instr_len;
|
space += instr_len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -134,7 +68,7 @@ void PatchMethodHooks(void)
|
|||||||
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
|
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
|
||||||
|
|
||||||
if(!real_addr){
|
if(!real_addr){
|
||||||
log_printf("Error. OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
|
log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
|
||||||
space += instr_len;
|
space += instr_len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -150,27 +84,21 @@ void PatchMethodHooks(void)
|
|||||||
|
|
||||||
if(DEBUG_LOG_DYN)log_printf("%s physical is located at %08X!\n", method_hooks[i].functionName,physical);
|
if(DEBUG_LOG_DYN)log_printf("%s physical is located at %08X!\n", method_hooks[i].functionName,physical);
|
||||||
|
|
||||||
bat_table_t my_dbat_table;
|
|
||||||
if(DEBUG_LOG_DYN)log_printf("Setting up DBAT\n");
|
|
||||||
KernelSetDBATsForDynamicFuction(&my_dbat_table,physical);
|
|
||||||
|
|
||||||
//log_printf("Setting call_addr to %08X\n",(unsigned int)(space) - CODE_RW_BASE_OFFSET);
|
|
||||||
*(volatile unsigned int *)(call_addr) = (unsigned int)(space) - CODE_RW_BASE_OFFSET;
|
*(volatile unsigned int *)(call_addr) = (unsigned int)(space) - CODE_RW_BASE_OFFSET;
|
||||||
|
|
||||||
// copy instructions from real function.
|
|
||||||
u32 offset_ptr = 0;
|
SC0x25_KernelCopyData((u32)space, physical, 4);
|
||||||
for(offset_ptr = 0;offset_ptr<skip_instr*4;offset_ptr +=4){
|
space++;
|
||||||
if(DEBUG_LOG_DYN)log_printf("(real_)%08X = %08X\n",space,*(volatile unsigned int*)(physical+offset_ptr));
|
|
||||||
*space = *(volatile unsigned int*)(physical+offset_ptr);
|
|
||||||
space++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Only works if skip_instr == 1
|
//Only works if skip_instr == 1
|
||||||
if(skip_instr == 1){
|
if(skip_instr == 1){
|
||||||
// fill the restore instruction section
|
// fill the restore instruction section
|
||||||
method_hooks[i].realAddr = real_addr;
|
method_hooks[i].realAddr = real_addr;
|
||||||
method_hooks[i].restoreInstruction = *(volatile unsigned int*)(physical);
|
method_hooks[i].restoreInstruction = *(space-1);
|
||||||
}else{
|
if(DEBUG_LOG_DYN)log_printf("method_hooks[i].realAddr = %08X!\n", method_hooks[i].realAddr);
|
||||||
|
if(DEBUG_LOG_DYN)log_printf("method_hooks[i].restoreInstruction = %08X!\n",method_hooks[i].restoreInstruction) ;
|
||||||
|
}
|
||||||
|
else{
|
||||||
log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName);
|
log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,63 +127,62 @@ void PatchMethodHooks(void)
|
|||||||
|
|
||||||
//setting jump back
|
//setting jump back
|
||||||
unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc);
|
unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc);
|
||||||
*(volatile unsigned int *)(physical) = replace_instr;
|
DCFlushRange(&replace_instr, 4);
|
||||||
|
|
||||||
|
SC0x25_KernelCopyData(physical, (u32)OSEffectiveToPhysical(&replace_instr), 4);
|
||||||
ICInvalidateRange((void*)(real_addr), 4);
|
ICInvalidateRange((void*)(real_addr), 4);
|
||||||
|
|
||||||
//restore my dbat stuff
|
|
||||||
KernelRestoreDBATs(&my_dbat_table);
|
|
||||||
|
|
||||||
method_hooks[i].alreadyPatched = 1;
|
method_hooks[i].alreadyPatched = 1;
|
||||||
|
|
||||||
log_printf("done!\n");
|
log_printf("done!\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
log_print("Done with patching all functions!\n");
|
log_print("Done with patching given functions!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ****************************************************************** */
|
/* ****************************************************************** */
|
||||||
/* RESTORE ORIGINAL INSTRUCTIONS */
|
/* RESTORE ORIGINAL INSTRUCTIONS */
|
||||||
/* ****************************************************************** */
|
/* ****************************************************************** */
|
||||||
void RestoreInstructions(void)
|
void RestoreInvidualInstructions(hooks_magic_t method_hooks[],int hook_information_size)
|
||||||
{
|
{
|
||||||
bat_table_t table;
|
log_printf("Restoring given functions!\n");
|
||||||
log_printf("Restore functions!\n");
|
int method_hooks_count = hook_information_size;
|
||||||
int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t);
|
|
||||||
for(int i = 0; i < method_hooks_count; i++)
|
for(int i = 0; i < method_hooks_count; i++)
|
||||||
{
|
{
|
||||||
log_printf("Restoring %s ...",method_hooks[i].functionName);
|
|
||||||
if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){
|
if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){
|
||||||
log_printf("Error. I dont have the information for the restore =( skip\n");
|
log_printf("I dont have the information for the restore =( skip\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
|
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
|
||||||
|
|
||||||
if(!real_addr){
|
if(!real_addr){
|
||||||
//log_printf("Error. OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
|
log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr);
|
u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr);
|
||||||
if(!physical){
|
if(!physical){
|
||||||
log_printf("Error. Something is wrong with the physical address\n");
|
log_printf("Something is wrong with the physical address\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isDynamicFunction(physical)){
|
if(isDynamicFunction(physical))
|
||||||
log_printf("Error. Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
|
{
|
||||||
}else{
|
log_printf("Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
|
||||||
KernelSetDBATs(&table);
|
}
|
||||||
|
else
|
||||||
*(volatile unsigned int *)(LIB_CODE_RW_BASE_OFFSET + method_hooks[i].realAddr) = method_hooks[i].restoreInstruction;
|
{
|
||||||
DCFlushRange((void*)(LIB_CODE_RW_BASE_OFFSET + method_hooks[i].realAddr), 4);
|
physical = (u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr); //When its an static function, we need to use the old location
|
||||||
|
if(DEBUG_LOG_DYN)log_printf("Restoring %08X to %08X\n",(u32)method_hooks[i].restoreInstruction,physical);
|
||||||
|
SC0x25_KernelCopyData(physical,(u32)&method_hooks[i].restoreInstruction , 4);
|
||||||
|
if(DEBUG_LOG_DYN)log_printf("ICInvalidateRange %08X\n",(void*)method_hooks[i].realAddr);
|
||||||
ICInvalidateRange((void*)method_hooks[i].realAddr, 4);
|
ICInvalidateRange((void*)method_hooks[i].realAddr, 4);
|
||||||
log_printf(" done\n");
|
|
||||||
KernelRestoreDBATs(&table);
|
|
||||||
}
|
}
|
||||||
method_hooks[i].alreadyPatched = 0; // In case a
|
method_hooks[i].alreadyPatched = 0; // In case a
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelRestoreInstructions();
|
KernelRestoreInstructions();
|
||||||
log_print("Done with restoring all functions!\n");
|
log_print("Done with restoring given functions!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int isDynamicFunction(unsigned int physicalAddress){
|
int isDynamicFunction(unsigned int physicalAddress){
|
70
src/utils/function_patcher.h
Normal file
70
src/utils/function_patcher.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2016 Maschell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FUNCTION_HOOKS_H_
|
||||||
|
#define _FUNCTION_HOOKS_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gctypes.h>
|
||||||
|
#include "common/common.h"
|
||||||
|
#include "dynamic_libs/aoc_functions.h"
|
||||||
|
#include "dynamic_libs/ax_functions.h"
|
||||||
|
#include "dynamic_libs/fs_functions.h"
|
||||||
|
#include "dynamic_libs/gx2_functions.h"
|
||||||
|
#include "dynamic_libs/os_functions.h"
|
||||||
|
#include "dynamic_libs/padscore_functions.h"
|
||||||
|
#include "dynamic_libs/socket_functions.h"
|
||||||
|
#include "dynamic_libs/sys_functions.h"
|
||||||
|
#include "dynamic_libs/vpad_functions.h"
|
||||||
|
#include "dynamic_libs/acp_functions.h"
|
||||||
|
#include "dynamic_libs/syshid_functions.h"
|
||||||
|
|
||||||
|
//Orignal code by Chadderz.
|
||||||
|
#define DECL(res, name, ...) \
|
||||||
|
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \
|
||||||
|
res my_ ## name(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define FUNCTION_PATCHER_METHOD_STORE_SIZE 7
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const unsigned int replaceAddr;
|
||||||
|
const unsigned int replaceCall;
|
||||||
|
const unsigned int library;
|
||||||
|
const char functionName[50];
|
||||||
|
unsigned int realAddr;
|
||||||
|
unsigned int restoreInstruction;
|
||||||
|
unsigned char functionType;
|
||||||
|
unsigned char alreadyPatched;
|
||||||
|
} hooks_magic_t;
|
||||||
|
|
||||||
|
void PatchInvidualMethodHooks(hooks_magic_t hook_information[],int hook_information_size, volatile unsigned int dynamic_method_calls[]);
|
||||||
|
void RestoreInvidualInstructions(hooks_magic_t hook_information[],int hook_information_size);
|
||||||
|
unsigned int GetAddressOfFunction(const char * functionName,unsigned int library);
|
||||||
|
int isDynamicFunction(unsigned int physicalAddress);
|
||||||
|
|
||||||
|
//Orignal code by Chadderz.
|
||||||
|
#define MAKE_MAGIC(x, lib,functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FS_H */
|
Loading…
Reference in New Issue
Block a user