Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
PonpiK committed Jun 10, 2024
1 parent 0487415 commit f9f20de
Show file tree
Hide file tree
Showing 9 changed files with 428 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# themadump
![](https://raw.githubusercontent.com/catmagicspell/themadump/master/app/resource/screenshot.png)</br>
This homebrew allows you to dump your PSP's active theme to your Memory Stick.<br/>
It should work on every PSP firmware **regardless of whether it's CFW or OFW**.

[Download and Installation](https://github.com/catmagicspell/themadump/releases/latest)

# Credits
- [reha](https://github.com/rreha) and [PonpiK](https://github.com/PonpiK) of **[Cat Magic Spell](https://github.com/catmagicspell)** for leading the project and testing<br/>
- Zenax for the **[ICON0](https://raw.githubusercontent.com/catmagicspell/themadump/master/app/resource/ICON0.PNG)**<br/>
- [Acid_Snake](https://github.com/JoseAaronLopezGarcia) and [others who contributed to the LibPspExploit](https://github.com/PSP-Archive/LibPspExploit?tab=readme-ov-file#credits) for **[LibPspExploit](https://github.com/PSP-Archive/LibPspExploit)**<br/>
- [krazynez](https://github.com/krazynez) for **[wallpaper_dumper](https://github.com/krazynez/wallpaper_dumper)**<br/>
26 changes: 26 additions & 0 deletions app/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
TARGET = themadump
SRCDIR = ./source
INCDIR = ./include
LIBDIR = ./library
RESDIR = ./resource

CFILES := $(wildcard $(SRCDIR)/*.c)
OBJS := $(CFILES:.c=.o)

CFLAGS = -Ofast -w
LIBS = -lpspexploit -lpsprtc
USE_PSPSDK_LIBC = 1
USE_PSPSDK_LIBS = 1

BUILD_PRX = 1
PSP_FW_VERSION = 370
PSP_LARGE_MEMORY = 0

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = ThemaDump
PSP_EBOOT_ICON= $(RESDIR)/ICON0.png
#PSP_EBOOT_PIC1= $(RESDIR)/PIC1.png
#PSP_EBOOT_SND0= $(RESDIR)/SND0.at3

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
28 changes: 28 additions & 0 deletions app/include/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef COMMON_H
#define COMMON_H
#pragma once

#include <pspsdk.h>
#include <pspkernel.h>
#include <libpspexploit.h>

#define RGB(r, g, b) (0xFF000000 | ((b) << 16) | ((g) << 8) | (r))
#define RED RGB(255, 0, 0)
#define GREEN RGB(0, 255, 0)
#define BLUE RGB(0, 0, 255)
#define BLACK RGB(0, 0, 0)
#define ORANGE RGB(255, 127, 0)
#define WHITE RGB(255, 255, 255)
#define YELLOW RGB(255, 255, 0)
#define GRAY RGB(103, 120, 137)

#define BackColor(color) pspDebugScreenSetBackColor(color)
#define TextColor(color) pspDebugScreenSetTextColor(color)
#define printf pspDebugScreenPrintf

#define VER_MAJOR 1
#define VER_MINOR 0

extern void kthread(void);
extern KernelFunctions *k_tbl;
#endif
204 changes: 204 additions & 0 deletions app/include/libpspexploit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#ifndef LIBPSPEXPLOIT_H
#define LIBPSPEXPLOIT_H
#pragma once

#include <pspsdk.h>
#include <psputils.h>
#include <pspkerror.h>
#include <psploadcore.h>
#include <psploadexec.h>
#include <psploadexec_kernel.h>
#include <psputility.h>
#include <psputility_modules.h>
#include <psputility_savedata.h>
#include <pspsysmem.h>
#include <pspmodulemgr.h>
#include <pspctrl.h>
#include <pspiofilemgr.h>
#include <string.h>

#define KERNELIFY(x) (((u32)x) | 0x80000000)

// j addr
#define JUMP(f) (0x08000000 | (((unsigned int)(f) >> 2) & 0x03ffffff))

// j addr getter (for kernel range, use in combination with KERNELIFY, works with j & jal)
#define JUMP_TARGET(i) (((unsigned int)(i) & 0x03ffffff) << 2)

// jal addr
#define JAL(f) (0x0C000000 | (((unsigned int)(f) >> 2) & 0x03ffffff))

#define MAKE_JUMP(a, f) _sw(JUMP(f), a);
#define MAKE_CALL(a, f) _sw(JAL(f), a);

// jal checker
#define IS_JAL(i) ((((unsigned int)i) & 0xFC000000) == 0x0C000000)
#define IS_JUMP(i) ((((unsigned int)i) & 0xFC000000) == 0x08000000)

// syscall number
#define SYSCALL(n) ((n << 6) | 12)

// nop
#define NOP 0

// jr ra
#define JR_RA 0x03E00008

// v0 result setter
#define LI_V0(n) ((0x2402 << 16) | ((n) & 0xFFFF))

#define MAKE_DUMMY_FUNCTION_RETURN_0(a) \
_sw(JR_RA, a); \
_sw(LI_V0(0), a + 4);

#define MAKE_DUMMY_FUNCTION_RETURN_1(a) \
_sw(JR_RA, a); \
_sw(LI_V0(1), a + 4);

// Array Element Counter
#define NELEMS(n) ((sizeof(n)) / sizeof(n[0]))

// is UID
#define IsUID(uid) ((uid > 0 && uid < 0x05000000) && ((uid & 1) == 1))

// Min & Max Macros
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))

#undef UNUSED
#define UNUSED(arg) ((void)(arg))

// by Bubbletune
#define U_EXTRACT_IMPORT(x) ((((u32)_lw((u32)x)) & ~0x08000000) << 2)
#define K_EXTRACT_IMPORT(x) (((((u32)_lw((u32)x)) & ~0x08000000) << 2) | 0x80000000)
#define U_EXTRACT_CALL(x) ((((u32)_lw((u32)x)) & ~0x0C000000) << 2)
#define K_EXTRACT_CALL(x) (((((u32)_lw((u32)x)) & ~0x0C000000) << 2) | 0x80000000)
#define K_EXTRACT_BRANCH(x) ((((((u32)_lw((u32)x)) & 0x0000FFFF) << 2) + x + 4) | 0x80000000)

// by Acid_Snake
// the opcode is filled with two 0's to the right and shifted to make it a byte long
#define GET_OPCODE(x) ((_lw(x) & 0xFC000000) >> 24)
#define GET_FUNCTION_OPCODE(x) (_lw(x) & 0x3F)

#define MAKE_JUMP_PATCH(a, f) _sw(0x08000000 | (((u32)(f) & 0x0FFFFFFC) >> 2), a);
#define PTR_ALIGN_64(p) ((void *)((((u32)p) + 64 - 1) & (~(64 - 1))))

// by Davee
#define HIJACK_FUNCTION(a, f, ptr) \
{ \
u32 func = a; \
static u32 patch_buffer[3]; \
_sw(_lw(func), (u32)patch_buffer); \
_sw(_lw(func + 4), (u32)patch_buffer + 8); \
MAKE_JUMP_PATCH((u32)patch_buffer + 4, func + 8); \
_sw(0x08000000 | (((u32)(f) >> 2) & 0x03FFFFFF), func); \
_sw(0, func + 4); \
ptr = (void *)patch_buffer; \
}

#define REDIRECT_SYSCALL(a, f) \
_sw(JR_RA, a); \
_sw(SYSCALL(sceKernelQuerySystemCall(f)), a + 4);

#define MAKE_DUMMY_FUNCTION(a, r) \
{ \
u32 func = a; \
if (r == 0) \
{ \
_sw(JR_RA, func); \
_sw(0x00001021, func + 4); \
} \
else \
{ \
_sw(JR_RA, func); \
_sw(0x24020000 | r, func + 4); \
} \
}

#define REDIRECT_FUNCTION(a, f) \
{ \
u32 func = a; \
_sw(0x08000000 | (((u32)(f) >> 2) & 0x03FFFFFF), func); \
_sw(0, func + 4); \
}

// Common Kernel Functions
typedef struct KernelFunctions
{
// iofilemgr.prx Functions
SceUID (*KernelIOOpen)(const char *, int, int); // 0
int (*KernelIOWrite)(SceUID, const void *, unsigned); // 4
int (*KernelIORead)(SceUID, void *, unsigned); // 8
int (*KernelIOLSeek)(int fd, s64 offset, int whence); // 12
int (*KernelIOClose)(SceUID); // 16
SceUID (*KernelIODopen)(char *); // 20
int (*KernelIODread)(SceUID, SceIoDirent *); // 24
int (*KernelIODclose)(SceUID); // 28
int (*KernelIOMkdir)(const char *, SceMode); // 32
int (*KernelIORmdir)(const char *path); // 36
int (*KernelIOGetStat)(const char *file, SceIoStat *stat); // 40
int (*KernelIORemove)(const char *file); // 44
int (*IoAssign)(const char *dev1, const char *dev2, const char *dev3, int mode, void *unk1, long unk2); // 48
int (*IoUnassign)(const char *dev); // 52

// sysmem.prx Functions
SceUID (*KernelAllocPartitionMemory)(SceUID partitionid, const char *name, int type, SceSize size, void *addr); // 56
void *(*KernelGetBlockHeadAddr)(SceUID blockid); // 60
int (*KernelFreePartitionMemory)(int); // 64
void (*KernelIcacheInvalidateAll)(void); // 68
void (*KernelDcacheWritebackInvalidateAll)(void); // 72
int (*KernelGzipDecompress)(unsigned char *dest, unsigned int destSize, const unsigned char *src, void *unknown); // 76
void (*KernelDcacheInvalidateRange)(const void *p, unsigned int size); // 80

// threadman.prx Functions
SceUID (*KernelCreateThread)(const char *name, SceKernelThreadEntry entry,
int initPriority, int stackSize, SceUInt attr, SceKernelThreadOptParam *option); // 84
int (*KernelStartThread)(SceUID thid, SceSize arglen, void *argp); // 88
int (*KernelDelayThread)(int); // 92
int (*KernelDeleteThread)(int); // 96
int (*KernelExitThread)(int); // 100
void (*waitThreadEnd)(int, int *); // 104
} KernelFunctions;

// extern KernelFunctions* k_tbl;

// Generic utils
#define pspXploitFindFirstJAL(addr) pspXploitFindAnyJAL(addr, 0, 0)
#define pspXploitFindFirstJALReverse(addr) pspXploitFindAnyJAL(addr, 1, 0)
#define pspXploitFindJAL(addr, pos) pspXploitFindAnyJAL(addr, 0, pos)
#define pspXploitFindJALReverse(addr, pos) pspXploitFindAnyJAL(addr, 1, pos)
#define pspXploitFindFirstJALForFunction(modname, libname, nid) findFirstJAL(FindFunction(modname, libname, nid))
#define pspXploitFindJALForFunction(modname, libname, nid, pos) findJAL(FindFunction(modname, libname, nid), pos)
#define pspXploitFindFirstJALReverseForFunction(modname, libname, nid) findFirstJALReverse(FindFunction(modname, libname, nid))
#define pspXploitFindJALReverseForFunction(modname, libname, nid, pos) findJALReverse(FindFunction(modname, libname, nid), pos)
u32 pspXploitFindAnyJAL(u32 addr, int reversed, int skip);
u32 pspXploitFindFirstBEQ(u32 addr);
u32 pspXploitFindRefInGlobals(char *libname, u32 addr, u32 ptr);
void pspXploitPatchAccurateError(u32 text_addr, u32 text_size, u16 error);
int pspXploitIsKernel();

// User Utils
u32 pspXploitFindImportRange(char *libname, u32 nid, u32 lower, u32 higher);
u32 pspXploitFindImportVolatileRam(char *libname, u32 nid);
u32 pspXploitFindImportUserRam(char *libname, u32 nid);
int pspXploitOpenP5(int mode);
int pspXploitCloseP5();
u32 pspXploitFindFunctionFromUsermode(const char *library, u32 nid, void *buf, u32 size);

// Kernel Utils
void pspXploitScanKernelFunctions(KernelFunctions *kfuncs);
u32 pspXploitFindModuleByName(const char *modulename);
u32 pspXploitFindTextAddrByName(const char *modulename);
u32 pspXploitFindFunction(const char *module, const char *library, u32 nid);
int pspXploitSetUserLevel(int level);

// kernel_read.c
uint64_t pspXploitKernelRead64(uint32_t addr);
void pspXploitDumpKernel(u32 *dst, u32 *src, u32 size);

// kernel_write.c
int pspXploitInitKernelExploit();
int pspXploitDoKernelExploit();
void pspXploitExecuteKernel(u32 kernelContentFunction);
void pspXploitRepairKernel();
#endif
Binary file added app/library/libpspexploit.a
Binary file not shown.
Binary file added app/resource/ICON0.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/resource/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
97 changes: 97 additions & 0 deletions app/source/kernel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <common.h>

int (*_sceIoAssign)(const char *, const char *, const char *, int, void *, long) = NULL;
int (*_sceIoUnassign)(const char *) = NULL;
int (*_sceIoOpen)(const char *, int, SceMode) = NULL;
int (*_sceIoClose)(SceUID) = NULL;
int (*_sceIoRead)(SceUID, void *, SceSize) = NULL;
int (*_sceIoWrite)(SceUID, const void *, SceSize) = NULL;
int (*_sceIoMkdir)(const char *, SceMode) = NULL;
int (*_sceKernelDelayThread)(int) = NULL;

void tthread(void)
{
printf("Assigning flash1...");
_sceIoUnassign("flash1:");
SceUID f1 = _sceIoAssign("flash1:", "lflash0:0,1", "flashfat1:", 0, NULL, 0);
if (f1 < 0)
{
TextColor(RED);
printf(" failed! (0x%08x)\n\n", f1);
TextColor(WHITE);
printf("Please try running the program again. Exiting...");
printf("Press any button to exit.");
return;
}
else
{
TextColor(GREEN);
printf(" success!\n");
}

TextColor(WHITE);
printf("Reading custom_theme.dat...");

SceUID ret = _sceIoOpen("flash1:/vsh/theme/custom_theme.dat", PSP_O_RDONLY, 0777);
if (ret < 0)
{
TextColor(RED);
printf(" failed! (0x%08x)\n\n", ret);
TextColor(WHITE);
printf("Maybe a custom theme wasn't set?\n");
printf("Press any button to exit.");
return;
}
else
{
TextColor(GREEN);
printf(" success!\n");
}

TextColor(WHITE);
printf("Dumping custom_theme.dat...");

int read;
u8 buf[512];

_sceKernelDelayThread(500000);
SceUID theme = _sceIoOpen("ms0:/PSP/THEME/custom_theme.ptf", PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC, 0777);
if (theme < 0)
{
_sceIoMkdir("ms0:/PSP/THEME", 0777);
theme = _sceIoOpen("ms0:/PSP/THEME/custom_theme.ptf", PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC, 0777);
}

while ((read = _sceIoRead(ret, buf, 512)) > 0)
_sceIoWrite(theme, buf, read);

_sceIoClose(ret);
_sceIoClose(theme);
_sceIoUnassign("flash1:");
_sceKernelDelayThread(3000000);

TextColor(GREEN);
printf(" success!\n\n");
TextColor(WHITE);
printf("Saved as ms0:/PSP/THEME/custom_theme.ptf\n");
printf("Press any button to exit.");
}

void kthread(void)
{
_sceIoAssign = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0xB2A628C1);
_sceIoUnassign = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0x6D08A871);
_sceIoOpen = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0x109F50BC);
_sceIoClose = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0x810C4BC3);
_sceIoRead = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0x6A638D83);
_sceIoWrite = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0x42EC03AC);
_sceIoMkdir = pspXploitFindFunction("sceIOFileManager", "IoFileMgrForKernel", 0x06A70004);
_sceKernelDelayThread = pspXploitFindFunction("sceThreadManager", "ThreadManForUser", 0xCEADEB47);

SceUID kthreadID = k_tbl->KernelCreateThread("themadump_kthread", (void *)KERNELIFY(&tthread), 1, 0x20000, PSP_THREAD_ATTR_VFPU, NULL);
if (kthreadID >= 0)
{
k_tbl->KernelStartThread(kthreadID, 0, NULL);
k_tbl->waitThreadEnd(kthreadID, NULL);
}
}
Loading

0 comments on commit f9f20de

Please sign in to comment.