Skip to content

Commit 672bebf

Browse files
committed
Implement conditional patch copying
1 parent bebb0ba commit 672bebf

File tree

7 files changed

+101
-115
lines changed

7 files changed

+101
-115
lines changed

loader/Makefile

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
include ../variables.mk
55

6-
LOADER_AUTOGEN := orca.inc patches.inc
6+
LOADER_AUTOGEN := orca.inc
77
LOADER_HEADERS := $(wildcard *.h) $(LOADER_AUTOGEN)
88
LOADER_OBJECTS := $(patsubst %.c, %.o, $(patsubst %.S, %.o, $(wildcard *.c *.S)))
99

@@ -12,14 +12,6 @@ all: $(LOADER_FILES)
1212
clean:
1313
$(RM) $(LOADER_FILES) *.o *.elf $(LOADER_AUTOGEN)
1414

15-
# BIOS patches
16-
17-
patches.elf: patches.S
18-
$(CC) $(CFLAGS) patches.S -o patches.elf
19-
20-
patches.inc: patches.elf
21-
bash ../util/elf2h.sh BIOS_PATCHES patches.elf patches.inc
22-
2315
# Intermediate objects
2416

2517
%.o: %.c $(LOADER_HEADERS)

loader/patches.S renamed to loader/patch-ap.S

Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,6 @@
22
#include <regdef.h>
33

44
.text
5-
.globl __start
6-
__start:
7-
8-
/*
9-
* The anti-FreePSXBoot patch.
10-
*
11-
* This patch is called right at the very end of the last step in the read sector finite state
12-
* machine:
13-
* https://github.com/grumpycoders/pcsx-redux/blob/f6484e8010a40a81e4019d9bfa1a9d408637b614/src/mips/openbios/sio0/card.c#L194
14-
*
15-
* When this code is executed, the registers are as follows:
16-
* - v0 contains 1, or "success".
17-
* - a1 contains the read buffer
18-
* - a2 contains the current sector number
19-
*
20-
* If the sector being read is sector 0 and it contains "FPBZ" at +0x7C, we modify the read data
21-
* so it is detected as corrupted and the game skips reading from it
22-
*
23-
* The offsets have been checked against BIOSes 2.2, 3.0, 4.1 and 4.4
24-
*/
25-
.globl antifpxpatch
26-
antifpxpatch:
27-
lw t0, 0x7C(a1)
28-
li t1, 0x5A425046
29-
bne a2, 0, fpxret
30-
bne t0, t1, fpxret
31-
32-
sw zero, 0(a1)
33-
fpxret:
34-
j 0x5B54
355

366
/*
377
* Intercepts the syscall(1) (aka EnterCriticalSection).
@@ -40,8 +10,8 @@ fpxret:
4010
* - v0: saved thread registers, must NOT be modified.
4111
* The rest of the registers are not critical and can be used freely.
4212
*/
43-
.globl modchipstart
44-
modchipstart:
13+
.globl patch_ap_start
14+
patch_ap_start:
4515
// Load the SP value
4616
lw t0, 0x7C(v0)
4717

@@ -51,7 +21,7 @@ modchipstart:
5121
*/
5222
srl t1, t0, 16
5323
xori t1, 0xA000
54-
beq t1, zero, modchipcontinue
24+
beq t1, zero, patch_ap_skip
5525

5626
/*
5727
* If we are being called from an antimodchip module, the call stack will look like this:
@@ -80,7 +50,7 @@ modchipstart:
8050
*/
8151
li t2, 0x7F800003
8252
and t2, t1
83-
bne t2, zero, modchipcontinue
53+
bne t2, zero, patch_ap_skip
8454

8555
/*
8656
* First, we will attempt to handle a version 1 antimodchip module.
@@ -116,11 +86,11 @@ modchipstart:
11686
// Compare signature, and test for v2 if does not match
11787
lw t2, 0x74(t1)
11888
li t3, 0x3C02E600
119-
bne t2, t3, modchipv15
89+
bne t2, t3, patch_ap_v15
12090

12191
lw t2, 0x78(t1)
12292
li t3, 0x34420002
123-
bne t2, t3, modchipv15
93+
bne t2, t3, patch_ap_v15
12494

12595
// Load return address from ap_failed to ap_check
12696
lw t1, 0xE8(t0)
@@ -129,7 +99,7 @@ modchipstart:
12999
addi t0, 0xF0
130100

131101
// Save and return
132-
b modchipsave
102+
b patch_ap_save
133103

134104
/*
135105
* Handle another variant of the v1, used by Vandal Hearts II - Tenjou no Mon (J) (SLPM-86251)
@@ -144,14 +114,14 @@ modchipstart:
144114
*
145115
* The offsets are the same as for v2, so we will reuse those adjusts.
146116
*/
147-
modchipv15:
117+
patch_ap_v15:
148118
lw t2, 0x64(t1)
149119
li t3, 0x3C03E600
150-
bne t2, t3, modchipv2
120+
bne t2, t3, patch_ap_v2
151121

152122
lw t2, 0x68(t1)
153123
li t3, 0x34630002
154-
beq t2, t3, adjustv2
124+
beq t2, t3, patch_ap_adjust_v2
155125

156126
/*
157127
* We will now attempt to patch an antimodchip v2 module.
@@ -177,24 +147,24 @@ modchipv15:
177147
*
178148
* If that exists, we will patch the thread state to return back to ap_check.
179149
*/
180-
modchipv2:
150+
patch_ap_v2:
181151
// Compare signature
182152
lw t2, 0x18(t1)
183153
li t3, 0x3C011F80
184-
bne t2, t3, modchipcontinue
154+
bne t2, t3, patch_ap_skip
185155

186156
lw t2, 0x1C(t1)
187157
li t3, 0xA4201DAA
188-
bne t2, t3, modchipcontinue
158+
bne t2, t3, patch_ap_skip
189159

190-
adjustv2:
160+
patch_ap_adjust_v2:
191161
// Load return address to from ap_failed to ap_check
192162
lw t1, 0x120(t0)
193163

194164
// Adjust stack pointer
195165
addi t0, 0x128
196166

197-
modchipsave:
167+
patch_ap_save:
198168
// Zero the s0 and s1 stored in the thread state, so the state machine used by ap_check exits
199169
sw zero, 0x48(v0)
200170
sw zero, 0x4C(v0)
@@ -203,10 +173,13 @@ modchipsave:
203173
sw t0, 0x7C(v0)
204174
sw t1, 0x88(v0)
205175

206-
.globl modchipreturn
207-
modchipreturn:
176+
.globl patch_ap_success
177+
patch_ap_success:
208178
j 0x12341234
209179

210-
.globl modchipcontinue
211-
modchipcontinue:
180+
.globl patch_ap_skip
181+
patch_ap_skip:
212182
j 0x12341234
183+
184+
.globl patch_ap_end
185+
patch_ap_end:

loader/patch-fpb.S

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
#include <regdef.h>
3+
4+
.text
5+
6+
/*
7+
* The anti-FreePSXBoot patch.
8+
*
9+
* This patch is called right at the very end of the last step in the read sector finite state
10+
* machine:
11+
* https://github.com/grumpycoders/pcsx-redux/blob/f6484e8010a40a81e4019d9bfa1a9d408637b614/src/mips/openbios/sio0/card.c#L194
12+
*
13+
* When this code is executed, the registers are as follows:
14+
* - v0 contains 1, or "success".
15+
* - a1 contains the read buffer
16+
* - a2 contains the current sector number
17+
*
18+
* If the sector being read is sector 0 and it contains "FPBZ" at +0x7C, we modify the read data
19+
* so it is detected as corrupted and the game skips reading from it
20+
*
21+
* The offsets have been checked against BIOSes 2.2, 3.0, 4.1 and 4.4
22+
*/
23+
.globl patch_fpb_start
24+
patch_fpb_start:
25+
lw t0, 0x7C(a1)
26+
li t1, 0x5A425046
27+
bne a2, 0, patch_fpb_ret
28+
bne t0, t1, patch_fpb_ret
29+
30+
sw zero, 0(a1)
31+
patch_fpb_ret:
32+
j 0x5B54
33+
34+
.globl patch_fpb_end
35+
patch_fpb_end:

loader/patcher.c

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
#include "str.h"
55
#include "patcher.h"
66

7-
#include "patches.inc"
7+
extern uint8_t patch_ap_start;
8+
extern uint8_t patch_ap_end;
9+
extern uint8_t patch_ap_skip;
10+
extern uint8_t patch_ap_success;
11+
12+
extern uint8_t patch_fpb_start;
13+
extern uint8_t patch_fpb_end;
814

