splat64 0.37.1__tar.gz → 0.37.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {splat64-0.37.1 → splat64-0.37.3}/.github/workflows/lint.yml +4 -16
- {splat64-0.37.1 → splat64-0.37.3}/.github/workflows/unit_tests.yml +1 -0
- {splat64-0.37.1 → splat64-0.37.3}/CHANGELOG.md +10 -0
- {splat64-0.37.1 → splat64-0.37.3}/PKG-INFO +2 -2
- {splat64-0.37.1 → splat64-0.37.3}/README.md +1 -1
- {splat64-0.37.1 → splat64-0.37.3}/docs/Configuration.md +4 -0
- {splat64-0.37.1 → splat64-0.37.3}/pyproject.toml +1 -1
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/__init__.py +1 -1
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/scripts/create_config.py +26 -21
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/scripts/split.py +46 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/c.py +3 -3
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/n64/rominfo.py +21 -5
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/options.py +5 -0
- splat64-0.37.3/test_n64_entrypoints.py +1592 -0
- {splat64-0.37.1 → splat64-0.37.3}/.gitattributes +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/.github/workflows/format.yml +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/.github/workflows/publish_docs_to_wiki.yml +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/.github/workflows/pypi.yml +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/.github/workflows/test_lib.yml +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/.gitignore +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/LICENSE +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/create_config.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Adding-Symbols.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Advanced-Reloc.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Advanced.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Examples.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/General-Workflow.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Home.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Quickstart-Elf.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Quickstart.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/Segments.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/docs/VramClasses.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/mypy.ini +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/requirements.txt +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/split.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/__main__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/disassembler/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/disassembler/disassembler.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/disassembler/disassembler_instance.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/disassembler/disassembler_section.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/disassembler/null_disassembler.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/disassembler/spimdisasm_disassembler.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/platforms/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/platforms/n64.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/platforms/ps2.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/platforms/psp.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/platforms/psx.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/py.typed +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/scripts/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/scripts/capy.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/asm.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/asmtu.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/bin.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/bss.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/code.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/codesubsegment.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/cpp.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/data.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/databin.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/eh_frame.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/gcc_except_table.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/group.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/hasm.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/header.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/lib.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/linker_offset.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/pad.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/rdata.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/rodata.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/rodatabin.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/sbss.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/sdata.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/segment.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/common/textbin.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/linker_entry.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ci.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ci4.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ci8.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/decompressor.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/gfx.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/header.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/i1.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/i4.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/i8.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ia16.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ia4.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ia8.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/img.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/ipl3.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/mio0.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/palette.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/rgba16.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/rgba32.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/rsp.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/vtx.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/n64/yay0.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/ps2/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/ps2/ctor.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/ps2/lit4.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/ps2/lit8.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/ps2/vtables.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/psp/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/psx/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/psx/header.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/segtypes/segment.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/cache_handler.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/color.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/compiler.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/conf.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/file_presets.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/log.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/n64/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/n64/find_code_length.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/palettes.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/progress_bar.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/ps2/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/ps2/ps2elfinfo.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/psx/__init__.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/psx/psxexeinfo.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/relocs.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/statistics.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/symbols.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/utils.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/src/splat/util/vram_classes.py +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/Dockerfile +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/README.md +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/.gitignore +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/Makefile +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/build/basic_app.bin +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/dummy_ipl3.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/.splache +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/data/main.bss.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/data/main.data.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/data/main.rodata.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/handwritten.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/header.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/main.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/nonmatchings/main/D_80000510.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/nonmatchings/main/func_80000400.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/asm/nonmatchings/main/func_800004A0.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/assets/dummy_ipl3.bin +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/basic_app.d +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/build/test/basic_app/split/src/main.asmproc.d +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/include/include_asm.h +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/include/labels.inc +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/include/macro.inc +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/src/main.c +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/undefined_funcs_auto.txt +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/expected/undefined_syms_auto.txt +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/handwritten.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/header.s +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/basic_app/main.c +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test/test_gen_expected.sh +0 -0
- {splat64-0.37.1 → splat64-0.37.3}/test.py +0 -0
|
@@ -45,14 +45,8 @@ jobs:
|
|
|
45
45
|
pip install -r requirements.txt
|
|
46
46
|
pip install types-PyYAML
|
|
47
47
|
|
|
48
|
-
- name: ruff
|
|
49
|
-
run: ruff check
|
|
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 .
|
|
56
50
|
|
|
57
51
|
mypy_splat_checks:
|
|
58
52
|
runs-on: ubuntu-latest
|
|
@@ -94,11 +88,5 @@ jobs:
|
|
|
94
88
|
pip install -r requirements.txt
|
|
95
89
|
pip install types-PyYAML
|
|
96
90
|
|
|
97
|
-
- name: mypy
|
|
98
|
-
run: mypy --show-column-numbers --hide-error-context
|
|
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
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
# splat Release Notes
|
|
2
2
|
|
|
3
|
+
### 0.37.3
|
|
4
|
+
|
|
5
|
+
* create_config: Avoid emitting relocations for addresses paired by using `ori`
|
|
6
|
+
|
|
7
|
+
### 0.37.2
|
|
8
|
+
|
|
9
|
+
* 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.
|
|
10
|
+
* Fix create_config missing bss segments due to unsigned LO instructions.
|
|
11
|
+
|
|
3
12
|
### 0.37.1
|
|
4
13
|
|
|
5
14
|
* Fix `make_full_disasm_for_code` not extracting data-only TUs.
|
|
6
15
|
* Fix `make_full_disasm_for_code` and `disassemble_all` combo
|
|
7
16
|
* Fixes not writing other sections to asm file when both options are enabled.
|
|
17
|
+
* Add UTF-8 encoding to file reads in c.py.
|
|
8
18
|
|
|
9
19
|
### 0.37.0
|
|
10
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: splat64
|
|
3
|
-
Version: 0.37.
|
|
3
|
+
Version: 0.37.3
|
|
4
4
|
Summary: A binary splitting tool to assist with decompilation and modding projects
|
|
5
5
|
Project-URL: Repository, https://github.com/ethteck/splat
|
|
6
6
|
Project-URL: Issues, https://github.com/ethteck/splat/issues
|
|
@@ -76,7 +76,7 @@ The brackets corresponds to the optional dependencies to install while installin
|
|
|
76
76
|
If you use a `requirements.txt` file in your repository, then you can add this library with the following line:
|
|
77
77
|
|
|
78
78
|
```txt
|
|
79
|
-
splat64[mips]>=0.37.
|
|
79
|
+
splat64[mips]>=0.37.3,<1.0.0
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
### Optional dependencies
|
|
@@ -21,7 +21,7 @@ The brackets corresponds to the optional dependencies to install while installin
|
|
|
21
21
|
If you use a `requirements.txt` file in your repository, then you can add this library with the following line:
|
|
22
22
|
|
|
23
23
|
```txt
|
|
24
|
-
splat64[mips]>=0.37.
|
|
24
|
+
splat64[mips]>=0.37.3,<1.0.0
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
### Optional dependencies
|
|
@@ -526,6 +526,10 @@ Generates a discard section like this:
|
|
|
526
526
|
|
|
527
527
|
Determines whether to add wildcards for section linking in the linker script (.rodata* for example)
|
|
528
528
|
|
|
529
|
+
### ld_sort_segments_by_vram_class_dependency
|
|
530
|
+
|
|
531
|
+
Ensures segments of vram classes with dependencies (`vram_symbol` / `follows_classes`) are written to the linker script AFTER the segments they depend on. This is intended to preserve vram class ordering for shifted builds (e.g., mods) and is not expected to produce a matching build. Disable this when a matching build is desired.
|
|
532
|
+
|
|
529
533
|
### ld_use_symbolic_vram_addresses
|
|
530
534
|
|
|
531
535
|
Determines whether to use `follows_vram` (segment option) and `vram_symbol` / `follows_classes` (vram_class options) to calculate vram addresses in the linker script.
|
|
@@ -193,32 +193,37 @@ segments:
|
|
|
193
193
|
file_presets.write_all_files()
|
|
194
194
|
|
|
195
195
|
# Write reloc_addrs.txt file
|
|
196
|
-
reloc_addrs = []
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
+
|
|
214
215
|
reloc_addrs.append(
|
|
215
|
-
f"rom:0x{
|
|
216
|
+
f"rom:0x{addr_info.rom_hi:06X} reloc:MIPS_HI16 symbol:{sym_name}"
|
|
216
217
|
)
|
|
217
218
|
reloc_addrs.append(
|
|
218
|
-
f"rom:0x{
|
|
219
|
+
f"rom:0x{addr_info.rom_lo:06X} reloc:MIPS_LO16 symbol:{sym_name}"
|
|
219
220
|
)
|
|
220
221
|
reloc_addrs.append("")
|
|
221
|
-
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
rom.entrypoint_info.stack_top is not None
|
|
225
|
+
and not rom.entrypoint_info.stack_top.ori
|
|
226
|
+
):
|
|
222
227
|
reloc_addrs.append(
|
|
223
228
|
'// This entry corresponds to the "stack top", which is the end of the array used as the stack for the main segment.'
|
|
224
229
|
)
|
|
@@ -6,6 +6,8 @@ import importlib
|
|
|
6
6
|
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
|
+
from collections import defaultdict, deque
|
|
10
|
+
|
|
9
11
|
from .. import __package_name__, __version__
|
|
10
12
|
from ..disassembler import disassembler_instance
|
|
11
13
|
from ..util import cache_handler, progress_bar, vram_classes, statistics, file_presets
|
|
@@ -222,6 +224,47 @@ def calc_segment_dependences(
|
|
|
222
224
|
return vram_class_to_follows_segments
|
|
223
225
|
|
|
224
226
|
|
|
227
|
+
def sort_segments_by_vram_class_dependency(
|
|
228
|
+
all_segments: List[Segment],
|
|
229
|
+
) -> List[Segment]:
|
|
230
|
+
# map all "_VRAM_END" strings to segments
|
|
231
|
+
end_sym_to_seg: Dict[str, Segment] = {}
|
|
232
|
+
for seg in all_segments:
|
|
233
|
+
end_sym_to_seg[get_segment_vram_end_symbol_name(seg)] = seg
|
|
234
|
+
|
|
235
|
+
# build dependency graph: A -> B means "A must come before B"
|
|
236
|
+
graph: Dict[Segment, List[Segment]] = defaultdict(list)
|
|
237
|
+
indeg: Dict[Segment, int] = {seg: 0 for seg in all_segments}
|
|
238
|
+
|
|
239
|
+
for seg in all_segments:
|
|
240
|
+
sym = seg.vram_symbol
|
|
241
|
+
if sym is None:
|
|
242
|
+
continue
|
|
243
|
+
dep = end_sym_to_seg.get(sym)
|
|
244
|
+
if dep is None or dep is seg:
|
|
245
|
+
continue
|
|
246
|
+
graph[dep].append(seg)
|
|
247
|
+
indeg[seg] += 1
|
|
248
|
+
|
|
249
|
+
# stable topo sort with queue seeded in original order
|
|
250
|
+
q = deque([seg for seg in all_segments if indeg[seg] == 0])
|
|
251
|
+
out: List[Segment] = []
|
|
252
|
+
|
|
253
|
+
while q:
|
|
254
|
+
n = q.popleft()
|
|
255
|
+
out.append(n)
|
|
256
|
+
for m in graph.get(n, []):
|
|
257
|
+
indeg[m] -= 1
|
|
258
|
+
if indeg[m] == 0:
|
|
259
|
+
q.append(m)
|
|
260
|
+
|
|
261
|
+
assert len(out) == len(all_segments), (
|
|
262
|
+
"Encountered cyclic dependency when reordering segments by vram class."
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
return out
|
|
266
|
+
|
|
267
|
+
|
|
225
268
|
def read_target_binary() -> bytes:
|
|
226
269
|
rom_bytes = options.opts.target_path.read_bytes()
|
|
227
270
|
|
|
@@ -317,6 +360,9 @@ def do_split(
|
|
|
317
360
|
|
|
318
361
|
|
|
319
362
|
def write_linker_script(all_segments: List[Segment]) -> LinkerWriter:
|
|
363
|
+
if options.opts.ld_sort_segments_by_vram_class_dependency:
|
|
364
|
+
all_segments = sort_segments_by_vram_class_dependency(all_segments)
|
|
365
|
+
|
|
320
366
|
vram_class_dependencies = calc_segment_dependences(all_segments)
|
|
321
367
|
vram_classes_to_search = set(vram_class_dependencies.keys())
|
|
322
368
|
|
|
@@ -51,7 +51,7 @@ class CommonSegC(CommonSegCodeSubsegment):
|
|
|
51
51
|
|
|
52
52
|
@staticmethod
|
|
53
53
|
def get_funcs_defined_in_c(c_file: Path) -> Set[str]:
|
|
54
|
-
with open(c_file, "r") as f:
|
|
54
|
+
with open(c_file, "r", encoding="utf-8") as f:
|
|
55
55
|
text = CommonSegC.strip_c_comments(f.read())
|
|
56
56
|
|
|
57
57
|
return set(m.group(1) for m in C_FUNC_RE.finditer(text))
|
|
@@ -105,7 +105,7 @@ class CommonSegC(CommonSegCodeSubsegment):
|
|
|
105
105
|
|
|
106
106
|
@staticmethod
|
|
107
107
|
def get_global_asm_funcs(c_file: Path) -> Set[str]:
|
|
108
|
-
with c_file.open() as f:
|
|
108
|
+
with c_file.open(encoding="utf-8") as f:
|
|
109
109
|
text = CommonSegC.strip_c_comments(f.read())
|
|
110
110
|
if options.opts.compiler == IDO:
|
|
111
111
|
return set(m.group(2) for m in C_GLOBAL_ASM_IDO_RE.finditer(text))
|
|
@@ -114,7 +114,7 @@ class CommonSegC(CommonSegCodeSubsegment):
|
|
|
114
114
|
|
|
115
115
|
@staticmethod
|
|
116
116
|
def get_global_asm_rodata_syms(c_file: Path) -> Set[str]:
|
|
117
|
-
with c_file.open() as f:
|
|
117
|
+
with c_file.open(encoding="utf-8") as f:
|
|
118
118
|
text = CommonSegC.strip_c_comments(f.read())
|
|
119
119
|
if options.opts.compiler == IDO:
|
|
120
120
|
return set(m.group(2) for m in C_GLOBAL_ASM_IDO_RE.finditer(text))
|
|
@@ -74,13 +74,14 @@ class EntryAddressInfo:
|
|
|
74
74
|
value: int
|
|
75
75
|
rom_hi: int
|
|
76
76
|
rom_lo: int
|
|
77
|
+
ori: bool
|
|
77
78
|
|
|
78
79
|
@staticmethod
|
|
79
80
|
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]
|
|
81
82
|
) -> Optional["EntryAddressInfo"]:
|
|
82
83
|
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)
|
|
84
85
|
return None
|
|
85
86
|
|
|
86
87
|
|
|
@@ -94,6 +95,7 @@ class N64EntrypointInfo:
|
|
|
94
95
|
main_address: Optional[EntryAddressInfo]
|
|
95
96
|
stack_top: Optional[EntryAddressInfo]
|
|
96
97
|
traditional_entrypoint: bool
|
|
98
|
+
ori_entrypoint: bool
|
|
97
99
|
|
|
98
100
|
def segment_size(self) -> int:
|
|
99
101
|
if self.data_size is not None:
|
|
@@ -120,6 +122,10 @@ class N64EntrypointInfo:
|
|
|
120
122
|
completed_pair = [False for _ in range(32)]
|
|
121
123
|
hi_assignments: List[Optional[int]] = [None for _ in range(32)]
|
|
122
124
|
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)]
|
|
123
129
|
|
|
124
130
|
register_bss_address: Optional[int] = None
|
|
125
131
|
register_bss_size: Optional[int] = None
|
|
@@ -130,6 +136,7 @@ class N64EntrypointInfo:
|
|
|
130
136
|
bss_end_address: Optional[EntryAddressInfo] = None
|
|
131
137
|
|
|
132
138
|
traditional_entrypoint = True
|
|
139
|
+
ori_entrypoint = False
|
|
133
140
|
decrementing_bss_routine = True
|
|
134
141
|
data_size: Optional[int] = None
|
|
135
142
|
func_call_target: Optional[EntryAddressInfo] = None
|
|
@@ -162,8 +169,10 @@ class N64EntrypointInfo:
|
|
|
162
169
|
register_values[insn.rs.value] + insn.getProcessedImmediate()
|
|
163
170
|
)
|
|
164
171
|
completed_pair[insn.rt.value] = True
|
|
165
|
-
|
|
166
|
-
|
|
172
|
+
lo_assignments[insn.rt.value] = current_rom
|
|
173
|
+
if insn.isUnsigned():
|
|
174
|
+
ori_assignments[insn.rt.value] = current_rom
|
|
175
|
+
ori_entrypoint = True
|
|
167
176
|
elif insn.doesStore():
|
|
168
177
|
if insn.rt == rabbitizer.RegGprO32.zero:
|
|
169
178
|
# Try to detect the zero-ing bss algorithm
|
|
@@ -209,11 +218,13 @@ class N64EntrypointInfo:
|
|
|
209
218
|
register_values[insn.rs.value],
|
|
210
219
|
hi_assignments[insn.rs.value],
|
|
211
220
|
lo_assignments[insn.rs.value],
|
|
221
|
+
ori_assignments[insn.rs.value],
|
|
212
222
|
)
|
|
213
223
|
bss_end_address = EntryAddressInfo.new(
|
|
214
224
|
register_values[insn.rt.value],
|
|
215
225
|
hi_assignments[insn.rt.value],
|
|
216
226
|
lo_assignments[insn.rt.value],
|
|
227
|
+
ori_assignments[insn.rt.value],
|
|
217
228
|
)
|
|
218
229
|
|
|
219
230
|
elif insn.isFunctionCall():
|
|
@@ -222,7 +233,7 @@ class N64EntrypointInfo:
|
|
|
222
233
|
# entrypoint to actual code.
|
|
223
234
|
traditional_entrypoint = False
|
|
224
235
|
func_call_target = EntryAddressInfo(
|
|
225
|
-
insn.getInstrIndexAsVram(), current_rom, current_rom
|
|
236
|
+
insn.getInstrIndexAsVram(), current_rom, current_rom, False
|
|
226
237
|
)
|
|
227
238
|
|
|
228
239
|
elif insn.uniqueId == rabbitizer.InstrId.cpu_break:
|
|
@@ -255,12 +266,14 @@ class N64EntrypointInfo:
|
|
|
255
266
|
register_values[register_bss_address],
|
|
256
267
|
hi_assignments[register_bss_address],
|
|
257
268
|
lo_assignments[register_bss_address],
|
|
269
|
+
ori_assignments[register_bss_address],
|
|
258
270
|
)
|
|
259
271
|
if register_bss_size is not None:
|
|
260
272
|
bss_size = EntryAddressInfo.new(
|
|
261
273
|
register_values[register_bss_size],
|
|
262
274
|
hi_assignments[register_bss_size],
|
|
263
275
|
lo_assignments[register_bss_size],
|
|
276
|
+
ori_assignments[register_bss_size],
|
|
264
277
|
)
|
|
265
278
|
|
|
266
279
|
if register_main_address is not None:
|
|
@@ -268,6 +281,7 @@ class N64EntrypointInfo:
|
|
|
268
281
|
register_values[register_main_address],
|
|
269
282
|
hi_assignments[register_main_address],
|
|
270
283
|
lo_assignments[register_main_address],
|
|
284
|
+
ori_assignments[register_main_address],
|
|
271
285
|
)
|
|
272
286
|
else:
|
|
273
287
|
main_address = None
|
|
@@ -276,6 +290,7 @@ class N64EntrypointInfo:
|
|
|
276
290
|
register_values[rabbitizer.RegGprO32.sp.value],
|
|
277
291
|
hi_assignments[rabbitizer.RegGprO32.sp.value],
|
|
278
292
|
lo_assignments[rabbitizer.RegGprO32.sp.value],
|
|
293
|
+
ori_assignments[rabbitizer.RegGprO32.sp.value],
|
|
279
294
|
)
|
|
280
295
|
|
|
281
296
|
if not traditional_entrypoint:
|
|
@@ -300,6 +315,7 @@ class N64EntrypointInfo:
|
|
|
300
315
|
main_address,
|
|
301
316
|
stack_top,
|
|
302
317
|
traditional_entrypoint,
|
|
318
|
+
ori_entrypoint,
|
|
303
319
|
)
|
|
304
320
|
|
|
305
321
|
|
|
@@ -127,6 +127,8 @@ class SplatOpts:
|
|
|
127
127
|
# `vram_symbol` / `follows_classes` (vram_class options) to calculate vram addresses in the linker script.
|
|
128
128
|
# If disabled, this uses the plain integer values for vram addresses defined in the yaml.
|
|
129
129
|
ld_use_symbolic_vram_addresses: bool
|
|
130
|
+
# Ensures segments of vram classes with dependencies (`vram_symbol` / `follows_classes`) are written to the linker script AFTER the segments they depend on.
|
|
131
|
+
ld_sort_segments_by_vram_class_dependency: bool
|
|
130
132
|
# Change linker script generation to allow partially linking segments. Requires both `ld_partial_scripts_path` and `ld_partial_build_segments_path` to be set.
|
|
131
133
|
ld_partial_linking: bool
|
|
132
134
|
# Folder were each intermediary linker script will be written to.
|
|
@@ -512,6 +514,9 @@ def _parse_yaml(
|
|
|
512
514
|
ld_sections_allowlist=p.parse_opt("ld_sections_allowlist", list, []),
|
|
513
515
|
ld_sections_denylist=p.parse_opt("ld_sections_denylist", list, []),
|
|
514
516
|
ld_wildcard_sections=p.parse_opt("ld_wildcard_sections", bool, False),
|
|
517
|
+
ld_sort_segments_by_vram_class_dependency=p.parse_opt(
|
|
518
|
+
"ld_sort_segments_by_vram_class_dependency", bool, False
|
|
519
|
+
),
|
|
515
520
|
ld_use_symbolic_vram_addresses=p.parse_opt(
|
|
516
521
|
"ld_use_symbolic_vram_addresses", bool, True
|
|
517
522
|
),
|