diff --git a/README.md b/README.md index a6cdffa..ba41394 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ See the launcher [README](launcher/README.md) for more details. - Support for launching applications from the memory card browser - Support for setting PS1 driver options on every boot - Support for HDD OSD 1.10U +- Ability to force OSD region ## Configuration @@ -104,11 +105,6 @@ See the MBR [README](mbr/README.md) for more details. OSDMenu comes with the fully-featured launcher that supports running applications from all devices supported by homebrew drivers. See the launcher [README](launcher/README.md) for more details. - -## Known issues that will not be fixed - -- For master discs, `PS2LOGO` may appear "inverted". - This issue does not occur when using pressed retail copies. ## Credits @@ -120,4 +116,5 @@ See the launcher [README](launcher/README.md) for more details. - CosmicScale for [RetroGEM Disc Launcher](https://github.com/CosmicScale/Retro-GEM-PS2-Disc-Launcher), [PSBBN Definitive English Patch](https://github.com/CosmicScale/PSBBN-Definitive-English-Patch) and extensive testing - Ripto for creating OSDMenu Browser icons and Yornn for collecting all files required for the PSU package - Alex Parrado for creating [SoftDev2 installer](https://github.com/parrado/SoftDev2) -- [R3Z3N/Saildot4K](https://github.com/saildot4k) for testing OSDMenu with various modchips, Crystal Chip PBT script and suggestions on documentation and release packaging improvements \ No newline at end of file +- [R3Z3N/Saildot4K](https://github.com/saildot4k) for testing OSDMenu with various modchips, Crystal Chip PBT script and suggestions on documentation and release packaging improvements +- l_oliveira for advices on fixing PS2LOGO for master discs \ No newline at end of file diff --git a/examples/OSDMENU.CNF b/examples/OSDMENU.CNF index 4e3ecb6..67ddc9d 100644 --- a/examples/OSDMENU.CNF +++ b/examples/OSDMENU.CNF @@ -2,6 +2,7 @@ OSDSYS_video_mode = AUTO OSDSYS_Skip_Disc = 1 OSDSYS_Skip_Logo = 1 OSDSYS_Inner_Browser = 0 +OSDSYS_region = AUTO OSDSYS_custom_menu = 1 OSDSYS_scroll_menu = 1 OSDSYS_menu_x = 320 diff --git a/patcher/CMakeLists.txt b/patcher/CMakeLists.txt index d5cce93..600a426 100644 --- a/patcher/CMakeLists.txt +++ b/patcher/CMakeLists.txt @@ -51,6 +51,7 @@ set(EE_SOURCES ${PATCHER_SOURCE_DIR}/src/patches_gs.c ${PATCHER_SOURCE_DIR}/src/patches_version.c ${PATCHER_SOURCE_DIR}/src/patches_ps1drv.c + ${PATCHER_SOURCE_DIR}/src/patches_osd.c ) # HOSDMenu build diff --git a/patcher/README.md b/patcher/README.md index 75cceb0..66ee9f9 100644 --- a/patcher/README.md +++ b/patcher/README.md @@ -11,12 +11,13 @@ It patches the OSDSYS/HDD OSD binary and applies the following patches: - HDD update check bypass - Override PS1 and PS2 disc launch functions with the launcher, bringing the following features to OSDSYS/HDD-OSD: - Skip the PlayStation 2 logo - - Patch the PlayStation 2 logo to work with all disc regions + - Patch the PlayStation 2 logo to work with all disc regions and master discs - Display the visual Game ID for the PixelFX RetroGM - Run disc-based games via the embedded Neutrino GSM (eGSM) - Run PS1 discs via the PS1 Video Mode Negator or DKWDRV - Additional system information in version submenu (Video mode, ROM version, EE, GS and MechaCon revision) - Set PS1 driver options to values from `OSDMENU.CNF` on every boot +- Force OSD region on non-protokernel systems **OSDMenu**: - The OSDMenu configuration file can be embedded into the patcher at compile time for memory card-independent setups and faster boot times @@ -79,38 +80,40 @@ DKWDRV and custom payload paths are limited to 49 characters. 2. `OSDSYS_Skip_Disc` — enables/disables automatic CD/DVD launch 3. `OSDSYS_Skip_Logo` — enables/disables SCE logo (also needs `OSDSYS_Skip_Disc` to be disabled to actually show the logo) 4. `OSDSYS_Inner_Browser` — enables/disables going to the Browser after launching OSDSYS +5. `OSDSYS_region` — forces OSDSYS region if set. Valid values are `AUTO`, `jap`, `usa`, `eur`. + This changes the video mode, button prompts and available languages (on some consoles) #### OSDSYS custom menu options -5. `OSDSYS_custom_menu` — enables or disables custom menu -6. `OSDSYS_scroll_menu` — enables or disables infinite scrolling in custom menu -7. `OSDSYS_menu_x` — menu X center coordinate -8. `OSDSYS_menu_y` — menu Y center coordinate -9. `OSDSYS_enter_x` — `Enter` button X coordinate (at main OSDSYS menu) -10. `OSDSYS_enter_y` — `Enter` button Y coordinate (at main OSDSYS menu) -11. `OSDSYS_version_x` — `Version` button X coordinate (at main OSDSYS menu) -12. `OSDSYS_version_y` — `Version` button Y coordinate (at main OSDSYS menu) -13. `OSDSYS_cursor_max_velocity` — max cursor speed -14. `OSDSYS_cursor_acceleration` — cursor speed -15. `OSDSYS_left_cursor` — left cursor text -16. `OSDSYS_right_cursor` — right cursor text -17. `OSDSYS_menu_top_delimiter` — top menu delimiter text -18. `OSDSYS_menu_bottom_delimiter` — bottom menu delimiter text -19. `OSDSYS_num_displayed_items` — the number of menu items displayed -20. `OSDSYS_selected_color` — color of selected menu entry -21. `OSDSYS_unselected_color` — color of unselected menu entry -22. `name_OSDSYS_ITEM_???` — menu entry name -23. `path?_OSDSYS_ITEM_???` — path to ELF. Also supports the following special paths: `cdrom`, `OSDSYS`, `POWEROFF` -24. `arg_OSDSYS_ITEM_???` — custom argument to be passed to the ELF. Each argument needs a separate entry. +6. `OSDSYS_custom_menu` — enables or disables custom menu +7. `OSDSYS_scroll_menu` — enables or disables infinite scrolling in custom menu +8. `OSDSYS_menu_x` — menu X center coordinate +9. `OSDSYS_menu_y` — menu Y center coordinate +10. `OSDSYS_enter_x` — `Enter` button X coordinate (at main OSDSYS menu) +11. `OSDSYS_enter_y` — `Enter` button Y coordinate (at main OSDSYS menu) +12. `OSDSYS_version_x` — `Version` button X coordinate (at main OSDSYS menu) +13. `OSDSYS_version_y` — `Version` button Y coordinate (at main OSDSYS menu) +14. `OSDSYS_cursor_max_velocity` — max cursor speed +15. `OSDSYS_cursor_acceleration` — cursor speed +16. `OSDSYS_left_cursor` — left cursor text +17. `OSDSYS_right_cursor` — right cursor text +18. `OSDSYS_menu_top_delimiter` — top menu delimiter text +19. `OSDSYS_menu_bottom_delimiter` — bottom menu delimiter text +20. `OSDSYS_num_displayed_items` — the number of menu items displayed +21. `OSDSYS_selected_color` — color of selected menu entry +22. `OSDSYS_unselected_color` — color of unselected menu entry +23. `name_OSDSYS_ITEM_???` — menu entry name +24. `path?_OSDSYS_ITEM_???` — path to ELF. Also supports the following special paths: `cdrom`, `OSDSYS`, `POWEROFF` +25. `arg_OSDSYS_ITEM_???` — custom argument to be passed to the ELF. Each argument needs a separate entry. #### Disc/application launch modifiers -25. `cdrom_skip_ps2logo` — enables or disables running discs via `rom0:PS2LOGO` -26. `cdrom_disable_gameid` — disables or enables visual Game ID -27. `cdrom_use_dkwdrv` — enables or disables launching DKWDRV for PS1 discs -28. `ps1drv_enable_fast` — will enable fast disc speed for PS1 discs when not using DKWDRV -29. `ps1drv_enable_smooth` — will enable texture smoothing for PS1 discs when not using DKWDRV -30. `ps1drv_use_ps1vn` — will run PS1DRV using the PS1DRV Video Mode Negator -31. `app_gameid` — if enabled, visual Game ID will be displayed for ELF applications launched from OSDMenu. The ID is generated from the ELF name (up to 11 characters). -32. `path_DKWDRV_ELF` — custom path to DKWDRV.ELF (exclsuive to OSDMenu). The path MUST be on the memory card, the default value is `mc?:/BOOT/DKWDRV.ELF` +26. `cdrom_skip_ps2logo` — enables or disables running discs via `rom0:PS2LOGO` +27. `cdrom_disable_gameid` — disables or enables visual Game ID +28. `cdrom_use_dkwdrv` — enables or disables launching DKWDRV for PS1 discs +29. `ps1drv_enable_fast` — will enable fast disc speed for PS1 discs when not using DKWDRV +30. `ps1drv_enable_smooth` — will enable texture smoothing for PS1 discs when not using DKWDRV +31. `ps1drv_use_ps1vn` — will run PS1DRV using the PS1DRV Video Mode Negator +32. `app_gameid` — if enabled, visual Game ID will be displayed for ELF applications launched from OSDMenu. The ID is generated from the ELF name (up to 11 characters). +33. `path_DKWDRV_ELF` — custom path to DKWDRV.ELF (exclsuive to OSDMenu). The path MUST be on the memory card, the default value is `mc?:/BOOT/DKWDRV.ELF` To add a custom separator to the menu, add a `name_OSDSYS_ITEM_???` entry that starts with `$!`. This will make the entry inactive, but still show it in the OSD without the `$!` prefix. diff --git a/patcher/include/patches_osdmenu.h b/patcher/include/patches_osdmenu.h index 2b07956..0a1e45a 100644 --- a/patcher/include/patches_osdmenu.h +++ b/patcher/include/patches_osdmenu.h @@ -21,6 +21,9 @@ void patchBrowserApplicationLaunch(uint8_t *osd, int isProtokernel); // Sets kernel PS1DRV configuration to values set in OSDMENU.CNF if not initialized void patchPS1DRVConfig(uint8_t *osd); +// Patches OSD region +void patchOSDRegion(uint8_t *osd); + #ifndef HOSD // Protokernel patches diff --git a/patcher/include/patterns_osd.h b/patcher/include/patterns_osd.h new file mode 100644 index 0000000..c3a3a8c --- /dev/null +++ b/patcher/include/patterns_osd.h @@ -0,0 +1,14 @@ +#ifndef _PATTERNS_OSD_H_ +#define _PATTERNS_OSD_H_ +// OSDMenu OSD patterns +#include + +// Pattern for overriding OSD region +static uint32_t patternOSDRegion[] = { + 0x80020000, // lw v0,0x0000,? <- patch target + 0x04410020, // bgez v0,0x002? + 0xffb00010, // sd s0,0x0010,sp +}; +static uint32_t patternOSDRegion_mask[] = {0xf00f0000, 0xfffffff0, 0xffffffff}; + +#endif diff --git a/patcher/include/settings.h b/patcher/include/settings.h index 5181220..2c064b0 100644 --- a/patcher/include/settings.h +++ b/patcher/include/settings.h @@ -31,6 +31,13 @@ typedef enum { FLAG_CUSTOM_MENU = (1 << 11), // Apply menu patches } PatcherFlags; +typedef enum { + OSD_REGION_DEFAULT, + OSD_REGION_JAP, + OSD_REGION_USA, + OSD_REGION_EUR, +} OSDRegion; + // Patcher settings struct, contains all configurable patch settings and menu items typedef struct { uint32_t colorSelected[4]; // The menu items color when selected @@ -53,6 +60,7 @@ typedef struct { char menuDelimiterBottom[NAME_LEN]; // The bottom menu delimiter text, only for scroll menu char menuItemName[CUSTOM_ITEMS][NAME_LEN]; // Menu items text GSVideoMode videoMode; // OSDSYS Video mode (0 for auto) + OSDRegion region; // OSD Region char romver[15]; // ROMVER string, initialized before patching #ifndef HOSD char dkwdrvPath[50]; // Path to DKWDRV diff --git a/patcher/src/patches_common.c b/patcher/src/patches_common.c index 9e97d15..86fe879 100644 --- a/patcher/src/patches_common.c +++ b/patcher/src/patches_common.c @@ -66,6 +66,9 @@ void patchExecuteOSDSYS(void *epc, void *gp, int argc, char *argv[]) { // Apply version menu patch patchVersionInfo((uint8_t *)epc); + // Apply OSD region patch + patchOSDRegion((uint8_t *)epc); + if ((settings.patcherFlags & FLAG_PS1DRV_FAST) || (settings.patcherFlags & FLAG_PS1DRV_SMOOTH)) // Patch PS1DRV config patchPS1DRVConfig((uint8_t *)epc); diff --git a/patcher/src/patches_osd.c b/patcher/src/patches_osd.c new file mode 100644 index 0000000..fe6cb37 --- /dev/null +++ b/patcher/src/patches_osd.c @@ -0,0 +1,37 @@ +#include "patches_common.h" +#include "patterns_osd.h" +#include "settings.h" +#include + +// OSD region patch +void patchOSDRegion(uint8_t *osd) { + if (settings.region == OSD_REGION_DEFAULT) + return; + + // Find the get region function + uint8_t *ptr = findPatternWithMask(osd, 0x100000, (uint8_t *)patternOSDRegion, (uint8_t *)patternOSDRegion_mask, sizeof(patternOSDRegion)); + if (!ptr) + return; + + // ROMVER -> OSD region mapping: + // 'J' --- 0 (Japan) + // 'A'/'H' --- 1 (USA) + // 'E' --- 2 (Europe) + // 'C' --- 3 (China?) + // Replace load from memory with just storing our value into v0 register + uint32_t val = 0x24020000; + switch (settings.region) { + case OSD_REGION_JAP: + val |= 0x0; + break; + case OSD_REGION_USA: + val |= 0x1; + break; + case OSD_REGION_EUR: + val |= 0x2; + break; + default: + return; + } + _sw(val, (uint32_t)ptr); +} diff --git a/patcher/src/settings.c b/patcher/src/settings.c index ddd31a8..fd41d58 100644 --- a/patcher/src/settings.c +++ b/patcher/src/settings.c @@ -229,6 +229,18 @@ int loadConfig(void) { continue; } + if (!strcmp(name, "OSDSYS_region")) { + if (!strcmp(value, "AUTO")) + settings.region = OSD_REGION_DEFAULT; + else if (!strcmp(value, "jap")) + settings.region = OSD_REGION_JAP; + else if (!strcmp(value, "usa")) + settings.region = OSD_REGION_USA; + else if (!strcmp(value, "eur")) + settings.region = OSD_REGION_EUR; + + continue; + } if (!strcmp(name, "OSDSYS_custom_menu")) { if (atoi(value)) settings.patcherFlags |= FLAG_CUSTOM_MENU; @@ -333,6 +345,7 @@ void initVariables() { void initConfig(void) { settings.patcherFlags = FLAG_CUSTOM_MENU | FLAG_SCROLL_MENU | FLAG_SKIP_SCE_LOGO | FLAG_SKIP_DISC; settings.videoMode = 0; + settings.region = OSD_REGION_DEFAULT; settings.menuX = 320; settings.menuY = 110; settings.enterX = 30; diff --git a/utils/loader/CMakeLists.txt b/utils/loader/CMakeLists.txt index 55918be..b67e96f 100644 --- a/utils/loader/CMakeLists.txt +++ b/utils/loader/CMakeLists.txt @@ -44,6 +44,5 @@ set_target_properties(loader PROPERTIES RUNTIME_OUTPUT_NAME "loader.elf" ) -add_dependencies(loader) target_sources(loader PRIVATE ${egsm_source}) target_compile_definitions(loader PRIVATE EGSM_BIN_SIZE) diff --git a/utils/loader/src/ps2logo.c b/utils/loader/src/ps2logo.c index dd52c0e..a187eaf 100644 --- a/utils/loader/src/ps2logo.c +++ b/utils/loader/src/ps2logo.c @@ -8,22 +8,38 @@ uint8_t isPAL = 0; -int getConsoleRegion() { - if (isPAL) - return 2; +// Unscrambles the logo +// Based on code from https://github.com/mlafeldt/ps2logo +int unscrambleLogo(char *whatever, void *logoBuffer, int bufSize) { + uint8_t *logo = 0; + asm volatile("move %0, $s1" : "=r"(logo)::); // Get logo buffer address from $s1 + + int key = logo[0]; + for (int i = 0; i < 0x6000; i++) { + logo[i] ^= key; + logo[i] = (logo[i] << 3) | (logo[i] >> 5); + } return 0; } // Does the actual patching -int doPatchWithOffsets(uint32_t getRegionLoc, uint32_t checksumLoc) { +// getRegionLoc — region getter function, with ROMVER check call at +8 bytes. Required to display the logo properly +// cdDecLoc — first sceCdDecSet call in logo handling function +int doPatchWithOffsets(uint32_t getRegionLoc, uint32_t cdDecLoc) { if ((_lw(getRegionLoc) != 0x27bdfff0) || ((_lw(getRegionLoc + 8) & 0xff000000) != 0x0c000000)) + // Make sure get region location target actually points to the expected code return -1; - if ((_lw(checksumLoc) & 0xffff0000) != 0x8f820000) + if (((_lw(cdDecLoc) & 0xff000000) != 0x0c000000) || (_lw(cdDecLoc) != _lw(cdDecLoc + 0x90))) + // Make sure sceCdDecSet location actually point to the expected code return -1; - _sw((0x0c000000 | ((uint32_t)getConsoleRegion >> 2)), - getRegionLoc + 8); // Patch function call at getRegionLoc + 8 to always return the disc's region - _sw(0x24020000, checksumLoc); // Replace load from memory with just writing zero to v0 to bypass logo checksum check + _sw((0x24020000 | ((isPAL) ? 2 : 0)), + getRegionLoc + 8); // Patch function call at getRegionLoc + 8 to always return the disc's region + + // Patch out sceCdDecSet(1,1,5) call to avoid DSP XORing the logo + _sw(0x00000000, cdDecLoc); + // Patch the sceCdDecSet(0,0,0) call after the logo has been read (+0x90 from the first call) to call our own unscrambling function + _sw(0x0c000000 | ((uint32_t)unscrambleLogo >> 2), cdDecLoc + 0x90); FlushCache(0); FlushCache(2); @@ -32,26 +48,22 @@ int doPatchWithOffsets(uint32_t getRegionLoc, uint32_t checksumLoc) { // Patches PS2LOGO region checks void doPatch() { + // Using fixed offsets instead of patterns to reduce ELF size: // ROM 1.10 // 0x100178 — region getter function, with ROMVER check call at +8 bytes. Required to display the logo properly - // 0x100278 — logo checksum check - if (!doPatchWithOffsets(0x100178, 0x100278)) + // 0x1069e8 — first sceCdDecSet call in logo handling function + if (!doPatchWithOffsets(0x100178, 0x1069e8)) return; // ROM 1.20-1.70 // 0x102078 — region getter function, with ROMVER check call at +8 bytes. Required to display the logo properly - // 0x102178 — logo checksum check - if (!doPatchWithOffsets(0x102078, 0x102178)) + // 0x1015b0 — first sceCdDecSet call in logo handling function + if (!doPatchWithOffsets(0x102078, 0x1015b0)) return; - // ROM 1.80-2.10 + // ROM 1.80+ // 0x102018 — region getter function, with ROMVER check call at +8 bytes. Required to display the logo properly - // 0x102118 — logo checksum check - if (!doPatchWithOffsets(0x102018, 0x102118)) + // 0x101578 — first sceCdDecSet call in logo handling function + if (!doPatchWithOffsets(0x102018, 0x101578)) return; - // ROM 2.20+ - // 0x102018 — region getter function, with ROMVER check call at +8 bytes. Required to display the logo properly - // 0x102264 — logo checksum check - if (!doPatchWithOffsets(0x102018, 0x102264)) - asm volatile("j 0x100000"); // Jump to PS2LOGO entrypoint } // Wraps ExecPS2 call for ROM 2.00 @@ -60,6 +72,12 @@ void patchedExecPS2(void *entry, void *gp, int argc, char *argv[]) { ExecPS2(entry, gp, argc, argv); } +// Replaces jump to PS2LOGO entrypoint for ROM 2.20 +void patchedJump(void *entry, void *gp, int argc, char *argv[]) { + doPatch(); + asm volatile("j 0x100000"); // Jump to PS2LOGO entrypoint +} + // Patches PS2LOGO to always use the disc region instead of the console region and removes logo checksum check void patchPS2LOGO(uint32_t epc) { static char syscnf[100] = {0}; @@ -85,7 +103,7 @@ void patchPS2LOGO(uint32_t epc) { if ((_lw(0x1000200) & 0xff000000) == 0x08000000) { // ROM 2.20+ // Replace the jump to 0x100000 in the unpacker with the patching function - _sw((0x08000000 | ((uint32_t)doPatch >> 2)), (uint32_t)0x1000200); + _sw((0x08000000 | ((uint32_t)patchedJump >> 2)), (uint32_t)0x1000200); } else if ((_lw(0x100011c) & 0xff000000) == 0x0c000000) // ROM 2.00 // Hijack the unpacker's ExecPS2 call to execute the patching function diff --git a/utils/res/psu/APPINFO.PBT b/utils/res/psu/APPINFO.PBT index 345eba6..d9fe3de 100644 --- a/utils/res/psu/APPINFO.PBT +++ b/utils/res/psu/APPINFO.PBT @@ -9,7 +9,7 @@ # # Source: https://github.com/pcm720/OSDMenu SET "TITLE" "[SYS] OSDMenu" -SET "VERSION" "1.1.0" +SET "VERSION" "1.2.0" SET "AUTHOR" "pcm720" SET "DESC" "Hacked OSDSYS based off FMCB 1.8 however with many enhancements such as more device support, GameID etc." SET "ELF" "osdmenu.elf"