mirror of
https://github.com/Maschell/hid_to_vpad.git
synced 2024-12-12 07:14:16 +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_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
|
||||
}
|
||||
#endif
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 4c496011da4937e9b518961f374d7f0693874bf1
|
||||
Subproject commit 4e38178c16f49e44900db0279494c8f1e605df54
|
@ -47,44 +47,3 @@ void SetupKernelCallback(void)
|
||||
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 "syscalls.h"
|
||||
|
||||
extern ReducedCosAppXmlInfo cosAppXmlInfoStruct;
|
||||
|
||||
void SetupKernelCallback(void);
|
||||
|
||||
void KernelRestoreDBATs(bat_table_t * table);
|
||||
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);
|
||||
extern ReducedCosAppXmlInfo cosAppXmlInfoStruct;
|
||||
|
||||
#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)
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
|
||||
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
|
||||
asm volatile("mfdbatu %0, 1" : "=r" (dbatu1));
|
||||
asm volatile("mfdbatl %0, 1" : "=r" (dbatl1));
|
||||
|
||||
// write our own DBATs into the array
|
||||
if( ((addr & 0xFFF00000) == 0xFFF00000) || ((src & 0xFFF00000) == 0xFFF00000) )
|
||||
{
|
||||
// setup kernel code access
|
||||
unsigned int dbatu = 0;
|
||||
unsigned int dbatl = 0;
|
||||
unsigned int target_dbatu0 = 0;
|
||||
unsigned int target_dbatl0 = 0;
|
||||
unsigned int target_dbatu1 = 0;
|
||||
unsigned int target_dbatl1 = 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 *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;
|
||||
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
|
||||
*/
|
||||
asm volatile("eieio; isync");
|
||||
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
|
||||
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
|
||||
asm volatile("mtdbatu 1, %0" : : "r" (dbatu1));
|
||||
@ -143,8 +162,35 @@ static void KernelWriteDBATs(bat_table_t * table)
|
||||
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 */
|
||||
static void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
|
||||
void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
|
||||
{
|
||||
asm volatile (
|
||||
"li 3,1\n"
|
||||
@ -195,9 +241,10 @@ void KernelSetupSyscalls(void)
|
||||
|
||||
//! write our hook to the
|
||||
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)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_
|
||||
#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 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
|
||||
}
|
||||
|
13
src/main.cpp
13
src/main.cpp
@ -4,6 +4,8 @@
|
||||
#include <malloc.h>
|
||||
#include "main.h"
|
||||
#include "version.h"
|
||||
#include "common/common.h"
|
||||
|
||||
#include "dynamic_libs/os_functions.h"
|
||||
#include "dynamic_libs/gx2_functions.h"
|
||||
#include "dynamic_libs/syshid_functions.h"
|
||||
@ -13,7 +15,8 @@
|
||||
#include "controller_patcher/controller_patcher.h"
|
||||
#include "controller_patcher/config_reader.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 "video/CursorDrawer.h"
|
||||
#include "utils/logger.h"
|
||||
@ -67,7 +70,7 @@ extern "C" int Menu_Main(void)
|
||||
//! Patching functions *
|
||||
//!*******************************************************************
|
||||
log_print("Patching functions\n");
|
||||
PatchMethodHooks();
|
||||
ApplyPatches();
|
||||
|
||||
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();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void ApplyPatches(){
|
||||
PatchInvidualMethodHooks(method_hooks_hid_controller, method_hooks_size_hid_controller, method_calls_hid_controller);
|
||||
}
|
||||
void deInit(){
|
||||
CursorDrawer::destroyInstance();
|
||||
RestoreInstructions();
|
||||
RestoreInvidualInstructions(method_hooks_hid_controller,method_hooks_size_hid_controller);
|
||||
deinit_config_controller();
|
||||
log_deinit();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ extern "C" {
|
||||
int Menu_Main(void);
|
||||
void SplashScreen(int time);
|
||||
void deInit(void);
|
||||
void ApplyPatches(void);
|
||||
|
||||
#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/>.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _FUNCTION_HOOKS_H_
|
||||
#define _FUNCTION_HOOKS_H_
|
||||
#ifndef _HID_CONTROLLER_FUNCTION_PATCHER_H
|
||||
#define _HID_CONTROLLER_FUNCTION_PATCHER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void PatchMethodHooks(void);
|
||||
void RestoreInstructions(void);
|
||||
unsigned int GetAddressOfFunction(const char * functionName,unsigned int library);
|
||||
int isDynamicFunction(unsigned int physicalAddress);
|
||||
#include "utils/function_patcher.h"
|
||||
|
||||
extern hooks_magic_t method_hooks_hid_controller[];
|
||||
extern u32 method_hooks_size_hid_controller;
|
||||
extern volatile unsigned int method_calls_hid_controller[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#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/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <gctypes.h>
|
||||
#include "function_hooks.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 "function_patcher.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 CODE_RW_BASE_OFFSET 0x00000000
|
||||
#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.
|
||||
* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok.
|
||||
* 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. 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. */
|
||||
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 my_instr_len = 6;
|
||||
@ -118,10 +52,10 @@ void PatchMethodHooks(void)
|
||||
log_printf("Patching %s ...",method_hooks[i].functionName);
|
||||
if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){
|
||||
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;
|
||||
}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;
|
||||
continue;
|
||||
}
|
||||
@ -134,7 +68,7 @@ void PatchMethodHooks(void)
|
||||
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
// copy instructions from real function.
|
||||
u32 offset_ptr = 0;
|
||||
for(offset_ptr = 0;offset_ptr<skip_instr*4;offset_ptr +=4){
|
||||
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++;
|
||||
}
|
||||
|
||||
SC0x25_KernelCopyData((u32)space, physical, 4);
|
||||
space++;
|
||||
|
||||
//Only works if skip_instr == 1
|
||||
if(skip_instr == 1){
|
||||
// fill the restore instruction section
|
||||
method_hooks[i].realAddr = real_addr;
|
||||
method_hooks[i].restoreInstruction = *(volatile unsigned int*)(physical);
|
||||
}else{
|
||||
method_hooks[i].restoreInstruction = *(space-1);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -199,63 +127,62 @@ void PatchMethodHooks(void)
|
||||
|
||||
//setting jump back
|
||||
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);
|
||||
|
||||
//restore my dbat stuff
|
||||
KernelRestoreDBATs(&my_dbat_table);
|
||||
|
||||
method_hooks[i].alreadyPatched = 1;
|
||||
|
||||
log_printf("done!\n");
|
||||
|
||||
}
|
||||
log_print("Done with patching all functions!\n");
|
||||
log_print("Done with patching given functions!\n");
|
||||
}
|
||||
|
||||
/* ****************************************************************** */
|
||||
/* RESTORE ORIGINAL INSTRUCTIONS */
|
||||
/* ****************************************************************** */
|
||||
void RestoreInstructions(void)
|
||||
void RestoreInvidualInstructions(hooks_magic_t method_hooks[],int hook_information_size)
|
||||
{
|
||||
bat_table_t table;
|
||||
log_printf("Restore functions!\n");
|
||||
int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t);
|
||||
log_printf("Restoring given functions!\n");
|
||||
int method_hooks_count = hook_information_size;
|
||||
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){
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr);
|
||||
if(!physical){
|
||||
log_printf("Error. Something is wrong with the physical address\n");
|
||||
log_printf("Something is wrong with the physical address\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isDynamicFunction(physical)){
|
||||
log_printf("Error. Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
|
||||
}else{
|
||||
KernelSetDBATs(&table);
|
||||
|
||||
*(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);
|
||||
if(isDynamicFunction(physical))
|
||||
{
|
||||
log_printf("Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
log_printf(" done\n");
|
||||
KernelRestoreDBATs(&table);
|
||||
}
|
||||
method_hooks[i].alreadyPatched = 0; // In case a
|
||||
}
|
||||
|
||||
KernelRestoreInstructions();
|
||||
log_print("Done with restoring all functions!\n");
|
||||
log_print("Done with restoring given functions!\n");
|
||||
}
|
||||
|
||||
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