Skip to content

Commit

Permalink
real hooking
Browse files Browse the repository at this point in the history
  • Loading branch information
Kethen committed Apr 28, 2024
1 parent a17ab0e commit c5c8f8b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 59 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ PRX_EXPORTS = exports.exp
# use kernel "libc"
USE_KERNEL_LIBS = 1

# use built-in libc to supply sprintf for ppsspp and atoi in general
LIBS = -lpspsystemctrl_kernel

PSP_FW_VERSION=661

PSPSDK = $(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build_prx.mak
124 changes: 66 additions & 58 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ static int logfd = -1;
} \
char _log_buf[128]; \
int _log_len = sprintf(_log_buf, __VA_ARGS__); \
_log_buf[_log_len] = '\n'; \
_log_len++; \
if(logfd >= 0){ \
if(_log_len != 0){ \
sceIoWrite(logfd, _log_buf, _log_len); \
Expand Down Expand Up @@ -117,9 +119,9 @@ u32 offset_populate_car_analog_control = 0;

#define HIJACK_FUNCTION(a, f, ptr) \
{ \
LOG("hijacking function at 0x%lx with 0x%lx\n", (u32)a, (u32)f); \
LOG("hijacking function at 0x%lx with 0x%lx", (u32)a, (u32)f); \
u32 _func_ = (u32)a; \
LOG("original instructions: 0x%lx 0x%lx\n", _lw(_func_), _lw(_func_ + 4)); \
LOG("original instructions: 0x%lx 0x%lx", _lw(_func_), _lw(_func_ + 4)); \
u32 ff = (u32)f; \
if(!is_emulator){ \
ff = MakeSyscallStub(f); \
Expand All @@ -141,61 +143,61 @@ static int get_disc_id_version(char *id_out, char *version_out){
int version_found = 0;

if(fd < 0){
LOG("cannot open %s for reading\n", sfo_path);
LOG("cannot open %s for reading", sfo_path);
return -1;
}

sceIoLseek(fd, 0x08, PSP_SEEK_SET);
unsigned char buf[4];
if(sceIoRead(fd, &buf, 4) != 4){
sceIoClose(fd);
LOG("failed reading key table start from sfo\n");
LOG("failed reading key table start from sfo");
return -1;
}
u32 key_table_start = 0;
CONV_LE(buf, key_table_start);
LOG_VERBOSE("key_table_start is %ld\n", key_table_start);
LOG_VERBOSE("key_table_start is %ld", key_table_start);

if(sceIoRead(fd, &buf, 4) != 4){
sceIoClose(fd);
LOG("failed reading data table start from sfo\n");
LOG("failed reading data table start from sfo");
return -1;
}
u32 data_table_start = 0;
CONV_LE(buf, data_table_start);
LOG_VERBOSE("data_table_start is %ld\n", data_table_start);
LOG_VERBOSE("data_table_start is %ld", data_table_start);

if(sceIoRead(fd, &buf, 4) != 4){
sceIoClose(fd);
LOG("failed reading tables entries from sfo\n");
LOG("failed reading tables entries from sfo");
return -1;
}
u32 tables_entries = 0;
CONV_LE(buf, tables_entries);
LOG_VERBOSE("tables_entries is %ld\n", tables_entries);
LOG_VERBOSE("tables_entries is %ld", tables_entries);

int i;
for(i = 0;i < tables_entries;i++){
sceIoLseek(fd, 0x14 + i * 0x10, PSP_SEEK_SET);
if(sceIoRead(fd, &buf, 2) != 2){
sceIoClose(fd);
LOG("failed reading key offset from sfo\n");
LOG("failed reading key offset from sfo");
return -1;
}
u32 key_offset = 0;
CONV_LE16(buf, key_offset);

if(sceIoRead(fd, &buf, 2) != 2){
sceIoClose(fd);
LOG("failed reading data format from sfo\n");
LOG("failed reading data format from sfo");
return -1;
}
u32 data_format = 0;
CONV_LE16(buf, data_format);

if(sceIoRead(fd, &buf, 4) != 4){
sceIoClose(fd);
LOG("failed reading data len from sfo\n");
LOG("failed reading data len from sfo");
return -1;
}
u32 data_len = 0;
Expand All @@ -204,7 +206,7 @@ static int get_disc_id_version(char *id_out, char *version_out){
sceIoLseek(fd, 4, PSP_SEEK_CUR);
if(sceIoRead(fd, &buf, 4) != 4){
sceIoClose(fd);
LOG("failed reading data offset from sfo\n");
LOG("failed reading data offset from sfo");
return -1;
}
u32 data_offset = 0;
Expand All @@ -216,26 +218,26 @@ static int get_disc_id_version(char *id_out, char *version_out){
for(j = 0;j < 50;j++){
if(sceIoRead(fd, &keybuf[j], 1) != 1){
sceIoClose(fd);
LOG("failed reading key from sfo\n");
LOG("failed reading key from sfo");
}
if(keybuf[j] == 0){
break;
}
}
LOG_VERBOSE("key is %s\n", keybuf);
LOG_VERBOSE("key is %s", keybuf);

sceIoLseek(fd, data_offset + data_table_start, PSP_SEEK_SET);
char databuf[data_len];
for(j = 0;j < data_len; j++){
if(sceIoRead(fd, &databuf[j], 1) != 1){
sceIoClose(fd);
LOG("failed reading data from sfo\n");
LOG("failed reading data from sfo");
}
}
if(data_format == 0x0204){
LOG_VERBOSE("utf8 data: %s\n", databuf);
LOG_VERBOSE("utf8 data: %s", databuf);
}else{
LOG_VERBOSE("data is not utf8, not printing\n");
LOG_VERBOSE("data is not utf8, not printing");
}

if(strncmp("DISC_ID", keybuf, 8) == 0){
Expand Down Expand Up @@ -270,11 +272,11 @@ static int apply_deadzone(int val){

static void sample_input(SceCtrlData *pad_data, int count, int negative){
if(count < 1){
LOG("count is %d, processing skipped\n", count);
LOG("count is %d, processing skipped", count);
return;
}

LOG_VERBOSE("processing %d buffers in %s mode\n", count, negative? "negative" : "positive");
LOG_VERBOSE("processing %d buffers in %s mode", count, negative? "negative" : "positive");

// for this game, it probably makes sense to just process the last buffer
int rx = pad_data[count - 1].Rsrv[0];
Expand Down Expand Up @@ -367,7 +369,7 @@ static void sample_input(SceCtrlData *pad_data, int count, int negative){
}
}

LOG_VERBOSE("timestamp: %lu lx: %d ly: %d rx: %d ry: %d\n", timestamp, lx, ly, rx, ry);
LOG_VERBOSE("timestamp: %lu lx: %d ly: %d rx: %d ry: %d", timestamp, lx, ly, rx, ry);
}

static int (*sceCtrlReadBufferPositiveOrig)(SceCtrlData *pad_data, int count);
Expand All @@ -392,13 +394,13 @@ static void log_modules(){
if (sceKernelQueryModuleInfo(modules[i], &info) < 0) {
continue;
}
LOG("module #%d: %s\n", i+1, info.name);
LOG("module #%d: %s", i+1, info.name);
}
}
}

int set_offsets(char *disc_id, char *disc_version){
LOG("game_base_addr: 0x%lx\n", game_base_addr);
LOG("game_base_addr: 0x%lx", game_base_addr);
// EU and US v2.00
if(strcmp("2.00", disc_version) == 0 && (strcmp("UCES01245", disc_id) == 0 || strcmp("UCUS98632", disc_id) == 0)){
offset_digital_to_analog = game_base_addr + 0x14eb40;
Expand All @@ -419,7 +421,7 @@ int set_offsets(char *disc_id, char *disc_version){
return 0;
}

LOG("unknown dics id %s with version %s\n", disc_id, disc_version);
LOG("unknown dics id %s with version %s", disc_id, disc_version);
return -1;
}

Expand All @@ -431,7 +433,7 @@ void digital_to_analog_patched(u32 *param_1, u32 *param_2){
float *brake = (float *)((u32)(param_1[2]) + 0x538);
u32 *brake_as_int = (u32 *)brake;

//LOG("accel at 0x%lx is %f, brake at 0x%lx is %f\n", (u32)accel, *accel, (u32)brake, *brake);
//LOG("accel at 0x%lx is %f, brake at 0x%lx is %f", (u32)accel, *accel, (u32)brake, *brake);

digital_to_analog_orig(param_1, param_2);
if(*accel_as_int != 0 && override_accel){
Expand Down Expand Up @@ -482,70 +484,71 @@ void populate_car_analog_control_patched(u32 param_1, int *param_2, unsigned cha

// no clutch..?

static uint8_t logged_location = 0;
if(!logged_location){
logged_location = 1;
LOG("car control struct is at 0x%lx\n", (uint32_t)param_3);
}

//populate_car_analog_control_orig(param_1, param_2, param_3, param_4, param_5, param_6);
// populate_car_analog_control_orig(param_1, param_2, param_3, param_4, param_5, param_6);
param_3[0] = 0;
param_3[1] = 0;

int k1 = pspSdkSetK1(0);

//if(is_emulator){
if(1){
// attempt to fix save state on ppsspp, but might sample more future input than the game did on the frame this was called...
SceCtrlData pad_data;
int res = sceCtrlPeekBufferPositive(&pad_data, 1);
sample_input(&pad_data, res, 0);
SceCtrlData pad_data;
int res = sceCtrlPeekBufferPositive(&pad_data, 1);
sample_input(&pad_data, res, 0);

int mode;
sceCtrlGetSamplingMode(&mode);
if(mode != PSP_CTRL_MODE_ANALOG){
// the mode might be per thread
LOG_VERBOSE("sceCtrlGetSamplingMode is not analog..? setting it to analog now");
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
return;
}

if(override_steering){
param_3[0] = param_3[0] | 1;
param_3[1] = param_3[1] | 2;
*steering = steering_override;
LOG("applying steering override, val is %d, steering is %d\n", override_steering, *steering);
LOG_VERBOSE("applying steering override, val is %d, steering is %d", steering_override, *steering);
}

if(override_accel){
// weird curve, 0-0.71 is roughly nothing, 0.81 is roughly 0.25 throttle, 0.91 is roughly 0.5 throttle, 0.96 is roughly 0.75 throttle
param_3[0] = param_3[0] | 2;
if(accel_override >= 95){
static short base = 0x1000 * 0.96;
static short offset_throttle = 0x1000 * (1.0 - 0.96) + 1;
static short base = (0x1000 * 0.96f);
static short offset_throttle = (0x1000 * (1.0f - 0.96f) + 1);
int throttle_segment = accel_override - 95;
static int range = 127 - 95;
*throttle = base + throttle_segment * offset_throttle / range;
if(*throttle > 4096){
*throttle = 4096;
}
}else if(accel_override >= 64){
static short base = 0x1000 * 0.91;
static short offset_throttle = 0x1000 * (0.96 - 0.91);
static short base = (0x1000 * 0.91f);
static short offset_throttle = (0x1000 * (0.96f - 0.91f));
int throttle_segment = accel_override - 64;
static int range = 94 - 64;
*throttle = base + throttle_segment * offset_throttle / range;
}else if(accel_override >= 32){
static short base = 0x1000 * 0.81;
static short offset_throttle = 0x1000 * (0.91 - 0.81);
static short base = (0x1000 * 0.81f);
static short offset_throttle = (0x1000 * (0.91f - 0.81f));
int throttle_segment = accel_override - 32;
static int range = 63 - 32;
*throttle = base + throttle_segment * offset_throttle / range;
}else{
static short base = 0x1000 * 0.71;
static short offset_throttle = 0x1000 * (0.81 - 0.71);
static short base = (0x1000 * 0.71f);
static short offset_throttle = (0x1000 * (0.81f - 0.71f));
int throttle_segment = accel_override;
static int range = 31;
*throttle = base + throttle_segment * offset_throttle / range;
}
// *throttle = accel_override * 0x1000 / 127;
LOG_VERBOSE("applying accel override, val is %d, throttle is %d\n", accel_override, *throttle);
LOG_VERBOSE("applying accel override, val is %d, throttle is %d", accel_override, *throttle);
}

if(override_brake){
param_3[0] = param_3[0] | 4;
*brake = brake_override * 0x1000 / 127;
LOG_VERBOSE("applying brake override, val is %d, brake is %d\n", brake_override, *brake);
LOG_VERBOSE("applying brake override, val is %d, brake is %d", brake_override, *brake);
}

if(override_camera){
Expand All @@ -566,15 +569,15 @@ int init(){
char disc_version[50];
int disc_id_valid = get_disc_id_version(disc_id, disc_version) == 0;
if(disc_id_valid){
LOG("disc id is %s\n", disc_id);
LOG("disc version is %s\n", disc_version);
LOG("disc id is %s", disc_id);
LOG("disc version is %s", disc_version);
}else{
LOG("cannot find disc id from sfo, aborting\n");
LOG("cannot find disc id from sfo, aborting");
return -1;
}

if(set_offsets(disc_id, disc_version) != 0){
LOG("cannot lookup function offsets with disc id and version, aborting\n");
LOG("cannot lookup function offsets with disc id and version, aborting");
return -1;
}

Expand All @@ -590,10 +593,10 @@ int init(){
int fd = sceIoOpen("ms0:/PSP/"MODULE_NAME"_camera_controls.txt", PSP_O_RDONLY, 0);
if(fd >= 0){
camera_controls = 1;
LOG("enabling camera controls\n");
LOG("enabling camera controls");
sceIoClose(fd);
}else{
LOG("not enabling camera controls\n");
LOG("not enabling camera controls");
}
}

Expand All @@ -606,17 +609,19 @@ int init(){

if(is_emulator){
sceKernelDelayThread(1000 * 1000 * 5);
LOG("boosting input sampling on ppsspp\n");
LOG("boosting input sampling on ppsspp");
sceCtrlSetSamplingCycle(5555);
}

LOG("main thread finishes\n");
LOG("main thread finishes");
return 0;
}

int StartPSP(SceModule2 *mod) {
if(strcmp(mod->modname, GAME_MODULE_NAME) == 0){
game_base_addr = mod->text_addr;
// XXX oh no
game_base_addr = game_base_addr + 0x28;
init();
}

Expand Down Expand Up @@ -652,19 +657,22 @@ int module_start(SceSize args, void *argp){
sceIoRemove("ms0:/PSP/"MODULE_NAME".log");
sceIoRemove("ef0:/PSP/"MODULE_NAME".log");
#endif
LOG("module started\n");
LOG("module started");

is_emulator = sceIoDevctl("kemulator:", EMULATOR_DEVCTL__IS_EMULATOR, NULL, 0, NULL, 0) == 0;

if (is_emulator) {
// Just scan the modules using normal/official syscalls.
LOG("starting in ppsspp mode");
StartPPSSPP();
}else{
LOG("starting in psp mode");
previous = sctrlHENSetStartModuleHandler(StartPSP);
}
return 0;
}

int module_stop(SceSize args, void *argp){
LOG("attempting to stop this module, but unload is not really implemented...");
return 0;
}

0 comments on commit c5c8f8b

Please sign in to comment.