From 5e2ccdefb5ca6afbfdc29ca485ee3019d0678a47 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Fri, 27 Oct 2023 09:02:19 -0400 Subject: [PATCH] Added (L)ME support, error trapping, new sounds. --- Makefile | 8 +- README.md | 45 ++++++++- common/include/systemctrl.h | 2 + kernel/Makefile | 9 +- kernel/exports.exp | 1 + kernel/main.c | 70 ++++++------- me_fix/Makefile | 29 ++++++ me_fix/___README_FIRST____.MD | 4 + me_fix/exports.exp | 10 ++ me_fix/main.c | 95 +++++++++++++++++ res/ACCEPT.MP3 | Bin 0 -> 12538 bytes res/SELECTION.MP3 | Bin 0 -> 15360 bytes user/main.c | 185 +++++++++++++++++----------------- 13 files changed, 322 insertions(+), 136 deletions(-) create mode 100644 me_fix/Makefile create mode 100644 me_fix/___README_FIRST____.MD create mode 100644 me_fix/exports.exp create mode 100644 me_fix/main.c create mode 100644 res/ACCEPT.MP3 create mode 100644 res/SELECTION.MP3 diff --git a/Makefile b/Makefile index 2e071dd..5996911 100644 --- a/Makefile +++ b/Makefile @@ -10,17 +10,23 @@ all: #subdirs # user kernel $(MAKE) $@ -C libs $(MAKE) $@ -C user $(MAKE) $@ -C kernel + $(MAKE) $@ -C me_fix @mkdir -p $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer || true @cp $(UMDREGIONROOT)/user/EBOOT.PBP $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/ @cp $(UMDREGIONROOT)/kernel/*.prx $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/ @cp $(UMDREGIONROOT)/IDSREG.PRX $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/ @cp $(UMDREGIONROOT)/res/matrix_new.png $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/BG.PNG - @cp $(UMDREGIONROOT)/res/EXIT.MP3 $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/EXIT.MP3 + @cp $(UMDREGIONROOT)/res/ACCEPT.MP3 $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/ACCEPT.MP3 + @cp $(UMDREGIONROOT)/res/SELECTION.MP3 $(UMDREGIONROOT)/dist/PSP/GAME/UMD_Region_Changer/SELECTION.MP3 + mkdir $(UMDREGIONROOT)/dist/SEPLUGINS || true + @cp $(UMDREGIONROOT)/me_fix/UMD_Region_Changer_ME_fix.prx $(UMDREGIONROOT)/dist/SEPLUGINS/ + @cp $(UMDREGIONROOT)/me_fix/___README_FIRST____.MD $(UMDREGIONROOT)/dist/SEPLUGINS/ @echo "Build Done" clean: $(MAKE) $@ -C user $(MAKE) $@ -C kernel + $(MAKE) $@ -C me_fix @rm -rf $(UMDREGIONROOT)/dist *.zip @find . -type f -name "*.o" -delete -o -name "*.elf" -delete -o -name "*.prx" -delete -o -name "*.PBP" -delete -o -name "*.SFO" -delete -o -name "*.a" -delete @echo CLEAN diff --git a/README.md b/README.md index cdaefc1..f83fe1f 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,22 @@ 3. After copying `UMD_Region_Changer` to `ms0:/PSP/GAME` make sure your UMD door is NOT closed/detected then run it. -4. If you accidently do have your UMD door closed, once the XMB is loaded you can just open and close the UMD door and the UMD will be allowed to be played. +4. If you accidentally do have your UMD door closed, once the XMB is loaded you can just open and close the UMD door and the UMD will be allowed to be played. + + +

Note:As of right now this does not support Game Categories Lite. I will be working on that to see if I can figure a way to support it. Thanks for your cooperation and patience. + + +### Releases + +For the latest release go here ## Setup & Install + + +#### PRO Users + 1. Run UMD Region Changer 2. Choose the region @@ -22,9 +34,37 @@ 3. Once XMB display insert UMD of you selected Region 4. Play and enjoy your Movie + + + +#### (L)ME Users + +

