Compare commits

..

No commits in common. "master" and "v1.0" have entirely different histories.
master ... v1.0

10 changed files with 305 additions and 167 deletions

View File

@ -1,33 +1,38 @@
# What does it do?
# TrophyShot by Team CBPS
## What does it do?
Just like in PS4, it takes a screenshot whenever you unlock a trophy.
Best used with reScreeny: https://forum.devchroma.nl/index.php/topic,51.0.html
Best used with [reScreeny](https://github.com/dots-tb/reScreeny)
# How do I install it?
Get it from here: https://git.homd.xyz/FMudanyali/TrophyShot/releases
## How do I install it?
In config.txt inside tai folder,
TrophyShot.suprx goes under *main
TrophyShot_shell.suprx goes under \*main
TrophyShot_app.suprx goes under \*ALL
like this:
```
*main
ur0:tai/TrophyShot.suprx
```
ur0:tai/TrophyShot_shell.suprx
*ALL
ur0:tai/TrophyShot_app.suprx
After modifying the config, reboot.
# Credits
- FMudanyali of Team CBPS - SceScreenShot implementation, first 4 iterations, taught teakhanirons how to use snprintf
- **Graphene of Team CBPS** - SceShellUtil reverse engineering and ShellUtil clipboard trick, stabilization by module seperation and platinum testing
- Princess of Sleeping of Team CBPS - SceShell reverse engineering guidance
- teakhanirons of Team CBPS - SceScreenShot and additional SceShell reverse engineering
- dots-tb of Team CBPS - Additional reverse engineering guidance, cool guy in general
- Silica of Team CBPS - Prevented a disaster, twice
- Pina of Team CBPS - Was there
- yasen of Team CBPS - Morale support
- cuevavirus of Team CBPS - DolceSDK maintainance
- Nkekev of Team CBPS - Requested this plugin a long time ago
- and Team CBPS.
## Credits
- [FMudanyali](https://github.com/FMudanyali) of Team CBPS - SceScreenShot implementation, first 4 iterations, taught teakhanirons how to use snprintf
- [Graphene](https://github.com/GrapheneCt) of Team CBPS - SceShellUtil reverse engineering and ShellUtil clipboard trick, stabilization by module seperation and platinum testing
- [Princess of Sleeping](https://github.com/Princess-of-Sleeping) of Team CBPS - SceShell reverse engineering guidance
- [teakhanirons](https://github.com/teakhanirons) of Team CBPS - Additional SceShell and SceScreenShot reverse engineering
- [dots-tb](https://github.com/dots-tb) of Team CBPS - Additional reverse engineering guidance, cool guy in general
- [Silica](https://github.com/KuromeSan) of Team CBPS - Prevented a disaster, twice
- [Pina](https://github.com/KuromeSan) of Team CBPS - Was there
- [yasen](https://github.com/nightyasen) of Team CBPS - Morale support
- [cuevavirus](https://github.com/cuevavirus) of Team CBPS - DolceSDK maintainance
- [Nkekev](https://github.com/Nkekev) of Team CBPS - Requested this plugin a long time ago
- and [Team CBPS](https://forum.devchroma.nl/).

51
app/CMakeLists.txt Normal file
View File

@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{DOLCESDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{DOLCESDK}/share/dolce.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define DOLCESDK to point to your SDK path!")
endif()
endif()
project(trophyshot_app)
include("$ENV{DOLCESDK}/share/dolce.cmake" REQUIRED)
dolce_gen_libs(SceShellSvc_stubs
SceShellSvc.yml
LIB SceShellSvc_stub_weak)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -std=gnu99")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions")
link_directories(
${CMAKE_CURRENT_BINARY_DIR}
)
add_executable(${PROJECT_NAME}
trophy_app.c
)
target_link_libraries(${PROJECT_NAME}
SceLibKernel_stub
SceKernelModulemgr_stub
SceKernelThreadMgr_stub
SceSysmem_stub
SceAppMgr_stub
SceScreenShot_stub_weak
SceShellSvc_stub_weak
SceSysmodule_stub
SceShellSvc_stub
ScePaf_stub_weak
SceRtc_stub
gcc
k
taihen_stub
taihenModuleUtils_stub
)
dolce_create_self(${PROJECT_NAME}.suprx ${PROJECT_NAME}
UNSAFE
CONFIG ${CMAKE_SOURCE_DIR}/TrophyShot.yml
)

12
app/SceShellSvc.yml Normal file
View File

@ -0,0 +1,12 @@
version: 2
firmware: 3.60
modules:
SceShellSvc:
nid: 0x36E557FA
libraries:
SceShellUtil:
kernel: false
nid: 0xD2B1C8AE
functions:
sceShellUtilTextClipboardWrite: 0xC4810C56
sceShellUtilTextClipboardRead: 0x1B186905

View File

@ -1,4 +1,4 @@
TrophyShot:
TrophyShotApp:
attributes: 0
version:
major: 1

79
app/trophy_app.c Normal file
View File

@ -0,0 +1,79 @@
#include <taihen.h>
#include <psp2/kernel/modulemgr.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/sysmodule.h>
#include <psp2/kernel/clib.h>
#include <psp2/screenshot.h>
#include <dolcesdk.h>
#include <stdio.h>
#include <string.h>
#define printf sceClibPrintf
#define TROPHY_MAGIC 12345678
#define DONE_MAGIC 87654321
int sceShellUtilTextClipboardRead(void* data, SceSize size, SceSize *textlen);
int sceShellUtilTextClipboardWrite(const void* data, SceSize size);
int sceAppMgrIsGameProgram(int);
int hook[1];
static tai_hook_ref_t screenshot_hook;
const static int done_magic = DONE_MAGIC;
static int frames = 0;
int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf* pParam, SceDisplaySetBufSync sync) {
int read_data, screenshot_ret;
if (frames == 5) {
frames = 0;
sceShellUtilTextClipboardRead(&read_data, sizeof(int), NULL);
if (read_data == TROPHY_MAGIC) {
printf("SHOOTING\n");
SceScreenShotCaptureFileInfo captureFileInfo;
sceClibMemset(&captureFileInfo, 0, sizeof(captureFileInfo));
screenshot_ret = sceScreenShotCapture(1, &captureFileInfo, NULL, NULL);
printf("INFO TrophyShot: sceScreenShotCapture() : 0x%08x path='%s'\n", screenshot_ret, captureFileInfo.path);
sceShellUtilTextClipboardWrite(&done_magic, sizeof(int));
}
}
frames++;
return TAI_CONTINUE(int, screenshot_hook, pParam, sync);
}
void _start() __attribute__((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
printf("TrophyShot APP PART 2.0 SALVO FIRE\n");
int ret = sceAppMgrIsGameProgram(-2);
printf("APP TYPE: %d\n", ret);
if (ret == 1) {
sceSysmoduleLoadModule(SCE_SYSMODULE_SCREEN_SHOT);
hook[0] = taiHookFunctionImport(
&screenshot_hook,
TAI_MAIN_MODULE,
TAI_ANY_LIBRARY, //SceDisplayUser
0x7A410B64, //sceDisplaySetFrameBuf
sceDisplaySetFrameBuf_patched);
printf("INFO TrophyShot_app: sceDisplaySetFrameBuf HOOK: 0x%x\n", hook[0]);
}
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hook[0] >= 0) taiHookRelease(hook[0], screenshot_hook);
return SCE_KERNEL_STOP_SUCCESS;
}

125
main.c
View File

@ -1,125 +0,0 @@
#include <taihen.h>
#include <psp2/kernel/modulemgr.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/kernel/clib.h>
#include <psp2/kernel/iofilemgr.h>
#define printf sceClibPrintf
int hook[1];
static tai_hook_ref_t shell_hook;
static uint8_t platinum_only = 1;
int (*shellShot)(void);
// Taken from sysident - taihen_min.c https://github.com/cuevavirus/sysident
int module_get_offset(SceUID modid, int segidx, uint32_t offset, void *stub_out){
int res = 0;
SceKernelModuleInfo info;
if(segidx > 3) return -1;
if(stub_out == NULL) return -2;
res = sceKernelGetModuleInfo(modid, &info);
if(res < 0) return res;
if(offset > info.segments[segidx].memsz) return -3;
*(uint32_t *)stub_out = (uint32_t)(info.segments[segidx].vaddr + offset);
return 0;
}
int sub_81229FAC_patched(int arg1, int arg2){
int ret = TAI_CONTINUE(int, shell_hook, arg1, arg2);
switch(arg2 - arg1){
case 0xDC4:
printf("Regular trophy unlocked.\n");
if(platinum_only){
sceKernelDelayThread(3200000);
}else{
sceKernelDelayThread(1800000);
shellShot();
}
break;
case 0x930:
printf("Platinum trophy unlocked.\n");
sceKernelDelayThread(1800000);
shellShot();
break;
default:
break;
}
return ret;
}
void _start() __attribute__((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
SceUID fd = sceIoOpen("ux0:/data/TrophyShot/platinum.txt", SCE_O_RDONLY, 0777);
if(fd < 0){
platinum_only = 0;
}
sceIoClose(fd);
tai_module_info_t tai_info;
int offset_shellshot, offset_dialog;
tai_info.size = sizeof(tai_module_info_t);
int ret = taiGetModuleInfo("SceShell", &tai_info);
if (ret < 0) return SCE_KERNEL_START_SUCCESS;
switch(tai_info.module_nid){
case 0x0552F692: // 3.60 retail
offset_shellshot = 0x14a928;
offset_dialog = 0x229fac;
break;
case 0x6CB01295: // 3.60 PDEL
case 0xEAB89D5C: // 3.60 PTEL
offset_shellshot = 0x142d5c;
offset_dialog = 0x2223e0;
break;
case 0x5549BF1F: // 3.65 retail
offset_shellshot = 0x14a980;
offset_dialog = 0x22a048;
break;
case 0x34B4D82E: // 3.67 retail
case 0x12DAC0F3: // 3.68 retail
case 0x0703C828: // 3.69 retail
case 0x2053B5A5: // 3.70 retail
case 0xF476E785: // 3.71 retail
case 0x939FFBE9: // 3.72 retail
case 0x734D476A: // 3.73 retail
case 0xE6A02F2B: // 3.65 PDEL
case 0x587F9CED: // 3.65 PTEL
offset_shellshot = 0x142db4;
offset_dialog = 0x22247c;
break;
default:
return SCE_KERNEL_START_SUCCESS;
}
//function found by teakhanirons
module_get_offset(
tai_info.modid,
0,
offset_shellshot | 1,
&shellShot
);
//function found by Graphene
hook[0] = taiHookFunctionOffset(
&shell_hook,
tai_info.modid,
0,
offset_dialog,
1,
sub_81229FAC_patched
);
printf("INFO sub_81229FAC_patched: 0x%x\n", hook[0]);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hook[0] >= 0) taiHookRelease(hook[0], shell_hook);
return SCE_KERNEL_STOP_SUCCESS;
}

View File

@ -8,9 +8,13 @@ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
endif()
endif()
project(TrophyShot)
project(trophyshot_shell)
include("$ENV{DOLCESDK}/share/dolce.cmake" REQUIRED)
dolce_gen_libs(SceShellSvc_stubs
SceShellSvc.yml
LIB SceShellSvc_stub_weak)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -std=gnu99")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions")
@ -20,17 +24,27 @@ link_directories(
)
add_executable(${PROJECT_NAME}
main.c
trophy_shell.c
)
target_link_libraries(${PROJECT_NAME}
SceLibKernel_stub
SceThreadmgr_stub
SceModulemgr_stub
taihenModuleUtils_stub
SceKernelModulemgr_stub
SceKernelThreadMgr_stub
SceSysmem_stub
SceScreenShot_stub_weak
SceShellSvc_stub_weak
SceSysmodule_stub
SceShellSvc_stub
ScePaf_stub_weak
SceRtc_stub
gcc
k
taihen_stub
taihenModuleUtils_stub
)
dolce_create_self(${PROJECT_NAME}.suprx ${PROJECT_NAME}
UNSAFE
CONFIG ${CMAKE_SOURCE_DIR}/TrophyShot.yml
)

12
main/SceShellSvc.yml Normal file
View File

@ -0,0 +1,12 @@
version: 2
firmware: 3.60
modules:
SceShellSvc:
nid: 0x36E557FA
libraries:
SceShellUtil:
kernel: false
nid: 0xD2B1C8AE
functions:
sceShellUtilTextClipboardWrite: 0xC4810C56
sceShellUtilTextClipboardRead: 0x1B186905

8
main/TrophyShot.yml Normal file
View File

@ -0,0 +1,8 @@
TrophyShotMain:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop

82
main/trophy_shell.c Normal file
View File

@ -0,0 +1,82 @@
#include <taihen.h>
#include <psp2/kernel/modulemgr.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/sysmodule.h>
#include <psp2/kernel/clib.h>
#include <psp2/screenshot.h>
#include <dolcesdk.h>
#include <stdio.h>
#include <string.h>
#define printf sceClibPrintf
#define TROPHY_MAGIC 12345678
#define DONE_MAGIC 87654321
int sceShellUtilTextClipboardRead(void* data, SceSize size, SceSize *textlen);
int sceShellUtilTextClipboardWrite(const void* data, SceSize size);
int hook[1];
static tai_hook_ref_t shell_hook;
const static int trophy_magic = TROPHY_MAGIC;
int sub_81229FAC_patched(int arg1, int arg2) {
int waiter = 0;
printf("I'M HOOKINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n");
int ret = TAI_CONTINUE(int, shell_hook, arg1, arg2);
sceKernelDelayThread(1300000);
printf("INFO TrophyShot: Trophy unlocked.\n");
sceShellUtilTextClipboardWrite(&trophy_magic, sizeof(int));
while (waiter != DONE_MAGIC) {
sceShellUtilTextClipboardRead(&waiter, sizeof(int), NULL);
sceKernelDelayThread(1000);
}
return ret;
}
void _start() __attribute__((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
printf("TrophyShot 2.0 SALVO FIRE\n");
tai_module_info_t tai_info;
tai_info.size = sizeof(tai_module_info_t);
int ret = taiGetModuleInfo("SceShell", &tai_info);
if (ret < 0) return SCE_KERNEL_START_FAILED;
int offset;
switch (tai_info.module_nid) { // trophy notification
case 0x0552F692: // retail 3.60 SceShell
case 0x532155E5: // retail 3.61 SceShell
offset = 0x229fac;
break;
case 0x5549BF1F: // retail 3.65 SceShell
case 0x34B4D82E: // retail 3.67 SceShell
case 0x12DAC0F3: // retail 3.68 SceShell
case 0x0703C828: // retail 3.69 SceShell
case 0x2053B5A5: // retail 3.70 SceShell
case 0xF476E785: // retail 3.71 SceShell
case 0x939FFBE9: // retail 3.72 SceShell
case 0x734D476A: // retail 3.73 SceShell
offset = 0x22a048;
break;
default:
return SCE_KERNEL_START_SUCCESS;
}
hook[0] = taiHookFunctionOffset(
&shell_hook,
tai_info.modid,
0,
offset,
1,
sub_81229FAC_patched);
printf("hook: 0x%x\n", hook[0]);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hook[0] >= 0) taiHookRelease(hook[0], shell_hook);
return SCE_KERNEL_STOP_SUCCESS;
}