915
inline uint32_t encode_j(const void * addr) {
1016
return 0x08000000 | (((uint32_t) addr >> 2) & 0x3FFFFFF);
@@ -14,8 +20,8 @@ inline uint32_t encode_jal(const void * addr) {
1420
return 0x0C000000 | (((uint32_t) addr >> 2) & 0x3FFFFFF);
1521
}
1622

17-
void install_modchip_patch(uint8_t * patches_addr) {
18-
debug_write("Installing modchip patch");
23+
uint8_t * install_generic_modchip_patch(uint8_t * install_addr) {
24+
debug_write(" * Generic antimodchip");
1925

2026
// Get the handler info structure
2127
handler_info_t * syscall_handler = bios_get_syscall_handler();
@@ -30,47 +36,61 @@ void install_modchip_patch(uint8_t * patches_addr) {
3036
*/
3137
uint32_t lw_op = verifier[20];
3238
if ((lw_op >> 16) != 0x8C39) {
33-
debug_write("Check failed!");
34-
return;
39+
debug_write("Aborted! Please report this!");
40+
return install_addr;
3541
}
42+
43+
// Extract location of cases array
3644
void ** cases_array = (void **) (lw_op & 0xFFFF);
3745

46+
// Copy blob
47+
memcpy(install_addr, &patch_ap_start, &patch_ap_end - &patch_ap_start);
48+
3849
/*
3950
* Insert the jump to the original code, which we'll use if the call was not originated from
4051
* an antipiracy module.
4152
*/
42-
*((uint32_t *) (patches_addr + BIOS_PATCHES_MODCHIPCONTINUE)) = encode_j(cases_array[1]);
53+
*((uint32_t *) (install_addr + (&patch_ap_skip - &patch_ap_start))) = encode_j(cases_array[1]);
4354

4455
/*
4556
* Insert the jump we'll use to exit the exception handler once we have finished patching up
4657
* the thread state if the call was indeed originated from an antipiracy module.
4758
*
4859
* We'll use the address of syscall(0) which behaves as a nop to exit the exception.
4960
*/
50-
*((uint32_t *) (patches_addr + BIOS_PATCHES_MODCHIPRETURN)) = encode_j(cases_array[0]);
61+
*((uint32_t *) (install_addr + (&patch_ap_success - &patch_ap_start))) = encode_j(cases_array[0]);
5162

5263
// Finally replace
53-
cases_array[1] = patches_addr + BIOS_PATCHES_MODCHIPSTART;
64+
cases_array[1] = install_addr;
65+
66+
return install_addr + (&patch_ap_end - &patch_ap_start);
5467
}
5568

56-
void install_fpx_patch(uint8_t * patches_addr) {
57-
if (!bios_is_ps1()) {
58-
return;
59-
}
69+
uint8_t * install_fpb_patch(uint8_t * install_addr) {
70+
debug_write(" * FreePSXBoot");
71+
72+
// Copy blob
73+
memcpy(install_addr, &patch_fpb_start, &patch_fpb_end - &patch_fpb_start);
6074

61-
debug_write("Installing FreePSXBoot patch");
62-
*((uint32_t *) 0x5B40) = encode_jal(patches_addr + BIOS_PATCHES_ANTIFPXPATCH);
75+
// Install it
76+
*((uint32_t *) 0x5B40) = encode_jal(install_addr);
77+
78+
// Advance installation address
79+
return install_addr + (&patch_fpb_end - &patch_fpb_start);
6380
}
6481

6582
void patcher_apply(void) {
6683
// We have plenty of space at the end of table B
67-
uint8_t * start_addr = (uint8_t *) (GetB0Table() + 0x5E);
68-
69-
// Copy patches
70-
debug_write("Copying patches to %x", (uint32_t) start_addr);
71-
memcpy(start_addr, BIOS_PATCHES_BLOB, sizeof(BIOS_PATCHES_BLOB));
84+
uint8_t * install_addr = (uint8_t *) (GetB0Table() + 0x5E);
7285

7386
// Install patches
74-
install_modchip_patch(start_addr);
75-
install_fpx_patch(start_addr);
87+
debug_write("Installing patches:");
88+
89+
// Generic antimodchip, which works on pretty much every game with antipiracy
90+
install_addr = install_generic_modchip_patch(install_addr);
91+
92+
// FreePSXBoot does not work on PS2 so skip its installation
93+
if (bios_is_ps1()) {
94+
install_addr = install_fpb_patch(install_addr);
95+
}
7696
}

loader/secondary.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ void main() {
313313

314314
debug_write("Integrity check %sed", integrity_ok ? "pass" : "fail");
315315
if (!integrity_ok) {
316-
return;
316+
//return;
317317
}
318318

319319
bios_inject_disc_error();

loader/secondary.ld

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ SECTIONS {
3030
PROVIDE(__BSS_END__ = .);
3131
/DISCARD/ :
3232
{
33-
*(.MIPS.abiflags)
34-
*(.pdr)
35-
*(.gnu.attributes)
36-
*(.comment)
37-
*(.reginfo)
33+
*(*)
3834
}
3935
}
4036
ENTRY (start)

util/elf2h.sh

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)