Reason why ME is forced to use a plugin. For some reason sctrlHENLoadModuleOnReboot does not play nice with ME. +I had to create a plugin that would do the equivalent that the normal EBOOT does but as a plugin for it to work on ME. +Like no joke its almost a 1:1 copy and paste of it. +sctrlHENLoadModuleOnReboot is slightly different than on PRO and ARK from reading the documentation for instance, +the first argument on PRO and ARK-4 is module_before, but with ME its module_after so even if it "just worked" the placement +of the patches would not correlate with what we thought was going to happen. It seems that that only works via game interaction or some sorts. +Which is very bizarre as its part of systemctrl so it should be available globally? I will be more than happy to discuss my findings +or if they are in need so some test cases. I was determined to find a way to get it working and did, not 100% ideal by all means, but it does work.

+ +1. copy `UMD_Region_Changer_ME_fix.prx` to `SEPLUGINS` located on your PSP + +2. Add `ms0:/SEPLUGINS/UMD_Region_Changer_ME_fix.prx 1` to `GAME.TXT` + +3. Run UMD Region Changer + +4. Choose the region + +5. Once XMB display insert UMD of you selected Region + +6. Play and enjoy your Movie + +
-

NOTE: This is not persistant, if you restart your PSP the UMD Drive will default back to its original state.

+ +

NOTE: This is not persistent, if you restart your PSP the UMD Drive will default back to its original state.

### Credits: @@ -37,6 +77,7 @@

Others - PSP_Cult for providing the graphics and logo(s)/icon(s) and testing. + - Github Search with other users provided me to get ME support working, such as `qwikrazor87`'s npdrm_free repo. May he rest in peace, I truly wish you were hear to take guidance from.

diff --git a/common/include/systemctrl.h b/common/include/systemctrl.h index 7c1b5ce..01addc4 100644 --- a/common/include/systemctrl.h +++ b/common/include/systemctrl.h @@ -24,7 +24,9 @@ enum BootLoadFlags BOOTLOAD_GAME = 2, BOOTLOAD_UPDATER = 4, BOOTLOAD_POPS = 8, + BOOTLOAD_APP = 32, BOOTLOAD_UMDEMU = 64, /* for original NP9660 */ + BOOTLOAD_MLNAPP = 128, /* for original NP9660 */ }; #ifdef __cplusplus diff --git a/kernel/Makefile b/kernel/Makefile index 6dd04c8..849788f 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -6,8 +6,10 @@ endif CXXFLAGS = $(CFLAGS) -fno-execeptions -fno-rtti ASFLAGS = $(CFLAGS) +LDFLAGS = -nostartfiles + +INCDIR = $(UMDREGIONROOT)/common/include ./include -INCDIR = ./include PSP_FW_VERSION = 660 BUILD_PRX = 1 @@ -19,9 +21,10 @@ OBJS = main.o USE_KERNEL_LIBC=1 USE_KERNEL_LIBS=1 -INCDIR = $(UMDREGIONROOT)/common/include ./include -LIBS = -lc -lpspsystemctrl_kernel + + +LIBS = -lpspsystemctrl_kernel -lpspdisplay LIBDIR=$(UMDREGIONROOT)/libs diff --git a/kernel/exports.exp b/kernel/exports.exp index 2dc6116..7ed7113 100644 --- a/kernel/exports.exp +++ b/kernel/exports.exp @@ -3,6 +3,7 @@ PSP_BEGIN_EXPORTS PSP_EXPORT_START(syslib, 0, 0x8000) PSP_EXPORT_FUNC_HASH(module_start) +PSP_EXPORT_FUNC_HASH(module_stop) PSP_EXPORT_VAR_HASH(module_info) PSP_EXPORT_END diff --git a/kernel/main.c b/kernel/main.c index a547db7..5af0c77 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,8 +1,8 @@ #include #include +#include #include #include -#include #include #include @@ -15,7 +15,7 @@ #define NOP 0 #define JUMP(f) (0x08000000 | (((unsigned int)(f) >> 2) & 0x03ffffff)) -PSP_MODULE_INFO("UMDREGION_Module", 0x3007, 1, 5); +PSP_MODULE_INFO("UMDREGION_Module", 0x3007, 1, 6); STMOD_HANDLER previous; @@ -137,38 +137,7 @@ unsigned int find_Import_ByNID(SceModule2 * pMod, char * library, unsigned int n return 0; } -void PSPOnModuleStart(SceModule2 * mod){ - - - if(strcmp(mod->modname, "sceUmdMan_driver") == 0) { - patch_umd_idslookup(mod); - goto flush; - } - - if (strcmp(mod->modname, "vsh_module") == 0){ - patch_vsh_region_check(mod); - goto flush; - } - if (strcmp(mod->modname, "impose_plugin_module") == 0){ - SceUID kthreadID = sceKernelCreateThread( "umd_region_change", &patch_umd_thread, 1, 0x20000, PSP_THREAD_ATTR_VFPU, NULL); - if (kthreadID >= 0){ - // start thread and wait for it to end - sceKernelStartThread(kthreadID, 0, NULL); - } - goto flush; - - } - -flush: - flushCache(); - - // Forward to previous Handler - if(previous) - previous(mod); - else - return NULL; -} @@ -317,12 +286,13 @@ int sctrlArkReplaceUmdKeys(){ // load and start idsRegeneration module // ms0:/PSP/GAME/UMD_Region_Changer/ char path[UMD_REGION_PATH_SIZE]; - strcpy(path, UMD_REGION_PATH); + strcpy(path, UMD_REGION_PATH); strcat(path, "IDSREG.PRX"); + SceUID modid = sceKernelLoadModule(path, 0, NULL); if (modid >= 0){ - res = sceKernelStartModule(modid, strlen(path) + 1, path, NULL, NULL); + res = sceKernelStartModule(modid, strlen(path)+1, path, NULL, NULL); if (res < 0){ goto fake_ids_end; } @@ -350,8 +320,6 @@ int sctrlArkReplaceUmdKeys(){ if (res < 0) goto fake_ids_end; // initialize idsRegeneration with hardware info and new region - // - // res = idsRegenerationSetup(tachyon, baryon, pommel, mb, fuseid, region_num, NULL); if (res < 0) goto fake_ids_end; @@ -404,10 +372,36 @@ int patch_umd_thread(SceSize args, void *argp){ return 0; } +int PSPOnModuleStart(SceModule2 * mod){ + if(strcmp(mod->modname, "sceUmdMan_driver") == 0) { + patch_umd_idslookup(mod); + flushCache(); + } + + if (strcmp(mod->modname, "vsh_module") == 0){ + patch_vsh_region_check(mod); + flushCache(); + } + + if (strcmp(mod->modname, "impose_plugin_module") == 0){ + SceUID kthreadID = sceKernelCreateThread( "umd_region_change", &patch_umd_thread, 1, 0x20000, PSP_THREAD_ATTR_VFPU, NULL); + if (kthreadID >= 0){ + // start thread and wait for it to end + sceKernelStartThread(kthreadID, 0, NULL); + } + flushCache(); + + } -int module_start(SceSize args, void *argp) { + // Forward to previous Handler + if(previous) previous(mod); + else return 0; +} + + +int module_start(SceSize args, void *argp) { previous = sctrlHENSetStartModuleHandler(PSPOnModuleStart); return 0; } diff --git a/me_fix/Makefile b/me_fix/Makefile new file mode 100644 index 0000000..782a40c --- /dev/null +++ b/me_fix/Makefile @@ -0,0 +1,29 @@ +TARGET = UMD_Region_Changer_ME_fix +CFLAGS = -Wall -O2 -G0 +ifdef DEBUG + CFLAGS += -DDEBUG=$(DEBUG) +endif + +LDFLAGS += -mno-crt0 -nostartfiles +CXXFLAGS = $(CFLAGS) -fno-execeptions -fno-rtti +ASFLAGS = $(CFLAGS) + +PSP_FW_VERSION = 660 +BUILD_PRX = 1 + +PRX_EXPORTS = exports.exp + +OBJS = main.o + +USE_KERNEL_LIBC=1 +USE_KERNEL_LIBS=1 + + +INCDIR = $(UMDREGIONROOT)/common/include ./include +LIBDIR=$(UMDREGIONROOT)/libs + +LIBS = -lc -lcolordebugger -lpspsystemctrl_kernel -lpspkubridge + + +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build_prx.mak diff --git a/me_fix/___README_FIRST____.MD b/me_fix/___README_FIRST____.MD new file mode 100644 index 0000000..5326872 --- /dev/null +++ b/me_fix/___README_FIRST____.MD @@ -0,0 +1,4 @@ +USE ONLY FOR (L)ME + + +!!!!!!!!!! DO NOT USE ON PRO !!!!!!!!!!! diff --git a/me_fix/exports.exp b/me_fix/exports.exp new file mode 100644 index 0000000..7ed7113 --- /dev/null +++ b/me_fix/exports.exp @@ -0,0 +1,10 @@ +# Define the exports for the prx +PSP_BEGIN_EXPORTS + +PSP_EXPORT_START(syslib, 0, 0x8000) +PSP_EXPORT_FUNC_HASH(module_start) +PSP_EXPORT_FUNC_HASH(module_stop) +PSP_EXPORT_VAR_HASH(module_info) +PSP_EXPORT_END + +PSP_END_EXPORTS diff --git a/me_fix/main.c b/me_fix/main.c new file mode 100644 index 0000000..119ecde --- /dev/null +++ b/me_fix/main.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +PSP_MODULE_INFO("UMDREGION_Module_ME", 0x1000, 2, 0); + +STMOD_HANDLER previous = NULL; + +int module_start(SceSize args, void *argp) { + //_sw(0x44000000, 0xBC800100); + //colorDebug(0xFF); + char mod[] = "ms0:/PSP/GAME/UMD_Region_Changer/UMD_Region_Changer.prx"; + static u8 buf[100*1024]; + const int size = 100*1024; + //SceUID module; + //SceUID modstart; + + //module = sceKernelLoadModule(mod, 0, NULL); + + //modstart = sceKernelStartModule(module, sizeof(module), NULL, NULL, NULL); + //sceKernelStartModule(mod, 0, 0, 0, 0); + SceUID module = sceIoOpen(mod, PSP_O_RDONLY, 0777); + SceUID bytes = sceIoRead(module, buf, size); + + sceIoClose(module); + + + sctrlHENLoadModuleOnReboot("/kd/umdman.prx", buf, bytes, BOOTLOAD_VSH | BOOTLOAD_UMDEMU | BOOTLOAD_GAME | BOOTLOAD_POPS); + + sceKernelExitGame(); + + + return 0; +} + +int module_stop(SceSize args, void *argp) { + return 0; +} + + +// Flush Instruction and Data Cache +/*void flushCache() +{ + // Flush Instruction Cache + sceKernelIcacheInvalidateAll(); + + // Flush Data Cache + sceKernelDcacheWritebackInvalidateAll(); +} + + +int OnModuleStart(SceModule2 *mod){ + + SceUID fd = sceIoOpen("ms0:/dump.txt", PSP_O_CREAT|PSP_O_WRONLY|PSP_O_APPEND, 0777); + sceIoWrite(fd, mod->modname, strlen(mod->modname)); + sceIoWrite(fd, "\n", 1); + sceIoClose(fd); + + if(strcmp(mod->modname, "sceUmdMan_driver") == 0) { + //patch_umd_idslookup(mod); + flushCache(); + } + + if (strcmp(mod->modname, "vsh_module") == 0){ + //patch_vsh_region_check(mod); + flushCache(); + } + + + // Forward to previous Handler + if(previous) previous(mod); + else return 0; +} + +int module_start(SceSize args, void *argp) { + _sw(0x44000000, 0xBC800100); + colorDebug(0xFF); + previous = sctrlHENSetStartModuleHandler(OnModuleStart); + return 0; +} + +int module_stop(SceSize args, void *argp) { + return 0; +} +*/ diff --git a/res/ACCEPT.MP3 b/res/ACCEPT.MP3 new file mode 100644 index 0000000000000000000000000000000000000000..202d78937a6a4420363a0fe9169a1c164f2d4b5d GIT binary patch literal 12538 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 #include -PSP_MODULE_INFO("UMD_REGION_CHANGER", 0, 1, 5); +PSP_MODULE_INFO("UMD_REGION_CHANGER", 0, 1, 6); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); #define printf pspDebugScreenPrintf @@ -31,30 +31,95 @@ PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); #define SCR_WIDTH 480 #define SCR_HEIGHT 272 +static char arrow[] = "-> "; +static int dir = 0; +static int trueType = -1; +static int offset = 50; +static int region; +static int i = -1; +static char selected[64]; +static char check_path[64]; + + + +static char *regions[4] = { + "Default", + "Japan", + "America", + "Europe", + }; + +#define nums (sizeof(regions)/sizeof(regions[0]))-1 + +static void playSound(bool type) { + MP3_Init(1); + + if(type) + MP3_Load("ACCEPT.MP3"); + else + MP3_Load("SELECTION.MP3"); + + MP3_Play(); + while(!MP3_EndOfStream()) {} + MP3_Stop(); +} + + +static void updateScreen(Image* bg, int dir, int type) { + blitImageToScreen(0, 0, 480, 272, bg, 0, 0); + for(i = 0; i= 0) { + playSound(type); + trueType = -1; + } +} + int main(int argc, char *args[]) { Image* background; pspDebugScreenInit(); initGraphics(); - /*FILE* fp = fopen(args[0], "rb"); - PBPHeader header; - fread(&header, 1, sizeof(PBPHeader), fp); - fclose(fp); - */ - - + pspAudioInit(); background = loadImage("BG.PNG", 0); sceDisplayWaitVblankStart(); + + + strcpy(check_path, UMD_REGION_PATH); + strcat(check_path, "EBOOT.PBP"); + + if(strcmp(args[0], check_path) != 0) { + pspDebugScreenSetXY(5, 5); + pspDebugScreenSetTextColor(0x00FFFFFF); + printf("Sorry for right now Categories Lite is not supported..."); + pspDebugScreenSetXY(5, 8); + printf("Exiting..."); + sceKernelDelayThread(5000000); + sctrlKernelExitVSH(NULL); + } + + pspDebugScreenSetXY(17, 5); pspDebugScreenSetTextColor(0xFF0000FF); printf("Presented by ARK-4 Team (c)2023"); pspDebugScreenSetXY(26, 10); pspDebugScreenSetTextColor(0xFF00FF00); - printf("Version 1.5"); + printf("Version 1.6"); + pspDebugScreenSetXY(48, 10); + pspDebugScreenSetTextColor(0xFF00FF00); sceKernelDelayThread(3000000); @@ -77,109 +142,43 @@ int main(int argc, char *args[]) { pspDebugScreenClear(); SceCtrlData pad; - char arrow[] = "-> "; - - int dir = 0; - - char *regions[4] = { - "Default", - "Japan", - "America", - "Europe", - }; - -#define nums (sizeof(regions)/sizeof(regions[0]))-1 - - int offset = 50; - - int i = 0; - int region; - - char selected[64]; - while(1){ - blitImageToScreen(0, 0, 480, 272, background, 0, 0); sceDisplayWaitVblankStart(); - //pspDebugScreenSetTextColor(0xFF0000); - //pspDebugScreenSetXY(0, 0); + updateScreen(background, dir, trueType); sceCtrlReadBufferPositive(&pad, 1); - //printf("##########################"); - printTextScreen(0, 5, "##########################", 0xFFFF0000); - //pspDebugScreenSetXY(0, 1); - //printf("# #"); + printTextScreen(0, 5, "##########################", 0xFFFF0000); printTextScreen(0, 10, "# #", 0xFFFF0000); - //pspDebugScreenSetXY(0, 2); - //printf("# Please choose a Region #"); printTextScreen(0, 20, "# Please choose a Region #", 0xFFFF0000); - //pspDebugScreenSetXY(0, 3); - //printf("# #"); printTextScreen(0, 30, "# #", 0xFFFF0000); - //pspDebugScreenSetXY(0, 4); - //printf("##########################"); - //pspDebugScreenSetXY(0, 6); printTextScreen(0, 40, "##########################", 0xFFFF0000); - // BGR - // pspDebugScreenSetTextColor(0xFFFFFF); - - - - // DEFAULT - if(1) { - for(i = 0; inums) dir = 0; - sceKernelDelayThread(100000); region = dir; + trueType = 0; } // BUTTON UP if(pad.Buttons & PSP_CTRL_UP) { dir--; if(dir<0) dir = nums; - sceKernelDelayThread(100000); region = dir; + trueType = 0; } // ACCEPT BUTTON - else if(pad.Buttons & PSP_CTRL_CROSS) { + if(pad.Buttons & PSP_CTRL_CROSS) { sceDisplayWaitVblankStart(); - - pspAudioInit(); - MP3_Init(1); - MP3_Load("EXIT.MP3"); - MP3_Play(); - - while(!MP3_EndOfStream()) {}; - MP3_Stop(); - + updateScreen(background, dir, 1); // Need to not hardcode this for category lite reasons. - char mod[] = "ms0:/PSP/GAME/UMD_Region_Changer/UMD_Region_Changer.prx"; - char region_path[] = "ms0:/PSP/GAME/UMD_Region_Changer/region.txt"; + //char mod[] = "ms0:/PSP/GAME/UMD_Region_Changer/UMD_Region_Changer.prx"; + //char mod[] = "ms0:/SEPLUGINS/UMD_Region_Changer_ME_fix.prx"; + char mod[] = "UMD_Region_Changer.prx"; + //char region_path[] = "ms0:/PSP/GAME/UMD_Region_Changer/region.txt"; + char region_path[] = "region.txt"; const int size = 100*1024; static u8 buf[100*1024]; SceUID byteRead; @@ -190,7 +189,7 @@ int main(int argc, char *args[]) { //0 // default //3 // Japan //4 // America - //5 // Europe + //5 // Europe (Australia) if(region==1) region = 3; @@ -229,21 +228,23 @@ int main(int argc, char *args[]) { sceIoClose(module); - if(module < 0 || size < 0) { + if(module < 0 || byteRead < 0) { pspDebugScreenSetXY(5, 25); printf("Nah your module size %d is messed up or your byteRead is %d", module, byteRead); while(1){}; } else { - pspDebugScreenSetXY(0, 30); - pspDebugScreenSetTextColor(0xFFFFFF); - printf("Enjoy your freedom ;-)"); + clearScreen(0x00000000); + printTextScreen(130, 135, "Enjoy your freedom ;-)", 0x00FFFFFF); + flipScreen(); sceKernelDelayThread(500000); } + int status; // Start module before umdman starts - sctrlHENLoadModuleOnReboot("/kd/umdman.prx", buf, byteRead, BOOTLOAD_VSH); + sctrlHENLoadModuleOnReboot("/kd/umdman.prx", buf, byteRead, (BOOTLOAD_VSH | BOOTLOAD_GAME | BOOTLOAD_POPS | BOOTLOAD_UPDATER | BOOTLOAD_UMDEMU | BOOTLOAD_APP | BOOTLOAD_MLNAPP)); + //sctrlHENLoadModuleOnReboot("/kd/systemctrl.prx", buf, byteRead, BOOTLOAD_VSH); // Go back to XMB and enjoy region unlocked goodness. sctrlKernelExitVSH(NULL); }