diff --git a/Makefile b/Makefile index 79350ef..0efb647 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,10 @@ # Thanks to whoever made https://devhints.io/makefile! include variables.mk +include variables-shared.mk PACKAGE_FILE = tonyhax-international-$(TONYHAX_VERSION).zip -PACKAGE_CONTENTS = $(ENTRY_FILES:%=entrypoints/%) $(ROM_FILES:%=rom/%) loader/HAX loader/FF9 loader/tonyhax.mcs loader/tonyhax-ff9.mcs loader/tonyhax.exe $(FREEPSXBOOT_IMAGES:%=freepsxboot/%) $(BOOT_CD_FILES:%=boot-cd/%) gshax/wipeout-usa/wipeout-usa-gshax-code.txt gshax/wipeout-usa/CODELIST00 gshax/parasite-eve-usa/parasite-eve-usa-gshax-code.txt gshax/parasite-eve-usa/CODELIST00 gshax/ridge-racer-usa/ridge-racer-usa-gshax-code.txt gshax/ridge-racer-usa/CODELIST00 gameshark/linux_x86_64_static/thigsgen gameshark/linux_x86_static/thigsgen gameshark/windows_x86_64/thigsgen.exe gameshark/windows_x86/thigsgen.exe *.md images/* LICENSE +PACKAGE_CONTENTS = $(ENTRY_FILES:%=entrypoints/%) $(ROM_FILES:%=rom/%) $(X_ROM_FILES:%=xstation/%) $(LOADER_OUTPUT_FILES:%=loader/%) $(FREEPSXBOOT_IMAGES:%=freepsxboot/%) $(BOOT_CD_FILES:%=boot-cd/%) $(GSHAX_FILES:%=gshax/%) $(THIGSGEN_FILES:%=gameshark/%) *.md LICENSE images/* .PHONY: clean modules clean @@ -20,6 +21,7 @@ modules: $(MAKE) -C util $(MAKE) -C entrypoints all $(MAKE) -C gameshark all + $(MAKE) -C gshax all $(MAKE) -C loader -f Makefile.freepsxboot all $(MAKE) -C freepsxboot all @@ -29,21 +31,26 @@ modules: $(MAKE) -C rom all $(MAKE) -C loader clean + $(MAKE) -C loader -f Makefile.xstation all + $(MAKE) -C xstation all + $(MAKE) -C loader clean + $(MAKE) -C loader -f Makefile.ff9 all $(MAKE) -C loader clean $(MAKE) -C loader all $(MAKE) -C boot-cd all - $(MAKE) -C gshax all clean: $(MAKE) -C util clean + $(MAKE) -C gshax-tool clean $(MAKE) -C entrypoints clean $(MAKE) -C loader clean $(MAKE) -C loader -f Makefile.ff9 clean $(MAKE) -C freepsxboot clean $(MAKE) -C boot-cd clean $(MAKE) -C rom clean + $(MAKE) -C xstation clean $(MAKE) -C gameshark clean $(MAKE) -C gshax clean $(RM) tonyhax-*.zip diff --git a/anti-piracy-bypass.md b/anti-piracy-bypass.md index 81df803..abc93a7 100644 --- a/anti-piracy-bypass.md +++ b/anti-piracy-bypass.md @@ -28,7 +28,7 @@ When triggered, the APv1 and APv2 style copy protections will trigger an 'anti-p In addition to APv1 or APv2 protection, some later games may also contain a protection measure known as the EDC check. For the affected games, this protection is triggered when you burn the EDC protected PSX CD image with standard CD burning software, which in most cases will changes the EDC data when burning an EDC protected PSX CD image. -The EDC check can be however be defeated by simply forcing the EDC data to not be changed when burning such a protected PSX CD image. Not every CD burning software has an option which can do this, please see the [CD Burning](#cd-burning-for-edc) section for a more in depth capability comparison of common burning software. +The EDC check can be however be defeated by simply forcing the EDC data to not be changed when burning such a protected PSX CD image. Not every CD burning software has an option which can do this, please see the [CD Burning](#cd-burning) section for a more in depth capability comparison of common burning software. Real 'imported region' PSX game discs with EDC protection will work just fine when booted via Tonyhax International. @@ -40,7 +40,7 @@ LibCrypt protection can be bypassed by burning a backup CD-R of a LibCrypt game Real PAL LibCrypt discs booted via Tonyhax International on USA or Japanese consoles ('imports') will not trip the detection. -## CD Burning For EDC +## CD Burning ### [CDRDAO-PLED](https://alex-free.github.io/cdrdao) @@ -441,21 +441,21 @@ This is the complete list of games with bypasses anti-piracy measures that are s - When Is The Anti-Piracy Screen Check: Immediately. - Versions With Anti-Piracy Bypass Support: Japan. -## NBA Shootout 2001 +### NBA Shootout 2001 - Versions Tested: [USA](http://redump.org/disc/16764/), [USA Demo](http://redump.org/disc/42465/). - Versions With Anti-Piracy Screen: USA, USA Demo. - When Is The Anti-Piracy Screen Check: At the end of the first loading screen. - Versions With Anti-Piracy Bypass Support: USA, USA Demo. -## NBA Shootout 2002 +### NBA Shootout 2002 - Versions Tested: [USA](http://redump.org/disc/14527/), [USA Demo](http://redump.org/disc/44305/). - Versions With Anti-Piracy Screen: USA, USA Demo. - When Is The Anti-Piracy Screen Check: At the end of the first loading screen. - Versions With Anti-Piracy Bypass Support: USA, USA Demo. -## NBA Shootout 2003 +### NBA Shootout 2003 - Versions Tested: [USA](http://redump.org/disc/14566/). - Versions With Anti-Piracy Screen: USA. diff --git a/boot-cd/Makefile b/boot-cd/Makefile index c934222..cc323fc 100644 --- a/boot-cd/Makefile +++ b/boot-cd/Makefile @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk +include ../variables-shared.mk .PHONY: clean diff --git a/changelog.md b/changelog.md index 777c515..61086e9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,15 @@ # Changelog +## Version 1.3.3 (6/5/2023) + +* [tonyhax-international-v1.3.3](https://github.com/alex-free/tonyhax/releases/download/v1.3.3i/tonyhax-international-v1.3.3.zip) + +Changes: + +* Added a [APv2 bypass](anti-piracy-bypass.md) for Boku no Natsuyasumi: Summer Holiday 20th Century Japan to close this [issue](https://github.com/alex-free/tonyhax/issues/28). Enjoy, [Bloom-Haven](https://github.com/Bloom-Haven)!!! + +* Added a ton of real hardware screen captures to the docs and improved documentation itself immensely with more in-depth steps. + ## Version 1.3.2 (6/3/2023) * [tonyhax-international-v1.3.2](https://github.com/alex-free/tonyhax/releases/download/v1.3.2i/tonyhax-international-v1.3.2.zip) diff --git a/docs/tonyhax-vs-tonyhax-international-diffs/tonyhax-international-v1.3.4.diff b/docs/tonyhax-vs-tonyhax-international-diffs/tonyhax-international-v1.3.4.diff new file mode 100644 index 0000000..99c20e7 --- /dev/null +++ b/docs/tonyhax-vs-tonyhax-international-diffs/tonyhax-international-v1.3.4.diff @@ -0,0 +1,3697 @@ +diff --git a/tmp/og-tonyhax.CFG/loader/Makefile b/loader/Makefile +index f121ebf..955f671 100644 +--- a/tmp/og-tonyhax.CFG/loader/Makefile ++++ b/loader/Makefile +@@ -2,6 +2,7 @@ + # Thanks to whoever made https://devhints.io/makefile! + + include ../variables.mk ++include ../variables-shared.mk + + LOADER_AUTOGEN := orca.inc + LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) +@@ -32,7 +33,7 @@ secondary.elf: secondary.ld $(LOADER_OBJECTS) + tonyhax.mcs: tonyhax-tpl.mcs secondary.elf + bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl.mcs tonyhax.mcs $(TONYHAX_VERSION) + +-BESLEM-99999TONYHAX: tonyhax.mcs ++HAX: tonyhax.mcs + bash ../util/mcs2raw.sh tonyhax.mcs + + tonyhax.exe: secondary.elf +diff --git a/loader/Makefile.ff9 b/loader/Makefile.ff9 +new file mode 100644 +index 0000000..28c53f8 +--- /dev/null ++++ b/loader/Makefile.ff9 +@@ -0,0 +1,40 @@ ++ ++# Thanks to whoever made https://devhints.io/makefile! ++ ++include ../variables.mk ++include ../variables-shared.mk ++ ++LOADER_AUTOGEN := orca.inc ++LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) ++LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) ++ ++all: $(LOADER_FILES) ++ ++clean: ++ $(RM) $(LOADER_FILES) FF9 tonyhax-ff9.mcs *.o *.elf $(LOADER_AUTOGEN) ++ ++# Intermediate objects ++ ++%.o: %.c $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++%.o: %.S $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++orca.inc: orca.img ++ bash ../util/bin2h.sh ORCA_IMAGE orca.img orca.inc ++ ++secondary.elf: secondary-ff9.ld $(LOADER_OBJECTS) ++ $(LD) $(LDFLAGS) -T secondary-ff9.ld $(LOADER_OBJECTS) -o $@ ++ bash insert-tonyhax-crc.sh secondary.elf ++ ++# Results ++ ++tonyhax.mcs: tonyhax-tpl-ff9.mcs secondary.elf ++ bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl-ff9.mcs tonyhax-ff9.mcs $(TONYHAX_VERSION) ++ ++HAX: tonyhax.mcs ++ bash ../util/mcs2raw.sh tonyhax-ff9.mcs ++ ++tonyhax.exe: secondary.elf ++ bash generate-tonyhax-exe.sh secondary.elf tonyhax.exe +diff --git a/loader/Makefile.freepsxboot b/loader/Makefile.freepsxboot +new file mode 100644 +index 0000000..53df243 +--- /dev/null ++++ b/loader/Makefile.freepsxboot +@@ -0,0 +1,39 @@ ++ ++# Thanks to whoever made https://devhints.io/makefile! ++ ++include ../variables.mk.freepsxboot ++include ../variables-shared.mk ++ ++LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) ++LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) ++ ++all: $(LOADER_FILES) ++ ++clean: ++ $(RM) $(LOADER_FILES) *.o *.elf $(LOADER_AUTOGEN) ++ ++# Intermediate objects ++ ++%.o: %.c $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++%.o: %.S $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++orca.inc: orca.img ++ bash ../util/bin2h.sh ORCA_IMAGE orca.img orca.inc ++ ++secondary.elf: secondary.ld $(LOADER_OBJECTS) ++ $(LD) $(LDFLAGS) -T secondary.ld $(LOADER_OBJECTS) -o $@ ++ bash insert-tonyhax-crc.sh secondary.elf ++ ++# Results ++ ++tonyhax.mcs: tonyhax-tpl.mcs secondary.elf ++ bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl.mcs tonyhax.mcs $(TONYHAX_VERSION) ++ ++HAX: tonyhax.mcs ++ bash ../util/mcs2raw.sh tonyhax.mcs ++ ++tonyhax.exe: secondary.elf ++ bash generate-tonyhax-exe.sh secondary.elf tonyhax.exe +diff --git a/loader/Makefile.rom b/loader/Makefile.rom +new file mode 100644 +index 0000000..d036c91 +--- /dev/null ++++ b/loader/Makefile.rom +@@ -0,0 +1,39 @@ ++ ++# Thanks to whoever made https://devhints.io/makefile! ++ ++include ../variables.mk.rom ++include ../variables-shared.mk ++ ++LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) ++LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) ++ ++all: $(LOADER_FILES) ++ ++clean: ++ $(RM) $(LOADER_FILES) *.o *.elf $(LOADER_AUTOGEN) ++ ++# Intermediate objects ++ ++%.o: %.c $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++%.o: %.S $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++orca.inc: orca.img ++ bash ../util/bin2h.sh ORCA_IMAGE orca.img orca.inc ++ ++secondary.elf: secondary.ld $(LOADER_OBJECTS) ++ $(LD) $(LDFLAGS) -T secondary.ld $(LOADER_OBJECTS) -o $@ ++ bash insert-tonyhax-crc.sh secondary.elf ++ ++# Results ++ ++tonyhax.mcs: tonyhax-tpl.mcs secondary.elf ++ bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl.mcs tonyhax.mcs $(TONYHAX_VERSION) ++ ++HAX: tonyhax.mcs ++ bash ../util/mcs2raw.sh tonyhax.mcs ++ ++tonyhax.exe: secondary.elf ++ bash generate-tonyhax-exe.sh secondary.elf tonyhax.exe +diff --git a/loader/Makefile.tocperfect b/loader/Makefile.tocperfect +new file mode 100644 +index 0000000..572f600 +--- /dev/null ++++ b/loader/Makefile.tocperfect +@@ -0,0 +1,39 @@ ++ ++# Thanks to whoever made https://devhints.io/makefile! ++ ++include ../variables.mk.tocperfect ++include ../variables-shared.mk ++ ++LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) ++LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) ++ ++all: $(LOADER_FILES) ++ ++clean: ++ $(RM) $(LOADER_FILES) *.o *.elf $(LOADER_AUTOGEN) ++ ++# Intermediate objects ++ ++%.o: %.c $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++%.o: %.S $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++orca.inc: orca.img ++ bash ../util/bin2h.sh ORCA_IMAGE orca.img orca.inc ++ ++secondary.elf: secondary.ld $(LOADER_OBJECTS) ++ $(LD) $(LDFLAGS) -T secondary.ld $(LOADER_OBJECTS) -o $@ ++ bash insert-tonyhax-crc.sh secondary.elf ++ ++# Results ++ ++tonyhax.mcs: tonyhax-tpl.mcs secondary.elf ++ bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl.mcs tonyhax.mcs $(TONYHAX_VERSION) ++ ++HAX: tonyhax.mcs ++ bash ../util/mcs2raw.sh tonyhax.mcs ++ ++tonyhax.exe: secondary.elf ++ bash generate-tonyhax-exe.sh secondary.elf tonyhax.exe +diff --git a/loader/Makefile.xstation b/loader/Makefile.xstation +new file mode 100644 +index 0000000..47d55ac +--- /dev/null ++++ b/loader/Makefile.xstation +@@ -0,0 +1,39 @@ ++ ++# Thanks to whoever made https://devhints.io/makefile! ++ ++include ../variables.mk.xstation ++include ../variables-shared.mk ++ ++LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) ++LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) ++ ++all: $(LOADER_FILES) ++ ++clean: ++ $(RM) $(LOADER_FILES) *.o *.elf $(LOADER_AUTOGEN) ++ ++# Intermediate objects ++ ++%.o: %.c $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++%.o: %.S $(LOADER_HEADERS) ++ $(CC) $(CFLAGS) -c $< ++ ++orca.inc: orca.img ++ bash ../util/bin2h.sh ORCA_IMAGE orca.img orca.inc ++ ++secondary.elf: secondary.ld $(LOADER_OBJECTS) ++ $(LD) $(LDFLAGS) -T secondary.ld $(LOADER_OBJECTS) -o $@ ++ bash insert-tonyhax-crc.sh secondary.elf ++ ++# Results ++ ++tonyhax.mcs: tonyhax-tpl.mcs secondary.elf ++ bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl.mcs tonyhax.mcs $(TONYHAX_VERSION) ++ ++HAX: tonyhax.mcs ++ bash ../util/mcs2raw.sh tonyhax.mcs ++ ++tonyhax.exe: secondary.elf ++ bash generate-tonyhax-exe.sh secondary.elf tonyhax.exe +diff --git a/loader/ap-bypass.c b/loader/ap-bypass.c +new file mode 100644 +index 0000000..26108f3 +--- /dev/null ++++ b/loader/ap-bypass.c +@@ -0,0 +1,1716 @@ ++ ++#include "bios.h" ++//#include "debugscreen.h" ++#include "str.h" ++#include "ap-bypass.h" ++ ++bool cheat_engine_installed; ++ ++uint8_t gs_code_type; ++ ++int32_t code_address_ram_location = 0xD000; ++int32_t code_compare_ram_location = 0xD004; ++int32_t code_enable_ram_location = 0xD00C; ++ ++void add_30_code(const uint32_t gs1, const uint8_t gs2) { ++ gs_code_type = 0x30; ++ memcpy((void*)code_address_ram_location, &gs1, 4); ++ memcpy((void*)code_compare_ram_location, &gs2, 1); ++ memcpy((void*)code_enable_ram_location, &gs_code_type, 1); ++// Update addresses to write to for an additional code ++ code_address_ram_location = (code_address_ram_location + 0x010); ++ code_compare_ram_location = (code_compare_ram_location + 0x010); ++ code_enable_ram_location = (code_enable_ram_location + 0x010); ++} ++ ++void add_E0_code(const uint32_t gs1, const uint8_t gs2) { ++ gs_code_type = 0xE0; ++ memcpy((void*)code_address_ram_location, &gs1, 4); ++ memcpy((void*)code_compare_ram_location, &gs2, 1); ++ memcpy((void*)code_enable_ram_location, &gs_code_type, 1); ++// Update addresses to write to for an additional code ++ code_address_ram_location = (code_address_ram_location + 0x010); ++ code_compare_ram_location = (code_compare_ram_location + 0x010); ++ code_enable_ram_location = (code_enable_ram_location + 0x010); ++} ++ ++void add_E1_code(const uint32_t gs1, const uint8_t gs2) { ++ gs_code_type = 0xE1; ++ memcpy((void*)code_address_ram_location, &gs1, 4); ++ memcpy((void*)code_compare_ram_location, &gs2, 1); ++ memcpy((void*)code_enable_ram_location, &gs_code_type, 1); ++// Update addresses to write to for an additional code ++ code_address_ram_location = (code_address_ram_location + 0x010); ++ code_compare_ram_location = (code_compare_ram_location + 0x010); ++ code_enable_ram_location = (code_enable_ram_location + 0x010); ++} ++ ++void add_80_code(const uint32_t gs1, const uint16_t gs2) { ++ gs_code_type = 0x80; ++ memcpy((void*)code_address_ram_location, &gs1, 4); ++ memcpy((void*)code_compare_ram_location, &gs2, 2); ++ memcpy((void*)code_enable_ram_location, &gs_code_type, 1); ++// Update addresses to write to for an additional code ++ code_address_ram_location = (code_address_ram_location + 0x010); ++ code_compare_ram_location = (code_compare_ram_location + 0x010); ++ code_enable_ram_location = (code_enable_ram_location + 0x010); ++} ++ ++void add_D0_code(const uint32_t gs1, const uint16_t gs2) { ++ gs_code_type = 0xD0; ++ memcpy((void*)code_address_ram_location, &gs1, 4); ++ memcpy((void*)code_compare_ram_location, &gs2, 2); ++ memcpy((void*)code_enable_ram_location, &gs_code_type, 1); ++// Update addresses to write to for an additional code ++ code_address_ram_location = (code_address_ram_location + 0x010); ++ code_compare_ram_location = (code_compare_ram_location + 0x010); ++ code_enable_ram_location = (code_enable_ram_location + 0x010); ++} ++ ++void add_D1_code(const uint32_t gs1, const uint16_t gs2) { ++ gs_code_type = 0xD1; ++ memcpy((void*)code_address_ram_location, &gs1, 4); ++ memcpy((void*)code_compare_ram_location, &gs2, 2); ++ memcpy((void*)code_enable_ram_location, &gs_code_type, 1); ++// Update addresses to write to for an additional code ++ code_address_ram_location = (code_address_ram_location + 0x010); ++ code_compare_ram_location = (code_compare_ram_location + 0x010); ++ code_enable_ram_location = (code_enable_ram_location + 0x010); ++} ++ ++void install_cheat_engine() { ++// generate with `scripts/stealth-engine-xxd.sh` after compiling .EXE file with No $ PSX Assembler ++const unsigned char cheat_engine_v1_0_3[] = { ++0xe0, 0xff, 0xbd, 0x27, 0x00, 0x00, 0xa4, 0xaf, ++ 0x04, 0x00, 0xa5, 0xaf, 0x08, 0x00, 0xa6, 0xaf, 0x0c, 0x00, 0xa7, 0xaf, ++ 0x00, 0x00, 0x04, 0x3c, 0x00, 0xd0, 0x84, 0x34, 0x00, 0x00, 0x00, 0x00, ++ 0x0c, 0x00, 0x86, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0xc0, 0x10, ++ 0x30, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc7, 0x10, ++ 0x80, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0xc7, 0x10, ++ 0xe0, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc7, 0x10, ++ 0xd0, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0xc7, 0x10, ++ 0xe1, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0xc7, 0x10, ++ 0xd1, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0xc7, 0x10, ++ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x07, 0x34, 0x1c, 0x00, 0x86, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x00, ++ 0x80, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0xc7, 0x10, ++ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0x94, 0x00, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xa4, 0x3a, 0x00, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0x90, 0x00, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xa0, 0x34, 0x00, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0x90, 0x00, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x90, 0x00, 0x00, 0x00, 0x00, ++ 0x2a, 0x00, 0xc5, 0x14, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xff, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0x90, 0x00, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x90, 0x00, 0x00, 0x00, 0x00, ++ 0x21, 0x00, 0xc5, 0x10, 0x00, 0x00, 0x00, 0x00, 0xda, 0xff, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0x94, 0x00, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x94, 0x00, 0x00, 0x00, 0x00, ++ 0x18, 0x00, 0xc5, 0x14, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0x94, 0x00, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x94, 0x00, 0x00, 0x00, 0x00, ++ 0x0f, 0x00, 0xc5, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x85, 0x90, 0x10, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xa0, 0x07, 0x00, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x85, 0x94, 0x10, 0x00, 0x87, 0x8c, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xa4, 0x01, 0x00, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x84, 0x24, 0xa3, 0xff, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x84, 0x24, 0xa0, 0xff, 0x00, 0x18, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x8f, 0x04, 0x00, 0xa5, 0x8f, ++ 0x08, 0x00, 0xa6, 0x8f, 0x0c, 0x00, 0xa7, 0x8f, 0x20, 0x00, 0xbd, 0x27, ++ 0x01, 0x00, 0x1a, 0x3c, 0xfc, 0xcf, 0x5a, 0x8f, 0x00, 0x00, 0x00, 0x00, ++ 0x08, 0x00, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++ //debug_write("Installing MottZilla AP Engine"); ++ memcpy((void*)0xC000, (void*)cheat_engine_v1_0_3, sizeof(cheat_engine_v1_0_3)); // Copy MottZilla's cheat engine assembly binary to 0xC000 ++ const uint32_t b0_jump = (*(uint32_t*)0xB4) & 0xFFFF; ++ //debug_write("Got jump address for B0 functions : %x", (uint32_t) b0_jump); ++ const uint32_t b0_base = (*(uint32_t*)(b0_jump + 4)) & 0xFFFF; ++ //debug_write("Got base address for B0 table : %x", (uint32_t) b0_base); ++ const uint32_t b0_entry = b0_base + (0x17 * 4); ++ //debug_write("Got B0 table entry address : %x", (uint32_t) b0_entry); ++ const uint32_t old_table_val = *(uint32_t*) b0_entry; ++ //debug_write("B0 table entry to modify has the original contents : %x", (uint32_t) old_table_val); ++ memcpy((void*)0xCFFC, (void*)&old_table_val, sizeof(old_table_val)); // Copy the original 32 bit number of the B table entry we want to modify to 0xCFFC ++ const uint16_t redirect = 0xC000; ++ memcpy((void*)b0_entry, &redirect, 2); // Write the value 0xC000 to table entry we want to modify ++ //for(volatile int i = 0; i < 0x100000; i++); // won't be optimized out by -Os, pause ++ cheat_engine_installed = 1; ++} ++ ++void activate_anti_anti_piracy(const char * bootfile, const int32_t load_addr) ++{ ++ int32_t ver_check; ++ uint8_t ver_check_val; ++ int8_t bootfile_len = strlen(bootfile); ++ ++ // Aprip code type constants ++ const uint16_t readtoc_compare_val = 0x001E; ++ const uint16_t readtoc_patch_val = 0x0000; ++ ++ // Many pre-existing 'skip mod check' or 'force routine ok' type codes from back in the day seem to share these values, so they are a const ++ const uint16_t common_routine_return_compare_val = 0x1040; ++ const uint16_t common_routine_return_patch_val = 0x1000; ++ ++ if(bootfile_len > 13) { ++ bootfile = &bootfile[bootfile_len-13]; // XXXX_XXX.XX;1 , we are only changing the locally declared bootfile here, not in secondary.c. ++ //debug_write("Stripped Bootfile: %s", bootfile); ++ } else if(bootfile_len < 13) { ++ return; ++ // Speed optimization. All anti-piracy games currently have a bootfile name that is at least 13 uchars long when stripped. So if the bootfile happens to have something like 'MAIN.EXE;1' (which is 10 in length), we already know not to bother even checking for an anti-piracy bootfile match to apply codes for (which takes time in itself to do as well). ++ } ++ ++// Animetic Story Game 1: Card Captor Sakura ++ if( ++ ((strcmp("SLPS_018.30;1", bootfile)) == 0) // Japan Disc 1 ++ || ((strcmp("SLPS_018.31;1", bootfile)) == 0) // Japan Disc 2 ++ ) { // 2 disc game ++ /* ++ D001516A 1040 ++ 8001516A 1000 ++ code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_c.shtml ++ */ ++ add_D0_code(0x8001516A, common_routine_return_compare_val); ++ add_80_code(0x8001516A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Alundra 2 ++ ((strcmp("SCPS_101.15;1", bootfile)) == 0) { // Japan ++ /* ++ D004E91A 1040 ++ 8004E91A 1000 ++ 'skip mod check' code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_a.shtml ++ */ ++ add_D0_code(0x8004E91A, common_routine_return_compare_val); ++ add_80_code(0x8004E91A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Arc The Lad III ++ ( ++ ((strcmp("SCPS_101.06;1", bootfile)) == 0) // Japan Rev 0/Rev 1 Disc 1 ++ || ((strcmp("SCPS_101.07;1", bootfile)) == 0) // Japan Rev 0/Rev 1 Disc 2 ++ ) { ++ ver_check = (load_addr + 0x20); // First different byte between revisions ++ //debug_write("Got address for version check: %x", (uint32_t) ver_check); ++ ver_check_val = *(uint8_t*) ver_check; ++ //debug_write("Ver check address has the contents : %x", (uint8_t) ver_check_val); ++ if((ver_check_val == 0x8C)) // Rev 0 ++ { ++ /* ++ D0021DF6 1040 ++ 80021DF6 1000 ++ code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_a.shtml ++ */ ++ add_D0_code(0x80021DF6, common_routine_return_compare_val); ++ add_80_code(0x80021DF6, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else { // Rev 1 ++ /* ++ D0022206 1040 my code via aprip gameshark code conversion ++ 80022206 1000 ++ */ ++ add_D0_code(0x80022206, common_routine_return_compare_val); ++ add_80_code(0x80022206, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } ++ } else if ++ ++// Beatmania featuring Dreams Come True ++ ((strcmp("SLPM_865.97;1", bootfile)) == 0) { // Japan ++ /* ++ D012255C 001E ++ 8012255C 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x8012255C, readtoc_compare_val); ++ add_80_code(0x8012255C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Beatmania Best Hits ++ ((strcmp("Slpm_865.96;1", bootfile)) == 0) { // Japan Rev 0/Rev 1 ++ // not a typo, weird asf filename ++ /* ++ D0151448 001E ++ 80151448 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x80151448, readtoc_compare_val); ++ add_80_code(0x80151448, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Beat Mania: The Sound of Tokyo ++ ((strcmp("SLPM_867.69;1", bootfile)) == 0) { // Japan ++ /* ++ D0134C48 001E ++ 80134C48 0000 ++ my code to patch out readtoc ++ */ ++ add_D0_code(0x80134C48, readtoc_compare_val); ++ add_80_code(0x80134C48, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Beat Mania 6thMix + Core Remix ++ ((strcmp("SLPM_870.12;1", bootfile)) == 0) { // Japan ++ /* ++ D0131B6C 001E ++ 80131B6C 001A ++ my code to patch out readtoc ++ */ ++ add_D0_code(0x80131B6C, readtoc_compare_val); ++ add_80_code(0x80131B6C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Boku no Natsuyasumi: Summer Holiday 20th Century ++ ((strcmp("SCPS_100.88;1", bootfile)) == 0) { // Japan ++ /* ++ D0068B30 001E ++ 80068B30 0000 ++ my code to patch out readtoc ++ */ ++ add_D0_code(0x80068B30, readtoc_compare_val); ++ add_80_code(0x80068B30, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Breath of Fire IV ++ ((strcmp("SLPS_027.28;1", bootfile)) == 0) { // Japan / USA E3 2000 Beta Build ++ /* ++ D01D0698 001E ++ 801D0698 0000 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x801D0698, readtoc_compare_val); ++ add_80_code(0x801D0698, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Capcom vs. SNK: Millennium Fight 2000 Pro ++ ((strcmp("SLPM_870.53;1", bootfile)) == 0) { // Japan ++ /* ++ D0051B60 001E ++ 80051B60 0000 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x80051B60, readtoc_compare_val); ++ add_80_code(0x80051B60, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Chase The Express ++ ( ++ ((strcmp("SCPS_101.09;1", bootfile)) == 0) // Japan Disc 1 ++ || ((strcmp("SCPS_101.10;1", bootfile)) == 0) // Japan Disc 2 ++ || ((strcmp("PAPX_901.06;1", bootfile)) == 0) // Japan Demo 1 ++ || ((strcmp("PCPX_961.89;1", bootfile)) == 0) // Japan Demo 2 ++ ) { ++ /* ++ D00EA6DE 1040 ++ 800EA6DE 1000 ++ 'skip mod check' code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_c.shtml ++ */ ++ add_D0_code(0x800EA6DE, common_routine_return_compare_val); ++ add_80_code(0x800EA6DE, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Crash Bash ++ ((strcmp("SCUS_945.70;1", bootfile)) == 0) { // USA ++ /* ++ D002D51E 1040 ++ 8002D51E 1000 ++ code from GameHacking: https://gamehacking.org/game/88640, skips mod check ++ */ ++ add_D0_code(0x8002D51E, common_routine_return_compare_val); ++ add_80_code(0x8002D51E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SCPS_101.40;1", bootfile)) == 0) { // Japan ++ /* ++ D002D7EE 1040 ++ 8002D7EE 1000 ++ code from GameHacking: https://gamehacking.org/game/93827, skips mod check ++ */ ++ add_D0_code(0x8002D7EE, common_routine_return_compare_val); ++ add_80_code(0x8002D7EE, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Crash Bandicoot Racing ++ ((strcmp("SCPS_101.18;1", bootfile)) == 0) { // Japan ++ /* ++ D001259A 1040 ++ 8001259A 1000 ++ 'skip mod check' code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_b.shtml (yes it's on the wrong lettered page) ++ */ ++ add_D0_code(0x8001259A, common_routine_return_compare_val); ++ add_80_code(0x8001259A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("PCPX_961.83;1", bootfile)) == 0) { // Japan Demo ++ /* ++ D001255E 1040 ++ 8001255E 1040 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x8001255E, common_routine_return_compare_val); ++ add_80_code(0x8001255E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Cool Boarders 2001 ++ ((strcmp("SCUS_946.25;1", bootfile)) == 0) { // USA Demo ++ /* ++ D00B35B0 001E ++ 800B35B0 0000 ++ code generated via aprip ++ */ ++ add_D0_code(0x800B35B0, readtoc_compare_val); ++ add_80_code(0x800B35B0, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SCUS_945.97;1", bootfile)) == 0) { // USA ++ /* ++ D00B35B8 001E ++ 800B35B8 0000 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x800B35B8, readtoc_compare_val); ++ add_80_code(0x800B35B8, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Dance Dance Revolution: Best Hits ++ ((strcmp("SLPM_866.93;1", bootfile)) == 0) { // Japan ++ /* ++ D0102FA0 001E ++ 80102FA0 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80102FA0, readtoc_compare_val); ++ add_80_code(0x80102FA0, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Dance Dance Revolution: Disney's Rave ++ ((strcmp("SLPM_866.67;1", bootfile)) == 0) { // Japan ++ /* ++ D0192248 001E ++ 80192248 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x80192248, readtoc_compare_val); ++ add_80_code(0x80192248, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Dance Dance Revolution: Extra Mix ++ ((strcmp("SLPM_868.31;1", bootfile)) == 0) { // Japan ++ /* ++ D00EB364 001E ++ 800EB364 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x800EB364, readtoc_compare_val); ++ add_80_code(0x800EB364, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Dance Dance Revolution 2nd Remix ++ ((strcmp("SLPM_862.52;1", bootfile)) == 0) { // Dance Dance Revolution 2nd Remix Append Club Vol 1 and Dance Dance Revolution 2nd Remix Append Club Vol 2 discs are booted with a 'disc change' feature within Dance Dance Revolution 2nd Remix (which is a 'base' disc when booting the others, kind of like DLC). ++ /* ++ Dance Dance Revolution 2nd Remix: ++ D00200A6 1040 ++ 800200A6 1000 ++ */ ++ add_D0_code(0x800200A6, common_routine_return_compare_val); ++ add_80_code(0x800200A6, common_routine_return_patch_val); ++ /* ++ D0020D64 FFF2 ++ 80020D64 0001 ++ */ ++ add_D0_code(0x80020D64, 0xFFF2); ++ add_80_code(0x80020D64, 0x0001); ++ /* ++ D01C1BE4 FFF2 ++ 801C1BE4 0001 ++ */ ++ add_D0_code(0x801C1BE4, 0xFFF2); ++ add_80_code(0x801C1BE4, 0x0001); ++ ++ /* ++ D01C1C7A 0C07 ++ 801C1C7A 3002 ++ */ ++ add_D0_code(0x801C1C7A, 0x0C07); ++ add_80_code(0x801C1C7A, 0x3002); ++ /* ++ D01C2936 1040 ++ 801C2936 1000 ++ */ ++ add_D0_code(0x801C2936, common_routine_return_compare_val); ++ add_80_code(0x801C2936, common_routine_return_patch_val); ++ /* ++ Dance Dance Revolution 2nd Remix Append Club Vol 1 ++ D01C2A18 0C92 ++ 801C2A18 0AA7 ++ */ ++ add_D0_code(0x801C2A18, 0x0C92); ++ add_80_code(0x801C2A18, 0x0AA7); ++ /* ++ D01C2EA2 1040 ++ 801C2EA2 1000 ++ */ ++ add_D0_code(0x801C2EA2,common_routine_return_compare_val); ++ add_80_code(0x801C2EA2, common_routine_return_patch_val); ++ ++ /* ++ Dance Dance Revolution 2nd Remix Append Club Vol 2 ++ D01C2F32 1040 ++ 801C2F32 1000 ++ */ ++ add_D0_code(0x801C2F32, common_routine_return_compare_val); ++ add_80_code(0x801C2F32, common_routine_return_patch_val); ++ /* ++ D01C2AA8 0CB6 ++ 801C2AA8 0ACB ++ */ ++ add_D0_code(0x801C2AA8, 0x0CB6); ++ add_80_code(0x801C2AA8, 0x0ACB); ++ // codes are from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_d.shtml . ++ install_cheat_engine(); ++ } else if ++ ++// Dancing Stage featuring Dreams Come True ++ ((strcmp("SLPM_865.05;1", bootfile)) == 0) { // Japan ++ /* ++ D019245C 001E ++ 8019245C 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x8019245C, readtoc_compare_val); ++ add_80_code(0x8019245C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Dancing Stage featuring True Kiss Destination ++ ((strcmp("SLPM_864.11;1", bootfile)) == 0) { // Japan ++ /* ++ D019117A 1040 ++ 8019117A 1000 ++ code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_d.shtml ++ */ ++ add_D0_code(0x8019117A, common_routine_return_compare_val); ++ add_80_code(0x8019117A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Dino Crisis ++ ((strcmp("SLUS_009.22;1", bootfile)) == 0) { // USA Rev 0/USA Rev 1 ++ ver_check = (load_addr + 0x61); // First different byte between revisions ++ //debug_write("Got address for version check: %x", (uint32_t) ver_check); ++ ver_check_val = *(uint8_t*) ver_check; ++ //debug_write("Ver check address has the contents : %x", (uint8_t) ver_check_val); ++ if(ver_check_val == 0xD0) { // Rev 0 ++ /* ++ D0149004 959C ++ 80149004 9E64 ++ Found independently by MottZilla, but actually turns out to be the same code by Epson found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_d.shtml ++ */ ++ add_D0_code(0x80149004, 0x959C); ++ add_80_code(0x80149004, 0x9E64); ++ install_cheat_engine(); ++ } else { // Rev 1 ++ /* ++ D0148004 8658 ++ 80148004 8F20 ++ my code, the anti-piracy table just moved memory addresses between versions :) ++ */ ++ add_D0_code(0x80148004, 0x8658); ++ add_80_code(0x80148004, 0x8F20); ++ install_cheat_engine(); ++ } ++ } else if ++ ++ ((strcmp("SLPS_021.80;1", bootfile)) == 0) { // Japan ++ /* ++ D0149004 959C ++ 80149004 9E64 ++ Found independently by MottZilla, but actually turns out to be the same code by Epson found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_d.shtml . Yes this is the same code as the USA rev 0 one. ++ */ ++ add_D0_code(0x80149004, 0x959C); ++ add_80_code(0x80149004, 0x9E64); ++ install_cheat_engine(); ++ } else if ++ ++// Dino Crisis 2 ++ ((strcmp("SLPM_866.27;1", bootfile)) == 0) { // Japan ++ /* ++ D00D7714 001E ++ 800D7714 0000 ++ my code via aprip to disable readtoc ++ */ ++ add_D0_code(0x800D7714, readtoc_compare_val); ++ add_80_code(0x800D7714, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SLPM_805.73;1", bootfile)) == 0) { // Japan Demo ++ /* ++ D00CB104 001E ++ 800CB104 0000 ++ my codevia aprip to disable readtoc ++ */ ++ add_D0_code(0x800CB104, readtoc_compare_val); ++ add_80_code(0x800CB104, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Disney's The Emperor's New Groove ++ ((strcmp("SCUS_945.71;1", bootfile)) == 0) { // USA ++ /* ++ D0063004 001E ++ 80063004 0000 ++ my code via aprip to disable readtoc ++ */ ++ add_D0_code(0x80063004, readtoc_compare_val); ++ add_80_code(0x80063004, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SCES_030.10;1", bootfile)) == 0) { // Europe ++ /* ++ D006351C 001E ++ 8006351C 0000 ++ my code via aprip to disable readtoc ++ */ ++ add_D0_code(0x8006351C, readtoc_compare_val); ++ add_80_code(0x8006351C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Exciting Bass 2 ++ ((strcmp("SLPM_862.95;1", bootfile)) == 0) { // Japan ++ /* ++ D00177BA 1040 ++ 800177BA 1000 ++ code found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_e.shtml ++ */ ++ add_D0_code(0x800177BA, common_routine_return_compare_val); ++ add_80_code(0x800177BA, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Exciting Bass 3 ++ ((strcmp("SLPM_867.29;1", bootfile)) == 0) { // Japan ++ /* ++ D00B9170 001E ++ 800B9170 0000 ++ my code to patch out readtoc via aprip ++ */ ++ add_D0_code(0x800B9170, readtoc_compare_val); ++ add_80_code(0x800B9170, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Gekitotsu Toma L'Arc - L'Arc en Ciel vs Tomarunner ++ ((strcmp("SCPS_101.34;1", bootfile)) == 0) { // Japan ++ /* ++ D0195D9C 001E ++ 80195D9C 0000 ++ my code to patch out readtoc via aprip ++ */ ++ add_D0_code(0x80195D9C, readtoc_compare_val); ++ add_80_code(0x80195D9C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Glint Glitters ++ ((strcmp("SLPM_862.00;1", bootfile)) == 0) { // Japan ++ /* ++ D01B3188 001E ++ 801B3188 0000 ++ my code to patch out readtoc via aprip ++ */ ++ add_D0_code(0x801B3188, readtoc_compare_val); ++ add_80_code(0x801B3188, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Goo! Goo! Soundry ++ ((strcmp("SLPM_862.50;1", bootfile)) == 0) { // Japan ++ /* ++ D0055278 001E ++ 80055278 0000 ++ my code to patch out readtoc via aprip ++ */ ++ add_D0_code(0x80055278, readtoc_compare_val); ++ add_80_code(0x80055278, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Grind Session ++ ((strcmp("SCUS_945.68;1", bootfile)) == 0) { // USA ++ /* ++ D0014274 52A9 ++ 80014274 50BE ++ code 1 of 2 by 'TheVoice' found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_g.shtml ++ */ ++ add_D0_code(0x80014274, 0x52A9); ++ add_80_code(0x80014274, 0x50BE); ++ /* ++ D00146FE 1040 ++ 800146FE 1000 ++ code 2 of 2 by 'TheVoice' found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_g.shtml ++ */ ++ add_D0_code(0x800146FE, common_routine_return_compare_val); ++ add_80_code(0x800146FE, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Guitar Freaks ++ ((strcmp("SLPM_862.65;1", bootfile)) == 0) { // Japan ++ /* ++ D001654E 1040 ++ 8001654E 1000 ++ code found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_g.shtml ++ */ ++ add_D0_code(0x8001654E, common_routine_return_compare_val); ++ add_80_code(0x8001654E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Harlem Beat: You're The One ++ ((strcmp("SLPM_863.29;1", bootfile)) == 0) { // Japan ++ /* ++ D01A411E 1040 ++ 801A411E 1000 ++ code found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_h.shtml ++ */ ++ add_D0_code(0x801A411E, common_routine_return_compare_val); ++ add_80_code(0x801A411E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Hyper Value 2800: Hanafuda ++ ((strcmp("SLPM_864.17;1", bootfile)) == 0) { // Japan ++ /* ++ D00A1188 001E ++ 800A1188 0000 ++ code found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_h.shtml ++ */ ++ add_D0_code(0x800A1188, readtoc_compare_val); ++ add_80_code(0x800A1188, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Hyper Value 2800: Mahjong ++ ((strcmp("SLPM_862.92;1", bootfile)) == 0) { // Japan ++ /* ++ D00A0186 1040 ++ 800A0186 1000 ++ code found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_h.shtml ++ */ ++ add_D0_code(0x800A0186, common_routine_return_compare_val); ++ add_80_code(0x800A0186, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// i-mode mo Issho: Doko Demo Issho Tsuika Disc ++ ((strcmp("SCPS_101.41;1", bootfile)) == 0) { // Japan ++ /* ++ D01698B4 001E ++ 801698B4 0000 ++ code generated via aprip by M4x1mumReZ: https://gbatemp.net/members/m4x1mumrez.610331/ ++ */ ++ add_D0_code(0x801698B4, readtoc_compare_val); ++ add_80_code(0x801698B4, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Jikkyou Powerful Pro Yakyuu '99 Ketteiban ++ ((strcmp("SLPM_864.33;1", bootfile)) == 0) { // Japan ++ /* ++ D016B4D8 001E ++ 8016B4D8 0000 ++ my code to patch out readtoc via aprip ++ */ ++ add_D0_code(0x8016B4D8, readtoc_compare_val); ++ add_80_code(0x8016B4D8, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Jikkyou Powerful Pro Yakyuu '99: Kaimakuban ++ ((strcmp("SLPM_862.53;1", bootfile)) == 0) { // Japan ++ /* ++ D016B268 001E ++ 8016B268 0000 ++ my code to patch out readtoc via aprip ++ */ ++ add_D0_code(0x8016B268, readtoc_compare_val); ++ add_80_code(0x8016B268, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// JoJo's Bizarre Adventure ++ ((strcmp("SLPS_022.36;1", bootfile)) == 0) { // Japan ++ /* ++ D0035C48 D91E ++ 80035C48 D733 ++ code 1 of 2 found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_j.shtml ++ */ ++ add_D0_code(0x80035C48, 0xD91E); ++ add_80_code(0x80035C48, 0xD733); ++ /* ++ D00360D2 1040 ++ 800360D2 1000 ++ code 2 of 2 found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_j.shtml ++ */ ++ add_D0_code(0x800360D2, common_routine_return_compare_val); ++ add_80_code(0x800360D2, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Koko Hore! Pukka ++ ((strcmp("SCPS_101.33;1", bootfile)) == 0) { // Japan ++ /* ++ D00A341C 001E ++ 800A341C 0000 ++ code generated via aprip by https://gbatemp.net/members/m4x1mumrez.610331/ ++ */ ++ add_D0_code(0x800A341C, readtoc_compare_val); ++ add_80_code(0x800A341C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Koneko mo Issho ++ ((strcmp("SCPS_101.27;1", bootfile)) == 0) { // Japan ++ /* ++ D016957C 001E ++ 8016957C 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x8016957C, readtoc_compare_val); ++ add_80_code(0x8016957C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Legend Of Dragoon ++ ( ++ ((strcmp("SCPS_101.19;1", bootfile)) == 0) // Japan Disc 1 ++ || ((strcmp("scps_101.20;1", bootfile)) == 0) // Japan Disc 2 (weird ass filename not a typo) ++ || ((strcmp("scps_101.21;1", bootfile)) == 0) // Japan Disc 3 (weird ass filename not a typo) ++ || ((strcmp("scps_101.22;1", bootfile)) == 0) // Japan Disc 4 (weird ass filename not a typo) ++ ) { ++ /* ++ D01BF172 1040 ++ 801BF172 1000 ++ code found on consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_l.shtml ++ */ ++ add_D0_code(0x801BF172, common_routine_return_compare_val); ++ add_80_code(0x801BF172, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ( ++ ((strcmp("SCUS_944.91;1", bootfile)) == 0) // USA Disc 1 ++ || ((strcmp("SCUS_945.84;1", bootfile)) == 0) // USA Disc 2 ++ || ((strcmp("SCUS_945.85;1", bootfile)) == 0) // USA Disc 3 ++ || ((strcmp("SCUS_945.86;1", bootfile)) == 0) // USA Disc 4 ++ ) { ++ /* ++ 801BF6F6 1040 ++ 801BF6F6 1000 ++ my code via aprip's gameshark conversion ++ */ ++ add_D0_code(0x801BF6F6, common_routine_return_compare_val); ++ add_80_code(0x801BF6F6, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ( ++ ( ++ (strcmp("SCES_030.43;1", bootfile)) == 0) // Europe Disc 1 ++ || ((strcmp("SCES_130.43;1", bootfile)) == 0) // Europe Disc 2 ++ || ((strcmp("SCES_230.43;1", bootfile)) == 0) // Europe Disc 3 ++ || ((strcmp("SCES_330.43;1", bootfile)) == 0) // Europe Disc 4 ++ ) { ++ /* ++ D01C0892 1040 ++ 801C0892 1000 ++ my code via aprip's gameshark conversion ++ */ ++ add_D0_code(0x801C0892, common_routine_return_compare_val); ++ add_80_code(0x801C0892, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ( ++ ((strcmp("SCES_030.44;1", bootfile)) == 0) // France Disc 1 ++ || ((strcmp("SCES_130.44;1", bootfile)) == 0) // France Disc 2 ++ || ((strcmp("SCES_230.44;1", bootfile)) == 0) // France Disc 3 ++ || ((strcmp("SCES_330.44;1", bootfile)) == 0) // France Disc 4 ++ ) { ++ /* ++ D01C0872 1040 ++ 801C0872 1040 ++ my code via aprip's gameshark conversion ++ */ ++ add_D0_code(0x801C0872, common_routine_return_compare_val); ++ add_80_code(0x801C0872, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ( ++ ((strcmp("SCES_030.45;1", bootfile)) == 0) // Germany Disc 1 ++ || ((strcmp("SCES_130.45;1", bootfile)) == 0) // Germany Disc 2 ++ || ((strcmp("SCES_230.45;1", bootfile)) == 0) // Germany Disc 3 ++ || ((strcmp("SCES_330.45;1", bootfile)) == 0)// Germany Disc 4 ++ ) { ++ /* ++ D01C082E 1040 ++ 801C082E 1000 ++ my code via aprip's gameshark conversion ++ */ ++ add_D0_code(0x801C082E, common_routine_return_compare_val); ++ add_80_code(0x801C082E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ( ++ ((strcmp("SCES_030.46;1", bootfile)) == 0) // Italian Disc 1 ++ || ((strcmp("SCES_130.46;1", bootfile)) == 0) // Italian Disc 2 ++ || ((strcmp("SCES_230.46;1", bootfile)) == 0) // Italian Disc 3 ++ || ((strcmp("SCES_330.46;1", bootfile)) == 0)// Italian Disc 4 ++ ) { ++ /* ++ D01C0826 1040 ++ 801C0826 1000 ++ my code via aprip's gameshark conversion ++ */ ++ add_D0_code(0x801C0826, common_routine_return_compare_val); ++ add_80_code(0x801C0826, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Legend Of Mana ++ ((strcmp("SLPS_021.70;1", bootfile)) == 0) { // Japan ++ //debug_write("Detected Legend Of Mana"); ++ /* ++ D0050ECA 1040 ++ 80050ECA 1000 ++ code 1 of 2 from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_l.shtml ++ */ ++ add_D0_code(0x80050ECA, common_routine_return_compare_val); ++ add_80_code(0x80050ECA, common_routine_return_patch_val); ++ /* ++ D00360D2 1040 ++ 800360D2 1000 ++ code 2 of 2 from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_l.shtml ++ */ ++ add_D0_code(0x800360D2, common_routine_return_compare_val); ++ add_80_code(0x800360D2, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Love Hina: Ai wa Kotoba no Naka ni / Love Hina 2: Kotoba wa Konayuki no You ni ++ ( ++ ((strcmp("SLPM_866.52;1", bootfile)) == 0) // Love Hina: Ai wa Kotoba no Naka ni ++ || ((strcmp("SLPM_866.77;1", bootfile)) == 0) // Love Hina 2: Kotoba wa Konayuki no You ni ++ ) { ++ // Same code works for both games ++ /* ++ D01011C0 001E ++ 801011C0 0000 ++ code generated via APrip by https://gbatemp.net/members/m4x1mumrez.610331/ ++ */ ++ add_D0_code(0x801011C0, readtoc_compare_val); ++ add_80_code(0x801011C0, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Marvel vs. Capcom: Clash of Super Heroes ++ ( ++ ((strcmp("SLPS_023.68;1", bootfile)) == 0) // Japan ++ || ((strcmp("SLPM_805.08;1", bootfile)) == 0) // Japan Demo ++ ) { ++ /* ++ D00F0C3A 1040 ++ 800F0C3A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_m.shtml ++ */ ++ add_D0_code(0x800F0C3A, common_routine_return_compare_val); ++ add_80_code(0x800F0C3A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Medievil II ++ ((strcmp("SCUS_945.64;1", bootfile)) == 0) { ++ /* ++ D0098804 023A ++ 80098806 1000 ++ code via https://gamehacking.org/game/89269 ++ */ ++ add_D0_code(0x80098804, 0x023A); ++ add_80_code(0x80098806, 0x1000); ++ install_cheat_engine(); ++ } else if ++ ++// MLB 2002 Demo, MLB 2002, MLB 2003 Demo, MLB 2003, MLB 2004 ++ ( ++ ((strcmp("SCUS_946.48;1", bootfile)) == 0) // MLB 2002 USA Demo ++ || ((strcmp("SCUS_946.38;1", bootfile)) == 0) // MLB 2002 USA ++ || ((strcmp("SCUS_946.72;1", bootfile)) == 0) // MLB 2003 USA Demo ++ || ((strcmp("SCUS_946.53;1", bootfile)) == 0) // MLB 2003 USA ++ || ((strcmp("SCUS_946.89;1", bootfile)) == 0) // MLB 2004 USA ++ ) { ++ /* ++ D0028DB4 001E ++ 80028DB4 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80028DB4, readtoc_compare_val); ++ add_80_code(0x80028DB4, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// My Garden ++ ((strcmp("SLPS_022.13;1", bootfile)) == 0) { // Japan ++ /* ++ D009E212 1040 ++ 8009E212 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_m.shtml ++ */ ++ add_D0_code(0x8009E212, common_routine_return_compare_val); ++ add_80_code(0x8009E212, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NBA Shootout 2001 and NBA Shootout 2001 Demo ++ ((strcmp("SCUS_945.81;1", bootfile)) == 0) { // this game is nuts. Seriously what the fuck is this. The demo and retail versions share not only the same executable filename, the demo executable file is the exact same with 0 diffs compared to the retail version. I guess retail functionallity is being enabled by some other file in track 01 (which do in fact differ between the demo and retail versions). EVEN FUCKING WORSE is that the demo version has serial number SCUS_945.82, but the boot file is SCUS_945.81! For now we enable both demo and retail codes for both versions to ensure it boots, since we can't detect this off of bootfile alone. To do this in a less ugly way we would need to find the file in track 01 that differs (to enable retail functionallity) and then diff that in memory. ++ /* ++ D01D1340 001E ++ 801D1340 0000 ++ my code generated via aprip (USA) ++ */ ++ add_D0_code(0x801D1340, readtoc_compare_val); ++ add_80_code(0x801D1340, readtoc_patch_val); ++ /* ++ D01CFD68 001E ++ 801CFD68 0000 ++ my code generated via aprip (USA Demo) ++ */ ++ add_D0_code(0x801CFD68, readtoc_compare_val); ++ add_80_code(0x801CFD68, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NBA Shootout 2002 Demo ++ ((strcmp("SCUS_946.60;1", bootfile)) == 0) { // USA ++ /* ++ D01D0FF4 001E ++ 801D0FF4 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x801D0FF4, readtoc_compare_val); ++ add_80_code(0x801D0FF4, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NBA Shootout 2002 ++ ((strcmp("SCUS_946.41;1", bootfile)) == 0) { // USA ++ /* ++ D01D2724 001E ++ 801D2724 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x801D2724, readtoc_compare_val); ++ add_80_code(0x801D2724, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NBA Shootout 2003 ++ ((strcmp("SCUS_946.73;1", bootfile)) == 0) { // USA ++ /* ++ D01D2860 001E ++ 801D2860 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x801D2860, readtoc_compare_val); ++ add_80_code(0x801D2860, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NBA Shootout 2004 ++ ((strcmp("SCUS_946.91;1", bootfile)) == 0) { // USA ++ /* ++ D01D2928 001E ++ 801D2928 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x801D2928, readtoc_compare_val); ++ add_80_code(0x801D2928, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NCAA FinalFour 2001 ++ ((strcmp("SCUS_945.79;1", bootfile)) == 0) { // USA ++ /* ++ D005B6A8 001E ++ 8005B6A8 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x8005B6A8, readtoc_compare_val); ++ add_80_code(0x8005B6A8, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NCAA GameBreaker 2001 ++ ( ++ ((strcmp("SCUS_945.74;1", bootfile)) == 0) // NCAA GameBreaker 2001 USA ++ || ((strcmp("SCUS_945.73;1", bootfile)) == 0) // NCAA GameBreaker 2001 USA Demo ++ ) { ++ /* ++ D0112338 001E ++ 80112338 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80112338, readtoc_compare_val); ++ add_80_code(0x80112338, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NFL GameDay 2001 ++ ((strcmp("SCUS_945.75;1", bootfile)) == 0) { // USA ++ /* ++ D0112404 001E ++ 80112404 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80112404, readtoc_compare_val); ++ add_80_code(0x80112404, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NFL GameDay 2001 Demo ++ ((strcmp("SCUS_945.76;1", bootfile)) == 0) { // USA ++ /* ++ D0112388 001E ++ 80112388 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80112388, readtoc_compare_val); ++ add_80_code(0x80112388, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NFL GameDay 2002 ++ ((strcmp("SCUS_946.39;1", bootfile)) == 0) { // USA ++ /* ++ D0032640 001E ++ 80032640 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80032640, readtoc_compare_val); ++ add_80_code(0x80032640, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NFL GameDay 2003, NFL GameDay 2004, and NFL GameDay 2005 (lmao they gave up?) ++ ( ++ ((strcmp("SCUS_946.65;1", bootfile)) == 0) // NFL GameDay 2003 USA ++ || ((strcmp("SCUS_946.90;1", bootfile)) == 0) // NFL GameDay 2004 USA ++ || ((strcmp("SCUS_946.95;1", bootfile)) == 0) // NFL GameDay 2005 USA ++ ) { ++ /* ++ D0032ACC 001E ++ 80032ACC 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x80032ACC, readtoc_compare_val); ++ add_80_code(0x80032ACC, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// NHL FaceOff 2001 ++ ((strcmp("SCUS_945.77;1", bootfile)) == 0) { // USA ++ /* ++ D00F2470 001E ++ 800F2470 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x800F2470, readtoc_compare_val); ++ add_80_code(0x800F2470, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SCUS_945.78;1", bootfile)) == 0) { // USA Demo ++ /* ++ D00F1938 001E ++ 800F1938 0000 ++ my code generated via aprip ++ */ ++ add_D0_code(0x800F1938, readtoc_compare_val); ++ add_80_code(0x800F1938, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Oha-Studio Dance Dance Revolution ++ ((strcmp("SLPM_866.03;1", bootfile)) == 0) { // Japan ++ /* ++ D00FAE58 001E ++ 800FAE58 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x800FAE58, readtoc_compare_val); ++ add_80_code(0x800FAE58, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Ore no Ryouri ++ ((strcmp("SCPS_100.99;1", bootfile)) == 0) { // Japan ++ /* ++ D0031C1A 1040 ++ 80031C1A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_m.shtml ++ */ ++ add_D0_code(0x80031C1A, common_routine_return_compare_val); ++ add_80_code(0x80031C1A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Pocket Jiman ++ ((strcmp("SCPS_101.04;1", bootfile)) == 0) { // Japan ++ /* ++ D0126BDC 001E ++ 80126BDC 0000 ++ code by https://gbatemp.net/members/m4x1mumrez.610331/ generated with APrip ++ */ ++ add_D0_code(0x80126BDC, readtoc_compare_val); ++ add_80_code(0x80126BDC, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// PoPoLoCrois Monogatari II ++ ( ++ ((strcmp("SCPS_101.12;1", bootfile)) == 0) // Japan Disc 1 ++ || ((strcmp("SCPS_101.13;1", bootfile)) == 0) // Japan Disc 2 ++ || ((strcmp("SCPS_101.14;1", bootfile)) == 0) // Japan Disc 3 ++ ) { ++ /* ++ D00B2612 1040 ++ 800B2612 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_p.shtml ++ */ ++ add_D0_code(0x800B2612, common_routine_return_compare_val); ++ add_80_code(0x800B2612, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Pop'n Music: Animation Melody ++ ((strcmp("SLPM_865.92;1", bootfile)) == 0) { // Japan ++ /* ++ D009E7E8 001E ++ 8009E7E8 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x8009E7E8, readtoc_compare_val); ++ add_80_code(0x8009E7E8, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Pop'n Music: Disney Tunes ++ ((strcmp("SLPM_866.70;1", bootfile)) == 0) { // Japan ++ /* ++ D008A45C 001E ++ 8008A45C 0000 ++ code generated via aprip by https://www.psx-place.com/members/trappedinlimbo.156719/ ++ */ ++ add_D0_code(0x8008A45C, readtoc_compare_val); ++ add_80_code(0x8008A45C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Pop'n Music 2 ++ ((strcmp("SLPM_862.94;1", bootfile)) == 0) { // Japan ++ /* ++ D0015342 1040 ++ 80015342 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_p.shtml ++ */ ++ add_D0_code(0x80015342, common_routine_return_compare_val); ++ add_80_code(0x80015342, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Pop'n Music 5 ++ ((strcmp("SLPM_869.37;1", bootfile)) == 0) { // Japan ++ /* ++ D0048F34 001E ++ 80048F34 0000 ++ my code via aprip to patch out readtoc ++ */ ++ add_D0_code(0x80048F34, readtoc_compare_val); ++ add_80_code(0x80048F34, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Pop'n Music 6 ++ ((strcmp("SLPM_870.89;1", bootfile)) == 0) { // Japan ++ /* ++ D004A24C 001E ++ 8004A24C 0000 ++ my code via aprip to patch out readtoc ++ */ ++ add_D0_code(0x8004A24C, readtoc_compare_val); ++ add_80_code(0x8004A24C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Resident Evil 3: The Last Escape ++ ((strcmp("SLPS_023.00;1", bootfile)) == 0) { // Japan Rev 0/ Japan Rev 1 ++ ver_check = (load_addr + 0x1B0); // First different byte between revisions ++ //debug_write("Got address for version check: %x", (uint32_t) ver_check); ++ ver_check_val = *(uint8_t*) ver_check; ++ //debug_write("Ver check address has the contents : %x", (uint8_t) ver_check_val); ++ if((ver_check_val == 0xF4)) // Rev 0 ++ { ++ /* ++ D01840E2 1040 ++ 801840E2 1000 ++ 'skip check' code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_b.shtml ++ */ ++ add_D0_code(0x801840E2, common_routine_return_compare_val); ++ add_80_code(0x801840E2, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else { // Rev 1 ++ /* ++ D018418E 1040 ++ 8018418E 1000 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x8018418E, common_routine_return_compare_val); ++ add_80_code(0x8018418E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } ++ } else if ++ ++ ((strcmp("SLPM_804.85;1", bootfile)) == 0) { // Japan Demo ++ /* ++ D01800E2 1040 ++ 801800E2 1000 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x801800E2, common_routine_return_compare_val); ++ add_80_code(0x801800E2, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Resident Evil Survivor ++ ((strcmp("SLPS_025.53;1", bootfile)) == 0) { // Japan ++ /* ++ D0017962 1040 ++ 80017962 1000 ++ 'skip mod check' code is from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_b.shtml ++ */ ++ add_D0_code(0x80017962, common_routine_return_compare_val); ++ add_80_code(0x80017962, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SLUS_010.87;1", bootfile)) == 0) { // USA ++ /* ++ D001714E 1040 ++ 8001714E 1000 ++ converted code via aprip ++ */ ++ add_D0_code(0x8001714E, common_routine_return_compare_val); ++ add_80_code(0x8001714E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ( ++ ((strcmp("SLES_027.32;1", bootfile)) == 0) // Europe ++ || ((strcmp("SLES_027.44;1", bootfile)) == 0) // France ++ ) { ++ /* ++ D001713E 1040 ++ 8001713E 1000 ++ converted code via aprip ++ */ ++ add_D0_code(0x8001713E, common_routine_return_compare_val); ++ add_80_code(0x8001713E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Robbit mon Dieu ++ ((strcmp("SCPS_101.03;1", bootfile)) == 0) { // Japan ++ /* ++ D001C646 1040 ++ 8001C646 1000 ++ 'skip mod check' code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_r.shtml ++ */ ++ add_D0_code(0x8001C646, common_routine_return_compare_val); ++ add_80_code(0x8001C646, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman ++ ((strcmp("SLPS_022.20;1", bootfile)) == 0) { // Japan ++ /* ++ D006C92A 1040 ++ 8006C92A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_r.shtml ++ */ ++ add_D0_code(0x8006C92A, common_routine_return_compare_val); ++ add_80_code(0x8006C92A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman 2: Dr. Wily no Nazo ++ ((strcmp("SLPS_022.55;1", bootfile)) == 0) { // Japan ++ /* ++ D006CA82 1040 ++ 8006CA82 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_r.shtml ++ */ ++ add_D0_code(0x8006CA82, common_routine_return_compare_val); ++ add_80_code(0x8006CA82, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman 3: Dr. Wily no Saigo!? ++ ((strcmp("SLPS_022.62;1", bootfile)) == 0) { // Japan ++ /* ++ D006CA1A 1040 ++ 8006CA1A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_r.shtml ++ */ ++ add_D0_code(0x8006CA1A, common_routine_return_compare_val); ++ add_80_code(0x8006CA1A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman 4: Aratanaru Yabou!! ++ ((strcmp("SLPS_023.24;1", bootfile)) == 0) { // Japan ++ /* ++ D007009C 001E ++ 8007009C 0000 ++ my code via aprip to patch out readtoc ++ */ ++ add_D0_code(0x8007009C, readtoc_compare_val); ++ add_80_code(0x8007009C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman 5: Blues no Wana!? ++ ((strcmp("SLPS_023.38;1", bootfile)) == 0) { // Japan ++ /* ++ D006FD84 001E ++ 8006FD84 0000 ++ my code via aprip ++ */ ++ add_D0_code(0x8006FD84, readtoc_compare_val); ++ add_80_code(0x8006FD84, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman 6 ++ ((strcmp("SLPS_023.79;1", bootfile)) == 0) { // Japan ++ /* ++ D006DA7A 1040 ++ 8006DA7A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_r.shtml ++ */ ++ add_D0_code(0x8006DA7A, common_routine_return_compare_val); ++ add_80_code(0x8006DA7A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman X5 ++ ((strcmp("SLPM_866.66;1", bootfile)) == 0) { // Japan ++ /* ++ D0070ED0 001E ++ 80070ED0 0000 ++ my code via aprip ++ */ ++ add_D0_code(0x80070ED0, readtoc_compare_val); ++ add_80_code(0x80070ED0, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Rockman X6 ++ ((strcmp("SLPM_869.59;1", bootfile)) == 0) { // Japan ++ /* ++ D006EC40 001E ++ 8006EC40 0000 ++ my code via aprip ++ */ ++ add_D0_code(0x8006EC40, readtoc_compare_val); ++ add_80_code(0x8006EC40, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Street Fighter EX2 Plus ++ ((strcmp("SLPS_025.08;1", bootfile)) == 0) { // Japan ++ /* ++ D01BD48A 1040 ++ 801BD48A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_s.shtml ++ */ ++ add_D0_code(0x801BD48A, common_routine_return_compare_val); ++ add_80_code(0x801BD48A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SLPM_805.17;1", bootfile)) == 0) { // Japan Demo ++ /* ++ D01BD13E 1040 ++ 801BD13E 1000 ++ my code via aprip gameshark code conversion ++ */ ++ add_D0_code(0x801BD48A, common_routine_return_compare_val); ++ add_80_code(0x801BD13E, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Spyro: Year Of The Dragon ++// codes co-developed by MottZilla (mostly) and myself. Get rekt anti-tamper/apv1/apv2 ++ ((strcmp("SCUS_944.67;1", bootfile)) == 0) { // has 2 versions, rev 0 and rev 1 ++ ver_check = (load_addr); // First different byte between revisions is well the first byte :) ++ //debug_write("Got address for version check: %x", (uint32_t) ver_check); ++ ver_check_val = *(uint8_t*) ver_check; ++ //debug_write("Ver check address has the contents : %x", (uint8_t) ver_check_val); ++ if(ver_check_val == 0xF4) { // Rev 0 ++ add_D0_code(0x8007F08C, 0x0001); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0002); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0003); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0004); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0005); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0006); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0007); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0008); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x0009); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x000A); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x000B); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x000C); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x000D); ++ add_80_code(0x8007F08C, 0x0000); ++ add_D0_code(0x8007F08C, 0x000E); ++ add_80_code(0x8007F08C, 0x0000); ++ install_cheat_engine(); ++ } else { // 0x08 = Rev 1 ++ add_D0_code(0x8007F23C, 0x0001); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0002); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0003); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0004); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0005); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0006); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0007); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0008); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x0009); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x000A); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x000B); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x000C); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x000D); ++ add_80_code(0x8007F23C, 0x0000); ++ add_D0_code(0x8007F23C, 0x000E); ++ add_80_code(0x8007F23C, 0x0000); ++ install_cheat_engine(); ++ } ++ } else if ++ ++// Strider 2 ++ ((strcmp("SLUS_011.63;1", bootfile)) == 0) { // USA ++ /* ++ D01F6570 001E ++ 801F6570 0000 ++ my code via aprip ++ */ ++ add_D0_code(0x801F6570, readtoc_compare_val); ++ add_80_code(0x801F6570, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Tokimeki Memorial 2 (soo many god damn discs/versions/bootfiles) ++ ( ++ // main game (5 discs) ++ ((strcmp("SLPM_863.55;1", bootfile)) == 0) // Tokimeki Memorial 2 Rev 0/Rev 1 Disc 1 ++ || ((strcmp("SLPM_863.50;1", bootfile)) == 0) // Tokimeki Memorial 2 Limited Box Disc 1 ++ || ((strcmp("SLPM_863.56;1", bootfile)) == 0) // Tokimeki Memorial 2 Rev 0/Rev 1 Disc 2 ++ || ((strcmp("SLPM_863.51;1", bootfile)) == 0) // Tokimeki Memorial 2 Limited Box Disc 2 ++ || ((strcmp("SLPM_863.57;1", bootfile)) == 0) // Tokimeki Memorial 2 Rev 0/Rev 1 Disc 3 ++ || ((strcmp("SLPM_863.52;1", bootfile)) == 0) // Tokimeki Memorial 2 Limited Box Disc 3 ++ || ((strcmp("SLPM_863.58;1", bootfile)) == 0) // Tokimeki Memorial 2 Rev 0/Rev 1 Disc 4 ++ || ((strcmp("SLPM_863.53;1", bootfile)) == 0) // Tokimeki Memorial 2 Limited Box Disc 4 ++ || ((strcmp("SLPM_863.59;1", bootfile)) == 0) // Tokimeki Memorial 2 Rev 0/Rev 1 Disc 5 ++ || ((strcmp("SLPM_863.54;1", bootfile)) == 0) // Tokimeki Memorial 2 Limited Box Disc 5 ++ // dlc evs (3 discs) ++ || ((strcmp("SLPM_805.27;1", bootfile)) == 0) // Tokimeki Memorial 2 Emotional Voice System Append Disc 1 ++ || ((strcmp("SLPM_805.44;1", bootfile)) == 0) // Tokimeki Memorial 2 Emotional Voice System Append Disc 2 ++ || ((strcmp("SLPM_805.50;1", bootfile)) == 0) // Tokimeki Memorial 2 Emotional Voice System Append Disc 3 ++ ) { ++ /* ++ D0011514 001E ++ 80011514 0000 ++ my code via aprip ++ */ ++ add_D0_code(0x80011514, readtoc_compare_val); ++ add_80_code(0x80011514, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Tomba! 2: The Evil Swine Return ++ ((strcmp("SCUS_944.54;1", bootfile)) == 0) { // USA ++ /* ++ D002542C 001E ++ 8002542C 0000 ++ my code via aprip ++ */ ++ add_D0_code(0x8002542C, readtoc_compare_val); ++ add_80_code(0x8002542C, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Tron ni Kobun ++ ((strcmp("SLPS_021.08;1", bootfile)) == 0) { // Japan ++ /* ++ D004E168 001E ++ 8004E168 0000 ++ my code via aprip ++ */ ++ add_D0_code(0xD004E168, readtoc_compare_val); ++ add_80_code(0x8004E168, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Vandal Harts II ++ ((strcmp("SLUS_009.40;1", bootfile)) == 0) { // USA ++ /* ++ D00865FC 001E ++ 800865FC 0000 ++ my code via aprip to patch out readtoc ++ */ ++ add_D0_code(0x800865FC, readtoc_compare_val); ++ add_80_code(0x800865FC, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Wild Arms 2 ++ ( ++ ((strcmp("SCUS_944.84;1", bootfile)) == 0) // USA Disc 1 ++ || ((strcmp("SCUS_944.98;1", bootfile)) == 0) // USA Disc 2 ++ ) { ++ /* ++ D003A4E8 001E ++ 8003A4E8 0000 ++ my code via aprip to patch out readtoc ++ */ ++ add_D0_code(0x8003A4E8, readtoc_compare_val); ++ add_80_code(0x8003A4E8, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++ ((strcmp("SCUS_945.92;1", bootfile)) == 0) { // USA Demo ++ /* ++ D003A5D4 001E ++ 8003A5D4 0000 ++ my code via aprip gameshark code conversion on my own code (code-ception) ++ */ ++ add_D0_code(0x8003A5D4, readtoc_compare_val); ++ add_80_code(0x8003A5D4, readtoc_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// World Soccer Jikkyou Winning Eleven 4 ++ ((strcmp("SLPM_862.91;1", bootfile)) == 0) { // Japan Rev 0/Japan Rev 1 ++ /* ++ D01030CA 1040 ++ 801030CA 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_w.shtml ++ */ ++ add_D0_code(0x801030CA, common_routine_return_compare_val); ++ add_80_code(0x801030CA, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// XI[SAI] Jumbo ++ ((strcmp("SCPS_101.23;1", bootfile)) == 0) { // Japan ++ /* ++ D010178A 1040 ++ 8010178A 1000 ++ code 1 of 3 from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_x.shtml ++ */ ++ add_D0_code(0x8010178A, common_routine_return_compare_val); ++ add_80_code(0x8010178A, common_routine_return_patch_val); ++ /* ++ D00A370A 1040 ++ 800A370A 1000 ++ code 2 of 3 from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_x.shtml ++ */ ++ add_D0_code(0x800A370A, common_routine_return_compare_val); ++ add_80_code(0x800A370A, common_routine_return_patch_val); ++ /* ++ D0113C1A 1040 ++ 80113C1A 1000 ++ code 3 of 3 from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_x.shtml ++ */ ++ add_D0_code(0x80113C1A, common_routine_return_compare_val); ++ add_80_code(0x80113C1A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } else if ++ ++// Yu-Gi-Oh! Forbidden Memories ++ ( ++ ((strcmp("SLPM_863.96;1", bootfile)) == 0) // Japan ++ || ((strcmp("SLPM_863.98;1", bootfile)) == 0) // Japan Demo ++ || ((strcmp("SLUS_014.11;1", bootfile)) == 0) // USA ++ || ((strcmp("SLES_039.47;1", bootfile)) == 0) // Europe ++ || ((strcmp("SLES_039.48;1", bootfile)) == 0) // France ++ || ((strcmp("SLES_039.49;1", bootfile)) == 0) // Germany ++ || ((strcmp("SLES_039.50;1", bootfile)) == 0) // Spain ++ || ((strcmp("SLES_039.51;1", bootfile)) == 0) // Italy ++ ) { ++ /* ++ D016818A 1040 ++ 8016818A 1000 ++ code from consolecopyworld: https://consolecopyworld.com/psx/psx_game_codes_y.shtml ++ */ ++ add_D0_code(0x8016818A, common_routine_return_compare_val); ++ add_80_code(0x8016818A, common_routine_return_patch_val); ++ install_cheat_engine(); ++ } ++} +\ No newline at end of file +diff --git a/loader/ap-bypass.h b/loader/ap-bypass.h +new file mode 100644 +index 0000000..ddff419 +--- /dev/null ++++ b/loader/ap-bypass.h +@@ -0,0 +1,16 @@ ++ ++#pragma once ++ ++void activate_anti_anti_piracy(const char * bootfile, const int32_t load_addr); ++ ++void add_30_code(const uint32_t gs1, const uint8_t gs2); ++void add_E0_code(const uint32_t gs1, const uint8_t gs2); ++void add_E1_code(const uint32_t gs1, const uint8_t gs2); ++ ++void add_80_code(const uint32_t gs1, const uint16_t gs2); ++void add_D0_code(const uint32_t gs1, const uint16_t gs2); ++void add_D1_code(const uint32_t gs1, const uint16_t gs2); ++ ++void install_cheat_engine(); ++ ++extern bool cheat_engine_installed; +diff --git a/tmp/og-tonyhax.CFG/loader/bios-asm.S b/loader/bios-asm.S +index 93837fa..a71573d 100644 +--- a/tmp/og-tonyhax.CFG/loader/bios-asm.S ++++ b/loader/bios-asm.S +@@ -69,11 +69,6 @@ memcpy: + li t1, 0x2A + j 0xA0 + +-.global std_out_puts +-std_out_puts: +- li t1, 0x3E +- j 0xA0 +- + .global DoExecute + DoExecute: + # Pepsiman (J) crashes if s5 is not zero +@@ -137,6 +132,11 @@ CdReadSector: + li t1, 0xA5 + j 0xA0 + ++.global SetMemSize ++SetMemSize: ++ li t1, 0x9F ++ j 0xA0 ++ + ############### + # B-FUNCTIONS # + ############### +diff --git a/tmp/og-tonyhax.CFG/loader/bios.c b/loader/bios.c +index 0f3d558..2ec6a3f 100644 +--- a/tmp/og-tonyhax.CFG/loader/bios.c ++++ b/loader/bios.c +@@ -5,23 +5,13 @@ + #include "debugscreen.h" + #include "str.h" + +-void * original_disc_error; +- +-bool console_has_tty() { +- /* +- * Check if the console has a SCN2681 TTY used for debug by writing data to the control +- * registers and reading it back. +- * +- * The control is 16 bit wide, and is accessed by writing or reading twice the same register. +- */ +- volatile uint8_t * scn2681modereg = (uint8_t *) 0x1F802020; ++// Set to zero unless you are using an emulator or have a physical UART on the PS1, else it'll freeze ++const uint32_t tty_enabled = 0; + +- *scn2681modereg = 0x55; +- *scn2681modereg = 0xAA; +- return *scn2681modereg == 0x55 && *scn2681modereg == 0xAA; +-} ++void * original_disc_error; + + void bios_reinitialize() { ++ // See https://github.com/ogamespec/psxdev/blob/master/reverse/Main.c for reference to some of this... + // Disable interrupts + EnterCriticalSection(); + +@@ -52,8 +42,11 @@ void bios_reinitialize() { + I_STAT = 0; + I_MASK = 0; + +- // Setup devices. +- InstallDevices(console_has_tty()); ++ // Setup devices ++ InstallDevices(tty_enabled); ++ ++ // BIOS sets the memory to 8MB (somewhere, haven't seen exactly where but this is well known), which causes the RAM to be mirrored 4 times since there is actually only 2MBs of RAM. The thing is, some games set this to the 'correct' value of 2 for the appropriate 2MBs of RAM. This will cause issues when booting games, so we explicitly set it like the BIOS does which is what every game initially expects at boot. ++ SetMemSize(8); // fixes Ridge Racer USA GSHAX boot method getting stuck at the doexecute() call for discs such as the Tonyhax International ROM Flasher CD + + /* + * Configure with default values +@@ -92,7 +85,7 @@ void bios_reinitialize() { + // End of code adapted + + // Re-enable interrupts +- ExitCriticalSection(); ++ ExitCriticalSection(); // unnecesary because SetConf() does this? Waiting on verdict from Socram8888: https://github.com/socram8888/tonyhax/issues/149 + + // Save for later + original_disc_error = BIOS_A0_TABLE[0xA1]; +diff --git a/tmp/og-tonyhax.CFG/loader/bios.h b/loader/bios.h +index c5b26f3..9498989 100644 +--- a/tmp/og-tonyhax.CFG/loader/bios.h ++++ b/loader/bios.h +@@ -219,13 +219,6 @@ void ExitCriticalSection(); + */ + uint32_t todigit(char c); + +-/** +- * Prints a text through the TTY. +- * +- * @param text text to print +- */ +-void std_out_puts(const char * text); +- + /** + * Starts a previously loaded executable. + * +@@ -439,3 +432,10 @@ void InstallDevices(uint32_t enable_tty); + * Table C, call 0x1C. + */ + void AdjustA0Table(void); ++ ++/** ++ * Called to set the RAM to 8MBs, which enables the mirroring of RAM 4 times in the real 2MBs of RAM (which is exactly what the BIOS ends up doing) ++ * ++ * Table A, call 0x9F. ++ */ ++void SetMemSize(uint8_t mem_size); +\ No newline at end of file +diff --git a/tmp/og-tonyhax.CFG/loader/cdrom.c b/loader/cdrom.c +index dddc533..40d9b6f 100644 +--- a/tmp/og-tonyhax.CFG/loader/cdrom.c ++++ b/loader/cdrom.c +@@ -43,6 +43,40 @@ void cd_command(uint_fast8_t cmd, const uint8_t * params, uint_fast8_t params_le + CD_REGS[1] = cmd; + } + ++void cd_command_race(uint_fast8_t cmd, const uint8_t * params, uint_fast8_t params_len) { ++ ++ // Wait for previous command to finish, if any ++ //while (CD_REGS[0] & 0x80); ++ ++ // Switch to page 0 ++ cd_set_page(0); ++ ++ // Clear read and write FIFOs ++ CD_REGS[3] = 0xC0; ++ ++ // Copy request ++ while (params_len != 0) { ++ CD_REGS[2] = *params; ++ params++; ++ params_len--; ++ } ++ ++ // Switch to page 1 ++ cd_set_page(1); ++ ++ // Disable interrupts as we'll poll ++ CD_REGS[2] = 0x00; ++ ++ // Acknowledge interrupts, if there were any ++ CD_REGS[3] = 0x07; ++ ++ // Switch to page 0 ++ cd_set_page(0); ++ ++ // Finally write command to start ++ CD_REGS[1] = cmd; ++} ++ + uint_fast8_t cd_wait_int(void) { + + // Wait for command to finish, if any +@@ -64,6 +98,28 @@ uint_fast8_t cd_wait_int(void) { + return interrupt; + } + ++uint_fast8_t cd_wait_int_race(void) { ++ ++ // Wait for command to finish, if any ++ //while (CD_REGS[0] & 0x80); ++ ++ // Switch to page 1 ++ cd_set_page(1); ++ ++ // Wait until an interrupt happens (int != 0) ++ uint_fast8_t interrupt; ++ do { ++ interrupt = CD_REGS[3] & 0x07; ++ } while (interrupt == 0); ++ ++ // Acknowledge it ++ CD_REGS[3] = 0x07; ++ ++ // Return it ++ return interrupt; ++} ++ ++ + uint_fast8_t cd_read_reply(uint8_t * reply_buffer) { + + // Switch to page 1 +@@ -81,6 +137,9 @@ uint_fast8_t cd_read_reply(uint8_t * reply_buffer) { + return len; + } + ++//we can't trust this due to a race condition. If the actual BIOS executes a CD command (affects the Tonyhax International ROM), or a game is in the middle of executing a CD command when Tonyhax International starts (affects GSHAX), and this is executed close enough in the Tonyhax International loader code itself, it will get stuck if done like below: ++ ++/* + bool cd_drive_init() { + cd_command(CD_CMD_INIT, NULL, 0); + +@@ -96,18 +155,22 @@ bool cd_drive_init() { + + return true; + } ++*/ + +-bool cd_drive_reset() { +- // Issue a reset ++void cd_drive_init() { ++ cd_command_race(CD_CMD_INIT, NULL, 0); ++ ++ cd_wait_int_race(); ++ cd_wait_int_race(); ++} ++ ++void cd_drive_reset() { ++ // Issue a reset (looses authentication and or unlock when completed, so do an unlock after this) + cd_command(CD_CMD_RESET, NULL, 0); + +- // Should succeed with 3 +- if (cd_wait_int() != 3) { +- return false; +- } ++ // Should succeed with 3 but doesn't sometimes so we can't check the return value ++ cd_wait_int(); + + // Need to wait for some cycles before it springs back to life +- for (int i = 0; i < 0x400000; i++); +- +- return true; ++ for (volatile int i = 0; i < 0x400000; i++); // unmodifiable compiler code when using -Os optimizations + } +diff --git a/tmp/og-tonyhax.CFG/loader/cdrom.h b/loader/cdrom.h +index 438e7cd..c26874d 100644 +--- a/tmp/og-tonyhax.CFG/loader/cdrom.h ++++ b/loader/cdrom.h +@@ -8,6 +8,12 @@ + #define CD_CMD_TEST 0x19 + #define CD_CMD_RESET 0x1C + #define CD_TEST_REGION 0x22 ++#define CD_CMD_SET_SESSION 0x12 ++#define CD_CMD_STOP 0x08 ++#define CD_CMD_GETID 0x1A ++#define CD_CMD_SETMODE 0x0E ++#define CD_CMD_GETTN 0x13 ++#define CD_CMD_GETTD 0x14 + + /** + * Starts executing a CD command. +@@ -38,11 +44,9 @@ uint_fast8_t cd_read_reply(uint8_t * reply_buffer); + * + * @returns true if succeded, or false otherwise. + */ +-bool cd_drive_init(void); ++//bool cd_drive_init(void); ++// we can't trust that: ++void cd_drive_init(); + +-/** +- * Resets the drive. +- * +- * @returns true if succeded, or false otherwise. +- */ +-bool cd_drive_reset(void); ++// Resets the drive. ++void cd_drive_reset(); +diff --git a/tmp/og-tonyhax.CFG/loader/debugscreen.c b/loader/debugscreen.c +index cb8c32e..926cb0c 100644 +--- a/tmp/og-tonyhax.CFG/loader/debugscreen.c ++++ b/loader/debugscreen.c +@@ -113,7 +113,7 @@ void debug_init() { + gpu_flush_cache(); + + // Draw border +- debug_text_at(TH_MARGIN, 40, "tonyhax " STRINGIFY(TONYHAX_VERSION)); ++ debug_text_at(TH_MARGIN, 40, "tonyhax international " STRINGIFY(TONYHAX_VERSION)); + struct gpu_solid_rect band = { + .pos = { + .x = 0, +@@ -237,9 +237,12 @@ void debug_write(const char * str, ...) { + } else { + last_printed_count++; + +- // Same line, so print with a repeat counter +- mini_sprintf(formatted_repeated, "%s (x%d)", last_printed_line, last_printed_count); +- ++ // Same line, so print with a repeat counter unless we are waiting for controller input on a Japanese console ++ if(!controller_input) { ++ mini_sprintf(formatted_repeated, "%s (x%d)", last_printed_line, last_printed_count); ++ } else { ++ mini_sprintf(formatted_repeated, "%s", last_printed_line); ++ } + to_print = formatted_repeated; + } + +diff --git a/tmp/og-tonyhax.CFG/loader/debugscreen.h b/loader/debugscreen.h +index 6ae71a5..d06a360 100644 +--- a/tmp/og-tonyhax.CFG/loader/debugscreen.h ++++ b/loader/debugscreen.h +@@ -10,3 +10,5 @@ void debug_write(const char * str, ...); + void debug_text_at(uint_fast16_t x, uint_fast16_t y, const char * str); + + void debug_switch_standard(bool pal); ++ ++extern bool controller_input; +\ No newline at end of file +diff --git a/tmp/og-tonyhax.CFG/loader/generate-tonyhax-mcs.sh b/loader/generate-tonyhax-mcs.sh +index 33116fa..b01a8b9 100644 +--- a/tmp/og-tonyhax.CFG/loader/generate-tonyhax-mcs.sh ++++ b/loader/generate-tonyhax-mcs.sh +@@ -25,11 +25,11 @@ load_len=$(printf "%08X" $(stat -c %s $bin_file)) + + # Create file + cp "$tpl_file" "$mcs_file" +-echo -n "tonyhax ${version}" | dd status=none conv=notrunc bs=1 seek=132 of="$mcs_file" ++echo -n "tonyhax-i ${version}" | dd status=none conv=notrunc bs=1 seek=132 of="$mcs_file" + dd status=none conv=notrunc bs=1 seek=384 if=$bin_file of="$mcs_file" + + # Insert address at 0xC0 and length at 0xC4, which is 0x40 and 0x44 inside the save file header +-echo -ne "\x${ro_start:6:2}\x${ro_start:4:2}\x${ro_start:2:2}\x${ro_start:0:2}\x${load_len:6:2}\x${load_len:4:2}\x${load_len:2:2}\x${load_len:0:2}" | dd status=none conv=notrunc of=tonyhax.mcs bs=1 seek=192 ++echo -ne "\x${ro_start:6:2}\x${ro_start:4:2}\x${ro_start:2:2}\x${ro_start:0:2}\x${load_len:6:2}\x${load_len:4:2}\x${load_len:2:2}\x${load_len:0:2}" | dd status=none conv=notrunc of="$mcs_file" bs=1 seek=192 + + # Cleanup + rm $bin_file +diff --git a/tmp/og-tonyhax.CFG/loader/patch-ap.S b/tmp/og-tonyhax.CFG/loader/patch-ap.S +deleted file mode 100644 +index 85511eb..0000000 +--- a/tmp/og-tonyhax.CFG/loader/patch-ap.S ++++ /dev/null +@@ -1,196 +0,0 @@ +- +-#include +- +-.text +- +-# +-# Intercepts the syscall(1) (aka EnterCriticalSection). +-# +-# When this code is executed, the registers are as follows: +-# - v0: saved thread registers, must NOT be modified. +-# The rest of the registers are not critical and can be used freely. +-# +-.globl patch_ap_start +-patch_ap_start: +- # Load the SP value +- lw t0, 0x7C(v0) +- +- # +- # If we are being called from an antimodchip module, the call stack will look like this: +- # - (game code) +- # - ap_check +- # - ap_failed +- # - StopCallback +- # - disable_ints +- # - EnterCriticalSection +- # +- # For all known modules, the return address from StopCallback to ap_failed sits at SP+0x28. +- # +- # Before reading from this address, we will check that after adding that offset, we do not +- # cross a 2MB boundary, which could cause an illegal memory read. +- # +- # Without this check the following games crash: +- # - Elemental Gearbolt (U) (SLUS-00654), calling with a stack at 0x807FFFE0, as we attempt +- # to read from 0x80800008. +- # - Rival Schools (U) (SLUS-00681), calling with a stack of 0x801FFFD8, as we attempt to +- # read from 0x80200000. A mirror would be generally present here, but not for this game +- # as it calls SetMemSize(2) to intentionally block this. +- # +- # Some games, like Grind Session (U) (SCUS-94568) use the scratchpad during gameplay for the +- # stack, which is only 1KB. For now, we will not add a safety check for this case since the +- # vast majority of games store the stack in RAM and no game is known to crash without it. +- # +- addi t1, t0, 0x28 +- xor t1, t0 +- srl t1, 21 +- bne t1, zero, patch_ap_skip +- +- # Load alledged return address +- lw t1, 0x28(t0) +- +- # +- # Check now if the loaded value could be a word-aligned address in either the KUSEG +- # (0x00000000-0x007FFFFF) or the KSEG0 (0x80000000-0x807FFFFF) regions, which is were user +- # code is executed. +- # +- # Most games use the KSEG0, except for Emperors New Groove (U) (SCUS-94571) whose programmers +- # seemed to prefer the KUSEG region. +- # +- # We cannot limit ourselves to checking the first 2MB of RAM, because some games, like +- # Robbit Mon Dieu (J) (SCPS-10103) use a mirror (0x80600000-0x807FFFFF). +- # +- li t2, 0x7F800003 +- and t2, t1 +- bne t2, zero, patch_ap_skip +- +- # +- # First, we will attempt to handle a version 1 antimodchip module. +- # +- # This checks only for the presence of a dumb modchip, by checking if the SCEx counter +- # increments when it should not. It is also only capable of displaying the stop screen +- # in Japanese. +- # +- # The offsets for some of the checked games are: +- # +- # Um Jammer Lammy (PAL-E): +- # - ap_check (0x801D8008) +- # - ap_failed (0x801D83E0, called from 0x801D8174) +- # - StopCallback (0x800356C4, called from 0x801D8400) +- # - disable_ints (0x80035B54, called from 0x800356E0) +- # - EnterCriticalSection +- # +- # For Saru! Get You (NTSC-J): +- # - ap_check (0x80136950) +- # - ap_failed (0x80136D28, called from 0x80136ABC) +- # - StopCallback (0x8002E814, called from 0x80136D48) +- # - disable_ints (0x8002ECA4, called from 0x8002E82C) +- # - EnterCriticalSection +- # +- # The return call from StopCallback to ap_failed is located at SP+0x28. We will check if +- # at this address +0x74 exists a "li v0, 0xE6000002", which is a black rentangle passed to +- # the DrawPrim function to clear the screen. +- # +- # If it exists, we will patch the thread state to return back to ap_check, as if the +- # ap_failed function had returned. +- # +- +- # Compare signature, and test for v2 if does not match +- lw t2, 0x74(t1) +- li t3, 0x3C02E600 +- bne t2, t3, patch_ap_v15 +- +- lw t2, 0x78(t1) +- li t3, 0x34420002 +- bne t2, t3, patch_ap_v15 +- +- # Load return address from ap_failed to ap_check +- lw t1, 0xE8(t0) +- +- # Adjust stack pointer +- addi t0, 0xF0 +- +- # Save and return +- b patch_ap_save +- +- # +- # Handle another variant of the v1, used by Vandal Hearts II - Tenjou no Mon (J) (SLPM-86251) +- # - ap_check (0x800C4868) +- # - ap_failed (0x800C4C40, called from 0x800C49D4) +- # - StopCallback (0x800D2700, called from 0x800C4C58) +- # - disable_ints (0x800D2B90, called from 0x800D2718) +- # - EnterCriticalSection +- # +- # Same idea, except the load is now a "li v1, 0xE6000002" at +0x64 bytes after ap_failed +- # returns to ap_check. +- # +- # The offsets are the same as for v2, so we will reuse those adjusts. +- # +-patch_ap_v15: +- lw t2, 0x64(t1) +- li t3, 0x3C03E600 +- bne t2, t3, patch_ap_v2 +- +- lw t2, 0x68(t1) +- li t3, 0x34630002 +- beq t2, t3, patch_ap_adjust_v2 +- +- # +- # We will now attempt to patch an antimodchip v2 module. +- # +- # This one is smarter and checks that the SCEx wobble is present in the inner tracks, +- # to detect CD swapping; and for dumb modchips by checking for absence of the wobble +- # in the outer tracks. +- # +- # The offsets for some of the checked games are: +- # +- # Rockman 2 - Dr. Wily no Nazo (J) (SLPS-02255): +- # - ap_check (0x8006CA58) +- # - ap_failed (0x8006D654, called from 0x8006CE5C and 0x8006D238) +- # - StopCallback (0x80024524, called from 0x8006D66C) +- # - disable_ints (0x800249B4, called from 0x8002453C) +- # - EnterCriticalSection +- # +- # The return address from StopCallback to ap_failed is located at SP+0x28, exactly as above +- # so we will not load it again. +- # +- # For this other version, we will check if at this return address +0x10 bytes exists a +- # "sh zero, 0x1F801DAA", which is used to mute the audio. +- # +- # If that exists, we will patch the thread state to return back to ap_check. +- # +-patch_ap_v2: +- # Compare signature +- lw t2, 0x18(t1) +- li t3, 0x3C011F80 +- bne t2, t3, patch_ap_skip +- +- lw t2, 0x1C(t1) +- li t3, 0xA4201DAA +- bne t2, t3, patch_ap_skip +- +-patch_ap_adjust_v2: +- # Load return address to from ap_failed to ap_check +- lw t1, 0x120(t0) +- +- # Adjust stack pointer +- addi t0, 0x128 +- +-patch_ap_save: +- # Zero the s0 and s1 stored in the thread state, so the state machine used by ap_check exits +- sw zero, 0x48(v0) +- sw zero, 0x4C(v0) +- +- # Save adjusted stack pointer and return address +- sw t0, 0x7C(v0) +- sw t1, 0x88(v0) +- +-.globl patch_ap_success +-patch_ap_success: +- j 0x12341234 +- +-.globl patch_ap_skip +-patch_ap_skip: +- j 0x12341234 +- +-.globl patch_ap_end +-patch_ap_end: +diff --git a/tmp/og-tonyhax.CFG/loader/patch-fpb.S b/tmp/og-tonyhax.CFG/loader/patch-fpb.S +deleted file mode 100644 +index e26fb72..0000000 +--- a/tmp/og-tonyhax.CFG/loader/patch-fpb.S ++++ /dev/null +@@ -1,35 +0,0 @@ +- +-#include +- +-.text +- +-# +-# The anti-FreePSXBoot patch. +-# +-# This patch is called right at the very end of the last step in the read sector finite state +-# machine: +-# https://github.com/grumpycoders/pcsx-redux/blob/f6484e8010a40a81e4019d9bfa1a9d408637b614/src/mips/openbios/sio0/card.c#L194 +-# +-# When this code is executed, the registers are as follows: +-# - v0 contains 1, or "success". +-# - a1 contains the read buffer +-# - a2 contains the current sector number +-# +-# If the sector being read is sector 0 and it contains "FPBZ" at +0x7C, we modify the read data +-# so it is detected as corrupted and the game skips reading from it +-# +-# The offsets have been checked against BIOSes 2.2, 3.0, 4.1 and 4.4 +-# +-.globl patch_fpb_start +-patch_fpb_start: +- lw t0, 0x7C(a1) +- li t1, 0x5A425046 +- bne a2, 0, patch_fpb_ret +- bne t0, t1, patch_fpb_ret +- +- sw zero, 0(a1) +-patch_fpb_ret: +- j 0x5B54 +- +-.globl patch_fpb_end +-patch_fpb_end: +diff --git a/tmp/og-tonyhax.CFG/loader/patch-uart.S b/tmp/og-tonyhax.CFG/loader/patch-uart.S +deleted file mode 100644 +index da95257..0000000 +--- a/tmp/og-tonyhax.CFG/loader/patch-uart.S ++++ /dev/null +@@ -1,121 +0,0 @@ +- +-#include +- +-.text +- +-# +-# This is a complete replacement for the original std_out_putc the BIOS has. +-# +-# In this function: +-# - a0: data to bitbang +-# - t0: working registers +-# - t1: bits to send +-# - t2: last IRQ flag value +-# - t3: 0x1F800000 (I/O start address) +-# - t4: COP0 SR value +-# +-.globl patch_uartputc_start +-patch_uartputc_start: +- # Add start (0) and stop (1) bits to byte +- andi a0, 0xFF +- sll a0, 1 +- ori a0, 0x200 +- +- # Newline (after processing) +- li t0, (0x0A << 1 | 0x200) +- +- # Bits to send (1 start + 8 data + 1 stop) +- li t1, 10 +- +- # Compare against newline (0x0A) +- bne a0, t0, notnl +- +- # If newline, prepend a 0x0D, like the original function did and increment bit count +- sll a0, 10 +- ori a0, (0x0D << 1 | 0x200) +- addi t1, 10 +- +-notnl: +- # We will directly manipulate the COP0 status registers instead of using EnterCriticalSection +- # to avoid other threads/interrupts from fucking up the timing. +- # +- # The reason is two-fold: +- # - The kernel does not support reentrant calls - if something calls us while we are +- # executing kernel code and we generate a syscall, we'd nuke the current thread state. +- # +- # - SetConf calls printf while re-configuring the TCBs (thread control blocks). Executing +- # *any* interrupt at that point (which includes syscalls) will cause the interrupt +- # handler to write the current thread state to the zero address, wiping the interrupt +- # trampoline at 0x80. +- # +- # By directly manipulating this register we're opening ourselves to all kinds of race +- # conditions, but since this is just for debugging tonyhax, that's good enough for me. +- +- # Load current SR state in t4 +- mfc0 t4, $12 +- +- # Clear bits 10 and 0, the same flags WarmBoot clears +- li t0, 0xFFFFFBFE +- and t0, t4 +- mtc0 t0, $12 +- +- # Load I/O start +- lui t3, 0x1F80 +- +- # Set timer 0 target to 293 cycles (33868800Hz/115200bps-1) +- li t0, 293 +- sw t0, 0x1108(t3) +- +- # Start timer 0 in: +- # - Source clock to SysClk (33868800Hz) +- # - Free-running mode +- # - Reset on reaching target value +- # - IRQ on repeat mode (can be fired multiple times) +- # - Toggle IRQ flag (bit 10) on every IRQ +- # +- # We must not use the "reached target value" flag because that seems to be affected by some +- # kind of undocumented hardware errata. In real hardware, that flag can read zero if the +- # elapsed cycles between timer start and read and target values are both even or odd. +- # +- # Also note that although we are using the IRQ bits, interrupts are actually disabled so +- # we will busy poll the corresponding bits. +- li t0, 0x04D8 +- sw t0, 0x1104(t3) +- +- # Current timer IRQ flag status +- li t2, 0x0400 +- +-writebit: +- # Emit bit via /JOY pin of port 2. +- # We need to invert it, then put it into JOY_CTRL.13. +- # The XOR also sets the bit JOY_CTRL.2 which enables outputing the /JOY signal +- andi t0, a0, 1 +- sll t0, 13 +- xori t0, 0x2002 +- sh t0, 0x104A(t3) +- +- # Shift right current buffer +- srl a0, 1 +- +- # Decrement count while we're waiting +- addi t1, -1 +- +- # Wait until the interrupt flag toggles +-writewait: +- lw t0, 0x1104(t3) +- andi t0, 0x0400 +- beq t0, t2, writewait +- +- # Save current IRQ flag status +- move t2, t0 +- +- # If not done, keep going +- bne t1, zero, writebit +- +- # Restore coprocessor flags +- mtc0 t4, $12 +- +- jr ra +- +-.global patch_uartputc_end +-patch_uartputc_end: +diff --git a/tmp/og-tonyhax.CFG/loader/patch-vandal-hearths-2.S b/tmp/og-tonyhax.CFG/loader/patch-vandal-hearths-2.S +deleted file mode 100644 +index 67f389a..0000000 +--- a/tmp/og-tonyhax.CFG/loader/patch-vandal-hearths-2.S ++++ /dev/null +@@ -1,35 +0,0 @@ +- +-#include +- +-.text +- +-# +-# This game needs a special treatment, as it has the regular antipiracy, but also an extra check +-# by calling CdGetDiskType. If it detects the disc is a burned one, it aborts. +-# +-# Furthermore, if the BIOS is an European one, it gets stuck on a loop, calling the AP module +-# forever. +-# +-# So we will just nuke the antipiracy call. This function is supposed to return a nonzero, but +-# we do not need to patch v0 as there is a load constant into v0 right before the call. +-# +-.globl patch_vandal_start +-patch_vandal_start: +- # Load address where the call to antipiracy sits +- la t0, 0x80040C98 +- +- # Check if it matches "jal 0x80042854" +- lw t1, 0(t0) +- li t2, 0x0C010A15 +- bne t1, t2, patch_vandal_return +- +- # If it does, NOP the opcode +- sw zero, 0(t0) +- +-.globl patch_vandal_return +-patch_vandal_return: +- # This will be replaced with the real address +- j 0x12341234 +- +-.globl patch_vandal_end +-patch_vandal_end: +diff --git a/tmp/og-tonyhax.CFG/loader/patcher.c b/tmp/og-tonyhax.CFG/loader/patcher.c +deleted file mode 100644 +index 27c1c49..0000000 +--- a/tmp/og-tonyhax.CFG/loader/patcher.c ++++ /dev/null +@@ -1,147 +0,0 @@ +- +-#include "bios.h" +-#include "debugscreen.h" +-#include "str.h" +-#include "patcher.h" +- +-inline void encode_j(void * jump_location, const void * jump_dest) { +- uint32_t * words = (uint32_t *) jump_location; +- words[0] = 0x08000000 | (((uint32_t) jump_dest >> 2) & 0x3FFFFFF); +-} +- +-inline void encode_jal(void * jump_location, const void * jump_dest) { +- uint32_t * words = (uint32_t *) jump_location; +- words[0] = 0x0C000000 | (((uint32_t) jump_dest >> 2) & 0x3FFFFFF); +-} +- +-inline void encode_li(void * load_location, int regnum, uint32_t value) { +- uint32_t * words = (uint32_t *) load_location; +- +- // LUI - Load Upper Immediate +- words[0] = 0x3C000000 | (regnum << 16) | (value >> 16); +- +- // ORI - OR Immediate +- words[1] = 0x34000000 | (regnum << 21) | (regnum << 16) | (value & 0xFFFF); +-} +- +-uint8_t * install_generic_antipiracy_patch(uint8_t * install_addr) { +- // Exports defined by the patch +- extern uint8_t patch_ap_start; +- extern uint8_t patch_ap_end; +- extern uint8_t patch_ap_skip; +- extern uint8_t patch_ap_success; +- +- debug_write(" * Generic antipiracy"); +- +- // Get the handler info structure +- handler_info_t * syscall_handler = bios_get_syscall_handler(); +- +- // Get the start of the verifier function (the only one set) +- uint32_t * verifier = (uint32_t *) syscall_handler->verifier; +- +- /* +- * At opcode 20 it accesses an 4-word array which contain where to jump depending on the +- * syscall performed. We're interested in modifying the value for 1 (EnterCriticalSection) +- * so we can intercept it and defuse the antimodchip. +- */ +- uint32_t lw_op = verifier[20]; +- if ((lw_op >> 16) != 0x8C39) { +- debug_write("Aborted! Please report this!"); +- return install_addr; +- } +- +- // Extract location of cases array +- void ** cases_array = (void **) (lw_op & 0xFFFF); +- +- // Copy blob +- memcpy(install_addr, &patch_ap_start, &patch_ap_end - &patch_ap_start); +- +- /* +- * Insert the jump to the original code, which we'll use if the call was not originated from +- * an antipiracy module. +- */ +- encode_j(install_addr + (&patch_ap_skip - &patch_ap_start), cases_array[1]); +- +- /* +- * Insert the jump we'll use to exit the exception handler once we have finished patching up +- * the thread state if the call was indeed originated from an antipiracy module. +- * +- * We'll use the address of syscall(0) which behaves as a nop to exit the exception. +- */ +- encode_j(install_addr + (&patch_ap_success - &patch_ap_start), cases_array[0]); +- +- // Finally replace +- cases_array[1] = install_addr; +- +- return install_addr + (&patch_ap_end - &patch_ap_start); +-} +- +-uint8_t * install_vandal_patch(uint8_t * install_addr) { +- // Exports defined by the patch +- extern uint8_t patch_vandal_start; +- extern uint8_t patch_vandal_return; +- extern uint8_t patch_vandal_end; +- +- debug_write(" * Vandal Hearths 2 AP"); +- +- // Copy blob +- memcpy(install_addr, &patch_vandal_start, &patch_vandal_end - &patch_vandal_start); +- +- // Hook into call 16 of table B (OutdatedPadGetButtons), which is called once per frame +- void ** b0_tbl = GetB0Table(); +- +- // Insert call to real function +- encode_j(install_addr + (&patch_vandal_return - &patch_vandal_start), b0_tbl[0x16]); +- +- // Replace it now +- b0_tbl[0x16] = install_addr; +- +- // Advance installation address +- return install_addr + (&patch_vandal_end - &patch_vandal_start); +-} +- +-uint8_t * install_fpb_patch(uint8_t * install_addr) { +- // Exports defined by the patch +- extern uint8_t patch_fpb_start; +- extern uint8_t patch_fpb_end; +- +- debug_write(" * FreePSXBoot"); +- +- // Copy blob +- memcpy(install_addr, &patch_fpb_start, &patch_fpb_end - &patch_fpb_start); +- +- // Install it +- encode_jal((void *) 0x5B40, install_addr); +- +- // Advance installation address +- return install_addr + (&patch_fpb_end - &patch_fpb_start); +-} +- +-void patcher_apply(const char * boot_file) { +- // We have plenty of space at the end of table B +- uint8_t * install_addr = (uint8_t *) (GetB0Table() + 0x5E); +- +- // Install patches +- debug_write("Installing patches:"); +- +- // Install a suitable antimodchip patch +- if (strcmp(boot_file, "cdrom:\\SLUS_009.40;1") == 0) { +- install_addr = install_vandal_patch(install_addr); +- } else { +- install_addr = install_generic_antipiracy_patch(install_addr); +- } +- +- // FreePSXBoot does not work on PS2 so skip its installation +- if (bios_is_ps1()) { +- install_addr = install_fpb_patch(install_addr); +- } +-} +- +-void patcher_apply_softuart() { +- // Exports defined by the patch +- extern uint8_t patch_uartputc_start; +- extern uint8_t patch_uartputc_end; +- +- // Overwrite BIOS' std_out_putchar function +- memcpy(BIOS_A0_TABLE[0x3C], &patch_uartputc_start, &patch_uartputc_end - &patch_uartputc_start); +-} +diff --git a/tmp/og-tonyhax.CFG/loader/patcher.h b/tmp/og-tonyhax.CFG/loader/patcher.h +deleted file mode 100644 +index 5b24f53..0000000 +--- a/tmp/og-tonyhax.CFG/loader/patcher.h ++++ /dev/null +@@ -1,12 +0,0 @@ +- +-#pragma once +- +-/** +- * Install and apply suitable BIOS patches. +- */ +-void patcher_apply(const char * boot_file); +- +-/** +- * Installs the softUART patch. +- */ +-void patcher_apply_softuart(); +diff --git a/loader/secondary-ff9.ld b/loader/secondary-ff9.ld +new file mode 100644 +index 0000000..bd6af40 +--- /dev/null ++++ b/loader/secondary-ff9.ld +@@ -0,0 +1,36 @@ ++MEMORY { ++ ram(wrx) :ORIGIN = 0x801F4380, LENGTH = 0x7E00 ++} ++SECTIONS { ++ . = 0x801F4380; ++ PROVIDE(__RO_START__ = .); ++ .text : ++ { ++ *(.start) ++ *(.text .text.*) ++ } >ram ++ .rodata : ++ { ++ *(.rodata .rodata.*) ++ } >ram ++ .data : ++ { ++ *(.data .data.*) ++ } >ram ++ PROVIDE(__CRC_START__ = .); ++ .crc : ++ { ++ *(.crc .crc.*) ++ } >ram ++ PROVIDE(__BSS_START__ = .); ++ .bss : ++ { ++ *(.bss .bss.*) ++ } >ram ++ PROVIDE(__BSS_END__ = .); ++ /DISCARD/ : ++ { ++ *(*) ++ } ++} ++ENTRY (start) +diff --git a/tmp/og-tonyhax.CFG/loader/secondary.c b/loader/secondary.c +index 18a2cab..73fc4e3 100644 +--- a/tmp/og-tonyhax.CFG/loader/secondary.c ++++ b/loader/secondary.c +@@ -10,13 +10,213 @@ + #include "crc.h" + #include "debugscreen.h" + #include "gpu.h" +-#include "patcher.h" ++#include "ap-bypass.h" + #include "integrity.h" + #include "io.h" + ++//to test ROM functionality in emulation via boot CD, uncomment the following 2 lines: ++//#undef ROM ++//#define ROM ++ ++//to test XSTATION ROM functionality in emulation via boot CD, uncomment the following 4 lines: ++//#undef XSTATION ++//#define XSTATION ++//#undef ROM ++//#define ROM ++ ++//to test behavior without any APv2 bypasses enabled (useful for testing D0 AP bypass codes via save game file gameshark functionality rather then internal activate_anti_piracy() function), uncomment: ++//#define AP_BYPASS_DISABLE ++ ++uint8_t sscmd; ++uint8_t cdcontrollerver[4]; ++ ++const char * p5_localized; ++const char * region_name; ++ ++bool calibrate_laser = 0; // Only Japanese VC2 and VC3 consoles need this so it is off by default ++bool bugged_setsession = 0; // VC0 A, VC0 B, and VC1 A CDROM Controller BIOS versions all have a buggy SetSession command that requires a special work around to use ++bool enable_unlock = 1; // Disabled on VC0A and VC0B Japanese CDROM Controller BIOS versions automatically. On VC1A+ the testregion command is run and if the region is Japan it is also disabled. ++bool controller_input = 0; // When enabled, debug_write does not display the repeat messages counter. This is so we can draw a blank line and then wait for controller input using vsync in debug_write. ++bool first_rev = 0; // VC0 A and VC0 B do not need any anti-piracy patching as they are immune to additional copy protection routines because of the lack of the ReadTOC command in the CDROM Controller BIOS Firmware. ++bool installed_cheat_engine = 0; // The cheat engine is installed when parse_memcard_save_gameshark_codes() completes. Some games may go on to set explicit anti-piracy bypass GameShark codes however, so to prevent the cheat engine from being installed twice (which is wasteful) we set a flag here. ++bool did_read_mc = 0; // We need to set the GameShark codes AFTER the last bios_reintialize(). I want to call bios_reinitilize() after reading the memory card data to prevent anything screwy in booting games, so we can just parse the data later after the final bios_reinitialize since it's still in RAM. ++bool controller_input_switch = 1; // modifies controller input pulling behavior in some functions later on ++uint8_t number_of_gameshark_code_lines; // part of my basic format to store codes, this tells us how many we will activate ++uint8_t * user_start = (uint8_t *) 0x80010000; ++uint16_t mc_base = 0x102; // start of gs code data in memcard buffer ++ + // Loading address of tonyhax, provided by the secondary.ld linker script + extern uint8_t __RO_START__, __BSS_START__, __BSS_END__; + ++// for controller input functions ++void * address; // For Calculating BIOS Functions ++uint8_t j; // Joypad ++uint8_t padbuf[2][0x22]; // Joypad Buffers ++ ++#if defined ROM ++void run_shell() { ++ // runs Sony BIOS. Can access CD Player/Memory Card Manager. Can not boot any discs, even ones that normally work without the flash cart inserted in the console. This has been adapted code from the SCPH-1001 decomp: https://github.com/ogamespec/psxdev/blob/97fbb2d03e5aff4449097afd2b59690002cb2341/reverse/Main.c#L395 ++ ++ debug_write("Starting Sony BIOS..."); ++ memcpy((void*)0x80030000, (void*)0xBFC18000, 0x67FF0); // uses 0x80030000-0x80077FF0 ++ FlushCache(); ++ ((void (*)(void))0x80030000)(); ++} ++#endif ++ ++void controller_input_start() { ++ controller_input = 1; // disable the repeat counter used in debug_write until controller input is done, see debugscreen.c ++ // BIOS Function InitPAD(buf1,sz1,buf2,sz2) ++ address = (uint32_t *) GetB0Table()[0x12]; ++ ((void (*)(uint8_t*,uint32_t,uint8_t*,uint32_t)) address)(padbuf[0],0x22,padbuf[1],0x22); // BIOS InitPAD(buf1,sz1,buf2,sz2) exec ++ // BIOS Function StartPAD() ++ address = (void *) (GetB0Table()[0x13]); ++ ((void (*)(void)) address)(); // BIOS StartPad exec ++} ++ ++void controller_input_stop() { // this doubles as 'closing' the memory card functions ++ controller_input = 0; // Set debug_write back to normal (enable repeat counter) as controller input is done ++ // BIOS Function StopPAD() ++ address = (void *) (GetB0Table()[0x14]); ++ // StopPAD() as we are done using Joypad input ++ ((void (*)(void)) address)(); // BIOS StopPad exec ++} ++ ++void read_memcard() { ++ debug_write("Reading MC..."); ++ int32_t read; ++ // InitCard(pad_enable) ++ address = (uint32_t *) GetB0Table()[0x4A]; ++ ((void (*)(uint8_t*)) address)(0); ++ // BIOS FunctionStartCard() ++ address = (void *) (GetB0Table()[0x4B]); ++ ((void (*)(void)) address)(); ++ // BIOS Function _bu_init() ++ address = (void *) (GetB0Table()[0x55]); ++ ((void (*)(void)) address)(); ++ int32_t mc_fd = FileOpen("bu00:TONYHAXINTGS", FILE_READ); ++ if(mc_fd == -1) { ++ debug_write("Can not read MC"); ++ return; ++ } ++ ++ if (mc_fd > 0) { ++ read = FileRead(mc_fd, user_start, 0x2000); // read the entire file "TONYHAXINTGS" to the start of 'user RAM' (which will be cleared later before booting an executable). So 0x80010000-0x80012000 in RAM contains the contents of "TONYHAXINTGS". ++ ++ if (read == -1) { ++ debug_write("Read error %d", GetLastError()); ++ return; ++ } ++ ++ FileClose(mc_fd); ++ number_of_gameshark_code_lines = user_start[mc_base + 1]; ++ debug_write("%d code lines detected", number_of_gameshark_code_lines); ++ } ++ ++ controller_input_stop(); //restart so we can once again pull controller input ++ ++ controller_input_start(); ++ ++ uint8_t sum; ++ uint8_t prev = 0; ++ uint8_t next; ++ uint8_t checksum_in_save_file = user_start[mc_base]; ++ ++ for (int i = 0x103; i < 0x2000; i++) ++ { ++ //debug_write("%x: @ %x", &user_start[i], user_start[i]); ++ next = user_start[i]; ++ sum = prev + next; ++ sum &= 0xFF; ++ prev = sum; ++ } ++ ++ if(checksum_in_save_file == sum) { ++ debug_write("Checksum: %x Verified", sum); ++ did_read_mc = 1; // set flag to parse codes uploaded to RAM, right before clearing RAM itself and booting the game ++ } else { ++ debug_write("Checksum: %x did not match the expected checksum %x!", sum, checksum_in_save_file); ++ debug_write("Can not enable codes, check that the TONYHAXINTGS file is not corrupted"); ++ } ++} ++ ++void parse_memcard_save_gameshark_codes() { ++ /* ++ TONYHAXINTGS format: ++ ++ 0x00-0x101 = static save file data ++ ++ 0x102 = checksum generated by thigsgen ++ ++ 0x103 = number of code lines in hex ++ ++ 0x104-0x107 = gameshark code address (may or may not include code prefix i.e. D0, E0, 30, or 80 could be 0x104) ++ ++ 0x108-0x109 = gameshark code mod value ++ ++ 0x110-0x103 = 2nd gameshark code address ++ ++ 0x114-0x115 = 2nd gameshark code mod value (and then so on and so on for number of code lines in hex number) ++ */ ++ ++ uint32_t gameshark_code_address; ++ uint8_t gameshark_code_type; ++ ++ /* ++ uint32_t sum; ++ uint8_t prev = 0; ++ uint8_t next; ++ for (int i = 0; i < 0x2000; i++) ++ { ++ debug_write("%x: @ %x", &user_start[i], user_start[i]); ++ next = user_start[i]; ++ sum = prev + next; ++ sum &= 0xFF; ++ prev = sum; ++ } ++ debug_write("Memory card buffer checksum: %x", sum); ++ for (volatile int i = 0; i < 0x100000; i++); // won't be optimized out by -Os, pause ++ */ ++ ++ for(int i = 0; i < number_of_gameshark_code_lines; i++) { ++ ++ gameshark_code_type = user_start[mc_base + 5]; ++ ++ if((gameshark_code_type == 0xD0) || (gameshark_code_type == 0xD1) || (gameshark_code_type == 0xE0) || (gameshark_code_type == 0xE1) || (gameshark_code_type == 0x30)) ++ user_start[mc_base + 5] = 0x80; // we need to convert the prefix to the real address first byte of 0x80 for the cheat engine ++ ++ gameshark_code_address = user_start[mc_base + 2] + (user_start[mc_base + 3] << 8) + (user_start[mc_base + 4] << 16) + (user_start[mc_base + 5] << 24); ++ //debug_write("GS Code Addr: %x", gameshark_code_address); ++ ++ if(gameshark_code_type == 0x80) { ++ uint16_t gameshark_code_mod_val = user_start[mc_base + 6] + (user_start[mc_base + 7] << 8); ++ //debug_write("GS Code Mod Val: %x", gameshark_code_mod_val); ++ add_80_code(gameshark_code_address, gameshark_code_mod_val); ++ } else if(gameshark_code_type == 0xD0) { ++ uint16_t gameshark_code_mod_val = user_start[mc_base + 6] + (user_start[mc_base + 7] << 8); ++ //debug_write("GS Code Mod Val: %x", gameshark_code_mod_val); ++ add_D0_code(gameshark_code_address, gameshark_code_mod_val); ++ } else if(gameshark_code_type == 0xD1) { ++ uint16_t gameshark_code_mod_val = user_start[mc_base + 6] + (user_start[mc_base + 7] << 8); ++ //debug_write("GS Code Mod Val: %x", gameshark_code_mod_val); ++ add_D1_code(gameshark_code_address, gameshark_code_mod_val); ++ } else if(gameshark_code_type == 0x30) { ++ uint8_t gameshark_code_mod_val = user_start[mc_base + 6]; ++ //debug_write("GS Code Mod Val: %x", gameshark_code_mod_val); ++ add_30_code(gameshark_code_address, gameshark_code_mod_val); ++ } else if(gameshark_code_type == 0xE0) { ++ uint8_t gameshark_code_mod_val = user_start[mc_base + 6]; ++ //debug_write("GS Code Mod Val: %x", gameshark_code_mod_val); ++ add_E0_code(gameshark_code_address, gameshark_code_mod_val); ++ } else if(gameshark_code_type == 0xE1) { ++ uint8_t gameshark_code_mod_val = user_start[mc_base + 6]; ++ //debug_write("GS Code Mod Val: %x", gameshark_code_mod_val); ++ add_E1_code(gameshark_code_address, gameshark_code_mod_val); ++ } ++ mc_base = (mc_base + 6); // advance 6 bytes from current val ++ } ++} ++ + void log_bios_version() { + /* + * "System ROM Version 4.5 05/25/00 A" +@@ -31,7 +231,7 @@ void log_bios_version() { + } + + debug_write("Console: %s", bios_is_ps1() ? "PS1": "PS2"); +- debug_write("BIOS: v%s", version); ++ debug_write("System BIOS: %s", version); + } + + bool backdoor_cmd(uint_fast8_t cmd, const char * string) { +@@ -65,43 +265,6 @@ bool backdoor_cmd(uint_fast8_t cmd, const char * string) { + } + + bool unlock_drive() { +- uint8_t cd_reply[16]; +- +- // Run "GetRegion" test +- uint8_t test = CD_TEST_REGION; +- cd_command(CD_CMD_TEST, &test, 1); +- +- // Should succeed with 3 +- if (cd_wait_int() != 3) { +- debug_write("Region read failed"); +- return false; +- } +- +- // Read actual region text and null terminate it +- int len = cd_read_reply(cd_reply); +- cd_reply[len] = 0; +- +- // Compare which is the fifth string we have to send to the backdoor +- const char * region_name; +- const char * p5_localized; +- if (strcmp((char *) cd_reply, "for Europe") == 0) { +- region_name = "European"; +- p5_localized = "(Europe)"; +- } else if (strcmp((char *) cd_reply, "for U/C") == 0) { +- region_name = "American"; +- p5_localized = "of America"; +- } else if (strcmp((char *) cd_reply, "for NETEU") == 0) { +- region_name = "NetYaroze (EU)"; +- p5_localized = "World wide"; +- } else if (strcmp((char *) cd_reply, "for NETNA") == 0) { +- region_name = "NetYaroze (US)"; +- p5_localized = "World wide"; +- } else { +- // +4 to skip past "for " +- debug_write("Unsupported region: %s", (char *) (cd_reply + 4)); +- return false; +- } +- + debug_write("Drive region: %s", region_name); + + // Note the kernel's implementation of strlen returns 0 for nulls. +@@ -121,11 +284,46 @@ bool unlock_drive() { + return true; + } + ++#if !defined TOCPERFECT + void wait_lid_status(bool open) { + uint8_t cd_reply[16]; ++ ++ controller_input_start(); + + uint8_t expected = open ? 0x10 : 0x00; + do { ++ ++ j = padbuf[0][3] ^ 0xFF; ++ debug_write(" "); // Vblank wait for controller input ++ ++ if(controller_input_switch) ++ { ++#if defined ROM // this is more optimized for variable button presses then otherwise if we didn't test both statements in an else if ++ if(j == 0x40) { // X button ++ controller_input_stop(); ++ run_shell(); // launch Sony BIOS ++ } else if(j == 0x20) { // Circle button ++ controller_input_switch = 0; // stop pulling for circle button input once we get it, as unlike the run_shell() function (which exits the program entirely) we still have to wait here until the user closes the console CD drive lid ++ read_memcard(); ++ } ++#else // booting the shell is unnecessary for every other boot method besides the ROM so we don't include it ++ if(j == 0x20) { // Circle button ++ controller_input_switch = 0; // stop pulling for circle button input once we get it, as unlike the run_shell() function (which exits the program entirely) we still have to wait here until the user closes the console CD drive lid ++ read_memcard(); ++ } ++#endif ++ ++#if defined ROM ++ } else { // still allow booting Sony BIOS after reading MC ++ if(j == 0x40) { // X button ++ controller_input_stop(); ++ run_shell(); // launch Sony BIOS ++ } ++ } ++#else ++ } ++#endif ++ + // Issue Getstat command + // We cannot issue the BIOS CD commands yet because we haven't called CdInit + cd_command(CD_CMD_GETSTAT, NULL, 0); +@@ -137,20 +335,164 @@ void wait_lid_status(bool open) { + cd_read_reply(cd_reply); + + } while ((cd_reply[0] & 0x10) != expected); ++ ++ controller_input_stop(); + } + +-void try_boot_cd() { +- int32_t read; ++bool is_lid_open() { ++ uint8_t cd_reply[16]; + +- debug_write("Swap CD now"); +- wait_lid_status(true); +- wait_lid_status(false); ++ // Issue Getstat command ++ // We cannot issue the BIOS CD commands yet because we haven't called CdInit ++ cd_command(CD_CMD_GETSTAT, NULL, 0); ++ ++ // Always returns 3, no need to check ++ cd_wait_int(); ++ ++ // Always returns one, no need to check either ++ cd_read_reply(cd_reply); ++ ++ if(cd_reply[0]==0x10) { ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++bool licensed_drive() { ++ uint8_t getid_response[9]; ++ unsigned char gid; + ++ while(1) { ++ cd_command(CD_CMD_GETID,0,0); ++ gid = cd_wait_int(); ++ if(gid!=5) ++ break; ++ } ++ ++ cd_wait_int(); ++ cd_read_reply(getid_response); ++ ++ if(getid_response[0]==0x02 && getid_response[1]==0x00 && getid_response[2]==0x20 && getid_response[3]==0x00) { ++ return true; ++ } else { ++ return false; ++ } ++} ++#endif // TOCPERFECT ++ ++void re_cd_init() { ++ debug_write("Reinitializing kernel"); ++ bios_reinitialize(); ++ bios_inject_disc_error(); ++ debug_write("Stopping Motor"); // Reset one last time to avoid potential lockups (here be dragons) ++ cd_command(CD_CMD_STOP, NULL, 0); cd_wait_int(); cd_wait_int(); ++ + debug_write("Initializing CD"); + if (!CdInit()) { + debug_write("Init failed"); + return; + } ++} ++ ++void try_boot_cd() { ++ int32_t read; ++#if defined FREEPSXBOOT ++ debug_write("Remove the FreePSXBoot memory card now from your console"); ++#elif defined ROM ++ debug_write("With the CD drive open, press X to boot the Sony BIOS or"); ++ debug_write("Press O to enable GS codes"); ++#endif ++ ++#if !defined XSTATION ++ uint8_t cbuf[4]; // CD Command Buffer ++ ++#if !defined TOCPERFECT ++ if(enable_unlock) { ++ #if !defined ROM ++ debug_write("With the CD drive open, press O to enable GS codes"); ++ #endif ++ debug_write("Put in a backup or import disc, then close the drive lid"); ++ wait_lid_status(true); // doesn't wait during the ROM method, unsure why but it is what we want as it allows us to auto-boot with the ROM boot method ++ wait_lid_status(false); ++ } else { ++ if(is_lid_open() || !licensed_drive()) { // If lid is open drive is not licensed, and if lid is closed we check if it is licensed (if it is not licensed but not open then the drive is closed and the user can open it and license it) ++ debug_write("Put in a real NTSC-J PSX game disc, then block the lid sensor"); ++ wait_lid_status(true); ++ wait_lid_status(false); // Blocking lid sensor = 'closing lid' ++ ++ debug_write("Initializing CD"); // Drive will be in licensed state after this is successful ++ if (!CdInit()) { ++ debug_write("Init failed"); ++ debug_write("Try unblocking then blocking the lid sensor again"); ++ return; ++ } ++ } // Drive is licensed and the lid is 'closed' at this point ++ debug_write("Drive is licensed"); ++ ++ debug_write("Stopping motor"); ++ cd_command(CD_CMD_STOP,0,0); cd_wait_int(); cd_wait_int(); ++ ++ debug_write("Press O to enable GS codes"); ++ controller_input_start(); ++ ++ debug_write("Keep the lid sensor blocked until turning off the console"); ++ debug_write("Remove the real NTSC-J PSX game disc"); ++ debug_write("Put in a backup/import disc, then press X"); // Thanks MottZilla! ++ ++ while(1) { ++ j = padbuf[0][3] ^ 0xFF; ++ ++ if(controller_input_switch) { ++ if(j == 0x40) { ++ break; // X button boots disc ++ } else if(j == 0x20) { // Circle button enables codes ++ controller_input_switch = 0; // stop pulling for circle button input once we get it, as unlike when the X button is pressed (which breaks this loop) we still have to wait here until the user closes the console CD drive lid ++ read_memcard(); // this allows Japanese console users to enable user supplied GameShark codes without having to unblock the lid sensor, resetting authentication which would just be more unnecessary steps. ++ } ++ } else { ++ if(j == 0x40) ++ break; // X button boots disc ++ } ++ debug_write(" "); // Vblank wait for controller input ++ } ++ controller_input_stop(); ++ } ++#endif // TOCPERFECT ++ ++ if(!enable_unlock) { ++ if(bugged_setsession) { ++ debug_write("Sending SetSessionSuperUltraCommandSmash v2, please wait"); // always works on real hardware, DuckStation can get stuck here rarely though since it is not that accurate when it comes to emulating the early VC0A/VC0B/VC1A CDROM behavior ++ sscmd = 2; cd_command(CD_CMD_SET_SESSION,(unsigned char *)&sscmd,1); cd_wait_int(); cd_wait_int(); // There is a 3rd response we are ignoring by sending SetSession 1 next ASAP after SetSession 2. ++ sscmd = 1; cd_command(CD_CMD_SET_SESSION,(unsigned char *)&sscmd,1); cd_wait_int(); cd_wait_int(); ++ } else { ++ debug_write("Sending SetSession 1"); ++ sscmd = 1; cd_command(CD_CMD_SET_SESSION,(unsigned char *)&sscmd,1); cd_wait_int(); cd_wait_int(); ++ } ++ ++ if(calibrate_laser) { // VC2 and VC3s do auto Bias/Gain calibration when reading a newly inserted real NTSC-J PS1 disc. A swapped in CD-R or just a different disc in general needs this to be updated ++ debug_write("Calibrating laser"); ++ cbuf[0] = 0x50; cbuf[1] = 0x38; cbuf[2] = 0x15; cbuf[3] = 0x0A; // ModeCompensateTrackingAutoGain ++ cd_command(CD_CMD_TEST,&cbuf[0],4); ++ cd_wait_int(); ++ } ++ ++ /* ++ We have to re-initilize the BIOS, stop, and init in that order to prevent the process from possibly freezing at this point on Japanese consoles. ++ ++ The first reason this is required is because the SetSessionSuperUltraCommandSmash screws up interrupts since we are sending the 2nd SetSession command before the possible 3rd interrupt (which is a second INT5 response sent if session 2 does not actually exist). ++ ++ The second reason is because of how we are using the BIOS controller functions, to go back to a clean state a bios re-intialization also accomplishes that. ++ */ ++ ++ re_cd_init(); ++ } ++#else // XSTATION DEFINED ++ debug_write("Open and then close the CD drive lid"); ++ wait_lid_status(true); // doesn't wait during the ROM method, unsure why but it is what we want as it allows us to auto-boot with the ROM boot method ++ wait_lid_status(false); ++ re_cd_init(); ++#endif // XSTATION + + /* + * Use the space the BIOS has allocated for reading CD sectors. +@@ -163,10 +505,17 @@ void try_boot_cd() { + uint8_t * data_buffer = (uint8_t *) (bios_is_ps1() ? 0xA000B070 : 0xA000A8D0); + + debug_write("Checking game region"); +- if (CdReadSector(1, 4, data_buffer) != 1) { ++#if defined TOCPERFECT ++ if (CdReadSector(1, 12, data_buffer) != 1) { // Real license data sector is copied to sector 12 by PS1 DemoSwap Patcher before it writes Japanese license data to sector 4 ++ debug_write("Failed to read sector"); ++ return; ++ } ++#else ++ if (CdReadSector(1, 4, data_buffer) != 1) { + debug_write("Failed to read sector"); + return; + } ++#endif + + const char * game_region; + bool game_is_pal = false; +@@ -203,9 +552,15 @@ void try_boot_cd() { + const char * bootfile = "cdrom:PSX.EXE;1"; + + char bootfilebuf[32]; +- debug_write("Loading SYSTEM.CNF"); + ++#if defined TOCPERFECT ++ debug_write("Loading SYSTEM.CN2"); ++ int32_t cnf_fd = FileOpen("cdrom:SYSTEM.CN2;1", FILE_READ); ++#else ++ debug_write("Loading SYSTEM.CNF"); + int32_t cnf_fd = FileOpen("cdrom:SYSTEM.CNF;1", FILE_READ); ++#endif ++ + if (cnf_fd > 0) { + read = FileRead(cnf_fd, data_buffer, 2048); + FileClose(cnf_fd); +@@ -241,6 +596,8 @@ void try_boot_cd() { + debug_write(" * %s = %x", "STACK", stacktop); + debug_write(" * %s = %s", "BOOT", bootfile); + ++ re_cd_init(); // Reset one last time to avoid potential lockups (here be dragons) ++ + /* + * SetConf is run by BIOS with interrupts disabled. + * +@@ -248,13 +605,18 @@ void try_boot_cd() { + * the interrupt handler will store the current thread state in the zero address, wiping + * vital data, like the interrupt trampoline at 0x80. + */ ++ + debug_write("Configuring kernel"); + EnterCriticalSection(); + SetConf(event, tcb, stacktop); +- ExitCriticalSection(); ++ ExitCriticalSection(); // unnecessary because SetConf() does this? Waiting on verdict from Socram8888: https://github.com/socram8888/tonyhax/issues/149 ++ ++ bzero((void*)0xD000, 0xF78); // 0xD000-0xDF78 are to be zeroed out to ensure correct parsing by the cheat engine (used for gs codes loaded via memcard AND for APv2 bypasses). 0xDF80 is used to contain BIOS patches so we stop 2 bytes previous to it. Every BIOS besides v3.0 has enough garbage in this 'reserved' area to break the cheat engine if we don't do this. ++ ++ if(did_read_mc) // before clearing RAM (which contains our mem card buffer if applicable) but after last bios_reinitalize/setconf() ++ parse_memcard_save_gameshark_codes(); + + debug_write("Clearing RAM"); +- uint8_t * user_start = (uint8_t *) 0x80010000; + bzero(user_start, &__RO_START__ - user_start); + + debug_write("Reading executable header"); +@@ -271,6 +633,37 @@ void try_boot_cd() { + return; + } + ++ /* ++ uint32_t sum; ++ uint8_t prev = 0; ++ uint8_t next; ++ uint8_t * ce = (uint8_t *) 0xC000; ++ ++ for (int i = 0; i < 0x100; i++) ++ { ++ //debug_write("%x: @ %x", &ce[i], ce[i]); ++ next = ce[i]; ++ sum = prev + next; ++ sum &= 0xFF; ++ prev = sum; ++ } ++ debug_write("Cheat engine checksum: %x", sum); ++ for (volatile int i = 0; i < 0x100000; i++); // won't be optimized out by -Os, pause ++ ++ uint8_t * codes = (uint8_t *) 0xD000; ++ ++ for (int i = 0; i < 0x1FFB; i++) ++ { ++ //debug_write("%x: @ %x", &codes[i], codes[i]); ++ next = codes[i]; ++ sum = prev + next; ++ sum &= 0xFF; ++ prev = sum; ++ } ++ debug_write("Cheat engine enabled codes Checksum: %x", sum); ++ for (volatile int i = 0; i < 0x100000; i++); // won't be optimized out by -Os, pause ++ */ ++ + exe_header_t * exe_header = (exe_header_t *) (data_buffer + 0x10); + + // If the file overlaps tonyhax, we will use the unstable LoadAndExecute function +@@ -286,6 +679,16 @@ void try_boot_cd() { + // Restore original error handler + bios_restore_disc_error(); + ++ #if !defined XSTATION ++ #if !defined AP_BYPASS_DISABLE ++ if(!first_rev) ++ activate_anti_anti_piracy(bootfile, (int32_t) exe_header->load_addr); ++ #endif ++ #endif ++ ++ if((did_read_mc) && (!cheat_engine_installed)) ++ install_cheat_engine(); ++ + LoadAndExecute(bootfile, exe_header->initial_sp_base, exe_header->initial_sp_offset); + return; + } +@@ -299,8 +702,6 @@ void try_boot_cd() { + + FileClose(exe_fd); + +- patcher_apply(bootfile); +- + if (game_is_pal != gpu_is_pal()) { + debug_write("Switching video mode"); + debug_switch_standard(game_is_pal); +@@ -311,6 +712,16 @@ void try_boot_cd() { + // Restore original error handler + bios_restore_disc_error(); + ++#if !defined XSTATION ++#if !defined AP_BYPASS_DISABLE ++ if(!first_rev) ++ activate_anti_anti_piracy(bootfile, (int32_t) exe_header->load_addr); ++#endif ++#endif ++ ++ if((did_read_mc) && (!cheat_engine_installed)) ++ install_cheat_engine(); ++ + // Games from WarmBoot start with interrupts disabled + EnterCriticalSection(); + +@@ -321,6 +732,7 @@ void try_boot_cd() { + } + + void main() { ++ + // Undo all possible fuckeries during exploiting + bios_reinitialize(); + +@@ -337,24 +749,76 @@ void main() { + + bios_inject_disc_error(); + log_bios_version(); ++ ++ debug_write("Resetting Drive"); ++ cd_drive_init(); ++ ++ sscmd = 0x20; cd_command(CD_CMD_TEST,(unsigned char *)&sscmd,1); cd_wait_int(); ++ cd_read_reply(cdcontrollerver); // Test Command $19,$20 gets the CDROM BIOS ++ debug_write("CD BIOS: %x", *(uint32_t*) cdcontrollerver); ++ if(cdcontrollerver[0] == 0x94) { ++ bugged_setsession = 1; ++ enable_unlock = 0; // VC0 A and VC0 B are both from 1994 and don't support the getregion command to figure out if it is unlockable or not. ++ first_rev = 1; ++ } ++ else if(cdcontrollerver[1] == 0x05 && cdcontrollerver[2] == 0x16 && cdcontrollerver[0] == 0x95 && cdcontrollerver[3] == 0xC1) { ++ bugged_setsession = 1; // NOTE I don't think this will ever be triggered but just in case. Earliest SCPH-3000s and late SCPH-1000s are VC0B and later SCPH-3000s are VC1B. Only unlockable systems have VC1A it seems. ++ } ++ else if((cdcontrollerver[3] == 0xC2) || (cdcontrollerver[3] == 0xC3)) { ++ calibrate_laser = 1; ++ } ++ ++#if !defined XSTATION ++ if(enable_unlock) { ++ uint8_t cd_reply[16]; ++ // Run "GetRegion" test ++ uint8_t test = CD_TEST_REGION; ++ cd_command(CD_CMD_TEST, &test, 1); ++ ++ // Should succeed with 3 ++ if (cd_wait_int() != 3) { ++ debug_write("Region read failed"); ++ return; ++ } + +- debug_write("Resetting drive"); +- if (!cd_drive_init()) { +- debug_write("Reset failed"); +- return; +- } ++ // Read actual region text and null terminate it ++ int len = cd_read_reply(cd_reply); ++ cd_reply[len] = 0; ++ ++ // Compare which is the fifth string we have to send to the backdoor ++ if (strcmp((char *) cd_reply, "for Europe") == 0) { ++ region_name = "European"; ++ p5_localized = "(Europe)"; ++ } else if (strcmp((char *) cd_reply, "for U/C") == 0) { ++ region_name = "American"; ++ p5_localized = "of America"; ++ } else if (strcmp((char *) cd_reply, "for NETEU") == 0) { ++ region_name = "NetYaroze (EU)"; ++ p5_localized = "World wide"; ++ } else if (strcmp((char *) cd_reply, "for NETNA") == 0) { ++ region_name = "NetYaroze (US)"; ++ p5_localized = "World wide"; ++ } else if (strcmp((char *) cd_reply, "for Japan") == 0) { ++ enable_unlock = 0; ++ } else { ++ // +4 to skip past "for " ++ debug_write("Unsupported region: %s", (char *) (cd_reply + 4)); ++ return; ++ } + +- debug_write("Unlocking drive"); +- if (!unlock_drive()) { +- return; ++ if(enable_unlock) { // Check again, this could be false now ++ #if defined TOCPERFECT // Get TOC via reset + unlock instead of unlock + opening/closing the drive lid for auto loading in TOCPerfect, thanks MottZilla! ++ debug_write("Resetting drive"); ++ cd_drive_reset(); ++ #endif ++ debug_write("Unlocking drive"); ++ if (!unlock_drive()) ++ return; ++ } + } ++#endif // XSTATION + + while (1) { +-#if SOFTUART_PATCH +- patcher_apply_softuart(); +- std_out_puts("SoftUART ready\n"); +-#endif +- + try_boot_cd(); + + debug_write("Reinitializing kernel"); +diff --git a/tmp/og-tonyhax.CFG/loader/secondary.ld b/loader/secondary.ld +index 7dc880a..dfd4eaa 100644 +--- a/tmp/og-tonyhax.CFG/loader/secondary.ld ++++ b/loader/secondary.ld +@@ -1,8 +1,8 @@ + MEMORY { +- ram(wrx) :ORIGIN = 0x801FA100, LENGTH = 0x3F00 ++ ram(wrx) :ORIGIN = 0x801F6200, LENGTH = 0x7E00 + } + SECTIONS { +- . = 0x801FA100; ++ . = 0x801F6200; + PROVIDE(__RO_START__ = .); + .text : + { +diff --git a/loader/tonyhax-tpl-ff9.mcs b/loader/tonyhax-tpl-ff9.mcs +new file mode 100644 +index 0000000..4001e74 +Binary files /dev/null and b/loader/tonyhax-tpl-ff9.mcs differ +diff --git a/loader/tonyhax-tpl-old.mcs b/loader/tonyhax-tpl-old.mcs +new file mode 100644 +index 0000000..50c3fa9 +Binary files /dev/null and b/loader/tonyhax-tpl-old.mcs differ +diff --git a/tmp/og-tonyhax.CFG/loader/tonyhax-tpl.mcs b/loader/tonyhax-tpl.mcs +index 50c3fa9..0aab208 100644 +Binary files a/tmp/og-tonyhax.CFG/loader/tonyhax-tpl.mcs and b/loader/tonyhax-tpl.mcs differ diff --git a/entrypoints/Makefile b/entrypoints/Makefile index 512f18b..adff2cc 100644 --- a/entrypoints/Makefile +++ b/entrypoints/Makefile @@ -4,6 +4,7 @@ # Seek value = offset to start of entry loader, which will be updated on code changes to entry.S include ../variables.mk +include ../variables-shared.mk all: $(ENTRY_MCS) $(ENTRY_RAW) diff --git a/freepsxboot-exploit.md b/freepsxboot-exploit.md index a1f9e12..e848ba7 100644 --- a/freepsxboot-exploit.md +++ b/freepsxboot-exploit.md @@ -1,23 +1,34 @@ # FreePSXBoot Exploit -The [FreePSXBoot Exploit](https://github.com/bradl-in/freepsxboot) can start the Tonyhax International loader from any PS1 console's boot menu/BIOS. +The [FreePSXBoot Exploit](https://github.com/bradl-in/freepsxboot) enables you to boot the Tonyhax International loader by selecting the Memory Card Manager option in the stock Sony BIOS while a special memory card is present in the console. -Memory card files are found in the `freepsxboot` directory in each Tonyhax International release, for **all PS1 BIOS versions**. These memory card files must be 'restored' (a.k.a. written raw) to a PSX memory card. One such way to do this is to use [Memory Card Annihilator v2.0](https://www.ps2-home.com/forum/viewtopic.php?t=116) with a modded PS2 console and USB flash drive containing the memory card file. Please note that at this time Memory Card Annihilator v2.0 does not work on the SCPH-10000 or SCPH-18000 due to not having an expansion bay (which is not accounted for by the software). Anyways for all SCPH-30000 and newer PS2 consoles here are the steps below to flash your PS1 memory card with the Memory Card Annihilator homebrew software: +## Requirements -Now you can turn on your PSX console without a disc in it, and then select the `Memory Card` option in the PS1's startup menu. This will start the Tonyhax international loader after a brief delay. **Before starting any backup or import disc in the loader YOU MUST REMOVE THE FREEPSXBOOT MEMORY CARD to ensure successful booting of your backup or import disc. THIS APPLIES TO BOTH SLOT 1 AND SLOT 2 FREEPSXBOOT CARDS.** +* Any PSX console. PS2 consoles _are not_ vulnerable to the FreePSXBoot exploit. -If you want to remove the FreePSXBoot exploit from your memory card, you can format it successfully using [MCTool](https://www.psx-place.com/threads/mctool-tonyhax-freepsxboot-installer.36569/). Most other programs are unable to format or read a FreePSXBoot exploited memory card. +* A PS1 memory card that your not using for any other save files. The FreePSXBoot exploit takes up the entire PS1 memory card disallowing it from being used for any normal functions besides booting Tonyhax International when selecting the Memory Card Manager in the stock Sony BIOS. -## Requirements +* All the required hardware for either the [Modded PS2 Method](#modded-ps2-method), or the [PS3 Memory Card USB Adaptor Method](#ps3-memory-card-usb-adapter-method) of writing the FreePSXBoot file to the PSX memory card. + +## Usage + +You need to copy the FreePSXBoot memory card file for you console (found in the `freepsxboot` directory in each Tonyhax International release). The memory card file then must be written to a PSX memory card. + +There are 2 methods that I personally use to copy a FreePSXBoot exploit file to a PS1 memory card, they are the [Modded PS2 Method](#modded-ps2-method), and the [PS3 Memory Card USB Adaptor Method](#ps3-memory-card-usb-adapter-method). There are other methods that I haven't tried though they would also work. You just need to get the correct file on the PS1 memory card. + +Once you write the correct file to the PSX memory card, insert it into slot 1 or slot 2 of the console (depending on which file you wrote to it). Turn on your PSX console **with the CD drive lid open**, and then select the `Memory Card` option in the PSX BIOS. This will start the Tonyhax international loader after a brief delay. **Before starting any backup or import disc in the loader YOU MUST REMOVE THE FREEPSXBOOT MEMORY CARD to ensure successful booting of your backup or import disc. THIS APPLIES TO BOTH SLOT 1 AND SLOT 2 FREEPSXBOOT CARDS.** -* PS2 console that can run [wLaunchELF/uLaunchELF](https://www.psx-place.com/resources/wlaunchelf.713/) and [Memory Card Annihilator v2.0](https://www.ps2-home.com/forum/viewtopic.php?t=116). You need to soft-mod with [FreeHDBoot](https://www.ps2-home.com/forum/viewtopic.php?t=5208), [FreeDVDBoot](https://github.com/CTurt/FreeDVDBoot) or [FreeMCBoot](https://www.ps2-home.com/forum/viewtopic.php?t=1248) to be able to use these programs on your PS2 console. -* Any PS1 console. -* An authentic PS1 memory card you are willing to dedicate to the FreePSXBoot exploit. -* A fat 32 formatted USB flash drive that your PS2 console can read (**not all USB flash drives seem to work**). +![scph-101 memory card manager selected](images/scph-101-memory-card-manager-selected.png) -## Flashing The PS1 Memory Card Image To A PS1 Memory Card +![scph-101 freepsxboot exploit exploiting](images/scph-101-freepsxboot-exploit-exploiting.png) -Copy the correct memory card file for your PSX console's BIOS version from the `freepsxboot` directory found in Tonyhax international releases downloadable above to a FAT32 formatted USB flash drive that your PS2 console can read. +![scph-101 freepsxboot loader](images/scph-101-freepsxboot-exploit-loader.png) + +If you want to remove the FreePSXBoot exploit from your memory card, you can format it successfully using [MCTool](https://www.psx-place.com/threads/mctool-tonyhax-freepsxboot-installer.36569/) or [MemcardRex](https://github.com/ShendoXT/memcardrex). Be aware that most other programs are unable to format or read a PSX memory card with the FreePSXBoot exploit on it. + +![memcardrex format freepsboot memory card](images/memcardrex-format-freepsxboot-mc.png) + +## Finding The Correct FreePSXBoot Exploit File Console models and the BIOS versions they contain are listed below: @@ -53,15 +64,91 @@ Console models and the BIOS versions they contain are listed below: * SCPH-102 - BIOS-4.4-2000-03-24-E or BIOS-4.5-2000-05-25-E * SCPH-103 - BIOS-4.5-2000-05-25-A -If you have a PSX console that can have multiple different BIOS versions, you may have to try each different memory card file one by one until you figure out what BIOS version you need for your PSX console. +If you have a PSX console that can have multiple different BIOS versions, you have to try each different memory card file one by one until you figure out what BIOS version you need for your PSX console. + +## Modded PS2 Method + +This installation method requires: + +* A modded PS2 that is a SCPH-18000 or newer model. This is because the early SCPH-10000 and SCPH-150000 models are incapable of running [Memory Card Annihilator](https://www.psx-place.com/threads/memory-card-annihilator-v2-0a-a-new-version-after-more-than-11-years.36277/). + +* A FAT32 formatted USB flash drive that your PS2 console can read, not that not all USB flash drives seem to work with PS2 consoles (due to iffy USB 1.1 support found in some newer USB flash drives). You may need to do a bit of trial and error testing to find a USB flash drive that works. + +Copy the [correct FreePSXBoot exploit file](#finding-the-correct-freepsxboot-exploit-file) for your console to the USB flash drive. + +Download [Memory Card Annihilator](https://www.psx-place.com/threads/memory-card-annihilator-v2-0a-a-new-version-after-more-than-11-years.36277/) and extract it. Copy **both** the `mca_v20a-2022-06-16/MCA/mca_v20a.elf` and the `mca_v20a-2022-06-16/MCA/lang.lng` files to the USB flash drive. + +![copy freepsxboot files to usb drive](images/copy-freepsxboot-files-to-usb-drive.png) + +![eject freepsxboot usb drive](images/eject-freepsxboot-usb-drive.png) + +Eject the USB drive and insert it and the target PSX memory card into the PS2 console. Start the wLaunchElf program. + +![SCPH 30001 wlaunchelf main menu](images/scph-30001-wlaunchelf-main-menu.png) + +![wlaunchelf](images/wlaunchelf.png) + +Navigate to the "mass" device and launch the Memory Card Annihilator.elf file you previously copied to the USB flash drive by pressing `O`. + +![wlaunchelf select mass](images/wlaunchelf-select-mass.png) + +![wlaunchelf select mca elf](images/wlaunchelf-select-mca-elf.png) + +Select the PS1 memory card in the menu and then select restore. In the file picker navigate to the memory card file you copied to the USB flash drive previously. Wait for the restore to complete and press X. Remove your memory card and put it into either Slot 1 or Slot 2 of your PS1 console depending on what memory card image you use. + +![mca select mc](images/mca-select-mc.png) + +![mca select restore mc](images/mca-select-restore-mc.png) + +![mca select mass](images/mca-select-mass.png) + +![mca select freepsxboot file](images/mca-select-freepsxboot-file.png) + +![mca confirm restore](images/mca-confirm-restore.png) + +![mca restoring mc](images/mca-restoring-mc.png) + +![mca restored mc](images/mca-restored-mc.png) + +Keep in mind that after you restore the memory card it will crash Memory Card Annihilator due to the FreePSXBoot exploit being present on the memory card. You should remove the PSX memory card you just restored, turn off your PS2, and then turn it back on if you want to use your PS2 console for something else. Don't keep the restored card in your PS2 console or it will cause problems with the console booting and maybe others, you must [format that card](#usage) before you can use it in any other capacity with your PS2 console. + +## PS3 Memory Card USB Adapter Method + +This installation method requires: + +* A Windows PC. +* A PS3 Memory Card USB Adapter. + +You can use a PS3 Memory Card adapter in combination with the [MemcardRex](https://github.com/ShendoXT/memcardrex) and a Windows PC to copy the freepsxboot exploit memory card image to a PS1 memory card. + +Get the latest version of [MemcardRex](https://github.com/ShendoXT/memcardrex) and follow the instructions to install the driver for the PS3 Memory card adapter. Those instructions are found in the previous link, as well as copied verbatim below: + +`PS3 Memory Card Adaptor +The PS3 Memory Card Adaptor is an official Sony USB adapter that allows reading and writing PS1 Memory Cards on a PlayStation 3. +To use it on a Windows PC, a custom USB driver needs to be installed.` + +`This USB driver can be easily created and installed using [Zadig](https://zadig.akeo.ie/) by following these steps:` + +`Plug the PS3 Memory Card Adaptor into a free USB port and start Zadig. +Zadig should display the PS3 MCA as an "Unknown Device". Verify that the USB ID matches: 054C 02EA` + +`Click the Edit checkbox and name the device "PS3 Memory Card Adaptor" +Ensure that "WinUSB" is selected from the list of Driver options and click the Install Driver button.` + +`After about 30 seconds Zadig should show a message that the driver was installed successfully.` + +`With the USB driver installed and the PS3 Memory Card Adaptor plugged in, you should now be able to read, write and format PS1 Memory Cards.` + +With everything ready, start up memcardrex. **Before you access the memory card in MemcardRex**, you need to disable one setting enabled by default. This setting is named `Try to fix corrupted Memory Cards`. Uncheck it, click `Apply`, then click `OK`. + +![memcardrex preferences](images/memcardrex-preferences.png) + +![memcard uncheck corrupted fix](images/memcardrex-uncheck-corrupted-fix.png) + +Drag and Drop the [correct FreePSXBoot exploit file](#finding-the-correct-freepsxboot-exploit-file) for your console into the MemcardRex window. -## Restoring the PS1 Memory Card +![memcard import fpsxboot file](images/memcardrex-import-fpsxboot-file.png) -After the correct memory card file is copied to the USB flash drive that your PS2 can read: +Write the FreePSXBoot file to the memory card. -* Download the [Memory Card Annihilator v2.0](https://www.ps2-home.com/forum/viewtopic.php?t=116) and extract it's .elf file. -* Copy the Memory Card Annihilator v2 .elf file to a FAT32 formatted USB flash drive that your PS2 console can read. -* Insert the PSX memory card and USB flash drive with the PS2 console off. Boot your modded PS2 (FreeHDBoot or FreeMCBoot, or something like that is required) and start the uLaunchElf program. -* Navigate to the "mass" device and launch the Memory Card Annihilator v2 .elf file you previosly copied to the USB flash drive. -* Select your PS1 memory card in the menu and then select restore. In the file picker navigate to the memory card file you copied to the USB flash drive previously. -* Wait for the restore to complete and press X. Remove your memory card and put it into either Slot 1 or Slot 2 of your PS1 console depending on what memory card image you use. +![memcard write fpsxboot file](images/memcardrex-write-fpsxboot-file.png) \ No newline at end of file diff --git a/freepsxboot/Makefile b/freepsxboot/Makefile index cdce600..2375b46 100644 --- a/freepsxboot/Makefile +++ b/freepsxboot/Makefile @@ -3,6 +3,7 @@ # NOTE: DO NOT EVER USE -fastload option it not only unreliably triggers the loading screen on different consoles, it screws up reading from memory cards after exploit! include ../variables.mk +include ../variables-shared.mk .PHONY: clean FreePSXBoot/builder/builder diff --git a/gshax/Makefile b/gshax/Makefile index b583ba5..786acac 100644 --- a/gshax/Makefile +++ b/gshax/Makefile @@ -1,19 +1,19 @@ .PHONY: clean -all: gshax-tool wipeout-usa parasite-eve-usa ridge-racer-usa +all: gshax-tool gen-wipeout-usa gen-parasite-eve-usa gen-ridge-racer-usa clean: $(RM) wipeout-usa/wipeout-usa-gshax-code.txt wipeout-usa/CODELIST00 parasite-eve-usa/parasite-eve-usa-gshax-code.txt parasite-eve-usa/CODELIST00 ridge-racer-usa/ridge-racer-usa-gshax-code.txt ridge-racer-usa/CODELIST00 -gshax-tool: ../entrypoints/entry-bb.bin - cd ../gshax-tool; make clean; make +gshax-tool: + cd ../gshax-tool; make clean; make -wipeout-usa: gshax-tool +gen-wipeout-usa: ../gshax-tool/gshax -g 8005798C -jal 8006C68C 8007E864 ../entrypoints/entry-bb.bin wipeout-usa/CODELIST00; ../gshax-tool/gshax -t 8005798C -jal 8006C68C 8007E864 ../entrypoints/entry-bb.bin wipeout-usa/wipeout-usa-gshax-code.txt -parasite-eve-usa: gshax-tool +gen-parasite-eve-usa: ../gshax-tool/gshax -g 8018FAC8 -j 8018FB78 80193288 ../entrypoints/entry-bb.bin parasite-eve-usa/CODELIST00; ../gshax-tool/gshax -t 8018FAC8 -j 8018FB78 80193288 ../entrypoints/entry-bb.bin parasite-eve-usa/parasite-eve-usa-gshax-code.txt -ridge-racer-usa: gshax-tool +gen-ridge-racer-usa: ../gshax-tool/gshax -g 8004EB1C -j 8004EB54 8007FA30 ../entrypoints/entry-bb.bin ridge-racer-usa/CODELIST00; ../gshax-tool/gshax -t 8004EB1C -j 8004EB54 8007FA30 ../entrypoints/entry-bb.bin ridge-racer-usa/ridge-racer-usa-gshax-code.txt \ No newline at end of file diff --git a/images/copy-freepsxboot-files-to-usb-drive.png b/images/copy-freepsxboot-files-to-usb-drive.png new file mode 100644 index 0000000..58f6a85 Binary files /dev/null and b/images/copy-freepsxboot-files-to-usb-drive.png differ diff --git a/images/eject-freepsxboot-usb-drive.png b/images/eject-freepsxboot-usb-drive.png new file mode 100644 index 0000000..b5cb5fe Binary files /dev/null and b/images/eject-freepsxboot-usb-drive.png differ diff --git a/images/mca-confirm-restore.png b/images/mca-confirm-restore.png new file mode 100644 index 0000000..b4ad258 Binary files /dev/null and b/images/mca-confirm-restore.png differ diff --git a/images/mca-restored-mc.png b/images/mca-restored-mc.png new file mode 100644 index 0000000..47b9024 Binary files /dev/null and b/images/mca-restored-mc.png differ diff --git a/images/mca-restoring-mc.png b/images/mca-restoring-mc.png new file mode 100644 index 0000000..e2f1dfc Binary files /dev/null and b/images/mca-restoring-mc.png differ diff --git a/images/mca-select-freepsxboot-file.png b/images/mca-select-freepsxboot-file.png new file mode 100644 index 0000000..b16b148 Binary files /dev/null and b/images/mca-select-freepsxboot-file.png differ diff --git a/images/mca-select-mass.png b/images/mca-select-mass.png new file mode 100644 index 0000000..88dbe88 Binary files /dev/null and b/images/mca-select-mass.png differ diff --git a/images/mca-select-mc.png b/images/mca-select-mc.png new file mode 100644 index 0000000..1fcdb1c Binary files /dev/null and b/images/mca-select-mc.png differ diff --git a/images/mca-select-restore-mc.png b/images/mca-select-restore-mc.png new file mode 100644 index 0000000..837645d Binary files /dev/null and b/images/mca-select-restore-mc.png differ diff --git a/images/memcardrex-format-freepsxboot-mc.png b/images/memcardrex-format-freepsxboot-mc.png new file mode 100755 index 0000000..41697b0 Binary files /dev/null and b/images/memcardrex-format-freepsxboot-mc.png differ diff --git a/images/memcardrex-import-fpsxboot-file.png b/images/memcardrex-import-fpsxboot-file.png new file mode 100755 index 0000000..92549d6 Binary files /dev/null and b/images/memcardrex-import-fpsxboot-file.png differ diff --git a/images/memcardrex-preferences.png b/images/memcardrex-preferences.png new file mode 100755 index 0000000..275da56 Binary files /dev/null and b/images/memcardrex-preferences.png differ diff --git a/images/memcardrex-uncheck-corrupted-fix.png b/images/memcardrex-uncheck-corrupted-fix.png new file mode 100755 index 0000000..39ccfb9 Binary files /dev/null and b/images/memcardrex-uncheck-corrupted-fix.png differ diff --git a/images/memcardrex-write-fpsxboot-file.png b/images/memcardrex-write-fpsxboot-file.png new file mode 100755 index 0000000..4b785f6 Binary files /dev/null and b/images/memcardrex-write-fpsxboot-file.png differ diff --git a/images/scph-101-freepsxboot-exploit-exploiting.png b/images/scph-101-freepsxboot-exploit-exploiting.png new file mode 100644 index 0000000..192c26f Binary files /dev/null and b/images/scph-101-freepsxboot-exploit-exploiting.png differ diff --git a/images/scph-101-freepsxboot-exploit-loader.png b/images/scph-101-freepsxboot-exploit-loader.png new file mode 100644 index 0000000..f952e8d Binary files /dev/null and b/images/scph-101-freepsxboot-exploit-loader.png differ diff --git a/images/scph-101-memory-card-manager-selected.png b/images/scph-101-memory-card-manager-selected.png new file mode 100644 index 0000000..93bc357 Binary files /dev/null and b/images/scph-101-memory-card-manager-selected.png differ diff --git a/images/scph-30001-wlaunchelf-main-menu.png b/images/scph-30001-wlaunchelf-main-menu.png new file mode 100644 index 0000000..579c6d5 Binary files /dev/null and b/images/scph-30001-wlaunchelf-main-menu.png differ diff --git a/images/wlaunch-elf-select-mass.png b/images/wlaunchelf-select-mass.png similarity index 100% rename from images/wlaunch-elf-select-mass.png rename to images/wlaunchelf-select-mass.png diff --git a/images/wlaunchelf-select-mca-elf.png b/images/wlaunchelf-select-mca-elf.png new file mode 100644 index 0000000..8b02a91 Binary files /dev/null and b/images/wlaunchelf-select-mca-elf.png differ diff --git a/loader/Makefile b/loader/Makefile index 7603534..955f671 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk +include ../variables-shared.mk LOADER_AUTOGEN := orca.inc LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) diff --git a/loader/Makefile.ff9 b/loader/Makefile.ff9 index cdfa377..28c53f8 100644 --- a/loader/Makefile.ff9 +++ b/loader/Makefile.ff9 @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk +include ../variables-shared.mk LOADER_AUTOGEN := orca.inc LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) diff --git a/loader/Makefile.freepsxboot b/loader/Makefile.freepsxboot index 20b067a..53df243 100644 --- a/loader/Makefile.freepsxboot +++ b/loader/Makefile.freepsxboot @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk.freepsxboot +include ../variables-shared.mk LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) diff --git a/loader/Makefile.rom b/loader/Makefile.rom index 162db42..d036c91 100644 --- a/loader/Makefile.rom +++ b/loader/Makefile.rom @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk.rom +include ../variables-shared.mk LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) diff --git a/loader/Makefile.tocperfect b/loader/Makefile.tocperfect index d1582a2..572f600 100644 --- a/loader/Makefile.tocperfect +++ b/loader/Makefile.tocperfect @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk.tocperfect +include ../variables-shared.mk LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) diff --git a/loader/Makefile.xstation b/loader/Makefile.xstation new file mode 100644 index 0000000..47d55ac --- /dev/null +++ b/loader/Makefile.xstation @@ -0,0 +1,39 @@ + +# Thanks to whoever made https://devhints.io/makefile! + +include ../variables.mk.xstation +include ../variables-shared.mk + +LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN) +LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S))) + +all: $(LOADER_FILES) + +clean: + $(RM) $(LOADER_FILES) *.o *.elf $(LOADER_AUTOGEN) + +# Intermediate objects + +%.o: %.c $(LOADER_HEADERS) + $(CC) $(CFLAGS) -c $< + +%.o: %.S $(LOADER_HEADERS) + $(CC) $(CFLAGS) -c $< + +orca.inc: orca.img + bash ../util/bin2h.sh ORCA_IMAGE orca.img orca.inc + +secondary.elf: secondary.ld $(LOADER_OBJECTS) + $(LD) $(LDFLAGS) -T secondary.ld $(LOADER_OBJECTS) -o $@ + bash insert-tonyhax-crc.sh secondary.elf + +# Results + +tonyhax.mcs: tonyhax-tpl.mcs secondary.elf + bash generate-tonyhax-mcs.sh secondary.elf tonyhax-tpl.mcs tonyhax.mcs $(TONYHAX_VERSION) + +HAX: tonyhax.mcs + bash ../util/mcs2raw.sh tonyhax.mcs + +tonyhax.exe: secondary.elf + bash generate-tonyhax-exe.sh secondary.elf tonyhax.exe diff --git a/loader/secondary.c b/loader/secondary.c index f5baf81..73fc4e3 100644 --- a/loader/secondary.c +++ b/loader/secondary.c @@ -14,6 +14,19 @@ #include "integrity.h" #include "io.h" +//to test ROM functionality in emulation via boot CD, uncomment the following 2 lines: +//#undef ROM +//#define ROM + +//to test XSTATION ROM functionality in emulation via boot CD, uncomment the following 4 lines: +//#undef XSTATION +//#define XSTATION +//#undef ROM +//#define ROM + +//to test behavior without any APv2 bypasses enabled (useful for testing D0 AP bypass codes via save game file gameshark functionality rather then internal activate_anti_piracy() function), uncomment: +//#define AP_BYPASS_DISABLE + uint8_t sscmd; uint8_t cdcontrollerver[4]; @@ -40,14 +53,6 @@ void * address; // For Calculating BIOS Functions uint8_t j; // Joypad uint8_t padbuf[2][0x22]; // Joypad Buffers - -//to test ROM functionality in emulation via boot CD, uncomment the following 2 lines: -//#undef ROM -//#define ROM - -//to test behavior without any APv2 bypasses enabled (useful for testing D0 AP bypass codes via save game file gameshark functionality rather then internal activate_anti_piracy() function), uncomment: -//#define AP_BYPASS_DISABLE - #if defined ROM void run_shell() { // runs Sony BIOS. Can access CD Player/Memory Card Manager. Can not boot any discs, even ones that normally work without the flash cart inserted in the console. This has been adapted code from the SCPH-1001 decomp: https://github.com/ogamespec/psxdev/blob/97fbb2d03e5aff4449097afd2b59690002cb2341/reverse/Main.c#L395 @@ -226,7 +231,7 @@ void log_bios_version() { } debug_write("Console: %s", bios_is_ps1() ? "PS1": "PS2"); - debug_write("Sys BIOS: %s", version); + debug_write("System BIOS: %s", version); } bool backdoor_cmd(uint_fast8_t cmd, const char * string) { @@ -308,16 +313,16 @@ void wait_lid_status(bool open) { } #endif - #if defined ROM +#if defined ROM } else { // still allow booting Sony BIOS after reading MC if(j == 0x40) { // X button controller_input_stop(); run_shell(); // launch Sony BIOS } } - #else +#else } - #endif +#endif // Issue Getstat command // We cannot issue the BIOS CD commands yet because we haven't called CdInit @@ -374,87 +379,99 @@ bool licensed_drive() { return false; } } -#endif +#endif // TOCPERFECT + +void re_cd_init() { + debug_write("Reinitializing kernel"); + bios_reinitialize(); + bios_inject_disc_error(); + debug_write("Stopping Motor"); // Reset one last time to avoid potential lockups (here be dragons) + cd_command(CD_CMD_STOP, NULL, 0); cd_wait_int(); cd_wait_int(); + + debug_write("Initializing CD"); + if (!CdInit()) { + debug_write("Init failed"); + return; + } +} void try_boot_cd() { int32_t read; - uint8_t cbuf[4]; // CD Command Buffer - - #if defined FREEPSXBOOT - debug_write("Remove the FreePSXBoot memory card now from your console"); - #elif defined ROM - debug_write("With the CD drive open, press X to boot the Sony BIOS"); - #endif - - #if !defined TOCPERFECT - if(enable_unlock) { - debug_write("Press O to enable GS codes"); - debug_write("Put in a backup or import disc, then close the drive lid"); - wait_lid_status(true); // doesn't wait during the ROM method, unsure why but it is what we want as it allows us to auto-boot with the ROM boot method - wait_lid_status(false); - } else { - if(is_lid_open() || !licensed_drive()) { // If lid is open drive is not licensed, and if lid is closed we check if it is licensed (if it is not licensed but not open then the drive is closed and the user can open it and license it) - debug_write("Put in a real NTSC-J PSX game disc, then block the lid sensor"); - wait_lid_status(true); - wait_lid_status(false); // Blocking lid sensor = 'closing lid' - - debug_write("Initializing CD"); // Drive will be in licensed state after this is successful - if (!CdInit()) { - debug_write("Init failed"); - debug_write("Try unblocking then blocking the lid sensor again"); - return; - } - } // Drive is licensed and the lid is 'closed' at this point - debug_write("Drive is licensed"); - - debug_write("Stopping motor"); - cd_command(CD_CMD_STOP,0,0); cd_wait_int(); cd_wait_int(); +#if defined FREEPSXBOOT + debug_write("Remove the FreePSXBoot memory card now from your console"); +#elif defined ROM + debug_write("With the CD drive open, press X to boot the Sony BIOS or"); + debug_write("Press O to enable GS codes"); +#endif - debug_write("Press O to enable GS codes"); - controller_input_start(); +#if !defined XSTATION + uint8_t cbuf[4]; // CD Command Buffer - debug_write("Keep the lid sensor blocked until turning off the console"); - debug_write("Remove the real NTSC-J PSX game disc"); - debug_write("Put in a backup/import disc, then press X"); // Thanks MottZilla! +#if !defined TOCPERFECT + if(enable_unlock) { + #if !defined ROM + debug_write("With the CD drive open, press O to enable GS codes"); + #endif + debug_write("Put in a backup or import disc, then close the drive lid"); + wait_lid_status(true); // doesn't wait during the ROM method, unsure why but it is what we want as it allows us to auto-boot with the ROM boot method + wait_lid_status(false); + } else { + if(is_lid_open() || !licensed_drive()) { // If lid is open drive is not licensed, and if lid is closed we check if it is licensed (if it is not licensed but not open then the drive is closed and the user can open it and license it) + debug_write("Put in a real NTSC-J PSX game disc, then block the lid sensor"); + wait_lid_status(true); + wait_lid_status(false); // Blocking lid sensor = 'closing lid' + + debug_write("Initializing CD"); // Drive will be in licensed state after this is successful + if (!CdInit()) { + debug_write("Init failed"); + debug_write("Try unblocking then blocking the lid sensor again"); + return; + } + } // Drive is licensed and the lid is 'closed' at this point + debug_write("Drive is licensed"); + + debug_write("Stopping motor"); + cd_command(CD_CMD_STOP,0,0); cd_wait_int(); cd_wait_int(); + + debug_write("Press O to enable GS codes"); + controller_input_start(); + + debug_write("Keep the lid sensor blocked until turning off the console"); + debug_write("Remove the real NTSC-J PSX game disc"); + debug_write("Put in a backup/import disc, then press X"); // Thanks MottZilla! - while(1) { - j = padbuf[0][3] ^ 0xFF; - - if(controller_input_switch) { - if(j == 0x40) { - break; // X button boots disc - } else if(j == 0x20) { // Circle button enables codes - controller_input_switch = 0; // stop pulling for circle button input once we get it, as unlike when the X button is pressed (which breaks this loop) we still have to wait here until the user closes the console CD drive lid - read_memcard(); // this allows Japanese console users to enable user supplied GameShark codes without having to unblock the lid sensor, resetting authentication which would just be more unnecessary steps. - } - } else { - if(j == 0x40) - break; // X button boots disc + while(1) { + j = padbuf[0][3] ^ 0xFF; + + if(controller_input_switch) { + if(j == 0x40) { + break; // X button boots disc + } else if(j == 0x20) { // Circle button enables codes + controller_input_switch = 0; // stop pulling for circle button input once we get it, as unlike when the X button is pressed (which breaks this loop) we still have to wait here until the user closes the console CD drive lid + read_memcard(); // this allows Japanese console users to enable user supplied GameShark codes without having to unblock the lid sensor, resetting authentication which would just be more unnecessary steps. } - debug_write(" "); // Vblank wait for controller input + } else { + if(j == 0x40) + break; // X button boots disc } - controller_input_stop(); + debug_write(" "); // Vblank wait for controller input } - #endif + controller_input_stop(); + } +#endif // TOCPERFECT if(!enable_unlock) { if(bugged_setsession) { - #if !defined STEALTH - debug_write("Sending SetSessionSuperUltraCommandSmash v2, please wait"); // always works on real hardware, DuckStation can get stuck here rarely though since it is not that accurate when it comes to emulating the early VC0A/VC0B/VC1A CDROM behavior - #endif + debug_write("Sending SetSessionSuperUltraCommandSmash v2, please wait"); // always works on real hardware, DuckStation can get stuck here rarely though since it is not that accurate when it comes to emulating the early VC0A/VC0B/VC1A CDROM behavior sscmd = 2; cd_command(CD_CMD_SET_SESSION,(unsigned char *)&sscmd,1); cd_wait_int(); cd_wait_int(); // There is a 3rd response we are ignoring by sending SetSession 1 next ASAP after SetSession 2. sscmd = 1; cd_command(CD_CMD_SET_SESSION,(unsigned char *)&sscmd,1); cd_wait_int(); cd_wait_int(); } else { - #if !defined STEALTH - debug_write("Sending SetSession 1"); - #endif + debug_write("Sending SetSession 1"); sscmd = 1; cd_command(CD_CMD_SET_SESSION,(unsigned char *)&sscmd,1); cd_wait_int(); cd_wait_int(); } if(calibrate_laser) { // VC2 and VC3s do auto Bias/Gain calibration when reading a newly inserted real NTSC-J PS1 disc. A swapped in CD-R or just a different disc in general needs this to be updated - #if !defined STEALTH debug_write("Calibrating laser"); - #endif cbuf[0] = 0x50; cbuf[1] = 0x38; cbuf[2] = 0x15; cbuf[3] = 0x0A; // ModeCompensateTrackingAutoGain cd_command(CD_CMD_TEST,&cbuf[0],4); cd_wait_int(); @@ -468,19 +485,14 @@ void try_boot_cd() { The second reason is because of how we are using the BIOS controller functions, to go back to a clean state a bios re-intialization also accomplishes that. */ - debug_write("Reinitializing kernel"); - bios_reinitialize(); - bios_inject_disc_error(); - - debug_write("Stopping Motor"); - cd_command(CD_CMD_STOP, NULL, 0); cd_wait_int(); cd_wait_int(); - } - - debug_write("Initializing CD"); - if (!CdInit()) { - debug_write("Init failed"); - return; + re_cd_init(); } +#else // XSTATION DEFINED + debug_write("Open and then close the CD drive lid"); + wait_lid_status(true); // doesn't wait during the ROM method, unsure why but it is what we want as it allows us to auto-boot with the ROM boot method + wait_lid_status(false); + re_cd_init(); +#endif // XSTATION /* * Use the space the BIOS has allocated for reading CD sectors. @@ -493,17 +505,17 @@ void try_boot_cd() { uint8_t * data_buffer = (uint8_t *) (bios_is_ps1() ? 0xA000B070 : 0xA000A8D0); debug_write("Checking game region"); - #if defined TOCPERFECT - if (CdReadSector(1, 12, data_buffer) != 1) { // Real license data sector is copied to sector 12 by PS1 DemoSwap Patcher before it writes Japanese license data to sector 4 - debug_write("Failed to read sector"); - return; - } - #else - if (CdReadSector(1, 4, data_buffer) != 1) { - debug_write("Failed to read sector"); - return; - } - #endif +#if defined TOCPERFECT + if (CdReadSector(1, 12, data_buffer) != 1) { // Real license data sector is copied to sector 12 by PS1 DemoSwap Patcher before it writes Japanese license data to sector 4 + debug_write("Failed to read sector"); + return; + } +#else + if (CdReadSector(1, 4, data_buffer) != 1) { + debug_write("Failed to read sector"); + return; + } +#endif const char * game_region; bool game_is_pal = false; @@ -541,13 +553,13 @@ void try_boot_cd() { char bootfilebuf[32]; - #if defined TOCPERFECT - debug_write("Loading SYSTEM.CN2"); - int32_t cnf_fd = FileOpen("cdrom:SYSTEM.CN2;1", FILE_READ); - #else - debug_write("Loading SYSTEM.CNF"); - int32_t cnf_fd = FileOpen("cdrom:SYSTEM.CNF;1", FILE_READ); - #endif +#if defined TOCPERFECT + debug_write("Loading SYSTEM.CN2"); + int32_t cnf_fd = FileOpen("cdrom:SYSTEM.CN2;1", FILE_READ); +#else + debug_write("Loading SYSTEM.CNF"); + int32_t cnf_fd = FileOpen("cdrom:SYSTEM.CNF;1", FILE_READ); +#endif if (cnf_fd > 0) { read = FileRead(cnf_fd, data_buffer, 2048); @@ -584,18 +596,7 @@ void try_boot_cd() { debug_write(" * %s = %x", "STACK", stacktop); debug_write(" * %s = %s", "BOOT", bootfile); - debug_write("Reinitializing kernel"); - bios_reinitialize(); - bios_inject_disc_error(); - - debug_write("Stopping Motor"); // Reset one last time to avoid potential lockups (here be dragons) - cd_command(CD_CMD_STOP, NULL, 0); cd_wait_int(); cd_wait_int(); - - debug_write("Initializing CD"); - if (!CdInit()) { - debug_write("Init failed"); - return; - } + re_cd_init(); // Reset one last time to avoid potential lockups (here be dragons) /* * SetConf is run by BIOS with interrupts disabled. @@ -678,9 +679,11 @@ void try_boot_cd() { // Restore original error handler bios_restore_disc_error(); + #if !defined XSTATION #if !defined AP_BYPASS_DISABLE - if(!first_rev) - activate_anti_anti_piracy(bootfile, (int32_t) exe_header->load_addr); + if(!first_rev) + activate_anti_anti_piracy(bootfile, (int32_t) exe_header->load_addr); + #endif #endif if((did_read_mc) && (!cheat_engine_installed)) @@ -709,10 +712,12 @@ void try_boot_cd() { // Restore original error handler bios_restore_disc_error(); - #if !defined AP_BYPASS_DISABLE - if(!first_rev) - activate_anti_anti_piracy(bootfile, (int32_t) exe_header->load_addr); - #endif +#if !defined XSTATION +#if !defined AP_BYPASS_DISABLE + if(!first_rev) + activate_anti_anti_piracy(bootfile, (int32_t) exe_header->load_addr); +#endif +#endif if((did_read_mc) && (!cheat_engine_installed)) install_cheat_engine(); @@ -751,7 +756,7 @@ void main() { sscmd = 0x20; cd_command(CD_CMD_TEST,(unsigned char *)&sscmd,1); cd_wait_int(); cd_read_reply(cdcontrollerver); // Test Command $19,$20 gets the CDROM BIOS debug_write("CD BIOS: %x", *(uint32_t*) cdcontrollerver); - if(cdcontrollerver[0]==0x94) { + if(cdcontrollerver[0] == 0x94) { bugged_setsession = 1; enable_unlock = 0; // VC0 A and VC0 B are both from 1994 and don't support the getregion command to figure out if it is unlockable or not. first_rev = 1; @@ -763,6 +768,7 @@ void main() { calibrate_laser = 1; } +#if !defined XSTATION if(enable_unlock) { uint8_t cd_reply[16]; // Run "GetRegion" test @@ -810,6 +816,7 @@ void main() { return; } } +#endif // XSTATION while (1) { try_boot_cd(); diff --git a/readme.md b/readme.md index 1b72682..7acda0e 100644 --- a/readme.md +++ b/readme.md @@ -20,6 +20,8 @@ Tonyhax International is a fork of the [Tonyhax](https://orca.pet/tonyhax/) "Sof * Supports [applying user-supplied GameShark codes](gameshark-code-support.md) to any game it booted by the Tonyhax International loader. Dare I say this is the world's first open source PSX GameShark. +* Enables speeding up xStation boot time and allows for applying codes to games `Full Boot`ed by xStation. This is accomplished by a [special xStation ROM version](xstation.md). + * Uses a completely different build system that is portable to many more Linux distributions. This new build system is more efficient and easier to use as well. ## Usage @@ -54,6 +56,7 @@ _Boot Methods_ _More Info_ * [GameShark Code Support](gameshark-code-support.md) +* [XStation ROM Version](xstation.md) * [Playing Games With Additional Copy Protection Routines](anti-piracy-bypass.md) * [CD-R Media For PSX Backups](#cd-r-media-for-psx-backups) * [Disc Read Errors And PS1 CD Drive Repair](https://alex-free.github.io/unofficial-ps1-cd-drive-service-manual/) @@ -80,15 +83,22 @@ _More Info_ ## Downloads -### Version 1.3.3 (6/5/2023) +### Version 1.3.4 (6/14/2023) -* [tonyhax-international-v1.3.3](https://github.com/alex-free/tonyhax/releases/download/v1.3.3i/tonyhax-international-v1.3.3.zip) +* [tonyhax-international-v1.3.4](https://github.com/alex-free/tonyhax/releases/download/v1.3.4i/tonyhax-international-v1.3.4.zip) Changes: -* Added a [APv2 bypass](anti-piracy-bypass.md) for Boku no Natsuyasumi: Summer Holiday 20th Century Japan to close this [issue](https://github.com/alex-free/tonyhax/issues/28). Enjoy, [Bloom-Haven](https://github.com/Bloom-Haven)!!! +* Added a special [xStation ROM version](xstation.md) due to request by +[L10N37](https://github.com/L10N37). This is actually super cool. + +* Added more in-depth info to the [CD-R Media For PSX Backups](#cd-r-media-for-psx-backups) section thanks to [XxTriviumxX](https://github.com/XxTriviumxX). + +* Added even more real hardware screen captures to the docs and improved documentation itself immensely with more in-depth steps (specifically related to the [FreePSXBoot exploit](freepsxboot-exploit.md) but also touched a few other pages). -* Added a ton of real hardware screen captures to the docs and improved documentation itself immensely with more in-depth steps. +* Updated [MKPSXISO](https://github.com/Lameguy64/mkpsxiso) to the latest version. + +* Build system/source cleanup/comment improvements. [About previous versions](changelog.md). @@ -276,9 +286,15 @@ The early PS2 models that Tonyhax International supports have the PS1 mode which * A highly reflective layer system. * High quality polycarbonate and "sealing" process combining all parts of the CD-R. -_Ideally, you want to use 74 minute discs_. The PSX was never designed for the now more common 80 minute discs, and it is easier for the laser to track 74 minute discs due to their wider data spiral track. As of 2023, 74 minute discs are not really manufactured anymore and new old stock can get pricey, so it really may not be worth it as the PSX can read 80 minute discs fine. It just can read 74 minute discs easier as that is closer to what it was designed for originally (which was 72 minute pressed CD-ROMs). +_You want to use 74 minute discs_. The PSX was never designed for the now more common 80 minute discs, and it is easier for the laser to track 74 minute discs due to their wider data spiral track. As of 2023, 74 minute discs are not really manufactured anymore and new old stock can get pricey, so it really may not be worth it as the PSX can read 80 minute discs okay (just not as optimally, you may experience longer load times or even straight up disc read errors on worn CD drives). + +The PSX can read 74 minute discs easier as that is closer to what it was designed for originally (which was 72 minute pressed CD-ROMs). Verbatim DataLifePlus 74min discs with a copyright date of 1997 or 1999 on the back of the CD case may be among the best media to acquire. -I have found Verbatim DataLifePlus CD-Rs to be really good with PS1 consoles. Here is the ATIP information displayed by `cdrecord -atip` for a Verbatim DataLifePlus CD-R: +Later PSX consoles and all PS2s appear to handle 80min discs much better then the earliest models. + +It is extremely important to note that as of 2023 one single monopoly known as CMC magnetics has [bought out every good manufacturer of CD-R media](https://github.com/alex-free/tonyhax/issues/30). Quality has seemed to [gone down due to this](https://gbatemp.net/threads/do-modern-burners-cds-make-lower-quality-ps1-backups.628708/page-3#post-10182249), so new old stock 74min media really is optimal. + +I have found Verbatim DataLifePlus CD-Rs to be really good with PS1 consoles. Here is the ATIP information displayed by `cdrecord -atip` for a Verbatim DataLifePlus 80min modern CD-R: ATIP info from disk: Indicated writing power: 4 @@ -291,7 +307,7 @@ I have found Verbatim DataLifePlus CD-Rs to be really good with PS1 consoles. He Manuf. index: 11 Manufacturer: Mitsubishi Chemical Corporation -Verbatim UltraLife Archival Grade Gold CD-Rs also are really good, although they are more expensive then Verbatim DataLifePlus. I think Verbatim DataLifePlus CD-Rs are slightly better with the PS1 as well, but they are an option. Here is the ATIP information displayed by `cdrecord -atip` for a Verbatim DataLifePlus CD-R: +Verbatim UltraLife Archival Grade Gold CD-Rs also are really good, although they are more expensive then Verbatim DataLifePlus. I think Verbatim DataLifePlus CD-Rs are slightly better with the PS1 as well, but they are an option. Here is the ATIP information displayed by `cdrecord -atip` for a Verbatim UltraLife Archival Grade Gold 80min modern CD-R: ATIP info from disk: Indicated writing power: 5 @@ -304,13 +320,26 @@ Verbatim UltraLife Archival Grade Gold CD-Rs also are really good, although they Manuf. index: 26 Manufacturer: TDK Corporation +CMC Pro discs have been [reported](https://github.com/alex-free/tonyhax/issues/30) to work very well with the PSX by [XxTriviumxX](https://github.com/XxTriviumxX). Here is the ATIP information displayed by `cdrecord -atip` for a CMC Pro 80min modern CD-R: + + ATIP info from disk: + Indicated writing power: 4 + Disk Is not unrestricted + Disk Is not erasable + Disk sub type: Medium Type A, high Beta category (A+) (3) + ATIP start of lead in: -11849 (97:24/01) + ATIP start of lead out: 359847 (79:59/72) + Disk type: Long strategy type (Cyanine, AZO or similar) + Manuf. index: 25 + Manufacturer: Taiyo Yuden Company Limited + **Do not use cheap/poor quality CD-R media, which is almost always all that is available in retail stores and most likely any CD-R that is not "archival grade"**. Poor quality cheap CD-R media _can_ result in: * Slower loading times/in-game lag because of CD drive tracking errors (bad noises from the CD drive). * Issues reading data off of the disc possibly resulting in a game to freeze and motor power off in the CD drive. * Skipping/silent audio and or music. -Later PS1 consoles (starting at the SCPH-5000 series and newer) and all PS2 consoles have a much greater tolerance to poor quality CD-R media, and _may_ work fine with it however in general it is still best to just always use Verbatim DataLifePlus/UltraLife CD-Rs or something of similar quality. Here is the ATIP information displayed by `cdrecord -atip` for a Maxell Music CD-R (which is a poor quality brand/CD-R media that is **highly not recommended**. +Here is the ATIP information displayed by `cdrecord -atip` for a Maxell Music CD-R (which is a poor quality brand/CD-R media that is **highly not recommended**. ATIP info from disk: Indicated writing power: 4 @@ -323,7 +352,7 @@ Later PS1 consoles (starting at the SCPH-5000 series and newer) and all PS2 cons Manuf. index: 22 Manufacturer: Ritek Co. -If you are having issues booting discs in Tonyhax International, consider wiping with a clean microfiber cloth from the inner ring to the outer edge of the disc in all directions and then trying to boot the disc again. +If you are still having issues booting discs in Tonyhax International, consider wiping with a clean microfiber cloth from the inner ring to the outer edge of the disc in all directions and then trying to boot the disc again. ## Building From Source @@ -358,11 +387,14 @@ With everything now installed, build Tonyhax International with the `build.sh` s ### MottZilla -* Guidance on increasing the size of the Tonyhax International loader. +* Guidance on increasing the size of the Tonyhax International loader and my general goto mentor on this project. -* Wrote the GameShark Code Engine now used by the anti-piracy bypass features and explained how to use it. +* Co-developed the Spyro Year Of The Dragon GameShark code bypass method. + +* Wrote the GameShark Code Engine, used first in the APv2 bypass system. With MottZilla's guidance this code has even been expanded and adapted for general use [GameShark Code Support](gameshark-code.md). * The original sole creator of [PS1 DemoSwap Patcher v1.0](https://www.psx-place.com/threads/mctool-tonyhax-freepsxboot-installer.36569). MottZilla re-implemented the TOCPerfect concept into a much superior method, and included his implementation alongside of his DemoSwap idea in PS1 DemoSwap Patcher. + * Wrote the controller input support for Tonyhax International. * Wrote the laser re-calibration function for VC2 and VC3 CDROM controllers. @@ -373,9 +405,7 @@ With everything now installed, build Tonyhax International with the `build.sh` s * Came up with reset+unlock technique for TOCPerfect booting on USA/PAL consoles. -* Helped debug the [FreePSXBoot](https://github.com/brad-lin/FreePSXBoot) builder's own patch to disable a FreePSXBoot memory card in slot 2. - -* Originally came up with the idea to involve the SetSession 2 command in a fix for the older CDROM controllers. +* Originally came up with the idea to involve the SetSession 2 command in a fix for the older CDROM controllers which resulted in the eventual discovery of the SetSessionSuperUltraCommandSmash v2. * Explained the save game checksum routines in both Tony Hawk Pro Skater 2 (Japanese version) & Castrol Honda VTR (Japanese version) to help me create SuccessCheckSumUpdater (SuccessCU). @@ -395,15 +425,18 @@ With everything now installed, build Tonyhax International with the `build.sh` s * Downhill Snow (Japan) save game exploit. +* Final Fantasy IX (Japan and USA) save game exploit. + ### SylverReZ (M4x1mumReZ) * Helping with debugging an [APrip](https://alex-free.github.io/aprip) issue on Windows. -* Contributing APrip GameShark codes to be added to the Tonyhax International loader. +* Generated Aprip codes for APv2 bypasses for i-mode mo Issho: Doko Demo Issho Tsuika Disc, Koko Hore! Pukka, Love Hina: Ai wa Kotoba no Naka ni / Love Hina 2: Kotoba wa Konayuki no You ni, Pocket Jiman. ### Misc Acknowledgements * [Berion](https://www.psx-place.com/members/berion.1431/) of [PSX-Place](https://psx-place.com) compressed the images of this document properly (this is the first time I've edited photos). + * Martin Korth for confirming the SetSession bug found in VC0A, VC0B, and VC1A CDROM controller BIOS versions, and for the priceless [PSX-SPX](http://problemkaputt.de/psx-spx.htm) document. * [Peppe90](https://www.psx-place.com/members/peppe90.42412/) of [PSX-Place](https://psx-place.com) for testing NTSC gamems on a PAL PS2. His results have confirmed that the video mode can not be changed from PS1 software in PS1 mode on a PS1. It must be changed in PS1DRV from the PS2, as PS1 mode is set to always display the same video mode that the console shipped with (for the early PS2s that Tonyhax International supports). He mentioned that PS1VModeNeg v1.0.1 can be used to overcome this. The original Tonyhax [issue](https://github.com/socram8888/tonyhax/issues/25) explaining this also was helpful in figuring out how to bypass this PS2 level limitation. diff --git a/rom/Makefile b/rom/Makefile index 1ee0919..4d30f11 100644 --- a/rom/Makefile +++ b/rom/Makefile @@ -2,6 +2,7 @@ # Thanks to whoever made https://devhints.io/makefile! include ../variables.mk +include ../variables-shared.mk .PHONY: clean diff --git a/rom/tonyhax-v1.2.7-international.rom b/rom/tonyhax-v1.2.7-international.rom deleted file mode 100644 index 0b078d0..0000000 Binary files a/rom/tonyhax-v1.2.7-international.rom and /dev/null differ diff --git a/save-game-exploit.md b/save-game-exploit.md index 21c2ba3..fd3f252 100644 --- a/save-game-exploit.md +++ b/save-game-exploit.md @@ -6,7 +6,7 @@ The original way to boot the Tonyhax International loader is with _a special gam * Any supported console. * A [supported authentic/'black' PSX game disc](#save-game-exploit-supported-games-list) that your console can boot normally (i.e. not an 'imported region disc'). -* A soft-modded PS2 console capable of [copying files](#ps2-installation-method) from a USB flash drive or other storage to a PS1 memory card. There are [alternative methods](#ps3-memory-card-usb-adapterdexdrivecomputer-installation-method) to copy the required files to a PS1 memory card available (which requires other hardware), but the soft-modded PS2 method is what I use. +* A soft-modded PS2 console capable of [copying files](#ps2-installation-method) from a USB flash drive or other storage to a PS1 memory card. There are [alternative methods](#ps3-memory-card-usb-adapter-method) to copy the required files to a PS1 memory card available (which requires other hardware). * A PS1 memory card with enough space for the special save game exploit file and for the Tonyhax International loader filed. * A FAT32 formatted USB flash drive that your PS2 console can read (if using a soft-modded [PS2](#ps2-installation-method) for installation). Please note that not all USB flash drives seem to work with PS2 consoles (due to iffy USB 1.1 support found in some newer USB flash drives). You may need to do a bit of trial and error testing to find a USB flash drive that works. diff --git a/scripts/burn-rom-flasher-cd.sh b/scripts/burn-rom-flasher-cd.sh index dc8a76b..9744ed5 100755 --- a/scripts/burn-rom-flasher-cd.sh +++ b/scripts/burn-rom-flasher-cd.sh @@ -2,4 +2,4 @@ cd "$(dirname "$0")" cd ../rom -cdrdao write --speed 1 --swap --eject tonyhax-rom-flasher.cue +cdrdao write --speed 1 --swap --eject -n tonyhax-rom-flasher.cue diff --git a/scripts/update-web.sh b/scripts/update-web.sh new file mode 100755 index 0000000..a1ea35c --- /dev/null +++ b/scripts/update-web.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd "$(dirname "$0")" +set -e +cd ../ +cp -rv *.md ~/dev/alex-free.github.io/tonyhax-international +rm -rf ~/dev/alex-free.github.io/tonyhax-international/images +cp -rv images ~/dev/alex-free.github.io/tonyhax-international \ No newline at end of file diff --git a/variables-shared.mk b/variables-shared.mk new file mode 100644 index 0000000..235bbd3 --- /dev/null +++ b/variables-shared.mk @@ -0,0 +1,169 @@ + +.DELETE_ON_ERROR: + +.PHONY: clean + +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +# Common variables + +CC=mips-linux-gnu-gcc +LD=mips-linux-gnu-ld +LDFLAGS=--gc-sections + +OBJCOPY=mips-linux-gnu-objcopy +OBJCOPYFLAGS=-O binary + +# Entry point variables + +ENTRY_MCS := \ + $(patsubst $(SELF_DIR)/entrypoints/%-tpl.mcs, %.mcs, $(wildcard $(SELF_DIR)/entrypoints/*-tpl.mcs)) \ + FF9-A-JP/ff9-a-jp.mcs \ + FF9-B-JP/ff9-b-jp.mcs \ + FF9-A-US/ff9-a-us.mcs \ + FF9-B-US/ff9-b-us.mcs + +ENTRY_RAW := \ + FF9-A-JP/BISLPS-0200000000-00 \ + FF9-B-JP/BISLPS-0200000000-00 \ + FF9-A-US/BASLUS-0125100000-00 \ + FF9-B-US/BASLUS-0125100000-00 \ + BISLPS-01391SKI00S \ + BISLPS-00300TEKKEN-2 \ + BISLPS-01300TEKKEN-3 \ + BISLPM-86922CHSVTRv1 \ + BISLPM-86489CHSv1 \ + BISLPM-86751CEEAG01 \ + BISLPM-86754DRACULA \ + BISLPS-01323010001 \ + BISCPS-1004700000000 \ + BISCPS-1007300000000 \ + BISLPS-00130DOKIOH \ + BASCUS-9415400047975 \ + BASCUS-9424400000000 \ + BASCUS-9455916 \ + BASLUS-00213TEKKEN-2 \ + BASLUS-00402TEKKEN-3 \ + BASLUS-00571 \ + BASLUS-00856 \ + BASLUS-00882CHSv1 \ + BASLUS-01066TNHXG01 \ + BASLUS-01384DRACULA \ + BASLUS-01419TNHXG01 \ + BASLUS-01485TNHXG01 \ + BASLUS-01506XSMOTOv1 \ + BESCES-00255TEKKEN-2 \ + BESCES-01237TEKKEN-3 \ + BESCES-0096700765150 \ + BESCES-0142000000000 \ + BESCES-0228316 \ + BESLES_01182CHSv1 \ + BESLES-01376 \ + BESLES-02618 \ + BESLES-02908TNHXG01 \ + BESLES-02909TNHXG01 \ + BESLES-02910TNHXG01 \ + BESLES-02942CHSVTRv1 \ + BESLES-03057SSBv1 \ + BESLES-03645TNHXG01 \ + BESLES-03646TNHXG01 \ + BESLES-03647TNHXG01 \ + BESLES-03827SSII \ + BESLES-03954TNHXG01 \ + BESLES-03955TNHXG01 \ + BESLES-03956TNHXG01 \ + BESLES-04095XSMOTO + +ENTRY_FILES := $(ENTRY_MCS) $(ENTRY_RAW) entry-bb.bin entry.bin + +# Program loader variables + +LOADER_FILES := orca.inc tonyhax.mcs HAX tonyhax.exe + +# Loader output + +LOADER_OUTPUT_FILES := HAX FF9 tonyhax.mcs tonyhax-ff9.mcs tonyhax.exe + +# FreePSXBoot images + +FREEPSXBOOT_IMAGES := \ + tonyhax_scph-1000_slot1.mcr \ + tonyhax_scph-1000_slot2.mcr \ + tonyhax_scph-3000_v1.1_slot1.mcr \ + tonyhax_scph-3000_v1.1_slot2.mcr \ + tonyhax_scph-3000_v2.1_slot1.mcr \ + tonyhax_scph-3000_v2.1_slot2.mcr \ + tonyhax_scph-3500_slot1.mcr \ + tonyhax_scph-3500_slot2.mcr \ + tonyhax_scph-5000_slot1.mcr \ + tonyhax_scph-5000_slot2.mcr \ + tonyhax_scph-5500_slot1.mcr \ + tonyhax_scph-5500_slot2.mcr \ + tonyhax_scph-7000_slot1.mcr \ + tonyhax_scph-7000_slot2.mcr \ + tonyhax_scph-7500_slot1.mcr \ + tonyhax_scph-7500_slot2.mcr \ + tonyhax_scph-9000_slot1.mcr \ + tonyhax_scph-9000_slot2.mcr \ + tonyhax_scph-100_slot1.mcr \ + tonyhax_scph-100_slot2.mcr \ + tonyhax_scph-1001_v2.0_slot1.mcr \ + tonyhax_scph-1001_v2.0_slot2.mcr \ + tonyhax_scph-1001_v2.1_slot1.mcr \ + tonyhax_scph-1001_v2.1_slot2.mcr \ + tonyhax_scph-1001_v2.2_slot1.mcr \ + tonyhax_scph-1001_v2.2_slot2.mcr \ + tonyhax_scph-1002_v2.0_slot1.mcr \ + tonyhax_scph-1002_v2.0_slot2.mcr \ + tonyhax_scph-1002_v2.1_slot1.mcr \ + tonyhax_scph-1002_v2.1_slot2.mcr \ + tonyhax_scph-1002_v2.2_slot1.mcr \ + tonyhax_scph-1002_v2.2_slot2.mcr \ + tonyhax_scph-5001_slot1.mcr \ + tonyhax_scph-5001_slot2.mcr \ + tonyhax_scph-5501_slot1.mcr \ + tonyhax_scph-5501_slot2.mcr \ + tonyhax_scph-5502_slot1.mcr \ + tonyhax_scph-5502_slot2.mcr \ + tonyhax_scph-5552_slot1.mcr \ + tonyhax_scph-5552_slot2.mcr \ + tonyhax_scph-7001_slot1.mcr \ + tonyhax_scph-7001_slot2.mcr \ + tonyhax_scph-7002_slot1.mcr \ + tonyhax_scph-7002_slot2.mcr \ + tonyhax_scph-7501_slot1.mcr \ + tonyhax_scph-7501_slot2.mcr \ + tonyhax_scph-7502_slot1.mcr \ + tonyhax_scph-7502_slot2.mcr \ + tonyhax_scph-9001_slot1.mcr \ + tonyhax_scph-9001_slot2.mcr \ + tonyhax_scph-9002_slot1.mcr \ + tonyhax_scph-9002_slot2.mcr \ + tonyhax_scph-101_v4.4_slot1.mcr \ + tonyhax_scph-101_v4.4_slot2.mcr \ + tonyhax_scph-101_v4.5_slot1.mcr \ + tonyhax_scph-101_v4.5_slot2.mcr \ + tonyhax_scph-102_v4.4_slot1.mcr \ + tonyhax_scph-102_v4.4_slot2.mcr \ + tonyhax_scph-102_v4.5_slot1.mcr \ + tonyhax_scph-102_v4.5_slot2.mcr + +# Boot CD files + +BOOT_CD_FILES := tonyhax-boot-cd-japan.bin tonyhax-boot-cd-japan.cue tonyhax-boot-cd-europe.bin tonyhax-boot-cd-europe.cue + +# ROM files + +ROM_FILES := tonyhax-international-$(TONYHAX_VERSION).rom tonyhax-rom-flasher.bin tonyhax-rom-flasher.cue + +# XSTATION ROM files + +X_ROM_FILES := tonyhax-international-x-$(TONYHAX_VERSION).rom tonyhax-x-rom-flasher.bin tonyhax-x-rom-flasher.cue + +# GSHAX Files + +GSHAX_FILES := wipeout-usa/wipeout-usa-gshax-code.txt wipeout-usa/CODELIST00 parasite-eve-usa/parasite-eve-usa-gshax-code.txt parasite-eve-usa/CODELIST00 ridge-racer-usa/ridge-racer-usa-gshax-code.txt ridge-racer-usa/CODELIST00 + +# THIGSGEN Files + +THIGSGEN_FILES := linux_x86_64_static/thigsgen linux_x86_static/thigsgen windows_x86_64/thigsgen.exe windows_x86/thigsgen.exe diff --git a/variables.mk b/variables.mk index 6f64e5b..6df1c1d 100644 --- a/variables.mk +++ b/variables.mk @@ -3,155 +3,5 @@ .PHONY: clean -SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) - -# Common variables - -TONYHAX_VERSION=v1.3.3 - -CC=mips-linux-gnu-gcc +TONYHAX_VERSION=v1.3.4 CFLAGS=-Os -Wall -Wextra -Wno-main -Werror -mfp32 -mno-abicalls -fno-pic -fdata-sections -ffunction-sections -fno-builtin -nostdlib -DTONYHAX_VERSION=$(TONYHAX_VERSION) - -LD=mips-linux-gnu-ld -LDFLAGS=--gc-sections - -OBJCOPY=mips-linux-gnu-objcopy -OBJCOPYFLAGS=-O binary - -# Entry point variables - -ENTRY_MCS := \ - $(patsubst $(SELF_DIR)/entrypoints/%-tpl.mcs, %.mcs, $(wildcard $(SELF_DIR)/entrypoints/*-tpl.mcs)) \ - FF9-A-JP/ff9-a-jp.mcs \ - FF9-B-JP/ff9-b-jp.mcs \ - FF9-A-US/ff9-a-us.mcs \ - FF9-B-US/ff9-b-us.mcs - -ENTRY_RAW := \ - FF9-A-JP/BISLPS-0200000000-00 \ - FF9-B-JP/BISLPS-0200000000-00 \ - FF9-A-US/BASLUS-0125100000-00 \ - FF9-B-US/BASLUS-0125100000-00 \ - BISLPS-01391SKI00S \ - BISLPS-00300TEKKEN-2 \ - BISLPS-01300TEKKEN-3 \ - BISLPM-86922CHSVTRv1 \ - BISLPM-86489CHSv1 \ - BISLPM-86751CEEAG01 \ - BISLPM-86754DRACULA \ - BISLPS-01323010001 \ - BISCPS-1004700000000 \ - BISCPS-1007300000000 \ - BISLPS-00130DOKIOH \ - BASCUS-9415400047975 \ - BASCUS-9424400000000 \ - BASCUS-9455916 \ - BASLUS-00213TEKKEN-2 \ - BASLUS-00402TEKKEN-3 \ - BASLUS-00571 \ - BASLUS-00856 \ - BASLUS-00882CHSv1 \ - BASLUS-01066TNHXG01 \ - BASLUS-01384DRACULA \ - BASLUS-01419TNHXG01 \ - BASLUS-01485TNHXG01 \ - BASLUS-01506XSMOTOv1 \ - BESCES-00255TEKKEN-2 \ - BESCES-01237TEKKEN-3 \ - BESCES-0096700765150 \ - BESCES-0142000000000 \ - BESCES-0228316 \ - BESLES_01182CHSv1 \ - BESLES-01376 \ - BESLES-02618 \ - BESLES-02908TNHXG01 \ - BESLES-02909TNHXG01 \ - BESLES-02910TNHXG01 \ - BESLES-02942CHSVTRv1 \ - BESLES-03057SSBv1 \ - BESLES-03645TNHXG01 \ - BESLES-03646TNHXG01 \ - BESLES-03647TNHXG01 \ - BESLES-03827SSII \ - BESLES-03954TNHXG01 \ - BESLES-03955TNHXG01 \ - BESLES-03956TNHXG01 \ - BESLES-04095XSMOTO - -ENTRY_FILES := $(ENTRY_MCS) $(ENTRY_RAW) entry-bb.bin entry.bin - -# Program loader variables - -LOADER_FILES := orca.inc tonyhax.mcs HAX tonyhax.exe - -# FreePSXBoot images - -FREEPSXBOOT_IMAGES := \ - tonyhax_scph-1000_slot1.mcr \ - tonyhax_scph-1000_slot2.mcr \ - tonyhax_scph-3000_v1.1_slot1.mcr \ - tonyhax_scph-3000_v1.1_slot2.mcr \ - tonyhax_scph-3000_v2.1_slot1.mcr \ - tonyhax_scph-3000_v2.1_slot2.mcr \ - tonyhax_scph-3500_slot1.mcr \ - tonyhax_scph-3500_slot2.mcr \ - tonyhax_scph-5000_slot1.mcr \ - tonyhax_scph-5000_slot2.mcr \ - tonyhax_scph-5500_slot1.mcr \ - tonyhax_scph-5500_slot2.mcr \ - tonyhax_scph-7000_slot1.mcr \ - tonyhax_scph-7000_slot2.mcr \ - tonyhax_scph-7500_slot1.mcr \ - tonyhax_scph-7500_slot2.mcr \ - tonyhax_scph-9000_slot1.mcr \ - tonyhax_scph-9000_slot2.mcr \ - tonyhax_scph-100_slot1.mcr \ - tonyhax_scph-100_slot2.mcr \ - tonyhax_scph-1001_v2.0_slot1.mcr \ - tonyhax_scph-1001_v2.0_slot2.mcr \ - tonyhax_scph-1001_v2.1_slot1.mcr \ - tonyhax_scph-1001_v2.1_slot2.mcr \ - tonyhax_scph-1001_v2.2_slot1.mcr \ - tonyhax_scph-1001_v2.2_slot2.mcr \ - tonyhax_scph-1002_v2.0_slot1.mcr \ - tonyhax_scph-1002_v2.0_slot2.mcr \ - tonyhax_scph-1002_v2.1_slot1.mcr \ - tonyhax_scph-1002_v2.1_slot2.mcr \ - tonyhax_scph-1002_v2.2_slot1.mcr \ - tonyhax_scph-1002_v2.2_slot2.mcr \ - tonyhax_scph-5001_slot1.mcr \ - tonyhax_scph-5001_slot2.mcr \ - tonyhax_scph-5501_slot1.mcr \ - tonyhax_scph-5501_slot2.mcr \ - tonyhax_scph-5502_slot1.mcr \ - tonyhax_scph-5502_slot2.mcr \ - tonyhax_scph-5552_slot1.mcr \ - tonyhax_scph-5552_slot2.mcr \ - tonyhax_scph-7001_slot1.mcr \ - tonyhax_scph-7001_slot2.mcr \ - tonyhax_scph-7002_slot1.mcr \ - tonyhax_scph-7002_slot2.mcr \ - tonyhax_scph-7501_slot1.mcr \ - tonyhax_scph-7501_slot2.mcr \ - tonyhax_scph-7502_slot1.mcr \ - tonyhax_scph-7502_slot2.mcr \ - tonyhax_scph-9001_slot1.mcr \ - tonyhax_scph-9001_slot2.mcr \ - tonyhax_scph-9002_slot1.mcr \ - tonyhax_scph-9002_slot2.mcr \ - tonyhax_scph-101_v4.4_slot1.mcr \ - tonyhax_scph-101_v4.4_slot2.mcr \ - tonyhax_scph-101_v4.5_slot1.mcr \ - tonyhax_scph-101_v4.5_slot2.mcr \ - tonyhax_scph-102_v4.4_slot1.mcr \ - tonyhax_scph-102_v4.4_slot2.mcr \ - tonyhax_scph-102_v4.5_slot1.mcr \ - tonyhax_scph-102_v4.5_slot2.mcr - -# Boot CD files - -BOOT_CD_FILES := tonyhax-boot-cd-japan.bin tonyhax-boot-cd-japan.cue tonyhax-boot-cd-europe.bin tonyhax-boot-cd-europe.cue - -# ROM files - -ROM_FILES := tonyhax-international-$(TONYHAX_VERSION).rom tonyhax-rom-flasher.bin tonyhax-rom-flasher.cue diff --git a/variables.mk.freepsxboot b/variables.mk.freepsxboot index 10e55ee..3674cfb 100644 --- a/variables.mk.freepsxboot +++ b/variables.mk.freepsxboot @@ -5,153 +5,5 @@ SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -# Common variables - -TONYHAX_VERSION=v1.3.3-freepsxboot - -CC=mips-linux-gnu-gcc +TONYHAX_VERSION=v1.3.4-freepsxboot CFLAGS=-Os -Wall -Wextra -Wno-main -Werror -mfp32 -mno-abicalls -fno-pic -fdata-sections -ffunction-sections -fno-builtin -nostdlib -DTONYHAX_VERSION=$(TONYHAX_VERSION) -DFREEPSXBOOT - -LD=mips-linux-gnu-ld -LDFLAGS=--gc-sections - -OBJCOPY=mips-linux-gnu-objcopy -OBJCOPYFLAGS=-O binary - -# Entry point variables - -ENTRY_MCS := \ - $(patsubst $(SELF_DIR)/entrypoints/%-tpl.mcs, %.mcs, $(wildcard $(SELF_DIR)/entrypoints/*-tpl.mcs)) \ - FF9-A-JP/ff9-a-jp.mcs \ - FF9-B-JP/ff9-b-jp.mcs \ - FF9-A-US/ff9-a-us.mcs \ - FF9-B-US/ff9-b-us.mcs - -ENTRY_RAW := \ - FF9-A-JP/BISLPS-0200000000-00 \ - FF9-B-JP/BISLPS-0200000000-00 \ - FF9-A-US/BASLUS-0125100000-00 \ - FF9-B-US/BASLUS-0125100000-00 \ - BISLPS-01391SKI00S \ - BISLPS-00300TEKKEN-2 \ - BISLPS-01300TEKKEN-3 \ - BISLPM-86922CHSVTRv1 \ - BISLPM-86489CHSv1 \ - BISLPM-86751CEEAG01 \ - BISLPM-86754DRACULA \ - BISLPS-01323010001 \ - BISCPS-1004700000000 \ - BISCPS-1007300000000 \ - BISLPS-00130DOKIOH \ - BASCUS-9415400047975 \ - BASCUS-9424400000000 \ - BASCUS-9455916 \ - BASLUS-00213TEKKEN-2 \ - BASLUS-00402TEKKEN-3 \ - BASLUS-00571 \ - BASLUS-00856 \ - BASLUS-00882CHSv1 \ - BASLUS-01066TNHXG01 \ - BASLUS-01384DRACULA \ - BASLUS-01419TNHXG01 \ - BASLUS-01485TNHXG01 \ - BASLUS-01506XSMOTOv1 \ - BESCES-00255TEKKEN-2 \ - BESCES-01237TEKKEN-3 \ - BESCES-0096700765150 \ - BESCES-0142000000000 \ - BESCES-0228316 \ - BESLES_01182CHSv1 \ - BESLES-01376 \ - BESLES-02618 \ - BESLES-02908TNHXG01 \ - BESLES-02909TNHXG01 \ - BESLES-02910TNHXG01 \ - BESLES-02942CHSVTRv1 \ - BESLES-03057SSBv1 \ - BESLES-03645TNHXG01 \ - BESLES-03646TNHXG01 \ - BESLES-03647TNHXG01 \ - BESLES-03827SSII \ - BESLES-03954TNHXG01 \ - BESLES-03955TNHXG01 \ - BESLES-03956TNHXG01 \ - BESLES-04095XSMOTO - -ENTRY_FILES := $(ENTRY_MCS) $(ENTRY_RAW) entry-bb.bin entry.bin - -# Program loader variables - -LOADER_FILES := orca.inc tonyhax.mcs HAX tonyhax.exe - -# FreePSXBoot images - -FREEPSXBOOT_IMAGES := \ - tonyhax_scph-1000_slot1.mcr \ - tonyhax_scph-1000_slot2.mcr \ - tonyhax_scph-3000_v1.1_slot1.mcr \ - tonyhax_scph-3000_v1.1_slot2.mcr \ - tonyhax_scph-3000_v2.1_slot1.mcr \ - tonyhax_scph-3000_v2.1_slot2.mcr \ - tonyhax_scph-3500_slot1.mcr \ - tonyhax_scph-3500_slot2.mcr \ - tonyhax_scph-5000_slot1.mcr \ - tonyhax_scph-5000_slot2.mcr \ - tonyhax_scph-5500_slot1.mcr \ - tonyhax_scph-5500_slot2.mcr \ - tonyhax_scph-7000_slot1.mcr \ - tonyhax_scph-7000_slot2.mcr \ - tonyhax_scph-7500_slot1.mcr \ - tonyhax_scph-7500_slot2.mcr \ - tonyhax_scph-9000_slot1.mcr \ - tonyhax_scph-9000_slot2.mcr \ - tonyhax_scph-100_slot1.mcr \ - tonyhax_scph-100_slot2.mcr \ - tonyhax_scph-1001_v2.0_slot1.mcr \ - tonyhax_scph-1001_v2.0_slot2.mcr \ - tonyhax_scph-1001_v2.1_slot1.mcr \ - tonyhax_scph-1001_v2.1_slot2.mcr \ - tonyhax_scph-1001_v2.2_slot1.mcr \ - tonyhax_scph-1001_v2.2_slot2.mcr \ - tonyhax_scph-1002_v2.0_slot1.mcr \ - tonyhax_scph-1002_v2.0_slot2.mcr \ - tonyhax_scph-1002_v2.1_slot1.mcr \ - tonyhax_scph-1002_v2.1_slot2.mcr \ - tonyhax_scph-1002_v2.2_slot1.mcr \ - tonyhax_scph-1002_v2.2_slot2.mcr \ - tonyhax_scph-5001_slot1.mcr \ - tonyhax_scph-5001_slot2.mcr \ - tonyhax_scph-5501_slot1.mcr \ - tonyhax_scph-5501_slot2.mcr \ - tonyhax_scph-5502_slot1.mcr \ - tonyhax_scph-5502_slot2.mcr \ - tonyhax_scph-5552_slot1.mcr \ - tonyhax_scph-5552_slot2.mcr \ - tonyhax_scph-7001_slot1.mcr \ - tonyhax_scph-7001_slot2.mcr \ - tonyhax_scph-7002_slot1.mcr \ - tonyhax_scph-7002_slot2.mcr \ - tonyhax_scph-7501_slot1.mcr \ - tonyhax_scph-7501_slot2.mcr \ - tonyhax_scph-7502_slot1.mcr \ - tonyhax_scph-7502_slot2.mcr \ - tonyhax_scph-9001_slot1.mcr \ - tonyhax_scph-9001_slot2.mcr \ - tonyhax_scph-9002_slot1.mcr \ - tonyhax_scph-9002_slot2.mcr \ - tonyhax_scph-101_v4.4_slot1.mcr \ - tonyhax_scph-101_v4.4_slot2.mcr \ - tonyhax_scph-101_v4.5_slot1.mcr \ - tonyhax_scph-101_v4.5_slot2.mcr \ - tonyhax_scph-102_v4.4_slot1.mcr \ - tonyhax_scph-102_v4.4_slot2.mcr \ - tonyhax_scph-102_v4.5_slot1.mcr \ - tonyhax_scph-102_v4.5_slot2.mcr - -# Boot CD files - -BOOT_CD_FILES := tonyhax-boot-cd-japan.bin tonyhax-boot-cd-japan.cue tonyhax-boot-cd-europe.bin tonyhax-boot-cd-europe.cue - -# ROM files - -ROM_FILES := tonyhax-international-$(TONYHAX_VERSION).rom tonyhax-rom-flasher.bin tonyhax-rom-flasher.cue diff --git a/variables.mk.rom b/variables.mk.rom index 5e53cfa..f4fddfb 100644 --- a/variables.mk.rom +++ b/variables.mk.rom @@ -5,153 +5,5 @@ SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -# Common variables - -TONYHAX_VERSION=v1.3.3-rom - -CC=mips-linux-gnu-gcc +TONYHAX_VERSION=v1.3.4-rom CFLAGS=-Os -Wall -Wextra -Wno-main -Werror -mfp32 -mno-abicalls -fno-pic -fdata-sections -ffunction-sections -fno-builtin -nostdlib -DTONYHAX_VERSION=$(TONYHAX_VERSION) -DROM - -LD=mips-linux-gnu-ld -LDFLAGS=--gc-sections - -OBJCOPY=mips-linux-gnu-objcopy -OBJCOPYFLAGS=-O binary - -# Entry point variables - -ENTRY_MCS := \ - $(patsubst $(SELF_DIR)/entrypoints/%-tpl.mcs, %.mcs, $(wildcard $(SELF_DIR)/entrypoints/*-tpl.mcs)) \ - FF9-A-JP/ff9-a-jp.mcs \ - FF9-B-JP/ff9-b-jp.mcs \ - FF9-A-US/ff9-a-us.mcs \ - FF9-B-US/ff9-b-us.mcs - -ENTRY_RAW := \ - FF9-A-JP/BISLPS-0200000000-00 \ - FF9-B-JP/BISLPS-0200000000-00 \ - FF9-A-US/BASLUS-0125100000-00 \ - FF9-B-US/BASLUS-0125100000-00 \ - BISLPS-01391SKI00S \ - BISLPS-00300TEKKEN-2 \ - BISLPS-01300TEKKEN-3 \ - BISLPM-86922CHSVTRv1 \ - BISLPM-86489CHSv1 \ - BISLPM-86751CEEAG01 \ - BISLPM-86754DRACULA \ - BISLPS-01323010001 \ - BISCPS-1004700000000 \ - BISCPS-1007300000000 \ - BISLPS-00130DOKIOH \ - BASCUS-9415400047975 \ - BASCUS-9424400000000 \ - BASCUS-9455916 \ - BASLUS-00213TEKKEN-2 \ - BASLUS-00402TEKKEN-3 \ - BASLUS-00571 \ - BASLUS-00856 \ - BASLUS-00882CHSv1 \ - BASLUS-01066TNHXG01 \ - BASLUS-01384DRACULA \ - BASLUS-01419TNHXG01 \ - BASLUS-01485TNHXG01 \ - BASLUS-01506XSMOTOv1 \ - BESCES-00255TEKKEN-2 \ - BESCES-01237TEKKEN-3 \ - BESCES-0096700765150 \ - BESCES-0142000000000 \ - BESCES-0228316 \ - BESLES_01182CHSv1 \ - BESLES-01376 \ - BESLES-02618 \ - BESLES-02908TNHXG01 \ - BESLES-02909TNHXG01 \ - BESLES-02910TNHXG01 \ - BESLES-02942CHSVTRv1 \ - BESLES-03057SSBv1 \ - BESLES-03645TNHXG01 \ - BESLES-03646TNHXG01 \ - BESLES-03647TNHXG01 \ - BESLES-03827SSII \ - BESLES-03954TNHXG01 \ - BESLES-03955TNHXG01 \ - BESLES-03956TNHXG01 \ - BESLES-04095XSMOTO - -ENTRY_FILES := $(ENTRY_MCS) $(ENTRY_RAW) entry-bb.bin entry.bin - -# Program loader variables - -LOADER_FILES := orca.inc tonyhax.mcs HAX tonyhax.exe - -# FreePSXBoot images - -FREEPSXBOOT_IMAGES := \ - tonyhax_scph-1000_slot1.mcr \ - tonyhax_scph-1000_slot2.mcr \ - tonyhax_scph-3000_v1.1_slot1.mcr \ - tonyhax_scph-3000_v1.1_slot2.mcr \ - tonyhax_scph-3000_v2.1_slot1.mcr \ - tonyhax_scph-3000_v2.1_slot2.mcr \ - tonyhax_scph-3500_slot1.mcr \ - tonyhax_scph-3500_slot2.mcr \ - tonyhax_scph-5000_slot1.mcr \ - tonyhax_scph-5000_slot2.mcr \ - tonyhax_scph-5500_slot1.mcr \ - tonyhax_scph-5500_slot2.mcr \ - tonyhax_scph-7000_slot1.mcr \ - tonyhax_scph-7000_slot2.mcr \ - tonyhax_scph-7500_slot1.mcr \ - tonyhax_scph-7500_slot2.mcr \ - tonyhax_scph-9000_slot1.mcr \ - tonyhax_scph-9000_slot2.mcr \ - tonyhax_scph-100_slot1.mcr \ - tonyhax_scph-100_slot2.mcr \ - tonyhax_scph-1001_v2.0_slot1.mcr \ - tonyhax_scph-1001_v2.0_slot2.mcr \ - tonyhax_scph-1001_v2.1_slot1.mcr \ - tonyhax_scph-1001_v2.1_slot2.mcr \ - tonyhax_scph-1001_v2.2_slot1.mcr \ - tonyhax_scph-1001_v2.2_slot2.mcr \ - tonyhax_scph-1002_v2.0_slot1.mcr \ - tonyhax_scph-1002_v2.0_slot2.mcr \ - tonyhax_scph-1002_v2.1_slot1.mcr \ - tonyhax_scph-1002_v2.1_slot2.mcr \ - tonyhax_scph-1002_v2.2_slot1.mcr \ - tonyhax_scph-1002_v2.2_slot2.mcr \ - tonyhax_scph-5001_slot1.mcr \ - tonyhax_scph-5001_slot2.mcr \ - tonyhax_scph-5501_slot1.mcr \ - tonyhax_scph-5501_slot2.mcr \ - tonyhax_scph-5502_slot1.mcr \ - tonyhax_scph-5502_slot2.mcr \ - tonyhax_scph-5552_slot1.mcr \ - tonyhax_scph-5552_slot2.mcr \ - tonyhax_scph-7001_slot1.mcr \ - tonyhax_scph-7001_slot2.mcr \ - tonyhax_scph-7002_slot1.mcr \ - tonyhax_scph-7002_slot2.mcr \ - tonyhax_scph-7501_slot1.mcr \ - tonyhax_scph-7501_slot2.mcr \ - tonyhax_scph-7502_slot1.mcr \ - tonyhax_scph-7502_slot2.mcr \ - tonyhax_scph-9001_slot1.mcr \ - tonyhax_scph-9001_slot2.mcr \ - tonyhax_scph-9002_slot1.mcr \ - tonyhax_scph-9002_slot2.mcr \ - tonyhax_scph-101_v4.4_slot1.mcr \ - tonyhax_scph-101_v4.4_slot2.mcr \ - tonyhax_scph-101_v4.5_slot1.mcr \ - tonyhax_scph-101_v4.5_slot2.mcr \ - tonyhax_scph-102_v4.4_slot1.mcr \ - tonyhax_scph-102_v4.4_slot2.mcr \ - tonyhax_scph-102_v4.5_slot1.mcr \ - tonyhax_scph-102_v4.5_slot2.mcr - -# Boot CD files - -BOOT_CD_FILES := tonyhax-boot-cd-japan.bin tonyhax-boot-cd-japan.cue tonyhax-boot-cd-europe.bin tonyhax-boot-cd-europe.cue - -# ROM files - -ROM_FILES := tonyhax-international-$(TONYHAX_VERSION).rom tonyhax-rom-flasher.bin tonyhax-rom-flasher.cue diff --git a/variables.mk.tocperfect b/variables.mk.tocperfect index 14629a5..d521f83 100644 --- a/variables.mk.tocperfect +++ b/variables.mk.tocperfect @@ -5,153 +5,5 @@ SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -# Common variables - -TONYHAX_VERSION=v1.3.3-tocperfect - -CC=mips-linux-gnu-gcc +TONYHAX_VERSION=v1.3.4-tocperfect CFLAGS=-Os -Wall -Wextra -Wno-main -Werror -mfp32 -mno-abicalls -fno-pic -fdata-sections -ffunction-sections -fno-builtin -nostdlib -DTONYHAX_VERSION=$(TONYHAX_VERSION) -DTOCPERFECT - -LD=mips-linux-gnu-ld -LDFLAGS=--gc-sections - -OBJCOPY=mips-linux-gnu-objcopy -OBJCOPYFLAGS=-O binary - -# Entry point variables - -ENTRY_MCS := \ - $(patsubst $(SELF_DIR)/entrypoints/%-tpl.mcs, %.mcs, $(wildcard $(SELF_DIR)/entrypoints/*-tpl.mcs)) \ - FF9-A-JP/ff9-a-jp.mcs \ - FF9-B-JP/ff9-b-jp.mcs \ - FF9-A-US/ff9-a-us.mcs \ - FF9-B-US/ff9-b-us.mcs - -ENTRY_RAW := \ - FF9-A-JP/BISLPS-0200000000-00 \ - FF9-B-JP/BISLPS-0200000000-00 \ - FF9-A-US/BASLUS-0125100000-00 \ - FF9-B-US/BASLUS-0125100000-00 \ - BISLPS-01391SKI00S \ - BISLPS-00300TEKKEN-2 \ - BISLPS-01300TEKKEN-3 \ - BISLPM-86922CHSVTRv1 \ - BISLPM-86489CHSv1 \ - BISLPM-86751CEEAG01 \ - BISLPM-86754DRACULA \ - BISLPS-01323010001 \ - BISCPS-1004700000000 \ - BISCPS-1007300000000 \ - BISLPS-00130DOKIOH \ - BASCUS-9415400047975 \ - BASCUS-9424400000000 \ - BASCUS-9455916 \ - BASLUS-00213TEKKEN-2 \ - BASLUS-00402TEKKEN-3 \ - BASLUS-00571 \ - BASLUS-00856 \ - BASLUS-00882CHSv1 \ - BASLUS-01066TNHXG01 \ - BASLUS-01384DRACULA \ - BASLUS-01419TNHXG01 \ - BASLUS-01485TNHXG01 \ - BASLUS-01506XSMOTOv1 \ - BESCES-00255TEKKEN-2 \ - BESCES-01237TEKKEN-3 \ - BESCES-0096700765150 \ - BESCES-0142000000000 \ - BESCES-0228316 \ - BESLES_01182CHSv1 \ - BESLES-01376 \ - BESLES-02618 \ - BESLES-02908TNHXG01 \ - BESLES-02909TNHXG01 \ - BESLES-02910TNHXG01 \ - BESLES-02942CHSVTRv1 \ - BESLES-03057SSBv1 \ - BESLES-03645TNHXG01 \ - BESLES-03646TNHXG01 \ - BESLES-03647TNHXG01 \ - BESLES-03827SSII \ - BESLES-03954TNHXG01 \ - BESLES-03955TNHXG01 \ - BESLES-03956TNHXG01 \ - BESLES-04095XSMOTO - -ENTRY_FILES := $(ENTRY_MCS) $(ENTRY_RAW) entry-bb.bin entry.bin - -# Program loader variables - -LOADER_FILES := orca.inc tonyhax.mcs HAX tonyhax.exe - -# FreePSXBoot images - -FREEPSXBOOT_IMAGES := \ - tonyhax_scph-1000_slot1.mcr \ - tonyhax_scph-1000_slot2.mcr \ - tonyhax_scph-3000_v1.1_slot1.mcr \ - tonyhax_scph-3000_v1.1_slot2.mcr \ - tonyhax_scph-3000_v2.1_slot1.mcr \ - tonyhax_scph-3000_v2.1_slot2.mcr \ - tonyhax_scph-3500_slot1.mcr \ - tonyhax_scph-3500_slot2.mcr \ - tonyhax_scph-5000_slot1.mcr \ - tonyhax_scph-5000_slot2.mcr \ - tonyhax_scph-5500_slot1.mcr \ - tonyhax_scph-5500_slot2.mcr \ - tonyhax_scph-7000_slot1.mcr \ - tonyhax_scph-7000_slot2.mcr \ - tonyhax_scph-7500_slot1.mcr \ - tonyhax_scph-7500_slot2.mcr \ - tonyhax_scph-9000_slot1.mcr \ - tonyhax_scph-9000_slot2.mcr \ - tonyhax_scph-100_slot1.mcr \ - tonyhax_scph-100_slot2.mcr \ - tonyhax_scph-1001_v2.0_slot1.mcr \ - tonyhax_scph-1001_v2.0_slot2.mcr \ - tonyhax_scph-1001_v2.1_slot1.mcr \ - tonyhax_scph-1001_v2.1_slot2.mcr \ - tonyhax_scph-1001_v2.2_slot1.mcr \ - tonyhax_scph-1001_v2.2_slot2.mcr \ - tonyhax_scph-1002_v2.0_slot1.mcr \ - tonyhax_scph-1002_v2.0_slot2.mcr \ - tonyhax_scph-1002_v2.1_slot1.mcr \ - tonyhax_scph-1002_v2.1_slot2.mcr \ - tonyhax_scph-1002_v2.2_slot1.mcr \ - tonyhax_scph-1002_v2.2_slot2.mcr \ - tonyhax_scph-5001_slot1.mcr \ - tonyhax_scph-5001_slot2.mcr \ - tonyhax_scph-5501_slot1.mcr \ - tonyhax_scph-5501_slot2.mcr \ - tonyhax_scph-5502_slot1.mcr \ - tonyhax_scph-5502_slot2.mcr \ - tonyhax_scph-5552_slot1.mcr \ - tonyhax_scph-5552_slot2.mcr \ - tonyhax_scph-7001_slot1.mcr \ - tonyhax_scph-7001_slot2.mcr \ - tonyhax_scph-7002_slot1.mcr \ - tonyhax_scph-7002_slot2.mcr \ - tonyhax_scph-7501_slot1.mcr \ - tonyhax_scph-7501_slot2.mcr \ - tonyhax_scph-7502_slot1.mcr \ - tonyhax_scph-7502_slot2.mcr \ - tonyhax_scph-9001_slot1.mcr \ - tonyhax_scph-9001_slot2.mcr \ - tonyhax_scph-9002_slot1.mcr \ - tonyhax_scph-9002_slot2.mcr \ - tonyhax_scph-101_v4.4_slot1.mcr \ - tonyhax_scph-101_v4.4_slot2.mcr \ - tonyhax_scph-101_v4.5_slot1.mcr \ - tonyhax_scph-101_v4.5_slot2.mcr \ - tonyhax_scph-102_v4.4_slot1.mcr \ - tonyhax_scph-102_v4.4_slot2.mcr \ - tonyhax_scph-102_v4.5_slot1.mcr \ - tonyhax_scph-102_v4.5_slot2.mcr - -# Boot CD files - -BOOT_CD_FILES := tonyhax-boot-cd-japan.bin tonyhax-boot-cd-japan.cue tonyhax-boot-cd-europe.bin tonyhax-boot-cd-europe.cue - -# ROM files - -ROM_FILES := tonyhax-international-$(TONYHAX_VERSION).rom tonyhax-rom-flasher.bin tonyhax-rom-flasher.cue diff --git a/variables.mk.xstation b/variables.mk.xstation new file mode 100644 index 0000000..6bfe502 --- /dev/null +++ b/variables.mk.xstation @@ -0,0 +1,9 @@ + +.DELETE_ON_ERROR: + +.PHONY: clean + +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +TONYHAX_VERSION=v1.3.4-xstation +CFLAGS=-Os -Wall -Wextra -Wno-main -Werror -mfp32 -mno-abicalls -fno-pic -fdata-sections -ffunction-sections -fno-builtin -nostdlib -DTONYHAX_VERSION=$(TONYHAX_VERSION) -DXSTATION -DROM diff --git a/xstation.md b/xstation.md new file mode 100644 index 0000000..08bb9bb --- /dev/null +++ b/xstation.md @@ -0,0 +1,13 @@ +# XStation Flashed Cheat Cart + +You can overwrite the contents of a GameShark, Action Reply, or other PS1 cheat cartridge with _a special version of the Tonyhax International loader_ to significantly speed up the boot time of consoles hard-modded with the xStation device. This feature was [asked for](https://github.com/alex-free/tonyhax/issues/29) by [L10N37](https://github.com/L10N37) after he pointed out that using the Tonyhax International loader via flashed cheat cart is significantly faster then the stock Sony BIOS when it comes to booting the xStation firmware. + +The instructions for installing the xStation version of the Tonyhax International rom are identical to the normal [flashed cheat cart](flashed-cheat-cart.md) instructions, except you want to use these files in the `xstation` directory found in the Tonyhax International releases: + +* tonyhax-x-rom-flasher.bin +* tonyhax-x-rom-flasher.cue +* tonyhax-x-*-international.rom + +If you use the `Fast Boot` option in the xStation firmware, your game will immediately start. + +If you use the `Full Boot` option in the xStation firmware, Tonyhax International itself will load the game. You will need to open/close the drive lid after using the full boot method (which allows you to enter the Sony BIOS or enable [GameShark codes](gameshark-code-support.md) when the lid is open). diff --git a/xstation/Makefile b/xstation/Makefile new file mode 100644 index 0000000..fd64b58 --- /dev/null +++ b/xstation/Makefile @@ -0,0 +1,15 @@ + +# Thanks to whoever made https://devhints.io/makefile! + +include ../variables.mk +include ../variables-shared.mk + +.PHONY: clean + +all: $(X_ROM_FILES) + +clean: + $(RM) $(X_ROM_FILES) + +$(X_ROM_FILES): ../loader/tonyhax.exe cd.xml ../boot-cd/licensej.dat ../nxflash/CDFILES/system.cnf + cd ../psexe2rom; make clean; make; rm -f romfile.dat; ./psexe2rom -d ../loader/tonyhax.exe ../xstation/tonyhax-international-x-$(TONYHAX_VERSION).rom; cp -r ../psexe2rom/romfile.dat ../boot-cd/licensej.dat ../nxflash/CDFILES/system.cnf ../nxflash/NXFLASH.EXE ../xstation; cd ../xstation; mkpsxiso -y cd.xml; rm -rf romfile.dat NXFLASH.EXE licensej.dat system.cnf ../psexe2rom/romfile.dat ../nxflash/tonyhax-international-x$(TONYHAX_VERSION).rom diff --git a/xstation/cd.xml b/xstation/cd.xml new file mode 100644 index 0000000..6536196 --- /dev/null +++ b/xstation/cd.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + +