Skip to content

Commit 6ce9c91

Browse files
authored
create_config: Avoid emitting relocations for addresses paired by using ori for N64 (#516)
* create_config: Avoid emitting relocations for addresses paired by using ori * Update tests * Cleanup * forgor to push * a
1 parent c8f0e5b commit 6ce9c91

File tree

8 files changed

+518
-104
lines changed

8 files changed

+518
-104
lines changed

.github/workflows/lint.yml

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,8 @@ jobs:
4545
pip install -r requirements.txt
4646
pip install types-PyYAML
4747
48-
- name: ruff split
49-
run: ruff check split.py
50-
51-
- name: ruff create_config
52-
run: ruff check create_config.py
53-
54-
- name: ruff test
55-
run: ruff check test.py
48+
- name: ruff
49+
run: ruff check .
5650

5751
mypy_splat_checks:
5852
runs-on: ubuntu-latest
@@ -94,11 +88,5 @@ jobs:
9488
pip install -r requirements.txt
9589
pip install types-PyYAML
9690
97-
- name: mypy split
98-
run: mypy --show-column-numbers --hide-error-context split.py
99-
100-
- name: mypy create_config
101-
run: mypy --show-column-numbers --hide-error-context create_config.py
102-
103-
- name: mypy test
104-
run: mypy --show-column-numbers --hide-error-context test.py
91+
- name: mypy
92+
run: mypy --show-column-numbers --hide-error-context *.py

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# splat Release Notes
22

3+
### 0.37.3
4+
5+
* create_config: Avoid emitting relocations for addresses paired by using `ori`
6+
37
### 0.37.2
8+
49
* Add new option `sort_segments_by_vram_dependency` to help with non-matching builds for binaries with complicated memory layouts. See the wiki for details.
510
* Fix create_config missing bss segments due to unsigned LO instructions.
611

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The brackets corresponds to the optional dependencies to install while installin
2121
If you use a `requirements.txt` file in your repository, then you can add this library with the following line:
2222

2323
```txt
24-
splat64[mips]>=0.37.2,<1.0.0
24+
splat64[mips]>=0.37.3,<1.0.0
2525
```
2626

2727
### Optional dependencies

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "splat64"
33
# Should be synced with src/splat/__init__.py
4-
version = "0.37.2"
4+
version = "0.37.3"
55
description = "A binary splitting tool to assist with decompilation and modding projects"
66
readme = "README.md"
77
license = {file = "LICENSE"}

src/splat/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
__package_name__ = __name__
22

33
# Should be synced with pyproject.toml
4-
__version__ = "0.37.2"
4+
__version__ = "0.37.3"
55
__author__ = "ethteck"
66

77
from . import util as util

src/splat/scripts/create_config.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -193,32 +193,37 @@ def create_n64_config(rom_path: Path):
193193
file_presets.write_all_files()
194194

195195
# Write reloc_addrs.txt file
196-
reloc_addrs = []
197-
if rom.entrypoint_info.bss_start_address is not None:
198-
reloc_addrs.append(
199-
f"rom:0x{rom.entrypoint_info.bss_start_address.rom_hi:06X} reloc:MIPS_HI16 symbol:main_BSS_START"
200-
)
201-
reloc_addrs.append(
202-
f"rom:0x{rom.entrypoint_info.bss_start_address.rom_lo:06X} reloc:MIPS_LO16 symbol:main_BSS_START"
203-
)
204-
reloc_addrs.append("")
205-
if rom.entrypoint_info.bss_size is not None:
206-
reloc_addrs.append(
207-
f"rom:0x{rom.entrypoint_info.bss_size.rom_hi:06X} reloc:MIPS_HI16 symbol:main_BSS_SIZE"
208-
)
209-
reloc_addrs.append(
210-
f"rom:0x{rom.entrypoint_info.bss_size.rom_lo:06X} reloc:MIPS_LO16 symbol:main_BSS_SIZE"
211-
)
212-
reloc_addrs.append("")
213-
if rom.entrypoint_info.bss_end_address is not None:
196+
reloc_addrs: list[str] = []
197+
198+
addresses_info: list[tuple[Optional[rominfo.EntryAddressInfo], str]] = [
199+
(rom.entrypoint_info.main_address, "main"),
200+
(rom.entrypoint_info.bss_start_address, "main_BSS_START"),
201+
(rom.entrypoint_info.bss_size, "main_BSS_SIZE"),
202+
(rom.entrypoint_info.bss_end_address, "main_BSS_END"),
203+
]
204+
205+
for addr_info, sym_name in addresses_info:
206+
if addr_info is None:
207+
continue
208+
if addr_info.ori:
209+
# Avoid emitting relocations for `ori`s since `%lo` doesn't support it.
210+
continue
211+
if addr_info.rom_hi == addr_info.rom_lo:
212+
# hi and lo may be the same for the "main" address, i.e. a direct jal.
213+
continue
214+
214215
reloc_addrs.append(
215-
f"rom:0x{rom.entrypoint_info.bss_end_address.rom_hi:06X} reloc:MIPS_HI16 symbol:main_BSS_END"
216+
f"rom:0x{addr_info.rom_hi:06X} reloc:MIPS_HI16 symbol:{sym_name}"
216217
)
217218
reloc_addrs.append(
218-
f"rom:0x{rom.entrypoint_info.bss_end_address.rom_lo:06X} reloc:MIPS_LO16 symbol:main_BSS_END"
219+
f"rom:0x{addr_info.rom_lo:06X} reloc:MIPS_LO16 symbol:{sym_name}"
219220
)
220221
reloc_addrs.append("")
221-
if rom.entrypoint_info.stack_top is not None:
222+
223+
if (
224+
rom.entrypoint_info.stack_top is not None
225+
and not rom.entrypoint_info.stack_top.ori
226+
):
222227
reloc_addrs.append(
223228
'// This entry corresponds to the "stack top", which is the end of the array used as the stack for the main segment.'
224229
)

src/splat/util/n64/rominfo.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,14 @@ class EntryAddressInfo:
7474
value: int
7575
rom_hi: int
7676
rom_lo: int
77+
ori: bool
7778

7879
@staticmethod
7980
def new(
80-
value: Optional[int], hi: Optional[int], lo: Optional[int]
81+
value: Optional[int], hi: Optional[int], lo: Optional[int], ori: Optional[int]
8182
) -> Optional["EntryAddressInfo"]:
8283
if value is not None and hi is not None and lo is not None:
83-
return EntryAddressInfo(value, hi, lo)
84+
return EntryAddressInfo(value, hi, lo, ori == lo)
8485
return None
8586

8687

@@ -94,6 +95,7 @@ class N64EntrypointInfo:
9495
main_address: Optional[EntryAddressInfo]
9596
stack_top: Optional[EntryAddressInfo]
9697
traditional_entrypoint: bool
98+
ori_entrypoint: bool
9799

98100
def segment_size(self) -> int:
99101
if self.data_size is not None:
@@ -120,6 +122,10 @@ def parse_rom_bytes(
120122
completed_pair = [False for _ in range(32)]
121123
hi_assignments: List[Optional[int]] = [None for _ in range(32)]
122124
lo_assignments: List[Optional[int]] = [None for _ in range(32)]
125+
# We need to track if something was paired using an ori instead of an
126+
# addiu or similar, because if that's the case we can't emit normal
127+
# relocations in the generated symbol_addrs file for it.
128+
ori_assignments: List[Optional[int]] = [None for _ in range(32)]
123129

124130
register_bss_address: Optional[int] = None
125131
register_bss_size: Optional[int] = None
@@ -130,6 +136,7 @@ def parse_rom_bytes(
130136
bss_end_address: Optional[EntryAddressInfo] = None
131137

132138
traditional_entrypoint = True
139+
ori_entrypoint = False
133140
decrementing_bss_routine = True
134141
data_size: Optional[int] = None
135142
func_call_target: Optional[EntryAddressInfo] = None
@@ -163,6 +170,9 @@ def parse_rom_bytes(
163170
)
164171
completed_pair[insn.rt.value] = True
165172
lo_assignments[insn.rt.value] = current_rom
173+
if insn.isUnsigned():
174+
ori_assignments[insn.rt.value] = current_rom
175+
ori_entrypoint = True
166176
elif insn.doesStore():
167177
if insn.rt == rabbitizer.RegGprO32.zero:
168178
# Try to detect the zero-ing bss algorithm
@@ -208,11 +218,13 @@ def parse_rom_bytes(
208218
register_values[insn.rs.value],
209219
hi_assignments[insn.rs.value],
210220
lo_assignments[insn.rs.value],
221+
ori_assignments[insn.rs.value],
211222
)
212223
bss_end_address = EntryAddressInfo.new(
213224
register_values[insn.rt.value],
214225
hi_assignments[insn.rt.value],
215226
lo_assignments[insn.rt.value],
227+
ori_assignments[insn.rt.value],
216228
)
217229

218230
elif insn.isFunctionCall():
@@ -221,7 +233,7 @@ def parse_rom_bytes(
221233
# entrypoint to actual code.
222234
traditional_entrypoint = False
223235
func_call_target = EntryAddressInfo(
224-
insn.getInstrIndexAsVram(), current_rom, current_rom
236+
insn.getInstrIndexAsVram(), current_rom, current_rom, False
225237
)
226238

227239
elif insn.uniqueId == rabbitizer.InstrId.cpu_break:
@@ -254,19 +266,22 @@ def parse_rom_bytes(
254266
register_values[register_bss_address],
255267
hi_assignments[register_bss_address],
256268
lo_assignments[register_bss_address],
269+
ori_assignments[register_bss_address],
257270
)
258271
if register_bss_size is not None:
259272
bss_size = EntryAddressInfo.new(
260273
register_values[register_bss_size],
261274
hi_assignments[register_bss_size],
262275
lo_assignments[register_bss_size],
276+
ori_assignments[register_bss_size],
263277
)
264278

265279
if register_main_address is not None:
266280
main_address = EntryAddressInfo.new(
267281
register_values[register_main_address],
268282
hi_assignments[register_main_address],
269283
lo_assignments[register_main_address],
284+
ori_assignments[register_main_address],
270285
)
271286
else:
272287
main_address = None
@@ -275,6 +290,7 @@ def parse_rom_bytes(
275290
register_values[rabbitizer.RegGprO32.sp.value],
276291
hi_assignments[rabbitizer.RegGprO32.sp.value],
277292
lo_assignments[rabbitizer.RegGprO32.sp.value],
293+
ori_assignments[rabbitizer.RegGprO32.sp.value],
278294
)
279295

280296
if not traditional_entrypoint:
@@ -299,6 +315,7 @@ def parse_rom_bytes(
299315
main_address,
300316
stack_top,
301317
traditional_entrypoint,
318+
ori_entrypoint,
302319
)
303320

304321

0 commit comments

Comments
 (0)