Use PSP platform to disassemble PSP overlays (#1118)

Having `platform: psx` will not correctly disassemble PSP functions with
opcodes that are not part of the R3000 (the PSX CPU) architecture. These
functions would be disassembled by Splat as a bunch of `.word
0xBLAHBLAH`.

Changing the platform to `psp` introduces all sort of new challenges.
Function prototypes needs to be declared earlier. But also the MWCC
compiler will not accept the `%lo` and `%hi` dialect from GNU AS. There
were some patches on `mwcpp.py` to use `la SYMBOL_NAME` that would
expand into a `lui / addiu` combo. But even though symbols needs to be
declared like function prototypes at the top of the file. This is simply
not feasible on bigger overlays.

As a solution to the problem above, I replaced the existing patches by
converting instructions into `.word`. The overlay cannot longer be
relocated with this approach, but it is not an issue as the final goal
is to decompile these functions any way.

The labels in the jump table has the same problem, which forced me to
change the segment type from `rodata` to `data.

This is just another single step to create the conditions to start
including bigger re-compilable PSP overlays. I am sure the `mwcpp.py`
solution will be thrown into the bin at some point, but this PR improves
our current situation.
This commit is contained in:
Luciano Ciccariello 2024-05-06 19:35:28 +01:00 committed by GitHub
parent 78e0739a6c
commit 18f2bde385
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 29 additions and 67 deletions

View File

@ -1,5 +1,5 @@
options:
platform: psx
platform: psp
basename: tt_000
base_path: ..
build_path: build/pspeu
@ -37,6 +37,6 @@ segments:
subsegments:
- [0x80, c, 10E8]
- [0x4C80, data]
- [0x5E00, rodata]
- [0x5E00, data] # rodata, not data
- {type: bss, vram: 0x092ed480}
- [0x5E80]

View File

@ -1,3 +1,6 @@
abs = 0x08906AF0;
memcpy = 0x08909F84;
rand = 0x0890B954;
LoadImage = 0x0891bfe4;
SquareRoot12 = 0x08927ccc;
ratan2 = 0x08927cfc;

View File

@ -16,3 +16,5 @@ extern void* malloc(size_t // Size of memory block to be allocated
);
extern void free(void*);
int printf(char*, ...);
int abs(int x);

View File

@ -66,7 +66,6 @@ extern EntitySearch D_80171094[];
#ifdef VERSION_PSP
extern ServantDesc D_8D1DC40;
void func_8909F84(ServantDesc* dst, ServantDesc* src, int len);
#endif
#endif

View File

@ -1,5 +1,6 @@
#include <servant.h>
#include <sfx.h>
#include <psxsdk/libc.h>
#define SFX_BAT_SCREECH SOUND_BAT_SCREECH
#define SFX_BAT_NOTIFY SE_UI_OVERWRITE_MSG
@ -71,8 +72,12 @@ extern s32 D_80174D3C;
void DestroyEntity();
s32 func_80174864(void);
void func_8909F84();
s32 func_801746A0(s32 arg0);
void ProcessEvent();
void CreateEventEntity(Entity* entityParent, s32 entityId, s32 params);
void func_80173F74();
void func_80173F30();
#endif
@ -1490,6 +1495,6 @@ s32 func_80174864(void) {
#ifdef VERSION_PSP
void func_092EC220(void) {
func_8909F84(&D_8D1DC40, &g_ServantDesc, sizeof(ServantDesc));
memcpy((u8*)&D_8D1DC40, (u8*)&g_ServantDesc, sizeof(ServantDesc));
}
#endif

View File

@ -7,6 +7,7 @@ from typing import TextIO
r_lui = r"\s*lui\s*\$(.*),\s\%hi\((.*)\)"
r_lui_addiu_combo = r"\s*addiu\s*\$(.*),\s\$(.*),\s\%lo\((.*)\)"
r_hilo = r"\/\*\s*\w*\s*\w*\s*(\w*)\s*\*\/\s*\w*\s*\$\w*,.*(?:%hi|%lo).*"
r_hi = r"%hi\((.*)\)"
r_lo = r"%lo\((.*)\)\(|%lo\((.*)\)"
r_jalr = r"jalr\s*\$([a-z][a-z0-9])"
@ -37,41 +38,18 @@ def process_asm_line(asm_f: TextIO, line: str) -> str | None:
if "#" in line:
line = line.split("#")[0] + "\n"
# look for a LUI/ADDIU combo
match_lui = re.search(r_lui, line)
if match_lui:
dst_reg = match_lui.group(1)
src_sym = match_lui.group(2)
second_line = asm_f.readline()
match_lui_addiu_combo = re.search(r_lui_addiu_combo, second_line)
if match_lui_addiu_combo:
dst_reg_2 = match_lui_addiu_combo.group(1)
src_reg_2 = match_lui_addiu_combo.group(2)
src_sym_2 = match_lui_addiu_combo.group(3)
if dst_reg == dst_reg_2 and src_reg_2 == dst_reg_2 and src_sym == src_sym_2:
return f"la ${dst_reg}, {src_sym}\n"
second_line = process_asm_line(asm_f, second_line)
line = line.replace(f"%hi({src_sym})", f"({src_sym})@ha")
return line + second_line
# use symbol@h instead of %hi(symbol)
himatch = re.search(r_hi, line)
if himatch:
symbol_name = himatch.group(1)
return line.replace(f"%hi({symbol_name})", f"({symbol_name})@ha")
# use symbol@l instead of %lo(symbol)
lomatch = re.search(r_lo, line)
if lomatch:
symbol_name = lomatch.group(1)
return line.replace(f"%lo({symbol_name})", f"({symbol_name}@l)")
# jalr needs two arguments
jalr_match = re.search(r_jalr, line)
if jalr_match:
reg_name = jalr_match.group(1)
return line.replace(reg_name, f"ra, ${reg_name}")
r_hilo_match = re.search(r_hilo, line)
if r_hilo_match:
raw_data = r_hilo_match.group(1)
if len(raw_data) == 8:
return f".word 0x{raw_data[6:8]}{raw_data[4:6]}{raw_data[2:4]}{raw_data[0:2]}\n"
# return unpatched assembly line
return line

View File

@ -87,41 +87,16 @@ LHELLO:
""",
)
def test_fix_lui_addiu_combo(self):
def test_fix_lo_hi(self):
self.assertEqual(
self.helper_process_lines(
"""lui $a0, %hi(D_8D1DC40)
/* some stuff */ addiu $a0, $a0, %lo(D_8D1DC40)
"""/* XXXX 09012348 DEADBEEF */ lui $v1, %hi(D_92EFFDE)
/* XXXX 09012344 BADC0FFE */ lh $a0, %lo(D_92EFFDE)
"""
),
"""asm void func_name() {
la $a0, D_8D1DC40
}
""",
)
def test_fix_lui_lh_combo(self):
self.assertEqual(
self.helper_process_lines(
"""lui $v1, %hi(D_92EFFDE)
/* some stuff */ lh $a0, -0x2948($v1)
"""
),
"""asm void func_name() {
lui $v1, (D_92EFFDE)@ha
/* some stuff */ lh $a0, -0x2948($v1)
}
""",
)
def test_fix_lower_16bit(self):
self.assertEqual(
self.helper_process_lines(
"""lw $s1, %lo(g_EventQueue)($v1)
"""
),
"""asm void func_name() {
lw $s1, (g_EventQueue@l)($v1)
.word 0xEFBEADDE
.word 0xFE0FDCBA
}
""",
)

View File

@ -11,10 +11,10 @@ mapfile-parser==2.1.4
tabulate
requests
graphviz
splat64>=0.23.2,<0.24.0
splat64>=0.24.1,<0.25.0
crunch64
spimdisasm>=1.24.3,<1.25.0
rabbitizer>=1.9.5,<1.10.0
spimdisasm>=1.25.0
rabbitizer>=1.10.0
n64img==0.3.3
PyYAML
pylibyaml