From b6cfac0e927d0b0d51b16969762d23653107e712 Mon Sep 17 00:00:00 2001 From: AKuHAK <621640+AKuHAK@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:36:16 +0200 Subject: [PATCH] clang-format --- kpatch/README.txt | 136 ++-- kpatch/linkfile-eeload | 220 +++--- kpatch/linkfile-patch | 214 +++--- kpatch/patch0100/EELOAD/EELOAD.c | 527 ++++++------- kpatch/patch0100/EELOAD/Makefile | 16 +- kpatch/patch0100/Makefile | 26 +- kpatch/patch0100/osdsys.c | 60 +- kpatch/patch0101/EELOAD/EELOAD.c | 523 ++++++------- kpatch/patch0101/EELOAD/Makefile | 16 +- kpatch/patch0101/Makefile | 26 +- kpatch/patch0101/osdsys.c | 60 +- osd/Makefile | 180 ++--- osd/README.txt | 182 ++--- osd/common/OSDConfig.c | 566 +++++++------- osd/common/OSDHistory.c | 826 ++++++++++----------- osd/common/OSDInit.c | 1182 +++++++++++++++--------------- osd/common/dvdplayer.c | 805 ++++++++++---------- osd/common/libcdvd_add.c | 293 ++++---- osd/common/libcdvd_add.h | 12 +- osd/common/modelname.c | 156 ++-- osd/common/ps1.c | 558 +++++++------- osd/common/ps2.c | 653 ++++++++--------- osd/include/OSDConfig.h | 160 ++-- osd/include/OSDHistory.h | 89 +-- osd/include/OSDInit.h | 317 ++++---- osd/include/dvdplayer.h | 8 +- osd/include/libcdvd_add.h | 13 +- osd/include/modelname.h | 10 +- osd/include/ps1.h | 16 +- osd/include/ps2.h | 6 +- osd/linkfile | 222 +++--- osd/main.c | 536 +++++++------- osd/psx/plibcdvd_add.h | 5 +- osd/psx/scmd_add.c | 58 +- 34 files changed, 4380 insertions(+), 4297 deletions(-) diff --git a/kpatch/README.txt b/kpatch/README.txt index 5ce022a..f6dc34f 100644 --- a/kpatch/README.txt +++ b/kpatch/README.txt @@ -1,68 +1,68 @@ -OSDSYS patch for ROM v1.0x - 2018/01/29 --------------------------------------------- - -This package contains the source code for clones of the OSDSYS patches, meant for ROM v1.00 and v1.01. -As with the OSD update files, these files were meant to be encapsulated as KELFs. But I will not cover that here. - -The first PlayStation 2 consoles (SCPH-10000 & SCPH-15000) had a considerably different boot ROM from the expansion-bay consoles. -Other than having the earliest-possible IOP and EE kernels, their OSDSYS programs were coded rather differently and had a design flaw that prevented arguments from being passed to memory-card updates. - -These are the original update files and their descriptions: - -Model ROM Update File Description -SCPH-10000 0100JC20000117 osdsys.elf OSDSYS patch (patch0100). -SCPH-10000/SCPH-15000 0101JC20000217 osd110.elf System Driver Update + OSDSYS patch (patch0101). -SCPH-18000 0120JC20001027 osd130.elf System Driver Update + OSDSYS patch (patch0101). Exactly the same in content as osd110.elf. - -The OSDSYS patch will copy a ROM image that contains a replacement EELOAD program, into kernel memory (0x80030000). -It will then patch the EE kernel to scan 0x80030000-0x80040000 for the EELOAD, instead of the boot ROM. - -The System Driver Update attempts to boot the HDD-based update from the HDD unit. -While the SCPH-18000 contained a modern ROM that did not have the same deficiencies as its predecessors, -it is incapable of supporting the CXD9566R PCMCIA controller of the SCPH-18000. As a result, it needed extra help to boot updates from the HDD unit. - -osd110.elf and osd130.elf are the system driver update main executables, which also contain a patch that is similar to the code within osdsys.elf, which install a replacement EELOAD program that will replace rom0:EELOAD. -This patch targets OSDSYS from ROM v1.01J, and does nothing for other ROM versions. -As a result, its patches are also different from the ones that osdsys.elf applies (see below). - -This EELOAD replacement will wait for a request that boots rom0:OSDSYS, before loading rom0:OSDSYS and applying a few fixes to it: - 1. Patch the memory card update dispatcher to pass arguments. - 2. patch0100 only: Overwrite the Japanese message (DVDプレーヤーが起動できませんでした。), which says that that the DVD Player could not be started. - 3. patch0100 only: Replaces update filenames and commands. - -Once the OSDSYS-patching code within EELOAD is run, its effects are binding until the console is hard-reset or powered off. - -Modifications for FMCB, which this package has: ------------------------------------------------ -FMCB sits in for the system driver update. To save space, I made osd110.elf similar to osdsys.elf; instead of being a full system driver update, it will patch OSDSYS to boot osd130.elf. -The osdsys.elf patch was also made to boot osd130.elf directly, hence allowing only one copy of the system driver update to exist. - -Official path of execution: -ROM v1.00J: osdsys.elf -> osd110.elf -> HDD update -ROM v1.01J: osd110.elf -> HDD update -ROM v1.20J: osd130.elf -> HDD update - -New (unofficial) path of execution: -ROM v1.00J: osdsys.elf -> osd130.elf -> HDD update -ROM v1.01J: osd110.elf -> osd130.elf -> HDD update -ROM v1.20J: osd130.elf -> HDD update - -Notes for compilation: ----------------------- -These patches are split into two parts: The main program and an ROM image that contains EELOAD. -It is possible to build the patch without rebuilding EELOAD, by just entering "make". - -The EELOAD module is a binary file, built to be loaded at 0x00082000. To build a ROM image, you need a tool (i.e. ROMIMG). -If you wish to rebuild EELOAD, you need to: -1. Build EELOAD, by entering "make" from within the EELOAD folder. -2. Convert it into a binary file. You can do that with ee-objdump. -3. Generate a new ROM image named 'EELOAD.img', that contains EELOAD. -4. Rebuild the patch. - -Other trivia: -------------- -Within the comments of the ROM images, the EELOAD images are known as "eeload.rom". -Their original paths were as follows: -osdsys.elf: horikawa@phoenix/ee/src/kernel/patch0100/kpatch -osd110.elf: horikawa@phoenix/ee/src/kernel/patch0101/kpatch - +OSDSYS patch for ROM v1.0x - 2018/01/29 +-------------------------------------------- + +This package contains the source code for clones of the OSDSYS patches, meant for ROM v1.00 and v1.01. +As with the OSD update files, these files were meant to be encapsulated as KELFs. But I will not cover that here. + +The first PlayStation 2 consoles (SCPH-10000 & SCPH-15000) had a considerably different boot ROM from the expansion-bay consoles. +Other than having the earliest-possible IOP and EE kernels, their OSDSYS programs were coded rather differently and had a design flaw that prevented arguments from being passed to memory-card updates. + +These are the original update files and their descriptions: + +Model ROM Update File Description +SCPH-10000 0100JC20000117 osdsys.elf OSDSYS patch (patch0100). +SCPH-10000/SCPH-15000 0101JC20000217 osd110.elf System Driver Update + OSDSYS patch (patch0101). +SCPH-18000 0120JC20001027 osd130.elf System Driver Update + OSDSYS patch (patch0101). Exactly the same in content as osd110.elf. + +The OSDSYS patch will copy a ROM image that contains a replacement EELOAD program, into kernel memory (0x80030000). +It will then patch the EE kernel to scan 0x80030000-0x80040000 for the EELOAD, instead of the boot ROM. + +The System Driver Update attempts to boot the HDD-based update from the HDD unit. +While the SCPH-18000 contained a modern ROM that did not have the same deficiencies as its predecessors, +it is incapable of supporting the CXD9566R PCMCIA controller of the SCPH-18000. As a result, it needed extra help to boot updates from the HDD unit. + +osd110.elf and osd130.elf are the system driver update main executables, which also contain a patch that is similar to the code within osdsys.elf, which install a replacement EELOAD program that will replace rom0:EELOAD. +This patch targets OSDSYS from ROM v1.01J, and does nothing for other ROM versions. +As a result, its patches are also different from the ones that osdsys.elf applies (see below). + +This EELOAD replacement will wait for a request that boots rom0:OSDSYS, before loading rom0:OSDSYS and applying a few fixes to it: + 1. Patch the memory card update dispatcher to pass arguments. + 2. patch0100 only: Overwrite the Japanese message (DVDプレーヤーが起動できませんでした。), which says that that the DVD Player could not be started. + 3. patch0100 only: Replaces update filenames and commands. + +Once the OSDSYS-patching code within EELOAD is run, its effects are binding until the console is hard-reset or powered off. + +Modifications for FMCB, which this package has: +----------------------------------------------- +FMCB sits in for the system driver update. To save space, I made osd110.elf similar to osdsys.elf; instead of being a full system driver update, it will patch OSDSYS to boot osd130.elf. +The osdsys.elf patch was also made to boot osd130.elf directly, hence allowing only one copy of the system driver update to exist. + +Official path of execution: +ROM v1.00J: osdsys.elf -> osd110.elf -> HDD update +ROM v1.01J: osd110.elf -> HDD update +ROM v1.20J: osd130.elf -> HDD update + +New (unofficial) path of execution: +ROM v1.00J: osdsys.elf -> osd130.elf -> HDD update +ROM v1.01J: osd110.elf -> osd130.elf -> HDD update +ROM v1.20J: osd130.elf -> HDD update + +Notes for compilation: +---------------------- +These patches are split into two parts: The main program and an ROM image that contains EELOAD. +It is possible to build the patch without rebuilding EELOAD, by just entering "make". + +The EELOAD module is a binary file, built to be loaded at 0x00082000. To build a ROM image, you need a tool (i.e. ROMIMG). +If you wish to rebuild EELOAD, you need to: +1. Build EELOAD, by entering "make" from within the EELOAD folder. +2. Convert it into a binary file. You can do that with ee-objdump. +3. Generate a new ROM image named 'EELOAD.img', that contains EELOAD. +4. Rebuild the patch. + +Other trivia: +------------- +Within the comments of the ROM images, the EELOAD images are known as "eeload.rom". +Their original paths were as follows: +osdsys.elf: horikawa@phoenix/ee/src/kernel/patch0100/kpatch +osd110.elf: horikawa@phoenix/ee/src/kernel/patch0101/kpatch + diff --git a/kpatch/linkfile-eeload b/kpatch/linkfile-eeload index 8dbb5cd..7d03e21 100644 --- a/kpatch/linkfile-eeload +++ b/kpatch/linkfile-eeload @@ -1,110 +1,110 @@ -/* -# _____ ___ ____ ___ ____ -# ____| | ____| | | |____| -# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. -#----------------------------------------------------------------------- -# Copyright 2001-2004, ps2dev - http://www.ps2dev.org -# Licenced under Academic Free License version 2.0 -# Review ps2sdk README & LICENSE files for further details. -# -# $Id$ -# Linkfile script for ee-ld -*/ - -ENTRY(_start); - -SECTIONS { - .text 0x00082000: { - _ftext = . ; - *(.start) - *(.text) - *(.text.*) - *(.gnu.linkonce.t*) - KEEP(*(.init)) - KEEP(*(.fini)) - QUAD(0) - } - - PROVIDE(_etext = .); - PROVIDE(etext = .); - - .reginfo : { *(.reginfo) } - - /* Global/static constructors and deconstructors. */ - .ctors ALIGN(16): { - KEEP(*crtbegin*.o(.ctors)) - KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) - KEEP(*(SORT(.ctors.*))) - KEEP(*(.ctors)) - } - .dtors ALIGN(16): { - KEEP(*crtbegin*.o(.dtors)) - KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) - KEEP(*(SORT(.dtors.*))) - KEEP(*(.dtors)) - } - - /* Static data. */ - .rodata ALIGN(128): { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r*) - } - - .data ALIGN(128): { - _fdata = . ; - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - SORT(CONSTRUCTORS) - } - - .rdata ALIGN(128): { *(.rdata) } - .gcc_except_table ALIGN(128): { *(.gcc_except_table) } - - _gp = ALIGN(128) + 0x7ff0; - .lit4 ALIGN(128): { *(.lit4) } - .lit8 ALIGN(128): { *(.lit8) } - - .sdata ALIGN(128): { - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s*) - } - - _edata = .; - PROVIDE(edata = .); - - /* Uninitialized data. */ - .sbss ALIGN(128) : { - _fbss = . ; - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb*) - *(.scommon) - } - - .bss ALIGN(128) : { - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b*) - *(COMMON) - } - _end_bss = .; - - /* Symbols needed by crt0.s. */ - PROVIDE(_heap_size = 0x2000); - PROVIDE(_stack_size = 0x2000); - - _stack = ALIGN(128); - PROVIDE(_stack = .); - . = _stack + _stack_size; - - _end = .; - PROVIDE(end = .); - - /* Unwanted stuff */ - /DISCARD/ : { - * ( .MIPS.abiflags ) - } -} +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# Linkfile script for ee-ld +*/ + +ENTRY(_start); + +SECTIONS { + .text 0x00082000: { + _ftext = . ; + *(.start) + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + KEEP(*(.init)) + KEEP(*(.fini)) + QUAD(0) + } + + PROVIDE(_etext = .); + PROVIDE(etext = .); + + .reginfo : { *(.reginfo) } + + /* Global/static constructors and deconstructors. */ + .ctors ALIGN(16): { + KEEP(*crtbegin*.o(.ctors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + } + .dtors ALIGN(16): { + KEEP(*crtbegin*.o(.dtors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + } + + /* Static data. */ + .rodata ALIGN(128): { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .data ALIGN(128): { + _fdata = . ; + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + + .rdata ALIGN(128): { *(.rdata) } + .gcc_except_table ALIGN(128): { *(.gcc_except_table) } + + _gp = ALIGN(128) + 0x7ff0; + .lit4 ALIGN(128): { *(.lit4) } + .lit8 ALIGN(128): { *(.lit8) } + + .sdata ALIGN(128): { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + + _edata = .; + PROVIDE(edata = .); + + /* Uninitialized data. */ + .sbss ALIGN(128) : { + _fbss = . ; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb*) + *(.scommon) + } + + .bss ALIGN(128) : { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + } + _end_bss = .; + + /* Symbols needed by crt0.s. */ + PROVIDE(_heap_size = 0x2000); + PROVIDE(_stack_size = 0x2000); + + _stack = ALIGN(128); + PROVIDE(_stack = .); + . = _stack + _stack_size; + + _end = .; + PROVIDE(end = .); + + /* Unwanted stuff */ + /DISCARD/ : { + * ( .MIPS.abiflags ) + } +} diff --git a/kpatch/linkfile-patch b/kpatch/linkfile-patch index ed3673f..71b48ba 100644 --- a/kpatch/linkfile-patch +++ b/kpatch/linkfile-patch @@ -1,107 +1,107 @@ -/* -# _____ ___ ____ ___ ____ -# ____| | ____| | | |____| -# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. -#----------------------------------------------------------------------- -# Copyright 2001-2004, ps2dev - http://www.ps2dev.org -# Licenced under Academic Free License version 2.0 -# Review ps2sdk README & LICENSE files for further details. -# -# $Id$ -# Linkfile script for ee-ld -*/ - -ENTRY(_start); - -SECTIONS { - .text 0x00200000: { - _ftext = . ; - *(.start) - *(.text) - *(.text.*) - *(.gnu.linkonce.t*) - KEEP(*(.init)) - KEEP(*(.fini)) - QUAD(0) - } - - PROVIDE(_etext = .); - PROVIDE(etext = .); - - .reginfo : { *(.reginfo) } - - /* Global/static constructors and deconstructors. */ - .ctors ALIGN(16): { - KEEP(*crtbegin*.o(.ctors)) - KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) - KEEP(*(SORT(.ctors.*))) - KEEP(*(.ctors)) - } - .dtors ALIGN(16): { - KEEP(*crtbegin*.o(.dtors)) - KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) - KEEP(*(SORT(.dtors.*))) - KEEP(*(.dtors)) - } - - /* Static data. */ - .rodata ALIGN(128): { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r*) - } - - .data ALIGN(128): { - _fdata = . ; - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - SORT(CONSTRUCTORS) - } - - .rdata ALIGN(128): { *(.rdata) } - .gcc_except_table ALIGN(128): { *(.gcc_except_table) } - - _gp = ALIGN(128) + 0x7ff0; - .lit4 ALIGN(128): { *(.lit4) } - .lit8 ALIGN(128): { *(.lit8) } - - .sdata ALIGN(128): { - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s*) - } - - _edata = .; - PROVIDE(edata = .); - - /* Uninitialized data. */ - .sbss ALIGN(128) : { - _fbss = . ; - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb*) - *(.scommon) - } - - .bss ALIGN(128) : { - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b*) - *(COMMON) - } - _end_bss = .; - - _end = . ; - PROVIDE(end = .); - - /* Symbols needed by crt0.s. */ - PROVIDE(_heap_size = -1); - PROVIDE(_stack = -1); - PROVIDE(_stack_size = 128*1024); - - /* Unwanted stuff */ - /DISCARD/ : { - * ( .MIPS.abiflags ) - } -} +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# Linkfile script for ee-ld +*/ + +ENTRY(_start); + +SECTIONS { + .text 0x00200000: { + _ftext = . ; + *(.start) + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + KEEP(*(.init)) + KEEP(*(.fini)) + QUAD(0) + } + + PROVIDE(_etext = .); + PROVIDE(etext = .); + + .reginfo : { *(.reginfo) } + + /* Global/static constructors and deconstructors. */ + .ctors ALIGN(16): { + KEEP(*crtbegin*.o(.ctors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + } + .dtors ALIGN(16): { + KEEP(*crtbegin*.o(.dtors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + } + + /* Static data. */ + .rodata ALIGN(128): { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .data ALIGN(128): { + _fdata = . ; + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + + .rdata ALIGN(128): { *(.rdata) } + .gcc_except_table ALIGN(128): { *(.gcc_except_table) } + + _gp = ALIGN(128) + 0x7ff0; + .lit4 ALIGN(128): { *(.lit4) } + .lit8 ALIGN(128): { *(.lit8) } + + .sdata ALIGN(128): { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + + _edata = .; + PROVIDE(edata = .); + + /* Uninitialized data. */ + .sbss ALIGN(128) : { + _fbss = . ; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb*) + *(.scommon) + } + + .bss ALIGN(128) : { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + } + _end_bss = .; + + _end = . ; + PROVIDE(end = .); + + /* Symbols needed by crt0.s. */ + PROVIDE(_heap_size = -1); + PROVIDE(_stack = -1); + PROVIDE(_stack_size = 128*1024); + + /* Unwanted stuff */ + /DISCARD/ : { + * ( .MIPS.abiflags ) + } +} diff --git a/kpatch/patch0100/EELOAD/EELOAD.c b/kpatch/patch0100/EELOAD/EELOAD.c index 046308c..08e267b 100644 --- a/kpatch/patch0100/EELOAD/EELOAD.c +++ b/kpatch/patch0100/EELOAD/EELOAD.c @@ -1,251 +1,276 @@ -/* - Filename: EELOAD - Description: EE executable Loader (OSDSYS update). Largely the same as EELOAD from ROM v1.01, but has a patching mechanism. - Date: 2013/04/25 - Arguments: - argv[0]= or <"moduleload"> - (Or if "moduleload" was specified as the first argument): - argv[1...n]= commands, where: - "-m " -> Loads a regular IOP module. - "-k " -> Loads an encrypted IOP module. - "-x " -> Loads and executes an encrypted EE program. - - (Strings remaining in the argv[] array are arguments that are to be passed to the loaded program) - - Other notes: If no arguments are specified, it loads rom0:OSDSYS. -*/ - -#include -#include -#include -#include -#include -#include -#include - -//0x00083e80 -#define NUM_BOOT_PATHS 1 -static char *DefaultBootPaths[NUM_BOOT_PATHS+1]={"rom0:OSDSYS", NULL}; - -//0x00083e88 -static t_ExecData ElfData; - -//0x00083ea0 - the patch that solves the problem with the browser being unable to pass arguments to the update. -//The same as the v1.01 OSDSYS patch, except for the addresses. -static const unsigned int OSDSYS_patch[]={ - 0x18a0000a, //blez a1, +11 - 0x3c0b004f, //lui t3, $004f - 0x25670100, //addiu a3, t3, $0100 - 0x00a0402d, //daddu t0, a1, zero - 0x8cc20000, //lw v0, $0000(a2) - 0x2508ffff, //addiu t0, t0, $ffff - 0x24c60004, //addiu a2, a2, $0004 - 0xace20000, //sw v0, $0000(a3) - 0x00000000, //nop - 0x1500fffa, //bne t0, zero, -5 - 0x24e70004, //addiu a3, a3, $0004 - 0x3c0a0029, //lui t2, $0029 - 0x8d4ad280, //lw t2, $d280(t2) - 0x24080001, //addiu t0, zero, $0001 - 0x010a102a, //slt v0, t0, t2 - 0x10400014, //beq v0, zero, +21 - 0x28a20010, //slti v0, a1, $0010 - 0x10400012, //beq v0, zero, +19 - 0x3c02004f, //lui v0, $004f - 0x00051880, //sll v1, a1, 2 - 0x24420100, //addiu v0, v0, $0100 - 0x3c070028, //lui a3, $0028 - 0x00624821, //addu t1, v1, v0 - 0x34e7d288, //ori a3, a3, $d288 - 0x8ce30000, //lw v1, $0000(a3) - 0x00000000, //nop - 0x25080001, //addiu t0, t0, $0001 - 0x24e70004, //addiu a3, a3, $0004 - 0x24a50001, //addiu a1, a1, $0001 - 0xad230000, //sw v1, $0000(t1) - 0x010a102a, //slt v0, t0, t2 - 0x10400004, //beq v0, zero, +5 - 0x25290004, //addiu t1, t1, $0004 - 0x28a20010, //slti v0, a1, $0010 - 0x5440fff7, //bnel v0, zero, -8 - 0x8ce30000, //lw v1, $0000(a3) - 0x24030006, //addiu v1, zero, $0006 - 0x0080202d, //daddu a0, a0, zero - 0x00a0282d, //daddu a1, a1, zero - 0x25660100, //addiu a2, t3, $0100 - 0x00c0302d, //daddu a2, a2, zero - 0x0000000c, //syscall (00000) - 0x03e00008, //jr ra - 0x00000000 //nop -}; - -/* 0x000820e8*/ -static void PatchOSDSYS(void){ - volatile unsigned int *ptr; - unsigned int i, size; - - FlushCache(0); - - //Copy the patch. - strcpy((char*)0x0028b9b0, "DVDv[[Nł܂łB"); //Don't know why they need to patch this as the original message is exactly the same. D: - //Originally, these lines made the OSD use osd110.elf instead. But since FMCB's v1.10 update only causes the v1.01 OSD to use osd130.elf, do the same thing here. The v1.20 update is the first update that doesn't require patching. - strcpy((char*)0x0028b770, "/BIEXEC-SYSTEM/osd130.elf"); - strcpy((char*)0x0028b790, "-x mc%d:/BIEXEC-SYSTEM/osd130.elf"); - strcpy((char*)0x0028b8a0, "osd130.elf"); - - *(volatile unsigned int*)0x00204ad0=((*(volatile unsigned int*)0x00204ad0)&0xFC000000)|0x0013c000; //jal 0x004f0000 - - size=sizeof(OSDSYS_patch); //It did a calculation on the size of the patch by subtracting the end from the start. - - for(i=0,ptr=(volatile unsigned int*)0x004f0000; i EE) - *DMA_REG_STAT=0x20; - while(*R_EE_SBUS_REG40&0x3000){}; - - for(i=0x1000; i>0; i--){}; - } -} - -/* 0x00082258 */ -static void SyncIOP(void){ - while((*R_EE_SBUS_SMFLAG&SIF_STAT_BOOTEND)==0){}; - *R_EE_SBUS_SMFLAG=SIF_STAT_BOOTEND; -} - -/* 0x00082298 */ -static void ResetIOP(void){ - SifIopReset("", 0); - while(!SifIopIsAlive()){}; - - SyncIOP(); -} - -/* 0x000822c8 */ -static void AckSIF0(void){ - if(*R_EE_SBUS_REG40&0x20){ - DI(); - ee_kmode_enter(); - - *(volatile unsigned int*)0xBD000040=0x20; - - ee_kmode_exit(); - EI(); - } - - if(*DMA_REG_STAT&0x20) - *DMA_REG_STAT=0x20; -} - -/* 0x00082368 - Returns NULL if the argument doesn't contain the specified switch, otherwise, returns the first character after the switch. -*/ -static const char *IsSwitchCheck(const char *SwitchString, const char *cmd){ - while(*SwitchString!='\0'){ - if(*SwitchString!=*cmd) return NULL; - SwitchString++; - cmd++; - } - - return cmd; -} - -/* 0x000823a8 */ -static void ExecExecutable(int argc, char *argv[]){ - FlushCache(0); - SifExitRpc(); //Original had SifExitCmd(); - - ExecPS2((void *)ElfData.epc, (void *)ElfData.gp, argc, argv); -} - -/* 0x00082400 */ -static void BootError(const char *path){ - char *argv[2]; - - SifExitRpc(); //Original had SifExitCmd(); - - argv[0]="BootError"; - argv[1]=(char*)path; - - ExecOSD(2, argv); -} - -/* 0x00082440 */ -int main(int argc, char *argv[]){ - const char *CommandString; - int i; - - if(argc>=2){ - argv++; - argc--; - SyncSIF0(); - ResetIOP(); - AckSIF0(); - - SifInitRpc(0); - - /* 0x000824b8 */ - if(IsSwitchCheck("moduleload", argv[0])!=NULL){ - argc--; - argv++; - - while(argc>0){ - if((CommandString=IsSwitchCheck("-m ", argv[0]))!=NULL){ - SifLoadModule(CommandString, 0, NULL); - } - else if((CommandString=IsSwitchCheck("-k ", argv[0]))!=NULL){ - SifLoadModuleEncrypted(CommandString, 0, NULL); - } - else if((CommandString=IsSwitchCheck("-x ", argv[0]))!=NULL){ - FlushCache(0); - if(SifLoadElfEncrypted(CommandString, &ElfData)<0){ - BootError(CommandString); - } - - argv[0]=(char*)CommandString; - ExecExecutable(argc, argv); - } - else break; - - argc--; - argv++; - } - } - - FlushCache(0); - if(SifLoadElf(argv[0], &ElfData)<0){ - BootError(argv[0]); - } - - if(IsSwitchCheck("rom0:OSDSYS", argv[0])!=NULL){ - PatchOSDSYS(); - } - - ExecExecutable(argc, argv); - } - - SyncIOP(); - SifInitRpc(0); - FlushCache(0); - for(i=0; i= 0) - break; - } - - PatchOSDSYS(); - ExecExecutable(1, &DefaultBootPaths[i]); - - return 0; -} +/* + Filename: EELOAD + Description: EE executable Loader (OSDSYS update). Largely the same as EELOAD from ROM v1.01, but has a patching mechanism. + Date: 2013/04/25 + Arguments: + argv[0]= or <"moduleload"> + (Or if "moduleload" was specified as the first argument): + argv[1...n]= commands, where: + "-m " -> Loads a regular IOP module. + "-k " -> Loads an encrypted IOP module. + "-x " -> Loads and executes an encrypted EE program. + + (Strings remaining in the argv[] array are arguments that are to be passed to the loaded program) + + Other notes: If no arguments are specified, it loads rom0:OSDSYS. +*/ + +#include +#include +#include +#include +#include +#include +#include + +// 0x00083e80 +#define NUM_BOOT_PATHS 1 +static char *DefaultBootPaths[NUM_BOOT_PATHS + 1] = {"rom0:OSDSYS", NULL}; + +// 0x00083e88 +static t_ExecData ElfData; + +// 0x00083ea0 - the patch that solves the problem with the browser being unable to pass arguments to the update. +// The same as the v1.01 OSDSYS patch, except for the addresses. +static const unsigned int OSDSYS_patch[] = { + 0x18a0000a, // blez a1, +11 + 0x3c0b004f, // lui t3, $004f + 0x25670100, // addiu a3, t3, $0100 + 0x00a0402d, // daddu t0, a1, zero + 0x8cc20000, // lw v0, $0000(a2) + 0x2508ffff, // addiu t0, t0, $ffff + 0x24c60004, // addiu a2, a2, $0004 + 0xace20000, // sw v0, $0000(a3) + 0x00000000, // nop + 0x1500fffa, // bne t0, zero, -5 + 0x24e70004, // addiu a3, a3, $0004 + 0x3c0a0029, // lui t2, $0029 + 0x8d4ad280, // lw t2, $d280(t2) + 0x24080001, // addiu t0, zero, $0001 + 0x010a102a, // slt v0, t0, t2 + 0x10400014, // beq v0, zero, +21 + 0x28a20010, // slti v0, a1, $0010 + 0x10400012, // beq v0, zero, +19 + 0x3c02004f, // lui v0, $004f + 0x00051880, // sll v1, a1, 2 + 0x24420100, // addiu v0, v0, $0100 + 0x3c070028, // lui a3, $0028 + 0x00624821, // addu t1, v1, v0 + 0x34e7d288, // ori a3, a3, $d288 + 0x8ce30000, // lw v1, $0000(a3) + 0x00000000, // nop + 0x25080001, // addiu t0, t0, $0001 + 0x24e70004, // addiu a3, a3, $0004 + 0x24a50001, // addiu a1, a1, $0001 + 0xad230000, // sw v1, $0000(t1) + 0x010a102a, // slt v0, t0, t2 + 0x10400004, // beq v0, zero, +5 + 0x25290004, // addiu t1, t1, $0004 + 0x28a20010, // slti v0, a1, $0010 + 0x5440fff7, // bnel v0, zero, -8 + 0x8ce30000, // lw v1, $0000(a3) + 0x24030006, // addiu v1, zero, $0006 + 0x0080202d, // daddu a0, a0, zero + 0x00a0282d, // daddu a1, a1, zero + 0x25660100, // addiu a2, t3, $0100 + 0x00c0302d, // daddu a2, a2, zero + 0x0000000c, // syscall (00000) + 0x03e00008, // jr ra + 0x00000000 // nop +}; + +/* 0x000820e8*/ +static void PatchOSDSYS(void) +{ + volatile unsigned int *ptr; + unsigned int i, size; + + FlushCache(0); + + // Copy the patch. + strcpy((char *)0x0028b9b0, "DVD�v���[���[���N���ł��܂���ł����B"); // Don't know why they need to patch this as the original message is exactly the same. D: + // Originally, these lines made the OSD use osd110.elf instead. But since FMCB's v1.10 update only causes the v1.01 OSD to use osd130.elf, do the same thing here. The v1.20 update is the first update that doesn't require patching. + strcpy((char *)0x0028b770, "/BIEXEC-SYSTEM/osd130.elf"); + strcpy((char *)0x0028b790, "-x mc%d:/BIEXEC-SYSTEM/osd130.elf"); + strcpy((char *)0x0028b8a0, "osd130.elf"); + + *(volatile unsigned int *)0x00204ad0 = ((*(volatile unsigned int *)0x00204ad0) & 0xFC000000) | 0x0013c000; // jal 0x004f0000 + + size = sizeof(OSDSYS_patch); // It did a calculation on the size of the patch by subtracting the end from the start. + + for (i = 0, ptr = (volatile unsigned int *)0x004f0000; i < size; ptr++, i += 4) + { + *ptr = OSDSYS_patch[i / 4]; + } + + FlushCache(0); + FlushCache(2); +} + +/* 0x000821d0 */ +static void SyncSIF0(void) +{ + int i; + + // If SIF0 has incoming data, initialize SIF0 and acknowledge incoming data. + if (*DMA_REG_STAT & 0x20) + { + SifSetDChain(); // Re-initialize SIF0 (IOP -> EE) + *DMA_REG_STAT = 0x20; + while (*R_EE_SBUS_REG40 & 0x3000) {}; + + for (i = 0x1000; i > 0; i--) {}; + } +} + +/* 0x00082258 */ +static void SyncIOP(void) +{ + while ((*R_EE_SBUS_SMFLAG & SIF_STAT_BOOTEND) == 0) {}; + *R_EE_SBUS_SMFLAG = SIF_STAT_BOOTEND; +} + +/* 0x00082298 */ +static void ResetIOP(void) +{ + SifIopReset("", 0); + while (!SifIopIsAlive()) {}; + + SyncIOP(); +} + +/* 0x000822c8 */ +static void AckSIF0(void) +{ + if (*R_EE_SBUS_REG40 & 0x20) + { + DI(); + ee_kmode_enter(); + + *(volatile unsigned int *)0xBD000040 = 0x20; + + ee_kmode_exit(); + EI(); + } + + if (*DMA_REG_STAT & 0x20) + *DMA_REG_STAT = 0x20; +} + +/* 0x00082368 + Returns NULL if the argument doesn't contain the specified switch, otherwise, returns the first character after the switch. +*/ +static const char *IsSwitchCheck(const char *SwitchString, const char *cmd) +{ + while (*SwitchString != '\0') + { + if (*SwitchString != *cmd) + return NULL; + SwitchString++; + cmd++; + } + + return cmd; +} + +/* 0x000823a8 */ +static void ExecExecutable(int argc, char *argv[]) +{ + FlushCache(0); + SifExitRpc(); // Original had SifExitCmd(); + + ExecPS2((void *)ElfData.epc, (void *)ElfData.gp, argc, argv); +} + +/* 0x00082400 */ +static void BootError(const char *path) +{ + char *argv[2]; + + SifExitRpc(); // Original had SifExitCmd(); + + argv[0] = "BootError"; + argv[1] = (char *)path; + + ExecOSD(2, argv); +} + +/* 0x00082440 */ +int main(int argc, char *argv[]) +{ + const char *CommandString; + int i; + + if (argc >= 2) + { + argv++; + argc--; + SyncSIF0(); + ResetIOP(); + AckSIF0(); + + SifInitRpc(0); + + /* 0x000824b8 */ + if (IsSwitchCheck("moduleload", argv[0]) != NULL) + { + argc--; + argv++; + + while (argc > 0) + { + if ((CommandString = IsSwitchCheck("-m ", argv[0])) != NULL) + { + SifLoadModule(CommandString, 0, NULL); + } + else if ((CommandString = IsSwitchCheck("-k ", argv[0])) != NULL) + { + SifLoadModuleEncrypted(CommandString, 0, NULL); + } + else if ((CommandString = IsSwitchCheck("-x ", argv[0])) != NULL) + { + FlushCache(0); + if (SifLoadElfEncrypted(CommandString, &ElfData) < 0) + { + BootError(CommandString); + } + + argv[0] = (char *)CommandString; + ExecExecutable(argc, argv); + } + else + break; + + argc--; + argv++; + } + } + + FlushCache(0); + if (SifLoadElf(argv[0], &ElfData) < 0) + { + BootError(argv[0]); + } + + if (IsSwitchCheck("rom0:OSDSYS", argv[0]) != NULL) + { + PatchOSDSYS(); + } + + ExecExecutable(argc, argv); + } + + SyncIOP(); + SifInitRpc(0); + FlushCache(0); + for (i = 0; i < NUM_BOOT_PATHS; i++) + { + if (SifLoadElf(DefaultBootPaths[i], &ElfData) >= 0) + break; + } + + PatchOSDSYS(); + ExecExecutable(1, &DefaultBootPaths[i]); + + return 0; +} diff --git a/kpatch/patch0100/EELOAD/Makefile b/kpatch/patch0100/EELOAD/Makefile index cc05a7d..adbd93c 100644 --- a/kpatch/patch0100/EELOAD/Makefile +++ b/kpatch/patch0100/EELOAD/Makefile @@ -1,8 +1,8 @@ -EE_BIN = EELOAD.elf -EE_OBJS = EELOAD.o - -CRT0_OBJ_S = ../../crt0-eeload.s -LINKFILE = ../../linkfile-eeload - -include $(PS2SDK)/Defs.make -include ../../Rules.eeload.make +EE_BIN = EELOAD.elf +EE_OBJS = EELOAD.o + +CRT0_OBJ_S = ../../crt0-eeload.s +LINKFILE = ../../linkfile-eeload + +include $(PS2SDK)/Defs.make +include ../../Rules.eeload.make diff --git a/kpatch/patch0100/Makefile b/kpatch/patch0100/Makefile index 1596ed3..229861e 100644 --- a/kpatch/patch0100/Makefile +++ b/kpatch/patch0100/Makefile @@ -1,13 +1,13 @@ -EE_BIN = osdsys.elf - -EE_OBJS = osdsys.o EELOAD_img.o - -include $(PS2SDK)/Defs.make -include ../Rules.patch.make - -clean: - rm -f EELOAD_img.c - -EELOAD_img.o: - bin2c EELOAD.img EELOAD_img.c EELOAD_img - $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c EELOAD_img.c -o EELOAD_img.o +EE_BIN = osdsys.elf + +EE_OBJS = osdsys.o EELOAD_img.o + +include $(PS2SDK)/Defs.make +include ../Rules.patch.make + +clean: + rm -f EELOAD_img.c + +EELOAD_img.o: + bin2c EELOAD.img EELOAD_img.c EELOAD_img + $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c EELOAD_img.c -o EELOAD_img.o diff --git a/kpatch/patch0100/osdsys.c b/kpatch/patch0100/osdsys.c index 375744e..ca0f070 100644 --- a/kpatch/patch0100/osdsys.c +++ b/kpatch/patch0100/osdsys.c @@ -1,29 +1,31 @@ -#include - -extern unsigned char EELOAD_img[]; -extern unsigned int size_EELOAD_img; - -void *_start(void){ - unsigned int i; - vu32 *start; - - DI(); - ee_kmode_enter(); - - for(i=0,start=(vu32*)0x80030000; i + +extern unsigned char EELOAD_img[]; +extern unsigned int size_EELOAD_img; + +void *_start(void) +{ + unsigned int i; + vu32 *start; + + DI(); + ee_kmode_enter(); + + for (i = 0, start = (vu32 *)0x80030000; i < size_EELOAD_img / 4; i++) + { + start[i] = ((vu32 *)EELOAD_img)[i]; + } + + *(vu16 *)0x80005670 = 0x8003; // Patch the start of address range of the IOPRP image containing EELOAD. + *(vu16 *)0x80005674 = 0x8004; // Patch the end of address range of the IOPRP image containing EELOAD. + + ee_kmode_exit(); + EI(); + + FlushCache(0); + FlushCache(2); + + ExecOSD(0, NULL); + + return ((void *)0x80005670); +} diff --git a/kpatch/patch0101/EELOAD/EELOAD.c b/kpatch/patch0101/EELOAD/EELOAD.c index 6ad265b..59ca225 100644 --- a/kpatch/patch0101/EELOAD/EELOAD.c +++ b/kpatch/patch0101/EELOAD/EELOAD.c @@ -1,249 +1,274 @@ -/* - Filename: EELOAD - Description: EE executable Loader (OSDSYS update). Largely the same as EELOAD from ROM v1.01, but has a patching mechanism. - Date: 2013/10/13 - Arguments: - argv[0]= or <"moduleload"> - (Or if "moduleload" was specified as the first argument): - argv[1...n]= commands, where: - "-m " -> Loads a regular IOP module. - "-k " -> Loads an encrypted IOP module. - "-x " -> Loads and executes an encrypted EE program. - - (Strings remaining in the argv[] array are arguments that are to be passed to the loaded program) - - Other notes: If no arguments are specified, it loads rom0:OSDSYS. -*/ - -#include -#include -#include -#include -#include -#include -#include - -//0x00084080 -#define NUM_BOOT_PATHS 1 -static char *DefaultBootPaths[NUM_BOOT_PATHS+1]={"rom0:OSDSYS", NULL}; - -//0x00084088 -static t_ExecData ElfData; - -//0x000840a0 - the patch that solves the problem with the browser being unable to pass arguments to the update. -//The same as the v1.00 OSDSYS patch, except for the addresses. -static const unsigned int OSDSYS_patch[]={ - 0x18a0000a, //blez a1, +11 - 0x3c0b004f, //lui t3, $004f - 0x25670100, //addiu a3, t3, $0100 - 0x00a0402d, //daddu t0, a1, zero - 0x8cc20000, //lw v0, $0000(a2) - 0x2508ffff, //addiu t0, t0, $ffff - 0x24c60004, //addiu a2, a2, $0004 - 0xace20000, //sw v0, $0000(a3) - 0x00000000, //nop - 0x1500fffa, //bne t0, zero, -5 - 0x24e70004, //addiu a3, a3, $0004 - 0x3c0a0029, //lui t2, $0029 - 0x8d4ad800, //lw t2, $d800(t2) - 0x24080001, //addiu t0, zero, $0001 - 0x010a102a, //slt v0, t0, t2 - 0x10400014, //beq v0, zero, +21 - 0x28a20010, //slti v0, a1, $0010 - 0x10400012, //beq v0, zero, +19 - 0x3c02004f, //lui v0, $004f - 0x00051880, //sll v1, a1, 2 - 0x24420100, //addiu v0, v0, $0100 - 0x3c070028, //lui a3, $0028 - 0x00624821, //addu t1, v1, v0 - 0x34e7d808, //ori a3, a3, $d808 - 0x8ce30000, //lw v1, $0000(a3) - 0x00000000, //nop - 0x25080001, //addiu t0, t0, $0001 - 0x24e70004, //addiu a3, a3, $0004 - 0x24a50001, //addiu a1, a1, $0001 - 0xad230000, //sw v1, $0000(t1) - 0x010a102a, //slt v0, t0, t2 - 0x10400004, //beq v0, zero, +5 - 0x25290004, //addiu t1, t1, $0004 - 0x28a20010, //slti v0, a1, $0010 - 0x5440fff7, //bnel v0, zero, -8 - 0x8ce30000, //lw v1, $0000(a3) - 0x24030006, //add iu v1, zero, $0006 - 0x0080202d, //daddu a0, a0, zero - 0x00a0282d, //daddu a1, a1, zero - 0x25660100, //addiu a2, t3, $0100 - 0x00c0302d, //daddu a2, a2, zero - 0x0000000c, //syscall (00000) - 0x03e00008, //jr ra - 0x00000000 //nop -}; - -/* 0x000820e8 */ -static void PatchOSDSYS(void){ - volatile unsigned int *ptr; - unsigned int i, size; - - FlushCache(0); - - //These lines weren't originally here, but I would like the kernel to use the update for v1.20 instead to save space (Since it's the first update that doesn't involve kernel patching). - strcpy((char*)0x0028bd00, "/BIEXEC-SYSTEM/osd130.elf"); - strcpy((char*)0x0028bca8, "-x mc0:/BIEXEC-SYSTEM/osd130.elf"); - strcpy((char*)0x0028be08, "osd130.elf"); - - //Copy the patch. - *(volatile unsigned int*)0x00204b28=((*(volatile unsigned int*)0x00204b28)&0xFC000000)|0x0013c000; //jal 0x004f0000 - - size=sizeof(OSDSYS_patch); //It did a calculation on the size of the patch by subtracting the end from the start. - - for(i=0,ptr=(volatile unsigned int*)0x004f0000; i EE) - *DMA_REG_STAT=0x20; - while(*R_EE_SBUS_REG40&0x3000){}; - - for(i=0x1000; i>0; i--){}; - } -} - -/* 0x00082208 */ -static void SyncIOP(void){ - while((*R_EE_SBUS_SMFLAG&SIF_STAT_BOOTEND)==0){}; - *R_EE_SBUS_SMFLAG=SIF_STAT_BOOTEND; -} - -/* 0x00082248 */ -static void ResetIOP(void){ - SifIopReset("", 0); - while(!SifIopIsAlive()){}; - - SyncIOP(); -} - -/* 0x00082278 */ -static void AckSIF0(void){ - if(*R_EE_SBUS_REG40&0x20){ - DI(); - ee_kmode_enter(); - - *(volatile unsigned int*)0xBD000040=0x20; - - ee_kmode_exit(); - EI(); - } - - if(*DMA_REG_STAT&0x20) - *DMA_REG_STAT=0x20; -} - -/* 0x00082300 - Returns NULL if the argument doesn't contain the specified switch, otherwise, returns the first character after the switch. -*/ -static const char *IsSwitchCheck(const char *SwitchString, const char *cmd){ - while(*SwitchString!='\0'){ - if(*SwitchString!=*cmd) return NULL; - SwitchString++; - cmd++; - } - - return cmd; -} - -/* 0x00082340 */ -static void ExecExecutable(int argc, char *argv[]){ - FlushCache(0); - SifExitRpc(); //Original had SifExitCmd(); - - ExecPS2((void *)ElfData.epc, (void *)ElfData.gp, argc, argv); -} - -/* 0x00082398 */ -static void BootError(const char *path){ - char *argv[2]; - - SifExitRpc(); //Original had SifExitCmd(); - - argv[0]="BootError"; - argv[1]=(char*)path; - - ExecOSD(2, argv); -} - -//0x000823d8 -int main(int argc, char *argv[]){ - const char *CommandString; - int i; - - if(argc>=2){ - argv++; - argc--; - SyncSIF0(); - ResetIOP(); - AckSIF0(); - - SifInitRpc(0); - - if(IsSwitchCheck("moduleload", argv[0])!=NULL){ - argc--; - argv++; - - while(argc>0){ - if((CommandString=IsSwitchCheck("-m ", argv[0]))!=NULL){ - SifLoadModule(CommandString, 0, NULL); - } - else if((CommandString=IsSwitchCheck("-k ", argv[0]))!=NULL){ - SifLoadModuleEncrypted(CommandString, 0, NULL); - } - else if((CommandString=IsSwitchCheck("-x ", argv[0]))!=NULL){ - FlushCache(0); - if(SifLoadElfEncrypted(CommandString, &ElfData)<0){ - BootError(CommandString); - } - - argv[0]=(char*)CommandString; - ExecExecutable(argc, argv); - } - else break; - - argc--; - argv++; - } - } - - FlushCache(0); - if(SifLoadElf(argv[0], &ElfData)<0){ - BootError(argv[0]); - } - - if(IsSwitchCheck("rom0:OSDSYS", argv[0])!=NULL){ - PatchOSDSYS(); - } - - ExecExecutable(argc, argv); - } - - SyncIOP(); - SifInitRpc(0); - FlushCache(0); - for(i=0; i= 0) - break; - } - - PatchOSDSYS(); - ExecExecutable(1, &DefaultBootPaths[i]); - - return 0; -} +/* + Filename: EELOAD + Description: EE executable Loader (OSDSYS update). Largely the same as EELOAD from ROM v1.01, but has a patching mechanism. + Date: 2013/10/13 + Arguments: + argv[0]= or <"moduleload"> + (Or if "moduleload" was specified as the first argument): + argv[1...n]= commands, where: + "-m " -> Loads a regular IOP module. + "-k " -> Loads an encrypted IOP module. + "-x " -> Loads and executes an encrypted EE program. + + (Strings remaining in the argv[] array are arguments that are to be passed to the loaded program) + + Other notes: If no arguments are specified, it loads rom0:OSDSYS. +*/ + +#include +#include +#include +#include +#include +#include +#include + +// 0x00084080 +#define NUM_BOOT_PATHS 1 +static char *DefaultBootPaths[NUM_BOOT_PATHS + 1] = {"rom0:OSDSYS", NULL}; + +// 0x00084088 +static t_ExecData ElfData; + +// 0x000840a0 - the patch that solves the problem with the browser being unable to pass arguments to the update. +// The same as the v1.00 OSDSYS patch, except for the addresses. +static const unsigned int OSDSYS_patch[] = { + 0x18a0000a, // blez a1, +11 + 0x3c0b004f, // lui t3, $004f + 0x25670100, // addiu a3, t3, $0100 + 0x00a0402d, // daddu t0, a1, zero + 0x8cc20000, // lw v0, $0000(a2) + 0x2508ffff, // addiu t0, t0, $ffff + 0x24c60004, // addiu a2, a2, $0004 + 0xace20000, // sw v0, $0000(a3) + 0x00000000, // nop + 0x1500fffa, // bne t0, zero, -5 + 0x24e70004, // addiu a3, a3, $0004 + 0x3c0a0029, // lui t2, $0029 + 0x8d4ad800, // lw t2, $d800(t2) + 0x24080001, // addiu t0, zero, $0001 + 0x010a102a, // slt v0, t0, t2 + 0x10400014, // beq v0, zero, +21 + 0x28a20010, // slti v0, a1, $0010 + 0x10400012, // beq v0, zero, +19 + 0x3c02004f, // lui v0, $004f + 0x00051880, // sll v1, a1, 2 + 0x24420100, // addiu v0, v0, $0100 + 0x3c070028, // lui a3, $0028 + 0x00624821, // addu t1, v1, v0 + 0x34e7d808, // ori a3, a3, $d808 + 0x8ce30000, // lw v1, $0000(a3) + 0x00000000, // nop + 0x25080001, // addiu t0, t0, $0001 + 0x24e70004, // addiu a3, a3, $0004 + 0x24a50001, // addiu a1, a1, $0001 + 0xad230000, // sw v1, $0000(t1) + 0x010a102a, // slt v0, t0, t2 + 0x10400004, // beq v0, zero, +5 + 0x25290004, // addiu t1, t1, $0004 + 0x28a20010, // slti v0, a1, $0010 + 0x5440fff7, // bnel v0, zero, -8 + 0x8ce30000, // lw v1, $0000(a3) + 0x24030006, // add iu v1, zero, $0006 + 0x0080202d, // daddu a0, a0, zero + 0x00a0282d, // daddu a1, a1, zero + 0x25660100, // addiu a2, t3, $0100 + 0x00c0302d, // daddu a2, a2, zero + 0x0000000c, // syscall (00000) + 0x03e00008, // jr ra + 0x00000000 // nop +}; + +/* 0x000820e8 */ +static void PatchOSDSYS(void) +{ + volatile unsigned int *ptr; + unsigned int i, size; + + FlushCache(0); + + // These lines weren't originally here, but I would like the kernel to use the update for v1.20 instead to save space (Since it's the first update that doesn't involve kernel patching). + strcpy((char *)0x0028bd00, "/BIEXEC-SYSTEM/osd130.elf"); + strcpy((char *)0x0028bca8, "-x mc0:/BIEXEC-SYSTEM/osd130.elf"); + strcpy((char *)0x0028be08, "osd130.elf"); + + // Copy the patch. + *(volatile unsigned int *)0x00204b28 = ((*(volatile unsigned int *)0x00204b28) & 0xFC000000) | 0x0013c000; // jal 0x004f0000 + + size = sizeof(OSDSYS_patch); // It did a calculation on the size of the patch by subtracting the end from the start. + + for (i = 0, ptr = (volatile unsigned int *)0x004f0000; i < size; ptr++, i += 4) + { + *ptr = OSDSYS_patch[i / 4]; + } + + FlushCache(0); + FlushCache(2); +} + +/* 0x00082180 */ +static void SyncSIF0(void) +{ + int i; + + // If SIF0 has incoming data, initialize SIF0 and acknowledge incoming data. + if (*DMA_REG_STAT & 0x20) + { + SifSetDChain(); // Re-initialize SIF0 (IOP -> EE) + *DMA_REG_STAT = 0x20; + while (*R_EE_SBUS_REG40 & 0x3000) {}; + + for (i = 0x1000; i > 0; i--) {}; + } +} + +/* 0x00082208 */ +static void SyncIOP(void) +{ + while ((*R_EE_SBUS_SMFLAG & SIF_STAT_BOOTEND) == 0) {}; + *R_EE_SBUS_SMFLAG = SIF_STAT_BOOTEND; +} + +/* 0x00082248 */ +static void ResetIOP(void) +{ + SifIopReset("", 0); + while (!SifIopIsAlive()) {}; + + SyncIOP(); +} + +/* 0x00082278 */ +static void AckSIF0(void) +{ + if (*R_EE_SBUS_REG40 & 0x20) + { + DI(); + ee_kmode_enter(); + + *(volatile unsigned int *)0xBD000040 = 0x20; + + ee_kmode_exit(); + EI(); + } + + if (*DMA_REG_STAT & 0x20) + *DMA_REG_STAT = 0x20; +} + +/* 0x00082300 + Returns NULL if the argument doesn't contain the specified switch, otherwise, returns the first character after the switch. +*/ +static const char *IsSwitchCheck(const char *SwitchString, const char *cmd) +{ + while (*SwitchString != '\0') + { + if (*SwitchString != *cmd) + return NULL; + SwitchString++; + cmd++; + } + + return cmd; +} + +/* 0x00082340 */ +static void ExecExecutable(int argc, char *argv[]) +{ + FlushCache(0); + SifExitRpc(); // Original had SifExitCmd(); + + ExecPS2((void *)ElfData.epc, (void *)ElfData.gp, argc, argv); +} + +/* 0x00082398 */ +static void BootError(const char *path) +{ + char *argv[2]; + + SifExitRpc(); // Original had SifExitCmd(); + + argv[0] = "BootError"; + argv[1] = (char *)path; + + ExecOSD(2, argv); +} + +// 0x000823d8 +int main(int argc, char *argv[]) +{ + const char *CommandString; + int i; + + if (argc >= 2) + { + argv++; + argc--; + SyncSIF0(); + ResetIOP(); + AckSIF0(); + + SifInitRpc(0); + + if (IsSwitchCheck("moduleload", argv[0]) != NULL) + { + argc--; + argv++; + + while (argc > 0) + { + if ((CommandString = IsSwitchCheck("-m ", argv[0])) != NULL) + { + SifLoadModule(CommandString, 0, NULL); + } + else if ((CommandString = IsSwitchCheck("-k ", argv[0])) != NULL) + { + SifLoadModuleEncrypted(CommandString, 0, NULL); + } + else if ((CommandString = IsSwitchCheck("-x ", argv[0])) != NULL) + { + FlushCache(0); + if (SifLoadElfEncrypted(CommandString, &ElfData) < 0) + { + BootError(CommandString); + } + + argv[0] = (char *)CommandString; + ExecExecutable(argc, argv); + } + else + break; + + argc--; + argv++; + } + } + + FlushCache(0); + if (SifLoadElf(argv[0], &ElfData) < 0) + { + BootError(argv[0]); + } + + if (IsSwitchCheck("rom0:OSDSYS", argv[0]) != NULL) + { + PatchOSDSYS(); + } + + ExecExecutable(argc, argv); + } + + SyncIOP(); + SifInitRpc(0); + FlushCache(0); + for (i = 0; i < NUM_BOOT_PATHS; i++) + { + if (SifLoadElf(DefaultBootPaths[i], &ElfData) >= 0) + break; + } + + PatchOSDSYS(); + ExecExecutable(1, &DefaultBootPaths[i]); + + return 0; +} diff --git a/kpatch/patch0101/EELOAD/Makefile b/kpatch/patch0101/EELOAD/Makefile index cc05a7d..adbd93c 100644 --- a/kpatch/patch0101/EELOAD/Makefile +++ b/kpatch/patch0101/EELOAD/Makefile @@ -1,8 +1,8 @@ -EE_BIN = EELOAD.elf -EE_OBJS = EELOAD.o - -CRT0_OBJ_S = ../../crt0-eeload.s -LINKFILE = ../../linkfile-eeload - -include $(PS2SDK)/Defs.make -include ../../Rules.eeload.make +EE_BIN = EELOAD.elf +EE_OBJS = EELOAD.o + +CRT0_OBJ_S = ../../crt0-eeload.s +LINKFILE = ../../linkfile-eeload + +include $(PS2SDK)/Defs.make +include ../../Rules.eeload.make diff --git a/kpatch/patch0101/Makefile b/kpatch/patch0101/Makefile index b7d2a20..1b35406 100644 --- a/kpatch/patch0101/Makefile +++ b/kpatch/patch0101/Makefile @@ -1,13 +1,13 @@ -EE_BIN = osd110.elf - -EE_OBJS = osdsys.o EELOAD_img.o - -include $(PS2SDK)/Defs.make -include ../Rules.patch.make - -clean: - rm -f EELOAD_img.c - -EELOAD_img.o: - bin2c EELOAD.img EELOAD_img.c EELOAD_img - $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c EELOAD_img.c -o EELOAD_img.o +EE_BIN = osd110.elf + +EE_OBJS = osdsys.o EELOAD_img.o + +include $(PS2SDK)/Defs.make +include ../Rules.patch.make + +clean: + rm -f EELOAD_img.c + +EELOAD_img.o: + bin2c EELOAD.img EELOAD_img.c EELOAD_img + $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c EELOAD_img.c -o EELOAD_img.o diff --git a/kpatch/patch0101/osdsys.c b/kpatch/patch0101/osdsys.c index 375744e..ca0f070 100644 --- a/kpatch/patch0101/osdsys.c +++ b/kpatch/patch0101/osdsys.c @@ -1,29 +1,31 @@ -#include - -extern unsigned char EELOAD_img[]; -extern unsigned int size_EELOAD_img; - -void *_start(void){ - unsigned int i; - vu32 *start; - - DI(); - ee_kmode_enter(); - - for(i=0,start=(vu32*)0x80030000; i + +extern unsigned char EELOAD_img[]; +extern unsigned int size_EELOAD_img; + +void *_start(void) +{ + unsigned int i; + vu32 *start; + + DI(); + ee_kmode_enter(); + + for (i = 0, start = (vu32 *)0x80030000; i < size_EELOAD_img / 4; i++) + { + start[i] = ((vu32 *)EELOAD_img)[i]; + } + + *(vu16 *)0x80005670 = 0x8003; // Patch the start of address range of the IOPRP image containing EELOAD. + *(vu16 *)0x80005674 = 0x8004; // Patch the end of address range of the IOPRP image containing EELOAD. + + ee_kmode_exit(); + EI(); + + FlushCache(0); + FlushCache(2); + + ExecOSD(0, NULL); + + return ((void *)0x80005670); +} diff --git a/osd/Makefile b/osd/Makefile index ca7305a..e1bb8c0 100644 --- a/osd/Makefile +++ b/osd/Makefile @@ -1,90 +1,90 @@ -#Enable to write ICOBYSYS (_SCE8 icon), if the console does not belong to US, Europe, Asia or Japan. -#The icon (icobysys.icn) must be supplied. -WRITE_ICOBYSYS = 0 - -#Enable to enable the check against DVD Player v1.00 and v1.01. -#This will prohibit them from being booted. -PROHBIT_DVD_0100 = 0 - -#Enable to enable the newer sceCdReadKey checks, which are only supported by a newer CDVDMAN module. -XCDVD_READKEY = 0 - -#Enable to build the PSX example. -PSX=0 - -EE_BIN = example.elf - -IOP_OBJS = sio2man_irx.o mcman_irx.o mcserv_irx.o -ICONS = icon_sys_A.o icon_sys_J.o icon_sys_C.o -ICONS_TEMP = icon_sys_A.c icon_sys_J.c icon_sys_C.c sio2man_irx.c mcman_irx.c mcserv_irx.c -IOPRP_TEMP = ioprp.c -EE_OBJS = main.o common/libcdvd_add.o common/OSDConfig.o common/OSDInit.o common/OSDHistory.o common/dvdplayer.o common/ps1.o common/ps2.o common/modelname.o $(ICONS) $(IOP_OBJS) - -EE_INCS := -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -I. -Iinclude -Ipsx -EE_LDFLAGS := -L$(PS2SDK)/ee/lib -nostartfiles -Tlinkfile -EE_LIBS := -lmc -ldebug -lpatches -lc -lkernel -EE_CFLAGS += -mno-gpopt -G0 -Os -Wall - -ifeq ($(WRITE_ICOBYSYS),1) - ICONS += icobysys_icn.o - ICONS_TEMP += icobysys_icn.c - EE_CFLAGS += -DWRITE_ICOBYSYS=1 -endif - -ifeq ($(XCDVD_READKEY),1) - EE_CFLAGS += -DXCDVD_READKEY=1 -endif - -ifeq ($(PROHBIT_DVD_0100),1) - EE_CFLAGS += -DPROHBIT_DVD_0100=1 -endif - -ifeq ($(PSX),1) - EE_CFLAGS += -DPSX=1 - EE_OBJS += psx/scmd_add.o ioprp.o - EE_LIBS += -lxcdvd -liopreboot -else - EE_LIBS += -lcdvd -endif - -%.o : %.c - $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@ - -%.o : %.s - $(EE_AS) $(EE_ASFLAGS) $< -o $@ - -%.o : %.S - $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@ - -$(EE_BIN) : $(EE_OBJS) - $(EE_CC) -T$(PS2SDK)/ee/startup/linkfile $(EE_LDFLAGS) \ - -o $(EE_BIN) $(EE_OBJS) $(PS2SDK)/ee/startup/crt0.o $(EE_LIBS) - -clean: - rm -f $(EE_BIN) $(EE_OBJS) $(ICONS_TEMP) $(IOPRP_TEMP) - -icon_sys_A.c : icons/icon_A.sys - bin2c $< $@ icon_sys_A - -icon_sys_J.c : icons/icon_J.sys - bin2c $< $@ icon_sys_J - -icon_sys_C.c : icons/icon_C.sys - bin2c $< $@ icon_sys_C - -icobysys_icn.c : icons/icobysys.icn - bin2c $< $@ icobysys_icn - -sio2man_irx.c : $(PS2SDK)/iop/irx/sio2man.irx - bin2c $< $@ sio2man_irx - -mcman_irx.c : $(PS2SDK)/iop/irx/mcman.irx - bin2c $< $@ mcman_irx - -mcserv_irx.c : $(PS2SDK)/iop/irx/mcserv.irx - bin2c $< $@ mcserv_irx - -ioprp.c : psx/ioprp.img - bin2c $< $@ psx_ioprp - -include $(PS2SDK)/Defs.make +#Enable to write ICOBYSYS (_SCE8 icon), if the console does not belong to US, Europe, Asia or Japan. +#The icon (icobysys.icn) must be supplied. +WRITE_ICOBYSYS = 0 + +#Enable to enable the check against DVD Player v1.00 and v1.01. +#This will prohibit them from being booted. +PROHBIT_DVD_0100 = 0 + +#Enable to enable the newer sceCdReadKey checks, which are only supported by a newer CDVDMAN module. +XCDVD_READKEY = 0 + +#Enable to build the PSX example. +PSX = 0 + +EE_BIN = example.elf + +IOP_OBJS = sio2man_irx.o mcman_irx.o mcserv_irx.o +ICONS = icon_sys_A.o icon_sys_J.o icon_sys_C.o +ICONS_TEMP = icon_sys_A.c icon_sys_J.c icon_sys_C.c sio2man_irx.c mcman_irx.c mcserv_irx.c +IOPRP_TEMP = ioprp.c +EE_OBJS = main.o common/libcdvd_add.o common/OSDConfig.o common/OSDInit.o common/OSDHistory.o common/dvdplayer.o common/ps1.o common/ps2.o common/modelname.o $(ICONS) $(IOP_OBJS) + +EE_INCS := -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -I. -Iinclude -Ipsx +EE_LDFLAGS := -L$(PS2SDK)/ee/lib -nostartfiles -Tlinkfile +EE_LIBS := -lmc -ldebug -lpatches -lc -lkernel +EE_CFLAGS += -mno-gpopt -G0 -Os -Wall + +ifeq ($(WRITE_ICOBYSYS),1) + ICONS += icobysys_icn.o + ICONS_TEMP += icobysys_icn.c + EE_CFLAGS += -DWRITE_ICOBYSYS=1 +endif + +ifeq ($(XCDVD_READKEY),1) + EE_CFLAGS += -DXCDVD_READKEY=1 +endif + +ifeq ($(PROHBIT_DVD_0100),1) + EE_CFLAGS += -DPROHBIT_DVD_0100=1 +endif + +ifeq ($(PSX),1) + EE_CFLAGS += -DPSX=1 + EE_OBJS += psx/scmd_add.o ioprp.o + EE_LIBS += -lxcdvd -liopreboot +else + EE_LIBS += -lcdvd +endif + +%.o : %.c + $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@ + +%.o : %.s + $(EE_AS) $(EE_ASFLAGS) $< -o $@ + +%.o : %.S + $(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@ + +$(EE_BIN) : $(EE_OBJS) + $(EE_CC) -T$(PS2SDK)/ee/startup/linkfile $(EE_LDFLAGS) \ + -o $(EE_BIN) $(EE_OBJS) $(PS2SDK)/ee/startup/crt0.o $(EE_LIBS) + +clean: + rm -f $(EE_BIN) $(EE_OBJS) $(ICONS_TEMP) $(IOPRP_TEMP) + +icon_sys_A.c : icons/icon_A.sys + bin2c $< $@ icon_sys_A + +icon_sys_J.c : icons/icon_J.sys + bin2c $< $@ icon_sys_J + +icon_sys_C.c : icons/icon_C.sys + bin2c $< $@ icon_sys_C + +icobysys_icn.c : icons/icobysys.icn + bin2c $< $@ icobysys_icn + +sio2man_irx.c : $(PS2SDK)/iop/irx/sio2man.irx + bin2c $< $@ sio2man_irx + +mcman_irx.c : $(PS2SDK)/iop/irx/mcman.irx + bin2c $< $@ mcman_irx + +mcserv_irx.c : $(PS2SDK)/iop/irx/mcserv.irx + bin2c $< $@ mcserv_irx + +ioprp.c : psx/ioprp.img + bin2c $< $@ psx_ioprp + +include $(PS2SDK)/Defs.make diff --git a/osd/README.txt b/osd/README.txt index 37ac9dc..2b38ff0 100644 --- a/osd/README.txt +++ b/osd/README.txt @@ -1,91 +1,91 @@ -OSD libary v1.04 - 2019/12/07 ------------------------------ - -The package contains various OSD-related files: - main.c: Contains the main function, which shows how the various library functions are to be used. - linkfile linkfile for this example. - Exists mainly for the sake of the PSX example, whereby the stack pointer must be within the first 32MB during the EE RAM capacity switch. - psx/ioprp.img: Contains an IOPRP image that contains a custom IOP BooT CONFiguration (IOPBTCONF) file. - This is necessary to load PCDVDMAN and PCDVDFSV from the PSX's boot ROM, to deal with the PSX-specific hardware. - psx/scmd_add.c Contains add-on functions for linking up with the PCDVDFSV module. Only for the PSX. - common/dvdplayer.c: Contains DVD Player management selection and booting code. - common/libcdvd_add.c: Contains add-on functions for the ancient libcdvd libraries that we use. - common/OSDConfig.c: Contains OSD configuration management functions. - common/OSDInit.c: Contains low-level OSD configuration-management functions. - common/OSDHistory.c: Contains functions for loading and updating the user's play history. - common/ps1.c Contains functions for booting PlayStation game discs - common/ps2.c Contains functions for booting PlayStation 2 game discs - common/modelname.c Contains functions for retrieving the PlayStation 2 console's model name (i.e. SCPH-77006). - - Most of files were based on the OSD from ROM v2.20, which has a late design. - -Notes regarding the PSX example: - The PSX's OSDSYS differs from the standard PS2's, whereby it isn't a fully-function dashboard on its own. - It will also perform the boot certification step, which is why it is not necessary. - The PSX's EE has 64MB and its IOP has 8MB. Similar to the TOOL, the memory capacity can be limited to 32MB with the TLB. - It also has a dual-mode CD/DVD drive - by default, it starts up in writer ("Rainbow") mode. In this mode, the usual registers do not work. - The PSX also has a "QUIT GAME" button, which must be enabled by "notifying" the MECHACON of the game mode with sceCdNotifyGameStart(). - - To build the PSX example, set the PSX variable in the Makefile to 1. - -Notes regarding disc-booting: - The example shows how the browser boots PlayStation and PlayStation 2 game discs. - The browser does not parse SYSTEM.CNF to determine what ELF to boot, but uses - SYSTEM.CNF to verify that the ID obtained from DRM matches. - - Your software does not need to do this (it is not even done with FMCB). - However, using the same method as the browser for parsing SYSTEM.CNF is good - for ensuring that exactly the same behaviour as the official browser is guaranteed. - - There was also code that directly accessed the hardware, to check that the appopriate type of disc is inserted. - Such code has been omitted, as I feel that they were meant to enforce the DRM and increases coupling with the hardware. - -Notes regarding the DVD Player: - The SCPH-10000 and SCPH-15000 have no DVD Player built in, as no DVD ROM chip is installed. - This is much like the DEX, TOOL and PSX consoles. - - Starting from the SCPH-75000, the DVD ROM became universal, containing the DVD players from all regions. - However, this requires the code to query the console for the MagicGate region. - -Notes regarding the functions within OSDHistory: - icon.sys: - The icon.sys file generated usually uses "_SCE8" as its icons. - "_SCE8" usually refers to an icon that is part of the browser. - - The icon.sys file for US (icon_A.sys), Japan (icon_J.sys) and China (icon_C.sys) - are reproductions of the icons that are found in the browser. - While each icon.sys file is assumed to be 964 bytes in length (like normal icon.sys files), - the browser always writes 1776 bytes of data when writing icon.sys. The icon is written, along with the data after it. - If the correct number of bytes (964) is written, the HDD Browser appears to deem the icon as invalid. - - ICOBYSYS: - When the console is not a US/Asian, European or Japanese console, - the icon (ICOBYSYS) is written to the memory card as "_SCE8" (along with icon.sys). - This leaves the Chinese (SCPH-50009) and DEX consoles (typically have an 'X' for the region) as potential targets for this code, - even though these consoles appear to support "_SCE8" without problems. - - However, as ICOBYSYS belongs to Sony, it is not part of this package. - If you want to have a complete system, you need to provide ICOBYSYS as icons/icobysys.icn and - change WRITE_ICOBYSYS in the Makefile to 1. - -Known limitations: - *Booting of PlayStation and PlayStation 2 discs on the Chinese console (SCPH-50009) is untested. - *Remote Control management does not actually do anything (sceCdBypassCtl not implemented). - sceCdBypassCtl() must be implemented on the IOP. CDVDMAN does a check against the IOP PRId, and acts according to the IOP revision. - Revisions before 2.3 will involve a S-command, while later revisions will involve other registers. - The only true way would be to execute code on the IOP. An easy way would be to use XCDVDMAN+XCDVDFSV from the target PS2. - However, this is a board-specific function that might not exist in the XCDVDMAN module versions from all PS2s. - *The actual purpose of OSDConfigGetRcEnabled & OSDConfigSetRcEnabled is not clear. - I am not entirely sure what this is. - In ROM v2.20, it seems to have a relationship to a menu that is labeled "Console" and has the text "Remote Control,Off,On". - However, I could not find the necessary conditions for accessing this menu. - In the HDD Browser, the "Remote Control,Off,On" menu text exists, but does not seem to be used. - On my SCPH-77006, this setting is disabled, although the other two remote control-related settings are enabled. - *Valid values for the timezone setting are currently unknown. - Likely 0x00-0x7F are valid values, but what do they really represent? - *Between the various OSD versions, Sony seemed to have changed the bit pattern to test for, when checking for runtime errors by the hardware. - In ROM v1.xx, the browser's code checks against 0x09. - In the HDD Browser, the browser's code generally checks against 0x81, while it checks against 0x09 while writing the EEPROM. - In ROM v2.20 (SCPH-75000+), the browser's code checks against 0x81 in all cases. - However, since the HDD Browser was made to work across different console models (although it was never intended to work on the SCPH-70000 and later), - it should be safer to follow the HDD Browser. +OSD libary v1.04 - 2019/12/07 +----------------------------- + +The package contains various OSD-related files: + main.c: Contains the main function, which shows how the various library functions are to be used. + linkfile linkfile for this example. + Exists mainly for the sake of the PSX example, whereby the stack pointer must be within the first 32MB during the EE RAM capacity switch. + psx/ioprp.img: Contains an IOPRP image that contains a custom IOP BooT CONFiguration (IOPBTCONF) file. + This is necessary to load PCDVDMAN and PCDVDFSV from the PSX's boot ROM, to deal with the PSX-specific hardware. + psx/scmd_add.c Contains add-on functions for linking up with the PCDVDFSV module. Only for the PSX. + common/dvdplayer.c: Contains DVD Player management selection and booting code. + common/libcdvd_add.c: Contains add-on functions for the ancient libcdvd libraries that we use. + common/OSDConfig.c: Contains OSD configuration management functions. + common/OSDInit.c: Contains low-level OSD configuration-management functions. + common/OSDHistory.c: Contains functions for loading and updating the user's play history. + common/ps1.c Contains functions for booting PlayStation game discs + common/ps2.c Contains functions for booting PlayStation 2 game discs + common/modelname.c Contains functions for retrieving the PlayStation 2 console's model name (i.e. SCPH-77006). + + Most of files were based on the OSD from ROM v2.20, which has a late design. + +Notes regarding the PSX example: + The PSX's OSDSYS differs from the standard PS2's, whereby it isn't a fully-function dashboard on its own. + It will also perform the boot certification step, which is why it is not necessary. + The PSX's EE has 64MB and its IOP has 8MB. Similar to the TOOL, the memory capacity can be limited to 32MB with the TLB. + It also has a dual-mode CD/DVD drive - by default, it starts up in writer ("Rainbow") mode. In this mode, the usual registers do not work. + The PSX also has a "QUIT GAME" button, which must be enabled by "notifying" the MECHACON of the game mode with sceCdNotifyGameStart(). + + To build the PSX example, set the PSX variable in the Makefile to 1. + +Notes regarding disc-booting: + The example shows how the browser boots PlayStation and PlayStation 2 game discs. + The browser does not parse SYSTEM.CNF to determine what ELF to boot, but uses + SYSTEM.CNF to verify that the ID obtained from DRM matches. + + Your software does not need to do this (it is not even done with FMCB). + However, using the same method as the browser for parsing SYSTEM.CNF is good + for ensuring that exactly the same behaviour as the official browser is guaranteed. + + There was also code that directly accessed the hardware, to check that the appopriate type of disc is inserted. + Such code has been omitted, as I feel that they were meant to enforce the DRM and increases coupling with the hardware. + +Notes regarding the DVD Player: + The SCPH-10000 and SCPH-15000 have no DVD Player built in, as no DVD ROM chip is installed. + This is much like the DEX, TOOL and PSX consoles. + + Starting from the SCPH-75000, the DVD ROM became universal, containing the DVD players from all regions. + However, this requires the code to query the console for the MagicGate region. + +Notes regarding the functions within OSDHistory: + icon.sys: + The icon.sys file generated usually uses "_SCE8" as its icons. + "_SCE8" usually refers to an icon that is part of the browser. + + The icon.sys file for US (icon_A.sys), Japan (icon_J.sys) and China (icon_C.sys) + are reproductions of the icons that are found in the browser. + While each icon.sys file is assumed to be 964 bytes in length (like normal icon.sys files), + the browser always writes 1776 bytes of data when writing icon.sys. The icon is written, along with the data after it. + If the correct number of bytes (964) is written, the HDD Browser appears to deem the icon as invalid. + + ICOBYSYS: + When the console is not a US/Asian, European or Japanese console, + the icon (ICOBYSYS) is written to the memory card as "_SCE8" (along with icon.sys). + This leaves the Chinese (SCPH-50009) and DEX consoles (typically have an 'X' for the region) as potential targets for this code, + even though these consoles appear to support "_SCE8" without problems. + + However, as ICOBYSYS belongs to Sony, it is not part of this package. + If you want to have a complete system, you need to provide ICOBYSYS as icons/icobysys.icn and + change WRITE_ICOBYSYS in the Makefile to 1. + +Known limitations: + *Booting of PlayStation and PlayStation 2 discs on the Chinese console (SCPH-50009) is untested. + *Remote Control management does not actually do anything (sceCdBypassCtl not implemented). + sceCdBypassCtl() must be implemented on the IOP. CDVDMAN does a check against the IOP PRId, and acts according to the IOP revision. + Revisions before 2.3 will involve a S-command, while later revisions will involve other registers. + The only true way would be to execute code on the IOP. An easy way would be to use XCDVDMAN+XCDVDFSV from the target PS2. + However, this is a board-specific function that might not exist in the XCDVDMAN module versions from all PS2s. + *The actual purpose of OSDConfigGetRcEnabled & OSDConfigSetRcEnabled is not clear. + I am not entirely sure what this is. + In ROM v2.20, it seems to have a relationship to a menu that is labeled "Console" and has the text "Remote Control,Off,On". + However, I could not find the necessary conditions for accessing this menu. + In the HDD Browser, the "Remote Control,Off,On" menu text exists, but does not seem to be used. + On my SCPH-77006, this setting is disabled, although the other two remote control-related settings are enabled. + *Valid values for the timezone setting are currently unknown. + Likely 0x00-0x7F are valid values, but what do they really represent? + *Between the various OSD versions, Sony seemed to have changed the bit pattern to test for, when checking for runtime errors by the hardware. + In ROM v1.xx, the browser's code checks against 0x09. + In the HDD Browser, the browser's code generally checks against 0x81, while it checks against 0x09 while writing the EEPROM. + In ROM v2.20 (SCPH-75000+), the browser's code checks against 0x81 in all cases. + However, since the HDD Browser was made to work across different console models (although it was never intended to work on the SCPH-70000 and later), + it should be safer to follow the HDD Browser. diff --git a/osd/common/OSDConfig.c b/osd/common/OSDConfig.c index 18876c3..a15d8c5 100644 --- a/osd/common/OSDConfig.c +++ b/osd/common/OSDConfig.c @@ -1,283 +1,283 @@ -#include -#include -#include - -#include "OSDInit.h" -#include "OSDConfig.h" - -static OSDConfig1_t osdConfigPS1; -static OSDConfig2_t osdConfigPS2; -static u8 ps1drvConfig; -static int timezone = 0x80; //This (as well as related checks) seems to be 0x7F in older versions. - -int OSDConfigLoad(void) -{ - int result; - result = OSDLoadConfigFromNVM(&osdConfigPS1, &osdConfigPS2); - ps1drvConfig = osdConfigPS1.data[0] & 0x11; - - return result; -} - -void OSDConfigSave(u8 invalid) -{ - osdConfigPS1.data[0] = ps1drvConfig & 0x11; - OSDSaveConfigToNVM(&osdConfigPS1, &osdConfigPS2, invalid); -} - -void OSDConfigApply(void) -{ - int language; - ConfigParam config; - Config2Param config2; - - config.spdifMode = OSDConfigGetSPDIF(); - config.screenType = OSDConfigGetScreenType(); - config.videoOutput = OSDConfigGetVideoOutput(); - config.japLanguage = 1; - config.ps1drvConfig = ps1drvConfig; - config.version = 2; - language = OSDConfigGetLanguage(); - config.language = (language <= LANGUAGE_PORTUGUESE) ? language : LANGUAGE_ENGLISH; - config.timezoneOffset = OSDConfigGetTimezoneOffset(); - - SetOsdConfigParam(&config); - GetOsdConfigParam(&config); - - /* Not supported by unpatched protokernels. - Older OSD2 browser versions only deal with 2 bytes, and do not set the format, version and language fields. */ - GetOsdConfigParam2(&config2, 4, 0); - if(config2.format < 2) - config2.format = 2; - - config2.daylightSaving = OSDConfigGetDaylightSaving(); - config2.timeFormat = OSDConfigGetTimeFormat(); - config2.dateFormat = OSDConfigGetDateFormat(); - - config2.version = 2; - config2.language = OSDConfigGetLanguage(); - - SetOsdConfigParam2(&config2, 4, 0); -} - -//Getter/Setter functions -int OSDConfigGetSPDIF(void) -{ - return osdConfigPS2.spdifMode; -} - -int OSDConfigSetSPDIF(int mode) -{ - osdConfigPS2.spdifMode = mode; - return osdConfigPS2.spdifMode; -} - -int OSDConfigGetScreenType(void) -{ - return osdConfigPS2.screenType < 3 ? osdConfigPS2.screenType : TV_SCREEN_43; -} - -int OSDConfigSetScreenType(int type) -{ - if(osdConfigPS2.screenType >= 3 && type == TV_SCREEN_43) - return TV_SCREEN_43; - - osdConfigPS2.screenType = type; - return osdConfigPS2.screenType; -} - -int OSDConfigGetVideoOutput(void) -{ - return osdConfigPS2.videoOutput; -} - -int OSDConfigSetVideoOutput(int type) -{ - osdConfigPS2.videoOutput = type; - return osdConfigPS2.videoOutput; -} - -//Old system, for version = 1 -/* int OSDConfigGetLanguage(void) -{ - if(OSDGetConsoleRegion() == OSD_REGION_JAPAN) - { //Domestic - return((osdConfigPS2.language^1) ? LANGUAGE_JAPANESE : LANGUAGE_ENGLISH); - } - else - { //Export - if(osdConfigPS2.language == LANGUAGE_JAPANESE) - { //Export sets cannot have Japanese set as a language - osdConfigPS2.language = LANGUAGE_ENGLISH; - return osdConfigPS2.language; - } - - return((osdConfigPS2.language > 0 && osdConfigPS2.language < 8) ? osdConfigPS2.language : LANGUAGE_ENGLISH); - } -} */ - -int OSDConfigGetLanguage(void) -{ - int region, DefaultLanguage; - - region = OSDGetRegion(); - DefaultLanguage = OSDGetDefaultLanguage(); - if(region != OSD_REGION_JAPAN) - { //Export sets cannot have Japanese set as a language - if(osdConfigPS2.language == LANGUAGE_JAPANESE) - { - osdConfigPS2.language = DefaultLanguage; - return osdConfigPS2.language; - } - } - - return(OSDIsLanguageValid(region, osdConfigPS2.language) >= 0 ? osdConfigPS2.language : DefaultLanguage); -} - -int OSDConfigSetLanguage(int language) -{ - if(OSDIsLanguageValid(OSDGetRegion(), osdConfigPS2.language) < 0) - { - if(OSDGetDefaultLanguage() == language) - return language; - } - - osdConfigPS2.language = language; - return osdConfigPS2.language; -} - -int OSDConfigGetLanguageRaw(void) -{ - return osdConfigPS2.language; -} - -int OSDConfigSetLanguageRaw(int language) -{ - osdConfigPS2.language = language; - return osdConfigPS2.language; -} - -int OSDConfigGetRcGameFunction(void) -{ - return osdConfigPS2.rcGameFunction; -} - -int OSDConfigSetRcGameFunction(int value) -{ - osdConfigPS2.rcGameFunction = value; - return osdConfigPS2.rcGameFunction; -} - -int OSDConfigGetRcEnabled(void) -{ - return osdConfigPS2.rcEnabled; -} - -int OSDConfigSetRcEnabled(int value) -{ - osdConfigPS2.rcEnabled = value; - return osdConfigPS2.rcEnabled; -} - -int OSDConfigGetRcSupported(void) -{ - return osdConfigPS2.rcSupported; -} - -int OSDConfigSetRcSupported(int value) -{ - osdConfigPS2.rcSupported = value; - return osdConfigPS2.rcSupported; -} - -int OSDConfigGetDVDPProgressive(void) -{ - return osdConfigPS2.dvdpProgressive; -} - -int OSDConfigSetDVDPProgressive(int value) -{ - osdConfigPS2.dvdpProgressive = value; - return osdConfigPS2.dvdpProgressive; -} - -int OSDConfigGetTimezoneOffset(void) -{ - return osdConfigPS2.timezoneOffset; -} - -int OSDConfigSetTimezoneOffset(int offset) -{ - osdConfigPS2.timezoneOffset = offset; - return osdConfigPS2.timezoneOffset; -} - -int OSDConfigGetTimezone(void) -{ - if(osdConfigPS2.timezone >= 0x80) - { - timezone = osdConfigPS2.timezone; - return 0x80; - } - - return osdConfigPS2.timezone; -} - -int OSDConfigSetTimezone(int value) -{ - if(value == 0x80) - { - osdConfigPS2.timezone = timezone; - return 0x80; - } - else - { - osdConfigPS2.timezone = value; - return osdConfigPS2.timezone; - } -} - -int OSDConfigGetDaylightSaving(void) -{ - return osdConfigPS2.daylightSaving; -} - -int OSDConfigSetDaylightSaving(int daylightSaving) -{ - osdConfigPS2.daylightSaving = daylightSaving; - return osdConfigPS2.daylightSaving; -} - -int OSDConfigGetTimeFormat(void) -{ - return osdConfigPS2.timeFormat; -} - -int OSDConfigSetTimeFormat(int timeFormat) -{ - osdConfigPS2.timeFormat = timeFormat; - return osdConfigPS2.timeFormat; -} - -int OSDConfigGetDateFormat(void) -{ - return osdConfigPS2.dateFormat; -} - -int OSDConfigSetDateFormat(int dateFormat) -{ - osdConfigPS2.dateFormat = dateFormat; - return osdConfigPS2.dateFormat; -} - -//Unofficially added, for uniformity. -int OSDConfigGetPSConfig(void) -{ - return((int)ps1drvConfig); -} - -int OSDConfigSetPSConfig(int config) -{ - ps1drvConfig = (u8)config; - return((int)ps1drvConfig); -} +#include +#include +#include + +#include "OSDInit.h" +#include "OSDConfig.h" + +static OSDConfig1_t osdConfigPS1; +static OSDConfig2_t osdConfigPS2; +static u8 ps1drvConfig; +static int timezone = 0x80; // This (as well as related checks) seems to be 0x7F in older versions. + +int OSDConfigLoad(void) +{ + int result; + result = OSDLoadConfigFromNVM(&osdConfigPS1, &osdConfigPS2); + ps1drvConfig = osdConfigPS1.data[0] & 0x11; + + return result; +} + +void OSDConfigSave(u8 invalid) +{ + osdConfigPS1.data[0] = ps1drvConfig & 0x11; + OSDSaveConfigToNVM(&osdConfigPS1, &osdConfigPS2, invalid); +} + +void OSDConfigApply(void) +{ + int language; + ConfigParam config; + Config2Param config2; + + config.spdifMode = OSDConfigGetSPDIF(); + config.screenType = OSDConfigGetScreenType(); + config.videoOutput = OSDConfigGetVideoOutput(); + config.japLanguage = 1; + config.ps1drvConfig = ps1drvConfig; + config.version = 2; + language = OSDConfigGetLanguage(); + config.language = (language <= LANGUAGE_PORTUGUESE) ? language : LANGUAGE_ENGLISH; + config.timezoneOffset = OSDConfigGetTimezoneOffset(); + + SetOsdConfigParam(&config); + GetOsdConfigParam(&config); + + /* Not supported by unpatched protokernels. + Older OSD2 browser versions only deal with 2 bytes, and do not set the format, version and language fields. */ + GetOsdConfigParam2(&config2, 4, 0); + if (config2.format < 2) + config2.format = 2; + + config2.daylightSaving = OSDConfigGetDaylightSaving(); + config2.timeFormat = OSDConfigGetTimeFormat(); + config2.dateFormat = OSDConfigGetDateFormat(); + + config2.version = 2; + config2.language = OSDConfigGetLanguage(); + + SetOsdConfigParam2(&config2, 4, 0); +} + +// Getter/Setter functions +int OSDConfigGetSPDIF(void) +{ + return osdConfigPS2.spdifMode; +} + +int OSDConfigSetSPDIF(int mode) +{ + osdConfigPS2.spdifMode = mode; + return osdConfigPS2.spdifMode; +} + +int OSDConfigGetScreenType(void) +{ + return osdConfigPS2.screenType < 3 ? osdConfigPS2.screenType : TV_SCREEN_43; +} + +int OSDConfigSetScreenType(int type) +{ + if (osdConfigPS2.screenType >= 3 && type == TV_SCREEN_43) + return TV_SCREEN_43; + + osdConfigPS2.screenType = type; + return osdConfigPS2.screenType; +} + +int OSDConfigGetVideoOutput(void) +{ + return osdConfigPS2.videoOutput; +} + +int OSDConfigSetVideoOutput(int type) +{ + osdConfigPS2.videoOutput = type; + return osdConfigPS2.videoOutput; +} + +// Old system, for version = 1 +/* int OSDConfigGetLanguage(void) +{ + if (OSDGetConsoleRegion() == OSD_REGION_JAPAN) + { // Domestic + return ((osdConfigPS2.language ^ 1) ? LANGUAGE_JAPANESE : LANGUAGE_ENGLISH); + } + else + { // Export + if (osdConfigPS2.language == LANGUAGE_JAPANESE) + { // Export sets cannot have Japanese set as a language + osdConfigPS2.language = LANGUAGE_ENGLISH; + return osdConfigPS2.language; + } + + return ((osdConfigPS2.language > 0 && osdConfigPS2.language < 8) ? osdConfigPS2.language : LANGUAGE_ENGLISH); + } +} */ + +int OSDConfigGetLanguage(void) +{ + int region, DefaultLanguage; + + region = OSDGetRegion(); + DefaultLanguage = OSDGetDefaultLanguage(); + if (region != OSD_REGION_JAPAN) + { // Export sets cannot have Japanese set as a language + if (osdConfigPS2.language == LANGUAGE_JAPANESE) + { + osdConfigPS2.language = DefaultLanguage; + return osdConfigPS2.language; + } + } + + return (OSDIsLanguageValid(region, osdConfigPS2.language) >= 0 ? osdConfigPS2.language : DefaultLanguage); +} + +int OSDConfigSetLanguage(int language) +{ + if (OSDIsLanguageValid(OSDGetRegion(), osdConfigPS2.language) < 0) + { + if (OSDGetDefaultLanguage() == language) + return language; + } + + osdConfigPS2.language = language; + return osdConfigPS2.language; +} + +int OSDConfigGetLanguageRaw(void) +{ + return osdConfigPS2.language; +} + +int OSDConfigSetLanguageRaw(int language) +{ + osdConfigPS2.language = language; + return osdConfigPS2.language; +} + +int OSDConfigGetRcGameFunction(void) +{ + return osdConfigPS2.rcGameFunction; +} + +int OSDConfigSetRcGameFunction(int value) +{ + osdConfigPS2.rcGameFunction = value; + return osdConfigPS2.rcGameFunction; +} + +int OSDConfigGetRcEnabled(void) +{ + return osdConfigPS2.rcEnabled; +} + +int OSDConfigSetRcEnabled(int value) +{ + osdConfigPS2.rcEnabled = value; + return osdConfigPS2.rcEnabled; +} + +int OSDConfigGetRcSupported(void) +{ + return osdConfigPS2.rcSupported; +} + +int OSDConfigSetRcSupported(int value) +{ + osdConfigPS2.rcSupported = value; + return osdConfigPS2.rcSupported; +} + +int OSDConfigGetDVDPProgressive(void) +{ + return osdConfigPS2.dvdpProgressive; +} + +int OSDConfigSetDVDPProgressive(int value) +{ + osdConfigPS2.dvdpProgressive = value; + return osdConfigPS2.dvdpProgressive; +} + +int OSDConfigGetTimezoneOffset(void) +{ + return osdConfigPS2.timezoneOffset; +} + +int OSDConfigSetTimezoneOffset(int offset) +{ + osdConfigPS2.timezoneOffset = offset; + return osdConfigPS2.timezoneOffset; +} + +int OSDConfigGetTimezone(void) +{ + if (osdConfigPS2.timezone >= 0x80) + { + timezone = osdConfigPS2.timezone; + return 0x80; + } + + return osdConfigPS2.timezone; +} + +int OSDConfigSetTimezone(int value) +{ + if (value == 0x80) + { + osdConfigPS2.timezone = timezone; + return 0x80; + } + else + { + osdConfigPS2.timezone = value; + return osdConfigPS2.timezone; + } +} + +int OSDConfigGetDaylightSaving(void) +{ + return osdConfigPS2.daylightSaving; +} + +int OSDConfigSetDaylightSaving(int daylightSaving) +{ + osdConfigPS2.daylightSaving = daylightSaving; + return osdConfigPS2.daylightSaving; +} + +int OSDConfigGetTimeFormat(void) +{ + return osdConfigPS2.timeFormat; +} + +int OSDConfigSetTimeFormat(int timeFormat) +{ + osdConfigPS2.timeFormat = timeFormat; + return osdConfigPS2.timeFormat; +} + +int OSDConfigGetDateFormat(void) +{ + return osdConfigPS2.dateFormat; +} + +int OSDConfigSetDateFormat(int dateFormat) +{ + osdConfigPS2.dateFormat = dateFormat; + return osdConfigPS2.dateFormat; +} + +// Unofficially added, for uniformity. +int OSDConfigGetPSConfig(void) +{ + return ((int)ps1drvConfig); +} + +int OSDConfigSetPSConfig(int config) +{ + ps1drvConfig = (u8)config; + return ((int)ps1drvConfig); +} diff --git a/osd/common/OSDHistory.c b/osd/common/OSDHistory.c index a982a45..c885929 100644 --- a/osd/common/OSDHistory.c +++ b/osd/common/OSDHistory.c @@ -1,410 +1,416 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "OSDInit.h" -#include "OSDHistory.h" - -/* The OSDs have this weird bug whereby the size of the icon file is hardcoded to 1776 bytes... even though that is way too long! - Unfortunately, using the right size will cause the icon to be deemed as corrupted data by the HDDOSD. */ -#define SYSDATA_ICON_SYS_SIZE 1776 - -#define NUM_TABLES 1024 -#define HISTORY_PATH_LEN 1024 - -extern unsigned char icon_sys_A[]; -extern unsigned char icon_sys_J[]; -extern unsigned char icon_sys_C[]; -#ifdef WRITE_ICOBYSYS -extern unsigned char icobysys_icn[]; -extern unsigned int size_icobysys_icn; -#endif - -/* Original used to maintain the time in global variables. These were updated by another thread. -extern int currentYear; -extern int currentMonth; -extern int currentDate; -extern int currentHour; -extern int currentSecond; -extern int currentMinute; */ - -static int HasTooManyHistoryRecords; -static struct HistoryEntry HistoryEntries[MAX_HISTORY_ENTRIES], OldHistoryEntry; - -static int WriteHistoryFile(int port, const char *path, const void *buffer, int len, int append) -{ - int fd, result, size; - - if(append) - { - sceMcOpen(port, 0, path, O_RDWR); - sceMcSync(0, NULL, &fd); - } - - if((!append) || (fd < 0)) //If not opened in append mode or if the file could not be opened. - sceMcOpen(port, 0, path, O_CREAT|O_WRONLY); - - sceMcSync(0, NULL, &fd); - - if(fd >= 0) - { - if(append) - { //Get length of file - sceMcSeek(fd, 0, SEEK_END); - sceMcSync(0, NULL, &size); - - if(size >= 0) - { //Seek to the last position within the file. - sceMcSeek(fd, size, SEEK_SET); - sceMcSync(0, NULL, &size); - } - - if(size < 0) - { //Seek error - result = sceMcClose(fd); - sceMcSync(0, NULL, &result); - return size; - } - } - - sceMcWrite(fd, buffer, len); - sceMcSync(0, NULL, &size); - - if(size >= 0) - { - sceMcClose(fd); - sceMcSync(0, NULL, &result); - - return(sceMcResSucceed <= result ? 0 : result); - } - else - { - result = sceMcClose(fd); - sceMcSync(0, NULL, &result); - - return size; - } - } - else - return fd; -} - -static int McCheckFileExists(int port, const char *path) -{ - int fd, result; - - if(sceMcOpen(port, 0, path, O_RDONLY) < sceMcResSucceed) - return -1; - - sceMcSync(0, NULL, &fd); - - if(fd >= 0) - { - sceMcClose(fd); - sceMcSync(0, NULL, &result); - return(sceMcResSucceed <= result ? 1 : result); - } - else - return 0; -} - -int LoadHistoryFile(int port) -{ - char fullpath[64]; - int fd, result, result2, type, format; - - sceMcGetInfo(port, 0, &type, NULL, &format); - sceMcSync(0, NULL, &result); - - if(result < sceMcResChangedCard || type != sceMcTypePS2 || format == 0) - return -1; - - sprintf(fullpath, "%s/%s", OSDGetHistoryDataFolder(), "history"); - fd = sceMcOpen(port, 0, fullpath, O_RDONLY); - sceMcSync(0, NULL, &fd); - - if(fd >= 0) - { - sceMcRead(fd, HistoryEntries, MAX_HISTORY_ENTRIES*sizeof(struct HistoryEntry)); - sceMcSync(0, NULL, &result); - - //Original had duplicated this block. - sceMcClose(fd); - sceMcSync(0, NULL, &result2); - - return((result >= 0) ? (result2 >= 0 ? 0 : -1) : result); - } - else result=fd; - - return result; -} - -int SaveHistoryFile(int port) -{ - int result, spaceRequired, makeIcon, dataFolderExists, i; - int type, free, format; - static sceMcTblGetDir table[NUM_TABLES] __attribute__((aligned(64))); //Keep this aligned since the data will be transferred here directly via DMA. - //These were originally static/global - char pathToFile[HISTORY_PATH_LEN]; - sceMcTblGetDir iconDirT; - - spaceRequired = 0; - makeIcon = 0; - - //Not present in older versions. It may be to compensate for those newer regions that were not supported by older ROMs (i.e. China), by having the icon (_SCE8) stored on the memory card. - switch(OSDGetConsoleRegion()) - { //The original may have used simple if/else blocks, as it called OSDGetConsoleRegion() multiple times. - case CONSOLE_REGION_JAPAN: - case CONSOLE_REGION_USA: - case CONSOLE_REGION_EUROPE: - spaceRequired = 0; - break; - default: //Includes China - spaceRequired = 3; - } - - sceMcGetInfo(port, 0, &type, &free, &format); - sceMcSync(0, NULL, &result); - - if((result >= sceMcResChangedCard) && (type == sceMcTypePS2) && (format != 0)) - { - dataFolderExists = 0; - sceMcGetDir(port, 0, "/*", 0, NUM_TABLES, table); - sceMcSync(0, NULL, &result); - - if(result >= sceMcResSucceed) - { //Locate system data directory - for(i = 0; i < result; i++) - { - if(strcmp(table[i].EntryName, OSDGetSystemDataFolder()) == 0) - { - dataFolderExists = 1; - break; - } - } - - if(dataFolderExists) - { //It exists, so check the icon. - if(spaceRequired) - { - sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "icon.sys"); - if((result = McCheckFileExists(port, pathToFile)) < 0) - return -1; - - if(result == 0) - { //Icon does not exist, hence assume that the system data folder does not exist. - spaceRequired = 9; - makeIcon = 1; - } - else - spaceRequired = 0; - } - - if(free < spaceRequired + 2) // Likely a check for at least 2 clusters, for history file (directory entry + file itself) - return -1; - } else { - if(free < spaceRequired + 10) - return -1; - - sceMcMkDir(port, 0, OSDGetHistoryDataFolder()); - sceMcSync(0, NULL, &result); - - if(result < sceMcResSucceed) - return -1; - - makeIcon = (0 < spaceRequired); - } - - iconDirT.AttrFile = sceMcFileAttrHidden | sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable; - sceMcSetFileInfo(port, 0, OSDGetHistoryDataFolder(), &iconDirT, 4); - sceMcSync(0, NULL, &result); - - sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "history"); - sceMcDelete(port, 0, pathToFile); - sceMcSync(0, NULL, &result); - - //There was no check on the return value. - WriteHistoryFile(port, pathToFile, HistoryEntries, sizeof(struct HistoryEntry) * MAX_HISTORY_ENTRIES, 0); - - if(makeIcon) - { //There was no code in older versions for writing _SCE8 (see comment above). -#ifdef WRITE_ICOBYSYS - sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "_SCE8"); - //The original got the ICOBYSYS resource's details (buffer position & size) from the resource manager via getter functions. - if(WriteHistoryFile(port, pathToFile, icobysys_icn, size_icobysys_icn, 0) < 0) - return -1; -#endif - } - - sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "icon.sys"); - - //There is no check on the result of the writing process. If writing fails, the browser will treat it as corrupted data - switch(OSDGetConsoleRegion()) - { //The original may have used simple if/else blocks, as it called OSDGetConsoleRegion() multiple times. - case CONSOLE_REGION_JAPAN: - WriteHistoryFile(port, pathToFile, icon_sys_J, SYSDATA_ICON_SYS_SIZE, 0); - break; - case CONSOLE_REGION_CHINA: - WriteHistoryFile(port, pathToFile, icon_sys_C, SYSDATA_ICON_SYS_SIZE, 0); - break; - default: //Others (US, Europe & Asia) - WriteHistoryFile(port, pathToFile, icon_sys_A, SYSDATA_ICON_SYS_SIZE, 0); - } - - if(HasTooManyHistoryRecords) - { //Append the selected history record to the end of history.old. - sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "history.old"); - WriteHistoryFile(port, pathToFile, &OldHistoryEntry, sizeof(struct HistoryEntry), 1); - } - } - else result = -1; - } - else result = -1; - - return result; -} - -static u16 GetTimestamp(void) -{ - //The original obtained the time and date from globals. - //return OSD_HISTORY_SET_DATE(currentYear, currentMonth, currentDate); - sceCdCLOCK time; - sceCdReadClock(&time); - return OSD_HISTORY_SET_DATE(btoi(time.year), btoi(time.month&0x7F), btoi(time.day)); -} - -static void AddHistoryRecord(const char *name) -{ - struct HistoryEntry *NewEntry; - int i, value, LeastUsedRecord, LeastUsedRecordLaunchCount, LeastUsedRecordTimestamp, NewLaunchCount; - u8 BlankSlotList[MAX_HISTORY_ENTRIES]; - int NumBlankSlots, NumSlotsUsed, IsNewRecord; - - LeastUsedRecord = 0; - LeastUsedRecordTimestamp = INT_MAX; - LeastUsedRecordLaunchCount = INT_MAX; - HasTooManyHistoryRecords = 0; - IsNewRecord = 1; - - for(i = 0; i < MAX_HISTORY_ENTRIES; i++) - { - if(HistoryEntries[i].LaunchCount=0x80) - NewLaunchCount=0x7F; - - if(NewLaunchCount>=14) - { - if((NewLaunchCount-14)%10 == 0) - { - while((HistoryEntries[i].bitmask >> (value = rand()%6))&1){}; - HistoryEntries[i].ShiftAmount = value; - HistoryEntries[i].bitmask |= 1<0) - { //Randomly choose an empty slot. - NewEntry=&HistoryEntries[BlankSlotList[rand()%NumBlankSlots]]; - } - else - { //Copy out the victim record - NewEntry=&HistoryEntries[LeastUsedRecord]; - memcpy(&OldHistoryEntry, NewEntry, sizeof(OldHistoryEntry)); - HasTooManyHistoryRecords = 1; - } - - //Initialize the new entry. - strncpy(NewEntry->name, name, sizeof(NewEntry->name)); - NewEntry->LaunchCount=1; - NewEntry->bitmask=1; - NewEntry->ShiftAmount=0; - NewEntry->DateStamp=GetTimestamp(); - } - } -} - -void UpdatePlayHistory(const char *name) -{ - //Try to load the history file from memory card slot 1 - if(LoadHistoryFile(0) < 0) - { //Try memory card slot 2 - if(LoadHistoryFile(1) < 0) - memset(HistoryEntries, 0, sizeof(HistoryEntries)); - } - - AddHistoryRecord(name); - if(SaveHistoryFile(0) < 0) - { - SaveHistoryFile(1); - } -} +#include +#include +#include +#include +#include +#include +#include + +#include "OSDInit.h" +#include "OSDHistory.h" + +/* The OSDs have this weird bug whereby the size of the icon file is hardcoded to 1776 bytes... even though that is way too long! + Unfortunately, using the right size will cause the icon to be deemed as corrupted data by the HDDOSD. */ +#define SYSDATA_ICON_SYS_SIZE 1776 + +#define NUM_TABLES 1024 +#define HISTORY_PATH_LEN 1024 + +extern unsigned char icon_sys_A[]; +extern unsigned char icon_sys_J[]; +extern unsigned char icon_sys_C[]; +#ifdef WRITE_ICOBYSYS +extern unsigned char icobysys_icn[]; +extern unsigned int size_icobysys_icn; +#endif + +/* Original used to maintain the time in global variables. These were updated by another thread. */ +/* extern int currentYear; +extern int currentMonth; +extern int currentDate; +extern int currentHour; +extern int currentSecond; +extern int currentMinute; */ + +static int HasTooManyHistoryRecords; +static struct HistoryEntry HistoryEntries[MAX_HISTORY_ENTRIES], OldHistoryEntry; + +static int WriteHistoryFile(int port, const char *path, const void *buffer, int len, int append) +{ + int fd, result, size; + + if (append) + { + sceMcOpen(port, 0, path, O_RDWR); + sceMcSync(0, NULL, &fd); + } + + if ((!append) || (fd < 0)) // If not opened in append mode or if the file could not be opened. + sceMcOpen(port, 0, path, O_CREAT | O_WRONLY); + + sceMcSync(0, NULL, &fd); + + if (fd >= 0) + { + if (append) + { // Get length of file + sceMcSeek(fd, 0, SEEK_END); + sceMcSync(0, NULL, &size); + + if (size >= 0) + { // Seek to the last position within the file. + sceMcSeek(fd, size, SEEK_SET); + sceMcSync(0, NULL, &size); + } + + if (size < 0) + { // Seek error + result = sceMcClose(fd); + sceMcSync(0, NULL, &result); + return size; + } + } + + sceMcWrite(fd, buffer, len); + sceMcSync(0, NULL, &size); + + if (size >= 0) + { + sceMcClose(fd); + sceMcSync(0, NULL, &result); + + return (sceMcResSucceed <= result ? 0 : result); + } + else + { + result = sceMcClose(fd); + sceMcSync(0, NULL, &result); + + return size; + } + } + else + return fd; +} + +static int McCheckFileExists(int port, const char *path) +{ + int fd, result; + + if (sceMcOpen(port, 0, path, O_RDONLY) < sceMcResSucceed) + return -1; + + sceMcSync(0, NULL, &fd); + + if (fd >= 0) + { + sceMcClose(fd); + sceMcSync(0, NULL, &result); + return (sceMcResSucceed <= result ? 1 : result); + } + else + return 0; +} + +int LoadHistoryFile(int port) +{ + char fullpath[64]; + int fd, result, result2, type, format; + + sceMcGetInfo(port, 0, &type, NULL, &format); + sceMcSync(0, NULL, &result); + + if (result < sceMcResChangedCard || type != sceMcTypePS2 || format == 0) + return -1; + + sprintf(fullpath, "%s/%s", OSDGetHistoryDataFolder(), "history"); + fd = sceMcOpen(port, 0, fullpath, O_RDONLY); + sceMcSync(0, NULL, &fd); + + if (fd >= 0) + { + sceMcRead(fd, HistoryEntries, MAX_HISTORY_ENTRIES * sizeof(struct HistoryEntry)); + sceMcSync(0, NULL, &result); + + // Original had duplicated this block. + sceMcClose(fd); + sceMcSync(0, NULL, &result2); + + return ((result >= 0) ? (result2 >= 0 ? 0 : -1) : result); + } + else + result = fd; + + return result; +} + +int SaveHistoryFile(int port) +{ + int result, spaceRequired, makeIcon, dataFolderExists, i; + int type, free, format; + static sceMcTblGetDir table[NUM_TABLES] __attribute__((aligned(64))); // Keep this aligned since the data will be transferred here directly via DMA. + // These were originally static/global + char pathToFile[HISTORY_PATH_LEN]; + sceMcTblGetDir iconDirT; + + spaceRequired = 0; + makeIcon = 0; + + // Not present in older versions. It may be to compensate for those newer regions that were not supported by older ROMs (i.e. China), by having the icon (_SCE8) stored on the memory card. + switch (OSDGetConsoleRegion()) + { // The original may have used simple if/else blocks, as it called OSDGetConsoleRegion() multiple times. + case CONSOLE_REGION_JAPAN: + case CONSOLE_REGION_USA: + case CONSOLE_REGION_EUROPE: + spaceRequired = 0; + break; + default: // Includes China + spaceRequired = 3; + } + + sceMcGetInfo(port, 0, &type, &free, &format); + sceMcSync(0, NULL, &result); + + if ((result >= sceMcResChangedCard) && (type == sceMcTypePS2) && (format != 0)) + { + dataFolderExists = 0; + sceMcGetDir(port, 0, "/*", 0, NUM_TABLES, table); + sceMcSync(0, NULL, &result); + + if (result >= sceMcResSucceed) + { // Locate system data directory + for (i = 0; i < result; i++) + { + if (strcmp(table[i].EntryName, OSDGetSystemDataFolder()) == 0) + { + dataFolderExists = 1; + break; + } + } + + if (dataFolderExists) + { // It exists, so check the icon. + if (spaceRequired) + { + sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "icon.sys"); + if ((result = McCheckFileExists(port, pathToFile)) < 0) + return -1; + + if (result == 0) + { // Icon does not exist, hence assume that the system data folder does not exist. + spaceRequired = 9; + makeIcon = 1; + } + else + spaceRequired = 0; + } + + if (free < spaceRequired + 2) // Likely a check for at least 2 clusters, for history file (directory entry + file itself) + return -1; + } + else + { + if (free < spaceRequired + 10) + return -1; + + sceMcMkDir(port, 0, OSDGetHistoryDataFolder()); + sceMcSync(0, NULL, &result); + + if (result < sceMcResSucceed) + return -1; + + makeIcon = (0 < spaceRequired); + } + + iconDirT.AttrFile = sceMcFileAttrHidden | sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable; + sceMcSetFileInfo(port, 0, OSDGetHistoryDataFolder(), &iconDirT, 4); + sceMcSync(0, NULL, &result); + + sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "history"); + sceMcDelete(port, 0, pathToFile); + sceMcSync(0, NULL, &result); + + // There was no check on the return value. + WriteHistoryFile(port, pathToFile, HistoryEntries, sizeof(struct HistoryEntry) * MAX_HISTORY_ENTRIES, 0); + + if (makeIcon) + { // There was no code in older versions for writing _SCE8 (see comment above). +#ifdef WRITE_ICOBYSYS + sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "_SCE8"); + // The original got the ICOBYSYS resource's details (buffer position & size) from the resource manager via getter functions. + if (WriteHistoryFile(port, pathToFile, icobysys_icn, size_icobysys_icn, 0) < 0) + return -1; +#endif + } + + sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "icon.sys"); + + // There is no check on the result of the writing process. If writing fails, the browser will treat it as corrupted data + switch (OSDGetConsoleRegion()) + { // The original may have used simple if/else blocks, as it called OSDGetConsoleRegion() multiple times. + case CONSOLE_REGION_JAPAN: + WriteHistoryFile(port, pathToFile, icon_sys_J, SYSDATA_ICON_SYS_SIZE, 0); + break; + case CONSOLE_REGION_CHINA: + WriteHistoryFile(port, pathToFile, icon_sys_C, SYSDATA_ICON_SYS_SIZE, 0); + break; + default: // Others (US, Europe & Asia) + WriteHistoryFile(port, pathToFile, icon_sys_A, SYSDATA_ICON_SYS_SIZE, 0); + } + + if (HasTooManyHistoryRecords) + { // Append the selected history record to the end of history.old. + sprintf(pathToFile, "%s/%s", OSDGetHistoryDataFolder(), "history.old"); + WriteHistoryFile(port, pathToFile, &OldHistoryEntry, sizeof(struct HistoryEntry), 1); + } + } + else + result = -1; + } + else + result = -1; + + return result; +} + +static u16 GetTimestamp(void) +{ + // The original obtained the time and date from globals. + // return OSD_HISTORY_SET_DATE(currentYear, currentMonth, currentDate); + sceCdCLOCK time; + sceCdReadClock(&time); + return OSD_HISTORY_SET_DATE(btoi(time.year), btoi(time.month & 0x7F), btoi(time.day)); +} + +static void AddHistoryRecord(const char *name) +{ + struct HistoryEntry *NewEntry; + int i, value, LeastUsedRecord, LeastUsedRecordLaunchCount, LeastUsedRecordTimestamp, NewLaunchCount; + u8 BlankSlotList[MAX_HISTORY_ENTRIES]; + int NumBlankSlots, NumSlotsUsed, IsNewRecord; + + LeastUsedRecord = 0; + LeastUsedRecordTimestamp = INT_MAX; + LeastUsedRecordLaunchCount = INT_MAX; + HasTooManyHistoryRecords = 0; + IsNewRecord = 1; + + for (i = 0; i < MAX_HISTORY_ENTRIES; i++) + { + if (HistoryEntries[i].LaunchCount < LeastUsedRecordLaunchCount) + { + LeastUsedRecord = i; + LeastUsedRecordLaunchCount = HistoryEntries[i].LaunchCount; + } + if (LeastUsedRecordLaunchCount == HistoryEntries[i].LaunchCount) + { + if (HistoryEntries[i].DateStamp < LeastUsedRecordTimestamp) + { + LeastUsedRecordTimestamp = HistoryEntries[i].DateStamp; + LeastUsedRecord = i; + } + } + + // In v1.0x, this was strcmp + if (!strncmp(HistoryEntries[i].name, name, sizeof(HistoryEntries[i].name))) + { + IsNewRecord = 0; + + HistoryEntries[i].DateStamp = GetTimestamp(); + if ((HistoryEntries[i].bitmask & 0x3F) != 0x3F) + { + NewLaunchCount = HistoryEntries[i].LaunchCount + 1; + if (NewLaunchCount >= 0x80) + NewLaunchCount = 0x7F; + + if (NewLaunchCount >= 14) + { + if ((NewLaunchCount - 14) % 10 == 0) + { + while ((HistoryEntries[i].bitmask >> (value = rand() % 6)) & 1) {}; + HistoryEntries[i].ShiftAmount = value; + HistoryEntries[i].bitmask |= 1 << value; + } + } + + HistoryEntries[i].LaunchCount = NewLaunchCount; + } + else + { + if (HistoryEntries[i].LaunchCount < 0x3F) + { // Was a check against 0x40 in v1.0x + HistoryEntries[i].LaunchCount++; + } + else + { + HistoryEntries[i].LaunchCount = HistoryEntries[i].bitmask & 0x3F; + HistoryEntries[i].ShiftAmount = 7; + } + } + } + } + + /* i = 0; + do + { // Original does this. I guess, it is used to ensure that the next random value is truly random? + rand(); + i++; + } while (i < (currentMinute * 60 + currentSecond)); */ + + if (IsNewRecord) + { + // Count and consolidate a list of blank slots. + NumBlankSlots = 0; + NumSlotsUsed = 0; + for (i = 0; i < MAX_HISTORY_ENTRIES; i++) + { + if (HistoryEntries[i].name[0] == '\0') + { + BlankSlotList[NumBlankSlots] = i; + NumBlankSlots++; + } + else + { // Not present in v1.0x. + if (HistoryEntries[i].ShiftAmount == 0x7) + NumSlotsUsed++; + } + } + + if (NumSlotsUsed != MAX_HISTORY_ENTRIES) + { + if (NumBlankSlots > 0) + { // Randomly choose an empty slot. + NewEntry = &HistoryEntries[BlankSlotList[rand() % NumBlankSlots]]; + } + else + { // Copy out the victim record + NewEntry = &HistoryEntries[LeastUsedRecord]; + memcpy(&OldHistoryEntry, NewEntry, sizeof(OldHistoryEntry)); + HasTooManyHistoryRecords = 1; + } + + // Initialize the new entry. + strncpy(NewEntry->name, name, sizeof(NewEntry->name)); + NewEntry->LaunchCount = 1; + NewEntry->bitmask = 1; + NewEntry->ShiftAmount = 0; + NewEntry->DateStamp = GetTimestamp(); + } + } +} + +void UpdatePlayHistory(const char *name) +{ + // Try to load the history file from memory card slot 1 + if (LoadHistoryFile(0) < 0) + { // Try memory card slot 2 + if (LoadHistoryFile(1) < 0) + memset(HistoryEntries, 0, sizeof(HistoryEntries)); + } + + AddHistoryRecord(name); + if (SaveHistoryFile(0) < 0) + { + SaveHistoryFile(1); + } +} diff --git a/osd/common/OSDInit.c b/osd/common/OSDInit.c index a5a5c22..afbe6e8 100644 --- a/osd/common/OSDInit.c +++ b/osd/common/OSDInit.c @@ -1,584 +1,598 @@ -#include -#include -#include -#include -#include "libcdvd_add.h" -#include - -#include "OSDInit.h" - -/* Parsing of values from the EEPROM and setting them into the EE kernel - was done in different ways, across different browser versions. - - The early browsers of ROM v1.00 and v1.01 (SCPH-10000/SCPH-15000) - parsed the values within the EEPROM into global variables, - which are used to set the individual fields in the OSD configuration. - - The newer browsers parsed the values into a bitfield structure, - which does not have the same layout as the OSD configuration structure. - - Both designs had the parsing and the preparation of the OSD - configuration data separated, presumably for clarity of code and - to achieve low-coupling (perhaps they belonged to different modules). */ - -static int ConsoleRegion = -1, ConsoleOSDRegion = -1, ConsoleOSDLanguage = -1; -static int ConsoleOSDRegionInitStatus = 0, ConsoleRegionParamInitStatus = 0; //0 = Not init. 1 = Init complete. <0 = Init failed. -static u8 ConsoleRegionData[16] = {0, 0, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -//Perhaps it once used to read more configuration blocks (original capacity was 7 blocks). -static u8 OSDConfigBuffer[CONFIG_BLOCK_SIZE * 2]; - -//Local function prototypes -static int InitMGRegion(void); -static int ConsoleInitRegion(void); -static int ConsoleRegionParamsInitPS1DRV(const char *romver); -static int GetConsoleRegion(void); -static int CdReadOSDRegionParams(char *OSDVer); -static int GetOSDRegion(void); -static void InitOSDDefaultLanguage(int region, const char *language); -static int ReadOSDConfigPS2(OSDConfig2_t *config, const OSDConfigStore_t* OSDConfigBuffer); -static void ReadOSDConfigPS1(OSDConfig1_t *config, const OSDConfigStore_t* OSDConfigBuffer); -static void WriteOSDConfigPS1(OSDConfigStore_t* OSDConfigBuffer, const OSDConfig1_t *config); -static void WriteOSDConfigPS2(OSDConfigStore_t* OSDConfigBuffer, const OSDConfig2_t *config, u8 invalid); -static void ReadConfigFromNVM(u8 *buffer); -static void WriteConfigToNVM(const u8 *buffer); - -//Directory names -static char SystemDataFolder[]="BRDATA-SYSTEM"; -static char SystemExecFolder[]="BREXEC-SYSTEM"; -static char DVDPLExecFolder[]="BREXEC-DVDPLAYER"; - -char ConsoleROMVER[ROMVER_MAX_LEN]; - -static int InitMGRegion(void) -{ - u32 stat; - int result; - - if(ConsoleRegionParamInitStatus == 0) - { - do{ - if((result = sceCdReadRegionParams(ConsoleRegionData, &stat)) == 0) - { //Failed. - ConsoleRegionParamInitStatus=1; - } - else - { - if(stat & 0x100) - { - //MECHACON does not support this function. - ConsoleRegionParamInitStatus=-1; - break; - } - else - { //Status OK, but the result yielded an error. - ConsoleRegionParamInitStatus=1; - } - } - }while((result == 0) || (stat & 0x80)); - } - - return ConsoleRegionParamInitStatus; -} - -void OSDInitSystemPaths(void) -{ - int region; - char regions[CONSOLE_REGION_COUNT]={'I', 'A', 'E', 'C'}; - - region = OSDGetConsoleRegion(); - if(region>=0 && region=0)?ConsoleRegionData[8]:0); -} - -static int ConsoleInitRegion(void) -{ - GetOSDRegion(); - return InitMGRegion(); -} - -static int ConsoleRegionParamsInitPS1DRV(const char *romver) -{ - int result; - - if(ConsoleInitRegion() >= 0) - { - ConsoleRegionData[2] = romver[4]; - result = 1; - } else - result = 0; - - return result; -} - -/* Present here, but not sure what it is (unused) -int OSDGetROMRegion(char *out) -{ - int result; - - if(ConsoleInitRegion() >= 0) - { - out[4] = ConsoleRegionData[2]; - result = 1; - } - else - result = 0; - - return result; -} */ - -int OSDGetPS1DRVRegion(char *region) -{ - int result; - - if(ConsoleInitRegion() >= 0) - { - *region = ConsoleRegionData[2]; - result = 1; - } - else - result = 0; - - return result; -} - -int OSDGetDVDPlayerRegion(char *region) -{ - int result; - - if(ConsoleInitRegion() >= 0) - { - *region = ConsoleRegionData[8]; - result = 1; - } - else - result = 0; - - return result; -} - -static int GetConsoleRegion(void) -{ - char romver[16]; - int fd, result; - - if((result=ConsoleRegion)<0) - { - if((fd = open("rom0:ROMVER", O_RDONLY)) >= 0) - { - read(fd, romver, sizeof(romver)); - close(fd); - ConsoleRegionParamsInitPS1DRV(romver); - - switch(romver[4]) - { - case 'C': - ConsoleRegion=CONSOLE_REGION_CHINA; - break; - case 'E': - ConsoleRegion=CONSOLE_REGION_EUROPE; - break; - case 'H': - case 'A': - ConsoleRegion=CONSOLE_REGION_USA; - break; - case 'J': - ConsoleRegion=CONSOLE_REGION_JAPAN; - } - - result=ConsoleRegion; - } else - result = -1; - } - - return result; -} - -static int CdReadOSDRegionParams(char *OSDVer) -{ - int result; - - if(OSDVer[4] == '?') - { - if(InitMGRegion() >= 0) - { - result = 1; - OSDVer[4] = ConsoleRegionData[3]; - OSDVer[5] = ConsoleRegionData[4]; - OSDVer[6] = ConsoleRegionData[5]; - OSDVer[7] = ConsoleRegionData[6]; - } else - result = 0; - } else { - ConsoleRegionParamInitStatus = -256; - result = 0; - } - - return result; -} - -static int GetOSDRegion(void) -{ - char OSDVer[16]; - int fd; - - if(ConsoleOSDRegionInitStatus == 0 || ConsoleOSDRegion == -1) - { - ConsoleOSDRegionInitStatus = 1; - if((fd = open("rom0:OSDVER", O_RDONLY)) >= 0) - { - read(fd, OSDVer, sizeof(OSDVer)); - close(fd); - CdReadOSDRegionParams(OSDVer); - switch(OSDVer[4]) - { - case 'A': - ConsoleOSDRegion = OSD_REGION_USA; - break; - case 'C': - ConsoleOSDRegion = OSD_REGION_CHINA; - break; - case 'E': - ConsoleOSDRegion = OSD_REGION_EUROPE; - break; - case 'H': - ConsoleOSDRegion = OSD_REGION_ASIA; - break; - case 'J': - ConsoleOSDRegion = OSD_REGION_JAPAN; - break; - case 'K': - ConsoleOSDRegion = OSD_REGION_KOREA; - break; - case 'R': - ConsoleOSDRegion = OSD_REGION_RUSSIA; - break; - default: - ConsoleOSDRegion = OSD_REGION_INVALID; - } - - if(ConsoleOSDRegion != OSD_REGION_INVALID) - InitOSDDefaultLanguage(ConsoleOSDRegion, &OSDVer[5]); - } else - ConsoleOSDRegion = OSD_REGION_INVALID; - } - - return ConsoleOSDRegion; -} - -static void InitOSDDefaultLanguage(int region, const char *language) -{ - int DefaultLang; - - DefaultLang = -1; - if(ConsoleOSDLanguage == -1) - { - if(language != NULL) - { - if(strncmp(language, "jpn", 3) == 0) - DefaultLang = LANGUAGE_JAPANESE; - else if(strncmp(language, "eng", 3) == 0) - DefaultLang = LANGUAGE_ENGLISH; - else if(strncmp(language, "fre", 3) == 0) - DefaultLang = LANGUAGE_FRENCH; - else if(strncmp(language, "spa", 3) == 0) - DefaultLang = LANGUAGE_SPANISH; - else if(strncmp(language, "ger", 3) == 0) - DefaultLang = LANGUAGE_GERMAN; - else if(strncmp(language, "ita", 3) == 0) - DefaultLang = LANGUAGE_ITALIAN; - else if(strncmp(language, "dut", 3) == 0) - DefaultLang = LANGUAGE_DUTCH; - else if(strncmp(language, "por", 3) == 0) - DefaultLang = LANGUAGE_PORTUGUESE; - else if(strncmp(language, "rus", 3) == 0) - DefaultLang = LANGUAGE_RUSSIAN; - else if(strncmp(language, "kor", 3) == 0) - DefaultLang = LANGUAGE_KOREAN; - else if(strncmp(language, "tch", 3) == 0) - DefaultLang = LANGUAGE_TRAD_CHINESE; - else if(strncmp(language, "sch", 3) == 0) - DefaultLang = LANGUAGE_SIMPL_CHINESE; - else DefaultLang = -1; - } - - //Check if the specified language is valid for the region - if(!OSDIsLanguageValid(region, DefaultLang)) - { - switch(region) - { - case OSD_REGION_JAPAN: - DefaultLang = LANGUAGE_JAPANESE; - break; - case OSD_REGION_CHINA: - DefaultLang = LANGUAGE_SIMPL_CHINESE; - break; - case OSD_REGION_RUSSIA: - DefaultLang = LANGUAGE_RUSSIAN; - break; - case OSD_REGION_KOREA: - DefaultLang = LANGUAGE_KOREAN; - break; - case OSD_REGION_USA: - case OSD_REGION_EUROPE: - case OSD_REGION_ASIA: - default: - DefaultLang = LANGUAGE_ENGLISH; - } - } - - ConsoleOSDLanguage = DefaultLang; - } -} - -int OSDIsLanguageValid(int region, int language) -{ - switch(region) - { - case OSD_REGION_JAPAN: - return(language == LANGUAGE_JAPANESE || language == LANGUAGE_ENGLISH) ? language : -1; - case OSD_REGION_CHINA: - return(language == LANGUAGE_ENGLISH || language == LANGUAGE_SIMPL_CHINESE) ? language : -1; - case OSD_REGION_RUSSIA: - return(language == LANGUAGE_ENGLISH || language == LANGUAGE_RUSSIAN) ? language : -1; - case OSD_REGION_KOREA: - return(language == LANGUAGE_ENGLISH || language == LANGUAGE_KOREAN) ? language : -1; - case OSD_REGION_ASIA: - return(language == LANGUAGE_ENGLISH || language == LANGUAGE_TRAD_CHINESE) ? language : -1; - case OSD_REGION_USA: - case OSD_REGION_EUROPE: - default: - return(language <= LANGUAGE_PORTUGUESE && region > OSD_REGION_JAPAN) ? language : -1; - } -} - -int OSDGetConsoleRegion(void) -{ //Default to Japan, if the region cannot be obtained. - int result; - - result=GetConsoleRegion(); - - return(result < 0 ? 0 : result); -} - -int OSDGetVideoMode(void) -{ - return(GetConsoleRegion() == CONSOLE_REGION_EUROPE); -} - -int OSDGetRegion(void) -{ - int region; - - if((region = GetOSDRegion()) < 0) - { - region = OSDGetConsoleRegion(); - InitOSDDefaultLanguage(region, NULL); - } - - return region; -} - -int OSDGetDefaultLanguage(void) -{ - if(ConsoleOSDLanguage == -1) - OSDGetRegion(); - - return ConsoleOSDLanguage; -} - -/* Notes: - Version = 0 (Protokernel consoles only) NTSC-J, 1 = ROM versions up to v1.70, 2 = v1.80 and later. 2 = support for extended languages (Osd2 bytes 3 and 4) - In the homebrew PS2SDK, this was previously known as the "region". - japLanguage = 0 (Japanese, protokernel consoles only), 1 = non-Japanese (Protokernel consoles only). Newer browsers have this set always to 1. -*/ -static int ReadOSDConfigPS2(OSDConfig2_t *config, const OSDConfigStore_t* OSDConfigBuffer) -{ - config->spdifMode = OSDConfigBuffer->PS2.spdifMode; - config->screenType = OSDConfigBuffer->PS2.screenType; - config->videoOutput = OSDConfigBuffer->PS2.videoOutput; - - if (OSDConfigBuffer->PS2.extendedLanguage) //Extended/Basic language set - { //One of the 8 standard languages - config->language = OSDConfigBuffer->PS2.language; - } - else - { //Japanese/English - config->language = OSDConfigBuffer->PS2.japLanguage; - } - - config->daylightSaving = OSDConfigBuffer->PS2.daylightSaving; - config->timeFormat = OSDConfigBuffer->PS2.timeFormat; - config->dateFormat = OSDConfigBuffer->PS2.dateFormat; - config->timezoneOffset = OSDConfigBuffer->PS2.timezoneOffsetLo | ((u32)OSDConfigBuffer->PS2.timezoneOffsetHi) << 8; - config->timezone = OSDConfigBuffer->PS2.timezoneLo | (((u32)OSDConfigBuffer->PS2.timezoneHi) << 8); - config->rcEnabled = OSDConfigBuffer->PS2.rcEnabled; - config->rcGameFunction = OSDConfigBuffer->PS2.rcGameFunction; - config->rcSupported = OSDConfigBuffer->PS2.rcSupported; - config->dvdpProgressive = OSDConfigBuffer->PS2.dvdpProgressive; - - return(OSDConfigBuffer->PS2.osdInit ^ 1); -} - -static void ReadOSDConfigPS1(OSDConfig1_t *config, const OSDConfigStore_t* OSDConfigBuffer) -{ - int i; - - for(i = 0; i < CONFIG_BLOCK_SIZE; i++) - config->data[i] = OSDConfigBuffer->PS1.bytes[i]; -} - -static void WriteOSDConfigPS1(OSDConfigStore_t* OSDConfigBuffer, const OSDConfig1_t *config) -{ - int i; - - for(i = 0; i < CONFIG_BLOCK_SIZE; i++) - OSDConfigBuffer->PS1.bytes[i] = config->data[i]; -} - -static void WriteOSDConfigPS2(OSDConfigStore_t* OSDConfigBuffer, const OSDConfig2_t *config, u8 invalid) -{ - int japLanguage, version, osdInitValue; - - osdInitValue = invalid ^ 1; - version = OSDConfigBuffer->PS2.extendedLanguage == 0 ? 1 : OSDConfigBuffer->PS2.extendedLanguage; - - if(config->language <= LANGUAGE_ENGLISH) - japLanguage = config->language; - else //Do not update the legacy language option if the language was changed to something unsupported. - japLanguage = OSDConfigBuffer->PS2.japLanguage; - - //0x0F - OSDConfigBuffer->PS2.videoOutput = config->videoOutput; - OSDConfigBuffer->PS2.japLanguage = japLanguage; - OSDConfigBuffer->PS2.extendedLanguage = 1; - OSDConfigBuffer->PS2.spdifMode = config->spdifMode; - OSDConfigBuffer->PS2.screenType = config->screenType; - - //0x10 - OSDConfigBuffer->PS2.language = config->language; - OSDConfigBuffer->PS2.version = version; - - //0x11 - OSDConfigBuffer->PS2.timezoneOffsetHi = config->timezoneOffset >> 8; - OSDConfigBuffer->PS2.dateFormat = config->dateFormat; - OSDConfigBuffer->PS2.timeFormat = config->timeFormat; - OSDConfigBuffer->PS2.daylightSaving = config->daylightSaving; - OSDConfigBuffer->PS2.osdInit = osdInitValue; - - //0x12 - OSDConfigBuffer->PS2.timezoneOffsetLo = config->timezoneOffset; - - //0x13 - OSDConfigBuffer->PS2.timezoneHi = config->timezone >> 8; - OSDConfigBuffer->PS2.unknownB13_01 = OSDConfigBuffer->PS2.unknownB13_01; //Carry over - OSDConfigBuffer->PS2.rcEnabled = config->rcEnabled; - OSDConfigBuffer->PS2.rcGameFunction = config->rcGameFunction; - OSDConfigBuffer->PS2.rcSupported = config->rcSupported; - OSDConfigBuffer->PS2.dvdpProgressive = config->dvdpProgressive; - - //0x14 - OSDConfigBuffer->PS2.timezoneLo = config->timezone; -} - -static void ReadConfigFromNVM(u8 *buffer) -{ /* Hmm. What should the check for stat be? In v1.xx, it seems to be a check against 0x9. In v2.20, it checks against 0x81. - In the HDD Browser, reading checks against 0x81, while writing checks against 0x9. - But because we are targeting all consoles, it would be probably safer to follow the HDD Browser. */ - int result; - u32 stat; - - do{ - sceCdOpenConfig(1, 0, 2, &stat); - }while(stat & 0x81); - - do{ - result=sceCdReadConfig(buffer, &stat); - }while((stat & 0x81) || (result == 0)); - - do{ - result=sceCdCloseConfig(&stat); - }while((stat & 0x81) || (result == 0)); -} - -static void WriteConfigToNVM(const u8 *buffer) -{ // Read the comment in ReadConfigFromNVM() about the error status bits. - u32 stat; - int result; - - do{ - sceCdOpenConfig(1, 1, 2, &stat); - }while(stat & 0x09); - - do{ - result=sceCdWriteConfig(buffer, &stat); - }while((stat & 0x09) || (result == 0)); - - do{ - result=sceCdCloseConfig(&stat); - }while((stat & 9) || (result == 0)); -} - -int OSDLoadConfigFromNVM(OSDConfig1_t *osdConfigPS1, OSDConfig2_t *osdConfigPS2) -{ - int result; - - ReadConfigFromNVM(OSDConfigBuffer); - result = ReadOSDConfigPS2(osdConfigPS2, (const OSDConfigStore_t*)OSDConfigBuffer); - ReadOSDConfigPS1(osdConfigPS1, (const OSDConfigStore_t*)OSDConfigBuffer); - - return result; -} - -int OSDSaveConfigToNVM(const OSDConfig1_t *osdConfigPS1, const OSDConfig2_t *osdConfigPS2, u8 invalid) -{ - WriteOSDConfigPS1((OSDConfigStore_t*)OSDConfigBuffer, osdConfigPS1); - WriteOSDConfigPS2((OSDConfigStore_t*)OSDConfigBuffer, osdConfigPS2, invalid); - WriteConfigToNVM(OSDConfigBuffer); - - return 0; -} - -//Directory management -const char *OSDGetHistoryDataFolder(void) -{ - return SystemDataFolder; -} - -const char *OSDGetSystemDataFolder(void) -{ - return SystemDataFolder; -} - -const char *OSDGetSystemExecFolder(void) -{ - return SystemExecFolder; -} - -const char *OSDGetDVDPLExecFolder(void) -{ - return DVDPLExecFolder; -} - -int OSDInitROMVER(void) -{ - int fd; - - memset(ConsoleROMVER, 0, ROMVER_MAX_LEN); - if((fd = open("rom0:ROMVER", O_RDONLY)) >= 0) - { - read(fd, ConsoleROMVER, ROMVER_MAX_LEN); - close(fd); - } - - return 0; -} +#include +#include +#include +#include +#include "libcdvd_add.h" +#include + +#include "OSDInit.h" + +/* Parsing of values from the EEPROM and setting them into the EE kernel + was done in different ways, across different browser versions. + + The early browsers of ROM v1.00 and v1.01 (SCPH-10000/SCPH-15000) + parsed the values within the EEPROM into global variables, + which are used to set the individual fields in the OSD configuration. + + The newer browsers parsed the values into a bitfield structure, + which does not have the same layout as the OSD configuration structure. + + Both designs had the parsing and the preparation of the OSD + configuration data separated, presumably for clarity of code and + to achieve low-coupling (perhaps they belonged to different modules). */ + +static int ConsoleRegion = -1, ConsoleOSDRegion = -1, ConsoleOSDLanguage = -1; +static int ConsoleOSDRegionInitStatus = 0, ConsoleRegionParamInitStatus = 0; // 0 = Not init. 1 = Init complete. <0 = Init failed. +static u8 ConsoleRegionData[16] = {0, 0, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +// Perhaps it once used to read more configuration blocks (original capacity was 7 blocks). +static u8 OSDConfigBuffer[CONFIG_BLOCK_SIZE * 2]; + +// Local function prototypes +static int InitMGRegion(void); +static int ConsoleInitRegion(void); +static int ConsoleRegionParamsInitPS1DRV(const char *romver); +static int GetConsoleRegion(void); +static int CdReadOSDRegionParams(char *OSDVer); +static int GetOSDRegion(void); +static void InitOSDDefaultLanguage(int region, const char *language); +static int ReadOSDConfigPS2(OSDConfig2_t *config, const OSDConfigStore_t *OSDConfigBuffer); +static void ReadOSDConfigPS1(OSDConfig1_t *config, const OSDConfigStore_t *OSDConfigBuffer); +static void WriteOSDConfigPS1(OSDConfigStore_t *OSDConfigBuffer, const OSDConfig1_t *config); +static void WriteOSDConfigPS2(OSDConfigStore_t *OSDConfigBuffer, const OSDConfig2_t *config, u8 invalid); +static void ReadConfigFromNVM(u8 *buffer); +static void WriteConfigToNVM(const u8 *buffer); + +// Directory names +static char SystemDataFolder[] = "BRDATA-SYSTEM"; +static char SystemExecFolder[] = "BREXEC-SYSTEM"; +static char DVDPLExecFolder[] = "BREXEC-DVDPLAYER"; + +char ConsoleROMVER[ROMVER_MAX_LEN]; + +static int InitMGRegion(void) +{ + u32 stat; + int result; + + if (ConsoleRegionParamInitStatus == 0) + { + do + { + if ((result = sceCdReadRegionParams(ConsoleRegionData, &stat)) == 0) + { // Failed. + ConsoleRegionParamInitStatus = 1; + } + else + { + if (stat & 0x100) + { + // MECHACON does not support this function. + ConsoleRegionParamInitStatus = -1; + break; + } + else + { // Status OK, but the result yielded an error. + ConsoleRegionParamInitStatus = 1; + } + } + } while ((result == 0) || (stat & 0x80)); + } + + return ConsoleRegionParamInitStatus; +} + +void OSDInitSystemPaths(void) +{ + int region; + char regions[CONSOLE_REGION_COUNT] = {'I', 'A', 'E', 'C'}; + + region = OSDGetConsoleRegion(); + if (region >= 0 && region < CONSOLE_REGION_COUNT) + { + SystemDataFolder[1] = regions[region]; + SystemExecFolder[1] = regions[region]; + DVDPLExecFolder[1] = regions[region]; + } +} + +int OSDGetMGRegion(void) +{ + return ((InitMGRegion() >= 0) ? ConsoleRegionData[8] : 0); +} + +static int ConsoleInitRegion(void) +{ + GetOSDRegion(); + return InitMGRegion(); +} + +static int ConsoleRegionParamsInitPS1DRV(const char *romver) +{ + int result; + + if (ConsoleInitRegion() >= 0) + { + ConsoleRegionData[2] = romver[4]; + result = 1; + } + else + result = 0; + + return result; +} + +/* Present here, but not sure what it is (unused) */ +/* int OSDGetROMRegion(char *out) +{ + int result; + + if (ConsoleInitRegion() >= 0) + { + out[4] = ConsoleRegionData[2]; + result = 1; + } + else + result = 0; + + return result; +} */ + +int OSDGetPS1DRVRegion(char *region) +{ + int result; + + if (ConsoleInitRegion() >= 0) + { + *region = ConsoleRegionData[2]; + result = 1; + } + else + result = 0; + + return result; +} + +int OSDGetDVDPlayerRegion(char *region) +{ + int result; + + if (ConsoleInitRegion() >= 0) + { + *region = ConsoleRegionData[8]; + result = 1; + } + else + result = 0; + + return result; +} + +static int GetConsoleRegion(void) +{ + char romver[16]; + int fd, result; + + if ((result = ConsoleRegion) < 0) + { + if ((fd = open("rom0:ROMVER", O_RDONLY)) >= 0) + { + read(fd, romver, sizeof(romver)); + close(fd); + ConsoleRegionParamsInitPS1DRV(romver); + + switch (romver[4]) + { + case 'C': + ConsoleRegion = CONSOLE_REGION_CHINA; + break; + case 'E': + ConsoleRegion = CONSOLE_REGION_EUROPE; + break; + case 'H': + case 'A': + ConsoleRegion = CONSOLE_REGION_USA; + break; + case 'J': + ConsoleRegion = CONSOLE_REGION_JAPAN; + } + + result = ConsoleRegion; + } + else + result = -1; + } + + return result; +} + +static int CdReadOSDRegionParams(char *OSDVer) +{ + int result; + + if (OSDVer[4] == '?') + { + if (InitMGRegion() >= 0) + { + result = 1; + OSDVer[4] = ConsoleRegionData[3]; + OSDVer[5] = ConsoleRegionData[4]; + OSDVer[6] = ConsoleRegionData[5]; + OSDVer[7] = ConsoleRegionData[6]; + } + else + result = 0; + } + else + { + ConsoleRegionParamInitStatus = -256; + result = 0; + } + + return result; +} + +static int GetOSDRegion(void) +{ + char OSDVer[16]; + int fd; + + if (ConsoleOSDRegionInitStatus == 0 || ConsoleOSDRegion == -1) + { + ConsoleOSDRegionInitStatus = 1; + if ((fd = open("rom0:OSDVER", O_RDONLY)) >= 0) + { + read(fd, OSDVer, sizeof(OSDVer)); + close(fd); + CdReadOSDRegionParams(OSDVer); + switch (OSDVer[4]) + { + case 'A': + ConsoleOSDRegion = OSD_REGION_USA; + break; + case 'C': + ConsoleOSDRegion = OSD_REGION_CHINA; + break; + case 'E': + ConsoleOSDRegion = OSD_REGION_EUROPE; + break; + case 'H': + ConsoleOSDRegion = OSD_REGION_ASIA; + break; + case 'J': + ConsoleOSDRegion = OSD_REGION_JAPAN; + break; + case 'K': + ConsoleOSDRegion = OSD_REGION_KOREA; + break; + case 'R': + ConsoleOSDRegion = OSD_REGION_RUSSIA; + break; + default: + ConsoleOSDRegion = OSD_REGION_INVALID; + } + + if (ConsoleOSDRegion != OSD_REGION_INVALID) + InitOSDDefaultLanguage(ConsoleOSDRegion, &OSDVer[5]); + } + else + ConsoleOSDRegion = OSD_REGION_INVALID; + } + + return ConsoleOSDRegion; +} + +static void InitOSDDefaultLanguage(int region, const char *language) +{ + int DefaultLang; + + DefaultLang = -1; + if (ConsoleOSDLanguage == -1) + { + if (language != NULL) + { + if (strncmp(language, "jpn", 3) == 0) + DefaultLang = LANGUAGE_JAPANESE; + else if (strncmp(language, "eng", 3) == 0) + DefaultLang = LANGUAGE_ENGLISH; + else if (strncmp(language, "fre", 3) == 0) + DefaultLang = LANGUAGE_FRENCH; + else if (strncmp(language, "spa", 3) == 0) + DefaultLang = LANGUAGE_SPANISH; + else if (strncmp(language, "ger", 3) == 0) + DefaultLang = LANGUAGE_GERMAN; + else if (strncmp(language, "ita", 3) == 0) + DefaultLang = LANGUAGE_ITALIAN; + else if (strncmp(language, "dut", 3) == 0) + DefaultLang = LANGUAGE_DUTCH; + else if (strncmp(language, "por", 3) == 0) + DefaultLang = LANGUAGE_PORTUGUESE; + else if (strncmp(language, "rus", 3) == 0) + DefaultLang = LANGUAGE_RUSSIAN; + else if (strncmp(language, "kor", 3) == 0) + DefaultLang = LANGUAGE_KOREAN; + else if (strncmp(language, "tch", 3) == 0) + DefaultLang = LANGUAGE_TRAD_CHINESE; + else if (strncmp(language, "sch", 3) == 0) + DefaultLang = LANGUAGE_SIMPL_CHINESE; + else + DefaultLang = -1; + } + + // Check if the specified language is valid for the region + if (!OSDIsLanguageValid(region, DefaultLang)) + { + switch (region) + { + case OSD_REGION_JAPAN: + DefaultLang = LANGUAGE_JAPANESE; + break; + case OSD_REGION_CHINA: + DefaultLang = LANGUAGE_SIMPL_CHINESE; + break; + case OSD_REGION_RUSSIA: + DefaultLang = LANGUAGE_RUSSIAN; + break; + case OSD_REGION_KOREA: + DefaultLang = LANGUAGE_KOREAN; + break; + case OSD_REGION_USA: + case OSD_REGION_EUROPE: + case OSD_REGION_ASIA: + default: + DefaultLang = LANGUAGE_ENGLISH; + } + } + + ConsoleOSDLanguage = DefaultLang; + } +} + +int OSDIsLanguageValid(int region, int language) +{ + switch (region) + { + case OSD_REGION_JAPAN: + return (language == LANGUAGE_JAPANESE || language == LANGUAGE_ENGLISH) ? language : -1; + case OSD_REGION_CHINA: + return (language == LANGUAGE_ENGLISH || language == LANGUAGE_SIMPL_CHINESE) ? language : -1; + case OSD_REGION_RUSSIA: + return (language == LANGUAGE_ENGLISH || language == LANGUAGE_RUSSIAN) ? language : -1; + case OSD_REGION_KOREA: + return (language == LANGUAGE_ENGLISH || language == LANGUAGE_KOREAN) ? language : -1; + case OSD_REGION_ASIA: + return (language == LANGUAGE_ENGLISH || language == LANGUAGE_TRAD_CHINESE) ? language : -1; + case OSD_REGION_USA: + case OSD_REGION_EUROPE: + default: + return (language <= LANGUAGE_PORTUGUESE && region > OSD_REGION_JAPAN) ? language : -1; + } +} + +int OSDGetConsoleRegion(void) +{ // Default to Japan, if the region cannot be obtained. + int result; + + result = GetConsoleRegion(); + + return (result < 0 ? 0 : result); +} + +int OSDGetVideoMode(void) +{ + return (GetConsoleRegion() == CONSOLE_REGION_EUROPE); +} + +int OSDGetRegion(void) +{ + int region; + + if ((region = GetOSDRegion()) < 0) + { + region = OSDGetConsoleRegion(); + InitOSDDefaultLanguage(region, NULL); + } + + return region; +} + +int OSDGetDefaultLanguage(void) +{ + if (ConsoleOSDLanguage == -1) + OSDGetRegion(); + + return ConsoleOSDLanguage; +} + +/* Notes: + Version = 0 (Protokernel consoles only) NTSC-J, 1 = ROM versions up to v1.70, 2 = v1.80 and later. 2 = support for extended languages (Osd2 bytes 3 and 4) + In the homebrew PS2SDK, this was previously known as the "region". + japLanguage = 0 (Japanese, protokernel consoles only), 1 = non-Japanese (Protokernel consoles only). Newer browsers have this set always to 1. +*/ +static int ReadOSDConfigPS2(OSDConfig2_t *config, const OSDConfigStore_t *OSDConfigBuffer) +{ + config->spdifMode = OSDConfigBuffer->PS2.spdifMode; + config->screenType = OSDConfigBuffer->PS2.screenType; + config->videoOutput = OSDConfigBuffer->PS2.videoOutput; + + if (OSDConfigBuffer->PS2.extendedLanguage) // Extended/Basic language set + { // One of the 8 standard languages + config->language = OSDConfigBuffer->PS2.language; + } + else + { // Japanese/English + config->language = OSDConfigBuffer->PS2.japLanguage; + } + + config->daylightSaving = OSDConfigBuffer->PS2.daylightSaving; + config->timeFormat = OSDConfigBuffer->PS2.timeFormat; + config->dateFormat = OSDConfigBuffer->PS2.dateFormat; + config->timezoneOffset = OSDConfigBuffer->PS2.timezoneOffsetLo | ((u32)OSDConfigBuffer->PS2.timezoneOffsetHi) << 8; + config->timezone = OSDConfigBuffer->PS2.timezoneLo | (((u32)OSDConfigBuffer->PS2.timezoneHi) << 8); + config->rcEnabled = OSDConfigBuffer->PS2.rcEnabled; + config->rcGameFunction = OSDConfigBuffer->PS2.rcGameFunction; + config->rcSupported = OSDConfigBuffer->PS2.rcSupported; + config->dvdpProgressive = OSDConfigBuffer->PS2.dvdpProgressive; + + return (OSDConfigBuffer->PS2.osdInit ^ 1); +} + +static void ReadOSDConfigPS1(OSDConfig1_t *config, const OSDConfigStore_t *OSDConfigBuffer) +{ + int i; + + for (i = 0; i < CONFIG_BLOCK_SIZE; i++) + config->data[i] = OSDConfigBuffer->PS1.bytes[i]; +} + +static void WriteOSDConfigPS1(OSDConfigStore_t *OSDConfigBuffer, const OSDConfig1_t *config) +{ + int i; + + for (i = 0; i < CONFIG_BLOCK_SIZE; i++) + OSDConfigBuffer->PS1.bytes[i] = config->data[i]; +} + +static void WriteOSDConfigPS2(OSDConfigStore_t *OSDConfigBuffer, const OSDConfig2_t *config, u8 invalid) +{ + int japLanguage, version, osdInitValue; + + osdInitValue = invalid ^ 1; + version = OSDConfigBuffer->PS2.extendedLanguage == 0 ? 1 : OSDConfigBuffer->PS2.extendedLanguage; + + if (config->language <= LANGUAGE_ENGLISH) + japLanguage = config->language; + else // Do not update the legacy language option if the language was changed to something unsupported. + japLanguage = OSDConfigBuffer->PS2.japLanguage; + + // 0x0F + OSDConfigBuffer->PS2.videoOutput = config->videoOutput; + OSDConfigBuffer->PS2.japLanguage = japLanguage; + OSDConfigBuffer->PS2.extendedLanguage = 1; + OSDConfigBuffer->PS2.spdifMode = config->spdifMode; + OSDConfigBuffer->PS2.screenType = config->screenType; + + // 0x10 + OSDConfigBuffer->PS2.language = config->language; + OSDConfigBuffer->PS2.version = version; + + // 0x11 + OSDConfigBuffer->PS2.timezoneOffsetHi = config->timezoneOffset >> 8; + OSDConfigBuffer->PS2.dateFormat = config->dateFormat; + OSDConfigBuffer->PS2.timeFormat = config->timeFormat; + OSDConfigBuffer->PS2.daylightSaving = config->daylightSaving; + OSDConfigBuffer->PS2.osdInit = osdInitValue; + + // 0x12 + OSDConfigBuffer->PS2.timezoneOffsetLo = config->timezoneOffset; + + // 0x13 + OSDConfigBuffer->PS2.timezoneHi = config->timezone >> 8; + OSDConfigBuffer->PS2.unknownB13_01 = OSDConfigBuffer->PS2.unknownB13_01; // Carry over + OSDConfigBuffer->PS2.rcEnabled = config->rcEnabled; + OSDConfigBuffer->PS2.rcGameFunction = config->rcGameFunction; + OSDConfigBuffer->PS2.rcSupported = config->rcSupported; + OSDConfigBuffer->PS2.dvdpProgressive = config->dvdpProgressive; + + // 0x14 + OSDConfigBuffer->PS2.timezoneLo = config->timezone; +} + +static void ReadConfigFromNVM(u8 *buffer) +{ /* Hmm. What should the check for stat be? In v1.xx, it seems to be a check against 0x9. In v2.20, it checks against 0x81. + In the HDD Browser, reading checks against 0x81, while writing checks against 0x9. + But because we are targeting all consoles, it would be probably safer to follow the HDD Browser. */ + int result; + u32 stat; + + do + { + sceCdOpenConfig(1, 0, 2, &stat); + } while (stat & 0x81); + + do + { + result = sceCdReadConfig(buffer, &stat); + } while ((stat & 0x81) || (result == 0)); + + do + { + result = sceCdCloseConfig(&stat); + } while ((stat & 0x81) || (result == 0)); +} + +static void WriteConfigToNVM(const u8 *buffer) +{ // Read the comment in ReadConfigFromNVM() about the error status bits. + u32 stat; + int result; + + do + { + sceCdOpenConfig(1, 1, 2, &stat); + } while (stat & 0x09); + + do + { + result = sceCdWriteConfig(buffer, &stat); + } while ((stat & 0x09) || (result == 0)); + + do + { + result = sceCdCloseConfig(&stat); + } while ((stat & 9) || (result == 0)); +} + +int OSDLoadConfigFromNVM(OSDConfig1_t *osdConfigPS1, OSDConfig2_t *osdConfigPS2) +{ + int result; + + ReadConfigFromNVM(OSDConfigBuffer); + result = ReadOSDConfigPS2(osdConfigPS2, (const OSDConfigStore_t *)OSDConfigBuffer); + ReadOSDConfigPS1(osdConfigPS1, (const OSDConfigStore_t *)OSDConfigBuffer); + + return result; +} + +int OSDSaveConfigToNVM(const OSDConfig1_t *osdConfigPS1, const OSDConfig2_t *osdConfigPS2, u8 invalid) +{ + WriteOSDConfigPS1((OSDConfigStore_t *)OSDConfigBuffer, osdConfigPS1); + WriteOSDConfigPS2((OSDConfigStore_t *)OSDConfigBuffer, osdConfigPS2, invalid); + WriteConfigToNVM(OSDConfigBuffer); + + return 0; +} + +// Directory management +const char *OSDGetHistoryDataFolder(void) +{ + return SystemDataFolder; +} + +const char *OSDGetSystemDataFolder(void) +{ + return SystemDataFolder; +} + +const char *OSDGetSystemExecFolder(void) +{ + return SystemExecFolder; +} + +const char *OSDGetDVDPLExecFolder(void) +{ + return DVDPLExecFolder; +} + +int OSDInitROMVER(void) +{ + int fd; + + memset(ConsoleROMVER, 0, ROMVER_MAX_LEN); + if ((fd = open("rom0:ROMVER", O_RDONLY)) >= 0) + { + read(fd, ConsoleROMVER, ROMVER_MAX_LEN); + close(fd); + } + + return 0; +} diff --git a/osd/common/dvdplayer.c b/osd/common/dvdplayer.c index 55409a9..f0d7e2d 100644 --- a/osd/common/dvdplayer.c +++ b/osd/common/dvdplayer.c @@ -1,400 +1,405 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" -#include "dvdplayer.h" -#include "OSDInit.h" -#include "OSDHistory.h" - -#define DVD_PLAYER_VER_LEN 32 - -struct DVDPlayer{ - char ver[DVD_PLAYER_VER_LEN]; - int major, minor; - int region; -}; - -static struct DVDPlayer ROMDVDPlayer; - -static char dvdid[] = "rom1:DVDID?"; -static char dvdver[] = "rom1:DVDVER?"; - -static char eromdrvCMD[] = "-k rom1:EROMDRV?"; -static char dvdelfCMD[] = "-x erom0:DVDELF"; - -static int readMCFile(int fd, void *buffer, int len); -static int ReadFileFromMC(int port, int slot, const char *file, void *buffer, int len); -static int getStatMC(int port, int slot, int *type, int *free, int *format); -static int openMCFile(int port, int slot, const char *path, int mode); -static int closeMCFile(int fd); -static int CheckFileFromMC(int port, int slot, const char *file); - -extern char ConsoleROMVER[ROMVER_MAX_LEN]; - -static int readMCFile(int fd, void *buffer, int len) -{ - int result; - - if(sceMcRead(fd, buffer, len) == 0) - { - return(sceMcSync(0, NULL, &result) == 1 ? result : 0); - } - else - return -10; -} - -static int ReadFileFromMC(int port, int slot, const char *file, void *buffer, int len) -{ - int fd, bytesRead; - int result; - - if((result = getStatMC(port, slot, NULL, NULL, NULL)) >= -2) - { - if((fd = openMCFile(port, slot, file, 1)) >= 0) - { - if((bytesRead = readMCFile(fd, buffer, len)) < 0) - return -1; - - return(closeMCFile(fd) >= 0 ? bytesRead : -1); - } - else - return -1; - } - else - return -1; -} - -static int getStatMC(int port, int slot, int *type, int *free, int *format) -{ - int result; - - if((result = sceMcGetInfo(port, slot, type, free, format)) == 0) - { - return(sceMcSync(0, NULL, &result) == 1 ? result : -11); - } - else - return -10; -} - -static int openMCFile(int port, int slot, const char *path, int mode) -{ - int result, type, format; - - getStatMC(port, slot, &type, NULL, &format); - if(type == sceMcTypePS2 && format == 1) - { - if((result = sceMcOpen(port, slot, path, mode)) == 0) - { - return(sceMcSync(0, NULL, &result) == 1 ? result : -11); - } - else - return -10; - } - else - return -12; -} - -static int closeMCFile(int fd) -{ - int result; - - if((result = sceMcClose(fd)) != 0) - return -10; - - return (sceMcSync(0, NULL, &result) == 1 ? result : -11); -} - -static int CheckFileFromMC(int port, int slot, const char *file) -{ - int fd; - - if((fd = openMCFile(port, slot, file, O_RDONLY)) >= 0) - { - closeMCFile(fd); - return 0; - } - - return 1; -} - -/* Note: this is a mesh-up of the two versions of this function. - Originally, the OSDSYS from ROM v2.20 had two similar versions, one for - DVDPlayerGetVersion() and the other for DVDPlayerGetUpdateVersion(). - - Both had their own versions of the memory-card access functions, - but the functions for DVDPlayerGetVersion seemed to have some additional code - (perhaps for updating access status with some other part). - - Both also did different things upon finding a valid update file (see below). */ -static int DVDPlayerUpdateCheck(int *pPort, int *pSlot, char *pVersion) -{ - char dvdplayer_id[64], dvdplayer_e_ver[64], version[32], id[32], region; - const char *pChar; - int port, slot, result, major, minor; - - sprintf(dvdplayer_id, "%s/%s", OSDGetDVDPLExecFolder(), "dvdplayer.id"); - //In OSD v1.0x, the browser used to check either "dvdplayer-j.ver" or "dvdplayer-e.ver", depending on the language setting. - sprintf(dvdplayer_e_ver, "%s/%s", OSDGetDVDPLExecFolder(), "dvdplayer-e.ver"); - - for(port = 0; port < 2; port++) - { - for(slot = 0; slot < 1; slot++) - { - result = ReadFileFromMC(port, slot, dvdplayer_id, id, sizeof(id)); - if(result >= 0) - { - if(result < sizeof(id)) //NULL-terminate, but truncate if too long - id[result] = '\0'; - else - id[sizeof(id) - 1] = '\0'; - - result = ReadFileFromMC(port, slot, dvdplayer_e_ver, version, sizeof(version)); - if(result >= 0) - { - if(result < sizeof(version)) //NULL-terminate, but truncate if too long - version[result] = '\0'; - else - version[sizeof(version) - 1] = '\0'; - - major = atoi(id); - - for(pChar = id; *pChar >= '0' && *pChar <= '9'; pChar++) - {}; - - if(*pChar == '.') - { - minor = atoi(pChar + 1); - - for( ; *pChar >= '0' && *pChar <= '9'; pChar++) - {}; - - result = 0; - region = *pChar; - } - else - { //Missing dot - major = 0; - minor = 0; - region = 0; - result = -1; - } - - if(result == 0) - { - result = -1; - if((ROMDVDPlayer.region == -2) || (ROMDVDPlayer.region == region)) - { - result = (major > ROMDVDPlayer.major) || ((major == ROMDVDPlayer.major) && (minor > ROMDVDPlayer.minor)) ? 0 : -1; - } - - if(result == 0) - { //DVD Player update of the right region exists and is newer. -#ifdef PROHBIT_DVD_0100 - //Ensure that the banned DVD Player is not being booted. - if(strcmp(version, "1.00\n") != 0 && strcmp(version, "1.01\n") != 0) - { -#endif - //This is done for DVDPlayerGetUpdateVersion(). - if(pPort != NULL && pSlot != NULL) - { - *pPort = port; - *pSlot = slot; - } - - //This is done for DVDPlayerGetVersion(). The check for the pointer also existed, even though it checks against a buffer's address. - if(pVersion != NULL) - { - strncpy(pVersion, version, DVD_PLAYER_VER_LEN - 1); - pVersion[DVD_PLAYER_VER_LEN - 1] = '\0'; - } - - return 0; -#ifdef PROHBIT_DVD_0100 - } -#endif - } - } - } - } - } - } - - return -1; -} - -static int DVDPlayerGetUpdateVersion(const char *file, int *pPort, int *pSlot) -{ - int result; - - if((result = DVDPlayerUpdateCheck(pPort, pSlot, NULL)) == 0) - { //DVD Player update of the right region exists and is newer. - return(CheckFileFromMC(*pPort, *pSlot, file) == 0 ? 0 : -1); - } - - return -1; -} - -static int CheckDVDPlayerUpdate(void) -{ - char path[1024]; - int port, slot, fd; - - sprintf(path, "%s/%s", OSDGetDVDPLExecFolder(), "dvdplayer.elf"); - if(DVDPlayerGetUpdateVersion(path, &port, &slot) == 0) - { - return port; - } - else - { - if(OSDGetDVDPlayerRegion(&dvdid[10]) == 0 || (fd = open(dvdid, O_RDONLY)) < 0) - fd = open("rom1:DVDID", O_RDONLY); - - if(fd < 0) - return -1; - close(fd); - - return 2; - } -} - -int DVDPlayerBoot(void) -{ - char *args[4]; - int port; - char dvdplayerCMD[1024]; //This was originally static/global. - - UpdatePlayHistory("DVDVIDEO"); - port = CheckDVDPlayerUpdate(); - if(port >= 0) - { - CleanUp(); //Deinit RPCs - SifExitCmd(); - - if(port >= 2) - { //ROM DVD Player - - args[0] = eromdrvCMD; - args[1] = "-m erom0:UDFIO"; - args[2] = dvdelfCMD; - - //Handle region-specific DVD Player of newer consoles. - if(OSDGetDVDPlayerRegion(&dvdelfCMD[14]) != 0 && dvdelfCMD[14] != '\0') - { - eromdrvCMD[15] = dvdelfCMD[14]; - dvdelfCMD[12] = 'P'; //Change 'E' to 'P': DVDELF -> DVDPLx - } - else - { //Restore the 'E' and 'F' - eromdrvCMD[15] = '\0'; //Replace '?' with a NULL. - dvdelfCMD[12] = 'E'; - dvdelfCMD[14] = 'F'; - } - - LoadExecPS2("moduleload2 rom1:UDNL rom1:DVDCNF", 3, args); - } - else - { //DVD Player Update - args[0] = "-m rom0:SIO2MAN"; - args[1] = "-m rom0:MCMAN"; - args[2] = "-m rom0:MCSERV"; - - sprintf(dvdplayerCMD, "-x mc%d:%s/%s", port, OSDGetDVDPLExecFolder(), "dvdplayer.elf"); - args[3] = dvdplayerCMD; - - LoadExecPS2("moduleload", 4, args); - } - - return 0; - } - else - return EIO; -} - -int DVDPlayerInit(void) -{ - const char *pChar; - char id[32]; - int fd, result; - - ROMDVDPlayer.ver[0] = '\0'; - ROMDVDPlayer.minor = -1; - ROMDVDPlayer.major = -1; - ROMDVDPlayer.region = -1; - - if(OSDGetDVDPlayerRegion(&dvdid[10]) == 0 || (fd = open(dvdid, O_RDONLY)) < 0) - fd = open("rom1:DVDID", O_RDONLY); - - if(fd < 0) - { //Not having a DVD player is not an error. - - //0100J and 0101J has no ROM DVD Player. This rule is copied from the HDD Browser, as it is absent in the normal browser. - if(ConsoleROMVER[0] == '0' && ConsoleROMVER[1] == '1' && ConsoleROMVER[2] == '0' && (ConsoleROMVER[3] == '0' || ConsoleROMVER[3] == '1') && ConsoleROMVER[4] == 'J') - ROMDVDPlayer.region = 'J'; - //I guess, this would be another possibility for such a case, but not used in practice: - // ROMDVDPlayer.region = -2; - - return 0; - } - - read(fd, id, sizeof(id)); - close(fd); - - ROMDVDPlayer.major = atoi(id); - - for(pChar = id; *pChar >= '0' && *pChar <= '9'; pChar++) - {}; - - if(*pChar == '.') - { - ROMDVDPlayer.minor = atoi(pChar + 1); - - for( ; *pChar >= '0' && *pChar <= '9'; pChar++) - {}; - - result = 0; - ROMDVDPlayer.region = *pChar; - } - else - { //Missing dot - ROMDVDPlayer.major = 0; - ROMDVDPlayer.minor = 0; - ROMDVDPlayer.region = 0; - result = -1; - } - - if(result == 0) - { - if(OSDGetDVDPlayerRegion(&dvdver[11]) == 0 || (fd = open(dvdver, O_RDONLY)) < 0) - fd = open("rom1:DVDVER", O_RDONLY); - - if(fd >= 0) - { - result = read(fd, ROMDVDPlayer.ver, sizeof(ROMDVDPlayer.ver)); - close(fd); - - //NULL-terminate, only if non-error - ROMDVDPlayer.ver[result >= 0 ? result : 0] = '\0'; - } - } - - //The original always returned -1. But we'll return something more meaningful. - return(result >= 0 ? 0 : -1); -} - -const char *DVDPlayerGetVersion(void) -{ - static char DVDPlayerUpdateVer[DVD_PLAYER_VER_LEN] = ""; - - if(DVDPlayerUpdateCheck(NULL, NULL, DVDPlayerUpdateVer) == 0) - { //DVD Player update of the right region exists and is newer. - return DVDPlayerUpdateVer; - } - - //DVD Player Update does not exist. Use DVD ROM version. - return ROMDVDPlayer.ver; -} +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "dvdplayer.h" +#include "OSDInit.h" +#include "OSDHistory.h" + +#define DVD_PLAYER_VER_LEN 32 + +struct DVDPlayer +{ + char ver[DVD_PLAYER_VER_LEN]; + int major, minor; + int region; +}; + +static struct DVDPlayer ROMDVDPlayer; + +static char dvdid[] = "rom1:DVDID?"; +static char dvdver[] = "rom1:DVDVER?"; + +static char eromdrvCMD[] = "-k rom1:EROMDRV?"; +static char dvdelfCMD[] = "-x erom0:DVDELF"; + +static int readMCFile(int fd, void *buffer, int len); +static int ReadFileFromMC(int port, int slot, const char *file, void *buffer, int len); +static int getStatMC(int port, int slot, int *type, int *free, int *format); +static int openMCFile(int port, int slot, const char *path, int mode); +static int closeMCFile(int fd); +static int CheckFileFromMC(int port, int slot, const char *file); + +extern char ConsoleROMVER[ROMVER_MAX_LEN]; + +static int readMCFile(int fd, void *buffer, int len) +{ + int result; + + if (sceMcRead(fd, buffer, len) == 0) + { + return (sceMcSync(0, NULL, &result) == 1 ? result : 0); + } + else + return -10; +} + +static int ReadFileFromMC(int port, int slot, const char *file, void *buffer, int len) +{ + int fd, bytesRead; + int result; + + if ((result = getStatMC(port, slot, NULL, NULL, NULL)) >= -2) + { + if ((fd = openMCFile(port, slot, file, 1)) >= 0) + { + if ((bytesRead = readMCFile(fd, buffer, len)) < 0) + return -1; + + return (closeMCFile(fd) >= 0 ? bytesRead : -1); + } + else + return -1; + } + else + return -1; +} + +static int getStatMC(int port, int slot, int *type, int *free, int *format) +{ + int result; + + if ((result = sceMcGetInfo(port, slot, type, free, format)) == 0) + { + return (sceMcSync(0, NULL, &result) == 1 ? result : -11); + } + else + return -10; +} + +static int openMCFile(int port, int slot, const char *path, int mode) +{ + int result, type, format; + + getStatMC(port, slot, &type, NULL, &format); + if (type == sceMcTypePS2 && format == 1) + { + if ((result = sceMcOpen(port, slot, path, mode)) == 0) + { + return (sceMcSync(0, NULL, &result) == 1 ? result : -11); + } + else + return -10; + } + else + return -12; +} + +static int closeMCFile(int fd) +{ + int result; + + if ((result = sceMcClose(fd)) != 0) + return -10; + + return (sceMcSync(0, NULL, &result) == 1 ? result : -11); +} + +static int CheckFileFromMC(int port, int slot, const char *file) +{ + int fd; + + if ((fd = openMCFile(port, slot, file, O_RDONLY)) >= 0) + { + closeMCFile(fd); + return 0; + } + + return 1; +} + +/* Note: this is a mesh-up of the two versions of this function. + Originally, the OSDSYS from ROM v2.20 had two similar versions, one for + DVDPlayerGetVersion() and the other for DVDPlayerGetUpdateVersion(). + + Both had their own versions of the memory-card access functions, + but the functions for DVDPlayerGetVersion seemed to have some additional code + (perhaps for updating access status with some other part). + + Both also did different things upon finding a valid update file (see below). */ +static int DVDPlayerUpdateCheck(int *pPort, int *pSlot, char *pVersion) +{ + char dvdplayer_id[64], dvdplayer_e_ver[64], version[32], id[32], region; + const char *pChar; + int port, slot, result, major, minor; + + sprintf(dvdplayer_id, "%s/%s", OSDGetDVDPLExecFolder(), "dvdplayer.id"); + // In OSD v1.0x, the browser used to check either "dvdplayer-j.ver" or "dvdplayer-e.ver", depending on the language setting. + sprintf(dvdplayer_e_ver, "%s/%s", OSDGetDVDPLExecFolder(), "dvdplayer-e.ver"); + + for (port = 0; port < 2; port++) + { + for (slot = 0; slot < 1; slot++) + { + result = ReadFileFromMC(port, slot, dvdplayer_id, id, sizeof(id)); + if (result >= 0) + { + if (result < sizeof(id)) // NULL-terminate, but truncate if too long + id[result] = '\0'; + else + id[sizeof(id) - 1] = '\0'; + + result = ReadFileFromMC(port, slot, dvdplayer_e_ver, version, sizeof(version)); + if (result >= 0) + { + if (result < sizeof(version)) // NULL-terminate, but truncate if too long + version[result] = '\0'; + else + version[sizeof(version) - 1] = '\0'; + + major = atoi(id); + + for (pChar = id; *pChar >= '0' && *pChar <= '9'; pChar++) + { + }; + + if (*pChar == '.') + { + minor = atoi(pChar + 1); + + for (; *pChar >= '0' && *pChar <= '9'; pChar++) + { + }; + + result = 0; + region = *pChar; + } + else + { // Missing dot + major = 0; + minor = 0; + region = 0; + result = -1; + } + + if (result == 0) + { + result = -1; + if ((ROMDVDPlayer.region == -2) || (ROMDVDPlayer.region == region)) + { + result = (major > ROMDVDPlayer.major) || ((major == ROMDVDPlayer.major) && (minor > ROMDVDPlayer.minor)) ? 0 : -1; + } + + if (result == 0) + { // DVD Player update of the right region exists and is newer. +#ifdef PROHBIT_DVD_0100 + // Ensure that the banned DVD Player is not being booted. + if (strcmp(version, "1.00\n") != 0 && strcmp(version, "1.01\n") != 0) + { +#endif + // This is done for DVDPlayerGetUpdateVersion(). + if (pPort != NULL && pSlot != NULL) + { + *pPort = port; + *pSlot = slot; + } + + // This is done for DVDPlayerGetVersion(). The check for the pointer also existed, even though it checks against a buffer's address. + if (pVersion != NULL) + { + strncpy(pVersion, version, DVD_PLAYER_VER_LEN - 1); + pVersion[DVD_PLAYER_VER_LEN - 1] = '\0'; + } + + return 0; +#ifdef PROHBIT_DVD_0100 + } +#endif + } + } + } + } + } + } + + return -1; +} + +static int DVDPlayerGetUpdateVersion(const char *file, int *pPort, int *pSlot) +{ + int result; + + if ((result = DVDPlayerUpdateCheck(pPort, pSlot, NULL)) == 0) + { // DVD Player update of the right region exists and is newer. + return (CheckFileFromMC(*pPort, *pSlot, file) == 0 ? 0 : -1); + } + + return -1; +} + +static int CheckDVDPlayerUpdate(void) +{ + char path[1024]; + int port, slot, fd; + + sprintf(path, "%s/%s", OSDGetDVDPLExecFolder(), "dvdplayer.elf"); + if (DVDPlayerGetUpdateVersion(path, &port, &slot) == 0) + { + return port; + } + else + { + if (OSDGetDVDPlayerRegion(&dvdid[10]) == 0 || (fd = open(dvdid, O_RDONLY)) < 0) + fd = open("rom1:DVDID", O_RDONLY); + + if (fd < 0) + return -1; + close(fd); + + return 2; + } +} + +int DVDPlayerBoot(void) +{ + char *args[4]; + int port; + char dvdplayerCMD[1024]; // This was originally static/global. + + UpdatePlayHistory("DVDVIDEO"); + port = CheckDVDPlayerUpdate(); + if (port >= 0) + { + CleanUp(); // Deinit RPCs + SifExitCmd(); + + if (port >= 2) + { // ROM DVD Player + + args[0] = eromdrvCMD; + args[1] = "-m erom0:UDFIO"; + args[2] = dvdelfCMD; + + // Handle region-specific DVD Player of newer consoles. + if (OSDGetDVDPlayerRegion(&dvdelfCMD[14]) != 0 && dvdelfCMD[14] != '\0') + { + eromdrvCMD[15] = dvdelfCMD[14]; + dvdelfCMD[12] = 'P'; // Change 'E' to 'P': DVDELF -> DVDPLx + } + else + { // Restore the 'E' and 'F' + eromdrvCMD[15] = '\0'; // Replace '?' with a NULL. + dvdelfCMD[12] = 'E'; + dvdelfCMD[14] = 'F'; + } + + LoadExecPS2("moduleload2 rom1:UDNL rom1:DVDCNF", 3, args); + } + else + { // DVD Player Update + args[0] = "-m rom0:SIO2MAN"; + args[1] = "-m rom0:MCMAN"; + args[2] = "-m rom0:MCSERV"; + + sprintf(dvdplayerCMD, "-x mc%d:%s/%s", port, OSDGetDVDPLExecFolder(), "dvdplayer.elf"); + args[3] = dvdplayerCMD; + + LoadExecPS2("moduleload", 4, args); + } + + return 0; + } + else + return EIO; +} + +int DVDPlayerInit(void) +{ + const char *pChar; + char id[32]; + int fd, result; + + ROMDVDPlayer.ver[0] = '\0'; + ROMDVDPlayer.minor = -1; + ROMDVDPlayer.major = -1; + ROMDVDPlayer.region = -1; + + if (OSDGetDVDPlayerRegion(&dvdid[10]) == 0 || (fd = open(dvdid, O_RDONLY)) < 0) + fd = open("rom1:DVDID", O_RDONLY); + + if (fd < 0) + { // Not having a DVD player is not an error. + + // 0100J and 0101J has no ROM DVD Player. This rule is copied from the HDD Browser, as it is absent in the normal browser. + if (ConsoleROMVER[0] == '0' && ConsoleROMVER[1] == '1' && ConsoleROMVER[2] == '0' && (ConsoleROMVER[3] == '0' || ConsoleROMVER[3] == '1') && ConsoleROMVER[4] == 'J') + ROMDVDPlayer.region = 'J'; + // I guess, this would be another possibility for such a case, but not used in practice: + // ROMDVDPlayer.region = -2; + + return 0; + } + + read(fd, id, sizeof(id)); + close(fd); + + ROMDVDPlayer.major = atoi(id); + + for (pChar = id; *pChar >= '0' && *pChar <= '9'; pChar++) + { + }; + + if (*pChar == '.') + { + ROMDVDPlayer.minor = atoi(pChar + 1); + + for (; *pChar >= '0' && *pChar <= '9'; pChar++) + { + }; + + result = 0; + ROMDVDPlayer.region = *pChar; + } + else + { // Missing dot + ROMDVDPlayer.major = 0; + ROMDVDPlayer.minor = 0; + ROMDVDPlayer.region = 0; + result = -1; + } + + if (result == 0) + { + if (OSDGetDVDPlayerRegion(&dvdver[11]) == 0 || (fd = open(dvdver, O_RDONLY)) < 0) + fd = open("rom1:DVDVER", O_RDONLY); + + if (fd >= 0) + { + result = read(fd, ROMDVDPlayer.ver, sizeof(ROMDVDPlayer.ver)); + close(fd); + + // NULL-terminate, only if non-error + ROMDVDPlayer.ver[result >= 0 ? result : 0] = '\0'; + } + } + + // The original always returned -1. But we'll return something more meaningful. + return (result >= 0 ? 0 : -1); +} + +const char *DVDPlayerGetVersion(void) +{ + static char DVDPlayerUpdateVer[DVD_PLAYER_VER_LEN] = ""; + + if (DVDPlayerUpdateCheck(NULL, NULL, DVDPlayerUpdateVer) == 0) + { // DVD Player update of the right region exists and is newer. + return DVDPlayerUpdateVer; + } + + // DVD Player Update does not exist. Use DVD ROM version. + return ROMDVDPlayer.ver; +} diff --git a/osd/common/libcdvd_add.c b/osd/common/libcdvd_add.c index becf553..246e054 100644 --- a/osd/common/libcdvd_add.c +++ b/osd/common/libcdvd_add.c @@ -1,147 +1,146 @@ -#include -#include -#include -#include -#include - -#include "libcdvd_add.h" - -static unsigned char MECHACON_CMD_S36_supported = 0, MECHACON_CMD_S27_supported = 0, MECHACON_CMD_S24_supported = 0; - -//Initialize add-on functions. Currently only retrieves the MECHACON's version to determine what sceCdAltGetRegionParams() should do. -int cdInitAdd(void) -{ - int result, status, i; - u8 MECHA_version_data[3]; - unsigned int MECHA_version; - - //Like how CDVDMAN checks sceCdMV(), do not continuously attempt to get the MECHACON version because some consoles (e.g. DTL-H301xx) can't return one. - for(i = 0; i <= 100; i++) - { - if((result=sceCdMV(MECHA_version_data, &status)) != 0 && ((status&0x80) == 0)) - { - MECHA_version = MECHA_version_data[2] | ((unsigned int)MECHA_version_data[1] << 8) | ((unsigned int)MECHA_version_data[0] << 16); - MECHACON_CMD_S36_supported = (0x5FFFF < MECHA_version); //v6.0 and later - MECHACON_CMD_S27_supported = (0x501FF < MECHA_version); //v5.2 and later - MECHACON_CMD_S24_supported = (0x4FFFF < MECHA_version); //v5.0 and later - return 0; - } - } - -// printf("Failed to get MECHACON version: %d 0x%x\n", result, status); - - return -1; -} - -/* - This function provides an equivalent of the sceCdGetRegionParams function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command. - It's supported by only slimline consoles, and returns regional information (e.g. MECHACON version, MG region mask, DVD player region letter etc.). -*/ -int sceCdReadRegionParams(u8 *data, u32 *stat) -{ - unsigned char RegionData[15]; - int result; - - memset(data, 0, 13); - if(MECHACON_CMD_S36_supported) - { - if((result = sceCdApplySCmd(0x36, NULL, 0, RegionData, sizeof(RegionData))) != 0) - { - *stat = RegionData[0]; - memcpy(data, &RegionData[1], 13); - } - } - else - { - *stat = 0x100; - result = 1; - } - - return result; -} - -// This function provides an equivalent of the sceCdBootCertify function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command. -int sceCdBootCertify(const u8* data) -{ - int result; - unsigned char CmdResult; - - if((result=sceCdApplySCmd(0x1A, data, 4, &CmdResult, 1))!=0) - { - result=CmdResult; - } - - return result; -} - -int sceCdRM(char *ModelName, u32 *stat) -{ - unsigned char rdata[9]; - unsigned char sdata; - int result1, result2; - - sdata=0; - result1=sceCdApplySCmd(0x17, &sdata, 1, rdata, 9); - - *stat=rdata[0]; - memcpy(ModelName, &rdata[1], 8); - - sdata=8; - result2=sceCdApplySCmd(0x17, &sdata, 1, rdata, 9); - - *stat|=rdata[0]; - memcpy(&ModelName[8], &rdata[1], 8); - - return((result1!=0&&result2!=0)?1:0); -} - -/* - This function provides an equivalent of the sceCdReadPS1BootParam function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command. - It's supported by only slimline consoles, and returns the boot path for the inserted PlayStation disc. -*/ -int sceCdReadPS1BootParam(char *param, u32 *stat) -{ - u8 out[16]; - int result; - - memset(param, 0, 11); - if(MECHACON_CMD_S27_supported) - { - if((result = sceCdApplySCmd(0x27, NULL, 0, out, 13)) != 0) - { - *stat = out[0]; - memcpy(param, &out[1], 11); //Yes, one byte is not copied. - } - } - else - { - *stat = 0x100; - result = 1; - } - - return result; -} - -int sceCdRcBypassCtl(int bypass, u32 *stat) -{ //TODO: not implemented. - u8 in[16], out[16]; - int result; - - memset(in, 0, 11); - if(MECHACON_CMD_S24_supported) - { - // TODO - if((result = sceCdApplySCmd(0x24, &bypass, 4, out, 13)) != 0) - { - *stat = out[0]; - } - } - else - { - *stat = 0x100; - result = 1; - } - - return result; -} - +#include +#include +#include +#include +#include + +#include "libcdvd_add.h" + +static unsigned char MECHACON_CMD_S36_supported = 0, MECHACON_CMD_S27_supported = 0, MECHACON_CMD_S24_supported = 0; + +// Initialize add-on functions. Currently only retrieves the MECHACON's version to determine what sceCdAltGetRegionParams() should do. +int cdInitAdd(void) +{ + int result, status, i; + u8 MECHA_version_data[3]; + unsigned int MECHA_version; + + // Like how CDVDMAN checks sceCdMV(), do not continuously attempt to get the MECHACON version because some consoles (e.g. DTL-H301xx) can't return one. + for (i = 0; i <= 100; i++) + { + if ((result = sceCdMV(MECHA_version_data, &status)) != 0 && ((status & 0x80) == 0)) + { + MECHA_version = MECHA_version_data[2] | ((unsigned int)MECHA_version_data[1] << 8) | ((unsigned int)MECHA_version_data[0] << 16); + MECHACON_CMD_S36_supported = (0x5FFFF < MECHA_version); // v6.0 and later + MECHACON_CMD_S27_supported = (0x501FF < MECHA_version); // v5.2 and later + MECHACON_CMD_S24_supported = (0x4FFFF < MECHA_version); // v5.0 and later + return 0; + } + } + + // printf("Failed to get MECHACON version: %d 0x%x\n", result, status); + + return -1; +} + +/* + This function provides an equivalent of the sceCdGetRegionParams function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command. + It's supported by only slimline consoles, and returns regional information (e.g. MECHACON version, MG region mask, DVD player region letter etc.). +*/ +int sceCdReadRegionParams(u8 *data, u32 *stat) +{ + unsigned char RegionData[15]; + int result; + + memset(data, 0, 13); + if (MECHACON_CMD_S36_supported) + { + if ((result = sceCdApplySCmd(0x36, NULL, 0, RegionData, sizeof(RegionData))) != 0) + { + *stat = RegionData[0]; + memcpy(data, &RegionData[1], 13); + } + } + else + { + *stat = 0x100; + result = 1; + } + + return result; +} + +// This function provides an equivalent of the sceCdBootCertify function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command. +int sceCdBootCertify(const u8 *data) +{ + int result; + unsigned char CmdResult; + + if ((result = sceCdApplySCmd(0x1A, data, 4, &CmdResult, 1)) != 0) + { + result = CmdResult; + } + + return result; +} + +int sceCdRM(char *ModelName, u32 *stat) +{ + unsigned char rdata[9]; + unsigned char sdata; + int result1, result2; + + sdata = 0; + result1 = sceCdApplySCmd(0x17, &sdata, 1, rdata, 9); + + *stat = rdata[0]; + memcpy(ModelName, &rdata[1], 8); + + sdata = 8; + result2 = sceCdApplySCmd(0x17, &sdata, 1, rdata, 9); + + *stat |= rdata[0]; + memcpy(&ModelName[8], &rdata[1], 8); + + return ((result1 != 0 && result2 != 0) ? 1 : 0); +} + +/* + This function provides an equivalent of the sceCdReadPS1BootParam function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command. + It's supported by only slimline consoles, and returns the boot path for the inserted PlayStation disc. +*/ +int sceCdReadPS1BootParam(char *param, u32 *stat) +{ + u8 out[16]; + int result; + + memset(param, 0, 11); + if (MECHACON_CMD_S27_supported) + { + if ((result = sceCdApplySCmd(0x27, NULL, 0, out, 13)) != 0) + { + *stat = out[0]; + memcpy(param, &out[1], 11); // Yes, one byte is not copied. + } + } + else + { + *stat = 0x100; + result = 1; + } + + return result; +} + +int sceCdRcBypassCtl(int bypass, u32 *stat) +{ // TODO: not implemented. + u8 in[16], out[16]; + int result; + + memset(in, 0, 11); + if (MECHACON_CMD_S24_supported) + { + // TODO + if ((result = sceCdApplySCmd(0x24, &bypass, 4, out, 13)) != 0) + { + *stat = out[0]; + } + } + else + { + *stat = 0x100; + result = 1; + } + + return result; +} diff --git a/osd/common/libcdvd_add.h b/osd/common/libcdvd_add.h index 0766666..3cfe7bc 100644 --- a/osd/common/libcdvd_add.h +++ b/osd/common/libcdvd_add.h @@ -1,6 +1,6 @@ -int cdInitAdd(void); -int sceCdReadRegionParams(u8 *data, u32 *stat); -int sceCdReadPS1BootParam(char *param, u32 *stat); -int sceCdBootCertify(const u8* data); -int sceCdRM(char *ModelName, u32 *stat); -int sceCdRcBypassCtl(int bypass, u32 *stat); //TODO: Not implemented. +int cdInitAdd(void); +int sceCdReadRegionParams(u8 *data, u32 *stat); +int sceCdReadPS1BootParam(char *param, u32 *stat); +int sceCdBootCertify(const u8 *data); +int sceCdRM(char *ModelName, u32 *stat); +int sceCdRcBypassCtl(int bypass, u32 *stat); // TODO: Not implemented. diff --git a/osd/common/modelname.c b/osd/common/modelname.c index e5f8d18..b326292 100644 --- a/osd/common/modelname.c +++ b/osd/common/modelname.c @@ -1,77 +1,79 @@ -#include -#include -#include -#include -#include -#include -#include "libcdvd_add.h" - -#include "main.h" -#include "modelname.h" - -#define MODEL_NAME_MAX_LEN 17 -static char ModelName[MODEL_NAME_MAX_LEN]; - -extern char ConsoleROMVER[]; - -static int ReadModelName(char *name) -{ - int stat, result, fd; - - /* This function is a hybrid between the late ROM browser program and the HDD Browser. - In v2.20, there was only a simple null-terminate before calling sceCdRM(), as below. - However, this does not support the early PlayStation 2 models. - In the HDD Browser, the model name buffer was a global instead of an argument. */ - memset(name, 0, MODEL_NAME_MAX_LEN); - - /* Invoking the "Read model" command on the first SCPH-10000 seems to return an error code, - but it seems to function on my SCPH-15000...although no valid name is returned! - In the HDD OSD, "SCPH-10000" is returned when the ROM v1.00 is detected (It checks rom0:ROMVER). - It attempts to read the model name from the ROM OSDSYS program, when ROM v1.01 (late SCPH-10000 and all SCPH-15000 models) is detected. - - The model name was originally hardcoded into the OSDSYS. The MECHACON EEPROM did not have the model name recorded in it. - - Oddly, the console models that come with v1.01, like the SCPH-15000 and DTL-H10000, - will always be identified as "SCPH-10000" by their ROM OSDSYS programs. - */ - if(ConsoleROMVER[0]=='0' && ConsoleROMVER[1]=='1' && ConsoleROMVER[2]=='0'){ - if(ConsoleROMVER[3]=='0') // For ROM v1.00 (Early SCPH-10000 units). - strcpy(name, "SCPH-10000"); - else - { //For ROM v1.01 (Late SCPH-10000, and all SCPH-15000 units). - if((fd = open("rom0:OSDSYS", O_RDONLY)) >= 0) - { //The model name is located at this address. - lseek(fd, 0x8C808, SEEK_SET); - read(fd, name, MODEL_NAME_MAX_LEN); - close(fd); - } - else - strcpy(name, "Unknown"); - } - - return 0; //Original returned -1 - } - else{ - if((result = sceCdRM(name, &stat)) == 1) - { //Command issued successfully. - if(stat & 0x80) - return -2; - if((stat & 0x40) || name[0] == '\0') - strcpy(name, "unknown"); - - return 0; //Original returned -1 - } - else - return -2; - } -} - -int ModelNameInit(void) -{ - return ReadModelName(ModelName); -} - -const char *ModelNameGet(void) -{ - return ModelName; -} +#include +#include +#include +#include +#include +#include +#include "libcdvd_add.h" + +#include "main.h" +#include "modelname.h" + +#define MODEL_NAME_MAX_LEN 17 +static char ModelName[MODEL_NAME_MAX_LEN]; + +extern char ConsoleROMVER[]; + +static int ReadModelName(char *name) +{ + int stat, result, fd; + + /* This function is a hybrid between the late ROM browser program and the HDD Browser. + In v2.20, there was only a simple null-terminate before calling sceCdRM(), as below. + However, this does not support the early PlayStation 2 models. + In the HDD Browser, the model name buffer was a global instead of an argument. */ + memset(name, 0, MODEL_NAME_MAX_LEN); + + /* Invoking the "Read model" command on the first SCPH-10000 seems to return an error code, + but it seems to function on my SCPH-15000...although no valid name is returned! + In the HDD OSD, "SCPH-10000" is returned when the ROM v1.00 is detected (It checks rom0:ROMVER). + It attempts to read the model name from the ROM OSDSYS program, when ROM v1.01 (late SCPH-10000 and all SCPH-15000 models) is detected. + + The model name was originally hardcoded into the OSDSYS. The MECHACON EEPROM did not have the model name recorded in it. + + Oddly, the console models that come with v1.01, like the SCPH-15000 and DTL-H10000, + will always be identified as "SCPH-10000" by their ROM OSDSYS programs. + */ + if (ConsoleROMVER[0] == '0' && ConsoleROMVER[1] == '1' && ConsoleROMVER[2] == '0') + { + if (ConsoleROMVER[3] == '0') // For ROM v1.00 (Early SCPH-10000 units). + strcpy(name, "SCPH-10000"); + else + { // For ROM v1.01 (Late SCPH-10000, and all SCPH-15000 units). + if ((fd = open("rom0:OSDSYS", O_RDONLY)) >= 0) + { // The model name is located at this address. + lseek(fd, 0x8C808, SEEK_SET); + read(fd, name, MODEL_NAME_MAX_LEN); + close(fd); + } + else + strcpy(name, "Unknown"); + } + + return 0; // Original returned -1 + } + else + { + if ((result = sceCdRM(name, &stat)) == 1) + { // Command issued successfully. + if (stat & 0x80) + return -2; + if ((stat & 0x40) || name[0] == '\0') + strcpy(name, "unknown"); + + return 0; // Original returned -1 + } + else + return -2; + } +} + +int ModelNameInit(void) +{ + return ReadModelName(ModelName); +} + +const char *ModelNameGet(void) +{ + return ModelName; +} diff --git a/osd/common/ps1.c b/osd/common/ps1.c index 7ec87b5..8baef6d 100644 --- a/osd/common/ps1.c +++ b/osd/common/ps1.c @@ -1,277 +1,281 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "libcdvd_add.h" - -#include "main.h" -#include "ps1.h" -#include "OSDInit.h" -#include "OSDHistory.h" - -struct PS1DRV{ - char ver[32]; - int major; - int minor; - int region; -}; - -static struct PS1DRV ps1drv = {"", 0, 0, 0}; -static char ps1ver_uni[] = "rom0:PS1VER?"; -static char ps1drv_boot[64] = ""; -static char ps1drv_ver[64] = ""; - -int PS1DRVInit(void) -{ - const char *pChar; - int fd, result; - - ps1drv.ver[0] = '\0'; - - fd = open("rom0:PS1ID", O_RDONLY); - - if(fd < 0) - return -1; - - read(fd, ps1drv.ver, sizeof(ps1drv.ver)); - close(fd); - - pChar = ps1drv.ver; - ps1drv.major = atoi(pChar); - - for(pChar = ps1drv.ver; *pChar >= '0' && *pChar <= '9'; pChar++) - {}; - - if(*pChar == '.') - { - ps1drv.minor = atoi(pChar + 1); - - for( ; *pChar >= '0' && *pChar <= '9'; pChar++) - {}; - - result = 0; - ps1drv.region = *pChar; - } - else - { //Missing dot - ps1drv.region = 0; - ps1drv.major = 0; - ps1drv.minor = 0; - result = -1; - } - - if(result == 0) - { - if(OSDGetPS1DRVRegion(&ps1ver_uni[11]) == 0 || (fd = open(ps1ver_uni, O_RDONLY)) < 0) - fd = open("rom0:PS1VER", O_RDONLY); - - if(fd >= 0) - { - result = read(fd, ps1drv.ver, sizeof(ps1drv.ver) - 1); - close(fd); - - //NULL-terminate, only if non-error - ps1drv.ver[result >= 0 ? result : 0] = '\0'; - } - } - - //The original always returned -1. But we'll return something more meaningful. - return result; -} - -const char *PS1DRVGetVersion(void) -{ - if(ps1drv.ver[0] == '\0') - { //rom0:PS1VER is missing (not present in the earliest ROMs) - return(OSDGetConsoleRegion() == CONSOLE_REGION_JAPAN ? "1.01" : "1.10"); - } - - return ps1drv.ver; -} - -static void CNFGetKey(char *cnf, char *line, const char *key) -{ - const char *pKey; - int len; - - if((len = strlen(key)) != 0) - { - do{ - if(strncmp(cnf, key, len) == 0) - { //Key located. - for(cnf += len; isspace(*cnf); cnf++) - { //Eliminate leading whitespaces. - if(*cnf == '\n' || *cnf == '\0') - return; - } - - if(*cnf == '=') - { //Equals sign found - ++cnf; - - for(; isspace(*cnf); cnf++) - { //Eliminate whitespaces after the equals sign. - if(*cnf == '\n' || *cnf == '\0') - return; - } - - pKey = cnf; - - //Carry on, until the end of the line. - for(; ; cnf++) - { //NULL-terminate at the newline character. - if(*cnf == '\n' || *cnf =='\r') - { - *cnf = '\0'; - break; - } - } - - strcpy(line, pKey); - } - - return; - } - - for(; *cnf != '\n'; cnf++) - { //Skip uptil the newline character - if(*cnf == '\0') //Parse error - return; - } - ++cnf; //Skip the newline character. - }while(*cnf != '\0'); - } -} - -#define CNF_PATH_LEN_MAX 64 - -static int ParseBootCNF(void) -{ - char system_cnf[2048], line[128]; - const char *pChar; - u32 stat; - int fd, size, i, len; - - strcpy(ps1drv_ver, "???"); - strcpy(ps1drv_boot, "???"); - - if(OSDGetConsoleRegion() == CONSOLE_REGION_CHINA) - { //China - /* I do not know why Sony did this for the Chinese console (SCPH-50009). - Perhaps it as an act to strengthen their DRM for that release, - since PlayStation 2 game booting is also slightly different. - - It is normally possible to actually parse SYSTEM.CNF and get the boot filename from BOOT. - Lots of homebrew software do that, and so does Sony (for all other regions). - But I do not know for sure whether that can be done for Chinese PlayStation discs. */ - sceCdReadPS1BootParam(ps1drv_boot, &stat); - - if(stat & 0x180) - { //Command unsupported or failed for some reason. - return 0; - } - - if(ps1drv_boot[4] == '-') - ps1drv_boot[4] = '_'; - - ps1drv_boot[11] = '\0'; - ps1drv_boot[10] = ps1drv_boot[9]; - ps1drv_boot[9] = ps1drv_boot[8]; - ps1drv_boot[8] = '.'; - - return 1; - } - - if((fd = open("cdrom0:\\SYSTEM.CNF;1", O_RDWR)) >= 0) - { - size = read(fd, system_cnf, sizeof(system_cnf)); - close(fd); - - system_cnf[size] = '\0'; - line[0] = '\0'; - - //Parse SYSTEM.CNF - CNFGetKey(system_cnf, line, "BOOT"); - pChar = line; - - //Locate the end of the line. - for(i = 0; *pChar != ';' && *pChar != '\n' && *pChar != '\0'; pChar++,i++) - { - if(i + 1 == CNF_PATH_LEN_MAX + 1) - { - strcpy(ps1drv_boot, "???"); - break; - } - } - - //Now we have reached the end of the line. Go back to the start of the filename and count the length of the filename. - for(i = 0, len = 0; *pChar != '\\' && *pChar != ':'; --pChar,i++,len++) - { - if(i + 1 == CNF_PATH_LEN_MAX + 1) - { - strcpy(ps1drv_boot, "???"); - break; - } - } - - //Copy the filename - --len; - strncpy(ps1drv_boot, pChar + 1, len); - ps1drv_boot[len] = '\0'; - - //Get the version number - ps1drv_ver[0] = '\0'; - CNFGetKey(ps1drv_boot, ps1drv_ver, "VER"); - if(ps1drv_ver[0] == '\0') - strcpy(ps1drv_ver, "???"); - - return 1; - } - else - { //Odd PlayStation title - if((fd = open("cdrom0:\\PSXMYST\\MYST.CCS;1", O_RDWR)) >= 0) - { - close(fd); - strcpy(ps1drv_boot, "SLPS_000.24"); - return 1; - } - else if ((fd = open("cdrom0:\\CDROM\\LASTPHOT\\ALL_C.NBN;1", O_RDWR)) >= 0) - { - close(fd); - strcpy(ps1drv_boot, "SLPS_000.65"); - return 1; - } - else if ((fd = open("cdrom0:\\PSX.EXE;1", O_RDWR)) >= 0) - { //Generic PlayStation game, with no ID information - close(fd); - strcpy(ps1drv_boot, "???"); - return 1; - } - else - return 0; - } -} - -int PS1DRVBoot(void) -{ - char *args[2]; - - if(ParseBootCNF() == 0) - return 4; - - args[0] = ps1drv_boot; - args[1] = ps1drv_ver; - - CleanUp(); - UpdatePlayHistory(ps1drv_boot); - - SifExitCmd(); - - LoadExecPS2("rom0:PS1DRV", 2, args); - - return 0; -} +#include +#include +#include +#include +#include +#include +#include +#include +#include "libcdvd_add.h" + +#include "main.h" +#include "ps1.h" +#include "OSDInit.h" +#include "OSDHistory.h" + +struct PS1DRV +{ + char ver[32]; + int major; + int minor; + int region; +}; + +static struct PS1DRV ps1drv = {"", 0, 0, 0}; +static char ps1ver_uni[] = "rom0:PS1VER?"; +static char ps1drv_boot[64] = ""; +static char ps1drv_ver[64] = ""; + +int PS1DRVInit(void) +{ + const char *pChar; + int fd, result; + + ps1drv.ver[0] = '\0'; + + fd = open("rom0:PS1ID", O_RDONLY); + + if (fd < 0) + return -1; + + read(fd, ps1drv.ver, sizeof(ps1drv.ver)); + close(fd); + + pChar = ps1drv.ver; + ps1drv.major = atoi(pChar); + + for (pChar = ps1drv.ver; *pChar >= '0' && *pChar <= '9'; pChar++) + { + }; + + if (*pChar == '.') + { + ps1drv.minor = atoi(pChar + 1); + + for (; *pChar >= '0' && *pChar <= '9'; pChar++) + { + }; + + result = 0; + ps1drv.region = *pChar; + } + else + { // Missing dot + ps1drv.region = 0; + ps1drv.major = 0; + ps1drv.minor = 0; + result = -1; + } + + if (result == 0) + { + if (OSDGetPS1DRVRegion(&ps1ver_uni[11]) == 0 || (fd = open(ps1ver_uni, O_RDONLY)) < 0) + fd = open("rom0:PS1VER", O_RDONLY); + + if (fd >= 0) + { + result = read(fd, ps1drv.ver, sizeof(ps1drv.ver) - 1); + close(fd); + + // NULL-terminate, only if non-error + ps1drv.ver[result >= 0 ? result : 0] = '\0'; + } + } + + // The original always returned -1. But we'll return something more meaningful. + return result; +} + +const char *PS1DRVGetVersion(void) +{ + if (ps1drv.ver[0] == '\0') + { // rom0:PS1VER is missing (not present in the earliest ROMs) + return (OSDGetConsoleRegion() == CONSOLE_REGION_JAPAN ? "1.01" : "1.10"); + } + + return ps1drv.ver; +} + +static void CNFGetKey(char *cnf, char *line, const char *key) +{ + const char *pKey; + int len; + + if ((len = strlen(key)) != 0) + { + do + { + if (strncmp(cnf, key, len) == 0) + { // Key located. + for (cnf += len; isspace(*cnf); cnf++) + { // Eliminate leading whitespaces. + if (*cnf == '\n' || *cnf == '\0') + return; + } + + if (*cnf == '=') + { // Equals sign found + ++cnf; + + for (; isspace(*cnf); cnf++) + { // Eliminate whitespaces after the equals sign. + if (*cnf == '\n' || *cnf == '\0') + return; + } + + pKey = cnf; + + // Carry on, until the end of the line. + for (;; cnf++) + { // NULL-terminate at the newline character. + if (*cnf == '\n' || *cnf == '\r') + { + *cnf = '\0'; + break; + } + } + + strcpy(line, pKey); + } + + return; + } + + for (; *cnf != '\n'; cnf++) + { // Skip uptil the newline character + if (*cnf == '\0') // Parse error + return; + } + ++cnf; // Skip the newline character. + } while (*cnf != '\0'); + } +} + +#define CNF_PATH_LEN_MAX 64 + +static int ParseBootCNF(void) +{ + char system_cnf[2048], line[128]; + const char *pChar; + u32 stat; + int fd, size, i, len; + + strcpy(ps1drv_ver, "???"); + strcpy(ps1drv_boot, "???"); + + if (OSDGetConsoleRegion() == CONSOLE_REGION_CHINA) + { // China + /* I do not know why Sony did this for the Chinese console (SCPH-50009). + Perhaps it as an act to strengthen their DRM for that release, + since PlayStation 2 game booting is also slightly different. + + It is normally possible to actually parse SYSTEM.CNF and get the boot filename from BOOT. + Lots of homebrew software do that, and so does Sony (for all other regions). + But I do not know for sure whether that can be done for Chinese PlayStation discs. */ + sceCdReadPS1BootParam(ps1drv_boot, &stat); + + if (stat & 0x180) + { // Command unsupported or failed for some reason. + return 0; + } + + if (ps1drv_boot[4] == '-') + ps1drv_boot[4] = '_'; + + ps1drv_boot[11] = '\0'; + ps1drv_boot[10] = ps1drv_boot[9]; + ps1drv_boot[9] = ps1drv_boot[8]; + ps1drv_boot[8] = '.'; + + return 1; + } + + if ((fd = open("cdrom0:\\SYSTEM.CNF;1", O_RDWR)) >= 0) + { + size = read(fd, system_cnf, sizeof(system_cnf)); + close(fd); + + system_cnf[size] = '\0'; + line[0] = '\0'; + + // Parse SYSTEM.CNF + CNFGetKey(system_cnf, line, "BOOT"); + pChar = line; + + // Locate the end of the line. + for (i = 0; *pChar != ';' && *pChar != '\n' && *pChar != '\0'; pChar++, i++) + { + if (i + 1 == CNF_PATH_LEN_MAX + 1) + { + strcpy(ps1drv_boot, "???"); + break; + } + } + + // Now we have reached the end of the line. Go back to the start of the filename and count the length of the filename. + for (i = 0, len = 0; *pChar != '\\' && *pChar != ':'; --pChar, i++, len++) + { + if (i + 1 == CNF_PATH_LEN_MAX + 1) + { + strcpy(ps1drv_boot, "???"); + break; + } + } + + // Copy the filename + --len; + strncpy(ps1drv_boot, pChar + 1, len); + ps1drv_boot[len] = '\0'; + + // Get the version number + ps1drv_ver[0] = '\0'; + CNFGetKey(ps1drv_boot, ps1drv_ver, "VER"); + if (ps1drv_ver[0] == '\0') + strcpy(ps1drv_ver, "???"); + + return 1; + } + else + { // Odd PlayStation title + if ((fd = open("cdrom0:\\PSXMYST\\MYST.CCS;1", O_RDWR)) >= 0) + { + close(fd); + strcpy(ps1drv_boot, "SLPS_000.24"); + return 1; + } + else if ((fd = open("cdrom0:\\CDROM\\LASTPHOT\\ALL_C.NBN;1", O_RDWR)) >= 0) + { + close(fd); + strcpy(ps1drv_boot, "SLPS_000.65"); + return 1; + } + else if ((fd = open("cdrom0:\\PSX.EXE;1", O_RDWR)) >= 0) + { // Generic PlayStation game, with no ID information + close(fd); + strcpy(ps1drv_boot, "???"); + return 1; + } + else + return 0; + } +} + +int PS1DRVBoot(void) +{ + char *args[2]; + + if (ParseBootCNF() == 0) + return 4; + + args[0] = ps1drv_boot; + args[1] = ps1drv_ver; + + CleanUp(); + UpdatePlayHistory(ps1drv_boot); + + SifExitCmd(); + + LoadExecPS2("rom0:PS1DRV", 2, args); + + return 0; +} diff --git a/osd/common/ps2.c b/osd/common/ps2.c index cc79278..cd0279a 100644 --- a/osd/common/ps2.c +++ b/osd/common/ps2.c @@ -1,340 +1,313 @@ -#include -#include -#include -#include -#include -#include -#include "libcdvd_add.h" - -#include "main.h" -#include "ps2.h" -#include "OSDInit.h" -#include "OSDHistory.h" - -void BootError(void) -{ - char *args[0]; - - args[0] = "BootBrowser"; - CleanUp(); - SifExitCmd(); - ExecOSD(1, args); -} - -#define CNF_PATH_LEN_MAX 64 -#define CNF_LEN_MAX 1024 - -static const char *CNFGetToken(const char *cnf, const char *key) -{ - for(; isspace(*cnf); cnf++) - {} - - for(; *key != '\0' ; key++,cnf++) - { - //End of file - if(*cnf == '\0') - return (const char*)-1; - - if(*cnf != *key) - return NULL; //Non-match - } - - return cnf; -} - -static const char *CNFAdvanceLine(const char *start, const char *end) -{ - for(; start <= end; start++) - { - if(*start == '\n') - return start; - } - - BootError(); - - return NULL; -} - -#define CNF_PATH_LEN_MAX 64 - -static const char *CNFGetKey(const char *line, char *key) -{ - int i; - - //Skip leading whitespace - for(; isspace(*line); line++) - { - } - - if(*line == '\0') - { //Unexpected end of file - return (const char*)-1; - } - - for(i = 0; i < CNF_PATH_LEN_MAX && *line != '\0'; i++) - { - if(isgraph(*line)) - { - *key = *line; - line++; - key++; - } - else if(isspace(*line)) - { - *key = '\0'; - break; - } - else if(*line == '\0') - { //Unexpected end of file. This check exists, along with the other similar check above. - return (const char*)-1; - } - } - - return line; -} - -static int CNFCheckBootFile(char *value, const char *key) -{ - int i; - - for( ; *key != ':'; key++) - { - if(*key == '\0') - return 0; - } - - ++key; - if(*key == '\\') - key++; - - for(i = 0; i < 10; i++) - { - if(value[i] != key[i]) - return 0; - } - - return 1; -} - -//The TRUE way (but not the only way!) to get the boot file. Read the comment above PS2DiscBoot(). -static int PS2GetBootFile(char *boot) -{ - u32 k32; - u8 key1[16]; -#ifdef XCDVD_READKEY - u8 key2[16]; -#endif - - if(sceCdReadKey(0, 0, 0x004B, key1) == 0) - return 2; - - switch(sceCdGetError()) - { - case SCECdErREAD: - return 3; - case 0x37: - return 3; - case 0: //Success condition - break; - default: - return 2; - } - -#ifdef XCDVD_READKEY - if(sceCdReadKey(0, 0, 0x0C03, key2) == 0) - return 2; - - switch(sceCdGetError()) - { - case SCECdErREAD: - return 3; - case 0x37: - return 3; - case 0: //Success condition - break; - default: - return 2; - } - - if(OSDGetConsoleRegion() != CONSOLE_REGION_CHINA) - { //The rest of the world - if(key1[0] == 0 - && key1[1] == 0 - && key1[2] == 0 - && key1[3] == 0 - && key1[4] == 0) - return 3; - - if((key2[0] != key1[0]) - || (key2[1] != key1[1]) - || (key2[2] != key1[2]) - || (key2[3] != key1[3]) - || (key2[4] != key1[4])) - return 3; - - if((key1[15] & 5) != 5) - return 3; - - if((key2[15] & 1) == 0) - return 3; -#endif - - boot[11] = '\0'; - - k32 = (key1[4] >> 3) | (key1[14] >> 3 << 5) | ((key1[0] & 0x7F) << 10); - boot[10] = '0' + (k32 % 10); - boot[9] = '0' + (k32 / 10 % 10); - boot[8] = '.'; - boot[7] = '0' + (k32 / 10 / 10 % 10); - boot[6] = '0' + (k32 / 10 / 10 / 10 % 10); - boot[5] = '0' + (k32 / 10 / 10 / 10 / 10 % 10); - boot[4] = '_'; - boot[3] = (key1[0] >> 7) | ((key1[1] & 0x3F) << 1); - boot[2] = (key1[1] >> 6) | ((key1[2] & 0x1F) << 2); - boot[1] = (key1[2] >> 5) | ((key1[3] & 0xF) << 3); - boot[0] = ((key1[4] & 0x7) << 4) | (key1[3] >> 4); - - return 0; -#ifdef XCDVD_READKEY - } - else - { //China - if(key1[0] == 0 - && key1[1] == 0 - && key1[2] == 0 - && key1[3] == 0 - && key1[4] == 0) - return 3; - - if(key1[5] == 0) - { - if(key1[6] == 0 - && key1[7] == 0 - && key1[8] == 0 - && key1[9] == 0) - return 3; - } - - if((key2[0] != key1[0]) - || (key2[1] != key1[1]) - || (key2[2] != key1[2]) - || (key2[3] != key1[3]) - || (key2[4] != key1[4]) - || (key2[5] != key1[5]) - || (key2[6] != key1[6]) - || (key2[7] != key1[7]) - || (key2[8] != key1[8]) - || (key2[9] != key1[9])) - return 3; - - if((key1[5] != key1[0]) - || (key1[6] != key1[1]) - || (key1[7] != key1[2]) - || (key1[8] != key1[3]) - || (key1[9] != key1[4])) - return 3; - - if((key1[15] & 7) != 7) - return 3; - - if((key2[15] & 3) != 3) - return 3; - - boot[11] = '\0'; - - k32 = (key1[4] >> 3 << 5) | (key1[9] >> 3) | ((key1[5] & 0x7F) << 10); - boot[10] = '0' + (k32 % 10); - boot[9] = '0' + (k32 / 10 % 10); - boot[8] = key1[3]; - boot[7] = '0' + (k32 / 10 / 10 % 10); - boot[6] = '0' + (k32 / 10 / 10 / 10 % 10); - boot[5] = '0' + (k32 / 10 / 10 / 10 / 10 % 10); - boot[4] = key1[5]; - boot[3] = ((key1[6] & 0x3F) << 1) | (key1[5] >> 7); - boot[2] = ((key1[7] & 0x1F) << 2) | (key1[6] >> 6); - boot[1] = ((key1[8] & 0xF) << 3) | (key1[7] >> 5); - boot[0] = ((key1[9] & 0x7) << 4) | (key1[8] >> 4); - - return 0; - } -#endif -} - -/* While this function uses sceCdReadKey() to obtain the filename, - it is possible to actually parse SYSTEM.CNF and get the boot filename from BOOT2. - Lots of homebrew software do that. */ -int PS2DiscBoot(void) -{ - char ps2disc_boot[CNF_PATH_LEN_MAX] = ""; //This was originally static/global. - char system_cnf[CNF_LEN_MAX], line[CNF_PATH_LEN_MAX]; //These were originally globals/static. - char *args[1]; - const char *pChar, *cnf_start, *cnf_end; - int fd, size, size_remaining, size_read; - - printf("ExecutePs2GameDisc\n"); - - switch(PS2GetBootFile(ps2disc_boot)) - { - case 2: - return 2; - case 3: - return 3; - } - - //The browser uses open mode 5 when a specific thread is created, otherwise mode 4. - if((fd = open("cdrom0:\\SYSTEM.CNF;1", O_RDONLY)) < 0) - { - printf("Can't open SYSTEM.CNF\n"); - BootError(); - } - - size = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - - if(size >= CNF_LEN_MAX) - size = CNF_LEN_MAX -1; - - for(size_remaining = size; size_remaining > 0; size_remaining -= size_read) - { - if((size_read = read(fd, system_cnf, size_remaining)) <= 0) - { - printf("Can't read SYSTEM.CNF\n"); - BootError(); - } - } - close(fd); - - system_cnf[size] = '\0'; - cnf_end = &system_cnf[size]; - - //Parse SYSTEM.CNF - cnf_start = system_cnf; - while((pChar = CNFGetToken(cnf_start, "BOOT2")) == NULL) - cnf_start = CNFAdvanceLine(cnf_start, cnf_end); - - if(pChar == (const char*)-1) - { //Unexpected EOF - BootError(); - } - - if((pChar = CNFGetToken(pChar, "=")) == (const char*)-1) - { //Unexpected EOF - BootError(); - } - - CNFGetKey(pChar, line); - if(CNFCheckBootFile(ps2disc_boot, line) == 0) - { //Parse error - BootError(); - } - - args[0] = ps2disc_boot; - - CleanUp(); - UpdatePlayHistory(ps2disc_boot); - - SifExitCmd(); - LoadExecPS2("rom0:PS2LOGO", 1, args); - - return 0; -} +#include +#include +#include +#include +#include +#include +#include "libcdvd_add.h" + +#include "main.h" +#include "ps2.h" +#include "OSDInit.h" +#include "OSDHistory.h" + +void BootError(void) +{ + char *args[0]; + + args[0] = "BootBrowser"; + CleanUp(); + SifExitCmd(); + ExecOSD(1, args); +} + +#define CNF_PATH_LEN_MAX 64 +#define CNF_LEN_MAX 1024 + +static const char *CNFGetToken(const char *cnf, const char *key) +{ + for (; isspace(*cnf); cnf++) + { + } + + for (; *key != '\0'; key++, cnf++) + { + // End of file + if (*cnf == '\0') + return (const char *)-1; + + if (*cnf != *key) + return NULL; // Non-match + } + + return cnf; +} + +static const char *CNFAdvanceLine(const char *start, const char *end) +{ + for (; start <= end; start++) + { + if (*start == '\n') + return start; + } + + BootError(); + + return NULL; +} + +#define CNF_PATH_LEN_MAX 64 + +static const char *CNFGetKey(const char *line, char *key) +{ + int i; + + // Skip leading whitespace + for (; isspace(*line); line++) + { + } + + if (*line == '\0') + { // Unexpected end of file + return (const char *)-1; + } + + for (i = 0; i < CNF_PATH_LEN_MAX && *line != '\0'; i++) + { + if (isgraph(*line)) + { + *key = *line; + line++; + key++; + } + else if (isspace(*line)) + { + *key = '\0'; + break; + } + else if (*line == '\0') + { // Unexpected end of file. This check exists, along with the other similar check above. + return (const char *)-1; + } + } + + return line; +} + +static int CNFCheckBootFile(char *value, const char *key) +{ + int i; + + for (; *key != ':'; key++) + { + if (*key == '\0') + return 0; + } + + ++key; + if (*key == '\\') + key++; + + for (i = 0; i < 10; i++) + { + if (value[i] != key[i]) + return 0; + } + + return 1; +} + +// The TRUE way (but not the only way!) to get the boot file. Read the comment above PS2DiscBoot(). +static int PS2GetBootFile(char *boot) +{ + u32 k32; + u8 key1[16]; +#ifdef XCDVD_READKEY + u8 key2[16]; +#endif + + if (sceCdReadKey(0, 0, 0x004B, key1) == 0) + return 2; + + switch (sceCdGetError()) + { + case SCECdErREAD: + return 3; + case 0x37: + return 3; + case 0: // Success condition + break; + default: + return 2; + } + +#ifdef XCDVD_READKEY + if (sceCdReadKey(0, 0, 0x0C03, key2) == 0) + return 2; + + switch (sceCdGetError()) + { + case SCECdErREAD: + return 3; + case 0x37: + return 3; + case 0: // Success condition + break; + default: + return 2; + } + + if (OSDGetConsoleRegion() != CONSOLE_REGION_CHINA) + { // The rest of the world + if (key1[0] == 0 && key1[1] == 0 && key1[2] == 0 && key1[3] == 0 && key1[4] == 0) + return 3; + + if ((key2[0] != key1[0]) || (key2[1] != key1[1]) || (key2[2] != key1[2]) || (key2[3] != key1[3]) || (key2[4] != key1[4])) + return 3; + + if ((key1[15] & 5) != 5) + return 3; + + if ((key2[15] & 1) == 0) + return 3; +#endif + + boot[11] = '\0'; + + k32 = (key1[4] >> 3) | (key1[14] >> 3 << 5) | ((key1[0] & 0x7F) << 10); + boot[10] = '0' + (k32 % 10); + boot[9] = '0' + (k32 / 10 % 10); + boot[8] = '.'; + boot[7] = '0' + (k32 / 10 / 10 % 10); + boot[6] = '0' + (k32 / 10 / 10 / 10 % 10); + boot[5] = '0' + (k32 / 10 / 10 / 10 / 10 % 10); + boot[4] = '_'; + boot[3] = (key1[0] >> 7) | ((key1[1] & 0x3F) << 1); + boot[2] = (key1[1] >> 6) | ((key1[2] & 0x1F) << 2); + boot[1] = (key1[2] >> 5) | ((key1[3] & 0xF) << 3); + boot[0] = ((key1[4] & 0x7) << 4) | (key1[3] >> 4); + + return 0; +#ifdef XCDVD_READKEY + } + else + { // China + if (key1[0] == 0 && key1[1] == 0 && key1[2] == 0 && key1[3] == 0 && key1[4] == 0) + return 3; + + if (key1[5] == 0) + { + if (key1[6] == 0 && key1[7] == 0 && key1[8] == 0 && key1[9] == 0) + return 3; + } + + if ((key2[0] != key1[0]) || (key2[1] != key1[1]) || (key2[2] != key1[2]) || (key2[3] != key1[3]) || (key2[4] != key1[4]) || (key2[5] != key1[5]) || (key2[6] != key1[6]) || (key2[7] != key1[7]) || (key2[8] != key1[8]) || (key2[9] != key1[9])) + return 3; + + if ((key1[5] != key1[0]) || (key1[6] != key1[1]) || (key1[7] != key1[2]) || (key1[8] != key1[3]) || (key1[9] != key1[4])) + return 3; + + if ((key1[15] & 7) != 7) + return 3; + + if ((key2[15] & 3) != 3) + return 3; + + boot[11] = '\0'; + + k32 = (key1[4] >> 3 << 5) | (key1[9] >> 3) | ((key1[5] & 0x7F) << 10); + boot[10] = '0' + (k32 % 10); + boot[9] = '0' + (k32 / 10 % 10); + boot[8] = key1[3]; + boot[7] = '0' + (k32 / 10 / 10 % 10); + boot[6] = '0' + (k32 / 10 / 10 / 10 % 10); + boot[5] = '0' + (k32 / 10 / 10 / 10 / 10 % 10); + boot[4] = key1[5]; + boot[3] = ((key1[6] & 0x3F) << 1) | (key1[5] >> 7); + boot[2] = ((key1[7] & 0x1F) << 2) | (key1[6] >> 6); + boot[1] = ((key1[8] & 0xF) << 3) | (key1[7] >> 5); + boot[0] = ((key1[9] & 0x7) << 4) | (key1[8] >> 4); + + return 0; + } +#endif +} + +/* While this function uses sceCdReadKey() to obtain the filename, + it is possible to actually parse SYSTEM.CNF and get the boot filename from BOOT2. + Lots of homebrew software do that. */ +int PS2DiscBoot(void) +{ + char ps2disc_boot[CNF_PATH_LEN_MAX] = ""; // This was originally static/global. + char system_cnf[CNF_LEN_MAX], line[CNF_PATH_LEN_MAX]; // These were originally globals/static. + char *args[1]; + const char *pChar, *cnf_start, *cnf_end; + int fd, size, size_remaining, size_read; + + printf("ExecutePs2GameDisc\n"); + + switch (PS2GetBootFile(ps2disc_boot)) + { + case 2: + return 2; + case 3: + return 3; + } + + // The browser uses open mode 5 when a specific thread is created, otherwise mode 4. + if ((fd = open("cdrom0:\\SYSTEM.CNF;1", O_RDONLY)) < 0) + { + printf("Can't open SYSTEM.CNF\n"); + BootError(); + } + + size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + + if (size >= CNF_LEN_MAX) + size = CNF_LEN_MAX - 1; + + for (size_remaining = size; size_remaining > 0; size_remaining -= size_read) + { + if ((size_read = read(fd, system_cnf, size_remaining)) <= 0) + { + printf("Can't read SYSTEM.CNF\n"); + BootError(); + } + } + close(fd); + + system_cnf[size] = '\0'; + cnf_end = &system_cnf[size]; + + // Parse SYSTEM.CNF + cnf_start = system_cnf; + while ((pChar = CNFGetToken(cnf_start, "BOOT2")) == NULL) + cnf_start = CNFAdvanceLine(cnf_start, cnf_end); + + if (pChar == (const char *)-1) + { // Unexpected EOF + BootError(); + } + + if ((pChar = CNFGetToken(pChar, "=")) == (const char *)-1) + { // Unexpected EOF + BootError(); + } + + CNFGetKey(pChar, line); + if (CNFCheckBootFile(ps2disc_boot, line) == 0) + { // Parse error + BootError(); + } + + args[0] = ps2disc_boot; + + CleanUp(); + UpdatePlayHistory(ps2disc_boot); + + SifExitCmd(); + LoadExecPS2("rom0:PS2LOGO", 1, args); + + return 0; +} diff --git a/osd/include/OSDConfig.h b/osd/include/OSDConfig.h index 6509424..ae90e3b 100644 --- a/osd/include/OSDConfig.h +++ b/osd/include/OSDConfig.h @@ -1,80 +1,80 @@ -//Loads the OSD configuration from EEPROM -//Returns 0 on success. Non-zero = configuration not initialized -int OSDConfigLoad(void); - -//Saves the OSD configuration to EEPROM -//Set invalid=0 to indicate that the OSD settings are initialized (not invalid). Tells the browser to not display first boot screen. -//Note: calling this function does not automatically apply the settings (call OSDConfigApply). -void OSDConfigSave(u8 invalid); - -//Applies OSD configuration (saves settings into the EE kernel) -void OSDConfigApply(void); - -//Getter/Setter functions -int OSDConfigGetSPDIF(void); -int OSDConfigSetSPDIF(int mode); -int OSDConfigGetScreenType(void); -int OSDConfigSetScreenType(int type); -int OSDConfigGetVideoOutput(void); -int OSDConfigSetVideoOutput(int type); -/* Note: PlayStation 2 consoles officially have a list of supported languages. - Use OSDGetConsoleRegion() to get the console's OSD region, which can determine what it was officially meant to offer. - OSD_REGION_JAPAN: Japanese, English - OSD_REGION_USA, OSD_REGION_EUROPE: English, French, Spanish, German, Italian, Dutch, Portuguese - OSD_REGION_CHINA: English, Simplified Chinese* - OSD_REGION_RUSSIA: English, Russian* - OSD_REGION_KOREA: English, Korean* - OSD_REGION_ASIA: English, Traditional Chinese* - - *These languages were added later on. - Even if the user selects these language, English will be saved as the language setting (refer to OSDConfigApply), which is obtained by games with GetOsdConfigParam. - The true language selected is saved with SetOsdConfigParam2, but no library has been found to support this field. */ -int OSDConfigGetLanguage(void); -int OSDConfigSetLanguage(int language); -int OSDConfigGetLanguageRaw(void); -int OSDConfigSetLanguageRaw(int language); - -int OSDConfigGetRcGameFunction(void); //Whether the Remote Control Game Function is enabled or not -int OSDConfigSetRcGameFunction(int value); //1 = enabled, 0 = disabled - -/* I am not entirely sure what this is. - In ROM v2.20, it seems to have a relationship to a menu that is labeled "Console" and has the text "Remote Control,Off,On". - However, I could not find the necessary conditions for accessing this menu. - - In the HDD Browser, the "Remote Control,Off,On" menu text exists, but does not seem to be used. - - On my SCPH-77006, this setting is disabled, although the other two remote control-related settings are enabled. */ -int OSDConfigGetRcEnabled(void); -int OSDConfigSetRcEnabled(int value); - -/* This should not be adjusted, other than by the code shown in main(). - This field indicates whether the PlayStation 2 supports the remote control. - If enabled, allow the user to enable/disable the remote control game function. */ -int OSDConfigGetRcSupported(void); -int OSDConfigSetRcSupported(int value); - -/* If the user chose to disable the DVD Player progressive scan setting, - it is actually disabled when a DVD Video disc is played because Sony probably wanted the setting to only bind if the user played a DVD. - The browser only allowed this setting to be disabled, by only showing the menu option for it if it was enabled by the DVD Player. */ -int OSDConfigGetDVDPProgressive(void); //Whether the DVD Player's progressive-scan option is enabled. -int OSDConfigSetDVDPProgressive(int value); //0 = progressive disabled (default), 1 = progressive enabled - -int OSDConfigGetTimezoneOffset(void); -int OSDConfigSetTimezoneOffset(int offset); - -int OSDConfigGetTimezone(void); //It appears to be related to the timezone offset field (I guess, the timezone itself). -int OSDConfigSetTimezone(int value); //0x80 seems to be for "Unknown", hence valid values should be from 0x00-0x7F. The browser seems to have code that checks this against the timezone offset. - -int OSDConfigGetDaylightSaving(void); -int OSDConfigSetDaylightSaving(int daylightSaving); -int OSDConfigGetTimeFormat(void); -int OSDConfigSetTimeFormat(int timeFormat); -int OSDConfigGetDateFormat(void); -int OSDConfigSetDateFormat(int dateFormat); -/* Unofficially added, for uniformity. - Only two bits are defined (0x11). - - One is for texture (standard = 0, smooth = 1), - while the other is for disc speed (standard = 0, fast = 1) */ -int OSDConfigGetPSConfig(void); -int OSDConfigSetPSConfig(int config); +// Loads the OSD configuration from EEPROM +// Returns 0 on success. Non-zero = configuration not initialized +int OSDConfigLoad(void); + +// Saves the OSD configuration to EEPROM +// Set invalid=0 to indicate that the OSD settings are initialized (not invalid). Tells the browser to not display first boot screen. +// Note: calling this function does not automatically apply the settings (call OSDConfigApply). +void OSDConfigSave(u8 invalid); + +// Applies OSD configuration (saves settings into the EE kernel) +void OSDConfigApply(void); + +// Getter/Setter functions +int OSDConfigGetSPDIF(void); +int OSDConfigSetSPDIF(int mode); +int OSDConfigGetScreenType(void); +int OSDConfigSetScreenType(int type); +int OSDConfigGetVideoOutput(void); +int OSDConfigSetVideoOutput(int type); +/* Note: PlayStation 2 consoles officially have a list of supported languages. + Use OSDGetConsoleRegion() to get the console's OSD region, which can determine what it was officially meant to offer. + OSD_REGION_JAPAN: Japanese, English + OSD_REGION_USA, OSD_REGION_EUROPE: English, French, Spanish, German, Italian, Dutch, Portuguese + OSD_REGION_CHINA: English, Simplified Chinese* + OSD_REGION_RUSSIA: English, Russian* + OSD_REGION_KOREA: English, Korean* + OSD_REGION_ASIA: English, Traditional Chinese* + + *These languages were added later on. + Even if the user selects these language, English will be saved as the language setting (refer to OSDConfigApply), which is obtained by games with GetOsdConfigParam. + The true language selected is saved with SetOsdConfigParam2, but no library has been found to support this field. */ +int OSDConfigGetLanguage(void); +int OSDConfigSetLanguage(int language); +int OSDConfigGetLanguageRaw(void); +int OSDConfigSetLanguageRaw(int language); + +int OSDConfigGetRcGameFunction(void); // Whether the Remote Control Game Function is enabled or not +int OSDConfigSetRcGameFunction(int value); // 1 = enabled, 0 = disabled + +/* I am not entirely sure what this is. + In ROM v2.20, it seems to have a relationship to a menu that is labeled "Console" and has the text "Remote Control,Off,On". + However, I could not find the necessary conditions for accessing this menu. + + In the HDD Browser, the "Remote Control,Off,On" menu text exists, but does not seem to be used. + + On my SCPH-77006, this setting is disabled, although the other two remote control-related settings are enabled. */ +int OSDConfigGetRcEnabled(void); +int OSDConfigSetRcEnabled(int value); + +/* This should not be adjusted, other than by the code shown in main(). + This field indicates whether the PlayStation 2 supports the remote control. + If enabled, allow the user to enable/disable the remote control game function. */ +int OSDConfigGetRcSupported(void); +int OSDConfigSetRcSupported(int value); + +/* If the user chose to disable the DVD Player progressive scan setting, + it is actually disabled when a DVD Video disc is played because Sony probably wanted the setting to only bind if the user played a DVD. + The browser only allowed this setting to be disabled, by only showing the menu option for it if it was enabled by the DVD Player. */ +int OSDConfigGetDVDPProgressive(void); // Whether the DVD Player's progressive-scan option is enabled. +int OSDConfigSetDVDPProgressive(int value); // 0 = progressive disabled (default), 1 = progressive enabled + +int OSDConfigGetTimezoneOffset(void); +int OSDConfigSetTimezoneOffset(int offset); + +int OSDConfigGetTimezone(void); // It appears to be related to the timezone offset field (I guess, the timezone itself). +int OSDConfigSetTimezone(int value); // 0x80 seems to be for "Unknown", hence valid values should be from 0x00-0x7F. The browser seems to have code that checks this against the timezone offset. + +int OSDConfigGetDaylightSaving(void); +int OSDConfigSetDaylightSaving(int daylightSaving); +int OSDConfigGetTimeFormat(void); +int OSDConfigSetTimeFormat(int timeFormat); +int OSDConfigGetDateFormat(void); +int OSDConfigSetDateFormat(int dateFormat); +/* Unofficially added, for uniformity. + Only two bits are defined (0x11). + + One is for texture (standard = 0, smooth = 1), + while the other is for disc speed (standard = 0, fast = 1) */ +int OSDConfigGetPSConfig(void); +int OSDConfigSetPSConfig(int config); diff --git a/osd/include/OSDHistory.h b/osd/include/OSDHistory.h index 8024f27..52cc67f 100644 --- a/osd/include/OSDHistory.h +++ b/osd/include/OSDHistory.h @@ -1,44 +1,45 @@ -#define MAX_HISTORY_ENTRIES 21 - -/* If the record is valid, the launch count will be >0. - - Starts with: - SLPM_550.52, data: 01 01 00 00 75 1a - After 2 launches: - SLPM_550.52, data: 02 01 00 00 75 1a - After 15 launches: - SLPM_550.52, data: 0e 11 04 00 75 1a - Clock advanced 1 day: - SLPM_550.52, data: 01 01 00 00 76 1a - Clock advanced 1 year: - SLPM_550.52, data: 01 01 00 00 75 1c - Clock set to Jan 1 2013: - SLPM_550.52, data: 01 01 00 00 21 1a - - data[0] = LaunchCount - data[1] = ?? (A bitmask) - data[2] = ?? (The last shift amount used for generating the value of data[1]) - data[3] = ?? (Seems to not be initialized) - data[4-5] = Timestamp in format: YYYYYYYMMMMDDDDD - Note: Year is since year 2000. -*/ - -#define OSD_HISTORY_GET_YEAR(datestamp) ((datestamp)>>9&0x7F) -#define OSD_HISTORY_GET_MONTH(datestamp) ((datestamp)>>5&0xF) -#define OSD_HISTORY_GET_DATE(datestamp) ((datestamp)&0x1F) -#define OSD_HISTORY_SET_DATE(year, month, date) (((u16)(year))<<9 | ((u16)(month)&0xF)<<5 | ((date)&0x1F)) - -struct HistoryEntry{ - char name[16]; - u8 LaunchCount; - u8 bitmask; - u8 ShiftAmount; - u8 padding; - u16 DateStamp; -}; - -void UpdatePlayHistory(const char *name); - -//Low-level functions. Use them for writing your own functions (i.e. writing your own boot animation). -int LoadHistoryFile(int port); -int SaveHistoryFile(int port); +#define MAX_HISTORY_ENTRIES 21 + +/* If the record is valid, the launch count will be >0. + + Starts with: + SLPM_550.52, data: 01 01 00 00 75 1a + After 2 launches: + SLPM_550.52, data: 02 01 00 00 75 1a + After 15 launches: + SLPM_550.52, data: 0e 11 04 00 75 1a + Clock advanced 1 day: + SLPM_550.52, data: 01 01 00 00 76 1a + Clock advanced 1 year: + SLPM_550.52, data: 01 01 00 00 75 1c + Clock set to Jan 1 2013: + SLPM_550.52, data: 01 01 00 00 21 1a + + data[0] = LaunchCount + data[1] = ?? (A bitmask) + data[2] = ?? (The last shift amount used for generating the value of data[1]) + data[3] = ?? (Seems to not be initialized) + data[4-5] = Timestamp in format: YYYYYYYMMMMDDDDD + Note: Year is since year 2000. +*/ + +#define OSD_HISTORY_GET_YEAR(datestamp) ((datestamp) >> 9 & 0x7F) +#define OSD_HISTORY_GET_MONTH(datestamp) ((datestamp) >> 5 & 0xF) +#define OSD_HISTORY_GET_DATE(datestamp) ((datestamp)&0x1F) +#define OSD_HISTORY_SET_DATE(year, month, date) (((u16)(year)) << 9 | ((u16)(month)&0xF) << 5 | ((date)&0x1F)) + +struct HistoryEntry +{ + char name[16]; + u8 LaunchCount; + u8 bitmask; + u8 ShiftAmount; + u8 padding; + u16 DateStamp; +}; + +void UpdatePlayHistory(const char *name); + +// Low-level functions. Use them for writing your own functions (i.e. writing your own boot animation). +int LoadHistoryFile(int port); +int SaveHistoryFile(int port); diff --git a/osd/include/OSDInit.h b/osd/include/OSDInit.h index 4674495..d1d2aa7 100644 --- a/osd/include/OSDInit.h +++ b/osd/include/OSDInit.h @@ -1,154 +1,163 @@ -#define ROMVER_MAX_LEN 16 - -int OSDInitROMVER(void); - -#define CONFIG_BLOCK_SIZE 15 - -enum CONSOLE_REGION{ - CONSOLE_REGION_INVALID = -1, - CONSOLE_REGION_JAPAN = 0, - CONSOLE_REGION_USA, //USA and Asia - CONSOLE_REGION_EUROPE, - CONSOLE_REGION_CHINA, - - CONSOLE_REGION_COUNT -}; - -enum OSD_REGION{ - OSD_REGION_INVALID = -1, - OSD_REGION_JAPAN = 0, - OSD_REGION_USA, - OSD_REGION_EUROPE, - OSD_REGION_CHINA, - OSD_REGION_RUSSIA, - OSD_REGION_KOREA, - OSD_REGION_ASIA, - - OSD_REGION_COUNT -}; - -//Used to store the values, as obtained from the EEPROM/NVM -typedef struct { - /** 0=enabled, 1=disabled */ -/*00*/u32 spdifMode:1; - /** 0=4:3, 1=fullscreen, 2=16:9 */ -/*01*/u32 screenType:2; - /** 0=rgb(scart), 1=component */ -/*03*/u32 videoOutput:1; - /** LANGUAGE_??? value */ -/*04*/u32 language:5; - /** Timezone minutes offset from GMT */ -/*09*/u32 timezoneOffset:11; - /** Timezone ID */ -/*20*/u32 timezone:9; - /** 0=standard(winter), 1=daylight savings(summer) */ -/*29*/u32 daylightSaving:1; - /** 0=24 hour, 1=12 hour */ -/*30*/u32 timeFormat:1; - - /** 0=YYYYMMDD, 1=MMDDYYYY, 2=DDMMYYYY */ -/*00*/u32 dateFormat:2; - /** Remote Control On/Off option */ -/*02*/u32 rcEnabled:1; - /** Remote Control Game Function On/Off */ -/*03*/u32 rcGameFunction:1; - /** Whether the Remote Control is supported by the PlayStation 2. */ -/*04*/u32 rcSupported:1; - /** Whether the DVD player should have progressive scanning enabled. */ -/*05*/u32 dvdpProgressive:1; -} OSDConfig2_t; - -typedef struct { - u8 data[CONFIG_BLOCK_SIZE]; - u8 padding; -} OSDConfig1_t; - -//Structure of OSD Configuration block within EEPROM -typedef struct { - union { - //0x00-0x0E - struct { - u8 ps1drv; - u8 unused[14]; - }; - u8 bytes[CONFIG_BLOCK_SIZE]; - } PS1; - - union { - struct { - //0x0F - u8 spdifMode:1; - u8 screenType:2; - u8 videoOutput:1; - u8 japLanguage:1; - u8 extendedLanguage:1; - u8 unused1:2; //Neither set nor read anywhere. - - //0x10 - u8 language:5; - u8 version:3; - - //0x11 - u8 timezoneOffsetHi:3; - u8 daylightSaving:1; - u8 timeFormat:1; - u8 dateFormat:2; - u8 osdInit:1; - - //0x12 - u8 timezoneOffsetLo; - - //0x13 - u8 timezoneHi:1; - u8 unknownB13_01:3; //Value is carried over - u8 dvdpProgressive:1; - u8 rcSupported:1; - u8 rcGameFunction:1; - u8 rcEnabled:1; - - //0x14 - u8 timezoneLo; - - //0x15-0x1E - u8 unusedBytes[9]; - }; - - u8 bytes[CONFIG_BLOCK_SIZE]; - } PS2; -} OSDConfigStore_t; - -int OSDIsLanguageValid(int region, int language); //Returns >= 0 if language is valid for use in the specified region. -int OSDGetConsoleRegion(void); //Initializes and returns the console's region (CONSOLE_REGION). -void OSDInitSystemPaths(void); //Initializes system directory names -int OSDGetDefaultLanguage(void); //Returns the default language for the console -int OSDGetRegion(void); //Initializes and returns the OSD region (OSD_REGION). -int OSDGetVideoMode(void); //0 = NTSC, 1 = PAL - -//MagicGate-related functions that are applicable to ROM v2.20 and later -int OSDGetPS1DRVRegion(char *region); //Returns the MagicGate region letter for the PlayStation Driver (returns 0 on error) -int OSDGetDVDPlayerRegion(char *region); //Returns the MagicGate region letter for the DVD Player (returns 0 on error) -int OSDGetMGRegion(void); //Returns MagicGate region letter (returns '\0' on error) - -//Low-level OSD configuration-management functions (Please use the functions in OSDConfig instead) -int OSDLoadConfigFromNVM(OSDConfig1_t *osdConfigPS1, OSDConfig2_t *osdConfigPS2); //Load OSD configuration from NVRAM. Returns 0 on success. -int OSDSaveConfigToNVM(const OSDConfig1_t *osdConfigPS1, const OSDConfig2_t *osdConfigPS2, u8 osdInit); //Save OSD configuration to NVRAM. Returns 0 on success. - -//For retrieving various folder names -const char *OSDGetSystemExecFolder(void); -const char *OSDGetSystemDataFolder(void); -const char *OSDGetDVDPLExecFolder(void); -const char *OSDGetHistoryDataFolder(void); - -//For compatibility with the homebrew SDK -#define sceMcInit mcInit -#define sceMcGetInfo mcGetInfo -#define sceMcOpen mcOpen -#define sceMcClose mcClose -#define sceMcSeek mcSeek -#define sceMcRead mcRead -#define sceMcWrite mcWrite -#define sceMcGetDir mcGetDir -#define sceMcMkDir mcMkDir -#define sceMcSetFileInfo mcSetFileInfo -#define sceMcDelete mcDelete -#define sceMcSync mcSync +#define ROMVER_MAX_LEN 16 + +int OSDInitROMVER(void); + +#define CONFIG_BLOCK_SIZE 15 + +enum CONSOLE_REGION +{ + CONSOLE_REGION_INVALID = -1, + CONSOLE_REGION_JAPAN = 0, + CONSOLE_REGION_USA, // USA and Asia + CONSOLE_REGION_EUROPE, + CONSOLE_REGION_CHINA, + + CONSOLE_REGION_COUNT +}; + +enum OSD_REGION +{ + OSD_REGION_INVALID = -1, + OSD_REGION_JAPAN = 0, + OSD_REGION_USA, + OSD_REGION_EUROPE, + OSD_REGION_CHINA, + OSD_REGION_RUSSIA, + OSD_REGION_KOREA, + OSD_REGION_ASIA, + + OSD_REGION_COUNT +}; + +// Used to store the values, as obtained from the EEPROM/NVM +typedef struct +{ + /** 0=enabled, 1=disabled */ + /*00*/ u32 spdifMode : 1; + /** 0=4:3, 1=fullscreen, 2=16:9 */ + /*01*/ u32 screenType : 2; + /** 0=rgb(scart), 1=component */ + /*03*/ u32 videoOutput : 1; + /** LANGUAGE_??? value */ + /*04*/ u32 language : 5; + /** Timezone minutes offset from GMT */ + /*09*/ u32 timezoneOffset : 11; + /** Timezone ID */ + /*20*/ u32 timezone : 9; + /** 0=standard(winter), 1=daylight savings(summer) */ + /*29*/ u32 daylightSaving : 1; + /** 0=24 hour, 1=12 hour */ + /*30*/ u32 timeFormat : 1; + + /** 0=YYYYMMDD, 1=MMDDYYYY, 2=DDMMYYYY */ + /*00*/ u32 dateFormat : 2; + /** Remote Control On/Off option */ + /*02*/ u32 rcEnabled : 1; + /** Remote Control Game Function On/Off */ + /*03*/ u32 rcGameFunction : 1; + /** Whether the Remote Control is supported by the PlayStation 2. */ + /*04*/ u32 rcSupported : 1; + /** Whether the DVD player should have progressive scanning enabled. */ + /*05*/ u32 dvdpProgressive : 1; +} OSDConfig2_t; + +typedef struct +{ + u8 data[CONFIG_BLOCK_SIZE]; + u8 padding; +} OSDConfig1_t; + +// Structure of OSD Configuration block within EEPROM +typedef struct +{ + union + { + // 0x00-0x0E + struct + { + u8 ps1drv; + u8 unused[14]; + }; + u8 bytes[CONFIG_BLOCK_SIZE]; + } PS1; + + union + { + struct + { + // 0x0F + u8 spdifMode : 1; + u8 screenType : 2; + u8 videoOutput : 1; + u8 japLanguage : 1; + u8 extendedLanguage : 1; + u8 unused1 : 2; // Neither set nor read anywhere. + + // 0x10 + u8 language : 5; + u8 version : 3; + + // 0x11 + u8 timezoneOffsetHi : 3; + u8 daylightSaving : 1; + u8 timeFormat : 1; + u8 dateFormat : 2; + u8 osdInit : 1; + + // 0x12 + u8 timezoneOffsetLo; + + // 0x13 + u8 timezoneHi : 1; + u8 unknownB13_01 : 3; // Value is carried over + u8 dvdpProgressive : 1; + u8 rcSupported : 1; + u8 rcGameFunction : 1; + u8 rcEnabled : 1; + + // 0x14 + u8 timezoneLo; + + // 0x15-0x1E + u8 unusedBytes[9]; + }; + + u8 bytes[CONFIG_BLOCK_SIZE]; + } PS2; +} OSDConfigStore_t; + +int OSDIsLanguageValid(int region, int language); // Returns >= 0 if language is valid for use in the specified region. +int OSDGetConsoleRegion(void); // Initializes and returns the console's region (CONSOLE_REGION). +void OSDInitSystemPaths(void); // Initializes system directory names +int OSDGetDefaultLanguage(void); // Returns the default language for the console +int OSDGetRegion(void); // Initializes and returns the OSD region (OSD_REGION). +int OSDGetVideoMode(void); // 0 = NTSC, 1 = PAL + +// MagicGate-related functions that are applicable to ROM v2.20 and later +int OSDGetPS1DRVRegion(char *region); // Returns the MagicGate region letter for the PlayStation Driver (returns 0 on error) +int OSDGetDVDPlayerRegion(char *region); // Returns the MagicGate region letter for the DVD Player (returns 0 on error) +int OSDGetMGRegion(void); // Returns MagicGate region letter (returns '\0' on error) + +// Low-level OSD configuration-management functions (Please use the functions in OSDConfig instead) +int OSDLoadConfigFromNVM(OSDConfig1_t *osdConfigPS1, OSDConfig2_t *osdConfigPS2); // Load OSD configuration from NVRAM. Returns 0 on success. +int OSDSaveConfigToNVM(const OSDConfig1_t *osdConfigPS1, const OSDConfig2_t *osdConfigPS2, u8 osdInit); // Save OSD configuration to NVRAM. Returns 0 on success. + +// For retrieving various folder names +const char *OSDGetSystemExecFolder(void); +const char *OSDGetSystemDataFolder(void); +const char *OSDGetDVDPLExecFolder(void); +const char *OSDGetHistoryDataFolder(void); + +// For compatibility with the homebrew SDK +#define sceMcInit mcInit +#define sceMcGetInfo mcGetInfo +#define sceMcOpen mcOpen +#define sceMcClose mcClose +#define sceMcSeek mcSeek +#define sceMcRead mcRead +#define sceMcWrite mcWrite +#define sceMcGetDir mcGetDir +#define sceMcMkDir mcMkDir +#define sceMcSetFileInfo mcSetFileInfo +#define sceMcDelete mcDelete +#define sceMcSync mcSync diff --git a/osd/include/dvdplayer.h b/osd/include/dvdplayer.h index cdc827e..33acb32 100644 --- a/osd/include/dvdplayer.h +++ b/osd/include/dvdplayer.h @@ -1,9 +1,9 @@ -//Returns 0 on success, non-zero on error. -//It is normal for this to fail on consoles that have no DVD ROM chip (i.e. DEX or the SCPH-10000/SCPH-15000). +// Returns 0 on success, non-zero on error. +// It is normal for this to fail on consoles that have no DVD ROM chip (i.e. DEX or the SCPH-10000/SCPH-15000). int DVDPlayerInit(void); -//Returns 0 on success, non-zero on error. +// Returns 0 on success, non-zero on error. int DVDPlayerBoot(void); -//Returns a human-readable version number for the DVD Player. +// Returns a human-readable version number for the DVD Player. const char *DVDPlayerGetVersion(void); diff --git a/osd/include/libcdvd_add.h b/osd/include/libcdvd_add.h index 20e4dae..2e069a6 100644 --- a/osd/include/libcdvd_add.h +++ b/osd/include/libcdvd_add.h @@ -1,7 +1,6 @@ -int cdInitAdd(void); -int sceCdAltReadRegionParams(u8 *data, u32 *stat); -int sceCdAltReadPS1BootParam(char *param, u32 *stat); -int sceCdAltBootCertify(const u8* data); -int sceCdAltRM(char *ModelName, u32 *stat); -int sceCdAltRcBypassCtl(int bypass, u32 *stat); //TODO: Not implemented. - +int cdInitAdd(void); +int sceCdAltReadRegionParams(u8 *data, u32 *stat); +int sceCdAltReadPS1BootParam(char *param, u32 *stat); +int sceCdAltBootCertify(const u8 *data); +int sceCdAltRM(char *ModelName, u32 *stat); +int sceCdAltRcBypassCtl(int bypass, u32 *stat); // TODO: Not implemented. diff --git a/osd/include/modelname.h b/osd/include/modelname.h index 761798d..41e5987 100644 --- a/osd/include/modelname.h +++ b/osd/include/modelname.h @@ -1,5 +1,5 @@ -//Initializes the console's model name. Returns 0 on success. -int ModelNameInit(void); - -//Returns a human-readable model number for the PlayStation 2 console. -const char *ModelNameGet(void); +// Initializes the console's model name. Returns 0 on success. +int ModelNameInit(void); + +// Returns a human-readable model number for the PlayStation 2 console. +const char *ModelNameGet(void); diff --git a/osd/include/ps1.h b/osd/include/ps1.h index 567d5ca..a1be106 100644 --- a/osd/include/ps1.h +++ b/osd/include/ps1.h @@ -1,8 +1,8 @@ -//Initialize the PlayStation driver in ROM. Returns 0 on success. -int PS1DRVInit(void); - -//Boots the inserted PlayStation game disc. -int PS1DRVBoot(void); - -//Returns a human-readable version number for the PlayStation driver. -const char *PS1DRVGetVersion(void); +// Initialize the PlayStation driver in ROM. Returns 0 on success. +int PS1DRVInit(void); + +// Boots the inserted PlayStation game disc. +int PS1DRVBoot(void); + +// Returns a human-readable version number for the PlayStation driver. +const char *PS1DRVGetVersion(void); diff --git a/osd/include/ps2.h b/osd/include/ps2.h index bd300c5..d6f6e60 100644 --- a/osd/include/ps2.h +++ b/osd/include/ps2.h @@ -1,6 +1,6 @@ -//Boots the inserted PlayStation 2 game disc. Returns 0 on success. +// Boots the inserted PlayStation 2 game disc. Returns 0 on success. int PS2DiscBoot(void); -//Function that reboots the browser with the "BootError" argument. -//You can use this if an unexpected error occurs while booting the software that the user wants to use. +// Function that reboots the browser with the "BootError" argument. +// You can use this if an unexpected error occurs while booting the software that the user wants to use. void BootError(void); diff --git a/osd/linkfile b/osd/linkfile index 9d46e8a..933122b 100644 --- a/osd/linkfile +++ b/osd/linkfile @@ -1,111 +1,111 @@ -/* -# _____ ___ ____ ___ ____ -# ____| | ____| | | |____| -# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. -#----------------------------------------------------------------------- -# Copyright 2001-2004, ps2dev - http://www.ps2dev.org -# Licenced under Academic Free License version 2.0 -# Review ps2sdk README & LICENSE files for further details. -# -# $Id$ -# Linkfile script for ee-ld -*/ - -ENTRY(_start); - -SECTIONS { - .text 0x00200000: { - _ftext = . ; - *(.start) - *(.text) - *(.text.*) - *(.gnu.linkonce.t*) - KEEP(*(.init)) - KEEP(*(.fini)) - QUAD(0) - } - - PROVIDE(_etext = .); - PROVIDE(etext = .); - - .reginfo : { *(.reginfo) } - - /* Global/static constructors and deconstructors. */ - .ctors ALIGN(16): { - KEEP(*crtbegin*.o(.ctors)) - KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) - KEEP(*(SORT(.ctors.*))) - KEEP(*(.ctors)) - } - .dtors ALIGN(16): { - KEEP(*crtbegin*.o(.dtors)) - KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) - KEEP(*(SORT(.dtors.*))) - KEEP(*(.dtors)) - } - - /* Static data. */ - .rodata ALIGN(128): { - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r*) - } - - .data ALIGN(128): { - _fdata = . ; - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - SORT(CONSTRUCTORS) - } - - .rdata ALIGN(128): { *(.rdata) } - .gcc_except_table ALIGN(128): { *(.gcc_except_table) } - - _gp = ALIGN(128) + 0x7ff0; - .lit4 ALIGN(128): { *(.lit4) } - .lit8 ALIGN(128): { *(.lit8) } - - .sdata ALIGN(128): { - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s*) - } - - _edata = .; - PROVIDE(edata = .); - - /* Uninitialized data. */ - .sbss ALIGN(128) : { - _fbss = . ; - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb*) - *(.scommon) - } - - .bss ALIGN(128) : { - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b*) - *(COMMON) - } - _end_bss = .; - - /* Symbols needed by crt0.s. */ - /* Define the stack and heap to be within the 32MB boundary. */ - PROVIDE(_heap_size = 0x02000000 - _end); - PROVIDE(_stack_size = 0x2000); - - _stack = ALIGN(128); - PROVIDE(_stack = .); - . = _stack + _stack_size; - - _end = . ; - PROVIDE(end = .); - - /* Unwanted stuff */ - /DISCARD/ : { - * ( .MIPS.abiflags ) - } -} +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# Linkfile script for ee-ld +*/ + +ENTRY(_start); + +SECTIONS { + .text 0x00200000: { + _ftext = . ; + *(.start) + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + KEEP(*(.init)) + KEEP(*(.fini)) + QUAD(0) + } + + PROVIDE(_etext = .); + PROVIDE(etext = .); + + .reginfo : { *(.reginfo) } + + /* Global/static constructors and deconstructors. */ + .ctors ALIGN(16): { + KEEP(*crtbegin*.o(.ctors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + } + .dtors ALIGN(16): { + KEEP(*crtbegin*.o(.dtors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + } + + /* Static data. */ + .rodata ALIGN(128): { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .data ALIGN(128): { + _fdata = . ; + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + + .rdata ALIGN(128): { *(.rdata) } + .gcc_except_table ALIGN(128): { *(.gcc_except_table) } + + _gp = ALIGN(128) + 0x7ff0; + .lit4 ALIGN(128): { *(.lit4) } + .lit8 ALIGN(128): { *(.lit8) } + + .sdata ALIGN(128): { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + + _edata = .; + PROVIDE(edata = .); + + /* Uninitialized data. */ + .sbss ALIGN(128) : { + _fbss = . ; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb*) + *(.scommon) + } + + .bss ALIGN(128) : { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + } + _end_bss = .; + + /* Symbols needed by crt0.s. */ + /* Define the stack and heap to be within the 32MB boundary. */ + PROVIDE(_heap_size = 0x02000000 - _end); + PROVIDE(_stack_size = 0x2000); + + _stack = ALIGN(128); + PROVIDE(_stack = .); + . = _stack + _stack_size; + + _end = . ; + PROVIDE(end = .); + + /* Unwanted stuff */ + /DISCARD/ : { + * ( .MIPS.abiflags ) + } +} diff --git a/osd/main.c b/osd/main.c index af35c8f..b9917f6 100644 --- a/osd/main.c +++ b/osd/main.c @@ -43,13 +43,13 @@ extern unsigned int size_psx_ioprp; #endif void CleanUp(void) -{ //This is called from DVDPlayerBoot(). Deinitialize all RPCs here. - sceCdInit(SCECdEXIT); +{ // This is called from DVDPlayerBoot(). Deinitialize all RPCs here. + sceCdInit(SCECdEXIT); } static void AlarmCallback(s32 alarm_id, u16 time, void *common) { - iWakeupThread((int)common); + iWakeupThread((int)common); } #ifdef PSX @@ -58,295 +58,305 @@ static void AlarmCallback(s32 alarm_id, u16 time, void *common) */ static void InitPSX() { - int result, stat; + int result, stat; - SifInitRpc(0); - sceCdInit(SCECdINoD); + SifInitRpc(0); + sceCdInit(SCECdINoD); - //No need to perform boot certification because rom0:OSDSYS does it. - while(sceCdChgSys(2) != 2){}; //Switch the drive into PS2 mode. + // No need to perform boot certification because rom0:OSDSYS does it. + while (sceCdChgSys(2) != 2) {}; // Switch the drive into PS2 mode. - //Signal the start of a game, so that the user can use the "quit" game button. - do{ - result = sceCdNoticeGameStart(1, &stat); - }while((result == 0) || (stat & 0x80)); + // Signal the start of a game, so that the user can use the "quit" game button. + do + { + result = sceCdNoticeGameStart(1, &stat); + } while ((result == 0) || (stat & 0x80)); - //Reset the IOP again to get the standard PS2 default modules. - while(!SifIopReset("", 0)){}; + // Reset the IOP again to get the standard PS2 default modules. + while (!SifIopReset("", 0)) {}; - /* Set the EE kernel into 32MB mode. Let's do this, while the IOP is being reboot. - The memory will be limited with the TLB. The remap can be triggered by calling the _InitTLB syscall - or with ExecPS2(). - WARNING! If the stack pointer resides above the 32MB offset at the point of remap, a TLB exception will occur. - This example has the stack pointer configured to be within the 32MB limit. */ - SetMemoryMode(1); - _InitTLB(); + /* Set the EE kernel into 32MB mode. Let's do this, while the IOP is being reboot. + The memory will be limited with the TLB. The remap can be triggered by calling the _InitTLB syscall + or with ExecPS2(). + WARNING! If the stack pointer resides above the 32MB offset at the point of remap, a TLB exception will occur. + This example has the stack pointer configured to be within the 32MB limit. */ + SetMemoryMode(1); + _InitTLB(); - while(!SifIopSync()) {}; + while (!SifIopSync()) {}; } #endif int main(int argc, char *argv[]) { - int fd, OldDiscType, DiscType, ValidDiscInserted, result; - u32 stat; + int fd, OldDiscType, DiscType, ValidDiscInserted, result; + u32 stat; #ifndef PSX - char romver[16], RomName[4]; + char romver[16], RomName[4]; #endif - //Initialize SIFCMD & SIFRPC - SifInitRpc(0); + // Initialize SIFCMD & SIFRPC + SifInitRpc(0); - //Reboot IOP + // Reboot IOP #ifndef PSX - while(!SifIopReset("", 0)){}; + while (!SifIopReset("", 0)) + { + }; #else - /* We need some of the PSX's CDVDMAN facilities, but we do not want to use its (too-)new FILEIO module. - This special IOPRP image contains a IOPBTCONF list that lists PCDVDMAN instead of CDVDMAN. - PCDVDMAN is the board-specific CDVDMAN module on all PSX, which can be used to switch the CD/DVD drive operating mode. - Usually, I would discourage people from using board-specific modules, but I do not have a proper replacement for this. */ - while(!SifIopRebootBuffer(psx_ioprp, size_psx_ioprp)){}; + /* We need some of the PSX's CDVDMAN facilities, but we do not want to use its (too-)new FILEIO module. + This special IOPRP image contains a IOPBTCONF list that lists PCDVDMAN instead of CDVDMAN. + PCDVDMAN is the board-specific CDVDMAN module on all PSX, which can be used to switch the CD/DVD drive operating mode. + Usually, I would discourage people from using board-specific modules, but I do not have a proper replacement for this. */ + while (!SifIopRebootBuffer(psx_ioprp, size_psx_ioprp)) {}; #endif - while(!SifIopSync()){}; + while (!SifIopSync()) + { + }; #ifdef PSX - InitPSX(); + InitPSX(); #endif - //Initialize SIFCMD & SIFRPC - SifInitRpc(0); + // Initialize SIFCMD & SIFRPC + SifInitRpc(0); - //Initialize SIF services for loading modules and files. - SifInitIopHeap(); - SifLoadFileInit(); - fioInit(); + // Initialize SIF services for loading modules and files. + SifInitIopHeap(); + SifLoadFileInit(); + fioInit(); - //The old IOP kernel has no support for LoadModuleBuffer. Apply the patch to enable it. - sbv_patch_enable_lmb(); - /* Load the SIO2 modules. You may choose to use the ones from ROM, - but they may not be supported by all PlayStation 2 variants. */ - SifExecModuleBuffer(sio2man_irx, size_sio2man_irx, 0, NULL, NULL); - SifExecModuleBuffer(mcman_irx, size_mcman_irx, 0, NULL, NULL); - SifExecModuleBuffer(mcserv_irx, size_mcserv_irx, 0, NULL, NULL); - //Initialize libmc. - mcInit(MC_TYPE_XMC); + // The old IOP kernel has no support for LoadModuleBuffer. Apply the patch to enable it. + sbv_patch_enable_lmb(); + /* Load the SIO2 modules. You may choose to use the ones from ROM, + but they may not be supported by all PlayStation 2 variants. */ + SifExecModuleBuffer(sio2man_irx, size_sio2man_irx, 0, NULL, NULL); + SifExecModuleBuffer(mcman_irx, size_mcman_irx, 0, NULL, NULL); + SifExecModuleBuffer(mcserv_irx, size_mcserv_irx, 0, NULL, NULL); + // Initialize libmc. + mcInit(MC_TYPE_XMC); - //Load ADDDRV. The OSD has it listed in rom0:OSDCNF/IOPBTCONF, but it is otherwise not loaded automatically. - SifLoadModule("rom0:ADDDRV", 0, NULL); + // Load ADDDRV. The OSD has it listed in rom0:OSDCNF/IOPBTCONF, but it is otherwise not loaded automatically. + SifLoadModule("rom0:ADDDRV", 0, NULL); - //Initialize libcdvd & supplement functions (which are not part of the ancient libcdvd library we use). - sceCdInit(SCECdINoD); - cdInitAdd(); + // Initialize libcdvd & supplement functions (which are not part of the ancient libcdvd library we use). + sceCdInit(SCECdINoD); + cdInitAdd(); - //Initialize system paths. - OSDInitSystemPaths(); + // Initialize system paths. + OSDInitSystemPaths(); #ifndef PSX - /* Perform boot certification to enable the CD/DVD drive. - This is not required for the PSX, as its OSDSYS will do it before booting the update. */ - if((fd = open("rom0:ROMVER", O_RDONLY)) >= 0) - { - read(fd, romver, sizeof(romver)); - close(fd); - - // e.g. 0160HC = 1,60,'H','C' - RomName[0]=(romver[0]-'0')*10 + (romver[1]-'0'); - RomName[1]=(romver[2]-'0')*10 + (romver[3]-'0'); - RomName[2]=romver[4]; - RomName[3]=romver[5]; - - //Do not check for success/failure. Early consoles do not support (and do not require) boot-certification. - sceCdBootCertify(RomName); - } - - //This disables DVD Video Disc playback. This functionality is restored by loading a DVD Player KELF. - /* Hmm. What should the check for stat be? In v1.xx, it seems to be a check against 0x08. In v2.20, it checks against 0x80. - The HDD Browser does not call this function, but I guess it would check against 0x08. */ -/* do{ - sceCdForbidDVDP(&stat); - }while(stat & 0x08); */ + /* Perform boot certification to enable the CD/DVD drive. + This is not required for the PSX, as its OSDSYS will do it before booting the update. */ + if ((fd = open("rom0:ROMVER", O_RDONLY)) >= 0) + { + read(fd, romver, sizeof(romver)); + close(fd); + + // e.g. 0160HC = 1,60,'H','C' + RomName[0] = (romver[0] - '0') * 10 + (romver[1] - '0'); + RomName[1] = (romver[2] - '0') * 10 + (romver[3] - '0'); + RomName[2] = romver[4]; + RomName[3] = romver[5]; + + // Do not check for success/failure. Early consoles do not support (and do not require) boot-certification. + sceCdBootCertify(RomName); + } + + // This disables DVD Video Disc playback. This functionality is restored by loading a DVD Player KELF. + /* Hmm. What should the check for stat be? In v1.xx, it seems to be a check against 0x08. In v2.20, it checks against 0x80. + The HDD Browser does not call this function, but I guess it would check against 0x08. */ + /* do + { + sceCdForbidDVDP(&stat); + } while (stat & 0x08); */ #endif - //Apply kernel updates for applicable kernels. - InitOsd(); - - //Initialize ROM version (must be done first). - OSDInitROMVER(); - - //Initialize model name - ModelNameInit(); - - //Initialize PlayStation Driver (PS1DRV) - PS1DRVInit(); - - //Initialize ROM DVD player. - //It is normal for this to fail on consoles that have no DVD ROM chip (i.e. DEX or the SCPH-10000/SCPH-15000). - DVDPlayerInit(); - - //Load OSD configuration - if(OSDConfigLoad() != 0) - { //OSD configuration not initialized. Defaults loaded. - printf("OSD Configuration not initialized. Defaults loaded.\n"); - } - - //Applies OSD configuration (saves settings into the EE kernel) - OSDConfigApply(); - - /* Try to enable the remote control, if it is enabled. - Indicate no hardware support for it, if it cannot be enabled. */ - do { - result = sceCdRcBypassCtl(OSDConfigGetRcGameFunction() ^ 1, &stat); - if(stat & 0x100) - { //Not supported by the PlayStation 2. - //Note: it does not seem like the browser updates the NVRAM here to change this status. - OSDConfigSetRcEnabled(0); - OSDConfigSetRcSupported(0); - break; - } - } while((stat & 0x80) || (result == 0)); - - //Remember to set the video output option (RGB or Y Cb/Pb Cr/Pr) accordingly, before SetGsCrt() is called. - SetGsVParam(OSDConfigGetVideoOutput() == VIDEO_OUTPUT_RGB ? 0 : 1); - - init_scr(); - scr_printf( "SIDIF Mode:\t%u\n" - "Screen type:\t%u\n" - "Video mode:\t%u\n" - "Language:\t%u\n" - "PS1DRV config:\t0x%02x\n" - "Timezone offset:\t%u\n" - "Daylight savings:\t%u\n" - "Time format:\t%u\n" - "Date format:\t%u\n", OSDConfigGetSPDIF(), - OSDConfigGetScreenType(), - OSDConfigGetVideoOutput(), - OSDConfigGetLanguage(), - OSDConfigGetPSConfig(), - OSDConfigGetTimezoneOffset(), - OSDConfigGetDaylightSaving(), - OSDConfigGetTimeFormat(), - OSDConfigGetDateFormat()); - - /* If required, make any changes with the getter/setter functions in OSDConfig.h, before calling OSDConfigSave(1). - Example: - OSDConfigSetScreenType(TV_SCREEN_169); - OSDConfigSave(0); - OSDConfigApply(); */ - - scr_printf( "\nModel:\t\t%s\n" - "PlayStation Driver:\t%s\n" - "DVD Player:\t%s\n", ModelNameGet(), - PS1DRVGetVersion(), - DVDPlayerGetVersion()); - - - /* Update Play History (if required) - This is now more of a FYI, since the DVD and PS/PS2 game disc-booting code will do it for you. - Provide the boot filename (without the ";1" suffix) for PlayStation/PlayStation 2 games. */ -// UpdatePlayHistory("SLPM_550.52"); - - /* If the user chose to have diagnosis enabled, it can be enabled/disabled at any time. - The browser does this in the background, but this is put here to show how it is done. - - Hmm. What should the check for stat be? In v1.xx, it seems to be a check against 0x08. In v2.20, it checks against 0x80. - The HDD browser checks for 0x08. - But because we are targeting all consoles, it would be probably safer to follow the HDD Browser. */ - scr_printf("Enabling Diagnosis...\n"); - do { //0 = enable, 1 = disable. - result = sceCdAutoAdjustCtrl(0, &stat); - } while((stat & 0x08) || (result == 0)); - - //For this demo, wait for a valid disc to be inserted. - scr_printf("Waiting for disc to be inserted...\n"); - - ValidDiscInserted = 0; - OldDiscType = -1; - while(!ValidDiscInserted) - { - DiscType = sceCdGetDiskType(); - if(DiscType != OldDiscType) - { - scr_printf("New Disc:\t"); - OldDiscType = DiscType; - - switch(DiscType) - { - case SCECdNODISC: - scr_printf("No Disc\n"); - break; - - case SCECdDETCT: - case SCECdDETCTCD: - case SCECdDETCTDVDS: - case SCECdDETCTDVDD: - scr_printf("Reading Disc...\n"); - break; - - case SCECdPSCD: - case SCECdPSCDDA: - scr_printf("PlayStation\n"); - ValidDiscInserted = 1; - break; - - case SCECdPS2CD: - case SCECdPS2CDDA: - case SCECdPS2DVD: - scr_printf("PlayStation 2\n"); - ValidDiscInserted = 1; - break; - - case SCECdCDDA: - scr_printf("Audio Disc (not supported by this demo)\n"); - break; - - case SCECdDVDV: - scr_printf("DVD Video\n"); - ValidDiscInserted = 1; - break; - default: - scr_printf("Unknown\n"); - } - } - - //Avoid spamming the IOP with sceCdGetDiskType(), or there may be a deadlock. - //The NTSC/PAL H-sync is approximately 16kHz. Hence approximately 16 ticks will pass every millisecond. - SetAlarm(1000 * 16, &AlarmCallback, (void*)GetThreadId()); - SleepThread(); - } - - //Now that a valid disc is inserted, do something. - //CleanUp() will be called, to deinitialize RPCs. SIFRPC will be deinitialized by the respective disc-handlers. - switch(DiscType) - { - case SCECdPSCD: - case SCECdPSCDDA: - //Boot PlayStation disc - PS1DRVBoot(); - break; - - case SCECdPS2CD: - case SCECdPS2CDDA: - case SCECdPS2DVD: - //Boot PlayStation 2 disc - PS2DiscBoot(); - break; - - case SCECdDVDV: - /* If the user chose to disable the DVD Player progressive scan setting, - it is disabled here because Sony probably wanted the setting to only bind if the user played a DVD. - The original did the updating of the EEPROM in the background, but I want to keep this demo simple. - The browser only allowed this setting to be disabled, by only showing the menu option for it if it was enabled by the DVD Player. */ - /* OSDConfigSetDVDPProgressive(0); - OSDConfigApply(); */ - - /* Boot DVD Player. If one is stored on the memory card and is newer, it is booted instead of the one from ROM. - Play history is automatically updated. */ - DVDPlayerBoot(); - break; - } - - /* If execution reaches here, SIFRPC has been initialized. You can choose to exit, or do something else. - But if you do something else that requires SIFRPC, remember to re-initialize SIFRPC first. */ - - return 0; + // Apply kernel updates for applicable kernels. + InitOsd(); + + // Initialize ROM version (must be done first). + OSDInitROMVER(); + + // Initialize model name + ModelNameInit(); + + // Initialize PlayStation Driver (PS1DRV) + PS1DRVInit(); + + // Initialize ROM DVD player. + // It is normal for this to fail on consoles that have no DVD ROM chip (i.e. DEX or the SCPH-10000/SCPH-15000). + DVDPlayerInit(); + + // Load OSD configuration + if (OSDConfigLoad() != 0) + { // OSD configuration not initialized. Defaults loaded. + printf("OSD Configuration not initialized. Defaults loaded.\n"); + } + + // Applies OSD configuration (saves settings into the EE kernel) + OSDConfigApply(); + + /* Try to enable the remote control, if it is enabled. + Indicate no hardware support for it, if it cannot be enabled. */ + do + { + result = sceCdRcBypassCtl(OSDConfigGetRcGameFunction() ^ 1, &stat); + if (stat & 0x100) + { // Not supported by the PlayStation 2. + // Note: it does not seem like the browser updates the NVRAM here to change this status. + OSDConfigSetRcEnabled(0); + OSDConfigSetRcSupported(0); + break; + } + } while ((stat & 0x80) || (result == 0)); + + // Remember to set the video output option (RGB or Y Cb/Pb Cr/Pr) accordingly, before SetGsCrt() is called. + SetGsVParam(OSDConfigGetVideoOutput() == VIDEO_OUTPUT_RGB ? 0 : 1); + + init_scr(); + scr_printf("SIDIF Mode:\t%u\n" + "Screen type:\t%u\n" + "Video mode:\t%u\n" + "Language:\t%u\n" + "PS1DRV config:\t0x%02x\n" + "Timezone offset:\t%u\n" + "Daylight savings:\t%u\n" + "Time format:\t%u\n" + "Date format:\t%u\n", + OSDConfigGetSPDIF(), + OSDConfigGetScreenType(), + OSDConfigGetVideoOutput(), + OSDConfigGetLanguage(), + OSDConfigGetPSConfig(), + OSDConfigGetTimezoneOffset(), + OSDConfigGetDaylightSaving(), + OSDConfigGetTimeFormat(), + OSDConfigGetDateFormat()); + + /* If required, make any changes with the getter/setter functions in OSDConfig.h, before calling OSDConfigSave(1). + Example: */ +/* OSDConfigSetScreenType(TV_SCREEN_169); + OSDConfigSave(0); + OSDConfigApply(); */ + + scr_printf("\nModel:\t\t%s\n" + "PlayStation Driver:\t%s\n" + "DVD Player:\t%s\n", + ModelNameGet(), + PS1DRVGetVersion(), + DVDPlayerGetVersion()); + + + /* Update Play History (if required) + This is now more of a FYI, since the DVD and PS/PS2 game disc-booting code will do it for you. + Provide the boot filename (without the ";1" suffix) for PlayStation/PlayStation 2 games. */ + // UpdatePlayHistory("SLPM_550.52"); + + /* If the user chose to have diagnosis enabled, it can be enabled/disabled at any time. + The browser does this in the background, but this is put here to show how it is done. + + Hmm. What should the check for stat be? In v1.xx, it seems to be a check against 0x08. In v2.20, it checks against 0x80. + The HDD browser checks for 0x08. + But because we are targeting all consoles, it would be probably safer to follow the HDD Browser. */ + scr_printf("Enabling Diagnosis...\n"); + do + { // 0 = enable, 1 = disable. + result = sceCdAutoAdjustCtrl(0, &stat); + } while ((stat & 0x08) || (result == 0)); + + // For this demo, wait for a valid disc to be inserted. + scr_printf("Waiting for disc to be inserted...\n"); + + ValidDiscInserted = 0; + OldDiscType = -1; + while (!ValidDiscInserted) + { + DiscType = sceCdGetDiskType(); + if (DiscType != OldDiscType) + { + scr_printf("New Disc:\t"); + OldDiscType = DiscType; + + switch (DiscType) + { + case SCECdNODISC: + scr_printf("No Disc\n"); + break; + + case SCECdDETCT: + case SCECdDETCTCD: + case SCECdDETCTDVDS: + case SCECdDETCTDVDD: + scr_printf("Reading Disc...\n"); + break; + + case SCECdPSCD: + case SCECdPSCDDA: + scr_printf("PlayStation\n"); + ValidDiscInserted = 1; + break; + + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + scr_printf("PlayStation 2\n"); + ValidDiscInserted = 1; + break; + + case SCECdCDDA: + scr_printf("Audio Disc (not supported by this demo)\n"); + break; + + case SCECdDVDV: + scr_printf("DVD Video\n"); + ValidDiscInserted = 1; + break; + default: + scr_printf("Unknown\n"); + } + } + + // Avoid spamming the IOP with sceCdGetDiskType(), or there may be a deadlock. + // The NTSC/PAL H-sync is approximately 16kHz. Hence approximately 16 ticks will pass every millisecond. + SetAlarm(1000 * 16, &AlarmCallback, (void *)GetThreadId()); + SleepThread(); + } + + // Now that a valid disc is inserted, do something. + // CleanUp() will be called, to deinitialize RPCs. SIFRPC will be deinitialized by the respective disc-handlers. + switch (DiscType) + { + case SCECdPSCD: + case SCECdPSCDDA: + // Boot PlayStation disc + PS1DRVBoot(); + break; + + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + // Boot PlayStation 2 disc + PS2DiscBoot(); + break; + + case SCECdDVDV: + /* If the user chose to disable the DVD Player progressive scan setting, + it is disabled here because Sony probably wanted the setting to only bind if the user played a DVD. + The original did the updating of the EEPROM in the background, but I want to keep this demo simple. + The browser only allowed this setting to be disabled, by only showing the menu option for it if it was enabled by the DVD Player. */ + /* OSDConfigSetDVDPProgressive(0); + OSDConfigApply(); */ + + /* Boot DVD Player. If one is stored on the memory card and is newer, it is booted instead of the one from ROM. + Play history is automatically updated. */ + DVDPlayerBoot(); + break; + } + + /* If execution reaches here, SIFRPC has been initialized. You can choose to exit, or do something else. + But if you do something else that requires SIFRPC, remember to re-initialize SIFRPC first. */ + + return 0; } diff --git a/osd/psx/plibcdvd_add.h b/osd/psx/plibcdvd_add.h index f9e5e43..4952a61 100644 --- a/osd/psx/plibcdvd_add.h +++ b/osd/psx/plibcdvd_add.h @@ -1,3 +1,2 @@ -int sceCdChgSys(int mode); -int sceCdNoticeGameStart(int mode, u32 *result); - +int sceCdChgSys(int mode); +int sceCdNoticeGameStart(int mode, u32 *result); diff --git a/osd/psx/scmd_add.c b/osd/psx/scmd_add.c index c58b69f..3032732 100644 --- a/osd/psx/scmd_add.c +++ b/osd/psx/scmd_add.c @@ -24,9 +24,10 @@ #include "plibcdvd_add.h" #include -enum PSX_CD_SCMD_CMDS { - CD_SCMD_CHG_SYS = 0x2D, //PSX-only - CD_SCMD_NOTICE_GAME_START = 0x2F //PSX-only +enum PSX_CD_SCMD_CMDS +{ + CD_SCMD_CHG_SYS = 0x2D, // PSX-only + CD_SCMD_NOTICE_GAME_START = 0x2F // PSX-only }; extern int bindSCmd; @@ -42,36 +43,43 @@ int _CdCheckSCmd(int cmd); int sceCdChgSys(int mode) { - int result; + int result; - if(_CdCheckSCmd(CD_SCMD_CHG_SYS) == 0) return 0; + if (_CdCheckSCmd(CD_SCMD_CHG_SYS) == 0) + return 0; - *(int*)sCmdSendBuff = mode; - if(SifCallRpc(&clientSCmd, CD_SCMD_CHG_SYS, 0, sCmdSendBuff, 4, sCmdRecvBuff, 4, NULL, NULL)>=0){ - result = *(int *)UNCACHED_SEG(sCmdRecvBuff); - }else{ - result = 0; - } + *(int *)sCmdSendBuff = mode; + if (SifCallRpc(&clientSCmd, CD_SCMD_CHG_SYS, 0, sCmdSendBuff, 4, sCmdRecvBuff, 4, NULL, NULL) >= 0) + { + result = *(int *)UNCACHED_SEG(sCmdRecvBuff); + } + else + { + result = 0; + } - SignalSema(sCmdSemaId); - return result; + SignalSema(sCmdSemaId); + return result; } int sceCdNoticeGameStart(int mode, u32 *result) { - int status; + int status; - if(_CdCheckSCmd(CD_SCMD_NOTICE_GAME_START) == 0) return 0; + if (_CdCheckSCmd(CD_SCMD_NOTICE_GAME_START) == 0) + return 0; - *(u32 *) sCmdSendBuff = mode; - if(SifCallRpc(&clientSCmd, CD_SCMD_NOTICE_GAME_START, 0, sCmdSendBuff, 4, sCmdRecvBuff, 8, NULL, NULL)>=0){ - *result=*(u32 *)UNCACHED_SEG(&sCmdRecvBuff[4]); - status = *(int *)UNCACHED_SEG(sCmdRecvBuff); - }else{ - status = 0; - } + *(u32 *)sCmdSendBuff = mode; + if (SifCallRpc(&clientSCmd, CD_SCMD_NOTICE_GAME_START, 0, sCmdSendBuff, 4, sCmdRecvBuff, 8, NULL, NULL) >= 0) + { + *result = *(u32 *)UNCACHED_SEG(&sCmdRecvBuff[4]); + status = *(int *)UNCACHED_SEG(sCmdRecvBuff); + } + else + { + status = 0; + } - SignalSema(sCmdSemaId); - return status; + SignalSema(sCmdSemaId); + return status; } -